]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mkdir: Add mkdirat_parents()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 26 Sep 2022 09:19:03 +0000 (11:19 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 9 Nov 2022 10:14:10 +0000 (11:14 +0100)
src/basic/mkdir.c
src/basic/mkdir.h
src/shared/mkdir-label.c
src/shared/mkdir-label.h

index 6ec7a0349cc0b8675bbb16214a0b4c9f8b46ed0b..6796d4aeda947fa961429d6bdb5124bd9a40f0f3 100644 (file)
@@ -92,46 +92,39 @@ int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid
         return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
 }
 
-int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
-        const char *p, *e = NULL;
+int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
+        const char *e = NULL;
         int r;
 
         assert(path);
         assert(_mkdirat != mkdirat);
 
-        if (prefix) {
-                p = path_startswith_full(path, prefix, /* accept_dot_dot= */ false);
-                if (!p)
-                        return -ENOTDIR;
-        } else
-                p = path;
-
-        if (isempty(p))
+        if (isempty(path))
                 return 0;
 
-        if (!path_is_safe(p))
+        if (!path_is_safe(path))
                 return -ENOTDIR;
 
         /* return immediately if directory exists */
-        r = path_find_last_component(p, /* accept_dot_dot= */ false, &e, NULL);
+        r = path_find_last_component(path, /* accept_dot_dot= */ false, &e, NULL);
         if (r <= 0) /* r == 0 means path is equivalent to prefix. */
                 return r;
-        if (e == p)
+        if (e == path)
                 return 0;
 
-        assert(e > p);
+        assert(e > path);
         assert(*e == '/');
 
         /* drop the last component */
         path = strndupa_safe(path, e - path);
-        r = is_dir(path, true);
+        r = is_dir_full(dir_fd, path, true);
         if (r > 0)
                 return 0;
         if (r == 0)
                 return -ENOTDIR;
 
         /* create every parent directory in the path, except the last component */
-        for (p = path;;) {
+        for (const char *p = path;;) {
                 char *s;
                 int n;
 
@@ -145,18 +138,39 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui
 
                 s[n] = '\0';
 
-                if (!prefix || !path_startswith_full(prefix, path, /* accept_dot_dot= */ false)) {
-                        r = mkdir_safe_internal(path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat);
-                        if (r < 0 && r != -EEXIST)
-                                return r;
-                }
+                r = mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat);
+                if (r < 0 && r != -EEXIST)
+                        return r;
 
                 s[n] = *p == '\0' ? '\0' : '/';
         }
 }
 
-int mkdir_parents(const char *path, mode_t mode) {
-        return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
+int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
+        _cleanup_close_ int fd = AT_FDCWD;
+        const char *p;
+
+        assert(path);
+        assert(_mkdirat != mkdirat);
+
+        if (prefix) {
+                p = path_startswith_full(path, prefix, /* accept_dot_dot= */ false);
+                if (!p)
+                        return -ENOTDIR;
+        } else
+                p = path;
+
+        if (prefix) {
+                fd = open(prefix, O_PATH|O_DIRECTORY|O_CLOEXEC);
+                if (fd < 0)
+                        return -errno;
+        }
+
+        return mkdirat_parents_internal(fd, p, mode, uid, gid, flags, _mkdirat);
+}
+
+int mkdirat_parents(int dir_fd, const char *path, mode_t mode) {
+        return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
 }
 
 int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
index 75f2b1b2f75f935f4cd72f559234e2b89a6b5bb5..117d9e80613362026a1551b9f7be8ae3bb424a4e 100644 (file)
@@ -16,7 +16,10 @@ int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid
 static inline int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
         return mkdirat_safe(AT_FDCWD, path, mode, uid, gid, flags);
 }
-int mkdir_parents(const char *path, mode_t mode);
+int mkdirat_parents(int dir_fd, const char *path, mode_t mode);
+static inline int mkdir_parents(const char *path, mode_t mode) {
+        return mkdirat_parents(AT_FDCWD, path, mode);
+}
 int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
 int mkdir_p(const char *path, mode_t mode);
 int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
@@ -28,5 +31,6 @@ int mkdirat_safe_internal(int dir_fd, const char *path, mode_t mode, uid_t uid,
 static inline int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir) {
         return mkdirat_safe_internal(AT_FDCWD, path, mode, uid, gid, flags, _mkdir);
 }
+int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat);
 int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
 int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
index 275298ff72b9b9e5d53cf4acd96a3da4275497c8..53081d5e173e863bd90ae82627b91ab6a949a5df 100644 (file)
@@ -29,8 +29,8 @@ int mkdirat_safe_label(int dir_fd, const char *path, mode_t mode, uid_t uid, gid
         return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_label);
 }
 
-int mkdir_parents_label(const char *path, mode_t mode) {
-        return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_label);
+int mkdirat_parents_label(int dir_fd, const char *path, mode_t mode) {
+        return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_label);
 }
 
 int mkdir_p_label(const char *path, mode_t mode) {
index 0f82e57f7182c0dd97f633d670148c3a39951a84..dcbe5bd5468f78f4e5202a26c1fba28b4fead8fc 100644 (file)
@@ -16,5 +16,8 @@ int mkdirat_safe_label(int dir_fd, const char *path, mode_t mode, uid_t uid, gid
 static inline int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
         return mkdirat_safe_label(AT_FDCWD, path, mode, uid, gid, flags);
 }
-int mkdir_parents_label(const char *path, mode_t mod);
+int mkdirat_parents_label(int dir_fd, const char *path, mode_t mod);
+static inline int mkdir_parents_label(const char *path, mode_t mod) {
+        return mkdirat_parents_label(AT_FDCWD, path, mod);
+}
 int mkdir_p_label(const char *path, mode_t mode);