Skip to content

Commit fe1e70e

Browse files
committed
[FS] Make fstat work on file descriptors with no name in memfs
This makes fstat work on anonymous memfs file descriptors. It is split off from emscripten-core#23058.
1 parent 9d4abe8 commit fe1e70e

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

src/lib/libfs.js

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,24 @@ FS.staticInit();
487487
stream.stream_ops?.dup?.(stream);
488488
return stream;
489489
},
490+
streamGetAttr(stream) {
491+
var node = stream.node;
492+
var res = stream.stream_ops?.getattr?.(stream) ?? node.node_ops?.getattr?.(node);
493+
if (res) {
494+
return res;
495+
}
496+
throw new FS.ErrnoError({{{ cDefs.EPERM }}});
497+
},
498+
streamSetAttr(stream, attr) {
499+
var node = stream.node;
500+
var set;
501+
if (set = stream.stream_ops.setattr) {
502+
return set(stream, attr);
503+
} else if (set = node.node_ops.setattr) {
504+
return set(node, attr);
505+
}
506+
throw new FS.ErrnoError({{{ cDefs.EPERM }}});
507+
},
490508

491509
//
492510
// devices
@@ -966,7 +984,8 @@ FS.staticInit();
966984
return getattr(node);
967985
},
968986
fstat(fd) {
969-
return FS.stat(FS.getStreamChecked(fd).path);
987+
var stream = FS.getStreamChecked(fd);
988+
return FS.streamGetAttr(stream);
970989
},
971990
lstat(path) {
972991
return FS.stat(path, true);
@@ -991,7 +1010,10 @@ FS.staticInit();
9911010
},
9921011
fchmod(fd, mode) {
9931012
var stream = FS.getStreamChecked(fd);
994-
FS.chmod(stream.node, mode);
1013+
FS.streamSetAttr(stream, {
1014+
mode: (mode & {{{ cDefs.S_IALLUGO }}}) | (stream.node.mode & ~{{{ cDefs.S_IALLUGO }}}),
1015+
ctime: Date.now()
1016+
});
9951017
},
9961018
chown(path, uid, gid, dontFollow) {
9971019
var node;
@@ -1013,7 +1035,22 @@ FS.staticInit();
10131035
},
10141036
fchown(fd, uid, gid) {
10151037
var stream = FS.getStreamChecked(fd);
1016-
FS.chown(stream.node, uid, gid);
1038+
FS.streamSetAttr(stream, {
1039+
timestamp: Date.now()
1040+
// we ignore the uid / gid for now
1041+
});
1042+
},
1043+
truncateChecks(node) {
1044+
if (FS.isDir(node.mode)) {
1045+
throw new FS.ErrnoError({{{ cDefs.EISDIR }}});
1046+
}
1047+
if (!FS.isFile(node.mode)) {
1048+
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
1049+
}
1050+
var errCode = FS.nodePermissions(node, 'w');
1051+
if (errCode) {
1052+
throw new FS.ErrnoError(errCode);
1053+
}
10171054
},
10181055
truncate(path, len) {
10191056
if (len < 0) {
@@ -1026,16 +1063,7 @@ FS.staticInit();
10261063
} else {
10271064
node = path;
10281065
}
1029-
if (FS.isDir(node.mode)) {
1030-
throw new FS.ErrnoError({{{ cDefs.EISDIR }}});
1031-
}
1032-
if (!FS.isFile(node.mode)) {
1033-
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
1034-
}
1035-
var errCode = FS.nodePermissions(node, 'w');
1036-
if (errCode) {
1037-
throw new FS.ErrnoError(errCode);
1038-
}
1066+
FS.truncateChecks(node);
10391067
var setattr = FS.checkOpExists(node.node_ops.setattr, {{{ cDefs.EPERM }}});
10401068
setattr(node, {
10411069
size: len,
@@ -1044,10 +1072,14 @@ FS.staticInit();
10441072
},
10451073
ftruncate(fd, len) {
10461074
var stream = FS.getStreamChecked(fd);
1047-
if ((stream.flags & {{{ cDefs.O_ACCMODE }}}) === {{{ cDefs.O_RDONLY}}}) {
1075+
if (len < 0 || (stream.flags & {{{ cDefs.O_ACCMODE }}}) === {{{ cDefs.O_RDONLY}}}) {
10481076
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
10491077
}
1050-
FS.truncate(stream.node, len);
1078+
FS.truncateChecks(stream.node);
1079+
FS.streamSetAttr(stream, {
1080+
size: len,
1081+
timestamp: Date.now()
1082+
});
10511083
},
10521084
utime(path, atime, mtime) {
10531085
var lookup = FS.lookupPath(path, { follow: true });

test/test_core.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5845,10 +5845,9 @@ def test_fs_64bit(self):
58455845
@crossplatform
58465846
@with_all_fs
58475847
def test_fs_stat_unnamed_file_descriptor(self):
5848-
noderawfs = '-DNODERAWFS' in self.emcc_args
5849-
wasmfs = self.get_setting('WASMFS')
5850-
if not (noderawfs or wasmfs):
5851-
self.skipTest('TODO: doesnt work in memfs or nodefs')
5848+
nodefs = '-DNODEFS' in self.emcc_args
5849+
if nodefs:
5850+
self.skipTest('TODO: doesnt work in nodefs')
58525851
self.do_runf('fs/test_stat_unnamed_file_descriptor.c', 'success')
58535852

58545853
@requires_node

0 commit comments

Comments
 (0)