dbox-file.c revision b0e62f0a402e768a7aa6fe43b15e990c8df5b069
/* Copyright (c) 2007-2012 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "hex-dec.h"
#include "hex-binary.h"
#include "hostpid.h"
#include "istream.h"
#include "ostream.h"
#include "file-lock.h"
#include "file-dotlock.h"
#include "mkdir-parents.h"
#include "eacces-error.h"
#include "str.h"
#include "dbox-storage.h"
#include "dbox-file.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#define DBOX_READ_BLOCK_SIZE IO_BLOCK_SIZE
#ifndef DBOX_FILE_LOCK_METHOD_FLOCK
static const struct dotlock_settings dotlock_set = {
};
#endif
const char *dbox_generate_tmp_filename(void)
{
static unsigned int create_count = 0;
create_count++,
(unsigned int)ioloop_timeval.tv_usec,
}
{
"%s failed for file %s: %m",
}
{
}
{
}
{
}
{
}
{
unsigned int pos;
enum dbox_header_key key;
return -1;
}
line += 2;
pos = 2;
file->msg_header_size = 0;
switch (key) {
break;
break;
case DBOX_HEADER_CREATE_STAMP:
break;
}
}
if (file->msg_header_size == 0) {
return -1;
}
return 0;
}
{
const char *line;
unsigned int hdr_size;
int ret;
"EOF while reading file header");
return 0;
}
return -1;
}
T_BEGIN {
} T_END;
if (ret > 0)
return ret;
}
{
const char *path;
/* try the primary path first */
continue;
}
"open(%s) failed: %m", path);
return -1;
}
/* not found */
return 0;
}
/* try the alternative path */
}
return 1;
}
bool *notfound_r)
{
int ret;
*notfound_r = FALSE;
return 1;
T_BEGIN {
} T_END;
if (ret <= 0) {
if (ret < 0)
return -1;
*notfound_r = TRUE;
return 1;
}
}
return dbox_file_read_header(file);
}
{
}
{
}
{
const char *path;
if (dbox_file_is_open(file)) {
return -1;
}
return 0;
}
/* try the primary path first */
"stat(%s) failed: %m", path);
return -1;
}
/* not found */
return -1;
}
/* try the alternative path */
}
return 0;
}
{
(unsigned int)sizeof(struct dbox_message_header),
DBOX_HEADER_CREATE_STAMP, (unsigned int)ioloop_time);
}
{
}
}
{
int ret;
#ifdef DBOX_FILE_LOCK_METHOD_FLOCK
if (ret < 0) {
}
#else
if (ret < 0) {
}
#endif
return ret;
}
{
#ifdef DBOX_FILE_LOCK_METHOD_FLOCK
#else
#endif
}
}
{
struct dbox_message_header hdr;
const unsigned char *data;
int ret;
if (ret <= 0) {
/* EOF, broken offset or file truncated */
return 0;
}
return -1;
}
/* probably broken offset */
return 0;
}
return 0;
}
sizeof(hdr.message_size_hex));
return 1;
}
{
int ret;
if (offset == 0)
if (ret <= 0)
return ret;
}
return 1;
}
static int
{
const char *line;
int ret;
return ret;
/* skip over the actual metadata */
/* end of metadata */
break;
}
}
return 1;
}
{
}
{
int ret;
/* first mail. we may not have read the file at all yet,
so set the offset afterwards. */
offset = 0;
} else {
return ret;
}
return 0;
}
}
if (*offset_r == 0)
return ret;
}
{
struct dbox_file_append_context *ctx;
}
return ctx;
}
{
int ret;
return -1;
}
}
return ret;
}
{
bool close_file = FALSE;
if (ctx->first_append_offset == 0) {
/* nothing changed */
/* rollbacking everything */
close_file = TRUE;
} else {
/* truncating only some mails */
}
if (close_file)
}
{
return 0;
return -1;
}
return -1;
}
}
return -1;
}
}
return 0;
}
{
}
{
/* file creation had failed */
return -1;
}
/* a message was aborted. don't try appending to this
file anymore. */
return -1;
}
if (file->file_version == 0) {
/* newly created file, write the file header */
return -1;
}
return 1;
}
/* file has existing mails */
/* created by an incompatible version, can't append */
return 0;
}
/* first append to existing file. seek to eof first. */
return -1;
}
"dbox file size too small");
return 0;
}
}
return 1;
}
{
struct dbox_metadata_header metadata_hdr;
const unsigned char *data;
int ret;
sizeof(metadata_hdr) - 1);
if (ret <= 0) {
/* EOF, broken offset */
"Unexpected EOF while reading metadata header");
return 0;
}
return -1;
}
sizeof(metadata_hdr.magic_post)) != 0) {
/* probably broken offset */
"metadata header has bad magic value");
return 0;
}
return 1;
}
static int
{
const char *line;
int ret;
else {
}
return ret;
ret = 0;
/* use unlimited line length for metadata */
/* end of metadata */
ret = 1;
break;
}
}
if (ret == 0)
return ret;
}
{
int ret;
return 1;
if (ret <= 0)
return ret;
return 1;
}
enum dbox_metadata_key key)
{
const char *const *metadata;
unsigned int i, count;
for (i = 0; i < count; i++) {
return metadata[i] + 1;
}
return NULL;
}
{
const char *value;
/* see if we have it in metadata */
else {
/* no. that means we can use the size in the header */
return file->cur_physical_size;
}
}
{
sizeof(dbox_msg_hdr->magic_pre));
sizeof(dbox_msg_hdr->message_size_hex));
}
{
const char *path;
"unlink(%s) failed: %m", path);
return -1;
}
/* not found */
return 0;
}
/* try the alternative path */
}
return 1;
}