path-util: introduce path_simplify()
The function is similar to path_kill_slashes() but also removes initial './', trailing '/.', and '/./' in the path. When the second argument of path_simplify() is false, then it behaves as the same as path_kill_slashes(). Hence, this also replaces path_kill_slashes() with path_simplify().
This commit is contained in:
@@ -628,7 +628,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
*fs = path_kill_slashes(t);
|
||||
*fs = path_simplify(t, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -645,7 +645,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
path_kill_slashes(*fs);
|
||||
path_simplify(*fs, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1250,7 +1250,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
*path = path_kill_slashes(t);
|
||||
*path = path_simplify(t, false);
|
||||
}
|
||||
|
||||
if (controller)
|
||||
@@ -1302,7 +1302,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
path_kill_slashes(u);
|
||||
path_simplify(u, false);
|
||||
}
|
||||
|
||||
if (controller)
|
||||
@@ -1333,7 +1333,7 @@ int cg_mangle_path(const char *path, char **result) {
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
*result = path_kill_slashes(t);
|
||||
*result = path_simplify(t, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1234,7 +1234,7 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
|
||||
|
||||
strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
|
||||
|
||||
*ret = path_kill_slashes(t);
|
||||
*ret = path_simplify(t, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1275,7 +1275,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
|
||||
|
||||
*x = 0;
|
||||
|
||||
*ret = path_kill_slashes(t);
|
||||
*ret = path_simplify(t, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1315,7 +1315,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
|
||||
|
||||
*x = 0;
|
||||
|
||||
*ret = path_kill_slashes(t);
|
||||
*ret = path_simplify(t, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -413,7 +413,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
|
||||
if (!cleaned)
|
||||
return -ENOMEM;
|
||||
|
||||
path_kill_slashes(cleaned);
|
||||
path_simplify(cleaned, false);
|
||||
|
||||
done = set_new(&path_hash_ops);
|
||||
if (!done)
|
||||
|
||||
+34
-18
@@ -159,7 +159,7 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
|
||||
if (!r)
|
||||
return -ENOMEM;
|
||||
|
||||
path_kill_slashes(r);
|
||||
path_simplify(r, false);
|
||||
|
||||
*_r = r;
|
||||
return 0;
|
||||
@@ -214,7 +214,7 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
|
||||
p = mempcpy(p, "../", 3);
|
||||
|
||||
strcpy(p, to_path);
|
||||
path_kill_slashes(r);
|
||||
path_simplify(r, false);
|
||||
|
||||
*_r = r;
|
||||
return 0;
|
||||
@@ -235,7 +235,7 @@ int path_strv_make_absolute_cwd(char **l) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
path_kill_slashes(t);
|
||||
path_simplify(t, false);
|
||||
free_and_replace(*s, t);
|
||||
}
|
||||
|
||||
@@ -335,17 +335,30 @@ char **path_strv_resolve_uniq(char **l, const char *root) {
|
||||
return strv_uniq(l);
|
||||
}
|
||||
|
||||
char *path_kill_slashes(char *path) {
|
||||
char *path_simplify(char *path, bool kill_dots) {
|
||||
char *f, *t;
|
||||
bool slash = false;
|
||||
bool slash = false, ignore_slash = false, absolute;
|
||||
|
||||
/* Removes redundant inner and trailing slashes. Modifies the
|
||||
* passed string in-place.
|
||||
assert(path);
|
||||
|
||||
/* Removes redundant inner and trailing slashes. Also removes unnecessary dots
|
||||
* if kill_dots is true. Modifies the passed string in-place.
|
||||
*
|
||||
* ///foo///bar/ becomes /foo/bar
|
||||
* ///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)
|
||||
*/
|
||||
|
||||
for (f = path, t = path; *f; f++) {
|
||||
absolute = path_is_absolute(path);
|
||||
|
||||
f = path;
|
||||
if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/')) {
|
||||
ignore_slash = true;
|
||||
f++;
|
||||
}
|
||||
|
||||
for (t = path; *f; f++) {
|
||||
|
||||
if (*f == '/') {
|
||||
slash = true;
|
||||
@@ -353,17 +366,21 @@ char *path_kill_slashes(char *path) {
|
||||
}
|
||||
|
||||
if (slash) {
|
||||
if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/'))
|
||||
continue;
|
||||
|
||||
slash = false;
|
||||
*(t++) = '/';
|
||||
if (ignore_slash)
|
||||
ignore_slash = false;
|
||||
else
|
||||
*(t++) = '/';
|
||||
}
|
||||
|
||||
*(t++) = *f;
|
||||
}
|
||||
|
||||
/* Special rule, if we are talking of the root directory, a
|
||||
trailing slash is good */
|
||||
|
||||
if (t == path && slash)
|
||||
/* Special rule, if we are talking of the root directory, a trailing slash is good */
|
||||
if (absolute && t == path)
|
||||
*(t++) = '/';
|
||||
|
||||
*t = 0;
|
||||
@@ -530,7 +547,7 @@ int find_binary(const char *name, char **ret) {
|
||||
/* Found it! */
|
||||
|
||||
if (ret) {
|
||||
*ret = path_kill_slashes(j);
|
||||
*ret = path_simplify(j, false);
|
||||
j = NULL;
|
||||
}
|
||||
|
||||
@@ -684,12 +701,11 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
|
||||
|
||||
path_kill_slashes(p);
|
||||
path_simplify(p, false);
|
||||
if (suppress_root && empty_or_root(p))
|
||||
p = mfree(p);
|
||||
|
||||
free(*arg);
|
||||
*arg = p;
|
||||
free_and_replace(*arg, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -50,12 +50,12 @@ char* path_make_absolute(const char *p, const char *prefix);
|
||||
int safe_getcwd(char **ret);
|
||||
int path_make_absolute_cwd(const char *p, char **ret);
|
||||
int path_make_relative(const char *from_dir, const char *to_path, char **_r);
|
||||
char* path_kill_slashes(char *path);
|
||||
char* path_startswith(const char *path, const char *prefix) _pure_;
|
||||
int path_compare(const char *a, const char *b) _pure_;
|
||||
bool path_equal(const char *a, const char *b) _pure_;
|
||||
bool path_equal_or_files_same(const char *a, const char *b, int flags);
|
||||
char* path_join(const char *root, const char *path, const char *rest);
|
||||
char* path_simplify(char *path, bool kill_dots);
|
||||
|
||||
static inline bool path_equal_ptr(const char *a, const char *b) {
|
||||
return !!a == !!b && (!a || path_equal(a, b));
|
||||
@@ -101,11 +101,11 @@ int mkfs_exists(const char *fstype);
|
||||
* the tree, to root. Also returns "" (and not "/"!) for the root
|
||||
* directory. Excludes the specified directory itself */
|
||||
#define PATH_FOREACH_PREFIX(prefix, path) \
|
||||
for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
|
||||
for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
|
||||
|
||||
/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
|
||||
#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
|
||||
for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
|
||||
for (char *_slash = ({ path_simplify(strcpy(prefix, path), false); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
|
||||
|
||||
char *prefix_root(const char *root, const char *path);
|
||||
|
||||
|
||||
@@ -383,7 +383,7 @@ int unit_name_path_escape(const char *f, char **ret) {
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
path_kill_slashes(p);
|
||||
path_simplify(p, false);
|
||||
|
||||
if (empty_or_root(p))
|
||||
s = strdup("-");
|
||||
|
||||
Reference in New Issue
Block a user