]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix ITERINDEX to leave \NoSelect parents after deleting child mailbox
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 30 Jun 2017 10:46:22 +0000 (13:46 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 3 Jul 2017 12:25:56 +0000 (15:25 +0300)
For example if "a/b" was created and deleted, "a" should be left behind.
(Or at least it shouldn't have left "a" to mail root directory and kept it
invisible since it didn't exist in index dir.)

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

index c56e8701932ab6e493c4a59247628c597730d332..4fa15af9848ef06f25f48a1c7ed16b57185f26d8 100644 (file)
@@ -286,7 +286,7 @@ void mailbox_list_delete_until_root(struct mailbox_list *list, const char *path,
 static int mailbox_list_try_delete(struct mailbox_list *list, const char *name,
                                   enum mailbox_list_path_type type)
 {
-       const char *mailbox_path, *path;
+       const char *mailbox_path, *index_path, *path;
        int ret;
 
        if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
@@ -295,6 +295,17 @@ static int mailbox_list_try_delete(struct mailbox_list *list, const char *name,
            strcmp(path, mailbox_path) == 0)
                return 0;
 
+       if (type == MAILBOX_LIST_PATH_TYPE_CONTROL &&
+           mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX,
+                                 &index_path) > 0 &&
+           strcmp(index_path, path) == 0) {
+               /* CONTROL dir is the same as INDEX dir, which we already
+                  deleted. We don't want to continue especially with
+                  iter_from_index_dir=yes, because it could be deleting the
+                  index directory. */
+               return 0;
+       }
+
        /* Note that only ALT currently uses maildir_name in paths.
           INDEX and CONTROL don't. */
        if (type != MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX ||
@@ -325,9 +336,18 @@ static int mailbox_list_try_delete(struct mailbox_list *list, const char *name,
                }
        }
 
-       /* Avoid leaving empty parent directories lying around.
-          They don't affect our return value. */
-       mailbox_list_delete_until_root(list, path, type);
+       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);
+       }
        return ret;
 }