dovecot-2.0: Implemented initial support for renaming mailboxes ...
dovecot at dovecot.org
dovecot at dovecot.org
Sat May 23 02:16:51 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/c86b65e4a510
changeset: 9353:c86b65e4a510
user: Timo Sirainen <tss at iki.fi>
date: Fri May 22 19:16:03 2009 -0400
description:
Implemented initial support for renaming mailboxes across namespaces.
diffstat:
12 files changed, 348 insertions(+), 222 deletions(-)
src/imap/cmd-rename.c | 41 +++----
src/lib-storage/index/dbox/dbox-storage.c | 122 ++++++++++++++---------
src/lib-storage/index/maildir/maildir-storage.c | 26 ++--
src/lib-storage/index/shared/shared-list.c | 74 +++++++------
src/lib-storage/list/mailbox-list-fs.c | 99 +++++++++++++-----
src/lib-storage/list/mailbox-list-maildir.c | 73 +++++++------
src/lib-storage/mailbox-list-private.h | 11 +-
src/lib-storage/mailbox-list.c | 43 ++++++--
src/lib-storage/mailbox-list.h | 16 +--
src/plugins/acl/acl-mailbox-list.c | 28 +++--
src/plugins/listescape/listescape-plugin.c | 20 ++-
src/plugins/mail-log/mail-log-plugin.c | 17 +--
diffs (truncated from 965 to 300 lines):
diff -r 9f2403f3e345 -r c86b65e4a510 src/imap/cmd-rename.c
--- a/src/imap/cmd-rename.c Fri May 22 18:28:08 2009 -0400
+++ b/src/imap/cmd-rename.c Fri May 22 19:16:03 2009 -0400
@@ -7,8 +7,8 @@ bool cmd_rename(struct client_command_co
bool cmd_rename(struct client_command_context *cmd)
{
struct mail_storage *old_storage, *new_storage;
- struct mailbox_list *list;
- struct mail_namespace *ns;
+ struct mailbox_list *old_list, *new_list;
+ struct mail_namespace *old_ns;
const char *oldname, *newname;
unsigned int oldlen;
@@ -22,33 +22,30 @@ bool cmd_rename(struct client_command_co
old_storage = client_find_storage(cmd, &oldname);
if (old_storage == NULL)
return TRUE;
+ old_list = mail_storage_get_list(old_storage);
new_storage = client_find_storage(cmd, &newname);
if (new_storage == NULL)
return TRUE;
+ new_list = mail_storage_get_list(new_storage);
- if (old_storage != new_storage) {
- client_send_tagline(cmd,
- "NO Can't rename mailbox to another storage type.");
- return TRUE;
+ if (old_storage == new_storage) {
+ /* disallow box -> box/child, because it may break clients and
+ there's really no point in doing it anyway. */
+ old_ns = mailbox_list_get_namespace(old_list);
+ oldlen = strlen(oldname);
+ if (strncmp(oldname, newname, oldlen) == 0 &&
+ newname[oldlen] == old_ns->real_sep) {
+ client_send_tagline(cmd,
+ "NO Can't rename mailbox under its own child.");
+ return TRUE;
+ }
}
- /* disallow box -> box/child, because it may break clients and there's
- really no point in doing it anyway. */
- list = mail_storage_get_list(old_storage);
- ns = mailbox_list_get_namespace(list);
- oldlen = strlen(oldname);
- if (strncmp(oldname, newname, oldlen) == 0 &&
- newname[oldlen] == ns->real_sep) {
- client_send_tagline(cmd,
- "NO Can't rename mailbox under its own child.");
- return TRUE;
- }
-
- if (mailbox_list_rename_mailbox(list, oldname, newname) < 0)
- client_send_list_error(cmd, list);
- else {
+ if (mailbox_list_rename_mailbox(old_list, oldname,
+ new_list, newname, TRUE) < 0)
+ client_send_list_error(cmd, old_list);
+ else
client_send_tagline(cmd, "OK Rename completed.");
- }
return TRUE;
}
diff -r 9f2403f3e345 -r c86b65e4a510 src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c Fri May 22 18:28:08 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.c Fri May 22 19:16:03 2009 -0400
@@ -39,11 +39,14 @@ static int
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);
+dbox_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
+ struct mailbox_list *newlist, const char *newname,
+ bool rename_children);
+static int
+dbox_list_rename_mailbox_pre(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ const char *newname);
static int dbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
const char *dir, const char *fname,
const char *mailbox_name,
@@ -605,47 +608,59 @@ dbox_list_delete_mailbox(struct mailbox_
return -1;
}
-static bool
-dbox_list_rename_get_alt_paths(struct mailbox_list *list,
- const char *oldname, const char *newname,
+static int
+dbox_list_rename_get_alt_paths(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ const char *newname,
+ enum mailbox_list_path_type path_type,
const char **oldpath_r, const char **newpath_r)
{
- struct dbox_storage *storage = DBOX_LIST_CONTEXT(list);
+ struct dbox_storage *oldstorage = DBOX_LIST_CONTEXT(oldlist);
+ struct dbox_storage *newstorage = DBOX_LIST_CONTEXT(newlist);
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);
+ path = mailbox_list_get_path(oldlist, oldname, path_type);
+ *oldpath_r = dbox_get_alt_path(oldstorage, 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)
+ return 0;
+
+ path = mailbox_list_get_path(newlist, newname, path_type);
+ *newpath_r = dbox_get_alt_path(newstorage, path);
+ if (*newpath_r == NULL) {
+ /* destination dbox storage doesn't have alt-path defined.
+ we can't do the rename easily. */
+ mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
+ "Can't rename mailboxes across specified storages.");
+ return -1;
+ }
+ return 1;
+}
+
+static int
+dbox_list_rename_mailbox_pre(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ 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;
+ int ret;
+
+ ret = dbox_list_rename_get_alt_paths(oldlist, oldname, newlist, newname,
+ MAILBOX_LIST_PATH_TYPE_DIR,
+ &alt_oldpath, &alt_newpath);
+ if (ret <= 0)
+ return ret;
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_EXISTS,
+ mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
"Target mailbox already exists");
return -1;
} else if (errno != ENOENT) {
- mailbox_list_set_critical(list, "stat(%s) failed: %m",
+ mailbox_list_set_critical(oldlist, "stat(%s) failed: %m",
alt_newpath);
return -1;
}
@@ -653,25 +668,42 @@ dbox_list_rename_mailbox_pre(struct mail
}
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;
+dbox_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
+ struct mailbox_list *newlist, const char *newname,
+ bool rename_children)
+{
+ struct dbox_storage *oldstorage = DBOX_LIST_CONTEXT(oldlist);
+ enum mailbox_list_path_type path_type;
+ const char *alt_oldpath, *alt_newpath, *path;
+ int ret;
+
+ if (oldstorage->list_module_ctx.super.
+ rename_mailbox(oldlist, oldname, newlist, newname,
+ rename_children) < 0)
+ return -1;
+
+ path_type = rename_children ? MAILBOX_LIST_PATH_TYPE_DIR :
+ MAILBOX_LIST_PATH_TYPE_MAILBOX;
+ ret = dbox_list_rename_get_alt_paths(oldlist, oldname, newlist, newname,
+ path_type, &alt_oldpath,
+ &alt_newpath);
+ if (ret <= 0)
+ return ret;
if (rename(alt_oldpath, alt_newpath) == 0) {
/* ok */
+ if (!rename_children) {
+ path = mailbox_list_get_path(oldlist, oldname,
+ MAILBOX_LIST_PATH_TYPE_DIR);
+ if (rmdir(path) < 0 &&
+ errno != ENOENT && errno != ENOTEMPTY) {
+ mailbox_list_set_critical(oldlist,
+ "rmdir(%s) failed: %m", path);
+ }
+ }
} else if (errno != ENOENT) {
/* renaming is done already, so just log the error */
- mailbox_list_set_critical(list, "rename(%s, %s) failed: %m",
+ mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
alt_oldpath, alt_newpath);
}
return 0;
diff -r 9f2403f3e345 -r c86b65e4a510 src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c Fri May 22 18:28:08 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.c Fri May 22 19:16:03 2009 -0400
@@ -43,8 +43,9 @@ static int
static int
maildir_list_delete_mailbox(struct mailbox_list *list, const char *name);
static int
-maildir_list_rename_mailbox(struct mailbox_list *list,
- const char *oldname, const char *newname);
+maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
+ struct mailbox_list *newlist, const char *newname,
+ bool rename_children);
static int
maildir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
const char *dir, const char *fname,
@@ -829,28 +830,31 @@ maildir_list_delete_mailbox(struct mailb
return 0;
}
-static int maildir_list_rename_mailbox(struct mailbox_list *list,
- const char *oldname, const char *newname)
-{
- struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+static int
+maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
+ struct mailbox_list *newlist, const char *newname,
+ bool rename_children)
+{
+ struct maildir_storage *oldstorage = MAILDIR_LIST_CONTEXT(oldlist);
const char *path1, *path2;
if (strcmp(oldname, "INBOX") == 0) {
/* INBOX often exists as the root ~/Maildir.
We can't rename it then. */
- path1 = mailbox_list_get_path(list, oldname,
+ path1 = mailbox_list_get_path(oldlist, oldname,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
- path2 = mailbox_list_get_path(list, NULL,
+ path2 = mailbox_list_get_path(oldlist, NULL,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
if (strcmp(path1, path2) == 0) {
- mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
+ mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
"Renaming INBOX isn't supported.");
return -1;
}
}
- return storage->list_module_ctx.super.
- rename_mailbox(list, oldname, newname);
+ return oldstorage->list_module_ctx.super.
+ rename_mailbox(oldlist, oldname, newlist, newname,
+ rename_children);
}
static int maildir_storage_mailbox_close(struct mailbox *box)
diff -r 9f2403f3e345 -r c86b65e4a510 src/lib-storage/index/shared/shared-list.c
--- a/src/lib-storage/index/shared/shared-list.c Fri May 22 18:28:08 2009 -0400
+++ b/src/lib-storage/index/shared/shared-list.c Fri May 22 19:16:03 2009 -0400
@@ -245,52 +245,62 @@ shared_list_delete_mailbox(struct mailbo
return ret;
}
-static int shared_list_rename_get_ns(struct mailbox_list *list,
- const char **oldname, const char **newname,
+static int shared_list_rename_get_ns(struct mailbox_list *oldlist,
+ const char **oldname,
+ struct mailbox_list *newlist,
+ const char **newname,
More information about the dovecot-cvs
mailing list