mail-storage.c revision 459348ce42d7ec13c191776e9dedb560b871afba
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainenextern struct mail_search_register *mail_search_register_imap;
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainenextern struct mail_search_register *mail_search_register_human;
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
9508ac436fff0e1dcea975855c139cd251deb703Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen mail_search_register_deinit(&mail_search_register_human);
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen mail_search_register_deinit(&mail_search_register_imap);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* append it after the list, so the autodetection order is correct */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen unsigned int i, count;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen classes = array_get(&mail_storage_classes, &count);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen for (i = 0; i < count; i++) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen unsigned int i, count;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen classes = array_get(&mail_storage_classes, &count);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen for (i = 0; i < count; i++) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen unsigned int i, count;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen classes = array_get(&mail_storage_classes, &count);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen for (i = 0; i < count; i++) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen const char *p;
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen while (i_isalnum(*p)) p++;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* no autodetection if the storage driver is given. */
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen enum mail_storage_flags flags, const char **error_r)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen storage_class = mail_storage_find_class(driver);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* no root directory given. is this allowed? */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* autodetection should take care of this */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen /* root not required for this layout */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen "Mail storage autodetection failed with home=%s", home);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen "Ambiguous mail location setting, "
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen "don't know what to do with it: %s "
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen "(try prefixing it with mbox: or maildir:)",
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enum mail_storage_flags flags, const char **error_r)
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen /* storage doesn't use directories (e.g. shared root) */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen } else if (list->ns->type == NAMESPACE_SHARED) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* can't create a new user, but we don't want to fail
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen the storage creation. */
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen } else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen "Root mail directory doesn't exist: %s", root_dir);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* we need to create the root directory. */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (mkdir_parents_chgrp(root_dir, mode, gid, origin) < 0 &&
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen *error_r = mail_error_create_eacces_msg("mkdir", root_dir);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* created */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen struct mail_storage *storage = user->storages;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen for (; storage != NULL; storage = storage->next) {
d229d26d263a57a77eec8fe7cba24fbfd9509966Timo Sirainen if (strcmp(storage->name, storage_class->name) == 0 &&
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen strcmp(storage->unique_root_dir, set->root_dir) == 0))
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen enum mail_storage_flags flags, const char **error_r)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen const char *p;
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen header MD5 sums stored even if we're not running POP3
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen right now. */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen /* autodetect */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* internal shared namespace */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen mail_storage_set_autodetection(&data, &driver);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* first storage for namespace */
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (mail_storage_is_mailbox_file(storage_class))
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* using an existing storage */
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
31750e7fddc514c68c4eaf85b4f8c00000c281e0Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* set *_storage=NULL only after calling destroy() callback.
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen for example mdbox wants to access ns->storage */
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen i_panic("Trying to deinit storage before freeing its objects");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
const char *fmt, ...)
const char *str;
const struct mail_storage_settings *
void *context)
const char *error_string;
return FALSE;
return FALSE;
return TRUE;
T_BEGIN {
} T_END;
return box;
int ret;
MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
T_BEGIN {
} T_END;
} 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;
const char *errormsg;
int ret;
return ret;
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;
unsigned int secs)