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