1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
11 #include "path-util.h"
12 #include "process-util.h"
14 #include "stat-util.h"
15 #include "string-util.h"
18 #include "tmpfile-util.h"
21 log_info("DEFAULT_PATH=%s", DEFAULT_PATH
);
22 log_info("DEFAULT_USER_PATH=%s", DEFAULT_USER_PATH
);
26 assert_se(path_is_absolute("/"));
27 assert_se(!path_is_absolute("./"));
29 assert_se(streq(basename("./aa/bb/../file.da."), "file.da."));
30 assert_se(streq(basename("/aa///.file"), ".file"));
31 assert_se(streq(basename("/aa///file..."), "file..."));
32 assert_se(streq(basename("file.../"), ""));
34 assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo"));
35 assert_se(PATH_IN_SET("/bin", "/bin"));
36 assert_se(PATH_IN_SET("/bin", "/foo/bar", "/bin"));
37 assert_se(PATH_IN_SET("/", "/", "/", "/foo/bar"));
38 assert_se(!PATH_IN_SET("/", "/abc", "/def"));
40 assert_se(path_equal_ptr(NULL
, NULL
));
41 assert_se(path_equal_ptr("/a", "/a"));
42 assert_se(!path_equal_ptr("/a", "/b"));
43 assert_se(!path_equal_ptr("/a", NULL
));
44 assert_se(!path_equal_ptr(NULL
, "/a"));
48 assert_se(!is_path("foo"));
49 assert_se(!is_path("dos.ext"));
50 assert_se( is_path("/dir"));
51 assert_se( is_path("a/b"));
52 assert_se( is_path("a/b.ext"));
54 assert_se(!is_path("."));
55 assert_se(!is_path(""));
56 assert_se(!is_path(".."));
58 assert_se( is_path("/dev"));
59 assert_se( is_path("/./dev"));
60 assert_se( is_path("/./dev/."));
61 assert_se( is_path("/./dev."));
62 assert_se( is_path("//dev"));
63 assert_se( is_path("///dev"));
64 assert_se( is_path("/dev/"));
65 assert_se( is_path("///dev/"));
66 assert_se( is_path("/./dev/"));
67 assert_se( is_path("/../dev/"));
68 assert_se( is_path("/dev/sda"));
69 assert_se( is_path("/dev/sda5"));
70 assert_se( is_path("/dev/sda5b3"));
71 assert_se( is_path("/dev/sda5b3/idontexit"));
72 assert_se( is_path("/../dev/sda"));
73 assert_se( is_path("/../../dev/sda5"));
74 assert_se( is_path("/../../../dev/sda5b3"));
75 assert_se( is_path("/.././.././dev/sda5b3/idontexit"));
76 assert_se( is_path("/sys"));
77 assert_se( is_path("/sys/"));
78 assert_se( is_path("/./sys"));
79 assert_se( is_path("/./sys/."));
80 assert_se( is_path("/./sys."));
81 assert_se( is_path("/sys/what"));
82 assert_se( is_path("/sys/something/.."));
83 assert_se( is_path("/sys/something/../"));
84 assert_se( is_path("/sys////"));
85 assert_se( is_path("/sys////."));
86 assert_se( is_path("/sys/.."));
87 assert_se( is_path("/sys/../"));
88 assert_se( is_path("/usr/../dev/sda"));
91 TEST(is_device_path
) {
92 assert_se(!is_device_path("foo"));
93 assert_se(!is_device_path("dos.ext"));
94 assert_se(!is_device_path("/dir"));
95 assert_se(!is_device_path("a/b"));
96 assert_se(!is_device_path("a/b.ext"));
98 assert_se(!is_device_path("."));
99 assert_se(!is_device_path(""));
100 assert_se(!is_device_path(".."));
102 assert_se( is_device_path("/dev"));
103 assert_se( is_device_path("/./dev"));
104 assert_se( is_device_path("/./dev/."));
105 assert_se(!is_device_path("/./dev."));
106 assert_se( is_device_path("/./dev/foo"));
107 assert_se( is_device_path("/./dev/./foo"));
108 assert_se(!is_device_path("/./dev./foo"));
109 assert_se( is_device_path("//dev"));
110 assert_se( is_device_path("///dev"));
111 assert_se( is_device_path("/dev/"));
112 assert_se( is_device_path("///dev/"));
113 assert_se( is_device_path("/./dev/"));
114 assert_se(!is_device_path("/../dev/"));
115 assert_se( is_device_path("/dev/sda"));
116 assert_se( is_device_path("/dev/sda5"));
117 assert_se( is_device_path("/dev/sda5b3"));
118 assert_se( is_device_path("/dev/sda5b3/idontexit"));
119 assert_se(!is_device_path("/../dev/sda"));
120 assert_se(!is_device_path("/../../dev/sda5"));
121 assert_se(!is_device_path("/../../../dev/sda5b3"));
122 assert_se(!is_device_path("/.././.././dev/sda5b3/idontexit"));
123 assert_se( is_device_path("/sys"));
124 assert_se( is_device_path("/sys/"));
125 assert_se( is_device_path("/./sys"));
126 assert_se( is_device_path("/./sys/."));
127 assert_se(!is_device_path("/./sys."));
128 assert_se( is_device_path("/./sys/foo"));
129 assert_se( is_device_path("/./sys/./foo"));
130 assert_se(!is_device_path("/./sys./foo"));
131 assert_se( is_device_path("/sys/what"));
132 assert_se( is_device_path("/sys/something/.."));
133 assert_se( is_device_path("/sys/something/../"));
134 assert_se( is_device_path("/sys////"));
135 assert_se( is_device_path("/sys////."));
136 assert_se( is_device_path("/sys/.."));
137 assert_se( is_device_path("/sys/../"));
138 assert_se(!is_device_path("/usr/../dev/sda"));
141 static void test_path_simplify_one(const char *in
, const char *out
, PathSimplifyFlags flags
) {
144 p
= strdupa_safe(in
);
145 path_simplify_full(p
, flags
);
146 log_debug("/* test_path_simplify(%s) → %s (expected: %s) */", in
, p
, out
);
147 assert_se(streq(p
, out
));
150 TEST(path_simplify
) {
151 _cleanup_free_
char *hoge
= NULL
, *hoge_out
= NULL
;
152 char foo
[NAME_MAX
* 2];
154 test_path_simplify_one("", "", 0);
155 test_path_simplify_one("aaa/bbb////ccc", "aaa/bbb/ccc", 0);
156 test_path_simplify_one("//aaa/.////ccc", "/aaa/ccc", 0);
157 test_path_simplify_one("///", "/", 0);
158 test_path_simplify_one("///", "/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH
);
159 test_path_simplify_one("///.//", "/", 0);
160 test_path_simplify_one("///.//.///", "/", 0);
161 test_path_simplify_one("////.././///../.", "/../..", 0);
162 test_path_simplify_one(".", ".", 0);
163 test_path_simplify_one("./", ".", 0);
164 test_path_simplify_one("./", "./", PATH_SIMPLIFY_KEEP_TRAILING_SLASH
);
165 test_path_simplify_one(".///.//./.", ".", 0);
166 test_path_simplify_one(".///.//././/", ".", 0);
167 test_path_simplify_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.",
168 "/aaa/.bbb/../c./d.dd/..eeee", 0);
169 test_path_simplify_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
170 "/aaa/.bbb/../c./d.dd/..eeee/..", 0);
171 test_path_simplify_one(".//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
172 "aaa/.bbb/../c./d.dd/..eeee/..", 0);
173 test_path_simplify_one("..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
174 "../aaa/.bbb/../c./d.dd/..eeee/..", 0);
175 test_path_simplify_one("abc///", "abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH
);
177 memset(foo
, 'a', sizeof(foo
) -1);
180 test_path_simplify_one(foo
, foo
, 0);
182 hoge
= strjoin("/", foo
);
184 test_path_simplify_one(hoge
, hoge
, 0);
187 hoge
= strjoin("a////.//././//./b///././/./c/////././//./", foo
, "//.//////d/e/.//f/");
190 hoge_out
= strjoin("a/b/c/", foo
, "//.//////d/e/.//f/");
193 test_path_simplify_one(hoge
, hoge_out
, 0);
196 static void test_path_compare_one(const char *a
, const char *b
, int expected
) {
199 assert_se(path_compare(a
, a
) == 0);
200 assert_se(path_compare(b
, b
) == 0);
202 r
= path_compare(a
, b
);
203 assert_se((r
> 0) == (expected
> 0) && (r
< 0) == (expected
< 0));
204 r
= path_compare(b
, a
);
205 assert_se((r
< 0) == (expected
> 0) && (r
> 0) == (expected
< 0));
207 assert_se(path_equal(a
, a
) == 1);
208 assert_se(path_equal(b
, b
) == 1);
209 assert_se(path_equal(a
, b
) == (expected
== 0));
210 assert_se(path_equal(b
, a
) == (expected
== 0));
214 test_path_compare_one("/goo", "/goo", 0);
215 test_path_compare_one("/goo", "/goo", 0);
216 test_path_compare_one("//goo", "/goo", 0);
217 test_path_compare_one("//goo/////", "/goo", 0);
218 test_path_compare_one("goo/////", "goo", 0);
219 test_path_compare_one("/goo/boo", "/goo//boo", 0);
220 test_path_compare_one("//goo/boo", "/goo/boo//", 0);
221 test_path_compare_one("//goo/././//./boo//././//", "/goo/boo//.", 0);
222 test_path_compare_one("/.", "//.///", 0);
223 test_path_compare_one("/x", "x/", 1);
224 test_path_compare_one("x/", "/", -1);
225 test_path_compare_one("/x/./y", "x/y", 1);
226 test_path_compare_one("/x/./y", "/x/y", 0);
227 test_path_compare_one("/x/./././y", "/x/y/././.", 0);
228 test_path_compare_one("./x/./././y", "./x/y/././.", 0);
229 test_path_compare_one(".", "./.", 0);
230 test_path_compare_one(".", "././.", 0);
231 test_path_compare_one("./..", ".", 1);
232 test_path_compare_one("x/.y", "x/y", -1);
233 test_path_compare_one("foo", "/foo", -1);
234 test_path_compare_one("/foo", "/foo/bar", -1);
235 test_path_compare_one("/foo/aaa", "/foo/b", -1);
236 test_path_compare_one("/foo/aaa", "/foo/b/a", -1);
237 test_path_compare_one("/foo/a", "/foo/aaa", -1);
238 test_path_compare_one("/foo/a/b", "/foo/aaa", -1);
241 static void test_path_compare_filename_one(const char *a
, const char *b
, int expected
) {
244 assert_se(path_compare_filename(a
, a
) == 0);
245 assert_se(path_compare_filename(b
, b
) == 0);
247 r
= path_compare_filename(a
, b
);
248 assert_se((r
> 0) == (expected
> 0) && (r
< 0) == (expected
< 0));
249 r
= path_compare_filename(b
, a
);
250 assert_se((r
< 0) == (expected
> 0) && (r
> 0) == (expected
< 0));
252 assert_se(path_equal_filename(a
, a
) == 1);
253 assert_se(path_equal_filename(b
, b
) == 1);
254 assert_se(path_equal_filename(a
, b
) == (expected
== 0));
255 assert_se(path_equal_filename(b
, a
) == (expected
== 0));
258 TEST(path_compare_filename
) {
259 test_path_compare_filename_one("/goo", "/goo", 0);
260 test_path_compare_filename_one("/goo", "/goo", 0);
261 test_path_compare_filename_one("//goo", "/goo", 0);
262 test_path_compare_filename_one("//goo/////", "/goo", 0);
263 test_path_compare_filename_one("goo/////", "goo", 0);
264 test_path_compare_filename_one("/goo/boo", "/goo//boo", 0);
265 test_path_compare_filename_one("//goo/boo", "/goo/boo//", 0);
266 test_path_compare_filename_one("//goo/././//./boo//././//", "/goo/boo//.", 0);
267 test_path_compare_filename_one("/.", "//.///", -1);
268 test_path_compare_filename_one("/x", "x/", 0);
269 test_path_compare_filename_one("x/", "/", 1);
270 test_path_compare_filename_one("/x/./y", "x/y", 0);
271 test_path_compare_filename_one("/x/./y", "/x/y", 0);
272 test_path_compare_filename_one("/x/./././y", "/x/y/././.", 0);
273 test_path_compare_filename_one("./x/./././y", "./x/y/././.", 0);
274 test_path_compare_filename_one(".", "./.", -1);
275 test_path_compare_filename_one(".", "././.", -1);
276 test_path_compare_filename_one("./..", ".", 1);
277 test_path_compare_filename_one("x/.y", "x/y", -1);
278 test_path_compare_filename_one("foo", "/foo", 0);
279 test_path_compare_filename_one("/foo", "/foo/bar", 1);
280 test_path_compare_filename_one("/foo/aaa", "/foo/b", -1);
281 test_path_compare_filename_one("/foo/aaa", "/foo/b/a", 1);
282 test_path_compare_filename_one("/foo/a", "/foo/aaa", -1);
283 test_path_compare_filename_one("/foo/a/b", "/foo/aaa", 1);
284 test_path_compare_filename_one("/a/c", "/b/c", 0);
285 test_path_compare_filename_one("/a", "/a", 0);
286 test_path_compare_filename_one("/a/b", "/a/c", -1);
287 test_path_compare_filename_one("/b", "/c", -1);
290 TEST(path_equal_root
) {
291 /* Nail down the details of how path_equal("/", ...) works. */
293 assert_se(path_equal("/", "/"));
294 assert_se(path_equal("/", "//"));
296 assert_se(path_equal("/", "/./"));
297 assert_se(!path_equal("/", "/../"));
299 assert_se(!path_equal("/", "/.../"));
301 /* Make sure that files_same works as expected. */
303 assert_se(inode_same("/", "/", 0) > 0);
304 assert_se(inode_same("/", "/", AT_SYMLINK_NOFOLLOW
) > 0);
305 assert_se(inode_same("/", "//", 0) > 0);
306 assert_se(inode_same("/", "//", AT_SYMLINK_NOFOLLOW
) > 0);
308 assert_se(inode_same("/", "/./", 0) > 0);
309 assert_se(inode_same("/", "/./", AT_SYMLINK_NOFOLLOW
) > 0);
310 assert_se(inode_same("/", "/../", 0) > 0);
311 assert_se(inode_same("/", "/../", AT_SYMLINK_NOFOLLOW
) > 0);
313 assert_se(inode_same("/", "/.../", 0) == -ENOENT
);
314 assert_se(inode_same("/", "/.../", AT_SYMLINK_NOFOLLOW
) == -ENOENT
);
316 /* The same for path_equal_or_files_same. */
318 assert_se(path_equal_or_inode_same("/", "/", 0));
319 assert_se(path_equal_or_inode_same("/", "/", AT_SYMLINK_NOFOLLOW
));
320 assert_se(path_equal_or_inode_same("/", "//", 0));
321 assert_se(path_equal_or_inode_same("/", "//", AT_SYMLINK_NOFOLLOW
));
323 assert_se(path_equal_or_inode_same("/", "/./", 0));
324 assert_se(path_equal_or_inode_same("/", "/./", AT_SYMLINK_NOFOLLOW
));
325 assert_se(path_equal_or_inode_same("/", "/../", 0));
326 assert_se(path_equal_or_inode_same("/", "/../", AT_SYMLINK_NOFOLLOW
));
328 assert_se(!path_equal_or_inode_same("/", "/.../", 0));
329 assert_se(!path_equal_or_inode_same("/", "/.../", AT_SYMLINK_NOFOLLOW
));
332 TEST(find_executable_full
) {
334 char* test_file_name
;
335 _cleanup_close_
int fd
= -EBADF
;
336 char fn
[] = "/tmp/test-XXXXXX";
338 assert_se(find_executable_full("sh", NULL
, NULL
, true, &p
, NULL
) == 0);
340 assert_se(streq(basename(p
), "sh"));
343 assert_se(find_executable_full("sh", NULL
, NULL
, false, &p
, NULL
) == 0);
345 assert_se(streq(basename(p
), "sh"));
348 _cleanup_free_
char *oldpath
= NULL
;
351 assert_se(oldpath
= strdup(p
));
353 assert_se(unsetenv("PATH") == 0);
355 assert_se(find_executable_full("sh", NULL
, NULL
, true, &p
, NULL
) == 0);
357 assert_se(streq(basename(p
), "sh"));
360 assert_se(find_executable_full("sh", NULL
, NULL
, false, &p
, NULL
) == 0);
362 assert_se(streq(basename(p
), "sh"));
366 assert_se(setenv("PATH", oldpath
, true) >= 0);
368 assert_se((fd
= mkostemp_safe(fn
)) >= 0);
369 assert_se(fchmod(fd
, 0755) >= 0);
371 test_file_name
= basename(fn
);
373 assert_se(find_executable_full(test_file_name
, NULL
, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p
, NULL
) == 0);
375 assert_se(streq(p
, fn
));
379 assert_se(find_executable_full(test_file_name
, NULL
, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p
, NULL
) == -ENOENT
);
382 TEST(find_executable
) {
385 assert_se(find_executable("/bin/sh", &p
) == 0);
387 assert_se(path_equal(p
, "/bin/sh"));
390 assert_se(find_executable(saved_argv
[0], &p
) == 0);
392 assert_se(endswith(p
, "/test-path-util"));
393 assert_se(path_is_absolute(p
));
396 assert_se(find_executable("sh", &p
) == 0);
398 assert_se(endswith(p
, "/sh"));
399 assert_se(path_is_absolute(p
));
402 assert_se(find_executable("/bin/touch", &p
) == 0);
403 assert_se(streq(p
, "/bin/touch"));
406 assert_se(find_executable("touch", &p
) == 0);
407 assert_se(path_is_absolute(p
));
408 assert_se(streq(basename(p
), "touch"));
411 assert_se(find_executable("xxxx-xxxx", &p
) == -ENOENT
);
412 assert_se(find_executable("/some/dir/xxxx-xxxx", &p
) == -ENOENT
);
413 assert_se(find_executable("/proc/filesystems", &p
) == -EACCES
);
416 static void test_find_executable_exec_one(const char *path
) {
417 _cleanup_free_
char *t
= NULL
;
418 _cleanup_close_
int fd
= -EBADF
;
422 r
= find_executable_full(path
, NULL
, NULL
, false, &t
, &fd
);
424 log_info_errno(r
, "%s: %s → %s: %d/%m", __func__
, path
, t
?: "-", fd
);
426 assert_se(fd
> STDERR_FILENO
);
427 assert_se(path_is_absolute(t
));
428 if (path_is_absolute(path
))
429 assert_se(streq(t
, path
));
434 r
= fexecve_or_execve(fd
, t
, STRV_MAKE(t
, "--version"), STRV_MAKE(NULL
));
435 log_error_errno(r
, "[f]execve: %m");
439 assert_se(wait_for_terminate_and_check(t
, pid
, WAIT_LOG
) == 0);
442 TEST(find_executable_exec
) {
443 test_find_executable_exec_one("touch");
444 test_find_executable_exec_one("/bin/touch");
446 _cleanup_free_
char *script
= NULL
;
447 assert_se(get_testdata_dir("test-path-util/script.sh", &script
) >= 0);
448 test_find_executable_exec_one(script
);
452 static const char* const values
[] = {
465 PATH_FOREACH_PREFIX_MORE(s
, "/a/b/c/d") {
466 log_error("---%s---", s
);
467 assert_se(streq(s
, values
[i
++]));
469 assert_se(values
[i
] == NULL
);
472 PATH_FOREACH_PREFIX(s
, "/a/b/c/d") {
473 log_error("---%s---", s
);
474 assert_se(streq(s
, values
[i
++]));
476 assert_se(values
[i
] == NULL
);
479 PATH_FOREACH_PREFIX_MORE(s
, "////a////b////c///d///////")
480 assert_se(streq(s
, values
[i
++]));
481 assert_se(values
[i
] == NULL
);
484 PATH_FOREACH_PREFIX(s
, "////a////b////c///d///////")
485 assert_se(streq(s
, values
[i
++]));
486 assert_se(values
[i
] == NULL
);
488 PATH_FOREACH_PREFIX(s
, "////")
489 assert_not_reached();
492 PATH_FOREACH_PREFIX_MORE(s
, "////") {
494 assert_se(streq(s
, ""));
499 PATH_FOREACH_PREFIX(s
, "")
500 assert_not_reached();
503 PATH_FOREACH_PREFIX_MORE(s
, "") {
505 assert_se(streq(s
, ""));
511 #define test_join(expected, ...) { \
512 _cleanup_free_ char *z = NULL; \
513 z = path_join(__VA_ARGS__); \
514 log_debug("got \"%s\", expected \"%s\"", z, expected); \
515 assert_se(streq(z, expected)); \
518 test_join("/root/a/b/c", "/root", "/a/b", "/c");
519 test_join("/root/a/b/c", "/root", "a/b", "c");
520 test_join("/root/a/b/c", "/root", "/a/b", "c");
521 test_join("/root/c", "/root", "/", "c");
522 test_join("/root/", "/root", "/", NULL
);
524 test_join("/a/b/c", "", "/a/b", "/c");
525 test_join("a/b/c", "", "a/b", "c");
526 test_join("/a/b/c", "", "/a/b", "c");
527 test_join("/c", "", "/", "c");
528 test_join("/", "", "/", NULL
);
530 test_join("/a/b/c", NULL
, "/a/b", "/c");
531 test_join("a/b/c", NULL
, "a/b", "c");
532 test_join("/a/b/c", NULL
, "/a/b", "c");
533 test_join("/c", NULL
, "/", "c");
534 test_join("/", NULL
, "/", NULL
);
536 test_join("", "", NULL
);
537 test_join("", NULL
, "");
538 test_join("", NULL
, NULL
);
540 test_join("foo/bar", "foo", "bar");
541 test_join("foo/bar", "", "foo", "bar");
542 test_join("foo/bar", NULL
, "foo", NULL
, "bar");
543 test_join("foo/bar", "", "foo", "", "bar", "");
544 test_join("foo/bar", "", "", "", "", "foo", "", "", "", "bar", "", "", "");
546 test_join("//foo///bar//", "", "/", "", "/foo/", "", "/", "", "/bar/", "", "/", "");
547 test_join("/foo/bar/", "/", "foo", "/", "bar", "/");
548 test_join("foo/bar/baz", "foo", "bar", "baz");
549 test_join("foo/bar/baz", "foo/", "bar", "/baz");
550 test_join("foo//bar//baz", "foo/", "/bar/", "/baz");
551 test_join("//foo////bar////baz//", "//foo/", "///bar/", "///baz//");
555 _cleanup_free_
char *p
= NULL
;
557 assert_se(path_extend(&p
, "foo", "bar", "baz") == p
);
558 assert_se(streq(p
, "foo/bar/baz"));
560 assert_se(path_extend(&p
, "foo", "bar", "baz") == p
);
561 assert_se(streq(p
, "foo/bar/baz/foo/bar/baz"));
564 assert_se(path_extend(&p
, "foo") == p
);
565 assert_se(streq(p
, "foo"));
567 assert_se(path_extend(&p
, "/foo") == p
);
568 assert_se(streq(p
, "foo/foo"));
569 assert_se(path_extend(&p
, "/waaaah/wahhh//") == p
);
570 assert_se(streq(p
, "foo/foo/waaaah/wahhh//")); /* path_extend() does not drop redundant slashes */
571 assert_se(path_extend(&p
, "/aaa/bbb/") == p
);
572 assert_se(streq(p
, "foo/foo/waaaah/wahhh///aaa/bbb/")); /* but not add an extra slash */
574 assert_se(free_and_strdup(&p
, "/") >= 0);
575 assert_se(path_extend(&p
, "foo") == p
);
576 assert_se(streq(p
, "/foo"));
580 /* Ensure we use a sane default for PATH. */
581 assert_se(unsetenv("PATH") == 0);
583 /* fsck.minix is provided by util-linux and will probably exist. */
584 assert_se(fsck_exists_for_fstype("minix") == 1);
586 assert_se(fsck_exists_for_fstype("AbCdE") == 0);
587 assert_se(fsck_exists_for_fstype("/../bin/") == 0);
590 static void test_path_make_relative_one(const char *from
, const char *to
, const char *expected
) {
591 _cleanup_free_
char *z
= NULL
;
594 log_info("/* %s(%s, %s) */", __func__
, from
, to
);
596 r
= path_make_relative(from
, to
, &z
);
597 assert_se((r
>= 0) == !!expected
);
598 assert_se(streq_ptr(z
, expected
));
601 TEST(path_make_relative
) {
602 test_path_make_relative_one("some/relative/path", "/some/path", NULL
);
603 test_path_make_relative_one("/some/path", "some/relative/path", NULL
);
604 test_path_make_relative_one("/some/dotdot/../path", "/some/path", NULL
);
606 test_path_make_relative_one("/", "/", ".");
607 test_path_make_relative_one("/", "/some/path", "some/path");
608 test_path_make_relative_one("/some/path", "/some/path", ".");
609 test_path_make_relative_one("/some/path", "/some/path/in/subdir", "in/subdir");
610 test_path_make_relative_one("/some/path", "/", "../..");
611 test_path_make_relative_one("/some/path", "/some/other/path", "../other/path");
612 test_path_make_relative_one("/some/path/./dot", "/some/further/path", "../../further/path");
613 test_path_make_relative_one("//extra.//.//./.slashes//./won't////fo.ol///anybody//", "/././/extra././/.slashes////ar.e/.just/././.fine///", "../../../ar.e/.just/.fine");
616 static void test_path_make_relative_parent_one(const char *from
, const char *to
, const char *expected
) {
617 _cleanup_free_
char *z
= NULL
;
620 log_info("/* %s(%s, %s) */", __func__
, from
, to
);
622 r
= path_make_relative_parent(from
, to
, &z
);
623 assert_se((r
>= 0) == !!expected
);
624 assert_se(streq_ptr(z
, expected
));
627 TEST(path_make_relative_parent
) {
628 test_path_make_relative_parent_one("some/relative/path/hoge", "/some/path", NULL
);
629 test_path_make_relative_parent_one("/some/path/hoge", "some/relative/path", NULL
);
630 test_path_make_relative_parent_one("/some/dotdot/../path/hoge", "/some/path", NULL
);
631 test_path_make_relative_parent_one("/", "/aaa", NULL
);
633 test_path_make_relative_parent_one("/hoge", "/", ".");
634 test_path_make_relative_parent_one("/hoge", "/some/path", "some/path");
635 test_path_make_relative_parent_one("/some/path/hoge", "/some/path", ".");
636 test_path_make_relative_parent_one("/some/path/hoge", "/some/path/in/subdir", "in/subdir");
637 test_path_make_relative_parent_one("/some/path/hoge", "/", "../..");
638 test_path_make_relative_parent_one("/some/path/hoge", "/some/other/path", "../other/path");
639 test_path_make_relative_parent_one("/some/path/./dot/hoge", "/some/further/path", "../../further/path");
640 test_path_make_relative_parent_one("//extra.//.//./.slashes//./won't////fo.ol///anybody//hoge", "/././/extra././/.slashes////ar.e/.just/././.fine///", "../../../ar.e/.just/.fine");
643 TEST(path_strv_resolve
) {
644 char tmp_dir
[] = "/tmp/test-path-util-XXXXXX";
645 _cleanup_strv_free_
char **search_dirs
= NULL
;
646 _cleanup_strv_free_
char **absolute_dirs
= NULL
;
648 assert_se(mkdtemp(tmp_dir
) != NULL
);
650 search_dirs
= strv_new("/dir1", "/dir2", "/dir3");
651 assert_se(search_dirs
);
652 STRV_FOREACH(d
, search_dirs
) {
653 char *p
= path_join(tmp_dir
, *d
);
655 assert_se(strv_push(&absolute_dirs
, p
) == 0);
658 assert_se(mkdir(absolute_dirs
[0], 0700) == 0);
659 assert_se(mkdir(absolute_dirs
[1], 0700) == 0);
660 assert_se(symlink("dir2", absolute_dirs
[2]) == 0);
662 path_strv_resolve(search_dirs
, tmp_dir
);
663 assert_se(streq(search_dirs
[0], "/dir1"));
664 assert_se(streq(search_dirs
[1], "/dir2"));
665 assert_se(streq(search_dirs
[2], "/dir2"));
667 assert_se(rm_rf(tmp_dir
, REMOVE_ROOT
|REMOVE_PHYSICAL
) == 0);
670 static void test_path_startswith_one(const char *path
, const char *prefix
, const char *skipped
, const char *expected
) {
673 log_debug("/* %s(%s, %s) */", __func__
, path
, prefix
);
675 p
= path_startswith(path
, prefix
);
676 assert_se(streq_ptr(p
, expected
));
678 q
= strjoina(skipped
, p
);
679 assert_se(streq(q
, path
));
680 assert_se(p
== path
+ strlen(skipped
));
684 TEST(path_startswith
) {
685 test_path_startswith_one("/foo/bar/barfoo/", "/foo", "/foo/", "bar/barfoo/");
686 test_path_startswith_one("/foo/bar/barfoo/", "/foo/", "/foo/", "bar/barfoo/");
687 test_path_startswith_one("/foo/bar/barfoo/", "/", "/", "foo/bar/barfoo/");
688 test_path_startswith_one("/foo/bar/barfoo/", "////", "/", "foo/bar/barfoo/");
689 test_path_startswith_one("/foo/bar/barfoo/", "/foo//bar/////barfoo///", "/foo/bar/barfoo/", "");
690 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfoo////", "/foo/bar/barfoo/", "");
691 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar///barfoo/", "/foo/bar/barfoo/", "");
692 test_path_startswith_one("/foo/bar/barfoo/", "/foo////bar/barfoo/", "/foo/bar/barfoo/", "");
693 test_path_startswith_one("/foo/bar/barfoo/", "////foo/bar/barfoo/", "/foo/bar/barfoo/", "");
694 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfoo", "/foo/bar/barfoo/", "");
696 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo", "/foo/./", "bar///barfoo/./.");
697 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo/", "/foo/./", "bar///barfoo/./.");
698 test_path_startswith_one("/foo/./bar///barfoo/./.", "/", "/", "foo/./bar///barfoo/./.");
699 test_path_startswith_one("/foo/./bar///barfoo/./.", "////", "/", "foo/./bar///barfoo/./.");
700 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo//bar/////barfoo///", "/foo/./bar///barfoo/./.", "");
701 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo/bar/barfoo////", "/foo/./bar///barfoo/./.", "");
702 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo/bar///barfoo/", "/foo/./bar///barfoo/./.", "");
703 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo////bar/barfoo/", "/foo/./bar///barfoo/./.", "");
704 test_path_startswith_one("/foo/./bar///barfoo/./.", "////foo/bar/barfoo/", "/foo/./bar///barfoo/./.", "");
705 test_path_startswith_one("/foo/./bar///barfoo/./.", "/foo/bar/barfoo", "/foo/./bar///barfoo/./.", "");
707 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfooa/", NULL
, NULL
);
708 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfooa", NULL
, NULL
);
709 test_path_startswith_one("/foo/bar/barfoo/", "", NULL
, NULL
);
710 test_path_startswith_one("/foo/bar/barfoo/", "/bar/foo", NULL
, NULL
);
711 test_path_startswith_one("/foo/bar/barfoo/", "/f/b/b/", NULL
, NULL
);
712 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/barfo", NULL
, NULL
);
713 test_path_startswith_one("/foo/bar/barfoo/", "/foo/bar/bar", NULL
, NULL
);
714 test_path_startswith_one("/foo/bar/barfoo/", "/fo", NULL
, NULL
);
717 static void test_prefix_root_one(const char *r
, const char *p
, const char *expected
) {
718 _cleanup_free_
char *s
= NULL
;
721 assert_se(s
= path_join(r
, p
));
722 assert_se(path_equal_ptr(s
, expected
));
724 t
= prefix_roota(r
, p
);
726 assert_se(path_equal_ptr(t
, expected
));
730 test_prefix_root_one("/", "/foo", "/foo");
731 test_prefix_root_one(NULL
, "/foo", "/foo");
732 test_prefix_root_one("", "/foo", "/foo");
733 test_prefix_root_one("///", "/foo", "/foo");
734 test_prefix_root_one("/", "////foo", "/foo");
735 test_prefix_root_one(NULL
, "////foo", "/foo");
736 test_prefix_root_one("/", "foo", "/foo");
737 test_prefix_root_one("", "foo", "foo");
738 test_prefix_root_one(NULL
, "foo", "foo");
740 test_prefix_root_one("/foo", "/bar", "/foo/bar");
741 test_prefix_root_one("/foo", "bar", "/foo/bar");
742 test_prefix_root_one("foo", "bar", "foo/bar");
743 test_prefix_root_one("/foo/", "/bar", "/foo/bar");
744 test_prefix_root_one("/foo/", "//bar", "/foo/bar");
745 test_prefix_root_one("/foo///", "//bar", "/foo/bar");
748 TEST(file_in_same_dir
) {
751 assert_se(file_in_same_dir("/", "a", &t
) == -EADDRNOTAVAIL
);
753 assert_se(file_in_same_dir("/", "/a", &t
) >= 0);
754 assert_se(streq(t
, "/a"));
757 assert_se(file_in_same_dir("", "a", &t
) == -EINVAL
);
759 assert_se(file_in_same_dir("a/", "x", &t
) >= 0);
760 assert_se(streq(t
, "x"));
763 assert_se(file_in_same_dir("bar/foo", "bar", &t
) >= 0);
764 assert_se(streq(t
, "bar/bar"));
768 static void test_path_find_first_component_one(
774 log_debug("/* %s(\"%s\", accept_dot_dot=%s) */", __func__
, strnull(path
), yes_no(accept_dot_dot
));
776 for (const char *p
= path
;;) {
780 r
= path_find_first_component(&p
, accept_dot_dot
, &e
);
784 assert_se(p
== path
+ strlen_ptr(path
));
785 assert_se(isempty(p
));
791 assert_se(strv_isempty(expected
));
796 assert_se(strcspn(e
, "/") == (size_t) r
);
797 assert_se(strlen_ptr(*expected
) == (size_t) r
);
798 assert_se(strneq(e
, *expected
++, r
));
801 log_debug("p=%s", p
);
802 if (!isempty(*expected
))
803 assert_se(startswith(p
, *expected
));
805 assert_se(p
== path
+ strlen_ptr(path
));
806 assert_se(isempty(p
));
811 TEST(path_find_first_component
) {
812 _cleanup_free_
char *hoge
= NULL
;
813 char foo
[NAME_MAX
* 2];
815 test_path_find_first_component_one(NULL
, false, NULL
, 0);
816 test_path_find_first_component_one("", false, NULL
, 0);
817 test_path_find_first_component_one("/", false, NULL
, 0);
818 test_path_find_first_component_one(".", false, NULL
, 0);
819 test_path_find_first_component_one("./", false, NULL
, 0);
820 test_path_find_first_component_one("./.", false, NULL
, 0);
821 test_path_find_first_component_one("..", false, NULL
, -EINVAL
);
822 test_path_find_first_component_one("/..", false, NULL
, -EINVAL
);
823 test_path_find_first_component_one("./..", false, NULL
, -EINVAL
);
824 test_path_find_first_component_one("////./././//.", false, NULL
, 0);
825 test_path_find_first_component_one("a/b/c", false, STRV_MAKE("a", "b", "c"), 0);
826 test_path_find_first_component_one("././//.///aa/bbb//./ccc", false, STRV_MAKE("aa", "bbb", "ccc"), 0);
827 test_path_find_first_component_one("././//.///aa/.../../bbb//./ccc/.", false, STRV_MAKE("aa", "..."), -EINVAL
);
828 test_path_find_first_component_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", false, STRV_MAKE("aaa", ".bbb"), -EINVAL
);
829 test_path_find_first_component_one("a/foo./b//././/", false, STRV_MAKE("a", "foo.", "b"), 0);
831 test_path_find_first_component_one(NULL
, true, NULL
, 0);
832 test_path_find_first_component_one("", true, NULL
, 0);
833 test_path_find_first_component_one("/", true, NULL
, 0);
834 test_path_find_first_component_one(".", true, NULL
, 0);
835 test_path_find_first_component_one("./", true, NULL
, 0);
836 test_path_find_first_component_one("./.", true, NULL
, 0);
837 test_path_find_first_component_one("..", true, STRV_MAKE(".."), 0);
838 test_path_find_first_component_one("/..", true, STRV_MAKE(".."), 0);
839 test_path_find_first_component_one("./..", true, STRV_MAKE(".."), 0);
840 test_path_find_first_component_one("////./././//.", true, NULL
, 0);
841 test_path_find_first_component_one("a/b/c", true, STRV_MAKE("a", "b", "c"), 0);
842 test_path_find_first_component_one("././//.///aa/bbb//./ccc", true, STRV_MAKE("aa", "bbb", "ccc"), 0);
843 test_path_find_first_component_one("././//.///aa/.../../bbb//./ccc/.", true, STRV_MAKE("aa", "...", "..", "bbb", "ccc"), 0);
844 test_path_find_first_component_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", true, STRV_MAKE("aaa", ".bbb", "..", "c.", "d.dd", "..eeee"), 0);
845 test_path_find_first_component_one("a/foo./b//././/", true, STRV_MAKE("a", "foo.", "b"), 0);
847 memset(foo
, 'a', sizeof(foo
) -1);
850 test_path_find_first_component_one(foo
, false, NULL
, -EINVAL
);
851 test_path_find_first_component_one(foo
, true, NULL
, -EINVAL
);
853 hoge
= strjoin("a/b/c/", foo
, "//d/e/.//f/");
856 test_path_find_first_component_one(hoge
, false, STRV_MAKE("a", "b", "c"), -EINVAL
);
857 test_path_find_first_component_one(hoge
, true, STRV_MAKE("a", "b", "c"), -EINVAL
);
860 static void test_path_find_last_component_one(
866 log_debug("/* %s(\"%s\", accept_dot_dot=%s) */", __func__
, strnull(path
), yes_no(accept_dot_dot
));
868 for (const char *next
= NULL
;;) {
872 r
= path_find_last_component(path
, accept_dot_dot
, &next
, &e
);
875 assert_se(next
== path
);
879 assert_se(strv_isempty(expected
));
884 assert_se(strcspn(e
, "/") == (size_t) r
);
885 assert_se(strlen_ptr(*expected
) == (size_t) r
);
886 assert_se(strneq(e
, *expected
++, r
));
889 log_debug("path=%s\nnext=%s", path
, next
);
890 if (!isempty(*expected
)) {
891 assert_se(next
< path
+ strlen(path
));
892 assert_se(next
>= path
+ strlen(*expected
));
893 assert_se(startswith(next
- strlen(*expected
), *expected
));
895 assert_se(next
== path
);
899 TEST(path_find_last_component
) {
900 _cleanup_free_
char *hoge
= NULL
;
901 char foo
[NAME_MAX
* 2];
903 test_path_find_last_component_one(NULL
, false, NULL
, 0);
904 test_path_find_last_component_one("", false, NULL
, 0);
905 test_path_find_last_component_one("/", false, NULL
, 0);
906 test_path_find_last_component_one(".", false, NULL
, 0);
907 test_path_find_last_component_one("./", false, NULL
, 0);
908 test_path_find_last_component_one("./.", false, NULL
, 0);
909 test_path_find_last_component_one("..", false, NULL
, -EINVAL
);
910 test_path_find_last_component_one("/..", false, NULL
, -EINVAL
);
911 test_path_find_last_component_one("./..", false, NULL
, -EINVAL
);
912 test_path_find_last_component_one("////./././//.", false, NULL
, 0);
913 test_path_find_last_component_one("a/b/c", false, STRV_MAKE("c", "b", "a"), 0);
914 test_path_find_last_component_one("././//.///aa./.bbb//./ccc/././/", false, STRV_MAKE("ccc", ".bbb", "aa."), 0);
915 test_path_find_last_component_one("././//.///aa/../.../bbb//./ccc/.", false, STRV_MAKE("ccc", "bbb", "..."), -EINVAL
);
916 test_path_find_last_component_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", false, STRV_MAKE("..eeee", "d.dd", "c."), -EINVAL
);
918 test_path_find_last_component_one(NULL
, true, NULL
, 0);
919 test_path_find_last_component_one("", true, NULL
, 0);
920 test_path_find_last_component_one("/", true, NULL
, 0);
921 test_path_find_last_component_one(".", true, NULL
, 0);
922 test_path_find_last_component_one("./", true, NULL
, 0);
923 test_path_find_last_component_one("./.", true, NULL
, 0);
924 test_path_find_last_component_one("..", true, STRV_MAKE(".."), 0);
925 test_path_find_last_component_one("/..", true, STRV_MAKE(".."), 0);
926 test_path_find_last_component_one("./..", true, STRV_MAKE(".."), 0);
927 test_path_find_last_component_one("////./././//.", true, NULL
, 0);
928 test_path_find_last_component_one("a/b/c", true, STRV_MAKE("c", "b", "a"), 0);
929 test_path_find_last_component_one("././//.///aa./.bbb//./ccc/././/", true, STRV_MAKE("ccc", ".bbb", "aa."), 0);
930 test_path_find_last_component_one("././//.///aa/../.../bbb//./ccc/.", true, STRV_MAKE("ccc", "bbb", "...", "..", "aa"), 0);
931 test_path_find_last_component_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", true, STRV_MAKE("..eeee", "d.dd", "c.", "..", ".bbb", "aaa"), 0);
933 memset(foo
, 'a', sizeof(foo
) -1);
936 test_path_find_last_component_one(foo
, false, NULL
, -EINVAL
);
937 test_path_find_last_component_one(foo
, true, NULL
, -EINVAL
);
939 hoge
= strjoin(foo
, "/a/b/c/");
942 test_path_find_last_component_one(hoge
, false, STRV_MAKE("c", "b", "a"), -EINVAL
);
943 test_path_find_last_component_one(hoge
, true, STRV_MAKE("c", "b", "a"), -EINVAL
);
946 TEST(last_path_component
) {
947 assert_se(last_path_component(NULL
) == NULL
);
948 assert_se(streq(last_path_component("a/b/c"), "c"));
949 assert_se(streq(last_path_component("a/b/c/"), "c/"));
950 assert_se(streq(last_path_component("/"), "/"));
951 assert_se(streq(last_path_component("//"), "/"));
952 assert_se(streq(last_path_component("///"), "/"));
953 assert_se(streq(last_path_component("."), "."));
954 assert_se(streq(last_path_component("./."), "."));
955 assert_se(streq(last_path_component("././"), "./"));
956 assert_se(streq(last_path_component("././/"), ".//"));
957 assert_se(streq(last_path_component("/foo/a"), "a"));
958 assert_se(streq(last_path_component("/foo/a/"), "a/"));
959 assert_se(streq(last_path_component(""), ""));
960 assert_se(streq(last_path_component("a"), "a"));
961 assert_se(streq(last_path_component("a/"), "a/"));
962 assert_se(streq(last_path_component("/a"), "a"));
963 assert_se(streq(last_path_component("/a/"), "a/"));
966 static void test_path_extract_filename_one(const char *input
, const char *output
, int ret
) {
967 _cleanup_free_
char *k
= NULL
;
970 r
= path_extract_filename(input
, &k
);
971 log_info("%s → %s/%s [expected: %s/%s]",
973 strnull(k
), r
< 0 ? STRERROR(r
) : "-",
974 strnull(output
), ret
< 0 ? STRERROR(ret
) : "-");
975 assert_se(streq_ptr(k
, output
));
979 TEST(path_extract_filename
) {
980 test_path_extract_filename_one(NULL
, NULL
, -EINVAL
);
981 test_path_extract_filename_one("a/b/c", "c", 0);
982 test_path_extract_filename_one("a/b/c/", "c", O_DIRECTORY
);
983 test_path_extract_filename_one("/", NULL
, -EADDRNOTAVAIL
);
984 test_path_extract_filename_one("//", NULL
, -EADDRNOTAVAIL
);
985 test_path_extract_filename_one("///", NULL
, -EADDRNOTAVAIL
);
986 test_path_extract_filename_one("/.", NULL
, -EADDRNOTAVAIL
);
987 test_path_extract_filename_one(".", NULL
, -EADDRNOTAVAIL
);
988 test_path_extract_filename_one("./", NULL
, -EADDRNOTAVAIL
);
989 test_path_extract_filename_one("./.", NULL
, -EADDRNOTAVAIL
);
990 test_path_extract_filename_one("././", NULL
, -EADDRNOTAVAIL
);
991 test_path_extract_filename_one("././/", NULL
, -EADDRNOTAVAIL
);
992 test_path_extract_filename_one("/foo/a", "a", 0);
993 test_path_extract_filename_one("/foo/a/", "a", O_DIRECTORY
);
994 test_path_extract_filename_one("", NULL
, -EINVAL
);
995 test_path_extract_filename_one("a", "a", 0);
996 test_path_extract_filename_one("a/", "a", O_DIRECTORY
);
997 test_path_extract_filename_one("a/././//.", "a", O_DIRECTORY
);
998 test_path_extract_filename_one("/a", "a", 0);
999 test_path_extract_filename_one("/a/", "a", O_DIRECTORY
);
1000 test_path_extract_filename_one("/a//./.", "a", O_DIRECTORY
);
1001 test_path_extract_filename_one("/////////////a/////////////", "a", O_DIRECTORY
);
1002 test_path_extract_filename_one("//./a/.///b./././.c//./d//.", "d", O_DIRECTORY
);
1003 test_path_extract_filename_one("xx/.", "xx", O_DIRECTORY
);
1004 test_path_extract_filename_one("xx/..", NULL
, -EINVAL
);
1005 test_path_extract_filename_one("..", NULL
, -EINVAL
);
1006 test_path_extract_filename_one("/..", NULL
, -EINVAL
);
1007 test_path_extract_filename_one("../", NULL
, -EINVAL
);
1010 static void test_path_extract_directory_one(const char *input
, const char *output
, int ret
) {
1011 _cleanup_free_
char *k
= NULL
;
1014 r
= path_extract_directory(input
, &k
);
1015 log_info("%s → %s/%s [expected: %s/%s]",
1017 strnull(k
), r
< 0 ? STRERROR(r
) : "-",
1018 strnull(output
), STRERROR(ret
));
1019 assert_se(streq_ptr(k
, output
));
1020 assert_se(r
== ret
);
1022 /* Extra safety check: let's make sure that if we split out the filename too (and it works) the
1023 * joined parts are identical to the original again */
1025 _cleanup_free_
char *f
= NULL
;
1027 r
= path_extract_filename(input
, &f
);
1029 _cleanup_free_
char *j
= NULL
;
1031 assert_se(j
= path_join(k
, f
));
1032 assert_se(path_equal(input
, j
));
1037 TEST(path_extract_directory
) {
1038 test_path_extract_directory_one(NULL
, NULL
, -EINVAL
);
1039 test_path_extract_directory_one("a/b/c", "a/b", 0);
1040 test_path_extract_directory_one("a/b/c/", "a/b", 0);
1041 test_path_extract_directory_one("/", NULL
, -EADDRNOTAVAIL
);
1042 test_path_extract_directory_one("//", NULL
, -EADDRNOTAVAIL
);
1043 test_path_extract_directory_one("///", NULL
, -EADDRNOTAVAIL
);
1044 test_path_extract_directory_one("/.", NULL
, -EADDRNOTAVAIL
);
1045 test_path_extract_directory_one(".", NULL
, -EADDRNOTAVAIL
);
1046 test_path_extract_directory_one("./", NULL
, -EADDRNOTAVAIL
);
1047 test_path_extract_directory_one("./.", NULL
, -EADDRNOTAVAIL
);
1048 test_path_extract_directory_one("././", NULL
, -EADDRNOTAVAIL
);
1049 test_path_extract_directory_one("././/", NULL
, -EADDRNOTAVAIL
);
1050 test_path_extract_directory_one("/foo/a", "/foo", 0);
1051 test_path_extract_directory_one("/foo/a/", "/foo", 0);
1052 test_path_extract_directory_one("", NULL
, -EINVAL
);
1053 test_path_extract_directory_one("a", NULL
, -EDESTADDRREQ
);
1054 test_path_extract_directory_one("a/", NULL
, -EDESTADDRREQ
);
1055 test_path_extract_directory_one("a/././//.", NULL
, -EDESTADDRREQ
);
1056 test_path_extract_directory_one("/a", "/", 0);
1057 test_path_extract_directory_one("/a/", "/", 0);
1058 test_path_extract_directory_one("/a//./.", "/", 0);
1059 test_path_extract_directory_one("/////////////a/////////////", "/", 0);
1060 test_path_extract_directory_one("//./a/.///b./././.c//./d//.", "/a/b./.c", 0);
1061 test_path_extract_directory_one("xx/.", NULL
, -EDESTADDRREQ
);
1062 test_path_extract_directory_one("xx/..", NULL
, -EINVAL
);
1063 test_path_extract_directory_one("..", NULL
, -EINVAL
);
1064 test_path_extract_directory_one("/..", NULL
, -EINVAL
);
1065 test_path_extract_directory_one("../", NULL
, -EINVAL
);
1068 TEST(filename_is_valid
) {
1069 char foo
[NAME_MAX
+2];
1071 assert_se(!filename_is_valid(""));
1072 assert_se(!filename_is_valid("/bar/foo"));
1073 assert_se(!filename_is_valid("/"));
1074 assert_se(!filename_is_valid("."));
1075 assert_se(!filename_is_valid(".."));
1076 assert_se(!filename_is_valid("bar/foo"));
1077 assert_se(!filename_is_valid("bar/foo/"));
1078 assert_se(!filename_is_valid("bar//"));
1080 memset(foo
, 'a', sizeof(foo
) - 1);
1083 assert_se(!filename_is_valid(foo
));
1085 assert_se(filename_is_valid("foo_bar-333"));
1086 assert_se(filename_is_valid("o.o"));
1089 static void test_path_is_valid_and_safe_one(const char *p
, bool ret
) {
1090 log_debug("/* %s(\"%s\") */", __func__
, strnull(p
));
1092 assert_se(path_is_valid(p
) == ret
);
1094 ret
= !streq(p
, "..") &&
1095 !startswith(p
, "../") &&
1096 !endswith(p
, "/..") &&
1098 assert_se(path_is_safe(p
) == ret
);
1101 TEST(path_is_valid_and_safe
) {
1102 char foo
[PATH_MAX
+2];
1105 test_path_is_valid_and_safe_one("", false);
1106 test_path_is_valid_and_safe_one("/bar/foo", true);
1107 test_path_is_valid_and_safe_one("/bar/foo/", true);
1108 test_path_is_valid_and_safe_one("/bar/foo/", true);
1109 test_path_is_valid_and_safe_one("//bar//foo//", true);
1110 test_path_is_valid_and_safe_one("/", true);
1111 test_path_is_valid_and_safe_one("/////", true);
1112 test_path_is_valid_and_safe_one("/////.///.////...///..//.", true);
1113 test_path_is_valid_and_safe_one(".", true);
1114 test_path_is_valid_and_safe_one("..", true);
1115 test_path_is_valid_and_safe_one("bar/foo", true);
1116 test_path_is_valid_and_safe_one("bar/foo/", true);
1117 test_path_is_valid_and_safe_one("bar//", true);
1119 memset(foo
, 'a', sizeof(foo
) -1);
1122 test_path_is_valid_and_safe_one(foo
, false);
1124 c
= strjoina("/xxx/", foo
, "/yyy");
1125 test_path_is_valid_and_safe_one(c
, false);
1127 test_path_is_valid_and_safe_one("foo_bar-333", true);
1128 test_path_is_valid_and_safe_one("o.o", true);
1131 TEST(hidden_or_backup_file
) {
1132 assert_se(hidden_or_backup_file(".hidden"));
1133 assert_se(hidden_or_backup_file("..hidden"));
1134 assert_se(!hidden_or_backup_file("hidden."));
1136 assert_se(hidden_or_backup_file("backup~"));
1137 assert_se(hidden_or_backup_file(".backup~"));
1139 assert_se(hidden_or_backup_file("lost+found"));
1140 assert_se(hidden_or_backup_file("aquota.user"));
1141 assert_se(hidden_or_backup_file("aquota.group"));
1143 assert_se(hidden_or_backup_file("test.rpmnew"));
1144 assert_se(hidden_or_backup_file("test.dpkg-old"));
1145 assert_se(hidden_or_backup_file("test.dpkg-remove"));
1146 assert_se(hidden_or_backup_file("test.swp"));
1148 assert_se(!hidden_or_backup_file("test.rpmnew."));
1149 assert_se(!hidden_or_backup_file("test.dpkg-old.foo"));
1152 TEST(skip_dev_prefix
) {
1153 assert_se(streq(skip_dev_prefix("/"), "/"));
1154 assert_se(streq(skip_dev_prefix("/dev"), ""));
1155 assert_se(streq(skip_dev_prefix("/dev/"), ""));
1156 assert_se(streq(skip_dev_prefix("/dev/foo"), "foo"));
1157 assert_se(streq(skip_dev_prefix("/dev/foo/bar"), "foo/bar"));
1158 assert_se(streq(skip_dev_prefix("//dev"), ""));
1159 assert_se(streq(skip_dev_prefix("//dev//"), ""));
1160 assert_se(streq(skip_dev_prefix("/dev///foo"), "foo"));
1161 assert_se(streq(skip_dev_prefix("///dev///foo///bar"), "foo///bar"));
1162 assert_se(streq(skip_dev_prefix("//foo"), "//foo"));
1163 assert_se(streq(skip_dev_prefix("foo"), "foo"));
1166 TEST(empty_or_root
) {
1167 assert_se(empty_or_root(NULL
));
1168 assert_se(empty_or_root(""));
1169 assert_se(empty_or_root("/"));
1170 assert_se(empty_or_root("//"));
1171 assert_se(empty_or_root("///"));
1172 assert_se(empty_or_root("/////////////////"));
1173 assert_se(!empty_or_root("xxx"));
1174 assert_se(!empty_or_root("/xxx"));
1175 assert_se(!empty_or_root("/xxx/"));
1176 assert_se(!empty_or_root("//yy//"));
1179 TEST(path_startswith_set
) {
1180 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/bar", "/zzz"), ""));
1181 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/", "/zzz"), "bar"));
1182 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo", "/zzz"), "bar"));
1183 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/", "/zzz"), "foo/bar"));
1184 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "", "/zzz"), NULL
));
1186 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/bar", "/zzz"), NULL
));
1187 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/", "/zzz"), "bar2"));
1188 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo", "/zzz"), "bar2"));
1189 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/", "/zzz"), "foo/bar2"));
1190 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "", "/zzz"), NULL
));
1192 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/bar", "/zzz"), NULL
));
1193 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/", "/zzz"), NULL
));
1194 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo", "/zzz"), NULL
));
1195 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/", "/zzz"), "foo2/bar"));
1196 assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "", "/zzz"), NULL
));
1199 TEST(path_startswith_strv
) {
1200 assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), ""));
1201 assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar"));
1202 assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar"));
1203 assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar"));
1204 assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL
));
1206 assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL
));
1207 assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar2"));
1208 assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar2"));
1209 assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar2"));
1210 assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "", "/zzz")), NULL
));
1212 assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL
));
1213 assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), NULL
));
1214 assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), NULL
));
1215 assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo2/bar"));
1216 assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL
));
1219 static void test_path_glob_can_match_one(const char *pattern
, const char *prefix
, const char *expected
) {
1220 _cleanup_free_
char *result
= NULL
;
1222 log_debug("%s(%s, %s, %s)", __func__
, pattern
, prefix
, strnull(expected
));
1224 assert_se(path_glob_can_match(pattern
, prefix
, &result
) == !!expected
);
1225 assert_se(streq_ptr(result
, expected
));
1228 TEST(path_glob_can_match
) {
1229 test_path_glob_can_match_one("/foo/hoge/aaa", "/foo/hoge/aaa/bbb", NULL
);
1230 test_path_glob_can_match_one("/foo/hoge/aaa", "/foo/hoge/aaa", "/foo/hoge/aaa");
1231 test_path_glob_can_match_one("/foo/hoge/aaa", "/foo/hoge", "/foo/hoge/aaa");
1232 test_path_glob_can_match_one("/foo/hoge/aaa", "/foo", "/foo/hoge/aaa");
1233 test_path_glob_can_match_one("/foo/hoge/aaa", "/", "/foo/hoge/aaa");
1235 test_path_glob_can_match_one("/foo/*/aaa", "/foo/hoge/aaa/bbb", NULL
);
1236 test_path_glob_can_match_one("/foo/*/aaa", "/foo/hoge/aaa", "/foo/hoge/aaa");
1237 test_path_glob_can_match_one("/foo/*/aaa", "/foo/hoge", "/foo/hoge/aaa");
1238 test_path_glob_can_match_one("/foo/*/aaa", "/foo", "/foo/*/aaa");
1239 test_path_glob_can_match_one("/foo/*/aaa", "/", "/foo/*/aaa");
1241 test_path_glob_can_match_one("/foo/*/*/aaa", "/foo/xxx/yyy/aaa/bbb", NULL
);
1242 test_path_glob_can_match_one("/foo/*/*/aaa", "/foo/xxx/yyy/aaa", "/foo/xxx/yyy/aaa");
1243 test_path_glob_can_match_one("/foo/*/*/aaa", "/foo/xxx/yyy", "/foo/xxx/yyy/aaa");
1244 test_path_glob_can_match_one("/foo/*/*/aaa", "/foo/xxx", "/foo/xxx/*/aaa");
1245 test_path_glob_can_match_one("/foo/*/*/aaa", "/foo", "/foo/*/*/aaa");
1246 test_path_glob_can_match_one("/foo/*/*/aaa", "/", "/foo/*/*/aaa");
1248 test_path_glob_can_match_one("/foo/*/aaa/*", "/foo/xxx/aaa/bbb/ccc", NULL
);
1249 test_path_glob_can_match_one("/foo/*/aaa/*", "/foo/xxx/aaa/bbb", "/foo/xxx/aaa/bbb");
1250 test_path_glob_can_match_one("/foo/*/aaa/*", "/foo/xxx/ccc", NULL
);
1251 test_path_glob_can_match_one("/foo/*/aaa/*", "/foo/xxx/aaa", "/foo/xxx/aaa/*");
1252 test_path_glob_can_match_one("/foo/*/aaa/*", "/foo/xxx", "/foo/xxx/aaa/*");
1253 test_path_glob_can_match_one("/foo/*/aaa/*", "/foo", "/foo/*/aaa/*");
1254 test_path_glob_can_match_one("/foo/*/aaa/*", "/", "/foo/*/aaa/*");
1258 log_info("PATH_MAX=%zu\n"
1259 "FILENAME_MAX=%zu\n"
1262 (size_t) FILENAME_MAX
,
1265 assert_cc(FILENAME_MAX
== PATH_MAX
);
1268 DEFINE_TEST_MAIN(LOG_DEBUG
);