Skip to content

Commit

Permalink
[FS] Make fstat work on file descriptors with no name in memfs (#23470)
Browse files Browse the repository at this point in the history
This makes fstat work on anonymous memfs file descriptors. It is split
off from #23058.
  • Loading branch information
hoodmane authored Jan 23, 2025
1 parent 738a20a commit 5cdda14
Show file tree
Hide file tree
Showing 21 changed files with 70 additions and 53 deletions.
79 changes: 49 additions & 30 deletions src/lib/libfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,13 @@ FS.staticInit();
stream.stream_ops?.dup?.(stream);
return stream;
},
doSetAttr(stream, node, attr) {
var setattr = stream?.stream_ops.setattr;
var arg = setattr ? stream : node;
setattr ??= node.node_ops.setattr;
FS.checkOpExists(setattr, {{{ cDefs.EPERM }}})
setattr(arg, attr);
},

//
// devices
Expand Down Expand Up @@ -966,11 +973,24 @@ FS.staticInit();
return getattr(node);
},
fstat(fd) {
return FS.stat(FS.getStreamChecked(fd).path);
var stream = FS.getStreamChecked(fd);
var node = stream.node;
var getattr = stream.stream_ops.getattr;
var arg = getattr ? stream : node;
getattr ??= node.node_ops.getattr;
FS.checkOpExists(getattr, {{{ cDefs.EPERM }}})
return getattr(arg);
},
lstat(path) {
return FS.stat(path, true);
},
doChmod(stream, node, mode, dontFollow) {
FS.doSetAttr(stream, node, {
mode: (mode & {{{ cDefs.S_IALLUGO }}}) | (node.mode & ~{{{ cDefs.S_IALLUGO }}}),
ctime: Date.now(),
dontFollow
});
},
chmod(path, mode, dontFollow) {
var node;
if (typeof path == 'string') {
Expand All @@ -979,19 +999,21 @@ FS.staticInit();
} else {
node = path;
}
var setattr = FS.checkOpExists(node.node_ops.setattr, {{{ cDefs.EPERM }}});
setattr(node, {
mode: (mode & {{{ cDefs.S_IALLUGO }}}) | (node.mode & ~{{{ cDefs.S_IALLUGO }}}),
ctime: Date.now(),
dontFollow
});
FS.doChmod(null, node, mode, dontFollow);
},
lchmod(path, mode) {
FS.chmod(path, mode, true);
},
fchmod(fd, mode) {
var stream = FS.getStreamChecked(fd);
FS.chmod(stream.node, mode);
FS.doChmod(stream, stream.node, mode, false);
},
doChown(stream, node, dontFollow) {
FS.doSetAttr(stream, node, {
timestamp: Date.now(),
dontFollow
// we ignore the uid / gid for now
});
},
chown(path, uid, gid, dontFollow) {
var node;
Expand All @@ -1001,31 +1023,16 @@ FS.staticInit();
} else {
node = path;
}
var setattr = FS.checkOpExists(node.node_ops.setattr, {{{ cDefs.EPERM }}});
setattr(node, {
timestamp: Date.now(),
dontFollow
// we ignore the uid / gid for now
});
FS.doChown(null, node, dontFollow);
},
lchown(path, uid, gid) {
FS.chown(path, uid, gid, true);
},
fchown(fd, uid, gid) {
var stream = FS.getStreamChecked(fd);
FS.chown(stream.node, uid, gid);
FS.doChown(stream, stream.node, false);
},
truncate(path, len) {
if (len < 0) {
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
}
var node;
if (typeof path == 'string') {
var lookup = FS.lookupPath(path, { follow: true });
node = lookup.node;
} else {
node = path;
}
doTruncate(stream, node, len) {
if (FS.isDir(node.mode)) {
throw new FS.ErrnoError({{{ cDefs.EISDIR }}});
}
Expand All @@ -1036,18 +1043,30 @@ FS.staticInit();
if (errCode) {
throw new FS.ErrnoError(errCode);
}
var setattr = FS.checkOpExists(node.node_ops.setattr, {{{ cDefs.EPERM }}});
setattr(node, {
FS.doSetAttr(stream, node, {
size: len,
timestamp: Date.now()
});
},
truncate(path, len) {
if (len < 0) {
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
}
var node;
if (typeof path == 'string') {
var lookup = FS.lookupPath(path, { follow: true });
node = lookup.node;
} else {
node = path;
}
FS.doTruncate(null, node, len);
},
ftruncate(fd, len) {
var stream = FS.getStreamChecked(fd);
if ((stream.flags & {{{ cDefs.O_ACCMODE }}}) === {{{ cDefs.O_RDONLY}}}) {
if (len < 0 || (stream.flags & {{{ cDefs.O_ACCMODE }}}) === {{{ cDefs.O_RDONLY}}}) {
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
}
FS.truncate(stream.node, len);
FS.doTruncate(stream, stream.node, len);
},
utime(path, atime, mtime) {
var lookup = FS.lookupPath(path, { follow: true });
Expand Down
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors1.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8343
8359
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors1.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20273
20296
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors2.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8327
8341
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors2.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20241
20264
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9343
9358
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24041
24064
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except_wasm.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8294
8303
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except_wasm.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20166
20189
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8294
8303
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20166
20189
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_lto.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8357
8372
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_lto.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20348
20371
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_mangle.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9349
9364
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_mangle.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24041
24064
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_noexcept.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8343
8359
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_noexcept.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20273
20296
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_js_fs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7647
7669
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_js_fs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18820
18843
6 changes: 2 additions & 4 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5845,10 +5845,8 @@ def test_fs_64bit(self):
@crossplatform
@with_all_fs
def test_fs_stat_unnamed_file_descriptor(self):
noderawfs = '-DNODERAWFS' in self.emcc_args
wasmfs = self.get_setting('WASMFS')
if not (noderawfs or wasmfs):
self.skipTest('TODO: doesnt work in memfs or nodefs')
if '-DNODEFS' in self.emcc_args:
self.skipTest('TODO: doesnt work in nodefs')
self.do_runf('fs/test_stat_unnamed_file_descriptor.c', 'success')

@requires_node
Expand Down
2 changes: 1 addition & 1 deletion test/unistd/dup.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ int main() {

printf("DUP truncate\n");
f = open("./blah.txt", O_RDWR, 0600);
f2 = dup(f);
assert(f != -1);
f2 = dup(f);
assert(f2 != -1);
rtn = ftruncate(f2, 0);
assert(rtn == 0);
Expand Down

0 comments on commit 5cdda14

Please sign in to comment.