summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-10-05 11:40:50 +0200
committerThomas Haller <thaller@redhat.com>2018-10-23 10:32:53 +0200
commit9dce4a426ba82307cd27de23f3f3d8aed569d79b (patch)
treeca513a95ae2dae9ba93025f6fd4343c829748b32
parenteece5aff0992c9076a9b5513e2a893e37e4999ea (diff)
downloadNetworkManager-9dce4a426ba82307cd27de23f3f3d8aed569d79b.tar.gz
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. https://github.com/systemd/systemd/commit/afbae3e9f23dc6682d48a1cc3585e8429ef07d8b
-rw-r--r--src/systemd/src/basic/path-util.c22
-rw-r--r--src/tests/test-systemd.c12
2 files changed, 21 insertions, 13 deletions
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index b758c34d0c..5877957822 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -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;
diff --git a/src/tests/test-systemd.c b/src/tests/test-systemd.c
index 4660bd0d17..6015e9df07 100644
--- a/src/tests/test-systemd.c
+++ b/src/tests/test-systemd.c
@@ -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");