From 85cbe5d66e22bc1290a33902fa2638245450a2df Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 16 Nov 2016 03:06:31 +0200 Subject: [PATCH] LAYOUT=index: Don't write corrupted mailbox names to box-name header. This way when opening a mailbox the box-name header isn't overwritten by a corrupted name. Keep track of the corrupted names with MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME flag in list index records. The flag isn't removed until the mailbox is renamed. --- .../list/mailbox-list-index-backend.c | 18 +++++++++++++++++- src/lib-storage/list/mailbox-list-index-sync.c | 5 +++++ src/lib-storage/list/mailbox-list-index.c | 2 ++ src/lib-storage/list/mailbox-list-index.h | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/lib-storage/list/mailbox-list-index-backend.c b/src/lib-storage/list/mailbox-list-index-backend.c index 0d37103ed6..24b376a95d 100644 --- a/src/lib-storage/list/mailbox-list-index-backend.c +++ b/src/lib-storage/list/mailbox-list-index-backend.c @@ -456,6 +456,15 @@ index_list_mailbox_exists(struct mailbox *box, bool auto_boxes ATTR_UNUSED, return 0; } +static bool mailbox_has_corrupted_name(struct mailbox *box) +{ + struct mailbox_list_index_node *node; + + node = mailbox_list_index_lookup(box->list, box->name); + return node != NULL && + (node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0; +} + static int index_list_mailbox_open(struct mailbox *box) { struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box); @@ -491,7 +500,7 @@ static int index_list_mailbox_open(struct mailbox *box) if (name_hdr_size == box_name_len && memcmp(box_zerosep_name, name_hdr, box_name_len) == 0) { /* Same mailbox name */ - } else { + } else if (!mailbox_has_corrupted_name(box)) { /* Mailbox name changed - update */ struct mail_index_transaction *trans = mail_index_transaction_begin(box->view, 0); @@ -699,6 +708,13 @@ index_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname, oldrec.name_id = newrec.name_id; oldrec.parent_uid = newrec.parent_uid; + if ((newnode->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0) { + /* mailbox is renamed - clear away the corruption flag so the + new name will be written to the mailbox index header. */ + newnode->flags &= ~MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME; + mail_index_update_flags(sync_ctx->trans, oldseq, MODIFY_REMOVE, + MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME); + } mail_index_update_ext(sync_ctx->trans, oldseq, sync_ctx->ilist->ext_id, &oldrec, NULL); mail_index_expunge(sync_ctx->trans, newseq); diff --git a/src/lib-storage/list/mailbox-list-index-sync.c b/src/lib-storage/list/mailbox-list-index-sync.c index 33c7c639df..4595801e01 100644 --- a/src/lib-storage/list/mailbox-list-index-sync.c +++ b/src/lib-storage/list/mailbox-list-index-sync.c @@ -378,6 +378,11 @@ mailbox_list_index_sync_update_corrupted_node(struct mailbox_list_index_sync_con sync_ctx->ilist->ext_id, &irec, NULL); node->corrupted_parent = FALSE; } + if ((node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0) { + /* rely on lib-index to drop unnecessary updates */ + mail_index_update_flags(sync_ctx->trans, seq, MODIFY_ADD, + MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME); + } } static void diff --git a/src/lib-storage/list/mailbox-list-index.c b/src/lib-storage/list/mailbox-list-index.c index bd848668a7..8217ff334c 100644 --- a/src/lib-storage/list/mailbox-list-index.c +++ b/src/lib-storage/list/mailbox-list-index.c @@ -233,6 +233,7 @@ mailbox_list_index_generate_name(struct mailbox_list_index *ilist, name = p_strdup_printf(ilist->mailbox_pool, "unknown-%s", guid_128_to_string(guid)); node->name = name; + node->flags |= MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME; hash_table_insert(ilist->mailbox_names, POINTER_CAST(node->name_id), name); @@ -372,6 +373,7 @@ static int mailbox_list_index_parse_records(struct mailbox_list_index *ilist, /* we have only the mailbox list index and this node may have a different GUID, so rename it. */ guid_128_generate(guid); + node->flags |= MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME; node->name = p_strdup_printf(ilist->mailbox_pool, "%s-duplicate-%s", node->name, guid_128_to_string(guid)); diff --git a/src/lib-storage/list/mailbox-list-index.h b/src/lib-storage/list/mailbox-list-index.h index 526f05bf2a..0b48a71264 100644 --- a/src/lib-storage/list/mailbox-list-index.h +++ b/src/lib-storage/list/mailbox-list-index.h @@ -43,6 +43,7 @@ enum mailbox_list_index_flags { MAILBOX_LIST_INDEX_FLAG_NONEXISTENT = MAIL_DELETED, MAILBOX_LIST_INDEX_FLAG_NOSELECT = MAIL_DRAFT, MAILBOX_LIST_INDEX_FLAG_NOINFERIORS = MAIL_ANSWERED, + MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME = MAIL_SEEN, /* set during syncing for mailboxes that still exist */ MAILBOX_LIST_INDEX_FLAG_SYNC_EXISTS = MAIL_FLAGGED -- 2.47.3