]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
LAYOUT=index: Don't write corrupted mailbox names to box-name header.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 16 Nov 2016 01:06:31 +0000 (03:06 +0200)
committerGitLab <gitlab@git.dovecot.net>
Wed, 16 Nov 2016 15:08:03 +0000 (17:08 +0200)
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.

src/lib-storage/list/mailbox-list-index-backend.c
src/lib-storage/list/mailbox-list-index-sync.c
src/lib-storage/list/mailbox-list-index.c
src/lib-storage/list/mailbox-list-index.h

index 0d37103ed622292d501843a2bff4c6371507581f..24b376a95de03ec3a433da293a1d4aedbab257b6 100644 (file)
@@ -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);
index 33c7c639dff67708d0761c371e903fea45812f1e..4595801e011a9476e97ee2366206696122931f62 100644 (file)
@@ -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
index bd848668a73d95cbb20f3653778d24715eff163c..8217ff334c56edf7a9b5b7c00d57e0f284d49fc3 100644 (file)
@@ -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));
index 526f05bf2a96e355fe1b12e8e09cd9293e0e980b..0b48a7126418f95641caf2e3ca3d7a02d24bd0d2 100644 (file)
@@ -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