summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorrobert <robert@hammelrath.com>2020-05-03 21:05:08 +0200
committerDamien George <damien.p.george@gmail.com>2020-05-08 21:52:15 +1000
commitd3ea28d04a7df9ca536a9002c8fda2f6e3a88f09 (patch)
tree130170efeea1cb3f89fa2f6c0faf7ef394b6f259
parenta5ea4b9f3f3fd394afdf65223b5e55c8d9fccc53 (diff)
downloadmicropython-d3ea28d04a7df9ca536a9002c8fda2f6e3a88f09.tar.gz
micropython-d3ea28d04a7df9ca536a9002c8fda2f6e3a88f09.zip
extmod/vfs_lfsx: Normalize path name in chdir.
This change scans for '.', '..' and multiple '/' and normalizes the new path name. If the resulting path does not exist, an error is raised. Non-existing interim path elements are ignored if they are removed during normalization.
-rw-r--r--extmod/vfs_lfsx.c37
-rw-r--r--tests/extmod/vfs_lfs.py24
-rw-r--r--tests/extmod/vfs_lfs.py.exp20
3 files changed, 81 insertions, 0 deletions
diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c
index 9474e960fc..5dcf951bc7 100644
--- a/extmod/vfs_lfsx.c
+++ b/extmod/vfs_lfsx.c
@@ -283,8 +283,45 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
}
// If not at root add trailing / to make it easy to build paths
+ // and then normalise the path
if (vstr_len(&self->cur_dir) != 1) {
vstr_add_byte(&self->cur_dir, '/');
+
+ #define CWD_LEN (vstr_len(&self->cur_dir))
+ size_t to = 1;
+ size_t from = 1;
+ char *cwd = vstr_str(&self->cur_dir);
+ while (from < CWD_LEN) {
+ for (; cwd[from] == '/' && from < CWD_LEN; ++from) {
+ // Scan for the start
+ }
+ if (from > to) {
+ // Found excessive slash chars, squeeze them out
+ vstr_cut_out_bytes(&self->cur_dir, to, from - to);
+ from = to;
+ }
+ for (; cwd[from] != '/' && from < CWD_LEN; ++from) {
+ // Scan for the next /
+ }
+ if ((from - to) == 1 && cwd[to] == '.') {
+ // './', ignore
+ vstr_cut_out_bytes(&self->cur_dir, to, ++from - to);
+ from = to;
+ } else if ((from - to) == 2 && cwd[to] == '.' && cwd[to + 1] == '.') {
+ // '../', skip back
+ if (to > 1) {
+ // Only skip back if not at the tip
+ for (--to; to > 1 && cwd[to - 1] != '/'; --to) {
+ // Skip back
+ }
+ }
+ vstr_cut_out_bytes(&self->cur_dir, to, ++from - to);
+ from = to;
+ } else {
+ // Normal element, keep it and just move the offset
+ to = ++from;
+ }
+ }
}
return mp_const_none;
diff --git a/tests/extmod/vfs_lfs.py b/tests/extmod/vfs_lfs.py
index 1d47605c55..82c8fead5a 100644
--- a/tests/extmod/vfs_lfs.py
+++ b/tests/extmod/vfs_lfs.py
@@ -98,6 +98,8 @@ def test(bdev, vfs_class):
print(list(vfs.ilistdir()))
# getcwd, chdir
+ vfs.mkdir("/testdir2")
+ vfs.mkdir("/testdir/subdir")
print(vfs.getcwd())
vfs.chdir("/testdir")
print(vfs.getcwd())
@@ -111,7 +113,29 @@ def test(bdev, vfs_class):
# chdir back to root and remove testdir
vfs.chdir("/")
print(vfs.getcwd())
+ vfs.chdir("testdir")
+ print(vfs.getcwd())
+ vfs.chdir("..")
+ print(vfs.getcwd())
+ vfs.chdir("testdir/subdir")
+ print(vfs.getcwd())
+ vfs.chdir("../..")
+ print(vfs.getcwd())
+ vfs.chdir("/./testdir2")
+ print(vfs.getcwd())
+ vfs.chdir("../testdir")
+ print(vfs.getcwd())
+ vfs.chdir("../..")
+ print(vfs.getcwd())
+ vfs.chdir(".//testdir")
+ print(vfs.getcwd())
+ vfs.chdir("subdir/./")
+ print(vfs.getcwd())
+ vfs.chdir("/")
+ print(vfs.getcwd())
+ vfs.rmdir("testdir/subdir")
vfs.rmdir("testdir")
+ vfs.rmdir("testdir2")
bdev = RAMBlockDevice(30)
diff --git a/tests/extmod/vfs_lfs.py.exp b/tests/extmod/vfs_lfs.py.exp
index de739e7330..4cfd74b474 100644
--- a/tests/extmod/vfs_lfs.py.exp
+++ b/tests/extmod/vfs_lfs.py.exp
@@ -23,6 +23,16 @@ write 3
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
/
+/testdir
+/
+/testdir/subdir
+/
+/testdir2
+/testdir
+/
+/testdir
+/testdir/subdir
+/
test <class 'VfsLfs2'>
(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255)
(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255)
@@ -48,3 +58,13 @@ write 3
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
/
+/testdir
+/
+/testdir/subdir
+/
+/testdir2
+/testdir
+/
+/testdir
+/testdir/subdir
+/