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