bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "lib.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "hostpid.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "mail-index.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "subscription-file.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "mailbox-list-delete.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "mailbox-list-subscriptions.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "mailbox-list-index-storage.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#include "mailbox-list-index-sync.h"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen#include <stdio.h>
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen#define GLOBAL_TEMP_PREFIX ".temp."
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstruct index_mailbox_list {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *temp_prefix;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen const char *create_mailbox_name;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_t create_mailbox_guid;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen};
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenextern struct mailbox_list index_mailbox_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainenstatic int
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainenindex_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname,
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen struct mailbox_list *_newlist, const char *newname);
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic struct mailbox_list *index_list_alloc(void)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen pool_t pool;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen pool = pool_alloconly_create("index list", 2048);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen list = p_new(pool, struct index_mailbox_list, 1);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen list->list = index_mailbox_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen list->list.pool = pool;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen list->temp_prefix = p_strconcat(pool, GLOBAL_TEMP_PREFIX,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen my_hostname, ".", my_pid, ".", NULL);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return &list->list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainenstatic int index_list_init(struct mailbox_list *_list, const char **error_r)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen{
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (!_list->mail_set->mailbox_list_index) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen *error_r = "LAYOUT=index requires mailbox_list_index=yes";
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen return -1;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen return 0;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen}
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void index_list_deinit(struct mailbox_list *_list)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen pool_unref(&list->list.pool);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
f3391d65cc830eab22ca6c5941774de682716edbTimo Sirainenstatic char index_list_get_hierarchy_sep(struct mailbox_list *list)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
f3391d65cc830eab22ca6c5941774de682716edbTimo Sirainen return *list->ns->set->separator != '\0' ? *list->ns->set->separator :
8528048c7b82c745bcfa5a6b1394251b3aaeb129Josef 'Jeff' Sipek MAILBOX_LIST_INDEX_HIERARCHY_SEP;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainenstatic int
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainenindex_list_get_refreshed_node_seq(struct index_mailbox_list *list,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen struct mail_index_view *view,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen const char *name,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen struct mailbox_list_index_node **node_r,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen uint32_t *seq_r)
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen{
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen unsigned int i;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen *node_r = NULL;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen *seq_r = 0;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen for (i = 0; i < 2; i++) {
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen *node_r = mailbox_list_index_lookup(&list->list, name);
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen if (*node_r == NULL)
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen return 0;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (mail_index_lookup_seq(view, (*node_r)->uid, seq_r))
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen return 1;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen /* mailbox was just expunged. refreshing should notice it. */
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (mailbox_list_index_refresh_force(&list->list) < 0)
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen return -1;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen i_panic("mailbox list index: refreshing doesn't lose expunged uid=%u",
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen (*node_r)->uid);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen return -1;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen}
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenstatic const char *
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenindex_get_guid_path(struct mailbox_list *_list, const char *root_dir,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen const guid_128_t mailbox_guid)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen{
7da0a157dbcb64d3e97c01bcc87262bd944c6890Timo Sirainen return t_strdup_printf("%s/%s%s", root_dir,
7da0a157dbcb64d3e97c01bcc87262bd944c6890Timo Sirainen _list->set.mailbox_dir_name,
7da0a157dbcb64d3e97c01bcc87262bd944c6890Timo Sirainen guid_128_to_string(mailbox_guid));
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen}
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
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{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mail_index_view *view;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_node *node;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_status status;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen guid_128_t mailbox_guid;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *root_dir;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen uint32_t seq;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (name == NULL) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* return root directories */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return mailbox_list_set_get_root_path(&_list->set, type,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen path_r) ? 1 : 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* consistently use mailbox_dir_name as part of all mailbox
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen directories (index/control/etc) */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen switch (type) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen type = MAILBOX_LIST_PATH_TYPE_DIR;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen break;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen type = MAILBOX_LIST_PATH_TYPE_ALT_DIR;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen break;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen i_unreached();
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen default:
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen break;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (!mailbox_list_set_get_root_path(&_list->set, type, &root_dir))
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (list->create_mailbox_name != NULL &&
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen strcmp(list->create_mailbox_name, name) == 0) {
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen *path_r = index_get_guid_path(_list, root_dir,
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen list->create_mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen return 1;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen }
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
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);
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (ilist->sync_ctx != NULL) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen /* we could get here during sync from
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen index_list_mailbox_create_selectable() */
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen view = ilist->sync_ctx->view;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen node = mailbox_list_index_lookup(&list->list, name);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (node == NULL) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen seq = 0;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret = 0;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen } else if (mail_index_lookup_seq(view, node->uid, &seq)) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret = 1;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen } else {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen i_panic("mailbox list index: lost uid=%u", node->uid);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen } else {
28f7485aaa7c5e0e3aa85d5a65d0dfc1c7ec7b89Timo Sirainen if (mailbox_list_index_refresh(&list->list) < 0)
28f7485aaa7c5e0e3aa85d5a65d0dfc1c7ec7b89Timo Sirainen return -1;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen view = mail_index_view_open(ilist->index);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret = index_list_get_refreshed_node_seq(list, view, name, &node, &seq);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (ret < 0) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen mail_index_view_close(&view);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen i_assert(ret == 0 || seq != 0);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (ret == 0) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen ret = -1;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen } else if (!mailbox_list_index_status(_list, view, seq, 0,
e048e63fec8d21d4af0fd9d27dd3fe5dcedf18e6Timo Sirainen &status, mailbox_guid, NULL) ||
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen guid_128_is_empty(mailbox_guid)) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen } else {
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen *path_r = index_get_guid_path(_list, root_dir, mailbox_guid);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = 1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen if (ilist->sync_ctx == NULL)
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen mail_index_view_close(&view);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic const char *
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_get_temp_prefix(struct mailbox_list *_list, bool global)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return global ? GLOBAL_TEMP_PREFIX : list->temp_prefix;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int index_list_set_subscribed(struct mailbox_list *_list,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *name, bool set)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *path;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen if (_list->set.subscription_fname == NULL) {
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTPOSSIBLE,
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen "Subscriptions not supported");
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen return -1;
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen }
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen path = t_strconcat(_list->set.control_dir != NULL ?
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen _list->set.control_dir : _list->set.root_dir,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "/", _list->set.subscription_fname, NULL);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return subsfile_set_subscribed(_list, path, list->temp_prefix,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen name, set);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_node_exists(struct index_mailbox_list *list, const char *name,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen enum mailbox_existence *existence_r)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_node *node;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NONE;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen if (mailbox_list_index_refresh(&list->list) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen node = mailbox_list_index_lookup(&list->list, name);
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen if (node == NULL)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if ((node->flags & (MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen MAILBOX_LIST_INDEX_FLAG_NOSELECT)) == 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* selectable */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen *existence_r = MAILBOX_EXISTENCE_SELECT;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen } else {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* non-selectable */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NOSELECT;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_mailbox_create_dir(struct index_mailbox_list *list, const char *name)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_sync_context *sync_ctx;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_node *node;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen uint32_t seq;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen bool created;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
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 (enum mail_flags)node->flags);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = 1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen } else {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* already existed */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainenindex_list_mailbox_create_selectable(struct mailbox *box,
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen const guid_128_t mailbox_guid)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen struct index_mailbox_list *list =
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen (struct index_mailbox_list *)box->list;
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 struct mailbox_list_index_record rec;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_index_node *node;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const void *data;
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen bool expunged, created;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen uint32_t seq;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen seq = mailbox_list_index_sync_name(sync_ctx, box->name, &node, &created);
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen if (box->corrupted_mailbox_name) {
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);
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (!created &&
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (node->flags & (MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen MAILBOX_LIST_INDEX_FLAG_NOSELECT)) == 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* already selectable */
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen (void)mailbox_list_index_sync_end(&sync_ctx, TRUE);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen mail_index_lookup_ext(sync_ctx->view, seq, ilist->ext_id,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen &data, &expunged);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_assert(data != NULL && !expunged);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen memcpy(&rec, data, sizeof(rec));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_assert(guid_128_is_empty(rec.guid));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* make it selectable */
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen node->flags &= ~(MAILBOX_LIST_INDEX_FLAG_NONEXISTENT |
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen MAILBOX_LIST_INDEX_FLAG_NOSELECT |
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen MAILBOX_LIST_INDEX_FLAG_NOINFERIORS);
0f242c946b153907d2e34bc9993942e6ca277bf8Timo Sirainen mail_index_update_flags(sync_ctx->trans, seq, MODIFY_REPLACE,
0f242c946b153907d2e34bc9993942e6ca277bf8Timo Sirainen (enum mail_flags)node->flags);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen /* set UIDVALIDITY if was set by the storage */
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen if (box->index != NULL) {
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen struct mail_index_view *view;
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen view = mail_index_view_open(box->index);
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 mail_index_view_close(&view);
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen }
0c9a1055469225bce4c309c5ad7c30531e1c0001Timo Sirainen
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);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen if (mailbox_list_index_sync_end(&sync_ctx, TRUE) < 0) {
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen /* make sure we forget any changes done internally */
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen mailbox_list_index_reset(ilist);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_mailbox_create(struct mailbox *box,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const struct mailbox_update *update, bool directory)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list =
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (struct index_mailbox_list *)box->list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_update new_update;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen enum mailbox_existence existence;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
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 return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
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 return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
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 (update == NULL)
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&new_update);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen else
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen new_update = *update;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (guid_128_is_empty(new_update.mailbox_guid))
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen guid_128_generate(new_update.mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
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 const char *old_name;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_t old_guid;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen old_name = list->create_mailbox_name;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_copy(old_guid, list->create_mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen list->create_mailbox_name = box->name;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_copy(list->create_mailbox_guid, new_update.mailbox_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen ret = ibox->module_ctx.super.create_box(box, &new_update, FALSE);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (ret == 0) {
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 if (ret < 0)
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen mail_storage_copy_list_error(box->storage, box->list);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (ret <= 0) {
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* failed to add to list. rollback the backend
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen mailbox creation */
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen bool create_error = ret < 0;
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen if (create_error)
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen mail_storage_last_error_push(box->storage);
453278403dbd2083b0c9a7aa5edb68d3f82ad4f6Timo Sirainen if (mailbox_delete(box) < 0)
453278403dbd2083b0c9a7aa5edb68d3f82ad4f6Timo Sirainen ret = -1;
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen if (create_error)
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen mail_storage_last_error_pop(box->storage);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen }
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen }
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen list->create_mailbox_name = old_name;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen guid_128_copy(list->create_mailbox_guid, old_guid);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (ret < 0)
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen return ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen } else {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (ret == 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Mailbox already exists");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenstatic int
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenindex_list_mailbox_update(struct mailbox *box,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen const struct mailbox_update *update)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen{
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen const char *root_dir, *old_path, *new_path;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen if (mailbox_list_get_path(box->list, box->name,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen &old_path) <= 0)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen old_path = NULL;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen if (ibox->module_ctx.super.update_box(box, update) < 0)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen return -1;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
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 MAILBOX_LIST_PATH_TYPE_MAILBOX,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen &root_dir)) {
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen new_path = index_get_guid_path(box->list, root_dir,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen update->mailbox_guid);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen if (strcmp(old_path, new_path) == 0)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen ;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen else if (rename(old_path, new_path) == 0)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen ;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen else if (errno == ENOENT) {
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen return -1;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen } else {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "rename(%s, %s) failed: %m",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi old_path, new_path);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen return -1;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen }
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen }
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen mailbox_list_index_update_mailbox_index(box, update);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen return 0;
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen}
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainenstatic int
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainenindex_list_mailbox_exists(struct mailbox *box, bool auto_boxes ATTR_UNUSED,
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen enum mailbox_existence *existence_r)
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen{
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen struct index_mailbox_list *list =
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen (struct index_mailbox_list *)box->list;
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen if (index_list_node_exists(list, box->name, existence_r) < 0) {
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen return -1;
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen }
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen return 0;
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen}
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainenstatic bool mailbox_has_corrupted_name(struct mailbox *box)
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen{
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen struct mailbox_list_index_node *node;
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen if (box->corrupted_mailbox_name)
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen return TRUE;
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen node = mailbox_list_index_lookup(box->list, box->name);
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen return node != NULL &&
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen (node->flags & MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME) != 0;
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen}
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen
55c88023635062105849a2cbab78232f483b2c02Timo Sirainenstatic void index_list_rename_corrupted(struct mailbox *box, const char *newname)
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen{
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen if (index_list_rename_mailbox(box->list, box->name,
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen box->list, newname) == 0 ||
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen box->list->error != MAIL_ERROR_EXISTS)
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen return;
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen
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 const char *oldname = box->name;
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen /* oldname should be at the root level, but check for hierarchies
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen anyway to be safe. */
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen const char *p = strrchr(oldname, sep);
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen if (p != NULL)
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen oldname = p+1;
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen newname = t_strdup_printf("%s-%s", newname, oldname);
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen (void)index_list_rename_mailbox(box->list, box->name,
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen box->list, newname);
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen}
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainenstatic int index_list_mailbox_open(struct mailbox *box)
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen{
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen const void *data;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen const unsigned char *name_hdr;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen size_t name_hdr_size;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen if (ibox->module_ctx.super.open(box) < 0)
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen return -1;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen if (box->view == NULL) {
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen /* FIXME: dsync-merge is performing a delete in obox - remove
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen this check once dsync-merging is no longer used. */
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen return 0;
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen }
9a8217a728581b4787ab65eb6d1b06681945803dTimo Sirainen
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
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);
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen for (size_t i = 0; i < box_name_len; i++) {
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen if (box_zerosep_name[i] == sep)
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen box_zerosep_name[i] = '\0';
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen }
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen
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 &data, &name_hdr_size);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen name_hdr = data;
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 name_hdr_size--;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen }
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen if (name_hdr_size == box_name_len &&
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 struct mail_index_transaction *trans =
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen mail_index_transaction_begin(box->view, 0);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen mail_index_ext_resize_hdr(trans, box->box_name_hdr_ext_id,
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen box_name_len);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen mail_index_update_header_ext(trans, box->box_name_hdr_ext_id, 0,
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen box_zerosep_name, box_name_len);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen (void)mail_index_transaction_commit(&trans);
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);
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen char *newname = t_malloc0(name_hdr_size + 1);
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen memcpy(newname, name_hdr, name_hdr_size);
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen for (size_t i = 0; i < name_hdr_size; i++) {
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen if (newname[i] == '\0')
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen newname[i] = sep;
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen }
83d0c8152f694ae5b5d1798abda5728dc886102aTimo Sirainen
55c88023635062105849a2cbab78232f483b2c02Timo Sirainen index_list_rename_corrupted(box, newname);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen }
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen return 0;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen}
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen
f5447068410d91377dad69e5393553015032ef6fTimo Sirainenvoid mailbox_list_index_backend_sync_init(struct mailbox *box,
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen enum mailbox_sync_flags flags)
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen{
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(box->list);
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0 &&
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen !ilist->force_resynced) {
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen enum mail_storage_list_index_rebuild_reason reason =
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen MAIL_STORAGE_LIST_INDEX_REBUILD_REASON_FORCE_RESYNC;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen
a8200366c303c9dd752303b094ef9a48fe7855dfTimo Sirainen if (box->storage->v.list_index_rebuild != NULL &&
a8200366c303c9dd752303b094ef9a48fe7855dfTimo Sirainen box->storage->v.list_index_rebuild(box->storage, reason) < 0)
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen ilist->force_resync_failed = TRUE;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen /* try to rebuild list index only once - even if it failed */
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen ilist->force_resynced = TRUE;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen }
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen}
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen
f5447068410d91377dad69e5393553015032ef6fTimo Sirainenint mailbox_list_index_backend_sync_deinit(struct mailbox *box)
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen{
43ce61b1d755832186f12b9739d18212b4744d14Aki Tuomi struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(box->list);
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen if (ilist->force_resync_failed) {
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen /* fail this only once */
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen ilist->force_resync_failed = FALSE;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen return -1;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen }
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen return 0;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen}
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void
c44f7761bba61503d573eb950b9377f9d55ce2aaTimo Sirainenindex_list_try_delete(struct mailbox_list *_list, const char *name,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen enum mailbox_list_path_type type)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen const char *mailbox_path, *path, *error;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_get_path(_list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen &mailbox_path) <= 0 ||
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_get_path(_list, name, type, &path) <= 0 ||
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen strcmp(path, mailbox_path) == 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (*_list->set.maildir_name == '\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,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen rmdir_path) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen } else {
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen if (mailbox_list_delete_trash(path, &error) < 0 &&
1d9053f57383a2382c70f76b0790a7bf192aa891Sergey Kitov errno != ENOTEMPTY) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_critical(_list,
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen "unlink_directory(%s) failed: %s", path, error);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* avoid leaving empty directories lying around */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_delete_until_root(_list, path, type);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void
c44f7761bba61503d573eb950b9377f9d55ce2aaTimo Sirainenindex_list_delete_finish(struct mailbox_list *list, const char *name)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
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);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainenstatic int
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainenindex_list_delete_entry(struct index_mailbox_list *list, const char *name,
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen bool delete_selectable)
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen{
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen struct mailbox_list_index_sync_context *sync_ctx;
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen int ret;
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen
34b858a4586db070d899e128a6fc76a4ea6050beTimo Sirainen if (list->create_mailbox_name != NULL &&
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 return 0;
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen }
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen return -1;
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)
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen return -1;
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen return ret;
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen}
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_delete_mailbox(struct mailbox_list *_list, const char *name)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *path;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* first delete the mailbox files */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_get_path(_list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen &path);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (ret <= 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen if ((_list->flags & (MAILBOX_LIST_FLAG_NO_MAIL_FILES |
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen MAILBOX_LIST_FLAG_NO_DELETES)) != 0) {
201437e07fd40d296377cc20ed1dab1f2777544aTimo Sirainen ret = 0;
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 } else {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_delete_mailbox_nonrecursive(_list, name,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen path, TRUE);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen if ((ret == 0 || (_list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) != 0) &&
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen (_list->flags & MAILBOX_LIST_FLAG_NO_DELETES) == 0)
c44f7761bba61503d573eb950b9377f9d55ce2aaTimo Sirainen index_list_delete_finish(_list, name);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (ret == 0) {
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if (index_list_delete_entry(list, name, TRUE) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_delete_dir(struct mailbox_list *_list, const char *name)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen int ret;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if ((ret = index_list_delete_entry(list, name, FALSE)) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (ret == 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_EXISTS,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Mailbox has children, delete them first");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_delete_symlink(struct mailbox_list *_list,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *name ATTR_UNUSED)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTPOSSIBLE,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Symlinks not supported");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list *_newlist, const char *newname)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct index_mailbox_list *list = (struct index_mailbox_list *)_oldlist;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen const size_t oldname_len = strlen(oldname);
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 const void *data;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen bool created, expunged;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen uint32_t oldseq, newseq;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (_oldlist != _newlist) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_set_error(_oldlist, MAIL_ERROR_NOTPOSSIBLE,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Renaming not supported across namespaces.");
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
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.");
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen return -1;
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen }
606e388022ed2c9e94f912a5205626d11a9da6dcTimo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (mailbox_list_index_sync_begin(&list->list, &sync_ctx) < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen oldnode = mailbox_list_index_lookup(&list->list, oldname);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen if (oldnode == NULL) {
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen (void)mailbox_list_index_sync_end(&sync_ctx, FALSE);
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen mailbox_list_set_error(&list->list, MAIL_ERROR_NOTFOUND,
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen return -1;
31159b598c4188211ff8f292daad1d23ee5db3cbTimo Sirainen }
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
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen newseq = mailbox_list_index_sync_name(sync_ctx, newname,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen &newnode, &created);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (!created) {
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 return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_assert(oldnode != newnode);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* copy all the data from old node to new node */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen newnode->uid = oldnode->uid;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen newnode->flags = oldnode->flags;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen newnode->children = oldnode->children; oldnode->children = NULL;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen for (child = newnode->children; child != NULL; child = child->next)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen child->parent = newnode;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* remove the old node from existence */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mailbox_list_index_node_unlink(sync_ctx->ilist, oldnode);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
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 &data, &expunged);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_assert(data != NULL && !expunged);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen memcpy(&oldrec, data, sizeof(oldrec));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_lookup_ext(sync_ctx->view, newseq, sync_ctx->ilist->ext_id,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen &data, &expunged);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_assert(data != NULL && !expunged);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen memcpy(&newrec, data, sizeof(newrec));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen oldrec.name_id = newrec.name_id;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen oldrec.parent_uid = newrec.parent_uid;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
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);
85cbe5d66e22bc1290a33902fa2638245450a2dfTimo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_update_ext(sync_ctx->trans, oldseq,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen sync_ctx->ilist->ext_id, &oldrec, NULL);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mail_index_expunge(sync_ctx->trans, newseq);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return mailbox_list_index_sync_end(&sync_ctx, TRUE);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic struct mailbox_list_iterate_context *
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenindex_list_iter_init(struct mailbox_list *list,
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen const char *const *patterns,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen enum mailbox_list_iter_flags flags)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mailbox_list_iterate_context *ctx;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen pool_t pool;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen return mailbox_list_subscriptions_iter_init(list, patterns,
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen flags);
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen }
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen
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 ctx->pool = pool;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ctx->list = list;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ctx->flags = flags;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen array_create(&ctx->module_contexts, pool, sizeof(void *), 5);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return ctx;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic const struct mailbox_info *
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainenindex_list_iter_next(struct mailbox_list_iterate_context *ctx)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen return mailbox_list_subscriptions_iter_next(ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return NULL;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int index_list_iter_deinit(struct mailbox_list_iterate_context *ctx)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen return mailbox_list_subscriptions_iter_deinit(ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen pool_unref(&ctx->pool);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return 0;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstruct mailbox_list index_mailbox_list = {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen .name = MAILBOX_LIST_NAME_INDEX,
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,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .v = {
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .alloc = index_list_alloc,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .init = index_list_init,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .deinit = index_list_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_hierarchy_sep = index_list_get_hierarchy_sep,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_vname = mailbox_list_default_get_vname,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_storage_name = mailbox_list_default_get_storage_name,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_path = index_list_get_path,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_temp_prefix = index_list_get_temp_prefix,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_init = index_list_iter_init,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_next = index_list_iter_next,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_deinit = index_list_iter_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .subscriptions_refresh = mailbox_list_subscriptions_refresh,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .set_subscribed = index_list_set_subscribed,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_mailbox = index_list_delete_mailbox,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_dir = index_list_delete_dir,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_symlink = index_list_delete_symlink,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .rename_mailbox = index_list_rename_mailbox,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen }
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen};
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen
f5447068410d91377dad69e5393553015032ef6fTimo Sirainenbool mailbox_list_index_backend_init_mailbox(struct mailbox *box,
58289301ce9f6aa7121891e33ef7e0a1b4559e8dTimo Sirainen struct mailbox_vfuncs *v)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (strcmp(box->list->name, MAILBOX_LIST_NAME_INDEX) != 0)
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen return TRUE;
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen
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. */
58289301ce9f6aa7121891e33ef7e0a1b4559e8dTimo Sirainen v->create_box = index_list_mailbox_create;
58289301ce9f6aa7121891e33ef7e0a1b4559e8dTimo Sirainen v->update_box = index_list_mailbox_update;
58289301ce9f6aa7121891e33ef7e0a1b4559e8dTimo Sirainen v->exists = index_list_mailbox_exists;
58289301ce9f6aa7121891e33ef7e0a1b4559e8dTimo Sirainen v->open = index_list_mailbox_open;
f5447068410d91377dad69e5393553015032ef6fTimo Sirainen return FALSE;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen}