Skip to content

Commit 81b7179

Browse files
authored
Add nodefs readdir handling for directories that contain exotic entries (#22925)
Resolves #22924.
1 parent 41eb941 commit 81b7179

File tree

5 files changed

+64
-6
lines changed

5 files changed

+64
-6
lines changed

src/library_syscall.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -695,9 +695,9 @@ var SyscallsLibrary = {
695695
var pos = 0;
696696
var off = FS.llseek(stream, 0, {{{ cDefs.SEEK_CUR }}});
697697
698-
var idx = Math.floor(off / struct_size);
699-
700-
while (idx < stream.getdents.length && pos + struct_size <= count) {
698+
var startIdx = Math.floor(off / struct_size);
699+
var endIdx = Math.min(stream.getdents.length, startIdx + Math.floor(count/struct_size))
700+
for (var idx = startIdx; idx < endIdx; idx++) {
701701
var id;
702702
var type;
703703
var name = stream.getdents[idx];
@@ -711,7 +711,17 @@ var SyscallsLibrary = {
711711
type = 4; // DT_DIR
712712
}
713713
else {
714-
var child = FS.lookupNode(stream.node, name);
714+
var child;
715+
try {
716+
child = FS.lookupNode(stream.node, name);
717+
} catch (e) {
718+
// If the entry is not a directory, file, or symlink, nodefs
719+
// lookupNode will raise EINVAL. Skip these and continue.
720+
if (e?.errno === {{{ cDefs.EINVAL }}}) {
721+
continue;
722+
}
723+
throw e;
724+
}
715725
id = child.id;
716726
type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device.
717727
FS.isDir(child.mode) ? 4 : // DT_DIR, directory.
@@ -727,7 +737,6 @@ var SyscallsLibrary = {
727737
{{{ makeSetValue('dirp + pos', C_STRUCTS.dirent.d_type, 'type', 'i8') }}};
728738
stringToUTF8(name, dirp + pos + {{{ C_STRUCTS.dirent.d_name }}}, 256);
729739
pos += struct_size;
730-
idx += 1;
731740
}
732741
FS.llseek(stream, idx * struct_size, {{{ cDefs.SEEK_SET }}});
733742
return pos;

test/fs/test_nodefs_readdir.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
listing contents of dir=/
2+
.
3+
..
4+
tmp
5+
home
6+
dev
7+
proc
8+
listing contents of dir=/working
9+
existing
10+
stdout
11+
test_nodefs_readdir.js
12+
test_nodefs_readdir.wasm
13+
success
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
listing contents of dir=/
2+
.
3+
..
4+
tmp
5+
home
6+
dev
7+
proc
8+
listing contents of dir=/working
9+
existing
10+
stdout
11+
test_nodefs_readdir.js
12+
success
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
listing contents of dir=/
2+
.
3+
..
4+
dev
5+
tmp
6+
listing contents of dir=/working
7+
.
8+
..
9+
existing
10+
named_pipe
11+
stdout
12+
test_nodefs_readdir.js
13+
test_nodefs_readdir.wasm
14+
success

test/test_core.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5779,14 +5779,24 @@ def test_fs_nodefs_nofollow(self):
57795779
self.emcc_args += ['-lnodefs.js']
57805780
self.do_runf('fs/test_nodefs_nofollow.c', 'success')
57815781

5782+
@crossplatform
57825783
@requires_node
57835784
def test_fs_nodefs_readdir(self):
57845785
# externally setup an existing folder structure: existing/a
57855786
if self.get_setting('WASMFS'):
57865787
self.set_setting('FORCE_FILESYSTEM')
5788+
if not WINDOWS:
5789+
# Add an entry that isn't a directory, file, or link to test that we handle
5790+
# it correctly.
5791+
os.mkfifo('named_pipe')
57875792
os.makedirs('existing/a')
57885793
self.emcc_args += ['-lnodefs.js']
5789-
self.do_runf('fs/test_nodefs_readdir.c', 'success')
5794+
suffix = ''
5795+
if self.get_setting('WASMFS'):
5796+
suffix = '.wasmfs'
5797+
elif self.is_wasm2js():
5798+
suffix = ".wasm2js"
5799+
self.do_run_in_out_file_test('fs/test_nodefs_readdir.c', out_suffix=suffix)
57905800

57915801
@requires_node
57925802
@crossplatform

0 commit comments

Comments
 (0)