# HG changeset patch # User Timo Sirainen # Date 1184502600 -10800 # Node ID 56879cc53cec31dc485350d3f2f7a3fcca93fa17 # Parent 8da2881df0dcac991c12e7929ee9543882072992 mail_storage.create() now returns error message string. Also fixed handling "/" and empty root paths. diff -r 8da2881df0dc -r 56879cc53cec src/deliver/deliver.c --- a/src/deliver/deliver.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/deliver/deliver.c Sun Jul 15 15:30:00 2007 +0300 @@ -555,7 +555,7 @@ const char *envelope_sender = DEFAULT_ENVELOPE_SENDER; const char *mailbox = "INBOX"; const char *auth_socket; - const char *home, *destination, *user, *value; + const char *home, *destination, *user, *value, *error; struct mail_namespace *ns, *mbox_ns; struct mail_storage *storage; struct mailbox *box; @@ -738,8 +738,8 @@ mbox_ns = mail_namespaces_init_empty(namespace_pool); if (mail_storage_create(mbox_ns, "mbox", "/tmp", destination, - 0, FILE_LOCK_METHOD_FCNTL) < 0) - i_fatal("Couldn't create internal mbox storage"); + 0, FILE_LOCK_METHOD_FCNTL, &error) < 0) + i_fatal("Couldn't create internal mbox storage: %s", error); input = create_mbox_stream(0, envelope_sender); box = mailbox_open(mbox_ns->storage, "Dovecot Delivery Mail", input, MAILBOX_OPEN_NO_INDEX_FILES | diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/index/cydir/cydir-storage.c --- a/src/lib-storage/index/cydir/cydir-storage.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/index/cydir/cydir-storage.c Sun Jul 15 15:30:00 2007 +0300 @@ -37,7 +37,8 @@ static int cydir_get_list_settings(struct mailbox_list_settings *list_set, - const char *data, enum mail_storage_flags flags) + const char *data, enum mail_storage_flags flags, + const char **error_r) { bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0; const char *p; @@ -47,10 +48,11 @@ list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME; list_set->maildir_name = ""; - if (data == NULL || *data == '\0') { + if (data == NULL || *data == '\0' || *data == ':') { /* we won't do any guessing for this format. */ if (debug) i_info("cydir: mailbox location not given"); + *error_r = "Root mail directory not given"; return -1; } @@ -73,7 +75,7 @@ /* strip trailing '/' */ len = strlen(list_set->root_dir); - if (list_set->root_dir[len-1] == '/') + if (len > 1 && list_set->root_dir[len-1] == '/') list_set->root_dir = t_strndup(list_set->root_dir, len-1); if (list_set->index_dir != NULL && @@ -95,14 +97,15 @@ return &storage->storage; } -static int cydir_create(struct mail_storage *_storage, const char *data) +static int cydir_create(struct mail_storage *_storage, const char *data, + const char **error_r) { struct cydir_storage *storage = (struct cydir_storage *)_storage; struct mailbox_list_settings list_set; - const char *error; struct stat st; - if (cydir_get_list_settings(&list_set, data, _storage->flags) < 0) + if (cydir_get_list_settings(&list_set, data, _storage->flags, + error_r) < 0) return -1; list_set.mail_storage_flags = &_storage->flags; list_set.lock_method = &_storage->lock_method; @@ -110,7 +113,12 @@ if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) { if (stat(list_set.root_dir, &st) < 0) { if (errno != ENOENT) { - i_error("stat(%s) failed: %m", + *error_r = t_strdup_printf( + "stat(%s) failed: %m", + list_set.root_dir); + } else { + *error_r = t_strdup_printf( + "Root mail directory doesn't exist: %s", list_set.root_dir); } return -1; @@ -118,18 +126,16 @@ } else { if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 && errno != EEXIST) { - i_error("mkdir_parents(%s) failed: %m", - list_set.root_dir); + *error_r = t_strdup_printf("mkdir(%s) failed: %m", + list_set.root_dir); return -1; } } if (mailbox_list_init(_storage->ns, "fs", &list_set, mail_storage_get_list_flags(_storage->flags), - &_storage->list, &error) < 0) { - i_error("cydir fs: %s", error); + &_storage->list, error_r) < 0) return -1; - } storage->list_module_ctx.super = _storage->list->v; _storage->list->v.iter_is_mailbox = cydir_list_iter_is_mailbox; _storage->list->v.delete_mailbox = cydir_list_delete_mailbox; diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/index/dbox/dbox-storage.c --- a/src/lib-storage/index/dbox/dbox-storage.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/index/dbox/dbox-storage.c Sun Jul 15 15:30:00 2007 +0300 @@ -117,7 +117,8 @@ static int dbox_get_list_settings(struct mailbox_list_settings *list_set, - const char *data, enum mail_storage_flags flags) + const char *data, enum mail_storage_flags flags, + const char **error_r) { bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0; const char *p; @@ -127,10 +128,11 @@ list_set->subscription_fname = DBOX_SUBSCRIPTION_FILE_NAME; list_set->maildir_name = DBOX_MAILDIR_NAME; - if (data == NULL || *data == '\0') { + if (data == NULL || *data == '\0' || *data == ':') { /* we won't do any guessing for this format. */ if (debug) i_info("dbox: mailbox location not given"); + *error_r = "Root mail directory not given"; return -1; } @@ -175,15 +177,16 @@ return &storage->storage; } -static int dbox_create(struct mail_storage *_storage, const char *data) +static int dbox_create(struct mail_storage *_storage, const char *data, + const char **error_r) { struct dbox_storage *storage = (struct dbox_storage *)_storage; struct mailbox_list_settings list_set; struct mailbox_list *list; - const char *error; struct stat st; - if (dbox_get_list_settings(&list_set, data, _storage->flags) < 0) + if (dbox_get_list_settings(&list_set, data, _storage->flags, + error_r) < 0) return -1; list_set.mail_storage_flags = &_storage->flags; list_set.lock_method = &_storage->lock_method; @@ -191,7 +194,12 @@ if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) { if (stat(list_set.root_dir, &st) < 0) { if (errno != ENOENT) { - i_error("stat(%s) failed: %m", + *error_r = t_strdup_printf( + "stat(%s) failed: %m", + list_set.root_dir); + } else { + *error_r = t_strdup_printf( + "Root mail directory doesn't exist: %s", list_set.root_dir); } return -1; @@ -199,18 +207,17 @@ } else { if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 && errno != EEXIST) { - i_error("mkdir_parents(%s) failed: %m", - list_set.root_dir); + *error_r = t_strdup_printf("mkdir(%s) failed: %m", + list_set.root_dir); return -1; } } if (mailbox_list_init(_storage->ns, "fs", &list_set, mail_storage_get_list_flags(_storage->flags), - &list, &error) < 0) { - i_error("dbox fs: %s", error); + &list, error_r) < 0) return -1; - } + _storage->list = list; storage->list_module_ctx.super = list->v; list->v.is_valid_existing_name = dbox_storage_is_valid_existing_name; diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/index/maildir/maildir-storage.c --- a/src/lib-storage/index/maildir/maildir-storage.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/index/maildir/maildir-storage.c Sun Jul 15 15:30:00 2007 +0300 @@ -62,7 +62,7 @@ { size_t len = strlen(path); - if (len > 0 && path[len-1] == '/') + if (len > 1 && path[len-1] == '/') return t_strndup(path, len-1); else return path; @@ -76,7 +76,7 @@ static int maildir_get_list_settings(struct mailbox_list_settings *list_set, const char *data, enum mail_storage_flags flags, - const char **layout_r) + const char **layout_r, const char **error_r) { bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0; const char *home, *path, *p; @@ -89,7 +89,7 @@ if (data == NULL || *data == '\0') { if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0) { - i_error("maildir: root directory not given"); + *error_r = "Root mail directory not given"; return -1; } @@ -149,9 +149,10 @@ } } - if (list_set->root_dir == NULL) { + if (list_set->root_dir == NULL || *list_set->root_dir == '\0') { if (debug) i_info("maildir: couldn't find root dir"); + *error_r = "Root mail directory not given"; return -1; } list_set->root_dir = strip_tail_slash(list_set->root_dir); @@ -223,16 +224,18 @@ } static int -maildir_create(struct mail_storage *_storage, const char *data) +maildir_create(struct mail_storage *_storage, const char *data, + const char **error_r) { struct maildir_storage *storage = (struct maildir_storage *)_storage; enum mail_storage_flags flags = _storage->flags; struct mailbox_list_settings list_set; struct mailbox_list *list; - const char *layout, *error; + const char *layout; struct stat st; - if (maildir_get_list_settings(&list_set, data, flags, &layout) < 0) + if (maildir_get_list_settings(&list_set, data, flags, &layout, + error_r) < 0) return -1; list_set.mail_storage_flags = &_storage->flags; list_set.lock_method = &_storage->lock_method; @@ -244,16 +247,16 @@ i_error("stat(%s) failed: %m", list_set.root_dir); } + *error_r = "Mail storage doesn't exist"; return -1; } } if (mailbox_list_init(_storage->ns, layout, &list_set, mail_storage_get_list_flags(flags), - &list, &error) < 0) { - i_error("maildir %s: %s", layout, error); + &list, error_r) < 0) return -1; - } + _storage->list = list; storage->list_module_ctx.super = list->v; if (strcmp(layout, MAILDIR_PLUSPLUS_DRIVER_NAME) == 0) { diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/index/mbox/mbox-storage.c --- a/src/lib-storage/index/mbox/mbox-storage.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.c Sun Jul 15 15:30:00 2007 +0300 @@ -253,20 +253,20 @@ return path; } -static const char *create_root_dir(bool debug) +static const char *create_root_dir(bool debug, const char **error_r) { const char *home, *path; home = getenv("HOME"); if (home == NULL) { - i_error("mbox: We need root mail directory, " - "but can't find it or HOME environment"); + *error_r = "Root mail directory not set and " + "home directory is missing"; return NULL; } path = t_strconcat(home, "/mail", NULL); if (mkdir_parents(path, CREATE_MODE) < 0) { - i_error("mbox: Can't create root mail directory %s: %m", path); + *error_r = t_strdup_printf("mkdir(%s) failed: %m", path); return NULL; } @@ -278,7 +278,7 @@ static int mbox_get_list_settings(struct mailbox_list_settings *list_set, const char *data, enum mail_storage_flags flags, - const char **layout_r) + const char **layout_r, const char **error_r) { bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0; const char *p; @@ -294,7 +294,7 @@ autodetect = data == NULL || *data == '\0'; if (autodetect) { if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0) { - i_error("mbox: root mail directory not given"); + *error_r = "Root mail directory not given"; return -1; } @@ -335,18 +335,20 @@ } } - if (list_set->root_dir == NULL) { - if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) + if (list_set->root_dir == NULL || *list_set->root_dir == '\0') { + if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) { + *error_r = "Root mail directory not given"; return -1; + } - list_set->root_dir = create_root_dir(debug); + list_set->root_dir = create_root_dir(debug, error_r); if (list_set->root_dir == NULL) return -1; } else { /* strip trailing '/' */ size_t len = strlen(list_set->root_dir); - if (list_set->root_dir[len-1] == '/') { + if (len > 1 && list_set->root_dir[len-1] == '/') { list_set->root_dir = t_strndup(list_set->root_dir, len-1); } @@ -357,14 +359,18 @@ lstat(list_set->root_dir, &st) == 0) { /* yep, go ahead */ } else if (errno != ENOENT && errno != ENOTDIR) { - i_error("lstat(%s) failed: %m", list_set->root_dir); + *error_r = t_strdup_printf("lstat(%s) failed: %m", + list_set->root_dir); return -1; } else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) { + *error_r = t_strdup_printf( + "Root mail directory doesn't exist: %s", + list_set->root_dir); return -1; } else if (mkdir_parents(list_set->root_dir, CREATE_MODE) < 0 && errno != EEXIST) { - i_error("mkdir_parents(%s) failed: %m", - list_set->root_dir); + *error_r = t_strdup_printf("mkdir(%s) failed: %m", + list_set->root_dir); return -1; } } @@ -413,24 +419,24 @@ return &storage->storage; } -static int mbox_create(struct mail_storage *_storage, const char *data) +static int mbox_create(struct mail_storage *_storage, const char *data, + const char **error_r) { struct mbox_storage *storage = (struct mbox_storage *)_storage; struct mailbox_list_settings list_set; - const char *layout, *error; + const char *layout; if (mbox_get_list_settings(&list_set, data, - _storage->flags, &layout) < 0) + _storage->flags, &layout, error_r) < 0) return -1; list_set.mail_storage_flags = &_storage->flags; list_set.lock_method = &_storage->lock_method; if (mailbox_list_init(_storage->ns, layout, &list_set, mail_storage_get_list_flags(_storage->flags), - &_storage->list, &error) < 0) { - i_error("mbox %s: %s", layout, error); + &_storage->list, error_r) < 0) return -1; - } + storage->list_module_ctx.super = _storage->list->v; if (strcmp(layout, "fs") == 0 && *list_set.maildir_name == '\0') { /* have to use .imap/ directories */ diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/mail-namespace.c --- a/src/lib-storage/mail-namespace.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/mail-namespace.c Sun Jul 15 15:30:00 2007 +0300 @@ -30,7 +30,7 @@ enum file_lock_method lock_method) { struct mail_namespace *ns; - const char *sep, *type, *prefix; + const char *sep, *type, *prefix, *error; ns = p_new(pool, struct mail_namespace, 1); @@ -69,9 +69,9 @@ } ns->prefix = p_strdup(pool, prefix); - if (mail_storage_create(ns, NULL, data, user, flags, lock_method) < 0) { - i_error("Namespace '%s' mail storage creation failed " - "with mail location: %s", ns->prefix, data); + if (mail_storage_create(ns, NULL, data, user, flags, lock_method, + &error) < 0) { + i_error("Namespace '%s': %s", ns->prefix, error); return NULL; } @@ -164,7 +164,7 @@ struct mail_namespace *namespaces, *ns, **ns_p; enum mail_storage_flags flags; enum file_lock_method lock_method; - const char *mail, *data; + const char *mail, *data, *error; unsigned int i; mail_storage_parse_env(&flags, &lock_method); @@ -212,18 +212,13 @@ ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST; ns->prefix = ""; - if (mail_storage_create(ns, NULL, mail, user, flags, lock_method) < 0) { - if (mail != NULL && *mail != '\0') { - i_error("Mail storage creation failed with " - "mail_location: %s", mail); - } else { - const char *home; - - home = getenv("HOME"); - if (home == NULL || *home == '\0') home = "(not set)"; - + if (mail_storage_create(ns, NULL, mail, user, flags, lock_method, + &error) < 0) { + if (mail != NULL && *mail != '\0') + i_error("mail_location: %s", error); + else { i_error("mail_location not set and " - "autodetection failed with home=%s", home); + "autodetection failed: %s", error); } return -1; } diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/mail-storage-private.h --- a/src/lib-storage/mail-storage-private.h Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/mail-storage-private.h Sun Jul 15 15:30:00 2007 +0300 @@ -24,7 +24,8 @@ void (*class_deinit)(void); struct mail_storage *(*alloc)(void); - int (*create)(struct mail_storage *storage, const char *data); + int (*create)(struct mail_storage *storage, const char *data, + const char **error_r); void (*destroy)(struct mail_storage *storage); bool (*autodetect)(const char *data, enum mail_storage_flags flags); diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/mail-storage.c Sun Jul 15 15:30:00 2007 +0300 @@ -164,10 +164,12 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver, const char *data, const char *user, enum mail_storage_flags flags, - enum file_lock_method lock_method) + enum file_lock_method lock_method, + const char **error_r) { struct mail_storage *storage_class, *storage; struct mail_storage *const *classes; + const char *home; unsigned int i, count; if (data == NULL) @@ -181,7 +183,8 @@ } else if (driver == NULL) { storage_class = mail_storage_autodetect(data, flags); if (storage_class == NULL) { - i_error("Ambiguous mail location setting, " + *error_r = t_strdup_printf( + "Ambiguous mail location setting, " "don't know what to do with it: %s " "(try prefixing it with mbox: or maildir:)", data); @@ -191,8 +194,11 @@ count = 1; } else { storage_class = mail_storage_find(driver); - if (storage_class == NULL) + if (storage_class == NULL) { + *error_r = t_strdup_printf( + "Unknown mail storage driver %s", driver); return -1; + } classes = &storage_class; count = 1; } @@ -208,14 +214,31 @@ p_new(storage->pool, struct mail_storage_callbacks, 1); p_array_init(&storage->module_contexts, storage->pool, 5); - if (classes[i]->v.create(storage, data) == 0) + if (classes[i]->v.create(storage, data, error_r) == 0) break; + if ((flags & MAIL_STORAGE_FLAG_DEBUG) != 0 && count > 1) { + i_info("%s: Couldn't create mail storage %s: %s", + classes[i]->name, data, *error_r); + } + /* try the next one */ pool_unref(storage->pool); } - if (i == count) + if (i == count) { + if (count <= 1) { + *error_r = t_strdup_printf("%s: %s", classes[0]->name, + *error_r); + return -1; + } + + home = getenv("HOME"); + if (home == NULL || *home == '\0') home = "(not set)"; + + *error_r = t_strdup_printf( + "Mail storage autodetection failed with home=%s", home); return -1; + } if (hook_mail_storage_created != NULL) hook_mail_storage_created(storage); diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/mail-storage.h Sun Jul 15 15:30:00 2007 +0300 @@ -214,7 +214,8 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver, const char *data, const char *user, enum mail_storage_flags flags, - enum file_lock_method lock_method); + enum file_lock_method lock_method, + const char **error_r); void mail_storage_destroy(struct mail_storage **storage); char mail_storage_get_hierarchy_sep(struct mail_storage *storage); diff -r 8da2881df0dc -r 56879cc53cec src/lib-storage/mailbox-list.c --- a/src/lib-storage/mailbox-list.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/lib-storage/mailbox-list.c Sun Jul 15 15:30:00 2007 +0300 @@ -86,7 +86,8 @@ unsigned int idx; if (!mailbox_list_driver_find(driver, &idx)) { - *error_r = "Unknown mailbox list driver"; + *error_r = t_strdup_printf("Unknown mailbox list driver: %s", + driver); return -1; } diff -r 8da2881df0dc -r 56879cc53cec src/plugins/convert/convert-storage.c --- a/src/plugins/convert/convert-storage.c Sun Jul 15 15:27:58 2007 +0300 +++ b/src/plugins/convert/convert-storage.c Sun Jul 15 15:30:00 2007 +0300 @@ -265,7 +265,7 @@ struct dotlock *dotlock; enum mail_storage_flags src_flags, dest_flags; enum file_lock_method lock_method; - const char *path; + const char *path, *error; int ret; source_ns = mail_namespaces_init_empty(pool_datastack_create()); @@ -274,7 +274,7 @@ src_flags |= MAIL_STORAGE_FLAG_NO_AUTOCREATE; if (mail_storage_create(source_ns, NULL, source_data, set->user, - src_flags, lock_method) < 0) { + src_flags, lock_method, &error) < 0) { /* No need for conversion. */ return 0; } @@ -283,9 +283,9 @@ will most likely create it. So do this before locking. */ dest_ns = mail_namespaces_init_empty(pool_datastack_create()); if (mail_storage_create(dest_ns, NULL, dest_data, set->user, - dest_flags, lock_method) < 0) { + dest_flags, lock_method, &error) < 0) { i_error("Mailbox conversion: Failed to create destination " - "storage with data: %s", dest_data); + "mail storage with data '%s': %s", dest_data, error); mail_namespaces_deinit(&dest_ns); mail_namespaces_deinit(&source_ns); return -1; @@ -306,7 +306,7 @@ reopen the source storage */ mail_storage_destroy(&source_ns->storage); if (mail_storage_create(source_ns, NULL, source_data, set->user, - src_flags, lock_method) < 0) { + src_flags, lock_method, &error) < 0) { /* No need for conversion anymore. */ file_dotlock_delete(&dotlock); return 0;