box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY |
MAILBOX_FLAG_IGNORE_ACLS);
- i_assert(box->storage == &ctx->storage->storage.storage);
+ if (box->storage != &ctx->storage->storage.storage) {
+ /* the namespace has multiple storages. */
+ mailbox_free(&box);
+ return 0;
+ }
if (mailbox_open(box) < 0) {
error = mailbox_get_last_mail_error(box);
i_error("Couldn't open mailbox '%s': %s",
void mail_namespace_add_storage(struct mail_namespace *ns,
struct mail_storage *storage)
{
- /* currently we support only a single storage */
- i_assert(ns->storage == NULL);
- ns->storage = storage;
+ if (ns->storage == NULL)
+ ns->storage = storage;
+ array_append(&ns->all_storages, &storage, 1);
if (storage->v.add_list != NULL)
storage->v.add_list(storage, ns->list);
static void mail_namespace_free(struct mail_namespace *ns)
{
- if (ns->storage != NULL)
- mail_storage_unref(&ns->storage);
+ struct mail_storage **storagep;
+
+ array_foreach_modifiable(&ns->all_storages, storagep)
+ mail_storage_unref(storagep);
+ array_free(&ns->all_storages);
if (ns->list != NULL)
mailbox_list_destroy(&ns->list);
ns->mail_set = mail_set;
ns->prefix = i_strdup(ns_set->prefix);
ns->special_use_mailboxes = namespace_has_special_use_mailboxes(ns_set);
+ i_array_init(&ns->all_storages, 2);
if (ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
(strchr(ns->prefix, '%') != NULL ||
void *context)
{
struct mail_namespace *ns;
+ struct mail_storage *const *storagep;
- for (ns = namespaces; ns != NULL; ns = ns->next)
- mail_storage_set_callbacks(ns->storage, callbacks, context);
+ for (ns = namespaces; ns != NULL; ns = ns->next) {
+ array_foreach(&ns->all_storages, storagep)
+ mail_storage_set_callbacks(*storagep, callbacks, context);
+ }
}
void mail_namespace_ref(struct mail_namespace *ns)
struct mail_storage *
mail_namespace_get_default_storage(struct mail_namespace *ns)
{
- /* currently we don't support more than one storage per namespace */
return ns->storage;
}
struct mail_user *user, *owner;
struct mailbox_list *list;
- /* FIXME: we should support multiple storages in one namespace */
- struct mail_storage *storage;
+ struct mail_storage *storage; /* default storage */
+ ARRAY(struct mail_storage *) all_storages;
const struct mail_namespace_settings *set, *unexpanded_set;
const struct mail_storage_settings *mail_set;
return NULL;
}
-int mail_storage_create(struct mail_namespace *ns, const char *driver,
- enum mail_storage_flags flags, const char **error_r)
+int mail_storage_create_full(struct mail_namespace *ns, const char *driver,
+ const char *data, enum mail_storage_flags flags,
+ struct mail_storage **storage_r,
+ const char **error_r)
{
struct mail_storage *storage_class, *storage = NULL;
struct mailbox_list *list;
struct mailbox_list_settings list_set;
enum mailbox_list_flags list_flags = 0;
- const char *data = ns->set->location;
const char *p;
if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
/* using an existing storage */
storage->refcount++;
mail_namespace_add_storage(ns, storage);
+ *storage_r = storage;
return 0;
}
} T_END;
DLLIST_PREPEND(&ns->user->storages, storage);
- mail_namespace_add_storage(ns, storage);
+ mail_namespace_add_storage(ns, storage);
+ *storage_r = storage;
return 0;
}
+int mail_storage_create(struct mail_namespace *ns, const char *driver,
+ enum mail_storage_flags flags, const char **error_r)
+{
+ struct mail_storage *storage;
+
+ return mail_storage_create_full(ns, driver, ns->set->location,
+ flags, &storage, error_r);
+}
+
void mail_storage_unref(struct mail_storage **_storage)
{
struct mail_storage *storage = *_storage;
struct mailbox_list *new_list = list;
struct mail_storage *storage;
struct mailbox *box;
+ enum mail_error open_error = 0;
+ const char *errstr = NULL;
i_assert(uni_utf8_str_is_valid(vname));
vname = t_strconcat("INBOX", vname + 5, NULL);
}
- if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
- /* just use the default storage. FIXME: does this break? */
- storage = mail_namespace_get_default_storage(list->ns);
- }
-
T_BEGIN {
+ if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
+ /* do a delayed failure at mailbox_open() */
+ storage = mail_namespace_get_default_storage(list->ns);
+ errstr = mailbox_list_get_last_error(new_list, &open_error);
+ errstr = t_strdup(errstr);
+ }
+
box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
box->set = mailbox_settings_find(storage->user, vname);
+ box->open_error = open_error;
+ if (open_error != 0)
+ mail_storage_set_error(storage, open_error, errstr);
hook_mailbox_allocated(box);
} T_END;
int mail_storage_create(struct mail_namespace *ns, const char *driver,
enum mail_storage_flags flags, const char **error_r)
ATTR_NULL(2);
+int mail_storage_create_full(struct mail_namespace *ns, const char *driver,
+ const char *data, enum mail_storage_flags flags,
+ struct mail_storage **storage_r,
+ const char **error_r) ATTR_NULL(2);
void mail_storage_unref(struct mail_storage **storage);
/* Returns the mail storage settings. */