Skip to content

Commit ca3c1f5

Browse files
authored
Always virtualize file descriptors when using NODERAWFS (#19528)
At least for the `dup*()` syscalls, virtualizing the file descriptors is necessary due to the absence of an API for these functions in Node.js. This commit ensures that a virtualized file descriptor is always returned, even for the `open()` system call and similar functions. While doing that, it revealed a few regressions in the NODERAWFS implementation of `fchmod()`, `fchown()` and `ftruncate()` as they were not remapping virtualized file descriptors to their native counterparts.
1 parent 69987f1 commit ca3c1f5

File tree

3 files changed

+51
-21
lines changed

3 files changed

+51
-21
lines changed

src/library_noderawfs.js

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,32 @@ mergeInto(LibraryManager.library, {
6969
stat: function() { return fs.statSync.apply(void 0, arguments); },
7070
lstat: function() { return fs.lstatSync.apply(void 0, arguments); },
7171
chmod: function() { fs.chmodSync.apply(void 0, arguments); },
72-
fchmod: function() { fs.fchmodSync.apply(void 0, arguments); },
72+
fchmod: function(fd, mode) {
73+
var stream = FS.getStream(fd);
74+
if (!stream) {
75+
throw new FS.ErrnoError({{{ cDefs.EBADF }}});
76+
}
77+
fs.fchmodSync(stream.nfd, mode);
78+
},
7379
chown: function() { fs.chownSync.apply(void 0, arguments); },
74-
fchown: function() { fs.fchownSync.apply(void 0, arguments); },
80+
fchown: function(fd, owner, group) {
81+
var stream = FS.getStream(fd);
82+
if (!stream) {
83+
throw new FS.ErrnoError({{{ cDefs.EBADF }}});
84+
}
85+
fs.fchownSync(stream.nfd, owner, group);
86+
},
7587
truncate: function() { fs.truncateSync.apply(void 0, arguments); },
7688
ftruncate: function(fd, len) {
7789
// See https://github.com/nodejs/node/issues/35632
7890
if (len < 0) {
7991
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
8092
}
81-
fs.ftruncateSync.apply(void 0, arguments);
93+
var stream = FS.getStream(fd);
94+
if (!stream) {
95+
throw new FS.ErrnoError({{{ cDefs.EBADF }}});
96+
}
97+
fs.ftruncateSync(stream.nfd, len);
8298
},
8399
utime: function(path, atime, mtime) { fs.utimesSync(path, atime/1000, mtime/1000); },
84100
open: function(path, flags, mode) {
@@ -94,7 +110,7 @@ mergeInto(LibraryManager.library, {
94110
}
95111
var newMode = NODEFS.getMode(pathTruncated);
96112
var node = { id: st.ino, mode: newMode, node_ops: NODERAWFS, path: path }
97-
return FS.createStream({ nfd: nfd, position: 0, path: path, flags: flags, node: node, seekable: true }, nfd);
113+
return FS.createStream({ nfd: nfd, position: 0, path: path, flags: flags, node: node, seekable: true });
98114
},
99115
createStream: function(stream, fd) {
100116
// Call the original FS.createStream
@@ -106,16 +122,11 @@ mergeInto(LibraryManager.library, {
106122
}
107123
return rtn;
108124
},
109-
closeStream: function(fd) {
110-
if (FS.streams[fd]) {
111-
FS.streams[fd].shared.refcnt--;
112-
}
113-
VFS.closeStream(fd);
114-
},
115125
close: function(stream) {
116-
FS.closeStream(stream.fd);
117-
if (!stream.stream_ops && stream.shared.refcnt === 0) {
118-
// this stream is created by in-memory filesystem
126+
VFS.closeStream(stream.fd);
127+
if (!stream.stream_ops && --stream.shared.refcnt === 0) {
128+
// This stream is created by our Node.js filesystem, close the
129+
// native file descriptor when its reference count drops to 0.
119130
fs.closeSync(stream.nfd);
120131
}
121132
},

test/unistd/dup.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,26 @@ int main() {
6464
assert(strcmp(buf, "abc") == 0);
6565
printf("\n");
6666

67-
printf("DUP2 shared seek position\n");
68-
int fd1 = open("./blah.txt", O_RDWR | O_CREAT | O_EXCL, 0600);
69-
int fd2 = dup(fd1);
70-
int n = write(fd1, "abcabc\n", 7);
71-
assert(n == 7);
72-
assert(lseek(fd1, 0, SEEK_CUR) == 7);
73-
assert(lseek(fd2, 0, SEEK_CUR) == 7);
67+
printf("DUP shared seek position\n");
68+
f = open("./blah.txt", O_RDWR | O_CREAT | O_EXCL, 0600);
69+
f2 = dup(f);
70+
rtn = write(f2, "abcabc\n", 7);
71+
assert(rtn == 7);
72+
assert(lseek(f, 0, SEEK_CUR) == 7);
73+
assert(lseek(f2, 0, SEEK_CUR) == 7);
74+
printf("close(f): %d\n", close(f));
75+
printf("close(f2): %d\n", close(f2));
76+
printf("\n");
77+
78+
printf("DUP truncate\n");
79+
f = open("./blah.txt", O_RDWR, 0600);
80+
f2 = dup(f);
81+
rtn = ftruncate(f2, 0);
82+
assert(rtn == 0);
83+
assert(lseek(f, 0, SEEK_END) == 0);
84+
assert(lseek(f2, 0, SEEK_END) == 0);
85+
printf("close(f): %d\n", close(f));
86+
printf("close(f2): %d\n", close(f2));
7487

7588
return 0;
7689
}

test/unistd/dup.out

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,10 @@ close(f): -1
2222
DUP2 pipe
2323
buf: abc
2424

25-
DUP2 shared seek position
25+
DUP shared seek position
26+
close(f): 0
27+
close(f2): 0
28+
29+
DUP truncate
30+
close(f): 0
31+
close(f2): 0

0 commit comments

Comments
 (0)