]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fs-util: make sure open_mkdir_at() does something roughly sensible when invoked with '/'
authorLennart Poettering <lennart@poettering.net>
Thu, 20 Apr 2023 16:44:21 +0000 (18:44 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 25 Apr 2023 09:38:00 +0000 (18:38 +0900)
src/basic/fs-util.c
src/test/test-fs-util.c

index 3722eb638b4c4f62875beecdc3dcfba9847f76f3..f8cd93800d5cd1c37fa0b66570494c52a1773d44 100644 (file)
@@ -1000,7 +1000,7 @@ int parse_cifs_service(
 
 int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) {
         _cleanup_close_ int fd = -EBADF, parent_fd = -EBADF;
-        _cleanup_free_ char *fname = NULL;
+        _cleanup_free_ char *fname = NULL, *parent = NULL;
         int r;
 
         /* Creates a directory with mkdirat() and then opens it, in the "most atomic" fashion we can
@@ -1015,19 +1015,13 @@ int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) {
         /* Note that O_DIRECTORY|O_NOFOLLOW is implied, but we allow specifying it anyway. The following
          * flags actually make sense to specify: O_CLOEXEC, O_EXCL, O_NOATIME, O_PATH */
 
-        if (isempty(path))
-                return -EINVAL;
-
-        if (!filename_is_valid(path)) {
-                _cleanup_free_ char *parent = NULL;
-
-                /* If this is not a valid filename, it's a path. Let's open the parent directory then, so
-                 * that we can pin it, and operate below it. */
-
-                r = path_extract_directory(path, &parent);
-                if (r < 0)
+        /* If this is not a valid filename, it's a path. Let's open the parent directory then, so
+         * that we can pin it, and operate below it. */
+        r = path_extract_directory(path, &parent);
+        if (r < 0) {
+                if (!IN_SET(r, -EDESTADDRREQ, -EADDRNOTAVAIL))
                         return r;
-
+        } else {
                 r = path_extract_filename(path, &fname);
                 if (r < 0)
                         return r;
index 9e3fbdd28feb57590c7f2302c3e94ecf7ce99444..fa33b807b28689eacc2c3e6890a0d705adb8ae53 100644 (file)
@@ -548,6 +548,23 @@ TEST(parse_cifs_service) {
 TEST(open_mkdir_at) {
         _cleanup_close_ int fd = -EBADF, subdir_fd = -EBADF, subsubdir_fd = -EBADF;
         _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
+        struct stat sta, stb;
+
+        assert_se(open_mkdir_at(AT_FDCWD, "/", O_EXCL|O_CLOEXEC, 0) == -EEXIST);
+        assert_se(open_mkdir_at(AT_FDCWD, ".", O_EXCL|O_CLOEXEC, 0) == -EEXIST);
+
+        fd = open_mkdir_at(AT_FDCWD, "/", O_CLOEXEC, 0);
+        assert_se(fd >= 0);
+        assert_se(stat("/", &sta) >= 0);
+        assert_se(fstat(fd, &stb) >= 0);
+        assert_se(stat_inode_same(&sta, &stb));
+        fd = safe_close(fd);
+
+        fd = open_mkdir_at(AT_FDCWD, ".", O_CLOEXEC, 0);
+        assert_se(stat(".", &sta) >= 0);
+        assert_se(fstat(fd, &stb) >= 0);
+        assert_se(stat_inode_same(&sta, &stb));
+        fd = safe_close(fd);
 
         assert_se(open_mkdir_at(AT_FDCWD, "/proc", O_EXCL|O_CLOEXEC, 0) == -EEXIST);