]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chase-symlinks: Add chase_and_open_parent() + at() variant 26961/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 24 Mar 2023 11:10:16 +0000 (12:10 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 26 Mar 2023 18:31:10 +0000 (20:31 +0200)
Helper to chase a path, pin its parent directory and return the filename
of the resolved path in its parent directory.

src/basic/chase.c
src/basic/chase.h
src/test/test-fs-util.c

index e3ee01271e166db324490719faa8a8e7111a2dd6..6c02aeab8ba2ebea7764d192351c5b30a9c80c2e 100644 (file)
@@ -784,6 +784,18 @@ int chase_and_unlink(
         return 0;
 }
 
+int chase_and_open_parent(const char *path, const char *root, ChaseFlags chase_flags, char **ret_filename) {
+        int pfd, r;
+
+        assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
+
+        r = chase(path, root, CHASE_PARENT|CHASE_EXTRACT_FILENAME|chase_flags, ret_filename, &pfd);
+        if (r < 0)
+                return r;
+
+        return pfd;
+}
+
 int chase_and_openat(
                 int dir_fd,
                 const char *path,
@@ -1003,3 +1015,20 @@ int chase_and_unlinkat(
 
         return 0;
 }
+
+int chase_and_open_parent_at(
+                int dir_fd,
+                const char *path,
+                ChaseFlags chase_flags,
+                char **ret_filename) {
+
+        int pfd, r;
+
+        assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
+
+        r = chaseat(dir_fd, path, CHASE_PARENT|CHASE_EXTRACT_FILENAME|chase_flags, ret_filename, &pfd);
+        if (r < 0)
+                return r;
+
+        return pfd;
+}
index c94cbde8fef533bd84b8aee8a7163d4b1283dfcf..1314777cb4fdaaeecb7c2aca6f2384eaa8368db6 100644 (file)
@@ -40,6 +40,7 @@ int chase_and_stat(const char *path, const char *root, ChaseFlags chase_flags, c
 int chase_and_access(const char *path, const char *root, ChaseFlags chase_flags, int access_mode, char **ret_path);
 int chase_and_fopen_unlocked(const char *path, const char *root, ChaseFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file);
 int chase_and_unlink(const char *path, const char *root, ChaseFlags chase_flags, int unlink_flags, char **ret_path);
+int chase_and_open_parent(const char *path, const char *root, ChaseFlags chase_flags, char **ret_filename);
 
 int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int *ret_fd);
 
@@ -49,3 +50,5 @@ int chase_and_statat(int dir_fd, const char *path, ChaseFlags chase_flags, char
 int chase_and_accessat(int dir_fd, const char *path, ChaseFlags chase_flags, int access_mode, char **ret_path);
 int chase_and_fopenat_unlocked(int dir_fd, const char *path, ChaseFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file);
 int chase_and_unlinkat(int dir_fd, const char *path, ChaseFlags chase_flags, int unlink_flags, char **ret_path);
+int chase_and_open_parent_at(int dir_fd, const char *path, ChaseFlags chase_flags, char **ret_filename);
+
index d79d9603d3c8ae9355ad7d50cfaba7addab2a6ab..ab84a5ba83c4b71aac3ef021f4a513c29d2715db 100644 (file)
@@ -432,7 +432,7 @@ TEST(chase) {
         assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
 }
 
-TEST(chase_at) {
+TEST(chaseat) {
         _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
         _cleanup_close_ int tfd = -EBADF, fd = -EBADF;
         _cleanup_free_ char *result = NULL;
@@ -564,20 +564,20 @@ TEST(chase_at) {
         assert_se(streq(result, "o/p/e/n/d/i"));
         result = mfree(result);
 
-        /* Test chase_at_and_stat() */
+        /* Test chase_and_statat() */
 
         assert_se(chase_and_statat(tfd, "o/p", 0, &result, &st) >= 0);
         assert_se(stat_verify_directory(&st) >= 0);
         assert_se(streq(result, "o/p"));
         result = mfree(result);
 
-        /* Test chase_at_and_access() */
+        /* Test chase_and_accessat() */
 
         assert_se(chase_and_accessat(tfd, "o/p/e", 0, F_OK, &result) >= 0);
         assert_se(streq(result, "o/p/e"));
         result = mfree(result);
 
-        /* Test chase_at_and_fopen_unlocked() */
+        /* Test chase_and_fopenat_unlocked() */
 
         assert_se(chase_and_fopenat_unlocked(tfd, "o/p/e/n/f/i/l/e", 0, "re", &result, &f) >= 0);
         assert_se(fread(&(char[1]) {}, 1, 1, f) == 0);
@@ -586,11 +586,35 @@ TEST(chase_at) {
         assert_se(streq(result, "o/p/e/n/f/i/l/e"));
         result = mfree(result);
 
-        /* Test chase_at_and_unlink() */
+        /* Test chase_and_unlinkat() */
 
         assert_se(chase_and_unlinkat(tfd, "o/p/e/n/f/i/l/e", 0, 0, &result) >= 0);
         assert_se(streq(result, "o/p/e/n/f/i/l/e"));
         result = mfree(result);
+
+        /* Test chase_and_open_parent_at() */
+
+        assert_se((fd = chase_and_open_parent_at(tfd, "chase/parent", CHASE_AT_RESOLVE_IN_ROOT|CHASE_NOFOLLOW, &result)) >= 0);
+        assert_se(faccessat(fd, result, F_OK, AT_SYMLINK_NOFOLLOW) >= 0);
+        assert_se(streq(result, "parent"));
+        fd = safe_close(fd);
+        result = mfree(result);
+
+        assert_se((fd = chase_and_open_parent_at(tfd, "chase", CHASE_AT_RESOLVE_IN_ROOT, &result)) >= 0);
+        assert_se(faccessat(fd, result, F_OK, 0) >= 0);
+        assert_se(streq(result, "chase"));
+        fd = safe_close(fd);
+        result = mfree(result);
+
+        assert_se((fd = chase_and_open_parent_at(tfd, "/", CHASE_AT_RESOLVE_IN_ROOT, &result)) >= 0);
+        assert_se(streq(result, "."));
+        fd = safe_close(fd);
+        result = mfree(result);
+
+        assert_se((fd = chase_and_open_parent_at(tfd, ".", CHASE_AT_RESOLVE_IN_ROOT, &result)) >= 0);
+        assert_se(streq(result, "."));
+        fd = safe_close(fd);
+        result = mfree(result);
 }
 
 TEST(readlink_and_make_absolute) {