mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
path-util: make path_simplify() use path_find_first_component()
This commit is contained in:
@@ -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 (add_slash)
|
||||
*f++ = '/';
|
||||
|
||||
if (r < 0) {
|
||||
/* if path is invalid, then refuse to simplify remaining part. */
|
||||
memmove(f, p, strlen(p) + 1);
|
||||
return path;
|
||||
}
|
||||
|
||||
if (slash) {
|
||||
if (*f == '.' && IN_SET(f[1], 0, '/'))
|
||||
continue;
|
||||
memmove(f, e, r);
|
||||
f += r;
|
||||
|
||||
slash = false;
|
||||
if (ignore_slash)
|
||||
ignore_slash = false;
|
||||
else
|
||||
*(t++) = '/';
|
||||
}
|
||||
|
||||
*(t++) = *f;
|
||||
add_slash = true;
|
||||
}
|
||||
|
||||
/* 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++) = '.';
|
||||
}
|
||||
/* Special rule, if we stripped everything, we need a "." for the current directory. */
|
||||
if (f == path)
|
||||
*f++ = '.';
|
||||
|
||||
*t = 0;
|
||||
*f = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,6 @@ static void test_print_paths(void) {
|
||||
log_info("DEFAULT_USER_PATH=%s", DEFAULT_USER_PATH);
|
||||
}
|
||||
|
||||
static void test_path_simplify(const char *in, const char *out) {
|
||||
char *p;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
p = strdupa(in);
|
||||
assert_se(streq(path_simplify(p), out));
|
||||
}
|
||||
|
||||
static void test_path(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
@@ -45,25 +36,6 @@ static void test_path(void) {
|
||||
assert_se(streq(basename("/aa///file..."), "file..."));
|
||||
assert_se(streq(basename("file.../"), ""));
|
||||
|
||||
test_path_simplify("aaa/bbb////ccc", "aaa/bbb/ccc");
|
||||
test_path_simplify("//aaa/.////ccc", "/aaa/ccc");
|
||||
test_path_simplify("///", "/");
|
||||
test_path_simplify("///.//", "/");
|
||||
test_path_simplify("///.//.///", "/");
|
||||
test_path_simplify("////.././///../.", "/../..");
|
||||
test_path_simplify(".", ".");
|
||||
test_path_simplify("./", ".");
|
||||
test_path_simplify(".///.//./.", ".");
|
||||
test_path_simplify(".///.//././/", ".");
|
||||
test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.",
|
||||
"/aaa/.bbb/../c./d.dd/..eeee");
|
||||
test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
|
||||
"/aaa/.bbb/../c./d.dd/..eeee/..");
|
||||
test_path_simplify(".//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
|
||||
"aaa/.bbb/../c./d.dd/..eeee/..");
|
||||
test_path_simplify("..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
|
||||
"../aaa/.bbb/../c./d.dd/..eeee/..");
|
||||
|
||||
assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo"));
|
||||
assert_se(PATH_IN_SET("/bin", "/bin"));
|
||||
assert_se(PATH_IN_SET("/bin", "/foo/bar", "/bin"));
|
||||
@@ -82,6 +54,60 @@ static void test_path(void) {
|
||||
assert_se(!path_equal_filename("/b", "/c"));
|
||||
}
|
||||
|
||||
static void test_path_simplify_one(const char *in, const char *out) {
|
||||
char *p;
|
||||
|
||||
p = strdupa(in);
|
||||
path_simplify(p);
|
||||
log_debug("/* test_path_simplify(%s) → %s (expected: %s) */", in, p, out);
|
||||
assert_se(streq(p, out));
|
||||
}
|
||||
|
||||
static void test_path_simplify(void) {
|
||||
_cleanup_free_ char *hoge = NULL, *hoge_out = NULL;
|
||||
char foo[NAME_MAX * 2];
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
test_path_simplify_one("", "");
|
||||
test_path_simplify_one("aaa/bbb////ccc", "aaa/bbb/ccc");
|
||||
test_path_simplify_one("//aaa/.////ccc", "/aaa/ccc");
|
||||
test_path_simplify_one("///", "/");
|
||||
test_path_simplify_one("///.//", "/");
|
||||
test_path_simplify_one("///.//.///", "/");
|
||||
test_path_simplify_one("////.././///../.", "/../..");
|
||||
test_path_simplify_one(".", ".");
|
||||
test_path_simplify_one("./", ".");
|
||||
test_path_simplify_one(".///.//./.", ".");
|
||||
test_path_simplify_one(".///.//././/", ".");
|
||||
test_path_simplify_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.",
|
||||
"/aaa/.bbb/../c./d.dd/..eeee");
|
||||
test_path_simplify_one("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
|
||||
"/aaa/.bbb/../c./d.dd/..eeee/..");
|
||||
test_path_simplify_one(".//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
|
||||
"aaa/.bbb/../c./d.dd/..eeee/..");
|
||||
test_path_simplify_one("..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..",
|
||||
"../aaa/.bbb/../c./d.dd/..eeee/..");
|
||||
|
||||
memset(foo, 'a', sizeof(foo) -1);
|
||||
char_array_0(foo);
|
||||
|
||||
test_path_simplify_one(foo, foo);
|
||||
|
||||
hoge = strjoin("/", foo);
|
||||
assert_se(hoge);
|
||||
test_path_simplify_one(hoge, hoge);
|
||||
hoge = mfree(hoge);
|
||||
|
||||
hoge = strjoin("a////.//././//./b///././/./c/////././//./", foo, "//.//////d/e/.//f/");
|
||||
assert_se(hoge);
|
||||
|
||||
hoge_out = strjoin("a/b/c/", foo, "//.//////d/e/.//f/");
|
||||
assert_se(hoge_out);
|
||||
|
||||
test_path_simplify_one(hoge, hoge_out);
|
||||
}
|
||||
|
||||
static void test_path_compare_one(const char *a, const char *b, int expected) {
|
||||
int r;
|
||||
|
||||
@@ -1057,6 +1083,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
test_print_paths();
|
||||
test_path();
|
||||
test_path_simplify();
|
||||
test_path_compare();
|
||||
test_path_equal_root();
|
||||
test_find_executable_full();
|
||||
|
||||
Reference in New Issue
Block a user