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