]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mkdir: Add mkdirat_safe()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 26 Sep 2022 08:52:33 +0000 (10:52 +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 c8ff342d0f7e45156f796bde8cc8d03ebe301f49..6ec7a0349cc0b8675bbb16214a0b4c9f8b46ed0b 100644 (file)
@@ -16,7 +16,8 @@
 #include "stdio-util.h"
 #include "user-util.h"
 
-int mkdir_safe_internal(
+int mkdirat_safe_internal(
+                int dir_fd,
                 const char *path,
                 mode_t mode,
                 uid_t uid,
@@ -31,27 +32,27 @@ int mkdir_safe_internal(
         assert(mode != MODE_INVALID);
         assert(_mkdirat && _mkdirat != mkdirat);
 
-        if (_mkdirat(AT_FDCWD, path, mode) >= 0) {
-                r = chmod_and_chown(path, mode, uid, gid);
+        if (_mkdirat(dir_fd, path, mode) >= 0) {
+                r = chmod_and_chown_at(dir_fd, path, mode, uid, gid);
                 if (r < 0)
                         return r;
         }
 
-        if (lstat(path, &st) < 0)
+        if (fstatat(dir_fd, path, &st, AT_SYMLINK_NOFOLLOW) < 0)
                 return -errno;
 
         if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) {
                 _cleanup_free_ char *p = NULL;
 
-                r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p, NULL);
+                r = chase_symlinks_at(dir_fd, path, CHASE_NONEXISTENT, &p, NULL);
                 if (r < 0)
                         return r;
                 if (r == 0)
-                        return mkdir_safe_internal(p, mode, uid, gid,
-                                                   flags & ~MKDIR_FOLLOW_SYMLINK,
-                                                   _mkdirat);
+                        return mkdirat_safe_internal(dir_fd, p, mode, uid, gid,
+                                                     flags & ~MKDIR_FOLLOW_SYMLINK,
+                                                     _mkdirat);
 
-                if (lstat(p, &st) < 0)
+                if (fstatat(dir_fd, p, &st, AT_SYMLINK_NOFOLLOW) < 0)
                         return -errno;
         }
 
@@ -87,8 +88,8 @@ int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode) {
         return RET_NERRNO(mkdirat(dirfd, pathname, mode));
 }
 
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
-        return mkdir_safe_internal(path, mode, uid, gid, flags, mkdirat_errno_wrapper);
+int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
+        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) {
index c0c0ea6c4f598bfef08d7b1bbba13f7befc08208..75f2b1b2f75f935f4cd72f559234e2b89a6b5bb5 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <fcntl.h>
 #include <sys/types.h>
 
 typedef enum MkdirFlags {
@@ -11,7 +12,10 @@ typedef enum MkdirFlags {
 
 int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode);
 
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
+int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
+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 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);
@@ -20,6 +24,9 @@ int mkdir_p_root(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m
 
 /* The following are used to implement the mkdir_xyz_label() calls, don't use otherwise. */
 typedef int (*mkdirat_func_t)(int dir_fd, const char *pathname, mode_t mode);
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
+int mkdirat_safe_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
+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 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 926d1faeeb0400b07c7d5dc5e6983bdfe37cd3d9..275298ff72b9b9e5d53cf4acd96a3da4275497c8 100644 (file)
@@ -25,8 +25,8 @@ int mkdirat_label(int dirfd, const char *path, mode_t mode) {
         return mac_smack_fix_full(dirfd, path, NULL, 0);
 }
 
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
-        return mkdir_safe_internal(path, mode, uid, gid, flags, mkdirat_label);
+int mkdirat_safe_label(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
+        return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_label);
 }
 
 int mkdir_parents_label(const char *path, mode_t mode) {
index 0b1a3894bd5ad060b3d0bc8a5002440f08c8eb78..0f82e57f7182c0dd97f633d670148c3a39951a84 100644 (file)
@@ -12,6 +12,9 @@ static inline int mkdir_label(const char *path, mode_t mode) {
         return mkdirat_label(AT_FDCWD, path, mode);
 }
 
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
+int mkdirat_safe_label(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
+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 mkdir_p_label(const char *path, mode_t mode);