]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added mkdir_parents_chown().
authorTimo Sirainen <tss@iki.fi>
Sun, 20 Jul 2008 20:19:25 +0000 (23:19 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 20 Jul 2008 20:19:25 +0000 (23:19 +0300)
--HG--
branch : HEAD

src/lib/mkdir-parents.c
src/lib/mkdir-parents.h

index 19563cf9edf087d6b575f8b347de0dc52f5a54ec..d4978ccdbee3935ff0f75b4b0c8f53599d8a0de3 100644 (file)
@@ -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)
 {
-       const char *p;
+       mode_t old_mask;
        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.
+       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.
-               */
-               if (errno == EISDIR && errno == ENOSYS)
+                          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;
-       } else {
+       }
+       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_chown(path, mode, uid, gid) < 0) {
+               if (errno != ENOENT)
+                       return -1;
+
+               /* 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);
+}
index 975033164fce3ea1269cc4db2544a8c7633be675..2959ff786bbc968ca5b519a0c69139a2d884cbeb 100644 (file)
@@ -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