dovecot: Delay creating directories until we really need them.

dovecot at dovecot.org dovecot at dovecot.org
Sun Nov 11 17:46:52 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/186b164a9579
changeset: 6777:186b164a9579
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Nov 11 17:46:47 2007 +0200
description:
Delay creating directories until we really need them.

diffstat:

11 files changed, 250 insertions(+), 145 deletions(-)
src/lib-storage/index/cydir/cydir-storage.c      |   16 +-
src/lib-storage/index/dbox/dbox-storage.c        |   16 +-
src/lib-storage/index/index-storage.c            |    1 
src/lib-storage/index/maildir/maildir-keywords.c |   34 +++--
src/lib-storage/index/maildir/maildir-storage.c  |  138 +++++++++++-----------
src/lib-storage/index/maildir/maildir-storage.h  |    8 +
src/lib-storage/index/maildir/maildir-sync.c     |   40 +++---
src/lib-storage/index/maildir/maildir-uidlist.c  |   61 ++++++---
src/lib-storage/index/maildir/maildir-util.c     |   64 ++++++++++
src/lib-storage/mail-storage-private.h           |    4 
src/lib-storage/mailbox-list.c                   |   13 --

diffs (truncated from 654 to 300 lines):

diff -r 47c746a769ba -r 186b164a9579 src/lib-storage/index/cydir/cydir-storage.c
--- a/src/lib-storage/index/cydir/cydir-storage.c	Sun Nov 11 17:43:56 2007 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Sun Nov 11 17:46:47 2007 +0200
@@ -150,9 +150,6 @@ cydir_open(struct cydir_storage *storage
 
 	path = mailbox_list_get_path(_storage->list, name,
 				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (create_cydir(_storage, path) < 0)
-		return NULL;
-
 	index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
 	mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
 				   MAIL_INDEX_SYNC_TYPE_EXPUNGE);
@@ -186,14 +183,17 @@ cydir_mailbox_open(struct mail_storage *
 		return NULL;
 	}
 
-	if (strcmp(name, "INBOX") == 0)
-		return cydir_open(storage, "INBOX", flags);
-
 	path = mailbox_list_get_path(_storage->list, name,
 				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(path, &st) == 0) {
+	if (stat(path, &st) == 0)
 		return cydir_open(storage, name, flags);
-	} else if (errno == ENOENT) {
+	else if (errno == ENOENT) {
+		if (strcmp(name, "INBOX") == 0) {
+			/* INBOX always exists, create it */
+			if (create_cydir(_storage, path) < 0)
+				return NULL;
+			return cydir_open(storage, "INBOX", flags);
+		}
 		mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
 			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
 		return NULL;
diff -r 47c746a769ba -r 186b164a9579 src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c	Sun Nov 11 17:43:56 2007 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Sun Nov 11 17:46:47 2007 +0200
@@ -169,8 +169,6 @@ dbox_open(struct dbox_storage *storage, 
 
 	path = mailbox_list_get_path(_storage->list, name,
 				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (create_dbox(_storage, path) < 0)
-		return NULL;
 
 	index = index_storage_alloc(_storage, name, flags, DBOX_INDEX_PREFIX);
 	mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
@@ -241,14 +239,18 @@ dbox_mailbox_open(struct mail_storage *_
 		return NULL;
 	}
 
-	if (strcmp(name, "INBOX") == 0)
-		return dbox_open(storage, "INBOX", flags);
-
 	path = mailbox_list_get_path(_storage->list, name,
 				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(path, &st) == 0) {
+	if (stat(path, &st) == 0)
 		return dbox_open(storage, name, flags);
-	} else if (errno == ENOENT) {
+	else if (errno == ENOENT) {
+		if (strcmp(name, "INBOX") == 0) {
+			/* INBOX always exists, create it */
+			if (create_dbox(_storage, path) < 0)
+				return NULL;
+			return dbox_open(storage, name, flags);
+		}
+
 		mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
 			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
 		return NULL;
diff -r 47c746a769ba -r 186b164a9579 src/lib-storage/index/index-storage.c
--- a/src/lib-storage/index/index-storage.c	Sun Nov 11 17:43:56 2007 +0200
+++ b/src/lib-storage/index/index-storage.c	Sun Nov 11 17:46:47 2007 +0200
@@ -406,6 +406,7 @@ void index_storage_mailbox_init(struct i
 	ibox->box.name = p_strdup(ibox->box.pool, name);
 	if (ibox->box.file_create_mode == 0) {
 		ibox->box.file_create_mode = 0600;
+		ibox->box.dir_create_mode = 0700;
 		ibox->box.file_create_gid = (gid_t)-1;
 	}
 
diff -r 47c746a769ba -r 186b164a9579 src/lib-storage/index/maildir/maildir-keywords.c
--- a/src/lib-storage/index/maildir/maildir-keywords.c	Sun Nov 11 17:43:56 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-keywords.c	Sun Nov 11 17:46:47 2007 +0200
@@ -342,26 +342,36 @@ static int maildir_keywords_commit(struc
 	struct dotlock *dotlock;
 	const char *lock_path;
 	mode_t old_mask;
-	int fd;
+	int i, fd;
 
 	mk->synced = FALSE;
 
 	if (!mk->changed || mk->mbox == NULL)
 		return 0;
 
-	/* we could just create the temp file directly, but doing it this
-	   ways avoids potential problems with overwriting contents in
-	   malicious symlinks */
 	lock_path = t_strconcat(mk->path, ".lock", NULL);
 	(void)unlink(lock_path);
-        old_mask = umask(0777 & ~mk->mbox->ibox.box.file_create_mode);
-	fd = file_dotlock_open(&mk->dotlock_settings, mk->path,
-			       DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock);
-	umask(old_mask);
-	if (fd == -1) {
-		mail_storage_set_critical(mk->storage,
-			"file_dotlock_open(%s) failed: %m", mk->path);
-		return -1;
+
+	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->ibox.box.file_create_mode);
+		fd = file_dotlock_open(&mk->dotlock_settings, mk->path,
+				       DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock);
+		umask(old_mask);
+		if (fd != -1)
+			break;
+
+		if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT) {
+			mail_storage_set_critical(mk->storage,
+				"file_dotlock_open(%s) failed: %m", mk->path);
+			return -1;
+		}
+		/* the control dir doesn't exist. create it unless the whole
+		   mailbox was just deleted. */
+		if (maildir_set_deleted(mk->mbox))
+			return -1;
 	}
 
 	if (maildir_keywords_write_fd(mk, lock_path, fd) < 0) {
diff -r 47c746a769ba -r 186b164a9579 src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c	Sun Nov 11 17:43:56 2007 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sun Nov 11 17:46:47 2007 +0200
@@ -41,7 +41,6 @@ static MODULE_CONTEXT_DEFINE_INIT(maildi
 				  &mailbox_list_module_register);
 static const char *maildir_subdirs[] = { "cur", "new", "tmp" };
 
-static int verify_inbox(struct mail_storage *storage);
 static int
 maildir_list_delete_mailbox(struct mailbox_list *list, const char *name);
 static int
@@ -249,9 +248,6 @@ maildir_create(struct mail_storage *_sto
 			p_strconcat(_storage->pool,
 				    "tmp/", storage->temp_prefix, NULL);
 	}
-
-	if ((_storage->ns->flags & NAMESPACE_FLAG_INBOX) != 0)
-		(void)verify_inbox(_storage);
 	return 0;
 }
 
@@ -312,76 +308,70 @@ static int mkdir_verify(struct mail_stor
 	return -1;
 }
 
+static int maildir_check_tmp(struct mail_storage *storage, const char *dir)
+{
+	const char *path;
+	struct stat st;
+
+	/* if tmp/ directory exists, we need to clean it up once in a while */
+	path = t_strconcat(dir, "/tmp", NULL);
+	if (stat(path, &st) < 0) {
+		if (errno == ENOENT)
+			return 0;
+		mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
+		return -1;
+	}
+
+	if (st.st_atime > st.st_ctime + MAILDIR_TMP_DELETE_SECS) {
+		/* the directory should be empty. we won't do anything
+		   until ctime changes. */
+	} else if (st.st_atime < ioloop_time - MAILDIR_TMP_SCAN_SECS) {
+		/* time to scan */
+		(void)maildir_tmp_cleanup(storage, path);
+	}
+	return 1;
+}
+
 /* create or fix maildir, ignore if it already exists */
 static int create_maildir(struct mail_storage *storage,
 			  const char *dir, bool verify)
 {
-	const char *path;
-	struct stat st;
-
+	int ret;
+
+	ret = maildir_check_tmp(storage, dir);
+	if (ret > 0) {
+		if (!verify) {
+			mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
+					       "Mailbox already exists");
+			return -1;
+		}
+		return 1;
+	}
+	if (ret < 0)
+		return -1;
+
+	/* doesn't exist, create */
 	if (mkdir_verify(storage, t_strconcat(dir, "/cur", NULL), verify) < 0)
 		return -1;
 	if (mkdir_verify(storage, t_strconcat(dir, "/new", NULL), verify) < 0)
 		return -1;
-
-	/* if tmp/ directory exists, we need to clean it up once in a while */
-	path = t_strconcat(dir, "/tmp", NULL);
-	if (stat(path, &st) == 0) {
-		if (st.st_atime >
-		    st.st_ctime + MAILDIR_TMP_DELETE_SECS) {
-			/* the directory should be empty. we won't do anything
-			   until ctime changes. */
-		} else if (st.st_atime < ioloop_time - MAILDIR_TMP_SCAN_SECS) {
-			/* time to scan */
-			(void)maildir_tmp_cleanup(storage, path);
-		}
-	} else if (errno == ENOENT) {
-		if (mkdir_verify(storage, path, verify) < 0)
-			return -1;
-	} else {
-		mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
-		return -1;
-	}
-
+	if (mkdir_verify(storage, t_strconcat(dir, "/tmp", NULL), verify) < 0)
+		return -1;
 	return 0;
 }
 
-static int create_control_dir(struct mail_storage *storage, const char *name)
-{
-	const char *control_dir, *root_dir;
-
-	control_dir = mailbox_list_get_path(storage->list, name,
-					    MAILBOX_LIST_PATH_TYPE_CONTROL);
-	root_dir = mailbox_list_get_path(storage->list, name,
-					 MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (strcmp(control_dir, root_dir) == 0)
-		return 0;
-
-	if (mkdir_parents(control_dir, CREATE_MODE) < 0 && errno != EEXIST) {
-		mail_storage_set_critical(storage,
-					  "mkdir(%s) failed: %m", control_dir);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int verify_inbox(struct mail_storage *storage)
-{
-	const char *path;
-
-	path = mailbox_list_get_path(storage->list, "INBOX",
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (create_maildir(storage, path, TRUE) < 0)
-		return -1;
-	if (create_control_dir(storage, "INBOX") < 0)
-		return -1;
-	return 0;
-}
-
 static void maildir_lock_touch_timeout(struct maildir_mailbox *mbox)
 {
 	(void)maildir_uidlist_lock_touch(mbox->uidlist);
+}
+
+static mode_t get_dir_mode(mode_t mode)
+{
+	/* add the execute bit if either read or write bit is set */
+	if ((mode & 0600) != 0) mode |= 0100;
+	if ((mode & 0060) != 0) mode |= 0010;
+	if ((mode & 0006) != 0) mode |= 0001;
+	return mode;
 }
 
 static struct mailbox *
@@ -409,7 +399,6 @@ maildir_open(struct maildir_storage *sto
 
 	mbox->storage = storage;
 	mbox->path = p_strdup(pool, path);
-	mbox->control_dir = p_strdup(pool, control_dir);
 
 	index = index_storage_alloc(&storage->storage, name, flags,
 				    MAILDIR_INDEX_PREFIX);
@@ -425,6 +414,8 @@ maildir_open(struct maildir_storage *sto
 		mail_index_set_permissions(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;
 	}


More information about the dovecot-cvs mailing list