diff options
author | robert <robert@hammelrath.com> | 2020-05-03 21:05:08 +0200 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2020-05-08 21:52:15 +1000 |
commit | d3ea28d04a7df9ca536a9002c8fda2f6e3a88f09 (patch) | |
tree | 130170efeea1cb3f89fa2f6c0faf7ef394b6f259 | |
parent | a5ea4b9f3f3fd394afdf65223b5e55c8d9fccc53 (diff) | |
download | micropython-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.c | 37 | ||||
-rw-r--r-- | tests/extmod/vfs_lfs.py | 24 | ||||
-rw-r--r-- | tests/extmod/vfs_lfs.py.exp | 20 |
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 +/ |