]> 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)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 18 Nov 2016 11:45:56 +0000 (13:45 +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 d192aa034bbd8c64a8067d52a08883cfab7e3f37..c9a11f869da48f697c2d2cf9984abcf088b2d3cc 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 8db5667df0002f45b32f53f3eb87e0088d0daea7..ccda93067d269462d9a2da23a94ce9c39cd7a96c 100644 (file)
@@ -377,6 +377,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 cf85bf103258b501119f63c11dedf1b3b00fdbf2..86b12a3db9f59ec966270407bf8f433c1542f2e0 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