From 6f9560d31a6fffeed234dc3b841169c40db1c5e1 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sun, 20 Jul 2008 23:19:25 +0300 Subject: [PATCH] Added mkdir_parents_chown(). --HG-- branch : HEAD --- src/lib/mkdir-parents.c | 55 ++++++++++++++++++++++++++++++----------- src/lib/mkdir-parents.h | 4 +++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/lib/mkdir-parents.c b/src/lib/mkdir-parents.c index 19563cf9ed..d4978ccdbe 100644 --- a/src/lib/mkdir-parents.c +++ b/src/lib/mkdir-parents.c @@ -4,38 +4,65 @@ #include "mkdir-parents.h" #include +#include -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); +} diff --git a/src/lib/mkdir-parents.h b/src/lib/mkdir-parents.h index 975033164f..2959ff786b 100644 --- a/src/lib/mkdir-parents.h +++ b/src/lib/mkdir-parents.h @@ -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 -- 2.47.3