dovecot-2.2: fs-posix: Added mode=auto parameter to copy mode fr...

dovecot at dovecot.org dovecot at dovecot.org
Thu Nov 19 15:44:15 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/52e0fb4f2693
changeset: 19403:52e0fb4f2693
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Nov 19 17:43:47 2015 +0200
description:
fs-posix: Added mode=auto parameter to copy mode from parent directory if setgid-bit is set

diffstat:

 src/lib-fs/fs-posix.c |  55 ++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 48 insertions(+), 7 deletions(-)

diffs (108 lines):

diff -r 4564f4300c91 -r 52e0fb4f2693 src/lib-fs/fs-posix.c
--- a/src/lib-fs/fs-posix.c	Thu Nov 19 17:19:19 2015 +0200
+++ b/src/lib-fs/fs-posix.c	Thu Nov 19 17:43:47 2015 +0200
@@ -34,6 +34,7 @@
 	unsigned int temp_file_prefix_len;
 	enum fs_posix_lock_method lock_method;
 	mode_t mode;
+	bool mode_auto;
 };
 
 struct posix_fs_file {
@@ -102,6 +103,8 @@
 				fs->path_prefix = i_strconcat(arg + 7, "/", NULL);
 			else
 				fs->path_prefix = i_strdup(arg + 7);
+		} else if (strcmp(arg, "mode=auto") == 0) {
+			fs->mode_auto = TRUE;
 		} else if (strncmp(arg, "mode=", 5) == 0) {
 			unsigned int mode;
 			if (str_to_uint_oct(arg+5, &mode) < 0) {
@@ -140,21 +143,51 @@
 		FS_PROPERTY_STAT | FS_PROPERTY_ITER | FS_PROPERTY_RELIABLEITER;
 }
 
+static int
+fs_posix_get_mode(struct posix_fs *fs, const char *path, mode_t *mode_r)
+{
+	struct stat st;
+	const char *p;
+
+	*mode_r = fs->mode;
+
+	while (stat(path, &st) < 0) {
+		if (errno != ENOENT) {
+			fs_set_error(&fs->fs, "stat(%s) failed: %m", path);
+			return -1;
+		}
+		p = strrchr(path, '/');
+		if (p != NULL)
+			path = t_strdup_until(path, p);
+		else if (strcmp(path, ".") != 0)
+			path = ".";
+		else
+			return 0;
+	}
+	if ((st.st_mode & S_ISGID) != 0) {
+		/* setgid set - copy mode from parent */
+		*mode_r = st.st_mode & 0666;
+	}
+	return 0;
+}
+
 static int fs_posix_mkdir_parents(struct posix_fs *fs, const char *path)
 {
 	const char *dir, *fname;
-	mode_t dir_mode;
+	mode_t mode, dir_mode;
 
 	fname = strrchr(path, '/');
 	if (fname == NULL)
 		return 1;
+	dir = t_strdup_until(path, fname);
 
-	dir_mode = fs->mode;
+	if (fs_posix_get_mode(fs, dir, &mode) < 0)
+		return -1;
+	dir_mode = mode;
 	if ((dir_mode & 0600) != 0) dir_mode |= 0100;
 	if ((dir_mode & 0060) != 0) dir_mode |= 0010;
 	if ((dir_mode & 0006) != 0) dir_mode |= 0001;
 
-	dir = t_strdup_until(path, fname);
 	if (mkdir_parents(dir, dir_mode) == 0)
 		return 0;
 	else if (errno == EEXIST)
@@ -198,20 +231,28 @@
 	string_t *str = t_str_new(256);
 	const char *slash;
 	unsigned int try_count = 0;
+	mode_t mode;
 	int fd;
 
 	i_assert(file->temp_path == NULL);
 
-	if ((slash = strrchr(file->full_path, '/')) != NULL)
-		str_append_n(str, file->full_path, slash - file->full_path + 1);
+	if ((slash = strrchr(file->full_path, '/')) != NULL) {
+		str_append_n(str, file->full_path, slash - file->full_path);
+		if (fs_posix_get_mode(fs, str_c(str), &mode) < 0)
+			return -1;
+		str_append_c(str, '/');
+	} else {
+		if (fs_posix_get_mode(fs, ".", &mode) < 0)
+			return -1;
+	}
 	str_append(str, fs->temp_file_prefix);
 
-	fd = safe_mkstemp_hostpid(str, fs->mode, (uid_t)-1, (gid_t)-1);
+	fd = safe_mkstemp_hostpid(str, mode, (uid_t)-1, (gid_t)-1);
 	while (fd == -1 && errno == ENOENT &&
 	       try_count <= MAX_MKDIR_RETRY_COUNT) {
 		if (fs_posix_mkdir_parents(fs, str_c(str)) < 0)
 			return -1;
-		fd = safe_mkstemp_hostpid(str, fs->mode, (uid_t)-1, (gid_t)-1);
+		fd = safe_mkstemp_hostpid(str, mode, (uid_t)-1, (gid_t)-1);
 		try_count++;
 	}
 	if (fd == -1) {


More information about the dovecot-cvs mailing list