]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chase: make chaseat() provides absolute path also when dir_fd points to the root...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 16 Apr 2023 20:04:27 +0000 (05:04 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 18 Apr 2023 18:28:34 +0000 (03:28 +0900)
Usually, we pass the file descriptor of the root directory to chaseat()
when `--root=` is not specified. Previously, even in such case, the
result was relative, and we need to prefix the path with "/" when we
want to pass the path to other functions that do not support dir_fd, or
log or show the path. That's inconvenient.

src/basic/chase.c
src/test/test-chase.c

index eb4bda07a6f99d2e6e4290de5d36aabf26a07b8a..a6a37978e8f57d727c5e51aaf1e434314096be1e 100644 (file)
@@ -190,8 +190,9 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
                 return -ENOMEM;
 
         /* If we receive an absolute path together with AT_FDCWD, we need to return an absolute path, because
-         * a relative path would be interpreted relative to the current working directory. */
-        bool need_absolute = dir_fd == AT_FDCWD && path_is_absolute(path);
+         * a relative path would be interpreted relative to the current working directory. Also, let's make
+         * the result absolute when the file descriptor of the root directory is specified. */
+        bool need_absolute = (dir_fd == AT_FDCWD && path_is_absolute(path)) || dir_fd_is_root(dir_fd) > 0;
         if (need_absolute) {
                 done = strdup("/");
                 if (!done)
index 1e98f5c6ed29e4960dd17b2b86bdbdc56f56b945..52ea21a54c67646dc8ae3adb3c65dbaf9d2d0f37 100644 (file)
@@ -442,6 +442,34 @@ TEST(chaseat) {
         assert_se(streq(result, "/usr"));
         result = mfree(result);
 
+        /* If the file descriptor points to the root directory, the result will be absolute. */
+
+        fd = open("/", O_CLOEXEC | O_DIRECTORY | O_PATH);
+        assert_se(fd >= 0);
+
+        assert_se(chaseat(fd, p, 0, &result, NULL) >= 0);
+        assert_se(streq(result, "/usr"));
+        result = mfree(result);
+
+        assert_se(chaseat(fd, p, CHASE_AT_RESOLVE_IN_ROOT, &result, NULL) >= 0);
+        assert_se(streq(result, "/usr"));
+        result = mfree(result);
+
+        fd = safe_close(fd);
+
+        /* If the file descriptor does not point to the root directory, the result will be relative. */
+
+        assert_se(chaseat(tfd, "abc", CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL) == -ENOENT);
+        assert_se(chaseat(tfd, "/abc", CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL) == -ENOENT);
+
+        assert_se(chaseat(tfd, "abc", CHASE_AT_RESOLVE_IN_ROOT | CHASE_NONEXISTENT, &result, NULL) >= 0);
+        assert_se(streq(result, "usr"));
+        result = mfree(result);
+
+        assert_se(chaseat(tfd, "/abc", CHASE_AT_RESOLVE_IN_ROOT | CHASE_NONEXISTENT, &result, NULL) >= 0);
+        assert_se(streq(result, "usr"));
+        result = mfree(result);
+
         /* Test that absolute path or not are the same when resolving relative to a directory file
          * descriptor and that we always get a relative path back. */