mail-storage.c revision 3fe2850e38ec8192e1c26f370c748d0a8a9685b3
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct mail_search_register *mail_search_register_imap;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct mail_search_register *mail_search_register_human;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_search_register_deinit(&mail_search_register_human);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen /* append it after the list, so the autodetection order is correct */
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen classes = array_get(&mail_storage_classes, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen unsigned int i, count;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen classes = array_get(&mail_storage_classes, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen unsigned int i, count;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen classes = array_get(&mail_storage_classes, &count);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen for (i = 0; i < count; i++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *p;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* no autodetection if the storage driver is given. */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen enum mail_storage_flags flags, const char **error_r)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* no mail_location, autodetect */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* explicit autodetection with "auto" driver. */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* handle the same as with driver=NULL */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* no root directory given. is this allowed? */
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* autodetection should take care of this */
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* root not required for this storage */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* root not required for this layout */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen "Mail storage autodetection failed with home=%s", home);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "Autodetection failed for %s (home=%s)",
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "Ambiguous mail location setting, "
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "don't know what to do with it: %s "
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "(try prefixing it with mbox: or maildir:)",
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainenmail_storage_verify_root(const char *root_dir, bool autocreate,
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen const char **error_r)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen } else if (!autocreate) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen "Root mail directory doesn't exist: %s", root_dir);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* doesn't exist */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen enum mail_storage_flags flags, const char **error_r)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen /* we don't need to verify, but since debugging is
053843989f13d9013b265fb401a4bde7e0e6568eTimo Sirainen enabled, check and log if the root doesn't exist */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (mail_storage_verify_root(root_dir, FALSE, &error) < 0) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ret = mail_storage_verify_root(root_dir, autocreate, error_r);
ab286a8b58306eb8d22fc18342b6c199fd428e1eTimo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenmail_storage_match_class(struct mail_storage *storage,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen strcmp(storage->unique_root_dir, set->root_dir) != 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* allow multiple independent shared namespaces */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_storage *storage = user->storages;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (; storage != NULL; storage = storage->next) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (mail_storage_match_class(storage, storage_class, set))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char *data, enum mail_storage_flags flags,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char **error_r)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *p;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen header MD5 sums stored even if we're not running POP3
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen right now. */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* autodetect */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* internal shared namespace */
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen mail_storage_set_autodetection(&data, &driver);
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen /* first storage for namespace */
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen if (mail_storage_is_mailbox_file(storage_class))
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* using an existing storage */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum mail_storage_flags flags, const char **error_r)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return mail_storage_create_full(ns, driver, ns->set->location,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen /* set *_storage=NULL only after calling destroy() callback.
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for example mdbox wants to access ns->storage */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_panic("Trying to deinit storage without freeing mailbox %s",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_panic("Trying to deinit storage before freeing its objects");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_obj_ref(struct mail_storage *storage)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_obj_unref(struct mail_storage *storage)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *str;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *fmt, ...)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen /* critical errors may contain sensitive data, so let user
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen see only "Internal error" with a timestamp to make it
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen easier to look from log files the actual error message. */
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenvoid mail_storage_copy_error(struct mail_storage *dest,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *str;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen str = mail_storage_get_last_error(src, &error);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = mailbox_list_get_last_error(list, &error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_set_index_error(struct mailbox *box)
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mail_storage_set_internal_error(box->storage);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainenmail_storage_get_settings(struct mail_storage *storage)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* We get here only in error situations, so we have to return some
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen error. If storage->error is NONE, it means we forgot to set it at
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen some point.. */
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen return storage->error_string != NULL ? storage->error_string :
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen "BUG: Unknown internal error";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* This shouldn't happen.. */
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainenconst char *mailbox_get_last_error(struct mailbox *box,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return mail_storage_get_last_error(box->storage, error_r);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenenum mail_error mailbox_get_last_mail_error(struct mailbox *box)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen mail_storage_get_last_error(box->storage, &error);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* debugging is enabled - admin may be debugging a
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (permission) problem, so return FALSE to get the caller to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log the full error message. */
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen mail_storage_set_error(storage, error, error_string);
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainenmailbox_settings_find(struct mail_user *user, const char *vname)
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen ns = mail_namespace_find(user->namespaces, vname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen strncmp(ns->prefix, vname, ns->prefix_len-1) == 0) {
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen if (vname[ns->prefix_len-1] == mail_namespace_get_sep(ns))
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen /* namespace prefix itself */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen /* make sure INBOX shows up in uppercase everywhere. do this
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen regardless of whether we're in inbox=yes namespace, because
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen clients expect INBOX to be case insensitive regardless of
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen server's internal configuration. */
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen else if (vname[5] != mail_namespace_get_sep(list->ns))
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen /* not INBOX prefix */ ;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen else if (strncasecmp(list->ns->prefix, vname, 6) == 0 &&
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Invalid server configuration: "
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Namespace prefix=%s must be uppercase INBOX",
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen vname = t_strconcat("INBOX", vname + 5, NULL);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* do a delayed failure at mailbox_open() */
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen storage = mail_namespace_get_default_storage(list->ns);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen errstr = mailbox_list_get_last_error(new_list, &open_error);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->set = mailbox_settings_find(storage->user, vname);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_storage_set_error(storage, open_error, errstr);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen DLLIST_PREPEND(&box->storage->mailboxes, box);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstruct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen /* GUID mismatch, refresh cache and try again */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* successfully opened the correct mailbox */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen "Couldn't verify mailbox GUID: %s",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen vname = t_strdup_printf("(error in mailbox with GUID=%s)",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic bool mailbox_is_autocreated(struct mailbox *box)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic int mailbox_autocreate(struct mailbox *box)
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Failed to autocreate mailbox %s: %s",
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Failed to autosubscribe to mailbox %s: %s",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->vname, mailbox_get_last_error(box, NULL));
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenstatic int mailbox_autocreate_and_reopen(struct mailbox *box)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen !box->storage->user->inbox_open_error_logged) {
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen "Opening INBOX failed: %s",
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenmailbox_name_verify_separators(const char *vname, char sep,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen const char **error_r)
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen unsigned int i;
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen /* Make sure the vname is correct: non-empty, doesn't begin or end
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen with separator and no adjacent separators */
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen *error_r = "Has adjacent hierarchy separators";
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (prev_sep && i > 0) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainenstatic int mailbox_verify_name(struct mailbox *box)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* this is INBOX - don't bother with further checks */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen list_sep = mailbox_list_get_hierarchy_sep(box->list);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* vname is either "namespace/box" or "namespace" */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen i_assert(strncmp(vname, ns->prefix, ns->prefix_len-1) == 0);
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* "namespace/" isn't a valid mailbox name. */
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen "Invalid mailbox name");
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (ns_sep != list_sep && box->list->set.escape_char == '\0' &&
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, t_strdup_printf(
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen "Character not allowed in mailbox name: '%c'", list_sep));
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen !box->storage->set->mail_full_filesystem_access) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen "Invalid mailbox name: Begins with hierarchy separator");
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (!mailbox_name_verify_separators(vname, ns_sep, &error) ||
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen !mailbox_list_is_valid_name(box->list, box->name, &error)) {
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen t_strdup_printf("Invalid mailbox name: %s", error));
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainenstatic int mailbox_verify_existing_name(struct mailbox *box)
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen /* Make sure box->_path is set, so mailbox_get_path() works from
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen now on. Note that this may also fail with some backends if the
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen mailbox doesn't exist. */
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) < 0) {
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen if (box->storage->error != MAIL_ERROR_NOTFOUND ||
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* if this is an autocreated mailbox, create it now */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainenstatic bool mailbox_name_has_control_chars(const char *name)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen const char *p;
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen if ((unsigned char)*p < ' ')
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainenint mailbox_verify_create_name(struct mailbox *box)
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen char sep = mail_namespace_get_sep(box->list->ns);
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen /* mailbox_alloc() already checks that vname is valid UTF8,
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen so we don't need to verify that.
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen check vname instead of storage name, because vname is what is
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen visible to users, while storage name may be a fixed length GUID. */
09714f2f8d4c8cc7d89930f7eb836816d8dc9eb8Timo Sirainen if (mailbox_name_has_control_chars(box->vname)) {
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen "Control characters not allowed in new mailbox names");
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen if (mailbox_list_name_is_too_large(box->vname, sep)) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen "Mailbox name too long");
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainenstatic bool have_listable_namespace_prefix(struct mail_namespace *ns,
2ef8fac74c9d0bfc330bf53bb06df7e9d5f08e7dTimo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* if prefix has multiple hierarchies, match
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen any of the hierarchies */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (strncmp(ns->prefix, name, name_len) == 0 &&
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen ns->prefix[name_len] == mail_namespace_get_sep(ns))
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainenint mailbox_exists(struct mailbox *box, bool auto_boxes,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen /* unsure if this exists or not */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen /* the mailbox name is invalid. we don't know if it currently
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen exists or not, but since it can never be accessed in any way
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen report it as if it didn't exist. */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (auto_boxes && box->set != NULL && mailbox_is_autocreated(box)) {
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (box->v.exists(box, auto_boxes, existence_r) < 0)
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen if (!box->inbox_user && *existence_r == MAILBOX_EXISTENCE_NOSELECT &&
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen have_listable_namespace_prefix(box->storage->user->namespaces,
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen /* listable namespace prefix always exists. */
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen /* if this is a shared namespace with only INBOX and
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen mail_shared_explicit_inbox=no, we'll need to mark the namespace as
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen usable here since nothing else will. */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainenmailbox_open_full(struct mailbox *box, struct istream *input)
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_storage_set_internal_error(box->storage);
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen "Storage doesn't support streamed mailboxes");
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic bool mailbox_try_undelete(struct mailbox *box)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((box->flags & MAILBOX_FLAG_READONLY) != 0) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* most importantly we don't do this because we want to avoid
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen a loop: mdbox storage rebuild -> mailbox_open() ->
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen mailbox_mark_index_deleted() -> mailbox_sync() ->
19593623a2278039be23fc93e3404c012920b664Timo Sirainen mdbox storage rebuild. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_get_modification_time(box->index, &mtime) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL))
3e4bbbceed7882b8dab558aa90913a491eb15cc6Timo Sirainen if (mailbox_mark_index_deleted(box, FALSE) < 0)
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen /* mailbox has been marked as deleted. if this deletion
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen started (and crashed) a long time ago, it can be confusing
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen to user that the mailbox can't be opened. so we'll just
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen undelete it and reopen. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mailbox_alloc_index_pvt(struct mailbox *box)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE) < 0)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen box->index_pvt = mail_index_alloc_cache_get(NULL, index_dir,
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen t_strconcat(box->index_prefix, ".pvt", NULL));
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_storage_get_lock_timeout(box->storage, UINT_MAX));
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenint mailbox_open_index_pvt(struct mailbox *box)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((ret = mailbox_alloc_index_pvt(box)) <= 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mail_index_open(box->index_pvt, MAIL_INDEX_OPEN_FLAG_CREATE) < 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->view_pvt = mail_index_view_open(box->index_pvt);
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainenint mailbox_open_stream(struct mailbox *box, struct istream *input)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainenint mailbox_enable(struct mailbox *box, enum mailbox_feature features)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenenum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenvoid mail_storage_free_binary_cache(struct mail_storage *storage)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen i_stream_destroy(&storage->binary_cache.input);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen memset(&storage->binary_cache, 0, sizeof(storage->binary_cache));
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen i_panic("Trying to close mailbox %s with open transactions",
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainenbool mailbox_equals(const struct mailbox *box1,
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen const struct mail_namespace *ns2, const char *vname2)
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen struct mail_namespace *ns1 = mailbox_get_namespace(box1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_create(struct mailbox *box, const struct mailbox_update *update,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = box->v.create_box(box, update, directory);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenint mailbox_update(struct mailbox *box, const struct mailbox_update *update)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen update->min_first_recent_uid <= update->min_next_uid);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenint mailbox_mark_index_deleted(struct mailbox *box, bool del)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen enum mail_index_transaction_flags trans_flags = 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* we already marked it deleted. this allows plugins to
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "lock" the deletion earlier. */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->flags = (box->flags & ~MAILBOX_FLAG_OPEN_DELETED) | old_flag;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen trans = mail_index_transaction_begin(box->view, trans_flags);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (mail_index_transaction_commit(&trans) < 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* sync the mailbox. this finishes the index deletion and it can
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen succeed only for a single session. we do it here, so the rest of
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen the deletion code doesn't have to worry about race conditions. */
c9f1a617593eb569fb02f45041bad3c13e534496Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "Storage root can't be deleted");
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* \noselect mailbox */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* deletion failed. revert the mark so it can maybe be
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen tried again later. */
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (mailbox_mark_index_deleted(box, FALSE) < 0)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* FIXME: should be a parameter to delete(), but since it changes API
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen don't do it for now */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_storages_rename_compatible(struct mail_storage *storage1,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcmp(storage1->name, storage2->name) != 0) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen *error_r = t_strdup_printf("storage %s != %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((storage1->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0) {
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen /* e.g. mdbox where all mails are in storage/ directory and
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen they can't be easily moved from there. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strdup_printf("storage %s uses unique root",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool nullequals(const void *p1, const void *p2)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return (p1 == NULL && p2 == NULL) || (p1 != NULL && p2 != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_lists_rename_compatible(struct mailbox_list *list1,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!nullequals(list1->set.alt_dir, list2->set.alt_dir)) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen *error_r = "one namespace has alt dir and another doesn't";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!nullequals(list1->set.index_dir, list2->set.index_dir)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "one namespace has index dir and another doesn't";
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (!nullequals(list1->set.control_dir, list2->set.control_dir)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "one namespace has control dir and another doesn't";
9fc077d3886b1584019bcc9b92c717cfffce5c67Timo Sirainenint mailbox_rename(struct mailbox *src, struct mailbox *dest)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Check only name validity, \Noselect don't necessarily exist. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Can't rename mailbox root");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_copy_error(dest->storage, src->storage);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_storages_rename_compatible(src->storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Can't rename mailboxes across specified storages.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (src->list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE ||
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen dest->list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)) {
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen "Renaming not supported across non-private namespaces.");
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen if (src->list == dest->list && strcmp(src->name, dest->name) == 0) {
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_EXISTS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Can't rename mailbox to itself.");
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainenint mailbox_set_subscribed(struct mailbox *box, bool set)
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainenbool mailbox_is_subscribed(struct mailbox *box)
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen node = mailbox_tree_lookup(box->list->subscriptions, box->vname);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen return node != NULL && (node->flags & MAILBOX_SUBSCRIBED) != 0;
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainenstruct mail_storage *mailbox_get_storage(const struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenmailbox_get_namespace(const struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenconst struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenconst char *mailbox_get_name(const struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenconst char *mailbox_get_vname(const struct mailbox *box)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool mailbox_backends_equal(const struct mailbox *box1,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen struct mail_namespace *ns1 = box1->list->ns, *ns2 = box2->list->ns;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_get_status_set_defaults(struct mailbox *box,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS) != 0)
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS) != 0)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen mailbox_get_status_set_defaults(box, status_r);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (box->v.get_status(box, items, status_r) < 0)
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen i_assert(status_r->have_guids || !status_r->have_save_guids);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenvoid mailbox_get_open_status(struct mailbox *box,
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_assert((items & MAILBOX_STATUS_FAILING_ITEMS) == 0);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen mailbox_get_status_set_defaults(box, status_r);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (box->v.get_status(box, items, status_r) < 0)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainenint mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (box->v.get_metadata(box, items, metadata_r) < 0)
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen i_assert((items & MAILBOX_METADATA_GUID) == 0 ||
99e8698f598d2b83da7c581584a538c0713fd11dTimo Sirainenenum mail_flags mailbox_get_private_flags_mask(struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen else if (box->list->set.index_pvt_dir != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_set(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_attribute_type type, const char *key,
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen return t->box->v.attribute_set(t, type, key, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_unset(struct mailbox_transaction_context *t,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen enum mail_attribute_type type, const char *key)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return t->box->v.attribute_set(t, type, key, &value);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenint mailbox_attribute_value_to_string(struct mail_storage *storage,
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen const char **str_r)
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen const unsigned char *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (i_stream_read_data(value->value_stream, &data, &size, 0) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Attribute string value has NULs");
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen mail_storage_set_critical(storage, "read(%s) failed: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_get(struct mailbox_transaction_context *t,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen enum mail_attribute_type type, const char *key,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if ((ret = t->box->v.attribute_get(t, type, key, value_r)) <= 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_get_stream(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_attribute_type type, const char *key,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_INT_STREAMS;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((ret = t->box->v.attribute_get(t, type, key, value_r)) <= 0)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_assert(value_r->value != NULL || value_r->value_stream != NULL);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenmailbox_attribute_iter_init(struct mailbox *box, enum mail_attribute_type type,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return box->v.attribute_iter_init(box, type, prefix);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenconst char *mailbox_attribute_iter_next(struct mailbox_attribute_iter *iter)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return iter->box->v.attribute_iter_next(iter);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenint mailbox_attribute_iter_deinit(struct mailbox_attribute_iter **_iter)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return iter->box->v.attribute_iter_deinit(iter);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenmailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_panic("Trying to sync mailbox %s with open transactions",
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenbool mailbox_sync_next(struct mailbox_sync_context *ctx,
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen return ctx->box->v.sync_next(ctx, sync_rec_r);
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainenint mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen !box->storage->user->inbox_open_error_logged) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen errormsg = mailbox_get_last_error(box, &error);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_error("Syncing INBOX failed: %s", errormsg);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenint mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* we don't care about mailbox's current state, so we might
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen as well fix inconsistency state */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenvoid mailbox_notify_changes(struct mailbox *box,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mailbox_notify_callback_t *callback, void *context)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenvoid mailbox_notify_changes_stop(struct mailbox *box)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenmailbox_search_init(struct mailbox_transaction_context *t,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return t->box->v.search_init(t, args, sort_program,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenint mailbox_search_deinit(struct mail_search_context **_ctx)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen ret = ctx->transaction->box->v.search_deinit(ctx);
321241fc56909ccb69d77c6a11686e0c25b4c4d4Timo Sirainenbool mailbox_search_next(struct mail_search_context *ctx, struct mail **mail_r)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen while (!mailbox_search_next_nonblock(ctx, mail_r, &tryagain)) {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenbool mailbox_search_next_nonblock(struct mail_search_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!box->v.search_next_nonblock(ctx, mail_r, tryagain_r))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mailbox_search_results_add(ctx, (*mail_r)->uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenbool mailbox_search_seen_lost_data(struct mail_search_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_search_result_build(struct mailbox_transaction_context *t,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen ctx = mailbox_search_init(t, args, NULL, 0, NULL);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen *result_r = mailbox_search_result_save(ctx, flags);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainenint mailbox_transaction_commit(struct mailbox_transaction_context **t)
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen struct mail_transaction_commit_changes changes;
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen /* Store changes temporarily so that plugins overriding
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen transaction_commit() can look at them. */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen ret = mailbox_transaction_commit_get_changes(t, &changes);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen struct mail_transaction_commit_changes *changes_r)
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen ret = box->v.transaction_commit(t, changes_r);
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen /* either all the saved messages get UIDs or none, because a) we
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen failed, b) MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS not set,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen c) backend doesn't support it (e.g. virtual plugin) */
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen seq_range_count(&changes_r->saved_uids) == save_count ||
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen /* decrease the transaction count only after transaction_commit().
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen that way if it creates and destroys transactions internally, we
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen don't see transaction_count=0 until the parent transaction is fully
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenunsigned int mailbox_transaction_get_count(const struct mailbox *box)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_transaction_set_max_modseq(t->itrans, max_modseq, seqs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_save_alloc(struct mailbox_transaction_context *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_save_set_flags(struct mail_save_context *ctx,
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen ctx->data.flags = flags & ~mailbox_get_private_flags_mask(box);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen ctx->data.pvt_flags = flags & mailbox_get_private_flags_mask(box);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainenvoid mailbox_save_copy_flags(struct mail_save_context *ctx, struct mail *mail)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen const char *const *keywords_list;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen keywords = str_array_length(keywords_list) == 0 ? NULL :
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mailbox_keywords_create_valid(ctx->transaction->box,
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mailbox_save_set_flags(ctx, mail_get_flags(mail), keywords);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainenvoid mailbox_save_set_min_modseq(struct mail_save_context *ctx,
const char *envelope)
unsigned int order)
int ret;
if (ret < 0) {
int ret;
if (pvt_flags != 0)
t->save_count++;
return ret;
struct mailbox_transaction_context *
int ret;
if (ret == 0) {
if (pvt_flags != 0)
t->save_count++;
return ret;
const char **path_r)
int ret;
if (ret < 0) {
return ret;
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;