changeset 9468:653183a81b6c HEAD

Mailbox opening and closing APIs changed.
author Timo Sirainen <tss@iki.fi>
date Mon, 15 Jun 2009 14:28:55 -0400
parents 7b6fe859ec64
children 7a63279e95ba
files src/imap/cmd-append.c src/imap/cmd-close.c src/imap/cmd-copy.c src/imap/cmd-delete.c src/imap/cmd-select.c src/imap/cmd-unselect.c src/imap/imap-status.c src/lda/main.c src/lib-lda/mail-deliver.c src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/cydir/cydir-storage.h src/lib-storage/index/cydir/cydir-sync.c src/lib-storage/index/dbox/dbox-file.c src/lib-storage/index/dbox/dbox-mail.c src/lib-storage/index/dbox/dbox-save.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/dbox/dbox-sync.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-thread.c src/lib-storage/index/maildir/maildir-copy.c src/lib-storage/index/maildir/maildir-keywords.c src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/maildir/maildir-save.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-sync.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/maildir/maildir-util.c src/lib-storage/index/mbox/mbox-file.c src/lib-storage/index/mbox/mbox-lock.c src/lib-storage/index/mbox/mbox-mail.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/mbox/mbox-sync-rewrite.c src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/index/raw/raw-mail.c src/lib-storage/index/raw/raw-storage.c src/lib-storage/index/raw/raw-storage.h src/lib-storage/index/raw/raw-sync.c src/lib-storage/list/index-mailbox-list-sync.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/lib-storage/mailbox-list-private.h src/lib-storage/mailbox-list.c src/lib-storage/test-mail-storage.c src/lib-storage/test-mail-storage.h src/lib-storage/test-mailbox.c src/lmtp/commands.c src/plugins/acl/acl-mailbox.c src/plugins/acl/acl-plugin.h src/plugins/acl/acl-storage.c src/plugins/convert/convert-storage.c src/plugins/expire/expire-plugin.c src/plugins/expire/expire-tool.c src/plugins/fts/fts-plugin.c src/plugins/fts/fts-plugin.h 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-storage.c src/plugins/trash/trash-plugin.c src/plugins/virtual/virtual-config.c src/plugins/virtual/virtual-storage.c src/plugins/virtual/virtual-storage.h src/plugins/virtual/virtual-sync.c src/plugins/zlib/zlib-plugin.c src/pop3/pop3-client.c src/util/doveadm.c
diffstat 80 files changed, 991 insertions(+), 1151 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-append.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/cmd-append.c	Mon Jun 15 14:28:55 2009 -0400
@@ -465,10 +465,11 @@
 	    mailbox_equals(cmd->client->mailbox, ns, name))
 		return cmd->client->mailbox;
 
-	box = mailbox_open(ns->list, name, NULL, MAILBOX_OPEN_SAVEONLY |
-			   MAILBOX_OPEN_KEEP_RECENT);
-	if (box == NULL) {
-		client_send_list_error(cmd, ns->list);
+	box = mailbox_alloc(ns->list, name, NULL, MAILBOX_FLAG_SAVEONLY |
+			    MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_open(box) < 0) {
+		client_send_storage_error(cmd, mailbox_get_storage(box));
+		mailbox_close(&box);
 		return NULL;
 	}
 	if (cmd->client->enabled_features != 0)
--- a/src/imap/cmd-close.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/cmd-close.c	Mon Jun 15 14:28:55 2009 -0400
@@ -23,8 +23,7 @@
 	if (mailbox_sync(mailbox, 0, 0, NULL) < 0)
 		client_send_untagged_storage_error(client, storage);
 
-	if (mailbox_close(&mailbox) < 0)
-		client_send_untagged_storage_error(client, storage);
+	mailbox_close(&mailbox);
 	client_update_mailbox_flags(client, NULL);
 
 	client_send_tagline(cmd, "OK Close completed.");
--- a/src/imap/cmd-copy.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/cmd-copy.c	Mon Jun 15 14:28:55 2009 -0400
@@ -127,11 +127,13 @@
 	if (mailbox_equals(client->mailbox, dest_ns, mailbox))
 		destbox = client->mailbox;
 	else {
-		destbox = mailbox_open(dest_ns->list, mailbox, NULL,
-				       MAILBOX_OPEN_SAVEONLY |
-				       MAILBOX_OPEN_KEEP_RECENT);
-		if (destbox == NULL) {
-			client_send_list_error(cmd, dest_ns->list);
+		destbox = mailbox_alloc(dest_ns->list, mailbox, NULL,
+					MAILBOX_FLAG_SAVEONLY |
+					MAILBOX_FLAG_KEEP_RECENT);
+		if (mailbox_open(destbox) < 0) {
+			client_send_storage_error(cmd,
+				mailbox_get_storage(destbox));
+			mailbox_close(&destbox);
 			return TRUE;
 		}
 		if (client->enabled_features != 0)
--- a/src/imap/cmd-delete.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/cmd-delete.c	Mon Jun 15 14:28:55 2009 -0400
@@ -33,8 +33,7 @@
 		storage = mailbox_get_storage(mailbox);
 		client->mailbox = NULL;
 
-		if (mailbox_close(&mailbox) < 0)
-			client_send_untagged_storage_error(client, storage);
+		mailbox_close(&mailbox);
 	}
 
 	if ((client->workarounds & WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
--- a/src/imap/cmd-select.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/cmd-select.c	Mon Jun 15 14:28:55 2009 -0400
@@ -263,13 +263,15 @@
 {
 	struct client *client = ctx->cmd->client;
 	struct mailbox_status status;
-	enum mailbox_open_flags open_flags = 0;
+	enum mailbox_flags flags = 0;
 
 	if (readonly)
-		open_flags |= MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT;
-	ctx->box = mailbox_open(ctx->ns->list, mailbox, NULL, open_flags);
-	if (ctx->box == NULL) {
-		client_send_list_error(ctx->cmd, ctx->ns->list);
+		flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT;
+	ctx->box = mailbox_alloc(ctx->ns->list, mailbox, NULL, flags);
+	if (mailbox_open(ctx->box) < 0) {
+		client_send_storage_error(ctx->cmd,
+					  mailbox_get_storage(ctx->box));
+		mailbox_close(&ctx->box);
 		return -1;
 	}
 
@@ -370,15 +372,11 @@
 	client->mailbox_change_lock = cmd;
 
 	if (client->mailbox != NULL) {
-		struct mail_storage *old_storage =
-			mailbox_get_storage(client->mailbox);
-
 		client_search_updates_free(client);
 		box = client->mailbox;
 		client->mailbox = NULL;
 
-		if (mailbox_close(&box) < 0)
-			client_send_untagged_storage_error(client, old_storage);
+		mailbox_close(&box);
 		/* CLOSED response is required by QRESYNC */
 		client_send_line(client, "* OK [CLOSED]");
 	}
--- a/src/imap/cmd-unselect.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/cmd-unselect.c	Mon Jun 15 14:28:55 2009 -0400
@@ -18,8 +18,7 @@
 	client->mailbox = NULL;
 
 	storage = mailbox_get_storage(mailbox);
-	if (mailbox_close(&mailbox) < 0)
-		client_send_untagged_storage_error(client, storage);
+	mailbox_close(&mailbox);
 	client_update_mailbox_flags(client, NULL);
 
 	client_send_tagline(cmd, "OK Unselect completed.");
--- a/src/imap/imap-status.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/imap/imap-status.c	Mon Jun 15 14:28:55 2009 -0400
@@ -62,13 +62,8 @@
 	}
 
 	/* open the mailbox */
-	box = mailbox_open(ns->list, mailbox, NULL, MAILBOX_OPEN_FAST |
-			   MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
-	if (box == NULL) {
-		*error_r = mailbox_list_get_last_error(ns->list, &error);
-		*error_r = imap_get_error_string(*error_r, error);
-		return -1;
-	}
+	box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_READONLY |
+			    MAILBOX_FLAG_KEEP_RECENT);
 
 	if ((items & STATUS_HIGHESTMODSEQ) != 0)
 		client_enable(client, MAILBOX_FEATURE_CONDSTORE);
--- a/src/lda/main.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lda/main.c	Mon Jun 15 14:28:55 2009 -0400
@@ -416,17 +416,17 @@
 		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->list, "Dovecot Delivery Mail",
-				   input, MAILBOX_OPEN_NO_INDEX_FILES);
+		box = mailbox_alloc(raw_ns->list, "Dovecot Delivery Mail",
+				    input, MAILBOX_FLAG_NO_INDEX_FILES);
 		i_stream_unref(&input);
 	} else {
 		mtime = (time_t)-1;
-		box = mailbox_open(raw_ns->list, path, NULL,
-				   MAILBOX_OPEN_NO_INDEX_FILES);
+		box = mailbox_alloc(raw_ns->list, path, NULL,
+				    MAILBOX_FLAG_NO_INDEX_FILES);
 	}
-	if (box == NULL) {
+	if (mailbox_open(box) < 0) {
 		i_fatal("Can't open delivery mail as raw: %s",
-			mailbox_list_get_last_error(raw_ns->list, &error));
+			mail_storage_get_last_error(box->storage, &error));
 	}
 	if (mailbox_sync(box, 0, 0, NULL) < 0) {
 		i_fatal("Can't sync delivery mail: %s",
--- a/src/lib-lda/mail-deliver.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-lda/mail-deliver.c	Mon Jun 15 14:28:55 2009 -0400
@@ -79,16 +79,16 @@
 	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;
+	enum mailbox_flags flags =
+		MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_SAVEONLY |
+		MAILBOX_FLAG_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;
+		flags |= MAILBOX_FLAG_IGNORE_ACLS;
 	}
 
 	*ns_r = ns = mail_namespace_find(ctx->dest_user->namespaces, &name);
@@ -101,16 +101,17 @@
 		return NULL;
 	}
 
-	box = mailbox_open(ns->list, name, NULL, open_flags);
-	if (box != NULL)
+	box = mailbox_alloc(ns->list, name, NULL, flags);
+	if (mailbox_open(box) == 0)
 		return box;
 
-	*error_r = mailbox_list_get_last_error(ns->list, &error);
+	storage = mailbox_get_storage(box);
+	*error_r = mail_storage_get_last_error(storage, &error);
+	mailbox_close(&box);
 	if (!ctx->set->lda_mailbox_autocreate || error != MAIL_ERROR_NOTFOUND)
 		return NULL;
 
 	/* try creating it. */
-	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;
@@ -121,16 +122,12 @@
 	}
 
 	/* and try opening again */
-	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) {
+	box = mailbox_alloc(ns->list, name, NULL, flags);
+	storage = mailbox_get_storage(box);
+	if (mailbox_open(box) < 0 ||
+	    mailbox_sync(box, 0, 0, NULL) < 0) {
+		*error_r = mail_storage_get_last_error(storage, &error);
 		mailbox_close(&box);
-		*error_r = mail_storage_get_last_error(mailbox_get_storage(box),
-						       &error);
 		return NULL;
 	}
 	return box;
--- a/src/lib-storage/index/cydir/cydir-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -48,13 +48,13 @@
 		set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
 }
 
-static int create_cydir(struct mail_storage *storage, struct mail_namespace *ns,
+static int create_cydir(struct mail_storage *storage, struct mailbox_list *list,
 			const char *path)
 {
 	mode_t mode;
 	gid_t gid;
 
-	mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid);
+	mailbox_list_get_dir_permissions(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)) {
@@ -67,76 +67,64 @@
 }
 
 static struct mailbox *
-cydir_open(struct mail_storage *storage, struct mailbox_list *list,
-	   const char *name, enum mailbox_open_flags flags)
+cydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		    const char *name, struct istream *input,
+		    enum mailbox_flags flags)
 {
 	struct cydir_mailbox *mbox;
-	struct mail_index *index;
-	const char *path;
 	pool_t pool;
 
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	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);
+	/* cydir can't work without index files */
+	flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
 
 	pool = pool_alloconly_create("cydir mailbox", 1024+512);
 	mbox = p_new(pool, struct cydir_mailbox, 1);
 	mbox->ibox.box = cydir_mailbox;
 	mbox->ibox.box.pool = pool;
 	mbox->ibox.box.storage = storage;
+	mbox->ibox.box.list = list;
 	mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
-	mbox->ibox.index = index;
+
+	index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+				    CYDIR_INDEX_PREFIX);
+	mail_index_set_fsync_types(mbox->ibox.index,
+				   MAIL_INDEX_SYNC_TYPE_APPEND |
+				   MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
 	mbox->storage = (struct cydir_storage *)storage;
-	mbox->path = p_strdup(pool, path);
-
-	index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
 	return &mbox->ibox.box;
 }
 
-static struct mailbox *
-cydir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		   const char *name, struct istream *input,
-		   enum mailbox_open_flags flags)
+static int cydir_mailbox_open(struct mailbox *box)
 {
-	const char *path;
 	struct stat st;
 
-	if (input != NULL) {
-		mailbox_list_set_critical(list,
+	if (box->input != NULL) {
+		mail_storage_set_critical(box->storage,
 			"cydir doesn't support streamed mailboxes");
-		return NULL;
+		return -1;
 	}
 
-	/* cydir can't work without index files */
-	flags &= ~MAILBOX_OPEN_NO_INDEX_FILES;
-
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(path, &st) == 0)
-		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, list->ns, path) < 0) {
-				mailbox_list_set_error_from_storage(list,
-								    storage);
-				return NULL;
-			}
-			return cydir_open(storage, list, "INBOX", flags);
-		}
-		mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+	if (stat(box->path, &st) == 0) {
+		/* exists, open it */
+	} else if (errno == ENOENT && strcmp(box->name, "INBOX") == 0) {
+		/* INBOX always exists, create it */
+		if (create_cydir(box->storage, box->list, box->path) < 0)
+			return -1;
+	} else if (errno == ENOENT) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+		return -1;
 	} else if (errno == EACCES) {
-		mail_storage_set_critical(storage, "%s",
-			mail_error_eacces_msg("stat", path));
+		mail_storage_set_critical(box->storage, "%s",
+			mail_error_eacces_msg("stat", box->path));
+		return -1;
 	} else {
-		mail_storage_set_critical(storage, "stat(%s) failed: %m",
-					  path);
+		mail_storage_set_critical(box->storage, "stat(%s) failed: %m",
+					  box->path);
+		return -1;
 	}
-	return NULL;
+	return index_storage_mailbox_open(box);
 }
 
 static int
@@ -154,7 +142,7 @@
 		return -1;
 	}
 
-	return create_cydir(storage, list->ns, path);
+	return create_cydir(storage, list, path);
 }
 
 static int
@@ -261,7 +249,7 @@
 	if (box->notify_callback == NULL)
 		index_mailbox_check_remove_all(&mbox->ibox);
 	else
-		index_mailbox_check_add(&mbox->ibox, mbox->path);
+		index_mailbox_check_add(&mbox->ibox, mbox->ibox.box.path);
 }
 
 static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
@@ -356,7 +344,7 @@
 		cydir_storage_add_list,
 		cydir_storage_get_list_settings,
 		NULL,
-		cydir_mailbox_open,
+		cydir_mailbox_alloc,
 		cydir_mailbox_create,
 		NULL
 	}
@@ -371,6 +359,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		cydir_mailbox_open,
 		index_storage_mailbox_close,
 		index_storage_get_status,
 		NULL,
--- a/src/lib-storage/index/cydir/cydir-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -16,8 +16,6 @@
 struct cydir_mailbox {
 	struct index_mailbox ibox;
 	struct cydir_storage *storage;
-
-	const char *path;
 };
 
 struct cydir_transaction_context {
--- a/src/lib-storage/index/cydir/cydir-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -175,10 +175,12 @@
 	struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
 	int ret = 0;
 
-	if (!box->opened)
-		index_storage_mailbox_open(&mbox->ibox);
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			ret = -1;
+	}
 
-	if (index_mailbox_want_full_sync(&mbox->ibox, flags))
+	if (index_mailbox_want_full_sync(&mbox->ibox, flags) && ret == 0)
 		ret = cydir_sync(mbox);
 
 	return index_mailbox_sync_init(box, flags, ret < 0);
--- a/src/lib-storage/index/dbox/dbox-file.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-file.c	Mon Jun 15 14:28:55 2009 -0400
@@ -151,7 +151,7 @@
 {
 	const char *dir;
 
-	dir = file->single_mbox != NULL ? file->single_mbox->path :
+	dir = file->single_mbox != NULL ? file->single_mbox->ibox.box.path :
 		file->storage->storage_dir;
 	return t_strdup_printf("%s/%s", dir, file->fname);
 }
@@ -184,7 +184,8 @@
 	} else {
 		file->fname = dbox_generate_tmp_filename();
 	}
-	file->current_path = i_strdup_printf("%s/%s", mbox->path, file->fname);
+	file->current_path = i_strdup_printf("%s/%s", mbox->ibox.box.path,
+					     file->fname);
 	return file;
 }
 
@@ -237,7 +238,8 @@
 	if (file->single_mbox != NULL) {
 		new_fname = dbox_file_uid_get_fname(file->single_mbox,
 						    id, &maildir);
-		new_path = i_strdup_printf("%s/%s", file->single_mbox->path,
+		new_path = i_strdup_printf("%s/%s",
+					   file->single_mbox->ibox.box.path,
 					   new_fname);
 	} else {
 		new_fname = i_strdup_printf(DBOX_MAIL_FILE_MULTI_FORMAT, id);
--- a/src/lib-storage/index/dbox/dbox-mail.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-mail.c	Mon Jun 15 14:28:55 2009 -0400
@@ -68,7 +68,8 @@
 					  &data, &data_size);
 		if (data_size != sizeof(*hdr)) {
 			mail_storage_set_critical(&mbox->storage->storage,
-				"dbox %s: Invalid dbox header size", mbox->path);
+				"dbox %s: Invalid dbox header size",
+				mbox->ibox.box.path);
 			mbox->storage->sync_rebuild = TRUE;
 			return -1;
 		}
@@ -82,7 +83,7 @@
 	if (cur_map_uid_validity != mbox->map_uid_validity) {
 		mail_storage_set_critical(&mbox->storage->storage,
 			"dbox %s: map uidvalidity mismatch (%u vs %u)",
-			mbox->path, mbox->map_uid_validity,
+			mbox->ibox.box.path, mbox->map_uid_validity,
 			cur_map_uid_validity);
 		mbox->storage->sync_rebuild = TRUE;
 		return -1;
--- a/src/lib-storage/index/dbox/dbox-save.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-save.c	Mon Jun 15 14:28:55 2009 -0400
@@ -445,9 +445,9 @@
 	dbox_map_append_free(&ctx->append_ctx);
 
 	if (!ctx->mbox->storage->storage.set->fsync_disable) {
-		if (fdatasync_path(ctx->mbox->path) < 0) {
+		if (fdatasync_path(ctx->mbox->ibox.box.path) < 0) {
 			i_error("fdatasync_path(%s) failed: %m",
-				ctx->mbox->path);
+				ctx->mbox->ibox.box.path);
 		}
 	}
 	dbox_transaction_save_rollback(ctx);
--- a/src/lib-storage/index/dbox/dbox-storage-rebuild.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage-rebuild.c	Mon Jun 15 14:28:55 2009 -0400
@@ -398,12 +398,13 @@
 	enum mail_error error;
 	int ret;
 
-	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) {
-		mailbox_list_get_last_error(ns->list, &error);
+	box = dbox_mailbox_alloc(&ctx->storage->storage, ns->list, name, NULL,
+				 MAILBOX_FLAG_READONLY |
+				 MAILBOX_FLAG_KEEP_RECENT |
+				 MAILBOX_FLAG_IGNORE_ACLS);
+	if (dbox_mailbox_open(box) < 0) {
+		(void)mail_storage_get_last_error(box->storage, &error);
+		mailbox_close(&box);
 		if (error == MAIL_ERROR_TEMP)
 			return -1;
 		/* non-temporary error, ignore */
@@ -416,7 +417,7 @@
 	if (ret <= 0) {
 		i_assert(ret != 0);
 		mail_storage_set_index_error(&mbox->ibox);
-		(void)mailbox_close(&box);
+		mailbox_close(&box);
 		return -1;
 	}
 
@@ -431,7 +432,7 @@
 		ret = -1;
 	}
 
-	(void)mailbox_close(&box);
+	mailbox_close(&box);
 	return ret < 0 ? -1 : 0;
 }
 
@@ -484,7 +485,7 @@
 {
 	if (mail_index_sync_commit(&msg->sync_ctx) < 0)
 		return -1;
-	(void)mailbox_close(&msg->box);
+	mailbox_close(&msg->box);
 	memset(msg, 0, sizeof(*msg));
 	return 0;
 }
@@ -533,15 +534,16 @@
 		strcmp(mailbox, ctx->prev_msg.box->name) == 0 ?
 		ctx->prev_msg.box : NULL;
 	while (box == NULL) {
-		box = dbox_mailbox_open(storage, ctx->default_list,
-					mailbox, NULL,
-					MAILBOX_OPEN_READONLY |
-					MAILBOX_OPEN_KEEP_RECENT |
-					MAILBOX_OPEN_IGNORE_ACLS);
-		if (box != NULL)
+		box = dbox_mailbox_alloc(storage, ctx->default_list,
+					 mailbox, NULL,
+					 MAILBOX_FLAG_READONLY |
+					 MAILBOX_FLAG_KEEP_RECENT |
+					 MAILBOX_FLAG_IGNORE_ACLS);
+		if (dbox_mailbox_open(box) == 0)
 			break;
 
-		mail_storage_get_last_error(storage, &error);
+		(void)mail_storage_get_last_error(box->storage, &error);
+		mailbox_close(&box);
 		if (error == MAIL_ERROR_TEMP)
 			return -1;
 
@@ -574,7 +576,7 @@
 		if (ret <= 0) {
 			i_assert(ret != 0);
 			mail_storage_set_index_error(&mbox->ibox);
-			(void)mailbox_close(&box);
+			mailbox_close(&box);
 			return -1;
 		}
 		ctx->prev_msg.box = box;
--- a/src/lib-storage/index/dbox/dbox-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -136,59 +136,49 @@
 	return NULL;
 }
 
-static struct mailbox *
-dbox_open(struct dbox_storage *storage, struct mailbox_list *list,
-	  const char *name, enum mailbox_open_flags flags)
+struct mailbox *
+dbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		   const char *name, struct istream *input,
+		   enum mailbox_flags flags)
 {
-	struct mail_storage *_storage = &storage->storage;
 	struct dbox_mailbox *mbox;
-	struct mailbox *box;
-	struct mail_index *index;
-	const char *path;
 	pool_t pool;
-	int ret;
 
 	/* dbox can't work without index files */
-	flags &= ~MAILBOX_OPEN_NO_INDEX_FILES;
-
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
-	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);
+	flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
 
 	pool = pool_alloconly_create("dbox mailbox", 1024+512);
 	mbox = p_new(pool, struct dbox_mailbox, 1);
 	mbox->ibox.box = dbox_mailbox;
 	mbox->ibox.box.pool = pool;
-	mbox->ibox.box.storage = _storage;
+	mbox->ibox.box.storage = storage;
 	mbox->ibox.box.list = list;
 	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(list, path));
-	mbox->storage = storage;
 
+	index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+				    DBOX_INDEX_PREFIX);
+	mail_index_set_fsync_types(mbox->ibox.index,
+				   MAIL_INDEX_SYNC_TYPE_APPEND |
+				   MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+
+	mbox->storage = (struct dbox_storage *)storage;
+	mbox->alt_path =
+		p_strdup(pool, dbox_get_alt_path(list, mbox->ibox.box.path));
 	mbox->dbox_ext_id =
-		mail_index_ext_register(index, "dbox", 0,
+		mail_index_ext_register(mbox->ibox.index, "dbox", 0,
 					sizeof(struct dbox_mail_index_record),
 					sizeof(uint32_t));
 	mbox->dbox_hdr_ext_id =
-		mail_index_ext_register(index, "dbox-hdr",
+		mail_index_ext_register(mbox->ibox.index, "dbox-hdr",
 					sizeof(struct dbox_index_header), 0, 0);
 	mbox->guid_ext_id =
-		mail_index_ext_register(index, "guid", 0, DBOX_GUID_BIN_LEN, 1);
-
-	ret = index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
-	mbox->maildir_uidlist = maildir_uidlist_init_readonly(&mbox->ibox);
+		mail_index_ext_register(mbox->ibox.index, "guid",
+					0, DBOX_GUID_BIN_LEN, 1);
 
-	box = &mbox->ibox.box;
-	if (ret < 0)
-		mailbox_close(&box);
-	return box;
+	mbox->maildir_uidlist = maildir_uidlist_init_readonly(&mbox->ibox);
+	return &mbox->ibox.box;
 }
 
 uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list)
@@ -201,7 +191,7 @@
 	return mailbox_uidvalidity_next(path);
 }
 
-static void dbox_write_index_header(struct mailbox *box)
+static int dbox_write_index_header(struct mailbox *box)
 {
 	struct dbox_mailbox *mbox = (struct dbox_mailbox *)box;
 	struct mail_index_transaction *trans;
@@ -209,7 +199,7 @@
 	uint32_t uid_validity;
 
 	if (dbox_map_open(mbox->storage->map, TRUE) < 0)
-		return;
+		return -1;
 
 	trans = mail_index_transaction_begin(mbox->ibox.view, 0);
 
@@ -225,33 +215,25 @@
 		offsetof(struct mail_index_header, uid_validity),
 		&uid_validity, sizeof(uid_validity), TRUE);
 
-	(void)mail_index_transaction_commit(&trans);
+	return mail_index_transaction_commit(&trans);
 }
 
-static int create_dbox(struct mail_storage *_storage, struct mailbox_list *list,
-		       const char *path, const char *name, bool directory)
+static int create_dbox(struct mailbox *box)
 {
-	struct dbox_storage *storage = (struct dbox_storage *)_storage;
-	struct mailbox *box;
 	mode_t mode;
 	gid_t 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, list, name,
-					MAILBOX_OPEN_KEEP_RECENT);
-			if (box == NULL)
-				return -1;
-			dbox_write_index_header(box);
-			mailbox_close(&box);
-			return 0;
-		}
+	mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid);
+	if (mkdir_parents_chown(box->path, mode, (uid_t)-1, gid) == 0) {
+		/* create indexes immediately with the dbox header */
+		if (index_storage_mailbox_open(box) < 0)
+			return -1;
+		if (dbox_write_index_header(box) < 0)
+			return -1;
 	} else if (errno != EEXIST) {
-		if (!mail_storage_set_error_from_errno(_storage)) {
-			mail_storage_set_critical(_storage,
-				"mkdir(%s) failed: %m", path);
+		if (!mail_storage_set_error_from_errno(box->storage)) {
+			mail_storage_set_critical(box->storage,
+				"mkdir(%s) failed: %m", box->path);
 		}
 		return -1;
 	}
@@ -281,53 +263,46 @@
 	return TRUE;
 }
 
-struct mailbox *
-dbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
-		  const char *name, struct istream *input,
-		  enum mailbox_open_flags flags)
+int dbox_mailbox_open(struct mailbox *box)
 {
-	struct dbox_storage *storage = (struct dbox_storage *)_storage;
-	const char *path;
-
-	if (input != NULL) {
-		mailbox_list_set_critical(list,
+	if (box->input != NULL) {
+		mail_storage_set_critical(box->storage,
 			"dbox doesn't support streamed mailboxes");
-		return NULL;
+		return -1;
 	}
 
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (dbox_cleanup_if_exists(list, path)) {
-		return dbox_open(storage, list, name, flags);
+	if (dbox_cleanup_if_exists(box->list, box->path)) {
+		return index_storage_mailbox_open(box);
 	} else if (errno == ENOENT) {
-		if (strcmp(name, "INBOX") == 0 &&
-		    (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+		if (strcmp(box->name, "INBOX") == 0 &&
+		    (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
 			/* INBOX always exists, create it */
-			if (create_dbox(_storage, list, path, name, FALSE) < 0) {
-				mailbox_list_set_error_from_storage(list,
-								    _storage);
-				return NULL;
-			}
-			return dbox_open(storage, list, name, flags);
+			if (create_dbox(box) < 0)
+				return -1;
+			return box->opened ? 0 :
+				index_storage_mailbox_open(box);
 		}
 
-		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+		return -1;
 	} else if (errno == EACCES) {
-		mailbox_list_set_critical(list, "%s",
-			mail_error_eacces_msg("stat", path));
+		mail_storage_set_critical(box->storage, "%s",
+			mail_error_eacces_msg("stat", box->path));
+		return -1;
 	} else {
-		mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", box->path);
+		return -1;
 	}
-	return NULL;
 }
 
-static int dbox_storage_mailbox_close(struct mailbox *box)
+static void dbox_mailbox_close(struct mailbox *box)
 {
 	struct dbox_mailbox *mbox = (struct dbox_mailbox *)box;
 
 	maildir_uidlist_deinit(&mbox->maildir_uidlist);
-	return index_storage_mailbox_close(box);
+	index_storage_mailbox_close(box);
 }
 
 static int
@@ -335,7 +310,9 @@
 		    const char *name, bool directory)
 {
 	const char *path, *alt_path;
+	struct mailbox *box;
 	struct stat st;
+	int ret;
 
 	path = mailbox_list_get_path(list, name,
 				     directory ? MAILBOX_LIST_PATH_TYPE_DIR :
@@ -346,18 +323,39 @@
 		return -1;
 	}
 
+	if (directory) {
+		mode_t mode;
+		gid_t gid;
+
+		mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
+		if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) == 0)
+			return 0;
+		else if (errno == EEXIST) {
+			mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
+					       "Mailbox already exists");
+		} else if (!mail_storage_set_error_from_errno(storage)) {
+			mail_storage_set_critical(storage,
+						  "mkdir(%s) failed: %m", path);
+		}
+		return -1;
+	}
+
 	/* make sure the alt path doesn't exist yet. it shouldn't (except with
 	   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(list, path);
+	alt_path = dbox_get_alt_path(list, path);
 	if (alt_path != NULL && stat(alt_path, &st) == 0) {
 		mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
 				       "Mailbox already exists");
 		return -1;
 	}
 
-	return create_dbox(storage, list, path, name, directory);
+	box = dbox_mailbox_alloc(storage, list, name, NULL,
+				 MAILBOX_FLAG_KEEP_RECENT);
+	ret = create_dbox(box);
+	mailbox_close(&box);
+	return ret;
 }
 
 static int
@@ -381,11 +379,15 @@
 	tmp_set = *list->mail_set;
 	tmp_set.mail_full_filesystem_access = TRUE;
 	list->mail_set = &tmp_set;
-	box = dbox_open(storage, list, path, MAILBOX_OPEN_IGNORE_ACLS |
-			MAILBOX_OPEN_KEEP_RECENT);
+	box = dbox_mailbox_alloc(&storage->storage, list, path, NULL,
+				 MAILBOX_FLAG_IGNORE_ACLS |
+				 MAILBOX_FLAG_KEEP_RECENT);
+	ret = mailbox_open(box);
 	list->mail_set = old_set;
-	if (box == NULL)
+	if (ret < 0) {
+		mailbox_close(&box);
 		return -1;
+	}
 	mbox = (struct dbox_mailbox *)box;
 
 	/* get a list of all map_uids in this mailbox */
@@ -644,7 +646,7 @@
 		index_mailbox_check_remove_all(&mbox->ibox);
 	else {
 		path = t_strdup_printf("%s/"DBOX_INDEX_PREFIX".log",
-				       mbox->path);
+				       mbox->ibox.box.path);
 		index_mailbox_check_add(&mbox->ibox, path);
 	}
 }
@@ -757,7 +759,7 @@
 		dbox_storage_add_list,
 		dbox_storage_get_list_settings,
 		NULL,
-		dbox_mailbox_open,
+		dbox_mailbox_alloc,
 		dbox_mailbox_create,
 		dbox_sync_purge
 	}
@@ -772,7 +774,8 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
-		dbox_storage_mailbox_close,
+		dbox_mailbox_open,
+		dbox_mailbox_close,
 		index_storage_get_status,
 		NULL,
 		NULL,
--- a/src/lib-storage/index/dbox/dbox-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -73,7 +73,7 @@
 
 	uint32_t dbox_ext_id, dbox_hdr_ext_id, guid_ext_id;
 
-	const char *path, *alt_path;
+	const char *alt_path;
 };
 
 struct dbox_transaction_context {
@@ -90,9 +90,10 @@
 void dbox_transaction_class_deinit(void);
 
 struct mailbox *
-dbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
-		  const char *name, struct istream *input,
-		  enum mailbox_open_flags flags);
+dbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		   const char *name, struct istream *input,
+		   enum mailbox_flags flags);
+int dbox_mailbox_open(struct mailbox *box);
 
 struct mail *
 dbox_mail_alloc(struct mailbox_transaction_context *t,
--- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c	Mon Jun 15 14:28:55 2009 -0400
@@ -191,7 +191,7 @@
 	uid = strtoul(fname, &p, 10);
 	if (*p != '\0' || uid == 0 || uid >= (uint32_t)-1) {
 		i_warning("dbox %s: Ignoring invalid filename %s",
-			  ctx->mbox->path, fname);
+			  ctx->mbox->ibox.box.path, fname);
 		return 0;
 	}
 
@@ -234,7 +234,7 @@
 	ret = maildir_uidlist_sync_next(ctx->maildir_sync_ctx, fname, 0);
 	if (ret == 0) {
 		i_warning("%s: Ignoring duplicate maildir file: %s",
-			  ctx->mbox->path, fname);
+			  ctx->mbox->ibox.box.path, fname);
 	}
 	return ret;
 }
@@ -334,7 +334,8 @@
 	while (maildir_uidlist_iter_next(iter, &uid, &flags, &fname)) {
 		file = dbox_file_init_single(mbox, uid);
 		file->current_path =
-			i_strdup_printf("%s/%s", ctx->mbox->path, fname);
+			i_strdup_printf("%s/%s", ctx->mbox->ibox.box.path,
+					fname);
 
 		ret = dbox_sync_add_file_index(ctx, file);
 		dbox_file_unref(&file);
@@ -411,7 +412,7 @@
 	int ret = 0;
 
 	dbox_sync_set_uidvalidity(ctx);
-	if (dbox_sync_index_rebuild_dir(ctx, ctx->mbox->path, TRUE) < 0)
+	if (dbox_sync_index_rebuild_dir(ctx, ctx->mbox->ibox.box.path, TRUE) < 0)
 		ret = -1;
 	else if (ctx->mbox->alt_path != NULL) {
 		if (dbox_sync_index_rebuild_dir(ctx, ctx->mbox->alt_path,
--- a/src/lib-storage/index/dbox/dbox-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -221,7 +221,7 @@
 		   data_size=4 is for backwards compatibility */
 		if (data_size != 0 && data_size != 4) {
 			i_warning("dbox %s: Invalid dbox header size",
-				  mbox->path);
+				  mbox->ibox.box.path);
 		}
 		ret = -1;
 	} else {
@@ -301,17 +301,17 @@
 			if (mbox->storage->have_multi_msgs) {
 				mail_storage_set_critical(storage,
 					"dbox %s: Storage keeps breaking",
-					ctx->mbox->path);
+					ctx->mbox->ibox.box.path);
 				ret = -1;
 			} else if (i >= DBOX_REBUILD_COUNT) {
 				mail_storage_set_critical(storage,
 					"dbox %s: Index keeps breaking",
-					ctx->mbox->path);
+					ctx->mbox->ibox.box.path);
 				ret = -1;
 			} else {
 				/* do a full resync and try again. */
 				i_warning("dbox %s: Rebuilding index",
-					  ctx->mbox->path);
+					  ctx->mbox->ibox.box.path);
 				ret = dbox_sync_index_rebuild(mbox);
 			}
 		}
@@ -373,7 +373,7 @@
 	int ret = 0;
 
 	if (!box->opened) {
-		if (index_storage_mailbox_open(&mbox->ibox) < 0)
+		if (mailbox_open(box) < 0)
 			ret = -1;
 	}
 
--- a/src/lib-storage/index/index-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/index-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -2,7 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
-#include "buffer.h"
+#include "istream.h"
 #include "ioloop.h"
 #include "imap-parser.h"
 #include "mkdir-parents.h"
@@ -107,11 +107,11 @@
 
 static const char *
 get_index_dir(struct mailbox_list *list, const char *name,
-	      enum mailbox_open_flags flags, struct stat *st_r)
+	      enum mailbox_flags flags, struct stat *st_r)
 {
 	const char *index_dir;
 
-	index_dir = (flags & MAILBOX_OPEN_NO_INDEX_FILES) != 0 ? "" :
+	index_dir = (flags & MAILBOX_FLAG_NO_INDEX_FILES) != 0 ? "" :
 		mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
 	if (*index_dir == '\0') {
 		/* disabled */
@@ -139,9 +139,9 @@
 	return index_dir;
 }
 
-struct mail_index *
+static struct mail_index *
 index_storage_alloc(struct mailbox_list *list, const char *name,
-		    enum mailbox_open_flags flags, const char *prefix)
+		    enum mailbox_flags flags, const char *prefix)
 {
 	struct index_list **indexp, *rec;
 	struct mail_index *index;
@@ -149,6 +149,7 @@
 	const char *index_dir, *mailbox_path;
 	int destroy_count;
 
+	// FIXME: failure handling when dirs don't exist yet?
 	mailbox_path = mailbox_list_get_path(list, name,
 					     MAILBOX_LIST_PATH_TYPE_MAILBOX);
 	index_dir = get_index_dir(list, name, flags, &st);
@@ -365,16 +366,30 @@
 	ibox->last_notify_type = MAILBOX_LOCK_NOTIFY_NONE;
 }
 
-int index_storage_mailbox_open(struct index_mailbox *ibox)
+int index_storage_mailbox_open(struct mailbox *box)
 {
-	struct mail_storage *storage = ibox->box.storage;
-	enum file_lock_method lock_method = storage->set->parsed_lock_method;
+	struct index_mailbox *ibox = (struct index_mailbox *)box;
+	enum file_lock_method lock_method =
+		box->storage->set->parsed_lock_method;
 	enum mail_index_open_flags index_flags;
+	gid_t dir_gid;
 	int ret;
 
-	i_assert(!ibox->box.opened);
+	i_assert(!box->opened);
 
-	index_flags = mail_storage_settings_to_index_flags(storage->set);
+	if (box->file_create_mode == 0) {
+		mailbox_list_get_permissions(box->list, box->name,
+					     &box->file_create_mode,
+					     &box->file_create_gid);
+		mailbox_list_get_dir_permissions(box->list, box->name,
+						 &box->dir_create_mode,
+						 &dir_gid);
+		mail_index_set_permissions(ibox->index,
+					   box->file_create_mode,
+					   box->file_create_gid);
+	}
+
+	index_flags = mail_storage_settings_to_index_flags(box->storage->set);
 	if (!ibox->move_to_memory)
 		index_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
 	if (ibox->keep_index_backups)
@@ -407,55 +422,52 @@
 	MODULE_CONTEXT_SET_FULL(ibox->view, mail_storage_mail_index_module,
 				ibox, &ibox->view_module_ctx);
 
-	ibox->box.opened = TRUE;
+	box->opened = TRUE;
 
 	index_thread_mailbox_index_opened(ibox);
 	if (hook_mailbox_index_opened != NULL)
-		hook_mailbox_index_opened(&ibox->box);
+		hook_mailbox_index_opened(box);
 	return 0;
 }
 
-int index_storage_mailbox_init(struct index_mailbox *ibox, const char *name,
-			       enum mailbox_open_flags flags,
-			       bool move_to_memory)
+void index_storage_mailbox_alloc(struct index_mailbox *ibox, const char *name,
+				 struct istream *input,
+				 enum mailbox_flags flags,
+				 const char *index_prefix)
 {
-	struct mail_storage *storage = ibox->box.storage;
 	struct mailbox *box = &ibox->box;
-	gid_t dir_gid;
-
-	i_assert(name != NULL);
+	const char *path;
 
-	box->storage = storage;
-	box->name = p_strdup(box->pool, name);
-	box->open_flags = flags;
-	if (box->file_create_mode == 0) {
-		mailbox_list_get_permissions(box->list, name,
-					     &box->file_create_mode,
-					     &box->file_create_gid);
-		mailbox_list_get_dir_permissions(box->list, name,
-						 &box->dir_create_mode,
-						 &dir_gid);
-		mail_index_set_permissions(ibox->index, box->file_create_mode,
-					   box->file_create_gid);
+	if (name != NULL)
+		box->name = p_strdup(box->pool, name);
+	else {
+		i_assert(input != NULL);
+		box->name = "(read-only input stream)";
 	}
 
+	if (input != NULL) {
+		flags |= MAILBOX_FLAG_READONLY;
+		box->input = input;
+		i_stream_ref(input);
+	}
+	box->flags = flags;
+
 	p_array_init(&box->search_results, box->pool, 16);
 	array_create(&box->module_contexts,
 		     box->pool, sizeof(void *), 5);
 
-	ibox->keep_recent = (flags & MAILBOX_OPEN_KEEP_RECENT) != 0;
-	ibox->keep_locked = (flags & MAILBOX_OPEN_KEEP_LOCKED) != 0;
-	ibox->move_to_memory = move_to_memory;
+	path = mailbox_list_get_path(box->list, name,
+				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
+	ibox->box.path = p_strdup(box->pool, path);
+
+	ibox->keep_recent = (flags & MAILBOX_FLAG_KEEP_RECENT) != 0;
+	ibox->keep_locked = (flags & MAILBOX_FLAG_KEEP_LOCKED) != 0;
 
 	ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
 	ibox->commit_log_file_seq = 0;
-
+	ibox->index = index_storage_alloc(box->list, name, flags, index_prefix);
 	ibox->md5hdr_ext_idx =
 		mail_index_ext_register(ibox->index, "header-md5", 0, 16, 1);
-
-	if ((flags & MAILBOX_OPEN_FAST) == 0)
-		return index_storage_mailbox_open(ibox);
-	return 0;
 }
 
 int index_storage_mailbox_enable(struct mailbox *box,
@@ -466,7 +478,7 @@
 	if ((feature & MAILBOX_FEATURE_CONDSTORE) != 0) {
 		box->enabled_features |= MAILBOX_FEATURE_CONDSTORE;
 		if (!box->opened) {
-			if (index_storage_mailbox_open(ibox) < 0)
+			if (mailbox_open(box) < 0)
 				return -1;
 		}
 		mail_index_modseq_enable(ibox->index);
@@ -474,7 +486,7 @@
 	return 0;
 }
 
-int index_storage_mailbox_close(struct mailbox *box)
+void index_storage_mailbox_close(struct mailbox *box)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
@@ -482,6 +494,8 @@
 		mail_index_view_close(&ibox->view);
 
 	index_mailbox_check_remove_all(ibox);
+	if (ibox->box.input != NULL)
+		i_stream_unref(&ibox->box.input);
 	if (ibox->index != NULL)
 		index_storage_unref(ibox->index);
 	if (array_is_created(&ibox->recent_flags))
@@ -489,14 +503,13 @@
 	i_free(ibox->cache_fields);
 
 	pool_unref(&box->pool);
-	return 0;
 }
 
 bool index_storage_is_readonly(struct mailbox *box)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
-	return (ibox->box.open_flags & MAILBOX_OPEN_READONLY) != 0 ||
+	return (box->flags & MAILBOX_FLAG_READONLY) != 0 ||
 		ibox->backend_readonly;
 }
 
--- a/src/lib-storage/index/index-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/index-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -85,20 +85,18 @@
 			       unsigned int secs_left);
 void index_storage_lock_notify_reset(struct index_mailbox *ibox);
 
-struct mail_index *
-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);
 void index_storage_destroy(struct mail_storage *storage ATTR_UNUSED);
 
-int index_storage_mailbox_init(struct index_mailbox *ibox, const char *name,
-			       enum mailbox_open_flags flags,
-			       bool move_to_memory);
-int index_storage_mailbox_open(struct index_mailbox *ibox);
+void index_storage_mailbox_alloc(struct index_mailbox *ibox, const char *name,
+				 struct istream *input,
+				 enum mailbox_flags flags,
+				 const char *index_prefix);
+int index_storage_mailbox_open(struct mailbox *box);
 int index_storage_mailbox_enable(struct mailbox *box,
 				 enum mailbox_feature feature);
-int index_storage_mailbox_close(struct mailbox *box);
+void index_storage_mailbox_close(struct mailbox *box);
 
 bool index_storage_is_readonly(struct mailbox *box);
 bool index_storage_allow_new_keywords(struct mailbox *box);
--- a/src/lib-storage/index/index-thread.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/index-thread.c	Mon Jun 15 14:28:55 2009 -0400
@@ -609,10 +609,9 @@
 					     thread_type, write_seqs);
 }
 
-static int mail_thread_mailbox_close(struct mailbox *box)
+static void mail_thread_mailbox_close(struct mailbox *box)
 {
 	struct mail_thread_mailbox *tbox = MAIL_THREAD_CONTEXT(box);
-	int ret;
 
 	i_assert(tbox->ctx == NULL);
 
@@ -624,9 +623,8 @@
 	array_free(&tbox->cache->thread_nodes);
 	i_free(tbox->cache);
 
-	ret = tbox->module_ctx.super.close(box);
+	tbox->module_ctx.super.close(box);
 	i_free(tbox);
-	return ret;
 }
 
 void index_thread_mailbox_index_opened(struct index_mailbox *ibox)
--- a/src/lib-storage/index/maildir/maildir-copy.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Mon Jun 15 14:28:55 2009 -0400
@@ -211,7 +211,7 @@
 		/* keywords, hardlink to tmp/ with basename and later when we
 		   have uidlist locked, move it to new/cur. */
 		str_printfa(do_ctx.dest_path, "%s/tmp/%s",
-			    dest_mbox->path, do_ctx.dest_fname);
+			    dest_mbox->ibox.box.path, do_ctx.dest_fname);
 		do_ctx.base_end_pos = str_len(do_ctx.dest_path);
 	}
 	if (src_mbox != NULL) {
--- a/src/lib-storage/index/maildir/maildir-keywords.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-keywords.c	Mon Jun 15 14:28:55 2009 -0400
@@ -372,7 +372,7 @@
 		}
 		/* the control dir doesn't exist. create it unless the whole
 		   mailbox was just deleted. */
-		if (!maildir_set_deleted(mk->mbox))
+		if (!maildir_set_deleted(&mk->mbox->ibox.box))
 			return -1;
 	}
 
--- a/src/lib-storage/index/maildir/maildir-mail.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Mon Jun 15 14:28:55 2009 -0400
@@ -226,8 +226,7 @@
 		/* either nothing is cached, or only vsize is cached. */
 		mail->pop3_state = 1;
 	} else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
-		   (mail->ibox->box.open_flags &
-		    MAILBOX_OPEN_POP3_SESSION) == 0) {
+		   (mail->ibox->box.flags & MAILBOX_FLAG_POP3_SESSION) == 0) {
 		/* if virtual size isn't cached permanently,
 		   POP3 isn't being used */
 		mail->pop3_state = -1;
@@ -502,7 +501,7 @@
 				"new" : "cur";
 			mail_storage_set_critical(_mail->box->storage,
 				"Maildir filename has wrong W value: %s/%s/%s",
-				mbox->path, subdir, fname);
+				mbox->ibox.box.path, subdir, fname);
 		} else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
 				MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
 			maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
--- a/src/lib-storage/index/maildir/maildir-save.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-save.c	Mon Jun 15 14:28:55 2009 -0400
@@ -122,9 +122,9 @@
 	ctx->files_tail = &ctx->files;
 	ctx->fd = -1;
 
-	ctx->tmpdir = p_strconcat(pool, mbox->path, "/tmp", NULL);
-	ctx->newdir = p_strconcat(pool, mbox->path, "/new", NULL);
-	ctx->curdir = p_strconcat(pool, mbox->path, "/cur", NULL);
+	ctx->tmpdir = p_strconcat(pool, mbox->ibox.box.path, "/tmp", NULL);
+	ctx->newdir = p_strconcat(pool, mbox->ibox.box.path, "/new", NULL);
+	ctx->curdir = p_strconcat(pool, mbox->ibox.box.path, "/cur", NULL);
 
 	ctx->keywords_buffer = buffer_create_const_data(pool, NULL, 0);
 	array_create_from_buffer(&ctx->keywords_array, ctx->keywords_buffer,
@@ -525,7 +525,8 @@
 				MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE);
 		} else if (errno != 0) {
 			mail_storage_set_critical(storage,
-				"write(%s) failed: %m", ctx->mbox->path);
+				"write(%s) failed: %m",
+				ctx->mbox->ibox.box.path);
 		}
 
 		/* remove from the linked list */
--- a/src/lib-storage/index/maildir/maildir-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -295,19 +295,17 @@
 	unsigned int i;
 	int ret;
 
-	ret = maildir_check_tmp(storage, dir);
-	if (ret > 0) {
-		if (!verify) {
+	if (!verify) {
+		ret = maildir_check_tmp(storage, dir);
+		if (ret > 0) {
 			mail_storage_set_error(storage,
 				MAIL_ERROR_EXISTS, "Mailbox already exists");
 			return -1;
 		}
-		return 1;
+		if (ret < 0)
+			return -1;
 	}
-	if (ret < 0)
-		return -1;
 
-	/* 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, ns, path, mode, gid, verify) < 0)
@@ -331,140 +329,114 @@
 }
 
 static struct mailbox *
-maildir_open(struct mail_storage *storage, struct mail_namespace *ns,
-	     const char *name, enum mailbox_open_flags flags)
+maildir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		      const char *name, struct istream *input,
+		      enum mailbox_flags flags)
 {
 	struct maildir_mailbox *mbox;
-	struct mail_index *index;
-	const char *path, *control_dir;
-	struct stat st;
 	pool_t pool;
 
-	path = mailbox_list_get_path(ns->list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	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.box.storage = storage;
-	mbox->ibox.box.list = ns->list;
+	mbox->ibox.box.list = list;
 	mbox->ibox.mail_vfuncs = &maildir_mail_vfuncs;
 
+	index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+				    MAILDIR_INDEX_PREFIX);
+
 	mbox->storage = (struct maildir_storage *)storage;
-	mbox->path = p_strdup(pool, path);
+	mbox->maildir_ext_id =
+		mail_index_ext_register(mbox->ibox.index, "maildir",
+					sizeof(mbox->maildir_hdr), 0, 0);
+	mbox->uidlist = maildir_uidlist_init(mbox);
+	mbox->keywords = maildir_keywords_init(mbox);
+	return &mbox->ibox.box;
+}
 
-	index = index_storage_alloc(ns->list, name, flags,
-				    MAILDIR_INDEX_PREFIX);
-	mbox->ibox.index = index;
+static int maildir_mailbox_open_existing(struct mailbox *box)
+{
+	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
+	struct stat st;
 
 	/* for shared mailboxes get the create mode from the
 	   permissions of dovecot-shared file. */
-	if (stat(t_strconcat(path, "/dovecot-shared", NULL), &st) == 0) {
+	if (stat(t_strconcat(box->path, "/dovecot-shared", NULL), &st) == 0) {
 		if ((st.st_mode & S_ISGID) != 0 ||
 		    (st.st_mode & 0060) == 0) {
 			/* Ignore GID */
 			st.st_gid = (gid_t)-1;
 		}
-		mail_index_set_permissions(index, st.st_mode & 0666, st.st_gid);
+		mail_index_set_permissions(mbox->ibox.index,
+					   st.st_mode & 0666, st.st_gid);
 
-		mbox->ibox.box.file_create_mode = st.st_mode & 0666;
-		mbox->ibox.box.dir_create_mode =
-			get_dir_mode(st.st_mode & 0666);
-		mbox->ibox.box.file_create_gid = st.st_gid;
-		mbox->ibox.box.private_flags_mask = MAIL_SEEN;
+		box->file_create_mode = st.st_mode & 0666;
+		box->dir_create_mode = get_dir_mode(st.st_mode & 0666);
+		box->file_create_gid = st.st_gid;
+		box->private_flags_mask = MAIL_SEEN;
 	}
 
-	mbox->maildir_ext_id =
-		mail_index_ext_register(index, "maildir",
-					sizeof(mbox->maildir_hdr), 0, 0);
-
-	index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
-	mbox->uidlist = maildir_uidlist_init(mbox);
-	if ((flags & MAILBOX_OPEN_KEEP_LOCKED) != 0) {
-		if (maildir_uidlist_lock(mbox->uidlist) <= 0) {
-			struct mailbox *box = &mbox->ibox.box;
-
-			mailbox_close(&box);
-			mailbox_list_set_error_from_storage(ns->list, storage);
-			return NULL;
-		}
+	if ((box->flags & MAILBOX_FLAG_KEEP_LOCKED) != 0) {
+		if (maildir_uidlist_lock(mbox->uidlist) <= 0)
+			return -1;
 		mbox->keep_lock_to = timeout_add(MAILDIR_LOCK_TOUCH_SECS * 1000,
 						 maildir_lock_touch_timeout,
 						 mbox);
 	}
 
-	if (access(t_strconcat(path, "/cur", NULL), W_OK) < 0 &&
+	if (access(t_strconcat(box->path, "/cur", NULL), W_OK) < 0 &&
 	    errno == EACCES)
 		mbox->ibox.backend_readonly = TRUE;
-
-	mbox->keywords = maildir_keywords_init(mbox);
-	return &mbox->ibox.box;
+	return index_storage_mailbox_open(box);
 }
 
-static struct mailbox *
-maildir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		     const char *name, struct istream *input,
-		     enum mailbox_open_flags flags)
+static int maildir_mailbox_open(struct mailbox *box)
 {
-	const char *path;
 	struct stat st;
 	mode_t mode;
 	gid_t gid;
 	int ret;
+	bool inbox;
 
-	if (input != NULL) {
-		mailbox_list_set_critical(list,
+	if (box->input != NULL) {
+		mail_storage_set_critical(box->storage,
 			"Maildir doesn't support streamed mailboxes");
-		return NULL;
+		return -1;
 	}
 
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (strcmp(name, "INBOX") == 0 &&
-	    (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
-		/* INBOX always exists */
-		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, list->ns, "INBOX", flags);
-	}
+	inbox = strcmp(box->name, "INBOX") == 0 &&
+		(box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0;
 
 	/* begin by checking if tmp/ directory exists and if it should be
 	   cleaned up. */
-	ret = maildir_check_tmp(storage, path);
+	ret = maildir_check_tmp(box->storage, box->path);
 	if (ret > 0) {
 		/* exists */
-		return maildir_open(storage, list->ns, name, flags);
+		return maildir_mailbox_open_existing(box);
 	}
-	if (ret < 0) {
-		mailbox_list_set_error_from_storage(list, storage);
-		return NULL;
-	}
+	if (ret < 0)
+		return -1;
 
 	/* tmp/ directory doesn't exist. does the maildir? */
-	if (stat(path, &st) == 0) {
+	if (inbox || stat(box->path, &st) == 0) {
 		/* yes, we'll need to create the missing dirs */
-		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;
-		}
+		mailbox_list_get_dir_permissions(box->list, box->name,
+						 &mode, &gid);
+		if (create_maildir(box->storage, box->list->ns, box->path,
+				   mode, gid, TRUE) < 0)
+			return -1;
 
-		return maildir_open(storage, list->ns, name, flags);
+		return maildir_mailbox_open_existing(box);
 	} else if (errno == ENOENT) {
-		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-		return NULL;
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+		return -1;
 	} else {
-		mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
-		return NULL;
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", box->path);
+		return -1;
 	}
 }
 
@@ -786,7 +758,7 @@
 			       rename_children);
 }
 
-static int maildir_storage_mailbox_close(struct mailbox *box)
+static void maildir_mailbox_close(struct mailbox *box)
 {
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
 
@@ -800,7 +772,7 @@
 	if (mbox->keywords != NULL)
 		maildir_keywords_deinit(&mbox->keywords);
 	maildir_uidlist_deinit(&mbox->uidlist);
-	return index_storage_mailbox_close(box);
+	index_storage_mailbox_close(box);
 }
 
 static void maildir_notify_changes(struct mailbox *box)
@@ -811,9 +783,9 @@
 		index_mailbox_check_remove_all(&mbox->ibox);
 	else {
 		index_mailbox_check_add(&mbox->ibox,
-					t_strconcat(mbox->path, "/new", NULL));
+			t_strconcat(mbox->ibox.box.path, "/new", NULL));
 		index_mailbox_check_add(&mbox->ibox,
-					t_strconcat(mbox->path, "/cur", NULL));
+			t_strconcat(mbox->ibox.box.path, "/cur", NULL));
 	}
 }
 
@@ -1040,7 +1012,7 @@
 		maildir_storage_add_list,
 		maildir_storage_get_list_settings,
 		maildir_storage_autodetect,
-		maildir_mailbox_open,
+		maildir_mailbox_alloc,
 		maildir_mailbox_create,
 		NULL
 	}
@@ -1055,7 +1027,8 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
-		maildir_storage_mailbox_close,
+		maildir_mailbox_open,
+		maildir_mailbox_close,
 		index_storage_get_status,
 		maildir_list_index_has_changed,
 		maildir_list_index_update_sync,
--- a/src/lib-storage/index/maildir/maildir-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -83,7 +83,6 @@
 	struct maildir_storage *storage;
 	struct mail_index_view *flags_view;
 
-	const char *path;
 	struct timeout *keep_lock_to;
 
 	/* maildir sync: */
@@ -122,7 +121,7 @@
 	maildir_file_do(mbox, seq, (maildir_file_do_func *)callback, context)
 #endif
 
-bool maildir_set_deleted(struct maildir_mailbox *mbox);
+bool maildir_set_deleted(struct mailbox *box);
 uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list);
 
 void maildir_transaction_class_init(void);
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Mon Jun 15 14:28:55 2009 -0400
@@ -160,7 +160,8 @@
 	maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
 
 	i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
-		  "(old uid=%u, file=%s)", ctx->mbox->path, uid, filename);
+		  "(old uid=%u, file=%s)", ctx->mbox->ibox.box.path,
+		  uid, filename);
 	return 0;
 }
 
@@ -402,7 +403,7 @@
 		   first time, reset the index so we can add all messages as
 		   new */
 		i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
-			  mbox->path, hdr->uid_validity, uid_validity);
+			  mbox->ibox.box.path, hdr->uid_validity, uid_validity);
 		mail_index_reset(trans);
 		index_mailbox_reset_uidvalidity(&mbox->ibox);
 		maildir_uidlist_set_next_uid(mbox->uidlist, 1, TRUE);
@@ -564,7 +565,7 @@
 	if (mbox->ibox.box.v.sync_notify != NULL)
 		mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0);
 
-	if (stat(t_strconcat(mbox->path, "/cur", NULL), &st) == 0) {
+	if (stat(t_strconcat(mbox->ibox.box.path, "/cur", NULL), &st) == 0) {
 		mbox->maildir_hdr.new_check_time =
 			I_MAX(st.st_mtime, time_before_sync);
 		mbox->maildir_hdr.cur_mtime = st.st_mtime;
--- a/src/lib-storage/index/maildir/maildir-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -255,8 +255,8 @@
 
 	ctx = t_new(struct maildir_sync_context, 1);
 	ctx->mbox = mbox;
-	ctx->new_dir = t_strconcat(mbox->path, "/new", NULL);
-	ctx->cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+	ctx->new_dir = t_strconcat(mbox->ibox.box.path, "/new", NULL);
+	ctx->cur_dir = t_strconcat(mbox->ibox.box.path, "/cur", NULL);
 	ctx->last_touch = ioloop_time;
 	ctx->last_notify = ioloop_time;
 	ctx->flags = flags;
@@ -321,7 +321,8 @@
 	}
 
 	new_fname = maildir_filename_generate();
-	new_path = t_strconcat(ctx->mbox->path, "/new/", new_fname, NULL);
+	new_path = t_strconcat(ctx->mbox->ibox.box.path, "/new/",
+			       new_fname, NULL);
 
 	if (rename(path2, new_path) == 0)
 		i_warning("Fixed a duplicate: %s -> %s", path2, new_fname);
@@ -337,6 +338,7 @@
 static int
 maildir_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st_r)
 {
+	struct mailbox *box = &mbox->ibox.box;
 	int i;
 
 	for (i = 0;; i++) {
@@ -345,13 +347,12 @@
 		if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT)
 			break;
 
-		if (!maildir_set_deleted(mbox))
+		if (!maildir_set_deleted(box))
 			return -1;
 		/* try again */
 	}
 
-	mail_storage_set_critical(mbox->ibox.box.storage,
-				  "stat(%s) failed: %m", path);
+	mail_storage_set_critical(box->storage, "stat(%s) failed: %m", path);
 	return -1;
 }
 
@@ -386,7 +387,7 @@
 			return -1;
 		}
 
-		if (!maildir_set_deleted(ctx->mbox))
+		if (!maildir_set_deleted(&ctx->mbox->ibox.box))
 			return -1;
 		/* try again */
 	}
@@ -909,8 +910,10 @@
 	bool lost_files, force_resync;
 	int ret = 0;
 
-	if (!box->opened)
-		index_storage_mailbox_open(&mbox->ibox);
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			return index_mailbox_sync_init(box, flags, TRUE);
+	}
 
 	force_resync = (flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0;
 	if (index_mailbox_want_full_sync(&mbox->ibox, flags)) {
@@ -967,8 +970,8 @@
 	T_BEGIN {
 		const char *new_dir, *cur_dir;
 
-		new_dir = t_strconcat(mbox->path, "/new", NULL);
-		cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+		new_dir = t_strconcat(mbox->ibox.box.path, "/new", NULL);
+		cur_dir = t_strconcat(mbox->ibox.box.path, "/cur", NULL);
 
 		ret = maildir_sync_quick_check(mbox, FALSE, new_dir, cur_dir,
 					       &new_changed, &cur_changed);
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Mon Jun 15 14:28:55 2009 -0400
@@ -174,7 +174,7 @@
 		}
 		/* the control dir doesn't exist. create it unless the whole
 		   mailbox was just deleted. */
-		if (!maildir_set_deleted(uidlist->mbox))
+		if (!maildir_set_deleted(&uidlist->mbox->ibox.box))
 			return -1;
 	}
 
@@ -1221,7 +1221,7 @@
 		}
 		/* the control dir doesn't exist. create it unless the whole
 		   mailbox was just deleted. */
-		if (!maildir_set_deleted(uidlist->mbox))
+		if (!maildir_set_deleted(&uidlist->mbox->ibox.box))
 			return -1;
 	}
 
--- a/src/lib-storage/index/maildir/maildir-util.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-util.c	Mon Jun 15 14:28:55 2009 -0400
@@ -74,13 +74,13 @@
 
 	if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
 		/* probably in new/ dir */
-		path = t_strconcat(mbox->path, "/new/", fname, NULL);
+		path = t_strconcat(mbox->ibox.box.path, "/new/", fname, NULL);
 		ret = callback(mbox, path, context);
 		if (ret != 0)
 			return ret;
 	}
 
-	path = t_strconcat(mbox->path, "/cur/", fname, NULL);
+	path = t_strconcat(mbox->ibox.box.path, "/cur/", fname, NULL);
 	ret = callback(mbox, path, context);
 	return ret;
 }
@@ -169,11 +169,10 @@
 	}
 }
 
-static int maildir_create_subdirs(struct maildir_mailbox *mbox)
+static int maildir_create_subdirs(struct mailbox *box)
 {
 	static const char *subdirs[] = { "cur", "new", "tmp" };
 	const char *dirs[N_ELEMENTS(subdirs) + 2];
-	struct mailbox *box = &mbox->ibox.box;
 	struct stat st;
 	const char *path;
 	unsigned int i;
@@ -181,7 +180,7 @@
 
 	/* @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] = t_strconcat(box->path, "/", subdirs[i], NULL);
 	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,
@@ -204,25 +203,24 @@
 	return i == N_ELEMENTS(dirs) ? 0 : -1;
 }
 
-bool maildir_set_deleted(struct maildir_mailbox *mbox)
+bool maildir_set_deleted(struct mailbox *box)
 {
-	struct mailbox *box = &mbox->ibox.box;
 	struct stat st;
 	int ret;
 
-	if (stat(mbox->path, &st) < 0) {
+	if (stat(box->path, &st) < 0) {
 		if (errno == ENOENT)
 			mailbox_set_deleted(box);
 		else {
 			mail_storage_set_critical(box->storage,
-				"stat(%s) failed: %m", mbox->path);
+				"stat(%s) failed: %m", box->path);
 		}
 		return FALSE;
 	}
 	/* maildir itself exists. create all of its subdirectories in case
 	   they got lost. */
 	T_BEGIN {
-		ret = maildir_create_subdirs(mbox);
+		ret = maildir_create_subdirs(box);
 	} T_END;
 	return ret < 0 ? FALSE : TRUE;
 }
--- a/src/lib-storage/index/mbox/mbox-file.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-file.c	Mon Jun 15 14:28:55 2009 -0400
@@ -23,10 +23,11 @@
 		return 0;
 	}
 
-	fd = open(mbox->path, mbox->ibox.backend_readonly ? O_RDONLY : O_RDWR);
+	fd = open(mbox->ibox.box.path,
+		  mbox->ibox.backend_readonly ? O_RDONLY : O_RDWR);
 	if (fd == -1 && errno == EACCES && !mbox->ibox.backend_readonly) {
                 mbox->ibox.backend_readonly = TRUE;
-		fd = open(mbox->path, O_RDONLY);
+		fd = open(mbox->ibox.box.path, O_RDONLY);
 	}
 
 	if (fd == -1) {
@@ -83,7 +84,7 @@
 	}
 
 	mbox->mbox_stream = i_stream_create_raw_mbox(mbox->mbox_file_stream,
-						     mbox->path);
+						     mbox->ibox.box.path);
 	if (mbox->mbox_lock_type != F_UNLCK)
 		istream_raw_mbox_set_locked(mbox->mbox_stream);
 	return 0;
@@ -106,7 +107,7 @@
 		if (st.st_atime >= st.st_mtime) {
 			buf.modtime = st.st_mtime;
 			buf.actime = buf.modtime - 1;
-			if (utime(mbox->path, &buf) < 0) {
+			if (utime(mbox->ibox.box.path, &buf) < 0) {
 				mbox_set_syscall_error(mbox, "utimes()");
 				return;
 			}
@@ -146,7 +147,7 @@
 	if (data == NULL) {
 		mail_storage_set_critical(&mbox->storage->storage,
 			"Cached message offset lost for seq %u in mbox file %s",
-			seq, mbox->path);
+			seq, mbox->ibox.box.path);
                 mbox->mbox_hdr.dirty_flag = TRUE;
                 mbox->mbox_broken_offsets = TRUE;
 		return 0;
@@ -183,7 +184,7 @@
 
 		mail_storage_set_critical(&mbox->storage->storage,
 			"Cached message offset %s is invalid for mbox file %s",
-			dec2str(offset), mbox->path);
+			dec2str(offset), mbox->ibox.box.path);
 		mbox->mbox_hdr.dirty_flag = TRUE;
 		mbox->mbox_broken_offsets = TRUE;
 		return 0;
--- a/src/lib-storage/index/mbox/mbox-lock.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Mon Jun 15 14:28:55 2009 -0400
@@ -174,7 +174,7 @@
 		   be sure that the file is latest, but mbox files get rarely
 		   deleted and the flushing might cause errors (e.g. EBUSY for
 		   trying to flush a /var/mail mountpoint) */
-		if (nfs_safe_stat(mbox->path, &st) < 0) {
+		if (nfs_safe_stat(mbox->ibox.box.path, &st) < 0) {
 			if (errno == ENOENT)
 				mailbox_set_deleted(&mbox->ibox.box);
 			else
@@ -268,12 +268,12 @@
 	      privileged group
 	    - DoS other users by dotlocking their mailboxes infinitely
 	*/
-	fname = strrchr(mbox->path, '/');
+	fname = strrchr(mbox->ibox.box.path, '/');
 	if (fname == NULL) {
 		/* already relative */
-		fname = mbox->path;
+		fname = mbox->ibox.box.path;
 	} else {
-		dir = t_strdup_until(mbox->path, fname);
+		dir = t_strdup_until(mbox->ibox.box.path, fname);
 		if (chdir(dir) < 0) {
 			mail_storage_set_critical(&mbox->storage->storage,
 				"chdir(%s) failed: %m", dir);
@@ -285,7 +285,7 @@
 	if (op == MBOX_DOTLOCK_OP_LOCK) {
 		if (access(fname, R_OK) < 0) {
 			mail_storage_set_critical(&mbox->storage->storage,
-				"access(%s) failed: %m", mbox->path);
+				"access(%s) failed: %m", mbox->ibox.box.path);
 			return -1;
 		}
 	}
@@ -410,7 +410,8 @@
 	set.callback = dotlock_callback;
 	set.context = ctx;
 
-	ret = file_dotlock_create(&set, mbox->path, 0, &mbox->mbox_dotlock);
+	ret = file_dotlock_create(&set, mbox->ibox.box.path, 0,
+				  &mbox->mbox_dotlock);
 	if (ret >= 0) {
 		/* success / timeout */
 	} else if (errno == EACCES && restrict_access_have_priv_gid() &&
@@ -419,7 +420,7 @@
 		ret = mbox_dotlock_privileged_op(mbox, &set,
 						 MBOX_DOTLOCK_OP_LOCK);
 	} else if (errno == EACCES)
-		mbox_dotlock_log_eacces_error(mbox, mbox->path);
+		mbox_dotlock_log_eacces_error(mbox, mbox->ibox.box.path);
 	else
 		mbox_set_syscall_error(mbox, "file_dotlock_create()");
 
@@ -631,7 +632,7 @@
 			mail_storage_set_critical(&ctx->mbox->storage->storage,
 				"fcntl() failed with mbox file %s: "
 				"File is locked by another process (EACCES)",
-				ctx->mbox->path);
+				ctx->mbox->ibox.box.path);
 			return -1;
 		}
 
@@ -766,6 +767,8 @@
 int mbox_lock(struct mbox_mailbox *mbox, int lock_type,
 	      unsigned int *lock_id_r)
 {
+	const char *path = mbox->ibox.box.path;
+	int mbox_fd = mbox->mbox_fd;
 	bool fcntl_locked;
 	int ret;
 
@@ -783,14 +786,11 @@
 
 		if (mbox->storage->storage.set->mail_nfs_storage) {
 			if (fcntl_locked) {
-				nfs_flush_attr_cache_fd_locked(mbox->path,
-							       mbox->mbox_fd);
-				nfs_flush_read_cache_locked(mbox->path,
-							    mbox->mbox_fd);
+				nfs_flush_attr_cache_fd_locked(path, mbox_fd);
+				nfs_flush_read_cache_locked(path, mbox_fd);
 			} else {
-				nfs_flush_attr_cache_unlocked(mbox->path);
-				nfs_flush_read_cache_unlocked(mbox->path,
-							      mbox->mbox_fd);
+				nfs_flush_attr_cache_unlocked(path);
+				nfs_flush_read_cache_unlocked(path, mbox_fd);
 			}
 		}
 
--- a/src/lib-storage/index/mbox/mbox-mail.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Mon Jun 15 14:28:55 2009 -0400
@@ -100,7 +100,7 @@
 	if (ret == 0) {
 		mail_storage_set_critical(&mbox->storage->storage,
 			"Losing sync for mail uid=%u in mbox file %s",
-			mail->mail.mail.uid, mbox->path);
+			mail->mail.mail.uid, mbox->ibox.box.path);
 	}
 	return 0;
 }
@@ -284,7 +284,7 @@
 		if (ret < 0) {
 			i_warning("mbox %s: Can't find next message offset "
 				  "for uid=%u",
-				  mbox->path, mail->mail.mail.uid);
+				  mbox->ibox.box.path, mail->mail.mail.uid);
 		}
 	}
 	if (ret <= 0)
--- a/src/lib-storage/index/mbox/mbox-save.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-save.c	Mon Jun 15 14:28:55 2009 -0400
@@ -734,7 +734,7 @@
 
 		buf.modtime = st.st_mtime;
 		buf.actime = ctx->orig_atime;
-		if (utime(mbox->path, &buf) < 0)
+		if (utime(mbox->ibox.box.path, &buf) < 0)
 			mbox_set_syscall_error(mbox, "utime()");
 	}
 
--- a/src/lib-storage/index/mbox/mbox-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -83,7 +83,7 @@
 	} else {
 		mail_storage_set_critical(&mbox->storage->storage,
 					  "%s failed with mbox file %s: %m",
-					  function, mbox->path);
+					  function, mbox->ibox.box.path);
 	}
 	return -1;
 }
@@ -313,6 +313,57 @@
 	return TRUE;
 }
 
+static bool want_memory_indexes(struct mbox_storage *storage, const char *path)
+{
+	struct stat st;
+
+	if (storage->set->mbox_min_index_size == 0)
+		return FALSE;
+
+	if (stat(path, &st) < 0) {
+		if (errno == ENOENT)
+			st.st_size = 0;
+		else {
+			mail_storage_set_critical(&storage->storage,
+						  "stat(%s) failed: %m", path);
+			return FALSE;
+		}
+	}
+	return st.st_size / 1024 < storage->set->mbox_min_index_size;
+}
+
+static struct mailbox *
+mbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		   const char *name, struct istream *input,
+		   enum mailbox_flags flags)
+{
+	struct mbox_mailbox *mbox;
+	pool_t pool;
+
+	pool = pool_alloconly_create("mbox mailbox", 1024+512);
+	mbox = p_new(pool, struct mbox_mailbox, 1);
+	mbox->ibox.box = mbox_mailbox;
+	mbox->ibox.box.pool = pool;
+	mbox->ibox.box.storage = storage;
+	mbox->ibox.box.list = list;
+	mbox->ibox.mail_vfuncs = &mbox_mail_vfuncs;
+
+	index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+				    MBOX_INDEX_PREFIX);
+
+	mbox->storage = (struct mbox_storage *)storage;
+	mbox->mbox_fd = -1;
+	mbox->mbox_lock_type = F_UNLCK;
+	mbox->mbox_ext_idx =
+		mail_index_ext_register(mbox->ibox.index, "mbox",
+					sizeof(mbox->mbox_hdr),
+					sizeof(uint64_t), sizeof(uint64_t));
+
+	if ((storage->flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0)
+		mbox->mbox_save_md5 = TRUE;
+	return &mbox->ibox.box;
+}
+
 static int verify_inbox(struct mailbox_list *list)
 {
 	const char *inbox_path, *rootdir;
@@ -353,101 +404,37 @@
 	return 0;
 }
 
-static bool want_memory_indexes(struct mbox_storage *storage, const char *path)
-{
-	struct stat st;
-
-	if (storage->set->mbox_min_index_size == 0)
-		return FALSE;
-
-	if (stat(path, &st) < 0) {
-		if (errno == ENOENT)
-			st.st_size = 0;
-		else {
-			mail_storage_set_critical(&storage->storage,
-						  "stat(%s) failed: %m", path);
-			return FALSE;
-		}
-	}
-	return st.st_size / 1024 < storage->set->mbox_min_index_size;
-}
-
 static void mbox_lock_touch_timeout(struct mbox_mailbox *mbox)
 {
 	mbox_dotlock_touch(mbox);
 }
 
-static struct mbox_mailbox *
-mbox_alloc_mailbox(struct mbox_storage *storage, struct mail_index *index,
-		   const char *name, const char *path,
-		   enum mailbox_open_flags flags)
+static int mbox_mailbox_open_existing(struct mbox_mailbox *mbox)
 {
-	struct mbox_mailbox *mbox;
-	pool_t pool;
-
-	pool = pool_alloconly_create("mbox mailbox", 1024+512);
-	mbox = p_new(pool, struct mbox_mailbox, 1);
-	mbox->ibox.box = mbox_mailbox;
-	mbox->ibox.box.pool = pool;
-	mbox->ibox.box.storage = &storage->storage;
-	mbox->ibox.mail_vfuncs = &mbox_mail_vfuncs;
-	mbox->ibox.index = index;
-
-	mbox->storage = storage;
-	mbox->path = p_strdup(mbox->ibox.box.pool, path);
-	mbox->mbox_fd = -1;
-	mbox->mbox_lock_type = F_UNLCK;
-	mbox->mbox_ext_idx =
-		mail_index_ext_register(index, "mbox",
-					sizeof(mbox->mbox_hdr),
-					sizeof(uint64_t), sizeof(uint64_t));
-
-	if ((storage->storage.flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0)
-		mbox->mbox_save_md5 = TRUE;
+	struct mailbox *box = &mbox->ibox.box;
+	const char *rootdir;
 
-	index_storage_mailbox_init(&mbox->ibox, name, flags,
-				   want_memory_indexes(storage, path));
-	return mbox;
-}
-
-static struct mailbox *
-mbox_open(struct mbox_storage *storage, struct mailbox_list *list,
-	  const char *name, enum mailbox_open_flags flags)
-{
-	struct mbox_mailbox *mbox;
-	struct mail_index *index;
-	const char *path, *rootdir;
+	if (access(box->path, R_OK|W_OK) < 0) {
+		if (errno != EACCES) {
+			mbox_set_syscall_error(mbox, "access()");
+			return -1;
+		}
+		mbox->ibox.backend_readonly = TRUE;
+	}
+	mbox->ibox.move_to_memory =
+		want_memory_indexes(mbox->storage, box->path);
 
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
-	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) {
-		if (errno < EACCES)
-			mbox_set_syscall_error(mbox, "access()");
-		else
-			mbox->ibox.backend_readonly = TRUE;
-	}
-
-	if (strcmp(name, "INBOX") == 0) {
+	if (strcmp(box->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(list, NULL,
+		rootdir = mailbox_list_get_path(box->list, NULL,
 						MAILBOX_LIST_PATH_TYPE_DIR);
-		if (strncmp(path, rootdir, strlen(rootdir)) != 0)
+		if (strncmp(box->path, rootdir, strlen(rootdir)) != 0)
 			mbox->mbox_privileged_locking = TRUE;
 	}
-	if ((flags & MAILBOX_OPEN_KEEP_LOCKED) != 0) {
-		if (mbox_lock(mbox, F_WRLCK, &mbox->mbox_global_lock_id) <= 0) {
-			struct mailbox *box = &mbox->ibox.box;
-
-			mailbox_close(&box);
-			mailbox_list_set_error_from_storage(list,
-							    &storage->storage);
-			return NULL;
-		}
+	if ((box->flags & MAILBOX_FLAG_KEEP_LOCKED) != 0) {
+		if (mbox_lock(mbox, F_WRLCK, &mbox->mbox_global_lock_id) <= 0)
+			return -1;
 
 		if (mbox->mbox_dotlock != NULL) {
 			mbox->keep_lock_to =
@@ -455,77 +442,48 @@
 					    mbox_lock_touch_timeout, mbox);
 		}
 	}
-	return &mbox->ibox.box;
-}
-
-static struct mailbox *
-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_index *index;
-	struct mbox_mailbox *mbox;
-	const char *path;
-
-	flags |= MAILBOX_OPEN_READONLY;
-
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	index = index_storage_alloc(list, name, flags, MBOX_INDEX_PREFIX);
-	mbox = mbox_alloc_mailbox(storage, index, name, path, flags);
-
-	i_stream_ref(input);
-	mbox->mbox_file_stream = input;
-	mbox->ibox.backend_readonly = TRUE;
-	mbox->no_mbox_file = TRUE;
-
-	mbox->path = "(read-only mbox stream)";
-	return &mbox->ibox.box;
+	return index_storage_mailbox_open(box);
 }
 
-static struct mailbox *
-mbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
-		  const char *name, struct istream *input,
-		  enum mailbox_open_flags flags)
+static int mbox_mailbox_open(struct mailbox *box)
 {
-	struct mbox_storage *storage = (struct mbox_storage *)_storage;
-	const char *path;
+	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
 	struct stat st;
+	int ret;
 
-	if (input != NULL) {
-		return mbox_mailbox_open_stream(storage, list, name,
-						input, flags);
-	}
-
-	if (strcmp(name, "INBOX") == 0 &&
-	    (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
-		/* make sure INBOX exists */
-		if (verify_inbox(list) < 0)
-			return NULL;
-		return mbox_open(storage, list, "INBOX", flags);
+	if (box->input != NULL) {
+		mbox->mbox_file_stream = box->input;
+		mbox->ibox.backend_readonly = TRUE;
+		mbox->no_mbox_file = TRUE;
+		return 0;
 	}
 
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(path, &st) == 0) {
-		if (S_ISDIR(st.st_mode)) {
-			mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
-				t_strdup_printf("Mailbox isn't selectable: %s",
-						name));
-			return NULL;
-		}
-
-		return mbox_open(storage, list, name, flags);
+	if (strcmp(box->name, "INBOX") == 0 &&
+	    (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+		/* make sure INBOX exists */
+		if (verify_inbox(box->list) < 0)
+			return -1;
+		return mbox_mailbox_open_existing(mbox);
 	}
 
-	if (ENOTFOUND(errno)) {
-		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-	} else if (!mailbox_list_set_error_from_errno(list)) {
-		mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
+	if ((ret = stat(box->path, &st)) == 0 && !S_ISDIR(st.st_mode))
+		return mbox_mailbox_open_existing(mbox);
+	else if (ret == 0) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+			t_strdup_printf("Mailbox isn't selectable: %s",
+					box->name));
+		return -1;
+	} else if (ENOTFOUND(errno)) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+		return -1;
+	} else if (mail_storage_set_error_from_errno(box->storage)) {
+		return -1;
+	} else {
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", box->path);
+		return -1;
 	}
-
-	return NULL;
 }
 
 static int
@@ -596,12 +554,11 @@
 	return -1;
 }
 
-static int mbox_storage_mailbox_close(struct mailbox *box)
+static void mbox_mailbox_close(struct mailbox *box)
 {
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
 	const struct mail_index_header *hdr;
 	enum mbox_sync_flags sync_flags = 0;
-	int ret = 0;
 
 	if (mbox->mbox_stream != NULL &&
 	    istream_raw_mbox_is_corrupted(mbox->mbox_stream)) {
@@ -618,10 +575,8 @@
 			sync_flags |= MBOX_SYNC_REWRITE;
 		}
 	}
-	if (sync_flags != 0 && !mbox->invalid_mbox_file) {
-		if (mbox_sync(mbox, sync_flags) < 0)
-			ret = -1;
-	}
+	if (sync_flags != 0 && !mbox->invalid_mbox_file)
+		(void)mbox_sync(mbox, sync_flags);
 
 	if (mbox->mbox_global_lock_id != 0)
 		(void)mbox_unlock(mbox, mbox->mbox_global_lock_id);
@@ -632,7 +587,7 @@
 	if (mbox->mbox_file_stream != NULL)
 		i_stream_destroy(&mbox->mbox_file_stream);
 
-	return index_storage_mailbox_close(box) < 0 ? -1 : ret;
+	index_storage_mailbox_close(box);
 }
 
 static void mbox_notify_changes(struct mailbox *box)
@@ -642,7 +597,7 @@
 	if (box->notify_callback == NULL)
 		index_mailbox_check_remove_all(&mbox->ibox);
 	else if (!mbox->no_mbox_file)
-		index_mailbox_check_add(&mbox->ibox, mbox->path);
+		index_mailbox_check_add(&mbox->ibox, mbox->ibox.box.path);
 }
 
 static bool
@@ -873,7 +828,7 @@
 		mbox_storage_add_list,
 		mbox_storage_get_list_settings,
 		mbox_storage_autodetect,
-		mbox_mailbox_open,
+		mbox_mailbox_alloc,
 		mbox_mailbox_create,
 		NULL
 	}
@@ -888,7 +843,8 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
-		mbox_storage_mailbox_close,
+		mbox_mailbox_open,
+		mbox_mailbox_close,
 		index_storage_get_status,
 		NULL,
 		NULL,
--- a/src/lib-storage/index/mbox/mbox-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -34,8 +34,6 @@
 	struct index_mailbox ibox;
 	struct mbox_storage *storage;
 
-	const char *path;
-
 	int mbox_fd;
 	struct istream *mbox_stream, *mbox_file_stream;
 	int mbox_lock_type;
--- a/src/lib-storage/index/mbox/mbox-sync-rewrite.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-sync-rewrite.c	Mon Jun 15 14:28:55 2009 -0400
@@ -44,8 +44,8 @@
 	else if (ret >= 0) {
 		mbox_sync_set_critical(sync_ctx,
 			"mbox_move(%"PRIuUOFF_T", %"PRIuUOFF_T", %"PRIuUOFF_T
-			") moved only %"PRIuUOFF_T" bytes in mbox file %s",
-			dest, source, size, (uoff_t)ret, sync_ctx->mbox->path);
+			") moved only %"PRIuUOFF_T" bytes",
+			dest, source, size, (uoff_t)ret);
 		ret = -1;
 	} else if (ret < 0) {
 		errno = output->stream_errno;
@@ -416,11 +416,10 @@
 			mbox_sync_file_update_ext_modified(sync_ctx);
 
 			mbox_sync_set_critical(sync_ctx,
-				"mbox %s: seq=%u uid=%u uid_broken=%d "
+				"seq=%u uid=%u uid_broken=%d "
 				"originally needed %"PRIuUOFF_T
 				" bytes, now needs %"PRIuSIZE_T" bytes",
-				sync_ctx->mbox->path, seq, mails[idx].uid,
-				mails[idx].uid_broken,
+				seq, mails[idx].uid, mails[idx].uid_broken,
 				(uoff_t)-mails[idx].space, need_space);
 		}
 	}
--- a/src/lib-storage/index/mbox/mbox-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -72,12 +72,15 @@
 	if (sync_ctx->ext_modified) {
 		mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
 			"mbox file %s was modified while we were syncing, "
-			"check your locking settings", sync_ctx->mbox->path);
+			"check your locking settings",
+			sync_ctx->mbox->ibox.box.path);
 	}
 
 	va_start(va, fmt);
 	mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
-				  "%s", t_strdup_vprintf(fmt, va));
+				  "Sync failed for mbox file %s: %s",
+				  sync_ctx->mbox->ibox.box.path,
+				  t_strdup_vprintf(fmt, va));
 	va_end(va);
 }
 
@@ -85,9 +88,8 @@
 {
 	if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
 		mbox_sync_set_critical(sync_ctx,
-			"Unexpectedly lost From-line at offset %"PRIuUOFF_T
-			" from mbox file %s", from_offset,
-			sync_ctx->mbox->path);
+			"Unexpectedly lost From-line at offset %"PRIuUOFF_T,
+			from_offset);
 		return -1;
 	}
 	return 0;
@@ -208,16 +210,16 @@
 	if (rec == NULL && uid < sync_ctx->idx_next_uid) {
 		/* this UID was already in index and it was expunged */
 		mbox_sync_set_critical(sync_ctx,
-			"mbox sync: Expunged message reappeared in mailbox %s "
+			"Expunged message reappeared to mailbox "
 			"(UID %u < %u, seq=%u, idx_msgs=%u)",
-			sync_ctx->mbox->path, uid, sync_ctx->idx_next_uid,
+			uid, sync_ctx->idx_next_uid,
 			sync_ctx->seq, messages_count);
 		ret = FALSE; rec = NULL;
 	} else if (rec != NULL && rec->uid != uid) {
 		/* new UID in the middle of the mailbox - shouldn't happen */
 		mbox_sync_set_critical(sync_ctx,
-			"mbox sync: UID inserted in the middle of mailbox %s "
-			"(%u > %u, seq=%u, idx_msgs=%u)", sync_ctx->mbox->path,
+			"UID inserted in the middle of mailbox "
+			"(%u > %u, seq=%u, idx_msgs=%u)",
 			rec->uid, uid, sync_ctx->seq, messages_count);
 		ret = FALSE; rec = NULL;
 	} else {
@@ -516,8 +518,7 @@
 	}
 	if (ret == 0) {
 		mbox_sync_set_critical(sync_ctx,
-			"X-IMAPbase uid-last unexpectedly points outside "
-			"mbox file %s", sync_ctx->mbox->path);
+			"X-IMAPbase uid-last offset unexpectedly outside mbox");
 		return -1;
 	}
 
@@ -531,8 +532,7 @@
 
 	if (uid_last != sync_ctx->base_uid_last) {
 		mbox_sync_set_critical(sync_ctx,
-			"X-IMAPbase uid-last unexpectedly lost in mbox file %s",
-			sync_ctx->mbox->path);
+			"X-IMAPbase uid-last unexpectedly lost");
 		return -1;
 	}
 
@@ -822,8 +822,7 @@
 		if (ret < 0) {
 			if (deleted) {
 				mbox_sync_set_critical(sync_ctx,
-					"Message was expunged unexpectedly "
-					"in mbox file %s", mbox->path);
+					"Message was expunged unexpectedly");
 			}
 			return -1;
 		}
@@ -832,8 +831,7 @@
 						  old_offset) < 0) {
 				mbox_sync_set_critical(sync_ctx,
 					"Error seeking back to original "
-					"offset %s in mbox file %s",
-					dec2str(old_offset), mbox->path);
+					"offset %s", dec2str(old_offset));
 				return -1;
 			}
 			return 0;
@@ -885,8 +883,7 @@
 		if (istream_raw_mbox_seek(sync_ctx->mbox->mbox_stream,
 					  size) < 0) {
 			mbox_sync_set_critical(sync_ctx,
-				"Error seeking to end of mbox file %s",
-				sync_ctx->mbox->path);
+				"Error seeking to end of mbox");
 			return -1;
 		}
 		sync_ctx->idx_seq =
@@ -968,7 +965,7 @@
 		i_warning("UIDVALIDITY changed (%u -> %u) in mbox file %s",
 			  sync_ctx->hdr->uid_validity,
 			  sync_ctx->base_uid_validity,
-			  sync_ctx->mbox->path);
+			  sync_ctx->mbox->ibox.box.path);
 		sync_ctx->index_reset = TRUE;
 		return TRUE;
 	}
@@ -1020,8 +1017,7 @@
 				return 0;
 
 			mbox_sync_set_critical(sync_ctx,
-				"UIDs broken with partial sync in mbox file %s",
-				sync_ctx->mbox->path);
+				"UIDs broken with partial sync");
 
 			sync_ctx->mbox->mbox_hdr.dirty_flag = TRUE;
 			return 0;
@@ -1089,7 +1085,8 @@
 				mail_storage_set_critical(
 					&sync_ctx->mbox->storage->storage,
 					"Out of UIDs, renumbering them in mbox "
-					"file %s", sync_ctx->mbox->path);
+					"file %s",
+					sync_ctx->mbox->ibox.box.path);
 				sync_ctx->renumber_uids = TRUE;
 				return 0;
 			}
@@ -1241,9 +1238,8 @@
 
 	if (file_size < sync_ctx->file_input->v_offset) {
 		mbox_sync_set_critical(sync_ctx,
-			"file size unexpectedly shrank in mbox file %s "
-			"(%"PRIuUOFF_T" vs %"PRIuUOFF_T")",
-			sync_ctx->mbox->path, file_size,
+			"file size unexpectedly shrank "
+			"(%"PRIuUOFF_T" vs %"PRIuUOFF_T")", file_size,
 			sync_ctx->file_input->v_offset);
 		return -1;
 	}
@@ -1382,7 +1378,7 @@
 		   quite minimal (an extra logged error message). */
 		while (sync_ctx->orig_mtime == st->st_mtime) {
 			usleep(500000);
-			if (utime(sync_ctx->mbox->path, NULL) < 0) {
+			if (utime(sync_ctx->mbox->ibox.box.path, NULL) < 0) {
 				mbox_set_syscall_error(sync_ctx->mbox,
 						       "utime()");
 				return -1;
@@ -1630,7 +1626,7 @@
 			return -1;
 		}
 	} else {
-		if (stat(mbox->path, &statbuf) < 0) {
+		if (stat(mbox->ibox.box.path, &statbuf) < 0) {
 			if (errno == ENOENT) {
 				mailbox_set_deleted(&mbox->ibox.box);
 				return 0;
@@ -1866,7 +1862,7 @@
 		else {
 			buf.modtime = st.st_mtime;
 			buf.actime = sync_ctx.orig_atime;
-			if (utime(mbox->path, &buf) < 0)
+			if (utime(mbox->ibox.box.path, &buf) < 0)
 				mbox_set_syscall_error(mbox, "utime()");
 		}
 	}
@@ -1926,10 +1922,12 @@
 	enum mbox_sync_flags mbox_sync_flags = 0;
 	int ret = 0;
 
-	if (!box->opened)
-		index_storage_mailbox_open(&mbox->ibox);
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			ret = -1;
+	}
 
-	if (index_mailbox_want_full_sync(&mbox->ibox, flags)) {
+	if (index_mailbox_want_full_sync(&mbox->ibox, flags) && ret == 0) {
 		if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
 		    !mbox->storage->set->mbox_very_dirty_syncs)
 			mbox_sync_flags |= MBOX_SYNC_UNDIRTY;
--- a/src/lib-storage/index/raw/raw-mail.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/raw/raw-mail.c	Mon Jun 15 14:28:55 2009 -0400
@@ -19,10 +19,10 @@
 		return mail_set_aborted(mail);
 
 	p->stats_fstat_lookup_count++;
-	st = i_stream_stat(mbox->input, TRUE);
+	st = i_stream_stat(mail->box->input, TRUE);
 	if (st == NULL) {
 		mail_storage_set_critical(mail->box->storage,
-					  "stat(%s) failed: %m", mbox->path);
+			"stat(%s) failed: %m", mail->box->path);
 		return -1;
 	}
 
@@ -81,13 +81,12 @@
 		    struct message_size *body_size, struct istream **stream_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
-	struct raw_mailbox *mbox = (struct raw_mailbox *)_mail->box;
 
 	if (mail->data.stream == NULL) {
 		/* we can't just reference mbox->input, because
 		   index_mail_close() expects to be able to free the stream */
 		mail->data.stream =
-			i_stream_create_limit(mbox->input, (uoff_t)-1);
+			i_stream_create_limit(_mail->box->input, (uoff_t)-1);
 	}
 
 	return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
@@ -104,7 +103,7 @@
 		*value_r = mbox->envelope_sender;
 		return 0;
 	case MAIL_FETCH_UIDL_FILE_NAME:
-		*value_r = mbox->have_filename ? mbox->path : "";
+		*value_r = mbox->have_filename ? _mail->box->path : "";
 		return 0;
 	default:
 		return index_mail_get_special(_mail, field, value_r);
--- a/src/lib-storage/index/raw/raw-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/raw/raw-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -9,10 +9,6 @@
 #include "raw-sync.h"
 #include "raw-storage.h"
 
-struct raw_mailbox_list {
-	union mailbox_list_module_context module_ctx;
-};
-
 extern struct mail_storage raw_storage;
 extern struct mailbox raw_mailbox;
 
@@ -38,78 +34,59 @@
 		set->subscription_fname = RAW_SUBSCRIPTION_FILE_NAME;
 }
 
-static int
-raw_mailbox_open_input(struct mailbox_list *list, const char *name,
-		       const char *path, struct istream **input_r)
-{
-	int fd;
-
-	fd = open(path, O_RDONLY);
-	if (fd == -1) {
-		if (ENOTFOUND(errno)) {
-			mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-		} else if (!mailbox_list_set_error_from_errno(list)) {
-			mailbox_list_set_critical(list, "open(%s) failed: %m",
-						  path);
-		}
-		return -1;
-	}
-	*input_r = i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
-	return 0;
-}
-
 static struct mailbox *
-raw_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		 const char *name, struct istream *input,
-		 enum mailbox_open_flags flags)
+raw_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		  const char *name, struct istream *input,
+		  enum mailbox_flags flags)
 {
 	struct raw_mailbox *mbox;
-	const char *path;
 	pool_t pool;
-	bool stream = input != NULL;
-
-	flags |= MAILBOX_OPEN_READONLY | MAILBOX_OPEN_NO_INDEX_FILES;
 
-	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(list, name, path, &input) < 0)
-			return NULL;
-	}
+	flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_NO_INDEX_FILES;
 
 	pool = pool_alloconly_create("raw mailbox", 1024+512);
 	mbox = p_new(pool, struct raw_mailbox, 1);
 	mbox->ibox.box = raw_mailbox;
 	mbox->ibox.box.pool = pool;
 	mbox->ibox.box.storage = storage;
+	mbox->ibox.box.list = list;
 	mbox->ibox.mail_vfuncs = &raw_mail_vfuncs;
-	mbox->ibox.index = index_storage_alloc(list, name, flags, NULL);
+
+	index_storage_mailbox_alloc(&mbox->ibox, name, input, flags, NULL);
 
 	mbox->storage = (struct raw_storage *)storage;
-	mbox->path = p_strdup(pool, path);
-	mbox->input = input;
 
-	if (stream)
+	if (input != NULL)
 		mbox->mtime = mbox->ctime = ioloop_time;
 	else {
 		mbox->mtime = mbox->ctime = (time_t)-1;
 		mbox->have_filename = TRUE;
 	}
 	mbox->size = (uoff_t)-1;
-
-	index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
 	return &mbox->ibox.box;
 }
 
-static int raw_mailbox_close(struct mailbox *box)
+static int raw_mailbox_open(struct mailbox *box)
 {
-	struct raw_mailbox *mbox = (struct raw_mailbox *)box;
+	int fd;
+
+	if (box->input != NULL)
+		return index_storage_mailbox_open(box);
 
-	i_stream_unref(&mbox->input);
-	return index_storage_mailbox_close(box);
+	fd = open(box->path, O_RDONLY);
+	if (fd == -1) {
+		if (ENOTFOUND(errno)) {
+			mail_storage_set_error(box->storage,
+				MAIL_ERROR_NOTFOUND,
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+		} else if (!mail_storage_set_error_from_errno(box->storage)) {
+			mail_storage_set_critical(box->storage,
+				"open(%s) failed: %m", box->path);
+		}
+		return -1;
+	}
+	box->input = i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
+	return index_storage_mailbox_open(box);
 }
 
 static int
@@ -207,7 +184,7 @@
 		raw_storage_add_list,
 		raw_storage_get_list_settings,
 		NULL,
-		raw_mailbox_open,
+		raw_mailbox_alloc,
 		raw_mailbox_create,
 		NULL
 	}
@@ -222,7 +199,8 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
-		raw_mailbox_close,
+		raw_mailbox_open,
+		index_storage_mailbox_close,
 		index_storage_get_status,
 		NULL,
 		NULL,
--- a/src/lib-storage/index/raw/raw-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/raw/raw-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -16,9 +16,6 @@
 	struct index_mailbox ibox;
 	struct raw_storage *storage;
 
-	const char *path;
-	struct istream *input;
-
 	time_t mtime, ctime;
 	uoff_t size;
 	const char *envelope_sender;
--- a/src/lib-storage/index/raw/raw-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/index/raw/raw-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -52,10 +52,12 @@
 	struct raw_mailbox *mbox = (struct raw_mailbox *)box;
 	int ret = 0;
 
-	if (!box->opened)
-		index_storage_mailbox_open(&mbox->ibox);
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			ret = -1;
+	}
 
-	if (!mbox->synced)
+	if (!mbox->synced && ret == 0)
 		ret = raw_sync(mbox);
 
 	return index_mailbox_sync_init(box, flags, ret < 0);
--- a/src/lib-storage/list/index-mailbox-list-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/list/index-mailbox-list-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -47,11 +47,11 @@
 static MODULE_CONTEXT_DEFINE_INIT(index_list_storage_module,
 				  &mail_storage_module_register);
 
-static int index_list_box_close(struct mailbox *box)
+static void index_list_box_close(struct mailbox *box)
 {
 	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
 
-	return ibox->module_ctx.super.close(box);
+	ibox->module_ctx.super.close(box);
 }
 
 static int index_list_update_mail_index(struct index_mailbox_list *ilist,
@@ -352,7 +352,7 @@
 	return 0;
 }
 
-static void index_list_mail_mailbox_opened(struct mailbox *box)
+static void index_list_mail_mailbox_allocated(struct mailbox *box)
 {
 	struct index_mailbox_list *ilist =
 		INDEX_LIST_CONTEXT(box->list);
@@ -391,6 +391,6 @@
 
 void index_mailbox_list_sync_init(void)
 {
-	index_list_next_hook_mailbox_created = hook_mailbox_opened;
-	hook_mailbox_opened = index_list_mail_mailbox_opened;
+	index_list_next_hook_mailbox_created = hook_mailbox_allocated;
+	hook_mailbox_allocated = index_list_mail_mailbox_allocated;
 }
--- a/src/lib-storage/mail-storage-private.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/mail-storage-private.h	Mon Jun 15 14:28:55 2009 -0400
@@ -12,8 +12,8 @@
 
 /* Called after mail storage has been created */
 extern void (*hook_mail_storage_created)(struct mail_storage *storage);
-/* Called after mailbox has been opened */
-extern void (*hook_mailbox_opened)(struct mailbox *box);
+/* Called after mailbox has been allocated */
+extern void (*hook_mailbox_allocated)(struct mailbox *box);
 /* Called after mailbox index has been opened */
 extern void (*hook_mailbox_index_opened)(struct mailbox *box);
 
@@ -43,11 +43,11 @@
 	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);
+	struct mailbox *(*mailbox_alloc)(struct mail_storage *storage,
+					 struct mailbox_list *list,
+					 const char *name,
+					 struct istream *input,
+					 enum mailbox_flags flags);
 
 	int (*mailbox_create)(struct mail_storage *storage,
 			      struct mailbox_list *list, const char *name,
@@ -101,7 +101,8 @@
 	bool (*allow_new_keywords)(struct mailbox *box);
 
 	int (*enable)(struct mailbox *box, enum mailbox_feature features);
-	int (*close)(struct mailbox *box);
+	int (*open)(struct mailbox *box);
+	void (*close)(struct mailbox *box);
 
 	void (*get_status)(struct mailbox *box, enum mailbox_status_items items,
 			   struct mailbox_status *status_r);
@@ -212,7 +213,7 @@
 };
 
 struct mailbox {
-	char *name;
+	const char *name;
 	struct mail_storage *storage;
 	struct mailbox_list *list;
 
@@ -220,7 +221,10 @@
 /* private: */
 	pool_t pool;
 
-	enum mailbox_open_flags open_flags;
+	/* mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX */
+	const char *path;
+	struct istream *input;
+	enum mailbox_flags flags;
 	unsigned int transaction_count;
 	enum mailbox_feature enabled_features;
 
--- a/src/lib-storage/mail-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/mail-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -24,7 +24,7 @@
 	MODULE_CONTEXT_INIT(&mail_index_module_register);
 
 void (*hook_mail_storage_created)(struct mail_storage *storage);
-void (*hook_mailbox_opened)(struct mailbox *box) = NULL;
+void (*hook_mailbox_allocated)(struct mailbox *box) = NULL;
 void (*hook_mailbox_index_opened)(struct mailbox *box) = NULL;
 
 ARRAY_TYPE(mail_storage) mail_storage_classes;
@@ -463,42 +463,49 @@
 	return TRUE;
 }
 
-struct mailbox *mailbox_open(struct mailbox_list *list, const char *name,
-			     struct istream *input,
-			     enum mailbox_open_flags flags)
+struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
+			      struct istream *input,
+			      enum mailbox_flags flags)
 {
 	struct mailbox_list *new_list = list;
 	struct mail_storage *storage;
 	struct mailbox *box;
 
-	if (mailbox_list_get_storage(&new_list, &name, &storage) < 0)
-		return NULL;
-
-	mailbox_list_clear_error(list);
-
-	if (!mailbox_list_is_valid_existing_name(new_list, name)) {
-		mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
-				       "Invalid mailbox name");
-		return NULL;
+	if (mailbox_list_get_storage(&new_list, &name, &storage) < 0) {
+		/* just use the first storage. FIXME: does this break? */
+		storage = list->ns->storage;
 	}
 
 	T_BEGIN {
-		box = storage->v.mailbox_open(storage, new_list,
-					      name, input, flags);
-		if (hook_mailbox_opened != NULL && box != NULL)
-			hook_mailbox_opened(box);
+		box = storage->v.mailbox_alloc(storage, new_list,
+					       name, input, flags);
+		if (hook_mailbox_allocated != NULL)
+			hook_mailbox_allocated(box);
+	} T_END;
+	return box;
+}
+
+int mailbox_open(struct mailbox *box)
+{
+	int ret;
+
+	mail_storage_clear_error(box->storage);
+
+	if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
+				       "Invalid mailbox name");
+		return -1;
+	}
+
+	T_BEGIN {
+		ret = box->v.open(box);
 	} T_END;
 
-	if (box != NULL)
-		box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
-	else if (new_list != list) {
-		const char *str;
-		enum mail_error error;
+	if (ret < 0)
+		return -1;
 
-		str = mailbox_list_get_last_error(new_list, &error);
-		mailbox_list_set_error(list, error, str);
-	}
-	return box;
+	box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
+	return 0;
 }
 
 int mailbox_enable(struct mailbox *box, enum mailbox_feature features)
@@ -511,7 +518,7 @@
 	return box->enabled_features;
 }
 
-int mailbox_close(struct mailbox **_box)
+void mailbox_close(struct mailbox **_box)
 {
 	struct mailbox *box = *_box;
 
@@ -521,7 +528,7 @@
 	}
 
 	*_box = NULL;
-	return box->v.close(box);
+	box->v.close(box);
 }
 
 struct mail_storage *mailbox_get_storage(const struct mailbox *box)
--- a/src/lib-storage/mail-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/mail-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -23,28 +23,25 @@
 	MAIL_STORAGE_FLAG_NO_AUTOCREATE		= 0x04
 };
 
-enum mailbox_open_flags {
+enum mailbox_flags {
 	/* Mailbox must not be modified even if asked */
-	MAILBOX_OPEN_READONLY		= 0x01,
+	MAILBOX_FLAG_READONLY		= 0x01,
 	/* Only saving/copying mails to mailbox works. */
-	MAILBOX_OPEN_SAVEONLY		= 0x02,
-	/* Delay opening index files (and possibly other files) until mailbox
-	   is being synchronized. */
-	MAILBOX_OPEN_FAST		= 0x04,
+	MAILBOX_FLAG_SAVEONLY		= 0x02,
 	/* Don't reset MAIL_RECENT flags when syncing */
-	MAILBOX_OPEN_KEEP_RECENT	= 0x08,
+	MAILBOX_FLAG_KEEP_RECENT	= 0x08,
 	/* Don't create index files for the mailbox */
-	MAILBOX_OPEN_NO_INDEX_FILES	= 0x10,
+	MAILBOX_FLAG_NO_INDEX_FILES	= 0x10,
 	/* Keep mailbox exclusively locked all the time while it's open */
-	MAILBOX_OPEN_KEEP_LOCKED	= 0x20,
+	MAILBOX_FLAG_KEEP_LOCKED	= 0x20,
 	/* Enable if mailbox is used for serving POP3. This allows making
 	   better caching decisions. */
-	MAILBOX_OPEN_POP3_SESSION	= 0x40,
+	MAILBOX_FLAG_POP3_SESSION	= 0x40,
 	/* Enable if mailbox is used for saving a mail delivery using MDA.
 	   This causes ACL plugin to use POST right rather than INSERT. */
-	MAILBOX_OPEN_POST_SESSION	= 0x80,
+	MAILBOX_FLAG_POST_SESSION	= 0x80,
 	/* Force opening mailbox and ignoring any ACLs */
-	MAILBOX_OPEN_IGNORE_ACLS	= 0x100
+	MAILBOX_FLAG_IGNORE_ACLS	= 0x100
 };
 
 enum mailbox_feature {
@@ -289,18 +286,20 @@
 /* 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.
+/* Initialize mailbox without actually opening any files or verifying that
+   it exists. If input stream is given, mailbox is opened read-only
+   using it as a backend.
 
    Note that append and copy may open the selected mailbox again
    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
-   the mailbox was closed anyway. */
-int mailbox_close(struct mailbox **box);
+struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
+			      struct istream *input,
+			      enum mailbox_flags flags);
+/* Open the mailbox. If this function isn't called explicitly, it's also called
+   internally by lib-storage when necessary. */
+int mailbox_open(struct mailbox *box);
+/* Close the box. */
+void mailbox_close(struct mailbox **box);
 
 /* Enable the given feature for the mailbox. */
 int mailbox_enable(struct mailbox *box, enum mailbox_feature features);
--- a/src/lib-storage/mailbox-list-private.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/mailbox-list-private.h	Mon Jun 15 14:28:55 2009 -0400
@@ -149,7 +149,5 @@
 	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	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/mailbox-list.c	Mon Jun 15 14:28:55 2009 -0400
@@ -321,6 +321,13 @@
 			i_info("Namespace %s: Permission lookup failed from %s",
 			       list->ns->prefix, path);
 		}
+		if (name != NULL) {
+			/* return defaults */
+			mailbox_list_get_permissions_full(list, NULL,
+							  file_mode_r,
+							  dir_mode_r, gid_r);
+			return;
+		}
 		/* return safe defaults */
 		*file_mode_r = 0600;
 		*dir_mode_r = 0700;
@@ -914,13 +921,3 @@
 	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/test-mail-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/test-mail-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -55,7 +55,7 @@
 		NULL,
 		test_storage_get_list_settings,
 		NULL,
-		test_mailbox_open,
+		test_mailbox_alloc,
 		test_mailbox_create,
 		NULL
 	}
--- a/src/lib-storage/test-mail-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/test-mail-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -4,9 +4,9 @@
 struct mail_storage *test_mail_storage_create(void);
 
 struct mailbox *
-test_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		  const char *name, struct istream *input,
-		  enum mailbox_open_flags flags);
+test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		   const char *name, struct istream *input,
+		   enum mailbox_flags flags);
 
 struct mail *
 test_mailbox_mail_alloc(struct mailbox_transaction_context *t,
--- a/src/lib-storage/test-mailbox.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lib-storage/test-mailbox.c	Mon Jun 15 14:28:55 2009 -0400
@@ -24,11 +24,15 @@
 	return 0;
 }
 
-static int test_mailbox_close(struct mailbox *box ATTR_UNUSED)
+static int test_mailbox_open(struct mailbox *box ATTR_UNUSED)
 {
 	return 0;
 }
 
+static void test_mailbox_close(struct mailbox *box ATTR_UNUSED)
+{
+}
+
 static void test_mailbox_get_status(struct mailbox *box ATTR_UNUSED,
 				    enum mailbox_status_items items ATTR_UNUSED,
 				    struct mailbox_status *status_r)
@@ -277,6 +281,7 @@
 		test_mailbox_is_readonly,
 		test_mailbox_allow_new_keywords,
 		test_mailbox_enable,
+		test_mailbox_open,
 		test_mailbox_close,
 		test_mailbox_get_status,
 		NULL,
@@ -318,9 +323,9 @@
 };
 
 struct mailbox *
-test_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		  const char *name, struct istream *input ATTR_UNUSED,
-		  enum mailbox_open_flags flags)
+test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		   const char *name, struct istream *input ATTR_UNUSED,
+		   enum mailbox_flags flags)
 {
 	struct mailbox *box;
 	pool_t pool;
@@ -333,7 +338,7 @@
 	box->list = list;
 
 	box->pool = pool;
-	box->open_flags = flags;
+	box->flags = flags;
 
 	p_array_init(&box->search_results, pool, 16);
 	p_array_init(&box->module_contexts, pool, 5);
--- a/src/lmtp/commands.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/lmtp/commands.c	Mon Jun 15 14:28:55 2009 -0400
@@ -290,18 +290,14 @@
 						  client->state.mail_data->used);
 	}
 	client->state.raw_box = box =
-		mailbox_open(raw_list, "Dovecot Delivery Mail", input,
-			     MAILBOX_OPEN_NO_INDEX_FILES);
+		mailbox_alloc(raw_list, "Dovecot Delivery Mail", input,
+			      MAILBOX_FLAG_NO_INDEX_FILES);
 	i_stream_unref(&input);
-	if (box == NULL) {
+	if (mailbox_open(box) < 0 ||
+	    mailbox_sync(box, 0, 0, NULL) < 0) {
 		i_error("Can't open delivery mail as raw: %s",
-			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",
-			mailbox_list_get_last_error(raw_list, &error));
+			mail_storage_get_last_error(box->storage, &error));
+		mailbox_close(&box);
 		client_rcpt_fail_all(client);
 		return -1;
 	}
--- a/src/plugins/acl/acl-mailbox.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/acl/acl-mailbox.c	Mon Jun 15 14:28:55 2009 -0400
@@ -65,7 +65,7 @@
 	if (abox->module_ctx.super.is_readonly(box))
 		return TRUE;
 
-	save_right = (box->open_flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
+	save_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
 		ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
 	if (acl_mailbox_right_lookup(box, save_right) > 0)
 		return FALSE;
@@ -95,12 +95,12 @@
 	return acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0;
 }
 
-static int acl_mailbox_close(struct mailbox *box)
+static void acl_mailbox_close(struct mailbox *box)
 {
 	struct acl_mailbox *abox = ACL_CONTEXT(box);
 
 	acl_object_deinit(&abox->aclobj);
-	return abox->module_ctx.super.close(box);
+	abox->module_ctx.super.close(box);
 }
 
 static int
@@ -262,7 +262,7 @@
 	struct acl_mailbox *abox = ACL_CONTEXT(box);
 	enum acl_storage_rights save_right;
 
-	save_right = (box->open_flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
+	save_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
 		ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
 	if (acl_mailbox_right_lookup(box, save_right) <= 0)
 		return -1;
@@ -279,7 +279,7 @@
 	struct acl_mailbox *abox = ACL_CONTEXT(t->box);
 	enum acl_storage_rights save_right;
 
-	save_right = (t->box->open_flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
+	save_right = (t->box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
 		ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
 	if (acl_mailbox_right_lookup(t->box, save_right) <= 0)
 		return -1;
@@ -336,19 +336,78 @@
 						      keywords_r, skip_invalid);
 }
 
-struct mailbox *acl_mailbox_open_box(struct mailbox *box)
+static int acl_mailbox_open_check_acl(struct mailbox *box)
 {
+	struct acl_mailbox *abox = ACL_CONTEXT(box);
 	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
+	const unsigned int *idx_arr = alist->rights.acl_storage_right_idx;
+	enum acl_storage_rights open_right;
+	int ret;
+
+	/* mailbox can be opened either for reading or appending new messages */
+	if ((box->flags & MAILBOX_FLAG_IGNORE_ACLS) != 0 ||
+	    (box->list->ns->flags & NAMESPACE_FLAG_NOACL) != 0)
+		return 0;
+
+	if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0) {
+		open_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
+			ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
+	} else {
+		open_right = ACL_STORAGE_RIGHT_READ;
+	}
+
+	ret = acl_object_have_right(abox->aclobj, idx_arr[open_right]);
+	if (ret > 0)
+		return 0;
+	if (ret < 0)
+		return -1;
+
+	/* no access. */
+	ret = acl_object_have_right(abox->aclobj,
+				    idx_arr[ACL_STORAGE_RIGHT_LOOKUP]);
+	if (ret < 0)
+		return -1;
+	if (ret > 0) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
+				       MAIL_ERRSTR_NO_PERMISSION);
+	} else {
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+	}
+	return -1;
+}
+
+static int acl_mailbox_open(struct mailbox *box)
+{
+	struct acl_mailbox *abox = ACL_CONTEXT(box);
+
+	if (acl_mailbox_open_check_acl(box) < 0)
+		return -1;
+
+	return abox->module_ctx.super.open(box);
+}
+
+struct mailbox *
+acl_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		  const char *name, struct istream *input,
+		  enum mailbox_flags flags)
+{
+	union mail_storage_module_context *astorage = ACL_CONTEXT(storage);
+	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
 	struct acl_mailbox *abox;
+	struct mailbox *box;
+
+	box = astorage->super.mailbox_alloc(storage, list, name, input, flags);
 
 	abox = p_new(box->pool, struct acl_mailbox, 1);
 	abox->module_ctx.super = box->v;
 	abox->aclobj = acl_object_init_from_name(alist->rights.backend,
 						 mailbox_get_name(box));
 
-	if ((box->open_flags & MAILBOX_OPEN_IGNORE_ACLS) == 0) {
+	if ((box->flags & MAILBOX_FLAG_IGNORE_ACLS) == 0) {
 		box->v.is_readonly = acl_is_readonly;
 		box->v.allow_new_keywords = acl_allow_new_keywords;
+		box->v.open = acl_mailbox_open;
 		box->v.close = acl_mailbox_close;
 		box->v.mail_alloc = acl_mail_alloc;
 		box->v.save_begin = acl_save_begin;
--- a/src/plugins/acl/acl-plugin.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/acl/acl-plugin.h	Mon Jun 15 14:28:55 2009 -0400
@@ -46,7 +46,10 @@
 void acl_mailbox_list_created(struct mailbox_list *list);
 void acl_mail_user_created(struct mail_user *list);
 
-struct mailbox *acl_mailbox_open_box(struct mailbox *box);
+struct mailbox *
+acl_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		  const char *name, struct istream *input,
+		  enum mailbox_flags flags);
 
 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,
--- a/src/plugins/acl/acl-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/acl/acl-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -16,51 +16,6 @@
 struct acl_user_module acl_user_module =
 	MODULE_CONTEXT_INIT(&mail_user_module_register);
 
-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)
-{
-	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 ||
-	    (list->ns->flags & NAMESPACE_FLAG_NOACL) != 0) {
-		ret = 1;
-	} else if ((flags & MAILBOX_OPEN_SAVEONLY) == 0) {
-		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_mailbox_list_have_right(list, name, FALSE,
-						  save_right, &can_see);
-	}
-	if (ret <= 0) {
-		if (ret < 0)
-			return NULL;
-		if (can_see) {
-			mailbox_list_set_error(list, MAIL_ERROR_PERM,
-					       MAIL_ERRSTR_NO_PERMISSION);
-		} else {
-			mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-		}
-		return NULL;
-	}
-
-	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, struct mailbox_list *list,
 		   const char *name, bool directory)
@@ -103,7 +58,7 @@
 		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_alloc = acl_mailbox_alloc;
 		storage->v.mailbox_create = acl_mailbox_create;
 
 		MODULE_CONTEXT_SET_SELF(storage, acl_storage_module, astorage);
--- a/src/plugins/convert/convert-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/convert/convert-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -29,13 +29,6 @@
 	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)
 {
@@ -298,15 +291,17 @@
 
 	/* First open the source mailbox. If we can't open it, don't create
 	   the destination mailbox either. */
-	srcbox = mailbox_open(source_ns->list, name, NULL,
-			      MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
-	if (srcbox == NULL) {
+	srcbox = mailbox_alloc(source_ns->list, name, NULL,
+			       MAILBOX_FLAG_READONLY |
+			       MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_open(srcbox) < 0) {
 		if (set->skip_broken_mailboxes)
 			return 0;
 
 		i_error("Mailbox conversion: "
 			"Couldn't open source mailbox %s: %s",
-			name, list_error(source_ns->list));
+			name, storage_error(mailbox_get_storage(srcbox)));
+		mailbox_close(&srcbox);
 		return -1;
 	}
 
@@ -322,12 +317,13 @@
 		}
 	}
 
-	destbox = mailbox_open(dest_ns->list, dest_name, NULL,
-			       MAILBOX_OPEN_KEEP_RECENT);
-	if (destbox == NULL) {
+	destbox = mailbox_alloc(dest_ns->list, dest_name, NULL,
+				MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_open(destbox) < 0) {
 		i_error("Mailbox conversion: Couldn't open dest mailbox %s: %s",
-			dest_name, list_error(dest_ns->list));
+			dest_name, storage_error(mailbox_get_storage(destbox)));
 		mailbox_close(&srcbox);
+		mailbox_close(&destbox);
 		return -1;
 	}
 
--- a/src/plugins/expire/expire-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/expire/expire-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -43,7 +43,7 @@
 
 const char *expire_plugin_version = PACKAGE_VERSION;
 
-static void (*next_hook_mail_storage_created)(struct mail_storage *storage);
+static void (*next_hook_mailbox_allocated)(struct mailbox *box);
 static void (*next_hook_mail_user_created)(struct mail_user *user);
 
 static MODULE_CONTEXT_DEFINE_INIT(expire_storage_module,
@@ -254,50 +254,27 @@
 	MODULE_CONTEXT_SET(box, expire_storage_module, xpr_box);
 }
 
-static struct mailbox *
-expire_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		    const char *name, struct istream *input,
-		    enum mailbox_open_flags flags)
+static void expire_mailbox_allocated(struct mailbox *box)
 {
-	struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->user);
-	union mail_storage_module_context *xpr_storage =
-		EXPIRE_CONTEXT(storage);
-	struct mailbox *box;
+	struct expire_mail_user *euser =
+		EXPIRE_USER_CONTEXT(box->storage->user);
+	struct mail_namespace *ns = mailbox_list_get_namespace(box->list);
 	string_t *vname;
 	unsigned int secs;
 	bool altmove;
 
-	box = xpr_storage->super.mailbox_open(storage, list, name, input, flags);
-	if (box != NULL) {
+	if (euser != NULL) {
 		vname = t_str_new(128);
-		(void)mail_namespace_get_vname(mailbox_list_get_namespace(list),
-					       vname, name);
+		(void)mail_namespace_get_vname(ns, vname, box->name);
 
 		secs = expire_box_find_min_secs(euser->env, str_c(vname),
 						&altmove);
 		if (secs != 0)
 			mailbox_expire_hook(box, secs, altmove);
 	}
-	return box;
-}
 
-static void expire_mail_storage_created(struct mail_storage *storage)
-{
-	struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->user);
-	union mail_storage_module_context *xpr_storage;
-
-	if (euser != NULL) {
-		xpr_storage = p_new(storage->pool,
-				    union mail_storage_module_context, 1);
-		xpr_storage->super = storage->v;
-		storage->v.mailbox_open = expire_mailbox_open;
-
-		MODULE_CONTEXT_SET_SELF(storage, expire_storage_module,
-					xpr_storage);
-	}
-
-	if (next_hook_mail_storage_created != NULL)
-		next_hook_mail_storage_created(storage);
+	if (next_hook_mailbox_allocated != NULL)
+		next_hook_mailbox_allocated(box);
 }
 
 static void expire_mail_user_deinit(struct mail_user *user)
@@ -349,8 +326,8 @@
 
 void expire_plugin_init(void)
 {
-	next_hook_mail_storage_created = hook_mail_storage_created;
-	hook_mail_storage_created = expire_mail_storage_created;
+	next_hook_mailbox_allocated = hook_mailbox_allocated;
+	hook_mailbox_allocated = expire_mailbox_allocated;
 
 	next_hook_mail_user_created = hook_mail_user_created;
 	hook_mail_user_created = expire_mail_user_created;
@@ -358,6 +335,6 @@
 
 void expire_plugin_deinit(void)
 {
-	hook_mail_storage_created = next_hook_mail_storage_created;
+	hook_mailbox_allocated = next_hook_mailbox_allocated;
 	hook_mail_user_created = next_hook_mail_user_created;
 }
--- a/src/plugins/expire/expire-tool.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/expire/expire-tool.c	Mon Jun 15 14:28:55 2009 -0400
@@ -80,9 +80,11 @@
 		return 0;
 	}
 
-	box = mailbox_open(ns->list, ns_mailbox, NULL, 0);
-	if (box == NULL) {
-		errstr = mailbox_list_get_last_error(ns->list, &error);
+	box = mailbox_alloc(ns->list, ns_mailbox, NULL, 0);
+	if (mailbox_open(box) < 0) {
+		errstr = mail_storage_get_last_error(mailbox_get_storage(box),
+						     &error);
+		mailbox_close(&box);
 		if (error != MAIL_ERROR_NOTFOUND) {
 			i_error("%s: Opening mailbox %s failed: %s",
 				user, mailbox, errstr);
--- a/src/plugins/fts/fts-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/fts/fts-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -12,11 +12,11 @@
 
 void fts_plugin_init(void)
 {
-	fts_next_hook_mailbox_opened = hook_mailbox_opened;
-	hook_mailbox_opened = fts_mailbox_opened;
+	fts_next_hook_mailbox_allocated = hook_mailbox_allocated;
+	hook_mailbox_allocated = fts_mailbox_allocated;
 }
 
 void fts_plugin_deinit(void)
 {
-	hook_mailbox_opened = fts_next_hook_mailbox_opened;
+	hook_mailbox_allocated = fts_next_hook_mailbox_allocated;
 }
--- a/src/plugins/fts/fts-plugin.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/fts/fts-plugin.h	Mon Jun 15 14:28:55 2009 -0400
@@ -1,9 +1,9 @@
 #ifndef FTS_PLUGIN_H
 #define FTS_PLUGIN_H
 
-extern void (*fts_next_hook_mailbox_opened)(struct mailbox *box);
+extern void (*fts_next_hook_mailbox_allocated)(struct mailbox *box);
 
-void fts_mailbox_opened(struct mailbox *box);
+void fts_mailbox_allocated(struct mailbox *box);
 
 void fts_plugin_init(void);
 void fts_plugin_deinit(void);
--- a/src/plugins/fts/fts-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/fts/fts-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -58,19 +58,17 @@
 				  &mail_storage_module_register);
 static MODULE_CONTEXT_DEFINE_INIT(fts_mail_module, &mail_module_register);
 
-static int fts_mailbox_close(struct mailbox *box)
+static void fts_mailbox_close(struct mailbox *box)
 {
 	struct fts_mailbox *fbox = FTS_CONTEXT(box);
-	int ret;
 
 	if (fbox->backend_substr != NULL)
 		fts_backend_deinit(&fbox->backend_substr);
 	if (fbox->backend_fast != NULL)
 		fts_backend_deinit(&fbox->backend_fast);
 
-	ret = fbox->module_ctx.super.close(box);
+	fbox->module_ctx.super.close(box);
 	i_free(fbox);
-	return ret;
 }
 
 static int fts_build_mail_flush_headers(struct fts_storage_build_context *ctx)
@@ -1057,7 +1055,7 @@
 	MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
 }
 
-void fts_mailbox_opened(struct mailbox *box)
+void fts_mailbox_allocated(struct mailbox *box)
 {
 	const char *env;
 
@@ -1065,6 +1063,6 @@
 	if (env != NULL)
 		fts_mailbox_init(box, env);
 
-	if (fts_next_hook_mailbox_opened != NULL)
-		fts_next_hook_mailbox_opened(box);
+	if (fts_next_hook_mailbox_allocated != NULL)
+		fts_next_hook_mailbox_allocated(box);
 }
--- a/src/plugins/imap-acl/imap-acl-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/imap-acl/imap-acl-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -17,8 +17,8 @@
 #define ERROR_NOT_ADMIN "["IMAP_RESP_CODE_NOPERM"] " \
 	"You lack administrator privileges on this mailbox."
 
-#define ACL_MAILBOX_OPEN_FLAGS \
-	(MAILBOX_OPEN_READONLY | MAILBOX_OPEN_FAST | MAILBOX_OPEN_KEEP_RECENT)
+#define ACL_MAILBOX_FLAGS \
+	(MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT)
 
 #define IMAP_ACL_ANYONE "anyone"
 #define IMAP_ACL_AUTHENTICATED "authenticated"
@@ -69,13 +69,8 @@
 
 	/* Force opening the mailbox so that we can give a nicer error message
 	   if mailbox isn't selectable but is listable. */
-	box = mailbox_open(ns->list, name, NULL, ACL_MAILBOX_OPEN_FLAGS |
-			   MAILBOX_OPEN_IGNORE_ACLS);
-	if (box == NULL) {
-		client_send_list_error(cmd, ns->list);
-		return NULL;
-	}
-
+	box = mailbox_alloc(ns->list, name, NULL, ACL_MAILBOX_FLAGS |
+			    MAILBOX_FLAG_IGNORE_ACLS);
 	ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
 	if (ret > 0)
 		return box;
@@ -304,13 +299,8 @@
 	if (ns == NULL)
 		return TRUE;
 
-	box = mailbox_open(ns->list, real_mailbox, NULL,
-			   ACL_MAILBOX_OPEN_FLAGS | MAILBOX_OPEN_IGNORE_ACLS);
-	if (box == NULL) {
-		client_send_list_error(cmd, ns->list);
-		return TRUE;
-	}
-
+	box = mailbox_alloc(ns->list, real_mailbox, NULL,
+			    ACL_MAILBOX_FLAGS | MAILBOX_FLAG_IGNORE_ACLS);
 	if (acl_object_get_my_rights(acl_mailbox_get_aclobj(box),
 				     pool_datastack_create(), &rights) < 0) {
 		client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
--- a/src/plugins/imap-quota/imap-quota-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/imap-quota/imap-quota-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -84,26 +84,19 @@
 	if (ns == NULL)
 		return TRUE;
 
-	box = mailbox_open(ns->list, mailbox, NULL, (MAILBOX_OPEN_READONLY |
-						     MAILBOX_OPEN_FAST |
-						     MAILBOX_OPEN_KEEP_RECENT));
-	if (box == NULL) {
-		client_send_list_error(cmd, ns->list);
-		return TRUE;
-	}
-
 	if (quser == NULL) {
-		mailbox_close(&box);
 		client_send_tagline(cmd, "OK No quota.");
 		return TRUE;
 	}
 	if (ns->owner != NULL && ns->owner != client->user &&
 	    !client->user->admin) {
-		mailbox_close(&box);
 		client_send_tagline(cmd, "NO Not showing other users' quota.");
 		return TRUE;
 	}
 
+	box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_READONLY |
+			    MAILBOX_FLAG_KEEP_RECENT);
+
 	/* send QUOTAROOT reply */
 	str = t_str_new(128);
 	str_append(str, "* QUOTAROOT ");
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -48,10 +48,6 @@
 	bool internal_namespace;
 };
 
-struct lazy_expunge_mail_storage {
-	union mail_storage_module_context module_ctx;
-};
-
 struct lazy_expunge_transaction {
 	union mailbox_transaction_module_context module_ctx;
 
@@ -65,8 +61,7 @@
 
 static void (*lazy_expunge_next_hook_mail_namespaces_created)
 	(struct mail_namespace *namespaces);
-static void (*lazy_expunge_next_hook_mail_storage_created)
-	(struct mail_storage *storage);
+static void (*lazy_expunge_next_hook_mailbox_allocated)(struct mailbox *box);
 static void (*lazy_expunge_next_hook_mailbox_list_created)
 	(struct mailbox_list *list);
 static void (*lazy_expunge_next_hook_mail_user_created)(struct mail_user *user);
@@ -88,13 +83,16 @@
 	struct mail_storage *storage;
 	enum mail_error error;
 
-	box = mailbox_open(list, name, NULL, MAILBOX_OPEN_FAST |
-			   MAILBOX_OPEN_KEEP_RECENT |
-			   MAILBOX_OPEN_NO_INDEX_FILES);
-	if (box != NULL)
+	box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT |
+			    MAILBOX_FLAG_NO_INDEX_FILES);
+	if (mailbox_open(box) == 0) {
+		*error_r = NULL;
 		return box;
+	}
 
-	*error_r = mailbox_list_get_last_error(list, &error);
+	*error_r = mail_storage_get_last_error(mailbox_get_storage(box),
+					       &error);
+	mailbox_close(&box);
 	if (error != MAIL_ERROR_NOTFOUND)
 		return NULL;
 
@@ -106,10 +104,13 @@
 	}
 
 	/* and try opening again */
-	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);
+	box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_open(box) < 0) {
+		*error_r = mail_storage_get_last_error(mailbox_get_storage(box),
+						       &error);
+		mailbox_close(&box);
+		return NULL;
+	}
 	return box;
 }
 
@@ -252,33 +253,26 @@
 	return _mail;
 }
 
-static struct mailbox *
-lazy_expunge_mailbox_open(struct mail_storage *storage,
-			  struct mailbox_list *list,
-			  const char *name, struct istream *input,
-			  enum mailbox_open_flags flags)
+static void lazy_expunge_mailbox_allocated(struct mailbox *box)
 {
-	struct lazy_expunge_mail_storage *lstorage =
-		LAZY_EXPUNGE_CONTEXT(storage);
 	struct lazy_expunge_mailbox_list *llist =
-		LAZY_EXPUNGE_LIST_CONTEXT(list);
-	struct mailbox *box;
+		LAZY_EXPUNGE_LIST_CONTEXT(box->list);
 	union mailbox_module_context *mbox;
 
-	box = lstorage->module_ctx.super.
-		mailbox_open(storage, list, name, input, flags);
-	if (box == NULL || llist == NULL || llist->internal_namespace)
-		return box;
+	if (llist != NULL && !llist->internal_namespace) {
+		mbox = p_new(box->pool, union mailbox_module_context, 1);
+		mbox->super = box->v;
 
-	mbox = p_new(box->pool, union mailbox_module_context, 1);
-	mbox->super = box->v;
+		box->v.transaction_begin = lazy_expunge_transaction_begin;
+		box->v.transaction_commit = lazy_expunge_transaction_commit;
+		box->v.transaction_rollback = lazy_expunge_transaction_rollback;
+		box->v.mail_alloc = lazy_expunge_mail_alloc;
+		MODULE_CONTEXT_SET_SELF(box, lazy_expunge_mail_storage_module,
+					mbox);
+	}
 
-	box->v.transaction_begin = lazy_expunge_transaction_begin;
-	box->v.transaction_commit = lazy_expunge_transaction_commit;
-	box->v.transaction_rollback = lazy_expunge_transaction_rollback;
-	box->v.mail_alloc = lazy_expunge_mail_alloc;
-	MODULE_CONTEXT_SET_SELF(box, lazy_expunge_mail_storage_module, mbox);
-	return box;
+	if (lazy_expunge_next_hook_mailbox_allocated != NULL)
+		lazy_expunge_next_hook_mailbox_allocated(box);
 }
 
 static int
@@ -373,25 +367,6 @@
 	return 0;
 }
 
-static void lazy_expunge_mail_storage_init(struct mail_storage *storage)
-{
-	struct lazy_expunge_mail_storage *lstorage;
-
-	lstorage = p_new(storage->pool, struct lazy_expunge_mail_storage, 1);
-	lstorage->module_ctx.super = storage->v;
-	storage->v.mailbox_open = lazy_expunge_mailbox_open;
-
-	MODULE_CONTEXT_SET(storage, lazy_expunge_mail_storage_module, lstorage);
-}
-
-static void lazy_expunge_mail_storage_created(struct mail_storage *storage)
-{
-	lazy_expunge_mail_storage_init(storage);
-
-	if (lazy_expunge_next_hook_mail_storage_created != NULL)
-		lazy_expunge_next_hook_mail_storage_created(storage);
-}
-
 static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
 {
 	struct lazy_expunge_mail_user *luser =
@@ -485,8 +460,8 @@
 	hook_mail_namespaces_created =
 		lazy_expunge_hook_mail_namespaces_created;
 
-	lazy_expunge_next_hook_mail_storage_created = hook_mail_storage_created;
-	hook_mail_storage_created = lazy_expunge_mail_storage_created;
+	lazy_expunge_next_hook_mailbox_allocated = hook_mailbox_allocated;
+	hook_mailbox_allocated = lazy_expunge_mailbox_allocated;
 
 	lazy_expunge_next_hook_mailbox_list_created = hook_mailbox_list_created;
 	hook_mailbox_list_created = lazy_expunge_mailbox_list_created;
@@ -499,7 +474,7 @@
 {
 	hook_mail_namespaces_created =
 		lazy_expunge_hook_mail_namespaces_created;
-	hook_mail_storage_created = lazy_expunge_next_hook_mail_storage_created;
+	hook_mailbox_allocated = lazy_expunge_next_hook_mailbox_allocated;
 	hook_mailbox_list_created = lazy_expunge_next_hook_mailbox_list_created;
 	hook_mail_user_created = lazy_expunge_next_hook_mail_user_created;
 }
--- a/src/plugins/listescape/listescape-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/listescape/listescape-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -163,9 +163,10 @@
 }
 
 static struct mailbox *
-listescape_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-			const char *name, struct istream *input,
-			enum mailbox_open_flags flags)
+listescape_mailbox_alloc(struct mail_storage *storage,
+			 struct mailbox_list *list,
+			 const char *name, struct istream *input,
+			 enum mailbox_flags flags)
 {
 	struct listescape_mail_storage *mstorage = LIST_ESCAPE_CONTEXT(storage);
 	struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
@@ -173,7 +174,7 @@
 	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, list, name, input, flags);
+		mailbox_alloc(storage, list, name, input, flags);
 }
 
 static int
@@ -266,7 +267,7 @@
 
 	mstorage = p_new(storage->pool, struct listescape_mail_storage, 1);
 	mstorage->module_ctx.super = storage->v;
-	storage->v.mailbox_open = listescape_mailbox_open;
+	storage->v.mailbox_alloc = listescape_mailbox_alloc;
 	storage->v.mailbox_create = listescape_mailbox_create;
 
 	MODULE_CONTEXT_SET(storage, listescape_storage_module, mstorage);
--- a/src/plugins/mail-log/mail-log-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/mail-log/mail-log-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -555,17 +555,15 @@
 }
 
 static struct mailbox *
-mail_log_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		      const char *name, struct istream *input,
-		      enum mailbox_open_flags flags)
+mail_log_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		       const char *name, struct istream *input,
+		       enum mailbox_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, list, name, input, flags);
-	if (box == NULL)
-		return NULL;
+	box = lstorage->super.mailbox_alloc(storage, list, name, input, flags);
 
 	lbox = p_new(box->pool, union mailbox_module_context, 1);
 	lbox->super = box->v;
@@ -625,7 +623,7 @@
 
 	lstorage = p_new(storage->pool, union mail_storage_module_context, 1);
 	lstorage->super = storage->v;
-	storage->v.mailbox_open = mail_log_mailbox_open;
+	storage->v.mailbox_alloc = mail_log_mailbox_alloc;
 
 	MODULE_CONTEXT_SET_SELF(storage, mail_log_storage_module, lstorage);
 
--- a/src/plugins/mbox-snarf/mbox-snarf-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/mbox-snarf/mbox-snarf-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -113,31 +113,30 @@
 		/* try to open the spool mbox */
 		mstorage->open_spool_inbox = TRUE;
 		mbox->spool_mbox =
-			mailbox_open(box->list, "INBOX", NULL,
-				     MAILBOX_OPEN_KEEP_RECENT |
-				     MAILBOX_OPEN_NO_INDEX_FILES);
+			mailbox_alloc(box->list, "INBOX", NULL,
+				      MAILBOX_FLAG_KEEP_RECENT |
+				      MAILBOX_FLAG_NO_INDEX_FILES);
 		mstorage->open_spool_inbox = FALSE;
 	}
-
-	if (mbox->spool_mbox != NULL)
-		mbox_snarf(mbox->spool_mbox, box);
+	(void)mbox_snarf(mbox->spool_mbox, box);
 
 	return mbox->module_ctx.super.sync_init(box, flags);
 }
 
-static int mbox_snarf_close(struct mailbox *box)
+static void mbox_snarf_close(struct mailbox *box)
 {
 	struct mbox_snarf_mailbox *mbox = MBOX_SNARF_CONTEXT(box);
 
 	if (mbox->spool_mbox != NULL)
 		mailbox_close(&mbox->spool_mbox);
-	return mbox->module_ctx.super.close(box);
+	mbox->module_ctx.super.close(box);
 }
 
 static struct mailbox *
-mbox_snarf_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-			const char *name, struct istream *input,
-			enum mailbox_open_flags flags)
+mbox_snarf_mailbox_alloc(struct mail_storage *storage,
+			 struct mailbox_list *list,
+			 const char *name, struct istream *input,
+			 enum mailbox_flags flags)
 {
 	struct mbox_snarf_mail_storage *mstorage =
 		MBOX_SNARF_CONTEXT(storage);
@@ -164,7 +163,7 @@
 	}
 
 	box = mstorage->module_ctx.super.
-		mailbox_open(storage, list, name, input, flags);
+		mailbox_alloc(storage, list, name, input, flags);
 	storage->flags = old_flags;
 	list->flags = old_list_flags;
 
@@ -189,7 +188,7 @@
 	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;
-	storage->v.mailbox_open = mbox_snarf_mailbox_open;
+	storage->v.mailbox_alloc = mbox_snarf_mailbox_alloc;
 
 	MODULE_CONTEXT_SET(storage, mbox_snarf_storage_module, mstorage);
 }
--- a/src/plugins/quota/quota-count.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/quota/quota-count.c	Mon Jun 15 14:28:55 2009 -0400
@@ -27,10 +27,11 @@
 		return 0;
 	}
 
-	box = mailbox_open(ns->list, name, NULL,
-			   MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
-	if (box == NULL) {
-		mailbox_list_get_last_error(ns->list, &error);
+	box = mailbox_alloc(ns->list, name, NULL,
+			    MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_open(box) < 0) {
+		mail_storage_get_last_error(mailbox_get_storage(box), &error);
+		mailbox_close(&box);
 		if (error == MAIL_ERROR_TEMP)
 			return -1;
 		/* non-temporary error, e.g. ACLs denied access. */
--- a/src/plugins/quota/quota-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/quota/quota-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -341,7 +341,7 @@
 	return ret;
 }
 
-static int quota_mailbox_close(struct mailbox *box)
+static void quota_mailbox_close(struct mailbox *box)
 {
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
 
@@ -352,19 +352,19 @@
 	i_assert(qbox->expunge_qt == NULL ||
 		 qbox->expunge_qt->tmp_mail == NULL);
 
-	return qbox->module_ctx.super.close(box);
+	qbox->module_ctx.super.close(box);
 }
 
 static struct mailbox *
-quota_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		   const char *name, struct istream *input,
-		   enum mailbox_open_flags flags)
+quota_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		    const char *name, struct istream *input,
+		    enum mailbox_flags flags)
 {
 	union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
 	struct mailbox *box;
 	struct quota_mailbox *qbox;
 
-	box = qstorage->super.mailbox_open(storage, list, name, input, flags);
+	box = qstorage->super.mailbox_alloc(storage, list, name, input, flags);
 	if (box == NULL || QUOTA_LIST_CONTEXT(list) == NULL)
 		return box;
 
@@ -440,10 +440,11 @@
 	   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. */
-	box = mailbox_open(list, name, NULL, MAILBOX_OPEN_KEEP_RECENT |
-			   MAILBOX_OPEN_KEEP_LOCKED);
-	if (box == NULL) {
-		str = mailbox_list_get_last_error(list, &error);
+	box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT |
+			    MAILBOX_FLAG_KEEP_LOCKED);
+	if (mailbox_open(box) < 0) {
+		str = mail_storage_get_last_error(mailbox_get_storage(box),
+						  &error);
 		if (error != MAIL_ERROR_NOTPOSSIBLE) {
 			ret = -1;
 		} else {
@@ -518,7 +519,7 @@
 
 	qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
 	qstorage->super = storage->v;
-	storage->v.mailbox_open = quota_mailbox_open;
+	storage->v.mailbox_alloc = quota_mailbox_alloc;
 
 	MODULE_CONTEXT_SET_SELF(storage, quota_storage_module, qstorage);
 	quota_maildir_storage_set(storage);
--- a/src/plugins/trash/trash-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/trash/trash-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -54,10 +54,12 @@
 {
 	struct mail_search_args *search_args;
 
-	trash->box = mailbox_open(trash->ns->list, trash->name, NULL,
-				  MAILBOX_OPEN_KEEP_RECENT);
-	if (trash->box == NULL)
+	trash->box = mailbox_alloc(trash->ns->list, trash->name, NULL,
+				   MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_open(trash->box) < 0) {
+		mailbox_close(&trash->box);
 		return 0;
+	}
 
 	if (mailbox_sync(trash->box, MAILBOX_SYNC_FLAG_FULL_READ, 0, NULL) < 0)
 		return -1;
--- a/src/plugins/virtual/virtual-config.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/virtual/virtual-config.c	Mon Jun 15 14:28:55 2009 -0400
@@ -323,7 +323,7 @@
 	i_array_init(&mbox->backend_boxes, 8);
 	mbox->search_args_crc32 = (uint32_t)-1;
 
-	path = t_strconcat(mbox->path, "/"VIRTUAL_CONFIG_FNAME, NULL);
+	path = t_strconcat(mbox->ibox.box.path, "/"VIRTUAL_CONFIG_FNAME, NULL);
 	fd = open(path, O_RDONLY);
 	if (fd == -1) {
 		if (errno == ENOENT) {
--- a/src/plugins/virtual/virtual-storage.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/virtual/virtual-storage.c	Mon Jun 15 14:28:55 2009 -0400
@@ -118,26 +118,27 @@
 }
 
 static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
-				  enum mailbox_open_flags open_flags)
+				  enum mailbox_flags flags)
 {
 	struct mail_user *user = mbox->storage->storage.user;
 	struct virtual_backend_box *const *bboxes;
+	struct mail_storage *storage;
 	struct mail_namespace *ns;
 	unsigned int i, count;
 	enum mail_error error;
 	const char *str, *mailbox;
 
-	open_flags |= MAILBOX_OPEN_KEEP_RECENT;
+	flags |= MAILBOX_FLAG_KEEP_RECENT;
 
 	bboxes = array_get(&mbox->backend_boxes, &count);
 	for (i = 0; i < count; ) {
 		mailbox = bboxes[i]->name;
 		ns = mail_namespace_find(user->namespaces, &mailbox);
-		bboxes[i]->box = mailbox_open(ns->list, mailbox,
-					      NULL, open_flags);
+		bboxes[i]->box = mailbox_alloc(ns->list, mailbox, NULL, flags);
 
-		if (bboxes[i]->box == NULL) {
-			str = mailbox_list_get_last_error(ns->list, &error);
+		if (mailbox_open(bboxes[i]->box) < 0) {
+			storage = mailbox_get_storage(bboxes[i]->box);
+			str = mail_storage_get_last_error(storage, &error);
 			if (bboxes[i]->wildcard &&
 			    (error == MAIL_ERROR_PERM ||
 			     error == MAIL_ERROR_NOTFOUND)) {
@@ -148,11 +149,9 @@
 				bboxes = array_get(&mbox->backend_boxes, &count);
 				continue;
 			}
-			if (ns->list != mbox->ibox.box.list) {
-				/* copy the error */
-				mailbox_list_set_error(mbox->ibox.box.list,
-						       error, str);
-			}
+			/* copy the error */
+			mail_storage_set_error(mbox->ibox.box.storage,
+					       error, str);
 			break;
 		}
 		i_array_init(&bboxes[i]->uids, 64);
@@ -166,7 +165,7 @@
 	else {
 		/* failed */
 		for (; i > 0; i--) {
-			(void)mailbox_close(&bboxes[i-1]->box);
+			mailbox_close(&bboxes[i-1]->box);
 			array_free(&bboxes[i-1]->uids);
 		}
 		return -1;
@@ -174,96 +173,83 @@
 }
 
 static struct mailbox *
-virtual_open(struct virtual_storage *storage, struct mailbox_list *list,
-	     const char *name, enum mailbox_open_flags flags)
+virtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
+		      const char *name, struct istream *input,
+		      enum mailbox_flags flags)
 {
-	struct mail_storage *_storage = &storage->storage;
+	struct virtual_storage *storage = (struct virtual_storage *)storage;
 	struct virtual_mailbox *mbox;
-	struct mail_index *index;
-	const char *path;
 	pool_t pool;
-	bool failed;
-
-	if (virtual_mailbox_is_in_open_stack(storage, name)) {
-		mail_storage_set_critical(_storage,
-					  "Virtual mailbox loops: %s", name);
-		return NULL;
-	}
-
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	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;
+	mbox->ibox.box.list = list;
 	mbox->ibox.mail_vfuncs = &virtual_mail_vfuncs;
-	mbox->ibox.index = index;
+
+	index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+				    VIRTUAL_INDEX_PREFIX);
 
 	mbox->storage = storage;
-	mbox->path = p_strdup(pool, path);
 	mbox->vseq_lookup_prev_mailbox = i_strdup("");
 
 	mbox->virtual_ext_id =
-		mail_index_ext_register(index, "virtual", 0,
+		mail_index_ext_register(mbox->ibox.index, "virtual", 0,
 			sizeof(struct virtual_mail_index_record),
 			sizeof(uint32_t));
-
-	array_append(&storage->open_stack, &name, 1);
-	failed = virtual_config_read(mbox) < 0 ||
-		virtual_mailboxes_open(mbox, flags) < 0;
-	array_delete(&storage->open_stack,
-		     array_count(&storage->open_stack)-1, 1);
-	if (failed) {
-		virtual_config_free(mbox);
-		index_storage_mailbox_close(&mbox->ibox.box);
-		return NULL;
-	}
-
-	index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
 	return &mbox->ibox.box;
 }
 
-static struct mailbox *
-virtual_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
-		     const char *name, struct istream *input,
-		     enum mailbox_open_flags flags)
+static int virtual_mailbox_open(struct mailbox *box)
 {
-	struct virtual_storage *storage = (struct virtual_storage *)_storage;
-	const char *path;
+	struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
 	struct stat st;
+	bool failed;
 
-	if (input != NULL) {
-		mailbox_list_set_critical(list,
+	if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) {
+		mail_storage_set_critical(box->storage,
+			"Virtual mailbox loops: %s", box->name);
+		return -1;
+	}
+
+	if (box->input != NULL) {
+		mail_storage_set_critical(box->storage,
 			"virtual doesn't support streamed mailboxes");
-		return NULL;
+		return -1;
 	}
 
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(path, &st) == 0)
-		return virtual_open(storage, list, name, flags);
-	else if (errno == ENOENT) {
-		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+	if (stat(box->path, &st) == 0) {
+		/* exists, open it */
+	} else if (errno == ENOENT) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+		return -1;
 	} else if (errno == EACCES) {
-		mailbox_list_set_critical(list, "%s",
-			mail_error_eacces_msg("stat", path));
+		mail_storage_set_critical(box->storage, "%s",
+			mail_error_eacces_msg("stat", box->path));
+		return -1;
 	} else {
-		mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", box->path);
+		return -1;
 	}
-	return NULL;
+
+	array_append(&mbox->storage->open_stack, &box->name, 1);
+	failed = virtual_config_read(mbox) < 0 ||
+		virtual_mailboxes_open(mbox, box->flags) < 0;
+	array_delete(&mbox->storage->open_stack,
+		     array_count(&mbox->storage->open_stack)-1, 1);
+	return failed ? -1 : 0;
 }
 
-static int virtual_storage_mailbox_close(struct mailbox *box)
+static void virtual_mailbox_close(struct mailbox *box)
 {
 	struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
 	struct mail_storage *storage;
 	struct virtual_backend_box **bboxes;
 	unsigned int i, count;
-	int ret = 0;
 
 	virtual_config_free(mbox);
 
@@ -273,14 +259,7 @@
 			mailbox_search_result_free(&bboxes[i]->search_result);
 
 		storage = bboxes[i]->box->storage;
-		if (mailbox_close(&bboxes[i]->box) < 0) {
-			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;
-		}
+		mailbox_close(&bboxes[i]->box);
 		if (array_is_created(&bboxes[i]->sync_outside_expunges))
 			array_free(&bboxes[i]->sync_outside_expunges);
 		array_free(&bboxes[i]->sync_pending_removes);
@@ -289,7 +268,7 @@
 	array_free(&mbox->backend_boxes);
 	i_free(mbox->vseq_lookup_prev_mailbox);
 
-	return index_storage_mailbox_close(box) < 0 ? -1 : ret;
+	index_storage_mailbox_close(box);
 }
 
 static int virtual_mailbox_create(struct mail_storage *_storage,
@@ -578,7 +557,7 @@
 		virtual_storage_add_list,
 		virtual_storage_get_list_settings,
 		NULL,
-		virtual_mailbox_open,
+		virtual_mailbox_alloc,
 		virtual_mailbox_create,
 		NULL
 	}
@@ -593,7 +572,8 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
-		virtual_storage_mailbox_close,
+		virtual_mailbox_open,
+		virtual_mailbox_close,
 		index_storage_get_status,
 		NULL,
 		NULL,
--- a/src/plugins/virtual/virtual-storage.h	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/virtual/virtual-storage.h	Mon Jun 15 14:28:55 2009 -0400
@@ -102,7 +102,6 @@
 	struct index_mailbox ibox;
 	struct virtual_storage *storage;
 
-	const char *path;
 	uint32_t virtual_ext_id;
 
 	uint32_t prev_uid_validity;
--- a/src/plugins/virtual/virtual-sync.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/virtual/virtual-sync.c	Mon Jun 15 14:28:55 2009 -0400
@@ -169,7 +169,7 @@
 		if (ext_name_offset >= ext_size ||
 		    ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
 			i_error("virtual index %s: Broken mailbox_count header",
-				ctx->mbox->path);
+				ctx->mbox->ibox.box.path);
 			ctx->index_broken = TRUE;
 			ext_mailbox_count = 0;
 			ret = FALSE;
@@ -184,18 +184,18 @@
 		if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
 		    mailboxes[i].id <= prev_mailbox_id) {
 			i_error("virtual index %s: Broken mailbox id",
-				ctx->mbox->path);
+				ctx->mbox->ibox.box.path);
 			break;
 		}
 		if (mailboxes[i].name_len == 0 ||
 		    mailboxes[i].name_len > ext_size) {
 			i_error("virtual index %s: Broken mailbox name_len",
-				ctx->mbox->path);
+				ctx->mbox->ibox.box.path);
 			break;
 		}
 		if (ext_name_offset + mailboxes[i].name_len > ext_size) {
 			i_error("virtual index %s: Broken mailbox list",
-				ctx->mbox->path);
+				ctx->mbox->ibox.box.path);
 			break;
 		}
 		T_BEGIN {
@@ -999,8 +999,10 @@
 	struct mailbox_status status;
 	int ret;
 
-	if (!bbox->box->opened)
-		index_storage_mailbox_open(ibox);
+	if (!bbox->box->opened) {
+		if (mailbox_open(bbox->box) < 0)
+			return -1;
+	}
 
 	/* if we already did some changes to index, commit them before
 	   syncing starts. */
@@ -1391,7 +1393,7 @@
 			if (mail_index_unlink(ctx->index) < 0) {
 				i_error("virtual index %s: Failed to unlink() "
 					"broken indexes: %m",
-					ctx->mbox->path);
+					ctx->mbox->ibox.box.path);
 			}
 		}
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
@@ -1452,10 +1454,12 @@
 	struct mailbox_sync_context *sync_ctx;
 	int ret = 0;
 
-	if (!box->opened)
-		index_storage_mailbox_open(&mbox->ibox);
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			ret = -1;
+	}
 
-	if (index_mailbox_want_full_sync(&mbox->ibox, flags))
+	if (index_mailbox_want_full_sync(&mbox->ibox, flags) && ret == 0)
 		ret = virtual_sync(mbox, flags);
 
 	sync_ctx = index_mailbox_sync_init(box, flags, ret < 0);
--- a/src/plugins/zlib/zlib-plugin.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/plugins/zlib/zlib-plugin.c	Mon Jun 15 14:28:55 2009 -0400
@@ -203,9 +203,9 @@
 }
 
 static struct mailbox *
-zlib_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
-		  const char *name, struct istream *input,
-		  enum mailbox_open_flags flags)
+zlib_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+		   const char *name, struct istream *input,
+		   enum mailbox_flags flags)
 {
 	union mail_storage_module_context *qstorage = ZLIB_CONTEXT(storage);
 	struct mailbox *box;
@@ -216,12 +216,12 @@
 			zlib_mailbox_open_input(storage, list, name);
 	}
 
-	box = qstorage->super.mailbox_open(storage, list, name, input, flags);
+	box = qstorage->super.mailbox_alloc(storage, list, name, input, flags);
 
 	if (zlib_input != NULL)
 		i_stream_unref(&zlib_input);
 
-	if (box != NULL && strcmp(storage->name, "maildir") == 0)
+	if (strcmp(box->storage->name, "maildir") == 0)
 		zlib_maildir_open_init(box);
 	return box;
 }
@@ -232,7 +232,7 @@
 
 	qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
 	qstorage->super = storage->v;
-	storage->v.mailbox_open = zlib_mailbox_open;
+	storage->v.mailbox_alloc = zlib_mailbox_alloc;
 
 	MODULE_CONTEXT_SET_SELF(storage, zlib_storage_module, qstorage);
 
--- a/src/pop3/pop3-client.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/pop3/pop3-client.c	Mon Jun 15 14:28:55 2009 -0400
@@ -221,7 +221,7 @@
 	struct mail_storage *storage;
 	const char *inbox, *ident;
 	struct client *client;
-        enum mailbox_open_flags flags;
+        enum mailbox_flags flags;
 	const char *errmsg;
 	enum mail_error error;
 
@@ -257,22 +257,22 @@
 	}
 	client->inbox_ns = ns;
 
-	flags = MAILBOX_OPEN_POP3_SESSION;
+	flags = MAILBOX_FLAG_POP3_SESSION;
 	if (set->pop3_no_flag_updates)
-		flags |= MAILBOX_OPEN_KEEP_RECENT;
+		flags |= MAILBOX_FLAG_KEEP_RECENT;
 	if (set->pop3_lock_session)
-		flags |= MAILBOX_OPEN_KEEP_LOCKED;
-	client->mailbox = mailbox_open(ns->list, "INBOX", NULL, flags);
-	if (client->mailbox == NULL) {
+		flags |= MAILBOX_FLAG_KEEP_LOCKED;
+	client->mailbox = mailbox_alloc(ns->list, "INBOX", NULL, flags);
+	storage = mailbox_get_storage(client->mailbox);
+	if (mailbox_open(client->mailbox) < 0) {
 		errmsg = t_strdup_printf("Couldn't open INBOX: %s",
-					 mailbox_list_get_last_error(ns->list,
+					 mail_storage_get_last_error(storage,
 								     &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)) {
--- a/src/util/doveadm.c	Fri Jun 12 12:52:38 2009 -0400
+++ b/src/util/doveadm.c	Mon Jun 15 14:28:55 2009 -0400
@@ -58,11 +58,12 @@
 	if (ns == NULL)
 		i_fatal("Can't find namespace for mailbox %s", mailbox);
 
-	box = mailbox_open(ns->list, mailbox, NULL, MAILBOX_OPEN_KEEP_RECENT |
-			   MAILBOX_OPEN_IGNORE_ACLS);
-	if (box == NULL) {
+	box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_KEEP_RECENT |
+			    MAILBOX_FLAG_IGNORE_ACLS);
+	if (mailbox_open(box) < 0) {
 		i_fatal("Opening mailbox %s failed: %s", orig_mailbox,
-			mailbox_list_get_last_error(ns->list, NULL));
+			mail_storage_get_last_error(mailbox_get_storage(box),
+						    NULL));
 	}
 	return box;
 }