dovecot-2.0: [m]dbox: If alt-dir exists for a mailbox while tryi...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jun 29 00:01:02 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/ad122febbf26
changeset: 11652:ad122febbf26
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jun 28 22:00:58 2010 +0100
description:
[m]dbox: If alt-dir exists for a mailbox while trying to create it, rebuild mailbox indexes.
This makes sure that if there are any mails in the alt-dir, they become
visible rather than be overwritten.

diffstat:

 src/lib-storage/index/dbox-common/dbox-storage.c  |  53 ++++++++++++++++++++++++++
 src/lib-storage/index/dbox-common/dbox-storage.h  |   2 +
 src/lib-storage/index/dbox-multi/mdbox-storage.c  |   8 ++++
 src/lib-storage/index/dbox-single/sdbox-storage.c |  10 ++++-
 src/lib-storage/list/mailbox-list-fs.c            |  17 +--------
 5 files changed, 73 insertions(+), 17 deletions(-)

diffs (182 lines):

diff -r 243166e7dd2d -r ad122febbf26 src/lib-storage/index/dbox-common/dbox-storage.c
--- a/src/lib-storage/index/dbox-common/dbox-storage.c	Mon Jun 28 21:58:42 2010 +0100
+++ b/src/lib-storage/index/dbox-common/dbox-storage.c	Mon Jun 28 22:00:58 2010 +0100
@@ -10,6 +10,8 @@
 #include "dbox-storage.h"
 
 #include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
 
 void dbox_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
 				    struct mailbox_list_settings *set)
@@ -90,6 +92,36 @@
 	}
 }
 
+static int dir_is_empty(struct mail_storage *storage, const char *path)
+{
+	DIR *dir;
+	struct dirent *d;
+	int ret = 1;
+
+	dir = opendir(path);
+	if (dir == NULL) {
+		if (errno == ENOENT) {
+			/* race condition with DELETE/RENAME? */
+			return 1;
+		}
+		mail_storage_set_critical(storage, "opendir(%s) failed: %m",
+					  path);
+		return -1;
+	}
+	while ((d = readdir(dir)) != NULL) {
+		if (*d->d_name == '.')
+			continue;
+
+		ret = 0;
+	}
+	if (closedir(dir) < 0) {
+		mail_storage_set_critical(storage, "closedir(%s) failed: %m",
+					  path);
+		ret = -1;
+	}
+	return ret;
+}
+
 int dbox_mailbox_create(struct mailbox *box,
 			const struct mailbox_update *update, bool directory)
 {
@@ -97,6 +129,8 @@
 	struct mail_index_sync_ctx *sync_ctx;
 	struct mail_index_view *view;
 	struct mail_index_transaction *trans;
+	const char *alt_path;
+	struct stat st;
 	int ret;
 
 	if (directory &&
@@ -106,6 +140,25 @@
 	if (index_storage_mailbox_open(box, FALSE) < 0)
 		return -1;
 
+	/* if alt path already exists and contains files, rebuild storage so
+	   that we don't start overwriting files. */
+	alt_path = mailbox_list_get_path(box->list, box->name,
+					 MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
+	if (alt_path != NULL && stat(alt_path, &st) == 0) {
+		ret = dir_is_empty(box->storage, alt_path);
+		if (ret < 0)
+			return -1;
+		if (ret == 0) {
+			mail_storage_set_critical(&storage->storage,
+				"Mailbox %s has existing files in alt path, "
+				"rebuilding storage to avoid losing messages",
+				box->vname);
+			storage->v.set_mailbox_corrupted(box);
+			return -1;
+		}
+		/* dir is empty, ignore it */
+	}
+
 	/* use syncing as a lock */
 	ret = mail_index_sync_begin(box->index, &sync_ctx, &view, &trans, 0);
 	if (ret <= 0) {
diff -r 243166e7dd2d -r ad122febbf26 src/lib-storage/index/dbox-common/dbox-storage.h
--- a/src/lib-storage/index/dbox-common/dbox-storage.h	Mon Jun 28 21:58:42 2010 +0100
+++ b/src/lib-storage/index/dbox-common/dbox-storage.h	Mon Jun 28 22:00:58 2010 +0100
@@ -39,6 +39,8 @@
 	int (*mailbox_create_indexes)(struct mailbox *box,
 				      const struct mailbox_update *update,
 				      struct mail_index_transaction *trans);
+	/* mark the mailbox corrupted */
+	void (*set_mailbox_corrupted)(struct mailbox *box);
 	/* mark the file corrupted */
 	void (*set_file_corrupted)(struct dbox_file *file);
 };
diff -r 243166e7dd2d -r ad122febbf26 src/lib-storage/index/dbox-multi/mdbox-storage.c
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Mon Jun 28 21:58:42 2010 +0100
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Mon Jun 28 22:00:58 2010 +0100
@@ -270,6 +270,13 @@
 	}
 }
 
+static void mdbox_set_mailbox_corrupted(struct mailbox *box)
+{
+	struct mdbox_storage *mstorage = (struct mdbox_storage *)box->storage;
+
+	mdbox_storage_set_corrupted(mstorage);
+}
+
 static void mdbox_set_file_corrupted(struct dbox_file *file)
 {
 	struct mdbox_storage *mstorage = (struct mdbox_storage *)file->storage;
@@ -426,5 +433,6 @@
 	mdbox_file_create_fd,
 	mdbox_mail_open,
 	mdbox_mailbox_create_indexes,
+	mdbox_set_mailbox_corrupted,
 	mdbox_set_file_corrupted
 };
diff -r 243166e7dd2d -r ad122febbf26 src/lib-storage/index/dbox-single/sdbox-storage.c
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Mon Jun 28 21:58:42 2010 +0100
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Mon Jun 28 22:00:58 2010 +0100
@@ -198,11 +198,18 @@
 	return ret;
 }
 
-static void sdbox_set_file_corrupted(struct dbox_file *file ATTR_UNUSED)
+static void sdbox_set_mailbox_corrupted(struct mailbox *box ATTR_UNUSED)
 {
 	/* FIXME */
 }
 
+static void sdbox_set_file_corrupted(struct dbox_file *_file)
+{
+	struct sdbox_file *file = (struct sdbox_file *)_file;
+
+	sdbox_set_mailbox_corrupted(&file->mbox->box);
+}
+
 static int
 sdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
 {
@@ -309,5 +316,6 @@
 	sdbox_file_create_fd,
 	sdbox_mail_open,
 	sdbox_mailbox_create_indexes,
+	sdbox_set_mailbox_corrupted,
 	sdbox_set_file_corrupted
 };
diff -r 243166e7dd2d -r ad122febbf26 src/lib-storage/list/mailbox-list-fs.c
--- a/src/lib-storage/list/mailbox-list-fs.c	Mon Jun 28 21:58:42 2010 +0100
+++ b/src/lib-storage/list/mailbox-list-fs.c	Mon Jun 28 22:00:58 2010 +0100
@@ -316,27 +316,12 @@
 fs_list_create_mailbox_dir(struct mailbox_list *list, const char *name,
 			   bool directory)
 {
-	const char *path, *alt_path, *gid_origin, *p;
-	struct stat st;
+	const char *path, *gid_origin, *p;
 	mode_t mode;
 	gid_t gid;
 	bool create_parent_dir;
 	int ret;
 
-	/* make sure the alt path doesn't exist yet. it shouldn't (except with
-	   race conditions with RENAME/DELETE), but if something crashed and
-	   left it lying around we don't want to start overwriting files in
-	   it. */
-	if (!directory) {
-		alt_path = mailbox_list_get_path(list, name,
-					MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
-		if (alt_path != NULL && stat(alt_path, &st) == 0) {
-			mailbox_list_set_error(list, MAIL_ERROR_EXISTS,
-					       "Mailbox already exists");
-			return -1;
-		}
-	}
-
 	path = mailbox_list_get_path(list, name,
 				     directory ? MAILBOX_LIST_PATH_TYPE_DIR :
 				     MAILBOX_LIST_PATH_TYPE_MAILBOX);


More information about the dovecot-cvs mailing list