dovecot: Support for looking up dbox files from an alternative d...

dovecot at dovecot.org dovecot at dovecot.org
Sat Nov 3 16:17:06 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/4a3cc2968040
changeset: 6668:4a3cc2968040
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Nov 03 16:09:05 2007 +0200
description:
Support for looking up dbox files from an alternative directory if they're
not found from the primary directory.

diffstat:

14 files changed, 209 insertions(+), 90 deletions(-)
src/lib-storage/index/cydir/cydir-storage.c     |    3 
src/lib-storage/index/dbox/dbox-file-maildir.c  |   16 --
src/lib-storage/index/dbox/dbox-file.c          |  127 ++++++++++++++++-------
src/lib-storage/index/dbox/dbox-file.h          |    8 +
src/lib-storage/index/dbox/dbox-index.c         |   14 +-
src/lib-storage/index/dbox/dbox-save.c          |   18 +--
src/lib-storage/index/dbox/dbox-storage.c       |   44 ++++++-
src/lib-storage/index/dbox/dbox-storage.h       |    3 
src/lib-storage/index/dbox/dbox-sync-file.c     |   38 +++++-
src/lib-storage/index/dbox/dbox-sync-rebuild.c  |   13 +-
src/lib-storage/index/maildir/maildir-storage.c |    2 
src/lib-storage/index/mbox/mbox-storage.c       |    3 
src/lib-storage/mailbox-list-private.h          |    3 
src/lib-storage/mailbox-list.c                  |    7 +

diffs (truncated from 811 to 300 lines):

diff -r b6c76ea86e2a -r 4a3cc2968040 src/lib-storage/index/cydir/cydir-storage.c
--- a/src/lib-storage/index/cydir/cydir-storage.c	Sat Nov 03 14:55:14 2007 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Sat Nov 03 16:09:05 2007 +0200
@@ -58,7 +58,8 @@ cydir_get_list_settings(struct mailbox_l
 
 	if (debug)
 		i_info("cydir: data=%s", data);
-	return mailbox_list_settings_parse(data, list_set, layout_r, error_r);
+	return mailbox_list_settings_parse(data, list_set, layout_r, NULL,
+					   error_r);
 }
 
 static struct mail_storage *cydir_alloc(void)
diff -r b6c76ea86e2a -r 4a3cc2968040 src/lib-storage/index/dbox/dbox-file-maildir.c
--- a/src/lib-storage/index/dbox/dbox-file-maildir.c	Sat Nov 03 14:55:14 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-file-maildir.c	Sat Nov 03 16:09:05 2007 +0200
@@ -16,18 +16,13 @@ dbox_file_maildir_get_flags(struct dbox_
 	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);
+				   file->fname, &flags, &keyword_indexes);
 	str = t_str_new(64);
 	if (key == DBOX_METADATA_FLAGS)
 		dbox_mail_metadata_flags_append(str, flags);
@@ -43,7 +38,6 @@ const char *dbox_file_maildir_metadata_g
 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;
 
@@ -59,7 +53,7 @@ const char *dbox_file_maildir_metadata_g
 				return NULL;
 			}
 		} else {
-			if (stat(file->path, &st) < 0) {
+			if (stat(dbox_file_get_path(file), &st) < 0) {
 				if (errno == ENOENT)
 					return NULL;
 				dbox_file_set_syscall_error(file, "stat");
@@ -71,10 +65,8 @@ const char *dbox_file_maildir_metadata_g
 		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);
+		maildir_filename_get_size(file->fname,
+					  MAILDIR_EXTRA_VIRTUAL_SIZE, &size);
 		return dec2str(size);
 	case DBOX_METADATA_EXPUNGED:
 	case DBOX_METADATA_EXT_REF:
diff -r b6c76ea86e2a -r 4a3cc2968040 src/lib-storage/index/dbox/dbox-file.c
--- a/src/lib-storage/index/dbox/dbox-file.c	Sat Nov 03 14:55:14 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-file.c	Sat Nov 03 16:09:05 2007 +0200
@@ -33,12 +33,12 @@ char dbox_mail_flag_chars[DBOX_METADATA_
 
 static int dbox_file_metadata_skip_header(struct dbox_file *file);
 
-static char *dbox_generate_tmp_filename(const char *path)
+static char *dbox_generate_tmp_filename(void)
 {
 	static unsigned int create_count = 0;
 
-	return i_strdup_printf("%s/temp.%s.P%sQ%uM%s.%s",
-			       path, dec2str(ioloop_timeval.tv_sec), my_pid,
+	return i_strdup_printf("temp.%s.P%sQ%uM%s.%s",
+			       dec2str(ioloop_timeval.tv_sec), my_pid,
 			       create_count++,
 			       dec2str(ioloop_timeval.tv_usec), my_hostname);
 }
@@ -46,14 +46,16 @@ void dbox_file_set_syscall_error(struct 
 void dbox_file_set_syscall_error(struct dbox_file *file, const char *function)
 {
 	mail_storage_set_critical(file->mbox->ibox.box.storage,
-				  "%s(%s) failed: %m", function, file->path);
+				  "%s(%s) failed: %m", function,
+				  dbox_file_get_path(file));
 }
 
 static void
 dbox_file_set_corrupted(struct dbox_file *file, const char *reason)
 {
 	mail_storage_set_critical(file->mbox->ibox.box.storage,
-				  "%s corrupted: %s", file->path, reason);
+				  "%s corrupted: %s", dbox_file_get_path(file),
+				  reason);
 }
 
 
@@ -91,7 +93,8 @@ static void dbox_file_free(struct dbox_f
 			dbox_file_set_syscall_error(file, "close");
 		file->fd = -1;
 	}
-	i_free(file->path);
+	i_free(file->current_path);
+	i_free(file->fname);
 	i_free(file);
 }
 
@@ -129,8 +132,8 @@ dbox_close_open_files(struct dbox_mailbo
 }
 
 static char *
-dbox_file_id_get_path(struct dbox_mailbox *mbox, unsigned int file_id,
-		      bool *maildir_file_r)
+dbox_file_id_get_fname(struct dbox_mailbox *mbox, unsigned int file_id,
+		       bool *maildir_file_r)
 {
 	struct dbox_index_record *rec;
 	const char *p;
@@ -138,8 +141,7 @@ dbox_file_id_get_path(struct dbox_mailbo
 	*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);
+		return i_strdup_printf(DBOX_MAIL_FILE_UID_FORMAT, file_id);
 	}
 
 	rec = dbox_index_record_lookup(mbox->dbox_index, file_id);
@@ -147,11 +149,10 @@ dbox_file_id_get_path(struct dbox_mailbo
 		/* 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);
+		return i_strdup_printf("%s", p + 1);
+	}
+
+	return i_strdup_printf(DBOX_MAIL_FILE_MULTI_FORMAT, file_id);
 }
 
 struct dbox_file *
@@ -177,10 +178,16 @@ 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, &maildir);
+		file->fname = dbox_file_id_get_fname(mbox, file_id, &maildir);
 		file->maildir_file = maildir;
 	} else {
-		file->path = dbox_generate_tmp_filename(mbox->path);
+		file->fname = dbox_generate_tmp_filename();
+	}
+	if (file->maildir_file || file_id == 0) {
+		/* newly created files and maildir files always exist in the
+		   primary path */
+		file->current_path =
+			i_strdup_printf("%s/%s", mbox->path, file->fname);
 	}
 	file->fd = -1;
 
@@ -196,33 +203,41 @@ dbox_file_init_new_maildir(struct dbox_m
 
 	file = dbox_file_init(mbox, 0);
 	file->maildir_file = TRUE;
-	file->path = i_strdup_printf("%s/%s", mbox->path, fname);
+	file->fname = i_strdup(fname);
 	return file;
 }
 
 int dbox_file_assign_id(struct dbox_file *file, unsigned int file_id)
 {
-	char *new_path;
+	struct dbox_mailbox *mbox = file->mbox;
+	const char *old_path;
+	char *new_fname, *new_path;
 	bool maildir;
 
 	i_assert(file->file_id == 0);
 	i_assert(file_id != 0);
 
 	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,
+		old_path = dbox_file_get_path(file);
+		new_fname = dbox_file_id_get_fname(mbox, file_id, &maildir);
+		new_path = i_strdup_printf("%s/%s", mbox->path, new_fname);
+
+		if (rename(old_path, new_path) < 0) {
+			mail_storage_set_critical(mbox->ibox.box.storage,
 						  "rename(%s, %s) failed: %m",
-						  file->path, new_path);
+						  old_path, new_path);
+			i_free(new_fname);
 			i_free(new_path);
 			return -1;
 		}
-		i_free(file->path);
-		file->path = new_path;
+		i_free(file->fname);
+		i_free(file->current_path);
+		file->fname = new_fname;
+		file->current_path = new_path;
 	}
 
 	file->file_id = file_id;
-	array_append(&file->mbox->open_files, &file, 1);
+	array_append(&mbox->open_files, &file, 1);
 	return 0;
 }
 
@@ -362,23 +377,53 @@ static int dbox_file_read_header(struct 
 	return dbox_file_parse_header(file, line) < 0 ? 0 : 1;
 }
 
+static int dbox_file_open_fd(struct dbox_file *file)
+{
+	const char *path;
+	int i;
+
+	/* try the primary path first */
+	path = t_strdup_printf("%s/%s", file->mbox->path, file->fname);
+	for (i = 0;; i++) {
+		file->fd = open(path, O_RDWR);
+		if (file->fd != -1)
+			break;
+
+		if (errno != ENOENT) {
+			mail_storage_set_critical(file->mbox->ibox.box.storage,
+						  "open(%s) failed: %m", path);
+			return -1;
+		}
+
+		if (file->mbox->alt_path == NULL || i == 1) {
+			/* file doesn't exist */
+			return 0;
+		}
+
+		/* try the alternative path */
+		path = t_strdup_printf("%s/%s", file->mbox->alt_path,
+				       file->fname);
+	}
+	return 1;
+}
+
 static int dbox_file_open(struct dbox_file *file, bool read_header,
 			  bool *deleted_r)
 {
+	int ret;
+
 	i_assert(file->input == NULL);
 
 	*deleted_r = FALSE;
 
-	if (file->fd == -1)
-		file->fd = open(file->path, O_RDWR);
 	if (file->fd == -1) {
-		if (errno == ENOENT) {
+		ret = dbox_file_open_fd(file);
+		if (ret <= 0) {
+			if (ret < 0)
+				return -1;
 			*deleted_r = TRUE;
 			return 1;
 		}
-
-		dbox_file_set_syscall_error(file, "open");
-		return -1;
 	}
 
 	file->input = i_stream_create_fd(file->fd, MAIL_READ_BLOCK_SIZE, FALSE);
@@ -393,10 +438,14 @@ static int dbox_file_create(struct dbox_
 
 	i_assert(file->fd == -1);
 
-	file->fd = open(file->path, O_RDWR | O_CREAT | O_TRUNC, 0600);
+	if (file->current_path == NULL) {
+		file->current_path =
+			i_strdup_printf("%s/%s", file->mbox->path, file->fname);
+	}
+	file->fd = open(file->current_path, O_RDWR | O_CREAT | O_TRUNC, 0600);
 	if (file->fd == -1) {
 		mail_storage_set_critical(file->mbox->ibox.box.storage,
-			"open(%s, O_CREAT) failed: %m", file->path);
+			"open(%s, O_CREAT) failed: %m", file->current_path);
 		return -1;
 	}
 	file->output = o_stream_create_fd_file(file->fd, 0, FALSE);
@@ -435,6 +484,13 @@ int dbox_file_open_or_create(struct dbox
 		return 1;


More information about the dovecot-cvs mailing list