diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-04 16:00:41 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-28 13:44:38 +0900 |
commit | cb71ed91f759acddbdedb6e47dc05c8375811143 (patch) | |
tree | ea0cfce1812fc42031157ceafc00260f3a32aa1e /src/basic/path-util.c | |
parent | 4ff361cc8611459388d7f75955bfe645f894f065 (diff) | |
download | systemd-cb71ed91f759acddbdedb6e47dc05c8375811143.tar.gz |
path-util: make path_simplify() use path_find_first_component()
Diffstat (limited to 'src/basic/path-util.c')
-rw-r--r-- | src/basic/path-util.c | 64 |
1 files changed, 27 insertions, 37 deletions
diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 82d6a28257..2742a27672 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -328,62 +328,52 @@ char **path_strv_resolve_uniq(char **l, const char *root) { } char *path_simplify(char *path) { - char *f, *t; - bool slash = false, ignore_slash = false, absolute; + bool add_slash = false; + char *f = path; + int r; assert(path); - /* Removes redundant inner and trailing slashes. Also removes unnecessary dots - * if kill_dots is true. Modifies the passed string in-place. + /* Removes redundant inner and trailing slashes. Also removes unnecessary dots. + * Modifies the passed string in-place. * - * ///foo//./bar/. becomes /foo/./bar/. (if kill_dots is false) - * ///foo//./bar/. becomes /foo/bar (if kill_dots is true) - * .//./foo//./bar/. becomes ././foo/./bar/. (if kill_dots is false) - * .//./foo//./bar/. becomes foo/bar (if kill_dots is true) + * ///foo//./bar/. becomes /foo/bar + * .//./foo//./bar/. becomes foo/bar */ if (isempty(path)) return path; - absolute = path_is_absolute(path); - - f = path; - if (*f == '.' && IN_SET(f[1], 0, '/')) { - ignore_slash = true; + if (path_is_absolute(path)) f++; - } - for (t = path; *f; f++) { + for (const char *p = f;;) { + const char *e; - if (*f == '/') { - slash = true; - continue; - } + r = path_find_first_component(&p, true, &e); + if (r == 0) + break; - if (slash) { - if (*f == '.' && IN_SET(f[1], 0, '/')) - continue; + if (add_slash) + *f++ = '/'; - slash = false; - if (ignore_slash) - ignore_slash = false; - else - *(t++) = '/'; + if (r < 0) { + /* if path is invalid, then refuse to simplify remaining part. */ + memmove(f, p, strlen(p) + 1); + return path; } - *(t++) = *f; - } + memmove(f, e, r); + f += r; - /* Special rule, if we stripped everything, we either need a "/" (for the root directory) - * or "." for the current directory */ - if (t == path) { - if (absolute) - *(t++) = '/'; - else - *(t++) = '.'; + add_slash = true; } - *t = 0; + /* Special rule, if we stripped everything, we need a "." for the current directory. */ + if (f == path) + *f++ = '.'; + + *f = '\0'; return path; } |