From 9a0dcf03faaf73527085c470f0ddf77e0457aecf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 17 Apr 2023 15:28:42 +0900 Subject: [PATCH] chase: prefix with the root directory only when it is not "/" --- src/basic/chase.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/basic/chase.c b/src/basic/chase.c index aff2bfc3b7c..96b59e7845f 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -551,19 +551,27 @@ int chase(const char *path, const char *root, ChaseFlags flags, char **ret_path, if (ret_path) { if (!FLAGS_SET(flags, CHASE_EXTRACT_FILENAME)) { - _cleanup_free_ char *q = NULL; - q = path_join(root, p); - if (!q) - return -ENOMEM; + /* When "root" points to the root directory, the result of chaseat() is always + * absolute, hence it is not necessary to prefix with the root. When "root" points to + * a non-root directory, the result path is always normalized and relative, hence + * we can simply call path_join() and not necessary to call path_simplify(). + * Note that the result of chaseat() may start with "." (more specifically, it may be + * "." or "./"), and we need to drop "." in that case. */ - path_simplify(q); + if (empty_or_root(root)) + assert(path_is_absolute(p)); + else { + char *q; - if (FLAGS_SET(flags, CHASE_TRAIL_SLASH) && ENDSWITH_SET(path, "/", "/.")) - if (!strextend(&q, "/")) + assert(!path_is_absolute(p)); + + q = path_join(root, p + (*p == '.')); + if (!q) return -ENOMEM; - free_and_replace(p, q); + free_and_replace(p, q); + } } *ret_path = TAKE_PTR(p);