mail-storage.c revision 4c0aff96fc7e6d779be43458f96cbf015849a3de
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenextern struct mail_search_register *mail_search_register_imap;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenextern struct mail_search_register *mail_search_register_human;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mail_module_register mail_module_register = { 0 };
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_search_register_deinit(&mail_search_register_human);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* append it after the list, so the autodetection order is correct */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i, count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen classes = array_get(&mail_storage_classes, &count);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < count; i++) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen unsigned int i, count;
35df1dd606c5ef21068ab4fe4be305859d4fad4bTimo Sirainen classes = array_get(&mail_storage_classes, &count);
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen for (i = 0; i < count; i++) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen unsigned int i, count;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen classes = array_get(&mail_storage_classes, &count);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen for (i = 0; i < count; i++) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen const char *p;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen /* no autodetection if the storage driver is given. */
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen enum mail_storage_flags flags, const char **error_r)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* no mail_location, autodetect */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* explicit autodetection with "auto" driver. */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* handle the same as with driver=NULL */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* no root directory given. is this allowed? */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* autodetection should take care of this */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* root not required for this storage */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* root not required for this layout */
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
3e25b17126e9536736d5da03697613e4c3af5f76Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Mail storage autodetection failed with home=%s", home);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Autodetection failed for %s (home=%s)",
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen "Ambiguous mail location setting, "
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen "don't know what to do with it: %s "
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen "(try prefixing it with mbox: or maildir:)",
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainenmail_storage_verify_root(const char *root_dir, bool autocreate,
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen const char **error_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if (!autocreate) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Root mail directory doesn't exist: %s", root_dir);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* doesn't exist */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen enum mail_storage_flags flags, const char **error_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* storage doesn't use directories (e.g. shared root) */
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we don't need to verify, but since debugging is
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen enabled, check and log if the root doesn't exist */
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen if (mail_storage_verify_root(root_dir, FALSE, &error) < 0) {
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = mail_storage_verify_root(root_dir, autocreate, error_r);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenmail_storage_match_class(struct mail_storage *storage,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen strcmp(storage->unique_root_dir, set->root_dir) != 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* allow multiple independent shared namespaces */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mail_storage *storage = user->storages;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (; storage != NULL; storage = storage->next) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mail_storage_match_class(storage, storage_class, set))
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char *data, enum mail_storage_flags flags,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char **error_r)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char *p;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen header MD5 sums stored even if we're not running POP3
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen right now. */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* autodetect */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* internal shared namespace */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_storage_set_autodetection(&data, &driver);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* first storage for namespace */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mail_storage_is_mailbox_file(storage_class))
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* using an existing storage */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
T_BEGIN {
} T_END;
const char *str;
const char *fmt, ...)
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)
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;
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)
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;
struct mail_namespace *
return FALSE;
i_unreached();
const char **str_r)
const unsigned char *data;
int ret;
return ret;
int ret;
return ret;
struct mailbox_attribute_iter *
const char *prefix)
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 *
return ctx;
const char *const *keywords_list;
const char *envelope)
unsigned int order)
int ret;
if (ret < 0) {
int ret;
if (pvt_flags != 0)
t->save_count++;
return ret;
struct mailbox_transaction_context *
int ret;
if (ret == 0) {
if (pvt_flags != 0)
t->save_count++;
return ret;
const char **path_r)
int ret;
if (ret < 0) {
return ret;
int *fd_r)
int fd;
const char *root_dir;
int ret;
return ret;
&mail_dir) < 0)
unsigned int secs)
#ifndef MMAP_CONFLICTS_WRITE
return index_flags;