changeset 12520:b26d6da05d48

lib-storage: Lazily look up mailbox path and permissions. Added functions to get them.
author Timo Sirainen <tss@iki.fi>
date Sun, 05 Dec 2010 23:18:55 +0000
parents b63ff46f82ee
children b22766c1aa51
files src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox-common/dbox-storage.c src/lib-storage/index/dbox-multi/mdbox-mail.c src/lib-storage/index/dbox-multi/mdbox-save.c src/lib-storage/index/dbox-multi/mdbox-storage.c src/lib-storage/index/dbox-multi/mdbox-sync.c src/lib-storage/index/dbox-single/sdbox-file.c src/lib-storage/index/dbox-single/sdbox-save.c src/lib-storage/index/dbox-single/sdbox-storage.c src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c src/lib-storage/index/dbox-single/sdbox-sync.c src/lib-storage/index/index-storage.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-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-sync.c src/lib-storage/index/raw/raw-mail.c src/lib-storage/index/raw/raw-storage.c src/lib-storage/mail-copy.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/plugins/fts-squat/fts-backend-squat.c src/plugins/virtual/virtual-config.c src/plugins/virtual/virtual-sync.c src/plugins/zlib/zlib-plugin.c
diffstat 36 files changed, 265 insertions(+), 193 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/cydir/cydir-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -71,9 +71,10 @@
 
 static int cydir_mailbox_open(struct mailbox *box)
 {
+	const char *box_path = mailbox_get_path(box);
 	struct stat st;
 
-	if (stat(box->path, &st) == 0) {
+	if (stat(box_path, &st) == 0) {
 		/* exists, open it */
 	} else if (errno == ENOENT) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
@@ -81,11 +82,11 @@
 		return -1;
 	} else if (errno == EACCES) {
 		mail_storage_set_critical(box->storage, "%s",
-			mail_error_eacces_msg("stat", box->path));
+			mail_error_eacces_msg("stat", box_path));
 		return -1;
 	} else {
 		mail_storage_set_critical(box->storage, "stat(%s) failed: %m",
-					  box->path);
+					  box_path);
 		return -1;
 	}
 	return index_storage_mailbox_open(box, FALSE);
@@ -105,12 +106,10 @@
 
 static void cydir_notify_changes(struct mailbox *box)
 {
-	struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
-
 	if (box->notify_callback == NULL)
-		index_mailbox_check_remove_all(&mbox->box);
+		index_mailbox_check_remove_all(box);
 	else
-		index_mailbox_check_add(&mbox->box, mbox->box.path);
+		index_mailbox_check_add(box, mailbox_get_path(box));
 }
 
 struct mail_storage cydir_storage = {
--- a/src/lib-storage/index/dbox-common/dbox-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-common/dbox-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -113,7 +113,9 @@
 
 int dbox_mailbox_open(struct mailbox *box)
 {
-	if (dbox_cleanup_if_exists(box->list, box->path)) {
+	const char *box_path = mailbox_get_path(box);
+
+	if (dbox_cleanup_if_exists(box->list, box_path)) {
 		return index_storage_mailbox_open(box, FALSE);
 	} else if (errno == ENOENT) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
@@ -121,11 +123,11 @@
 		return -1;
 	} else if (errno == EACCES) {
 		mail_storage_set_critical(box->storage, "%s",
-			mail_error_eacces_msg("stat", box->path));
+			mail_error_eacces_msg("stat", box_path));
 		return -1;
 	} else {
 		mail_storage_set_critical(box->storage,
-					  "stat(%s) failed: %m", box->path);
+					  "stat(%s) failed: %m", box_path);
 		return -1;
 	}
 }
--- a/src/lib-storage/index/dbox-multi/mdbox-mail.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-multi/mdbox-mail.c	Sun Dec 05 23:18:55 2010 +0000
@@ -29,7 +29,7 @@
 		mail_index_lookup_uid(view, seq, &uid);
 		mail_storage_set_critical(&mbox->storage->storage.storage,
 			"mdbox %s: map uid lost for uid %u",
-			mbox->box.path, uid);
+			mailbox_get_path(&mbox->box), uid);
 		mdbox_storage_set_corrupted(mbox->storage);
 		return -1;
 	}
@@ -48,7 +48,7 @@
 	if (cur_map_uid_validity != mbox->map_uid_validity) {
 		mail_storage_set_critical(&mbox->storage->storage.storage,
 			"mdbox %s: map uidvalidity mismatch (%u vs %u)",
-			mbox->box.path, mbox->map_uid_validity,
+			mailbox_get_path(&mbox->box), mbox->map_uid_validity,
 			cur_map_uid_validity);
 		mdbox_storage_set_corrupted(mbox->storage);
 		return -1;
--- a/src/lib-storage/index/dbox-multi/mdbox-save.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-multi/mdbox-save.c	Sun Dec 05 23:18:55 2010 +0000
@@ -364,10 +364,11 @@
 	(void)mdbox_map_atomic_finish(&ctx->atomic);
 
 	if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
-		if (fdatasync_path(ctx->mbox->box.path) < 0) {
+		const char *box_path = mailbox_get_path(&ctx->mbox->box);
+
+		if (fdatasync_path(box_path) < 0) {
 			mail_storage_set_critical(storage,
-				"fdatasync_path(%s) failed: %m",
-				ctx->mbox->box.path);
+				"fdatasync_path(%s) failed: %m", box_path);
 		}
 	}
 	mdbox_transaction_save_rollback(_ctx);
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -149,7 +149,7 @@
 	    (!mbox->creating || data_size != 0)) {
 		mail_storage_set_critical(&mbox->storage->storage.storage,
 			"mdbox %s: Invalid dbox header size: %"PRIuSIZE_T,
-			mbox->box.path, data_size);
+			mailbox_get_path(&mbox->box), data_size);
 		mdbox_storage_set_corrupted(mbox->storage);
 		return -1;
 	}
--- a/src/lib-storage/index/dbox-multi/mdbox-sync.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-multi/mdbox-sync.c	Sun Dec 05 23:18:55 2010 +0000
@@ -264,7 +264,7 @@
 		if (storage_rebuilt) {
 			mail_storage_set_critical(storage,
 				"mdbox %s: Storage keeps breaking",
-				mbox->box.path);
+				mailbox_get_path(&mbox->box));
 			return -1;
 		}
 
--- a/src/lib-storage/index/dbox-single/sdbox-file.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-single/sdbox-file.c	Sun Dec 05 23:18:55 2010 +0000
@@ -22,7 +22,7 @@
 	i_free(file->file.primary_path);
 	i_free(file->file.alt_path);
 	file->file.primary_path =
-		i_strdup_printf("%s/%s", box->path, fname);
+		i_strdup_printf("%s/%s", mailbox_get_path(box), fname);
 
 	alt_path = mailbox_list_get_path(box->list, box->name,
 					 MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
@@ -46,7 +46,7 @@
 		} else {
 			file->file.primary_path =
 				i_strdup_printf("%s/%s",
-						file->mbox->box.path,
+						mailbox_get_path(&mbox->box),
 						dbox_generate_tmp_filename());
 		}
 	} T_END;
@@ -151,7 +151,7 @@
 
 	old_path = file->file.cur_path;
 	new_fname = t_strdup_printf(SDBOX_MAIL_FILE_FORMAT, uid);
-	new_path = t_strdup_printf("%s/%s", file->mbox->box.path,
+	new_path = t_strdup_printf("%s/%s", mailbox_get_path(&file->mbox->box),
 				   new_fname);
 	if (rename(old_path, new_path) < 0) {
 		mail_storage_set_critical(&file->file.storage->storage,
@@ -221,43 +221,44 @@
 {
 	struct sdbox_file *sfile = (struct sdbox_file *)file;
 	struct mailbox *box = &sfile->mbox->box;
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *p, *dir;
 	mode_t old_mask;
 	int fd;
 
-	old_mask = umask(0666 & ~box->file_create_mode);
+	old_mask = umask(0666 & ~perm->file_create_mode);
 	fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
 	umask(old_mask);
 	if (fd == -1 && errno == ENOENT && parents &&
 	    (p = strrchr(path, '/')) != NULL) {
 		dir = t_strdup_until(path, p);
-		if (mkdir_parents_chgrp(dir, box->dir_create_mode,
-					box->file_create_gid,
-					box->file_create_gid_origin) < 0) {
+		if (mkdir_parents_chgrp(dir, perm->dir_create_mode,
+					perm->file_create_gid,
+					perm->file_create_gid_origin) < 0) {
 			mail_storage_set_critical(box->storage,
 				"mkdir_parents(%s) failed: %m", dir);
 			return -1;
 		}
 		/* try again */
-		old_mask = umask(0666 & ~box->file_create_mode);
+		old_mask = umask(0666 & ~perm->file_create_mode);
 		fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
 		umask(old_mask);
 	}
 	if (fd == -1) {
 		mail_storage_set_critical(box->storage,
 			"open(%s, O_CREAT) failed: %m", path);
-	} else if (box->file_create_gid == (gid_t)-1) {
+	} else if (perm->file_create_gid == (gid_t)-1) {
 		/* no group change */
-	} else if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
+	} else if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
 		if (errno == EPERM) {
 			mail_storage_set_critical(box->storage, "%s",
 				eperm_error_get_chgrp("fchown", path,
-					box->file_create_gid,
-					box->file_create_gid_origin));
+					perm->file_create_gid,
+					perm->file_create_gid_origin));
 		} else {
 			mail_storage_set_critical(box->storage,
 				"fchown(%s, -1, %ld) failed: %m",
-				path, (long)box->file_create_gid);
+				path, (long)perm->file_create_gid);
 		}
 		/* continue anyway */
 	}
--- a/src/lib-storage/index/dbox-single/sdbox-save.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-single/sdbox-save.c	Sun Dec 05 23:18:55 2010 +0000
@@ -307,10 +307,11 @@
 		ctx->ctx.failed = TRUE;
 
 	if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
-		if (fdatasync_path(ctx->mbox->box.path) < 0) {
+		const char *box_path = mailbox_get_path(&ctx->mbox->box);
+
+		if (fdatasync_path(box_path) < 0) {
 			mail_storage_set_critical(storage,
-				"fdatasync_path(%s) failed: %m",
-				ctx->mbox->box.path);
+				"fdatasync_path(%s) failed: %m", box_path);
 		}
 	}
 	sdbox_transaction_save_rollback(_ctx);
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -84,7 +84,7 @@
 			mail_storage_set_critical(
 				&mbox->storage->storage.storage,
 				"sdbox %s: Invalid dbox header size",
-				mbox->box.path);
+				mailbox_get_path(&mbox->box));
 		}
 		ret = -1;
 	} else {
--- a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c	Sun Dec 05 23:18:55 2010 +0000
@@ -73,7 +73,7 @@
 
 	if (str_to_uint32(fname, &uid) < 0 || uid == 0) {
 		i_warning("sdbox %s: Ignoring invalid filename %s",
-			  ctx->box->path, fname);
+			  mailbox_get_path(ctx->box), fname);
 		return 0;
 	}
 
@@ -146,14 +146,15 @@
 static int
 sdbox_sync_index_rebuild_singles(struct dbox_sync_rebuild_context *ctx)
 {
-	const char *alt_path;
+	const char *path, *alt_path;
 	int ret = 0;
 
+	path = mailbox_get_path(ctx->box);
 	alt_path = mailbox_list_get_path(ctx->box->list, ctx->box->name,
 					 MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
 
 	sdbox_sync_set_uidvalidity(ctx);
-	if (sdbox_sync_index_rebuild_dir(ctx, ctx->box->path, TRUE) < 0)
+	if (sdbox_sync_index_rebuild_dir(ctx, path, TRUE) < 0)
 		ret = -1;
 	else if (alt_path != NULL)
 		ret = sdbox_sync_index_rebuild_dir(ctx, alt_path, FALSE);
--- a/src/lib-storage/index/dbox-single/sdbox-sync.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/dbox-single/sdbox-sync.c	Sun Dec 05 23:18:55 2010 +0000
@@ -202,12 +202,12 @@
 			if (i >= SDBOX_REBUILD_COUNT) {
 				mail_storage_set_critical(storage,
 					"sdbox %s: Index keeps breaking",
-					ctx->mbox->box.path);
+					mailbox_get_path(&ctx->mbox->box));
 				ret = -1;
 			} else {
 				/* do a full resync and try again. */
 				i_warning("sdbox %s: Rebuilding index",
-					  ctx->mbox->box.path);
+					  mailbox_get_path(&ctx->mbox->box));
 				rebuild = FALSE;
 				ret = sdbox_sync_index_rebuild(mbox,
 							       force_rebuild);
--- a/src/lib-storage/index/index-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/index-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -175,6 +175,9 @@
 		return -1;
 	}
 
+	/* make sure mail_index_set_permissions() has been called */
+	(void)mailbox_get_permissions(box);
+
 	ret = mail_index_open(box->index, index_flags);
 	if (ret <= 0 || move_to_memory) {
 		if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
@@ -221,7 +224,6 @@
 				 const char *index_prefix)
 {
 	struct index_mailbox_context *ibox;
-	const char *path;
 	string_t *vname;
 
 	i_assert(name != NULL);
@@ -242,19 +244,11 @@
 	ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
 	MODULE_CONTEXT_SET(box, index_storage_module, ibox);
 
-	path = mailbox_list_get_path(box->list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	box->path = p_strdup(box->pool, path);
 	box->index = index_storage_alloc(box->list, name, flags, index_prefix);
 	box->inbox_user = strcmp(name, "INBOX") == 0 &&
 		(box->list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
 	box->inbox_any = strcmp(name, "INBOX") == 0 &&
 		(box->list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0;
-	if (box->file_create_mode == 0)
-		mailbox_refresh_permissions(box);
-	mail_index_set_permissions(box->index, box->file_create_mode,
-				   box->file_create_gid,
-				   box->file_create_gid_origin);
 	mail_index_set_fsync_mode(box->index,
 				  box->storage->set->parsed_fsync_mode, 0);
 	mail_index_set_lock_method(box->index,
--- a/src/lib-storage/index/maildir/maildir-copy.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Sun Dec 05 23:18:55 2010 +0000
@@ -83,7 +83,8 @@
 	dest_fname = maildir_filename_generate();
 	memset(&do_ctx, 0, sizeof(do_ctx));
 	do_ctx.dest_path =
-		t_strdup_printf("%s/tmp/%s", dest_mbox->box.path, dest_fname);
+		t_strdup_printf("%s/tmp/%s", mailbox_get_path(&dest_mbox->box),
+				dest_fname);
 	if (src_mbox != NULL) {
 		/* maildir */
 		if (maildir_file_do(src_mbox, mail->uid,
--- a/src/lib-storage/index/maildir/maildir-keywords.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-keywords.c	Sun Dec 05 23:18:55 2010 +0000
@@ -290,6 +290,7 @@
 {
 	struct maildir_mailbox *mbox = mk->mbox;
 	struct mailbox *box = &mbox->box;
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *const *keywords;
 	unsigned int i, count;
 	string_t *str;
@@ -313,14 +314,14 @@
 		return -1;
 	}
 
-	if (st.st_gid != box->file_create_gid &&
-	    box->file_create_gid != (gid_t)-1) {
-		if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
+	if (st.st_gid != perm->file_create_gid &&
+	    perm->file_create_gid != (gid_t)-1) {
+		if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
 			if (errno == EPERM) {
 				mail_storage_set_critical(mk->storage, "%s",
 					eperm_error_get_chgrp("fchown", path,
-						box->file_create_gid,
-						box->file_create_gid_origin));
+						perm->file_create_gid,
+						perm->file_create_gid_origin));
 			} else {
 				mail_storage_set_critical(mk->storage,
 					"fchown(%s) failed: %m", path);
@@ -353,6 +354,7 @@
 
 static int maildir_keywords_commit(struct maildir_keywords *mk)
 {
+	const struct mailbox_permissions *perm;
 	struct dotlock *dotlock;
 	const char *lock_path;
 	mode_t old_mask;
@@ -366,11 +368,12 @@
 	lock_path = t_strconcat(mk->path, ".lock", NULL);
 	(void)unlink(lock_path);
 
+	perm = mailbox_get_permissions(&mk->mbox->box);
 	for (i = 0;; i++) {
 		/* we could just create the temp file directly, but doing it
 		   this ways avoids potential problems with overwriting
 		   contents in malicious symlinks */
-		old_mask = umask(0777 & ~mk->mbox->box.file_create_mode);
+		old_mask = umask(0777 & ~perm->file_create_mode);
 		fd = file_dotlock_open(&mk->dotlock_settings, mk->path,
 				       DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock);
 		umask(old_mask);
--- a/src/lib-storage/index/maildir/maildir-mail.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-mail.c	Sun Dec 05 23:18:55 2010 +0000
@@ -598,7 +598,7 @@
 				"new" : "cur";
 			mail_storage_set_critical(_mail->box->storage,
 				"Maildir filename has wrong W value: %s/%s/%s",
-				mbox->box.path, subdir, fname);
+				mailbox_get_path(&mbox->box), 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	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-save.c	Sun Dec 05 23:18:55 2010 +0000
@@ -117,6 +117,7 @@
 {
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->box;
 	struct maildir_save_context *ctx;
+	const char *path;
 	pool_t pool;
 
 	pool = pool_alloconly_create("maildir_save_context", 4096);
@@ -128,9 +129,10 @@
 	ctx->files_tail = &ctx->files;
 	ctx->fd = -1;
 
-	ctx->tmpdir = p_strconcat(pool, mbox->box.path, "/tmp", NULL);
-	ctx->newdir = p_strconcat(pool, mbox->box.path, "/new", NULL);
-	ctx->curdir = p_strconcat(pool, mbox->box.path, "/cur", NULL);
+	path = mailbox_get_path(&mbox->box);
+	ctx->tmpdir = p_strconcat(pool, path, "/tmp", NULL);
+	ctx->newdir = p_strconcat(pool, path, "/new", NULL);
+	ctx->curdir = p_strconcat(pool, path, "/cur", NULL);
 
 	buffer_create_const_data(&ctx->keywords_buffer, NULL, 0);
 	array_create_from_buffer(&ctx->keywords_array, &ctx->keywords_buffer,
@@ -323,6 +325,7 @@
 			      const char **fname_r)
 {
 	struct mailbox *box = &mbox->box;
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	unsigned int prefix_len;
 	const char *tmp_fname;
 	string_t *path;
@@ -343,7 +346,7 @@
 		   might return an existing filename is if the time moved
 		   backwards. so we'll use O_EXCL anyway, although it's mostly
 		   useless. */
-		old_mask = umask(0777 & ~box->file_create_mode);
+		old_mask = umask(0777 & ~perm->file_create_mode);
 		fd = open(str_c(path),
 			  O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0777);
 		umask(old_mask);
@@ -358,14 +361,14 @@
 			mail_storage_set_critical(box->storage,
 				"open(%s) failed: %m", str_c(path));
 		}
-	} else if (box->file_create_gid != (gid_t)-1) {
-		if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
+	} else if (perm->file_create_gid != (gid_t)-1) {
+		if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
 			if (errno == EPERM) {
 				mail_storage_set_critical(box->storage, "%s",
 					eperm_error_get_chgrp("fchown",
 						str_c(path),
-						box->file_create_gid,
-						box->file_create_gid_origin));
+						perm->file_create_gid,
+						perm->file_create_gid_origin));
 			} else {
 				mail_storage_set_critical(box->storage,
 					"fchown(%s) failed: %m", str_c(path));
--- a/src/lib-storage/index/maildir/maildir-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -233,16 +233,18 @@
 /* create or fix maildir, ignore if it already exists */
 static int create_maildir(struct mailbox *box, bool verify)
 {
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *path;
 	unsigned int i;
 	enum mail_error error;
 	int ret = 0;
 
 	for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
-		path = t_strconcat(box->path, "/", maildir_subdirs[i], NULL);
+		path = t_strconcat(mailbox_get_path(box), "/",
+				   maildir_subdirs[i], NULL);
 		if (mkdir_verify(box->storage, box->list->ns, path,
-				 box->dir_create_mode, box->file_create_gid,
-				 box->file_create_gid_origin, verify) < 0) {
+				 perm->dir_create_mode, perm->file_create_gid,
+				 perm->file_create_gid_origin, verify) < 0) {
 			(void)mail_storage_get_last_error(box->storage, &error);
 			if (error != MAIL_ERROR_EXISTS)
 				return -1;
@@ -293,13 +295,13 @@
 static int maildir_mailbox_open_existing(struct mailbox *box)
 {
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
+	const char *shared_path, *box_path = mailbox_get_path(box);
 	struct stat st;
-	const char *shared_path;
 
 	mbox->uidlist = maildir_uidlist_init(mbox);
 	mbox->keywords = maildir_keywords_init(mbox);
 
-	shared_path = t_strconcat(box->path, "/dovecot-shared", NULL);
+	shared_path = t_strconcat(box_path, "/dovecot-shared", NULL);
 	if (stat(shared_path, &st) == 0)
 		box->private_flags_mask = MAIL_SEEN;
 
@@ -311,7 +313,7 @@
 						 mbox);
 	}
 
-	if (access(t_strconcat(box->path, "/cur", NULL), W_OK) < 0 &&
+	if (access(t_strconcat(box_path, "/cur", NULL), W_OK) < 0 &&
 	    errno == EACCES)
 		mbox->box.backend_readonly = TRUE;
 	return index_storage_mailbox_open(box, FALSE);
@@ -319,13 +321,14 @@
 
 static int maildir_mailbox_open(struct mailbox *box)
 {
+	const char *box_path = mailbox_get_path(box);
 	const char *root_dir;
 	struct stat st;
 	int ret;
 
 	/* begin by checking if tmp/ directory exists and if it should be
 	   cleaned up. */
-	ret = maildir_check_tmp(box->storage, box->path);
+	ret = maildir_check_tmp(box->storage, box_path);
 	if (ret > 0) {
 		/* exists */
 		return maildir_mailbox_open_existing(box);
@@ -336,10 +339,10 @@
 	/* tmp/ directory doesn't exist. does the maildir? */
 	root_dir = mailbox_list_get_path(box->list, NULL,
 					 MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (strcmp(box->path, root_dir) == 0) {
+	if (strcmp(box_path, root_dir) == 0) {
 		/* root directory. either INBOX or some other namespace root */
 		errno = ENOENT;
-	} else if (stat(box->path, &st) == 0) {
+	} else if (stat(box_path, &st) == 0) {
 		/* yes, we'll need to create the missing dirs */
 		if (create_maildir(box, TRUE) < 0)
 			return -1;
@@ -353,20 +356,21 @@
 		return -1;
 	} else {
 		mail_storage_set_critical(box->storage,
-					  "stat(%s) failed: %m", box->path);
+					  "stat(%s) failed: %m", box_path);
 		return -1;
 	}
 }
 
 static int maildir_create_shared(struct mailbox *box)
 {
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *path;
 	mode_t old_mask;
 	int fd;
 
 	old_mask = umask(0);
-	path = t_strconcat(box->path, "/dovecot-shared", NULL);
-	fd = open(path, O_WRONLY | O_CREAT, box->file_create_mode);
+	path = t_strconcat(mailbox_get_path(box), "/dovecot-shared", NULL);
+	fd = open(path, O_WRONLY | O_CREAT, perm->file_create_mode);
 	umask(old_mask);
 
 	if (fd == -1) {
@@ -375,12 +379,12 @@
 		return -1;
 	}
 
-	if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
+	if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
 		if (errno == EPERM) {
 			mail_storage_set_critical(box->storage, "%s",
 				eperm_error_get_chgrp("fchown", path,
-					box->file_create_gid,
-					box->file_create_gid_origin));
+					perm->file_create_gid,
+					perm->file_create_gid_origin));
 		} else {
 			mail_storage_set_critical(box->storage,
 				"fchown(%s) failed: %m", path);
@@ -433,7 +437,7 @@
 	    (box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) == 0)
 		return 0;
 
-	ret = maildir_check_tmp(box->storage, box->path);
+	ret = maildir_check_tmp(box->storage, mailbox_get_path(box));
 	if (ret > 0) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
 				       "Mailbox already exists");
@@ -486,14 +490,15 @@
 static void maildir_notify_changes(struct mailbox *box)
 {
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
+	const char *box_path = mailbox_get_path(box);
 
 	if (box->notify_callback == NULL)
 		index_mailbox_check_remove_all(&mbox->box);
 	else {
 		index_mailbox_check_add(&mbox->box,
-			t_strconcat(mbox->box.path, "/new", NULL));
+			t_strconcat(box_path, "/new", NULL));
 		index_mailbox_check_add(&mbox->box,
-			t_strconcat(mbox->box.path, "/cur", NULL));
+			t_strconcat(box_path, "/cur", NULL));
 	}
 }
 
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Sun Dec 05 23:18:55 2010 +0000
@@ -206,7 +206,7 @@
 	maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
 
 	i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
-		  "(old uid=%u, file=%s)%s", ctx->mbox->box.path,
+		  "(old uid=%u, file=%s)%s", mailbox_get_path(&ctx->mbox->box),
 		  uid, filename, strncmp(filename, "msg.", 4) != 0 ? "" :
 		  " (Your MDA is saving MH files into Maildir?)");
 	return 0;
@@ -278,12 +278,13 @@
 maildir_sync_index_update_ext_header(struct maildir_index_sync_context *ctx)
 {
 	struct maildir_mailbox *mbox = ctx->mbox;
+	const char *cur_path;
 	const void *data;
 	size_t data_size;
 	struct stat st;
 
-	if (ctx->update_maildir_hdr_cur &&
-	    stat(t_strconcat(mbox->box.path, "/cur", NULL), &st) == 0) {
+	cur_path = t_strconcat(mailbox_get_path(&mbox->box), "/cur", NULL);
+	if (ctx->update_maildir_hdr_cur && stat(cur_path, &st) == 0) {
 		if ((time_t)mbox->maildir_hdr.cur_check_time < st.st_mtime)
 			mbox->maildir_hdr.cur_check_time = st.st_mtime;
 		mbox->maildir_hdr.cur_mtime = st.st_mtime;
@@ -312,7 +313,7 @@
 		i_warning("Maildir %s: Synchronization took %u seconds "
 			  "(%u new msgs, %u flag change attempts, "
 			  "%u expunge attempts)",
-			  ctx->mbox->box.path, time_diff,
+			  mailbox_get_path(&ctx->mbox->box), time_diff,
 			  ctx->new_msgs_count, ctx->flag_change_count,
 			  ctx->expunge_count);
 	}
@@ -479,7 +480,8 @@
 		   first time, reset the index so we can add all messages as
 		   new */
 		i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
-			  mbox->box.path, hdr->uid_validity, uid_validity);
+			  mailbox_get_path(&ctx->mbox->box),
+			  hdr->uid_validity, uid_validity);
 		mail_index_reset(trans);
 		index_mailbox_reset_uidvalidity(&mbox->box);
 
--- a/src/lib-storage/index/maildir/maildir-sync.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Sun Dec 05 23:18:55 2010 +0000
@@ -255,8 +255,8 @@
 
 	ctx = t_new(struct maildir_sync_context, 1);
 	ctx->mbox = mbox;
-	ctx->new_dir = t_strconcat(mbox->box.path, "/new", NULL);
-	ctx->cur_dir = t_strconcat(mbox->box.path, "/cur", NULL);
+	ctx->new_dir = t_strconcat(mailbox_get_path(&mbox->box), "/new", NULL);
+	ctx->cur_dir = t_strconcat(mailbox_get_path(&mbox->box), "/cur", NULL);
 	ctx->last_touch = ioloop_time;
 	ctx->last_notify = ioloop_time;
 	ctx->flags = flags;
@@ -319,7 +319,8 @@
 	}
 
 	new_fname = maildir_filename_generate();
-	new_path = t_strconcat(ctx->mbox->box.path, "/new/", new_fname, NULL);
+	new_path = t_strconcat(mailbox_get_path(&ctx->mbox->box),
+			       "/new/", new_fname, NULL);
 
 	if (rename(path2, new_path) == 0)
 		i_warning("Fixed a duplicate: %s -> %s", path2, new_fname);
@@ -1017,10 +1018,11 @@
 	int ret;
 
 	T_BEGIN {
+		const char *box_path = mailbox_get_path(&mbox->box);
 		const char *new_dir, *cur_dir;
 
-		new_dir = t_strconcat(mbox->box.path, "/new", NULL);
-		cur_dir = t_strconcat(mbox->box.path, "/cur", NULL);
+		new_dir = t_strconcat(box_path, "/new", NULL);
+		cur_dir = t_strconcat(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	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Sun Dec 05 23:18:55 2010 +0000
@@ -136,6 +136,7 @@
 					bool refresh_when_locked)
 {
 	struct mailbox *box = uidlist->box;
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *control_dir, *path;
 	mode_t old_mask;
 	const enum dotlock_create_flags dotlock_flags =
@@ -158,7 +159,7 @@
 	path = t_strconcat(control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
 
 	for (i = 0;; i++) {
-		old_mask = umask(0777 & ~box->file_create_mode);
+		old_mask = umask(0777 & ~perm->file_create_mode);
 		ret = file_dotlock_create(&uidlist->dotlock_settings, path,
 					  dotlock_flags, &uidlist->dotlock);
 		umask(old_mask);
@@ -1351,6 +1352,7 @@
 static int maildir_uidlist_recreate(struct maildir_uidlist *uidlist)
 {
 	struct mailbox *box = uidlist->box;
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *control_dir, *temp_path;
 	struct stat st;
 	mode_t old_mask;
@@ -1367,7 +1369,7 @@
 				"/" MAILDIR_UIDLIST_NAME ".tmp", NULL);
 
 	for (i = 0;; i++) {
-		old_mask = umask(0777 & ~box->file_create_mode);
+		old_mask = umask(0777 & ~perm->file_create_mode);
 		fd = open(temp_path, O_RDWR | O_CREAT | O_TRUNC, 0777);
 		umask(old_mask);
 		if (fd != -1)
@@ -1384,13 +1386,13 @@
 			return -1;
 	}
 
-	if (box->file_create_gid != (gid_t)-1 &&
-	    fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
+	if (perm->file_create_gid != (gid_t)-1 &&
+	    fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
 		if (errno == EPERM) {
 			mail_storage_set_critical(box->storage, "%s",
 				eperm_error_get_chgrp("fchown", temp_path,
-						box->file_create_gid,
-						box->file_create_gid_origin));
+						perm->file_create_gid,
+						perm->file_create_gid_origin));
 		} else {
 			mail_storage_set_critical(box->storage,
 				"fchown(%s) failed: %m", temp_path);
--- a/src/lib-storage/index/maildir/maildir-util.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/maildir/maildir-util.c	Sun Dec 05 23:18:55 2010 +0000
@@ -76,13 +76,14 @@
 
 	if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
 		/* probably in new/ dir */
-		path = t_strconcat(mbox->box.path, "/new/", fname, NULL);
+		path = t_strconcat(mailbox_get_path(&mbox->box),
+				   "/new/", fname, NULL);
 		ret = callback(mbox, path, context);
 		if (ret != 0)
 			return ret;
 	}
 
-	path = t_strconcat(mbox->box.path, "/cur/", fname, NULL);
+	path = t_strconcat(mailbox_get_path(&mbox->box), "/cur/", fname, NULL);
 	ret = callback(mbox, path, context);
 	return ret;
 }
@@ -135,10 +136,11 @@
 static int maildir_create_path(struct mailbox *box, const char *path,
 			       enum mailbox_list_path_type type, bool retry)
 {
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	const char *p, *parent;
 
-	if (mkdir_chgrp(path, box->dir_create_mode, box->file_create_gid,
-			box->file_create_gid_origin) == 0)
+	if (mkdir_chgrp(path, perm->dir_create_mode, perm->file_create_gid,
+			perm->file_create_gid_origin) == 0)
 		return 0;
 
 	switch (errno) {
@@ -179,7 +181,8 @@
 	/* @UNSAFE: get a list of directories we want to create */
 	for (i = 0; i < N_ELEMENTS(subdirs); i++) {
 		types[i] = MAILBOX_LIST_PATH_TYPE_MAILBOX;
-		dirs[i] = t_strconcat(box->path, "/", subdirs[i], NULL);
+		dirs[i] = t_strconcat(mailbox_get_path(box),
+				      "/", subdirs[i], NULL);
 	}
 	types[i] = MAILBOX_LIST_PATH_TYPE_CONTROL;
 	dirs[i++] = mailbox_list_get_path(box->list, box->name,
@@ -209,12 +212,12 @@
 	struct stat st;
 	int ret;
 
-	if (stat(box->path, &st) < 0) {
+	if (stat(mailbox_get_path(box), &st) < 0) {
 		if (errno == ENOENT)
 			mailbox_set_deleted(box);
 		else {
 			mail_storage_set_critical(box->storage,
-				"stat(%s) failed: %m", box->path);
+				"stat(%s) failed: %m", mailbox_get_path(box));
 		}
 		return FALSE;
 	}
--- a/src/lib-storage/index/mbox/mbox-file.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/mbox/mbox-file.c	Sun Dec 05 23:18:55 2010 +0000
@@ -25,11 +25,11 @@
 		return 0;
 	}
 
-	fd = open(mbox->box.path,
+	fd = open(mailbox_get_path(&mbox->box),
 		  mbox->box.backend_readonly ? O_RDONLY : O_RDWR);
 	if (fd == -1 && errno == EACCES && !mbox->box.backend_readonly) {
                 mbox->box.backend_readonly = TRUE;
-		fd = open(mbox->box.path, O_RDONLY);
+		fd = open(mailbox_get_path(&mbox->box), O_RDONLY);
 	}
 
 	if (fd == -1) {
@@ -86,7 +86,8 @@
 			i_stream_set_init_buffer_size(mbox->mbox_file_stream,
 						      MBOX_READ_BLOCK_SIZE);
 		}
-		i_stream_set_name(mbox->mbox_file_stream, mbox->box.path);
+		i_stream_set_name(mbox->mbox_file_stream,
+				  mailbox_get_path(&mbox->box));
 	}
 
 	mbox->mbox_stream = i_stream_create_raw_mbox(mbox->mbox_file_stream);
@@ -115,7 +116,8 @@
 			buf.modtime = st.st_mtime;
 			buf.actime = buf.modtime - 1;
 			/* EPERM can happen with shared mailboxes */
-			if (utime(mbox->box.path, &buf) < 0 && errno != EPERM)
+			if (utime(mailbox_get_path(&mbox->box), &buf) < 0 &&
+			    errno != EPERM)
 				mbox_set_syscall_error(mbox, "utime()");
 		}
 	}
@@ -153,7 +155,7 @@
 	if (data == NULL) {
 		mail_storage_set_critical(&mbox->storage->storage,
 			"Cached message offset lost for seq %u in mbox file %s",
-			seq, mbox->box.path);
+			seq, mailbox_get_path(&mbox->box));
                 mbox->mbox_hdr.dirty_flag = TRUE;
                 mbox->mbox_broken_offsets = TRUE;
 		return 0;
@@ -190,7 +192,7 @@
 
 		mail_storage_set_critical(&mbox->storage->storage,
 			"Cached message offset %s is invalid for mbox file %s",
-			dec2str(offset), mbox->box.path);
+			dec2str(offset), mailbox_get_path(&mbox->box));
 		mbox->mbox_hdr.dirty_flag = TRUE;
 		mbox->mbox_broken_offsets = TRUE;
 		return 0;
--- a/src/lib-storage/index/mbox/mbox-lock.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Sun Dec 05 23:18:55 2010 +0000
@@ -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->box.path, &st) < 0) {
+		if (nfs_safe_stat(mailbox_get_path(&mbox->box), &st) < 0) {
 			if (errno == ENOENT)
 				mailbox_set_deleted(&mbox->box);
 			else
@@ -250,7 +250,7 @@
 				      struct dotlock_settings *set,
 				      enum mbox_dotlock_op op)
 {
-	const char *dir, *fname;
+	const char *box_path, *dir, *fname;
 	int ret = -1, orig_dir_fd, orig_errno;
 
 	orig_dir_fd = open(".", O_RDONLY);
@@ -268,12 +268,13 @@
 	      privileged group
 	    - DoS other users by dotlocking their mailboxes infinitely
 	*/
-	fname = strrchr(mbox->box.path, '/');
+	box_path = mailbox_get_path(&mbox->box);
+	fname = strrchr(box_path, '/');
 	if (fname == NULL) {
 		/* already relative */
-		fname = mbox->box.path;
+		fname = box_path;
 	} else {
-		dir = t_strdup_until(mbox->box.path, fname);
+		dir = t_strdup_until(box_path, fname);
 		if (chdir(dir) < 0) {
 			mail_storage_set_critical(&mbox->storage->storage,
 				"chdir(%s) failed: %m", dir);
@@ -285,7 +286,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->box.path);
+				"access(%s) failed: %m", box_path);
 			return -1;
 		}
 	}
@@ -415,7 +416,7 @@
 	set.callback = dotlock_callback;
 	set.context = ctx;
 
-	ret = file_dotlock_create(&set, mbox->box.path, 0,
+	ret = file_dotlock_create(&set, mailbox_get_path(&mbox->box), 0,
 				  &mbox->mbox_dotlock);
 	if (ret >= 0) {
 		/* success / timeout */
@@ -425,7 +426,7 @@
 		ret = mbox_dotlock_privileged_op(mbox, &set,
 						 MBOX_DOTLOCK_OP_LOCK);
 	} else if (errno == EACCES)
-		mbox_dotlock_log_eacces_error(mbox, mbox->box.path);
+		mbox_dotlock_log_eacces_error(mbox, mailbox_get_path(&mbox->box));
 	else
 		mbox_set_syscall_error(mbox, "file_dotlock_create()");
 
@@ -635,7 +636,7 @@
 			mail_storage_set_critical(&ctx->mbox->storage->storage,
 				"fcntl() failed with mbox file %s: "
 				"File is locked by another process (EACCES)",
-				ctx->mbox->box.path);
+				mailbox_get_path(&ctx->mbox->box));
 			return -1;
 		}
 
@@ -772,7 +773,7 @@
 int mbox_lock(struct mbox_mailbox *mbox, int lock_type,
 	      unsigned int *lock_id_r)
 {
-	const char *path = mbox->box.path;
+	const char *path = mailbox_get_path(&mbox->box);
 	int mbox_fd = mbox->mbox_fd;
 	bool fcntl_locked;
 	int ret;
--- a/src/lib-storage/index/mbox/mbox-mail.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/mbox/mbox-mail.c	Sun Dec 05 23:18:55 2010 +0000
@@ -102,7 +102,7 @@
 	if (ret == 0) {
 		mail_storage_set_critical(&mbox->storage->storage,
 			"Losing sync for mail uid=%u in mbox file %s",
-			_mail->uid, mbox->box.path);
+			_mail->uid, mailbox_get_path(&mbox->box));
 	}
 	return 0;
 }
@@ -324,8 +324,8 @@
 		ret = mbox_mail_get_next_offset(mail, &next_offset);
 		if (ret < 0) {
 			i_warning("mbox %s: Can't find next message offset "
-				  "for uid=%u",
-				  mbox->box.path, mail->mail.mail.uid);
+				  "for uid=%u", mailbox_get_path(&mbox->box),
+				  mail->mail.mail.uid);
 		}
 	}
 	if (ret <= 0)
--- a/src/lib-storage/index/mbox/mbox-save.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/mbox/mbox-save.c	Sun Dec 05 23:18:55 2010 +0000
@@ -770,7 +770,8 @@
 
 		buf.modtime = st.st_mtime;
 		buf.actime = ctx->orig_atime;
-		if (utime(mbox->box.path, &buf) < 0 && errno != EPERM)
+		if (utime(mailbox_get_path(&mbox->box), &buf) < 0 &&
+		    errno != EPERM)
 			mbox_set_syscall_error(mbox, "utime()");
 	}
 
--- a/src/lib-storage/index/mbox/mbox-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -79,9 +79,8 @@
 		const char *toobig_error = errno != EFBIG ? "" :
 			" (process was started with ulimit -f limit)";
 		mail_storage_set_critical(&mbox->storage->storage,
-					  "%s failed with mbox file %s: %m%s",
-					  function, mbox->box.path,
-					  toobig_error);
+			"%s failed with mbox file %s: %m%s", function,
+			mailbox_get_path(&mbox->box), toobig_error);
 	}
 	return -1;
 }
@@ -391,24 +390,24 @@
 static int mbox_mailbox_open_existing(struct mbox_mailbox *mbox)
 {
 	struct mailbox *box = &mbox->box;
-	const char *rootdir;
+	const char *rootdir, *box_path = mailbox_get_path(box);
 	bool move_to_memory;
 
-	if (access(box->path, R_OK|W_OK) < 0) {
+	if (access(box_path, R_OK|W_OK) < 0) {
 		if (errno != EACCES) {
 			mbox_set_syscall_error(mbox, "access()");
 			return -1;
 		}
 		mbox->box.backend_readonly = TRUE;
 	}
-	move_to_memory = want_memory_indexes(mbox->storage, box->path);
+	move_to_memory = want_memory_indexes(mbox->storage, box_path);
 
 	if (box->inbox_any || 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(box->list, NULL,
 						MAILBOX_LIST_PATH_TYPE_DIR);
-		if (strncmp(box->path, rootdir, strlen(rootdir)) != 0)
+		if (strncmp(box_path, rootdir, strlen(rootdir)) != 0)
 			mbox->mbox_privileged_locking = TRUE;
 	}
 	if ((box->flags & MAILBOX_FLAG_KEEP_LOCKED) != 0) {
@@ -438,9 +437,10 @@
 		return index_storage_mailbox_open(box, FALSE);
 	}
 
-	if ((ret = stat(box->path, &st)) == 0 && !S_ISDIR(st.st_mode))
-		return mbox_mailbox_open_existing(mbox);
-	else if (ret == 0) {
+	ret = stat(mailbox_get_path(box), &st);
+	if (ret == 0) {
+		if (!S_ISDIR(st.st_mode))
+			return mbox_mailbox_open_existing(mbox);
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
 				       "Mailbox isn't selectable");
 		return -1;
@@ -452,7 +452,7 @@
 		return -1;
 	} else {
 		mail_storage_set_critical(box->storage,
-					  "stat(%s) failed: %m", box->path);
+			"stat(%s) failed: %m", mailbox_get_path(box));
 		return -1;
 	}
 }
@@ -523,7 +523,7 @@
 			return -1;
 	} else {
 		/* create the mbox file */
-		ret = mailbox_create_fd(box, box->path,
+		ret = mailbox_create_fd(box, mailbox_get_path(box),
 					O_RDWR | O_CREAT | O_EXCL, &fd);
 		if (ret < 0)
 			return -1;
@@ -596,9 +596,9 @@
 	struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
 
 	if (box->notify_callback == NULL)
-		index_mailbox_check_remove_all(&mbox->box);
+		index_mailbox_check_remove_all(box);
 	else if (!mbox->no_mbox_file)
-		index_mailbox_check_add(&mbox->box, mbox->box.path);
+		index_mailbox_check_add(box, mailbox_get_path(box));
 }
 
 static bool
--- a/src/lib-storage/index/mbox/mbox-sync.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Sun Dec 05 23:18:55 2010 +0000
@@ -73,13 +73,13 @@
 		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->box.path);
+			mailbox_get_path(&sync_ctx->mbox->box));
 	}
 
 	va_start(va, fmt);
 	mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
 				  "Sync failed for mbox file %s: %s",
-				  sync_ctx->mbox->box.path,
+				  mailbox_get_path(&sync_ctx->mbox->box),
 				  t_strdup_vprintf(fmt, va));
 	va_end(va);
 }
@@ -991,7 +991,7 @@
 		i_warning("UIDVALIDITY changed (%u -> %u) in mbox file %s",
 			  sync_ctx->hdr->uid_validity,
 			  sync_ctx->base_uid_validity,
-			  sync_ctx->mbox->box.path);
+			  mailbox_get_path(&sync_ctx->mbox->box));
 		sync_ctx->index_reset = TRUE;
 		return TRUE;
 	}
@@ -1114,7 +1114,7 @@
 					&sync_ctx->mbox->storage->storage,
 					"Out of UIDs, renumbering them in mbox "
 					"file %s",
-					sync_ctx->mbox->box.path);
+					mailbox_get_path(&sync_ctx->mbox->box));
 				sync_ctx->renumber_uids = TRUE;
 				return 0;
 			}
@@ -1429,7 +1429,7 @@
 		   quite minimal (an extra logged error message). */
 		while (sync_ctx->orig_mtime == st->st_mtime) {
 			usleep(500000);
-			if (utime(sync_ctx->mbox->box.path, NULL) < 0) {
+			if (utime(mailbox_get_path(&sync_ctx->mbox->box), NULL) < 0) {
 				mbox_set_syscall_error(sync_ctx->mbox,
 						       "utime()");
 				return -1;
@@ -1678,7 +1678,7 @@
 			return -1;
 		}
 	} else {
-		if (stat(mbox->box.path, &statbuf) < 0) {
+		if (stat(mailbox_get_path(&mbox->box), &statbuf) < 0) {
 			if (errno == ENOENT) {
 				mailbox_set_deleted(&mbox->box);
 				return 0;
@@ -1915,7 +1915,8 @@
 		else {
 			buf.modtime = st.st_mtime;
 			buf.actime = sync_ctx.orig_atime;
-			if (utime(mbox->box.path, &buf) < 0 && errno != EPERM)
+			if (utime(mailbox_get_path(&mbox->box), &buf) < 0 &&
+			    errno != EPERM)
 				mbox_set_syscall_error(mbox, "utime()");
 		}
 	}
--- a/src/lib-storage/index/raw/raw-mail.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/raw/raw-mail.c	Sun Dec 05 23:18:55 2010 +0000
@@ -22,7 +22,8 @@
 	st = i_stream_stat(mail->box->input, TRUE);
 	if (st == NULL) {
 		mail_storage_set_critical(mail->box->storage,
-			"stat(%s) failed: %m", mail->box->path);
+					  "stat(%s) failed: %m",
+					  i_stream_get_name(mail->box->input));
 		return -1;
 	}
 
@@ -103,7 +104,8 @@
 		*value_r = mbox->envelope_sender;
 		return 0;
 	case MAIL_FETCH_UIDL_FILE_NAME:
-		*value_r = mbox->have_filename ? _mail->box->path : "";
+		*value_r = mbox->have_filename ?
+			mailbox_get_path(_mail->box) : "";
 		return 0;
 	default:
 		return index_mail_get_special(_mail, field, value_r);
--- a/src/lib-storage/index/raw/raw-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/index/raw/raw-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -62,6 +62,7 @@
 static int raw_mailbox_open(struct mailbox *box)
 {
 	struct raw_mailbox *mbox = (struct raw_mailbox *)box;
+	const char *path;
 	int fd;
 
 	if (box->input != NULL) {
@@ -69,9 +70,9 @@
 		return index_storage_mailbox_open(box, FALSE);
 	}
 
-	box->path = box->name;
+	path = box->_path = box->name;
 	mbox->have_filename = TRUE;
-	fd = open(box->path, O_RDONLY);
+	fd = open(path, O_RDONLY);
 	if (fd == -1) {
 		if (ENOTFOUND(errno)) {
 			mail_storage_set_error(box->storage,
@@ -79,12 +80,12 @@
 				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);
+				"open(%s) failed: %m", path);
 		}
 		return -1;
 	}
 	box->input = i_stream_create_fd(fd, MAIL_READ_FULL_BLOCK_SIZE, TRUE);
-	i_stream_set_name(box->input, box->path);
+	i_stream_set_name(box->input, path);
 	i_stream_set_init_buffer_size(box->input, MAIL_READ_FULL_BLOCK_SIZE);
 	return index_storage_mailbox_open(box, FALSE);
 }
--- a/src/lib-storage/mail-copy.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/mail-copy.c	Sun Dec 05 23:18:55 2010 +0000
@@ -78,7 +78,12 @@
 bool mail_storage_copy_can_use_hardlink(struct mailbox *src,
 					struct mailbox *dest)
 {
-	return src->file_create_mode == dest->file_create_mode &&
-		src->file_create_gid == dest->file_create_gid &&
+	const struct mailbox_permissions *src_perm =
+		mailbox_get_permissions(src);
+	const struct mailbox_permissions *dest_perm =
+		mailbox_get_permissions(dest);
+
+	return src_perm->file_create_mode == dest_perm->file_create_mode &&
+		src_perm->file_create_gid == dest_perm->file_create_gid &&
 		!dest->disable_reflink_copy_to;
 }
--- a/src/lib-storage/mail-storage-private.h	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/mail-storage-private.h	Sun Dec 05 23:18:55 2010 +0000
@@ -224,6 +224,14 @@
 	struct mail_storage_module_register *reg;
 };
 
+struct mailbox_permissions {
+	/* mode and GID to use for newly created files/dirs */
+	mode_t file_create_mode, dir_create_mode;
+	gid_t file_create_gid;
+	/* origin (e.g. path) where the file_create_gid was got from */
+	const char *file_create_gid_origin;
+};
+
 struct mailbox {
 	const char *name;
 	struct mail_storage *storage;
@@ -233,15 +241,18 @@
 /* private: */
 	pool_t pool;
 
+	/* these won't be set until mailbox is opened: */
 	struct mail_index *index;
 	struct mail_index_view *view;
 	struct mail_cache *cache;
+	/* Filled lazily by mailbox_get_permissions() */
+	struct mailbox_permissions _perm;
+	/* Filled lazily by mailbox_get_path() */
+	const char *_path;
 
 	/* default vfuncs for new struct mails. */
 	const struct mail_vfuncs *mail_vfuncs;
 
-	/* mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX */
-	const char *path;
 	/* mailbox's virtual name (from mail_namespace_get_vname()) */
 	const char *vname;
 	struct istream *input;
@@ -252,12 +263,6 @@
 	/* User's private flags if this is a shared mailbox */
 	enum mail_flags private_flags_mask;
 
-	/* mode and GID to use for newly created files/dirs */
-	mode_t file_create_mode, dir_create_mode;
-	gid_t file_create_gid;
-	/* origin (e.g. path) where the file_create_gid was got from */
-	const char *file_create_gid_origin;
-
 	/* Mailbox notification settings: */
 	unsigned int notify_min_interval;
 	mailbox_notify_callback_t *notify_callback;
@@ -491,6 +496,11 @@
 void mail_set_expunged(struct mail *mail);
 void mailbox_set_deleted(struct mailbox *box);
 int mailbox_mark_index_deleted(struct mailbox *box, bool del);
+/* Easy wrapper for getting mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX */
+const char *mailbox_get_path(struct mailbox *box) ATTR_PURE;
+/* Get mailbox permissions. */
+const struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box);
+/* Force permissions to be refreshed on next lookup */
 void mailbox_refresh_permissions(struct mailbox *box);
 
 /* Returns -1 if error, 0 if failed with EEXIST, 1 if ok */
--- a/src/lib-storage/mail-storage.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/lib-storage/mail-storage.c	Sun Dec 05 23:18:55 2010 +0000
@@ -1458,42 +1458,66 @@
 	box->mailbox_deleted = TRUE;
 }
 
-void mailbox_refresh_permissions(struct mailbox *box)
+const char *mailbox_get_path(struct mailbox *box)
+{
+	const char *path;
+
+	if (box->_path == NULL) {
+		path = mailbox_list_get_path(box->list, box->name,
+					     MAILBOX_LIST_PATH_TYPE_MAILBOX);
+		box->_path = p_strdup(box->pool, path);
+	}
+	return box->_path;
+}
+
+const struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box)
 {
 	const char *origin, *dir_origin;
 	gid_t dir_gid;
 
+	if (box->_perm.file_create_mode != 0)
+		return &box->_perm;
+
 	if (box->input != NULL) {
-		box->file_create_mode = 0600;
-		box->dir_create_mode = 0700;
-		box->file_create_gid = (gid_t)-1;
-		box->file_create_gid_origin = "defaults";
-		return;
+		box->_perm.file_create_mode = 0600;
+		box->_perm.dir_create_mode = 0700;
+		box->_perm.file_create_gid = (gid_t)-1;
+		box->_perm.file_create_gid_origin = "defaults";
+		return &box->_perm;
 	}
 
 	mailbox_list_get_permissions(box->list, box->name,
-				     &box->file_create_mode,
-				     &box->file_create_gid, &origin);
+				     &box->_perm.file_create_mode,
+				     &box->_perm.file_create_gid, &origin);
+	mail_index_set_permissions(box->index, box->_perm.file_create_mode,
+				   box->_perm.file_create_gid, origin);
 
-	box->file_create_gid_origin = p_strdup(box->pool, origin);
+	box->_perm.file_create_gid_origin = p_strdup(box->pool, origin);
 	mailbox_list_get_dir_permissions(box->list, box->name,
-					 &box->dir_create_mode,
+					 &box->_perm.dir_create_mode,
 					 &dir_gid, &dir_origin);
+	return &box->_perm;
+}
+
+void mailbox_refresh_permissions(struct mailbox *box)
+{
+	memset(&box->_perm, 0, sizeof(box->_perm));
+	(void)mailbox_get_permissions(box);
 }
 
 int mailbox_create_fd(struct mailbox *box, const char *path, int flags,
 		      int *fd_r)
 {
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	mode_t old_mask;
 	int fd;
 
-	i_assert(box->file_create_mode != 0);
 	i_assert((flags & O_CREAT) != 0);
 
 	*fd_r = -1;
 
 	old_mask = umask(0);
-	fd = open(path, flags, box->file_create_mode);
+	fd = open(path, flags, perm->file_create_mode);
 	umask(old_mask);
 
 	if (fd != -1) {
@@ -1516,14 +1540,14 @@
 		return -1;
 	}
 
-	if (box->file_create_gid != (gid_t)-1) {
-		if (fchown(fd, (uid_t)-1, box->file_create_gid) == 0) {
+	if (perm->file_create_gid != (gid_t)-1) {
+		if (fchown(fd, (uid_t)-1, perm->file_create_gid) == 0) {
 			/* ok */
 		} else if (errno == EPERM) {
 			mail_storage_set_critical(box->storage, "%s",
 				eperm_error_get_chgrp("fchown", path,
-					box->file_create_gid,
-					box->file_create_gid_origin));
+					perm->file_create_gid,
+					perm->file_create_gid_origin));
 		} else {
 			mail_storage_set_critical(box->storage,
 				"fchown(%s) failed: %m", path);
--- a/src/plugins/fts-squat/fts-backend-squat.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/plugins/fts-squat/fts-backend-squat.c	Sun Dec 05 23:18:55 2010 +0000
@@ -52,6 +52,7 @@
 
 static struct fts_backend *fts_backend_squat_init(struct mailbox *box)
 {
+	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
 	struct squat_fts_backend *backend;
 	struct mail_storage *storage;
 	struct mailbox_status status;
@@ -82,8 +83,8 @@
 		squat_trie_init(t_strconcat(path, "/"SQUAT_FILE_PREFIX, NULL),
 				status.uidvalidity,
 				storage->set->parsed_lock_method,
-				flags, box->file_create_mode,
-				box->file_create_gid);
+				flags, perm->file_create_mode,
+				perm->file_create_gid);
 
 	env = mail_user_plugin_getenv(box->storage->user, "fts_squat");
 	if (env != NULL)
--- a/src/plugins/virtual/virtual-config.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/plugins/virtual/virtual-config.c	Sun Dec 05 23:18:55 2010 +0000
@@ -327,23 +327,24 @@
 	struct mail_storage *storage = mbox->box.storage;
 	struct virtual_parse_context ctx;
 	struct stat st;
-	const char *path, *line, *error;
+	const char *box_path, *path, *line, *error;
 	unsigned int linenum = 0;
 	int fd, ret = 0;
 
 	i_array_init(&mbox->backend_boxes, 8);
 	mbox->search_args_crc32 = (uint32_t)-1;
 
-	path = t_strconcat(mbox->box.path, "/"VIRTUAL_CONFIG_FNAME, NULL);
+	box_path = mailbox_get_path(&mbox->box);
+	path = t_strconcat(box_path, "/"VIRTUAL_CONFIG_FNAME, NULL);
 	fd = open(path, O_RDONLY);
 	if (fd == -1) {
 		if (errno == EACCES) {
 			mail_storage_set_critical(storage, "%s",
-				mail_error_eacces_msg("stat", mbox->box.path));
+				mail_error_eacces_msg("open", path));
 		} else if (errno != ENOENT) {
 			mail_storage_set_critical(storage,
 						  "open(%s) failed: %m", path);
-		} else if (stat(mbox->box.path, &st) == 0) {
+		} else if (stat(box_path, &st) == 0) {
 			mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
 				"Virtual mailbox missing configuration file");
 		} else if (errno == ENOENT) {
@@ -351,7 +352,7 @@
 				T_MAIL_ERR_MAILBOX_NOT_FOUND(mbox->box.name));
 		} else {
 			mail_storage_set_critical(storage,
-				"stat(%s) failed: %m", mbox->box.path);
+				"stat(%s) failed: %m", box_path);
 		}
 		return -1;
 	}
--- a/src/plugins/virtual/virtual-sync.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/plugins/virtual/virtual-sync.c	Sun Dec 05 23:18:55 2010 +0000
@@ -148,6 +148,7 @@
 
 static int virtual_sync_ext_header_read(struct virtual_sync_context *ctx)
 {
+	const char *box_path = mailbox_get_path(&ctx->mbox->box);
 	const struct virtual_mail_index_header *ext_hdr;
 	const struct mail_index_header *hdr;
 	const struct virtual_mail_index_mailbox_record *mailboxes;
@@ -184,7 +185,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->box.path);
+				box_path);
 			ctx->index_broken = TRUE;
 			ext_mailbox_count = 0;
 			ret = 0;
@@ -199,18 +200,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->box.path);
+				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->box.path);
+				box_path);
 			break;
 		}
 		if (ext_name_offset + mailboxes[i].name_len > ext_size) {
 			i_error("virtual index %s: Broken mailbox list",
-				ctx->mbox->box.path);
+				box_path);
 			break;
 		}
 		T_BEGIN {
@@ -1444,7 +1445,7 @@
 			if (mail_index_unlink(ctx->index) < 0) {
 				i_error("virtual index %s: Failed to unlink() "
 					"broken indexes: %m",
-					ctx->mbox->box.path);
+					mailbox_get_path(&ctx->mbox->box));
 			}
 		}
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
--- a/src/plugins/zlib/zlib-plugin.c	Sun Dec 05 22:11:01 2010 +0000
+++ b/src/plugins/zlib/zlib-plugin.c	Sun Dec 05 23:18:55 2010 +0000
@@ -310,14 +310,16 @@
 	if (mail_storage_is_mailbox_file(box->storage)) {
 		/* looks like a compressed single file mailbox. we should be
 		   able to handle this. */
-		fd = open(box->path, O_RDONLY);
+		const char *box_path = mailbox_get_path(box);
+
+		fd = open(box_path, O_RDONLY);
 		if (fd == -1) {
 			mail_storage_set_critical(box->storage,
-				"open(%s) failed: %m", box->path);
+				"open(%s) failed: %m", box_path);
 			return -1;
 		}
 		input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
-		i_stream_set_name(input, box->path);
+		i_stream_set_name(input, box_path);
 		box->input = handler->create_istream(input, TRUE);
 		i_stream_unref(&input);
 		box->flags |= MAILBOX_FLAG_READONLY;