mail-storage.c revision 98c217499d578495e982ea6010ebff831e9669ae
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenextern struct mail_search_register *mail_search_register_imap;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenextern struct mail_search_register *mail_search_register_human;
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen mail_search_register_deinit(&mail_search_register_human);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen /* append it after the list, so the autodetection order is correct */
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen unsigned int i, count;
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen classes = array_get(&mail_storage_classes, &count);
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen for (i = 0; i < count; i++) {
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen unsigned int i, count;
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen classes = array_get(&mail_storage_classes, &count);
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen for (i = 0; i < count; i++) {
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen unsigned int i, count;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen classes = array_get(&mail_storage_classes, &count);
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen for (i = 0; i < count; i++) {
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch const char *p;
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch /* check if data is in driver:data format (eg. mbox:~/mail) */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* no autodetection if the storage driver is given. */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Boschmail_storage_get_class(struct mail_namespace *ns, const char *driver,
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch enum mail_storage_flags flags, const char **error_r)
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch /* no mail_location, autodetect */
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch /* explicit autodetection with "auto" driver. */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* handle the same as with driver=NULL */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch storage_class = mail_user_get_storage_class(ns->user, driver);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* no root directory given. is this allowed? */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* autodetection should take care of this */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* root not required for this storage */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* root not required for this layout */
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi (void)mail_user_get_home(ns->user, &home);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi if (home == NULL || *home == '\0') home = "(not set)";
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi if (ns->set->location == NULL || *ns->set->location == '\0') {
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi "Mail storage autodetection failed with home=%s", home);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi "Autodetection failed for %s (home=%s)",
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi "Ambiguous mail location setting, "
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi "don't know what to do with it: %s "
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi "(try prefixing it with mbox: or maildir:)",
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvimail_storage_verify_root(const char *root_dir, bool autocreate,
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen } else if (!autocreate) {
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen "Root mail directory doesn't exist: %s", root_dir);
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen /* doesn't exist */
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvimail_storage_create_root(struct mailbox_list *list,
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi enum mail_storage_flags flags, const char **error_r)
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen /* we don't need to verify, but since debugging is
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen enabled, check and log if the root doesn't exist */
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen if (mail_storage_verify_root(root_dir, FALSE, &error) < 0) {
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen ret = mail_storage_verify_root(root_dir, autocreate, error_r);
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
9464dc83df5da54457ff0b629d02e543e43d53bfTimo Sirainenmail_storage_match_class(struct mail_storage *storage,
9464dc83df5da54457ff0b629d02e543e43d53bfTimo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
9464dc83df5da54457ff0b629d02e543e43d53bfTimo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
9464dc83df5da54457ff0b629d02e543e43d53bfTimo Sirainen (set->root_dir != NULL ? set->root_dir : "")) != 0)
9464dc83df5da54457ff0b629d02e543e43d53bfTimo Sirainen /* allow multiple independent shared namespaces */
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen struct mail_storage *storage = user->storages;
a1fff894178eb4279a3acb44948c1ba98db104deTimo Sirainen for (; storage != NULL; storage = storage->next) {
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen if (mail_storage_match_class(storage, storage_class, set))
c8d88cb784cc7f7edcdc97f8b24b243eb1bba7aaTimo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
9464dc83df5da54457ff0b629d02e543e43d53bfTimo Sirainen const char *data, enum mail_storage_flags flags,
const char **error_r)
error_r) < 0)
error_r);
T_BEGIN {
} T_END;
const char *str;
const char *fmt, ...)
error_r);
const char *str;
const char *str;
const struct mail_storage_settings *
void *context)
return error;
const char *error_string;
return FALSE;
return FALSE;
return TRUE;
const struct mailbox_settings *
return NULL;
return *box_set;
return NULL;
T_BEGIN {
if (open_error != 0)
} T_END;
return box;
const char *vname;
&metadata) < 0) {
return box;
return box;
return TRUE;
const char *errstr;
MAILBOX_SET_AUTO_SUBSCRIBE) == 0) {
int ret;
return ret;
const char **error_r)
if (prev_sep) {
return FALSE;
if (prev_sep && i > 0) {
return FALSE;
return TRUE;
vname++;
const char *path;
&path) < 0)
return TRUE;
return FALSE;
const char *name;
name++;
const char *name)
NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
return TRUE;
return FALSE;
case MAIL_ERROR_NOTFOUND:
int ret;
case MAIL_ERROR_NOTFOUND:
MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
T_BEGIN {
} T_END;
} T_END;
if (ret < 0) {
return FALSE;
return FALSE;
return FALSE;
if (ret < 0)
return FALSE;
return TRUE;
const char *index_dir;
int ret;
&index_dir);
if (ret <= 0)
int ret;
return ret;
const char *name1;
return FALSE;
return TRUE;
bool directory)
int ret;
if (ret == 0) {
return ret;
int ret;
return ret;
int ret;
if (ret < 0)
if (del)
if (del) {
if (ret < 0)
int ret;
return ret;
int ret;
return ret;
const char **error_r)
return TRUE;
return FALSE;
return FALSE;
return TRUE;
const char **error_r)
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret = 0;
return ret;
struct mail_namespace *
return FALSE;
i_unreached();
struct mailbox_sync_context *
T_BEGIN {
} T_END;
return ctx;
const char *errormsg;
int ret;
if (ret == 0)
return ret;
struct mail_search_context *
int ret;
return ret;
bool tryagain;
if (!tryagain)
return FALSE;
return TRUE;
return FALSE;
return TRUE;
int ret;
if (ret < 0)
return ret;
struct mailbox_transaction_context *
return trans;
int ret;
return ret;
int ret;
T_BEGIN {
} T_END;
return ret;
struct mailbox *
return t->box;
struct mail_save_context *
T_BEGIN {
} T_END;
return ctx;
const char *const *keywords_list;
const char *envelope)
unsigned int order)
int ret;
} else T_BEGIN {
} T_END;
if (ret < 0) {
int ret;
T_BEGIN {
} T_END;
return ret;
int ret;
T_BEGIN {
} T_END;
if (pvt_flags != 0)
t->save_count++;
return ret;
T_BEGIN {
} T_END;
struct mailbox_transaction_context *
int ret;
T_BEGIN {
} T_END;
if (ret == 0) {
if (pvt_flags != 0)
t->save_count++;
return ret;
int ret;
return ret;
const char **path_r)
int ret;
if (ret < 0) {
return ret;
int *fd_r)
int fd;
const char *root_dir;
int ret;
return ret;
&mail_dir) < 0)
unsigned int secs)
#ifndef MMAP_CONFLICTS_WRITE
return index_flags;
bool *utc_r)
unsigned int secs;
const char *error;