Skip to content

Commit d3ea28d

Browse files
robert-hhdpgeorge
authored andcommitted
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.
1 parent a5ea4b9 commit d3ea28d

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

extmod/vfs_lfsx.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,45 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
283283
}
284284

285285
// If not at root add trailing / to make it easy to build paths
286+
// and then normalise the path
286287
if (vstr_len(&self->cur_dir) != 1) {
287288
vstr_add_byte(&self->cur_dir, '/');
289+
290+
#define CWD_LEN (vstr_len(&self->cur_dir))
291+
size_t to = 1;
292+
size_t from = 1;
293+
char *cwd = vstr_str(&self->cur_dir);
294+
while (from < CWD_LEN) {
295+
for (; cwd[from] == '/' && from < CWD_LEN; ++from) {
296+
// Scan for the start
297+
}
298+
if (from > to) {
299+
// Found excessive slash chars, squeeze them out
300+
vstr_cut_out_bytes(&self->cur_dir, to, from - to);
301+
from = to;
302+
}
303+
for (; cwd[from] != '/' && from < CWD_LEN; ++from) {
304+
// Scan for the next /
305+
}
306+
if ((from - to) == 1 && cwd[to] == '.') {
307+
// './', ignore
308+
vstr_cut_out_bytes(&self->cur_dir, to, ++from - to);
309+
from = to;
310+
} else if ((from - to) == 2 && cwd[to] == '.' && cwd[to + 1] == '.') {
311+
// '../', skip back
312+
if (to > 1) {
313+
// Only skip back if not at the tip
314+
for (--to; to > 1 && cwd[to - 1] != '/'; --to) {
315+
// Skip back
316+
}
317+
}
318+
vstr_cut_out_bytes(&self->cur_dir, to, ++from - to);
319+
from = to;
320+
} else {
321+
// Normal element, keep it and just move the offset
322+
to = ++from;
323+
}
324+
}
288325
}
289326

290327
return mp_const_none;

tests/extmod/vfs_lfs.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ def test(bdev, vfs_class):
9898
print(list(vfs.ilistdir()))
9999

100100
# getcwd, chdir
101+
vfs.mkdir("/testdir2")
102+
vfs.mkdir("/testdir/subdir")
101103
print(vfs.getcwd())
102104
vfs.chdir("/testdir")
103105
print(vfs.getcwd())
@@ -111,7 +113,29 @@ def test(bdev, vfs_class):
111113
# chdir back to root and remove testdir
112114
vfs.chdir("/")
113115
print(vfs.getcwd())
116+
vfs.chdir("testdir")
117+
print(vfs.getcwd())
118+
vfs.chdir("..")
119+
print(vfs.getcwd())
120+
vfs.chdir("testdir/subdir")
121+
print(vfs.getcwd())
122+
vfs.chdir("../..")
123+
print(vfs.getcwd())
124+
vfs.chdir("/./testdir2")
125+
print(vfs.getcwd())
126+
vfs.chdir("../testdir")
127+
print(vfs.getcwd())
128+
vfs.chdir("../..")
129+
print(vfs.getcwd())
130+
vfs.chdir(".//testdir")
131+
print(vfs.getcwd())
132+
vfs.chdir("subdir/./")
133+
print(vfs.getcwd())
134+
vfs.chdir("/")
135+
print(vfs.getcwd())
136+
vfs.rmdir("testdir/subdir")
114137
vfs.rmdir("testdir")
138+
vfs.rmdir("testdir2")
115139

116140

117141
bdev = RAMBlockDevice(30)

tests/extmod/vfs_lfs.py.exp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ write 3
2323
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2424
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2525
/
26+
/testdir
27+
/
28+
/testdir/subdir
29+
/
30+
/testdir2
31+
/testdir
32+
/
33+
/testdir
34+
/testdir/subdir
35+
/
2636
test <class 'VfsLfs2'>
2737
(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255)
2838
(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255)
@@ -48,3 +58,13 @@ write 3
4858
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
4959
(32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
5060
/
61+
/testdir
62+
/
63+
/testdir/subdir
64+
/
65+
/testdir2
66+
/testdir
67+
/
68+
/testdir
69+
/testdir/subdir
70+
/

0 commit comments

Comments
 (0)