mail-storage.c revision a62e12ba4afefb302ef87faf6173aef012c3b5d6
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenextern struct mail_search_register *mail_search_register_imap;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenextern struct mail_search_register *mail_search_register_human;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_search_register_deinit(&mail_search_register_human);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_search_register_deinit(&mail_search_register_imap);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* append it after the list, so the autodetection order is correct */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int i, count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen classes = array_get(&mail_storage_classes, &count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < count; i++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int i, count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen classes = array_get(&mail_storage_classes, &count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen for (i = 0; i < count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen unsigned int i, count;
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen classes = array_get(&mail_storage_classes, &count);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < count; i++) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen const char *p;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen /* no autodetection if the storage driver is given. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen enum mail_storage_flags flags, const char **error_r)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* no mail_location, autodetect */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* explicit autodetection with "auto" driver. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* handle the same as with driver=NULL */
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* no root directory given. is this allowed? */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen /* autodetection should take care of this */
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* root not required for this storage */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* root not required for this layout */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen storage_class->v.get_list_settings(ns, list_set);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen "Mail storage autodetection failed with home=%s", home);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Autodetection failed for %s (home=%s)",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Ambiguous mail location setting, "
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "don't know what to do with it: %s "
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen "(try prefixing it with mbox: or maildir:)",
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenmail_storage_verify_root(const char *root_dir, const char *dir_type,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Root mail directory is a file: %s", root_dir);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen } else if (!autocreate) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen "Root %s directory doesn't exist: %s", dir_type, root_dir);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* doesn't exist */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenmail_storage_create_root(struct mailbox_list *list,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen enum mail_storage_flags flags, const char **error_r)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!mailbox_list_get_root_path(list, type, &root_dir)) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* we don't need to verify, but since debugging is
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen enabled, check and log if the root doesn't exist */
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen if (mail_storage_verify_root(root_dir, type_name, FALSE, &error) < 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = mail_storage_verify_root(root_dir, type_name, autocreate, error_r);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX, &mail_root_dir))
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = mailbox_list_try_mkdir_root(list, mail_root_dir,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ret == 0 && list->set.iter_from_index_dir) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenmail_storage_match_class(struct mail_storage *storage,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (set->root_dir != NULL ? set->root_dir : "")) != 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* allow multiple independent shared namespaces */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_storage *storage = user->storages;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (; storage != NULL; storage = storage->next) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_storage_match_class(storage, storage_class, set))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *data, enum mail_storage_flags flags,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char **error_r)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_storage *storage_class, *storage = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *p;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen header MD5 sums stored even if we're not running POP3
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen right now. */
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen mailbox_list_settings_init_defaults(&list_set);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* autodetect */
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen /* internal shared namespace */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_storage_set_autodetection(&data, &driver);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* first storage for namespace */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_storage_is_mailbox_file(storage_class))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_LIST_DELETES) != 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* using an existing storage */
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen storage->v.create(storage, ns, error_r) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum mail_storage_flags flags, const char **error_r)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return mail_storage_create_full(ns, driver, ns->set->location,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* set *_storage=NULL only after calling destroy() callback.
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for example mdbox wants to access ns->storage */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_panic("Trying to deinit storage without freeing mailbox %s",
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen i_panic("Trying to deinit storage before freeing its objects");
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (array_is_created(&storage->error_stack)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(array_count(&storage->error_stack) == 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid mail_storage_obj_ref(struct mail_storage *storage)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenvoid mail_storage_obj_unref(struct mail_storage *storage)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *str;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const char *fmt, ...)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen char *old_error = storage->last_internal_error;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen storage->last_internal_error = i_strdup_vprintf(fmt, va);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* free the old_error only after the new error is generated, because
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen the old_error may be one of the parameters. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* critical errors may contain sensitive data, so let user
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen see only "Internal error" with a timestamp to make it
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen easier to look from log files the actual error message. */
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainenconst char *mail_storage_get_last_internal_error(struct mail_storage *storage,
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen i_assert(storage->last_internal_error != NULL);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen return mail_storage_get_last_error(storage, error_r);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenconst char *mailbox_get_last_internal_error(struct mailbox *box,
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen return mail_storage_get_last_internal_error(mailbox_get_storage(box),
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainenvoid mail_storage_copy_error(struct mail_storage *dest,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *str;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen str = mail_storage_get_last_error(src, &error);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen const char *str;
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen str = mailbox_list_get_last_error(list, &error);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid mailbox_set_index_error(struct mailbox *box)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen mail_storage_set_internal_error(box->storage);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenmail_storage_get_settings(struct mail_storage *storage)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* We get here only in error situations, so we have to return some
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen error. If storage->error is NONE, it means we forgot to set it at
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen some point.. */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return storage->error_string != NULL ? storage->error_string :
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen "BUG: Unknown internal error";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* This shouldn't happen.. */
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainenconst char *mailbox_get_last_error(struct mailbox *box,
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen return mail_storage_get_last_error(box->storage, error_r);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenenum mail_error mailbox_get_last_mail_error(struct mailbox *box)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen mail_storage_get_last_error(box->storage, &error);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid mail_storage_last_error_push(struct mail_storage *storage)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen err = array_append_space(&storage->error_stack);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen err->error_string = i_strdup(storage->error_string);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen err->last_error_is_internal = storage->last_error_is_internal;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen err->last_internal_error = i_strdup(storage->last_internal_error);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid mail_storage_last_error_pop(struct mail_storage *storage)
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen unsigned int count = array_count(&storage->error_stack);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen storage->last_error_is_internal = err->last_error_is_internal;
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen storage->last_internal_error = err->last_internal_error;
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen array_delete(&storage->error_stack, count-1, 1);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* debugging is enabled - admin may be debugging a
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen (permission) problem, so return FALSE to get the caller to
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen log the full error message. */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen mail_storage_set_error(storage, error, error_string);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenmailbox_settings_find(struct mail_namespace *ns, const char *vname)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen strncmp(ns->prefix, vname, ns->prefix_len-1) == 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (vname[ns->prefix_len-1] == mail_namespace_get_sep(ns))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* namespace prefix itself */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* make sure INBOX shows up in uppercase everywhere. do this
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen regardless of whether we're in inbox=yes namespace, because
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen clients expect INBOX to be case insensitive regardless of
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen server's internal configuration. */
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen else if (vname[5] != mail_namespace_get_sep(list->ns))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* not INBOX prefix */ ;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen else if (strncasecmp(list->ns->prefix, vname, 6) == 0 &&
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Invalid server configuration: "
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Namespace prefix=%s must be uppercase INBOX",
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vname = t_strconcat("INBOX", vname + 5, NULL);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* do a delayed failure at mailbox_open() */
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen storage = mail_namespace_get_default_storage(list->ns);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen errstr = mailbox_list_get_last_error(new_list, &open_error);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen box->set = mailbox_settings_find(new_list->ns, vname);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen mail_storage_set_error(storage, open_error, errstr);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen DLLIST_PREPEND(&box->storage->mailboxes, box);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainenstruct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* GUID mismatch, refresh cache and try again */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* successfully opened the correct mailbox */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Couldn't verify mailbox GUID: %s",
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vname = t_strdup_printf("(error in mailbox with GUID=%s)",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid mailbox_set_reason(struct mailbox *box, const char *reason)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenbool mailbox_is_autocreated(struct mailbox *box)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int mailbox_autocreate(struct mailbox *box)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen errstr = mailbox_get_last_internal_error(box, &error);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Failed to autocreate mailbox %s: %s",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Failed to autosubscribe to mailbox %s: %s",
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenstatic int mailbox_autocreate_and_reopen(struct mailbox *box)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen !box->storage->user->inbox_open_error_logged) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Opening INBOX failed: %s",
41955c400476941fa274f18b106a5922866fd780Timo Sirainenmailbox_name_verify_separators(const char *vname, char sep,
41955c400476941fa274f18b106a5922866fd780Timo Sirainen const char **error_r)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen unsigned int i;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen /* Make sure the vname is correct: non-empty, doesn't begin or end
41955c400476941fa274f18b106a5922866fd780Timo Sirainen with separator and no adjacent separators */
41955c400476941fa274f18b106a5922866fd780Timo Sirainen *error_r = "Has adjacent hierarchy separators";
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (prev_sep && i > 0) {
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainenstatic int mailbox_verify_name(struct mailbox *box)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* this is INBOX - don't bother with further checks */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen list_sep = mailbox_list_get_hierarchy_sep(box->list);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* vname is either "namespace/box" or "namespace" */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (strncmp(vname, ns->prefix, ns->prefix_len-1) != 0 ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen vname[ns->prefix_len-1] != ns->prefix[ns->prefix_len-1])) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* User input shouldn't normally be able to get us in
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen here. The main reason this isn't an assert is to
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen allow any input at all to mailbox_verify_*_name()
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen without crashing. */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Missing namespace prefix '%s'",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* "namespace/" isn't a valid mailbox name. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Invalid mailbox name");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ns_sep != list_sep && box->list->set.escape_char == '\0' &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, t_strdup_printf(
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Character not allowed in mailbox name: '%c'", list_sep));
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen !box->storage->set->mail_full_filesystem_access) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen "Invalid mailbox name: Begins with hierarchy separator");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!mailbox_name_verify_separators(vname, ns_sep, &error) ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen !mailbox_list_is_valid_name(box->list, box->name, &error)) {
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen t_strdup_printf("Invalid mailbox name: %s", error));
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainenstatic int mailbox_verify_existing_name(struct mailbox *box)
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen /* Make sure box->_path is set, so mailbox_get_path() works from
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen now on. Note that this may also fail with some backends if the
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mailbox doesn't exist. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) < 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (box->storage->error != MAIL_ERROR_NOTFOUND ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* if this is an autocreated mailbox, create it now */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic bool mailbox_name_has_control_chars(const char *name)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *p;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((unsigned char)*p < ' ')
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainenvoid mailbox_skip_create_name_restrictions(struct mailbox *box, bool set)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainenint mailbox_verify_create_name(struct mailbox *box)
a385399497bdb50d4dfce729ffc852b75ed46a36Timo Sirainen /* mailbox_alloc() already checks that vname is valid UTF8,
a385399497bdb50d4dfce729ffc852b75ed46a36Timo Sirainen so we don't need to verify that.
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen check vname instead of storage name, because vname is what is
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen visible to users, while storage name may be a fixed length GUID. */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (mailbox_name_has_control_chars(box->vname)) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Control characters not allowed in new mailbox names");
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (strlen(box->vname) > MAILBOX_LIST_NAME_MAX_LENGTH) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen "Mailbox name too long");
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen /* check individual component names, too */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen const char sep = mailbox_list_get_hierarchy_sep(box->list);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen while((name = strchr(old_name, sep)) != NULL) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (name - old_name > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen "Mailbox name too long");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (strlen(old_name) > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Mailbox name too long");
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic bool have_listable_namespace_prefix(struct mail_namespace *ns,
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if prefix has multiple hierarchies, match
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen any of the hierarchies */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (strncmp(ns->prefix, name, name_len) == 0 &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ns->prefix[name_len] == mail_namespace_get_sep(ns))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mailbox_exists(struct mailbox *box, bool auto_boxes,
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen /* unsure if this exists or not */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* the mailbox name is invalid. we don't know if it currently
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen exists or not, but since it can never be accessed in any way
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen report it as if it didn't exist. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (auto_boxes && mailbox_is_autocreated(box)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (box->v.exists(box, auto_boxes, existence_r) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!box->inbox_user && *existence_r == MAILBOX_EXISTENCE_NOSELECT &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen have_listable_namespace_prefix(box->storage->user->namespaces,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* listable namespace prefix always exists. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if this is a shared namespace with only INBOX and
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_shared_explicit_inbox=no, we'll need to mark the namespace as
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen usable here since nothing else will. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenmailbox_open_full(struct mailbox *box, struct istream *input)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (box->storage->set->mail_debug && box->reason != NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_storage_set_internal_error(box->storage);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Storage doesn't support streamed mailboxes");
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic bool mailbox_try_undelete(struct mailbox *box)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((box->flags & MAILBOX_FLAG_READONLY) != 0) {
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen /* most importantly we don't do this because we want to avoid
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen a loop: mdbox storage rebuild -> mailbox_open() ->
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mailbox_mark_index_deleted() -> mailbox_sync() ->
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mdbox storage rebuild. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (mail_index_get_modification_time(box->index, &mtime) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen int ret = mailbox_mark_index_deleted(box, FALSE);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* check that the storage supports stubs if require them */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (((box->flags & MAILBOX_FLAG_USE_STUBS) != 0) &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ((box->storage->storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_STUBS) == 0)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "Mailbox does not support mail stubs");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!box->mailbox_deleted || box->mailbox_undeleting)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* mailbox has been marked as deleted. if this deletion
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen started (and crashed) a long time ago, it can be confusing
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen to user that the mailbox can't be opened. so we'll just
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen undelete it and reopen. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* make sure we close the mailbox in the middle. some backends
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen may not have fully opened the mailbox while it was being
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen undeleted. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int mailbox_alloc_index_pvt(struct mailbox *box)
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE) < 0)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen box->index_pvt = mail_index_alloc_cache_get(NULL, index_dir,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_strconcat(box->index_prefix, ".pvt", NULL));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_storage_get_lock_timeout(box->storage, UINT_MAX));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mailbox_open_index_pvt(struct mailbox *box)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((ret = mailbox_alloc_index_pvt(box)) <= 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mail_storage_settings_to_index_flags(box->storage->set);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0)
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen if (mail_index_open(box->index_pvt, index_flags) < 0)
e5601cd11edce275b4c423523bd00ee3e4eeae42Timo Sirainen box->view_pvt = mail_index_view_open(box->index_pvt);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mailbox_open_stream(struct mailbox *box, struct istream *input)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mailbox_enable(struct mailbox *box, enum mailbox_feature features)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenenum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenvoid mail_storage_free_binary_cache(struct mail_storage *storage)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_stream_destroy(&storage->binary_cache.input);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen i_panic("Trying to close mailbox %s with open transactions",
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenbool mailbox_equals(const struct mailbox *box1,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen const struct mail_namespace *ns2, const char *vname2)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen struct mail_namespace *ns1 = mailbox_get_namespace(box1);
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainenstatic void mailbox_copy_cache_decisions_from_inbox(struct mailbox *box)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_namespace_find_inbox(box->storage->user->namespaces);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mailbox_alloc(ns->list, "INBOX", MAILBOX_FLAG_READONLY);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* this should be NoSelect but since inbox can never be
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen NoSelect we use EXISTENCE_NONE to avoid creating inbox by accident */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mailbox_set_reason(inbox, "copy caching decisions");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (mailbox_exists(inbox, FALSE, &existence) == 0 &&
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen mail_cache_decisions_copy(dit, inbox->cache, box->cache);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* we can't do much about errors here */
942302b0247403645394d848b3c620ead262a2a5Timo Sirainenint mailbox_create(struct mailbox *box, const struct mailbox_update *update,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ret = box->v.create_box(box, update, directory);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* Creation failed after (partially) opening the mailbox.
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen It may not be in a valid state, so close it. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mailbox_update(struct mailbox *box, const struct mailbox_update *update)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen update->min_first_recent_uid <= update->min_next_uid);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainenint mailbox_mark_index_deleted(struct mailbox *box, bool del)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen enum mail_index_transaction_flags trans_flags = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* we already marked it deleted. this allows plugins to
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen "lock" the deletion earlier. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen box->flags = (box->flags & ~MAILBOX_FLAG_OPEN_DELETED) | old_flag;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen trans = mail_index_transaction_begin(box->view, trans_flags);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_index_transaction_commit(&trans) < 0) {
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen /* sync the mailbox. this finishes the index deletion and it
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen can succeed only for a single session. we do it here, so the
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen rest of the deletion code doesn't have to worry about race
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen conditions. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenstatic void mailbox_close_reset_path(struct mailbox *box)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Storage root can't be deleted");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND &&
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* might be a \noselect mailbox, so continue deletion */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* deletion failed. revert the mark so it can maybe be
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen tried again later. */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (mailbox_mark_index_deleted(box, FALSE) < 0)
return ret;
int ret;
return ret;
const char **error_r)
return TRUE;
return FALSE;
return FALSE;
return TRUE;
const char **error_r)
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret = 0;
return ret;
struct mail_namespace *
return FALSE;
i_unreached();
struct mailbox_sync_context *
T_BEGIN {
} T_END;
return ctx;
const char *errormsg;
int ret;
if (ret == 0)
return ret;
struct mail_search_context *
int ret;
return ret;
bool tryagain;
if (!tryagain)
return FALSE;
return TRUE;
return FALSE;
return TRUE;
int ret;
if (ret < 0)
return ret;
struct mailbox_transaction_context *
return trans;
int ret;
return ret;
int ret;
T_BEGIN {
} T_END;
return ret;
const char *reason)
struct mailbox *
return t->box;
struct mail_save_context *
T_BEGIN {
} T_END;
return ctx;
const char *const *keywords_list;
const char *envelope)
unsigned int order)
int ret;
} else T_BEGIN {
} T_END;
if (ret < 0) {
int ret;
T_BEGIN {
} T_END;
return ret;
int ret;
T_BEGIN {
} T_END;
if (pvt_flags != 0)
t->save_count++;
return ret;
T_BEGIN {
} T_END;
struct mailbox_transaction_context *
int ret;
T_BEGIN {
} T_END;
if (ret == 0) {
if (pvt_flags != 0)
t->save_count++;
return ret;
int ret;
return ret;
int ret;
if (ret < 0) {
return ret;
const char **path_r)
int *fd_r)
int fd;
const char *root_dir;
int ret;
return ret;
&mail_dir) < 0)
unsigned int secs)
#ifndef MMAP_CONFLICTS_WRITE
return index_flags;
bool *utc_r)
unsigned int secs;
const char *error;
T_BEGIN {
} T_END;
const char **error_r)
const char *lock_path;
bool created;