changeset 21204:77b49389ebf5

lib-storage: Try harder to rename a corrupted mailbox name to its old name. If the old name exists, use it as a prefix for the new name. This is especially useful when restoring autocreated mailboxes. A new mailbox could have already been autocreated, but it's still useful to have the broken one renamed with the same prefix, so it'll be clear that these mailboxes should be merged.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 23 Nov 2016 22:42:03 +0200
parents 63989e9ddf0c
children 5d905618c4b1
files src/lib-storage/list/mailbox-list-index-backend.c
diffstat 1 files changed, 24 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-index-backend.c	Thu Nov 24 19:32:44 2016 +0200
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Wed Nov 23 22:42:03 2016 +0200
@@ -483,6 +483,29 @@
 		(node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0;
 }
 
+static void index_list_rename_corrupted(struct mailbox *box, const char *newname)
+{
+	if (index_list_rename_mailbox(box->list, box->name,
+				      box->list, newname) == 0 ||
+	    box->list->error != MAIL_ERROR_EXISTS)
+		return;
+
+	/* mailbox already exists. don't give up yet, just use the newname
+	   as prefix and add the "lost-xx" as suffix. */
+	char sep = mailbox_list_get_hierarchy_sep(box->list);
+	const char *oldname = box->name;
+
+	/* oldname should be at the root level, but check for hierarchies
+	   anyway to be safe. */
+	const char *p = strrchr(oldname, sep);
+	if (p != NULL)
+		oldname = p+1;
+
+	newname = t_strdup_printf("%s-%s", newname, oldname);
+	(void)index_list_rename_mailbox(box->list, box->name,
+					box->list, newname);
+}
+
 static int index_list_mailbox_open(struct mailbox *box)
 {
 	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
@@ -537,8 +560,7 @@
 				newname[i] = sep;
 		}
 
-		(void)index_list_rename_mailbox(box->list, box->name,
-						box->list, newname);
+		index_list_rename_corrupted(box, newname);
 	}
 	return 0;
 }