dovecot: Support for reading maildir files. This makes it possib...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Oct 21 18:58:04 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/416d9ee66047
changeset: 6600:416d9ee66047
user: Timo Sirainen <tss at iki.fi>
date: Sun Oct 21 18:58:00 2007 +0300
description:
Support for reading maildir files. This makes it possible to do a fast
maildir to dbox conversion by only renaming a few files.
diffstat:
10 files changed, 335 insertions(+), 37 deletions(-)
src/lib-storage/index/dbox/Makefile.am | 1
src/lib-storage/index/dbox/dbox-file-maildir.c | 85 ++++++++++++++++++
src/lib-storage/index/dbox/dbox-file-maildir.h | 7 +
src/lib-storage/index/dbox/dbox-file.c | 108 +++++++++++++++++++-----
src/lib-storage/index/dbox/dbox-file.h | 5 -
src/lib-storage/index/dbox/dbox-index.c | 52 ++++++++++-
src/lib-storage/index/dbox/dbox-index.h | 6 -
src/lib-storage/index/dbox/dbox-mail.c | 6 -
src/lib-storage/index/dbox/dbox-storage.h | 2
src/lib-storage/index/dbox/dbox-sync-rebuild.c | 100 ++++++++++++++++++++--
diffs (truncated from 729 to 300 lines):
diff -r a6f51026b969 -r 416d9ee66047 src/lib-storage/index/dbox/Makefile.am
--- a/src/lib-storage/index/dbox/Makefile.am Sun Oct 21 18:54:32 2007 +0300
+++ b/src/lib-storage/index/dbox/Makefile.am Sun Oct 21 18:58:00 2007 +0300
@@ -10,6 +10,7 @@ AM_CPPFLAGS = \
libstorage_dbox_a_SOURCES = \
dbox-file.c \
+ dbox-file-maildir.c \
dbox-index.c \
dbox-mail.c \
dbox-save.c \
diff -r a6f51026b969 -r 416d9ee66047 src/lib-storage/index/dbox/dbox-file-maildir.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/index/dbox/dbox-file-maildir.c Sun Oct 21 18:58:00 2007 +0300
@@ -0,0 +1,85 @@
+/* Copyright (c) 2007-2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+#include "dbox-storage.h"
+#include "../maildir/maildir-storage.h"
+#include "../maildir/maildir-filename.h"
+#include "dbox-file.h"
+#include "dbox-file-maildir.h"
+
+static const char *
+dbox_file_maildir_get_flags(struct dbox_file *file, enum dbox_metadata_key key)
+{
+ ARRAY_TYPE(keyword_indexes) keyword_indexes;
+ struct mail_keywords *keywords;
+ enum mail_flags flags;
+ string_t *str;
+ const char *fname;
+
+ if (file->mbox->maildir_sync_keywords == NULL)
+ return NULL;
+
+ fname = strrchr(file->path, '/');
+ i_assert(fname != NULL);
+ fname++;
+
+ t_array_init(&keyword_indexes, 32);
+ maildir_filename_get_flags(file->mbox->maildir_sync_keywords,
+ fname, &flags, &keyword_indexes);
+ str = t_str_new(64);
+ if (key == DBOX_METADATA_FLAGS)
+ dbox_mail_metadata_flags_append(str, flags);
+ else {
+ keywords = mail_index_keywords_create_from_indexes(
+ file->mbox->ibox.index, &keyword_indexes);
+ dbox_mail_metadata_keywords_append(file->mbox, str, keywords);
+ mail_index_keywords_free(&keywords);
+ }
+ return str_c(str);
+}
+
+const char *dbox_file_maildir_metadata_get(struct dbox_file *file,
+ enum dbox_metadata_key key)
+{
+ const char *fname;
+ struct stat st;
+ uoff_t size;
+
+ switch (key) {
+ case DBOX_METADATA_FLAGS:
+ case DBOX_METADATA_KEYWORDS:
+ return dbox_file_maildir_get_flags(file, key);
+ case DBOX_METADATA_RECEIVED_TIME:
+ case DBOX_METADATA_SAVE_TIME:
+ if (file->fd != -1) {
+ if (fstat(file->fd, &st) < 0) {
+ dbox_file_set_syscall_error(file, "fstat");
+ return NULL;
+ }
+ } else {
+ if (stat(file->path, &st) < 0) {
+ if (errno == ENOENT)
+ return NULL;
+ dbox_file_set_syscall_error(file, "stat");
+ return NULL;
+ }
+ }
+ if (key == DBOX_METADATA_RECEIVED_TIME)
+ return dec2str(st.st_mtime);
+ else
+ return dec2str(st.st_ctime);
+ case DBOX_METADATA_VIRTUAL_SIZE:
+ fname = strrchr(file->path, '/');
+ i_assert(fname != NULL);
+ maildir_filename_get_size(fname + 1, MAILDIR_EXTRA_VIRTUAL_SIZE,
+ &size);
+ return dec2str(size);
+ case DBOX_METADATA_EXPUNGED:
+ case DBOX_METADATA_EXT_REF:
+ case DBOX_METADATA_SPACE:
+ break;
+ }
+ return NULL;
+}
diff -r a6f51026b969 -r 416d9ee66047 src/lib-storage/index/dbox/dbox-file-maildir.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/index/dbox/dbox-file-maildir.h Sun Oct 21 18:58:00 2007 +0300
@@ -0,0 +1,7 @@
+#ifndef DBOX_FILE_MAILDIR_H
+#define DBOX_FILE_MAILDIR_H
+
+const char *dbox_file_maildir_metadata_get(struct dbox_file *file,
+ enum dbox_metadata_key key);
+
+#endif
diff -r a6f51026b969 -r 416d9ee66047 src/lib-storage/index/dbox/dbox-file.c
--- a/src/lib-storage/index/dbox/dbox-file.c Sun Oct 21 18:54:32 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-file.c Sun Oct 21 18:58:00 2007 +0300
@@ -12,6 +12,7 @@
#include "dbox-storage.h"
#include "dbox-index.h"
#include "dbox-file.h"
+#include "dbox-file-maildir.h"
#include <stdio.h>
#include <stdlib.h>
@@ -128,16 +129,29 @@ dbox_close_open_files(struct dbox_mailbo
}
static char *
-dbox_file_id_get_path(struct dbox_mailbox *mbox, unsigned int file_id)
-{
+dbox_file_id_get_path(struct dbox_mailbox *mbox, unsigned int file_id,
+ 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) {
file_id &= ~DBOX_FILE_ID_FLAG_UID;
return i_strdup_printf("%s/"DBOX_MAIL_FILE_UID_FORMAT,
mbox->path, file_id);
- } else {
- return i_strdup_printf("%s/"DBOX_MAIL_FILE_MULTI_FORMAT,
- mbox->path, file_id);
- }
+ }
+
+ rec = dbox_index_record_lookup(mbox->dbox_index, file_id);
+ if (rec != NULL && rec->status == DBOX_INDEX_FILE_STATUS_MAILDIR) {
+ /* data contains <uid> <filename> */
+ *maildir_file_r = TRUE;
+ p = strchr(rec->data, ' ');
+ return i_strdup_printf("%s/%s", mbox->path, p + 1);
+ }
+
+ return i_strdup_printf("%s/"DBOX_MAIL_FILE_MULTI_FORMAT,
+ mbox->path, file_id);
}
struct dbox_file *
@@ -145,6 +159,7 @@ dbox_file_init(struct dbox_mailbox *mbox
{
struct dbox_file *file;
unsigned int count;
+ bool maildir;
file = file_id == 0 ? NULL :
dbox_find_and_move_open_file(mbox, file_id);
@@ -162,7 +177,8 @@ dbox_file_init(struct dbox_mailbox *mbox
file->mbox = mbox;
if (file_id != 0) {
file->file_id = file_id;
- file->path = dbox_file_id_get_path(mbox, file_id);
+ file->path = dbox_file_id_get_path(mbox, file_id, &maildir);
+ file->maildir_file = maildir;
} else {
file->path = dbox_generate_tmp_filename(mbox->path);
}
@@ -173,23 +189,37 @@ dbox_file_init(struct dbox_mailbox *mbox
return file;
}
+struct dbox_file *
+dbox_file_init_new_maildir(struct dbox_mailbox *mbox, const char *fname)
+{
+ struct dbox_file *file;
+
+ file = dbox_file_init(mbox, 0);
+ file->maildir_file = TRUE;
+ file->path = i_strdup_printf("%s/%s", mbox->path, fname);
+ return file;
+}
+
int dbox_file_assign_id(struct dbox_file *file, unsigned int file_id)
{
char *new_path;
+ bool maildir;
i_assert(file->file_id == 0);
i_assert(file_id != 0);
- new_path = dbox_file_id_get_path(file->mbox, file_id);
- if (rename(file->path, new_path) < 0) {
- mail_storage_set_critical(file->mbox->ibox.box.storage,
- "rename(%s, %s) failed: %m", file->path, new_path);
- i_free(new_path);
- return -1;
- }
-
- i_free(file->path);
- file->path = new_path;
+ if (!file->maildir_file) {
+ new_path = dbox_file_id_get_path(file->mbox, file_id, &maildir);
+ if (rename(file->path, new_path) < 0) {
+ mail_storage_set_critical(file->mbox->ibox.box.storage,
+ "rename(%s, %s) failed: %m",
+ file->path, new_path);
+ i_free(new_path);
+ return -1;
+ }
+ i_free(file->path);
+ file->path = new_path;
+ }
file->file_id = file_id;
array_append(&file->mbox->open_files, &file, 1);
@@ -252,7 +282,7 @@ bool dbox_file_can_append(struct dbox_fi
bool dbox_file_can_append(struct dbox_file *file, uoff_t mail_size)
{
if (file->nonappendable)
- return 0;
+ return FALSE;
if (file->append_offset == 0) {
/* messages have been expunged */
@@ -352,7 +382,8 @@ static int dbox_file_open(struct dbox_fi
}
file->input = i_stream_create_fd(file->fd, MAIL_READ_BLOCK_SIZE, FALSE);
- return !read_header ? 1 : dbox_file_read_header(file);
+ return !read_header || file->maildir_file ? 1 :
+ dbox_file_read_header(file);
}
static int dbox_file_create(struct dbox_file *file)
@@ -406,6 +437,30 @@ int dbox_file_open_or_create(struct dbox
return dbox_file_open(file, read_header, deleted_r);
}
+static int
+dbox_file_get_maildir_data(struct dbox_file *file, uint32_t *uid_r,
+ uoff_t *physical_size_r)
+{
+ struct dbox_index_record *rec;
+ struct stat st;
+
+ if (fstat(file->fd, &st) < 0) {
+ dbox_file_set_syscall_error(file, "fstat");
+ return -1;
+ }
+
+ rec = dbox_index_record_lookup(file->mbox->dbox_index, file->file_id);
+ if (rec == NULL) {
+ /* should happen only when we're rebuilding the index */
+ *uid_r = 0;
+ } else {
+ i_assert(rec->status == DBOX_INDEX_FILE_STATUS_MAILDIR);
+ *uid_r = strtoul(rec->data, NULL, 10);
+ }
+ *physical_size_r = st.st_size;
+ return 1;
+}
+
static int dbox_file_read_mail_header(struct dbox_file *file, uint32_t *uid_r,
uoff_t *physical_size_r)
{
@@ -413,6 +468,9 @@ static int dbox_file_read_mail_header(st
const unsigned char *data;
size_t size;
int ret;
+
+ if (file->maildir_file)
+ return dbox_file_get_maildir_data(file, uid_r, physical_size_r);
ret = i_stream_read_data(file->input, &data, &size,
file->msg_header_size - 1);
@@ -627,6 +685,9 @@ uoff_t dbox_file_get_metadata_offset(str
uoff_t physical_size)
{
if (offset == 0) {
+ if (file->maildir_file)
+ return 0;
+
i_assert(file->file_header_size != 0);
offset = file->file_header_size;
}
@@ -683,6 +744,12 @@ int dbox_file_metadata_seek(struct dbox_
}
file->metadata_read_offset = 0;
+ if (file->maildir_file) {
+ /* no metadata in maildir files, but we do later some kludging
More information about the dovecot-cvs
mailing list