dovecot-1.1: dbox: Fixes to creating, deleting and renaming mail...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Mar 5 03:53:43 EET 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/5193f5c6ab5d
changeset: 7355:5193f5c6ab5d
user: Timo Sirainen <tss at iki.fi>
date: Wed Mar 05 03:53:39 2008 +0200
description:
dbox: Fixes to creating, deleting and renaming mailboxes when using alt
directories.
diffstat:
4 files changed, 118 insertions(+), 11 deletions(-)
src/lib-storage/index/dbox/dbox-storage.c | 108 +++++++++++++++++++++++++--
src/lib-storage/list/mailbox-list-fs.c | 12 ++-
src/lib-storage/list/mailbox-list-maildir.c | 6 +
src/lib-storage/mailbox-list-private.h | 3
diffs (253 lines):
diff -r de47a37ca0c1 -r 5193f5c6ab5d src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c Wed Mar 05 02:59:55 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.c Wed Mar 05 03:53:39 2008 +0200
@@ -33,6 +33,12 @@ static MODULE_CONTEXT_DEFINE_INIT(dbox_m
static int
dbox_list_delete_mailbox(struct mailbox_list *list, const char *name);
+static int
+dbox_list_rename_mailbox(struct mailbox_list *list,
+ const char *oldname, const char *newname);
+static int
+dbox_list_rename_mailbox_pre(struct mailbox_list *list,
+ const char *oldname, const char *newname);
static int dbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
const char *dir, const char *fname,
enum mailbox_list_file_type type,
@@ -126,6 +132,8 @@ static int dbox_create(struct mail_stora
storage->alt_dir = p_strdup(_storage->pool, alt_dir);
_storage->list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
_storage->list->v.delete_mailbox = dbox_list_delete_mailbox;
+ _storage->list->v.rename_mailbox = dbox_list_rename_mailbox;
+ _storage->list->v.rename_mailbox_pre = dbox_list_rename_mailbox_pre;
MODULE_CONTEXT_SET_FULL(_storage->list, dbox_mailbox_list_module,
storage, &storage->list_module_ctx);
@@ -313,7 +321,8 @@ static int dbox_mailbox_create(struct ma
static int dbox_mailbox_create(struct mail_storage *_storage,
const char *name, bool directory ATTR_UNUSED)
{
- const char *path;
+ struct dbox_storage *storage = (struct dbox_storage *)_storage;
+ const char *path, *alt_path;
struct stat st;
path = mailbox_list_get_path(_storage->list, name,
@@ -324,6 +333,17 @@ static int dbox_mailbox_create(struct ma
return -1;
}
+ /* 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. */
+ alt_path = dbox_get_alt_path(storage, path);
+ if (alt_path != NULL && stat(alt_path, &st) == 0) {
+ mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
+ "Mailbox already exists");
+ return -1;
+ }
+
return create_dbox(_storage, path);
}
@@ -339,6 +359,8 @@ dbox_delete_nonrecursive(struct mailbox_
dir = opendir(path);
if (dir == NULL) {
+ if (errno == ENOENT)
+ return 0;
if (!mailbox_list_set_error_from_errno(list)) {
mailbox_list_set_critical(list,
"opendir(%s) failed: %m", path);
@@ -394,7 +416,7 @@ dbox_delete_nonrecursive(struct mailbox_
"can't delete it.", name));
return -1;
}
- return 0;
+ return 1;
}
static int
@@ -404,6 +426,7 @@ dbox_list_delete_mailbox(struct mailbox_
struct stat st;
const char *path, *alt_path;
bool deleted = FALSE;
+ int ret;
/* Make sure the indexes are closed before trying to delete the
directory that contains them. It can still fail with some NFS
@@ -418,11 +441,8 @@ dbox_list_delete_mailbox(struct mailbox_
/* check if the mailbox actually exists */
path = mailbox_list_get_path(list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (stat(path, &st) == 0) {
+ if ((ret = dbox_delete_nonrecursive(list, path, name)) > 0) {
/* delete the mailbox first */
- if (dbox_delete_nonrecursive(list, path, name) < 0)
- return -1;
-
alt_path = dbox_get_alt_path(storage, path);
if (alt_path != NULL) {
if (dbox_delete_nonrecursive(list, alt_path, name) < 0)
@@ -452,6 +472,10 @@ dbox_list_delete_mailbox(struct mailbox_
}
}
+ alt_path = dbox_get_alt_path(storage, path);
+ if (alt_path != NULL)
+ (void)rmdir(alt_path);
+
if (rmdir(path) == 0)
return 0;
else if (errno == ENOTEMPTY) {
@@ -465,6 +489,78 @@ dbox_list_delete_mailbox(struct mailbox_
path);
}
return -1;
+}
+
+static bool
+dbox_list_rename_get_alt_paths(struct mailbox_list *list,
+ const char *oldname, const char *newname,
+ const char **oldpath_r, const char **newpath_r)
+{
+ struct dbox_storage *storage = DBOX_LIST_CONTEXT(list);
+ const char *path;
+
+ if (storage->alt_dir == NULL)
+ return FALSE;
+
+ path = mailbox_list_get_path(list, oldname, MAILBOX_LIST_PATH_TYPE_DIR);
+ *oldpath_r = dbox_get_alt_path(storage, path);
+ if (*oldpath_r == NULL)
+ return FALSE;
+
+ path = mailbox_list_get_path(list, newname, MAILBOX_LIST_PATH_TYPE_DIR);
+ *newpath_r = dbox_get_alt_path(storage, path);
+ i_assert(*newpath_r != NULL);
+ return TRUE;
+}
+
+static int
+dbox_list_rename_mailbox_pre(struct mailbox_list *list,
+ const char *oldname, const char *newname)
+{
+ const char *alt_oldpath, *alt_newpath;
+ struct stat st;
+
+ if (!dbox_list_rename_get_alt_paths(list, oldname, newname,
+ &alt_oldpath, &alt_newpath))
+ return 0;
+
+ if (stat(alt_newpath, &st) == 0) {
+ /* race condition or a directory left there lying around?
+ safest to just report error. */
+ mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
+ "Target mailbox already exists");
+ return -1;
+ } else if (errno != ENOENT) {
+ mailbox_list_set_critical(list, "stat(%s) failed: %m",
+ alt_newpath);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+dbox_list_rename_mailbox(struct mailbox_list *list,
+ const char *oldname, const char *newname)
+{
+ struct dbox_storage *storage = DBOX_LIST_CONTEXT(list);
+ const char *alt_oldpath, *alt_newpath;
+
+ if (storage->list_module_ctx.super.rename_mailbox(list, oldname,
+ newname) < 0)
+ return -1;
+
+ if (!dbox_list_rename_get_alt_paths(list, oldname, newname,
+ &alt_oldpath, &alt_newpath))
+ return 0;
+
+ if (rename(alt_oldpath, alt_newpath) == 0) {
+ /* ok */
+ } else if (errno != ENOENT) {
+ /* renaming is done already, so just log the error */
+ mailbox_list_set_critical(list, "rename(%s, %s) failed: %m",
+ alt_oldpath, alt_newpath);
+ }
+ return 0;
}
static void dbox_notify_changes(struct mailbox *box)
diff -r de47a37ca0c1 -r 5193f5c6ab5d src/lib-storage/list/mailbox-list-fs.c
--- a/src/lib-storage/list/mailbox-list-fs.c Wed Mar 05 02:59:55 2008 +0200
+++ b/src/lib-storage/list/mailbox-list-fs.c Wed Mar 05 03:53:39 2008 +0200
@@ -285,9 +285,9 @@ static int fs_list_rename_mailbox(struct
struct stat st;
oldpath = mailbox_list_get_path(list, oldname,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ MAILBOX_LIST_PATH_TYPE_DIR);
newpath = mailbox_list_get_path(list, newname,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ MAILBOX_LIST_PATH_TYPE_DIR);
/* create the hierarchy */
p = strrchr(newpath, '/');
@@ -319,6 +319,11 @@ static int fs_list_rename_mailbox(struct
mailbox_list_set_critical(list, "lstat(%s) failed: %m",
newpath);
return -1;
+ }
+
+ if (list->v.rename_mailbox_pre != NULL) {
+ if (list->v.rename_mailbox_pre(list, oldname, newname) < 0)
+ return -1;
}
/* NOTE: renaming INBOX works just fine with us, it's simply recreated
@@ -372,6 +377,7 @@ struct mailbox_list fs_mailbox_list = {
NULL,
fs_list_set_subscribed,
fs_list_delete_mailbox,
- fs_list_rename_mailbox
+ fs_list_rename_mailbox,
+ NULL
}
};
diff -r de47a37ca0c1 -r 5193f5c6ab5d src/lib-storage/list/mailbox-list-maildir.c
--- a/src/lib-storage/list/mailbox-list-maildir.c Wed Mar 05 02:59:55 2008 +0200
+++ b/src/lib-storage/list/mailbox-list-maildir.c Wed Mar 05 03:53:39 2008 +0200
@@ -457,7 +457,8 @@ struct mailbox_list maildir_mailbox_list
NULL,
maildir_list_set_subscribed,
maildir_list_delete_mailbox,
- maildir_list_rename_mailbox
+ maildir_list_rename_mailbox,
+ NULL
}
};
@@ -482,6 +483,7 @@ struct mailbox_list imapdir_mailbox_list
NULL,
maildir_list_set_subscribed,
maildir_list_delete_mailbox,
- maildir_list_rename_mailbox
+ maildir_list_rename_mailbox,
+ NULL
}
};
diff -r de47a37ca0c1 -r 5193f5c6ab5d src/lib-storage/mailbox-list-private.h
--- a/src/lib-storage/mailbox-list-private.h Wed Mar 05 02:59:55 2008 +0200
+++ b/src/lib-storage/mailbox-list-private.h Wed Mar 05 03:53:39 2008 +0200
@@ -49,6 +49,9 @@ struct mailbox_list_vfuncs {
int (*delete_mailbox)(struct mailbox_list *list, const char *name);
int (*rename_mailbox)(struct mailbox_list *list, const char *oldname,
const char *newname);
+ /* called by rename_mailbox() just before running the actual rename() */
+ int (*rename_mailbox_pre)(struct mailbox_list *list,
+ const char *oldname, const char *newname);
};
struct mailbox_list_module_register {
More information about the dovecot-cvs
mailing list