mail-storage.c revision 2039bdca260cd123832ddda9b2b6862a4abc53aa
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenextern struct mail_search_register *mail_search_register_imap;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenextern struct mail_search_register *mail_search_register_human;
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainenstruct event_category event_category_storage = {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct event_category event_category_mailbox = {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_search_register_deinit(&mail_search_register_human);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* append it after the list, so the autodetection order is correct */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen unsigned int i, count;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen classes = array_get(&mail_storage_classes, &count);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen for (i = 0; i < count; i++) {
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen unsigned int i, count;
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen classes = array_get(&mail_storage_classes, &count);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen for (i = 0; i < count; i++) {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen unsigned int i, count;
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen classes = array_get(&mail_storage_classes, &count);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen for (i = 0; i < count; i++) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const char *p;
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen /* no autodetection if the storage driver is given. */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen enum mail_storage_flags flags, const char **error_r)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* no mail_location, autodetect */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* explicit autodetection with "auto" driver. */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* handle the same as with driver=NULL */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* no root directory given. is this allowed? */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* autodetection should take care of this */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* root not required for this storage */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* root not required for this layout */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen storage_class->v.get_list_settings(ns, list_set);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen "Mail storage autodetection failed with home=%s", home);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen "Autodetection failed for %s (home=%s)",
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen "Ambiguous mail location setting, "
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen "don't know what to do with it: %s "
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "(try prefixing it with mbox: or maildir:)",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenmail_storage_verify_root(const char *root_dir, const char *dir_type,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen const char **error_r)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "Root mail directory is a file: %s", root_dir);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen "Root %s directory doesn't exist: %s", dir_type, root_dir);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen enum mail_storage_flags flags, const char **error_r)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (!mailbox_list_get_root_path(list, type, &root_dir)) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen /* we don't need to verify, but since debugging is
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen enabled, check and log if the root doesn't exist */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (mail_storage_verify_root(root_dir, type_name, &error) < 0) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* If the directories don't exist, we'll just autocreate them
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return mail_storage_verify_root(root_dir, type_name, error_r);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenmail_storage_match_class(struct mail_storage *storage,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (set->root_dir != NULL ? set->root_dir : "")) != 0)
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen /* allow multiple independent shared namespaces */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct mail_storage *storage = user->storages;
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen for (; storage != NULL; storage = storage->next) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (mail_storage_match_class(storage, storage_class, set))
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen const char *data, enum mail_storage_flags flags,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char **error_r)
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *p;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen header MD5 sums stored even if we're not running POP3
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen right now. */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen mailbox_list_settings_init_defaults(&list_set);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen /* autodetect */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
error_r) < 0)
error_r);
T_BEGIN {
} T_END;
const char *str;
const char *fmt, ...)
T_BEGIN {
} T_END;
T_BEGIN {
} T_END;
error_r);
const char *str;
const char *str;
const char *index_error;
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;
return TRUE;
return TRUE;
const char *errstr;
errstr);
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 FALSE;
return TRUE;
int ret = 0;
return ret;
struct mail_namespace *
return FALSE;
i_unreached();
struct mailbox_sync_context *
return ctx;
T_BEGIN {
} T_END;
return ctx;
return FALSE;
const char *errormsg;
int ret;
if (ret == 0)
return ret;
struct mail_search_context *
int ret;
return ret;
bool tryagain;
if (!tryagain)
return FALSE;
return TRUE;
return FALSE;
return TRUE;
int ret;
if (ret < 0)
return ret;
struct mailbox_transaction_context *
const char *reason)
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;
int ret;
if (ret < 0) {
return ret;
const char **path_r)
int *fd_r)
int fd;
const char *root_dir;
int ret;
return ret;
&mail_dir) < 0)
unsigned int secs)
#ifndef MMAP_CONFLICTS_WRITE
return index_flags;
bool *utc_r)
unsigned int secs;
const char *error;
T_BEGIN {
} T_END;
bool created;
const char **error_r)
const char *lock_path;