summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/tests/vfs.c6
-rw-r--r--src/kernel/vfs/path.c27
2 files changed, 16 insertions, 17 deletions
diff --git a/src/kernel/tests/vfs.c b/src/kernel/tests/vfs.c
index 8b450e5..339c6bd 100644
--- a/src/kernel/tests/vfs.c
+++ b/src/kernel/tests/vfs.c
@@ -38,6 +38,12 @@ TEST(path_simplify) {
TEST_WRAPPER("/asdf/.", "/asdf/");
TEST_WRAPPER("/asdf//.", "/asdf/");
+ TEST_WRAPPER("/foo/bar/..", "/foo/");
+ TEST_WRAPPER("/foo/bar/../bar", "/foo/bar");
+ TEST_WRAPPER("/foo/bar/../bar/", "/foo/bar/");
+ TEST_WRAPPER("/foo/bar/xyz/..", "/foo/bar/");
+ TEST_WRAPPER("/foo/bar/xyz/../", "/foo/bar/");
+
// going under the root or close to it
TEST_WRAPPER("/..", NULL);
TEST_WRAPPER("/../asdf", NULL);
diff --git a/src/kernel/vfs/path.c b/src/kernel/vfs/path.c
index 00af95c..096d3fe 100644
--- a/src/kernel/vfs/path.c
+++ b/src/kernel/vfs/path.c
@@ -5,7 +5,6 @@ int path_simplify(const char *in, char *out, size_t len) {
if (len == 0) return -1; // empty paths are invalid
if (in[0] != '/') return -1; // so are relative paths
- int depth = 0; // shouldn't be needed!
int seg_len; // the length of the current path segment
int out_pos = 0;
bool directory = 0;
@@ -33,32 +32,26 @@ int path_simplify(const char *in, char *out, size_t len) {
* (segment starts at i+1) */
if (seg_len == 0 || (seg_len == 1 && in[i + 1] == '.')) {
- // the segment is // or /./
+ /* // or /./ */
directory = true;
} else if (seg_len == 2 && in[i + 1] == '.' && in[i + 2] == '.') {
- // the segment is /../
- if (--depth < 0)
- return -1;
- // backtrack to last slash
- while (out[--out_pos] != '/');
+ /* /../ */
+ directory = true;
+
+ /* try to backtrack to the last slash */
+ while (--out_pos >= 0 && out[out_pos] != '/');
+ if (out_pos < 0) return -1;
} else {
- // normal segment
+ /* a normal segment, e.g. /asdf/ */
out[out_pos] = '/';
memcpy(&out[out_pos + 1], &in[i + 1], seg_len);
out_pos += seg_len + 1;
- depth++;
}
}
- /* if we were backtracking, out_pos can become 0. i don't like this,
- * it feels sloppy. this algorithm should be implemented differently. TODO? */
- if (out_pos == 0)
- out[out_pos++] = '/';
-
- if (directory) // if the path refers to a directory, append a trailing slash
- if (out[out_pos-1] != '/') // unless it's already there
- out[out_pos++] = '/';
+ /* paths to directories should have a trailing slash */
+ if (directory) out[out_pos++] = '/';
return out_pos;
}