From fd39acb7846edc27af2bc8b0ef97ea9763dc62dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Nov 2026 11:36:12 +0100 Subject: [PATCH] path-util: retain directory-ness of a trailing "/." in path_simplify() With PATH_SIMPLIFY_KEEP_TRAILING_SLASH path_simplify() retains a trailing slash, since it indicates that the path must refer to a directory. A trailing "/." indicates the same, but so far it was simply dropped, losing that information. Turn it into a trailing slash instead. (A trailing ".." is not dropped by path_simplify(), hence needs no special handling.) --- src/basic/path-util.c | 4 +++- src/test/test-path-util.c | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index ab8674cd156..f59d4286273 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -369,7 +369,9 @@ char* path_simplify_full(char *path, PathSimplifyFlags flags) { if (isempty(path)) return path; - keep_trailing_slash = FLAGS_SET(flags, PATH_SIMPLIFY_KEEP_TRAILING_SLASH) && endswith(path, "/"); + /* A trailing "/." is dropped below just like a trailing slash, but carries the same meaning + * (i.e. "this must be a directory"), hence turn it into a trailing slash too, if requested. */ + keep_trailing_slash = FLAGS_SET(flags, PATH_SIMPLIFY_KEEP_TRAILING_SLASH) && ENDSWITH_SET(path, "/", "/."); absolute = path_is_absolute(path); f += absolute; /* Keep leading /, if present. */ diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 89af3d6b63c..96d1482b81b 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -198,6 +198,13 @@ TEST(path_simplify) { test_path_simplify_one("/../abc///..", "/abc/..", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); test_path_simplify_one("/../abc///../", "/abc/../", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); test_path_simplify_one("/../abc///../", "/abc/..", /* flags= */ 0); + test_path_simplify_one("/abc/.", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/abc/./", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/abc//.//.", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/abc/.", "/abc", /* flags= */ 0); + test_path_simplify_one("/.", "/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("./.", "./", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one(".", ".", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); test_path_simplify_one("/../../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); test_path_simplify_one("/../../abc///", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH);