mail-storage.c revision 8e853397a7ce4faaee6b90dac6f4d1615fdbedf5
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
7fa573e6ea36024f618492e7d3649a69c1b41028Timo Sirainenextern struct mail_search_register *mail_search_register_imap;
5a9e240ebf8d0daaf029973973b52e415148070bTimo Sirainenextern struct mail_search_register *mail_search_register_human;
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mail_module_register mail_module_register = { 0 };
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch mail_search_register_deinit(&mail_search_register_human);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Bosch mail_search_register_deinit(&mail_search_register_imap);
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Boschvoid mail_storage_class_register(struct mail_storage *storage_class)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* append it after the list, so the autodetection order is correct */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
529944a3554da75c2e6231a25fe489d815519b22Stephan Bosch unsigned int i, count;
8ac6623677005256bf99ab33a2ed98c69c1d656cStephan Bosch classes = array_get(&mail_storage_classes, &count);
f32d0295c90ed810889504cdfa5e1a25a415f65fStephan Bosch for (i = 0; i < count; i++) {
36b072d84a9076c3c483bf710444a716e987ccc3Stephan Boschstruct mail_storage *mail_storage_find_class(const char *name)
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen unsigned int i, count;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen classes = array_get(&mail_storage_classes, &count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (i = 0; i < count; i++) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen unsigned int i, count;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen classes = array_get(&mail_storage_classes, &count);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen for (i = 0; i < count; i++) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen const char *p;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen while (i_isalnum(*p)) p++;
ae797f3368ebb86e7786ca25d7c9c703f672b9f5Timo Sirainen /* no autodetection if the storage driver is given. */
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
b045b66988bfbaa2795791e42ee724fae6f0db1cAki Tuomi enum mail_storage_flags flags, const char **error_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* no mail_location, autodetect */
64e244defe74f513ce94f33d000a048ddbe2ea23Timo Sirainen /* explicit autodetection with "auto" driver. */
009217abb57a24a4076092e8e4e165545747839eStephan Bosch /* handle the same as with driver=NULL */
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen storage_class = mail_storage_find_class(driver);
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen /* no root directory given. is this allowed? */
bbba7d0fce1b6ce5baa2d7ef946eb1b63e2ab518Timo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
bbba7d0fce1b6ce5baa2d7ef946eb1b63e2ab518Timo Sirainen /* autodetection should take care of this */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* root not required for this storage */
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen /* root not required for this layout */
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen storage_class->v.get_list_settings(ns, list_set);
bf72c930996df0691932fb1143f360d260f27a06Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
02ccba3d3be96444abd15b5254864c9151bbeb30Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen "Mail storage autodetection failed with home=%s", home);
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
ce1a6c9b82117d253df9acd77e54ac84dd8a247eTimo Sirainen "Autodetection failed for %s (home=%s)",
ec9429535e925610513bd6bfde6729e273082ccbTimo Sirainen "Ambiguous mail location setting, "
ec9429535e925610513bd6bfde6729e273082ccbTimo Sirainen "don't know what to do with it: %s "
66ea9eaaa2d7531b3be8f633937628c94d907031Timo Sirainen "(try prefixing it with mbox: or maildir:)",
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenmail_storage_verify_root(const char *root_dir, bool autocreate,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen const char **error_r)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen } else if (!autocreate) {
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen "Root mail directory doesn't exist: %s", root_dir);
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen /* doesn't exist */
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen enum mail_storage_flags flags, const char **error_r)
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen /* storage doesn't use directories (e.g. shared root) */
66ea9eaaa2d7531b3be8f633937628c94d907031Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* we don't need to verify, but since debugging is
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enabled, check and log if the root doesn't exist */
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen if (mail_storage_verify_root(root_dir, FALSE, &error) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
c4ec7cb598805b1387dc3aab59ec8f32d8cc24e1Timo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = mail_storage_verify_root(root_dir, autocreate, error_r);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainenmail_storage_match_class(struct mail_storage *storage,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen strcmp(storage->unique_root_dir, set->root_dir) != 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* allow multiple independent shared namespaces */
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen struct mail_storage *storage = user->storages;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (; storage != NULL; storage = storage->next) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mail_storage_match_class(storage, storage_class, set))
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
717bb0dbaf4bd3f745669570647845e6d493bfe0Timo Sirainen enum mail_storage_flags flags, const char **error_r)
c5e62353a11087958ea4e619660e084a613e1a37Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
error_r) < 0)
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 NULL;
return *box_set;
return NULL;
T_BEGIN {
} 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 TRUE;
const char *name1;
return FALSE;
return TRUE;
bool directory)
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();
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;
return ret;
struct mailbox_transaction_context *
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;