summaryrefslogtreecommitdiff
path: root/src/basic/path-util.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-05-04 16:00:41 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-05-28 13:44:38 +0900
commitcb71ed91f759acddbdedb6e47dc05c8375811143 (patch)
treeea0cfce1812fc42031157ceafc00260f3a32aa1e /src/basic/path-util.c
parent4ff361cc8611459388d7f75955bfe645f894f065 (diff)
downloadsystemd-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.c64
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;
}