]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Mailbox rename shouldn't auto-rmdir parent index dirs with ITERINDEX
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 25 Jul 2017 12:54:37 +0000 (15:54 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 25 Jul 2017 19:15:19 +0000 (22:15 +0300)
For example:
 - create a/b
 - rename a/b c

This resulted in "a" existing in mail root directory, but not in index
directory. With ITERINDEX this meant that the "a" was lost.

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

index 37f7a19bff0fc6b621d1f6c5813e51e62ef785c4..5112c9e672b2af7d6a62c8a705b1a0788614b405 100644 (file)
@@ -256,12 +256,35 @@ int mailbox_list_delete_mailbox_nonrecursive(struct mailbox_list *list,
        return 0;
 }
 
+static bool mailbox_list_path_is_index(struct mailbox_list *list,
+                                      enum mailbox_list_path_type type)
+{
+       const char *index_root, *type_root;
+
+       if (type == MAILBOX_LIST_PATH_TYPE_INDEX)
+               return TRUE;
+
+       /* e.g. CONTROL dir could point to the same INDEX dir. */
+       type_root = mailbox_list_get_root_forced(list, type);
+       index_root = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_INDEX);
+       return strcmp(type_root, index_root) == 0;
+}
+
 void mailbox_list_delete_until_root(struct mailbox_list *list, const char *path,
                                    enum mailbox_list_path_type type)
 {
        const char *root_dir, *p;
        size_t len;
 
+       if (list->set.iter_from_index_dir &&
+           mailbox_list_path_is_index(list, type)) {
+               /* Don't auto-rmdir parent index directories with ITERINDEX.
+                  Otherwise it'll get us into inconsistent state with a
+                  \NoSelect mailbox in the mail directory but not in index
+                  directory. */
+               return;
+       }
+
        root_dir = mailbox_list_get_root_forced(list, type);
        if (strncmp(path, root_dir, strlen(root_dir)) != 0) {
                /* mbox workaround: name=child/box, root_dir=mail/.imap/,
@@ -350,18 +373,10 @@ static int mailbox_list_try_delete(struct mailbox_list *list, const char *name,
                }
        }
 
-       if (!list->set.iter_from_index_dir ||
-           type != MAILBOX_LIST_PATH_TYPE_INDEX) {
-               /* Avoid leaving empty parent directories lying around.
-                  We don't want to do it though when we're iterating mailboxes
-                  from index directory, since it'll get us into inconsistent
-                  state with a \NoSelect mailbox in the mail directory but not
-                  in index directory.
-
-                  These parent directories' existence or removal doesn't
-                  affect our return value. */
-               mailbox_list_delete_until_root(list, path, type);
-       }
+       /* Avoid leaving empty parent directories lying around.
+          These parent directories' existence or removal doesn't
+          affect our return value. */
+       mailbox_list_delete_until_root(list, path, type);
        return ret;
 }