]> 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 08:49:41 +0000 (11:49 +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 9c3b26ad41062a2816134a6ed8509d446f72e5ce..49ef84bb49361486f278f4032d63e4a33fea02cf 100644 (file)
@@ -287,7 +287,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, *error;
+       const char *mailbox_path, *index_path, *path, *error;
        int ret;
 
        if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
@@ -296,6 +296,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 ||
@@ -326,9 +337,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;
 }