From a24519c36d5f8fa22f58b2c693ba547e8d175a54 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 5 Apr 2010 04:49:17 +0300 Subject: [PATCH] lib-storage: Added "none" mailbox list driver. Fixed the most obvious crashes when using the driver. --HG-- branch : HEAD --- src/lib-storage/index/index-storage.c | 2 +- src/lib-storage/list/Makefile.am | 1 + src/lib-storage/list/mailbox-list-none.c | 185 +++++++++++++++++++++++ src/lib-storage/mail-storage.c | 34 +++-- src/lib-storage/mailbox-list.c | 35 ++++- src/lib-storage/mailbox-list.h | 7 +- src/lib-storage/register/Makefile.am | 2 +- 7 files changed, 245 insertions(+), 21 deletions(-) create mode 100644 src/lib-storage/list/mailbox-list-none.c diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index 5837ff4f6e..40cc2ce467 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -39,7 +39,7 @@ int index_list_create_missing_index_dir(struct mailbox_list *list, MAILBOX_LIST_PATH_TYPE_MAILBOX); index_dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX); - if (strcmp(index_dir, root_dir) == 0 || *index_dir == '\0') + if (*index_dir == '\0' || strcmp(index_dir, root_dir) == 0) return 0; mailbox_list_get_dir_permissions(list, name, &mode, &gid, &origin); diff --git a/src/lib-storage/list/Makefile.am b/src/lib-storage/list/Makefile.am index 2cbbcd2ef1..6b4db3dc22 100644 --- a/src/lib-storage/list/Makefile.am +++ b/src/lib-storage/list/Makefile.am @@ -17,6 +17,7 @@ libstorage_list_la_SOURCES = \ mailbox-list-fs-iter.c \ mailbox-list-maildir.c \ mailbox-list-maildir-iter.c \ + mailbox-list-none.c \ mailbox-list-subscriptions.c \ subscription-file.c diff --git a/src/lib-storage/list/mailbox-list-none.c b/src/lib-storage/list/mailbox-list-none.c new file mode 100644 index 0000000000..ea1d1fceb2 --- /dev/null +++ b/src/lib-storage/list/mailbox-list-none.c @@ -0,0 +1,185 @@ +/* Copyright (c) 2006-2010 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "mailbox-list-private.h" + +#define MAILBOX_LIST_NAME_NONE "none" +#define GLOBAL_TEMP_PREFIX ".temp." + +extern struct mailbox_list none_mailbox_list; + +static struct mailbox_list *none_list_alloc(void) +{ + struct mailbox_list *list; + pool_t pool; + + pool = pool_alloconly_create("none list", 2048); + + list = p_new(pool, struct mailbox_list, 1); + *list = none_mailbox_list; + list->pool = pool; + return list; +} + +static void none_list_deinit(struct mailbox_list *list) +{ + pool_unref(&list->pool); +} + +static bool +none_is_valid_pattern(struct mailbox_list *list ATTR_UNUSED, + const char *pattern ATTR_UNUSED) +{ + return TRUE; +} + +static bool +none_is_valid_existing_name(struct mailbox_list *list ATTR_UNUSED, + const char *name ATTR_UNUSED) +{ + return TRUE; +} + +static bool +none_is_valid_create_name(struct mailbox_list *list ATTR_UNUSED, + const char *name ATTR_UNUSED) +{ + return FALSE; +} + +static const char * +none_list_get_path(struct mailbox_list *list ATTR_UNUSED, + const char *name ATTR_UNUSED, + enum mailbox_list_path_type type ATTR_UNUSED) +{ + if (type == MAILBOX_LIST_PATH_TYPE_INDEX) + return ""; + return NULL; +} + +static int +none_list_get_mailbox_name_status(struct mailbox_list *list ATTR_UNUSED, + const char *name ATTR_UNUSED, + enum mailbox_name_status *status) +{ + *status = MAILBOX_NAME_VALID; + return 0; +} + +static const char * +none_list_get_temp_prefix(struct mailbox_list *list ATTR_UNUSED, + bool global ATTR_UNUSED) +{ + return GLOBAL_TEMP_PREFIX; +} + +static int none_list_set_subscribed(struct mailbox_list *list, + const char *name ATTR_UNUSED, + bool set ATTR_UNUSED) +{ + mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, "Not supported"); + return -1; +} + +static int +none_list_create_mailbox_dir(struct mailbox_list *list, + const char *name ATTR_UNUSED, + bool directory ATTR_UNUSED) +{ + mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, "Not supported"); + return -1; +} + +static int none_list_delete_mailbox(struct mailbox_list *list, + const char *name ATTR_UNUSED) +{ + mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, "Not supported"); + return -1; +} + +static int none_list_delete_dir(struct mailbox_list *list, + const char *name ATTR_UNUSED) +{ + mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, "Not supported"); + return -1; +} + +static int +none_list_rename_mailbox(struct mailbox_list *oldlist, + const char *oldname ATTR_UNUSED, + struct mailbox_list *newlist ATTR_UNUSED, + const char *newname ATTR_UNUSED, + bool rename_children ATTR_UNUSED) +{ + mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE, + "Not supported"); + return -1; +} + +static struct mailbox_list_iterate_context * +none_list_iter_init(struct mailbox_list *list, + const char *const *patterns ATTR_UNUSED, + enum mailbox_list_iter_flags flags) +{ + struct mailbox_list_iterate_context *ctx; + + ctx = i_new(struct mailbox_list_iterate_context, 1); + ctx->list = list; + ctx->flags = flags; + return ctx; +} + +static int +none_list_iter_deinit(struct mailbox_list_iterate_context *ctx) +{ + i_free(ctx); + return 0; +} + +static const struct mailbox_info * +none_list_iter_next(struct mailbox_list_iterate_context *ctx ATTR_UNUSED) +{ + return NULL; +} + +static int +none_list_get_mailbox_flags(struct mailbox_list *list ATTR_UNUSED, + const char *dir ATTR_UNUSED, + const char *fname ATTR_UNUSED, + enum mailbox_list_file_type type ATTR_UNUSED, + struct stat *st_r ATTR_UNUSED, + enum mailbox_info_flags *flags) +{ + *flags = MAILBOX_NONEXISTENT; + return 0; +} + +struct mailbox_list none_mailbox_list = { + .name = MAILBOX_LIST_NAME_NONE, + .hierarchy_sep = '/', + .props = MAILBOX_LIST_PROP_NO_ROOT, + .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH, + + { + none_list_alloc, + none_list_deinit, + NULL, + none_is_valid_pattern, + none_is_valid_existing_name, + none_is_valid_create_name, + none_list_get_path, + none_list_get_mailbox_name_status, + none_list_get_temp_prefix, + NULL, + none_list_iter_init, + none_list_iter_next, + none_list_iter_deinit, + none_list_get_mailbox_flags, + NULL, + none_list_set_subscribed, + none_list_create_mailbox_dir, + none_list_delete_mailbox, + none_list_delete_dir, + none_list_rename_mailbox + } +}; diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index a26a781c57..1837a6d0ca 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -118,9 +118,9 @@ mail_storage_set_autodetection(const char **data, const char **driver) static struct mail_storage * mail_storage_get_class(struct mail_namespace *ns, const char *driver, struct mailbox_list_settings *list_set, - const char **error_r) + enum mail_storage_flags flags, const char **error_r) { - struct mail_storage *storage_class; + struct mail_storage *storage_class = NULL; const char *home; if (driver != NULL) { @@ -130,7 +130,27 @@ mail_storage_get_class(struct mail_namespace *ns, const char *driver, "Unknown mail storage driver %s", driver); return NULL; } + } + if (list_set->root_dir == NULL || *list_set->root_dir == '\0') { + /* no root directory given. is this allowed? */ + const struct mailbox_list *list; + + list = list_set->layout == NULL ? NULL : + mailbox_list_find_class(list_set->layout); + if (storage_class == NULL && + (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) { + /* autodetection should take care of this */ + } else if (list != NULL && + (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) { + /* root not required for this layout */ + } else { + *error_r = "Root mail directory not given"; + return NULL; + } + } + + if (storage_class != NULL) { storage_class->v.get_list_settings(ns, list_set); return storage_class; } @@ -255,14 +275,8 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver, return -1; } - if ((list_set.root_dir == NULL || *list_set.root_dir == '\0') && - (driver != NULL || - (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0)) { - *error_r = "Root mail directory not given"; - return -1; - } - - storage_class = mail_storage_get_class(ns, driver, &list_set, error_r); + storage_class = mail_storage_get_class(ns, driver, &list_set, flags, + error_r); if (storage_class == NULL) return -1; i_assert(list_set.layout != NULL); diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c index 2e304d6950..0b3c589335 100644 --- a/src/lib-storage/mailbox-list.c +++ b/src/lib-storage/mailbox-list.c @@ -93,6 +93,19 @@ void mailbox_list_unregister(const struct mailbox_list *list) array_delete(&mailbox_list_drivers, idx, 1); } +const struct mailbox_list * +mailbox_list_find_class(const char *driver) +{ + const struct mailbox_list *const *class_p; + unsigned int idx; + + if (!mailbox_list_driver_find(driver, &idx)) + return NULL; + + class_p = array_idx(&mailbox_list_drivers, idx); + return *class_p; +} + int mailbox_list_create(const char *driver, struct mail_namespace *ns, const struct mailbox_list_settings *set, enum mailbox_list_flags flags, const char **error_r) @@ -103,7 +116,6 @@ int mailbox_list_create(const char *driver, struct mail_namespace *ns, i_assert(ns->list == NULL); - i_assert(set->root_dir == NULL || *set->root_dir != '\0'); i_assert(set->subscription_fname == NULL || *set->subscription_fname != '\0'); @@ -124,6 +136,9 @@ int mailbox_list_create(const char *driver, struct mail_namespace *ns, return -1; } + i_assert(set->root_dir == NULL || *set->root_dir != '\0' || + ((*class_p)->props & MAILBOX_LIST_PROP_NO_ROOT) != 0); + list = (*class_p)->v.alloc(); array_create(&list->module_contexts, list->pool, sizeof(void *), 5); @@ -359,8 +374,16 @@ mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name, const char *path; struct stat st; + /* use safe defaults */ + *file_mode_r = 0600; + *dir_mode_r = 0700; + *gid_r = (gid_t)-1; + *gid_origin_r = "defaults"; + path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR); - if (stat(path, &st) < 0) { + if (path == NULL) { + /* no filesystem support in storage */ + } else if (stat(path, &st) < 0) { if (!ENOTFOUND(errno)) { mailbox_list_set_critical(list, "stat(%s) failed: %m", path); @@ -376,11 +399,6 @@ mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name, gid_origin_r); return; } - /* return safe defaults */ - *file_mode_r = 0600; - *dir_mode_r = 0700; - *gid_r = (gid_t)-1; - *gid_origin_r = "defaults"; } else { *file_mode_r = st.st_mode & 0666; *dir_mode_r = st.st_mode & 0777; @@ -418,7 +436,8 @@ mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name, if (list->mail_set->mail_debug && name == NULL) { i_debug("Namespace %s: Using permissions from %s: " - "mode=0%o gid=%ld", list->ns->prefix, path, + "mode=0%o gid=%ld", list->ns->prefix, + path != NULL ? path : "", (int)list->dir_create_mode, list->file_create_gid == (gid_t)-1 ? -1L : (long)list->file_create_gid); diff --git a/src/lib-storage/mailbox-list.h b/src/lib-storage/mailbox-list.h index 41f3197fb8..6a9d4b49d9 100644 --- a/src/lib-storage/mailbox-list.h +++ b/src/lib-storage/mailbox-list.h @@ -21,7 +21,9 @@ enum mailbox_list_properties { /* alt directories not supported */ MAILBOX_LIST_PROP_NO_ALT_DIR = 0x02, /* no support for \noselect directories, only mailboxes */ - MAILBOX_LIST_PROP_NO_NOSELECT = 0x04 + MAILBOX_LIST_PROP_NO_NOSELECT = 0x04, + /* mail root directory isn't required */ + MAILBOX_LIST_PROP_NO_ROOT = 0x08 }; enum mailbox_list_flags { @@ -141,6 +143,9 @@ void mailbox_list_register_all(void); void mailbox_list_register(const struct mailbox_list *list); void mailbox_list_unregister(const struct mailbox_list *list); +const struct mailbox_list * +mailbox_list_find_class(const char *driver); + /* Returns 0 if ok, -1 if driver was unknown. */ int mailbox_list_create(const char *driver, struct mail_namespace *ns, const struct mailbox_list_settings *set, diff --git a/src/lib-storage/register/Makefile.am b/src/lib-storage/register/Makefile.am index 70f22df0ef..5ff9a522ef 100644 --- a/src/lib-storage/register/Makefile.am +++ b/src/lib-storage/register/Makefile.am @@ -2,7 +2,7 @@ noinst_LTLIBRARIES = libstorage_register.la mail_storages = @mail_storages@ -mailbox_list_drivers = maildir imapdir fs shared +mailbox_list_drivers = maildir imapdir none fs shared mail-storage-register.c: Makefile rm -f $@ -- 2.47.3