changeset 9434:e374a365521d HEAD

Initial commit for making mail_storage:mailbox_list to be from 1:1 to n:n. 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.
author Timo Sirainen <tss@iki.fi>
date Tue, 02 Jun 2009 22:30:28 -0400
parents 438491c166cb
children da12e994d942
files 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
diffstat 102 files changed, 2025 insertions(+), 2389 deletions(-) [+]
line wrap: on
line diff
--- a/src/config/settings-get.pl	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/config/settings-get.pl	Tue Jun 02 22:30:28 2009 -0400
@@ -4,6 +4,7 @@
 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";
--- a/src/imap/cmd-append.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-append.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 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)
--- a/src/imap/cmd-copy.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-copy.c	Tue Jun 02 22:30:28 2009 -0400
@@ -93,7 +93,8 @@
 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 @@
 	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 @@
 		}
 	}
 
+	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 @@
 			"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;
 	}
 }
--- a/src/imap/cmd-create.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-create.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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;
--- a/src/imap/cmd-delete.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-delete.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 		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 @@
 
 		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.");
 	}
--- a/src/imap/cmd-list.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-list.c	Tue Jun 02 22:30:28 2009 -0400
@@ -310,16 +310,16 @@
 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 @@
 		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);
--- a/src/imap/cmd-rename.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-rename.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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 @@
 		}
 	}
 
-	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;
--- a/src/imap/cmd-select.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-select.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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 @@
 	}
 
 	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 @@
 
 	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 @@
 			 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 @@
 	}
 
 	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 @@
 
 	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) {
--- a/src/imap/cmd-status.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-status.c	Tue Jun 02 22:30:28 2009 -0400
@@ -12,8 +12,8 @@
 	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 @@
 				    &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;
 	}
 
--- a/src/imap/cmd-subscribe.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/cmd-subscribe.c	Tue Jun 02 22:30:28 2009 -0400
@@ -29,7 +29,6 @@
 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 @@
 	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 @@
 		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 @@
 
 	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);
 	}
--- a/src/imap/imap-client.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/imap-client.c	Tue Jun 02 22:30:28 2009 -0400
@@ -34,7 +34,6 @@
 			     const struct imap_settings *set)
 {
 	struct client *client;
-	struct mail_namespace *ns;
 	const char *ident;
 
 	/* always use nonblocking I/O */
@@ -60,10 +59,8 @@
 		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);
--- a/src/imap/imap-commands-util.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/imap-commands-util.c	Tue Jun 02 22:30:28 2009 -0400
@@ -32,21 +32,11 @@
 	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 @@
 	}
 
 	/* 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 @@
 	}
 }
 
-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 @@
 	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 @@
 	}
 
 	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 @@
 }
 
 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);
--- a/src/imap/imap-commands-util.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/imap-commands-util.h	Tue Jun 02 22:30:28 2009 -0400
@@ -13,10 +13,6 @@
    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 @@
    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 @@
 			 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);
--- a/src/imap/imap-commands.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/imap-commands.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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"
--- a/src/imap/imap-status.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/imap-status.c	Tue Jun 02 22:30:28 2009 -0400
@@ -46,25 +46,29 @@
 	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 @@
 		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,
--- a/src/imap/imap-status.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/imap/imap-status.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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);
--- a/src/lda/main.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lda/main.c	Tue Jun 02 22:30:28 2009 -0400
@@ -416,21 +416,21 @@
 		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 ?
--- a/src/lib-lda/mail-deliver.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-lda/mail-deliver.c	Tue Jun 02 22:30:28 2009 -0400
@@ -72,28 +72,28 @@
 
 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 @@
 		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 @@
 	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 @@
 		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 @@
 		}
 	} 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)
--- a/src/lib-storage/index/cydir/cydir-mail.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-mail.c	Tue Jun 02 22:30:28 2009 -0400
@@ -13,7 +13,7 @@
 {
 	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);
 }
--- a/src/lib-storage/index/cydir/cydir-save.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-save.c	Tue Jun 02 22:30:28 2009 -0400
@@ -49,7 +49,7 @@
 {
 	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 @@
 	*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);
 
--- a/src/lib-storage/index/cydir/cydir-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -13,51 +13,22 @@
 #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 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";
+static void cydir_list_init(struct mailbox_list *list);
 
-	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 @@
 	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 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 @@
 	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 @@
 }
 
 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 @@
 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 @@
 	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 @@
 	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 @@
 		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 mailbox cydir_mailbox = {
 	MEMBER(name) NULL, 
 	MEMBER(storage) NULL, 
+	MEMBER(list) NULL,
 
 	{
 		index_storage_is_readonly,
--- a/src/lib-storage/index/cydir/cydir-sync.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-sync.c	Tue Jun 02 22:30:28 2009 -0400
@@ -21,8 +21,7 @@
 	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, '/');
--- a/src/lib-storage/index/dbox/dbox-map.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-map.c	Tue Jun 02 22:30:28 2009 -0400
@@ -69,13 +69,9 @@
 
 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 @@
 		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);
--- a/src/lib-storage/index/dbox/dbox-settings.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-settings.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 
 	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;
--- a/src/lib-storage/index/dbox/dbox-storage-rebuild.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage-rebuild.c	Tue Jun 02 22:30:28 2009 -0400
@@ -46,6 +46,7 @@
 	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 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 			/* 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";
--- a/src/lib-storage/index/dbox/dbox-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -25,69 +25,24 @@
 #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 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";
+static void dbox_list_init(struct mailbox_list *list,
+			   const struct dbox_settings *set);
 
-	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 @@
 	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;
+	const char *dir;
 
-	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);
+	storage->set = mail_storage_get_driver_settings(_storage);
+	i_assert(storage->set->dbox_max_open_files >= 2);
+
+	if (*ns->list->set.mailbox_dir_name == '\0') {
+		*error_r = "dbox: MAILBOXDIR must not be empty";
 		return -1;
 	}
 
-	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;
-	}
+	dbox_list_init(ns->list, storage->set);
 
-	if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
-		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);
-
-	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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 				     &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 @@
 	(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 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 @@
 	} 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 @@
 }
 
 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 @@
 	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 @@
 	   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 @@
 	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 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 @@
 	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 @@
 		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 @@
 			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 @@
 		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 @@
 			       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 @@
 			 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 @@
 	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 @@
                 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 mailbox dbox_mailbox = {
 	MEMBER(name) NULL, 
 	MEMBER(storage) NULL, 
+	MEMBER(list) NULL,
 
 	{
 		index_storage_is_readonly,
--- a/src/lib-storage/index/dbox/dbox-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -90,8 +90,9 @@
 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 @@
 /* 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);
--- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c	Tue Jun 02 22:30:28 2009 -0400
@@ -36,13 +36,13 @@
 
 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 @@
 	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 @@
 #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);
--- a/src/lib-storage/index/index-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/index-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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 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 @@
 	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 @@
 }
 
 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 @@
 	/* 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 @@
 		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 @@
 			}
 		}
 
-                list = &(*list)->next;
+                indexp = &(*indexp)->next;
 	}
 
 	if (index == NULL) {
@@ -367,7 +367,8 @@
 
 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 @@
 	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 @@
 			   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 @@
 			       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 @@
 	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,
--- a/src/lib-storage/index/index-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/index-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -20,8 +20,6 @@
 	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_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);
--- a/src/lib-storage/index/maildir/maildir-keywords.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-keywords.c	Tue Jun 02 22:30:28 2009 -0400
@@ -65,7 +65,8 @@
 	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 @@
 	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;
 }
 
--- a/src/lib-storage/index/maildir/maildir-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -21,12 +21,16 @@
 #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 @@
 				  &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_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_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 @@
 	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 @@
 	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);
+	storage->temp_prefix = mailbox_list_get_temp_prefix(list);
 
-	/* 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 @@
 	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;
 
-	path = t_strconcat(t_strcut(ns->set->location, ':'), "/cur", NULL);
+	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(root_dir, "/cur", NULL);
 	if (stat(path, &st) < 0) {
 		if (debug)
 			i_info("maildir autodetect: stat(%s) failed: %m", path);
@@ -289,10 +211,13 @@
 			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 @@
 		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 @@
 }
 
 /* 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 @@
 	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 @@
 	/* 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 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 @@
 	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 @@
 			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 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 	}
 
 	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 @@
 		/* 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 @@
 		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 @@
 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 @@
 	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 @@
 			    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 @@
 		}
 	}
 
-	return oldstorage->list_module_ctx.super.
+	return oldmlist->module_ctx.super.
 		rename_mailbox(oldlist, oldname, newlist, newname,
 			       rename_children);
 }
@@ -982,11 +915,10 @@
 				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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
                 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 mailbox maildir_mailbox = {
 	MEMBER(name) NULL, 
 	MEMBER(storage) NULL, 
+	MEMBER(list) NULL,
 
 	{
 		index_storage_is_readonly,
--- a/src/lib-storage/index/maildir/maildir-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -70,7 +70,6 @@
 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 @@
 #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);
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Tue Jun 02 22:30:28 2009 -0400
@@ -573,7 +573,7 @@
 
 	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 @@
 		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 */
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Tue Jun 02 22:30:28 2009 -0400
@@ -148,7 +148,7 @@
 
         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 @@
 	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 @@
 
 	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 @@
 		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 @@
 		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);
--- a/src/lib-storage/index/maildir/maildir-util.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-util.c	Tue Jun 02 22:30:28 2009 -0400
@@ -153,7 +153,7 @@
 		}
 		/* 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 @@
 	/* @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++) {
--- a/src/lib-storage/index/mbox/mbox-lock.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Tue Jun 02 22:30:28 2009 -0400
@@ -352,7 +352,7 @@
 		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)",
--- a/src/lib-storage/index/mbox/mbox-save.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-save.c	Tue Jun 02 22:30:28 2009 -0400
@@ -120,7 +120,7 @@
 			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);
 		}
 
--- a/src/lib-storage/index/mbox/mbox-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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)
 
@@ -35,6 +33,11 @@
 #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 @@
 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 @@
 	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 @@
 	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:");
+	path = t_strconcat(home, "/mail", NULL);
+	if (mbox_storage_is_root_dir(path, debug))
+		return path;
 
-	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 "/";
-
-	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;
-		}
+	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);
-
-		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 (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("/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(home, "/mail", NULL);
-	if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
-		*error_r = mail_error_create_eacces_msg("mkdir", path);
-		return NULL;
-	}
-
-	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;
+	bool debug = ns->mail_set->mail_debug;
+	const char *root_dir, *inbox_path;
 
-	*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;
-		}
+	root_dir = set->root_dir;
+	inbox_path = set->inbox_path;
 
-		/* 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;
+	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 (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->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;
-		}
+	if (inbox_path == NULL) {
+		inbox_path = mbox_storage_find_inbox_file(ns->user->username,
+							  debug);
+	}
+	set->root_dir = root_dir;
+	set->inbox_path = inbox_path;
 
-		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 (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;
+	mbox_storage_get_list_settings(ns, set);
+	return TRUE;
 }
 
-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;
-	}
-	_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;
-
-	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;
-}
-
-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 @@
 		(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 = 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 @@
 }
 
 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 @@
 	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 @@
 			struct mailbox *box = &mbox->ibox.box;
 
 			mailbox_close(&box);
+			mailbox_list_set_error_from_storage(list,
+							    &storage->storage);
 			return NULL;
 		}
 
@@ -643,22 +463,20 @@
 }
 
 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 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 	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 @@
 		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_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 @@
 
 	/* 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 @@
 	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 @@
                 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 mailbox mbox_mailbox = {
 	MEMBER(name) NULL, 
 	MEMBER(storage) NULL, 
+	MEMBER(list) NULL,
 
 	{
 		index_storage_is_readonly,
--- a/src/lib-storage/index/mbox/mbox-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -28,8 +28,6 @@
 	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 {
--- a/src/lib-storage/index/raw/raw-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/raw/raw-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 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";
+static void raw_list_init(struct mailbox_list *list);
 
-	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 @@
 	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 @@
 	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 @@
 }
 
 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 @@
 
 	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 @@
 	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 @@
 	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 @@
 				    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 @@
 		*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 @@
 	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 @@
 		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 mailbox raw_mailbox = {
 	MEMBER(name) NULL, 
 	MEMBER(storage) NULL, 
+	MEMBER(list) NULL,
 
 	{
 		index_storage_is_readonly,
--- a/src/lib-storage/index/shared/shared-list.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/shared/shared-list.c	Tue Jun 02 22:30:28 2009 -0400
@@ -43,13 +43,14 @@
 }
 
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 	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_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_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 @@
 				     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,
--- a/src/lib-storage/index/shared/shared-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/shared/shared-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -11,16 +11,9 @@
 #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 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 @@
 	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 @@
 	}
 	_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,17 +80,14 @@
 	/* 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);
+	return 0;
+}
 
-	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
@@ -116,17 +100,18 @@
 	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 @@
 		{ '\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 @@
 	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 @@
 		}
 		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 @@
 	}
 	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 @@
 		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 @@
 		}
 	}
 	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 @@
 	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 @@
 	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;
+	}
+
+	new_list = ns->list;
+	if (mailbox_list_get_storage(&new_list, &name, &new_storage) < 0)
 		return -1;
 
-	ret = mail_storage_mailbox_create(ns->storage, name, directory);
-	if (ret < 0)
-		shared_mailbox_copy_error(storage, ns);
+	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 @@
 		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,
--- a/src/lib-storage/index/shared/shared-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/index/shared/shared-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -9,7 +9,6 @@
 	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 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
--- a/src/lib-storage/list/index-mailbox-list-sync.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/list/index-mailbox-list-sync.c	Tue Jun 02 22:30:28 2009 -0400
@@ -86,14 +86,12 @@
 				       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 @@
 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 @@
 	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 @@
 {
 	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 @@
 		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 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)
--- a/src/lib-storage/list/index-mailbox-list.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/list/index-mailbox-list.c	Tue Jun 02 22:30:28 2009 -0400
@@ -457,25 +457,19 @@
 	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
--- a/src/lib-storage/list/mailbox-list-fs.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/list/mailbox-list-fs.c	Tue Jun 02 22:30:28 2009 -0400
@@ -313,18 +313,21 @@
 				  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;
 
-	(void)mail_storage_get_mailbox_path(oldlist->ns->storage,
-					    oldname, &isfile);
+	if (mailbox_list_get_storage(&oldlist, &oldname, &oldstorage) < 0)
+		return -1;
+
 	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 @@
 }
 
 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,
--- a/src/lib-storage/list/mailbox-list-maildir.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/list/mailbox-list-maildir.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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)
--- a/src/lib-storage/mail-namespace.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-namespace.c	Tue Jun 02 22:30:28 2009 -0400
@@ -12,17 +12,25 @@
 
 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 @@
 
 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 @@
 		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 @@
 	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;
--- a/src/lib-storage/mail-namespace.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-namespace.h	Tue Jun 02 22:30:28 2009 -0400
@@ -3,6 +3,8 @@
 
 #include "mail-user.h"
 
+struct mail_storage_callbacks;
+
 enum namespace_type {
 	NAMESPACE_PRIVATE,
 	NAMESPACE_SHARED,
@@ -73,6 +75,14 @@
    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 @@
    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 @@
 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
--- a/src/lib-storage/mail-storage-private.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-storage-private.h	Tue Jun 02 22:30:28 2009 -0400
@@ -32,18 +32,23 @@
 	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 @@
 	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 @@
 struct mailbox {
 	char *name;
 	struct mail_storage *storage;
+	struct mailbox_list *list;
 
         struct mailbox_vfuncs v;
 /* private: */
--- a/src/lib-storage/mail-storage-settings.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-storage-settings.c	Tue Jun 02 22:30:28 2009 -0400
@@ -224,7 +224,7 @@
 
 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 @@
 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 @@
 		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 @@
 
 	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);
--- a/src/lib-storage/mail-storage-settings.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-storage-settings.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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 {
--- a/src/lib-storage/mail-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 }
 
 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 @@
 	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 @@
 		}
 	}
 
+	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;
-
-		storage->callbacks =
-			p_new(storage->pool, struct mail_storage_callbacks, 1);
-		p_array_init(&storage->module_contexts, storage->pool, 5);
-
-		if (classes[i]->v.create(storage, data, error_r) == 0)
-			break;
-
-		if (ns->mail_set->mail_debug && count > 1) {
-			i_info("%s: Couldn't create mail storage %s: %s",
-			       classes[i]->name, data, *error_r);
-		}
-
-		/* try the next one */
-		pool_unref(&storage->pool);
-	}
-	if (i == count) {
-		if (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);
+	if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0 &&
+	    list_set.root_dir == NULL) {
+		*error_r = "Root mail directory not given";
 		return -1;
 	}
 
+	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 (hook_mail_storage_created != NULL) {
-		T_BEGIN {
-			hook_mail_storage_created(storage);
-		} T_END;
+	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;
 	}
 
-	ns->storage = storage;
-        mail_namespace_init_storage(ns);
+	storage = storage_class->v.alloc();
+	storage->storage_class = storage_class;
+	storage->user = ns->user;
+	storage->set = ns->mail_set;
+	storage->flags = flags;
+
+	storage->callbacks =
+		p_new(storage->pool, struct mail_storage_callbacks, 1);
+	p_array_init(&storage->module_contexts, storage->pool, 5);
+
+	if (storage->v.create(storage, ns, error_r) < 0) {
+		*error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
+		pool_unref(&storage->pool);
+		return -1;
+	}
+
+	if (hook_mail_storage_created != NULL) T_BEGIN {
+		hook_mail_storage_created(storage);
+	} T_END;
+
+        mail_namespace_add_storage(ns, storage);
 	return 0;
 }
 
@@ -234,7 +287,6 @@
 	*_storage = NULL;
 
 	storage->v.destroy(storage);
-	mailbox_list_deinit(storage->list);
 	i_free(storage->error_string);
 	pool_unref(&storage->pool);
 }
@@ -287,22 +339,6 @@
 	}
 }
 
-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 @@
 	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 @@
 	return storage->error_string;
 }
 
-const char *mail_storage_get_mailbox_path(struct mail_storage *storage,
-					  const char *name, bool *is_file_r)
-{
-	*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)
+bool mail_storage_is_mailbox_file(struct mail_storage *storage)
 {
-	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 @@
 	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 @@
 	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 @@
 		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 {
--- a/src/lib-storage/mail-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -261,14 +261,6 @@
 			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 @@
    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 @@
 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 @@
 
 /* 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;
--- a/src/lib-storage/mail-user.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mail-user.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 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 @@
 	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)
--- a/src/lib-storage/mailbox-list-private.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mailbox-list-private.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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 *(*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 @@
 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 @@
 	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
--- a/src/lib-storage/mailbox-list.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mailbox-list.c	Tue Jun 02 22:30:28 2009 -0400
@@ -87,13 +87,20 @@
 	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 @@
 	}
 
 	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 @@
 
 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;
 
-	*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 @@
 			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 @@
 	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');
-
-	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);
+	struct mailbox_list *list = *_list;
 
-	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 @@
 	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 @@
 				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 @@
 	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);
+}
--- a/src/lib-storage/mailbox-list.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lib-storage/mailbox-list.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 };
 
 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 @@
 	/* 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_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 @@
 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
--- a/src/lmtp/commands.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/lmtp/commands.c	Tue Jun 02 22:30:28 2009 -0400
@@ -274,8 +274,7 @@
 		"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 @@
 						  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 @@
 		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);
--- a/src/plugins/acl/acl-api-private.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-api-private.h	Tue Jun 02 22:30:28 2009 -0400
@@ -23,10 +23,8 @@
 		(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);
 
--- a/src/plugins/acl/acl-api.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-api.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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)
--- a/src/plugins/acl/acl-api.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-api.h	Tue Jun 02 22:30:28 2009 -0400
@@ -120,10 +120,8 @@
 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);
 
--- a/src/plugins/acl/acl-backend-vfile-acllist.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-backend-vfile-acllist.c	Tue Jun 02 22:30:28 2009 -0400
@@ -128,7 +128,7 @@
 
 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 @@
 	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 @@
 	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;
 		}
--- a/src/plugins/acl/acl-backend-vfile.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-backend-vfile.c	Tue Jun 02 22:30:28 2009 -0400
@@ -122,22 +122,25 @@
 }
 
 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 @@
 	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 @@
 }
 
 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 @@
 }
 
 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 @@
 	/* 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 @@
 
 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 @@
 	   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 @@
 		/* 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)
--- a/src/plugins/acl/acl-backend.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-backend.c	Tue Jun 02 22:30:28 2009 -0400
@@ -82,7 +82,7 @@
 		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;
 }
 
--- a/src/plugins/acl/acl-lookup-dict.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-lookup-dict.c	Tue Jun 02 22:30:28 2009 -0400
@@ -104,10 +104,10 @@
 		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) {
--- a/src/plugins/acl/acl-mailbox-list.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-mailbox-list.c	Tue Jun 02 22:30:28 2009 -0400
@@ -12,17 +12,8 @@
 #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 @@
 	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 @@
 	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;
 
-	ret = acl_storage_rights_ctx_have_right(&alist->rights, name, FALSE,
-						acl_storage_right_idx,
-						can_see_r);
+	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);
+
 	if (ret < 0)
 		mailbox_list_set_internal_error(list);
 	return ret;
@@ -297,7 +318,7 @@
 	}
 
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 
 	/* 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 @@
 	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);
--- a/src/plugins/acl/acl-mailbox.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-mailbox.c	Tue Jun 02 22:30:28 2009 -0400
@@ -30,20 +30,6 @@
 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 @@
 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 @@
 
 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) {
--- a/src/plugins/acl/acl-plugin.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-plugin.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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_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 @@
 
 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);
--- a/src/plugins/acl/acl-shared-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-shared-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 		{ '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 @@
 	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 @@
 
 	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 @@
 	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(ns, storage, name);
 		} T_END;
 	}
 	return acl_lookup_dict_iterate_visible_deinit(&iter);
--- a/src/plugins/acl/acl-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -16,138 +16,64 @@
 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)
+static struct mailbox *
+acl_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
+		 const char *name, struct istream *input,
+		 enum mailbox_open_flags flags)
 {
-	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)
-{
-	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 @@
 		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)
--- a/src/plugins/acl/acl-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/acl/acl-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -17,10 +17,6 @@
 	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
--- a/src/plugins/autocreate/autocreate-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/autocreate/autocreate-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -16,6 +16,7 @@
 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 @@
 		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);
--- a/src/plugins/convert/convert-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/convert/convert-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -29,6 +29,13 @@
 	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 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 @@
 	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 @@
 		"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 @@
 	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 @@
 		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 @@
 
 	/* 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 @@
 
 		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 @@
 		}
 	}
 
-	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 @@
 	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 @@
 	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_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 @@
 	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 @@
 		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 @@
 		/* 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) {
--- a/src/plugins/expire/expire-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/expire/expire-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -104,7 +104,7 @@
 				  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 @@
 		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 @@
 }
 
 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 @@
 	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 @@
 
 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) {
--- a/src/plugins/expire/expire-tool.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/expire/expire-tool.c	Tue Jun 02 22:30:28 2009 -0400
@@ -32,7 +32,6 @@
 	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 @@
 		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);
--- a/src/plugins/fts-lucene/fts-backend-lucene.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/fts-lucene/fts-backend-lucene.c	Tue Jun 02 22:30:28 2009 -0400
@@ -48,8 +48,8 @@
 
 	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)
--- a/src/plugins/fts-solr/fts-backend-solr.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/fts-solr/fts-backend-solr.c	Tue Jun 02 22:30:28 2009 -0400
@@ -66,7 +66,7 @@
 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 @@
 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 @@
 		    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 @@
 	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 @@
 	/* 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 {
--- a/src/plugins/fts-squat/fts-backend-squat.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/fts-squat/fts-backend-squat.c	Tue Jun 02 22:30:28 2009 -0400
@@ -59,8 +59,8 @@
 	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 @@
 	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;
--- a/src/plugins/fts/fts-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/fts/fts-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -355,14 +355,14 @@
 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 @@
 {
 	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);
 
--- a/src/plugins/imap-acl/imap-acl-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/imap-acl/imap-acl-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -54,7 +54,7 @@
 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 @@
 		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 @@
 {
 	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 @@
 	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_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 @@
 	}
 
 	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 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 @@
 	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);
--- a/src/plugins/imap-quota/imap-quota-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/imap-quota/imap-quota-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -68,7 +68,6 @@
 {
 	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 @@
 		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.");
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -44,13 +44,12 @@
 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 @@
 				  &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 @@
 }
 
 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 @@
 {
 	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 @@
 	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 @@
 	}
 
 	/* 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 @@
 	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 @@
 {
 	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 @@
 
 		/* 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)
--- a/src/plugins/listescape/listescape-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/listescape/listescape-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -163,30 +163,31 @@
 }
 
 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 @@
 	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;
--- a/src/plugins/mail-log/mail-log-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/mail-log/mail-log-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -183,7 +183,7 @@
 			  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 @@
 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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 }
 
 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;
 
--- a/src/plugins/mbox-snarf/mbox-snarf-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/mbox-snarf/mbox-snarf-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -107,15 +107,13 @@
 {
 	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 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 @@
 	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 @@
 	}
 
 	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 @@
 {
 	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 @@
 {
 	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);
 
--- a/src/plugins/quota/quota-count.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota-count.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 		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 @@
 }
 
 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 @@
 
 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;
 	}
--- a/src/plugins/quota/quota-dirsize.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota-dirsize.c	Tue Jun 02 22:30:28 2009 -0400
@@ -148,7 +148,7 @@
 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 @@
 	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);
 	}
 
--- a/src/plugins/quota/quota-fs.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota-fs.c	Tue Jun 02 22:30:28 2009 -0400
@@ -249,19 +249,19 @@
 	}
 }
 
-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 @@
 	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 @@
 		fs_quota_deinit,
 		NULL,
 
-		fs_quota_storage_added,
+		fs_quota_namespace_added,
 
 		fs_quota_root_get_resources,
 		fs_quota_get_resource,
--- a/src/plugins/quota/quota-maildir.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota-maildir.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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_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 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 @@
 {
 	struct quota_rule *rule;
 	struct stat st;
-	bool is_file;
 
 	for (;;) {
 		if (ctx->state == 0) {
@@ -161,9 +160,8 @@
 		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
 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 @@
 
 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 @@
 	   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 @@
 	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(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 @@
 	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 @@
 		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 @@
 }
 
 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 @@
 	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 @@
 		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,
--- a/src/plugins/quota/quota-private.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota-private.h	Tue Jun 02 22:30:28 2009 -0400
@@ -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_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_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 @@
 };
 
 /* 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);
 
--- a/src/plugins/quota/quota-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 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 @@
 	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 @@
 	   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 @@
 			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 @@
 		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 @@
 		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 @@
 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 @@
 	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);
 
-		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);
--- a/src/plugins/quota/quota.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/quota/quota.c	Tue Jun 02 22:30:28 2009 -0400
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 	}
 
 	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 @@
 	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 @@
 		/* 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 *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;
--- a/src/plugins/trash/trash-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/trash/trash-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -23,7 +23,7 @@
 	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_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 @@
 		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;
 		}
 	}
--- a/src/plugins/virtual/virtual-config.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/virtual/virtual-config.c	Tue Jun 02 22:30:28 2009 -0400
@@ -100,7 +100,7 @@
 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 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 @@
 
 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 @@
 	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 @@
 		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 @@
 	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 @@
 		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;
 	}
--- a/src/plugins/virtual/virtual-mail.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/virtual/virtual-mail.c	Tue Jun 02 22:30:28 2009 -0400
@@ -336,7 +336,7 @@
 		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;
 	}
--- a/src/plugins/virtual/virtual-storage.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/virtual/virtual-storage.c	Tue Jun 02 22:30:28 2009 -0400
@@ -22,6 +22,10 @@
 #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 @@
 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 @@
 	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,53 +61,27 @@
 	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;
+	ns->flags |= NAMESPACE_FLAG_NOQUOTA;
+	virtual_list_init(ns->list);
+	return 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;
-	}
-
-	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);
-	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 *
@@ -201,10 +132,9 @@
 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 @@
 	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 @@
 				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 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 @@
 		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 @@
 }
 
 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 @@
 
 		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_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 @@
 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 @@
 	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 @@
 	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 @@
 		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 mailbox virtual_mailbox = {
 	MEMBER(name) NULL, 
 	MEMBER(storage) NULL, 
+	MEMBER(list) NULL,
 
 	{
 		index_storage_is_readonly,
--- a/src/plugins/virtual/virtual-storage.h	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/virtual/virtual-storage.h	Tue Jun 02 22:30:28 2009 -0400
@@ -168,7 +168,6 @@
 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);
--- a/src/plugins/zlib/zlib-plugin.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/plugins/zlib/zlib-plugin.c	Tue Jun 02 22:30:28 2009 -0400
@@ -179,21 +179,22 @@
 }
 
 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 @@
 }
 
 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);
--- a/src/pop3/pop3-client.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/pop3/pop3-client.c	Tue Jun 02 22:30:28 2009 -0400
@@ -157,9 +157,10 @@
 				 "-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 @@
 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 @@
 	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 @@
 
 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 @@
 		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)
--- a/src/util/doveadm.c	Tue Jun 02 17:42:40 2009 -0400
+++ b/src/util/doveadm.c	Tue Jun 02 22:30:28 2009 -0400
@@ -51,7 +51,6 @@
 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 @@
 	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;
 }