systemd: fix handling special cases kill_dots and path_simplify()

Previously, paths like ".", "./", ./." would all result in an
empty path. That is wrong, one dot must be kept.

afbae3e9f2
This commit is contained in:
Thomas Haller 2018-10-05 11:40:50 +02:00
parent eece5aff09
commit 9dce4a426b
2 changed files with 21 additions and 13 deletions

View file

@ -337,12 +337,15 @@ char *path_simplify(char *path, bool kill_dots) {
/* 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/. (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/. (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)
*/
if (isempty(path))
return path;
absolute = path_is_absolute(path);
f = path;
@ -372,9 +375,14 @@ char *path_simplify(char *path, bool kill_dots) {
*(t++) = *f;
}
/* Special rule, if we are talking of the root directory, a trailing slash is good */
if (absolute && t == path)
*(t++) = '/';
/* 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++) = '.';
}
*t = 0;
return path;

View file

@ -201,16 +201,16 @@ test_path_equal (void)
} G_STMT_END
_path_equal_check ("", "", NULL);
_path_equal_check (".", ".", "");
_path_equal_check (".", ".", NULL);
_path_equal_check ("..", "..", NULL);
_path_equal_check ("/..", "/..", NULL);
_path_equal_check ("//..", "/..", NULL);
_path_equal_check ("/.", "/.", "/");
_path_equal_check ("./", ".", "");
_path_equal_check ("./.", "./.", "");
_path_equal_check (".///.", "./.", "");
_path_equal_check (".///./", "./.", "");
_path_equal_check (".////", ".", "");
_path_equal_check ("./", ".", ".");
_path_equal_check ("./.", "./.", ".");
_path_equal_check (".///.", "./.", ".");
_path_equal_check (".///./", "./.", ".");
_path_equal_check (".////", ".", ".");
_path_equal_check ("//..//foo/", "/../foo", NULL);
_path_equal_check ("///foo//./bar/.", "/foo/./bar/.", "/foo/bar");
_path_equal_check (".//./foo//./bar/.", "././foo/./bar/.", "foo/bar");