bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainenindex_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname,
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen struct mailbox_list *_newlist, const char *newname);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic struct mailbox_list *index_list_alloc(void)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen pool = pool_alloconly_create("index list", 2048);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen list = p_new(pool, struct index_mailbox_list, 1);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen list->temp_prefix = p_strconcat(pool, GLOBAL_TEMP_PREFIX,
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainenstatic int index_list_init(struct mailbox_list *_list, const char **error_r)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen *error_r = "LAYOUT=index requires mailbox_list_index=yes";
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void index_list_deinit(struct mailbox_list *_list)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
f3391d65cc830eab22ca6c5941774de682716edbTimo Sirainenstatic char index_list_get_hierarchy_sep(struct mailbox_list *list)
f3391d65cc830eab22ca6c5941774de682716edbTimo Sirainen return *list->ns->set->separator != '\0' ? *list->ns->set->separator :
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainenindex_list_get_refreshed_node_seq(struct index_mailbox_list *list,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen unsigned int i;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen for (i = 0; i < 2; i++) {
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen *node_r = mailbox_list_index_lookup(&list->list, name);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (mail_index_lookup_seq(view, (*node_r)->uid, seq_r))
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen /* mailbox was just expunged. refreshing should notice it. */
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (mailbox_list_index_refresh_force(&list->list) < 0)
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen i_panic("mailbox list index: refreshing doesn't lose expunged uid=%u",
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenstatic const char *
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenindex_get_guid_path(struct mailbox_list *_list, const char *root_dir,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_get_path(struct mailbox_list *_list, const char *name,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen enum mailbox_list_path_type type, const char **path_r)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* return root directories */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return mailbox_list_set_get_root_path(&_list->set, type,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* consistently use mailbox_dir_name as part of all mailbox
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen directories (index/control/etc) */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (!mailbox_list_set_get_root_path(&_list->set, type, &root_dir))
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen strcmp(list->create_mailbox_name, name) == 0) {
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen *path_r = index_get_guid_path(_list, root_dir,
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi /* ilist is only required from this point onwards.
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi At least imapc calls index_list_get_path without this context*/
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(_list);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen /* we could get here during sync from
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen index_list_mailbox_create_selectable() */
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen node = mailbox_list_index_lookup(&list->list, name);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen } else if (mail_index_lookup_seq(view, node->uid, &seq)) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen i_panic("mailbox list index: lost uid=%u", node->uid);
28f7485aaa7c5e0e3aa85d5a65d0dfc1c7ec7b89Timo Sirainen if (mailbox_list_index_refresh(&list->list) < 0)
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret = index_list_get_refreshed_node_seq(list, view, name, &node, &seq);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen } else if (!mailbox_list_index_status(_list, view, seq, 0,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen *path_r = index_get_guid_path(_list, root_dir, mailbox_guid);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic const char *
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_get_temp_prefix(struct mailbox_list *_list, bool global)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return global ? GLOBAL_TEMP_PREFIX : list->temp_prefix;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int index_list_set_subscribed(struct mailbox_list *_list,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTPOSSIBLE,
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen "Subscriptions not supported");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen path = t_strconcat(_list->set.control_dir != NULL ?
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return subsfile_set_subscribed(_list, path, list->temp_prefix,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_node_exists(struct index_mailbox_list *list, const char *name,
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen if (mailbox_list_index_refresh(&list->list) < 0)
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen node = mailbox_list_index_lookup(&list->list, name);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if ((node->flags & (MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* selectable */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* non-selectable */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_mailbox_create_dir(struct index_mailbox_list *list, const char *name)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_sync_context *sync_ctx;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen seq = mailbox_list_index_sync_name(sync_ctx, name, &node, &created);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (created || (node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* didn't already exist */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen node->flags = MAILBOX_LIST_INDEX_FLAG_NOSELECT;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_update_flags(sync_ctx->trans, seq, MODIFY_REPLACE,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* already existed */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0)
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainenindex_list_mailbox_create_selectable(struct mailbox *box,
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(box->list);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_sync_context *sync_ctx;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen seq = mailbox_list_index_sync_name(sync_ctx, box->name, &node, &created);
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen /* an existing mailbox is being created with a "unknown" name.
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen opening the mailbox will hopefully find its real name and
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen rename it. */
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen node->flags |= MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME;
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen mail_index_update_flags(sync_ctx->trans, seq, MODIFY_ADD,
0f242c946b153907d2e34bc9993942e6ca277bf8Timo Sirainen (enum mail_flags)MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (node->flags & (MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* already selectable */
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen (void)mailbox_list_index_sync_end(&sync_ctx, TRUE);
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen mail_index_lookup_ext(sync_ctx->view, seq, ilist->ext_id,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* make it selectable */
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen node->flags &= ~(MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
0f242c946b153907d2e34bc9993942e6ca277bf8Timo Sirainen mail_index_update_flags(sync_ctx->trans, seq, MODIFY_REPLACE,
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen /* set UIDVALIDITY if was set by the storage */
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen if (mail_index_get_header(view)->uid_validity != 0)
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen rec.uid_validity = mail_index_get_header(view)->uid_validity;
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen /* set GUID */
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen memcpy(rec.guid, mailbox_guid, sizeof(rec.guid));
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen mail_index_update_ext(sync_ctx->trans, seq, ilist->ext_id, &rec, NULL);
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0) {
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen /* make sure we forget any changes done internally */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const struct mailbox_update *update, bool directory)
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* first do a quick check that it doesn't exist */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if ((ret = index_list_node_exists(list, box->name, &existence)) < 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (existence == MAILBOX_EXISTENCE_NONE && directory) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* now add the directory to index locked */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if ((ret = index_list_mailbox_create_dir(list, box->name)) < 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen } else if (existence != MAILBOX_EXISTENCE_SELECT && !directory) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* if no GUID is requested, generate it ourself. set
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen UIDVALIDITY to index sometimes later. */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (guid_128_is_empty(new_update.mailbox_guid))
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* create the backend mailbox first before it exists in the
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen list. the mailbox creation wants to use get_path() though,
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen so use a bit kludgy create_mailbox_* variables during the
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen creation to return the path. we'll also support recursively
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen creating more mailboxes in here. */
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_copy(old_guid, list->create_mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_copy(list->create_mailbox_guid, new_update.mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen ret = ibox->module_ctx.super.create_box(box, &new_update, FALSE);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* backend mailbox was successfully created. now add it
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen to the list. */
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen ret = index_list_mailbox_create_selectable(box, new_update.mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen mail_storage_copy_list_error(box->storage, box->list);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* failed to add to list. rollback the backend
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen mailbox creation */
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_copy(list->create_mailbox_guid, old_guid);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Mailbox already exists");
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen if (mailbox_list_get_path(box->list, box->name,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen if (ibox->module_ctx.super.update_box(box, update) < 0)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen /* rename the directory */
dfc96c43be0720d3a03faa1eb44032276cbf94cfTimo Sirainen if (!guid_128_is_empty(update->mailbox_guid) && old_path != NULL &&
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen mailbox_list_set_get_root_path(&box->list->set,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen new_path = index_get_guid_path(box->list, root_dir,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "rename(%s, %s) failed: %m",
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen mailbox_list_index_update_mailbox_index(box, update);
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainenindex_list_mailbox_exists(struct mailbox *box, bool auto_boxes ATTR_UNUSED,
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen if (index_list_node_exists(list, box->name, existence_r) < 0) {
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainenstatic bool mailbox_has_corrupted_name(struct mailbox *box)
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen node = mailbox_list_index_lookup(box->list, box->name);
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen (node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0;
55c88023635062105849a2cbab78232f483b2c02Timo Sirainenstatic void index_list_rename_corrupted(struct mailbox *box, const char *newname)
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen if (index_list_rename_mailbox(box->list, box->name,
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen /* mailbox already exists. don't give up yet, just use the newname
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen as prefix and add the "lost-xx" as suffix. */
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen char sep = mailbox_list_get_hierarchy_sep(box->list);
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen /* oldname should be at the root level, but check for hierarchies
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen anyway to be safe. */
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen newname = t_strdup_printf("%s-%s", newname, oldname);
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen (void)index_list_rename_mailbox(box->list, box->name,
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainenstatic int index_list_mailbox_open(struct mailbox *box)
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen /* FIXME: dsync-merge is performing a delete in obox - remove
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen this check once dsync-merging is no longer used. */
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen /* if mailbox name has changed, update it to the header. Use \0
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen as the hierarchy separator in the header. This is to make sure
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen we don't keep rewriting the name just in case some backend switches
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen between separators when accessed different ways. */
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen /* Get the current mailbox name with \0 separators. */
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen char sep = mailbox_list_get_hierarchy_sep(box->list);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen char *box_zerosep_name = t_strdup_noconst(box->name);
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t box_name_len = strlen(box_zerosep_name);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen /* Does it match what's in the header now? */
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen mail_index_get_header_ext(box->view, box->box_name_hdr_ext_id,
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen while (name_hdr_size > 0 && name_hdr[name_hdr_size-1] == '\0') {
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen /* Remove trailing \0 - header doesn't shrink always */
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen memcmp(box_zerosep_name, name_hdr, box_name_len) == 0) {
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen /* Same mailbox name */
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen } else if (!mailbox_has_corrupted_name(box)) {
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen /* Mailbox name changed - update */
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen mail_index_ext_resize_hdr(trans, box->box_name_hdr_ext_id,
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen mail_index_update_header_ext(trans, box->box_name_hdr_ext_id, 0,
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen } else if (name_hdr_size > 0) {
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen /* Mailbox name is corrupted. Rename it to the previous name. */
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen char sep = mailbox_list_get_hierarchy_sep(box->list);
f5447068410d91377dad69e5393553015032ef6fTimo Sirainenvoid mailbox_list_index_backend_sync_init(struct mailbox *box,
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(box->list);
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0 &&
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen enum mail_storage_list_index_rebuild_reason reason =
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen MAIL_STORAGE_LIST_INDEX_REBUILD_REASON_FORCE_RESYNC;
a8200366c303c9dd752303b094ef9a48fe7855dfTimo Sirainen if (box->storage->v.list_index_rebuild != NULL &&
a8200366c303c9dd752303b094ef9a48fe7855dfTimo Sirainen box->storage->v.list_index_rebuild(box->storage, reason) < 0)
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen /* try to rebuild list index only once - even if it failed */
f5447068410d91377dad69e5393553015032ef6fTimo Sirainenint mailbox_list_index_backend_sync_deinit(struct mailbox *box)
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(box->list);
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen /* fail this only once */
c44f7761bba61503d573eb950b9377f9d55ce2aaTimo Sirainenindex_list_try_delete(struct mailbox_list *_list, const char *name,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_get_path(_list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_get_path(_list, name, type, &path) <= 0 ||
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (_list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) == 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* this directory may contain also child mailboxes' data.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen we don't want to delete that. */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen bool rmdir_path = *_list->set.maildir_name != '\0';
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_delete_mailbox_nonrecursive(_list, name, path,
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen if (mailbox_list_delete_trash(path, &error) < 0 &&
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen "unlink_directory(%s) failed: %s", path, error);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* avoid leaving empty directories lying around */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_delete_until_root(_list, path, type);
c44f7761bba61503d573eb950b9377f9d55ce2aaTimo Sirainenindex_list_delete_finish(struct mailbox_list *list, const char *name)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen index_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen index_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen index_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainenindex_list_delete_entry(struct index_mailbox_list *list, const char *name,
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen struct mailbox_list_index_sync_context *sync_ctx;
34b858a4586db070d899e128a6fc76a4ea6050beTimo Sirainen strcmp(name, list->create_mailbox_name) == 0) {
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* we're rolling back a failed create. if the name exists in the
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen list, it was done by somebody else so we don't want to
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen remove it. */
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen ret = mailbox_list_index_sync_delete(sync_ctx, name, delete_selectable);
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_delete_mailbox(struct mailbox_list *_list, const char *name)
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* first delete the mailbox files */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_get_path(_list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen if ((_list->flags & (MAILBOX_LIST_FLAG_NO_MAIL_FILES |
201437e07fd40d296377cc20ed1dab1f2777544aTimo Sirainen } else if ((_list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_delete_mailbox_file(_list, name, path);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_delete_mailbox_nonrecursive(_list, name,
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen if ((ret == 0 || (_list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) != 0) &&
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen (_list->flags & MAILBOX_LIST_FLAG_NO_DELETES) == 0)
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (index_list_delete_entry(list, name, TRUE) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_delete_dir(struct mailbox_list *_list, const char *name)
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if ((ret = index_list_delete_entry(list, name, FALSE)) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_EXISTS,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Mailbox has children, delete them first");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_delete_symlink(struct mailbox_list *_list,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTPOSSIBLE,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Symlinks not supported");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list *_newlist, const char *newname)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_oldlist;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_sync_context *sync_ctx;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_record oldrec, newrec;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_node *oldnode, *newnode, *child;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_oldlist, MAIL_ERROR_NOTPOSSIBLE,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Renaming not supported across namespaces.");
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen if (strncmp(oldname, newname, oldname_len) == 0 &&
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen newname[oldname_len] == mailbox_list_get_hierarchy_sep(_newlist)) {
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen mailbox_list_set_error(_oldlist, MAIL_ERROR_NOTPOSSIBLE,
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen "Can't rename mailbox under itself.");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen oldnode = mailbox_list_index_lookup(&list->list, oldname);
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen (void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen mailbox_list_set_error(&list->list, MAIL_ERROR_NOTFOUND,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (!mail_index_lookup_seq(sync_ctx->view, oldnode->uid, &oldseq))
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_panic("mailbox list index: lost uid=%u", oldnode->uid);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen newseq = mailbox_list_index_sync_name(sync_ctx, newname,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(&list->list, MAIL_ERROR_EXISTS,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Target mailbox already exists");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* copy all the data from old node to new node */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen newnode->children = oldnode->children; oldnode->children = NULL;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen for (child = newnode->children; child != NULL; child = child->next)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* remove the old node from existence */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_index_node_unlink(sync_ctx->ilist, oldnode);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* update the old index record to contain the new name_id/parent_uid,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen then expunge the added index record */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_lookup_ext(sync_ctx->view, oldseq, sync_ctx->ilist->ext_id,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_lookup_ext(sync_ctx->view, newseq, sync_ctx->ilist->ext_id,
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen if ((newnode->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0) {
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen /* mailbox is renamed - clear away the corruption flag so the
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen new name will be written to the mailbox index header. */
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen newnode->flags &= ~MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME;
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen mail_index_update_flags(sync_ctx->trans, oldseq, MODIFY_REMOVE,
0f242c946b153907d2e34bc9993942e6ca277bf8Timo Sirainen (enum mail_flags)MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_update_ext(sync_ctx->trans, oldseq,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return mailbox_list_index_sync_end(&sync_ctx, TRUE);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_iter_init(struct mailbox_list *list,
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen const char *const *patterns,
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen return mailbox_list_subscriptions_iter_init(list, patterns,
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen pool = pool_alloconly_create("mailbox list index backend iter", 1024);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ctx = p_new(pool, struct mailbox_list_iterate_context, 1);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen array_create(&ctx->module_contexts, pool, sizeof(void *), 5);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic const struct mailbox_info *
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainenindex_list_iter_next(struct mailbox_list_iterate_context *ctx)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen return mailbox_list_subscriptions_iter_next(ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int index_list_iter_deinit(struct mailbox_list_iterate_context *ctx)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen return mailbox_list_subscriptions_iter_deinit(ctx);
bfaf911d4e0003f2679b1f5d36fd2f2674989ff8Timo Sirainen .props = MAILBOX_LIST_PROP_NO_ROOT | MAILBOX_LIST_PROP_NO_INTERNAL_NAMES,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_hierarchy_sep = index_list_get_hierarchy_sep,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_storage_name = mailbox_list_default_get_storage_name,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_temp_prefix = index_list_get_temp_prefix,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .subscriptions_refresh = mailbox_list_subscriptions_refresh,
f5447068410d91377dad69e5393553015032ef6fTimo Sirainenbool mailbox_list_index_backend_init_mailbox(struct mailbox *box,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (strcmp(box->list->name, MAILBOX_LIST_NAME_INDEX) != 0)
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen /* NOTE: this is using the same v as
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen mailbox_list_index_status_init_mailbox(), so don't have them
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen accidentally override each others. */