changeset 8035:ed12eee73357 HEAD

Added mkdir_parents_chown().
author Timo Sirainen <tss@iki.fi>
date Sun, 20 Jul 2008 23:19:25 +0300
parents b3efdd9dc293
children b3303b65c3f2
files src/lib/mkdir-parents.c src/lib/mkdir-parents.h
diffstat 2 files changed, 46 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/mkdir-parents.c	Sun Jul 20 23:03:09 2008 +0300
+++ b/src/lib/mkdir-parents.c	Sun Jul 20 23:19:25 2008 +0300
@@ -4,38 +4,65 @@
 #include "mkdir-parents.h"
 
 #include <sys/stat.h>
+#include <unistd.h>
 
-int mkdir_parents(const char *path, mode_t mode)
+static int mkdir_chown(const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+	mode_t old_mask;
+	int ret;
+
+	old_mask = umask(0);
+	ret = mkdir(path, mode);
+	umask(old_mask);
+
+	if (ret < 0) {
+		if (errno == EISDIR || errno == ENOSYS) {
+			/* EISDIR check is for BSD/OS which returns it if path
+			   contains '/' at the end and it exists.
+
+			   ENOSYS check is for NFS mount points. */
+			errno = EEXIST;
+		}
+		return -1;
+	}
+	if (chown(path, uid, gid) < 0) {
+		i_error("chown(%s, %ld, %ld) failed: %m", path,
+			uid == (uid_t)-1 ? -1L : (long)uid,
+			gid == (gid_t)-1 ? -1L : (long)gid);
+		return -1;
+	}
+	return 0;
+}
+
+int mkdir_parents_chown(const char *path, mode_t mode, uid_t uid, gid_t gid)
 {
 	const char *p;
 	int ret;
 
-	if (mkdir(path, mode) == 0) {
-		/* success */
-	} else if (errno != ENOENT) {
-		/* EISDIR check is for BSD/OS which returns it if path
-		   contains '/' at the end and it exists.
+	if (mkdir_chown(path, mode, uid, gid) < 0) {
+		if (errno != ENOENT)
+			return -1;
 
-		   ENOSYS check is for NFS mount points.
-		*/
-		if (errno == EISDIR && errno == ENOSYS)
-			errno = EEXIST;
-		return -1;
-	} else {
+		/* doesn't exist, try recursively creating our parent dir */
 		p = strrchr(path, '/');
 		if (p == NULL || p == path)
 			return -1; /* shouldn't happen */
 
 		T_BEGIN {
-			ret = mkdir_parents(t_strdup_until(path, p), mode);
+			ret = mkdir_parents_chown(t_strdup_until(path, p),
+						  mode, uid, gid);
 		} T_END;
 		if (ret < 0)
 			return -1;
 
 		/* should work now */
-		if (mkdir(path, mode) < 0 && errno != EEXIST && errno != EISDIR)
+		if (mkdir_chown(path, mode, uid, gid) < 0)
 			return -1;
 	}
-
 	return 0;
 }
+
+int mkdir_parents(const char *path, mode_t mode)
+{
+	return mkdir_parents_chown(path, mode, (uid_t)-1, (gid_t)-1);
+}
--- a/src/lib/mkdir-parents.h	Sun Jul 20 23:03:09 2008 +0300
+++ b/src/lib/mkdir-parents.h	Sun Jul 20 23:19:25 2008 +0300
@@ -6,4 +6,8 @@
    exists, returns -1 with errno=EXIST. */
 int mkdir_parents(const char *path, mode_t mode);
 
+/* Like mkdir_parents(), but use the given uid/gid for newly created
+   directories. */
+int mkdir_parents_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
+
 #endif