From: Timo Sirainen Date: Tue, 15 Nov 2016 23:03:20 +0000 (+0200) Subject: lib-storage: Fix invalid parents in LAYOUT=index X-Git-Tag: 2.2.27~137 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dbe6c905e7050c2217f8e2cfc1b8a54a6d49610c;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Fix invalid parents in LAYOUT=index Previously it just kept complaining without fixing the errors. --- diff --git a/src/lib-storage/list/mailbox-list-index-sync.c b/src/lib-storage/list/mailbox-list-index-sync.c index 13d3f6331e..8db5667df0 100644 --- a/src/lib-storage/list/mailbox-list-index-sync.c +++ b/src/lib-storage/list/mailbox-list-index-sync.c @@ -353,6 +353,52 @@ mailbox_list_index_sync_update_hdr(struct mailbox_list_index_sync_context *sync_ } } +static void +mailbox_list_index_sync_update_corrupted_node(struct mailbox_list_index_sync_context *sync_ctx, + struct mailbox_list_index_node *node) +{ + struct mailbox_list_index_record irec; + uint32_t seq; + const void *data; + bool expunged; + + if (!mail_index_lookup_seq(sync_ctx->view, node->uid, &seq)) + return; + + if (node->corrupted_parent) { + mail_index_lookup_ext(sync_ctx->view, seq, + sync_ctx->ilist->ext_id, + &data, &expunged); + i_assert(data != NULL); + + memcpy(&irec, data, sizeof(irec)); + irec.parent_uid = node->parent == NULL ? 0 : node->parent->uid; + mail_index_update_ext(sync_ctx->trans, seq, + sync_ctx->ilist->ext_id, &irec, NULL); + node->corrupted_parent = FALSE; + } +} + +static void +mailbox_list_index_sync_update_corrupted_nodes(struct mailbox_list_index_sync_context *sync_ctx, + struct mailbox_list_index_node *node) +{ + for (; node != NULL; node = node->next) { + mailbox_list_index_sync_update_corrupted_node(sync_ctx, node); + mailbox_list_index_sync_update_corrupted_nodes(sync_ctx, node->children); + } +} + +static void +mailbox_list_index_sync_update_corrupted(struct mailbox_list_index_sync_context *sync_ctx) +{ + if (!sync_ctx->ilist->corrupted) + return; + + mailbox_list_index_sync_update_corrupted_nodes(sync_ctx, + sync_ctx->ilist->mailbox_tree); +} + int mailbox_list_index_sync_end(struct mailbox_list_index_sync_context **_sync_ctx, bool success) { @@ -361,8 +407,10 @@ int mailbox_list_index_sync_end(struct mailbox_list_index_sync_context **_sync_c *_sync_ctx = NULL; - if (success) + if (success) { + mailbox_list_index_sync_update_corrupted(sync_ctx); mailbox_list_index_sync_update_hdr(sync_ctx); + } mail_index_view_close(&sync_ctx->view); if (success) { diff --git a/src/lib-storage/list/mailbox-list-index.c b/src/lib-storage/list/mailbox-list-index.c index f36e9ae7a2..fcf2cd13f0 100644 --- a/src/lib-storage/list/mailbox-list-index.c +++ b/src/lib-storage/list/mailbox-list-index.c @@ -258,7 +258,7 @@ static int mailbox_list_index_parse_records(struct mailbox_list_index *ilist, struct mail_index_view *view, const char **error_r) { - struct mailbox_list_index_node *node; + struct mailbox_list_index_node *node, *parent; HASH_TABLE(struct mailbox_list_index_node *, struct mailbox_list_index_node *) duplicate_hash; const struct mail_index_record *rec; @@ -319,19 +319,22 @@ static int mailbox_list_index_parse_records(struct mailbox_list_index *ilist, if (irec->parent_uid != 0) { /* node should have a parent */ - node->parent = mailbox_list_index_lookup_uid(ilist, - irec->parent_uid); - if (node->parent != NULL) { - node->next = node->parent->children; - node->parent->children = node; + parent = mailbox_list_index_lookup_uid(ilist, + irec->parent_uid); + if (parent == NULL) { + *error_r = t_strdup_printf( + "parent_uid=%u points to nonexistent record", + irec->parent_uid); + if (ilist->has_backing_store) + break; + /* just place it under the root */ + node->corrupted_parent = TRUE; + } else { + node->parent = parent; + node->next = parent->children; + parent->children = node; continue; } - *error_r = t_strdup_printf( - "parent_uid=%u points to nonexistent record", - irec->parent_uid); - if (ilist->has_backing_store) - break; - /* just place it under the root */ } if (hash_table_lookup(duplicate_hash, node) == NULL) hash_table_insert(duplicate_hash, node, node); diff --git a/src/lib-storage/list/mailbox-list-index.h b/src/lib-storage/list/mailbox-list-index.h index ba274c472d..cf85bf1032 100644 --- a/src/lib-storage/list/mailbox-list-index.h +++ b/src/lib-storage/list/mailbox-list-index.h @@ -80,6 +80,8 @@ struct mailbox_list_index_node { uint32_t name_id, uid; enum mailbox_list_index_flags flags; + /* parent_uid is corrupted on disk - need to update it */ + bool corrupted_parent; const char *name; };