]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Initial commit for making mail_storage:mailbox_list to be from 1:1 to n:n.
authorTimo Sirainen <tss@iki.fi>
Wed, 3 Jun 2009 02:30:28 +0000 (22:30 -0400)
committerTimo Sirainen <tss@iki.fi>
Wed, 3 Jun 2009 02:30:28 +0000 (22:30 -0400)
This will allow namespaces to share the same storage and a single namespace
to have multiple storages (multiple mailbox formats). Neither works
currently, and this commit probably breaks some things.

--HG--
branch : HEAD

102 files changed:
src/config/settings-get.pl
src/imap/cmd-append.c
src/imap/cmd-copy.c
src/imap/cmd-create.c
src/imap/cmd-delete.c
src/imap/cmd-list.c
src/imap/cmd-rename.c
src/imap/cmd-select.c
src/imap/cmd-status.c
src/imap/cmd-subscribe.c
src/imap/imap-client.c
src/imap/imap-commands-util.c
src/imap/imap-commands-util.h
src/imap/imap-commands.h
src/imap/imap-status.c
src/imap/imap-status.h
src/lda/main.c
src/lib-lda/mail-deliver.c
src/lib-storage/index/cydir/cydir-mail.c
src/lib-storage/index/cydir/cydir-save.c
src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/cydir/cydir-sync.c
src/lib-storage/index/dbox/dbox-map.c
src/lib-storage/index/dbox/dbox-settings.c
src/lib-storage/index/dbox/dbox-storage-rebuild.c
src/lib-storage/index/dbox/dbox-storage.c
src/lib-storage/index/dbox/dbox-storage.h
src/lib-storage/index/dbox/dbox-sync-rebuild.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/maildir/maildir-keywords.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/maildir/maildir-storage.h
src/lib-storage/index/maildir/maildir-sync-index.c
src/lib-storage/index/maildir/maildir-uidlist.c
src/lib-storage/index/maildir/maildir-util.c
src/lib-storage/index/mbox/mbox-lock.c
src/lib-storage/index/mbox/mbox-save.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/mbox/mbox-storage.h
src/lib-storage/index/raw/raw-storage.c
src/lib-storage/index/shared/shared-list.c
src/lib-storage/index/shared/shared-storage.c
src/lib-storage/index/shared/shared-storage.h
src/lib-storage/list/index-mailbox-list-sync.c
src/lib-storage/list/index-mailbox-list.c
src/lib-storage/list/mailbox-list-fs.c
src/lib-storage/list/mailbox-list-maildir.h
src/lib-storage/mail-namespace.c
src/lib-storage/mail-namespace.h
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage-settings.c
src/lib-storage/mail-storage-settings.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/lib-storage/mail-user.c
src/lib-storage/mailbox-list-private.h
src/lib-storage/mailbox-list.c
src/lib-storage/mailbox-list.h
src/lmtp/commands.c
src/plugins/acl/acl-api-private.h
src/plugins/acl/acl-api.c
src/plugins/acl/acl-api.h
src/plugins/acl/acl-backend-vfile-acllist.c
src/plugins/acl/acl-backend-vfile.c
src/plugins/acl/acl-backend.c
src/plugins/acl/acl-lookup-dict.c
src/plugins/acl/acl-mailbox-list.c
src/plugins/acl/acl-mailbox.c
src/plugins/acl/acl-plugin.h
src/plugins/acl/acl-shared-storage.c
src/plugins/acl/acl-storage.c
src/plugins/acl/acl-storage.h
src/plugins/autocreate/autocreate-plugin.c
src/plugins/convert/convert-storage.c
src/plugins/expire/expire-plugin.c
src/plugins/expire/expire-tool.c
src/plugins/fts-lucene/fts-backend-lucene.c
src/plugins/fts-solr/fts-backend-solr.c
src/plugins/fts-squat/fts-backend-squat.c
src/plugins/fts/fts-storage.c
src/plugins/imap-acl/imap-acl-plugin.c
src/plugins/imap-quota/imap-quota-plugin.c
src/plugins/lazy-expunge/lazy-expunge-plugin.c
src/plugins/listescape/listescape-plugin.c
src/plugins/mail-log/mail-log-plugin.c
src/plugins/mbox-snarf/mbox-snarf-plugin.c
src/plugins/quota/quota-count.c
src/plugins/quota/quota-dirsize.c
src/plugins/quota/quota-fs.c
src/plugins/quota/quota-maildir.c
src/plugins/quota/quota-private.h
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c
src/plugins/trash/trash-plugin.c
src/plugins/virtual/virtual-config.c
src/plugins/virtual/virtual-mail.c
src/plugins/virtual/virtual-storage.c
src/plugins/virtual/virtual-storage.h
src/plugins/zlib/zlib-plugin.c
src/pop3/pop3-client.c
src/util/doveadm.c

index c98c9c6ba11a0407d71553b47e207c4a4f5adc38..26f113d5ed6d80b0ed430a7e691e77fa4ce8164f 100755 (executable)
@@ -4,6 +4,7 @@ use strict;
 print '#include "lib.h"'."\n";
 print '#include "array.h"'."\n";
 print '#include "var-expand.h"'."\n";
+print '#include "file-lock.h"'."\n";
 print '#include "settings-parser.h"'."\n";
 print '#include "all-settings.h"'."\n";
 print '#include <stddef.h>'."\n";
index b89df3086b88f62f0b5d8aa78c0cb64da388d22b..5a28795b46195bab486faac42a16f711ee1608f6 100644 (file)
@@ -8,7 +8,6 @@
 #include "imap-commands.h"
 #include "imap-parser.h"
 #include "imap-date.h"
-#include "mail-storage.h"
 
 #include <sys/time.h>
 
@@ -452,24 +451,24 @@ static bool cmd_append_continue_message(struct client_command_context *cmd)
 static struct mailbox *
 get_mailbox(struct client_command_context *cmd, const char *name)
 {
-       struct mail_storage *storage;
+       struct mail_namespace *ns;
        struct mailbox *box;
 
        if (!client_verify_mailbox_name(cmd, name, TRUE, FALSE))
                return NULL;
 
-       storage = client_find_storage(cmd, &name);
-       if (storage == NULL)
+       ns = client_find_namespace(cmd, &name);
+       if (ns == NULL)
                return NULL;
 
        if (cmd->client->mailbox != NULL &&
-           mailbox_equals(cmd->client->mailbox, storage, name))
+           mailbox_equals(cmd->client->mailbox, ns, name))
                return cmd->client->mailbox;
 
-       box = mailbox_open(&storage, name, NULL, MAILBOX_OPEN_SAVEONLY |
+       box = mailbox_open(ns->list, name, NULL, MAILBOX_OPEN_SAVEONLY |
                           MAILBOX_OPEN_KEEP_RECENT);
        if (box == NULL) {
-               client_send_storage_error(cmd, storage);
+               client_send_list_error(cmd, ns->list);
                return NULL;
        }
        if (cmd->client->enabled_features != 0)
index d92490795044d3575bea4014ce5cc8f0a27aad2f..47e0b571eb21789be6b68a7ab6b82e075f583258 100644 (file)
@@ -93,7 +93,8 @@ static int fetch_and_copy(struct client *client, struct mailbox *destbox,
 bool cmd_copy(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
-       struct mail_storage *storage;
+       struct mail_namespace *dest_ns;
+       struct mail_storage *dest_storage;
        struct mailbox *destbox;
        struct mailbox_transaction_context *t;
         struct mail_search_args *search_args;
@@ -119,18 +120,18 @@ bool cmd_copy(struct client_command_context *cmd)
        if (ret <= 0)
                return ret < 0;
 
-       storage = client_find_storage(cmd, &mailbox);
-       if (storage == NULL)
+       dest_ns = client_find_namespace(cmd, &mailbox);
+       if (dest_ns == NULL)
                return TRUE;
 
-       if (mailbox_equals(client->mailbox, storage, mailbox))
+       if (mailbox_equals(client->mailbox, dest_ns, mailbox))
                destbox = client->mailbox;
        else {
-               destbox = mailbox_open(&storage, mailbox, NULL,
+               destbox = mailbox_open(dest_ns->list, mailbox, NULL,
                                       MAILBOX_OPEN_SAVEONLY |
                                       MAILBOX_OPEN_KEEP_RECENT);
                if (destbox == NULL) {
-                       client_send_storage_error(cmd, storage);
+                       client_send_list_error(cmd, dest_ns->list);
                        return TRUE;
                }
                if (client->enabled_features != 0)
@@ -168,6 +169,7 @@ bool cmd_copy(struct client_command_context *cmd)
                }
        }
 
+       dest_storage = mailbox_get_storage(destbox);
        if (destbox != client->mailbox) {
                sync_flags |= MAILBOX_SYNC_FLAG_FAST;
                imap_flags |= IMAP_SYNC_FLAG_SAFE;
@@ -182,7 +184,7 @@ bool cmd_copy(struct client_command_context *cmd)
                        "NO ["IMAP_RESP_CODE_EXPUNGEISSUED"] "
                        "Some of the requested messages no longer exist.");
        } else {
-               client_send_storage_error(cmd, storage);
+               client_send_storage_error(cmd, dest_storage);
                return TRUE;
        }
 }
index c514f5d4f178218532321ef2b18a03ec6d495385..d4561bf9aadd0a3cd10eb9909bb0e018f025ba26 100644 (file)
@@ -7,6 +7,7 @@
 bool cmd_create(struct client_command_context *cmd)
 {
        struct mail_namespace *ns;
+       struct mail_storage *storage;
        const char *mailbox, *full_mailbox;
        bool directory;
        size_t len;
@@ -38,8 +39,9 @@ bool cmd_create(struct client_command_context *cmd)
        if (!client_verify_mailbox_name(cmd, full_mailbox, FALSE, TRUE))
                return TRUE;
 
-       if (mail_storage_mailbox_create(ns->storage, mailbox, directory) < 0)
-               client_send_storage_error(cmd, ns->storage);
+       storage = mail_namespace_get_default_storage(ns);
+       if (mail_storage_mailbox_create(storage, ns, mailbox, directory) < 0)
+               client_send_storage_error(cmd, storage);
        else
                client_send_tagline(cmd, "OK Create completed.");
        return TRUE;
index e4df7ccd433358d0a2efb14b114d71567441ef7b..872ab608eff8cc86f8d886e1545efa4ae9d6e0b6 100644 (file)
@@ -6,8 +6,8 @@
 bool cmd_delete(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
+       struct mail_namespace *ns;
        struct mail_storage *storage;
-       struct mailbox_list *list;
        struct mailbox *mailbox;
        const char *name;
 
@@ -21,8 +21,13 @@ bool cmd_delete(struct client_command_context *cmd)
                return TRUE;
        }
 
+       ns = client_find_namespace(cmd, &name);
+       if (ns == NULL)
+               return TRUE;
+
        mailbox = client->mailbox;
-       if (mailbox != NULL && strcmp(mailbox_get_name(mailbox), name) == 0) {
+       if (mailbox != NULL && mailbox_get_namespace(mailbox) == ns &&
+           strcmp(mailbox_get_name(mailbox), name) == 0) {
                /* deleting selected mailbox. close it first */
                client_search_updates_free(client);
                storage = mailbox_get_storage(mailbox);
@@ -30,22 +35,17 @@ bool cmd_delete(struct client_command_context *cmd)
 
                if (mailbox_close(&mailbox) < 0)
                        client_send_untagged_storage_error(client, storage);
-       } else {
-               storage = client_find_storage(cmd, &name);
-               if (storage == NULL)
-                       return TRUE;
        }
 
        if ((client->workarounds & WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
            *name != '\0' &&
-           name[strlen(name)-1] == mail_storage_get_hierarchy_sep(storage)) {
+           name[strlen(name)-1] == mailbox_list_get_hierarchy_sep(ns->list)) {
                /* drop the extra trailing hierarchy separator */
                name = t_strndup(name, strlen(name)-1);
        }
 
-       list = mail_storage_get_list(storage);
-       if (mailbox_list_delete_mailbox(list, name) < 0)
-               client_send_list_error(cmd, list);
+       if (mailbox_list_delete_mailbox(ns->list, name) < 0)
+               client_send_list_error(cmd, ns->list);
        else {
                client_send_tagline(cmd, "OK Delete completed.");
        }
index 13836c7fbb5f1fcd41f459311835868c72a58fef..3d325023249882ef49b197723db5fad4a8cb6e43 100644 (file)
@@ -310,16 +310,16 @@ list_namespace_send_prefix(struct cmd_list_context *ctx, bool have_children)
 static void list_send_status(struct cmd_list_context *ctx, const char *name)
 {
        struct mailbox_status status;
-       const char *storage_name;
+       const char *storage_name, *error;
        size_t prefix_len = strlen(ctx->ns->prefix);
 
        storage_name = strncmp(name, ctx->ns->prefix, prefix_len) == 0 ?
                name + prefix_len : name;
 
-       if (!imap_status_get(ctx->cmd->client, ctx->ns->storage, storage_name,
-                            ctx->status_items, &status)) {
-               client_send_untagged_storage_error(ctx->cmd->client,
-                                                  ctx->ns->storage);
+       if (imap_status_get(ctx->cmd->client, ctx->ns, storage_name,
+                           ctx->status_items, &status, &error) < 0) {
+               client_send_line(ctx->cmd->client,
+                                t_strconcat("* NO ", error, NULL));
                return;
        }
 
@@ -775,7 +775,7 @@ static void cmd_list_ref_root(struct client *client, const char *ref)
                ns_sep = ns->sep;
        } else {
                ns_prefix = "";
-               ns_sep = mail_namespace_get_root_sep(client->user->namespaces);
+               ns_sep = mail_namespaces_get_root_sep(client->user->namespaces);
        }
 
        str = t_str_new(64);
index fb7d208f9a025bcb7d5defb41ecd34c79a5036ff..387bc4fb88f7276f6c63067c25ead9509c7f058e 100644 (file)
@@ -6,9 +6,7 @@
 
 bool cmd_rename(struct client_command_context *cmd)
 {
-       struct mail_storage *old_storage, *new_storage;
-       struct mailbox_list *old_list, *new_list;
-       struct mail_namespace *old_ns;
+       struct mail_namespace *old_ns, *new_ns;
        const char *oldname, *newname;
        unsigned int oldlen;
 
@@ -19,20 +17,18 @@ bool cmd_rename(struct client_command_context *cmd)
        if (!client_verify_mailbox_name(cmd, newname, FALSE, TRUE))
                return TRUE;
 
-       old_storage = client_find_storage(cmd, &oldname);
-       if (old_storage == NULL)
+       old_ns = client_find_namespace(cmd, &oldname);
+       if (old_ns == NULL)
                return TRUE;
-       old_list = mail_storage_get_list(old_storage);
 
-       new_storage = client_find_storage(cmd, &newname);
-       if (new_storage == NULL)
+       new_ns = client_find_namespace(cmd, &newname);
+       if (new_ns == NULL)
                return TRUE;
-       new_list = mail_storage_get_list(new_storage);
 
-       if (old_storage == new_storage) {
+       if (old_ns == new_ns) {
                /* disallow box -> box/child, because it may break clients and
                   there's really no point in doing it anyway. */
-               old_ns = mailbox_list_get_namespace(old_list);
+               old_ns = mailbox_list_get_namespace(old_ns->list);
                oldlen = strlen(oldname);
                if (strncmp(oldname, newname, oldlen) == 0 &&
                    newname[oldlen] == old_ns->real_sep) {
@@ -42,9 +38,9 @@ bool cmd_rename(struct client_command_context *cmd)
                }
        }
 
-       if (mailbox_list_rename_mailbox(old_list, oldname,
-                                       new_list, newname, TRUE) < 0)
-               client_send_list_error(cmd, old_list);
+       if (mailbox_list_rename_mailbox(old_ns->list, oldname,
+                                       new_ns->list, newname, TRUE) < 0)
+               client_send_list_error(cmd, old_ns->list);
        else
                client_send_tagline(cmd, "OK Rename completed.");
        return TRUE;
index d7d0ae5afa044449a51f8ada76010cdd4e6fac9f..15c07833760059a805a3193ba69acc6f710c21fc 100644 (file)
@@ -12,7 +12,7 @@
 
 struct imap_select_context {
        struct client_command_context *cmd;
-       struct mail_storage *storage;
+       struct mail_namespace *ns;
        struct mailbox *box;
 
        struct imap_fetch_context *fetch_ctx;
@@ -188,7 +188,6 @@ static void cmd_select_finish(struct imap_select_context *ctx, int ret)
        if (ret < 0) {
                if (ctx->box != NULL)
                        mailbox_close(&ctx->box);
-               client_send_storage_error(ctx->cmd, ctx->storage);
                ctx->cmd->client->mailbox = NULL;
        } else {
                client_send_tagline(ctx->cmd, mailbox_is_readonly(ctx->box) ?
@@ -209,6 +208,10 @@ static bool cmd_select_continue(struct client_command_context *cmd)
        }
 
        ret = imap_fetch_deinit(ctx->fetch_ctx);
+       if (ret < 0) {
+               client_send_storage_error(ctx->cmd,
+                                         mailbox_get_storage(ctx->box));
+       }
        cmd_select_finish(ctx, ret);
        return TRUE;
 }
@@ -264,9 +267,11 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
 
        if (readonly)
                open_flags |= MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT;
-       ctx->box = mailbox_open(&ctx->storage, mailbox, NULL, open_flags);
-       if (ctx->box == NULL)
+       ctx->box = mailbox_open(ctx->ns->list, mailbox, NULL, open_flags);
+       if (ctx->box == NULL) {
+               client_send_list_error(ctx->cmd, ctx->ns->list);
                return -1;
+       }
 
        if (client->enabled_features != 0)
                mailbox_enable(ctx->box, client->enabled_features);
@@ -274,8 +279,11 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
                         STATUS_MESSAGES | STATUS_RECENT |
                         STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
                         STATUS_UIDNEXT | STATUS_KEYWORDS |
-                        STATUS_HIGHESTMODSEQ, &status) < 0)
+                        STATUS_HIGHESTMODSEQ, &status) < 0) {
+               client_send_storage_error(ctx->cmd,
+                                         mailbox_get_storage(ctx->box));
                return -1;
+       }
 
        client->mailbox = ctx->box;
        client->select_counter++;
@@ -317,8 +325,11 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly)
        }
 
        if (ctx->qresync_uid_validity == status.uidvalidity) {
-               if (select_qresync(ctx) < 0)
+               if (select_qresync(ctx) < 0) {
+                       client_send_storage_error(ctx->cmd,
+                               mailbox_get_storage(ctx->box));
                        return -1;
+               }
        }
        return 0;
 }
@@ -344,8 +355,8 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
 
        ctx = p_new(cmd->pool, struct imap_select_context, 1);
        ctx->cmd = cmd;
-       ctx->storage = client_find_storage(cmd, &mailbox);
-       if (ctx->storage == NULL)
+       ctx->ns = client_find_namespace(cmd, &mailbox);
+       if (ctx->ns == NULL)
                return TRUE;
 
        if (args[1].type == IMAP_ARG_LIST) {
index 68dad356e4e7fa385e9fe943c8e4f8c426560eb0..1af4764a279a5ecdbb13edaae57af9fb3132cc78 100644 (file)
@@ -12,8 +12,8 @@ bool cmd_status(struct client_command_context *cmd)
        const struct imap_arg *args;
        struct mailbox_status status;
        enum mailbox_status_items items;
-       struct mail_storage *storage;
-       const char *mailbox, *real_mailbox;
+       struct mail_namespace *ns;
+       const char *mailbox, *real_mailbox, *error;
        bool selected_mailbox;
 
        /* <mailbox> <status items> */
@@ -31,14 +31,15 @@ bool cmd_status(struct client_command_context *cmd)
                                    &items) < 0)
                return TRUE;
 
-       storage = client_find_storage(cmd, &real_mailbox);
-       if (storage == NULL)
+       ns = client_find_namespace(cmd, &real_mailbox);
+       if (ns == NULL)
                return TRUE;
 
        selected_mailbox = client->mailbox != NULL &&
-               mailbox_equals(client->mailbox, storage, real_mailbox);
-       if (!imap_status_get(client, storage, real_mailbox, items, &status)) {
-               client_send_storage_error(cmd, storage);
+               mailbox_equals(client->mailbox, ns, real_mailbox);
+       if (imap_status_get(client, ns, real_mailbox, items,
+                           &status, &error) < 0) {
+               client_send_tagline(cmd, error);
                return TRUE;
        }
 
index 85639092c4b6911417449fe33880e67e04b4ab37..c920d3b16ea2146106e044f0f0065b2eec735e43 100644 (file)
@@ -29,7 +29,6 @@ static bool have_listable_namespace_prefix(struct mail_namespace *ns,
 bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
 {
        struct mail_namespace *ns, *real_ns;
-       struct mail_storage *storage;
        const char *mailbox, *verify_name, *real_name;
 
        /* <mailbox> */
@@ -38,8 +37,8 @@ bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
        verify_name = mailbox;
 
        real_name = mailbox;
-       storage = client_find_storage(cmd, &real_name);
-       if (storage == NULL)
+       real_ns = client_find_namespace(cmd, &real_name);
+       if (real_ns == NULL)
                return TRUE;
 
        /* now find a namespace where the subscription can be added to */
@@ -50,7 +49,6 @@ bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
                return TRUE;
        }
 
-       real_ns = mail_storage_get_namespace(storage);
        if (ns != real_ns) {
                /* subscription is being written to a different namespace
                   than where the mailbox exists. */
@@ -62,7 +60,7 @@ bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
 
        if ((cmd->client->workarounds & WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
            *mailbox != '\0' && mailbox[strlen(mailbox)-1] ==
-           mail_storage_get_hierarchy_sep(ns->storage)) {
+           mailbox_list_get_hierarchy_sep(ns->list)) {
                /* verify the validity without the trailing '/' */
                verify_name = t_strndup(verify_name, strlen(verify_name)-1);
        }
index d1b4e5ce54a623d3388a347abf4597a238ef54d8..73b8c3c22729c6d05c5b866ac0f5e568a8a4eac0 100644 (file)
@@ -34,7 +34,6 @@ struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
                             const struct imap_settings *set)
 {
        struct client *client;
-       struct mail_namespace *ns;
        const char *ident;
 
        /* always use nonblocking I/O */
@@ -60,10 +59,8 @@ struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
                pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*12);
        client->user = user;
 
-       for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-               mail_storage_set_callbacks(ns->storage,
-                                          &mail_storage_callbacks, client);
-       }
+       mail_namespaces_set_storage_callbacks(user->namespaces,
+                                             &mail_storage_callbacks, client);
 
        client->capability_string =
                str_new(default_pool, sizeof(CAPABILITY_STRING)+32);
index 23d0f53cc1e18e89c1df21bf122c0bba71ab0326..53d77bc5177f848e139af342ae7112152760d369 100644 (file)
@@ -32,21 +32,11 @@ client_find_namespace(struct client_command_context *cmd, const char **mailbox)
        return NULL;
 }
 
-struct mail_storage *
-client_find_storage(struct client_command_context *cmd, const char **mailbox)
-{
-       struct mail_namespace *ns;
-
-       ns = client_find_namespace(cmd, mailbox);
-       return ns == NULL ? NULL : ns->storage;
-}
-
 bool client_verify_mailbox_name(struct client_command_context *cmd,
                                const char *mailbox,
                                bool should_exist, bool should_not_exist)
 {
        struct mail_namespace *ns;
-       struct mailbox_list *list;
        enum mailbox_name_status mailbox_status;
        const char *orig_mailbox, *p;
 
@@ -90,10 +80,9 @@ bool client_verify_mailbox_name(struct client_command_context *cmd,
        }
 
        /* check what our storage thinks of it */
-       list = mail_storage_get_list(ns->storage);
-       if (mailbox_list_get_mailbox_name_status(list, mailbox,
+       if (mailbox_list_get_mailbox_name_status(ns->list, mailbox,
                                                 &mailbox_status) < 0) {
-               client_send_list_error(cmd, list);
+               client_send_list_error(cmd, ns->list);
                return FALSE;
        }
 
@@ -144,8 +133,8 @@ bool client_verify_open_mailbox(struct client_command_context *cmd)
        }
 }
 
-static const char *
-get_error_string(const char *error_string, enum mail_error error)
+const char *
+imap_get_error_string(const char *error_string, enum mail_error error)
 {
        const char *resp_code = NULL;
 
@@ -191,7 +180,7 @@ void client_send_list_error(struct client_command_context *cmd,
        enum mail_error error;
 
        error_string = mailbox_list_get_last_error(list, &error);
-       client_send_tagline(cmd, get_error_string(error_string, error));
+       client_send_tagline(cmd, imap_get_error_string(error_string, error));
 }
 
 void client_send_storage_error(struct client_command_context *cmd,
@@ -209,7 +198,7 @@ void client_send_storage_error(struct client_command_context *cmd,
        }
 
        error_string = mail_storage_get_last_error(storage, &error);
-       client_send_tagline(cmd, get_error_string(error_string, error));
+       client_send_tagline(cmd, imap_get_error_string(error_string, error));
 }
 
 void client_send_untagged_storage_error(struct client *client,
@@ -363,12 +352,12 @@ client_get_keyword_names(struct client *client, ARRAY_TYPE(keywords) *dest,
 }
 
 bool mailbox_equals(const struct mailbox *box1,
-                   const struct mail_storage *storage2, const char *name2)
+                   const struct mail_namespace *ns2, const char *name2)
 {
-       struct mail_storage *storage1 = mailbox_get_storage(box1);
+       struct mail_namespace *ns1 = mailbox_get_namespace(box1);
        const char *name1;
 
-       if (storage1 != storage2)
+       if (ns1 != ns2)
                return FALSE;
 
         name1 = mailbox_get_name(box1);
index d8830eecd84f80a45302aab1b039f353817c38cc..07205b8c62f3c1a524ad54b209d913a29f54acfe 100644 (file)
@@ -13,10 +13,6 @@ struct mailbox_keywords;
    sends "Unknown namespace" error message to client. */
 struct mail_namespace *
 client_find_namespace(struct client_command_context *cmd, const char **mailbox);
-/* Finds mail storage for given mailbox from namespaces. If not found,
-   sends "Unknown namespace" error message to client. */
-struct mail_storage *
-client_find_storage(struct client_command_context *cmd, const char **mailbox);
 
 /* If should_exist is TRUE, this function returns TRUE if the mailbox
    exists. If it doesn't exist but would be a valid mailbox name, the
@@ -32,6 +28,9 @@ bool client_verify_mailbox_name(struct client_command_context *cmd,
    error message to client. */
 bool client_verify_open_mailbox(struct client_command_context *cmd);
 
+const char *
+imap_get_error_string(const char *error_string, enum mail_error error);
+
 /* Send last mailbox list error message to client. */
 void client_send_list_error(struct client_command_context *cmd,
                            struct mailbox_list *list);
@@ -62,7 +61,7 @@ client_get_keyword_names(struct client *client, ARRAY_TYPE(keywords) *dest,
                         const ARRAY_TYPE(keyword_indexes) *src);
 
 bool mailbox_equals(const struct mailbox *box1,
-                   const struct mail_storage *storage2,
+                   const struct mail_namespace *ns2,
                    const char *name2) ATTR_PURE;
 
 void msgset_generator_init(struct msgset_generator_context *ctx, string_t *str);
index e53202c09d87d269b216f0a91f14869fdb4cfc10..5b38686d89b4d645fce6f0075f1678cf78d264de 100644 (file)
@@ -4,6 +4,7 @@
 struct client_command_context;
 
 #include "mail-storage.h"
+#include "mail-namespace.h"
 #include "imap-parser.h"
 #include "imap-sync.h"
 #include "imap-commands-util.h"
index 275ead45cde5552994fd5f6cf448ec9aab93edb6..76c6d9f03e0129fe1d07fe0350453b74e967640d 100644 (file)
@@ -46,25 +46,29 @@ int imap_status_parse_items(struct client_command_context *cmd,
        return 0;
 }
 
-bool imap_status_get(struct client *client, struct mail_storage *storage,
-                    const char *mailbox, enum mailbox_status_items items,
-                    struct mailbox_status *status_r)
+int imap_status_get(struct client *client, struct mail_namespace *ns,
+                   const char *mailbox, enum mailbox_status_items items,
+                   struct mailbox_status *status_r, const char **error_r)
 {
        struct mailbox *box;
+       enum mail_error error;
        int ret;
 
        if (client->mailbox != NULL &&
-           mailbox_equals(client->mailbox, storage, mailbox)) {
+           mailbox_equals(client->mailbox, ns, mailbox)) {
                /* this mailbox is selected */
                mailbox_get_status(client->mailbox, items, status_r);
                return TRUE;
        }
 
        /* open the mailbox */
-       box = mailbox_open(&storage, mailbox, NULL, MAILBOX_OPEN_FAST |
+       box = mailbox_open(ns->list, mailbox, NULL, MAILBOX_OPEN_FAST |
                           MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
-       if (box == NULL)
-               return FALSE;
+       if (box == NULL) {
+               *error_r = mailbox_list_get_last_error(ns->list, &error);
+               *error_r = imap_get_error_string(*error_r, error);
+               return -1;
+       }
 
        if ((items & STATUS_HIGHESTMODSEQ) != 0)
                client_enable(client, MAILBOX_FEATURE_CONDSTORE);
@@ -72,8 +76,13 @@ bool imap_status_get(struct client *client, struct mail_storage *storage,
                mailbox_enable(box, client->enabled_features);
 
        ret = mailbox_sync(box, 0, items, status_r);
+       if (ret < 0) {
+               struct mail_storage *storage = mailbox_get_storage(box);
+               *error_r = mail_storage_get_last_error(storage, &error);
+               *error_r = imap_get_error_string(*error_r, error);
+       }
        mailbox_close(&box);
-       return ret == 0;
+       return ret;
 }
 
 void imap_status_send(struct client *client, const char *mailbox,
index 162d277337ad9c7816caa9dd7aaa485c8d49c4dc..dcb7b0b5940401d76438ebc4083f09f47a65e2f3 100644 (file)
@@ -4,9 +4,9 @@
 int imap_status_parse_items(struct client_command_context *cmd,
                            const struct imap_arg *args,
                            enum mailbox_status_items *items_r);
-bool imap_status_get(struct client *client, struct mail_storage *storage,
-                    const char *mailbox, enum mailbox_status_items items,
-                    struct mailbox_status *status_r);
+int imap_status_get(struct client *client, struct mail_namespace *ns,
+                   const char *mailbox, enum mailbox_status_items items,
+                   struct mailbox_status *status_r, const char **error_r);
 void imap_status_send(struct client *client, const char *mailbox,
                      enum mailbox_status_items items,
                      const struct mailbox_status *status);
index 7f021fcaf90f02a48cb837599d8b1ebc0b3b4ef2..43c076d1d3b59664bdfe680eecd836b174650d45 100644 (file)
@@ -416,21 +416,21 @@ int main(int argc, char *argv[])
                i_fatal("Couldn't create internal raw storage: %s", errstr);
        if (path == NULL) {
                input = create_raw_stream(&ctx, 0, &mtime);
-               box = mailbox_open(&raw_ns->storage, "Dovecot Delivery Mail",
+               box = mailbox_open(raw_ns->list, "Dovecot Delivery Mail",
                                   input, MAILBOX_OPEN_NO_INDEX_FILES);
                i_stream_unref(&input);
        } else {
                mtime = (time_t)-1;
-               box = mailbox_open(&raw_ns->storage, path, NULL,
+               box = mailbox_open(raw_ns->list, path, NULL,
                                   MAILBOX_OPEN_NO_INDEX_FILES);
        }
        if (box == NULL) {
                i_fatal("Can't open delivery mail as raw: %s",
-                       mail_storage_get_last_error(raw_ns->storage, &error));
+                       mailbox_list_get_last_error(raw_ns->list, &error));
        }
        if (mailbox_sync(box, 0, 0, NULL) < 0) {
                i_fatal("Can't sync delivery mail: %s",
-                       mail_storage_get_last_error(raw_ns->storage, &error));
+                       mail_storage_get_last_error(box->storage, &error));
        }
        raw_box = (struct raw_mailbox *)box;
        raw_box->envelope_sender = ctx.src_envelope_sender != NULL ?
index 74bcb6f8e9d0cb526b956412382718285f6d169b..66c6d26228a7fae3f012d4c6ba7b17d3c72bc195 100644 (file)
@@ -72,28 +72,28 @@ void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...)
 
 static struct mailbox *
 mailbox_open_or_create_synced(struct mail_deliver_context *ctx, 
-                             struct mail_storage **storage_r,
-                             const char *name)
+                             const char *name, struct mail_namespace **ns_r,
+                             const char **error_r)
 {
        struct mail_namespace *ns;
+       struct mail_storage *storage;
        struct mailbox *box;
        enum mail_error error;
        enum mailbox_open_flags open_flags =
                MAILBOX_OPEN_KEEP_RECENT | MAILBOX_OPEN_SAVEONLY |
                MAILBOX_OPEN_POST_SESSION;
 
+       *error_r = NULL;
+
        if (strcasecmp(name, "INBOX") == 0) {
                /* deliveries to INBOX must always succeed,
                   regardless of ACLs */
                open_flags |= MAILBOX_OPEN_IGNORE_ACLS;
        }
 
-       ns = mail_namespace_find(ctx->dest_user->namespaces, &name);
-       if (ns == NULL) {
-               *storage_r = NULL;
+       *ns_r = ns = mail_namespace_find(ctx->dest_user->namespaces, &name);
+       if (*ns_r == NULL)
                return NULL;
-       }
-       *storage_r = ns->storage;
 
        if (*name == '\0') {
                /* delivering to a namespace prefix means we actually want to
@@ -101,29 +101,36 @@ mailbox_open_or_create_synced(struct mail_deliver_context *ctx,
                return NULL;
        }
 
-       box = mailbox_open(storage_r, name, NULL, open_flags);
-       if (box != NULL || !ctx->set->lda_mailbox_autocreate)
+       box = mailbox_open(ns->list, name, NULL, open_flags);
+       if (box != NULL)
                return box;
 
-       (void)mail_storage_get_last_error(*storage_r, &error);
-       if (error != MAIL_ERROR_NOTFOUND)
+       *error_r = mailbox_list_get_last_error(ns->list, &error);
+       if (!ctx->set->lda_mailbox_autocreate || error != MAIL_ERROR_NOTFOUND)
                return NULL;
 
        /* try creating it. */
-       if (mail_storage_mailbox_create(*storage_r, name, FALSE) < 0)
+       storage = mail_namespace_get_default_storage(ns);
+       if (mail_storage_mailbox_create(storage, ns, name, FALSE) < 0) {
+               *error_r = mail_storage_get_last_error(storage, &error);
                return NULL;
+       }
        if (ctx->set->lda_mailbox_autosubscribe) {
                /* (try to) subscribe to it */
                (void)mailbox_list_set_subscribed(ns->list, name, TRUE);
        }
 
        /* and try opening again */
-       box = mailbox_open(storage_r, name, NULL, open_flags);
-       if (box == NULL)
+       box = mailbox_open(ns->list, name, NULL, open_flags);
+       if (box == NULL) {
+               *error_r = mailbox_list_get_last_error(ns->list, &error);
                return NULL;
+       }
 
        if (mailbox_sync(box, 0, 0, NULL) < 0) {
                mailbox_close(&box);
+               *error_r = mail_storage_get_last_error(mailbox_get_storage(box),
+                                                      &error);
                return NULL;
        }
        return box;
@@ -140,7 +147,7 @@ int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
        struct mail_save_context *save_ctx;
        struct mail_keywords *kw;
        enum mail_error error;
-       const char *mailbox_name;
+       const char *mailbox_name, *errstr;
        uint32_t uid_validity, uid1 = 0, uid2 = 0;
        bool default_save;
        int ret = 0;
@@ -150,23 +157,23 @@ int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
                ctx->tried_default_save = TRUE;
 
        mailbox_name = str_sanitize(mailbox, 80);
-       box = mailbox_open_or_create_synced(ctx, storage_r, mailbox);
+       box = mailbox_open_or_create_synced(ctx, mailbox, &ns, &errstr);
        if (box == NULL) {
-               if (*storage_r == NULL) {
+               if (ns == NULL) {
                        mail_deliver_log(ctx,
                                         "save failed to %s: Unknown namespace",
                                         mailbox_name);
                        return -1;
                }
-               ns = mail_storage_get_namespace(*storage_r);
                if (default_save && strcmp(ns->prefix, mailbox) == 0) {
                        /* silently store to the INBOX instead */
                        return -1;
                }
-               mail_deliver_log(ctx, "save failed to %s: %s", mailbox_name,
-                                mail_storage_get_last_error(*storage_r, &error));
+               mail_deliver_log(ctx, "save failed to %s: %s",
+                                mailbox_name, errstr);
                return -1;
        }
+       *storage_r = mailbox_get_storage(box);
 
        trans_flags = MAILBOX_TRANSACTION_FLAG_EXTERNAL;
        if (ctx->save_dest_mail)
@@ -205,7 +212,7 @@ int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
                }
        } else {
                mail_deliver_log(ctx, "save failed to %s: %s", mailbox_name,
-                                mail_storage_get_last_error(*storage_r, &error));
+                       mail_storage_get_last_error(*storage_r, &error));
        }
 
        if (ctx->dest_mail == NULL)
index 62aa3250786cdfff02f1b7a88355208d3de75550..42ab9771c6e46df6f958478e21ee0881bb03fbf0 100644 (file)
@@ -13,7 +13,7 @@ static const char *cydir_mail_get_path(struct mail *mail)
 {
        const char *dir;
 
-       dir = mailbox_list_get_path(mail->box->storage->list, mail->box->name,
+       dir = mailbox_list_get_path(mail->box->list, mail->box->name,
                                    MAILBOX_LIST_PATH_TYPE_MAILBOX);
        return t_strdup_printf("%s/%u.", dir, mail->uid);
 }
index 0528815b644d31ef0cfae3aad4b0ccf109d8ef83..4826dafc2949f2c3e15e1206891645b6d626a612 100644 (file)
@@ -49,7 +49,7 @@ cydir_get_save_path(struct cydir_save_context *ctx, unsigned int num)
 {
        const char *dir;
 
-       dir = mailbox_list_get_path(ctx->mbox->storage->storage.list,
+       dir = mailbox_list_get_path(ctx->mbox->ibox.box.list,
                                    ctx->mbox->ibox.box.name,
                                    MAILBOX_LIST_PATH_TYPE_MAILBOX);
        return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num);
@@ -253,7 +253,7 @@ int cydir_transaction_save_commit_pre(struct cydir_save_context *ctx)
        *t->ictx.first_saved_uid = uid;
        *t->ictx.last_saved_uid = next_uid - 1;
 
-       dir = mailbox_list_get_path(ctx->mbox->storage->storage.list,
+       dir = mailbox_list_get_path(ctx->mbox->ibox.box.list,
                                    ctx->mbox->ibox.box.name,
                                    MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
index 70569cf422901e5358268d0ac642f000f06498f4..6b4b74f99f69ebb7d532fe219ab7cb33035f54b9 100644 (file)
 #include <dirent.h>
 #include <sys/stat.h>
 
-#define CREATE_MODE 0770 /* umask() should limit it more */
-
 #define CYDIR_LIST_CONTEXT(obj) \
        MODULE_CONTEXT(obj, cydir_mailbox_list_module)
 
+struct cydir_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+};
+
 extern struct mail_storage cydir_storage;
 extern struct mailbox cydir_mailbox;
 
 static MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static int
-cydir_list_delete_mailbox(struct mailbox_list *list, const char *name);
-static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                                     const char *dir, const char *fname,
-                                     const char *mailbox_name,
-                                     enum mailbox_list_file_type type,
-                                     enum mailbox_info_flags *flags);
+static void cydir_list_init(struct mailbox_list *list);
 
-static int
-cydir_get_list_settings(struct mailbox_list_settings *list_set,
-                       const char *data, struct mail_storage *storage,
-                       const char **layout_r, const char **error_r)
-{
-       *layout_r = "fs";
-
-       memset(list_set, 0, sizeof(*list_set));
-       list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
-       list_set->maildir_name = "";
-
-       if (data == NULL || *data == '\0' || *data == ':') {
-               /* we won't do any guessing for this format. */
-               if (storage->set->mail_debug)
-                       i_info("cydir: mailbox location not given");
-               *error_r = "Root mail directory not given";
-               return -1;
-       }
-
-       if (storage->set->mail_debug)
-               i_info("cydir: data=%s", data);
-       return mailbox_list_settings_parse(data, list_set, storage->ns,
-                                          layout_r, NULL, error_r);
-}
-
-static struct mail_storage *cydir_alloc(void)
+static struct mail_storage *cydir_storage_alloc(void)
 {
        struct cydir_storage *storage;
        pool_t pool;
@@ -66,73 +37,35 @@ static struct mail_storage *cydir_alloc(void)
        storage = p_new(pool, struct cydir_storage, 1);
        storage->storage = cydir_storage;
        storage->storage.pool = pool;
-       storage->storage.storage_class = &cydir_storage;
-
        return &storage->storage;
 }
 
-static int cydir_create(struct mail_storage *_storage, const char *data,
-                       const char **error_r)
+static int
+cydir_storage_create(struct mail_storage *_storage ATTR_UNUSED,
+                    struct mail_namespace *ns,
+                    const char **error_r ATTR_UNUSED)
 {
-       struct cydir_storage *storage = (struct cydir_storage *)_storage;
-       struct mailbox_list_settings list_set;
-       struct stat st;
-       const char *layout;
-
-       if (cydir_get_list_settings(&list_set, data, _storage,
-                                   &layout, error_r) < 0)
-               return -1;
-       list_set.mail_storage_flags = &_storage->flags;
-       list_set.lock_method = &_storage->lock_method;
-
-       if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
-               if (stat(list_set.root_dir, &st) < 0) {
-                       if (errno == ENOENT) {
-                               *error_r = t_strdup_printf(
-                                       "Root mail directory doesn't exist: %s",
-                                       list_set.root_dir);
-                       } else if (errno == EACCES) {
-                               *error_r = mail_error_eacces_msg("stat",
-                                                       list_set.root_dir);
-                       } else {
-                               *error_r = t_strdup_printf(
-                                                       "stat(%s) failed: %m",
-                                                       list_set.root_dir);
-                       }
-                       return -1;
-               }
-       } else if (mkdir_parents(list_set.root_dir,
-                                CREATE_MODE) == 0 || errno == EEXIST) {
-       } else if (errno == EACCES) {
-               *error_r = mail_error_create_eacces_msg("mkdir",
-                                                       list_set.root_dir);
-               return -1;
-       } else {
-               *error_r = t_strdup_printf("mkdir(%s) failed: %m",
-                                          list_set.root_dir);
-               return -1;
-       }
-
-       if (mailbox_list_alloc(layout, &_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;
-
-       MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
-                               storage, &storage->list_module_ctx);
-
-       /* finish list init after we've overridden vfuncs */
-       mailbox_list_init(_storage->list, _storage->ns, &list_set, 0);
+       cydir_list_init(ns->list);
        return 0;
 }
 
-static int create_cydir(struct mail_storage *storage, const char *path)
+static void
+cydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
+                               struct mailbox_list_settings *set)
+{
+       if (set->layout == NULL)
+               set->layout = MAILBOX_LIST_NAME_FS;
+       if (set->subscription_fname == NULL)
+               set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
+}
+
+static int create_cydir(struct mail_storage *storage, struct mail_namespace *ns,
+                       const char *path)
 {
        mode_t mode;
        gid_t gid;
 
-       mailbox_list_get_dir_permissions(storage->list, NULL, &mode, &gid);
+       mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid);
        if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 &&
            errno != EEXIST) {
                if (!mail_storage_set_error_from_errno(storage)) {
@@ -145,18 +78,17 @@ static int create_cydir(struct mail_storage *storage, const char *path)
 }
 
 static struct mailbox *
-cydir_open(struct cydir_storage *storage, const char *name,
-          enum mailbox_open_flags flags)
+cydir_open(struct mail_storage *storage, struct mailbox_list *list,
+          const char *name, enum mailbox_open_flags flags)
 {
-       struct mail_storage *_storage = &storage->storage;
        struct cydir_mailbox *mbox;
        struct mail_index *index;
        const char *path;
        pool_t pool;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
+       index = index_storage_alloc(list, name, flags, CYDIR_INDEX_PREFIX);
        mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
                                   MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
@@ -164,11 +96,11 @@ cydir_open(struct cydir_storage *storage, const char *name,
        mbox = p_new(pool, struct cydir_mailbox, 1);
        mbox->ibox.box = cydir_mailbox;
        mbox->ibox.box.pool = pool;
-       mbox->ibox.storage = &storage->storage;
+       mbox->ibox.box.storage = storage;
        mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
        mbox->ibox.index = index;
 
-       mbox->storage = storage;
+       mbox->storage = (struct cydir_storage *)storage;
        mbox->path = p_strdup(pool, path);
 
        index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
@@ -176,58 +108,61 @@ cydir_open(struct cydir_storage *storage, const char *name,
 }
 
 static struct mailbox *
-cydir_mailbox_open(struct mail_storage *_storage, const char *name,
-                  struct istream *input, enum mailbox_open_flags flags)
+cydir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                  const char *name, struct istream *input,
+                  enum mailbox_open_flags flags)
 {
-       struct cydir_storage *storage = (struct cydir_storage *)_storage;
        const char *path;
        struct stat st;
 
        if (input != NULL) {
-               mail_storage_set_critical(_storage,
+               mailbox_list_set_critical(list,
                        "cydir doesn't support streamed mailboxes");
                return NULL;
        }
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(path, &st) == 0)
-               return cydir_open(storage, name, flags);
+               return cydir_open(storage, list, name, flags);
        else if (errno == ENOENT) {
                if (strcmp(name, "INBOX") == 0) {
                        /* INBOX always exists, create it */
-                       if (create_cydir(_storage, path) < 0)
+                       if (create_cydir(storage, list->ns, path) < 0) {
+                               mailbox_list_set_error_from_storage(list,
+                                                                   storage);
                                return NULL;
-                       return cydir_open(storage, "INBOX", flags);
+                       }
+                       return cydir_open(storage, list, "INBOX", flags);
                }
-               mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+               mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
        } else if (errno == EACCES) {
-               mail_storage_set_critical(_storage, "%s",
+               mail_storage_set_critical(storage, "%s",
                        mail_error_eacces_msg("stat", path));
        } else {
-               mail_storage_set_critical(_storage, "stat(%s) failed: %m",
+               mail_storage_set_critical(storage, "stat(%s) failed: %m",
                                          path);
        }
        return NULL;
 }
 
-static int cydir_mailbox_create(struct mail_storage *_storage,
-                               const char *name,
-                               bool directory ATTR_UNUSED)
+static int
+cydir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
+                    const char *name, bool directory ATTR_UNUSED)
 {
        const char *path;
        struct stat st;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(path, &st) == 0) {
-               mail_storage_set_error(_storage, MAIL_ERROR_EXISTS,
+               mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
                                       "Mailbox already exists");
                return -1;
        }
 
-       return create_cydir(_storage, path);
+       return create_cydir(storage, list->ns, path);
 }
 
 static int
@@ -302,7 +237,7 @@ cydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
 static int
 cydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
 {
-       struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
+       struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
        struct stat st;
        const char *src;
 
@@ -313,7 +248,7 @@ cydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
        index_storage_destroy_unrefed();
 
        /* delete the index and control directories */
-       if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
+       if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
                return -1;
 
        /* check if the mailbox actually exists */
@@ -401,6 +336,19 @@ static void cydir_class_deinit(void)
        cydir_transaction_class_deinit();
 }
 
+static void cydir_list_init(struct mailbox_list *list)
+{
+       struct cydir_mailbox_list *mlist;
+
+       mlist = p_new(list->pool, struct cydir_mailbox_list, 1);
+       mlist->module_ctx.super = list->v;
+
+       list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
+       list->v.delete_mailbox = cydir_list_delete_mailbox;
+
+       MODULE_CONTEXT_SET(list, cydir_mailbox_list_module, mlist);
+}
+
 struct mail_storage cydir_storage = {
        MEMBER(name) CYDIR_STORAGE_NAME,
        MEMBER(mailbox_is_file) FALSE,
@@ -409,9 +357,10 @@ struct mail_storage cydir_storage = {
                NULL,
                cydir_class_init,
                cydir_class_deinit,
-               cydir_alloc,
-               cydir_create,
+               cydir_storage_alloc,
+               cydir_storage_create,
                index_storage_destroy,
+               cydir_storage_get_list_settings,
                NULL,
                cydir_mailbox_open,
                cydir_mailbox_create,
@@ -422,6 +371,7 @@ struct mail_storage cydir_storage = {
 struct mailbox cydir_mailbox = {
        MEMBER(name) NULL, 
        MEMBER(storage) NULL, 
+       MEMBER(list) NULL,
 
        {
                index_storage_is_readonly,
index c4f069ef97764ce7a15a411abd0955142ea2977c..c2d00c2a1c16897179fe19815ffabbd1ac6cddca 100644 (file)
@@ -21,8 +21,7 @@ static string_t *cydir_get_path_prefix(struct cydir_mailbox *mbox)
        string_t *path = str_new(default_pool, 256);
        const char *dir;
 
-       dir = mailbox_list_get_path(mbox->storage->storage.list,
-                                   mbox->ibox.box.name,
+       dir = mailbox_list_get_path(mbox->ibox.box.list, mbox->ibox.box.name,
                                    MAILBOX_LIST_PATH_TYPE_MAILBOX);
        str_append(path, dir);
        str_append_c(path, '/');
index 15450d8460c7401a59be1cb615c88a0058699f48..2990dbbbda6f7a1ab022e997339077b37d4ea65f 100644 (file)
@@ -69,13 +69,9 @@ void dbox_map_deinit(struct dbox_map **_map)
 
 static int dbox_map_mkdir_storage(struct dbox_storage *storage)
 {
-       mode_t mode;
-       gid_t gid;
-
-       mailbox_list_get_dir_permissions(storage->storage.list, NULL,
-                                        &mode, &gid);
-       if (mkdir_parents_chown(storage->storage_dir, mode,
-                               (uid_t)-1, gid) < 0 && errno != EEXIST) {
+       if (mkdir_parents_chown(storage->storage_dir, storage->create_mode,
+                               (uid_t)-1, storage->create_gid) < 0 &&
+           errno != EEXIST) {
                mail_storage_set_critical(&storage->storage,
                        "mkdir(%s) failed: %m", storage->storage_dir);
                return -1;
@@ -101,7 +97,8 @@ int dbox_map_open(struct dbox_map *map, bool create_missing)
                if (dbox_map_mkdir_storage(map->storage) < 0)
                        return -1;
        }
-       ret = mail_index_open(map->index, open_flags, storage->lock_method);
+       ret = mail_index_open(map->index, open_flags,
+                             storage->set->parsed_lock_method);
        if (ret < 0) {
                mail_storage_set_internal_error(storage);
                mail_index_reset_error(map->index);
index 64e8bedc87b91195ab7e78a7ce9d66784508b451..fc63775c964af037dcbdc002f8377d484e8f2ec4 100644 (file)
@@ -11,6 +11,9 @@
 #define DEF(type, name) \
        { type, #name, offsetof(struct dbox_settings, name), NULL }
 
+static bool dbox_settings_verify(void *_set, pool_t pool ATTR_UNUSED,
+                                const char **error_r);
+
 static struct setting_define dbox_setting_defines[] = {
        DEF(SET_UINT, dbox_rotate_size),
        DEF(SET_UINT, dbox_rotate_min_size),
@@ -38,9 +41,24 @@ static struct setting_parser_info dbox_setting_parser_info = {
 
        MEMBER(parent_offset) (size_t)-1,
        MEMBER(type_offset) (size_t)-1,
-       MEMBER(struct_size) sizeof(struct dbox_settings)
+       MEMBER(struct_size) sizeof(struct dbox_settings),
+       MEMBER(check_func) dbox_settings_verify
 };
 
+/* <settings checks> */
+static bool dbox_settings_verify(void *_set, pool_t pool ATTR_UNUSED,
+                                const char **error_r)
+{
+       const struct dbox_settings *set = _set;
+
+       if (set->dbox_max_open_files < 2) {
+               *error_r = "dbox_max_open_files must be at least 2";
+               return FALSE;
+       }
+       return TRUE;
+}
+/* </settings checks> */
+
 const struct setting_parser_info *dbox_get_setting_parser_info(void)
 {
        return &dbox_setting_parser_info;
index 2e6c13e93160a4df397382627dec2ffee71b8c25..b33e6e007c7e2e4877d31b0eef57709351ad6ff4 100644 (file)
@@ -46,6 +46,7 @@ struct dbox_storage_rebuild_context {
        uint32_t prev_file_id;
        uint32_t highest_seen_map_uid;
 
+       struct mailbox_list *default_list;
        struct mail_index_sync_ctx *sync_ctx;
        struct mail_index_view *sync_view;
        struct mail_index_transaction *trans;
@@ -385,7 +386,8 @@ rebuild_mailbox_multi(struct dbox_storage_rebuild_context *ctx,
 }
 
 static int
-rebuild_mailbox(struct dbox_storage_rebuild_context *ctx, const char *name)
+rebuild_mailbox(struct dbox_storage_rebuild_context *ctx,
+               struct mail_namespace *ns, const char *name)
 {
        struct mailbox *box;
        struct dbox_mailbox *mbox;
@@ -396,12 +398,12 @@ rebuild_mailbox(struct dbox_storage_rebuild_context *ctx, const char *name)
        enum mail_error error;
        int ret;
 
-       box = dbox_mailbox_open(&ctx->storage->storage, name, NULL,
+       box = dbox_mailbox_open(&ctx->storage->storage, ns->list, name, NULL,
                                MAILBOX_OPEN_READONLY |
                                MAILBOX_OPEN_KEEP_RECENT |
                                MAILBOX_OPEN_IGNORE_ACLS);
        if (box == NULL) {
-               mail_storage_get_last_error(&ctx->storage->storage, &error);
+               mailbox_list_get_last_error(ns->list, &error);
                if (error == MAIL_ERROR_TEMP)
                        return -1;
                /* non-temporary error, ignore */
@@ -433,19 +435,24 @@ rebuild_mailbox(struct dbox_storage_rebuild_context *ctx, const char *name)
        return ret < 0 ? -1 : 0;
 }
 
-static int rebuild_mailboxes(struct dbox_storage_rebuild_context *ctx)
+static int rebuild_namespace_mailboxes(struct dbox_storage_rebuild_context *ctx,
+                                      struct mail_namespace *ns)
 {
        struct mailbox_list_iterate_context *iter;
        const struct mailbox_info *info;
        int ret = 0;
 
-       iter = mailbox_list_iter_init(ctx->storage->storage.list, "*",
+       if (ctx->default_list == NULL ||
+           (ns->flags & NAMESPACE_FLAG_INBOX) != 0)
+               ctx->default_list = ns->list;
+
+       iter = mailbox_list_iter_init(ns->list, "*",
                                      MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        while ((info = mailbox_list_iter_next(iter)) != NULL) {
                if ((info->flags & (MAILBOX_NONEXISTENT |
                                    MAILBOX_NOSELECT)) == 0) {
                        T_BEGIN {
-                               ret = rebuild_mailbox(ctx, info->name);
+                               ret = rebuild_mailbox(ctx, ns, info->name);
                        } T_END;
                        if (ret < 0) {
                                ret = -1;
@@ -458,6 +465,28 @@ static int rebuild_mailboxes(struct dbox_storage_rebuild_context *ctx)
        return ret;
 }
 
+static int rebuild_mailboxes(struct dbox_storage_rebuild_context *ctx)
+{
+       struct mail_user *user = ctx->storage->storage.user;
+       struct mail_namespace *ns;
+       const char *rebuild_dir, *ns_dir;
+
+       rebuild_dir = ctx->storage->storage_dir;
+       for (ns = user->namespaces; ns != NULL; ns = ns->next) {
+               if (strcmp(ns->storage->name, "dbox") != 0)
+                       continue;
+
+               ns_dir = mailbox_list_get_path(ns->list, NULL,
+                                              MAILBOX_LIST_PATH_TYPE_DIR);
+               if (strcmp(ns_dir, rebuild_dir) != 0)
+                       continue;
+
+               if (rebuild_namespace_mailboxes(ctx, ns) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
 static int rebuild_msg_mailbox_commit(struct rebuild_msg_mailbox *msg)
 {
        if (mail_index_sync_commit(&msg->sync_ctx) < 0)
@@ -511,7 +540,8 @@ static int rebuild_restore_msg(struct dbox_storage_rebuild_context *ctx,
                strcmp(mailbox, ctx->prev_msg.box->name) == 0 ?
                ctx->prev_msg.box : NULL;
        while (box == NULL) {
-               box = dbox_mailbox_open(storage, mailbox, NULL,
+               box = dbox_mailbox_open(storage, ctx->default_list,
+                                       mailbox, NULL,
                                        MAILBOX_OPEN_READONLY |
                                        MAILBOX_OPEN_KEEP_RECENT |
                                        MAILBOX_OPEN_IGNORE_ACLS);
@@ -526,8 +556,8 @@ static int rebuild_restore_msg(struct dbox_storage_rebuild_context *ctx,
                        /* mailbox doesn't exist currently? see if creating
                           it helps. */
                        created = TRUE;
-                       (void)mail_storage_mailbox_create(storage, mailbox,
-                                                         FALSE);
+                       (void)mail_storage_mailbox_create(storage,
+                               ctx->default_list->ns, mailbox, FALSE);
                } else if (strcmp(mailbox, "INBOX") != 0) {
                        /* see if we can save to INBOX instead. */
                        mailbox = "INBOX";
index 0d0c6b626b0d90276777b024eacaa9022352d72f..c07310031e41882bc091a505f49a6aa975e142ab 100644 (file)
 #include <dirent.h>
 #include <sys/stat.h>
 
-#define CREATE_MODE 0770 /* umask() should limit it more */
-
 #define DBOX_LIST_CONTEXT(obj) \
        MODULE_CONTEXT(obj, dbox_mailbox_list_module)
 
+struct dbox_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+       const struct dbox_settings *set;
+};
+
 extern struct mail_storage dbox_storage;
 extern struct mailbox dbox_mailbox;
 
 static MODULE_CONTEXT_DEFINE_INIT(dbox_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static int
-dbox_list_delete_mailbox(struct mailbox_list *list, const char *name);
-static int
-dbox_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
-                        struct mailbox_list *newlist, const char *newname,
-                        bool rename_children);
-static int
-dbox_list_rename_mailbox_pre(struct mailbox_list *oldlist,
-                            const char *oldname,
-                            struct mailbox_list *newlist,
-                            const char *newname);
-static int dbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                                    const char *dir, const char *fname,
-                                    const char *mailbox_name,
-                                    enum mailbox_list_file_type type,
-                                    enum mailbox_info_flags *flags);
+static void dbox_list_init(struct mailbox_list *list,
+                          const struct dbox_settings *set);
 
-static int
-dbox_get_list_settings(struct mailbox_list_settings *list_set,
-                      const char *data, struct mail_storage *storage,
-                      const char **layout_r, const char **alt_dir_r,
-                      const char **error_r)
-{
-       *layout_r = "fs";
-
-       memset(list_set, 0, sizeof(*list_set));
-       list_set->subscription_fname = DBOX_SUBSCRIPTION_FILE_NAME;
-       list_set->maildir_name = DBOX_MAILDIR_NAME;
-       list_set->mailbox_dir_name = DBOX_MAILBOX_DIR_NAME;
-
-       if (data == NULL || *data == '\0' || *data == ':') {
-               /* we won't do any guessing for this format. */
-               if (storage->set->mail_debug)
-                       i_info("dbox: mailbox location not given");
-               *error_r = "Root mail directory not given";
-               return -1;
-       }
-
-       if (storage->set->mail_debug)
-               i_info("dbox: data=%s", data);
-       if (mailbox_list_settings_parse(data, list_set, storage->ns,
-                                       layout_r, alt_dir_r, error_r) < 0)
-               return -1;
-
-       if (*list_set->mailbox_dir_name == '\0') {
-               *error_r = "dbox: MAILBOXDIR must not be empty";
-               return -1;
-       }
-       return 0;
-}
-
-static struct mail_storage *dbox_alloc(void)
+static struct mail_storage *dbox_storage_alloc(void)
 {
        struct dbox_storage *storage;
        pool_t pool;
@@ -96,96 +51,42 @@ static struct mail_storage *dbox_alloc(void)
        storage = p_new(pool, struct dbox_storage, 1);
        storage->storage = dbox_storage;
        storage->storage.pool = pool;
-       storage->storage.storage_class = &dbox_storage;
-
        return &storage->storage;
 }
 
-static int dbox_create(struct mail_storage *_storage, const char *data,
-                      const char **error_r)
+static int
+dbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
+                   const char **error_r)
 {
        struct dbox_storage *storage = (struct dbox_storage *)_storage;
-       struct mailbox_list_settings list_set;
-       struct stat st;
-       const char *layout, *alt_dir, *dir;
-
-       if (dbox_get_list_settings(&list_set, data, _storage,
-                                  &layout, &alt_dir, error_r) < 0)
-               return -1;
-       list_set.mail_storage_flags = &_storage->flags;
-       list_set.lock_method = &_storage->lock_method;
-
-       if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
-               if (stat(list_set.root_dir, &st) < 0) {
-                       if (errno == ENOENT) {
-                               *error_r = t_strdup_printf(
-                                       "Root mail directory doesn't exist: %s",
-                                       list_set.root_dir);
-                       } else if (errno == EACCES) {
-                               *error_r = mail_error_eacces_msg("stat",
-                                                       list_set.root_dir);
-                       } else {
-                               *error_r = t_strdup_printf(
-                                                       "stat(%s) failed: %m",
-                                                       list_set.root_dir);
-                       }
-                       return -1;
-               }
-       } else if (mkdir_parents(list_set.root_dir,
-                                CREATE_MODE) == 0 || errno == EEXIST) {
-       } else if (errno == EACCES) {
-               if (_storage->ns->type != NAMESPACE_SHARED) {
-                       *error_r = mail_error_create_eacces_msg("mkdir",
-                                                       list_set.root_dir);
-                       return -1;
-               }
-               /* can't create a new user, but we don't want to fail
-                  the storage creation. */
-       } else {
-               *error_r = t_strdup_printf("mkdir(%s) failed: %m",
-                                          list_set.root_dir);
-               return -1;
-       }
+       const char *dir;
 
        storage->set = mail_storage_get_driver_settings(_storage);
-       if (storage->set->dbox_max_open_files <= 1) {
-               /* we store file offsets in a 32bit integer. */
-               *error_r = "dbox_max_open_files must be at least 2";
-               return -1;
-       }
+       i_assert(storage->set->dbox_max_open_files >= 2);
 
-       if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
+       if (*ns->list->set.mailbox_dir_name == '\0') {
+               *error_r = "dbox: MAILBOXDIR must not be empty";
                return -1;
-       storage->list_module_ctx.super = _storage->list->v;
-       storage->alt_dir = p_strdup(_storage->pool, alt_dir);
-       _storage->list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
-       _storage->list->v.delete_mailbox = dbox_list_delete_mailbox;
-       _storage->list->v.rename_mailbox = dbox_list_rename_mailbox;
-       _storage->list->v.rename_mailbox_pre = dbox_list_rename_mailbox_pre;
-
-       MODULE_CONTEXT_SET_FULL(_storage->list, dbox_mailbox_list_module,
-                               storage, &storage->list_module_ctx);
+       }
 
-       /* finish list init after we've overridden vfuncs */
-       mailbox_list_init(_storage->list, _storage->ns, &list_set, 0);
+       dbox_list_init(ns->list, storage->set);
 
-       dir = mailbox_list_get_path(storage->storage.list, NULL,
-                                   MAILBOX_LIST_PATH_TYPE_DIR);
+       dir = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
        storage->storage_dir = p_strconcat(_storage->pool, dir,
                                           "/"DBOX_GLOBAL_DIR_NAME, NULL);
-       storage->alt_storage_dir = p_strconcat(_storage->pool, alt_dir,
+       storage->alt_storage_dir = p_strconcat(_storage->pool,
+                                              ns->list->set.alt_dir,
                                               "/"DBOX_GLOBAL_DIR_NAME, NULL);
        i_array_init(&storage->open_files,
                     I_MIN(storage->set->dbox_max_open_files, 128));
 
        storage->map = dbox_map_init(storage);
-       mailbox_list_get_permissions(storage->storage.list, NULL,
-                                    &storage->create_mode,
+       mailbox_list_get_permissions(ns->list, NULL, &storage->create_mode,
                                     &storage->create_gid);
        return 0;
 }
 
-static void dbox_destroy(struct mail_storage *_storage)
+static void dbox_storage_destroy(struct mail_storage *_storage)
 {
        struct dbox_storage *storage = (struct dbox_storage *)_storage;
 
@@ -200,9 +101,24 @@ static void dbox_destroy(struct mail_storage *_storage)
        index_storage_destroy(_storage);
 }
 
+static void
+dbox_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
+                              struct mailbox_list_settings *set)
+{
+       if (set->layout == NULL)
+               set->layout = MAILBOX_LIST_NAME_FS;
+       if (set->subscription_fname == NULL)
+               set->subscription_fname = DBOX_SUBSCRIPTION_FILE_NAME;
+       if (set->maildir_name == NULL)
+               set->maildir_name = DBOX_MAILDIR_NAME;
+       if (set->mailbox_dir_name == NULL)
+               set->mailbox_dir_name = DBOX_MAILBOX_DIR_NAME;
+}
+
 static const char *
-dbox_get_alt_path(struct dbox_storage *storage, const char *path)
+dbox_get_alt_path(struct mailbox_list *list, const char *path)
 {
+#if 0 // FIXME
        const char *root;
        unsigned int len;
 
@@ -218,11 +134,13 @@ dbox_get_alt_path(struct dbox_storage *storage, const char *path)
                return NULL;
        }
        return t_strconcat(storage->alt_dir, path + len, NULL);
+#endif
+       return NULL;
 }
 
 static struct mailbox *
-dbox_open(struct dbox_storage *storage, const char *name,
-         enum mailbox_open_flags flags)
+dbox_open(struct dbox_storage *storage, struct mailbox_list *list,
+         const char *name, enum mailbox_open_flags flags)
 {
        struct mail_storage *_storage = &storage->storage;
        struct dbox_mailbox *mbox;
@@ -232,10 +150,10 @@ dbox_open(struct dbox_storage *storage, const char *name,
        pool_t pool;
        int ret;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
-       index = index_storage_alloc(_storage, name, flags, DBOX_INDEX_PREFIX);
+       index = index_storage_alloc(list, name, flags, DBOX_INDEX_PREFIX);
        mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
                                   MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
@@ -243,13 +161,13 @@ dbox_open(struct dbox_storage *storage, const char *name,
        mbox = p_new(pool, struct dbox_mailbox, 1);
        mbox->ibox.box = dbox_mailbox;
        mbox->ibox.box.pool = pool;
-       mbox->ibox.storage = &storage->storage;
+       mbox->ibox.box.storage = _storage;
        mbox->ibox.mail_vfuncs = &dbox_mail_vfuncs;
        mbox->ibox.index = index;
        mbox->ibox.keep_index_backups = TRUE;
        mbox->ibox.index_never_in_memory = TRUE;
        mbox->path = p_strdup(pool, path);
-       mbox->alt_path = p_strdup(pool, dbox_get_alt_path(storage, path));
+       mbox->alt_path = p_strdup(pool, dbox_get_alt_path(list, path));
        mbox->storage = storage;
 
        mbox->dbox_ext_id =
@@ -271,11 +189,11 @@ dbox_open(struct dbox_storage *storage, const char *name,
        return box;
 }
 
-uint32_t dbox_get_uidvalidity_next(struct mail_storage *storage)
+uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list)
 {
        const char *path;
 
-       path = mailbox_list_get_path(storage->list, NULL,
+       path = mailbox_list_get_path(list, NULL,
                                     MAILBOX_LIST_PATH_TYPE_CONTROL);
        path = t_strconcat(path, "/"DBOX_UIDVALIDITY_FILE_NAME, NULL);
        return mailbox_uidvalidity_next(path);
@@ -296,7 +214,7 @@ static void dbox_write_index_header(struct mailbox *box)
                                     &hdr, sizeof(hdr));
 
        /* set uidvalidity */
-       uid_validity = dbox_get_uidvalidity_next(&mbox->storage->storage);
+       uid_validity = dbox_get_uidvalidity_next(box->list);
        mail_index_update_header(trans,
                offsetof(struct mail_index_header, uid_validity),
                &uid_validity, sizeof(uid_validity), TRUE);
@@ -304,19 +222,19 @@ static void dbox_write_index_header(struct mailbox *box)
        (void)mail_index_transaction_commit(&trans);
 }
 
-static int create_dbox(struct mail_storage *_storage, const char *path,
-                      const char *name, bool directory)
+static int create_dbox(struct mail_storage *_storage, struct mailbox_list *list,
+                      const char *path, const char *name, bool directory)
 {
        struct dbox_storage *storage = (struct dbox_storage *)_storage;
        struct mailbox *box;
        mode_t mode;
        gid_t gid;
 
-       mailbox_list_get_dir_permissions(_storage->list, NULL, &mode, &gid);
+       mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
        if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) == 0) {
                if (!directory) {
                        /* create indexes immediately with the dbox header */
-                       box = dbox_open(storage, name,
+                       box = dbox_open(storage, list, name,
                                        MAILBOX_OPEN_KEEP_RECENT);
                        if (box == NULL)
                                return -1;
@@ -335,7 +253,7 @@ static int create_dbox(struct mail_storage *_storage, const char *path,
 }
 
 static bool
-dbox_cleanup_if_exists(struct mail_storage *storage, const char *path)
+dbox_cleanup_if_exists(struct mailbox_list *list, const char *path)
 {
        struct stat st;
 
@@ -349,7 +267,7 @@ dbox_cleanup_if_exists(struct mail_storage *storage, const char *path)
        } else if (st.st_atime < ioloop_time - DBOX_TMP_SCAN_SECS) {
                /* time to scan */
                const char *prefix =
-                       mailbox_list_get_global_temp_prefix(storage->list);
+                       mailbox_list_get_global_temp_prefix(list);
 
                (void)unlink_old_files(path, prefix,
                                       ioloop_time - DBOX_TMP_DELETE_SECS);
@@ -358,39 +276,42 @@ dbox_cleanup_if_exists(struct mail_storage *storage, const char *path)
 }
 
 struct mailbox *
-dbox_mailbox_open(struct mail_storage *_storage, const char *name,
-                 struct istream *input, enum mailbox_open_flags flags)
+dbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
+                 const char *name, struct istream *input,
+                 enum mailbox_open_flags flags)
 {
        struct dbox_storage *storage = (struct dbox_storage *)_storage;
        const char *path;
 
        if (input != NULL) {
-               mail_storage_set_critical(_storage,
+               mailbox_list_set_critical(list,
                        "dbox doesn't support streamed mailboxes");
                return NULL;
        }
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       if (dbox_cleanup_if_exists(_storage, path)) {
-               return dbox_open(storage, name, flags);
+       if (dbox_cleanup_if_exists(list, path)) {
+               return dbox_open(storage, list, name, flags);
        } else if (errno == ENOENT) {
                if (strcmp(name, "INBOX") == 0 &&
-                   (_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+                   (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
                        /* INBOX always exists, create it */
-                       if (create_dbox(_storage, path, "INBOX", FALSE) < 0)
+                       if (create_dbox(_storage, list, path, name, FALSE) < 0) {
+                               mailbox_list_set_error_from_storage(list,
+                                                                   _storage);
                                return NULL;
-                       return dbox_open(storage, name, flags);
+                       }
+                       return dbox_open(storage, list, name, flags);
                }
 
-               mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+               mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
        } else if (errno == EACCES) {
-               mail_storage_set_critical(_storage, "%s",
+               mailbox_list_set_critical(list, "%s",
                        mail_error_eacces_msg("stat", path));
        } else {
-               mail_storage_set_critical(_storage, "stat(%s) failed: %m",
-                                         path);
+               mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
        }
        return NULL;
 }
@@ -403,18 +324,18 @@ static int dbox_storage_mailbox_close(struct mailbox *box)
        return index_storage_mailbox_close(box);
 }
 
-static int dbox_mailbox_create(struct mail_storage *_storage,
-                              const char *name, bool directory)
+static int
+dbox_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
+                   const char *name, bool directory)
 {
-       struct dbox_storage *storage = (struct dbox_storage *)_storage;
        const char *path, *alt_path;
        struct stat st;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     directory ? MAILBOX_LIST_PATH_TYPE_DIR :
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(path, &st) == 0) {
-               mail_storage_set_error(_storage, MAIL_ERROR_EXISTS,
+               mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
                                       "Mailbox already exists");
                return -1;
        }
@@ -423,20 +344,20 @@ static int dbox_mailbox_create(struct mail_storage *_storage,
           race conditions with RENAME/DELETE), but if something crashed and
           left it lying around we don't want to start overwriting files in
           it. */
-       alt_path = directory ? NULL : dbox_get_alt_path(storage, path);
+       alt_path = directory ? NULL : dbox_get_alt_path(list, path);
        if (alt_path != NULL && stat(alt_path, &st) == 0) {
-               mail_storage_set_error(_storage, MAIL_ERROR_EXISTS,
+               mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
                                       "Mailbox already exists");
                return -1;
        }
 
-       return create_dbox(_storage, path, name, directory);
+       return create_dbox(storage, list, path, name, directory);
 }
 
 static int
-dbox_mailbox_unref_mails(struct dbox_storage *storage, const char *path)
+dbox_mailbox_unref_mails(struct mailbox_list *list, const char *path)
 {
-       struct mailbox_list *list = storage->storage.list;
+       struct dbox_storage *storage = (struct dbox_storage *)list->ns->storage;
        const struct mail_storage_settings *old_set;
        struct mail_storage_settings tmp_set;
        struct mailbox *box;
@@ -454,7 +375,7 @@ dbox_mailbox_unref_mails(struct dbox_storage *storage, const char *path)
        tmp_set = *list->mail_set;
        tmp_set.mail_full_filesystem_access = TRUE;
        list->mail_set = &tmp_set;
-       box = dbox_open(storage, path, MAILBOX_OPEN_IGNORE_ACLS |
+       box = dbox_open(storage, list, path, MAILBOX_OPEN_IGNORE_ACLS |
                        MAILBOX_OPEN_KEEP_RECENT);
        list->mail_set = old_set;
        if (box == NULL)
@@ -504,7 +425,7 @@ static const char *dbox_get_trash_dest(const char *trash_dir)
 static int
 dbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
 {
-       struct dbox_storage *storage = DBOX_LIST_CONTEXT(list);
+       struct dbox_mailbox_list *mlist = DBOX_LIST_CONTEXT(list);
        struct stat st;
        const char *path, *alt_path, *trash_dir, *trash_dest;
        bool deleted = FALSE;
@@ -517,7 +438,7 @@ dbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
        index_storage_destroy_unrefed();
 
        /* delete the index and control directories */
-       if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
+       if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
                return -1;
 
        path = mailbox_list_get_path(list, name,
@@ -545,7 +466,7 @@ dbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
                ret = rename(path, trash_dest);
        }
        if (ret == 0) {
-               if (dbox_mailbox_unref_mails(storage, trash_dest) < 0) {
+               if (dbox_mailbox_unref_mails(list, trash_dest) < 0) {
                        /* we've already renamed it. there's no going back. */
                        mailbox_list_set_internal_error(list);
                        ret = -1;
@@ -556,7 +477,7 @@ dbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
                        ret = -1;
                }
                /* if there's an alt path, delete it too */
-               alt_path = dbox_get_alt_path(storage, path);
+               alt_path = dbox_get_alt_path(list, path);
                if (alt_path != NULL) {
                        if (unlink_directory(alt_path, TRUE) < 0) {
                                mailbox_list_set_critical(list,
@@ -589,7 +510,7 @@ dbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
                ret = 0;
        }
 
-       alt_path = dbox_get_alt_path(storage, path);
+       alt_path = dbox_get_alt_path(list, path);
        if (alt_path != NULL)
                (void)rmdir(alt_path);
 
@@ -616,17 +537,15 @@ dbox_list_rename_get_alt_paths(struct mailbox_list *oldlist,
                               enum mailbox_list_path_type path_type,
                               const char **oldpath_r, const char **newpath_r)
 {
-       struct dbox_storage *oldstorage = DBOX_LIST_CONTEXT(oldlist);
-       struct dbox_storage *newstorage = DBOX_LIST_CONTEXT(newlist);
        const char *path;
 
        path = mailbox_list_get_path(oldlist, oldname, path_type);
-       *oldpath_r = dbox_get_alt_path(oldstorage, path);
+       *oldpath_r = dbox_get_alt_path(oldlist, path);
        if (*oldpath_r == NULL)
                return 0;
 
        path = mailbox_list_get_path(newlist, newname, path_type);
-       *newpath_r = dbox_get_alt_path(newstorage, path);
+       *newpath_r = dbox_get_alt_path(newlist, path);
        if (*newpath_r == NULL) {
                /* destination dbox storage doesn't have alt-path defined.
                   we can't do the rename easily. */
@@ -672,14 +591,15 @@ dbox_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
                         struct mailbox_list *newlist, const char *newname,
                         bool rename_children)
 {
-       struct dbox_storage *oldstorage = DBOX_LIST_CONTEXT(oldlist);
+       struct dbox_mailbox_list *oldmlist = DBOX_LIST_CONTEXT(oldlist);
        enum mailbox_list_path_type path_type;
        const char *alt_oldpath, *alt_newpath, *path;
        int ret;
 
-       if (oldstorage->list_module_ctx.super.
-                       rename_mailbox(oldlist, oldname, newlist, newname,
-                                      rename_children) < 0)
+       ret = oldmlist->module_ctx.super.
+               rename_mailbox(oldlist, oldname, newlist, newname,
+                              rename_children);
+       if (ret < 0)
                return -1;
 
        path_type = rename_children ? MAILBOX_LIST_PATH_TYPE_DIR :
@@ -800,6 +720,23 @@ static void dbox_class_deinit(void)
        dbox_transaction_class_deinit();
 }
 
+static void dbox_list_init(struct mailbox_list *list,
+                          const struct dbox_settings *set)
+{
+       struct dbox_mailbox_list *mlist;
+
+       mlist = p_new(list->pool, struct dbox_mailbox_list, 1);
+       mlist->module_ctx.super = list->v;
+       mlist->set = set;
+
+       list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
+       list->v.delete_mailbox = dbox_list_delete_mailbox;
+       list->v.rename_mailbox = dbox_list_rename_mailbox;
+       list->v.rename_mailbox_pre = dbox_list_rename_mailbox_pre;
+
+       MODULE_CONTEXT_SET(list, dbox_mailbox_list_module, mlist);
+}
+
 struct mail_storage dbox_storage = {
        MEMBER(name) DBOX_STORAGE_NAME,
        MEMBER(mailbox_is_file) FALSE,
@@ -808,9 +745,10 @@ struct mail_storage dbox_storage = {
                 dbox_get_setting_parser_info,
                dbox_class_init,
                dbox_class_deinit,
-               dbox_alloc,
-               dbox_create,
-               dbox_destroy,
+               dbox_storage_alloc,
+               dbox_storage_create,
+               dbox_storage_destroy,
+               dbox_storage_get_list_settings,
                NULL,
                dbox_mailbox_open,
                dbox_mailbox_create,
@@ -821,6 +759,7 @@ struct mail_storage dbox_storage = {
 struct mailbox dbox_mailbox = {
        MEMBER(name) NULL, 
        MEMBER(storage) NULL, 
+       MEMBER(list) NULL,
 
        {
                index_storage_is_readonly,
index 3b3a9707b88fff15eac1d983806ef6700c4ccfdc..9471910cd2d4697089d373fdee3a6776f5a2e47a 100644 (file)
@@ -90,8 +90,9 @@ void dbox_transaction_class_init(void);
 void dbox_transaction_class_deinit(void);
 
 struct mailbox *
-dbox_mailbox_open(struct mail_storage *storage, const char *name,
-                 struct istream *input, enum mailbox_open_flags flags);
+dbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
+                 const char *name, struct istream *input,
+                 enum mailbox_open_flags flags);
 
 struct mail *
 dbox_mail_alloc(struct mailbox_transaction_context *t,
@@ -101,7 +102,7 @@ dbox_mail_alloc(struct mailbox_transaction_context *t,
 /* Get map_uid for wanted message. */
 int dbox_mail_lookup(struct dbox_mailbox *mbox, struct mail_index_view *view,
                     uint32_t seq, uint32_t *map_uid_r);
-uint32_t dbox_get_uidvalidity_next(struct mail_storage *storage);
+uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list);
 
 struct mail_save_context *
 dbox_save_alloc(struct mailbox_transaction_context *_t);
index 63897882b03136a8547860fbefb2f6f2971a1c9e..6e66dfa7dea654b224a025e75e46857430bc1f2e 100644 (file)
@@ -36,13 +36,13 @@ struct dbox_sync_rebuild_context {
 
 static void dbox_sync_set_uidvalidity(struct dbox_sync_rebuild_context *ctx)
 {
-       struct mail_storage *storage = &ctx->mbox->storage->storage;
+       struct mailbox *box = &ctx->mbox->ibox.box;
        uint32_t uid_validity;
 
        /* if uidvalidity is set in the old index, use it */
        uid_validity = mail_index_get_header(ctx->view)->uid_validity;
        if (uid_validity == 0)
-               uid_validity = dbox_get_uidvalidity_next(storage);
+               uid_validity = dbox_get_uidvalidity_next(box->list);
 
        mail_index_update_header(ctx->trans,
                offsetof(struct mail_index_header, uid_validity),
@@ -389,7 +389,7 @@ dbox_sync_index_rebuild_init(struct dbox_mailbox *mbox,
        mail_index_ext_lookup(mbox->ibox.index, "cache", &ctx->cache_ext_id);
 
        /* if backup index file exists, try to use it */
-       index_dir = mailbox_list_get_path(box->storage->list, box->name,
+       index_dir = mailbox_list_get_path(box->list, box->name,
                                          MAILBOX_LIST_PATH_TYPE_INDEX);
        ctx->backup_index =
                mail_index_alloc(index_dir, DBOX_INDEX_PREFIX".backup");
@@ -399,7 +399,7 @@ dbox_sync_index_rebuild_init(struct dbox_mailbox *mbox,
 #endif
                open_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE;
        if (mail_index_open(ctx->backup_index, open_flags,
-                           box->storage->lock_method) <= 0)
+                           box->storage->set->parsed_lock_method) <= 0)
                mail_index_free(&ctx->backup_index);
        else
                ctx->backup_view = mail_index_view_open(ctx->backup_index);
index ba7340e86d2091cb56bf2159a57367d1486a4e33..678cebbf32657073165820c6c069d0e6b9e64991 100644 (file)
@@ -8,6 +8,7 @@
 #include "mkdir-parents.h"
 #include "mail-index-private.h"
 #include "mail-index-modseq.h"
+#include "mailbox-list-private.h"
 #include "index-storage.h"
 #include "index-mail.h"
 #include "index-thread-private.h"
@@ -64,39 +65,39 @@ static void index_list_free(struct index_list *list)
        i_free(list);
 }
 
-static int create_index_dir(struct mail_storage *storage, const char *name)
+static int create_index_dir(struct mailbox_list *list, const char *name)
 {
        const char *root_dir, *index_dir, *p, *parent_dir;
        mode_t mode, parent_mode;
        gid_t gid, parent_gid;
        int n = 0;
 
-       root_dir = mailbox_list_get_path(storage->list, name,
+       root_dir = mailbox_list_get_path(list, name,
                                         MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       index_dir = mailbox_list_get_path(storage->list, name,
+       index_dir = mailbox_list_get_path(list, name,
                                          MAILBOX_LIST_PATH_TYPE_INDEX);
        if (strcmp(index_dir, root_dir) == 0 || *index_dir == '\0')
                return 0;
 
-       mailbox_list_get_dir_permissions(storage->list, name, &mode, &gid);
+       mailbox_list_get_dir_permissions(list, name, &mode, &gid);
        while (mkdir_chown(index_dir, mode, (uid_t)-1, gid) < 0) {
                if (errno == EEXIST)
                        break;
 
                p = strrchr(index_dir, '/');
                if (errno != ENOENT || p == NULL || ++n == 2) {
-                       mail_storage_set_critical(storage,
+                       mailbox_list_set_critical(list,
                                "mkdir(%s) failed: %m", index_dir);
                        return -1;
                }
                /* create the parent directory first */
-               mailbox_list_get_dir_permissions(storage->list, NULL,
+               mailbox_list_get_dir_permissions(list, NULL,
                                                 &parent_mode, &parent_gid);
                parent_dir = t_strdup_until(index_dir, p);
                if (mkdir_parents_chown(parent_dir, parent_mode,
                                        (uid_t)-1, parent_gid) < 0 &&
                    errno != EEXIST) {
-                       mail_storage_set_critical(storage,
+                       mailbox_list_set_critical(list,
                                "mkdir(%s) failed: %m", parent_dir);
                        return -1;
                }
@@ -105,14 +106,13 @@ static int create_index_dir(struct mail_storage *storage, const char *name)
 }
 
 static const char *
-get_index_dir(struct mail_storage *storage, const char *name,
+get_index_dir(struct mailbox_list *list, const char *name,
              enum mailbox_open_flags flags, struct stat *st_r)
 {
        const char *index_dir;
 
        index_dir = (flags & MAILBOX_OPEN_NO_INDEX_FILES) != 0 ? "" :
-               mailbox_list_get_path(storage->list, name,
-                                     MAILBOX_LIST_PATH_TYPE_INDEX);
+               mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
        if (*index_dir == '\0') {
                /* disabled */
                return NULL;
@@ -121,18 +121,18 @@ get_index_dir(struct mail_storage *storage, const char *name,
        if (stat(index_dir, st_r) < 0) {
                if (errno == ENOENT) {
                        /* try to create it */
-                       if (create_index_dir(storage, name) < 0)
+                       if (create_index_dir(list, name) < 0)
                                return NULL;
                        if (stat(index_dir, st_r) == 0)
                                return index_dir;
                }
                if (errno == EACCES) {
-                       mail_storage_set_critical(storage, "%s",
+                       mailbox_list_set_critical(list, "%s",
                                mail_error_eacces_msg("stat", index_dir));
                        return NULL;
                }
 
-               mail_storage_set_critical(storage, "stat(%s) failed: %m",
+               mailbox_list_set_critical(list, "stat(%s) failed: %m",
                                          index_dir);
                return NULL;
        }
@@ -140,18 +140,18 @@ get_index_dir(struct mail_storage *storage, const char *name,
 }
 
 struct mail_index *
-index_storage_alloc(struct mail_storage *storage, const char *name,
+index_storage_alloc(struct mailbox_list *list, const char *name,
                    enum mailbox_open_flags flags, const char *prefix)
 {
-       struct index_list **list, *rec;
+       struct index_list **indexp, *rec;
        struct mail_index *index;
        struct stat st, st2;
        const char *index_dir, *mailbox_path;
        int destroy_count;
 
-       mailbox_path = mailbox_list_get_path(storage->list, name,
+       mailbox_path = mailbox_list_get_path(list, name,
                                             MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       index_dir = get_index_dir(storage, name, flags, &st);
+       index_dir = get_index_dir(list, name, flags, &st);
 
        if (index_dir == NULL)
                memset(&st, 0, sizeof(st));
@@ -159,8 +159,8 @@ index_storage_alloc(struct mail_storage *storage, const char *name,
        /* compare index_dir inodes so we don't break even with symlinks.
           for in-memory indexes compare just mailbox paths */
        destroy_count = 0; index = NULL;
-       for (list = &indexes; *list != NULL;) {
-               rec = *list;
+       for (indexp = &indexes; *indexp != NULL;) {
+               rec = *indexp;
 
                if (index_dir != NULL) {
                        if (index == NULL && st.st_ino == rec->index_dir_ino &&
@@ -188,7 +188,7 @@ index_storage_alloc(struct mail_storage *storage, const char *name,
                if (rec->refcount == 0) {
                        if (rec->destroy_time <= ioloop_time ||
                            destroy_count >= INDEX_CACHE_MAX) {
-                               *list = rec->next;
+                               *indexp = rec->next;
                                index_list_free(rec);
                                continue;
                        } else {
@@ -196,7 +196,7 @@ index_storage_alloc(struct mail_storage *storage, const char *name,
                        }
                }
 
-                list = &(*list)->next;
+                indexp = &(*indexp)->next;
        }
 
        if (index == NULL) {
@@ -367,7 +367,8 @@ void index_storage_lock_notify_reset(struct index_mailbox *ibox)
 
 int index_storage_mailbox_open(struct index_mailbox *ibox)
 {
-       struct mail_storage *storage = ibox->storage;
+       struct mail_storage *storage = ibox->box.storage;
+       enum file_lock_method lock_method = storage->set->parsed_lock_method;
        enum mail_index_open_flags index_flags;
        int ret;
 
@@ -381,7 +382,7 @@ int index_storage_mailbox_open(struct index_mailbox *ibox)
        if (ibox->index_never_in_memory)
                index_flags |= MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY;
 
-       ret = mail_index_open(ibox->index, index_flags, storage->lock_method);
+       ret = mail_index_open(ibox->index, index_flags, lock_method);
        if (ret <= 0 || ibox->move_to_memory) {
                if (ibox->index_never_in_memory) {
                        mail_storage_set_index_error(ibox);
@@ -393,7 +394,7 @@ int index_storage_mailbox_open(struct index_mailbox *ibox)
                           directly into memory now. */
                        if (mail_index_open_or_create(ibox->index,
                                                      index_flags,
-                                                     storage->lock_method) < 0)
+                                                     lock_method) < 0)
                                i_panic("in-memory index creation failed");
                }
        }
@@ -418,7 +419,7 @@ int index_storage_mailbox_init(struct index_mailbox *ibox, const char *name,
                               enum mailbox_open_flags flags,
                               bool move_to_memory)
 {
-       struct mail_storage *storage = ibox->storage;
+       struct mail_storage *storage = ibox->box.storage;
        struct mailbox *box = &ibox->box;
        gid_t dir_gid;
 
@@ -428,10 +429,10 @@ int index_storage_mailbox_init(struct index_mailbox *ibox, const char *name,
        box->name = p_strdup(box->pool, name);
        box->open_flags = flags;
        if (box->file_create_mode == 0) {
-               mailbox_list_get_permissions(box->storage->list, name,
+               mailbox_list_get_permissions(box->list, name,
                                             &box->file_create_mode,
                                             &box->file_create_gid);
-               mailbox_list_get_dir_permissions(box->storage->list, name,
+               mailbox_list_get_dir_permissions(box->list, name,
                                                 &box->dir_create_mode,
                                                 &dir_gid);
                mail_index_set_permissions(ibox->index, box->file_create_mode,
index 756249db3e4378c6fe20bd66d268f687f316c0cc..3e19b803a27fecce8aa10a99f9daf1ffc6470633 100644 (file)
@@ -20,8 +20,6 @@ struct index_mailbox {
        struct mailbox box;
        union mail_index_view_module_context view_module_ctx;
 
-       struct mail_storage *storage;
-
        struct mail_index *index;
        struct mail_index_view *view;
        struct mail_cache *cache;
@@ -88,7 +86,7 @@ void index_storage_lock_notify(struct index_mailbox *ibox,
 void index_storage_lock_notify_reset(struct index_mailbox *ibox);
 
 struct mail_index *
-index_storage_alloc(struct mail_storage *storage, const char *name,
+index_storage_alloc(struct mailbox_list *list, const char *name,
                    enum mailbox_open_flags flags, const char *prefix);
 void index_storage_unref(struct mail_index *index);
 void index_storage_destroy_unrefed(void);
index 09c89ba6270e3134c9c4f8e61338339d27408940..71698a9968b2cb786820cd379374e1d395982486 100644 (file)
@@ -65,7 +65,8 @@ maildir_keywords_init_readonly(struct mailbox *box)
        struct maildir_keywords *mk;
        const char *dir;
 
-       dir = mail_storage_get_mailbox_control_dir(box->storage, box->name);
+       dir = mailbox_list_get_path(box->list, box->name,
+                                   MAILBOX_LIST_PATH_TYPE_CONTROL);
 
        mk = i_new(struct maildir_keywords, 1);
        mk->storage = box->storage;
@@ -82,7 +83,7 @@ maildir_keywords_init_readonly(struct mailbox *box)
        mk->dotlock_settings.timeout = KEYWORDS_LOCK_STALE_TIMEOUT + 2;
        mk->dotlock_settings.stale_timeout = KEYWORDS_LOCK_STALE_TIMEOUT;
        mk->dotlock_settings.temp_prefix =
-               mailbox_list_get_temp_prefix(box->storage->list);
+               mailbox_list_get_temp_prefix(box->list);
        return mk;
 }
 
index 711f445dd21c2882264630a0e3d7cc31aec90528..442bd63411ad497077423d5b1c0a0f6fdeb7b44b 100644 (file)
 #include <unistd.h>
 #include <sys/stat.h>
 
-#define MAILDIR_PLUSPLUS_DRIVER_NAME "maildir++"
 #define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
 
 #define MAILDIR_LIST_CONTEXT(obj) \
        MODULE_CONTEXT(obj, maildir_mailbox_list_module)
 
+struct maildir_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+       const struct maildir_settings *set;
+};
+
 struct rename_context {
        bool found;
        size_t oldnamelen;
@@ -40,89 +44,8 @@ static MODULE_CONTEXT_DEFINE_INIT(maildir_mailbox_list_module,
                                  &mailbox_list_module_register);
 static const char *maildir_subdirs[] = { "cur", "new", "tmp" };
 
-static int
-maildir_list_delete_mailbox(struct mailbox_list *list, const char *name);
-static int
-maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
-                           struct mailbox_list *newlist, const char *newname,
-                           bool rename_children);
-static int
-maildir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                            const char *dir, const char *fname,
-                            const char *mailbox_name,
-                            enum mailbox_list_file_type type,
-                            enum mailbox_info_flags *flags_r);
-static int
-maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                               const char *dir, const char *fname,
-                               const char *mailbox_name,
-                               enum mailbox_list_file_type type,
-                               enum mailbox_info_flags *flags_r);
-
-static int
-maildir_get_list_settings(struct mailbox_list_settings *list_set,
-                         const char *data, struct mail_storage *storage,
-                         const char **layout_r, const char **error_r)
-{
-       struct mail_user *user = storage->ns->user;
-       bool debug = storage->set->mail_debug;
-       const char *path, *home;
-
-       *layout_r = MAILDIR_PLUSPLUS_DRIVER_NAME;
-
-       memset(list_set, 0, sizeof(*list_set));
-       list_set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
-       list_set->maildir_name = "";
-
-       if (data == NULL || *data == '\0') {
-               if ((storage->flags &
-                    MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0) {
-                       *error_r = "Root mail directory not given";
-                       return -1;
-               }
-
-               /* we'll need to figure out the maildir location ourself.
-                  It's ~/Maildir unless we are chrooted. */
-               if (mail_user_get_home(user, &home) > 0) {
-                       path = t_strconcat(home, "/Maildir", NULL);
-                       if (access(path, R_OK|W_OK|X_OK) == 0) {
-                               if (debug) {
-                                       i_info("maildir: root exists (%s)",
-                                              path);
-                               }
-                               list_set->root_dir = path;
-                       } else {
-                               if (debug) {
-                                       i_info("maildir: access(%s, rwx): "
-                                              "failed: %m", path);
-                               }
-                       }
-               } else {
-                       if (debug)
-                               i_info("maildir: Home directory not set");
-               }
-
-               if (access("/cur", R_OK|W_OK|X_OK) == 0) {
-                       if (debug)
-                               i_info("maildir: /cur exists, assuming chroot");
-                       list_set->root_dir = "/";
-               }
-       } else {
-               if (debug)
-                       i_info("maildir: data=%s", data);
-               if (mailbox_list_settings_parse(data, list_set, storage->ns,
-                                               layout_r, NULL, error_r) < 0)
-                       return -1;
-       }
-
-       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;
-       }
-       return 0;
-}
+static void maildir_list_init(struct mailbox_list *list,
+                             const struct maildir_settings *set);
 
 static bool maildir_is_internal_name(const char *name)
 {
@@ -134,10 +57,10 @@ static bool maildir_is_internal_name(const char *name)
 static bool maildir_storage_is_valid_existing_name(struct mailbox_list *list,
                                                   const char *name)
 {
-       struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+       struct maildir_mailbox_list *mlist = MAILDIR_LIST_CONTEXT(list);
        const char *p;
 
-       if (!storage->list_module_ctx.super.is_valid_existing_name(list, name))
+       if (!mlist->module_ctx.super.is_valid_existing_name(list, name))
                return FALSE;
 
        /* Don't allow the mailbox name to end in cur/new/tmp */
@@ -150,10 +73,10 @@ static bool maildir_storage_is_valid_existing_name(struct mailbox_list *list,
 static bool maildir_storage_is_valid_create_name(struct mailbox_list *list,
                                                 const char *name)
 {
-       struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+       struct maildir_mailbox_list *mlist = MAILDIR_LIST_CONTEXT(list);
        bool ret = TRUE;
 
-       if (!storage->list_module_ctx.super.is_valid_create_name(list, name))
+       if (!mlist->module_ctx.super.is_valid_create_name(list, name))
                return FALSE;
 
        /* Don't allow creating mailboxes under cur/new/tmp */
@@ -170,7 +93,7 @@ static bool maildir_storage_is_valid_create_name(struct mailbox_list *list,
        return ret;
 }
 
-static struct mail_storage *maildir_alloc(void)
+static struct mail_storage *maildir_storage_alloc(void)
 {
        struct maildir_storage *storage;
        pool_t pool;
@@ -179,83 +102,25 @@ static struct mail_storage *maildir_alloc(void)
        storage = p_new(pool, struct maildir_storage, 1);
        storage->storage = maildir_storage;
        storage->storage.pool = pool;
-       storage->storage.storage_class = &maildir_storage;
-
        return &storage->storage;
 }
 
 static int
-maildir_create(struct mail_storage *_storage, const char *data,
-              const char **error_r)
+maildir_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
+                      const char **error_r ATTR_UNUSED)
 {
        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, *dir;
-       struct stat st;
-
-       if (maildir_get_list_settings(&list_set, data, _storage, &layout,
-                                     error_r) < 0)
-               return -1;
-       list_set.mail_storage_flags = &_storage->flags;
-       list_set.lock_method = &_storage->lock_method;
-
-       if (list_set.inbox_path == NULL &&
-           strcmp(layout, MAILDIR_PLUSPLUS_DRIVER_NAME) == 0 &&
-           (_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
-               /* Maildir++ INBOX is the Maildir base itself */
-               list_set.inbox_path = list_set.root_dir;
-       }
-
-       if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
-               if (stat(list_set.root_dir, &st) == 0) {
-                       /* ok */
-               } else if (errno == EACCES) {
-                       *error_r = mail_error_eacces_msg("stat",
-                                                        list_set.root_dir);
-                       return -1;
-               } else if (errno == ENOENT) {
-                       *error_r = t_strdup_printf(
-                                       "Root mail directory doesn't exist: %s",
-                                       list_set.root_dir);
-                       return -1;
-               } else {
-                       *error_r = t_strdup_printf("stat(%s) failed: %m",
-                                                  list_set.root_dir);
-                       return -1;
-               }
-       }
-
-       if (mailbox_list_alloc(layout, &list, error_r) < 0)
-               return -1;
+       struct mailbox_list *list = ns->list;
+       const char *dir;
 
        storage->set = mail_storage_get_driver_settings(_storage);
+       maildir_list_init(list, storage->set);
 
-       _storage->list = list;
-       storage->list_module_ctx.super = list->v;
-       if (strcmp(layout, MAILDIR_PLUSPLUS_DRIVER_NAME) == 0) {
-               list->v.iter_is_mailbox = maildirplusplus_iter_is_mailbox;
-       } else {
-               list->v.is_valid_existing_name =
-                       maildir_storage_is_valid_existing_name;
-               list->v.is_valid_create_name =
-                       maildir_storage_is_valid_create_name;
-               list->v.iter_is_mailbox = maildir_list_iter_is_mailbox;
-       }
-       list->v.delete_mailbox = maildir_list_delete_mailbox;
-       list->v.rename_mailbox = maildir_list_rename_mailbox;
        storage->maildir_list_ext_id = (uint32_t)-1;
-
-       MODULE_CONTEXT_SET_FULL(list, maildir_mailbox_list_module,
-                               storage, &storage->list_module_ctx);
-
-       /* finish list init after we've overridden vfuncs */
-       mailbox_list_init(list, _storage->ns, &list_set, 0);
-
        storage->temp_prefix = mailbox_list_get_temp_prefix(list);
-       if (list_set.control_dir == NULL && list_set.inbox_path == NULL &&
-           (_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+
+       if (list->set.control_dir == NULL && list->set.inbox_path == NULL &&
+           (ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
                /* put the temp files into tmp/ directory preferrably */
                storage->temp_prefix = p_strconcat(_storage->pool, "tmp/",
                                                   storage->temp_prefix, NULL);
@@ -271,13 +136,70 @@ maildir_create(struct mail_storage *_storage, const char *data,
        return 0;
 }
 
-static bool maildir_autodetect(const struct mail_namespace *ns)
+static void maildir_storage_get_list_settings(const struct mail_namespace *ns,
+                                             struct mailbox_list_settings *set)
+{
+       if (set->layout == NULL)
+               set->layout = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS;
+       if (set->subscription_fname == NULL)
+               set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
+
+       if (set->inbox_path == NULL &&
+           strcmp(set->layout, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0 &&
+           (ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+               /* Maildir++ INBOX is the Maildir base itself */
+               set->inbox_path = set->root_dir;
+       }
+}
+
+static const char *
+maildir_storage_find_root_dir(const struct mail_namespace *ns)
+{
+       bool debug = ns->mail_set->mail_debug;
+       const char *home, *path;
+
+       /* we'll need to figure out the maildir location ourself.
+          It's ~/Maildir unless we are chrooted. */
+       if (mail_user_get_home(ns->user, &home) > 0) {
+               path = t_strconcat(home, "/Maildir", NULL);
+               if (access(path, R_OK|W_OK|X_OK) == 0) {
+                       if (debug)
+                               i_info("maildir: root exists (%s)", path);
+                       return path;
+               } 
+               if (debug)
+                       i_info("maildir: access(%s, rwx): failed: %m", path);
+       } else {
+               if (debug)
+                       i_info("maildir: Home directory not set");
+               if (access("/cur", R_OK|W_OK|X_OK) == 0) {
+                       if (debug)
+                               i_info("maildir: /cur exists, assuming chroot");
+                       return "/";
+               }
+       }
+       return NULL;
+}
+
+static bool maildir_storage_autodetect(const struct mail_namespace *ns,
+                                      struct mailbox_list_settings *set)
 {
        bool debug = ns->mail_set->mail_debug;
        struct stat st;
-       const char *path;
+       const char *path, *root_dir;
+
+       if (set->root_dir != NULL)
+               root_dir = set->root_dir;
+       else {
+               root_dir = maildir_storage_find_root_dir(ns);
+               if (root_dir == NULL) {
+                       if (debug)
+                               i_info("maildir: couldn't find root dir");
+                       return FALSE;
+               }
+       }
 
-       path = t_strconcat(t_strcut(ns->set->location, ':'), "/cur", NULL);
+       path = t_strconcat(root_dir, "/cur", NULL);
        if (stat(path, &st) < 0) {
                if (debug)
                        i_info("maildir autodetect: stat(%s) failed: %m", path);
@@ -289,10 +211,13 @@ static bool maildir_autodetect(const struct mail_namespace *ns)
                        i_info("maildir autodetect: %s not a directory", path);
                return FALSE;
        }
+
+       set->root_dir = root_dir;
+       maildir_storage_get_list_settings(ns, set);
        return TRUE;
 }
 
-static int mkdir_verify(struct mail_storage *storage,
+static int mkdir_verify(struct mail_storage *storage, struct mail_namespace *ns,
                        const char *dir, mode_t mode, gid_t gid, bool verify)
 {
        struct stat st;
@@ -320,7 +245,7 @@ static int mkdir_verify(struct mail_storage *storage,
                mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
                        "Mailbox was deleted while it was being created");
        } else if (errno == EACCES) {
-               if (storage->ns->type == NAMESPACE_SHARED) {
+               if (ns->type == NAMESPACE_SHARED) {
                        /* shared namespace, don't log permission errors */
                        mail_storage_set_error(storage, MAIL_ERROR_PERM,
                                               MAIL_ERRSTR_NO_PERMISSION);
@@ -366,8 +291,9 @@ static int maildir_check_tmp(struct mail_storage *storage, const char *dir)
 }
 
 /* create or fix maildir, ignore if it already exists */
-static int create_maildir(struct mail_storage *storage,
-                         const char *dir, mode_t mode, gid_t gid, bool verify)
+static int
+create_maildir(struct mail_storage *storage, struct mail_namespace *ns,
+              const char *dir, mode_t mode, gid_t gid, bool verify)
 {
        const char *path;
        unsigned int i;
@@ -376,8 +302,8 @@ static int create_maildir(struct mail_storage *storage,
        ret = maildir_check_tmp(storage, dir);
        if (ret > 0) {
                if (!verify) {
-                       mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
-                                              "Mailbox already exists");
+                       mail_storage_set_error(storage,
+                               MAIL_ERROR_EXISTS, "Mailbox already exists");
                        return -1;
                }
                return 1;
@@ -388,7 +314,7 @@ static int create_maildir(struct mail_storage *storage,
        /* doesn't exist, create */
        for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
                path = t_strconcat(dir, "/", maildir_subdirs[i], NULL);
-               if (mkdir_verify(storage, path, mode, gid, verify) < 0)
+               if (mkdir_verify(storage, ns, path, mode, gid, verify) < 0)
                        return -1;
        }
        return 0;
@@ -409,8 +335,8 @@ static mode_t get_dir_mode(mode_t mode)
 }
 
 static struct mailbox *
-maildir_open(struct maildir_storage *storage, const char *name,
-            enum mailbox_open_flags flags)
+maildir_open(struct mail_storage *storage, struct mail_namespace *ns,
+            const char *name, enum mailbox_open_flags flags)
 {
        struct maildir_mailbox *mbox;
        struct mail_index *index;
@@ -418,22 +344,23 @@ maildir_open(struct maildir_storage *storage, const char *name,
        struct stat st;
        pool_t pool;
 
-       path = mailbox_list_get_path(storage->storage.list, name,
+       path = mailbox_list_get_path(ns->list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       control_dir = mailbox_list_get_path(storage->storage.list, name,
+       control_dir = mailbox_list_get_path(ns->list, name,
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
 
        pool = pool_alloconly_create("maildir mailbox", 1024+512);
        mbox = p_new(pool, struct maildir_mailbox, 1);
        mbox->ibox.box = maildir_mailbox;
        mbox->ibox.box.pool = pool;
-       mbox->ibox.storage = &storage->storage;
+       mbox->ibox.box.storage = storage;
+       mbox->ibox.box.list = ns->list;
        mbox->ibox.mail_vfuncs = &maildir_mail_vfuncs;
 
-       mbox->storage = storage;
+       mbox->storage = (struct maildir_storage *)storage;
        mbox->path = p_strdup(pool, path);
 
-       index = index_storage_alloc(&storage->storage, name, flags,
+       index = index_storage_alloc(ns->list, name, flags,
                                    MAILDIR_INDEX_PREFIX);
        mbox->ibox.index = index;
 
@@ -465,6 +392,7 @@ maildir_open(struct maildir_storage *storage, const char *name,
                        struct mailbox *box = &mbox->ibox.box;
 
                        mailbox_close(&box);
+                       mailbox_list_set_error_from_storage(ns->list, storage);
                        return NULL;
                }
                mbox->keep_lock_to = timeout_add(MAILDIR_LOCK_TOUCH_SECS * 1000,
@@ -481,10 +409,10 @@ maildir_open(struct maildir_storage *storage, const char *name,
 }
 
 static struct mailbox *
-maildir_mailbox_open(struct mail_storage *_storage, const char *name,
-                    struct istream *input, enum mailbox_open_flags flags)
+maildir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                    const char *name, struct istream *input,
+                    enum mailbox_open_flags flags)
 {
-       struct maildir_storage *storage = (struct maildir_storage *)_storage;
        const char *path;
        struct stat st;
        mode_t mode;
@@ -492,56 +420,61 @@ maildir_mailbox_open(struct mail_storage *_storage, const char *name,
        int ret;
 
        if (input != NULL) {
-               mail_storage_set_critical(_storage,
+               mailbox_list_set_critical(list,
                        "Maildir doesn't support streamed mailboxes");
                return NULL;
        }
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
        if (strcmp(name, "INBOX") == 0 &&
-           (_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+           (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
                /* INBOX always exists */
-               mailbox_list_get_dir_permissions(_storage->list, NULL,
-                                                &mode, &gid);
-               if (create_maildir(_storage, path, mode, gid, TRUE) < 0)
+               mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
+               if (create_maildir(storage, list->ns, path,
+                                  mode, gid, TRUE) < 0) {
+                       mailbox_list_set_error_from_storage(list, storage);
                        return NULL;
-               return maildir_open(storage, "INBOX", flags);
+               }
+               return maildir_open(storage, list->ns, "INBOX", flags);
        }
 
        /* begin by checking if tmp/ directory exists and if it should be
           cleaned up. */
-       ret = maildir_check_tmp(_storage, path);
+       ret = maildir_check_tmp(storage, path);
        if (ret > 0) {
                /* exists */
-               return maildir_open(storage, name, flags);
+               return maildir_open(storage, list->ns, name, flags);
        }
-       if (ret < 0)
+       if (ret < 0) {
+               mailbox_list_set_error_from_storage(list, storage);
                return NULL;
+       }
 
        /* tmp/ directory doesn't exist. does the maildir? */
        if (stat(path, &st) == 0) {
                /* yes, we'll need to create the missing dirs */
-               mailbox_list_get_dir_permissions(_storage->list, name,
-                                                &mode, &gid);
-               if (create_maildir(_storage, path, mode, gid, TRUE) < 0)
+               mailbox_list_get_dir_permissions(list, name, &mode, &gid);
+               if (create_maildir(storage, list->ns, path,
+                                  mode, gid, TRUE) < 0) {
+                       mailbox_list_set_error_from_storage(list, storage);
                        return NULL;
+               }
 
-               return maildir_open(storage, name, flags);
+               return maildir_open(storage, list->ns, name, flags);
        } else if (errno == ENOENT) {
-               mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+               mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
                return NULL;
        } else {
-               mail_storage_set_critical(_storage, "stat(%s) failed: %m",
-                                         path);
+               mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
                return NULL;
        }
 }
 
-static int maildir_create_shared(struct mail_storage *storage,
-                                const char *dir, mode_t mode, gid_t gid)
+static int
+maildir_create_shared(struct mail_storage *storage, struct mail_namespace *ns,
+                     const char *dir, mode_t mode, gid_t gid)
 {
        const char *path;
        mode_t old_mask;
@@ -552,7 +485,7 @@ static int maildir_create_shared(struct mail_storage *storage,
        if ((mode & 0060) != 0) mode |= 0010;
        if ((mode & 0006) != 0) mode |= 0001;
 
-       if (create_maildir(storage, dir, mode, gid, FALSE) < 0)
+       if (create_maildir(storage, ns, dir, mode, gid, FALSE) < 0)
                return -1;
 
        old_mask = umask(0777 ^ mode);
@@ -566,43 +499,43 @@ static int maildir_create_shared(struct mail_storage *storage,
        }
 
        if (fchown(fd, (uid_t)-1, gid) < 0) {
-               mail_storage_set_critical(storage,
-                                         "fchown(%s) failed: %m", path);
+               mail_storage_set_critical(storage, "fchown(%s) failed: %m",
+                                         path);
        }
        (void)close(fd);
        return 0;
 }
 
-static int maildir_mailbox_create(struct mail_storage *_storage,
-                                 const char *name,
-                                 bool directory ATTR_UNUSED)
+static int
+maildir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
+                      const char *name, bool directory ATTR_UNUSED)
 {
        struct stat st;
        const char *path, *root_dir, *shared_path;
        mode_t old_mask;
        int fd;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       root_dir = mailbox_list_get_path(_storage->list, NULL,
+       root_dir = mailbox_list_get_path(list, NULL,
                                         MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
        /* if dovecot-shared exists in the root dir, create the mailbox using
           its permissions and gid, and copy the dovecot-shared inside it. */
        shared_path = t_strconcat(root_dir, "/dovecot-shared", NULL);
        if (stat(shared_path, &st) == 0) {
-               if (maildir_create_shared(_storage, path,
+               if (maildir_create_shared(storage, list->ns, path,
                                          st.st_mode & 0666, st.st_gid) < 0)
                        return -1;
        } else {
-               mailbox_list_get_dir_permissions(_storage->list, NULL,
+               mailbox_list_get_dir_permissions(list, NULL,
                                                 &st.st_mode, &st.st_gid);
-               if (create_maildir(_storage, path, st.st_mode, st.st_gid,
-                                  FALSE) < 0)
+               if (create_maildir(storage, list->ns, path,
+                                  st.st_mode, st.st_gid, FALSE) < 0)
                        return -1;
        }
 
-       /* Maildir++ spec want that maildirfolder named file is created for
+       /* Maildir++ spec wants that maildirfolder named file is created for
           all subfolders. */
        path = t_strconcat(path, "/" MAILDIR_SUBFOLDER_FILENAME, NULL);
        old_mask = umask(0777 ^ (st.st_mode & 0666));
@@ -612,16 +545,16 @@ static int maildir_mailbox_create(struct mail_storage *_storage,
                /* if dovecot-shared exists, use the same group */
                if (st.st_gid != (gid_t)-1 &&
                    fchown(fd, (uid_t)-1, st.st_gid) < 0) {
-                       mail_storage_set_critical(_storage,
+                       mail_storage_set_critical(storage,
                                "fchown(%s) failed: %m", path);
                }
                (void)close(fd);
        } else if (errno == ENOENT) {
-               mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+               mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
                        "Mailbox was deleted while it was being created");
                return -1;
        } else {
-               mail_storage_set_critical(_storage,
+               mail_storage_set_critical(storage,
                        "open(%s, O_CREAT) failed: %m", path);
        }
        return 0;
@@ -638,7 +571,7 @@ maildir_get_unlink_dest(struct mailbox_list *list, const char *name)
                return NULL;
 
        if (strcmp(mailbox_list_get_driver_name(list),
-                  MAILDIR_PLUSPLUS_DRIVER_NAME) != 0) {
+                  MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) != 0) {
                /* Not maildir++ driver. Don't use this trick. */
                return NULL;
        }
@@ -737,7 +670,7 @@ maildir_delete_nonrecursive(struct mailbox_list *list, const char *path,
 static int
 maildir_list_delete_mailbox(struct mailbox_list *list, const char *name)
 {
-       struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(list);
+       union mailbox_list_module_context *mlist = MAILDIR_LIST_CONTEXT(list);
        struct stat st;
        const char *src, *dest, *base;
        int count;
@@ -749,7 +682,7 @@ maildir_list_delete_mailbox(struct mailbox_list *list, const char *name)
        index_storage_destroy_unrefed();
 
        /* delete the index and control directories */
-       if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
+       if (mlist->super.delete_mailbox(list, name) < 0)
                return -1;
 
        /* check if the mailbox actually exists */
@@ -835,7 +768,7 @@ maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
                            struct mailbox_list *newlist, const char *newname,
                            bool rename_children)
 {
-       struct maildir_storage *oldstorage = MAILDIR_LIST_CONTEXT(oldlist);
+       struct maildir_mailbox_list *oldmlist = MAILDIR_LIST_CONTEXT(oldlist);
        const char *path1, *path2;
 
        if (strcmp(oldname, "INBOX") == 0) {
@@ -852,7 +785,7 @@ maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
                }
        }
 
-       return oldstorage->list_module_ctx.super.
+       return oldmlist->module_ctx.super.
                rename_mailbox(oldlist, oldname, newlist, newname,
                               rename_children);
 }
@@ -982,11 +915,10 @@ maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
                                enum mailbox_list_file_type type,
                                enum mailbox_info_flags *flags)
 {
-       struct maildir_storage *storage = MAILDIR_LIST_CONTEXT(ctx->list);
-       struct mail_storage *_storage = &storage->storage;
+       struct maildir_mailbox_list *mlist = MAILDIR_LIST_CONTEXT(ctx->list);
        int ret;
 
-       if (fname[1] == mailbox_list_get_hierarchy_sep(_storage->list) &&
+       if (fname[1] == mailbox_list_get_hierarchy_sep(ctx->list) &&
            strcmp(fname+2, MAILDIR_UNLINK_DIRNAME) == 0) {
                const char *path;
                struct stat st;
@@ -1023,7 +955,7 @@ maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
 
        /* Check files beginning with .nfs always because they may be
           temporary files created by the kernel */
-       if (storage->set->maildir_stat_dirs || *fname == '\0' ||
+       if (mlist->set->maildir_stat_dirs || *fname == '\0' ||
            strncmp(fname, ".nfs", 4) == 0) {
                const char *path;
                struct stat st;
@@ -1055,11 +987,11 @@ maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
        return ret;
 }
 
-uint32_t maildir_get_uidvalidity_next(struct mail_storage *storage)
+uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list)
 {
        const char *path;
 
-       path = mailbox_list_get_path(storage->list, NULL,
+       path = mailbox_list_get_path(list, NULL,
                                     MAILBOX_LIST_PATH_TYPE_CONTROL);
        path = t_strconcat(path, "/"MAILDIR_UIDVALIDITY_FNAME, NULL);
        return mailbox_uidvalidity_next(path);
@@ -1075,6 +1007,29 @@ static void maildir_class_deinit(void)
        maildir_transaction_class_deinit();
 }
 
+static void maildir_list_init(struct mailbox_list *list,
+                             const struct maildir_settings *set)
+{
+       struct maildir_mailbox_list *mlist;
+
+       mlist = p_new(list->pool, struct maildir_mailbox_list, 1);
+       mlist->module_ctx.super = list->v;
+       mlist->set = set;
+
+       if (strcmp(list->name, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0) {
+               list->v.iter_is_mailbox = maildirplusplus_iter_is_mailbox;
+       } else {
+               list->v.is_valid_existing_name =
+                       maildir_storage_is_valid_existing_name;
+               list->v.is_valid_create_name =
+                       maildir_storage_is_valid_create_name;
+               list->v.iter_is_mailbox = maildir_list_iter_is_mailbox;
+       }
+       list->v.delete_mailbox = maildir_list_delete_mailbox;
+       list->v.rename_mailbox = maildir_list_rename_mailbox;
+       MODULE_CONTEXT_SET(list, maildir_mailbox_list_module, mlist);
+}
+
 struct mail_storage maildir_storage = {
        MEMBER(name) MAILDIR_STORAGE_NAME,
        MEMBER(mailbox_is_file) FALSE,
@@ -1083,10 +1038,11 @@ struct mail_storage maildir_storage = {
                 maildir_get_setting_parser_info,
                maildir_class_init,
                maildir_class_deinit,
-               maildir_alloc,
-               maildir_create,
+               maildir_storage_alloc,
+               maildir_storage_create,
                index_storage_destroy,
-               maildir_autodetect,
+               maildir_storage_get_list_settings,
+               maildir_storage_autodetect,
                maildir_mailbox_open,
                maildir_mailbox_create,
                NULL
@@ -1096,6 +1052,7 @@ struct mail_storage maildir_storage = {
 struct mailbox maildir_mailbox = {
        MEMBER(name) NULL, 
        MEMBER(storage) NULL, 
+       MEMBER(list) NULL,
 
        {
                index_storage_is_readonly,
index 708c4ad07c5264a489bfa19ab24d93161def3387..4e0880bce9e6bed6159a0ec5ee79827a73962c56 100644 (file)
@@ -70,7 +70,6 @@ struct maildir_list_index_record {
 struct maildir_storage {
        struct mail_storage storage;
 
-       union mailbox_list_module_context list_module_ctx;
        const struct maildir_settings *set;
        const char *temp_prefix;
 
@@ -124,7 +123,7 @@ int maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
 #endif
 
 bool maildir_set_deleted(struct maildir_mailbox *mbox);
-uint32_t maildir_get_uidvalidity_next(struct mail_storage *storage);
+uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list);
 
 void maildir_transaction_class_init(void);
 void maildir_transaction_class_deinit(void);
index 307f57ec3759eaae935754b9bcedbda8450d4697..cb671eb015286b3a75e380f0c15d3c422e270070 100644 (file)
@@ -573,7 +573,7 @@ int maildir_sync_index(struct maildir_index_sync_context *ctx,
 
        if (uid_validity == 0) {
                uid_validity = hdr->uid_validity != 0 ? hdr->uid_validity :
-                       maildir_get_uidvalidity_next(mbox->ibox.box.storage);
+                       maildir_get_uidvalidity_next(mbox->ibox.box.list);
                maildir_uidlist_set_uid_validity(mbox->uidlist, uid_validity);
        }
        maildir_uidlist_set_next_uid(mbox->uidlist, hdr_next_uid, FALSE);
@@ -635,8 +635,7 @@ int maildir_list_index_has_changed(struct mailbox *box,
                return 1;
        }
 
-       root_dir = mailbox_list_get_path(mail_storage_get_list(box->storage),
-                                        box->name,
+       root_dir = mailbox_list_get_path(box->list, box->name,
                                         MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
        /* check if new/ changed */
index 39ef31aea3b10e11cdddfd93801e313cdae82f17..b70b847600e709dbcfe3eca5c2f471e7e42a87cf 100644 (file)
@@ -148,7 +148,7 @@ static int maildir_uidlist_lock_timeout(struct maildir_uidlist *uidlist,
 
         index_storage_lock_notify_reset(&uidlist->mbox->ibox);
 
-       control_dir = mailbox_list_get_path(box->storage->list, box->name,
+       control_dir = mailbox_list_get_path(box->list, box->name,
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
        path = t_strconcat(control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
 
@@ -243,7 +243,7 @@ maildir_uidlist_init_readonly(struct index_mailbox *ibox)
        struct maildir_uidlist *uidlist;
        const char *control_dir;
 
-       control_dir = mailbox_list_get_path(box->storage->list, box->name,
+       control_dir = mailbox_list_get_path(box->list, box->name,
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
 
        uidlist = i_new(struct maildir_uidlist, 1);
@@ -1201,7 +1201,7 @@ static int maildir_uidlist_recreate(struct maildir_uidlist *uidlist)
 
        i_assert(uidlist->initial_read);
 
-       control_dir = mailbox_list_get_path(box->storage->list, box->name,
+       control_dir = mailbox_list_get_path(box->list, box->name,
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
        temp_path = t_strconcat(control_dir,
                                "/" MAILDIR_UIDLIST_NAME ".tmp", NULL);
@@ -1330,7 +1330,7 @@ static int maildir_uidlist_sync_update(struct maildir_uidlist_sync_ctx *ctx)
                hdr = mail_index_get_header(uidlist->ibox->view);
                uidlist->uid_validity = hdr->uid_validity != 0 ?
                        hdr->uid_validity :
-                       maildir_get_uidvalidity_next(storage);
+                       maildir_get_uidvalidity_next(uidlist->ibox->box.list);
        }
 
 
@@ -1548,8 +1548,7 @@ int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx,
                if (*p == 13 || *p == 10) {
                        struct mailbox *box = &uidlist->ibox->box;
 
-                       dir = mailbox_list_get_path(box->storage->list,
-                                               box->name,
+                       dir = mailbox_list_get_path(box->list, box->name,
                                                MAILBOX_LIST_PATH_TYPE_MAILBOX);
                        i_warning("Maildir %s: Ignoring a file with #0x%x: %s",
                                  dir, *p, filename);
index 6646f5a834906f6e813a34d96acd330f95d875a6..026d5d05e536c0dd305a2d8b451ac032ac8d76cf 100644 (file)
@@ -153,7 +153,7 @@ static int maildir_create_path(struct mailbox *box, const char *path,
                }
                /* create index/control root directory */
                parent = t_strdup_until(path, p);
-               mailbox_list_get_dir_permissions(box->storage->list, NULL,
+               mailbox_list_get_dir_permissions(box->list, NULL,
                                                 &parent_mode, &parent_gid);
                if (mkdir_parents_chown(parent, parent_mode, (uid_t)-1,
                                        parent_gid) == 0 || errno == EEXIST) {
@@ -182,10 +182,10 @@ static int maildir_create_subdirs(struct maildir_mailbox *mbox)
        /* @UNSAFE: get a list of directories we want to create */
        for (i = 0; i < N_ELEMENTS(subdirs); i++)
                dirs[i] = t_strconcat(mbox->path, "/", subdirs[i], NULL);
-       dirs[i++] = mail_storage_get_mailbox_control_dir(box->storage,
-                                                        box->name);
-       dirs[i++] = mail_storage_get_mailbox_index_dir(box->storage,
-                                                      box->name);
+       dirs[i++] = mailbox_list_get_path(box->list, box->name,
+                                         MAILBOX_LIST_PATH_TYPE_CONTROL);
+       dirs[i++] = mailbox_list_get_path(box->list, box->name,
+                                         MAILBOX_LIST_PATH_TYPE_INDEX);
        i_assert(i == N_ELEMENTS(dirs));
 
        for (i = 0; i < N_ELEMENTS(dirs); i++) {
index af2dd309a59eced79979fcfc77eb43127aa9591a..ce4a287aaa9454340ac7d1202a683b0d620603e1 100644 (file)
@@ -352,7 +352,7 @@ mbox_dotlock_log_eacces_error(struct mbox_mailbox *mbox, const char *path)
                mail_storage_set_critical(&mbox->storage->storage,
                        "%s (not INBOX -> no privileged locking)", errmsg);
        } else if (!mbox->mbox_privileged_locking) {
-               dir = mailbox_list_get_path(mbox->storage->storage.list, NULL,
+               dir = mailbox_list_get_path(mbox->ibox.box.list, NULL,
                                            MAILBOX_LIST_PATH_TYPE_DIR);
                mail_storage_set_critical(&mbox->storage->storage,
                        "%s (under root dir %s -> no privileged locking)",
index f98049c90688e57de368ef93c59793cba16a9778..9b9c90ca4c43f8519dea4de248b3a000a6c6257d 100644 (file)
@@ -120,7 +120,7 @@ static int write_from_line(struct mbox_save_context *ctx, time_t received_date,
                        struct mail_storage *storage =
                                &ctx->mbox->storage->storage;
 
-                       from_envelope = t_strconcat(storage->ns->user->username,
+                       from_envelope = t_strconcat(storage->user->username,
                                                    "@", my_hostdomain(), NULL);
                }
 
index 5fc7bddc8fe3a7c3d19512cd2164eb0efe674575..2a8c7a4bfc1a0d2f4000b859d585079c2e8a9d90 100644 (file)
@@ -21,8 +21,6 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 
-#define CREATE_MODE 0770 /* umask() should limit it more */
-
 /* How often to touch the dotlock file when using KEEP_LOCKED flag */
 #define MBOX_LOCK_TOUCH_MSECS (10*1000)
 
 #define MBOX_LIST_CONTEXT(obj) \
        MODULE_CONTEXT(obj, mbox_mailbox_list_module)
 
+struct mbox_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+       const struct mbox_settings *set;
+};
+
 /* NOTE: must be sorted for istream-header-filter. Note that it's not such
    a good idea to change this list, as the messages will then change from
    client's point of view. So if you do it, change all mailboxes' UIDVALIDITY
@@ -70,13 +73,8 @@ extern struct mailbox mbox_mailbox;
 static MODULE_CONTEXT_DEFINE_INIT(mbox_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static int mbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                                    const char *dir, const char *fname,
-                                    const char *mailbox_name,
-                                    enum mailbox_list_file_type type,
-                                    enum mailbox_info_flags *flags);
-static int mbox_list_delete_mailbox(struct mailbox_list *list,
-                                   const char *name);
+static void mbox_list_init(struct mailbox_list *list,
+                          const struct mbox_settings *set);
 
 int mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function)
 {
@@ -93,6 +91,75 @@ int mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function)
        return -1;
 }
 
+static const char *
+mbox_list_get_path(struct mailbox_list *list, const char *name,
+                  enum mailbox_list_path_type type)
+{
+       struct mbox_mailbox_list *mlist = MBOX_LIST_CONTEXT(list);
+       const char *path, *p;
+
+       path = mlist->module_ctx.super.get_path(list, name, type);
+       if (type == MAILBOX_LIST_PATH_TYPE_CONTROL ||
+           type == MAILBOX_LIST_PATH_TYPE_INDEX) {
+               if (name == NULL)
+                       return t_strconcat(path, "/"MBOX_INDEX_DIR_NAME, NULL);
+
+               p = strrchr(path, '/');
+               if (p == NULL)
+                       return "";
+
+               return t_strconcat(t_strdup_until(path, p),
+                                  "/"MBOX_INDEX_DIR_NAME"/", p+1, NULL);
+       }
+       return path;
+}
+
+static struct mail_storage *mbox_storage_alloc(void)
+{
+       struct mbox_storage *storage;
+       pool_t pool;
+
+       pool = pool_alloconly_create("mbox storage", 512+256);
+       storage = p_new(pool, struct mbox_storage, 1);
+       storage->storage = mbox_storage;
+       storage->storage.pool = pool;
+       return &storage->storage;
+}
+
+static int
+mbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
+                   const char **error_r ATTR_UNUSED)
+{
+       struct mbox_storage *storage = (struct mbox_storage *)_storage;
+       const char *dir;
+
+       storage->set = mail_storage_get_driver_settings(_storage);
+       mbox_list_init(ns->list, storage->set);
+
+       dir = mailbox_list_get_path(ns->list, NULL,
+                                   MAILBOX_LIST_PATH_TYPE_INDEX);
+       if (*dir != '\0') {
+               _storage->temp_path_prefix = p_strconcat(_storage->pool, dir,
+                       "/", mailbox_list_get_temp_prefix(ns->list), NULL);
+       }
+       return 0;
+}
+
+static void mbox_storage_get_list_settings(const struct mail_namespace *ns,
+                                          struct mailbox_list_settings *set)
+{
+       if (set->layout == NULL)
+               set->layout = MAILBOX_LIST_NAME_FS;
+       if (set->subscription_fname == NULL)
+               set->subscription_fname = MBOX_SUBSCRIPTION_FILE_NAME;
+
+       if (set->inbox_path == NULL) {
+               set->inbox_path = t_strconcat(set->root_dir, "/inbox", NULL);
+               if (ns->mail_set->mail_debug)
+                       i_info("mbox: INBOX defaulted to %s", set->inbox_path);
+       }
+}
+
 static bool mbox_is_file(const char *path, const char *name, bool debug)
 {
        struct stat st;
@@ -155,357 +222,109 @@ static bool mbox_is_dir(const char *path, const char *name, bool debug)
        return TRUE;
 }
 
-static bool mbox_autodetect(const struct mail_namespace *ns)
+static bool mbox_storage_is_root_dir(const char *dir, bool debug)
 {
-       bool debug = ns->mail_set->mail_debug;
-       const char *data = ns->set->location;
-       const char *path;
-
-       path = t_strcut(data, ':');
-       if (debug) {
-               if (strchr(data, ':') != NULL) {
-                       i_info("mbox autodetect: data=%s, splitting ':' -> %s",
-                              data, path);
-               } else {
-                       i_info("mbox autodetect: data=%s", data);
-               }
-       }
-
-       if (*path != '\0' && mbox_is_file(path, "INBOX file", debug))
-               return TRUE;
-
-       if (mbox_is_dir(t_strconcat(path, "/"MBOX_INDEX_DIR_NAME, NULL),
+       if (mbox_is_dir(t_strconcat(dir, "/"MBOX_INDEX_DIR_NAME, NULL),
                        "has "MBOX_INDEX_DIR_NAME"/", debug))
                return TRUE;
-       if (mbox_is_file(t_strconcat(path, "/inbox", NULL), "has inbox", debug))
+       if (mbox_is_file(t_strconcat(dir, "/inbox", NULL), "has inbox", debug))
                return TRUE;
-       if (mbox_is_file(t_strconcat(path, "/mbox", NULL), "has mbox", debug))
+       if (mbox_is_file(t_strconcat(dir, "/mbox", NULL), "has mbox", debug))
                return TRUE;
-
        return FALSE;
 }
 
-static const char *get_root_dir(struct mail_storage *storage)
+static const char *mbox_storage_find_root_dir(const struct mail_namespace *ns)
 {
-       struct mail_namespace auto_ns;
-       struct mail_namespace_settings ns_set;
+       bool debug = ns->mail_set->mail_debug;
        const char *home, *path;
-       bool debug = storage->set->mail_debug;
 
-       if (mail_user_get_home(storage->ns->user, &home) > 0) {
-               path = t_strconcat(home, "/mail", NULL);
-               if (access(path, R_OK|W_OK|X_OK) == 0) {
-                       if (debug)
-                               i_info("mbox: root exists (%s)", path);
-                       return path;
-               }
+       if (mail_user_get_home(ns->user, &home) <= 0) {
                if (debug)
-                       i_info("mbox: root: access(%s, rwx) failed: %m", path);
-
-               path = t_strconcat(home, "/Mail", NULL);
-               if (access(path, R_OK|W_OK|X_OK) == 0) {
-                       if (debug)
-                               i_info("mbox: root exists (%s)", path);
-                       return path;
-               }
-               if (debug)
-                       i_info("mbox: root: access(%s, rwx) failed: %m", path);
+                       i_info("maildir: Home directory not set");
+               home = "";
        }
 
-       if (debug)
-               i_info("mbox: checking if we are chrooted:");
-
-       memset(&ns_set, 0, sizeof(ns_set));
-       ns_set.location = "";
-       memset(&auto_ns, 0, sizeof(auto_ns));
-       auto_ns.set = &ns_set;
-       auto_ns.mail_set = storage->set;
-       if (mbox_autodetect(&auto_ns))
-               return "/";
+       path = t_strconcat(home, "/mail", NULL);
+       if (mbox_storage_is_root_dir(path, debug))
+               return path;
 
-       if (debug)
-               i_info("mbox: root mail directory not found");
+       path = t_strconcat(home, "/Mail", NULL);
+       if (mbox_storage_is_root_dir(path, debug))
+               return path;
        return NULL;
 }
 
 static const char *
-get_inbox_file(const char *user, const char *root_dir,
-              bool only_root, bool debug)
+mbox_storage_find_inbox_file(const char *user, bool debug)
 {
        const char *path;
 
-       if (!only_root) {
-               path = t_strconcat("/var/mail/", user, NULL);
-               if (access(path, R_OK|W_OK) == 0) {
-                       if (debug)
-                               i_info("mbox: INBOX exists (%s)", path);
-                       return path;
-               }
-               if (debug)
-                       i_info("mbox: INBOX: access(%s, rw) failed: %m", path);
-
-               path = t_strconcat("/var/spool/mail/", user, NULL);
-               if (access(path, R_OK|W_OK) == 0) {
-                       if (debug)
-                               i_info("mbox: INBOX exists (%s)", path);
-                       return path;
-               }
+       path = t_strconcat("/var/mail/", user, NULL);
+       if (access(path, R_OK|W_OK) == 0) {
                if (debug)
-                       i_info("mbox: INBOX: access(%s, rw) failed: %m", path);
+                       i_info("mbox: INBOX exists (%s)", path);
+               return path;
        }
-
-       path = t_strconcat(root_dir, "/inbox", NULL);
        if (debug)
-               i_info("mbox: INBOX defaulted to %s", path);
-       return path;
-}
-
-static const char *create_root_dir(struct mail_storage *storage,
-                                  const char **error_r)
-{
-       const char *home, *path;
+               i_info("mbox: INBOX: access(%s, rw) failed: %m", path);
 
-       if (mail_user_get_home(storage->ns->user, &home) <= 0) {
-               *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 && errno != EEXIST) {
-               *error_r = mail_error_create_eacces_msg("mkdir", path);
-               return NULL;
+       path = t_strconcat("/var/spool/mail/", user, NULL);
+       if (access(path, R_OK|W_OK) == 0) {
+               if (debug)
+                       i_info("mbox: INBOX exists (%s)", path);
+               return path;
        }
-
-       if (storage->set->mail_debug)
-               i_info("mbox: root directory created: %s", path);
-       return path;
+       if (debug)
+               i_info("mbox: INBOX: access(%s, rw) failed: %m", path);
+       return NULL;
 }
 
-static int
-mbox_get_list_settings(struct mailbox_list_settings *list_set,
-                      const char *data, struct mail_storage *storage,
-                      const char **layout_r, const char **error_r)
+static bool mbox_storage_autodetect(const struct mail_namespace *ns,
+                                   struct mailbox_list_settings *set)
 {
-       enum mail_storage_flags flags = storage->flags;
-       bool debug = storage->set->mail_debug;
-       const char *p;
-       struct stat st;
-       bool autodetect;
-
-       *layout_r = "fs";
-
-       memset(list_set, 0, sizeof(*list_set));
-       list_set->subscription_fname = MBOX_SUBSCRIPTION_FILE_NAME;
-       list_set->maildir_name = "";
-
-       autodetect = data == NULL || *data == '\0';
-       if (autodetect) {
-               if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0) {
-                       *error_r = "Root mail directory not given";
-                       return -1;
-               }
-
-               /* we'll need to figure out the mail location ourself.
-                  it's root dir if we've already chroot()ed, otherwise
-                  either ~/mail or ~/Mail */
-               list_set->root_dir = get_root_dir(storage);
-               if (list_set->root_dir == NULL) {
-                       *error_r = "Autodetection failed";
-                       return -1;
-               }
-       } else {
-               if (debug)
-                       i_info("mbox: data=%s", data);
-               p = strchr(data, ':');
-               if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0 &&
-                   p == NULL && data[strlen(data)-1] != '/') {
-                       /* if the data points to a file, treat it as an INBOX */
-                       data = mail_user_home_expand(storage->ns->user, data);
-                       if (stat(data, &st) < 0 || S_ISDIR(st.st_mode))
-                               list_set->root_dir = data;
-                       else {
-                               list_set->root_dir = get_root_dir(storage);
-                               list_set->inbox_path = data;
-                       }
-               } else if (strncmp(data, "INBOX=", 6) == 0) {
-                       /* the most common misconfiguration */
-                       *error_r = "Root mail directory not given";
-                       return -1;
-               } else {
-                       if (mailbox_list_settings_parse(data, list_set,
-                                                       storage->ns,
-                                                       layout_r, NULL,
-                                                       error_r) < 0)
-                               return -1;
-               }
+       bool debug = ns->mail_set->mail_debug;
+       const char *root_dir, *inbox_path;
+
+       root_dir = set->root_dir;
+       inbox_path = set->inbox_path;
+
+       if (root_dir != NULL) {
+               if (inbox_path == NULL &&
+                   mbox_is_file(root_dir, "INBOX file", debug)) {
+                       /* using location=<INBOX> */
+                       inbox_path = root_dir;
+                       root_dir = NULL;
+               } else if (!mbox_storage_is_root_dir(root_dir, debug))
+                       return FALSE;
        }
-
-       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(storage, error_r);
-               if (list_set->root_dir == NULL)
-                       return -1;
-       } else {
-               /* make sure the directory exists */
-               if (lstat(list_set->root_dir, &st) == 0) {
-                       /* yep, go ahead */
-               } else if (errno == EACCES) {
-                       *error_r = mail_error_eacces_msg("lstat",
-                                                        list_set->root_dir);
-                       return -1;
-               } else if (errno != ENOENT && errno != ENOTDIR) {
-                       *error_r = t_strdup_printf("lstat(%s) failed: %m",
-                                                  list_set->root_dir);
-                       return -1;
-               } else if (errno == ENOENT &&
-                          storage->ns->type == NAMESPACE_SHARED) {
-                       /* can't create a new user, but we don't want to fail
-                          the storage creation. */
-               } 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) {
-                       *error_r = mail_error_create_eacces_msg("mkdir",
-                                                       list_set->root_dir);
-                       return -1;
+       if (root_dir == NULL) {
+               root_dir = mbox_storage_find_root_dir(ns);
+               if (root_dir == NULL) {
+                       if (debug)
+                               i_info("mbox: couldn't find root dir");
+                       return FALSE;
                }
        }
-
-       if (list_set->inbox_path == NULL) {
-               list_set->inbox_path =
-                       get_inbox_file(storage->ns->user->username,
-                                      list_set->root_dir, !autodetect, debug);
-       }
-       return 0;
-}
-
-static const char *
-mbox_list_get_path(struct mailbox_list *list, const char *name,
-                  enum mailbox_list_path_type type)
-{
-       struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
-       const char *path, *p;
-
-       path = storage->list_module_ctx.super.get_path(list, name, type);
-       if (type == MAILBOX_LIST_PATH_TYPE_CONTROL ||
-           type == MAILBOX_LIST_PATH_TYPE_INDEX) {
-               if (name == NULL)
-                       return t_strconcat(path, "/"MBOX_INDEX_DIR_NAME, NULL);
-
-               p = strrchr(path, '/');
-               if (p == NULL)
-                       return "";
-
-               return t_strconcat(t_strdup_until(path, p),
-                                  "/"MBOX_INDEX_DIR_NAME"/", p+1, NULL);
-       }
-       return path;
-}
-
-static struct mail_storage *mbox_alloc(void)
-{
-       struct mbox_storage *storage;
-       pool_t pool;
-
-       pool = pool_alloconly_create("mbox storage", 512+256);
-       storage = p_new(pool, struct mbox_storage, 1);
-       storage->storage = mbox_storage;
-       storage->storage.pool = pool;
-       storage->storage.storage_class = &mbox_storage;
-
-       return &storage->storage;
-}
-
-static bool mbox_name_is_dotlock(const char *name)
-{
-       unsigned int len = strlen(name);
-
-       return len >= 5 && strcmp(name + len - 5, ".lock") == 0;
-}
-
-static bool
-mbox_is_valid_existing_name(struct mailbox_list *list, const char *name)
-{
-       struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
-
-       return storage->list_module_ctx.super.
-               is_valid_existing_name(list, name) &&
-               !mbox_name_is_dotlock(name);
-}
-
-static bool
-mbox_is_valid_create_name(struct mailbox_list *list, const char *name)
-{
-       struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
-
-       return storage->list_module_ctx.super.
-               is_valid_create_name(list, name) &&
-               !mbox_name_is_dotlock(name);
-}
-
-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, *dir;
-
-       if (mbox_get_list_settings(&list_set, data, _storage,
-                                  &layout, error_r) < 0)
-               return -1;
-       list_set.mail_storage_flags = &_storage->flags;
-       list_set.lock_method = &_storage->lock_method;
-
-       if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
-               return -1;
-
-       storage->set = mail_storage_get_driver_settings(_storage);
-
-       storage->list_module_ctx.super = _storage->list->v;
-       if (strcmp(layout, "fs") == 0 && *list_set.maildir_name == '\0') {
-               /* have to use .imap/ directories */
-               _storage->list->v.get_path = mbox_list_get_path;
+       if (inbox_path == NULL) {
+               inbox_path = mbox_storage_find_inbox_file(ns->user->username,
+                                                         debug);
        }
-       _storage->list->v.iter_is_mailbox = mbox_list_iter_is_mailbox;
-       _storage->list->v.delete_mailbox = mbox_list_delete_mailbox;
-       _storage->list->v.is_valid_existing_name = mbox_is_valid_existing_name;
-       _storage->list->v.is_valid_create_name = mbox_is_valid_create_name;
+       set->root_dir = root_dir;
+       set->inbox_path = inbox_path;
 
-       MODULE_CONTEXT_SET_FULL(_storage->list, mbox_mailbox_list_module,
-                               storage, &storage->list_module_ctx);
-
-       /* finish list init after we've overridden vfuncs */
-       mailbox_list_init(_storage->list, _storage->ns, &list_set,
-                         MAILBOX_LIST_FLAG_MAILBOX_FILES);
-
-       dir = mailbox_list_get_path(_storage->list, NULL,
-                                   MAILBOX_LIST_PATH_TYPE_INDEX);
-       if (*dir == '\0') {
-               /* no index directory. just fallback to writing to root. */
-               dir = mailbox_list_get_path(_storage->list, NULL,
-                                           MAILBOX_LIST_PATH_TYPE_DIR);
-       }
-       _storage->temp_path_prefix = p_strconcat(_storage->pool, dir, "/",
-               mailbox_list_get_temp_prefix(_storage->list), NULL);
-       return 0;
+       mbox_storage_get_list_settings(ns, set);
+       return TRUE;
 }
 
-static int verify_inbox(struct mail_storage *storage)
+static int verify_inbox(struct mailbox_list *list)
 {
        const char *inbox_path, *rootdir;
        int fd;
 
-       inbox_path = mailbox_list_get_path(storage->list, "INBOX",
+       inbox_path = mailbox_list_get_path(list, "INBOX",
                                           MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       rootdir = mailbox_list_get_path(storage->list, "",
+       rootdir = mailbox_list_get_path(list, NULL,
                                        MAILBOX_LIST_PATH_TYPE_DIR);
 
        /* make sure inbox file itself exists */
@@ -520,17 +339,17 @@ static int verify_inbox(struct mail_storage *storage)
                (void)close(fd);
        else if (errno == ENOTDIR &&
                 strncmp(inbox_path, rootdir, strlen(rootdir)) == 0) {
-               mail_storage_set_critical(storage,
+               mailbox_list_set_critical(list,
                        "mbox root directory can't be a file: %s "
                        "(http://wiki.dovecot.org/MailLocation/Mbox)",
                        rootdir);
                return -1;
        } else if (errno == EACCES) {
-               mail_storage_set_critical(storage, "%s",
+               mailbox_list_set_critical(list, "%s",
                        mail_error_create_eacces_msg("open", inbox_path));
                return -1;
        } else if (errno != EEXIST) {
-               mail_storage_set_critical(storage,
+               mailbox_list_set_critical(list,
                        "open(%s, O_CREAT) failed: %m", inbox_path);
                return -1;
        }
@@ -574,7 +393,7 @@ mbox_alloc_mailbox(struct mbox_storage *storage, struct mail_index *index,
        mbox = p_new(pool, struct mbox_mailbox, 1);
        mbox->ibox.box = mbox_mailbox;
        mbox->ibox.box.pool = pool;
-       mbox->ibox.storage = &storage->storage;
+       mbox->ibox.box.storage = &storage->storage;
        mbox->ibox.mail_vfuncs = &mbox_mail_vfuncs;
        mbox->ibox.index = index;
 
@@ -596,18 +415,17 @@ mbox_alloc_mailbox(struct mbox_storage *storage, struct mail_index *index,
 }
 
 static struct mailbox *
-mbox_open(struct mbox_storage *storage, const char *name,
-         enum mailbox_open_flags flags)
+mbox_open(struct mbox_storage *storage, struct mailbox_list *list,
+         const char *name, enum mailbox_open_flags flags)
 {
-       struct mail_storage *_storage = &storage->storage;
        struct mbox_mailbox *mbox;
        struct mail_index *index;
        const char *path, *rootdir;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
-       index = index_storage_alloc(_storage, name, flags, MBOX_INDEX_PREFIX);
+       index = index_storage_alloc(list, name, flags, MBOX_INDEX_PREFIX);
        mbox = mbox_alloc_mailbox(storage, index, name, path, flags);
 
        if (access(path, R_OK|W_OK) < 0) {
@@ -620,7 +438,7 @@ mbox_open(struct mbox_storage *storage, const char *name,
        if (strcmp(name, "INBOX") == 0) {
                /* if INBOX isn't under the root directory, it's probably in
                   /var/mail and we want to allow privileged dotlocking */
-               rootdir = mailbox_list_get_path(_storage->list, NULL,
+               rootdir = mailbox_list_get_path(list, NULL,
                                                MAILBOX_LIST_PATH_TYPE_DIR);
                if (strncmp(path, rootdir, strlen(rootdir)) != 0)
                        mbox->mbox_privileged_locking = TRUE;
@@ -630,6 +448,8 @@ mbox_open(struct mbox_storage *storage, const char *name,
                        struct mailbox *box = &mbox->ibox.box;
 
                        mailbox_close(&box);
+                       mailbox_list_set_error_from_storage(list,
+                                                           &storage->storage);
                        return NULL;
                }
 
@@ -643,22 +463,20 @@ mbox_open(struct mbox_storage *storage, const char *name,
 }
 
 static struct mailbox *
-mbox_mailbox_open_stream(struct mbox_storage *storage, const char *name,
+mbox_mailbox_open_stream(struct mbox_storage *storage,
+                        struct mailbox_list *list, const char *name,
                         struct istream *input, enum mailbox_open_flags flags)
 {
-       struct mail_storage *_storage = &storage->storage;
        struct mail_index *index;
        struct mbox_mailbox *mbox;
        const char *path;
 
        flags |= MAILBOX_OPEN_READONLY;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       index = index_storage_alloc(_storage, name, flags, MBOX_INDEX_PREFIX);
+       index = index_storage_alloc(list, name, flags, MBOX_INDEX_PREFIX);
        mbox = mbox_alloc_mailbox(storage, index, name, path, flags);
-       if (mbox == NULL)
-               return NULL;
 
        i_stream_ref(input);
        mbox->mbox_file_stream = input;
@@ -670,50 +488,53 @@ mbox_mailbox_open_stream(struct mbox_storage *storage, const char *name,
 }
 
 static struct mailbox *
-mbox_mailbox_open(struct mail_storage *_storage, const char *name,
-                 struct istream *input, enum mailbox_open_flags flags)
+mbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
+                 const char *name, struct istream *input,
+                 enum mailbox_open_flags flags)
 {
        struct mbox_storage *storage = (struct mbox_storage *)_storage;
        const char *path;
        struct stat st;
 
-       if (input != NULL)
-               return mbox_mailbox_open_stream(storage, name, input, flags);
+       if (input != NULL) {
+               return mbox_mailbox_open_stream(storage, list, name,
+                                               input, flags);
+       }
 
        if (strcmp(name, "INBOX") == 0 &&
-           (_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+           (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
                /* make sure INBOX exists */
-               if (verify_inbox(_storage) < 0)
+               if (verify_inbox(list) < 0)
                        return NULL;
-               return mbox_open(storage, "INBOX", flags);
+               return mbox_open(storage, list, "INBOX", flags);
        }
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(path, &st) == 0) {
                if (S_ISDIR(st.st_mode)) {
-                       mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
+                       mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
                                t_strdup_printf("Mailbox isn't selectable: %s",
                                                name));
                        return NULL;
                }
 
-               return mbox_open(storage, name, flags);
+               return mbox_open(storage, list, name, flags);
        }
 
        if (ENOTFOUND(errno)) {
-               mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+               mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-       } else if (!mail_storage_set_error_from_errno(_storage)) {
-               mail_storage_set_critical(_storage, "stat(%s) failed: %m",
-                                         path);
+       } else if (!mailbox_list_set_error_from_errno(list)) {
+               mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
        }
 
        return NULL;
 }
 
-static int mbox_mailbox_create(struct mail_storage *_storage, const char *name,
-                              bool directory)
+static int
+mbox_mailbox_create(struct mail_storage *_storage, struct mailbox_list *list,
+                   const char *name, bool directory)
 {
        const char *path, *p;
        struct stat st;
@@ -722,7 +543,7 @@ static int mbox_mailbox_create(struct mail_storage *_storage, const char *name,
        int fd;
 
        /* make sure it doesn't exist already */
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(path, &st) == 0) {
                mail_storage_set_error(_storage, MAIL_ERROR_EXISTS,
@@ -745,8 +566,7 @@ static int mbox_mailbox_create(struct mail_storage *_storage, const char *name,
        p = directory ? path + strlen(path) : strrchr(path, '/');
        if (p != NULL) {
                p = t_strdup_until(path, p);
-               mailbox_list_get_dir_permissions(_storage->list, NULL,
-                                                &mode, &gid);
+               mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
                if (mkdir_parents_chown(p, mode, (uid_t)-1, gid) < 0 &&
                    errno != EEXIST) {
                        if (!mail_storage_set_error_from_errno(_storage)) {
@@ -842,13 +662,37 @@ is_inbox_file(struct mailbox_list *list, const char *path, const char *fname)
        return strcmp(inbox_path, path) == 0;
 }
 
+static bool mbox_name_is_dotlock(const char *name)
+{
+       unsigned int len = strlen(name);
+
+       return len >= 5 && strcmp(name + len - 5, ".lock") == 0;
+}
+
+static bool
+mbox_is_valid_existing_name(struct mailbox_list *list, const char *name)
+{
+       struct mbox_mailbox_list *mlist = MBOX_LIST_CONTEXT(list);
+
+       return mlist->module_ctx.super.is_valid_existing_name(list, name) &&
+               !mbox_name_is_dotlock(name);
+}
+
+static bool
+mbox_is_valid_create_name(struct mailbox_list *list, const char *name)
+{
+       struct mbox_mailbox_list *mlist = MBOX_LIST_CONTEXT(list);
+
+       return mlist->module_ctx.super.is_valid_create_name(list, name) &&
+               !mbox_name_is_dotlock(name);
+}
+
 static int mbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
                                     const char *dir, const char *fname,
                                     const char *mailbox_name ATTR_UNUSED,
                                     enum mailbox_list_file_type type,
                                     enum mailbox_info_flags *flags)
 {
-       struct mail_storage *storage = MBOX_LIST_CONTEXT(ctx->list);
        const char *path, *root_dir;
        size_t len;
        struct stat st;
@@ -858,7 +702,7 @@ static int mbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
                return 0;
        }
        if (strcmp(fname, ctx->list->set.subscription_fname) == 0) {
-               root_dir = mailbox_list_get_path(storage->list, NULL,
+               root_dir = mailbox_list_get_path(ctx->list, NULL,
                                                 MAILBOX_LIST_PATH_TYPE_DIR);
                if (strcmp(root_dir, dir) == 0) {
                        *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
@@ -916,7 +760,7 @@ static int mbox_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
 static int mbox_list_delete_mailbox(struct mailbox_list *list,
                                    const char *name)
 {
-       struct mbox_storage *storage = MBOX_LIST_CONTEXT(list);
+       struct mbox_mailbox_list *mlist = MBOX_LIST_CONTEXT(list);
        struct stat st;
        const char *path, *index_dir;
 
@@ -970,7 +814,7 @@ static int mbox_list_delete_mailbox(struct mailbox_list *list,
 
        /* delete index / control files first */
        index_storage_destroy_unrefed();
-       if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
+       if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
                return -1;
 
        if (unlink(path) < 0) {
@@ -997,6 +841,28 @@ static void mbox_class_deinit(void)
        mbox_transaction_class_deinit();
 }
 
+static void mbox_list_init(struct mailbox_list *list,
+                          const struct mbox_settings *set)
+{
+       struct mbox_mailbox_list *mlist;
+
+       mlist = p_new(list->pool, struct mbox_mailbox_list, 1);
+       mlist->module_ctx.super = list->v;
+       mlist->set = set;
+
+       if (strcmp(list->name, MAILBOX_LIST_NAME_FS) == 0 &&
+           *list->set.maildir_name == '\0') {
+               /* have to use .imap/ directories */
+               list->v.get_path = mbox_list_get_path;
+       }
+       list->v.iter_is_mailbox = mbox_list_iter_is_mailbox;
+       list->v.delete_mailbox = mbox_list_delete_mailbox;
+       list->v.is_valid_existing_name = mbox_is_valid_existing_name;
+       list->v.is_valid_create_name = mbox_is_valid_create_name;
+
+       MODULE_CONTEXT_SET(list, mbox_mailbox_list_module, mlist);
+}
+
 struct mail_storage mbox_storage = {
        MEMBER(name) MBOX_STORAGE_NAME,
        MEMBER(mailbox_is_file) TRUE,
@@ -1005,10 +871,11 @@ struct mail_storage mbox_storage = {
                 mbox_get_setting_parser_info,
                mbox_class_init,
                mbox_class_deinit,
-               mbox_alloc,
-               mbox_create,
+               mbox_storage_alloc,
+               mbox_storage_create,
                index_storage_destroy,
-               mbox_autodetect,
+               mbox_storage_get_list_settings,
+               mbox_storage_autodetect,
                mbox_mailbox_open,
                mbox_mailbox_create,
                NULL
@@ -1018,6 +885,7 @@ struct mail_storage mbox_storage = {
 struct mailbox mbox_mailbox = {
        MEMBER(name) NULL, 
        MEMBER(storage) NULL, 
+       MEMBER(list) NULL,
 
        {
                index_storage_is_readonly,
index a06d12cc4dfd0a75265c401f9f4a39812652102a..ca99a4342bc5432844271b1cb76c48ab82e2f170 100644 (file)
@@ -28,8 +28,6 @@ struct mbox_storage {
        enum mbox_lock_type *read_locks;
        enum mbox_lock_type *write_locks;
        unsigned int lock_settings_initialized:1;
-
-       union mailbox_list_module_context list_module_ctx;
 };
 
 struct mbox_mailbox {
index 43404bc2266005c6e32b2c7ac506e641920ca686..686c647c9913378ac5971162e1a77c2d4a7dd67f 100644 (file)
@@ -9,50 +9,16 @@
 #include "raw-sync.h"
 #include "raw-storage.h"
 
-#define RAW_LIST_CONTEXT(obj) \
-       MODULE_CONTEXT(obj, raw_mailbox_list_module)
+struct raw_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+};
 
 extern struct mail_storage raw_storage;
 extern struct mailbox raw_mailbox;
 
-static MODULE_CONTEXT_DEFINE_INIT(raw_mailbox_list_module,
-                                 &mailbox_list_module_register);
-
-static int raw_list_delete_mailbox(struct mailbox_list *list, const char *name);
-static int raw_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                                   const char *dir, const char *fname,
-                                   const char *mailbox_name,
-                                   enum mailbox_list_file_type type,
-                                   enum mailbox_info_flags *flags);
+static void raw_list_init(struct mailbox_list *list);
 
-static int
-raw_get_list_settings(struct mailbox_list_settings *list_set,
-                     const char *data, struct mail_storage *storage,
-                     const char **layout_r, const char **error_r)
-{
-       bool debug = storage->set->mail_debug;
-
-       *layout_r = "fs";
-
-       memset(list_set, 0, sizeof(*list_set));
-       list_set->subscription_fname = RAW_SUBSCRIPTION_FILE_NAME;
-       list_set->maildir_name = "";
-
-       if (data == NULL || *data == '\0' || *data == ':') {
-               /* we won't do any guessing for this format. */
-               if (debug)
-                       i_info("raw: mailbox location not given");
-               *error_r = "Root mail directory not given";
-               return -1;
-       }
-
-       if (debug)
-               i_info("raw: data=%s", data);
-       return mailbox_list_settings_parse(data, list_set, storage->ns,
-                                          layout_r, NULL, error_r);
-}
-
-static struct mail_storage *raw_alloc(void)
+static struct mail_storage *raw_storage_alloc(void)
 {
        struct raw_storage *storage;
        pool_t pool;
@@ -61,53 +27,29 @@ static struct mail_storage *raw_alloc(void)
        storage = p_new(pool, struct raw_storage, 1);
        storage->storage = raw_storage;
        storage->storage.pool = pool;
-
        return &storage->storage;
 }
 
-static int raw_create(struct mail_storage *_storage, const char *data,
-                     const char **error_r)
+static int
+raw_storage_create(struct mail_storage *_storage ATTR_UNUSED,
+                  struct mail_namespace *ns, const char **error_r ATTR_UNUSED)
 {
-       struct raw_storage *storage = (struct raw_storage *)_storage;
-       struct mailbox_list_settings list_set;
-       struct stat st;
-       const char *layout;
-
-       if (raw_get_list_settings(&list_set, data, _storage,
-                                 &layout, error_r) < 0)
-               return -1;
-       list_set.mail_storage_flags = &_storage->flags;
-       list_set.lock_method = &_storage->lock_method;
-
-       if (stat(list_set.root_dir, &st) < 0) {
-               if (errno != ENOENT) {
-                       *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;
-       }
-
-       if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
-               return -1;
-       storage->list_module_ctx.super = _storage->list->v;
-       _storage->list->v.iter_is_mailbox = raw_list_iter_is_mailbox;
-       _storage->list->v.delete_mailbox = raw_list_delete_mailbox;
-
-       MODULE_CONTEXT_SET_FULL(_storage->list, raw_mailbox_list_module,
-                               storage, &storage->list_module_ctx);
-
-       /* finish list init after we've overridden vfuncs */
-       mailbox_list_init(_storage->list, _storage->ns, &list_set,
-                         MAILBOX_LIST_FLAG_MAILBOX_FILES);
+       raw_list_init(ns->list);
        return 0;
 }
 
+static void
+raw_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
+                             struct mailbox_list_settings *set)
+{
+       if (set->layout == NULL)
+               set->layout = MAILBOX_LIST_NAME_FS;
+       if (set->subscription_fname == NULL)
+               set->subscription_fname = RAW_SUBSCRIPTION_FILE_NAME;
+}
+
 static int
-raw_mailbox_open_input(struct mail_storage *storage, const char *name,
+raw_mailbox_open_input(struct mailbox_list *list, const char *name,
                       const char *path, struct istream **input_r)
 {
        int fd;
@@ -115,11 +57,11 @@ raw_mailbox_open_input(struct mail_storage *storage, const char *name,
        fd = open(path, O_RDONLY);
        if (fd == -1) {
                if (ENOTFOUND(errno)) {
-                       mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
+                       mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                                T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-               } else if (!mail_storage_set_error_from_errno(storage)) {
-                       mail_storage_set_critical(storage,
-                                                 "open(%s) failed: %m", path);
+               } else if (!mailbox_list_set_error_from_errno(list)) {
+                       mailbox_list_set_critical(list, "open(%s) failed: %m",
+                                                 path);
                }
                return -1;
        }
@@ -128,10 +70,10 @@ raw_mailbox_open_input(struct mail_storage *storage, const char *name,
 }
 
 static struct mailbox *
-raw_mailbox_open(struct mail_storage *_storage, const char *name,
-                struct istream *input, enum mailbox_open_flags flags)
+raw_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                const char *name, struct istream *input,
+                enum mailbox_open_flags flags)
 {
-       struct raw_storage *storage = (struct raw_storage *)_storage;
        struct raw_mailbox *mbox;
        const char *path;
        pool_t pool;
@@ -139,12 +81,12 @@ raw_mailbox_open(struct mail_storage *_storage, const char *name,
 
        flags |= MAILBOX_OPEN_READONLY | MAILBOX_OPEN_NO_INDEX_FILES;
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (input != NULL)
                i_stream_ref(input);
        else {
-               if (raw_mailbox_open_input(_storage, name, path, &input) < 0)
+               if (raw_mailbox_open_input(list, name, path, &input) < 0)
                        return NULL;
        }
 
@@ -152,11 +94,11 @@ raw_mailbox_open(struct mail_storage *_storage, const char *name,
        mbox = p_new(pool, struct raw_mailbox, 1);
        mbox->ibox.box = raw_mailbox;
        mbox->ibox.box.pool = pool;
-       mbox->ibox.storage = &storage->storage;
+       mbox->ibox.box.storage = storage;
        mbox->ibox.mail_vfuncs = &raw_mail_vfuncs;
-       mbox->ibox.index = index_storage_alloc(_storage, name, flags, NULL);
+       mbox->ibox.index = index_storage_alloc(list, name, flags, NULL);
 
-       mbox->storage = storage;
+       mbox->storage = (struct raw_storage *)storage;
        mbox->path = p_strdup(pool, path);
        mbox->input = input;
 
@@ -180,9 +122,10 @@ static int raw_mailbox_close(struct mailbox *box)
        return index_storage_mailbox_close(box);
 }
 
-static int raw_mailbox_create(struct mail_storage *storage,
-                             const char *name ATTR_UNUSED,
-                             bool directory ATTR_UNUSED)
+static int
+raw_mailbox_create(struct mail_storage *storage,
+                  struct mailbox_list *list ATTR_UNUSED,
+                  const char *name ATTR_UNUSED, bool directory ATTR_UNUSED)
 {
        mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
                               "Raw mailbox creation isn't supported");
@@ -207,7 +150,6 @@ static int raw_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
                                    enum mailbox_list_file_type type,
                                    enum mailbox_info_flags *flags_r)
 {
-       struct mail_storage *storage = RAW_LIST_CONTEXT(ctx->list);
        const char *path;
        struct stat st;
 
@@ -238,7 +180,8 @@ static int raw_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
                *flags_r = MAILBOX_NONEXISTENT;
                return 0;
        } else {
-               mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
+               mailbox_list_set_critical(ctx->list, "stat(%s) failed: %m",
+                                         path);
                return -1;
        }
 }
@@ -253,6 +196,12 @@ static void raw_class_deinit(void)
        raw_transaction_class_deinit();
 }
 
+static void raw_list_init(struct mailbox_list *list)
+{
+       list->v.iter_is_mailbox = raw_list_iter_is_mailbox;
+       list->v.delete_mailbox = raw_list_delete_mailbox;
+}
+
 struct mail_storage raw_storage = {
        MEMBER(name) RAW_STORAGE_NAME,
        MEMBER(mailbox_is_file) TRUE,
@@ -261,9 +210,10 @@ struct mail_storage raw_storage = {
                NULL,
                raw_class_init,
                raw_class_deinit,
-               raw_alloc,
-               raw_create,
+               raw_storage_alloc,
+               raw_storage_create,
                index_storage_destroy,
+               raw_storage_get_list_settings,
                NULL,
                raw_mailbox_open,
                raw_mailbox_create,
@@ -274,6 +224,7 @@ struct mail_storage raw_storage = {
 struct mailbox raw_mailbox = {
        MEMBER(name) NULL, 
        MEMBER(storage) NULL, 
+       MEMBER(list) NULL,
 
        {
                index_storage_is_readonly,
index 52ec9a77720b69d07701beca78b7ac0104b1b69f..1ec49b9c57ed8d86e253d25a1b97f43d8a5d9157 100644 (file)
@@ -43,13 +43,14 @@ static void shared_list_copy_error(struct mailbox_list *shared_list,
 }
 
 static int
-shared_get_storage(struct mailbox_list *list, const char **name,
+shared_get_storage(struct mailbox_list **list, const char **name,
                   struct mail_storage **storage_r)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = (*list)->ns;
 
-       if (shared_storage_get_namespace(list->ns->storage, name, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, name) < 0)
                return -1;
+       *list = ns->list;
        *storage_r = ns->storage;
        return 0;
 }
@@ -57,9 +58,9 @@ shared_get_storage(struct mailbox_list *list, const char **name,
 static bool
 shared_is_valid_pattern(struct mailbox_list *list, const char *pattern)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
 
-       if (shared_storage_get_namespace(list->ns->storage, &pattern, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, &pattern) < 0)
                return FALSE;
        return mailbox_list_is_valid_pattern(ns->list, pattern);
 }
@@ -67,9 +68,9 @@ shared_is_valid_pattern(struct mailbox_list *list, const char *pattern)
 static bool
 shared_is_valid_existing_name(struct mailbox_list *list, const char *name)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
 
-       if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, &name) < 0)
                return FALSE;
        return mailbox_list_is_valid_existing_name(ns->list, name);
 }
@@ -77,9 +78,9 @@ shared_is_valid_existing_name(struct mailbox_list *list, const char *name)
 static bool
 shared_is_valid_create_name(struct mailbox_list *list, const char *name)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
 
-       if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, &name) < 0)
                return FALSE;
        return mailbox_list_is_valid_create_name(ns->list, name);
 }
@@ -88,10 +89,10 @@ static const char *
 shared_list_get_path(struct mailbox_list *list, const char *name,
                     enum mailbox_list_path_type type)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
 
        if (list->ns->storage == NULL || name == NULL ||
-           shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0) {
+           shared_storage_get_namespace(&ns, &name) < 0) {
                switch (type) {
                case MAILBOX_LIST_PATH_TYPE_DIR:
                case MAILBOX_LIST_PATH_TYPE_MAILBOX:
@@ -111,10 +112,10 @@ 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;
+       struct mail_namespace *ns = list->ns;
        int ret;
 
-       if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, &name) < 0)
                return -1;
        ret = mailbox_list_get_mailbox_name_status(ns->list, name, status_r);
        if (ret < 0)
@@ -134,7 +135,7 @@ static const char *
 shared_list_join_refpattern(struct mailbox_list *list,
                            const char *ref, const char *pattern)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
        const char *ns_ref, *prefix = list->ns->prefix;
        unsigned int prefix_len = strlen(prefix);
 
@@ -143,9 +144,7 @@ shared_list_join_refpattern(struct mailbox_list *list,
        else
                ns_ref = NULL;
 
-       if (ns_ref != NULL &&
-           shared_storage_get_namespace(list->ns->storage,
-                                        &ns_ref, &ns) == 0)
+       if (ns_ref != NULL && shared_storage_get_namespace(&ns, &ns_ref) == 0)
                return mailbox_list_join_refpattern(ns->list, ns_ref, pattern);
 
        /* fallback to default behavior */
@@ -220,10 +219,10 @@ static int shared_list_iter_deinit(struct mailbox_list_iterate_context *_ctx)
 static int shared_list_set_subscribed(struct mailbox_list *list,
                                      const char *name, bool set)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
        int ret;
 
-       if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, &name) < 0)
                return -1;
        ret = mailbox_list_set_subscribed(ns->list, name, set);
        if (ret < 0)
@@ -234,10 +233,10 @@ static int shared_list_set_subscribed(struct mailbox_list *list,
 static int
 shared_list_delete_mailbox(struct mailbox_list *list, const char *name)
 {
-       struct mail_namespace *ns;
+       struct mail_namespace *ns = list->ns;
        int ret;
 
-       if (shared_storage_get_namespace(list->ns->storage, &name, &ns) < 0)
+       if (shared_storage_get_namespace(&ns, &name) < 0)
                return -1;
        ret = mailbox_list_delete_mailbox(ns->list, name);
        if (ret < 0)
@@ -251,12 +250,10 @@ static int shared_list_rename_get_ns(struct mailbox_list *oldlist,
                                     const char **newname,
                                     struct mail_namespace **ns_r)
 {
-       struct mail_namespace *old_ns, *new_ns;
+       struct mail_namespace *old_ns = oldlist->ns, *new_ns = newlist->ns;
 
-       if (shared_storage_get_namespace(oldlist->ns->storage,
-                                        oldname, &old_ns) < 0 ||
-           shared_storage_get_namespace(newlist->ns->storage,
-                                        newname, &new_ns) < 0)
+       if (shared_storage_get_namespace(&old_ns, oldname) < 0 ||
+           shared_storage_get_namespace(&new_ns, newname) < 0)
                return -1;
        if (old_ns != new_ns) {
                mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
index 8764a39259c027ef57e14c1c7b25072c9ecb9145..fdc0ddcab21eb1a87052d178f4167bfba97f031a 100644 (file)
 #include <stdlib.h>
 #include <ctype.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)
+static struct mail_storage *shared_storage_alloc(void)
 {
        struct shared_storage *storage;
        pool_t pool;
@@ -29,32 +22,26 @@ static struct mail_storage *shared_alloc(void)
        storage = p_new(pool, struct shared_storage, 1);
        storage->storage = shared_storage;
        storage->storage.pool = pool;
-       storage->storage.storage_class = &shared_storage;
-
-       storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
-       if (storage->base_dir == NULL)
-               storage->base_dir = PKG_RUNDIR;
-
        return &storage->storage;
 }
 
-static int shared_create(struct mail_storage *_storage, const char *data,
-                        const char **error_r)
+static int
+shared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
+                     const char **error_r)
 {
        struct shared_storage *storage = (struct shared_storage *)_storage;
-       struct mailbox_list_settings list_set;
        const char *driver, *p;
        char *wildcardp;
        bool have_username;
 
-       /* data must begin with the actual mailbox driver */
-       p = strchr(data, ':');
+       /* location must begin with the actual mailbox driver */
+       p = strchr(ns->set->location, ':');
        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);
+       driver = t_strdup_until(ns->set->location, p);
+       storage->location = p_strdup(_storage->pool, ns->set->location);
        storage->storage_class = mail_storage_find_class(driver);
        if (storage->storage_class == NULL) {
                *error_r = t_strconcat("Unknown shared storage driver: ",
@@ -63,7 +50,7 @@ static int shared_create(struct mail_storage *_storage, const char *data,
        }
        _storage->mailbox_is_file = storage->storage_class->mailbox_is_file;
 
-       wildcardp = strchr(_storage->ns->prefix, '%');
+       wildcardp = strchr(ns->prefix, '%');
        if (wildcardp == NULL) {
                *error_r = "Shared namespace prefix doesn't contain %";
                return -1;
@@ -93,19 +80,16 @@ static int shared_create(struct mail_storage *_storage, const char *data,
        /* truncate prefix after the above checks are done, so they can log
           the full prefix in error conditions */
        *wildcardp = '\0';
-
-       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, 0);
        return 0;
 }
 
+static void
+shared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
+                                struct mailbox_list_settings *set)
+{
+       set->layout = "shared";
+}
+
 static void
 get_nonexisting_user_location(struct shared_storage *storage,
                              const char *username, string_t *location)
@@ -116,17 +100,18 @@ get_nonexisting_user_location(struct shared_storage *storage,
        str_append_c(location, ':');
 
        /* use a reachable but non-existing path as the mail root directory */
-       str_append(location, storage->base_dir);
+       str_append(location, storage->storage.user->set->base_dir);
        str_append(location, "/user-not-found/");
        str_append(location, username);
 }
 
-int shared_storage_get_namespace(struct mail_storage *_storage,
-                                const char **_name,
-                                struct mail_namespace **ns_r)
+int shared_storage_get_namespace(struct mail_namespace **_ns,
+                                const char **_name)
 {
+       struct mail_storage *_storage = (*_ns)->storage;
+       struct mailbox_list *list = (*_ns)->list;
        struct shared_storage *storage = (struct shared_storage *)_storage;
-       struct mail_user *user = _storage->ns->user;
+       struct mail_user *user = _storage->user;
        static struct var_expand_table static_tab[] = {
                { 'u', NULL, "user" },
                { 'n', NULL, "username" },
@@ -135,7 +120,7 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
                { '\0', NULL, NULL }
        };
        struct var_expand_table *tab;
-       struct mail_namespace *ns;
+       struct mail_namespace *new_ns, *ns = *_ns;
        struct mail_namespace_settings *ns_set;
        struct mail_user *owner;
        const char *domain = NULL, *username = NULL, *userdomain = NULL;
@@ -143,8 +128,6 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
        string_t *prefix, *location;
        int ret;
 
-       *ns_r = NULL;
-
        p = storage->ns_prefix_pattern;
        for (name = *_name; *p != '\0';) {
                if (*p != '%') {
@@ -169,7 +152,7 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
                }
                p++;
 
-               next = strchr(name, *p != '\0' ? *p : _storage->ns->sep);
+               next = strchr(name, *p != '\0' ? *p : ns->sep);
                if (next == NULL) {
                        *dest = name;
                        name = "";
@@ -180,11 +163,11 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
        }
        if (*p != '\0') {
                if (*name == '\0' ||
-                   (name[1] == '\0' && *name == _storage->ns->sep)) {
+                   (name[1] == '\0' && *name == ns->sep)) {
                        /* trying to open <prefix>/<user> mailbox */
                        name = "INBOX";
                } else {
-                       mail_storage_set_critical(_storage,
+                       mailbox_list_set_critical(list,
                                        "Invalid namespace prefix %s vs %s",
                                        storage->ns_prefix_pattern, *_name);
                        return -1;
@@ -196,7 +179,7 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
                if (username == NULL) {
                        /* trying to open namespace "shared/domain"
                           namespace prefix. */
-                       mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+                       mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                                T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
                        return -1;
                }
@@ -212,7 +195,7 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
                }
        }
        if (*userdomain == '\0') {
-               mail_storage_set_error(_storage, MAIL_ERROR_PARAMS,
+               mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
                                       "Empty username doesn't exist");
                return -1;
        }
@@ -226,13 +209,12 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
        tab[2].value = domain;
 
        prefix = t_str_new(128);
-       str_append(prefix, _storage->ns->prefix);
+       str_append(prefix, ns->prefix);
        var_expand(prefix, storage->ns_prefix_pattern, tab);
 
-       ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
-       if (ns != NULL) {
+       *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
+       if (*_ns != NULL) {
                *_name = mail_namespace_fix_sep(ns, name);
-               *ns_r = ns;
                return 0;
        }
 
@@ -242,86 +224,90 @@ int shared_storage_get_namespace(struct mail_storage *_storage,
        else {
                /* we'll need to look up the user's home directory */
                if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
-                       mail_storage_set_critical(_storage, "Namespace '%s': "
+                       mailbox_list_set_critical(list, "Namespace '%s': "
                                "Could not lookup home for user %s",
-                               _storage->ns->prefix, userdomain);
+                               ns->prefix, userdomain);
                        mail_user_unref(&owner);
                        return -1;
                }
        }
        if (mail_user_init(owner, &error) < 0) {
-               mail_storage_set_critical(_storage,
+               mailbox_list_set_critical(list,
                        "Couldn't create namespace '%s' for user %s: %s",
-                       _storage->ns->prefix, userdomain, error);
+                       ns->prefix, userdomain, error);
                mail_user_unref(&owner);
                return -1;
        }
 
        /* create the new namespace */
-       ns = i_new(struct mail_namespace, 1);
-       ns->type = NAMESPACE_SHARED;
-       ns->user = user;
-       ns->prefix = i_strdup(str_c(prefix));
-       ns->owner = owner;
-       ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & _storage->ns->flags) |
+       new_ns = i_new(struct mail_namespace, 1);
+       new_ns->type = NAMESPACE_SHARED;
+       new_ns->user = user;
+       new_ns->prefix = i_strdup(str_c(prefix));
+       new_ns->owner = owner;
+       new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
                NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
                NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX;
-       ns->sep = _storage->ns->sep;
-       ns->mail_set = _storage->set;
+       new_ns->sep = ns->sep;
+       new_ns->mail_set = _storage->set;
 
        location = t_str_new(256);
        if (ret > 0)
                var_expand(location, storage->location, tab);
        else {
                get_nonexisting_user_location(storage, userdomain, location);
-               ns->flags |= NAMESPACE_FLAG_UNUSABLE;
+               new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
        }
 
        ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
        ns_set->type = "shared";
-       ns_set->separator = p_strdup_printf(user->pool, "%c", ns->sep);
-       ns_set->prefix = ns->prefix;
+       ns_set->separator = p_strdup_printf(user->pool, "%c", new_ns->sep);
+       ns_set->prefix = new_ns->prefix;
        ns_set->location = p_strdup(user->pool, str_c(location));
        ns_set->hidden = TRUE;
        ns_set->list = "yes";
-       ns->set = ns_set;
+       new_ns->set = ns_set;
 
-       if (mail_storage_create(ns, NULL, _storage->flags, &error) < 0) {
-               mail_storage_set_critical(_storage, "Namespace '%s': %s",
-                                         ns->prefix, error);
-               mail_namespace_destroy(ns);
+       if (mail_storage_create(new_ns, NULL, _storage->flags, &error) < 0) {
+               mailbox_list_set_critical(list, "Namespace '%s': %s",
+                                         new_ns->prefix, error);
+               mail_namespace_destroy(new_ns);
                return -1;
        }
-       _storage->ns->flags |= NAMESPACE_FLAG_USABLE;
-       *_name = mail_namespace_fix_sep(ns, name);
-       *ns_r = ns;
+       ns->flags |= NAMESPACE_FLAG_USABLE;
+       *_name = mail_namespace_fix_sep(new_ns, name);
+       *_ns = new_ns;
 
-       mail_user_add_namespace(user, &ns);
+       mail_user_add_namespace(user, &new_ns);
        return 0;
 }
 
-static void shared_mailbox_copy_error(struct mail_storage *shared_storage,
-                                     struct mail_namespace *backend_ns)
+static int
+shared_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
+                     const char *name, bool directory)
 {
+       struct mail_namespace *ns = list->ns;
+       struct mailbox_list *new_list;
+       struct mail_storage *new_storage;
        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 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)
+       if (shared_storage_get_namespace(&ns, &name) < 0) {
+               str = mailbox_list_get_last_error(list, &error);
+               mail_storage_set_error(storage, error, str);
                return -1;
+       }
 
-       ret = mail_storage_mailbox_create(ns->storage, name, directory);
-       if (ret < 0)
-               shared_mailbox_copy_error(storage, ns);
+       new_list = ns->list;
+       if (mailbox_list_get_storage(&new_list, &name, &new_storage) < 0)
+               return -1;
+
+       ret = mail_storage_mailbox_create(new_storage, ns, name, directory);
+       if (ret < 0) {
+               str = mail_storage_get_last_error(new_storage, &error);
+               mail_storage_set_error(storage, error, str);
+       }
        return ret;
 }
 
@@ -333,9 +319,10 @@ struct mail_storage shared_storage = {
                NULL,
                NULL,
                NULL,
-               shared_alloc,
-               shared_create,
+               shared_storage_alloc,
+               shared_storage_create,
                index_storage_destroy,
+               shared_storage_get_list_settings,
                NULL,
                NULL,
                shared_mailbox_create,
index 2dfcd29c78781a43253f626a6c0db983ca3700f8..a2d153395f02c80c2968670605f155eb2ab4e1c2 100644 (file)
@@ -9,7 +9,6 @@ struct shared_storage {
        struct mail_storage storage;
        union mailbox_list_module_context list_module_ctx;
 
-       const char *base_dir;
        const char *ns_prefix_pattern;
        const char *location;
 
@@ -19,8 +18,7 @@ struct shared_storage {
 struct mailbox_list *shared_mailbox_list_alloc(void);
 
 /* Returns -1 = error, 0 = user doesn't exist, 1 = ok */
-int shared_storage_get_namespace(struct mail_storage *storage,
-                                const char **name,
-                                struct mail_namespace **ns_r);
+int shared_storage_get_namespace(struct mail_namespace **_ns,
+                                const char **_name);
 
 #endif
index 245178e5958fd90c3aa9c60b232ebb41a2cea5b7..e13ddfb81ce5109d1e721188b7d97b063a89fa2a 100644 (file)
@@ -86,14 +86,12 @@ index_list_mailbox_open_unchanged_view(struct mailbox *box,
                                       struct mail_index_view **view_r,
                                       uint32_t *seq_r)
 {
-       struct mailbox_list *list;
        struct index_mailbox_list *ilist;
        struct mail_index_view *view;
        uint32_t uid, seq;
        int ret;
 
-       list = mail_storage_get_list(box->storage);
-       ilist = INDEX_LIST_CONTEXT(list);
+       ilist = INDEX_LIST_CONTEXT(box->list);
 
        if (ilist == NULL) {
                /* indexing disabled */
@@ -132,7 +130,6 @@ index_list_mailbox_open_unchanged_view(struct mailbox *box,
 static int
 index_list_get_cached_status(struct mailbox *box, struct mailbox_status *status)
 {
-       struct mailbox_list *list;
        struct index_mailbox_list *ilist;
        struct mail_index_view *view;
        const void *data;
@@ -147,8 +144,7 @@ index_list_get_cached_status(struct mailbox *box, struct mailbox_status *status)
        if (ret <= 0)
                return ret;
 
-       list = mail_storage_get_list(box->storage);
-       ilist = INDEX_LIST_CONTEXT(list);
+       ilist = INDEX_LIST_CONTEXT(box->list);
        for (i = 0; index_list_map[i].name != NULL; i++) {
                ext_id_p = PTR_OFFSET(ilist, index_list_map[i].eid_offset);
                mail_index_lookup_ext(view, seq, *ext_id_p, &data, &expunged);
@@ -312,7 +308,6 @@ static int index_list_sync_deinit(struct mailbox_sync_context *ctx,
 {
        struct mailbox *box = ctx->box;
        struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
-       struct mailbox_list *list;
        struct index_mailbox_list *ilist;
        struct mail_index_view *view;
        struct mailbox_status tmp_status, *status;
@@ -327,8 +322,7 @@ static int index_list_sync_deinit(struct mailbox_sync_context *ctx,
                return 0;
        }
 
-       list = mail_storage_get_list(box->storage);
-       ilist = INDEX_LIST_CONTEXT(list);
+       ilist = INDEX_LIST_CONTEXT(box->list);
 
        if (ilist == NULL) {
                /* indexing disabled */
@@ -361,7 +355,7 @@ static int index_list_sync_deinit(struct mailbox_sync_context *ctx,
 static void index_list_mail_mailbox_opened(struct mailbox *box)
 {
        struct index_mailbox_list *ilist =
-               INDEX_LIST_CONTEXT(box->storage->list);
+               INDEX_LIST_CONTEXT(box->list);
        struct index_list_mailbox *ibox;
 
        if (index_list_next_hook_mailbox_created != NULL)
index 4d0681a89c368ffcb223d40e2b442c4547c8a13b..edb2e041992fe7aec82dd3e70335e267c091d553 100644 (file)
@@ -457,25 +457,19 @@ static int index_mailbox_list_open_indexes(struct mailbox_list *list,
        struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(list);
        const char *path;
        enum mail_index_open_flags index_flags = 0;
-       enum file_lock_method lock_method;
+       enum file_lock_method lock_method = list->mail_set->parsed_lock_method;
        int ret;
 
        index_flags = mail_storage_settings_to_index_flags(list->mail_set);
 
-       if (!file_lock_method_parse(list->mail_set->lock_method,
-                                   &lock_method)) {
-               i_error("Unknown lock_method: %s", list->mail_set->lock_method);
-               return -1;
-       }
-
        if (mail_index_open_or_create(ilist->mail_index, index_flags,
-                                     *list->set.lock_method) < 0) {
+                                     lock_method) < 0) {
                if (mail_index_move_to_memory(ilist->mail_index) < 0) {
                        /* try opening once more. it should be created
                           directly into memory now. */
                        ret = mail_index_open_or_create(ilist->mail_index,
                                                        index_flags,
-                                                       *list->set.lock_method);
+                                                       lock_method);
                        if (ret < 0) {
                                /* everything failed. there's a bug in the
                                   code, but just work around it by disabling
index 0cabff94ce0ac5279bdeb9c1e092a2f8b380f687..5bb65a6fe094d1f94196e40a4a7f6e1038b72490 100644 (file)
@@ -313,18 +313,21 @@ static int fs_list_rename_mailbox(struct mailbox_list *oldlist,
                                  struct mailbox_list *newlist,
                                  const char *newname, bool rename_children)
 {
+       struct mail_storage *oldstorage;
        const char *oldpath, *newpath, *p;
        enum mailbox_list_path_type path_type;
        struct stat st;
        mode_t mode;
        gid_t gid;
-       bool isfile, rmdir_parent = FALSE;
+       bool rmdir_parent = FALSE;
+
+       if (mailbox_list_get_storage(&oldlist, &oldname, &oldstorage) < 0)
+               return -1;
 
-       (void)mail_storage_get_mailbox_path(oldlist->ns->storage,
-                                           oldname, &isfile);
        if (rename_children)
                path_type = MAILBOX_LIST_PATH_TYPE_DIR;
-       else if (isfile || *oldlist->set.maildir_name != '\0')
+       else if (mail_storage_is_mailbox_file(oldstorage) ||
+                *oldlist->set.maildir_name != '\0')
                path_type = MAILBOX_LIST_PATH_TYPE_MAILBOX;
        else {
                /* we can't do this, our children would get renamed with us */
@@ -410,7 +413,7 @@ static int fs_list_rename_mailbox(struct mailbox_list *oldlist,
 }
 
 struct mailbox_list fs_mailbox_list = {
-       MEMBER(name) "fs",
+       MEMBER(name) MAILBOX_LIST_NAME_FS,
        MEMBER(hierarchy_sep) '/',
        MEMBER(props) 0,
        MEMBER(mailbox_name_max_length) PATH_MAX,
index 14b6f74cbc4299e9d9acee7d5a412827ab4284f1..84261314112ce26880de1ca157da8454b3559e07 100644 (file)
@@ -3,9 +3,6 @@
 
 #include "mailbox-list-private.h"
 
-#define MAILBOX_LIST_NAME_MAILDIRPLUSPLUS "maildir++"
-#define MAILBOX_LIST_NAME_IMAPDIR "imapdir"
-
 /* Don't allow creating too long mailbox names. They could start causing
    problems when they reach the limit. */
 #define MAILDIR_MAX_CREATE_MAILBOX_NAME_LENGTH (PATH_MAX/2)
index 8a5f5ed57786c31ff35fc4f908854e1cf3bc5b39..f35512b77a09ac1fc11a8f973e4e95eb88a82b01 100644 (file)
 
 void (*hook_mail_namespaces_created)(struct mail_namespace *namespaces);
 
-void mail_namespace_init_storage(struct mail_namespace *ns)
+void mail_namespace_add_storage(struct mail_namespace *ns,
+                               struct mail_storage *storage)
 {
-       ns->list = mail_storage_get_list(ns->storage);
+       /* currently we support only a single storage */
+       i_assert(ns->storage == NULL);
+       ns->storage = storage;
+}
+
+void mail_namespace_finish_list_init(struct mail_namespace *ns,
+                                    struct mailbox_list *list)
+{
+       ns->list = list;
+       ns->real_sep = mailbox_list_get_hierarchy_sep(list);
        ns->prefix_len = strlen(ns->prefix);
-       ns->real_sep = mailbox_list_get_hierarchy_sep(ns->list);
 
        if (ns->set->separator != NULL)
                ns->sep = *ns->set->separator;
        if (ns->sep == '\0')
                 ns->sep = ns->real_sep;
-
        if (ns->sep == '"' || ns->sep == '\\') {
                ns->sep_str[0] = '\\';
                ns->sep_str[1] = ns->sep;
@@ -33,6 +41,11 @@ void mail_namespace_init_storage(struct mail_namespace *ns)
 
 static void mail_namespace_free(struct mail_namespace *ns)
 {
+       if (ns->storage != NULL)
+               mail_storage_destroy(&ns->storage);
+       if (ns->list != NULL)
+               mailbox_list_destroy(&ns->list);
+
        if (ns->owner != ns->user && ns->owner != NULL)
                mail_user_unref(&ns->owner);
        i_free(ns->prefix);
@@ -320,12 +333,20 @@ void mail_namespaces_deinit(struct mail_namespace **_namespaces)
                ns = namespaces;
                namespaces = namespaces->next;
 
-               if (ns->storage != NULL)
-                       mail_storage_destroy(&ns->storage);
                mail_namespace_free(ns);
        }
 }
 
+void mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces,
+                                          struct mail_storage_callbacks *callbacks,
+                                          void *context)
+{
+       struct mail_namespace *ns;
+
+       for (ns = namespaces; ns != NULL; ns = ns->next)
+               mail_storage_set_callbacks(ns->storage, callbacks, context);
+}
+
 void mail_namespace_destroy(struct mail_namespace *ns)
 {
        struct mail_namespace **nsp;
@@ -376,7 +397,14 @@ const char *mail_namespace_get_vname(struct mail_namespace *ns, string_t *dest,
        return str_c(dest);
 }
 
-char mail_namespace_get_root_sep(const struct mail_namespace *namespaces)
+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;
+}
+
+char mail_namespaces_get_root_sep(const struct mail_namespace *namespaces)
 {
        while ((namespaces->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0)
                namespaces = namespaces->next;
index b95c454879daff10cf1b0e30f5ba516635592edd..686dcf3133475228a8a96204e32b7825c1591fa1 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "mail-user.h"
 
+struct mail_storage_callbacks;
+
 enum namespace_type {
        NAMESPACE_PRIVATE,
        NAMESPACE_SHARED,
@@ -73,6 +75,14 @@ struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user);
    for user's namespaces. */
 void mail_namespaces_deinit(struct mail_namespace **namespaces);
 
+/* Set storage callback functions to use in all namespaces. */
+void mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces,
+                                          struct mail_storage_callbacks *callbacks,
+                                          void *context);
+
+/* Add a new storage to namespace. */
+void mail_namespace_add_storage(struct mail_namespace *ns,
+                               struct mail_storage *storage);
 /* Destroy a single namespace and remove it from user's namespaces list. */
 void mail_namespace_destroy(struct mail_namespace *ns);
 
@@ -82,9 +92,12 @@ const char *mail_namespace_fix_sep(struct mail_namespace *ns, const char *name);
    virtual ones and namespace prefix is inserted except for INBOX. */
 const char *mail_namespace_get_vname(struct mail_namespace *ns, string_t *dest,
                                     const char *name);
+/* Returns the default storage to use for newly created mailboxes. */
+struct mail_storage *
+mail_namespace_get_default_storage(struct mail_namespace *ns);
 
 /* Returns the hierarchy separator for mailboxes that are listed at root. */
-char mail_namespace_get_root_sep(const struct mail_namespace *namespaces)
+char mail_namespaces_get_root_sep(const struct mail_namespace *namespaces)
        ATTR_PURE;
 
 /* Returns namespace based on the mailbox name's prefix. Updates mailbox to
@@ -121,7 +134,8 @@ struct mail_namespace *
 mail_namespace_find_prefix_nosep(struct mail_namespace *namespaces,
                                 const char *prefix);
 
-/* Called internally by mail_storage_create(). */
-void mail_namespace_init_storage(struct mail_namespace *ns);
+/* Called internally by mailbox_list_create(). */
+void mail_namespace_finish_list_init(struct mail_namespace *ns,
+                                    struct mailbox_list *list);
 
 #endif
index 15a25718c86f8f384e69739758bada83ba7a289a..18a9db0f9ba0f60146fba2bcc73a279f70d8239a 100644 (file)
@@ -32,18 +32,23 @@ struct mail_storage_vfuncs {
        void (*class_deinit)(void);
 
        struct mail_storage *(*alloc)(void);
-       int (*create)(struct mail_storage *storage, const char *data,
+       int (*create)(struct mail_storage *storage, struct mail_namespace *ns,
                      const char **error_r);
        void (*destroy)(struct mail_storage *storage);
 
-       bool (*autodetect)(const struct mail_namespace *ns);
+       void (*get_list_settings)(const struct mail_namespace *ns,
+                                 struct mailbox_list_settings *set);
+       bool (*autodetect)(const struct mail_namespace *ns,
+                          struct mailbox_list_settings *set);
 
        struct mailbox *(*mailbox_open)(struct mail_storage *storage,
+                                       struct mailbox_list *list,
                                        const char *name,
                                        struct istream *input,
                                        enum mailbox_open_flags flags);
 
-       int (*mailbox_create)(struct mail_storage *storage, const char *name,
+       int (*mailbox_create)(struct mail_storage *storage,
+                             struct mailbox_list *list, const char *name,
                              bool directory);
        int (*purge)(struct mail_storage *storage);
 };
@@ -66,13 +71,11 @@ struct mail_storage {
        enum mail_error error;
 
         const struct mail_storage *storage_class;
-       struct mail_namespace *ns;
-       struct mailbox_list *list;
+       struct mail_user *user;
        const char *temp_path_prefix;
        const struct mail_storage_settings *set;
 
        enum mail_storage_flags flags;
-       enum file_lock_method lock_method;
 
        struct mail_storage_callbacks *callbacks;
        void *callback_context;
@@ -197,6 +200,7 @@ union mailbox_module_context {
 struct mailbox {
        char *name;
        struct mail_storage *storage;
+       struct mailbox_list *list;
 
         struct mailbox_vfuncs v;
 /* private: */
index 44f8c369eac4987dfe922803bece8437536d2543..e5081bdc337cb9848040cf737b3fee44f2a8bc4f 100644 (file)
@@ -224,7 +224,7 @@ mail_user_set_get_storage_set(const struct mail_user_settings *set)
 
 const void *mail_storage_get_driver_settings(struct mail_storage *storage)
 {
-       return mail_user_set_get_driver_settings(storage->ns->user->set,
+       return mail_user_set_get_driver_settings(storage->user->set,
                                                 storage->name);
 }
 
@@ -279,7 +279,7 @@ fix_base_path(struct mail_user_settings *set, pool_t pool, const char **str)
 static bool mail_storage_settings_check(void *_set, pool_t pool ATTR_UNUSED,
                                        const char **error_r)
 {
-       const struct mail_storage_settings *set = _set;
+       struct mail_storage_settings *set = _set;
        const char *p;
        bool uidl_format_ok;
        char c;
@@ -293,6 +293,13 @@ static bool mail_storage_settings_check(void *_set, pool_t pool ATTR_UNUSED,
                return FALSE;
        }
 
+       if (!file_lock_method_parse(set->lock_method,
+                                   &set->parsed_lock_method)) {
+               *error_r = t_strdup_printf("Unknown lock_method: %s",
+                                          set->lock_method);
+               return FALSE;
+       }
+
        uidl_format_ok = FALSE;
        for (p = set->pop3_uidl_format; *p != '\0'; p++) {
                if (p[0] != '%' || p[1] == '\0')
@@ -332,8 +339,7 @@ static bool namespace_settings_check(void *_set, pool_t pool ATTR_UNUSED,
 
        name = ns->prefix != NULL ? ns->prefix : "";
 
-       if (ns->separator != NULL &&
-           ns->separator[0] != '\0' && ns->separator[1] != '\0') {
+       if (ns->separator[0] != '\0' && ns->separator[1] != '\0') {
                *error_r = t_strdup_printf("Namespace '%s': "
                        "Hierarchy separator must be only one character long",
                        name);
index 62135bf7952bc8e6c256b77234f79d3a583caba8..f64ffcf3cde46976f27b19d1a78b2e45a14bd2ec 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MAIL_STORAGE_SETTINGS_H
 #define MAIL_STORAGE_SETTINGS_H
 
+#include "file-lock.h"
+
 struct mail_user;
 struct mail_storage;
 
@@ -22,6 +24,8 @@ struct mail_storage_settings {
        bool mail_full_filesystem_access;
        const char *lock_method;
        const char *pop3_uidl_format;
+
+       enum file_lock_method parsed_lock_method;
 };
 
 struct mail_namespace_settings {
index 66c97c67b7a1e3f5ff44a3a6760300f734a6851c..fffb516ffc6bfa8d2236a20c3768f5285993159a 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "array.h"
+#include "mkdir-parents.h"
 #include "var-expand.h"
 #include "mail-index-private.h"
 #include "mailbox-list-private.h"
@@ -83,23 +84,24 @@ struct mail_storage *mail_storage_find_class(const char *name)
 }
 
 static struct mail_storage *
-mail_storage_autodetect(const struct mail_namespace *ns)
+mail_storage_autodetect(const struct mail_namespace *ns,
+                       struct mailbox_list_settings *set)
 {
        struct mail_storage *const *classes;
        unsigned int i, count;
 
        classes = array_get(&mail_storage_classes, &count);
        for (i = 0; i < count; i++) {
-               if (classes[i]->v.autodetect != NULL &&
-                   classes[i]->v.autodetect(ns))
-                       return classes[i];
+               if (classes[i]->v.autodetect != NULL) {
+                       if (classes[i]->v.autodetect(ns, set))
+                               return classes[i];
+               }
        }
        return NULL;
 }
 
 static void
-mail_storage_set_autodetection(const char **data, const char **driver,
-                              enum mail_storage_flags *flags)
+mail_storage_set_autodetection(const char **data, const char **driver)
 {
        const char *p;
 
@@ -108,22 +110,100 @@ mail_storage_set_autodetection(const char **data, const char **driver,
        while (i_isalnum(*p)) p++;
 
        if (*p == ':' && p != *data) {
-               /* no autodetection if the storage format is given. */
-               *flags |= MAIL_STORAGE_FLAG_NO_AUTODETECTION;
-
+               /* no autodetection if the storage driver is given. */
                *driver = t_strdup_until(*data, p);
                *data = p + 1;
        }
 }
 
+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)
+{
+       struct mail_storage *storage_class;
+       const char *home;
+
+       if (driver != NULL) {
+               storage_class = mail_storage_find_class(driver);
+               if (storage_class == NULL) {
+                       *error_r = t_strdup_printf(
+                               "Unknown mail storage driver %s", driver);
+               }
+               i_assert(list_set->root_dir != NULL);
+               storage_class->v.get_list_settings(ns, list_set);
+               return storage_class;
+       }
+
+       storage_class = mail_storage_autodetect(ns, list_set);
+       if (storage_class != NULL)
+               return storage_class;
+
+       if (ns->set->location == NULL || *ns->set->location == '\0') {
+               (void)mail_user_get_home(ns->user, &home);
+               if (home == NULL || *home == '\0') home = "(not set)";
+
+               *error_r = t_strdup_printf(
+                       "Mail storage autodetection failed with home=%s", home);
+       } else {
+               *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:)",
+                       ns->set->location);
+       }
+       return NULL;
+}
+
+static int
+mail_storage_create_root(struct mailbox_list *list,
+                        enum mail_storage_flags flags, const char **error_r)
+{
+       const char *root_dir;
+       struct stat st;
+       mode_t mode;
+       gid_t gid;
+
+       root_dir = mailbox_list_get_path(list, NULL,
+                                        MAILBOX_LIST_PATH_TYPE_MAILBOX);
+       if (stat(root_dir, &st) == 0) {
+               /* ok */
+               return 0;
+       } else if (errno == EACCES) {
+               *error_r = mail_error_eacces_msg("stat", root_dir);
+               return -1;
+       } else if (errno != ENOENT && errno != ENOTDIR) {
+               *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
+               return -1;
+       } else if (list->ns->type == NAMESPACE_SHARED) {
+               /* can't create a new user, but we don't want to fail
+                  the storage creation. */
+       } else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
+               *error_r = t_strdup_printf(
+                       "Root mail directory doesn't exist: %s", root_dir);
+               return -1;
+       }
+
+       /* we need to create the root directory. */
+       mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
+       if (mkdir_parents_chown(root_dir, mode, (uid_t)-1, gid) < 0 &&
+           errno != EEXIST) {
+               *error_r = mail_error_create_eacces_msg("mkdir", root_dir);
+               return -1;
+       } else {
+               /* created */
+               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_class, *storage = NULL;
-       struct mail_storage *const *classes;
+       struct mailbox_list_settings list_set;
+       enum mailbox_list_flags list_flags = 0;
        const char *data = ns->set->location;
-       const char *home, *p;
-       unsigned int i, count;
+       const char *p;
 
        if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
            ns->mail_set->pop3_uidl_format != NULL) {
@@ -141,87 +221,60 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                }
        }
 
+       memset(&list_set, 0, sizeof(list_set));
        if (data == NULL)
                data = "";
-       else if (driver == NULL)
-               mail_storage_set_autodetection(&data, &driver, &flags);
-
-       if (*data == '\0' && driver == NULL) {
-               /* use the first driver that works */
-               classes = array_get(&mail_storage_classes, &count);
-       } else if (driver == NULL) {
-               storage_class = mail_storage_autodetect(ns);
-               if (storage_class == NULL) {
-                       *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);
+       else {
+               if (driver == NULL)
+                       mail_storage_set_autodetection(&data, &driver);
+               if (mailbox_list_settings_parse(data, &list_set, ns,
+                                               error_r) < 0)
                        return -1;
-               }
-               classes = &storage_class;
-               count = 1;
-       } else {
-               storage_class = mail_storage_find_class(driver);
-               if (storage_class == NULL) {
-                       *error_r = t_strdup_printf(
-                               "Unknown mail storage driver %s", driver);
-                       return -1;
-               }
-               classes = &storage_class;
-               count = 1;
        }
 
-       for (i = 0; i < count; i++) {
-               storage = classes[i]->v.alloc();
-               storage->set = ns->mail_set;
-               storage->flags = flags;
-               if (!file_lock_method_parse(storage->set->lock_method,
-                                           &storage->lock_method)) {
-                       i_fatal("Unknown lock_method: %s",
-                               storage->set->lock_method);
-               }
-               storage->ns = ns;
+       if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0 &&
+           list_set.root_dir == NULL) {
+               *error_r = "Root mail directory not given";
+               return -1;
+       }
 
-               storage->callbacks =
-                       p_new(storage->pool, struct mail_storage_callbacks, 1);
-               p_array_init(&storage->module_contexts, storage->pool, 5);
+       storage_class = mail_storage_get_class(ns, driver, &list_set, error_r);
+       if (storage_class == NULL)
+               return -1;
+       i_assert(list_set.layout != NULL);
+
+       if (ns->list == NULL) {
+               /* first storage for namespace */
+               if (mail_storage_is_mailbox_file(storage_class))
+                       list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
+               if (mailbox_list_create(list_set.layout, ns, &list_set,
+                                       list_flags, error_r) < 0)
+                       return -1;
+               if (mail_storage_create_root(ns->list, flags, error_r) < 0)
+                       return -1;
+       }
 
-               if (classes[i]->v.create(storage, data, error_r) == 0)
-                       break;
+       storage = storage_class->v.alloc();
+       storage->storage_class = storage_class;
+       storage->user = ns->user;
+       storage->set = ns->mail_set;
+       storage->flags = flags;
 
-               if (ns->mail_set->mail_debug && count > 1) {
-                       i_info("%s: Couldn't create mail storage %s: %s",
-                              classes[i]->name, data, *error_r);
-               }
+       storage->callbacks =
+               p_new(storage->pool, struct mail_storage_callbacks, 1);
+       p_array_init(&storage->module_contexts, storage->pool, 5);
 
-               /* try the next one */
+       if (storage->v.create(storage, ns, error_r) < 0) {
+               *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
                pool_unref(&storage->pool);
-       }
-       if (i == count) {
-               if (count <= 1) {
-                       *error_r = t_strdup_printf("%s: %s", classes[0]->name,
-                                                  *error_r);
-                       return -1;
-               }
-
-               (void)mail_user_get_home(ns->user, &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) T_BEGIN {
+               hook_mail_storage_created(storage);
+       } T_END;
 
-       if (hook_mail_storage_created != NULL) {
-               T_BEGIN {
-                       hook_mail_storage_created(storage);
-               } T_END;
-       }
-
-       ns->storage = storage;
-        mail_namespace_init_storage(ns);
+        mail_namespace_add_storage(ns, storage);
        return 0;
 }
 
@@ -234,7 +287,6 @@ void mail_storage_destroy(struct mail_storage **_storage)
        *_storage = NULL;
 
        storage->v.destroy(storage);
-       mailbox_list_deinit(storage->list);
        i_free(storage->error_string);
        pool_unref(&storage->pool);
 }
@@ -287,22 +339,6 @@ void mail_storage_set_critical(struct mail_storage *storage,
        }
 }
 
-char mail_storage_get_hierarchy_sep(struct mail_storage *storage)
-{
-       return mailbox_list_get_hierarchy_sep(storage->list);
-}
-
-struct mailbox_list *mail_storage_get_list(const struct mail_storage *storage)
-{
-       return storage->list;
-}
-
-struct mail_namespace *
-mail_storage_get_namespace(const struct mail_storage *storage)
-{
-       return storage->ns;
-}
-
 const struct mail_storage_settings *
 mail_storage_get_settings(struct mail_storage *storage)
 {
@@ -317,18 +353,19 @@ void mail_storage_set_callbacks(struct mail_storage *storage,
        storage->callback_context = context;
 }
 
-int mail_storage_mailbox_create(struct mail_storage *storage, const char *name,
+int mail_storage_mailbox_create(struct mail_storage *storage,
+                               struct mail_namespace *ns, const char *name,
                                bool directory)
 {
        mail_storage_clear_error(storage);
 
-       if (!mailbox_list_is_valid_create_name(storage->list, name)) {
+       if (!mailbox_list_is_valid_create_name(ns->list, name)) {
                mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
                                       "Invalid mailbox name");
                return -1;
        }
 
-       return storage->v.mailbox_create(storage, name, directory);
+       return storage->v.mailbox_create(storage, ns->list, name, directory);
 }
 
 int mail_storage_purge(struct mail_storage *storage)
@@ -364,50 +401,9 @@ const char *mail_storage_get_last_error(struct mail_storage *storage,
        return storage->error_string;
 }
 
-const char *mail_storage_get_mailbox_path(struct mail_storage *storage,
-                                         const char *name, bool *is_file_r)
+bool mail_storage_is_mailbox_file(struct mail_storage *storage)
 {
-       *is_file_r = storage->mailbox_is_file;
-
-       if (*name == '\0')
-               name = NULL;
-
-       return mailbox_list_get_path(storage->list, name,
-                                    MAILBOX_LIST_PATH_TYPE_MAILBOX);
-}
-
-const char *mail_storage_get_mailbox_control_dir(struct mail_storage *storage,
-                                                const char *name)
-{
-       if (*name == '\0')
-               name = NULL;
-
-       return mailbox_list_get_path(storage->list, name,
-                                    MAILBOX_LIST_PATH_TYPE_CONTROL);
-}
-
-const char *mail_storage_get_mailbox_index_dir(struct mail_storage *storage,
-                                              const char *name)
-{
-       if (*name == '\0')
-               name = NULL;
-
-       return mailbox_list_get_path(storage->list, name,
-                                    MAILBOX_LIST_PATH_TYPE_INDEX);
-}
-
-const char *mail_storage_get_temp_prefix(struct mail_storage *storage)
-{
-       const char *dir;
-
-       if (storage->temp_path_prefix == NULL) {
-               dir = mailbox_list_get_path(storage->list, NULL,
-                                           MAILBOX_LIST_PATH_TYPE_DIR);
-               storage->temp_path_prefix = p_strconcat(storage->pool, dir, "/",
-                       mailbox_list_get_temp_prefix(storage->list), NULL);
-       }
-
-       return storage->temp_path_prefix;
+       return storage->mailbox_is_file;
 }
 
 bool mail_storage_set_error_from_errno(struct mail_storage *storage)
@@ -428,36 +424,41 @@ bool mail_storage_set_error_from_errno(struct mail_storage *storage)
        return TRUE;
 }
 
-struct mailbox *mailbox_open(struct mail_storage **_storage, const char *name,
+struct mailbox *mailbox_open(struct mailbox_list *list, const char *name,
                             struct istream *input,
                             enum mailbox_open_flags flags)
 {
-       struct mail_storage *storage = *_storage;
+       struct mailbox_list *new_list = list;
+       struct mail_storage *storage;
        struct mailbox *box;
 
-       if (storage->list->v.get_storage != NULL) {
-               if (storage->list->v.get_storage(storage->list,
-                                                &name, &storage) < 0)
-                       return NULL;
-               *_storage = storage;
-       }
+       if (mailbox_list_get_storage(&new_list, &name, &storage) < 0)
+               return NULL;
 
-       mail_storage_clear_error(storage);
+       mailbox_list_clear_error(list);
 
-       if (!mailbox_list_is_valid_existing_name(storage->list, name)) {
-               mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
+       if (!mailbox_list_is_valid_existing_name(new_list, name)) {
+               mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
                                       "Invalid mailbox name");
                return NULL;
        }
 
        T_BEGIN {
-               box = storage->v.mailbox_open(storage, name, input, flags);
+               box = storage->v.mailbox_open(storage, new_list,
+                                             name, input, flags);
                if (hook_mailbox_opened != NULL && box != NULL)
                        hook_mailbox_opened(box);
        } T_END;
 
        if (box != NULL)
-               box->storage->ns->flags |= NAMESPACE_FLAG_USABLE;
+               box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
+       else if (new_list != list) {
+               const char *str;
+               enum mail_error error;
+
+               str = mailbox_list_get_last_error(new_list, &error);
+               mailbox_list_set_error(list, error, str);
+       }
        return box;
 }
 
@@ -489,6 +490,12 @@ struct mail_storage *mailbox_get_storage(const struct mailbox *box)
        return box->storage;
 }
 
+struct mail_namespace *
+mailbox_get_namespace(const struct mailbox *box)
+{
+       return box->list->ns;
+}
+
 const struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
 {
        return box->storage->set;
@@ -661,7 +668,7 @@ void mailbox_get_virtual_box_patterns(struct mailbox *box,
                struct mailbox_virtual_pattern pat;
 
                memset(&pat, 0, sizeof(pat));
-               pat.ns = box->storage->ns;
+               pat.ns = box->list->ns;
                pat.pattern = box->name;
                array_append(includes, &pat, 1);
        } else {
index b1f0dc66897a4c4fa5e9c8e397288adc03ed8266..40bfe5475894dc7ad6c36bb7fbd52253195eb0f4 100644 (file)
@@ -261,14 +261,6 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                        enum mail_storage_flags flags, const char **error_r);
 void mail_storage_destroy(struct mail_storage **storage);
 
-/* Returns the storage's real hierarchy separator. */
-char mail_storage_get_hierarchy_sep(struct mail_storage *storage);
-/* Returns the storage's mailbox list backend. */
-struct mailbox_list *
-mail_storage_get_list(const struct mail_storage *storage) ATTR_PURE;
-/* Returns the storage's namespace. */
-struct mail_namespace *
-mail_storage_get_namespace(const struct mail_storage *storage) ATTR_PURE;
 /* Returns the mail storage settings. */
 const struct mail_storage_settings *
 mail_storage_get_settings(struct mail_storage *storage) ATTR_PURE;
@@ -282,7 +274,8 @@ void mail_storage_set_callbacks(struct mail_storage *storage,
    If directory is TRUE, the mailbox should be created so that it
    can contain children. The mailbox itself doesn't have to be
    created as long as it shows in LIST. */
-int mail_storage_mailbox_create(struct mail_storage *storage, const char *name,
+int mail_storage_mailbox_create(struct mail_storage *storage,
+                               struct mail_namespace *ns, const char *name,
                                bool directory);
 /* Purge storage's mailboxes (freeing disk space from expunged mails),
    if supported by the storage. Otherwise just a no-op. */
@@ -292,33 +285,16 @@ int mail_storage_purge(struct mail_storage *storage);
 const char *mail_storage_get_last_error(struct mail_storage *storage,
                                        enum mail_error *error_r);
 
-/* Returns path to the given mailbox, or NULL if mailbox doesn't exist in
-   filesystem. is_file_r is set to TRUE if returned path points to a file,
-   and FALSE if it points to a directory. If name is "", the root storage
-   directory is returned. */
-const char *mail_storage_get_mailbox_path(struct mail_storage *storage,
-                                         const char *name, bool *is_file_r);
-/* Returns path to the control directory of the mailbox, or NULL if mailbox
-   doesn't exist in filesystem. */
-const char *mail_storage_get_mailbox_control_dir(struct mail_storage *storage,
-                                                const char *name);
-/* Returns path to the index directory of the mailbox, or NULL if using
-   in-memory indexes or mailbox doesn't exist. */
-const char *mail_storage_get_mailbox_index_dir(struct mail_storage *storage,
-                                              const char *name);
-/* Returns path + file prefix for creating a temporary file. */
-const char *mail_storage_get_temp_prefix(struct mail_storage *storage);
+/* Returns TRUE if mailboxes are files. */
+bool mail_storage_is_mailbox_file(struct mail_storage *storage) ATTR_PURE;
 
 /* Open a mailbox. If input stream is given, mailbox is opened read-only
    using it as a backend. If storage doesn't support stream backends and its
    tried to be used, NULL is returned.
 
    Note that append and copy may open the selected mailbox again
-   with possibly different readonly-state.
-
-   Given storage is a pointer-to-pointer because it may change as a result of
-   a new namespace being created for shared mailboxes. */
-struct mailbox *mailbox_open(struct mail_storage **storage, const char *name,
+   with possibly different readonly-state. */
+struct mailbox *mailbox_open(struct mailbox_list *list, const char *name,
                             struct istream *input,
                             enum mailbox_open_flags flags);
 /* Close the box. Returns -1 if some cleanup errors occurred, but
@@ -333,6 +309,9 @@ mailbox_get_enabled_features(struct mailbox *box) ATTR_PURE;
 
 /* Returns storage of given mailbox */
 struct mail_storage *mailbox_get_storage(const struct mailbox *box) ATTR_PURE;
+/* Return namespace of given mailbox. */
+struct mail_namespace *
+mailbox_get_namespace(const struct mailbox *box) ATTR_PURE;
 /* Returns the storage's settings. */
 const struct mail_storage_settings *
 mailbox_get_settings(struct mailbox *box) ATTR_PURE;
index 0113528fa07e200d1ad553df10b343ae5203921d..e5ed351bededf73abb0dea473e33c1faa1f170cb 100644 (file)
@@ -11,6 +11,7 @@
 #include "auth-master.h"
 #include "master-service.h"
 #include "mail-storage-settings.h"
+#include "mail-storage-private.h"
 #include "mail-namespace.h"
 #include "mail-storage.h"
 #include "mail-user.h"
@@ -306,6 +307,7 @@ int mail_user_try_home_expand(struct mail_user *user, const char **pathp)
 const char *mail_user_get_temp_prefix(struct mail_user *user)
 {
        struct mail_namespace *ns;
+       const char *dir;
 
        if (user->_home != NULL) {
                return t_strconcat(user->_home, "/.temp.", my_hostname, ".",
@@ -315,7 +317,14 @@ const char *mail_user_get_temp_prefix(struct mail_user *user)
        ns = mail_namespace_find_inbox(user->namespaces);
        if (ns == NULL)
                ns = user->namespaces;
-       return mail_storage_get_temp_prefix(ns->storage);
+
+       if (ns->storage->temp_path_prefix != NULL)
+               return ns->storage->temp_path_prefix;
+
+       dir = mailbox_list_get_path(ns->list, NULL,
+                                   MAILBOX_LIST_PATH_TYPE_DIR);
+       return t_strconcat(dir, "/",
+                          mailbox_list_get_temp_prefix(ns->list), NULL);
 }
 
 const char *mail_user_get_anvil_userip_ident(struct mail_user *user)
index 1dae0fa6b00660c81090e1b46006731ab63964bb..38139c9357babbf5cca1984e4fdc8ac24e896f70 100644 (file)
@@ -5,6 +5,10 @@
 #include "mailbox-list.h"
 #include "mail-storage-settings.h"
 
+#define MAILBOX_LIST_NAME_MAILDIRPLUSPLUS "maildir++"
+#define MAILBOX_LIST_NAME_IMAPDIR "imapdir"
+#define MAILBOX_LIST_NAME_FS "fs"
+
 struct dirent;
 struct imap_match_glob;
 struct mailbox_tree_context;
@@ -13,8 +17,8 @@ struct mailbox_list_vfuncs {
        struct mailbox_list *(*alloc)(void);
        void (*deinit)(struct mailbox_list *list);
 
-       int (*get_storage)(struct mailbox_list *list,
-                          const char **name, struct mail_storage **storage_r);
+       int (*get_storage)(struct mailbox_list **list, const char **name,
+                          struct mail_storage **storage_r);
        bool (*is_valid_pattern)(struct mailbox_list *list,
                                 const char *pattern);
        bool (*is_valid_existing_name)(struct mailbox_list *list,
@@ -125,7 +129,6 @@ void mailbox_lists_deinit(void);
 int mailbox_list_settings_parse(const char *data,
                                struct mailbox_list_settings *set,
                                struct mail_namespace *ns,
-                               const char **layout, const char **alt_dir_r,
                                const char **error_r);
 
 int mailbox_list_delete_index_control(struct mailbox_list *list,
@@ -146,5 +149,7 @@ void mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
        ATTR_FORMAT(2, 3);
 void mailbox_list_set_internal_error(struct mailbox_list *list);
 bool mailbox_list_set_error_from_errno(struct mailbox_list *list);
+void mailbox_list_set_error_from_storage(struct mailbox_list *list,
+                                        struct mail_storage *storage);
 
 #endif
index 2af0f72bcdef8105c26d8f54393cf6c36cd3d2b1..56249324b9d89f9c3dff8617eea6b9a3e6327acf 100644 (file)
@@ -87,13 +87,20 @@ void mailbox_list_unregister(const struct mailbox_list *list)
        array_delete(&mailbox_list_drivers, idx, 1);
 }
 
-int mailbox_list_alloc(const char *driver, struct mailbox_list **list_r,
-                      const char **error_r)
+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)
 {
        const struct mailbox_list *const *class_p;
        struct mailbox_list *list;
        unsigned int idx;
 
+       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');
+
        if (!mailbox_list_driver_find(driver, &idx)) {
                *error_r = t_strdup_printf("Unknown mailbox list driver: %s",
                                           driver);
@@ -101,8 +108,59 @@ int mailbox_list_alloc(const char *driver, struct mailbox_list **list_r,
        }
 
        class_p = array_idx(&mailbox_list_drivers, idx);
-       list = *list_r = (*class_p)->v.alloc();
+       list = (*class_p)->v.alloc();
        array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
+
+       list->ns = ns;
+       list->mail_set = ns->mail_set;
+       list->flags = flags;
+       list->file_create_mode = (mode_t)-1;
+       list->dir_create_mode = (mode_t)-1;
+       list->file_create_gid = (gid_t)-1;
+
+       /* copy settings */
+       list->set.root_dir = p_strdup(list->pool, set->root_dir);
+       list->set.index_dir = set->index_dir == NULL ||
+               strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
+               p_strdup(list->pool, set->index_dir);
+       list->set.control_dir = set->control_dir == NULL ||
+               strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
+               p_strdup(list->pool, set->control_dir);
+
+       list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
+       list->set.subscription_fname =
+               p_strdup(list->pool, set->subscription_fname);
+       list->set.maildir_name = set->maildir_name == NULL ||
+               (list->props & MAILBOX_LIST_PROP_NO_MAILDIR_NAME) != 0 ? "" :
+               p_strdup(list->pool, set->maildir_name);
+       list->set.mailbox_dir_name =
+               p_strdup(list->pool, set->mailbox_dir_name);
+
+       if (set->mailbox_dir_name == NULL || *set->mailbox_dir_name == '\0')
+               list->set.mailbox_dir_name = "";
+       else if (set->mailbox_dir_name[strlen(set->mailbox_dir_name)-1] == '/') {
+               list->set.mailbox_dir_name =
+                       p_strdup(list->pool, set->mailbox_dir_name);
+       } else {
+               list->set.mailbox_dir_name =
+                       p_strconcat(list->pool, set->mailbox_dir_name, "/", NULL);
+       }
+
+       if (ns->mail_set->mail_debug) {
+               i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
+                      list->name,
+                      list->set.root_dir == NULL ? "" : list->set.root_dir,
+                      list->set.index_dir == NULL ? "" : list->set.index_dir,
+                      list->set.control_dir == NULL ?
+                      "" : list->set.control_dir,
+                      list->set.inbox_path == NULL ?
+                      "" : list->set.inbox_path);
+       }
+
+       mail_namespace_finish_list_init(ns, list);
+
+       if (hook_mailbox_list_created != NULL)
+               hook_mailbox_list_created(list);
        return 0;
 }
 
@@ -121,17 +179,14 @@ static int fix_path(struct mail_namespace *ns, const char *path,
 
 int mailbox_list_settings_parse(const char *data,
                                struct mailbox_list_settings *set,
-                               struct mail_namespace *ns,
-                               const char **layout, const char **alt_dir_r,
-                               const char **error_r)
+                               struct mail_namespace *ns, const char **error_r)
 {
        const char *const *tmp, *key, *value, **dest;
 
-       i_assert(*data != '\0');
-
        *error_r = NULL;
-       if (alt_dir_r != NULL)
-               *alt_dir_r = NULL;
+
+       if (*data == '\0')
+               return 0;
 
        /* <root dir> */
        tmp = t_strsplit(data, ":");
@@ -159,10 +214,10 @@ int mailbox_list_settings_parse(const char *data,
                        dest = &set->index_dir;
                else if (strcmp(key, "CONTROL") == 0)
                        dest = &set->control_dir;
-               else if (strcmp(key, "ALT") == 0 && alt_dir_r != NULL)
-                       dest = alt_dir_r;
+               else if (strcmp(key, "ALT") == 0)
+                       dest = &set->alt_dir;
                else if (strcmp(key, "LAYOUT") == 0)
-                       dest = layout;
+                       dest = &set->layout;
                else if (strcmp(key, "SUBSCRIPTIONS") == 0)
                        dest = &set->subscription_fname;
                else if (strcmp(key, "DIRNAME") == 0)
@@ -186,72 +241,11 @@ int mailbox_list_settings_parse(const char *data,
        return 0;
 }
 
-void mailbox_list_init(struct mailbox_list *list, struct mail_namespace *ns,
-                      const struct mailbox_list_settings *set,
-                      enum mailbox_list_flags flags)
+void mailbox_list_destroy(struct mailbox_list **_list)
 {
-       i_assert(set->root_dir == NULL || *set->root_dir != '\0');
-       i_assert(set->subscription_fname == NULL ||
-                *set->subscription_fname != '\0');
+       struct mailbox_list *list = *_list;
 
-       list->ns = ns;
-       list->mail_set = ns->mail_set;
-       list->flags = flags;
-       list->file_create_mode = (mode_t)-1;
-       list->dir_create_mode = (mode_t)-1;
-       list->file_create_gid = (gid_t)-1;
-
-       /* copy settings */
-       list->set.root_dir = p_strdup(list->pool, set->root_dir);
-       list->set.index_dir = set->index_dir == NULL ||
-               strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
-               p_strdup(list->pool, set->index_dir);
-       list->set.control_dir = set->control_dir == NULL ||
-               strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
-               p_strdup(list->pool, set->control_dir);
-
-       list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
-       list->set.subscription_fname =
-               p_strdup(list->pool, set->subscription_fname);
-       list->set.maildir_name =
-               (list->props & MAILBOX_LIST_PROP_NO_MAILDIR_NAME) != 0 ? "" :
-               p_strdup(list->pool, set->maildir_name);
-       list->set.mailbox_dir_name =
-               p_strdup(list->pool, set->mailbox_dir_name);
-
-       if (set->mailbox_dir_name == NULL || *set->mailbox_dir_name == '\0')
-               list->set.mailbox_dir_name = "";
-       else if (set->mailbox_dir_name[strlen(set->mailbox_dir_name)-1] == '/') {
-               list->set.mailbox_dir_name =
-                       p_strdup(list->pool, set->mailbox_dir_name);
-       } else {
-               list->set.mailbox_dir_name =
-                       p_strconcat(list->pool, set->mailbox_dir_name, "/", NULL);
-       }
-
-       list->set.mail_storage_flags = set->mail_storage_flags;
-       list->set.lock_method = set->lock_method;
-
-       if (ns->mail_set->mail_debug) {
-               i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
-                      list->name,
-                      list->set.root_dir == NULL ? "" : list->set.root_dir,
-                      list->set.index_dir == NULL ? "" : list->set.index_dir,
-                      list->set.control_dir == NULL ?
-                      "" : list->set.control_dir,
-                      list->set.inbox_path == NULL ?
-                      "" : list->set.inbox_path);
-       }
-
-       if (hook_mailbox_list_created != NULL)
-               hook_mailbox_list_created(list);
-
-       list->set.mail_storage_flags = NULL;
-       list->set.lock_method = NULL;
-}
-
-void mailbox_list_deinit(struct mailbox_list *list)
-{
+       *_list = NULL;
        i_free_and_null(list->error_string);
 
        list->v.deinit(list);
@@ -293,6 +287,23 @@ mailbox_list_get_user(const struct mailbox_list *list)
        return list->ns->user;
 }
 
+int mailbox_list_get_storage(struct mailbox_list **list, const char **name,
+                            struct mail_storage **storage_r)
+{
+       if ((*list)->v.get_storage != NULL)
+               return (*list)->v.get_storage(list, name, storage_r);
+       else {
+               *storage_r = (*list)->ns->storage;
+               return 0;
+       }
+}
+
+void mailbox_list_get_closest_storage(struct mailbox_list *list,
+                                     struct mail_storage **storage)
+{
+       *storage = list->ns->storage;
+}
+
 static void
 mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name,
                                  mode_t *file_mode_r, mode_t *dir_mode_r,
@@ -600,14 +611,22 @@ int mailbox_list_rename_mailbox(struct mailbox_list *oldlist,
                                struct mailbox_list *newlist,
                                const char *newname, bool rename_children)
 {
+       struct mail_storage *oldstorage;
+       struct mail_storage *newstorage;
+
+       if (mailbox_list_get_storage(&oldlist, &oldname, &oldstorage) < 0)
+               return -1;
+
+       newstorage = oldstorage;
+       mailbox_list_get_closest_storage(newlist, &newstorage);
+
        if (!mailbox_list_is_valid_existing_name(oldlist, oldname) ||
            !mailbox_list_is_valid_create_name(newlist, newname)) {
                mailbox_list_set_error(oldlist, MAIL_ERROR_PARAMS,
                                       "Invalid mailbox name");
                return -1;
        }
-       if (strcmp(oldlist->ns->storage->name,
-                  newlist->ns->storage->name) != 0) {
+       if (strcmp(oldstorage->name, newstorage->name) != 0) {
                mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
                        "Can't rename mailbox to another storage type.");
                return -1;
@@ -894,3 +913,13 @@ bool mailbox_list_set_error_from_errno(struct mailbox_list *list)
        mailbox_list_set_error(list, error, error_string);
        return TRUE;
 }
+
+void mailbox_list_set_error_from_storage(struct mailbox_list *list,
+                                        struct mail_storage *storage)
+{
+       const char *str;
+       enum mail_error error;
+
+       str = mail_storage_get_last_error(storage, &error);
+       mailbox_list_set_error(list, error, str);
+}
index 804cccd20d9d0a25d624ce1c9f8e8f1df8877a00..2cdfc76f6e7c64fdd7e10d9db5ca8c013ab73c79 100644 (file)
@@ -4,6 +4,7 @@
 #include "mail-error.h"
 
 struct mail_namespace;
+struct mail_storage;
 struct mailbox_list;
 struct mailbox_list_iterate_context;
 
@@ -80,9 +81,11 @@ enum mailbox_list_file_type {
 };
 
 struct mailbox_list_settings {
+       const char *layout; /* FIXME: shouldn't be here */
        const char *root_dir;
        const char *index_dir;
        const char *control_dir;
+       const char *alt_dir; /* FIXME: dbox-specific.. */
 
        const char *inbox_path;
        const char *subscription_fname;
@@ -102,11 +105,6 @@ struct mailbox_list_settings {
        /* if set, store mailboxes under root_dir/mailbox_dir_name/.
           this setting contains either "" or "dir/". */
        const char *mailbox_dir_name;
-
-       /* If mailbox index is used, use these settings for it
-          (pointers, so they're set to NULL after init is finished): */
-       const enum mail_storage_flags *mail_storage_flags;
-       const enum file_lock_method *lock_method;
 };
 
 struct mailbox_info {
@@ -122,12 +120,10 @@ void mailbox_list_register(const struct mailbox_list *list);
 void mailbox_list_unregister(const struct mailbox_list *list);
 
 /* Returns 0 if ok, -1 if driver was unknown. */
-int mailbox_list_alloc(const char *driver, struct mailbox_list **list_r,
-                      const char **error_r);
-void mailbox_list_init(struct mailbox_list *list, struct mail_namespace *ns,
-                      const struct mailbox_list_settings *set,
-                      enum mailbox_list_flags flags);
-void mailbox_list_deinit(struct mailbox_list *list);
+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);
+void mailbox_list_destroy(struct mailbox_list **list);
 
 const char *
 mailbox_list_get_driver_name(const struct mailbox_list *list) ATTR_PURE;
@@ -138,6 +134,10 @@ struct mail_namespace *
 mailbox_list_get_namespace(const struct mailbox_list *list) ATTR_PURE;
 struct mail_user *
 mailbox_list_get_user(const struct mailbox_list *list) ATTR_PURE;
+int mailbox_list_get_storage(struct mailbox_list **list, const char **name,
+                            struct mail_storage **storage_r);
+void mailbox_list_get_closest_storage(struct mailbox_list *list,
+                                     struct mail_storage **storage);
 
 /* Returns the mode and GID that should be used when creating new files to
    the specified mailbox, or to mailbox list root if name is NULL. (gid_t)-1 is
index 1226f8103fbf56a3ac8aa80e50511b70ee9c6368..656c4e83434c2261491d567f0d8d833f1d77a813 100644 (file)
@@ -274,8 +274,7 @@ static int client_open_raw_mail(struct client *client)
                "From", "To", "Message-ID", "Subject", "Return-Path",
                NULL
        };
-       struct mail_storage *raw_storage =
-               client->raw_mail_user->namespaces->storage;
+       struct mailbox_list *raw_list = client->raw_mail_user->namespaces->list;
        struct mailbox *box;
        struct raw_mailbox *raw_box;
        struct mailbox_header_lookup_ctx *headers_ctx;
@@ -291,18 +290,18 @@ static int client_open_raw_mail(struct client *client)
                                                  client->state.mail_data->used);
        }
        client->state.raw_box = box =
-               mailbox_open(&raw_storage, "Dovecot Delivery Mail", input,
+               mailbox_open(raw_list, "Dovecot Delivery Mail", input,
                             MAILBOX_OPEN_NO_INDEX_FILES);
        i_stream_unref(&input);
        if (box == NULL) {
                i_error("Can't open delivery mail as raw: %s",
-                       mail_storage_get_last_error(raw_storage, &error));
+                       mailbox_list_get_last_error(raw_list, &error));
                client_rcpt_fail_all(client);
                return -1;
        }
        if (mailbox_sync(box, 0, 0, NULL) < 0) {
                i_error("Can't sync delivery mail: %s",
-                       mail_storage_get_last_error(raw_storage, &error));
+                       mailbox_list_get_last_error(raw_list, &error));
                client_rcpt_fail_all(client);
                return -1;
        }
@@ -348,7 +347,7 @@ static void client_input_data_finish(struct client *client)
                struct mail *mail = client->state.first_saved_mail;
                struct mailbox_transaction_context *trans = mail->transaction;
                struct mailbox *box = trans->box;
-               struct mail_user *user = box->storage->ns->user;
+               struct mail_user *user = box->storage->user;
 
                mail_free(&mail);
                mailbox_transaction_rollback(&trans);
index 83c72157ca4746c6a346aca2874b2d88708d08a0..46478e9e62a0cedf88fc4cd2d3951e989d75ccc4 100644 (file)
@@ -23,10 +23,8 @@ struct acl_backend_vfuncs {
                (struct acl_mailbox_list_context *ctx);
 
        struct acl_object *(*object_init)(struct acl_backend *backend,
-                                         struct mail_storage *storage,
                                          const char *name);
        struct acl_object *(*object_init_parent)(struct acl_backend *backend,
-                                                struct mail_storage *storage,
                                                 const char *child_name);
        void (*object_deinit)(struct acl_object *aclobj);
 
index 47c6a31187eb1a75a60ab5d1cb913f1b2e85536c..6e888efa2b734c12ece714998785e4319ec4ac02 100644 (file)
@@ -7,17 +7,15 @@
 #include "acl-api-private.h"
 
 struct acl_object *acl_object_init_from_name(struct acl_backend *backend,
-                                            struct mail_storage *storage,
                                             const char *name)
 {
-       return backend->v.object_init(backend, storage, name);
+       return backend->v.object_init(backend, name);
 }
 
 struct acl_object *acl_object_init_from_parent(struct acl_backend *backend,
-                                              struct mail_storage *storage,
                                               const char *child_name)
 {
-       return backend->v.object_init_parent(backend, storage, child_name);
+       return backend->v.object_init_parent(backend, child_name);
 }
 
 void acl_object_deinit(struct acl_object **_aclobj)
index 56de5b8ad63522f4d5e5dfff81a33924a85af59c..2144ebc64f6214b7bf59ba541c188f5cab2be931 100644 (file)
@@ -120,10 +120,8 @@ void
 acl_backend_nonowner_lookups_iter_deinit(struct acl_mailbox_list_context **ctx);
 
 struct acl_object *acl_object_init_from_name(struct acl_backend *backend,
-                                            struct mail_storage *storage,
                                             const char *name);
 struct acl_object *acl_object_init_from_parent(struct acl_backend *backend,
-                                              struct mail_storage *storage,
                                               const char *child_name);
 void acl_object_deinit(struct acl_object **aclobj);
 
index 542c032001edbda2bd506426f8ba862b2167710a..e826468079d82d97f1af43ca3b6027f14e49d6bc 100644 (file)
@@ -128,7 +128,7 @@ void acl_backend_vfile_acllist_refresh(struct acl_backend_vfile *backend)
 
 static int
 acllist_append(struct acl_backend_vfile *backend, struct ostream *output,
-              struct mail_storage *storage, const char *name)
+              const char *name)
 {
        struct acl_object *aclobj;
        struct acl_object_list_iter *iter;
@@ -137,7 +137,7 @@ acllist_append(struct acl_backend_vfile *backend, struct ostream *output,
        int ret;
 
        acl_cache_flush(backend->backend.cache, name);
-       aclobj = acl_object_init_from_name(&backend->backend, storage, name);
+       aclobj = acl_object_init_from_name(&backend->backend, name);
 
        iter = acl_object_list_init(aclobj);
        while ((ret = acl_object_list_next(iter, &rights)) > 0) {
@@ -217,8 +217,7 @@ int acl_backend_vfile_acllist_rebuild(struct acl_backend_vfile *backend)
        iter = mailbox_list_iter_init(list, "*", MAILBOX_LIST_ITER_RAW_LIST |
                                      MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        while ((info = mailbox_list_iter_next(iter)) != NULL) {
-               if (acllist_append(backend, output, ns->storage,
-                                  info->name) < 0) {
+               if (acllist_append(backend, output, info->name) < 0) {
                        ret = -1;
                        break;
                }
index d356849932390276d32a59af7865c186e9da01de..d39b1b0b03227d0a9dfbd7272f61442f9622f1e0 100644 (file)
@@ -122,22 +122,25 @@ static void acl_backend_vfile_deinit(struct acl_backend *_backend)
 }
 
 static const char *
-acl_backend_vfile_get_local_dir(struct mail_storage *storage, const char *name)
+acl_backend_vfile_get_local_dir(struct acl_backend *backend, const char *name)
 {
+       struct mail_namespace *ns;
        const char *dir;
-       bool is_file;
 
-       dir = mail_storage_get_mailbox_path(storage, name, &is_file);
-       if (is_file) {
-               dir = mailbox_list_get_path(storage->list, name,
+       ns = mailbox_list_get_namespace(backend->list);
+       if (mail_storage_is_mailbox_file(ns->storage)) {
+               dir = mailbox_list_get_path(ns->list, name,
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
+       } else {
+               dir = mailbox_list_get_path(ns->list, name,
+                                           MAILBOX_LIST_PATH_TYPE_MAILBOX);
        }
        return dir;
 }
 
 static struct acl_object *
 acl_backend_vfile_object_init(struct acl_backend *_backend,
-                             struct mail_storage *storage, const char *name)
+                             const char *name)
 {
        struct acl_backend_vfile *backend =
                (struct acl_backend_vfile *)_backend;
@@ -150,11 +153,11 @@ acl_backend_vfile_object_init(struct acl_backend *_backend,
        aclobj->global_path = backend->global_dir == NULL ? NULL :
                i_strconcat(backend->global_dir, "/", name, NULL);
 
-       if (storage == NULL) {
+       if (*name == '\0') {
                /* the default ACL for mailbox list */
                dir = NULL;
        } else {
-               dir = acl_backend_vfile_get_local_dir(storage, name);
+               dir = acl_backend_vfile_get_local_dir(_backend, name);
        }
        aclobj->local_path = dir == NULL ? NULL :
                i_strconcat(dir, "/"ACL_FILENAME, NULL);
@@ -162,12 +165,12 @@ acl_backend_vfile_object_init(struct acl_backend *_backend,
 }
 
 static const char *
-get_parent_mailbox(struct mail_storage *storage, const char *name)
+get_parent_mailbox(struct acl_backend *backend, const char *name)
 {
        const char *p;
        char sep;
 
-       sep = mailbox_list_get_hierarchy_sep(storage->list);
+       sep = mailbox_list_get_hierarchy_sep(backend->list);
        p = strrchr(name, sep);
        return p == NULL ? NULL : t_strdup_until(name, p);
 }
@@ -202,8 +205,7 @@ acl_backend_vfile_exists(struct acl_backend_vfile *backend, const char *path,
 }
 
 static bool
-acl_backend_vfile_has_acl(struct acl_backend *_backend,
-                         struct mail_storage *storage, const char *name)
+acl_backend_vfile_has_acl(struct acl_backend *_backend, const char *name)
 {
        struct acl_backend_vfile *backend =
                (struct acl_backend_vfile *)_backend;
@@ -220,13 +222,13 @@ acl_backend_vfile_has_acl(struct acl_backend *_backend,
        /* See if the mailbox exists. If we wanted recursive lookups we could
           skip this, but at least for now we assume that if an existing
           mailbox has no ACL it's equivalent to default ACLs. */
-       path = mailbox_list_get_path(storage->list, name,
+       path = mailbox_list_get_path(_backend->list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        ret = path == NULL ? 0 :
                acl_backend_vfile_exists(backend, path,
                                         &new_validity.mailbox_validity);
        if (ret == 0) {
-               dir = acl_backend_vfile_get_local_dir(storage, name);
+               dir = acl_backend_vfile_get_local_dir(_backend, name);
                local_path = t_strconcat(dir, "/", name, NULL);
                ret = acl_backend_vfile_exists(backend, local_path,
                                               &new_validity.local_validity);
@@ -242,7 +244,6 @@ acl_backend_vfile_has_acl(struct acl_backend *_backend,
 
 static struct acl_object *
 acl_backend_vfile_object_init_parent(struct acl_backend *backend,
-                                    struct mail_storage *storage,
                                     const char *child_name)
 {
        const char *parent;
@@ -251,8 +252,8 @@ acl_backend_vfile_object_init_parent(struct acl_backend *backend,
           a) has global ACL file
           b) has local ACL file
           c) exists */
-       while ((parent = get_parent_mailbox(storage, child_name)) != NULL) {
-               if (acl_backend_vfile_has_acl(backend, storage, parent))
+       while ((parent = get_parent_mailbox(backend, child_name)) != NULL) {
+               if (acl_backend_vfile_has_acl(backend, parent))
                        break;
                child_name = parent;
        }
@@ -260,7 +261,7 @@ acl_backend_vfile_object_init_parent(struct acl_backend *backend,
                /* use the root */
                parent = "";
        }
-       return acl_backend_vfile_object_init(backend, storage, parent);
+       return acl_backend_vfile_object_init(backend, parent);
 }
 
 static void acl_backend_vfile_object_deinit(struct acl_object *_aclobj)
index e88c6930859481b3879fc0ca2e6b2faf99169062..5a6cc7df6fd4fbf781d3b4a996add1aae4845ef0 100644 (file)
@@ -82,7 +82,7 @@ acl_backend_init(const char *data, struct mailbox_list *list,
                acl_cache_mask_init(backend->cache, backend->pool,
                                    backend->default_rights);
 
-       backend->default_aclobj = acl_object_init_from_name(backend, NULL, "");
+       backend->default_aclobj = acl_object_init_from_name(backend, "");
        return backend;
 }
 
index acba4e09467be650634debe7ba682c8aec602d4b..2706242f75d324f2487410186f9272fe223d03fd 100644 (file)
@@ -104,10 +104,10 @@ static int acl_lookup_dict_rebuild_add_backend(struct mail_namespace *ns,
                return 0;
 
        id = t_str_new(128);
-       backend = acl_storage_get_backend(ns->storage);
+       backend = acl_mailbox_list_get_backend(ns->list);
        ctx = acl_backend_nonowner_lookups_iter_init(backend);
        while ((ret = acl_backend_nonowner_lookups_iter_next(ctx, &name)) > 0) {
-               aclobj = acl_object_init_from_name(backend, ns->storage, name);
+               aclobj = acl_object_init_from_name(backend, name);
 
                iter = acl_object_list_init(aclobj);
                while ((ret = acl_object_list_next(iter, &rights)) > 0) {
index ea221838888d23928bce5881817d186d13f52b88..9797e59aeb63992fb6667b5f35ce6f4d4e5f43ad 100644 (file)
 #include "acl-shared-storage.h"
 #include "acl-plugin.h"
 
-#define ACL_LIST_CONTEXT(obj) \
-       MODULE_CONTEXT(obj, acl_mailbox_list_module)
-
 #define MAILBOX_FLAG_MATCHED 0x40000000
 
-struct acl_mailbox_list {
-       union mailbox_list_module_context module_ctx;
-
-       struct acl_storage_rights_context rights;
-};
-
 struct acl_mailbox_list_iterate_context {
        struct mailbox_list_iterate_context ctx;
        struct mailbox_list_iterate_context *super_ctx;
@@ -35,8 +26,22 @@ struct acl_mailbox_list_iterate_context {
        unsigned int simple_star_glob:1;
 };
 
-static MODULE_CONTEXT_DEFINE_INIT(acl_mailbox_list_module,
-                                 &mailbox_list_module_register);
+static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = {
+       MAIL_ACL_LOOKUP,
+       MAIL_ACL_READ,
+       MAIL_ACL_WRITE,
+       MAIL_ACL_WRITE_SEEN,
+       MAIL_ACL_WRITE_DELETED,
+       MAIL_ACL_INSERT,
+       MAIL_ACL_POST,
+       MAIL_ACL_EXPUNGE,
+       MAIL_ACL_CREATE,
+       MAIL_ACL_DELETE,
+       MAIL_ACL_ADMIN
+};
+
+struct acl_mailbox_list_module acl_mailbox_list_module =
+       MODULE_CONTEXT_INIT(&mailbox_list_module_register);
 
 struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list)
 {
@@ -45,16 +50,32 @@ struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list)
        return alist->rights.backend;
 }
 
-static int
-acl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
-                           unsigned int acl_storage_right_idx, bool *can_see_r)
+int acl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
+                               bool parent, unsigned int acl_storage_right_idx,
+                               bool *can_see_r)
 {
        struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
-       int ret;
+       struct acl_backend *backend = alist->rights.backend;
+       const unsigned int *idx_arr = alist->rights.acl_storage_right_idx;
+       struct mail_namespace *ns;
+       struct acl_object *aclobj;
+       int ret, ret2;
+
+       ns = mailbox_list_get_namespace(list);
+       aclobj = !parent ?
+               acl_object_init_from_name(backend, name) :
+               acl_object_init_from_parent(backend, name);
+       ret = acl_object_have_right(aclobj, idx_arr[acl_storage_right_idx]);
+
+       if (can_see_r != NULL) {
+               ret2 = acl_object_have_right(aclobj,
+                                            idx_arr[ACL_STORAGE_RIGHT_LOOKUP]);
+               if (ret2 < 0)
+                       ret = -1;
+               *can_see_r = ret2 > 0;
+       }
+       acl_object_deinit(&aclobj);
 
-       ret = acl_storage_rights_ctx_have_right(&alist->rights, name, FALSE,
-                                               acl_storage_right_idx,
-                                               can_see_r);
        if (ret < 0)
                mailbox_list_set_internal_error(list);
        return ret;
@@ -297,7 +318,7 @@ acl_mailbox_list_info_is_visible(struct acl_mailbox_list_iterate_context *ctx)
        }
 
        acl_name = acl_mailbox_list_iter_get_name(&ctx->ctx, info->name);
-       ret = acl_mailbox_list_have_right(ctx->ctx.list, acl_name,
+       ret = acl_mailbox_list_have_right(ctx->ctx.list, acl_name, FALSE,
                                          ACL_STORAGE_RIGHT_LOOKUP,
                                          NULL);
        if (ret != 0) {
@@ -381,14 +402,14 @@ static int acl_get_mailbox_name_status(struct mailbox_list *list,
        struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
        int ret;
 
-       ret = acl_mailbox_list_have_right(list, name, ACL_STORAGE_RIGHT_LOOKUP,
-                                         NULL);
+       ret = acl_mailbox_list_have_right(list, name, FALSE,
+                                         ACL_STORAGE_RIGHT_LOOKUP, NULL);
        if (ret < 0)
                return -1;
        if (ret == 0) {
                /* If we have INSERT right for the mailbox, we'll need to
                   reveal its existence so that APPEND and COPY works. */
-               ret = acl_mailbox_list_have_right(list, name,
+               ret = acl_mailbox_list_have_right(list, name, FALSE,
                                                  ACL_STORAGE_RIGHT_INSERT,
                                                  NULL);
                if (ret < 0)
@@ -412,7 +433,7 @@ static int acl_get_mailbox_name_status(struct mailbox_list *list,
        case MAILBOX_NAME_NOINFERIORS:
                /* have to check if we are allowed to see the parent */
                T_BEGIN {
-                       ret = acl_storage_rights_ctx_have_right(&alist->rights, name,
+                       ret = acl_mailbox_list_have_right(list, name,
                                        TRUE, ACL_STORAGE_RIGHT_LOOKUP, NULL);
                } T_END;
 
@@ -436,8 +457,8 @@ acl_mailbox_list_delete(struct mailbox_list *list, const char *name)
        bool can_see;
        int ret;
 
-       ret = acl_mailbox_list_have_right(list, name, ACL_STORAGE_RIGHT_DELETE,
-                                         &can_see);
+       ret = acl_mailbox_list_have_right(list, name, FALSE,
+                                         ACL_STORAGE_RIGHT_DELETE, &can_see);
        if (ret <= 0) {
                if (ret < 0)
                        return -1;
@@ -460,12 +481,11 @@ acl_mailbox_list_rename(struct mailbox_list *oldlist, const char *oldname,
                        bool rename_children)
 {
        struct acl_mailbox_list *old_alist = ACL_LIST_CONTEXT(oldlist);
-       struct acl_mailbox_list *new_alist = ACL_LIST_CONTEXT(newlist);
        bool can_see;
        int ret;
 
        /* renaming requires rights to delete the old mailbox */
-       ret = acl_mailbox_list_have_right(oldlist, oldname,
+       ret = acl_mailbox_list_have_right(oldlist, oldname, FALSE,
                                          ACL_STORAGE_RIGHT_DELETE, &can_see);
        if (ret <= 0) {
                if (ret < 0)
@@ -482,8 +502,8 @@ acl_mailbox_list_rename(struct mailbox_list *oldlist, const char *oldname,
 
        /* and create the new one under the parent mailbox */
        T_BEGIN {
-               ret = acl_storage_rights_ctx_have_right(&new_alist->rights,
-                               newname, TRUE, ACL_STORAGE_RIGHT_CREATE, NULL);
+               ret = acl_mailbox_list_have_right(newlist, newname, TRUE,
+                                               ACL_STORAGE_RIGHT_CREATE, NULL);
        } T_END;
 
        if (ret <= 0) {
@@ -515,6 +535,19 @@ static void acl_mailbox_list_init_shared(struct mailbox_list *list)
        MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
 }
 
+static void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx,
+                                       struct acl_backend *backend)
+{
+       unsigned int i;
+
+       ctx->backend = backend;
+       for (i = 0; i < ACL_STORAGE_RIGHT_COUNT; i++) {
+               ctx->acl_storage_right_idx[i] =
+                       acl_backend_lookup_right(backend,
+                                                acl_storage_right_names[i]);
+       }
+}
+
 static void acl_mailbox_list_init_default(struct mailbox_list *list)
 {
        struct acl_user *auser = ACL_USER_CONTEXT(list->ns->user);
index ab42e53842cb3321ae32ab04a5cc9be0b2eb4818..77d6084d91dabb19d40e80e9d2aa72cf41bc9e60 100644 (file)
@@ -30,20 +30,6 @@ struct acl_transaction_context {
 static MODULE_CONTEXT_DEFINE_INIT(acl_mail_module, &mail_module_register);
 static struct acl_transaction_context acl_transaction_failure;
 
-struct acl_backend *acl_storage_get_backend(struct mail_storage *storage)
-{
-       struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
-
-       return astorage->rights.backend;
-}
-
-struct acl_object *acl_storage_get_default_aclobj(struct mail_storage *storage)
-{
-       struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
-
-       return astorage->rights.backend->default_aclobj;
-}
-
 struct acl_object *acl_mailbox_get_aclobj(struct mailbox *box)
 {
        struct acl_mailbox *abox = ACL_CONTEXT(box);
@@ -54,11 +40,11 @@ struct acl_object *acl_mailbox_get_aclobj(struct mailbox *box)
 int acl_mailbox_right_lookup(struct mailbox *box, unsigned int right_idx)
 {
        struct acl_mailbox *abox = ACL_CONTEXT(box);
-       struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
+       struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
        int ret;
 
        ret = acl_object_have_right(abox->aclobj,
-                       astorage->rights.acl_storage_right_idx[right_idx]);
+                       alist->rights.acl_storage_right_idx[right_idx]);
        if (ret > 0)
                return 1;
        if (ret < 0) {
@@ -352,13 +338,12 @@ acl_keywords_create(struct mailbox *box, const char *const keywords[],
 
 struct mailbox *acl_mailbox_open_box(struct mailbox *box)
 {
-       struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
+       struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
        struct acl_mailbox *abox;
 
        abox = p_new(box->pool, struct acl_mailbox, 1);
        abox->module_ctx.super = box->v;
-       abox->aclobj = acl_object_init_from_name(astorage->rights.backend,
-                                                box->storage,
+       abox->aclobj = acl_object_init_from_name(alist->rights.backend,
                                                 mailbox_get_name(box));
 
        if ((box->open_flags & MAILBOX_OPEN_IGNORE_ACLS) == 0) {
index 8b0ef0b101a1432b9c580e8beb9025a240d1e655..924e76b1aca5ebfb74cb8909a935fd303fcfdf16 100644 (file)
@@ -3,10 +3,13 @@
 
 #include "mail-user.h"
 #include "mail-storage-private.h"
+#include "mailbox-list-private.h"
 #include "acl-storage.h"
 
 #define ACL_CONTEXT(obj) \
        MODULE_CONTEXT(obj, acl_storage_module)
+#define ACL_LIST_CONTEXT(obj) \
+       MODULE_CONTEXT(obj, acl_mailbox_list_module)
 #define ACL_USER_CONTEXT(obj) \
        MODULE_CONTEXT(obj, acl_user_module)
 
@@ -26,8 +29,8 @@ struct acl_storage_rights_context {
        unsigned int acl_storage_right_idx[ACL_STORAGE_RIGHT_COUNT];
 };
 
-struct acl_mail_storage {
-       union mail_storage_module_context module_ctx;
+struct acl_mailbox_list {
+       union mailbox_list_module_context module_ctx;
        struct acl_storage_rights_context rights;
 };
 
@@ -36,6 +39,8 @@ extern void (*acl_next_hook_mailbox_list_created)(struct mailbox_list *list);
 extern void (*acl_next_hook_mail_user_created)(struct mail_user *user);
 extern MODULE_CONTEXT_DEFINE(acl_storage_module, &mail_storage_module_register);
 extern MODULE_CONTEXT_DEFINE(acl_user_module, &mail_user_module_register);
+extern MODULE_CONTEXT_DEFINE(acl_mailbox_list_module,
+                            &mailbox_list_module_register);
 
 void acl_mail_storage_created(struct mail_storage *storage);
 void acl_mailbox_list_created(struct mailbox_list *list);
@@ -43,14 +48,10 @@ void acl_mail_user_created(struct mail_user *list);
 
 struct mailbox *acl_mailbox_open_box(struct mailbox *box);
 
-void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx,
-                                struct acl_backend *backend);
-int acl_storage_rights_ctx_have_right(struct acl_storage_rights_context *ctx,
-                                     const char *name, bool parent,
-                                     unsigned int acl_storage_right_idx,
-                                     bool *can_see_r);
-
 struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list);
+int acl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
+                               bool parent, unsigned int acl_storage_right_idx,
+                               bool *can_see_r);
 
 void acl_plugin_init(void);
 void acl_plugin_deinit(void);
index 806ef926a98f33b7dc55fe3cba787f7772a2e1df..660e60203bcca45fc4e1896ddbcad2886006e93a 100644 (file)
@@ -13,9 +13,8 @@
 #define SHARED_NS_RETRY_SECS (60*60)
 
 static void
-acl_shared_namespace_add(struct mail_user *user,
-                        struct shared_storage *sstorage,
-                        const char *userdomain)
+acl_shared_namespace_add(struct mail_namespace *ns,
+                        struct mail_storage *storage, const char *userdomain)
 {
        static struct var_expand_table static_tab[] = {
                { 'u', NULL, "user" },
@@ -23,14 +22,15 @@ acl_shared_namespace_add(struct mail_user *user,
                { 'd', NULL, "domain" },
                { '\0', NULL, NULL }
        };
+       struct shared_storage *sstorage = (struct shared_storage *)storage;
+       struct mail_namespace *new_ns = ns;
        struct var_expand_table *tab;
-       struct mail_namespace *ns;
        struct mailbox_list_iterate_context *iter;
        const struct mailbox_info *info;
        const char *p, *mailbox;
        string_t *str;
 
-       if (strcmp(user->username, userdomain) == 0) {
+       if (strcmp(ns->user->username, userdomain) == 0) {
                /* skip ourself */
                return;
        }
@@ -46,11 +46,11 @@ acl_shared_namespace_add(struct mail_user *user,
        str = t_str_new(128);
        var_expand(str, sstorage->ns_prefix_pattern, tab);
        mailbox = str_c(str);
-       if (shared_storage_get_namespace(&sstorage->storage, &mailbox, &ns) < 0)
+       if (shared_storage_get_namespace(&new_ns, &mailbox) < 0)
                return;
 
        /* check if there are any mailboxes really visible to us */
-       iter = mailbox_list_iter_init(ns->list, "*",
+       iter = mailbox_list_iter_init(new_ns->list, "*",
                                      MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        while ((info = mailbox_list_iter_next(iter)) != NULL)
                break;
@@ -58,19 +58,19 @@ acl_shared_namespace_add(struct mail_user *user,
 
        if (info == NULL) {
                /* no visible mailboxes, remove the namespace */
-               mail_namespace_destroy(ns);
+               mail_namespace_destroy(new_ns);
        }
 }
 
 int acl_shared_namespaces_add(struct mail_namespace *ns)
 {
-       struct shared_storage *sstorage = (struct shared_storage *)ns->storage;
        struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
+       struct mail_storage *storage = ns->storage;
        struct acl_lookup_dict_iter *iter;
        const char *name;
 
        i_assert(ns->type == NAMESPACE_SHARED);
-       i_assert(strcmp(ns->storage->name, SHARED_STORAGE_NAME) == 0);
+       i_assert(strcmp(storage->name, SHARED_STORAGE_NAME) == 0);
 
        if (ioloop_time < auser->last_shared_add_check + SHARED_NS_RETRY_SECS) {
                /* already added, don't bother rechecking */
@@ -81,7 +81,7 @@ int acl_shared_namespaces_add(struct mail_namespace *ns)
        iter = acl_lookup_dict_iterate_visible_init(auser->acl_lookup_dict);
        while ((name = acl_lookup_dict_iterate_visible_next(iter)) != NULL) {
                T_BEGIN {
-                       acl_shared_namespace_add(ns->user, sstorage, name);
+                       acl_shared_namespace_add(nsstorage, name);
                } T_END;
        }
        return acl_lookup_dict_iterate_visible_deinit(&iter);
index 626d1c48b3d01691ce0c5fd98209b16d51ccef61..27f097b63abe9faaaa261d4b5e431730b14e6270 100644 (file)
@@ -16,138 +16,64 @@ struct acl_storage_module acl_storage_module =
 struct acl_user_module acl_user_module =
        MODULE_CONTEXT_INIT(&mail_user_module_register);
 
-static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = {
-       MAIL_ACL_LOOKUP,
-       MAIL_ACL_READ,
-       MAIL_ACL_WRITE,
-       MAIL_ACL_WRITE_SEEN,
-       MAIL_ACL_WRITE_DELETED,
-       MAIL_ACL_INSERT,
-       MAIL_ACL_POST,
-       MAIL_ACL_EXPUNGE,
-       MAIL_ACL_CREATE,
-       MAIL_ACL_DELETE,
-       MAIL_ACL_ADMIN
-};
-
-void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx,
-                                struct acl_backend *backend)
-{
-       unsigned int i;
-
-       ctx->backend = backend;
-       for (i = 0; i < ACL_STORAGE_RIGHT_COUNT; i++) {
-               ctx->acl_storage_right_idx[i] =
-                       acl_backend_lookup_right(backend,
-                                                acl_storage_right_names[i]);
-       }
-}
-
-int acl_storage_rights_ctx_have_right(struct acl_storage_rights_context *ctx,
-                                     const char *name, bool parent,
-                                     unsigned int acl_storage_right_idx,
-                                     bool *can_see_r)
-{
-       const unsigned int *idx_arr = ctx->acl_storage_right_idx;
-       struct mail_namespace *ns;
-       struct acl_object *aclobj;
-       int ret, ret2;
-
-       ns = mailbox_list_get_namespace(ctx->backend->list);
-       aclobj = !parent ?
-               acl_object_init_from_name(ctx->backend, ns->storage, name) :
-               acl_object_init_from_parent(ctx->backend, ns->storage, name);
-       ret = acl_object_have_right(aclobj, idx_arr[acl_storage_right_idx]);
-
-       if (can_see_r != NULL) {
-               ret2 = acl_object_have_right(aclobj,
-                                            idx_arr[ACL_STORAGE_RIGHT_LOOKUP]);
-               if (ret2 < 0)
-                       ret = -1;
-               *can_see_r = ret2 > 0;
-       }
-       acl_object_deinit(&aclobj);
-
-       return ret;
-}
-
-static int
-acl_storage_have_right(struct mail_storage *storage, const char *name,
-                      unsigned int acl_storage_right_idx, bool *can_see_r)
-{
-       struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
-       int ret;
-
-       ret = acl_storage_rights_ctx_have_right(&astorage->rights, name, FALSE,
-                                               acl_storage_right_idx,
-                                               can_see_r);
-       if (ret < 0) 
-               mail_storage_set_internal_error(storage);
-       return ret;
-}
-
-static void acl_storage_destroy(struct mail_storage *storage)
-{
-       struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
-
-       acl_backend_deinit(&astorage->rights.backend);
-       if (astorage->module_ctx.super.destroy != NULL)
-               astorage->module_ctx.super.destroy(storage);
-}
-
 static struct mailbox *
-acl_mailbox_open(struct mail_storage *storage, const char *name,
-                struct istream *input, enum mailbox_open_flags flags)
+acl_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                const char *name, struct istream *input,
+                enum mailbox_open_flags flags)
 {
-       struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
+       union mail_storage_module_context *astorage = ACL_CONTEXT(storage);
        struct mailbox *box;
        enum acl_storage_rights save_right;
        bool can_see;
        int ret;
 
        /* mailbox can be opened either for reading or appending new messages */
-       if ((flags & MAILBOX_OPEN_IGNORE_ACLS) != 0) {
+       if ((flags & MAILBOX_OPEN_IGNORE_ACLS) != 0 ||
+           (list->ns->flags & NAMESPACE_FLAG_NOACL) != 0) {
                ret = 1;
        } else if ((flags & MAILBOX_OPEN_SAVEONLY) == 0) {
-               ret = acl_storage_have_right(storage, name,
-                                            ACL_STORAGE_RIGHT_READ,
-                                            &can_see);
+               ret = acl_mailbox_list_have_right(list, name, FALSE,
+                                                 ACL_STORAGE_RIGHT_READ,
+                                                 &can_see);
        } else {
                save_right = (flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
                        ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
-               ret = acl_storage_have_right(storage, name, save_right,
-                                            &can_see);
+               ret = acl_mailbox_list_have_right(list, name, FALSE,
+                                                 save_right, &can_see);
        }
        if (ret <= 0) {
                if (ret < 0)
                        return NULL;
                if (can_see) {
-                       mail_storage_set_error(storage, MAIL_ERROR_PERM,
+                       mailbox_list_set_error(list, MAIL_ERROR_PERM,
                                               MAIL_ERRSTR_NO_PERMISSION);
                } else {
-                       mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
+                       mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                                T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
                }
                return NULL;
        }
 
-       box = astorage->module_ctx.super.
-               mailbox_open(storage, name, input, flags);
+       box = astorage->super.mailbox_open(storage, list, name, input, flags);
        if (box == NULL)
                return NULL;
 
        return acl_mailbox_open_box(box);
 }
 
-static int acl_mailbox_create(struct mail_storage *storage, const char *name,
-                             bool directory)
+static int
+acl_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
+                  const char *name, bool directory)
 {
-       struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
+       union mail_storage_module_context *astorage = ACL_CONTEXT(storage);
        int ret;
 
-       T_BEGIN {
-               ret = acl_storage_rights_ctx_have_right(&astorage->rights, name,
-                               TRUE, ACL_STORAGE_RIGHT_CREATE, NULL);
+       if ((list->ns->flags & NAMESPACE_FLAG_NOACL) != 0)
+               ret = 1;
+       else T_BEGIN {
+               ret = acl_mailbox_list_have_right(list, name, TRUE,
+                                                 ACL_STORAGE_RIGHT_CREATE,
+                                                 NULL);
        } T_END;
 
        if (ret <= 0) {
@@ -163,31 +89,24 @@ static int acl_mailbox_create(struct mail_storage *storage, const char *name,
                return -1;
        }
 
-       return astorage->module_ctx.super.
-               mailbox_create(storage, name, directory);
+       return astorage->super.mailbox_create(storage, list, name, directory);
 }
 
 void acl_mail_storage_created(struct mail_storage *storage)
 {
-       struct acl_user *auser = ACL_USER_CONTEXT(storage->ns->user);
-       struct acl_mail_storage *astorage;
-       struct acl_backend *backend;
+       struct acl_user *auser = ACL_USER_CONTEXT(storage->user);
+       union mail_storage_module_context *astorage;
 
        if (auser == NULL) {
                /* ACLs disabled for this user */
-       } else if ((storage->ns->flags & NAMESPACE_FLAG_NOACL) != 0) {
-               /* no ACL checks for internal namespaces (lda) */
        } else {
-               astorage = p_new(storage->pool, struct acl_mail_storage, 1);
-               astorage->module_ctx.super = storage->v;
-               storage->v.destroy = acl_storage_destroy;
+               astorage = p_new(storage->pool,
+                                union mail_storage_module_context, 1);
+               astorage->super = storage->v;
                storage->v.mailbox_open = acl_mailbox_open;
                storage->v.mailbox_create = acl_mailbox_create;
 
-               backend = acl_mailbox_list_get_backend(mail_storage_get_list(storage));
-               acl_storage_rights_ctx_init(&astorage->rights, backend);
-
-               MODULE_CONTEXT_SET(storage, acl_storage_module, astorage);
+               MODULE_CONTEXT_SET_SELF(storage, acl_storage_module, astorage);
        }
 
        if (acl_next_hook_mail_storage_created != NULL)
index 3ed7cf55832826a2d3a41a31d74fff720df28b77..38374f3dec1fa256de26475cf20fbc2d30cd3e3d 100644 (file)
@@ -17,10 +17,6 @@ enum acl_storage_rights {
        ACL_STORAGE_RIGHT_COUNT
 };
 
-/* Returns acl_backend for the given mail storage. */
-struct acl_backend *acl_storage_get_backend(struct mail_storage *storage);
-/* Returns default acl_object for the given mail storage. */
-struct acl_object *acl_storage_get_default_aclobj(struct mail_storage *storage);
 /* Returns acl_object for the given mailbox. */
 struct acl_object *acl_mailbox_get_aclobj(struct mailbox *box);
 /* Returns 1 if we have the requested right. If not, returns 0 and sets storage
index d8e04a89d32d7c23cdb905f07efed3ff2cc27368..ce924785573ff28d37e662797820dae95f98d484 100644 (file)
@@ -16,6 +16,7 @@ static void
 autocreate_mailbox(struct mail_namespace *namespaces, const char *name)
 {
        struct mail_namespace *ns;
+       struct mail_storage *storage;
        const char *str;
        enum mail_error error;
 
@@ -26,8 +27,9 @@ autocreate_mailbox(struct mail_namespace *namespaces, const char *name)
                return;
        }
 
-       if (mail_storage_mailbox_create(ns->storage, name, FALSE) < 0) {
-               str = mail_storage_get_last_error(ns->storage, &error);
+       storage = mail_namespace_get_default_storage(ns);
+       if (mail_storage_mailbox_create(storage, ns, name, FALSE) < 0) {
+               str = mail_storage_get_last_error(storage, &error);
                if (error != MAIL_ERROR_EXISTS && ns->mail_set->mail_debug) {
                        i_info("autocreate: Failed to create mailbox %s: %s",
                               name, str);
index efe06faac38d406552cb6ffdf781fad8160d5f12..9c8631d582d9a44f1927f2989137301acda5387c 100644 (file)
@@ -29,6 +29,13 @@ static const char *storage_error(struct mail_storage *storage)
        return mail_storage_get_last_error(storage, &error);
 }
 
+static const char *list_error(struct mailbox_list *list)
+{
+       enum mail_error error;
+
+       return mailbox_list_get_last_error(list, &error);
+}
+
 static int mailbox_copy_mails(struct mailbox *srcbox, struct mailbox *destbox,
                              struct dotlock *dotlock, const char **error_r)
 {
@@ -109,15 +116,15 @@ static int mailbox_copy_mails(struct mailbox *srcbox, struct mailbox *destbox,
 }
 
 static const char *
-mailbox_name_convert(struct mail_storage *dest_storage,
-                    struct mail_storage *source_storage,
+mailbox_name_convert(struct mail_namespace *dest_ns,
+                    struct mail_namespace *source_ns,
                     const struct convert_plugin_settings *set,
                     const char *name)
 {
        char *dest_name, *p, src_sep, dest_sep;
 
-       src_sep = mail_storage_get_hierarchy_sep(source_storage);
-       dest_sep = mail_storage_get_hierarchy_sep(dest_storage);
+       src_sep = mailbox_list_get_hierarchy_sep(source_ns->list);
+       dest_sep = mailbox_list_get_hierarchy_sep(dest_ns->list);
 
        if (src_sep == dest_sep || set->alt_hierarchy_char == '\0')
                return name;
@@ -132,10 +139,10 @@ mailbox_name_convert(struct mail_storage *dest_storage,
        return dest_name;
 }
 
-static int mailbox_convert_maildir_to_dbox(struct mail_storage *src_storage,
-                                          struct mail_storage *dest_storage,
-                                          const char *src_name,
-                                          const char *dest_name)
+static int
+mailbox_convert_maildir_to_dbox(struct mail_namespace *source_ns,
+                               struct mail_namespace *dest_ns,
+                               const char *src_name, const char *dest_name)
 {
        static const char *maildir_files[] = {
                "dovecot-uidlist",
@@ -144,25 +151,29 @@ static int mailbox_convert_maildir_to_dbox(struct mail_storage *src_storage,
                "dovecot.index.log",
                "dovecot.index.cache"
        };
+       struct mail_storage *dest_storage;
        string_t *src, *dest;
        DIR *dir;
        struct dirent *dp;
        const char *src_path, *dest_path, *new_path, *cur_path;
        unsigned int i, src_dir_len, dest_dir_len;
-       bool t;
        int ret;
 
        /* create as non-selectable mailbox so the dbox-Mails directory
           isn't created yet */
-       if (mail_storage_mailbox_create(dest_storage, dest_name, TRUE) < 0) {
+       dest_storage = mail_namespace_get_default_storage(dest_ns);
+       if (mail_storage_mailbox_create(dest_storage, dest_ns,
+                                       dest_name, TRUE) < 0) {
                i_error("Mailbox conversion: "
                        "Couldn't create mailbox %s: %s",
                        dest_name, storage_error(dest_storage));
                return -1;
        }
 
-       src_path = mail_storage_get_mailbox_path(src_storage, src_name, &t);
-       dest_path = mail_storage_get_mailbox_path(dest_storage, dest_name, &t);
+       src_path = mailbox_list_get_path(source_ns->list, src_name,
+                                        MAILBOX_LIST_PATH_TYPE_MAILBOX);
+       dest_path = mailbox_list_get_path(dest_ns->list, dest_name,
+                                        MAILBOX_LIST_PATH_TYPE_MAILBOX);
 
        /* rename cur/ directory as the destination directory */
        cur_path = t_strconcat(src_path, "/cur", NULL);
@@ -241,12 +252,13 @@ static int mailbox_convert_maildir_to_dbox(struct mail_storage *src_storage,
        return ret;
 }
 
-static int mailbox_convert_list_item(struct mail_storage *source_storage,
-                                    struct mail_storage *dest_storage,
+static int mailbox_convert_list_item(struct mail_namespace *source_ns,
+                                    struct mail_namespace *dest_ns,
                                     const struct mailbox_info *info,
                                     struct dotlock *dotlock,
                                     const struct convert_plugin_settings *set)
 {
+       struct mail_storage *dest_storage;
        const char *name, *dest_name, *error;
        struct mailbox *srcbox, *destbox;
        int ret = 0;
@@ -255,27 +267,27 @@ static int mailbox_convert_list_item(struct mail_storage *source_storage,
                return 0;
 
        name = strcasecmp(info->name, "INBOX") == 0 ? "INBOX" : info->name;
-       dest_name = mailbox_name_convert(dest_storage, source_storage,
-                                        set, name);
+       dest_name = mailbox_name_convert(dest_ns, source_ns, set, name);
+       dest_storage = mail_namespace_get_default_storage(dest_ns);
 
        if ((info->flags & MAILBOX_NOSELECT) != 0) {
                /* \NoSelect mailbox, so it's probably a "directory" */
                if (*info->name == '.' && set->skip_dotdirs)
                        return 0;
 
-               if (mail_storage_mailbox_create(dest_storage, dest_name,
-                                               TRUE) < 0) {
+               if (mail_storage_mailbox_create(dest_storage, dest_ns,
+                                               dest_name, TRUE) < 0) {
                        i_error("Mailbox conversion: Couldn't create mailbox "
-                               "directory %s", dest_name);
+                               "directory %s: %s", dest_name,
+                               storage_error(dest_storage));
                        return -1;
                }
                return 0;
        }
 
-       if (strcmp(source_storage->name, "maildir") == 0 &&
+       if (strcmp(source_ns->storage->name, "maildir") == 0 &&
            strcmp(dest_storage->name, "dbox") == 0) {
-               if (mailbox_convert_maildir_to_dbox(source_storage,
-                                                   dest_storage,
+               if (mailbox_convert_maildir_to_dbox(source_ns, dest_ns,
                                                    name, dest_name) < 0) {
                        i_error("Mailbox conversion failed for mailbox %s",
                                name);
@@ -286,7 +298,7 @@ static int mailbox_convert_list_item(struct mail_storage *source_storage,
 
        /* First open the source mailbox. If we can't open it, don't create
           the destination mailbox either. */
-       srcbox = mailbox_open(&source_storage, name, NULL,
+       srcbox = mailbox_open(source_ns->list, name, NULL,
                              MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
        if (srcbox == NULL) {
                if (set->skip_broken_mailboxes)
@@ -294,14 +306,14 @@ static int mailbox_convert_list_item(struct mail_storage *source_storage,
 
                i_error("Mailbox conversion: "
                        "Couldn't open source mailbox %s: %s",
-                       name, storage_error(source_storage));
+                       name, list_error(source_ns->list));
                return -1;
        }
 
        /* Create and open the destination mailbox. */
        if (strcmp(dest_name, "INBOX") != 0) {
-               if (mail_storage_mailbox_create(dest_storage, dest_name,
-                                               FALSE) < 0) {
+               if (mail_storage_mailbox_create(dest_storage, dest_ns,
+                                               dest_name, FALSE) < 0) {
                        i_error("Mailbox conversion: "
                                "Couldn't create mailbox %s: %s",
                                dest_name, storage_error(dest_storage));
@@ -310,11 +322,11 @@ static int mailbox_convert_list_item(struct mail_storage *source_storage,
                }
        }
 
-       destbox = mailbox_open(&dest_storage, dest_name, NULL,
+       destbox = mailbox_open(dest_ns->list, dest_name, NULL,
                               MAILBOX_OPEN_KEEP_RECENT);
        if (destbox == NULL) {
                i_error("Mailbox conversion: Couldn't open dest mailbox %s: %s",
-                       dest_name, storage_error(dest_storage));
+                       dest_name, list_error(dest_ns->list));
                mailbox_close(&srcbox);
                return -1;
        }
@@ -329,7 +341,7 @@ static int mailbox_convert_list_item(struct mail_storage *source_storage,
        return ret;
 }
 
-static int mailbox_list_copy(struct mail_storage *source_storage,
+static int mailbox_list_copy(struct mail_namespace *source_ns,
                             struct mail_namespace *dest_namespaces,
                             struct dotlock *dotlock,
                             const struct convert_plugin_settings *set)
@@ -340,12 +352,11 @@ static int mailbox_list_copy(struct mail_storage *source_storage,
        int ret = 0;
 
        dest_ns = mail_namespace_find_inbox(dest_namespaces);
-       iter = mailbox_list_iter_init(mail_storage_get_list(source_storage),
+       iter = mailbox_list_iter_init(source_ns->list,
                                      "*", MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        while ((info = mailbox_list_iter_next(iter)) != NULL) {
                T_BEGIN {
-                       ret = mailbox_convert_list_item(source_storage,
-                                                       dest_ns->storage,
+                       ret = mailbox_convert_list_item(source_ns, dest_ns,
                                                        info, dotlock, set);
                } T_END;
                if (ret < 0)
@@ -361,27 +372,24 @@ static int mailbox_list_copy(struct mail_storage *source_storage,
 }
 
 static int
-mailbox_list_copy_subscriptions(struct mail_storage *source_storage,
+mailbox_list_copy_subscriptions(struct mail_namespace *source_ns,
                                struct mail_namespace *dest_namespaces,
                                const struct convert_plugin_settings *set)
 {
        struct mailbox_list_iterate_context *iter;
        struct mail_namespace *dest_ns;
        const struct mailbox_info *info;
-       struct mailbox_list *dest_list;
        const char *dest_name;
        int ret = 0;
 
        dest_ns = mail_namespace_find_inbox(dest_namespaces);
-       dest_list = mail_storage_get_list(dest_ns->storage);
-       iter = mailbox_list_iter_init(mail_storage_get_list(source_storage),
+       iter = mailbox_list_iter_init(source_ns->list,
                                      "*", MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
                                      MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        while ((info = mailbox_list_iter_next(iter)) != NULL) {
-               dest_name = mailbox_name_convert(dest_ns->storage,
-                                                source_storage,
+               dest_name = mailbox_name_convert(dest_ns, source_ns,
                                                 set, info->name);
-               if (mailbox_list_set_subscribed(dest_list, dest_name,
+               if (mailbox_list_set_subscribed(dest_ns->list, dest_name,
                                                TRUE) < 0) {
                        ret = -1;
                        break;
@@ -420,10 +428,8 @@ int convert_storage(const char *source_data,
        if (mail_user_get_home(user, &home) <= 0)
                i_unreached();
         path = t_strconcat(home, "/"CONVERT_LOCK_FILENAME, NULL);
-       dotlock_settings.use_excl_lock =
-               source_ns->storage->set->dotlock_use_excl;
-       dotlock_settings.nfs_flush =
-               source_ns->storage->set->mail_nfs_storage;
+       dotlock_settings.use_excl_lock = source_ns->mail_set->dotlock_use_excl;
+       dotlock_settings.nfs_flush = source_ns->mail_set->mail_nfs_storage;
        ret = file_dotlock_create(&dotlock_settings, path, 0, &dotlock);
        if (ret <= 0) {
                if (ret == 0)
@@ -443,10 +449,10 @@ int convert_storage(const char *source_data,
                return 0;
        }
 
-       ret = mailbox_list_copy(source_ns->storage, dest_namespaces,
+       ret = mailbox_list_copy(source_ns, dest_namespaces,
                                dotlock, set);
        if (ret == 0) {
-               ret = mailbox_list_copy_subscriptions(source_ns->storage,
+               ret = mailbox_list_copy_subscriptions(source_ns,
                                                      dest_namespaces, set);
        }
 
@@ -454,10 +460,9 @@ int convert_storage(const char *source_data,
                /* all finished. rename the source directory to mark the
                   move as finished. */
                const char *src, *dest;
-               bool is_file;
 
-               src = mail_storage_get_mailbox_path(source_ns->storage, "",
-                                                   &is_file);
+               src = mailbox_list_get_path(source_ns->list, NULL,
+                                           MAILBOX_LIST_PATH_TYPE_MAILBOX);
                if (src != NULL) {
                        dest = t_strconcat(src, "-converted", NULL);
                        if (rename(src, dest) < 0) {
index 590c9612273fd4f650376def34f4f88ed4622e14..baa800bed7b09e4a45b16d152a8cc82248b6cce0 100644 (file)
@@ -104,7 +104,7 @@ expire_mailbox_transaction_commit(struct mailbox_transaction_context *t,
                                  uint32_t *last_saved_uid_r)
 {
        struct expire_mail_user *euser =
-               EXPIRE_USER_CONTEXT(t->box->storage->ns->user);
+               EXPIRE_USER_CONTEXT(t->box->storage->user);
        struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
        struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
        struct mailbox *box = t->box;
@@ -133,8 +133,9 @@ expire_mailbox_transaction_commit(struct mailbox_transaction_context *t,
                const char *key, *value;
 
                key = t_strconcat(DICT_EXPIRE_PREFIX,
-                                 box->storage->ns->user->username, "/",
-                                 box->storage->ns->prefix, box->name, NULL);
+                                 box->storage->user->username, "/",
+                                 mailbox_get_namespace(box)->prefix,
+                                 box->name, NULL);
                if (!xt->first_expunged && xt->saves) {
                        /* saved new mails. dict needs to be updated only if
                           this is the first mail in the database */
@@ -254,10 +255,11 @@ mailbox_expire_hook(struct mailbox *box, time_t expire_secs, bool altmove)
 }
 
 static struct mailbox *
-expire_mailbox_open(struct mail_storage *storage, const char *name,
-                   struct istream *input, enum mailbox_open_flags flags)
+expire_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                   const char *name, struct istream *input,
+                   enum mailbox_open_flags flags)
 {
-       struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->ns->user);
+       struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->user);
        union mail_storage_module_context *xpr_storage =
                EXPIRE_CONTEXT(storage);
        struct mailbox *box;
@@ -265,10 +267,11 @@ expire_mailbox_open(struct mail_storage *storage, const char *name,
        unsigned int secs;
        bool altmove;
 
-       box = xpr_storage->super.mailbox_open(storage, name, input, flags);
+       box = xpr_storage->super.mailbox_open(storage, list, name, input, flags);
        if (box != NULL) {
                vname = t_str_new(128);
-               (void)mail_namespace_get_vname(storage->ns, vname, name);
+               (void)mail_namespace_get_vname(mailbox_list_get_namespace(list),
+                                              vname, name);
 
                secs = expire_box_find_min_secs(euser->env, str_c(vname),
                                                &altmove);
@@ -280,7 +283,7 @@ expire_mailbox_open(struct mail_storage *storage, const char *name,
 
 static void expire_mail_storage_created(struct mail_storage *storage)
 {
-       struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->ns->user);
+       struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->user);
        union mail_storage_module_context *xpr_storage;
 
        if (euser != NULL) {
index 55367671c5b4e2b63fee3bf5f282008140f30125..59692591f91d93e6e0e52e968096f316b878d595 100644 (file)
@@ -32,7 +32,6 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
        struct mail_storage_service_input input;
        struct mail_storage_service_multi_user *multi_user;
        struct mail_namespace *ns;
-       struct mail_storage *storage;
        struct mailbox *box;
        struct mail_search_context *search_ctx;
        struct mailbox_transaction_context *t;
@@ -81,10 +80,9 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
                return 0;
        }
 
-       storage = ns->storage;
-       box = mailbox_open(&storage, ns_mailbox, NULL, 0);
+       box = mailbox_open(ns->list, ns_mailbox, NULL, 0);
        if (box == NULL) {
-               errstr = mail_storage_get_last_error(storage, &error);
+               errstr = mailbox_list_get_last_error(ns->list, &error);
                if (error != MAIL_ERROR_NOTFOUND) {
                        i_error("%s: Opening mailbox %s failed: %s",
                                user, mailbox, errstr);
index 2fb578efa50147e6f7385fc5c350c655807bb1aa..7059448039627bfb97135a755edf9035d7a60d66 100644 (file)
@@ -48,8 +48,8 @@ static struct fts_backend *fts_backend_lucene_init(struct mailbox *box)
 
        lstorage = LUCENE_CONTEXT(box->storage);
        if (lstorage == NULL) {
-               path = mail_storage_get_mailbox_index_dir(box->storage,
-                                                         "INBOX");
+               path = mailbox_list_get_path(box->list, "INBOX",
+                                            MAILBOX_LIST_PATH_TYPE_INDEX);
                if (path == NULL) {
                        /* in-memory indexes */
                        if (box->storage->set->mail_debug)
index 28142f61283f8f3440630832bb7e3388969db81a..867ba09a2bcc7c3b512699912bff966bb1c82f7a 100644 (file)
@@ -66,7 +66,7 @@ static void fts_box_name_get_root(struct mail_namespace **ns, const char **name)
 static const char *
 fts_box_get_root(struct mailbox *box, struct mail_namespace **ns_r)
 {
-       struct mail_namespace *ns = box->storage->ns;
+       struct mail_namespace *ns = mailbox_get_namespace(box);
        const char *name = box->name;
 
        fts_box_name_get_root(&ns, &name);
@@ -161,7 +161,7 @@ static struct fts_backend *
 fts_backend_solr_init(struct mailbox *box)
 {
        struct fts_solr_user *fuser =
-               FTS_SOLR_USER_CONTEXT(box->storage->ns->user);
+               FTS_SOLR_USER_CONTEXT(box->storage->user);
        const struct fts_solr_settings *set = &fuser->set;
        struct solr_fts_backend *backend;
        struct mail_namespace *ns;
@@ -339,7 +339,7 @@ solr_get_namespaces(struct fts_backend *_backend,
                    struct mailbox *box, const char *ns_prefix)
 {
        struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
-       struct mail_namespace *namespaces = box->storage->ns->user->namespaces;
+       struct mail_namespace *namespaces = box->storage->user->namespaces;
 
        if (ns_prefix == NULL)
                return backend->default_ns;
@@ -485,7 +485,7 @@ fts_backend_solr_get_all_last_uids(struct fts_backend *backend, pool_t pool,
        str = t_str_new(256);
        str_printfa(str, "fl=uid,box,uidv,ns&rows=%u&q=last_uid:TRUE+user:",
                    SOLR_MAX_ROWS);
-       solr_quote_http(str, backend->box->storage->ns->user->username);
+       solr_quote_http(str, backend->box->storage->user->username);
        fts_backend_solr_filter_mailboxes(backend, str, backend->box);
 
        return solr_connection_select(solr_conn, str_c(str),
@@ -765,7 +765,7 @@ static int fts_backend_solr_lookup(struct fts_backend_lookup_context *ctx,
        /* use a separate filter query for selecting the mailbox. it shouldn't
           affect the score and there could be some caching benefits too. */
        str_append(str, "&fq=%2Buser:");
-       solr_quote_http(str, box->storage->ns->user->username);
+       solr_quote_http(str, box->storage->user->username);
        if (virtual)
                fts_backend_solr_filter_mailboxes(ctx->backend, str, box);
        else {
index a8b80c7a8abbbc26f70d7708c8b1eb8e2ace9ecd..4ed3783743af9f298835a9765ec54ded5aaa0944 100644 (file)
@@ -59,8 +59,8 @@ static struct fts_backend *fts_backend_squat_init(struct mailbox *box)
        enum squat_index_flags flags = 0;
 
        storage = mailbox_get_storage(box);
-       path = mail_storage_get_mailbox_index_dir(storage,
-                                                 mailbox_get_name(box));
+       path = mailbox_list_get_path(box->list, box->name,
+                                    MAILBOX_LIST_PATH_TYPE_INDEX);
        if (*path == '\0') {
                /* in-memory indexes */
                if (storage->set->mail_debug)
@@ -80,11 +80,12 @@ static struct fts_backend *fts_backend_squat_init(struct mailbox *box)
        backend->backend = fts_backend_squat;
        backend->trie =
                squat_trie_init(t_strconcat(path, "/"SQUAT_FILE_PREFIX, NULL),
-                               status.uidvalidity, storage->lock_method,
+                               status.uidvalidity,
+                               storage->set->parsed_lock_method,
                                flags, box->file_create_mode,
                                box->file_create_gid);
 
-       env = mail_user_plugin_getenv(box->storage->ns->user, "fts_squat");
+       env = mail_user_plugin_getenv(box->storage->user, "fts_squat");
        if (env != NULL)
                fts_backend_squat_set(backend, env);
        return &backend->backend;
index de20f98ddfa0995b2366116b0ccc75d9a7d839ab..a067b611e4133572d340cd3060011ee74d85055b 100644 (file)
@@ -355,14 +355,14 @@ static int fts_build_init_virtual_next(struct fts_search_context *fctx)
 static const char *
 fts_box_get_root(struct mailbox *box, struct mail_namespace **ns_r)
 {
-       struct mail_namespace *ns = box->storage->ns;
+       struct mail_namespace *ns = mailbox_get_namespace(box);
        const char *name = box->name;
 
        while (ns->alias_for != NULL)
                ns = ns->alias_for;
        *ns_r = ns;
 
-       if (*name == '\0' && ns != box->storage->ns &&
+       if (*name == '\0' && ns != mailbox_get_namespace(box) &&
            (ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
                /* ugly workaround to allow selecting INBOX from a Maildir/
                   when it's not in the inbox=yes namespace. */
@@ -1061,7 +1061,7 @@ void fts_mailbox_opened(struct mailbox *box)
 {
        const char *env;
 
-       env = mail_user_plugin_getenv(box->storage->ns->user, "fts");
+       env = mail_user_plugin_getenv(box->storage->user, "fts");
        if (env != NULL)
                fts_mailbox_init(box, env);
 
index 1fecb06cd15a3864e5d85032f538315eac1523b2..7ad6d85e5141cdadbf0c62a00666f09276740fe5 100644 (file)
@@ -54,7 +54,7 @@ static void (*next_hook_client_created)(struct client **client);
 static struct mailbox *
 acl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
 {
-       struct mail_storage *storage;
+       struct mail_namespace *ns;
        struct mailbox *box;
        int ret;
 
@@ -63,16 +63,16 @@ acl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
                return NULL;
        }
 
-       storage = client_find_storage(cmd, &name);
-       if (storage == NULL)
+       ns = client_find_namespace(cmd, &name);
+       if (ns == NULL)
                return NULL;
 
        /* Force opening the mailbox so that we can give a nicer error message
           if mailbox isn't selectable but is listable. */
-       box = mailbox_open(&storage, name, NULL, ACL_MAILBOX_OPEN_FLAGS |
+       box = mailbox_open(ns->list, name, NULL, ACL_MAILBOX_OPEN_FLAGS |
                           MAILBOX_OPEN_IGNORE_ACLS);
        if (box == NULL) {
-               client_send_storage_error(cmd, storage);
+               client_send_list_error(cmd, ns->list);
                return NULL;
        }
 
@@ -248,7 +248,6 @@ static bool cmd_getacl(struct client_command_context *cmd)
 {
        struct acl_backend *backend;
        struct mail_namespace *ns;
-       struct mail_storage *storage;
        struct mailbox *box;
        const char *mailbox;
        string_t *str;
@@ -267,9 +266,8 @@ static bool cmd_getacl(struct client_command_context *cmd)
        str_append(str, "* ACL ");
        imap_quote_append_string(str, mailbox, FALSE);
 
-       storage = mailbox_get_storage(box);
-       backend = acl_storage_get_backend(storage);
-       ns = mail_storage_get_namespace(storage);
+       ns = mailbox_get_namespace(box);
+       backend = acl_mailbox_list_get_backend(ns->list);
        ret = imap_acl_write_aclobj(str, backend,
                                    acl_mailbox_get_aclobj(box), TRUE,
                                    ns->type == NAMESPACE_PRIVATE);
@@ -285,7 +283,7 @@ static bool cmd_getacl(struct client_command_context *cmd)
 
 static bool cmd_myrights(struct client_command_context *cmd)
 {
-       struct mail_storage *storage;
+       struct mail_namespace *ns;
        struct mailbox *box;
        const char *mailbox, *real_mailbox;
        const char *const *rights;
@@ -302,14 +300,14 @@ static bool cmd_myrights(struct client_command_context *cmd)
        }
 
        real_mailbox = mailbox;
-       storage = client_find_storage(cmd, &real_mailbox);
-       if (storage == NULL)
+       ns = client_find_namespace(cmd, &real_mailbox);
+       if (ns == NULL)
                return TRUE;
 
-       box = mailbox_open(&storage, real_mailbox, NULL,
+       box = mailbox_open(ns->list, real_mailbox, NULL,
                           ACL_MAILBOX_OPEN_FLAGS | MAILBOX_OPEN_IGNORE_ACLS);
        if (box == NULL) {
-               client_send_storage_error(cmd, storage);
+               client_send_list_error(cmd, ns->list);
                return TRUE;
        }
 
@@ -507,7 +505,6 @@ static void imap_acl_update_ensure_keep_admins(struct acl_rights_update *update)
 static bool cmd_setacl(struct client_command_context *cmd)
 {
        struct mail_namespace *ns;
-       struct mail_storage *storage;
        struct mailbox *box;
        struct acl_backend *backend;
        struct acl_rights_update update;
@@ -556,9 +553,8 @@ static bool cmd_setacl(struct client_command_context *cmd)
        if (box == NULL)
                return TRUE;
 
-       storage = mailbox_get_storage(box);
-       backend = acl_storage_get_backend(storage);
-       ns = mail_storage_get_namespace(storage);
+       ns = mailbox_get_namespace(box);
+       backend = acl_mailbox_list_get_backend(ns->list);
        if (ns->type == NAMESPACE_PUBLIC && r->id_type == ACL_ID_OWNER) {
                client_send_tagline(cmd, "NO Public namespaces have no owner");
                mailbox_close(&box);
index cb3d9bc9888bfedd35384e81677fefe7c94cc5e6..9700fb6f386187aba4c727ffac2509c92877e6b5 100644 (file)
@@ -68,7 +68,6 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
        struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
-       struct mail_storage *storage;
        struct mail_namespace *ns;
        struct mailbox *box;
        struct quota_root_iter *iter;
@@ -81,19 +80,18 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
                return FALSE;
 
        orig_mailbox = mailbox;
-       storage = client_find_storage(cmd, &mailbox);
-       if (storage == NULL)
+       ns = client_find_namespace(cmd, &mailbox);
+       if (ns == NULL)
                return TRUE;
 
-       box = mailbox_open(&storage, mailbox, NULL, (MAILBOX_OPEN_READONLY |
+       box = mailbox_open(ns->list, mailbox, NULL, (MAILBOX_OPEN_READONLY |
                                                     MAILBOX_OPEN_FAST |
                                                     MAILBOX_OPEN_KEEP_RECENT));
        if (box == NULL) {
-               client_send_storage_error(cmd, storage);
+               client_send_list_error(cmd, ns->list);
                return TRUE;
        }
 
-       ns = mail_storage_get_namespace(storage);
        if (quser == NULL) {
                mailbox_close(&box);
                client_send_tagline(cmd, "OK No quota.");
index c697c0d6ebfe15fa4ac5c8b68bae822a67fab26c..86eda5ac36b89e0083078138ddd10b2aadca36a9 100644 (file)
@@ -44,13 +44,12 @@ struct lazy_expunge_mail_user {
 struct lazy_expunge_mailbox_list {
        union mailbox_list_module_context module_ctx;
 
-       struct mail_storage *storage;
+       struct mailbox_list *expunge_list;
+       bool internal_namespace;
 };
 
 struct lazy_expunge_mail_storage {
        union mail_storage_module_context module_ctx;
-
-       bool internal_namespace;
 };
 
 struct lazy_expunge_transaction {
@@ -82,59 +81,66 @@ static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_user_module,
                                  &mail_user_module_register);
 
 static struct mailbox *
-mailbox_open_or_create(struct mail_storage *storage, const char *name)
+mailbox_open_or_create(struct mailbox_list *list, const char *name,
+                      const char **error_r)
 {
        struct mailbox *box;
+       struct mail_storage *storage;
        enum mail_error error;
 
-       box = mailbox_open(&storage, name, NULL, MAILBOX_OPEN_FAST |
+       box = mailbox_open(list, name, NULL, MAILBOX_OPEN_FAST |
                           MAILBOX_OPEN_KEEP_RECENT |
                           MAILBOX_OPEN_NO_INDEX_FILES);
        if (box != NULL)
                return box;
 
-       (void)mail_storage_get_last_error(storage, &error);
+       *error_r = mailbox_list_get_last_error(list, &error);
        if (error != MAIL_ERROR_NOTFOUND)
                return NULL;
 
        /* try creating it. */
-       if (mail_storage_mailbox_create(storage, name, FALSE) < 0)
+       storage = mail_namespace_get_default_storage(list->ns);
+       if (mail_storage_mailbox_create(storage, list->ns, name, FALSE) < 0) {
+               *error_r = mail_storage_get_last_error(storage, &error);
                return NULL;
+       }
 
        /* and try opening again */
-       box = mailbox_open(&storage, name, NULL, MAILBOX_OPEN_FAST |
+       box = mailbox_open(list, name, NULL, MAILBOX_OPEN_FAST |
                           MAILBOX_OPEN_KEEP_RECENT);
+       if (box == NULL)
+               *error_r = mailbox_list_get_last_error(list, &error);
        return box;
 }
 
-static struct mail_storage *
-get_lazy_storage(struct mail_user *user, enum lazy_namespace type)
+static struct mail_namespace *
+get_lazy_ns(struct mail_user *user, enum lazy_namespace type)
 {
        struct lazy_expunge_mail_user *luser = LAZY_EXPUNGE_USER_CONTEXT(user);
 
-       return luser->lazy_ns[type]->storage;
+       return luser->lazy_ns[type];
 }
 
 static void lazy_expunge_mail_expunge(struct mail *_mail)
 {
-       struct mail_storage *storage = _mail->box->storage;
+       struct mail_namespace *ns = _mail->box->list->ns;
        struct mail_private *mail = (struct mail_private *)_mail;
        union mail_module_context *mmail = LAZY_EXPUNGE_MAIL_CONTEXT(mail);
        struct lazy_expunge_transaction *lt =
                LAZY_EXPUNGE_CONTEXT(_mail->transaction);
-       struct mail_storage *deststorage;
+       struct mail_namespace *dest_ns;
        struct mail_save_context *save_ctx;
        struct mail_keywords *keywords;
-       const char *const *keywords_list;
+       const char *const *keywords_list, *error;
 
-       deststorage = get_lazy_storage(storage->ns->user,
-                                      LAZY_NAMESPACE_EXPUNGE);
+       dest_ns = get_lazy_ns(ns->user, LAZY_NAMESPACE_EXPUNGE);
        if (lt->dest_box == NULL) {
-               lt->dest_box = mailbox_open_or_create(deststorage,
-                                                     _mail->box->name);
+               lt->dest_box = mailbox_open_or_create(dest_ns->list,
+                                                     _mail->box->name, &error);
                if (lt->dest_box == NULL) {
                        mail_storage_set_critical(_mail->box->storage,
-                               "lazy_expunge: Couldn't open expunge mailbox");
+                               "lazy_expunge: Couldn't open expunge mailbox: "
+                               "%s", error);
                        lt->failed = TRUE;
                        return;
                }
@@ -247,17 +253,21 @@ lazy_expunge_mail_alloc(struct mailbox_transaction_context *t,
 }
 
 static struct mailbox *
-lazy_expunge_mailbox_open(struct mail_storage *storage, const char *name,
-                         struct istream *input, enum mailbox_open_flags flags)
+lazy_expunge_mailbox_open(struct mail_storage *storage,
+                         struct mailbox_list *list,
+                         const char *name, struct istream *input,
+                         enum mailbox_open_flags flags)
 {
        struct lazy_expunge_mail_storage *lstorage =
                LAZY_EXPUNGE_CONTEXT(storage);
+       struct lazy_expunge_mailbox_list *llist =
+               LAZY_EXPUNGE_LIST_CONTEXT(list);
        struct mailbox *box;
        union mailbox_module_context *mbox;
 
        box = lstorage->module_ctx.super.
-               mailbox_open(storage, name, input, flags);
-       if (box == NULL || lstorage->internal_namespace)
+               mailbox_open(storage, list, name, input, flags);
+       if (box == NULL || llist == NULL || llist->internal_namespace)
                return box;
 
        mbox = p_new(box->pool, union mailbox_module_context, 1);
@@ -315,16 +325,14 @@ lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
 {
        struct lazy_expunge_mailbox_list *llist =
                LAZY_EXPUNGE_LIST_CONTEXT(list);
-       struct lazy_expunge_mail_storage *lstorage;
-       struct mailbox_list *dest_list;
+       struct mail_namespace *src_ns, *dest_ns;
        enum mailbox_name_status status;
        const char *destname;
        struct tm *tm;
        char timestamp[256];
        int ret;
 
-       lstorage = LAZY_EXPUNGE_CONTEXT(llist->storage);
-       if (lstorage->internal_namespace)
+       if (llist->internal_namespace)
                return llist->module_ctx.super.delete_mailbox(list, name);
 
        /* first do the normal sanity checks */
@@ -349,9 +357,8 @@ lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
        destname = t_strconcat(name, "-", timestamp, NULL);
 
        /* first move the actual mailbox */
-       dest_list = get_lazy_storage(list->ns->user,
-                                    LAZY_NAMESPACE_DELETE)->list;
-       if ((ret = mailbox_move(list, name, dest_list, &destname)) < 0)
+       dest_ns = get_lazy_ns(list->ns->user, LAZY_NAMESPACE_DELETE);
+       if ((ret = mailbox_move(list, name, dest_ns->list, &destname)) < 0)
                return -1;
        if (ret == 0) {
                mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
@@ -360,37 +367,15 @@ lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
        }
 
        /* next move the expunged messages mailbox, if it exists */
-       list = get_lazy_storage(list->ns->user, LAZY_NAMESPACE_EXPUNGE)->list;
-       dest_list = get_lazy_storage(list->ns->user,
-                                    LAZY_NAMESPACE_DELETE_EXPUNGE)->list;
-       (void)mailbox_move(list, name, dest_list, &destname);
+       src_ns = get_lazy_ns(list->ns->user, LAZY_NAMESPACE_EXPUNGE);
+       dest_ns = get_lazy_ns(list->ns->user, LAZY_NAMESPACE_DELETE_EXPUNGE);
+       (void)mailbox_move(src_ns->list, name, dest_ns->list, &destname);
        return 0;
 }
 
 static void lazy_expunge_mail_storage_init(struct mail_storage *storage)
 {
-       struct lazy_expunge_mail_user *luser =
-               LAZY_EXPUNGE_USER_CONTEXT(storage->ns->user);
-       struct lazy_expunge_mailbox_list *llist =
-               LAZY_EXPUNGE_LIST_CONTEXT(storage->list);
        struct lazy_expunge_mail_storage *lstorage;
-       const char *const *p;
-       unsigned int i;
-
-       if (llist == NULL)
-               return;
-
-       /* if this is one of our internal storages, mark it as such before
-          quota plugin sees it */
-       p = t_strsplit_spaces(luser->env, " ");
-       for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
-               if (strcmp(storage->ns->prefix, *p) == 0) {
-                       storage->ns->flags |= NAMESPACE_FLAG_NOQUOTA;
-                       break;
-               }
-       }
-
-       llist->storage = storage;
 
        lstorage = p_new(storage->pool, struct lazy_expunge_mail_storage, 1);
        lstorage->module_ctx.super = storage->v;
@@ -412,6 +397,18 @@ static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
        struct lazy_expunge_mail_user *luser =
                LAZY_EXPUNGE_USER_CONTEXT(list->ns->user);
        struct lazy_expunge_mailbox_list *llist;
+       const char *const *p;
+       unsigned int i;
+
+       /* if this is one of our internal namespaces, mark it as such before
+          quota plugin sees it */
+       p = t_strsplit_spaces(luser->env, " ");
+       for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
+               if (strcmp(list->ns->prefix, *p) == 0) {
+                       list->ns->flags |= NAMESPACE_FLAG_NOQUOTA;
+                       break;
+               }
+       }
 
        if (luser != NULL && list->ns->type == NAMESPACE_PRIVATE) {
                llist = p_new(list->pool, struct lazy_expunge_mailbox_list, 1);
@@ -431,7 +428,7 @@ lazy_expunge_hook_mail_namespaces_created(struct mail_namespace *namespaces)
 {
        struct lazy_expunge_mail_user *luser =
                LAZY_EXPUNGE_USER_CONTEXT(namespaces->user);
-       struct lazy_expunge_mail_storage *lstorage;
+       struct lazy_expunge_mailbox_list *llist;
        const char *const *p;
        int i;
 
@@ -452,8 +449,8 @@ lazy_expunge_hook_mail_namespaces_created(struct mail_namespace *namespaces)
 
                /* we don't want to override these namespaces' expunge/delete
                   operations. */
-               lstorage = LAZY_EXPUNGE_CONTEXT(luser->lazy_ns[i]->storage);
-               lstorage->internal_namespace = TRUE;
+               llist = LAZY_EXPUNGE_LIST_CONTEXT(luser->lazy_ns[i]->list);
+               llist->internal_namespace = TRUE;
        }
 
        if (lazy_expunge_next_hook_mail_namespaces_created != NULL)
index 5770d696da475dbc9ea2cf36fa16891ea9a7f280..3423e8836d0e29710dbf259c40ef8fac955146c0 100644 (file)
@@ -163,30 +163,31 @@ listescape_mailbox_list_iter_deinit(struct mailbox_list_iterate_context *ctx)
 }
 
 static struct mailbox *
-listescape_mailbox_open(struct mail_storage *storage, const char *name,
-                       struct istream *input, enum mailbox_open_flags flags)
+listescape_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                       const char *name, struct istream *input,
+                       enum mailbox_open_flags flags)
 {
-       struct listescape_mail_storage *mstorage =
-               LIST_ESCAPE_CONTEXT(storage);
-       struct listescape_mailbox_list *mlist =
-               LIST_ESCAPE_LIST_CONTEXT(storage->list);
+       struct listescape_mail_storage *mstorage = LIST_ESCAPE_CONTEXT(storage);
+       struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
 
-       if (!mlist->name_escaped)
-               name = list_escape(storage->ns, name, TRUE);
+       if (!mlist->name_escaped && list->hierarchy_sep != list->ns->sep)
+               name = list_escape(list->ns, name, TRUE);
        return mstorage->module_ctx.super.
-               mailbox_open(storage, name, input, flags);
+               mailbox_open(storage, list, name, input, flags);
 }
 
 static int
-listescape_mailbox_create(struct mail_storage *storage, const char *name,
-                         bool directory)
+listescape_mailbox_create(struct mail_storage *storage,
+                         struct mailbox_list *list,
+                         const char *name, bool directory)
 {
        struct listescape_mail_storage *mstorage =
                LIST_ESCAPE_CONTEXT(storage);
 
-       name = list_escape(storage->ns, name, TRUE);
+       if (list->hierarchy_sep != list->ns->sep)
+               name = list_escape(list->ns, name, TRUE);
        return mstorage->module_ctx.super.
-               mailbox_create(storage, name, directory);
+               mailbox_create(storage, list, name, directory);
 }
 
 static int
@@ -263,9 +264,6 @@ static void listescape_mail_storage_created(struct mail_storage *storage)
        if (listescape_next_hook_mail_storage_created != NULL)
                listescape_next_hook_mail_storage_created(storage);
 
-       if (storage->list->hierarchy_sep == storage->ns->sep)
-               return;
-
        mstorage = p_new(storage->pool, struct listescape_mail_storage, 1);
        mstorage->module_ctx.super = storage->v;
        storage->v.mailbox_open = listescape_mailbox_open;
index 90d86df074eee90d252354b3409e43458d84afbf..dea1996ac19a955ff30fb281ef365696566d4bcb 100644 (file)
@@ -183,7 +183,7 @@ mail_log_action_add_group(struct mail_log_transaction_context *lt,
                          const char *data)
 {
        struct mail_log_user *muser =
-               MAIL_LOG_USER_CONTEXT(mail->box->storage->ns->user);
+               MAIL_LOG_USER_CONTEXT(mail->box->storage->user);
        struct mail_log_group_changes *group;
        uoff_t size;
 
@@ -225,7 +225,7 @@ static void
 mail_log_group(struct mailbox *box, const struct mail_log_group_changes *group)
 {
        struct mail_log_user *muser =
-               MAIL_LOG_USER_CONTEXT(box->storage->ns->user);
+               MAIL_LOG_USER_CONTEXT(box->storage->user);
        const struct seq_range *range;
        unsigned int i, count;
        string_t *str;
@@ -295,7 +295,7 @@ static void mail_log_action(struct mailbox_transaction_context *dest_trans,
 {
        struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(dest_trans);
        struct mail_log_user *muser =
-               MAIL_LOG_USER_CONTEXT(mail->box->storage->ns->user);
+               MAIL_LOG_USER_CONTEXT(mail->box->storage->user);
        uoff_t size;
        string_t *str;
 
@@ -522,7 +522,7 @@ mail_log_transaction_commit(struct mailbox_transaction_context *t,
        struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
        union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
        struct mail_log_user *muser =
-               MAIL_LOG_USER_CONTEXT(t->box->storage->ns->user);
+               MAIL_LOG_USER_CONTEXT(t->box->storage->user);
 
        if (lt->changes > 0 && muser->group_events)
                mail_log_group_changes(t->box, lt);
@@ -541,7 +541,7 @@ mail_log_transaction_rollback(struct mailbox_transaction_context *t)
        struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
        union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
        struct mail_log_user *muser =
-               MAIL_LOG_USER_CONTEXT(t->box->storage->ns->user);
+               MAIL_LOG_USER_CONTEXT(t->box->storage->user);
 
        if (lt->changes > 0 && !muser->group_events) {
                i_info("Transaction rolled back: "
@@ -555,14 +555,15 @@ mail_log_transaction_rollback(struct mailbox_transaction_context *t)
 }
 
 static struct mailbox *
-mail_log_mailbox_open(struct mail_storage *storage, const char *name,
-                     struct istream *input, enum mailbox_open_flags flags)
+mail_log_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                     const char *name, struct istream *input,
+                     enum mailbox_open_flags flags)
 {
        union mail_storage_module_context *lstorage = MAIL_LOG_CONTEXT(storage);
        struct mailbox *box;
        union mailbox_module_context *lbox;
 
-       box = lstorage->super.mailbox_open(storage, name, input, flags);
+       box = lstorage->super.mailbox_open(storage, list, name, input, flags);
        if (box == NULL)
                return NULL;
 
index 6affe9ae2b439f929d05996db34fb3d15b6545d0..06a1753c26ac3bf6f401d83716a07549874315a4 100644 (file)
@@ -107,15 +107,13 @@ mbox_snarf_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
 {
        struct mbox_snarf_mail_storage *mstorage =
                MBOX_SNARF_CONTEXT(box->storage);
-       struct mail_storage *storage;
        struct mbox_snarf_mailbox *mbox = MBOX_SNARF_CONTEXT(box);
 
        if (mbox->spool_mbox == NULL) {
                /* try to open the spool mbox */
                mstorage->open_spool_inbox = TRUE;
-               storage = box->storage;
                mbox->spool_mbox =
-                       mailbox_open(&storage, "INBOX", NULL,
+                       mailbox_open(box->list, "INBOX", NULL,
                                     MAILBOX_OPEN_KEEP_RECENT |
                                     MAILBOX_OPEN_NO_INDEX_FILES);
                mstorage->open_spool_inbox = FALSE;
@@ -137,12 +135,12 @@ static int mbox_snarf_close(struct mailbox *box)
 }
 
 static struct mailbox *
-mbox_snarf_mailbox_open(struct mail_storage *storage, const char *name,
-                       struct istream *input, enum mailbox_open_flags flags)
+mbox_snarf_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                       const char *name, struct istream *input,
+                       enum mailbox_open_flags flags)
 {
        struct mbox_snarf_mail_storage *mstorage =
                MBOX_SNARF_CONTEXT(storage);
-       struct mailbox_list *list;
        struct mailbox *box;
        struct mbox_snarf_mailbox *mbox;
        struct stat st;
@@ -150,7 +148,6 @@ mbox_snarf_mailbox_open(struct mail_storage *storage, const char *name,
        enum mailbox_list_flags old_list_flags;
        bool use_snarfing = FALSE;
 
-       list = mail_storage_get_list(storage);
        old_list_flags = list->flags;
 
        if (strcasecmp(name, "INBOX") == 0 && !mstorage->open_spool_inbox) {
@@ -167,7 +164,7 @@ mbox_snarf_mailbox_open(struct mail_storage *storage, const char *name,
        }
 
        box = mstorage->module_ctx.super.
-               mailbox_open(storage, name, input, flags);
+               mailbox_open(storage, list, name, input, flags);
        storage->flags = old_flags;
        list->flags = old_list_flags;
 
@@ -188,7 +185,7 @@ mbox_snarf_mail_storage_create(struct mail_storage *storage, const char *path)
 {
        struct mbox_snarf_mail_storage *mstorage;
 
-       path = mail_user_home_expand(storage->ns->user, path);
+       path = mail_user_home_expand(storage->user, path);
        mstorage = p_new(storage->pool, struct mbox_snarf_mail_storage, 1);
        mstorage->snarf_inbox_path = p_strdup(storage->pool, path);
        mstorage->module_ctx.super = storage->v;
@@ -201,7 +198,7 @@ static void mbox_snarf_mail_storage_created(struct mail_storage *storage)
 {
        const char *path;
 
-       path = mail_user_plugin_getenv(storage->ns->user, "mbox_snarf");
+       path = mail_user_plugin_getenv(storage->user, "mbox_snarf");
        if (path != NULL)
                mbox_snarf_mail_storage_create(storage, path);
 
index 09f9aa3377496593cff7d4513a48cc5eade3cd3a..33294651a79ceb71b6099b4dad767fdaf3c31c88 100644 (file)
@@ -4,10 +4,11 @@
 #include "array.h"
 #include "mail-search-build.h"
 #include "mail-storage.h"
+#include "mail-namespace.h"
 #include "quota-private.h"
 
 static int
-quota_count_mailbox(struct quota_root *root, struct mail_storage *storage,
+quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
                    const char *name, uint64_t *bytes_r, uint64_t *count_r)
 {
        struct quota_rule *rule;
@@ -26,10 +27,10 @@ quota_count_mailbox(struct quota_root *root, struct mail_storage *storage,
                return 0;
        }
 
-       box = mailbox_open(&storage, name, NULL,
+       box = mailbox_open(ns->list, name, NULL,
                           MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
        if (box == NULL) {
-               mail_storage_get_last_error(storage, &error);
+               mailbox_list_get_last_error(ns->list, &error);
                if (error == MAIL_ERROR_TEMP)
                        return -1;
                /* non-temporary error, e.g. ACLs denied access. */
@@ -68,19 +69,19 @@ quota_count_mailbox(struct quota_root *root, struct mail_storage *storage,
 }
 
 static int
-quota_count_storage(struct quota_root *root, struct mail_storage *storage,
-                   uint64_t *bytes, uint64_t *count)
+quota_count_namespace(struct quota_root *root, struct mail_namespace *ns,
+                     uint64_t *bytes, uint64_t *count)
 {
        struct mailbox_list_iterate_context *ctx;
        const struct mailbox_info *info;
        int ret = 0;
 
-       ctx = mailbox_list_iter_init(storage->list, "*",
+       ctx = mailbox_list_iter_init(ns->list, "*",
                                     MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        while ((info = mailbox_list_iter_next(ctx)) != NULL) {
                if ((info->flags & (MAILBOX_NONEXISTENT |
                                    MAILBOX_NOSELECT)) == 0) {
-                       ret = quota_count_mailbox(root, storage, info->name,
+                       ret = quota_count_mailbox(root, ns, info->name,
                                                  bytes, count);
                        if (ret < 0)
                                break;
@@ -94,18 +95,19 @@ quota_count_storage(struct quota_root *root, struct mail_storage *storage,
 
 int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
 {
-       struct mail_storage *const *storages;
+       struct mail_namespace *const *namespaces;
        unsigned int i, count;
        int ret = 0;
 
        *bytes_r = *count_r = 0;
 
-       storages = array_get(&root->quota->storages, &count);
+       namespaces = array_get(&root->quota->namespaces, &count);
        for (i = 0; i < count; i++) {
-               if (!quota_root_is_storage_visible(root, storages[i]))
+               if (!quota_root_is_namespace_visible(root, namespaces[i]))
                        continue;
 
-               ret = quota_count_storage(root, storages[i], bytes_r, count_r);
+               ret = quota_count_namespace(root, namespaces[i],
+                                           bytes_r, count_r);
                if (ret < 0)
                        break;
        }
index 1b9a033509f4cba28904ec9cf1830a51cab3a6b5..687504a36a5e44504ef16cee1894e6b13bb9229e 100644 (file)
@@ -148,7 +148,7 @@ static void quota_count_path_add(ARRAY_TYPE(quota_count_path) *paths,
 static int
 get_quota_root_usage(struct quota_root *root, uint64_t *value_r)
 {
-       struct mail_storage *const *storages;
+       struct mail_namespace *const *namespaces;
        ARRAY_TYPE(quota_count_path) paths;
        const struct quota_count_path *count_paths;
        unsigned int i, count;
@@ -156,17 +156,19 @@ get_quota_root_usage(struct quota_root *root, uint64_t *value_r)
        bool is_file;
 
        t_array_init(&paths, 8);
-       storages = array_get(&root->quota->storages, &count);
+       namespaces = array_get(&root->quota->namespaces, &count);
        for (i = 0; i < count; i++) {
-               if (!quota_root_is_storage_visible(root, storages[i]))
+               if (!quota_root_is_namespace_visible(root, namespaces[i]))
                        continue;
 
-               path = mail_storage_get_mailbox_path(storages[i], "", &is_file);
+               is_file = mail_storage_is_mailbox_file(namespaces[i]->storage);
+               path = mailbox_list_get_path(namespaces[i]->list, NULL,
+                                            MAILBOX_LIST_PATH_TYPE_MAILBOX);
                quota_count_path_add(&paths, path, FALSE);
 
                /* INBOX may be in different path. */
-               path = mail_storage_get_mailbox_path(storages[i], "INBOX",
-                                                    &is_file);
+               path = mailbox_list_get_path(namespaces[i]->list, "INBOX",
+                                            MAILBOX_LIST_PATH_TYPE_MAILBOX);
                quota_count_path_add(&paths, path, is_file);
        }
 
index 63f3b62ed2fb439e86b38575654637f3893f968e..0590a745b2c4b34f4d43e43339151ea2b3c28d98 100644 (file)
@@ -249,19 +249,19 @@ static void fs_quota_add_missing_mounts(struct quota *quota)
        }
 }
 
-static void fs_quota_storage_added(struct quota *quota,
-                                  struct mail_storage *storage)
+static void fs_quota_namespace_added(struct quota *quota,
+                                    struct mail_namespace *ns)
 {
        struct fs_quota_mountpoint *mount;
        struct fs_quota_root *root;
        const char *dir;
-       bool is_file;
 
-       dir = mail_storage_get_mailbox_path(storage, "", &is_file);
+       dir = mailbox_list_get_path(ns->list, NULL,
+                                   MAILBOX_LIST_PATH_TYPE_MAILBOX);
        mount = fs_quota_mountpoint_get(dir);
        if (mount != NULL) {
                if (quota->set->debug) {
-                       i_info("fs quota add storage dir = %s", dir);
+                       i_info("fs quota add mailbox dir = %s", dir);
                        i_info("fs quota block device = %s", mount->device_path);
                        i_info("fs quota mount point = %s", mount->mount_path);
                }
@@ -709,10 +709,10 @@ static bool fs_quota_match_box(struct quota_root *_root, struct mailbox *box)
        struct fs_quota_root *root = (struct fs_quota_root *)_root;
        struct stat mst, rst;
        const char *mailbox_path;
-       bool is_file, match;
+       bool match;
 
-       mailbox_path = mail_storage_get_mailbox_path(box->storage, box->name,
-                                                    &is_file);
+       mailbox_path = mailbox_list_get_path(box->list, box->name,
+                                            MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(mailbox_path, &mst) < 0) {
                if (errno != ENOENT)
                        i_error("stat(%s) failed: %m", mailbox_path);
@@ -795,7 +795,7 @@ struct quota_backend quota_backend_fs = {
                fs_quota_deinit,
                NULL,
 
-               fs_quota_storage_added,
+               fs_quota_namespace_added,
 
                fs_quota_root_get_resources,
                fs_quota_get_resource,
index 1287e9d5243f500b84c6880ff598618a9ec3a98f..6487550abfde9e8da1e419d3efdc30382fb89b7f 100644 (file)
@@ -23,6 +23,7 @@
 struct maildir_quota_root {
        struct quota_root root;
 
+       struct mail_namespace *maildirsize_ns;
        const char *maildirsize_path;
 
        uint64_t total_bytes;
@@ -36,7 +37,7 @@ struct maildir_quota_root {
 };
 
 struct maildir_list_context {
-       struct mail_storage *storage;
+       struct mailbox_list *list;
        struct maildir_quota_root *root;
        struct mailbox_list_iterate_context *iter;
        const struct mailbox_info *info;
@@ -123,16 +124,15 @@ static int maildir_sum_dir(const char *dir, uint64_t *total_bytes,
 }
 
 static struct maildir_list_context *
-maildir_list_init(struct maildir_quota_root *root,
-                 struct mail_storage *storage)
+maildir_list_init(struct maildir_quota_root *root, struct mailbox_list *list)
 {
        struct maildir_list_context *ctx;
 
        ctx = i_new(struct maildir_list_context, 1);
-       ctx->storage = storage;
        ctx->root = root;
        ctx->path = str_new(default_pool, 512);
-       ctx->iter = mailbox_list_iter_init(mail_storage_get_list(storage), "*",
+       ctx->list = list;
+       ctx->iter = mailbox_list_iter_init(list, "*",
                                           MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
        return ctx;
 }
@@ -142,7 +142,6 @@ maildir_list_next(struct maildir_list_context *ctx, time_t *mtime_r)
 {
        struct quota_rule *rule;
        struct stat st;
-       bool is_file;
 
        for (;;) {
                if (ctx->state == 0) {
@@ -161,9 +160,8 @@ maildir_list_next(struct maildir_list_context *ctx, time_t *mtime_r)
                T_BEGIN {
                        const char *path;
 
-                       path = mail_storage_get_mailbox_path(ctx->storage,
-                                                            ctx->info->name,
-                                                            &is_file);
+                       path = mailbox_list_get_path(ctx->list, ctx->info->name,
+                                       MAILBOX_LIST_PATH_TYPE_MAILBOX);
                        str_truncate(ctx->path, 0);
                        str_append(ctx->path, path);
                        str_append(ctx->path, ctx->state == 0 ?
@@ -198,13 +196,13 @@ static int maildir_list_deinit(struct maildir_list_context *ctx)
 
 static int
 maildirs_check_have_changed(struct maildir_quota_root *root,
-                           struct mail_storage *storage, time_t latest_mtime)
+                           struct mail_namespace *ns, time_t latest_mtime)
 {
        struct maildir_list_context *ctx;
        time_t mtime;
        int ret = 0;
 
-       ctx = maildir_list_init(root, storage);
+       ctx = maildir_list_init(root, ns->list);
        while (maildir_list_next(ctx, &mtime) != NULL) {
                if (mtime > latest_mtime) {
                        ret = 1;
@@ -218,8 +216,10 @@ maildirs_check_have_changed(struct maildir_quota_root *root,
 
 static int maildirsize_write(struct maildir_quota_root *root, const char *path)
 {
+       const struct mail_storage_settings *set =
+               root->maildirsize_ns->mail_set;
        struct quota_root *_root = &root->root;
-       struct mail_storage *const *storages;
+       struct mail_namespace *const *namespaces;
        unsigned int i, count;
        struct dotlock *dotlock;
        const char *p, *dir;
@@ -234,21 +234,21 @@ static int maildirsize_write(struct maildir_quota_root *root, const char *path)
           use the inbox namespace's permissions if possible. */
        mode = 0600; dir_mode = 0700;
        gid = dir_gid = (gid_t)-1;
-       storages = array_get(&root->root.quota->storages, &count);
+       namespaces = array_get(&root->root.quota->namespaces, &count);
        i_assert(count > 0);
        for (i = 0; i < count; i++) {
-               if ((storages[i]->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
-                       mailbox_list_get_permissions(storages[i]->ns->list,
+               if ((namespaces[i]->flags & NAMESPACE_FLAG_INBOX) != 0) {
+                       mailbox_list_get_permissions(namespaces[i]->list,
                                                     NULL, &mode, &gid);
-                       mailbox_list_get_dir_permissions(storages[i]->ns->list,
+                       mailbox_list_get_dir_permissions(namespaces[i]->list,
                                                         NULL,
                                                         &dir_mode, &dir_gid);
                        break;
                }
        }
 
-       dotlock_settings.use_excl_lock = storages[0]->set->dotlock_use_excl;
-       dotlock_settings.nfs_flush = storages[0]->set->mail_nfs_storage;
+       dotlock_settings.use_excl_lock = set->dotlock_use_excl;
+       dotlock_settings.nfs_flush = set->mail_nfs_storage;
        fd = file_dotlock_open_mode(&dotlock_settings, path,
                                    DOTLOCK_CREATE_FLAG_NONBLOCK,
                                    mode, (uid_t)-1, gid, &dotlock);
@@ -317,15 +317,15 @@ static void maildirsize_recalculate_init(struct maildir_quota_root *root)
        root->recalc_last_stamp = 0;
 }
 
-static int maildirsize_recalculate_storage(struct maildir_quota_root *root,
-                                          struct mail_storage *storage)
+static int maildirsize_recalculate_namespace(struct maildir_quota_root *root,
+                                            struct mail_namespace *ns)
 {
        struct maildir_list_context *ctx;
        const char *dir;
        time_t mtime;
        int ret = 0;
 
-       ctx = maildir_list_init(root, storage);
+       ctx = maildir_list_init(root, ns->list);
        while ((dir = maildir_list_next(ctx, &mtime)) != NULL) {
                if (mtime > root->recalc_last_stamp)
                        root->recalc_last_stamp = mtime;
@@ -369,19 +369,19 @@ static int maildirsize_recalculate_finish(struct maildir_quota_root *root,
 
 static int maildirsize_recalculate(struct maildir_quota_root *root)
 {
-       struct mail_storage *const *storages;
+       struct mail_namespace *const *namespaces;
        unsigned int i, count;
        int ret = 0;
 
        maildirsize_recalculate_init(root);
 
-       /* count mails from all storages */
-       storages = array_get(&root->root.quota->storages, &count);
+       /* count mails from all namespaces */
+       namespaces = array_get(&root->root.quota->namespaces, &count);
        for (i = 0; i < count; i++) {
-               if (!quota_root_is_storage_visible(&root->root, storages[i]))
+               if (!quota_root_is_namespace_visible(&root->root, namespaces[i]))
                        continue;
 
-               if (maildirsize_recalculate_storage(root, storages[i]) < 0) {
+               if (maildirsize_recalculate_namespace(root, namespaces[i]) < 0) {
                        ret = -1;
                        break;
                }
@@ -390,11 +390,11 @@ static int maildirsize_recalculate(struct maildir_quota_root *root)
        if (ret == 0) {
                /* check if any of the directories have changed */
                for (i = 0; i < count; i++) {
-                       if (!quota_root_is_storage_visible(&root->root,
-                                                          storages[i]))
+                       if (!quota_root_is_namespace_visible(&root->root,
+                                                          namespaces[i]))
                                continue;
 
-                       ret = maildirs_check_have_changed(root, storages[i],
+                       ret = maildirs_check_have_changed(root, namespaces[i],
                                                root->recalc_last_stamp);
                        if (ret != 0)
                                break;
@@ -623,7 +623,7 @@ static bool maildirquota_limits_init(struct maildir_quota_root *root)
                root->limits_initialized = TRUE;
 
                if (root->maildirsize_path == NULL) {
-                       i_warning("quota maildir: No maildir storages, "
+                       i_warning("quota maildir: No maildir namespaces, "
                                  "ignoring quota.");
                }
        }
@@ -742,8 +742,8 @@ maildir_quota_parse_rule(struct quota_root_settings *root_set ATTR_UNUSED,
 }
 
 static void
-maildir_quota_root_storage_added(struct quota_root *_root,
-                                struct mail_storage *storage)
+maildir_quota_root_namespace_added(struct quota_root *_root,
+                                  struct mail_namespace *ns)
 {
        struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
        const char *control_dir;
@@ -751,28 +751,29 @@ maildir_quota_root_storage_added(struct quota_root *_root,
        if (root->maildirsize_path != NULL)
                return;
 
-       control_dir = mail_storage_get_mailbox_control_dir(storage, "");
+       control_dir = mailbox_list_get_path(ns->list, NULL,
+                                           MAILBOX_LIST_PATH_TYPE_CONTROL);
+       root->maildirsize_ns = ns;
        root->maildirsize_path =
                p_strconcat(_root->pool, control_dir,
                            "/"MAILDIRSIZE_FILENAME, NULL);
 }
 
 static void
-maildir_quota_storage_added(struct quota *quota, struct mail_storage *storage)
+maildir_quota_namespace_added(struct quota *quota, struct mail_namespace *ns)
 {
        struct quota_root **roots;
        unsigned int i, count;
 
-       if (strcmp(storage->name, "maildir") != 0)
+       if (strcmp(ns->storage->name, "maildir") != 0)
                return;
 
        roots = array_get_modifiable(&quota->roots, &count);
        for (i = 0; i < count; i++) {
                if (roots[i]->backend.name == quota_backend_maildir.name &&
                    ((roots[i]->ns_prefix == NULL &&
-                     storage->ns->type == NAMESPACE_PRIVATE) ||
-                    roots[i]->ns == storage->ns))
-                       maildir_quota_root_storage_added(roots[i], storage);
+                     ns->type == NAMESPACE_PRIVATE) || roots[i]->ns == ns))
+                       maildir_quota_root_namespace_added(roots[i], ns);
        }
 }
 
@@ -840,7 +841,7 @@ struct quota_backend quota_backend_maildir = {
                maildir_quota_init,
                maildir_quota_deinit,
                maildir_quota_parse_rule,
-               maildir_quota_storage_added,
+               maildir_quota_namespace_added,
                maildir_quota_root_get_resources,
                maildir_quota_get_resource,
                maildir_quota_update,
index 45a7e3b2231759201b8a78b9e7807fbca80ec97f..4899bd3d54b470a1a44470a0a6b21c8ae1d68f69 100644 (file)
@@ -2,6 +2,7 @@
 #define QUOTA_PRIVATE_H
 
 #include "mail-storage-private.h"
+#include "mail-namespace.h"
 #include "quota.h"
 
 /* Modules should use do "my_id = quota_module_id++" and
@@ -13,7 +14,7 @@ struct quota {
        struct quota_settings *set;
 
        ARRAY_DEFINE(roots, struct quota_root *);
-       ARRAY_DEFINE(storages, struct mail_storage *);
+       ARRAY_DEFINE(namespaces, struct mail_namespace *);
 };
 
 struct quota_settings {
@@ -53,9 +54,9 @@ struct quota_backend_vfuncs {
                           struct quota_rule *rule,
                           const char *str, const char **error_r);
 
-       /* called once for each backend */
-       void (*storage_added)(struct quota *quota,
-                             struct mail_storage *storage);
+       /* called once for each namespace */
+       void (*namespace_added)(struct quota *quota,
+                               struct mail_namespace *ns);
 
        const char *const *(*get_resources)(struct quota_root *root);
        int (*get_resource)(struct quota_root *root,
@@ -134,13 +135,13 @@ struct quota_transaction_context {
 };
 
 /* Register storage to all user's quota roots. */
-void quota_add_user_storage(struct quota *quota, struct mail_storage *storage);
-void quota_remove_user_storage(struct mail_storage *storage);
+void quota_add_user_namespace(struct quota *quota, struct mail_namespace *ns);
+void quota_remove_user_namespace(struct mail_namespace *ns);
 
 struct quota *quota_get_mail_user_quota(struct mail_user *user);
 
-bool quota_root_is_storage_visible(struct quota_root *root,
-                                  struct mail_storage *storage);
+bool quota_root_is_namespace_visible(struct quota_root *root,
+                                    struct mail_namespace *ns);
 struct quota_rule *
 quota_root_rule_find(struct quota_root_settings *root_set, const char *name);
 
index a8e6333e89dde99ccd6b7edc0e888c2423b0b8cd..34aa281741031b2981b8de97912ab7ae2916de4b 100644 (file)
@@ -6,6 +6,7 @@
 #include "mail-search-build.h"
 #include "mail-storage-private.h"
 #include "mailbox-list-private.h"
+#include "maildir-storage.h"
 #include "quota-private.h"
 #include "quota-plugin.h"
 
@@ -20,8 +21,6 @@
 
 struct quota_mailbox_list {
        union mailbox_list_module_context module_ctx;
-
-       struct mail_storage *storage;
 };
 
 struct quota_mailbox {
@@ -357,16 +356,17 @@ static int quota_mailbox_close(struct mailbox *box)
 }
 
 static struct mailbox *
-quota_mailbox_open(struct mail_storage *storage, const char *name,
-                  struct istream *input, enum mailbox_open_flags flags)
+quota_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                  const char *name, struct istream *input,
+                  enum mailbox_open_flags flags)
 {
        union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
        struct mailbox *box;
        struct quota_mailbox *qbox;
 
-       box = qstorage->super.mailbox_open(storage, name, input, flags);
-       if (box == NULL)
-               return NULL;
+       box = qstorage->super.mailbox_open(storage, list, name, input, flags);
+       if (box == NULL || QUOTA_LIST_CONTEXT(list) == NULL)
+               return box;
 
        qbox = p_new(box->pool, struct quota_mailbox, 1);
        qbox->module_ctx.super = box->v;
@@ -419,11 +419,18 @@ quota_mailbox_delete_shrink_quota(struct mailbox *box)
        return ret;
 }
 
+static void quota_mailbox_list_deinit(struct mailbox_list *list)
+{
+       struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(list);
+
+       quota_remove_user_namespace(list->ns);
+       qlist->module_ctx.super.deinit(list);
+}
+
 static int
 quota_mailbox_list_delete(struct mailbox_list *list, const char *name)
 {
        struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(list);
-       struct mail_storage *storage;
        struct mailbox *box;
        enum mail_error error;
        const char *str;
@@ -433,11 +440,10 @@ quota_mailbox_list_delete(struct mailbox_list *list, const char *name)
           and free the quota for all the messages existing in it. Open the
           mailbox locked so that other processes can't mess up the quota
           calculations by adding/removing mails while we're doing this. */
-       storage = qlist->storage;
-       box = mailbox_open(&storage, name, NULL, MAILBOX_OPEN_KEEP_RECENT |
+       box = mailbox_open(list, name, NULL, MAILBOX_OPEN_KEEP_RECENT |
                           MAILBOX_OPEN_KEEP_LOCKED);
        if (box == NULL) {
-               str = mail_storage_get_last_error(qlist->storage, &error);
+               str = mailbox_list_get_last_error(list, &error);
                if (error != MAIL_ERROR_NOTPOSSIBLE) {
                        ret = -1;
                } else {
@@ -445,11 +451,10 @@ quota_mailbox_list_delete(struct mailbox_list *list, const char *name)
                        ret = 0;
                }
        } else {
-               ret = quota_mailbox_delete_shrink_quota(box);
-       }
-       if (ret < 0) {
-               str = mail_storage_get_last_error(qlist->storage, &error);
-               mailbox_list_set_error(list, error, str);
+               if ((ret = quota_mailbox_delete_shrink_quota(box)) < 0) {
+                       str = mail_storage_get_last_error(box->storage, &error);
+                       mailbox_list_set_error(list, error, str);
+               }
        }
        if (box != NULL)
                mailbox_close(&box);
@@ -459,16 +464,6 @@ quota_mailbox_list_delete(struct mailbox_list *list, const char *name)
                qlist->module_ctx.super.delete_mailbox(list, name);
 }
 
-static void quota_storage_destroy(struct mail_storage *storage)
-{
-       union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
-
-       quota_remove_user_storage(storage);
-
-       if (qstorage->super.destroy != NULL)
-               qstorage->super.destroy(storage);
-}
-
 struct quota *quota_get_mail_user_quota(struct mail_user *user)
 {
        struct quota_user *quser = QUOTA_USER_CONTEXT(user);
@@ -505,29 +500,28 @@ void quota_mail_user_created(struct mail_user *user)
                quota_next_hook_mail_user_created(user);
 }
 
+static void quota_maildir_storage_set(struct mail_storage *storage)
+{
+       /* FIXME: a bit ugly location for this code. */
+       if (strcmp(storage->name, "maildir") == 0) {
+               /* For newly generated filenames add ,S=size. */
+               struct maildir_storage *mstorage =
+                       (struct maildir_storage *)storage;
+
+               mstorage->save_size_in_filename = TRUE;
+       }
+}
+
 void quota_mail_storage_created(struct mail_storage *storage)
 {
-       struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(storage->list);
        union mail_storage_module_context *qstorage;
-       struct quota *quota;
 
-       if (qlist != NULL) {
-               qlist->storage = storage;
-               qstorage = p_new(storage->pool,
-                                union mail_storage_module_context, 1);
-               qstorage->super = storage->v;
-               storage->v.destroy = quota_storage_destroy;
-               storage->v.mailbox_open = quota_mailbox_open;
+       qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
+       qstorage->super = storage->v;
+       storage->v.mailbox_open = quota_mailbox_open;
 
-               MODULE_CONTEXT_SET_SELF(storage, quota_storage_module,
-                                       qstorage);
-
-               /* register to owner's quota roots */
-               quota = storage->ns->owner != NULL ?
-                       quota_get_mail_user_quota(storage->ns->owner) :
-                       quota_get_mail_user_quota(storage->ns->user);
-               quota_add_user_storage(quota, storage);
-       }
+       MODULE_CONTEXT_SET_SELF(storage, quota_storage_module, qstorage);
+       quota_maildir_storage_set(storage);
 
        if (quota_next_hook_mail_storage_created != NULL)
                quota_next_hook_mail_storage_created(storage);
@@ -551,7 +545,7 @@ quota_find_root_for_ns(struct quota *quota, struct mail_namespace *ns)
 void quota_mailbox_list_created(struct mailbox_list *list)
 {
        struct quota_mailbox_list *qlist;
-       struct quota *quota;
+       struct quota *quota = NULL;
        struct quota_root *root;
        bool add;
 
@@ -572,9 +566,15 @@ void quota_mailbox_list_created(struct mailbox_list *list)
        if (add) {
                qlist = p_new(list->pool, struct quota_mailbox_list, 1);
                qlist->module_ctx.super = list->v;
+               list->v.deinit = quota_mailbox_list_deinit;
                list->v.delete_mailbox = quota_mailbox_list_delete;
-
                MODULE_CONTEXT_SET(list, quota_mailbox_list_module, qlist);
+
+               /* register to owner's quota roots */
+               quota = list->ns->owner != NULL ?
+                       quota_get_mail_user_quota(list->ns->owner) :
+                       quota_get_mail_user_quota(list->ns->user);
+               quota_add_user_namespace(quota, list->ns);
        }
        if (quota_next_hook_mailbox_list_created != NULL)
                quota_next_hook_mailbox_list_created(list);
index fe6b943c9a0d8fe983c9abeb036685b723bfbd90..fe96b6375ed0d698c3c2f7b3136531b8ec532b06 100644 (file)
@@ -4,7 +4,6 @@
 #include "array.h"
 #include "hash.h"
 #include "mailbox-list-private.h"
-#include "maildir-storage.h"
 #include "quota-private.h"
 #include "quota-fs.h"
 
@@ -259,7 +258,7 @@ struct quota *quota_init(struct quota_settings *quota_set,
        i_array_init(&quota->roots, 8);
 
        root_sets = array_get(&quota_set->root_sets, &count);
-       i_array_init(&quota->storages, count);
+       i_array_init(&quota->namespaces, count);
        for (i = 0; i < count; i++) {
                root = quota_root_init(root_sets[i], quota);
                array_append(&quota->roots, &root, 1);
@@ -279,7 +278,7 @@ void quota_deinit(struct quota **_quota)
        for (i = 0; i < count; i++)
                quota_root_deinit(roots[i]);
        array_free(&quota->roots);
-       array_free(&quota->storages);
+       array_free(&quota->namespaces);
        i_free(quota);
 }
 
@@ -531,45 +530,31 @@ static bool quota_root_get_rule_limits(struct quota_root *root,
        return found;
 }
 
-static void quota_maildir_storage_set(struct mail_storage *storage)
-{
-       /* FIXME: a bit ugly location for this code. */
-       if (strcmp(storage->name, "maildir") == 0) {
-               /* For newly generated filenames add ,S=size. */
-               struct maildir_storage *mstorage =
-                       (struct maildir_storage *)storage;
-
-               mstorage->save_size_in_filename = TRUE;
-       }
-}
-
-void quota_add_user_storage(struct quota *quota, struct mail_storage *storage)
+void quota_add_user_namespace(struct quota *quota, struct mail_namespace *ns)
 {
        struct quota_root *const *roots;
-       struct mail_storage *const *storages;
+       struct mail_namespace *const *namespaces;
        struct quota_backend **backends;
        const char *path, *path2;
        unsigned int i, j, count;
-       bool is_file;
-
-       quota_maildir_storage_set(storage);
 
-       /* first check if there already exists a storage with the exact same
+       /* first check if there already exists a namespace with the exact same
           path. we don't want to count them twice. */
-       path = mail_storage_get_mailbox_path(storage, "", &is_file);
+       path = mailbox_list_get_path(ns->list, NULL,
+                                    MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (path != NULL) {
-               storages = array_get(&quota->storages, &count);
+               namespaces = array_get(&quota->namespaces, &count);
                for (i = 0; i < count; i++) {
-                       path2 = mail_storage_get_mailbox_path(storages[i], "",
-                                                             &is_file);
-                       if (path2 != NULL && strcmp(path, path2) == 0) {
+                       path2 = mailbox_list_get_path(namespaces[i]->list, NULL,
+                                       MAILBOX_LIST_PATH_TYPE_MAILBOX);
+                       if (strcmp(path, path2) == 0) {
                                /* duplicate */
                                return;
                        }
                }
        }
 
-       array_append(&quota->storages, &storage, 1);
+       array_append(&quota->namespaces, &ns, 1);
 
        roots = array_get(&quota->roots, &count);
        /* @UNSAFE: get different backends into one array */
@@ -584,29 +569,29 @@ void quota_add_user_storage(struct quota *quota, struct mail_storage *storage)
        }
 
        for (i = 0; backends[i] != NULL; i++) {
-               if (backends[i]->v.storage_added != NULL)
-                       backends[i]->v.storage_added(quota, storage);
+               if (backends[i]->v.namespace_added != NULL)
+                       backends[i]->v.namespace_added(quota, ns);
        }
 }
 
-void quota_remove_user_storage(struct mail_storage *storage)
+void quota_remove_user_namespace(struct mail_namespace *ns)
 {
        struct quota *quota;
-       struct mail_storage *const *storages;
+       struct mail_namespace *const *namespaces;
        unsigned int i, count;
 
-       quota = storage->ns->owner != NULL ?
-               quota_get_mail_user_quota(storage->ns->owner) :
-               quota_get_mail_user_quota(storage->ns->user);
+       quota = ns->owner != NULL ?
+               quota_get_mail_user_quota(ns->owner) :
+               quota_get_mail_user_quota(ns->user);
        if (quota == NULL) {
-               /* no quota for this storage */
+               /* no quota for this namespace */
                return;
        }
 
-       storages = array_get(&quota->storages, &count);
+       namespaces = array_get(&quota->namespaces, &count);
        for (i = 0; i < count; i++) {
-               if (storages[i] == storage) {
-                       array_delete(&quota->storages, i, 1);
+               if (namespaces[i] == ns) {
+                       array_delete(&quota->namespaces, i, 1);
                        break;
                }
        }
@@ -658,21 +643,21 @@ quota_root_iter_init(struct mailbox *box)
        struct quota_root_iter *iter;
 
        iter = i_new(struct quota_root_iter, 1);
-       iter->quota = box->storage->ns->owner != NULL ?
-               quota_get_mail_user_quota(box->storage->ns->owner) :
-               quota_get_mail_user_quota(box->storage->ns->user);
+       iter->quota = box->list->ns->owner != NULL ?
+               quota_get_mail_user_quota(box->list->ns->owner) :
+               quota_get_mail_user_quota(box->list->ns->user);
        iter->box = box;
        return iter;
 }
 
-bool quota_root_is_storage_visible(struct quota_root *root,
-                                  struct mail_storage *storage)
+bool quota_root_is_namespace_visible(struct quota_root *root,
+                                    struct mail_namespace *ns)
 {
        if (root->ns != NULL) {
-               if (root->ns != storage->ns)
+               if (root->ns != ns)
                        return FALSE;
        } else {
-               if (storage->ns->owner == NULL)
+               if (ns->owner == NULL)
                        return FALSE;
        }
        return TRUE;
@@ -686,7 +671,7 @@ quota_root_is_visible(struct quota_root *root, struct mailbox *box,
                /* we don't want to include this root in quota enforcing */
                return FALSE;
        }
-       if (!quota_root_is_storage_visible(root, box->storage))
+       if (!quota_root_is_namespace_visible(root, box->list->ns))
                return FALSE;
        if (array_count(&root->quota->roots) == 1) {
                /* a single quota root: don't bother checking further */
@@ -816,9 +801,9 @@ struct quota_transaction_context *quota_transaction_begin(struct mailbox *box)
        struct quota_transaction_context *ctx;
 
        ctx = i_new(struct quota_transaction_context, 1);
-       ctx->quota = box->storage->ns->owner != NULL ?
-               quota_get_mail_user_quota(box->storage->ns->owner) :
-               quota_get_mail_user_quota(box->storage->ns->user);
+       ctx->quota = box->list->ns->owner != NULL ?
+               quota_get_mail_user_quota(box->list->ns->owner) :
+               quota_get_mail_user_quota(box->list->ns->user);
        ctx->box = box;
        ctx->bytes_left = (uint64_t)-1;
        ctx->count_left = (uint64_t)-1;
index b04216621a252dfcbfd8053fd112df8cca8536f6..4f59847a14449b6b954c8c51404da36b673c9ce7 100644 (file)
@@ -23,7 +23,7 @@ struct trash_mailbox {
        const char *name;
        int priority; /* lower number = higher priority */
 
-       struct mail_storage *storage;
+       struct mail_namespace *ns;
 
        /* temporarily set while cleaning: */
        struct mailbox *box;
@@ -52,10 +52,9 @@ static int (*trash_next_quota_test_alloc)(struct quota_transaction_context *,
 
 static int trash_clean_mailbox_open(struct trash_mailbox *trash)
 {
-       struct mail_storage *storage = trash->storage;
        struct mail_search_args *search_args;
 
-       trash->box = mailbox_open(&storage, trash->name, NULL,
+       trash->box = mailbox_open(trash->ns->list, trash->name, NULL,
                                  MAILBOX_OPEN_KEEP_RECENT);
        if (trash->box == NULL)
                return 0;
@@ -233,7 +232,7 @@ static bool trash_find_storage(struct mail_user *user,
                if (mail_namespace_update_name(ns, &name)) {
                        if (name != trash->name)
                                trash->name = p_strdup(user->pool, name);
-                       trash->storage = ns->storage;
+                       trash->ns = ns;
                        return TRUE;
                }
        }
index 31578323ee34234ee9a378eda9d01cdc55f59b86..f145e87fdca07f11445386fda2c28e0b013221fe 100644 (file)
@@ -100,7 +100,7 @@ static int
 virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
                          const char **error_r)
 {
-       struct mail_user *user = ctx->mbox->storage->storage.ns->user;
+       struct mail_user *user = ctx->mbox->storage->storage.user;
        struct virtual_backend_box *bbox;
        const char *name;
 
@@ -254,7 +254,7 @@ static bool virtual_config_match(const struct mailbox_info *info,
 
 static int virtual_config_expand_wildcards(struct virtual_parse_context *ctx)
 {
-       struct mail_user *user = ctx->mbox->storage->storage.ns->user;
+       struct mail_user *user = ctx->mbox->storage->storage.user;
        ARRAY_TYPE(virtual_backend_box) wildcard_boxes, neg_boxes;
        struct mailbox_list_iterate_context *iter;
        struct virtual_backend_box *const *wboxes;
@@ -314,7 +314,7 @@ static void virtual_config_search_args_dup(struct virtual_mailbox *mbox)
 
 int virtual_config_read(struct virtual_mailbox *mbox)
 {
-       struct mail_user *user = mbox->storage->storage.ns->user;
+       struct mail_user *user = mbox->storage->storage.user;
        struct virtual_parse_context ctx;
        const char *path, *line, *error;
        unsigned int linenum = 0;
@@ -327,18 +327,18 @@ int virtual_config_read(struct virtual_mailbox *mbox)
        fd = open(path, O_RDONLY);
        if (fd == -1) {
                if (errno == ENOENT) {
-                       mail_storage_set_error(mbox->ibox.storage,
+                       mailbox_list_set_error(mbox->ibox.box.list,
                                MAIL_ERROR_NOTPOSSIBLE,
                                "Virtual mailbox missing configuration file");
                        return -1;
                }
-               mail_storage_set_critical(mbox->ibox.storage,
+               mailbox_list_set_critical(mbox->ibox.box.list,
                                          "open(%s) failed: %m", path);
                return -1;
        }
 
        memset(&ctx, 0, sizeof(ctx));
-       ctx.sep = mail_namespace_get_root_sep(user->namespaces);
+       ctx.sep = mail_namespaces_get_root_sep(user->namespaces);
        ctx.mbox = mbox;
        ctx.pool = mbox->ibox.box.pool;
        ctx.rule = t_str_new(256);
@@ -353,7 +353,7 @@ int virtual_config_read(struct virtual_mailbox *mbox)
                else
                        ret = virtual_config_parse_line(&ctx, line, &error);
                if (ret < 0) {
-                       mail_storage_set_critical(mbox->ibox.storage,
+                       mailbox_list_set_critical(mbox->ibox.box.list,
                                                  "%s: Error at line %u: %s",
                                                  path, linenum, error);
                        break;
@@ -362,7 +362,7 @@ int virtual_config_read(struct virtual_mailbox *mbox)
        if (ret == 0) {
                ret = virtual_config_add_rule(&ctx, &error);
                if (ret < 0) {
-                       mail_storage_set_critical(mbox->ibox.storage,
+                       mailbox_list_set_critical(mbox->ibox.box.list,
                                                  "%s: Error at line %u: %s",
                                                  path, linenum, error);
                }
@@ -373,7 +373,7 @@ int virtual_config_read(struct virtual_mailbox *mbox)
                ret = virtual_config_expand_wildcards(&ctx);
 
        if (ret == 0 && array_count(&mbox->backend_boxes) == 0) {
-               mail_storage_set_critical(mbox->ibox.storage,
+               mailbox_list_set_critical(mbox->ibox.box.list,
                                          "%s: No mailboxes defined", path);
                ret = -1;
        }
index 3227562487664e14ad8d0c7fb8b6c2d98217e2f5..9522371b6ebd64b38dfd37743774250197986558 100644 (file)
@@ -336,7 +336,7 @@ virtual_mail_get_special(struct mail *mail, enum mail_fetch_field field,
                return -1;
        if (field == MAIL_FETCH_MAILBOX_NAME) {
                *value_r = p_strconcat(vmail->imail.data_pool,
-                                      box->storage->ns->prefix,
+                                      box->list->ns->prefix,
                                       box->name, NULL);
                return 0;
        }
index 057e8536f38cca4278764f75f80bb97542eaa685..31532c7b1f76786c314b41d02abc79adebe0d31a 100644 (file)
 #define VIRTUAL_LIST_CONTEXT(obj) \
        MODULE_CONTEXT(obj, virtual_mailbox_list_module)
 
+struct virtual_mailbox_list {
+       union mailbox_list_module_context module_ctx;
+};
+
 extern struct mail_storage virtual_storage;
 extern struct mailbox virtual_mailbox;
 
@@ -30,27 +34,7 @@ struct virtual_storage_module virtual_storage_module =
 static MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
                                  &mailbox_list_module_register);
 
-static int
-virtual_list_delete_mailbox(struct mailbox_list *list, const char *name);
-static int
-virtual_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
-                            const char *dir, const char *fname,
-                            const char *mailbox_name,
-                            enum mailbox_list_file_type type,
-                            enum mailbox_info_flags *flags);
-
-void virtual_copy_error(struct mail_storage *dest, struct mail_storage *src)
-{
-       const char *str;
-       enum mail_error error;
-
-       str = mail_storage_get_last_error(src, &error);
-       if ((src->ns->flags & NAMESPACE_FLAG_HIDDEN) == 0) {
-               str = t_strdup_printf("%s (namespace %s)", str,
-                                     src->ns->prefix);
-       }
-       mail_storage_set_error(dest, error, str);
-}
+static void virtual_list_init(struct mailbox_list *list);
 
 void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
 {
@@ -58,43 +42,16 @@ void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
        enum mail_error error;
 
        str = mail_storage_get_last_error(src->storage, &error);
-       if ((src->storage->ns->flags & NAMESPACE_FLAG_HIDDEN) != 0)
+       if ((src->list->ns->flags & NAMESPACE_FLAG_HIDDEN) != 0)
                str = t_strdup_printf("%s (mailbox %s)", str, src->name);
        else {
                str = t_strdup_printf("%s (mailbox %s%s)", str,
-                                     src->storage->ns->prefix, src->name);
+                                     src->list->ns->prefix, src->name);
        }
        mail_storage_set_error(dest->storage, error, str);
 }
 
-static int
-virtual_get_list_settings(struct mailbox_list_settings *list_set,
-                         const char *data, struct mail_storage *storage,
-                         const char **layout_r, const char **error_r)
-{
-       bool debug = storage->set->mail_debug;
-
-       *layout_r = "fs";
-
-       memset(list_set, 0, sizeof(*list_set));
-       list_set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
-       list_set->maildir_name = "";
-
-       if (data == NULL || *data == '\0' || *data == ':') {
-               /* we won't do any guessing for this format. */
-               if (debug)
-                       i_info("virtual: mailbox location not given");
-               *error_r = "Root mail directory not given";
-               return -1;
-       }
-
-       if (debug)
-               i_info("virtual: data=%s", data);
-       return mailbox_list_settings_parse(data, list_set, storage->ns,
-                                          layout_r, NULL, error_r);
-}
-
-static struct mail_storage *virtual_alloc(void)
+static struct mail_storage *virtual_storage_alloc(void)
 {
        struct virtual_storage *storage;
        pool_t pool;
@@ -104,55 +61,29 @@ static struct mail_storage *virtual_alloc(void)
        storage->storage = virtual_storage;
        storage->storage.pool = pool;
        p_array_init(&storage->open_stack, pool, 8);
-
        return &storage->storage;
 }
 
-static int virtual_create(struct mail_storage *_storage, const char *data,
-                         const char **error_r)
+static int
+virtual_storage_create(struct mail_storage *_storage ATTR_UNUSED,
+                      struct mail_namespace *ns,
+                      const char **error_r ATTR_UNUSED)
 {
-       struct virtual_storage *storage = (struct virtual_storage *)_storage;
-       struct mailbox_list_settings list_set;
-       struct stat st;
-       const char *layout;
-
-       _storage->ns->flags |= NAMESPACE_FLAG_NOQUOTA;
-
-       if (virtual_get_list_settings(&list_set, data, _storage,
-                                     &layout, error_r) < 0)
-               return -1;
-       list_set.mail_storage_flags = &_storage->flags;
-       list_set.lock_method = &_storage->lock_method;
-
-       if (stat(list_set.root_dir, &st) < 0) {
-               if (errno == ENOENT) {
-                       *error_r = t_strdup_printf(
-                               "Root mail directory doesn't exist: %s",
-                               list_set.root_dir);
-               } else if (errno == EACCES) {
-                       *error_r = mail_error_eacces_msg("stat",
-                                                        list_set.root_dir);
-               } else {
-                       *error_r = t_strdup_printf("stat(%s) failed: %m",
-                                                  list_set.root_dir);
-               }
-               return -1;
-       }
-
-       if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
-               return -1;
-       storage->list_module_ctx.super = _storage->list->v;
-       _storage->list->v.iter_is_mailbox = virtual_list_iter_is_mailbox;
-       _storage->list->v.delete_mailbox = virtual_list_delete_mailbox;
-
-       MODULE_CONTEXT_SET_FULL(_storage->list, virtual_mailbox_list_module,
-                               storage, &storage->list_module_ctx);
-
-       /* finish list init after we've overridden vfuncs */
-       mailbox_list_init(_storage->list, _storage->ns, &list_set, 0);
+       ns->flags |= NAMESPACE_FLAG_NOQUOTA;
+       virtual_list_init(ns->list);
        return 0;
 }
 
+static void
+virtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
+                                 struct mailbox_list_settings *set)
+{
+       if (set->layout == NULL)
+               set->layout = MAILBOX_LIST_NAME_FS;
+       if (set->subscription_fname == NULL)
+               set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
+}
+
 struct virtual_backend_box *
 virtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name)
 {
@@ -201,10 +132,9 @@ static bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage,
 static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
                                  enum mailbox_open_flags open_flags)
 {
-       struct mail_user *user = mbox->storage->storage.ns->user;
+       struct mail_user *user = mbox->storage->storage.user;
        struct virtual_backend_box *const *bboxes;
        struct mail_namespace *ns;
-       struct mail_storage *storage;
        unsigned int i, count;
        enum mail_error error;
        const char *str, *mailbox;
@@ -215,12 +145,11 @@ static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
        for (i = 0; i < count; ) {
                mailbox = bboxes[i]->name;
                ns = mail_namespace_find(user->namespaces, &mailbox);
-               storage = ns->storage;
-               bboxes[i]->box = mailbox_open(&storage, mailbox,
+               bboxes[i]->box = mailbox_open(ns->list, mailbox,
                                              NULL, open_flags);
 
                if (bboxes[i]->box == NULL) {
-                       str = mail_storage_get_last_error(storage, &error);
+                       str = mailbox_list_get_last_error(ns->list, &error);
                        if (bboxes[i]->wildcard &&
                            (error == MAIL_ERROR_PERM ||
                             error == MAIL_ERROR_NOTFOUND)) {
@@ -231,9 +160,9 @@ static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
                                bboxes = array_get(&mbox->backend_boxes, &count);
                                continue;
                        }
-                       if (storage != mbox->ibox.box.storage) {
+                       if (ns->list != mbox->ibox.box.list) {
                                /* copy the error */
-                               mail_storage_set_error(mbox->ibox.box.storage,
+                               mailbox_list_set_error(mbox->ibox.box.list,
                                                       error, str);
                        }
                        break;
@@ -257,8 +186,8 @@ static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
 }
 
 static struct mailbox *
-virtual_open(struct virtual_storage *storage, const char *name,
-            enum mailbox_open_flags flags)
+virtual_open(struct virtual_storage *storage, struct mailbox_list *list,
+            const char *name, enum mailbox_open_flags flags)
 {
        struct mail_storage *_storage = &storage->storage;
        struct virtual_mailbox *mbox;
@@ -273,17 +202,15 @@ virtual_open(struct virtual_storage *storage, const char *name,
                return NULL;
        }
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-       index = index_storage_alloc(_storage, name, flags,
-                                   VIRTUAL_INDEX_PREFIX);
+       index = index_storage_alloc(list, name, flags, VIRTUAL_INDEX_PREFIX);
 
        pool = pool_alloconly_create("virtual mailbox", 1024+512);
        mbox = p_new(pool, struct virtual_mailbox, 1);
        mbox->ibox.box = virtual_mailbox;
        mbox->ibox.box.pool = pool;
-       mbox->ibox.box.storage = &storage->storage;
-       mbox->ibox.storage = &storage->storage;
+       mbox->ibox.box.storage = _storage;
        mbox->ibox.mail_vfuncs = &virtual_mail_vfuncs;
        mbox->ibox.index = index;
 
@@ -312,32 +239,32 @@ virtual_open(struct virtual_storage *storage, const char *name,
 }
 
 static struct mailbox *
-virtual_mailbox_open(struct mail_storage *_storage, const char *name,
-                    struct istream *input, enum mailbox_open_flags flags)
+virtual_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
+                    const char *name, struct istream *input,
+                    enum mailbox_open_flags flags)
 {
        struct virtual_storage *storage = (struct virtual_storage *)_storage;
        const char *path;
        struct stat st;
 
        if (input != NULL) {
-               mail_storage_set_critical(_storage,
+               mailbox_list_set_critical(list,
                        "virtual doesn't support streamed mailboxes");
                return NULL;
        }
 
-       path = mailbox_list_get_path(_storage->list, name,
+       path = mailbox_list_get_path(list, name,
                                     MAILBOX_LIST_PATH_TYPE_MAILBOX);
        if (stat(path, &st) == 0)
-               return virtual_open(storage, name, flags);
+               return virtual_open(storage, list, name, flags);
        else if (errno == ENOENT) {
-               mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
+               mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
        } else if (errno == EACCES) {
-               mail_storage_set_critical(_storage, "%s",
+               mailbox_list_set_critical(list, "%s",
                        mail_error_eacces_msg("stat", path));
        } else {
-               mail_storage_set_critical(_storage, "stat(%s) failed: %m",
-                                         path);
+               mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
        }
        return NULL;
 }
@@ -359,7 +286,11 @@ static int virtual_storage_mailbox_close(struct mailbox *box)
 
                storage = bboxes[i]->box->storage;
                if (mailbox_close(&bboxes[i]->box) < 0) {
-                       virtual_copy_error(box->storage, storage);
+                       const char *str;
+                       enum mail_error error;
+
+                       str = mail_storage_get_last_error(storage, &error);
+                       mail_storage_set_error(box->storage, error, str);
                        ret = -1;
                }
                if (array_is_created(&bboxes[i]->sync_outside_expunges))
@@ -374,6 +305,7 @@ static int virtual_storage_mailbox_close(struct mailbox *box)
 }
 
 static int virtual_mailbox_create(struct mail_storage *_storage,
+                                 struct mailbox_list *list ATTR_UNUSED,
                                  const char *name ATTR_UNUSED,
                                  bool directory ATTR_UNUSED)
 {
@@ -455,7 +387,7 @@ virtual_delete_nonrecursive(struct mailbox_list *list, const char *path,
 static int
 virtual_list_delete_mailbox(struct mailbox_list *list, const char *name)
 {
-       struct virtual_storage *storage = VIRTUAL_LIST_CONTEXT(list);
+       struct virtual_mailbox_list *mlist = VIRTUAL_LIST_CONTEXT(list);
        struct stat st;
        const char *src;
 
@@ -466,7 +398,7 @@ virtual_list_delete_mailbox(struct mailbox_list *list, const char *name)
        index_storage_destroy_unrefed();
 
        /* delete the index and control directories */
-       if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
+       if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
                return -1;
 
        /* check if the mailbox actually exists */
@@ -628,6 +560,19 @@ static void virtual_class_deinit(void)
        virtual_transaction_class_deinit();
 }
 
+static void virtual_list_init(struct mailbox_list *list)
+{
+       struct virtual_mailbox_list *mlist;
+
+       mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
+       mlist->module_ctx.super = list->v;
+
+       list->v.iter_is_mailbox = virtual_list_iter_is_mailbox;
+       list->v.delete_mailbox = virtual_list_delete_mailbox;
+
+       MODULE_CONTEXT_SET(list, virtual_mailbox_list_module, mlist);
+}
+
 struct mail_storage virtual_storage = {
        MEMBER(name) VIRTUAL_STORAGE_NAME,
        MEMBER(mailbox_is_file) FALSE,
@@ -636,9 +581,10 @@ struct mail_storage virtual_storage = {
                NULL,
                virtual_class_init,
                virtual_class_deinit,
-               virtual_alloc,
-               virtual_create,
+               virtual_storage_alloc,
+               virtual_storage_create,
                index_storage_destroy,
+               virtual_storage_get_list_settings,
                NULL,
                virtual_mailbox_open,
                virtual_mailbox_create,
@@ -649,6 +595,7 @@ struct mail_storage virtual_storage = {
 struct mailbox virtual_mailbox = {
        MEMBER(name) NULL, 
        MEMBER(storage) NULL, 
+       MEMBER(list) NULL,
 
        {
                index_storage_is_readonly,
index a81376a942a8a80c63cc3792b5a717ec6f69b8aa..1822c59d7cc4c2e7b61163f3fdd32ea53577f85e 100644 (file)
@@ -168,7 +168,6 @@ int virtual_save_finish(struct mail_save_context *ctx);
 void virtual_save_cancel(struct mail_save_context *ctx);
 void virtual_save_free(struct virtual_save_context *ctx);
 
-void virtual_copy_error(struct mail_storage *dest, struct mail_storage *src);
 void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src);
 
 void virtual_transaction_class_init(void);
index da020517c1ed4f7905ef59fcfb34dfe859d31525..a60ef36e0303c1fdf29947a20942e2178ffba267 100644 (file)
@@ -179,21 +179,22 @@ static void zlib_maildir_open_init(struct mailbox *box)
 }
 
 static struct istream *
-zlib_mailbox_open_input(struct mail_storage *storage, const char *name)
+zlib_mailbox_open_input(struct mail_storage *storage, struct mailbox_list *list,
+                       const char *name)
 {
        struct zlib_handler *handler;
        const char *path;
        int fd;
-       bool is_file;
 
        handler = zlib_get_zlib_handler_ext(name);
        if (handler == NULL || handler->create_istream == NULL)
                return NULL;
 
-       path = mail_storage_get_mailbox_path(storage, name, &is_file);
-       if (is_file && path != NULL) {
+       if (mail_storage_is_mailbox_file(storage)) {
                /* looks like a compressed single file mailbox. we should be
                   able to handle this. */
+               path = mailbox_list_get_path(list, name,
+                                            MAILBOX_LIST_PATH_TYPE_MAILBOX);
                fd = open(path, O_RDONLY);
                if (fd != -1)
                        return handler->create_istream(fd);
@@ -202,17 +203,20 @@ zlib_mailbox_open_input(struct mail_storage *storage, const char *name)
 }
 
 static struct mailbox *
-zlib_mailbox_open(struct mail_storage *storage, const char *name,
-                 struct istream *input, enum mailbox_open_flags flags)
+zlib_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+                 const char *name, struct istream *input,
+                 enum mailbox_open_flags flags)
 {
        union mail_storage_module_context *qstorage = ZLIB_CONTEXT(storage);
        struct mailbox *box;
        struct istream *zlib_input = NULL;
 
-       if (input == NULL && strcmp(storage->name, "mbox") == 0)
-               input = zlib_input = zlib_mailbox_open_input(storage, name);
+       if (input == NULL && strcmp(storage->name, "mbox") == 0) {
+               input = zlib_input =
+                       zlib_mailbox_open_input(storage, list, name);
+       }
 
-       box = qstorage->super.mailbox_open(storage, name, input, flags);
+       box = qstorage->super.mailbox_open(storage, list, name, input, flags);
 
        if (zlib_input != NULL)
                i_stream_unref(&zlib_input);
index 524d828f413346cd9dbbb2dae25ec8f71555734c..ec0fe2d2153fceaf12fee73d166181d07c7236f9 100644 (file)
@@ -157,9 +157,10 @@ static bool init_mailbox(struct client *client, const char **error_r)
                                 "-ERR [IN-USE] Couldn't sync mailbox.");
                *error_r = "Can't sync mailbox: Messages keep getting expunged";
        } else {
-               struct mail_storage *storage = client->inbox_ns->storage;
+               struct mail_storage *storage;
                enum mail_error error;
 
+               storage = mailbox_get_storage(client->mailbox);
                *error_r = mail_storage_get_last_error(storage, &error);
        }
        buffer_free(&message_sizes_buf);
@@ -216,6 +217,7 @@ static enum uidl_keys parse_uidl_keymask(const char *format)
 struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
                             const struct pop3_settings *set)
 {
+       struct mail_namespace *ns;
        struct mail_storage *storage;
        const char *inbox, *ident;
        struct client *client;
@@ -247,31 +249,31 @@ struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
        client->user = user;
 
        inbox = "INBOX";
-       client->inbox_ns = mail_namespace_find(user->namespaces, &inbox);
-       if (client->inbox_ns == NULL) {
+       ns = mail_namespace_find(user->namespaces, &inbox);
+       if (ns == NULL) {
                client_send_line(client, "-ERR No INBOX namespace for user.");
                client_destroy(client, "No INBOX namespace for user.");
                return NULL;
        }
+       client->inbox_ns = ns;
 
-       storage = client->inbox_ns->storage;
-
-       client->mail_set = mail_storage_get_settings(storage);
        flags = MAILBOX_OPEN_POP3_SESSION;
        if (set->pop3_no_flag_updates)
                flags |= MAILBOX_OPEN_KEEP_RECENT;
        if (set->pop3_lock_session)
                flags |= MAILBOX_OPEN_KEEP_LOCKED;
-       client->mailbox = mailbox_open(&storage, "INBOX", NULL, flags);
+       client->mailbox = mailbox_open(ns->list, "INBOX", NULL, flags);
        if (client->mailbox == NULL) {
                errmsg = t_strdup_printf("Couldn't open INBOX: %s",
-                               mail_storage_get_last_error(storage,
-                                                           &error));
+                                        mailbox_list_get_last_error(ns->list,
+                                                                    &error));
                i_error("%s", errmsg);
                client_send_line(client, "-ERR [IN-USE] %s", errmsg);
                client_destroy(client, "Couldn't open INBOX");
                return NULL;
        }
+       storage = mailbox_get_storage(client->mailbox);
+       client->mail_set = mail_storage_get_settings(storage);
 
        if (!init_mailbox(client, &errmsg)) {
                i_error("Couldn't init INBOX: %s", errmsg);
@@ -468,6 +470,7 @@ int client_send_line(struct client *client, const char *fmt, ...)
 
 void client_send_storage_error(struct client *client)
 {
+       struct mail_storage *storage;
        enum mail_error error;
 
        if (mailbox_is_inconsistent(client->mailbox)) {
@@ -477,9 +480,9 @@ void client_send_storage_error(struct client *client)
                return;
        }
 
+       storage = mailbox_get_storage(client->mailbox);
        client_send_line(client, "-ERR %s",
-                        mail_storage_get_last_error(client->inbox_ns->storage,
-                                                    &error));
+                        mail_storage_get_last_error(storage, &error));
 }
 
 bool client_handle_input(struct client *client)
index 8fb40ec1ea65a701edc095ee3c33b158a78d3125..cd49470c02a8cabfc9407fd121354e8dc4641629 100644 (file)
@@ -51,7 +51,6 @@ static struct mailbox *
 mailbox_find_and_open(struct mail_user *user, const char *mailbox)
 {
        struct mail_namespace *ns;
-       struct mail_storage *storage;
        struct mailbox *box;
        const char *orig_mailbox = mailbox;
 
@@ -59,12 +58,11 @@ mailbox_find_and_open(struct mail_user *user, const char *mailbox)
        if (ns == NULL)
                i_fatal("Can't find namespace for mailbox %s", mailbox);
 
-       storage = ns->storage;
-       box = mailbox_open(&storage, mailbox, NULL, MAILBOX_OPEN_KEEP_RECENT |
+       box = mailbox_open(ns->list, mailbox, NULL, MAILBOX_OPEN_KEEP_RECENT |
                           MAILBOX_OPEN_IGNORE_ACLS);
        if (box == NULL) {
                i_fatal("Opening mailbox %s failed: %s", orig_mailbox,
-                       mail_storage_get_last_error(storage, NULL));
+                       mailbox_list_get_last_error(ns->list, NULL));
        }
        return box;
 }