# HG changeset patch # User Timo Sirainen # Date 1220816051 -10800 # Node ID 6dd0c6755afe13a4f3eb8260a1f179e3c7230528 # Parent c0a80d6b8ef6b4fc4c15cba14074e5ceb540e050 Added initial support for shared mailboxes. Listing isn't supported yet. Each user gets their own hidden namespace created automatically when they're accessed the first time. diff -r c0a80d6b8ef6 -r 6dd0c6755afe configure.in --- a/configure.in Sun Sep 07 20:48:43 2008 +0300 +++ b/configure.in Sun Sep 07 22:34:11 2008 +0300 @@ -362,12 +362,12 @@ AC_ARG_WITH(storages, [ --with-storages Build with specified mail storage formats - (maildir mbox dbox cydir raw)], [ + (maildir mbox dbox cydir shared raw)], [ if test "$withval" = "yes" -o "$withval" = "no"; then AC_MSG_ERROR([--with-storages needs storage list as parameter]) fi mail_storages=`echo "$withval"|sed 's/,/ /g'` ], - mail_storages="maildir mbox dbox cydir raw") + mail_storages="maildir mbox dbox cydir shared raw") AC_SUBST(mail_storages) AC_ARG_WITH(sql-drivers, @@ -2238,6 +2238,7 @@ dbox_libs='$(top_builddir)/src/lib-storage/index/dbox/libstorage_dbox.a' cydir_libs='$(top_builddir)/src/lib-storage/index/cydir/libstorage_cydir.a' raw_libs='$(top_builddir)/src/lib-storage/index/raw/libstorage_raw.a' +shared_libs='$(top_builddir)/src/lib-storage/index/shared/libstorage_shared.a' CORE_LIBS='$(top_builddir)/src/lib-storage/index/libstorage_index.a $(top_builddir)/src/lib-storage/libstorage.a $(top_builddir)/src/lib-index/libindex.a' deliver_storage="raw" @@ -2404,6 +2405,7 @@ src/lib-storage/index/dbox/Makefile src/lib-storage/index/cydir/Makefile src/lib-storage/index/raw/Makefile +src/lib-storage/index/shared/Makefile src/lib-storage/register/Makefile src/auth/Makefile src/deliver/Makefile diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/index/Makefile.am --- a/src/lib-storage/index/Makefile.am Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/index/Makefile.am Sun Sep 07 22:34:11 2008 +0300 @@ -1,4 +1,4 @@ -SUBDIRS = maildir mbox dbox cydir raw +SUBDIRS = maildir mbox dbox cydir raw shared noinst_LIBRARIES = libstorage_index.a diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/index/shared/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/shared/Makefile.am Sun Sep 07 22:34:11 2008 +0300 @@ -0,0 +1,23 @@ +noinst_LIBRARIES = libstorage_shared.a + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-imap \ + -I$(top_srcdir)/src/lib-index \ + -I$(top_srcdir)/src/lib-storage \ + -I$(top_srcdir)/src/lib-storage/index + +libstorage_shared_a_SOURCES = \ + shared-list.c \ + shared-storage.c + +headers = \ + shared-storage.h + +if INSTALL_HEADERS + pkginc_libdir=$(pkgincludedir)/src/lib-storage/index/shared + pkginc_lib_HEADERS = $(headers) +else + noinst_HEADERS = $(headers) +endif diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/index/shared/shared-list.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/shared/shared-list.c Sun Sep 07 22:34:11 2008 +0300 @@ -0,0 +1,269 @@ +/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "mailbox-list-private.h" +#include "shared-storage.h" + +struct shared_mailbox_list_iterate_context { + struct mailbox_list_iterate_context ctx; +}; + +extern struct mailbox_list shared_mailbox_list; + +static struct mailbox_list *shared_list_alloc(void) +{ + struct mailbox_list *list; + pool_t pool; + + pool = pool_alloconly_create("shared list", 256); + list = p_new(pool, struct mailbox_list, 1); + *list = shared_mailbox_list; + list->pool = pool; + return list; +} + +static void shared_list_deinit(struct mailbox_list *list) +{ + pool_unref(&list->pool); +} + +static void shared_list_copy_error(struct mailbox_list *shared_list, + struct mail_namespace *backend_ns) +{ + const char *str; + enum mail_error error; + + str = mailbox_list_get_last_error(backend_ns->list, &error); + mailbox_list_set_error(shared_list, error, str); +} + +static bool +shared_is_valid_pattern(struct mailbox_list *list, const char *pattern) +{ + struct mail_namespace *ns; + + if (shared_storage_get_namespace(list->ns->storage, &pattern, &ns) < 0) + return FALSE; + return mailbox_list_is_valid_pattern(ns->list, pattern); +} + +static bool +shared_is_valid_existing_name(struct mailbox_list *list, const char *name) +{ + struct mail_namespace *ns; + + if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) + return FALSE; + return mailbox_list_is_valid_existing_name(ns->list, name); +} + +static bool +shared_is_valid_create_name(struct mailbox_list *list, const char *name) +{ + struct mail_namespace *ns; + + if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) + return FALSE; + return mailbox_list_is_valid_create_name(ns->list, name); +} + +static const char * +shared_list_get_path(struct mailbox_list *list, const char *name, + enum mailbox_list_path_type type) +{ + struct mail_namespace *ns; + + if (list->ns->storage == NULL || + shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) { + switch (type) { + case MAILBOX_LIST_PATH_TYPE_DIR: + case MAILBOX_LIST_PATH_TYPE_MAILBOX: + case MAILBOX_LIST_PATH_TYPE_CONTROL: + break; + case MAILBOX_LIST_PATH_TYPE_INDEX: + /* we can safely say we don't use indexes */ + return ""; + } + i_panic("shared mailbox list: Can't return path for '%s'", + list->ns->prefix); + } + return mailbox_list_get_path(ns->list, name, type); +} + +static int +shared_list_get_mailbox_name_status(struct mailbox_list *list, const char *name, + enum mailbox_name_status *status_r) +{ + struct mail_namespace *ns; + int ret; + + if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) + return -1; + ret = mailbox_list_get_mailbox_name_status(ns->list, name, status_r); + if (ret < 0) + shared_list_copy_error(list, ns); + return ret; +} + +static const char * +shared_list_get_temp_prefix(struct mailbox_list *list, bool global ATTR_UNUSED) +{ + i_panic("shared mailbox list: Can't return a temp prefix for '%s'", + list->ns->prefix); + return NULL; +} + +static const char * +shared_list_join_refpattern(struct mailbox_list *list, + const char *ref, const char *pattern) +{ + struct mail_namespace *ns; + + if (*ref != '\0' && + shared_storage_get_namespace(list->ns->storage, &ref, &ns) == 0) + return mailbox_list_join_refpattern(ns->list, ref, pattern); + + if (*ref == '\0' && + shared_storage_get_namespace(list->ns->storage, &pattern, &ns) == 0) + return mailbox_list_join_refpattern(ns->list, "", pattern); + + /* fallback to default behavior */ + if (*ref != '\0') + pattern = t_strconcat(ref, pattern, NULL); + return pattern; +} + +static struct mailbox_list_iterate_context * +shared_list_iter_init(struct mailbox_list *list, const char *const *patterns, + enum mailbox_list_iter_flags flags) +{ + struct shared_mailbox_list_iterate_context *ctx; + + ctx = i_new(struct shared_mailbox_list_iterate_context, 1); + ctx->ctx.list = list; + ctx->ctx.flags = flags; + + /* FIXME */ + return &ctx->ctx; +} + +static const struct mailbox_info * +shared_list_iter_next(struct mailbox_list_iterate_context *_ctx) +{ + struct shared_mailbox_list_iterate_context *ctx = + (struct shared_mailbox_list_iterate_context *)_ctx; + + return NULL; +} + +static int shared_list_iter_deinit(struct mailbox_list_iterate_context *_ctx) +{ + struct shared_mailbox_list_iterate_context *ctx = + (struct shared_mailbox_list_iterate_context *)_ctx; + + i_free(ctx); + return -1; +} + +static int shared_list_set_subscribed(struct mailbox_list *list, + const char *name, bool set) +{ + struct mail_namespace *ns; + int ret; + + if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) + return -1; + ret = mailbox_list_set_subscribed(ns->list, name, set); + if (ret < 0) + shared_list_copy_error(list, ns); + return ret; +} + +static int +shared_list_delete_mailbox(struct mailbox_list *list, const char *name) +{ + struct mail_namespace *ns; + int ret; + + if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) + return -1; + ret = mailbox_list_delete_mailbox(ns->list, name); + if (ret < 0) + shared_list_copy_error(list, ns); + return ret; +} + +static int shared_list_rename_get_ns(struct mailbox_list *list, + const char **oldname, const char **newname, + struct mail_namespace **ns_r) +{ + struct mail_namespace *old_ns, *new_ns; + + if (shared_storage_get_namespace(list->ns->storage, + oldname, &old_ns) < 0 || + shared_storage_get_namespace(list->ns->storage, + newname, &new_ns) < 0) + return -1; + if (old_ns != new_ns) { + mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + "Can't rename mailboxes across storages"); + return -1; + } + *ns_r = old_ns; + return 0; +} + +static int shared_list_rename_mailbox(struct mailbox_list *list, + const char *oldname, const char *newname) +{ + struct mail_namespace *ns; + int ret; + + if (shared_list_rename_get_ns(list, &oldname, &newname, &ns) < 0) + return -1; + ret = mailbox_list_rename_mailbox(ns->list, oldname, newname); + if (ret < 0) + shared_list_copy_error(list, ns); + return ret; +} + +static int +shared_list_rename_mailbox_pre(struct mailbox_list *list, + const char *oldname, const char *newname) +{ + struct mail_namespace *ns; + int ret; + + if (shared_list_rename_get_ns(list, &oldname, &newname, &ns) < 0) + return -1; + ret = ns->list->v.rename_mailbox_pre(ns->list, oldname, newname); + if (ret < 0) + shared_list_copy_error(list, ns); + return ret; +} + +struct mailbox_list shared_mailbox_list = { + MEMBER(name) "shared", + MEMBER(hierarchy_sep) '/', + MEMBER(mailbox_name_max_length) PATH_MAX, + + { + shared_list_alloc, + shared_list_deinit, + shared_is_valid_pattern, + shared_is_valid_existing_name, + shared_is_valid_create_name, + shared_list_get_path, + shared_list_get_mailbox_name_status, + shared_list_get_temp_prefix, + shared_list_join_refpattern, + shared_list_iter_init, + shared_list_iter_next, + shared_list_iter_deinit, + NULL, + shared_list_set_subscribed, + shared_list_delete_mailbox, + shared_list_rename_mailbox, + shared_list_rename_mailbox_pre + } +}; diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/index/shared/shared-storage.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/shared/shared-storage.c Sun Sep 07 22:34:11 2008 +0300 @@ -0,0 +1,262 @@ +/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "var-expand.h" +#include "shared-storage.h" + +#define SHARED_LIST_CONTEXT(obj) \ + MODULE_CONTEXT(obj, shared_mailbox_list_module) + +extern struct mail_storage shared_storage; +extern struct mailbox shared_mailbox; + +static MODULE_CONTEXT_DEFINE_INIT(shared_mailbox_list_module, + &mailbox_list_module_register); + +static struct mail_storage *shared_alloc(void) +{ + struct shared_storage *storage; + pool_t pool; + + pool = pool_alloconly_create("shared storage", 256); + storage = p_new(pool, struct shared_storage, 1); + storage->storage = shared_storage; + storage->storage.pool = pool; + + return &storage->storage; +} + +static int shared_create(struct mail_storage *_storage, const char *data, + const char **error_r) +{ + struct shared_storage *storage = (struct shared_storage *)_storage; + struct mailbox_list_settings list_set; + const char *driver, *p; + bool have_username; + + /* data must begin with the actual mailbox driver */ + p = strchr(data, ':'); + if (p == NULL) { + *error_r = "Shared mailbox location not prefixed with driver"; + return -1; + } + driver = t_strdup_until(data, p); + storage->location = p_strdup(_storage->pool, data); + storage->storage_class = mail_storage_find_class(driver); + if (storage->storage_class == NULL) { + *error_r = t_strconcat("Unknown shared storage driver: ", + driver, NULL); + return -1; + } + _storage->mailbox_is_file = storage->storage_class->mailbox_is_file; + + p = strchr(_storage->ns->prefix, '%'); + if (p == NULL) { + *error_r = "Shared namespace prefix doesn't contain %"; + return -1; + } + storage->ns_prefix_pattern = p_strdup(_storage->pool, p); + _storage->ns->prefix = p_strdup_until(_storage->ns->user->pool, + _storage->ns->prefix, p); + + have_username = FALSE; + for (p = storage->ns_prefix_pattern; *p != '\0'; p++) { + if (*p != '%') + continue; + if (*++p == '\0') + break; + if (*p == 'u' || *p == 'n') + have_username = TRUE; + else if (*p != 'd') + break; + } + if (*p != '\0') { + *error_r = "Shared namespace prefix contains unknown variables"; + return -1; + } + if (!have_username) { + *error_r = "Shared namespace prefix doesn't contain %u or %n"; + return -1; + } + + if (mailbox_list_alloc("shared", &_storage->list, error_r) < 0) + return -1; + MODULE_CONTEXT_SET_FULL(_storage->list, shared_mailbox_list_module, + storage, &storage->list_module_ctx); + + memset(&list_set, 0, sizeof(list_set)); + list_set.mail_storage_flags = &_storage->flags; + list_set.lock_method = &_storage->lock_method; + mailbox_list_init(_storage->list, _storage->ns, &list_set, + mail_storage_get_list_flags(_storage->flags)); + return 0; +} + +int shared_storage_get_namespace(struct mail_storage *_storage, + const char **_name, + struct mail_namespace **ns_r) +{ + struct shared_storage *storage = (struct shared_storage *)_storage; + struct mail_user *user = _storage->ns->user; + static struct var_expand_table static_tab[] = { + { 'u', NULL }, + { 'n', NULL }, + { 'd', NULL }, + { '\0', NULL } + }; + struct var_expand_table *tab; + struct mail_namespace *ns; + const char *domain = NULL, *username = NULL, *userdomain = NULL; + const char *name, *p, *next, **dest, *error; + string_t *prefix, *location; + + p = storage->ns_prefix_pattern; + for (name = *_name; *p != '\0';) { + if (*p != '%') { + if (*p != *name) + return -1; + p++; name++; + continue; + } + switch (*++p) { + case 'd': + dest = &domain; + break; + case 'n': + dest = &username; + break; + case 'u': + dest = &userdomain; + break; + default: + /* we checked this already above */ + i_unreached(); + } + p++; + + next = strchr(name, *p != '\0' ? *p : _storage->ns->sep); + if (next == NULL) + return -1; + + *dest = t_strdup_until(name, next); + name = next; + } + /* successfully matched the name. */ + if (userdomain == NULL) { + i_assert(username != NULL); + userdomain = domain == NULL ? username : + t_strconcat(username, "@", domain, NULL); + } else { + domain = strchr(userdomain, '@'); + if (domain == NULL) + username = userdomain; + else { + username = t_strdup_until(userdomain, domain); + domain++; + } + } + + /* expand the namespace prefix and see if it already exists. + this should normally happen only when the mailbox is being opened */ + tab = t_malloc(sizeof(static_tab)); + memcpy(tab, static_tab, sizeof(static_tab)); + tab[0].value = userdomain; + tab[1].value = username; + tab[2].value = domain; + prefix = t_str_new(128); + str_append(prefix, _storage->ns->prefix); + var_expand(prefix, storage->ns_prefix_pattern, tab); + + ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix)); + if (ns != NULL) { + *_name = name; + *ns_r = ns; + return 0; + } + + /* create the new namespace */ + ns = p_new(user->pool, struct mail_namespace, 1); + ns->type = NAMESPACE_SHARED; + ns->user = user; + ns->prefix = p_strdup(user->pool, str_c(prefix)); + ns->flags = NAMESPACE_FLAG_LIST | NAMESPACE_FLAG_HIDDEN; + + location = t_str_new(256); + var_expand(location, storage->location, tab); + if (mail_storage_create(ns, NULL, str_c(location), _storage->flags, + _storage->lock_method, &error) < 0) { + i_error("Namespace '%s': %s", ns->prefix, error); + return -1; + } + /* FIXME: we could remove namespaces here that don't have usable + mailboxes. otherwise the memory usage could just keep growing. */ + mail_user_add_namespace(user, ns); + + *_name = name; + *ns_r = ns; + return 0; +} + +static void shared_mailbox_copy_error(struct mail_storage *shared_storage, + struct mail_namespace *backend_ns) +{ + const char *str; + enum mail_error error; + + str = mail_storage_get_last_error(backend_ns->storage, &error); + mail_storage_set_error(shared_storage, error, str); +} + +static struct mailbox * +shared_mailbox_open(struct mail_storage *storage, const char *name, + struct istream *input, enum mailbox_open_flags flags) +{ + struct mail_namespace *ns; + struct mailbox *box; + + if (input != NULL) { + mail_storage_set_critical(storage, + "Shared storage doesn't support streamed mailboxes"); + return NULL; + } + + if (shared_storage_get_namespace(storage, &name, &ns) < 0) + return NULL; + + box = mailbox_open(ns->storage, name, NULL, flags); + if (box == NULL) + shared_mailbox_copy_error(storage, ns); + return box; +} + +static int shared_mailbox_create(struct mail_storage *storage, + const char *name, bool directory) +{ + struct mail_namespace *ns; + int ret; + + if (shared_storage_get_namespace(storage, &name, &ns) < 0) + return -1; + ret = mail_storage_mailbox_create(ns->storage, name, directory); + if (ret < 0) + shared_mailbox_copy_error(storage, ns); + return ret; +} + +struct mail_storage shared_storage = { + MEMBER(name) SHARED_STORAGE_NAME, + MEMBER(mailbox_is_file) FALSE, /* unknown at this point */ + + { + NULL, + NULL, + shared_alloc, + shared_create, + index_storage_destroy, + NULL, + shared_mailbox_open, + shared_mailbox_create + } +}; diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/index/shared/shared-storage.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/shared/shared-storage.h Sun Sep 07 22:34:11 2008 +0300 @@ -0,0 +1,25 @@ +#ifndef SHARED_STORAGE_H +#define SHARED_STORAGE_H + +#include "index-storage.h" +#include "mailbox-list-private.h" + +#define SHARED_STORAGE_NAME "shared" + +struct shared_storage { + struct mail_storage storage; + union mailbox_list_module_context list_module_ctx; + + const char *ns_prefix_pattern; + const char *location; + + struct mail_storage *storage_class; +}; + +struct mailbox_list *shared_mailbox_list_alloc(void); + +int shared_storage_get_namespace(struct mail_storage *storage, + const char **name, + struct mail_namespace **ns_r); + +#endif diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/mail-namespace.c --- a/src/lib-storage/mail-namespace.c Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/mail-namespace.c Sun Sep 07 22:34:11 2008 +0300 @@ -33,7 +33,7 @@ enum file_lock_method lock_method) { struct mail_namespace *ns; - const char *sep, *type, *prefix, *error; + const char *sep, *type, *prefix, *driver, *error; ns = p_new(user->pool, struct mail_namespace, 1); @@ -79,7 +79,14 @@ ns->prefix = p_strdup(user->pool, prefix); ns->user = user; - if (mail_storage_create(ns, NULL, data, flags, lock_method, + if (ns->type == NAMESPACE_SHARED && strchr(ns->prefix, '%') != NULL) { + /* dynamic shared namespace */ + driver = "shared"; + } else { + driver = NULL; + } + + if (mail_storage_create(ns, driver, data, flags, lock_method, &error) < 0) { i_error("Namespace '%s': %s", ns->prefix, error); return NULL; @@ -160,24 +167,6 @@ return TRUE; } -static struct mail_namespace * -namespaces_sort(struct mail_namespace *src) -{ - struct mail_namespace **tmp, *next, *dest = NULL; - - for (; src != NULL; src = next) { - next = src->next; - - for (tmp = &dest; *tmp != NULL; tmp = &(*tmp)->next) { - if (strlen(src->prefix) < strlen((*tmp)->prefix)) - break; - } - src->next = *tmp; - *tmp = src; - } - return dest; -} - int mail_namespaces_init(struct mail_user *user) { struct mail_namespace *namespaces, *ns, **ns_p; @@ -212,8 +201,7 @@ if (namespaces != NULL) { if (!namespaces_check(namespaces)) return -1; - namespaces = namespaces_sort(namespaces); - user->namespaces = namespaces; + mail_user_add_namespace(user, namespaces); if (hook_mail_namespaces_created != NULL) { T_BEGIN { diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/mail-storage.c Sun Sep 07 22:34:11 2008 +0300 @@ -119,7 +119,7 @@ i_fatal("Unknown lock_method: %s", str); } -static struct mail_storage *mail_storage_find(const char *name) +struct mail_storage *mail_storage_find_class(const char *name) { struct mail_storage *const *classes; unsigned int i, count; @@ -199,7 +199,7 @@ classes = &storage_class; count = 1; } else { - storage_class = mail_storage_find(driver); + storage_class = mail_storage_find_class(driver); if (storage_class == NULL) { *error_r = t_strdup_printf( "Unknown mail storage driver %s", driver); diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/mail-storage.h Sun Sep 07 22:34:11 2008 +0300 @@ -238,6 +238,8 @@ are set to default methods */ void mail_storage_class_register(struct mail_storage *storage_class); void mail_storage_class_unregister(struct mail_storage *storage_class); +/* Find mail storage class by name */ +struct mail_storage *mail_storage_find_class(const char *name); /* Returns flags and lock_method based on environment settings. */ void mail_storage_parse_env(enum mail_storage_flags *flags_r, diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/mail-user.c --- a/src/lib-storage/mail-user.c Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/mail-user.c Sun Sep 07 22:34:11 2008 +0300 @@ -42,6 +42,23 @@ user->v.deinit(user); } +void mail_user_add_namespace(struct mail_user *user, struct mail_namespace *ns) +{ + struct mail_namespace **tmp, *next; + + for (; ns != NULL; ns = next) { + next = ns->next; + + tmp = &user->namespaces; + for (; *tmp != NULL; tmp = &(*tmp)->next) { + if (strlen(ns->prefix) < strlen((*tmp)->prefix)) + break; + } + ns->next = *tmp; + *tmp = ns; + } +} + const char *mail_user_home_expand(struct mail_user *user, const char *path) { (void)mail_user_try_home_expand(user, &path); diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/mail-user.h --- a/src/lib-storage/mail-user.h Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/mail-user.h Sun Sep 07 22:34:11 2008 +0300 @@ -36,6 +36,9 @@ struct mail_user *mail_user_init(const char *username, const char *home); void mail_user_deinit(struct mail_user **user); +/* Add a new namespace to user's namespaces. */ +void mail_user_add_namespace(struct mail_user *user, struct mail_namespace *ns); + /* Replace ~/ at the beginning of the path with the user's home directory. */ const char *mail_user_home_expand(struct mail_user *user, const char *path); /* Returns 0 if ok, -1 if home directory isn't set. */ diff -r c0a80d6b8ef6 -r 6dd0c6755afe src/lib-storage/register/Makefile.am --- a/src/lib-storage/register/Makefile.am Sun Sep 07 20:48:43 2008 +0300 +++ b/src/lib-storage/register/Makefile.am Sun Sep 07 22:34:11 2008 +0300 @@ -3,7 +3,7 @@ BUILT_SOURCES = mail-storage-register.c mail_storages = @mail_storages@ -mailbox_list_drivers = maildir imapdir fs +mailbox_list_drivers = maildir imapdir fs shared mail-storage-register.c: Makefile rm -f $@