Skip to content

Commit e37dc5a

Browse files
committed
FS: lookupPath should throw an error on an empty string
It's inconsistent that lookupPath returns `node:null` when the path is an empty string. Normally it either raises `ENOENT` or `node` is truthy. This makes empty string into an edge case that every caller has to handle. `stat` has special handling for the empty string case and correctly returns ENOENT on empty string, but chmod, truncate, and mknod all crash. utime and some other functions mishandle the empty string in an unrelated way.
1 parent dde19fa commit e37dc5a

File tree

6 files changed

+23
-4
lines changed

6 files changed

+23
-4
lines changed

src/library_fs.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ FS.staticInit();
172172
// paths
173173
//
174174
lookupPath(path, opts = {}) {
175-
if (!path) return { path: '', node: null };
175+
if (!path)
176+
throw new FS.ErrnoError({{{ cDefs.ENOENT }}});
176177
opts.follow_mount ??= true
177178

178179
if (!PATH.isAbs(path)) {
@@ -948,9 +949,6 @@ FS.staticInit();
948949
stat(path, dontFollow) {
949950
var lookup = FS.lookupPath(path, { follow: !dontFollow });
950951
var node = lookup.node;
951-
if (!node) {
952-
throw new FS.ErrnoError({{{ cDefs.ENOENT }}});
953-
}
954952
if (!node.node_ops.getattr) {
955953
throw new FS.ErrnoError({{{ cDefs.EPERM }}});
956954
}

test/stat/test_chmod.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ void test() {
159159
assert(s.st_mode == (S_IRUSR | S_IFREG));
160160
#endif // WASMFS
161161

162+
// assert(stat("", &s) == -1);
163+
// assert(errno == ENOENT);
164+
// assert(chmod("", 0777) == -1);
165+
// assert(errno == ENOENT);
166+
assert(chown("", 1000, 1000) == -1);
167+
assert(errno == ENOENT);
168+
162169
puts("success");
163170
}
164171

test/stat/test_mknod.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ void test() {
5959
assert(S_ISCHR(s.st_mode));
6060
#endif // WASMFS
6161

62+
assert(mknod("", 0777, 0) == -1);
63+
assert(errno == ENOENT);
6264
#endif
6365

6466
//

test/unistd/truncate.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ int main() {
8686
errno = 0;
8787
printf("\n");
8888

89+
printf("truncate(empty_path, 2): %d\n", truncate("", 2));
90+
printf("errno: %s\n", strerror(errno));
91+
printf("\n");
92+
8993
printf("ftruncate(readonly, 4): %d\n", ftruncate(f2, 4));
9094
printf("errno: %s\n", strerror(errno));
9195
fstat(f2, &s);

test/unistd/truncate.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ truncate(readonly, 2): -1
2424
errno: Permission denied
2525
st_size: 6
2626

27+
truncate(empty_path, 2): -1
28+
errno: No such file or directory
29+
2730
ftruncate(readonly, 4): -1
2831
errno: Invalid argument
2932
st_size: 6

test/utime/test_futimens.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ void test() {
140140

141141
close(fd);
142142

143+
// TODO:
144+
// printf("check utime on empty path...\n");
145+
// assert(utime("", &tb) == -1);
146+
// assert(errno == ENOENT);
147+
143148
puts("success");
144149
}
145150

0 commit comments

Comments
 (0)