]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
path-util: add helper that checks if a path definitely refers to a dir
authorLennart Poettering <lennart@poettering.net>
Wed, 13 Mar 2024 22:17:11 +0000 (23:17 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 14 Mar 2024 08:17:46 +0000 (09:17 +0100)
src/basic/path-util.c
src/basic/path-util.h
src/test/test-path-util.c

index 6810bf66aa32f8b7459fc8ab0c8f96fd4bf3e638..05a21f8f8e271deab4a9f693d9ab478bb64a8383 100644 (file)
@@ -1336,6 +1336,20 @@ bool dot_or_dot_dot(const char *path) {
         return path[2] == 0;
 }
 
+bool path_implies_directory(const char *path) {
+
+        /* Sometimes, if we look at a path we already know it must refer to a directory, because it is
+         * suffixed with a slash, or its last component is "." or ".." */
+
+        if (!path)
+                return false;
+
+        if (dot_or_dot_dot(path))
+                return true;
+
+        return ENDSWITH_SET(path, "/", "/.", "/..");
+}
+
 bool empty_or_root(const char *path) {
 
         /* For operations relative to some root directory, returns true if the specified root directory is
index 39b6714525e95d20170a32ae2c15760dcb752d25..052bbd7031b0471295abe083a74a734fab8b27d3 100644 (file)
@@ -201,6 +201,8 @@ bool valid_device_allow_pattern(const char *path);
 
 bool dot_or_dot_dot(const char *path);
 
+bool path_implies_directory(const char *path);
+
 static inline const char *skip_dev_prefix(const char *p) {
         const char *e;
 
index f5a425689a3f0a9481484e6916e481d0ea47a717..ca11bf3a29c854073bc031f1e9dd9d3c9fde252e 100644 (file)
@@ -1305,4 +1305,28 @@ TEST(print_MAX) {
         assert_cc(FILENAME_MAX == PATH_MAX);
 }
 
+TEST(path_implies_directory) {
+        assert_se(!path_implies_directory(NULL));
+        assert_se(!path_implies_directory(""));
+        assert_se(path_implies_directory("/"));
+        assert_se(path_implies_directory("////"));
+        assert_se(path_implies_directory("////.///"));
+        assert_se(path_implies_directory("////./"));
+        assert_se(path_implies_directory("////."));
+        assert_se(path_implies_directory("."));
+        assert_se(path_implies_directory("./"));
+        assert_se(path_implies_directory("/."));
+        assert_se(path_implies_directory(".."));
+        assert_se(path_implies_directory("../"));
+        assert_se(path_implies_directory("/.."));
+        assert_se(!path_implies_directory("a"));
+        assert_se(!path_implies_directory("ab"));
+        assert_se(path_implies_directory("ab/"));
+        assert_se(!path_implies_directory("ab/a"));
+        assert_se(path_implies_directory("ab/a/"));
+        assert_se(path_implies_directory("ab/a/.."));
+        assert_se(path_implies_directory("ab/a/."));
+        assert_se(path_implies_directory("ab/a//"));
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);