From: Timo Sirainen Date: Fri, 29 Jul 2011 09:25:52 +0000 (+0300) Subject: lib-storage: renaming mailboxes under different parent was broken in fs layout X-Git-Tag: 2.0.14~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=253201e2b423d3eceb6a8b41cb3493edeab4d224;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: renaming mailboxes under different parent was broken in fs layout If alt storage was used with sdbox or if index or control dirs were used, renaming "foo" to "bar/foo" would result "foo" not being renamed for those directories. --- diff --git a/src/lib-storage/list/mailbox-list-fs.c b/src/lib-storage/list/mailbox-list-fs.c index a413302077..38e9852493 100644 --- a/src/lib-storage/list/mailbox-list-fs.c +++ b/src/lib-storage/list/mailbox-list-fs.c @@ -466,7 +466,8 @@ static int rename_dir(struct mailbox_list *oldlist, const char *oldname, struct mailbox_list *newlist, const char *newname, enum mailbox_list_path_type type, bool rmdir_parent) { - const char *oldpath, *newpath, *p; + struct stat st; + const char *oldpath, *newpath, *p, *oldparent, *newparent; oldpath = mailbox_list_get_path(oldlist, oldname, type); newpath = mailbox_list_get_path(newlist, newname, type); @@ -474,6 +475,30 @@ static int rename_dir(struct mailbox_list *oldlist, const char *oldname, if (strcmp(oldpath, newpath) == 0) return 0; + p = strrchr(oldpath, '/'); + oldparent = p == NULL ? "/" : t_strdup_until(oldpath, p); + p = strrchr(newpath, '/'); + newparent = p == NULL ? "/" : t_strdup_until(newpath, p); + + if (strcmp(oldparent, newparent) != 0 && stat(oldpath, &st) == 0) { + /* make sure the newparent exists */ + mode_t mode; + gid_t gid; + const char *origin; + + mailbox_list_get_dir_permissions(newlist, NULL, &mode, + &gid, &origin); + if (mkdir_parents_chgrp(newparent, mode, gid, origin) < 0 && + errno != EEXIST) { + if (mailbox_list_set_error_from_errno(oldlist)) + return -1; + + mailbox_list_set_critical(oldlist, + "mkdir_parents(%s) failed: %m", newparent); + return -1; + } + } + if (rename(oldpath, newpath) < 0 && errno != ENOENT) { mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m", oldpath, newpath);