mail-storage.c revision b12798bbbda561680191eef393c6ee7259569850
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenextern struct mail_search_register *mail_search_register_imap;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenextern struct mail_search_register *mail_search_register_human;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstruct mail_module_register mail_module_register = { 0 };
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_search_register_deinit(&mail_search_register_human);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* append it after the list, so the autodetection order is correct */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen classes = array_get(&mail_storage_classes, &count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < count; i++) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen unsigned int i, count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen classes = array_get(&mail_storage_classes, &count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; i < count; i++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen unsigned int i, count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen classes = array_get(&mail_storage_classes, &count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < count; i++) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const char *p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* no autodetection if the storage driver is given. */
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen enum mail_storage_flags flags, const char **error_r)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen /* no mail_location, autodetect */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen /* explicit autodetection with "auto" driver. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* handle the same as with driver=NULL */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* no root directory given. is this allowed? */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* autodetection should take care of this */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* root not required for this storage */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* root not required for this layout */
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Mail storage autodetection failed with home=%s", home);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Autodetection failed for %s (home=%s)",
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Ambiguous mail location setting, "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "don't know what to do with it: %s "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "(try prefixing it with mbox: or maildir:)",
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenmail_storage_verify_root(const char *root_dir, const char *dir_type,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen "Root mail directory is a file: %s", root_dir);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen } else if (!autocreate) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen "Root %s directory doesn't exist: %s", dir_type, root_dir);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* doesn't exist */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen enum mail_storage_flags flags, const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (!mailbox_list_get_root_path(list, type, &root_dir)) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen /* we don't need to verify, but since debugging is
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen enabled, check and log if the root doesn't exist */
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (mail_storage_verify_root(root_dir, type_name, FALSE, &error) < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (autocreate && list->set.iter_from_index_dir) {
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen /* If the directories don't exist, we'll just autocreate them
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen later. FIXME: Make this the default in v2.3 even when
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen ITERINDEX isn't used. */
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen ret = mail_storage_verify_root(root_dir, type_name, autocreate, error_r);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenmail_storage_match_class(struct mail_storage *storage,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (set->root_dir != NULL ? set->root_dir : "")) != 0)
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen /* allow multiple independent shared namespaces */
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen struct mail_storage *storage = user->storages;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen for (; storage != NULL; storage = storage->next) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mail_storage_match_class(storage, storage_class, set))
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *data, enum mail_storage_flags flags,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char **error_r)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mail_storage *storage_class, *storage = NULL;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *p;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen header MD5 sums stored even if we're not running POP3
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen right now. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mailbox_list_settings_init_defaults(&list_set);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* autodetect */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* internal shared namespace */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen mail_storage_set_autodetection(&data, &driver);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* first storage for namespace */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (mail_storage_is_mailbox_file(storage_class))
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_LIST_DELETES) != 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* using an existing storage */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen enum mail_storage_flags flags, const char **error_r)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return mail_storage_create_full(ns, driver, ns->set->location,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* set *_storage=NULL only after calling destroy() callback.
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen for example mdbox wants to access ns->storage */
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen i_panic("Trying to deinit storage without freeing mailbox %s",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_panic("Trying to deinit storage before freeing its objects");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen if (array_is_created(&storage->error_stack)) {
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen i_assert(array_count(&storage->error_stack) == 0);
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainenvoid mail_storage_obj_ref(struct mail_storage *storage)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenvoid mail_storage_obj_unref(struct mail_storage *storage)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen const char *str;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
b82d6d7f02734007c129fa25bc876049c8d9bddeTimo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const char *fmt, ...)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen char *old_error = storage->last_internal_error;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->last_internal_error = i_strdup_vprintf(fmt, va);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* free the old_error only after the new error is generated, because
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen the old_error may be one of the parameters. */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* critical errors may contain sensitive data, so let user
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen see only "Internal error" with a timestamp to make it
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen easier to look from log files the actual error message. */
e91543761d0b7b97a1dc28e036e44d76405545c2Timo Sirainenconst char *mail_storage_get_last_internal_error(struct mail_storage *storage,
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen i_assert(storage->last_internal_error != NULL);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen return mail_storage_get_last_error(storage, error_r);
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainenconst char *mailbox_get_last_internal_error(struct mailbox *box,
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen return mail_storage_get_last_internal_error(mailbox_get_storage(box),
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainenvoid mail_storage_copy_error(struct mail_storage *dest,
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen const char *str;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen str = mail_storage_get_last_error(src, &error);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volkvoid mail_storage_copy_list_error(struct mail_storage *storage,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk const char *str;
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen str = mailbox_list_get_last_error(list, &error);
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainenvoid mailbox_set_index_error(struct mailbox *box)
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mail_storage_set_internal_error(box->storage);
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainenmail_storage_get_settings(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint mail_storage_purge(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* We get here only in error situations, so we have to return some
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen error. If storage->error is NONE, it means we forgot to set it at
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen some point.. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return storage->error_string != NULL ? storage->error_string :
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "BUG: Unknown internal error";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* This shouldn't happen.. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenconst char *mailbox_get_last_error(struct mailbox *box,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return mail_storage_get_last_error(box->storage, error_r);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenenum mail_error mailbox_get_last_mail_error(struct mailbox *box)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_storage_get_last_error(box->storage, &error);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenvoid mail_storage_last_error_push(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen err = array_append_space(&storage->error_stack);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen err->error_string = i_strdup(storage->error_string);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen err->last_error_is_internal = storage->last_error_is_internal;
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen err->last_internal_error = i_strdup(storage->last_internal_error);
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainenvoid mail_storage_last_error_pop(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unsigned int count = array_count(&storage->error_stack);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen storage->last_error_is_internal = err->last_error_is_internal;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen storage->last_internal_error = err->last_internal_error;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen array_delete(&storage->error_stack, count-1, 1);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (!mail_error_from_errno(&error, &error_string))
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* debugging is enabled - admin may be debugging a
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (permission) problem, so return FALSE to get the caller to
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen log the full error message. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_storage_set_error(storage, error, error_string);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenmailbox_settings_find(struct mail_namespace *ns, const char *vname)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen strncmp(ns->prefix, vname, ns->prefix_len-1) == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (vname[ns->prefix_len-1] == mail_namespace_get_sep(ns))
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen /* namespace prefix itself */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen /* make sure INBOX shows up in uppercase everywhere. do this
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen regardless of whether we're in inbox=yes namespace, because
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen clients expect INBOX to be case insensitive regardless of
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen server's internal configuration. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen else if (vname[5] != mail_namespace_get_sep(list->ns))
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen /* not INBOX prefix */ ;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen else if (strncasecmp(list->ns->prefix, vname, 6) == 0 &&
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen "Invalid server configuration: "
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen "Namespace prefix=%s must be uppercase INBOX",
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen vname = t_strconcat("INBOX", vname + 5, NULL);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* do a delayed failure at mailbox_open() */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen storage = mail_namespace_get_default_storage(list->ns);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen errstr = mailbox_list_get_last_error(new_list, &open_error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen box->set = mailbox_settings_find(new_list->ns, vname);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen mail_storage_set_error(storage, open_error, errstr);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen DLLIST_PREPEND(&box->storage->mailboxes, box);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainenstruct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen /* GUID mismatch, refresh cache and try again */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* successfully opened the correct mailbox */
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen "Couldn't verify mailbox GUID: %s",
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen vname = t_strdup_printf("(error in mailbox with GUID=%s)",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_set_reason(struct mailbox *box, const char *reason)
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenbool mailbox_is_autocreated(struct mailbox *box)
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenstatic int mailbox_autocreate(struct mailbox *box)
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen errstr = mailbox_get_last_internal_error(box, &error);
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen "Failed to autocreate mailbox %s: %s",
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen "Failed to autosubscribe to mailbox %s: %s",
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstatic int mailbox_autocreate_and_reopen(struct mailbox *box)
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen !box->storage->user->inbox_open_error_logged) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
6b8bcce7a001076605cb2cfdca8507204c88f376Timo Sirainen "Opening INBOX failed: %s",
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenmailbox_name_verify_separators(const char *vname, char sep,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen const char **error_r)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen unsigned int i;
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* Make sure the vname is correct: non-empty, doesn't begin or end
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen with separator and no adjacent separators */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen *error_r = "Has adjacent hierarchy separators";
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (prev_sep && i > 0) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenstatic int mailbox_verify_name(struct mailbox *box)
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* this is INBOX - don't bother with further checks */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen list_sep = mailbox_list_get_hierarchy_sep(box->list);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* vname is either "namespace/box" or "namespace" */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (strncmp(vname, ns->prefix, ns->prefix_len-1) != 0 ||
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen vname[ns->prefix_len-1] != ns->prefix[ns->prefix_len-1])) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* User input shouldn't normally be able to get us in
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen here. The main reason this isn't an assert is to
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen allow any input at all to mailbox_verify_*_name()
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen without crashing. */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen "Missing namespace prefix '%s'",
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* "namespace/" isn't a valid mailbox name. */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen "Invalid mailbox name");
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (ns_sep != list_sep && box->list->set.escape_char == '\0' &&
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, t_strdup_printf(
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen "Character not allowed in mailbox name: '%c'", list_sep));
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen !box->storage->set->mail_full_filesystem_access) {
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen "Invalid mailbox name: Begins with hierarchy separator");
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen if (!mailbox_name_verify_separators(vname, ns_sep, &error) ||
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen !mailbox_list_is_valid_name(box->list, box->name, &error)) {
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen t_strdup_printf("Invalid mailbox name: %s", error));
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainenstatic int mailbox_verify_existing_name(struct mailbox *box)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen /* Make sure box->_path is set, so mailbox_get_path() works from
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen now on. Note that this may also fail with some backends if the
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen mailbox doesn't exist. */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) < 0) {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (box->storage->error != MAIL_ERROR_NOTFOUND ||
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen /* if this is an autocreated mailbox, create it now */
407453d06e5622ac3bf099cc76bfcbfb5860b444Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstatic bool mailbox_name_has_control_chars(const char *name)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const char *p;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if ((unsigned char)*p < ' ')
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenvoid mailbox_skip_create_name_restrictions(struct mailbox *box, bool set)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenint mailbox_verify_create_name(struct mailbox *box)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen /* mailbox_alloc() already checks that vname is valid UTF8,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen so we don't need to verify that.
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen check vname instead of storage name, because vname is what is
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen visible to users, while storage name may be a fixed length GUID. */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (mailbox_name_has_control_chars(box->vname)) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen "Control characters not allowed in new mailbox names");
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (strlen(box->vname) > MAILBOX_LIST_NAME_MAX_LENGTH) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen "Mailbox name too long");
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* check individual component names, too */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen const char sep = mailbox_list_get_hierarchy_sep(box->list);
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen while((name = strchr(old_name, sep)) != NULL) {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (name - old_name > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen "Mailbox name too long");
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if (strlen(old_name) > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen "Mailbox name too long");
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenstatic bool have_listable_namespace_prefix(struct mail_namespace *ns,
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen /* if prefix has multiple hierarchies, match
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen any of the hierarchies */
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen if (strncmp(ns->prefix, name, name_len) == 0 &&
547847191d4a95cd267fc846a1ca3c2111214719Timo Sirainen ns->prefix[name_len] == mail_namespace_get_sep(ns))
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainenint mailbox_exists(struct mailbox *box, bool auto_boxes,
b337d3b6871b878d6467d7d8ed600433af5da5a1Timo Sirainen /* unsure if this exists or not */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* the mailbox name is invalid. we don't know if it currently
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen exists or not, but since it can never be accessed in any way
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen report it as if it didn't exist. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (auto_boxes && mailbox_is_autocreated(box)) {
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen if (box->v.exists(box, auto_boxes, existence_r) < 0)
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (!box->inbox_user && *existence_r == MAILBOX_EXISTENCE_NOSELECT &&
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen have_listable_namespace_prefix(box->storage->user->namespaces,
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen /* listable namespace prefix always exists. */
af86c8415338fc2ea1819dc091b971c93cbee5d2Timo Sirainen /* if this is a shared namespace with only INBOX and
af86c8415338fc2ea1819dc091b971c93cbee5d2Timo Sirainen mail_shared_explicit_inbox=no, we'll need to mark the namespace as
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen usable here since nothing else will. */
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainenmailbox_open_full(struct mailbox *box, struct istream *input)
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen if (box->storage->set->mail_debug && box->reason != NULL) {
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen mail_storage_set_internal_error(box->storage);
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen "Storage doesn't support streamed mailboxes");
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstatic bool mailbox_try_undelete(struct mailbox *box)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if ((box->flags & MAILBOX_FLAG_READONLY) != 0) {
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen /* most importantly we don't do this because we want to avoid
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen a loop: mdbox storage rebuild -> mailbox_open() ->
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen mailbox_mark_index_deleted() -> mailbox_sync() ->
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen mdbox storage rebuild. */
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen if (mail_index_get_modification_time(box->index, &mtime) < 0)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL))
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen int ret = mailbox_mark_index_deleted(box, FALSE);
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen /* check that the storage supports stubs if require them */
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen if (((box->flags & MAILBOX_FLAG_USE_STUBS) != 0) &&
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen ((box->storage->storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_STUBS) == 0)) {
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen "Mailbox does not support mail stubs");
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen if (!box->mailbox_deleted || box->mailbox_undeleting)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen /* mailbox has been marked as deleted. if this deletion
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen started (and crashed) a long time ago, it can be confusing
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen to user that the mailbox can't be opened. so we'll just
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen undelete it and reopen. */
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen /* make sure we close the mailbox in the middle. some backends
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen may not have fully opened the mailbox while it was being
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen undeleted. */
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainenstatic int mailbox_alloc_index_pvt(struct mailbox *box)
0185427dd52fddec6fc76d6e99c7659620d4366eTimo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE) < 0)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen box->index_pvt = mail_index_alloc_cache_get(NULL, index_dir,
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen t_strconcat(box->index_prefix, ".pvt", NULL));
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen mail_storage_get_lock_timeout(box->storage, UINT_MAX));
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenint mailbox_open_index_pvt(struct mailbox *box)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if ((ret = mailbox_alloc_index_pvt(box)) <= 0)
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainen mail_storage_settings_to_index_flags(box->storage->set);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen if (mail_index_open(box->index_pvt, index_flags) < 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen box->view_pvt = mail_index_view_open(box->index_pvt);
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenint mailbox_open_stream(struct mailbox *box, struct istream *input)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenint mailbox_enable(struct mailbox *box, enum mailbox_feature features)
4366a21968093172d9b757fe6894b1ee8916434eTimo Sirainenenum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenvoid mail_storage_free_binary_cache(struct mail_storage *storage)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen i_stream_destroy(&storage->binary_cache.input);
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen i_panic("Trying to close mailbox %s with open transactions",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_equals(const struct mailbox *box1,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mail_namespace *ns2, const char *vname2)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_namespace *ns1 = mailbox_get_namespace(box1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void mailbox_copy_cache_decisions_from_inbox(struct mailbox *box)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_namespace_find_inbox(box->storage->user->namespaces);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_alloc(ns->list, "INBOX", MAILBOX_FLAG_READONLY);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* this should be NoSelect but since inbox can never be
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen NoSelect we use EXISTENCE_NONE to avoid creating inbox by accident */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_set_reason(inbox, "copy caching decisions");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mailbox_exists(inbox, FALSE, &existence) == 0 &&
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_cache_decisions_copy(dit, inbox->cache, box->cache);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* we can't do much about errors here */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenint mailbox_create(struct mailbox *box, const struct mailbox_update *update,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen ret = box->v.create_box(box, update, directory);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* Creation failed after (partially) opening the mailbox.
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen It may not be in a valid state, so close it. */
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenint mailbox_update(struct mailbox *box, const struct mailbox_update *update)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen update->min_first_recent_uid <= update->min_next_uid);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenint mailbox_mark_index_deleted(struct mailbox *box, bool del)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen enum mail_index_transaction_flags trans_flags = 0;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen /* we already marked it deleted. this allows plugins to
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen "lock" the deletion earlier. */
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen box->flags = (box->flags & ~MAILBOX_FLAG_OPEN_DELETED) | old_flag;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen trans = mail_index_transaction_begin(box->view, trans_flags);
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen if (mail_index_transaction_commit(&trans) < 0) {
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen /* sync the mailbox. this finishes the index deletion and it
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen can succeed only for a single session. we do it here, so the
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen rest of the deletion code doesn't have to worry about race
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen conditions. */
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen ret = mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
b30f98f260924a50343c4d0493a7c4fe5e714d0fTimo Sirainenstatic void mailbox_close_reset_path(struct mailbox *box)
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen "Storage root can't be deleted");
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND &&
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen /* might be a \noselect mailbox, so continue deletion */
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen /* deletion failed. revert the mark so it can maybe be
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen tried again later. */
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (mailbox_mark_index_deleted(box, FALSE) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* if mailbox is reopened, its path may be different with
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen LAYOUT=index */
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen /* FIXME: should be a parameter to delete(), but since it changes API
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen don't do it for now */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmail_storages_rename_compatible(struct mail_storage *storage1,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcmp(storage1->name, storage2->name) != 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *error_r = t_strdup_printf("storage %s != %s",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((storage1->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* e.g. mdbox where all mails are in storage/ directory and
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen they can't be easily moved from there. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *error_r = t_strdup_printf("storage %s uses unique root",
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenstatic bool nullequals(const void *p1, const void *p2)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return (p1 == NULL && p2 == NULL) || (p1 != NULL && p2 != NULL);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenmailbox_lists_rename_compatible(struct mailbox_list *list1,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char **error_r)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!nullequals(list1->set.alt_dir, list2->set.alt_dir)) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen *error_r = "one namespace has alt dir and another doesn't";
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret = 0;
return ret;
struct mail_namespace *
return FALSE;
i_unreached();
struct mailbox_sync_context *
return ctx;
T_BEGIN {
} T_END;
return ctx;
return FALSE;
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;