mail-storage.c revision 0cb1eb9a12488be403e4179877c31729efaa3c2f
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* append it after the list, so the autodetection order is correct */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen unsigned int i, count;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen classes = array_get(&mail_storage_classes, &count);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen for (i = 0; i < count; i++) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int i, count;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen classes = array_get(&mail_storage_classes, &count);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (i = 0; i < count; i++) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int i, count;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen classes = array_get(&mail_storage_classes, &count);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (i = 0; i < count; i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *p;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (i_isalnum(*p)) p++;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* no autodetection if the storage driver is given. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage_class = mail_storage_find_class(driver);
a5e89374cb2fb2cad575fee6c3b33a9487ab9b3aTimo Sirainen storage_class->v.get_list_settings(ns, list_set);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Mail storage autodetection failed with home=%s", home);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Ambiguous mail location setting, "
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen "don't know what to do with it: %s "
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "(try prefixing it with mbox: or maildir:)",
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen enum mail_storage_flags flags, const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen } else if (list->ns->type == NAMESPACE_SHARED) {
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen /* can't create a new user, but we don't want to fail
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen the storage creation. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Root mail directory doesn't exist: %s", root_dir);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen /* we need to create the root directory. */
437a8b0fe254057b0c1f1723d689bafa91cae2abTimo Sirainen mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen if (mkdir_parents_chgrp(root_dir, mode, gid, origin) < 0 &&
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen *error_r = mail_error_create_eacces_msg("mkdir", root_dir);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen /* created */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen struct mail_storage *storage = user->storages;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (; storage != NULL; storage = storage->next) {
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (strcmp(storage->name, storage_class->name) == 0 &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(storage->unique_root_dir, set->root_dir) == 0))
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen enum mail_storage_flags flags, const char **error_r)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_storage *storage_class, *storage = NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *p;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen header MD5 sums stored even if we're not running POP3
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen right now. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* autodetect */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* internal shared namespace */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_storage_set_autodetection(&data, &driver);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mailbox_list_settings_parse(data, &list_set, ns,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0 &&
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, error_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* first storage for namespace */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mail_storage_is_mailbox_file(storage_class))
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen /* using an existing storage */
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen storage->v.create(storage, ns, error_r) < 0) {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_storage_ref(struct mail_storage *storage)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_strdup(str) : i_strdup(MAIL_ERRSTR_CRITICAL_MSG);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *fmt, ...)
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen /* critical errors may contain sensitive data, so let user
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen see only "Internal error" with a timestamp to make it
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen easier to look from log files the actual error message. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen const char *str;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen str = mailbox_list_get_last_error(list, &error);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_storage_set_index_error(struct mailbox *box)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_storage_set_internal_error(box->storage);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenmail_storage_get_settings(struct mail_storage *storage)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen /* We get here only in error situations, so we have to return some
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen error. If storage->error is NONE, it means we forgot to set it at
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen some point.. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return storage->error_string != NULL ? storage->error_string :
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "BUG: Unknown internal error";
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* This shouldn't happen.. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* debugging is enabled - admin may be debugging a
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen (permission) problem, so return FALSE to get the caller to
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen log the full error message. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_storage_set_error(storage, error, error_string);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mailbox_list_get_storage(&new_list, &name, &storage) < 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* just use the first storage. FIXME: does this break? */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen box = storage->v.mailbox_alloc(storage, new_list, name, flags);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int mailbox_open_full(struct mailbox *box, struct istream *input)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Invalid mailbox name");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "Storage doesn't support streamed mailboxes");
} T_END;
if (ret < 0) {
bool directory)
directory) < 0) {
if (del)
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret;
return ret;
return TRUE;
return FALSE;
return FALSE;
return TRUE;
bool rename_children)
struct mail_namespace *
return FALSE;
struct mailbox_sync_context *
T_BEGIN {
} T_END;
return ctx;
struct mail_keywords *
const char *const keywords[])
i_unreached();
return kw;
struct mail_keywords *
const char **error_r)
return FALSE;
bool only_with_msgs)
struct mailbox_header_lookup_ctx *
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)
int ret;
if (ret < 0) {
int ret;
return ret;
int ret;
return ret;
int *fd_r)
int fd;