dbox-file.c revision 10c96a244935de4add8213ba0b894178dfb889a5
/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "hex-dec.h"
#include "hostpid.h"
#include "istream.h"
#include "ostream.h"
#include "write-full.h"
#include "str.h"
#include "dbox-storage.h"
#include "dbox-index.h"
#include "dbox-file.h"
#include "dbox-file-maildir.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
};
'A', 'F', 'D', 'S', 'T'
};
static char *dbox_generate_tmp_filename(void)
{
static unsigned int create_count = 0;
return i_strdup_printf("temp.%lu.P%sQ%uM%u.%s",
create_count++,
(unsigned int)ioloop_timeval.tv_usec,
}
{
"%s(%s) failed: %m", function,
}
static void
{
reason);
}
static struct dbox_file *
{
unsigned int i, count;
for (i = 0; i < count; i++) {
/* move to last in the array */
return file;
}
}
return NULL;
}
{
}
{
unsigned int i, count;
for (i = 0; i < count; i++)
dbox_file_free(files[i]);
}
static void
{
unsigned int i, count;
for (i = 0; i < count;) {
dbox_file_free(files[i]);
if (--close_count == 0)
break;
} else {
i++;
}
}
}
static char *
bool *maildir_file_r)
{
struct dbox_index_record *rec;
const char *p;
*maildir_file_r = FALSE;
if ((file_id & DBOX_FILE_ID_FLAG_UID) != 0) {
}
/* data contains <uid> <filename> */
*maildir_file_r = TRUE;
}
}
struct dbox_file *
{
unsigned int count;
bool maildir;
return file;
}
if (file_id != 0) {
} else {
}
/* newly created files and maildir files always exist in the
primary path */
file->current_path =
}
if (file_id != 0)
return file;
}
struct dbox_file *
{
return file;
}
{
const char *old_path;
bool maildir;
if (!file->maildir_file) {
"rename(%s, %s) failed: %m",
return -1;
}
}
return 0;
}
{
unsigned int i, count;
return;
/* don't cache metadata seeks while file isn't being referenced */
file->metadata_read_offset = 0;
/* we can leave this file open for now */
return;
}
for (i = 0; i < count; i++) {
break;
}
}
}
{
if (days == 0)
return 0;
/* get beginning of today */
i_panic("mktime(today) failed");
}
{
if (file->nonappendable)
return FALSE;
if (file->append_offset == 0) {
/* messages have been expunged */
return FALSE;
}
return TRUE;
return FALSE;
}
{
unsigned int pos;
enum dbox_header_key key;
return -1;
}
line += 2;
pos = 2;
file->append_offset = 0;
file->msg_header_size = 0;
switch (key) {
break;
break;
case DBOX_HEADER_CREATE_STAMP:
break;
}
}
if (file->msg_header_size == 0) {
return -1;
}
if (!file->nonappendable)
return 0;
}
{
const char *line;
int ret;
return 0;
return -1;
}
);
return ret;
}
{
const char *path;
int i;
/* try the primary path first */
for (i = 0;; i++) {
break;
"open(%s) failed: %m", path);
return -1;
}
/* file doesn't exist */
return 0;
}
/* try the alternative path */
}
return 1;
}
bool *deleted_r)
{
int ret;
);
if (ret <= 0) {
if (ret < 0)
return -1;
return 1;
}
}
}
{
int fd;
if (fd == -1) {
"open(%s, O_CREAT) failed: %m", path);
}
return fd;
}
{
const char *hdrsize;
file->current_path =
}
return -1;
(unsigned int)sizeof(struct dbox_message_header),
DBOX_HEADER_CREATE_STAMP, (unsigned int)ioloop_time,
return -1;
}
return 0;
}
bool *deleted_r)
{
int ret;
);
return ret;
return 1;
else
}
{
const char *path;
int ret;
return 0;
);
if (ret == 0) {
"open(%s) failed: %m", path);
}
return ret <= 0 ? -1 : 0;
}
{
}
}
{
return file->current_path;
}
static int
{
struct dbox_index_record *rec;
return -1;
}
/* should happen only when we're rebuilding the index */
*uid_r = 0;
} else {
}
return 1;
}
{
struct dbox_message_header hdr;
const unsigned char *data;
int ret;
if (file->maildir_file)
if (ret <= 0) {
/* EOF, broken offset */
return 0;
}
return -1;
}
return 0;
/* probably broken offset */
return 0;
}
sizeof(hdr.message_size_hex));
return 1;
}
{
int ret;
*expunged_r = FALSE;
return 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 */
if (*line == DBOX_METADATA_SPACE) {
/* end of metadata */
break;
}
}
*uid_r = 0;
*physical_size_r = 0;
return 1;
}
}
{
bool deleted;
int ret;
&deleted);
if (ret <= 0)
return ret;
if (deleted) {
*uid_r = 0;
*physical_size_r = 0;
return 1;
}
if (first) {
*physical_size_r = size;
return 1;
}
}
{
int ret;
return ret;
if (file->append_offset == 0 ||
/* can't append */
return 0;
}
return 1;
}
static int
{
bool deleted;
int ret;
return ret;
}
if (ret <= 0)
return ret;
} else {
return 0;
}
/* we use 32bit offsets to messages */
return 0;
}
return 1;
}
{
int ret;
if (file->nonappendable)
return 0;
if (ret == 0)
return ret;
}
{
return file->output_stream_offset;
}
{
file->append_offset = 0;
}
}
{
file->append_count++;
}
static uoff_t
{
if (offset == 0) {
if (file->maildir_file)
return 0;
}
}
{
struct dbox_metadata_header metadata_hdr;
const unsigned char *data;
int ret;
sizeof(metadata_hdr) - 1);
if (ret <= 0) {
/* EOF, broken offset */
return 0;
}
return -1;
}
sizeof(metadata_hdr.magic_post)) != 0) {
/* probably broken offset */
return 0;
}
return 1;
}
bool *expunged_r)
{
const char *line;
bool deleted;
int ret;
*expunged_r = FALSE;
} else {
}
file->metadata_read_offset = 0;
return 1;
return ret;
if (deleted) {
*expunged_r = TRUE;
return 1;
}
}
return ret;
*expunged_r = TRUE;
for (;;) {
break;
/* end of metadata */
*expunged_r = FALSE;
break;
}
}
if (*expunged_r)
return 1;
}
bool *expunged_r)
{
int ret;
NULL, expunged_r);
if (ret <= 0 || *expunged_r)
return ret;
}
enum dbox_metadata_key key)
{
const char *const *metadata;
unsigned int i, count;
if (file->maildir_file)
for (i = 0; i < count; i++) {
return metadata[i] + 1;
}
return NULL;
}
const char *value)
{
unsigned int i, count;
/* value didn't change */
return;
}
else {
/* see if we have already changed this metadata */
for (i = 0; i < count; i++) {
return;
}
}
}
}
{
int ret;
return 1;
}
unsigned int len)
{
char space[256];
len--;
return -1;
}
}
/* @UNSAFE: last block ends with LF */
return -1;
}
return 1;
}
{
int ret;
&lock_status);
return ret;
} else {
i_error("%s: Metadata changed unexpectedly",
ret = 0;
}
return ret;
}
{
char space[DBOX_EXTRA_SPACE];
int ret;
/* nothing to write */
return 1;
}
if (file->maildir_file)
return 0;
sizeof(struct dbox_metadata_header);
/* skip as many metadata fields from beginning as we can */
for (j = 0; j < changes_count; j++) {
break;
}
if (j != changes_count)
break;
}
last_change_len = orig_len = 0;
/* overwrite existing metadata fields */
for (; i < count; i++) {
for (j = 0; j < changes_count; j++) {
break;
}
if (j != changes_count) {
} else {
}
}
/* add new metadata */
for (j = 0; j < changes_count; j++) {
for (i = 0; i < count; i++) {
break;
}
if (i == count) {
}
}
return ret;
}
}
if (ret < 0) {
return -1;
}
return 1;
}
{
int ret;
);
return ret;
}
{
struct dbox_metadata_header metadata_hdr;
char space[DBOX_EXTRA_SPACE];
unsigned int i, j, count, changes_count;
sizeof(metadata_hdr.magic_post));
return -1;
for (i = 0; i < count; i++) {
return -1;
}
} else {
/* write unmodified metadata */
for (i = 0; i < count; i++) {
for (j = 0; j < changes_count; j++) {
break;
}
if (j == changes_count) {
return -1;
return -1;
}
}
/* write modified metadata */
for (i = 0; i < changes_count; i++) {
return -1;
}
}
return -1;
return 0;
}
{
const struct dbox_mail_index_record *dbox_rec;
const void *data;
bool expunged;
if (expunged)
return FALSE;
if ((uid & DBOX_FILE_ID_FLAG_UID) != 0) {
/* something's broken, we can't handle this high UIDs */
return FALSE;
}
*offset_r = 0;
} else {
}
return TRUE;
}
{
unsigned int i;
for (i = 0; i < DBOX_METADATA_FLAGS_COUNT; i++) {
if ((flags & dbox_mail_flags_map[i]) != 0)
else
}
}
const struct mail_keywords *keywords)
{
const char *const *keyword_names;
unsigned int i, keyword_names_count;
return;
}
}
{
sizeof(dbox_msg_hdr->magic_pre));
sizeof(dbox_msg_hdr->message_size_hex));
}