Mercurial > dovecot > core-2.2
changeset 22387:6cbca06276e6
lib-storage: Hide and rmdir \NoSelect leaf mailboxes with NO-NOSELECT
If the leaf is successfully rmdir()ed, rmdir() also its parents.
This doesn't work perfectly with if there are multiple levels of \NoSelect
mailboxes. For example with "a/b/c" the listing will already have returned
"a" and "a/b" before it reaches the "a/b/c" code, which will rmdir all of
them, but it's a bit too late at that point. It's too much work to fix
though, and the situation will be fixed on the next list anyway.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 25 Jul 2017 20:53:18 +0300 |
parents | 1534de106851 |
children | df373becc66c |
files | src/lib-storage/list/mailbox-list-delete.c src/lib-storage/list/mailbox-list-delete.h src/lib-storage/list/mailbox-list-fs-iter.c src/lib-storage/list/mailbox-list-index-iter.c src/lib-storage/list/mailbox-list-iter-private.h |
diffstat | 5 files changed, 58 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-delete.c Tue Jul 25 16:10:51 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-delete.c Tue Jul 25 20:53:18 2017 +0300 @@ -320,6 +320,24 @@ } } +void mailbox_list_delete_mailbox_until_root(struct mailbox_list *list, + const char *storage_name) +{ + enum mailbox_list_path_type types[] = { + MAILBOX_LIST_PATH_TYPE_DIR, + MAILBOX_LIST_PATH_TYPE_ALT_DIR, + MAILBOX_LIST_PATH_TYPE_CONTROL, + MAILBOX_LIST_PATH_TYPE_INDEX, + MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE, + }; + const char *path; + + for (unsigned int i = 0; i < N_ELEMENTS(types); i++) { + if (mailbox_list_get_path(list, storage_name, types[i], &path) > 0) + mailbox_list_delete_until_root(list, path, types[i]); + } +} + static int mailbox_list_try_delete(struct mailbox_list *list, const char *name, enum mailbox_list_path_type type) { @@ -463,4 +481,3 @@ } return -1; } -
--- a/src/lib-storage/list/mailbox-list-delete.h Tue Jul 25 16:10:51 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-delete.h Tue Jul 25 20:53:18 2017 +0300 @@ -65,6 +65,9 @@ The root isn't rmdir()ed. */ void mailbox_list_delete_until_root(struct mailbox_list *list, const char *path, enum mailbox_list_path_type type); +/* Call mailbox_list_delete_until_root() for all the paths of the mailbox. */ +void mailbox_list_delete_mailbox_until_root(struct mailbox_list *list, + const char *storage_name); /* Wrapper to unlink_directory(UNLINK_DIRECTORY_FLAG_RMDIR). If it fails due to ELOOP, try to unlink() the path instead. */ int mailbox_list_delete_trash(const char *path);
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Tue Jul 25 16:10:51 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Tue Jul 25 20:53:18 2017 +0300 @@ -9,6 +9,7 @@ #include "mail-storage.h" #include "mailbox-tree.h" #include "mailbox-list-subscriptions.h" +#include "mailbox-list-iter-private.h" #include "mailbox-list-fs.h" #include <stdio.h> @@ -741,6 +742,8 @@ doesn't */ return 0; } + if (mailbox_list_iter_try_delete_noselect(&ctx->ctx, &ctx->info, storage_name)) + return 0; return 1; }
--- a/src/lib-storage/list/mailbox-list-index-iter.c Tue Jul 25 16:10:51 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-index-iter.c Tue Jul 25 20:53:18 2017 +0300 @@ -5,6 +5,7 @@ #include "imap-match.h" #include "mail-storage.h" #include "mailbox-list-subscriptions.h" +#include "mailbox-list-iter-private.h" #include "mailbox-list-index.h" static bool iter_use_index(struct mailbox_list *list, @@ -174,8 +175,21 @@ follow_children = (match & (IMAP_MATCH_YES | IMAP_MATCH_CHILDREN)) != 0; if (match == IMAP_MATCH_YES && iter_subscriptions_ok(ctx)) { - mailbox_list_index_update_next(ctx, TRUE); - return &ctx->info; + /* If this is a) \NoSelect leaf, b) not LAYOUT=index + and c) NO-NOSELECT is set, try to rmdir the leaf + directores from filesystem. (With LAYOUT=index the + \NoSelect mailboxes aren't on the filesystem.) */ + if (ilist->has_backing_store && + mailbox_list_iter_try_delete_noselect(_ctx, &ctx->info, + str_c(ctx->path))) { + /* Deleted \NoSelect leaf. Refresh the index + later on so it gets removed from the index + as well. */ + mailbox_list_index_refresh_later(_ctx->list); + } else { + mailbox_list_index_update_next(ctx, TRUE); + return &ctx->info; + } } else if ((_ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 && (ctx->info.flags & MAILBOX_CHILD_SUBSCRIBED) == 0) { /* listing only subscriptions, but there are no
--- a/src/lib-storage/list/mailbox-list-iter-private.h Tue Jul 25 16:10:51 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-iter-private.h Tue Jul 25 20:53:18 2017 +0300 @@ -1,7 +1,9 @@ #ifndef MAILBOX_LIST_ITER_PRIVATE_H #define MAILBOX_LIST_ITER_PRIVATE_H +#include "mailbox-list-private.h" #include "mailbox-list-iter.h" +#include "mailbox-list-delete.h" struct autocreate_box { const char *name; @@ -21,4 +23,20 @@ bool listing_autoboxes:1; }; +static inline bool +mailbox_list_iter_try_delete_noselect(struct mailbox_list_iterate_context *ctx, + const struct mailbox_info *info, + const char *storage_name) +{ + if ((info->flags & (MAILBOX_NOSELECT|MAILBOX_NOCHILDREN)) == + (MAILBOX_NOSELECT|MAILBOX_NOCHILDREN) && + ctx->list->set.no_noselect) { + /* Try to rmdir() all \NoSelect mailbox leafs and + afterwards their parents. */ + mailbox_list_delete_mailbox_until_root(ctx->list, storage_name); + return TRUE; + } + return FALSE; +} + #endif