mail-storage.c revision 3fe2850e38ec8192e1c26f370c748d0a8a9685b3
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "array.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "llist.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "unichar.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "eacces-error.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mkdir-parents.h"
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include "time-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "var-expand.h"
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen#include "mail-index-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-alloc-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mailbox-tree.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mailbox-list-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage-private.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "mail-storage-settings.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "mail-namespace.h"
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen#include "mail-search.h"
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen#include "mail-search-register.h"
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen#include "mailbox-search-result-private.h"
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen#include "mailbox-guid-cache.h"
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <ctype.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MAILBOX_DELETE_RETRY_SECS (60*5)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct mail_search_register *mail_search_register_imap;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct mail_search_register *mail_search_register_human;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo SirainenARRAY_TYPE(mail_storage) mail_storage_classes;
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenvoid mail_storage_init(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mailbox_lists_init();
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_storage_hooks_init();
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_array_init(&mail_storage_classes, 8);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenvoid mail_storage_deinit(void)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_search_register_human != NULL)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_search_register_deinit(&mail_search_register_human);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_search_register_imap != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&mail_storage_classes))
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen array_free(&mail_storage_classes);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_hooks_deinit();
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mailbox_lists_deinit();
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen /* append it after the list, so the autodetection order is correct */
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage *const *classes;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen classes = array_get(&mail_storage_classes, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (classes[i] == storage_class) {
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen array_delete(&mail_storage_classes, i, 1);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen break;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen }
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen }
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen}
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_storage *const *classes;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen unsigned int i, count;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen i_assert(name != NULL);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen classes = array_get(&mail_storage_classes, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (strcasecmp(classes[i]->name, name) == 0)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return classes[i];
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return NULL;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainenstatic struct mail_storage *
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen struct mailbox_list_settings *set)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct mail_storage *const *classes;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen unsigned int i, count;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen classes = array_get(&mail_storage_classes, &count);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen for (i = 0; i < count; i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (classes[i]->v.autodetect != NULL) {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (classes[i]->v.autodetect(ns, set))
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return classes[i];
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainenstatic void
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *p;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen p = *data;
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen while (i_isalnum(*p) || *p == '_') p++;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen if (*p == ':' && p != *data) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* no autodetection if the storage driver is given. */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *driver = t_strdup_until(*data, p);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *data = p + 1;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic struct mail_storage *
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen struct mailbox_list_settings *list_set,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen enum mail_storage_flags flags, const char **error_r)
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_storage *storage_class = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const char *home;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (driver == NULL) {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* no mail_location, autodetect */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } else if (strcmp(driver, "auto") == 0) {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* explicit autodetection with "auto" driver. */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (list_set->root_dir != NULL &&
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen *list_set->root_dir == '\0') {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* handle the same as with driver=NULL */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen list_set->root_dir = NULL;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen } else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (storage_class == NULL) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *error_r = t_strdup_printf(
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen "Unknown mail storage driver %s", driver);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return NULL;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* no root directory given. is this allowed? */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen const struct mailbox_list *list;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen list = list_set->layout == NULL ? NULL :
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mailbox_list_find_class(list_set->layout);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen if (storage_class == NULL &&
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* autodetection should take care of this */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen } else if (storage_class != NULL &&
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* root not required for this storage */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen } else if (list != NULL &&
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* root not required for this layout */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen } else {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *error_r = "Root mail directory not given";
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return NULL;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (storage_class != NULL) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return storage_class;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (storage_class != NULL)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return storage_class;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen (void)mail_user_get_home(ns->user, &home);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen *error_r = t_strdup_printf(
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen "Mail storage autodetection failed with home=%s", home);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen *error_r = t_strdup_printf(
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "Autodetection failed for %s (home=%s)",
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen ns->set->location, home);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen } else {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen *error_r = t_strdup_printf(
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:)",
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ns->set->location);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen }
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen return NULL;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen}
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainenstatic int
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainenmail_storage_verify_root(const char *root_dir, bool autocreate,
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen const char **error_r)
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct stat st;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen if (stat(root_dir, &st) == 0) {
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen /* exists */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return 1;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen } else if (errno == EACCES) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen } else if (!autocreate) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *error_r = t_strdup_printf(
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen "Root mail directory doesn't exist: %s", root_dir);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return -1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* doesn't exist */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen enum mail_storage_flags flags, const char **error_r)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char *root_dir, *error;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen bool autocreate;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen &root_dir)) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return 0;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!list->mail_set->mail_debug)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen return 0;
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen
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",
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen list->ns->prefix, error);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ret = mail_storage_verify_root(root_dir, autocreate, error_r);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (ret == 0) {
ab286a8b58306eb8d22fc18342b6c199fd428e1eTimo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen error_r);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return ret < 0 ? -1 : 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic bool
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenmail_storage_match_class(struct mail_storage *storage,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const struct mail_storage *storage_class,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct mailbox_list_settings *set)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
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 return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strcmp(storage->name, "shared") == 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* allow multiple independent shared namespaces */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return TRUE;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic struct mail_storage *
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenmail_storage_find(struct mail_user *user,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct mail_storage *storage_class,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const struct mailbox_list_settings *set)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_storage *storage = user->storages;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (; storage != NULL; storage = storage->next) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (mail_storage_match_class(storage, storage_class, set))
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return storage;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char *data, enum mail_storage_flags flags,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_storage **storage_r,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char **error_r)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mailbox_list *list;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct mailbox_list_settings list_set;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen enum mailbox_list_flags list_flags = 0;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *p;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen ns->mail_set->pop3_uidl_format != NULL) {
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. */
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen p = ns->mail_set->pop3_uidl_format;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen while ((p = strchr(p, '%')) != NULL) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (p[1] == '%')
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen p += 2;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen else if (var_get_key(++p) == 'm') {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen flags |= MAIL_STORAGE_FLAG_KEEP_HEADER_MD5;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen break;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen memset(&list_set, 0, sizeof(list_set));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen list_set.mailbox_dir_name = "";
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen list_set.maildir_name = "";
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (data == NULL) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* autodetect */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* internal shared namespace */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen list_set.root_dir = ns->user->set->base_dir;
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen } else {
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen if (driver == NULL)
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen mail_storage_set_autodetection(&data, &driver);
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen error_r) < 0)
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen return -1;
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen }
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen error_r);
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen if (storage_class == NULL)
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen return -1;
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen i_assert(list_set.layout != NULL);
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen if (ns->list == NULL) {
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,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen list_flags, &list, error_r) < 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen list_set.layout, *error_r);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
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)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return -1;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (storage != NULL) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* using an existing storage */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->refcount++;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_namespace_add_storage(ns, storage);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *storage_r = storage;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen return 0;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen }
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage = storage_class->v.alloc();
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->refcount = 1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->storage_class = storage_class;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->user = ns->user;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->set = ns->mail_set;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->flags = flags;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (storage->v.create != NULL &&
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen pool_unref(&storage->pool);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return -1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen T_BEGIN {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen hook_mail_storage_created(storage);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } T_END;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen DLLIST_PREPEND(&ns->user->storages, storage);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_namespace_add_storage(ns, storage);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *storage_r = storage;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return 0;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum mail_storage_flags flags, const char **error_r)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct mail_storage *storage;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return mail_storage_create_full(ns, driver, ns->set->location,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen flags, &storage, error_r);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct mail_storage *storage = *_storage;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen i_assert(storage->refcount > 0);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen /* set *_storage=NULL only after calling destroy() callback.
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for example mdbox wants to access ns->storage */
b4931fc08faa0079f32f29286f4c3abd0d8788bcTimo Sirainen if (--storage->refcount > 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *_storage = NULL;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (storage->mailboxes != NULL) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_panic("Trying to deinit storage without freeing mailbox %s",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->mailboxes->vname);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen }
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if (storage->obj_refcount != 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_panic("Trying to deinit storage before freeing its objects");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->v.destroy(storage);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_free(storage->error_string);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *_storage = NULL;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen pool_unref(&storage->pool);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_index_alloc_cache_destroy_unrefed();
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_obj_ref(struct mail_storage *storage)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(storage->refcount > 0);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (storage->obj_refcount++ == 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_user_ref(storage->user);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_obj_unref(struct mail_storage *storage)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(storage->refcount > 0);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(storage->obj_refcount > 0);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (--storage->obj_refcount == 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct mail_user *user = storage->user;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_user_unref(&user);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
871c7b8969e8627dc4c8b3e56fd126f948e6bce6Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_free_and_null(storage->error_string);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->error = MAIL_ERROR_NONE;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen}
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen enum mail_error error, const char *string)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen i_free(storage->error_string);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->error_string = i_strdup(string);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->error = error;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *str;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_free(storage->error_string);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->error_string = i_strdup(str);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen storage->error = MAIL_ERROR_TEMP;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *fmt, ...)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen va_list va;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen va_start(va, fmt);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen va_end(va);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
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. */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen mail_storage_set_internal_error(storage);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenvoid mail_storage_copy_error(struct mail_storage *dest,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen struct mail_storage *src)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *str;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum mail_error error;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (src == dest)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen str = mail_storage_get_last_error(src, &error);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen mail_storage_set_error(dest, error, str);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_list *list)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_error error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = mailbox_list_get_last_error(list, &error);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen mail_storage_set_error(storage, error, str);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_set_index_error(struct mailbox *box)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (mail_index_is_deleted(box->index))
8830fab191cab8440281eb641dfdd93974b2933bTimo Sirainen mailbox_set_deleted(box);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen else
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mail_storage_set_internal_error(box->storage);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_reset_error(box->index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst struct mail_storage_settings *
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainenmail_storage_get_settings(struct mail_storage *storage)
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return storage->set;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen{
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen return storage->user;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen}
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen struct mail_storage_callbacks *callbacks,
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen void *context)
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen{
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen storage->callbacks = *callbacks;
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen storage->callback_context = context;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen{
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen return storage->v.purge == NULL ? 0 :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage->v.purge(storage);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_error *error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
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 if (storage->error == MAIL_ERROR_NONE) {
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen if (error_r != NULL)
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen *error_r = MAIL_ERROR_TEMP;
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen return storage->error_string != NULL ? storage->error_string :
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen "BUG: Unknown internal error";
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen }
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (storage->error_string == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* This shouldn't happen.. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage->error_string =
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen i_strdup_printf("BUG: Unknown 0x%x error",
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen storage->error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (error_r != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = storage->error;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return storage->error_string;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainenconst char *mailbox_get_last_error(struct mailbox *box,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_error *error_r)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return mail_storage_get_last_error(box->storage, error_r);
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen}
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenenum mail_error mailbox_get_last_mail_error(struct mailbox *box)
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen{
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen enum mail_error error;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen mail_storage_get_last_error(box->storage, &error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return error;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen}
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return (storage->class_flags &
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen const char *error_string;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen enum mail_error error;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return FALSE;
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. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen }
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen mail_storage_set_error(storage, error, error_string);
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen return TRUE;
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen}
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainenconst struct mailbox_settings *
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainenmailbox_settings_find(struct mail_user *user, const char *vname)
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen{
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen struct mailbox_settings *const *box_set;
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen struct mail_namespace *ns;
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen ns = mail_namespace_find(user->namespaces, vname);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (!array_is_created(&ns->set->mailboxes))
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return NULL;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (ns->prefix_len > 0 &&
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 vname += ns->prefix_len;
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen else if (vname[ns->prefix_len-1] == '\0') {
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen /* namespace prefix itself */
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen vname = "";
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen }
3c24d47ad5ff02ea00684233bef314ef2eefda4aTimo Sirainen }
4c1827d5d718d6f610df3209a2eb95a6591698afTimo Sirainen array_foreach(&ns->set->mailboxes, box_set) {
5a4ab3d6e108a899c8b51bebd0094a37b738d5a1Timo Sirainen if (strcmp((*box_set)->name, vname) == 0)
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen return *box_set;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen }
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen return NULL;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen}
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mailbox_flags flags)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen struct mailbox_list *new_list = list;
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen struct mail_storage *storage;
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen struct mailbox *box;
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen enum mail_error open_error = 0;
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen const char *errstr = NULL;
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen i_assert(uni_utf8_str_is_valid(vname));
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (strncasecmp(vname, "INBOX", 5) == 0 &&
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen strncmp(vname, "INBOX", 5) != 0) {
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. */
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (vname[5] == '\0')
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen vname = "INBOX";
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 strncmp(list->ns->prefix, "INBOX", 5) != 0) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen mailbox_list_set_critical(list,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Invalid server configuration: "
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Namespace prefix=%s must be uppercase INBOX",
cd65dfcedc603fabbf644be793efb09096f6c1b5Timo Sirainen list->ns->prefix);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen open_error = MAIL_ERROR_TEMP;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen } else {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen vname = t_strconcat("INBOX", vname + 5, NULL);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen }
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen T_BEGIN {
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);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen errstr = t_strdup(errstr);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->set = mailbox_settings_find(storage->user, vname);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->open_error = open_error;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (open_error != 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_storage_set_error(storage, open_error, errstr);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen hook_mailbox_allocated(box);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen } T_END;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen DLLIST_PREPEND(&box->storage->mailboxes, box);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_storage_obj_ref(box->storage);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return box;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstruct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen const guid_128_t guid,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen enum mailbox_flags flags)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen struct mailbox *box = NULL;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen struct mailbox_metadata metadata;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen enum mail_error open_error = MAIL_ERROR_TEMP;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen const char *vname;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen vname = NULL;
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen } else if (vname != NULL) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen box = mailbox_alloc(list, vname, flags);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen &metadata) < 0) {
28dd1eeb9fdb93051bb5899c80cf300d69ba9f9eTimo Sirainen } else if (memcmp(metadata.guid, guid,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen sizeof(metadata.guid)) != 0) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen /* GUID mismatch, refresh cache and try again */
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mailbox_free(&box);
4c1827d5d718d6f610df3209a2eb95a6591698afTimo Sirainen mailbox_guid_cache_refresh(list);
4c1827d5d718d6f610df3209a2eb95a6591698afTimo Sirainen return mailbox_alloc_guid(list, guid, flags);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen } else {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* successfully opened the correct mailbox */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return box;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
05751847e5e493fecfd0634d35d21722aad44a0bTimo Sirainen i_error("mailbox_alloc_guid(%s): "
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen "Couldn't verify mailbox GUID: %s",
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen guid_128_to_string(guid),
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen mailbox_get_last_error(box, NULL));
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen vname = NULL;
91b5eae18db48ebb70eee5407a7ab52bf798ee12Timo Sirainen mailbox_free(&box);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen } else {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen guid_128_to_string(guid));
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen open_error = MAIL_ERROR_NOTFOUND;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (vname == NULL) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen vname = t_strdup_printf("(error in mailbox with GUID=%s)",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen guid_128_to_string(guid));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen box = mailbox_alloc(list, vname, flags);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->open_error = open_error;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return box;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic bool mailbox_is_autocreated(struct mailbox *box)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (box->inbox_user)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return TRUE;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return box->set != NULL &&
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic int mailbox_autocreate(struct mailbox *box)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen const char *errstr;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen enum mail_error error;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mailbox_create(box, NULL, FALSE) < 0) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen errstr = mailbox_get_last_error(box, &error);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (error != MAIL_ERROR_EXISTS) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mail_storage_set_critical(box->storage,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Failed to autocreate mailbox %s: %s",
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen box->vname, errstr);
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen return -1;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen }
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen } else if (box->set != NULL &&
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen strcmp(box->set->autocreate,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen MAILBOX_SET_AUTO_SUBSCRIBE) == 0) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (mailbox_set_subscribed(box, TRUE) < 0) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mail_storage_set_critical(box->storage,
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen "Failed to autosubscribe to mailbox %s: %s",
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->vname, mailbox_get_last_error(box, NULL));
28dd1eeb9fdb93051bb5899c80cf300d69ba9f9eTimo Sirainen return -1;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen }
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen }
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen return 0;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenstatic int mailbox_autocreate_and_reopen(struct mailbox *box)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen int ret;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (mailbox_autocreate(box) < 0)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return -1;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen mailbox_close(box);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = box->v.open(box);
b47c57ee07ccfe76cc23b23bc720e17fe9a46d5cTimo Sirainen if (ret < 0 && box->inbox_user &&
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen !box->storage->user->inbox_open_error_logged) {
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mail_storage_set_critical(box->storage,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen "Opening INBOX failed: %s",
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen mailbox_get_last_error(box, NULL));
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ret;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic bool
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenmailbox_name_verify_separators(const char *vname, char sep,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen const char **error_r)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen unsigned int i;
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen bool prev_sep = FALSE;
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen
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 for (i = 0; vname[i] != '\0'; i++) {
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen if (vname[i] == sep) {
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen if (prev_sep) {
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen *error_r = "Has adjacent hierarchy separators";
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen return FALSE;
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen }
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen prev_sep = TRUE;
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen } else {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen prev_sep = FALSE;
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (prev_sep && i > 0) {
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen *error_r = "Ends with hierarchy separator";
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return FALSE;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return TRUE;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen}
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainenstatic int mailbox_verify_name(struct mailbox *box)
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen{
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen struct mail_namespace *ns = box->list->ns;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen const char *error, *vname = box->vname;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen char list_sep, ns_sep;
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (box->inbox_user) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* this is INBOX - don't bother with further checks */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return 0;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen list_sep = mailbox_list_get_hierarchy_sep(box->list);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen ns_sep = mail_namespace_get_sep(ns);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (ns->prefix_len > 0) {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* vname is either "namespace/box" or "namespace" */
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen i_assert(strncmp(vname, ns->prefix, ns->prefix_len-1) == 0);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen vname += ns->prefix_len - 1;
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen if (vname[0] != '\0') {
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen vname++;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (vname[0] == '\0') {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* "namespace/" isn't a valid mailbox name. */
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen mail_storage_set_error(box->storage,
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen MAIL_ERROR_PARAMS,
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen "Invalid mailbox name");
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return -1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen }
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (ns_sep != list_sep && box->list->set.escape_char == '\0' &&
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen strchr(vname, list_sep) != NULL) {
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 return -1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (vname[0] == ns_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 return -1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
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));
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return -1;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return 0;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen}
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainenstatic int mailbox_verify_existing_name(struct mailbox *box)
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen{
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen const char *path;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (box->opened)
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen return 0;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen if (mailbox_verify_name(box) < 0)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return -1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
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 ||
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen !mailbox_is_autocreated(box))
fea541eec46707f9b01bd3cbc981d73c1e808a54Timo Sirainen return -1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen /* if this is an autocreated mailbox, create it now */
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen if (mailbox_autocreate(box) < 0)
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen return -1;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen mailbox_close(box);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen &path) < 0)
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen return -1;
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return 0;
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen}
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainenstatic bool mailbox_name_has_control_chars(const char *name)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen{
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen const char *p;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen for (p = name; *p != '\0'; p++) {
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen if ((unsigned char)*p < ' ')
0b38c17fb10e2ad1d081369d34b93d0448d971a2Timo Sirainen return TRUE;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return FALSE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainenint mailbox_verify_create_name(struct mailbox *box)
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen{
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen char sep = mail_namespace_get_sep(box->list->ns);
0c583855501178ec9c62f2a94946192df2a01be4Timo Sirainen
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen /* mailbox_alloc() already checks that vname is valid UTF8,
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen so we don't need to verify that.
5e2cf2e665bb0c3c68fa34bc6d0e9ce93426fdd0Timo Sirainen
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. */
a80241dc44ee43bc809ed5ec6dedb74711966dafTimo Sirainen if (mailbox_verify_name(box) < 0)
09714f2f8d4c8cc7d89930f7eb836816d8dc9eb8Timo Sirainen return -1;
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");
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return -1;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen }
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");
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen return -1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen}
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainenstatic bool have_listable_namespace_prefix(struct mail_namespace *ns,
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainen const char *name)
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainen{
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainen unsigned int name_len = strlen(name);
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainen
673ab5815277e6f9ac09227c866c90ab57438912Timo Sirainen for (; ns != NULL; ns = ns->next) {
2ef8fac74c9d0bfc330bf53bb06df7e9d5f08e7dTimo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
2ef8fac74c9d0bfc330bf53bb06df7e9d5f08e7dTimo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
2ef8fac74c9d0bfc330bf53bb06df7e9d5f08e7dTimo Sirainen continue;
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (ns->prefix_len <= name_len)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen continue;
b9ce555e8624a5593b3bfd81b572b7d2e1e1fca5Timo Sirainen
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))
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen return TRUE;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen }
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen return FALSE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainenint mailbox_exists(struct mailbox *box, bool auto_boxes,
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen enum mailbox_existence *existence_r)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen switch (box->open_error) {
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen case 0:
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen break;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen case MAIL_ERROR_NOTFOUND:
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NONE;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return 0;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen default:
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen /* unsure if this exists or not */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return -1;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mailbox_verify_name(box) < 0) {
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 *existence_r = MAILBOX_EXISTENCE_NONE;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return 0;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen }
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (auto_boxes && box->set != NULL && mailbox_is_autocreated(box)) {
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen *existence_r = MAILBOX_EXISTENCE_SELECT;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return 0;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen }
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (box->v.exists(box, auto_boxes, existence_r) < 0)
19593623a2278039be23fc93e3404c012920b664Timo Sirainen return -1;
19593623a2278039be23fc93e3404c012920b664Timo Sirainen
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen if (!box->inbox_user && *existence_r == MAILBOX_EXISTENCE_NOSELECT &&
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen have_listable_namespace_prefix(box->storage->user->namespaces,
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen box->vname)) {
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen /* listable namespace prefix always exists. */
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen *existence_r = MAILBOX_EXISTENCE_NOSELECT;
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen return 0;
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen }
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen
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 Sirainen return 0;
0ce3bbb0f03fb0ee99258b41b5a1d689c1158a75Timo Sirainen}
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainenstatic int ATTR_NULL(2)
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainenmailbox_open_full(struct mailbox *box, struct istream *input)
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen{
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen int ret;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen if (box->opened)
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen return 0;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen switch (box->open_error) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case 0:
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen break;
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen case MAIL_ERROR_NOTFOUND:
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return -1;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen default:
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_storage_set_internal_error(box->storage);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen box->storage->error = box->open_error;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return -1;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen if (mailbox_verify_existing_name(box) < 0)
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen return -1;
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen if (input != NULL) {
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen if ((box->storage->class_flags &
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen mail_storage_set_critical(box->storage,
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen "Storage doesn't support streamed mailboxes");
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen box->input = input;
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen box->flags |= MAILBOX_FLAG_READONLY;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_stream_ref(box->input);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen
e2ea49bd487d76b425e270321e9cf1e546642de0Timo Sirainen T_BEGIN {
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen ret = box->v.open(box);
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen } T_END;
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen ret = mailbox_autocreate_and_reopen(box);
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen } T_END;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen if (ret < 0) {
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen if (box->input != NULL)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen i_stream_unref(&box->input);
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen return -1;
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen }
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen return 0;
c48140ca508ebc9642737e7fd6c8d9e52f95df32Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic bool mailbox_try_undelete(struct mailbox *box)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen time_t mtime;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
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. */
19593623a2278039be23fc93e3404c012920b664Timo Sirainen return FALSE;
19593623a2278039be23fc93e3404c012920b664Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_get_modification_time(box->index, &mtime) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3e4bbbceed7882b8dab558aa90913a491eb15cc6Timo Sirainen if (mailbox_mark_index_deleted(box, FALSE) < 0)
3e4bbbceed7882b8dab558aa90913a491eb15cc6Timo Sirainen return FALSE;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen box->mailbox_deleted = FALSE;
45edf6cad665a5c270322516c587708a0c630b80Timo Sirainen return TRUE;
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen}
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainenint mailbox_open(struct mailbox *box)
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen{
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen if (mailbox_open_full(box, NULL) < 0) {
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen if (!box->mailbox_deleted)
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen return -1;
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen
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. */
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen if(!mailbox_try_undelete(box))
0e17a51126ed6f376f9207217797103b610ff8ebTimo Sirainen return -1;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (mailbox_open_full(box, NULL) < 0)
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen return -1;
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mailbox_alloc_index_pvt(struct mailbox *box)
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen{
ed3ce1282f6bc35d20e82c2c23a2990c8dfe876fTimo Sirainen const char *index_dir;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (box->index_pvt != NULL)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen return 1;
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen &index_dir);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (ret <= 0)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen return ret; /* error / no private indexes */
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE) < 0)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen return -1;
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen box->index_pvt = mail_index_alloc_cache_get(NULL, index_dir,
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen t_strconcat(box->index_prefix, ".pvt", NULL));
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen mail_index_set_fsync_mode(box->index_pvt,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->storage->set->parsed_fsync_mode, 0);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_index_set_lock_method(box->index_pvt,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->storage->set->parsed_lock_method,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_storage_get_lock_timeout(box->storage, UINT_MAX));
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return 1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenint mailbox_open_index_pvt(struct mailbox *box)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen int ret;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (box->view_pvt != NULL)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return 1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mailbox_get_private_flags_mask(box) == 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return 0;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((ret = mailbox_alloc_index_pvt(box)) <= 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return ret;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mail_index_open(box->index_pvt, MAIL_INDEX_OPEN_FLAG_CREATE) < 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return -1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->view_pvt = mail_index_view_open(box->index_pvt);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return 1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainenint mailbox_open_stream(struct mailbox *box, struct istream *input)
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen{
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen return mailbox_open_full(box, input);
c485524d09c650ff6e6c552129d4257ac6145a8bTimo Sirainen}
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainenint mailbox_enable(struct mailbox *box, enum mailbox_feature features)
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen{
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if (mailbox_verify_name(box) < 0)
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return box->v.enable(box, features);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenenum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen{
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen return box->enabled_features;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenvoid mail_storage_free_binary_cache(struct mail_storage *storage)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (storage->binary_cache.box == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen timeout_remove(&storage->binary_cache.to);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen i_stream_destroy(&storage->binary_cache.input);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen memset(&storage->binary_cache, 0, sizeof(storage->binary_cache));
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenvoid mailbox_close(struct mailbox *box)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen{
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (!box->opened)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen return;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (box->transaction_count != 0) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen i_panic("Trying to close mailbox %s with open transactions",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->name);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->v.close(box);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen if (box->storage->binary_cache.box == box)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mail_storage_free_binary_cache(box->storage);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen box->opened = FALSE;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen box->mailbox_deleted = FALSE;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen array_clear(&box->search_results);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenvoid mailbox_free(struct mailbox **_box)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct mailbox *box = *_box;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen *_box = NULL;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mailbox_close(box);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen box->v.free(box);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen DLLIST_REMOVE(&box->storage->mailboxes, box);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mail_storage_obj_unref(box->storage);
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen if (box->metadata_pool != NULL)
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen pool_unref(&box->metadata_pool);
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen pool_unref(&box->pool);
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen}
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainenbool mailbox_equals(const struct mailbox *box1,
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen const struct mail_namespace *ns2, const char *vname2)
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen{
c234379ba20d2513b1acca97f13c64e2a9e5d622Timo Sirainen struct mail_namespace *ns1 = mailbox_get_namespace(box1);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char *name1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (ns1 != ns2)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen name1 = mailbox_get_vname(box1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (strcmp(name1, vname2) == 0)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return strcasecmp(name1, "INBOX") == 0 &&
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen strcasecmp(vname2, "INBOX") == 0;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen}
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenbool mailbox_is_any_inbox(struct mailbox *box)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return box->inbox_any;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_create(struct mailbox *box, const struct mailbox_update *update,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen bool directory)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int ret;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mailbox_verify_create_name(box) < 0)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return -1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen box->creating = TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = box->v.create_box(box, update, directory);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen box->creating = FALSE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return ret;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenint mailbox_update(struct mailbox *box, const struct mailbox_update *update)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_assert(update->min_next_uid == 0 ||
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen update->min_first_recent_uid == 0 ||
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen update->min_first_recent_uid <= update->min_next_uid);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (mailbox_verify_existing_name(box) < 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return -1;
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen return box->v.update_box(box, update);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenint mailbox_mark_index_deleted(struct mailbox *box, bool del)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen struct mail_index_transaction *trans;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen enum mail_index_transaction_flags trans_flags = 0;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen enum mailbox_flags old_flag;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen int ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (box->marked_deleted && del) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* we already marked it deleted. this allows plugins to
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "lock" the deletion earlier. */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->flags |= MAILBOX_FLAG_OPEN_DELETED;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ret = mailbox_open(box);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->flags = (box->flags & ~MAILBOX_FLAG_OPEN_DELETED) | old_flag;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (ret < 0)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return -1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen trans = mail_index_transaction_begin(box->view, trans_flags);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (del)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mail_index_set_deleted(trans);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen else
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen mail_index_set_undeleted(trans);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (mail_index_transaction_commit(&trans) < 0) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mailbox_set_index_error(box);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return -1;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
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)
c9f1a617593eb569fb02f45041bad3c13e534496Timo Sirainen return -1;
c9f1a617593eb569fb02f45041bad3c13e534496Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->marked_deleted = del;
c9f1a617593eb569fb02f45041bad3c13e534496Timo Sirainen return 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenint mailbox_delete(struct mailbox *box)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen int ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (*box->name == '\0') {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen "Storage root can't be deleted");
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return -1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->deleting = TRUE;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (mailbox_open(box) < 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return -1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* \noselect mailbox */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen ret = box->v.delete_box(box);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (ret < 0 && box->marked_deleted) {
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)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen return -1;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen }
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen box->deleting = FALSE;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen mailbox_close(box);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
ea9e10039e23a4926984a56860b5cc88f7b1f75eTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenint mailbox_delete_empty(struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen int ret;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* FIXME: should be a parameter to delete(), but since it changes API
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen don't do it for now */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->deleting_must_be_empty = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mailbox_delete(box);
2bc9f8181d576165cd30ce0522754420097037cdTimo Sirainen box->deleting_must_be_empty = FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_storages_rename_compatible(struct mail_storage *storage1,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage *storage2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen if (storage1 == storage2)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcmp(storage1->name, storage2->name) != 0) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen *error_r = t_strdup_printf("storage %s != %s",
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen storage1->name, storage2->name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen }
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 Sirainen storage1->name);
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool nullequals(const void *p1, const void *p2)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return (p1 == NULL && p2 == NULL) || (p1 != NULL && p2 != NULL);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen}
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_lists_rename_compatible(struct mailbox_list *list1,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_list *list2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
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";
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen return FALSE;
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen }
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";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
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";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
9fc077d3886b1584019bcc9b92c717cfffce5c67Timo Sirainen
9fc077d3886b1584019bcc9b92c717cfffce5c67Timo Sirainenint mailbox_rename(struct mailbox *src, struct mailbox *dest)
9fc077d3886b1584019bcc9b92c717cfffce5c67Timo Sirainen{
9fc077d3886b1584019bcc9b92c717cfffce5c67Timo Sirainen const char *error = NULL;
9fc077d3886b1584019bcc9b92c717cfffce5c67Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Check only name validity, \Noselect don't necessarily exist. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mailbox_verify_name(src) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*src->name == '\0') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Can't rename mailbox root");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen if (mailbox_verify_create_name(dest) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_copy_error(dest->storage, src->storage);
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_storages_rename_compatible(src->storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dest->storage, &error) ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !mailbox_lists_rename_compatible(src->list,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dest->list, &error)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (src->storage->set->mail_debug) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_debug("Can't rename '%s' to '%s': %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen src->vname, dest->vname, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Can't rename mailboxes across specified storages.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (src->list != dest->list &&
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 return -1;
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen }
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.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
86bc22621dcce6d9f1ca7216c9cc958381a61277Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return src->v.rename_box(src, dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainenint mailbox_set_subscribed(struct mailbox *box, bool set)
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen{
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen if (mailbox_verify_name(box) < 0)
264bc938e956288ec7a2a43417c01c3a3ce840fdTimo Sirainen return -1;
264bc938e956288ec7a2a43417c01c3a3ce840fdTimo Sirainen return box->v.set_subscribed(box, set);
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen}
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainenbool mailbox_is_subscribed(struct mailbox *box)
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen{
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen struct mailbox_node *node;
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen i_assert(box->list->subscriptions != NULL);
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen node = mailbox_tree_lookup(box->list->subscriptions, box->vname);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen return node != NULL && (node->flags & MAILBOX_SUBSCRIBED) != 0;
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen}
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainenstruct mail_storage *mailbox_get_storage(const struct mailbox *box)
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen{
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen return box->storage;
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen}
e687badfdd7f4001e9a89a80a2c4a79ec4bafc8dTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenstruct mail_namespace *
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenmailbox_get_namespace(const struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return box->list->ns;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenconst struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return box->storage->set;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenconst char *mailbox_get_name(const struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return box->name;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenconst char *mailbox_get_vname(const struct mailbox *box)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return box->vname;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenbool mailbox_is_readonly(struct mailbox *box)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen{
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen i_assert(box->opened);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return box->v.is_readonly(box);
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool mailbox_backends_equal(const struct mailbox *box1,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mailbox *box2)
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen{
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen struct mail_namespace *ns1 = box1->list->ns, *ns2 = box2->list->ns;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcmp(box1->name, box2->name) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen while (ns1->alias_for != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ns1 = ns1->alias_for;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen while (ns2->alias_for != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ns2 = ns2->alias_for;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ns1 == ns2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_get_status_set_defaults(struct mailbox *box,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_status *status_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(status_r, 0, sizeof(*status_r));
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS) != 0)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen status_r->have_guids = TRUE;
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS) != 0)
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen status_r->have_save_guids = TRUE;
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen}
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainenint mailbox_get_status(struct mailbox *box,
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen enum mailbox_status_items items,
67b9db4e0bd93ffe24cc95f609193f6f642f6448Timo Sirainen struct mailbox_status *status_r)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen{
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen mailbox_get_status_set_defaults(box, status_r);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (mailbox_verify_existing_name(box) < 0)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen return -1;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (box->v.get_status(box, items, status_r) < 0)
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen return -1;
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen i_assert(status_r->have_guids || !status_r->have_save_guids);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen return 0;
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen}
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenvoid mailbox_get_open_status(struct mailbox *box,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen enum mailbox_status_items items,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen struct mailbox_status *status_r)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen{
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_assert(box->opened);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_assert((items & MAILBOX_STATUS_FAILING_ITEMS) == 0);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen mailbox_get_status_set_defaults(box, status_r);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (box->v.get_status(box, items, status_r) < 0)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_unreached();
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen}
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainenint mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen struct mailbox_metadata *metadata_r)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen{
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen memset(metadata_r, 0, sizeof(*metadata_r));
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (mailbox_verify_existing_name(box) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen if (box->metadata_pool != NULL)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen p_clear(box->metadata_pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (box->v.get_metadata(box, items, metadata_r) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen i_assert((items & MAILBOX_METADATA_GUID) == 0 ||
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen !guid_128_is_empty(metadata_r->guid));
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen return 0;
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen}
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen
99e8698f598d2b83da7c581584a538c0713fd11dTimo Sirainenenum mail_flags mailbox_get_private_flags_mask(struct mailbox *box)
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen{
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen if (box->v.get_private_flags_mask != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return box->v.get_private_flags_mask(box);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen else if (box->list->set.index_pvt_dir != NULL)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return MAIL_SEEN; /* FIXME */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen else
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen return 0;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_set(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_attribute_type type, const char *key,
ec1e30ecc38f0deddaf655413cf02d5972ddbc70Timo Sirainen const struct mail_attribute_value *value)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen return t->box->v.attribute_set(t, type, key, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_unset(struct mailbox_transaction_context *t,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen enum mail_attribute_type type, const char *key)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen struct mail_attribute_value value;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen memset(&value, 0, sizeof(value));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return t->box->v.attribute_set(t, type, key, &value);
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen}
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenint mailbox_attribute_value_to_string(struct mail_storage *storage,
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen const struct mail_attribute_value *value,
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen const char **str_r)
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen{
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen string_t *str;
6fcaeede31ef2292b3ff59c461eb6ef4ae989dfdTimo Sirainen const unsigned char *data;
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen size_t size;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (value->value_stream == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *str_r = value->value;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_str_new(128);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_stream_seek(value->value_stream, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (i_stream_read_data(value->value_stream, &data, &size, 0) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (memchr(data, '\0', size) != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Attribute string value has NULs");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_n(str, data, size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_stream_skip(value->value_stream, size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (value->value_stream->stream_errno != 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen mail_storage_set_critical(storage, "read(%s) failed: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_stream_get_name(value->value_stream));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(value->value_stream->eof);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *str_r = str_c(str);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_get(struct mailbox_transaction_context *t,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen enum mail_attribute_type type, const char *key,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_attribute_value *value_r)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen int ret;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen memset(value_r, 0, sizeof(*value_r));
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if ((ret = t->box->v.attribute_get(t, type, key, value_r)) <= 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return ret;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_assert(value_r->value != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_attribute_get_stream(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_attribute_type type, const char *key,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_attribute_value *value_r)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(value_r, 0, sizeof(*value_r));
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)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_assert(value_r->value != NULL || value_r->value_stream != NULL);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return 1;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenstruct mailbox_attribute_iter *
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenmailbox_attribute_iter_init(struct mailbox *box, enum mail_attribute_type type,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen const char *prefix)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return box->v.attribute_iter_init(box, type, prefix);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenconst char *mailbox_attribute_iter_next(struct mailbox_attribute_iter *iter)
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return iter->box->v.attribute_iter_next(iter);
325d4ad220bd13f6d176391d962a0e33c856a7f6Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenint mailbox_attribute_iter_deinit(struct mailbox_attribute_iter **_iter)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_attribute_iter *iter = *_iter;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen *_iter = NULL;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return iter->box->v.attribute_iter_deinit(iter);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenstruct mailbox_sync_context *
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenmailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_sync_context *ctx;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (box->transaction_count != 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_panic("Trying to sync mailbox %s with open transactions",
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->name);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen T_BEGIN {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ctx = box->v.sync_init(box, flags);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen } T_END;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return ctx;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenbool mailbox_sync_next(struct mailbox_sync_context *ctx,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_sync_rec *sync_rec_r)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen return ctx->box->v.sync_next(ctx, sync_rec_r);
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen}
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainen
68917b81c83e8a4d18a81cda188ffa5cb643c46cTimo Sirainenint mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_sync_status *status_r)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_sync_context *ctx = *_ctx;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox *box = ctx->box;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen const char *errormsg;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen enum mail_error error;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen int ret;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen *_ctx = NULL;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen memset(status_r, 0, sizeof(*status_r));
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ret = box->v.sync_deinit(ctx, status_r);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (ret < 0 && box->inbox_user &&
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen !box->storage->user->inbox_open_error_logged) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen errormsg = mailbox_get_last_error(box, &error);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (error == MAIL_ERROR_NOTPOSSIBLE) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_error("Syncing INBOX failed: %s", errormsg);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (ret == 0)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->synced = TRUE;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenint mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_sync_context *ctx;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_sync_status status;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (array_count(&box->search_results) == 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* we don't care about mailbox's current state, so we might
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen as well fix inconsistency state */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen ctx = mailbox_sync_init(box, flags);
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen return mailbox_sync_deinit(&ctx, &status);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen#undef mailbox_notify_changes
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenvoid mailbox_notify_changes(struct mailbox *box,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen mailbox_notify_callback_t *callback, void *context)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen i_assert(box->opened);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->notify_callback = callback;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->notify_context = context;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen box->v.notify_changes(box);
6143fece58262865ce89b5012b73ef08f2ad6abcTimo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenvoid mailbox_notify_changes_stop(struct mailbox *box)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_assert(box->opened);
cf48e5c9975b854a23aeca883b7e689eb24430c4Timo Sirainen
cf48e5c9975b854a23aeca883b7e689eb24430c4Timo Sirainen box->notify_callback = NULL;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->notify_context = NULL;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen box->v.notify_changes(box);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenstruct mail_search_context *
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenmailbox_search_init(struct mailbox_transaction_context *t,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mail_search_args *args,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen const enum mail_sort_type *sort_program,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen enum mail_fetch_field wanted_fields,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen mail_search_args_ref(args);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (!args->simplified)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen mail_search_args_simplify(args);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return t->box->v.search_init(t, args, sort_program,
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen wanted_fields, wanted_headers);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenint mailbox_search_deinit(struct mail_search_context **_ctx)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen struct mail_search_context *ctx = *_ctx;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen struct mail_search_args *args = ctx->args;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen int ret;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen *_ctx = NULL;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen mailbox_search_results_initial_done(ctx);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen ret = ctx->transaction->box->v.search_deinit(ctx);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen mail_search_args_unref(&args);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return ret;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen}
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
321241fc56909ccb69d77c6a11686e0c25b4c4d4Timo Sirainenbool mailbox_search_next(struct mail_search_context *ctx, struct mail **mail_r)
321241fc56909ccb69d77c6a11686e0c25b4c4d4Timo Sirainen{
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen bool tryagain;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen while (!mailbox_search_next_nonblock(ctx, mail_r, &tryagain)) {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (!tryagain)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return FALSE;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen }
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return TRUE;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen}
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenbool mailbox_search_next_nonblock(struct mail_search_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail **mail_r, bool *tryagain_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox *box = ctx->transaction->box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *mail_r = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!box->v.search_next_nonblock(ctx, mail_r, tryagain_r))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mailbox_search_results_add(ctx, (*mail_r)->uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenbool mailbox_search_seen_lost_data(struct mail_search_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ctx->seen_lost_data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mailbox_search_result_build(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_search_args *args,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mailbox_search_result_flags flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_search_result **result_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen struct mail_search_context *ctx;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen struct mail *mail;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen int ret;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen ctx = mailbox_search_init(t, args, NULL, 0, NULL);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen *result_r = mailbox_search_result_save(ctx, flags);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen while (mailbox_search_next(ctx, &mail)) ;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen ret = mailbox_search_deinit(&ctx);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen if (ret < 0)
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen mailbox_search_result_free(result_r);
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen return ret;
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen}
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainenstruct mailbox_transaction_context *
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainenmailbox_transaction_begin(struct mailbox *box,
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen enum mailbox_transaction_flags flags)
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen{
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen struct mailbox_transaction_context *trans;
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen
11fa9bc1e84f7cc88d953c0a0ae4e2cd07881957Timo Sirainen i_assert(box->opened);
11fa9bc1e84f7cc88d953c0a0ae4e2cd07881957Timo Sirainen
11fa9bc1e84f7cc88d953c0a0ae4e2cd07881957Timo Sirainen box->transaction_count++;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen trans = box->v.transaction_begin(box, flags);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen trans->flags = flags;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen return trans;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen}
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainenint mailbox_transaction_commit(struct mailbox_transaction_context **t)
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen{
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen struct mail_transaction_commit_changes changes;
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen int ret;
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen
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);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (changes.pool != NULL)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen pool_unref(&changes.pool);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen return ret;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen}
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainenint mailbox_transaction_commit_get_changes(
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen struct mailbox_transaction_context **_t,
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen struct mail_transaction_commit_changes *changes_r)
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen{
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen struct mailbox_transaction_context *t = *_t;
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen struct mailbox *box = t->box;
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen unsigned int save_count = t->save_count;
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen int ret;
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen changes_r->pool = NULL;
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen
11fa9bc1e84f7cc88d953c0a0ae4e2cd07881957Timo Sirainen *_t = NULL;
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen T_BEGIN {
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen ret = box->v.transaction_commit(t, changes_r);
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen } T_END;
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 i_assert(ret < 0 ||
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen seq_range_count(&changes_r->saved_uids) == save_count ||
5ec0ca7ff13595daf0d096c17100afb352e6294aTimo Sirainen array_count(&changes_r->saved_uids) == 0);
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 Sirainen finished */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->transaction_count--;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0 && changes_r->pool != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(&changes_r->pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_transaction_context *t = *_t;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox *box = t->box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *_t = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->v.transaction_rollback(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box->transaction_count--;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenunsigned int mailbox_transaction_get_count(const struct mailbox *box)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return box->transaction_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint64_t max_modseq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) *seqs)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_transaction_set_max_modseq(t->itrans, max_modseq, seqs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mailbox *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return t->box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_save_context *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmailbox_save_alloc(struct mailbox_transaction_context *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_save_context *ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx = t->box->v.save_alloc(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!ctx->unfinished);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->unfinished = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data.received_date = (time_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data.save_date = (time_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mailbox_save_set_flags(struct mail_save_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_flags flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_keywords *keywords)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox *box = ctx->transaction->box;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
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 Sirainen ctx->data.keywords = keywords;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if (keywords != NULL)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mailbox_keywords_ref(keywords);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen}
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainenvoid mailbox_save_copy_flags(struct mail_save_context *ctx, struct mail *mail)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen{
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen const char *const *keywords_list;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen struct mail_keywords *keywords;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen keywords_list = mail_get_keywords(mail);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen keywords = str_array_length(keywords_list) == 0 ? NULL :
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mailbox_keywords_create_valid(ctx->transaction->box,
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen keywords_list);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mailbox_save_set_flags(ctx, mail_get_flags(mail), keywords);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if (keywords != NULL)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mailbox_keywords_unref(&keywords);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen}
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainenvoid mailbox_save_set_min_modseq(struct mail_save_context *ctx,
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen uint64_t min_modseq)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen{
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen ctx->data.min_modseq = min_modseq;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen}
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
void mailbox_save_set_received_date(struct mail_save_context *ctx,
time_t received_date, int timezone_offset)
{
ctx->data.received_date = received_date;
ctx->data.received_tz_offset = timezone_offset;
}
void mailbox_save_set_save_date(struct mail_save_context *ctx,
time_t save_date)
{
ctx->data.save_date = save_date;
}
void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
const char *envelope)
{
i_free(ctx->data.from_envelope);
ctx->data.from_envelope = i_strdup(envelope);
}
void mailbox_save_set_uid(struct mail_save_context *ctx, uint32_t uid)
{
ctx->data.uid = uid;
}
void mailbox_save_set_guid(struct mail_save_context *ctx, const char *guid)
{
i_assert(guid == NULL || *guid != '\0');
i_free(ctx->data.guid);
ctx->data.guid = i_strdup(guid);
}
void mailbox_save_set_pop3_uidl(struct mail_save_context *ctx, const char *uidl)
{
i_assert(*uidl != '\0');
i_assert(strchr(uidl, '\n') == NULL);
i_free(ctx->data.pop3_uidl);
ctx->data.pop3_uidl = i_strdup(uidl);
}
void mailbox_save_set_pop3_order(struct mail_save_context *ctx,
unsigned int order)
{
i_assert(order > 0);
ctx->data.pop3_order = order;
}
void mailbox_save_set_dest_mail(struct mail_save_context *ctx,
struct mail *mail)
{
ctx->dest_mail = mail;
}
int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
{
struct mailbox *box = (*ctx)->transaction->box;
int ret;
if (mail_index_is_deleted(box->index)) {
mailbox_set_deleted(box);
mailbox_save_cancel(ctx);
return -1;
}
if (!(*ctx)->copying_via_save)
(*ctx)->saving = TRUE;
if (box->v.save_begin == NULL) {
mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
"Saving messages not supported");
ret = -1;
} else {
ret = box->v.save_begin(*ctx, input);
}
if (ret < 0) {
mailbox_save_cancel(ctx);
return -1;
}
return 0;
}
int mailbox_save_continue(struct mail_save_context *ctx)
{
return ctx->transaction->box->v.save_continue(ctx);
}
static void
mailbox_save_add_pvt_flags(struct mailbox_transaction_context *t,
enum mail_flags pvt_flags)
{
struct mail_save_private_changes *save;
if (!array_is_created(&t->pvt_saves))
i_array_init(&t->pvt_saves, 8);
save = array_append_space(&t->pvt_saves);
save->mailnum = t->save_count;
save->flags = pvt_flags;
}
int mailbox_save_finish(struct mail_save_context **_ctx)
{
struct mail_save_context *ctx = *_ctx;
struct mailbox_transaction_context *t = ctx->transaction;
struct mail_keywords *keywords = ctx->data.keywords;
enum mail_flags pvt_flags = ctx->data.pvt_flags;
bool copying_via_save = ctx->copying_via_save;
int ret;
/* Do one final continue. The caller may not have done it if the
input stream's offset already matched the number of bytes that
were wanted to be saved. But due to nested istreams some of the
underlying ones may not have seen the EOF yet, and haven't flushed
out the pending data. */
if (mailbox_save_continue(ctx) < 0) {
mailbox_save_cancel(_ctx);
return -1;
}
*_ctx = NULL;
ret = t->box->v.save_finish(ctx);
if (ret == 0 && !copying_via_save) {
if (pvt_flags != 0)
mailbox_save_add_pvt_flags(t, pvt_flags);
t->save_count++;
}
if (keywords != NULL)
mailbox_keywords_unref(&keywords);
i_assert(!ctx->unfinished);
ctx->saving = FALSE;
return ret;
}
void mailbox_save_cancel(struct mail_save_context **_ctx)
{
struct mail_save_context *ctx = *_ctx;
struct mail_keywords *keywords = ctx->data.keywords;
struct mail_private *mail;
*_ctx = NULL;
ctx->transaction->box->v.save_cancel(ctx);
if (keywords != NULL)
mailbox_keywords_unref(&keywords);
if (ctx->dest_mail != NULL) {
/* the dest_mail is no longer valid. if we're still saving
more mails, the mail sequence may get reused. make sure
the mail gets reset in between */
mail = (struct mail_private *)ctx->dest_mail;
mail->v.close(&mail->mail);
}
i_assert(!ctx->unfinished);
ctx->saving = FALSE;
}
struct mailbox_transaction_context *
mailbox_save_get_transaction(struct mail_save_context *ctx)
{
return ctx->transaction;
}
int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail)
{
struct mail_save_context *ctx = *_ctx;
struct mailbox_transaction_context *t = ctx->transaction;
struct mail_keywords *keywords = ctx->data.keywords;
enum mail_flags pvt_flags = ctx->data.pvt_flags;
struct mail *real_mail;
int ret;
*_ctx = NULL;
if (mail_index_is_deleted(t->box->index)) {
mailbox_set_deleted(t->box);
mailbox_save_cancel(&ctx);
return -1;
}
/* bypass virtual storage, so hard linking can be used whenever
possible */
real_mail = mail_get_real_mail(mail);
ret = t->box->v.copy(ctx, real_mail);
if (ret == 0) {
if (pvt_flags != 0)
mailbox_save_add_pvt_flags(t, pvt_flags);
t->save_count++;
}
if (keywords != NULL)
mailbox_keywords_unref(&keywords);
i_assert(!ctx->unfinished);
ctx->copying_via_save = FALSE;
ctx->saving = FALSE;
return ret;
}
int mailbox_move(struct mail_save_context **_ctx, struct mail *mail)
{
struct mail_save_context *ctx = *_ctx;
ctx->moving = TRUE;
if (mailbox_copy(_ctx, mail) < 0)
return -1;
mail_expunge(mail);
ctx->moving = FALSE;
return 0;
}
int mailbox_save_using_mail(struct mail_save_context **ctx, struct mail *mail)
{
(*ctx)->saving = TRUE;
return mailbox_copy(ctx, mail);
}
bool mailbox_is_inconsistent(struct mailbox *box)
{
return box->mailbox_deleted || box->v.is_inconsistent(box);
}
void mailbox_set_deleted(struct mailbox *box)
{
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
"Mailbox was deleted under us");
box->mailbox_deleted = TRUE;
}
int mailbox_get_path_to(struct mailbox *box, enum mailbox_list_path_type type,
const char **path_r)
{
int ret;
if (type == MAILBOX_LIST_PATH_TYPE_MAILBOX && box->_path != NULL) {
if (box->_path[0] == '\0') {
*path_r = NULL;
return 0;
}
*path_r = box->_path;
return 1;
}
ret = mailbox_list_get_path(box->list, box->name, type, path_r);
if (ret < 0) {
mail_storage_copy_list_error(box->storage, box->list);
return -1;
}
if (type == MAILBOX_LIST_PATH_TYPE_MAILBOX && box->_path == NULL)
box->_path = ret == 0 ? "" : p_strdup(box->pool, *path_r);
return ret;
}
const char *mailbox_get_path(struct mailbox *box)
{
i_assert(box->_path != NULL);
i_assert(box->_path[0] != '\0');
return box->_path;
}
static void mailbox_get_permissions_if_not_set(struct mailbox *box)
{
if (box->_perm.file_create_mode != 0)
return;
if (box->input != NULL) {
box->_perm.file_uid = geteuid();
box->_perm.file_create_mode = 0600;
box->_perm.dir_create_mode = 0700;
box->_perm.file_create_gid = (gid_t)-1;
box->_perm.file_create_gid_origin = "defaults";
return;
}
mailbox_list_get_permissions(box->list, box->name, &box->_perm);
box->_perm.file_create_gid_origin =
p_strdup(box->pool, box->_perm.file_create_gid_origin);
}
const struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box)
{
mailbox_get_permissions_if_not_set(box);
if (!box->_perm.mail_index_permissions_set && box->index != NULL) {
box->_perm.mail_index_permissions_set = TRUE;
mail_index_set_permissions(box->index,
box->_perm.file_create_mode,
box->_perm.file_create_gid,
box->_perm.file_create_gid_origin);
}
return &box->_perm;
}
void mailbox_refresh_permissions(struct mailbox *box)
{
memset(&box->_perm, 0, sizeof(box->_perm));
(void)mailbox_get_permissions(box);
}
int mailbox_create_fd(struct mailbox *box, const char *path, int flags,
int *fd_r)
{
const struct mailbox_permissions *perm = mailbox_get_permissions(box);
mode_t old_mask;
int fd;
i_assert((flags & O_CREAT) != 0);
*fd_r = -1;
old_mask = umask(0);
fd = open(path, flags, perm->file_create_mode);
umask(old_mask);
if (fd != -1) {
/* ok */
} else if (errno == EEXIST) {
/* O_EXCL used, caller will handle this error */
return 0;
} else if (errno == ENOENT) {
mailbox_set_deleted(box);
return -1;
} else if (errno == ENOTDIR) {
mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
"Mailbox doesn't allow inferior mailboxes");
return -1;
} else if (mail_storage_set_error_from_errno(box->storage)) {
return -1;
} else {
mail_storage_set_critical(box->storage,
"open(%s, O_CREAT) failed: %m", path);
return -1;
}
if (perm->file_create_gid != (gid_t)-1) {
if (fchown(fd, (uid_t)-1, perm->file_create_gid) == 0) {
/* ok */
} else if (errno == EPERM) {
mail_storage_set_critical(box->storage, "%s",
eperm_error_get_chgrp("fchown", path,
perm->file_create_gid,
perm->file_create_gid_origin));
} else {
mail_storage_set_critical(box->storage,
"fchown(%s) failed: %m", path);
}
}
*fd_r = fd;
return 1;
}
int mailbox_mkdir(struct mailbox *box, const char *path,
enum mailbox_list_path_type type)
{
const struct mailbox_permissions *perm = mailbox_get_permissions(box);
const char *root_dir;
if (!perm->gid_origin_is_mailbox_path) {
/* mailbox root directory doesn't exist, create it */
root_dir = mailbox_list_get_root_forced(box->list, type);
if (mailbox_list_mkdir_root(box->list, root_dir, type) < 0) {
mail_storage_copy_list_error(box->storage, box->list);
return -1;
}
}
if (mkdir_parents_chgrp(path, perm->dir_create_mode,
perm->file_create_gid,
perm->file_create_gid_origin) == 0)
return 1;
else if (errno == EEXIST)
return 0;
else if (errno == ENOTDIR) {
mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
"Mailbox doesn't allow inferior mailboxes");
return -1;
} else if (mail_storage_set_error_from_errno(box->storage)) {
return -1;
} else {
mail_storage_set_critical(box->storage,
"mkdir_parents(%s) failed: %m", path);
return -1;
}
}
int mailbox_create_missing_dir(struct mailbox *box,
enum mailbox_list_path_type type)
{
const char *mail_dir, *dir;
struct stat st;
int ret;
if ((ret = mailbox_get_path_to(box, type, &dir)) <= 0)
return ret;
if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
&mail_dir) < 0)
return -1;
if (null_strcmp(dir, mail_dir) == 0) {
if ((box->list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) == 0)
return 0;
/* the directory might not have been created yet */
}
/* we call this function even when the directory exists, so first do a
quick check to see if we need to mkdir anything */
if (stat(dir, &st) == 0)
return 0;
return mailbox_mkdir(box, dir, type);
}
unsigned int mail_storage_get_lock_timeout(struct mail_storage *storage,
unsigned int secs)
{
return storage->set->mail_max_lock_timeout == 0 ? secs :
I_MIN(secs, storage->set->mail_max_lock_timeout);
}
enum mail_index_open_flags
mail_storage_settings_to_index_flags(const struct mail_storage_settings *set)
{
enum mail_index_open_flags index_flags = 0;
#ifndef MMAP_CONFLICTS_WRITE
if (set->mmap_disable)
#endif
index_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE;
if (set->dotlock_use_excl)
index_flags |= MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL;
if (set->mail_nfs_index)
index_flags |= MAIL_INDEX_OPEN_FLAG_NFS_FLUSH;
return index_flags;
}