dovecot-1.2: storage: Create index/control root directories usin...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jun 1 04:26:06 EEST 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/2f2a907f1132
changeset: 9105:2f2a907f1132
user: Timo Sirainen <tss at iki.fi>
date: Sun May 31 21:26:00 2009 -0400
description:
storage: Create index/control root directories using same permissions as mail root.
diffstat:
3 files changed, 128 insertions(+), 64 deletions(-)
src/lib-storage/index/index-storage.c | 36 ++++++---
src/lib-storage/index/maildir/maildir-util.c | 53 ++++++++++---
src/lib-storage/mailbox-list.c | 103 +++++++++++++++-----------
diffs (268 lines):
diff -r 3870069faea3 -r 2f2a907f1132 src/lib-storage/index/index-storage.c
--- a/src/lib-storage/index/index-storage.c Sun May 31 21:24:50 2009 -0400
+++ b/src/lib-storage/index/index-storage.c Sun May 31 21:26:00 2009 -0400
@@ -69,9 +69,10 @@ static void index_list_free(struct index
static int create_index_dir(struct mail_storage *storage, const char *name)
{
- const char *root_dir, *index_dir;
- mode_t mode;
- gid_t gid;
+ const char *root_dir, *index_dir, *p, *parent_dir;
+ mode_t mode, parent_mode;
+ gid_t gid, parent_gid;
+ int n = 0;
root_dir = mailbox_list_get_path(storage->list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
@@ -81,13 +82,28 @@ static int create_index_dir(struct mail_
return 0;
mailbox_list_get_dir_permissions(storage->list, name, &mode, &gid);
- if (mkdir_parents_chown(index_dir, mode, (uid_t)-1, gid) < 0 &&
- errno != EEXIST) {
- mail_storage_set_critical(storage, "mkdir(%s) failed: %m",
- index_dir);
- return -1;
- }
-
+ while (mkdir_chown(index_dir, mode, (uid_t)-1, gid) < 0) {
+ if (errno == EEXIST)
+ break;
+
+ p = strrchr(index_dir, '/');
+ if (errno != ENOENT || p == NULL || ++n == 2) {
+ mail_storage_set_critical(storage,
+ "mkdir(%s) failed: %m", index_dir);
+ return -1;
+ }
+ /* create the parent directory first */
+ mailbox_list_get_dir_permissions(storage->list, NULL,
+ &parent_mode, &parent_gid);
+ parent_dir = t_strdup_until(index_dir, p);
+ if (mkdir_parents_chown(parent_dir, parent_mode,
+ (uid_t)-1, parent_gid) < 0 &&
+ errno != EEXIST) {
+ mail_storage_set_critical(storage,
+ "mkdir(%s) failed: %m", parent_dir);
+ return -1;
+ }
+ }
return 0;
}
diff -r 3870069faea3 -r 2f2a907f1132 src/lib-storage/index/maildir/maildir-util.c
--- a/src/lib-storage/index/maildir/maildir-util.c Sun May 31 21:24:50 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-util.c Sun May 31 21:26:00 2009 -0400
@@ -130,6 +130,45 @@ int maildir_file_do(struct maildir_mailb
return ret == -2 ? 0 : ret;
}
+static int maildir_create_path(struct mailbox *box, const char *path,
+ bool is_mail_dir)
+{
+ const char *p, *parent;
+ mode_t parent_mode;
+ gid_t parent_gid;
+
+ if (mkdir_chown(path, box->dir_create_mode,
+ (uid_t)-1, box->file_create_gid) == 0)
+ return 0;
+
+ switch (errno) {
+ case EEXIST:
+ return 0;
+ case ENOENT:
+ p = strrchr(path, '/');
+ if (is_mail_dir || p == NULL) {
+ /* mailbox was being deleted just now */
+ mailbox_set_deleted(box);
+ return -1;
+ }
+ /* create index/control root directory */
+ parent = t_strdup_until(path, p);
+ mailbox_list_get_dir_permissions(box->storage->list, NULL,
+ &parent_mode, &parent_gid);
+ if (mkdir_parents_chown(parent, parent_mode, (uid_t)-1,
+ parent_gid) == 0 || errno == EEXIST) {
+ /* should work now, try again */
+ return maildir_create_path(box, path, TRUE);
+ }
+ /* fall through */
+ path = parent;
+ default:
+ mail_storage_set_critical(box->storage,
+ "mkdir(%s) failed: %m", path);
+ return -1;
+ }
+}
+
static int maildir_create_subdirs(struct maildir_mailbox *mbox)
{
static const char *subdirs[] = { "cur", "new", "tmp" };
@@ -138,6 +177,7 @@ static int maildir_create_subdirs(struct
struct stat st;
const char *path;
unsigned int i;
+ bool is_mail_dir;
/* @UNSAFE: get a list of directories we want to create */
for (i = 0; i < N_ELEMENTS(subdirs); i++)
@@ -157,18 +197,9 @@ static int maildir_create_subdirs(struct
"stat(%s) failed: %m", path);
break;
}
- if (mkdir_parents_chown(path, box->dir_create_mode,
- (uid_t)-1, box->file_create_gid) < 0 &&
- errno != EEXIST) {
- if (errno == ENOENT) {
- /* mailbox was being deleted just now */
- mailbox_set_deleted(box);
- break;
- }
- mail_storage_set_critical(box->storage,
- "mkdir(%s) failed: %m", path);
+ is_mail_dir = i < N_ELEMENTS(subdirs);
+ if (maildir_create_path(box, path, is_mail_dir) < 0)
break;
- }
}
return i == N_ELEMENTS(dirs) ? 0 : -1;
}
diff -r 3870069faea3 -r 2f2a907f1132 src/lib-storage/mailbox-list.c
--- a/src/lib-storage/mailbox-list.c Sun May 31 21:24:50 2009 -0400
+++ b/src/lib-storage/mailbox-list.c Sun May 31 21:26:00 2009 -0400
@@ -283,17 +283,13 @@ static mode_t get_dir_mode(mode_t mode)
return mode;
}
-void mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
- mode_t *mode_r, gid_t *gid_r)
+static void
+mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name,
+ mode_t *file_mode_r, mode_t *dir_mode_r,
+ gid_t *gid_r)
{
const char *path;
struct stat st;
-
- if (list->file_create_mode != (mode_t)-1 && name == NULL) {
- *mode_r = list->file_create_mode;
- *gid_r = list->file_create_gid;
- return;
- }
path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
if (stat(path, &st) < 0) {
@@ -305,35 +301,39 @@ void mailbox_list_get_permissions(struct
list->ns->prefix, path);
}
/* return safe defaults */
- list->file_create_mode = 0600;
- list->dir_create_mode = 0700;
- list->file_create_gid = (gid_t)-1;
-
- *mode_r = list->file_create_mode;
- *gid_r = list->file_create_gid;
- return;
- }
-
- list->file_create_mode = st.st_mode & 0666;
- list->dir_create_mode = st.st_mode & 0777;
- if (!S_ISDIR(st.st_mode)) {
- /* we're getting permissions from a file.
- apply +x modes as necessary. */
- list->dir_create_mode = get_dir_mode(list->dir_create_mode);
- }
-
- if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
- /* directory's GID is used automatically for new files */
- list->file_create_gid = (gid_t)-1;
- } else if ((st.st_mode & 0070) == 0) {
- /* group doesn't have any permissions, so don't bother
- changing it */
- list->file_create_gid = (gid_t)-1;
- } else if (getegid() == st.st_gid) {
- /* using our own gid, no need to change it */
- list->file_create_gid = (gid_t)-1;
+ *file_mode_r = 0600;
+ *dir_mode_r = 0700;
+ *gid_r = (gid_t)-1;
} else {
- list->file_create_gid = st.st_gid;
+ *file_mode_r = st.st_mode & 0666;
+ *dir_mode_r = st.st_mode & 0777;
+
+ if (!S_ISDIR(st.st_mode)) {
+ /* we're getting permissions from a file.
+ apply +x modes as necessary. */
+ *dir_mode_r = get_dir_mode(*dir_mode_r);
+ }
+
+ if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
+ /* directory's GID is used automatically for new
+ files */
+ *gid_r = (gid_t)-1;
+ } else if ((st.st_mode & 0070) == 0) {
+ /* group doesn't have any permissions, so don't bother
+ changing it */
+ *gid_r = (gid_t)-1;
+ } else if (getegid() == st.st_gid) {
+ /* using our own gid, no need to change it */
+ *gid_r = (gid_t)-1;
+ } else {
+ *gid_r = st.st_gid;
+ }
+ }
+
+ if (name == NULL) {
+ list->file_create_mode = *file_mode_r;
+ list->dir_create_mode = *dir_mode_r;
+ list->file_create_gid = *gid_r;
}
if ((list->flags & MAILBOX_LIST_FLAG_DEBUG) != 0 && name == NULL) {
@@ -343,19 +343,36 @@ void mailbox_list_get_permissions(struct
list->file_create_gid == (gid_t)-1 ? -1L :
(long)list->file_create_gid);
}
-
- *mode_r = list->file_create_mode;
- *gid_r = list->file_create_gid;
+}
+
+void mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
+ mode_t *mode_r, gid_t *gid_r)
+{
+ mode_t dir_mode;
+
+ if (list->file_create_mode != (mode_t)-1 && name == NULL) {
+ *mode_r = list->file_create_mode;
+ *gid_r = list->file_create_gid;
+ return;
+ }
+
+ mailbox_list_get_permissions_full(list, name, mode_r, &dir_mode, gid_r);
}
void mailbox_list_get_dir_permissions(struct mailbox_list *list,
const char *name,
mode_t *mode_r, gid_t *gid_r)
{
- mode_t mode;
-
- mailbox_list_get_permissions(list, name, &mode, gid_r);
- *mode_r = list->dir_create_mode;
+ mode_t file_mode;
+
+ if (list->dir_create_mode != (mode_t)-1 && name == NULL) {
+ *mode_r = list->dir_create_mode;
+ *gid_r = list->file_create_gid;
+ return;
+ }
+
+ mailbox_list_get_permissions_full(list, name, &file_mode,
+ mode_r, gid_r);
}
bool mailbox_list_is_valid_pattern(struct mailbox_list *list,
More information about the dovecot-cvs
mailing list