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.
This commit is contained in:
parent
a5ea4b9f3f
commit
d3ea28d04a
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
/
|
||||
|
|
Loading…
Reference in New Issue