]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: renaming mailboxes under different parent was broken in fs layout
authorTimo Sirainen <tss@iki.fi>
Fri, 29 Jul 2011 09:25:52 +0000 (12:25 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 29 Jul 2011 09:25:52 +0000 (12:25 +0300)
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.

src/lib-storage/list/mailbox-list-fs.c

index a413302077571a0dfdcfb788e360eaac8480f460..38e985249317229a61a46705435613c0cb0ddb6c 100644 (file)
@@ -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);