]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
path-util: introduce path_prefix_root_cwd()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 10 Apr 2023 19:09:55 +0000 (04:09 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 10 Apr 2023 21:27:05 +0000 (06:27 +0900)
src/basic/path-util.c
src/basic/path-util.h
src/test/test-path-util.c

index 0b0f0da7602675b5e33797c09dc1f403413442a7..fa2e26789f39cbe1a63701dc094998a9340601e2 100644 (file)
@@ -100,6 +100,34 @@ int path_make_absolute_cwd(const char *p, char **ret) {
         return 0;
 }
 
+int path_prefix_root_cwd(const char *p, const char *root, char **ret) {
+        _cleanup_free_ char *root_abs = NULL;
+        char *c;
+        int r;
+
+        assert(p);
+        assert(ret);
+
+        /* Unlike path_make_absolute(), this always prefixes root path if specified.
+         * The root path is always simplified, but the provided path will not.
+         * This is useful for prefixing the result of chaseat(). */
+
+        if (empty_or_root(root))
+                return path_make_absolute_cwd(p, ret);
+
+        r = path_make_absolute_cwd(root, &root_abs);
+        if (r < 0)
+                return r;
+
+        path_simplify(root_abs);
+        c = path_join(root_abs, p);
+        if (!c)
+                return -ENOMEM;
+
+        *ret = c;
+        return 0;
+}
+
 int path_make_relative(const char *from, const char *to, char **ret) {
         _cleanup_free_ char *result = NULL;
         unsigned n_parents;
index 7843599816e69972bc283daf7e074df654adbe0d..a0af9de6742c5ca3bab7d360a2a81020ec3864c9 100644 (file)
@@ -60,6 +60,7 @@ int path_split_and_make_absolute(const char *p, char ***ret);
 char* path_make_absolute(const char *p, const char *prefix);
 int safe_getcwd(char **ret);
 int path_make_absolute_cwd(const char *p, char **ret);
+int path_prefix_root_cwd(const char *p, const char *root, char **ret);
 int path_make_relative(const char *from, const char *to, char **ret);
 int path_make_relative_parent(const char *from_child, const char *to, char **ret);
 char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) _pure_;
index e40ffea4d53e72726e70390c11421229c6981c3d..22e8f3481afbf33f1e64c6bdb5b99eafc81f6440 100644 (file)
@@ -494,6 +494,45 @@ TEST(fsck_exists) {
         assert_se(fsck_exists_for_fstype("/../bin/") == 0);
 }
 
+TEST(path_prefix_root_cwd) {
+        _cleanup_free_ char *cwd = NULL, *ret = NULL, *expected = NULL;
+
+        assert_se(safe_getcwd(&cwd) >= 0);
+
+        assert_se(path_prefix_root_cwd("hoge", NULL, &ret) >= 0);
+        assert_se(expected = path_join(cwd, "hoge"));
+        assert_se(streq(ret, expected));
+
+        ret = mfree(ret);
+        expected = mfree(expected);
+
+        assert_se(path_prefix_root_cwd("/hoge", NULL, &ret) >= 0);
+        assert_se(streq(ret, "/hoge"));
+
+        ret = mfree(ret);
+
+        assert_se(path_prefix_root_cwd("hoge", "/a/b//./c///", &ret) >= 0);
+        assert_se(streq(ret, "/a/b/c/hoge"));
+
+        ret = mfree(ret);
+
+        assert_se(path_prefix_root_cwd("hoge", "a/b//./c///", &ret) >= 0);
+        assert_se(expected = path_join(cwd, "a/b/c/hoge"));
+        assert_se(streq(ret, expected));
+
+        ret = mfree(ret);
+        expected = mfree(expected);
+
+        assert_se(path_prefix_root_cwd("/../hoge/aaa/../././b", "/a/b//./c///", &ret) >= 0);
+        assert_se(streq(ret, "/a/b/c/../hoge/aaa/../././b"));
+
+        ret = mfree(ret);
+
+        assert_se(path_prefix_root_cwd("/../hoge/aaa/../././b", "a/b//./c///", &ret) >= 0);
+        assert_se(expected = path_join(cwd, "a/b/c/../hoge/aaa/../././b"));
+        assert_se(streq(ret, expected));
+}
+
 static void test_path_make_relative_one(const char *from, const char *to, const char *expected) {
         _cleanup_free_ char *z = NULL;
         int r;