Skip to content

Commit 4c3c38f

Browse files
committed
vfs: add remaining fs/promises VFS interceptions
Intercept the remaining ~18 fs methods that still called C++ bindings directly when operating on VFS paths/FDs: Path-based no-ops (VFS doesn't track permissions/ownership/timestamps): - chown/chownSync, lchown/lchownSync, lutimes/lutimesSync FD-based no-ops (VFS FDs don't need sync/permissions/ownership): - fchmod/fchmodSync, fchown/fchownSync, futimes/futimesSync, fdatasync/fdatasyncSync, fsync/fsyncSync Real implementations: - statfs/statfsSync (return synthetic StatFs for VFS mount) - readv/readvSync (scatter read via readSync loop) - writev/writevSync (gather write via writeSync loop) Promise API: - lchmod, lchown, chown, lutimes, statfs Also moves the VFS check in promises.lchmod() before the O_SYMLINK gate so it works on Linux where O_SYMLINK is undefined.
1 parent 91889e1 commit 4c3c38f

File tree

4 files changed

+664
-9
lines changed

4 files changed

+664
-9
lines changed

lib/fs.js

Lines changed: 196 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -876,12 +876,26 @@ function readv(fd, buffers, position, callback) {
876876
callback ||= position;
877877
validateFunction(callback, 'cb');
878878

879-
const req = new FSReqCallback();
880-
req.oncomplete = wrapper;
881-
882879
if (typeof position !== 'number')
883880
position = null;
884881

882+
const h = vfsState.handlers;
883+
if (h !== null) {
884+
try {
885+
const result = h.readvSync(fd, buffers, position);
886+
if (result !== undefined) {
887+
process.nextTick(callback, null, result, buffers);
888+
return;
889+
}
890+
} catch (err) {
891+
process.nextTick(callback, err);
892+
return;
893+
}
894+
}
895+
896+
const req = new FSReqCallback();
897+
req.oncomplete = wrapper;
898+
885899
binding.readBuffers(fd, buffers, position, req);
886900
}
887901

@@ -903,6 +917,12 @@ function readvSync(fd, buffers, position) {
903917
if (typeof position !== 'number')
904918
position = null;
905919

920+
const h = vfsState.handlers;
921+
if (h !== null) {
922+
const result = h.readvSync(fd, buffers, position);
923+
if (result !== undefined) return result;
924+
}
925+
906926
return binding.readBuffers(fd, buffers, position);
907927
}
908928

@@ -1106,12 +1126,26 @@ function writev(fd, buffers, position, callback) {
11061126
return;
11071127
}
11081128

1109-
const req = new FSReqCallback();
1110-
req.oncomplete = wrapper;
1111-
11121129
if (typeof position !== 'number')
11131130
position = null;
11141131

1132+
const h = vfsState.handlers;
1133+
if (h !== null) {
1134+
try {
1135+
const result = h.writevSync(fd, buffers, position);
1136+
if (result !== undefined) {
1137+
process.nextTick(callback, null, result, buffers);
1138+
return;
1139+
}
1140+
} catch (err) {
1141+
process.nextTick(callback, err);
1142+
return;
1143+
}
1144+
}
1145+
1146+
const req = new FSReqCallback();
1147+
req.oncomplete = wrapper;
1148+
11151149
binding.writeBuffers(fd, buffers, position, req);
11161150
}
11171151

@@ -1139,6 +1173,12 @@ function writevSync(fd, buffers, position) {
11391173
if (typeof position !== 'number')
11401174
position = null;
11411175

1176+
const h = vfsState.handlers;
1177+
if (h !== null) {
1178+
const result = h.writevSync(fd, buffers, position);
1179+
if (result !== undefined) return result;
1180+
}
1181+
11421182
return binding.writeBuffers(fd, buffers, position);
11431183
}
11441184

@@ -1476,8 +1516,19 @@ function rmSync(path, options) {
14761516
* @returns {void}
14771517
*/
14781518
function fdatasync(fd, callback) {
1519+
callback = makeCallback(callback);
1520+
1521+
const h = vfsState.handlers;
1522+
if (h !== null) {
1523+
const result = h.fdatasyncSync(fd);
1524+
if (result !== undefined) {
1525+
process.nextTick(callback, null);
1526+
return;
1527+
}
1528+
}
1529+
14791530
const req = new FSReqCallback();
1480-
req.oncomplete = makeCallback(callback);
1531+
req.oncomplete = callback;
14811532

14821533
if (permission.isEnabled()) {
14831534
callback(new ERR_ACCESS_DENIED('fdatasync API is disabled when Permission Model is enabled.'));
@@ -1494,6 +1545,12 @@ function fdatasync(fd, callback) {
14941545
* @returns {void}
14951546
*/
14961547
function fdatasyncSync(fd) {
1548+
const h = vfsState.handlers;
1549+
if (h !== null) {
1550+
const result = h.fdatasyncSync(fd);
1551+
if (result !== undefined) return;
1552+
}
1553+
14971554
if (permission.isEnabled()) {
14981555
throw new ERR_ACCESS_DENIED('fdatasync API is disabled when Permission Model is enabled.');
14991556
}
@@ -1508,8 +1565,19 @@ function fdatasyncSync(fd) {
15081565
* @returns {void}
15091566
*/
15101567
function fsync(fd, callback) {
1568+
callback = makeCallback(callback);
1569+
1570+
const h = vfsState.handlers;
1571+
if (h !== null) {
1572+
const result = h.fsyncSync(fd);
1573+
if (result !== undefined) {
1574+
process.nextTick(callback, null);
1575+
return;
1576+
}
1577+
}
1578+
15111579
const req = new FSReqCallback();
1512-
req.oncomplete = makeCallback(callback);
1580+
req.oncomplete = callback;
15131581
if (permission.isEnabled()) {
15141582
callback(new ERR_ACCESS_DENIED('fsync API is disabled when Permission Model is enabled.'));
15151583
return;
@@ -1524,6 +1592,12 @@ function fsync(fd, callback) {
15241592
* @returns {void}
15251593
*/
15261594
function fsyncSync(fd) {
1595+
const h = vfsState.handlers;
1596+
if (h !== null) {
1597+
const result = h.fsyncSync(fd);
1598+
if (result !== undefined) return;
1599+
}
1600+
15271601
if (permission.isEnabled()) {
15281602
throw new ERR_ACCESS_DENIED('fsync API is disabled when Permission Model is enabled.');
15291603
}
@@ -1992,6 +2066,16 @@ function statfs(path, options = { bigint: false }, callback) {
19922066
options = kEmptyObject;
19932067
}
19942068
validateFunction(callback, 'cb');
2069+
2070+
const h = vfsState.handlers;
2071+
if (h !== null) {
2072+
const result = h.statfsSync(path);
2073+
if (result !== undefined) {
2074+
process.nextTick(callback, null, result);
2075+
return;
2076+
}
2077+
}
2078+
19952079
path = getValidatedPath(path);
19962080
const req = new FSReqCallback(options.bigint);
19972081
req.oncomplete = (err, stats) => {
@@ -2087,6 +2171,12 @@ function statSync(path, options = { bigint: false, throwIfNoEntry: true }) {
20872171
}
20882172

20892173
function statfsSync(path, options = { bigint: false }) {
2174+
const h = vfsState.handlers;
2175+
if (h !== null) {
2176+
const result = h.statfsSync(path);
2177+
if (result !== undefined) return result;
2178+
}
2179+
20902180
const stats = binding.statfs(getValidatedPath(path), options.bigint);
20912181
return getStatFsFromBinding(stats);
20922182
}
@@ -2376,6 +2466,15 @@ function fchmod(fd, mode, callback) {
23762466
mode = parseFileMode(mode, 'mode');
23772467
callback = makeCallback(callback);
23782468

2469+
const h = vfsState.handlers;
2470+
if (h !== null) {
2471+
const result = h.fchmodSync(fd);
2472+
if (result !== undefined) {
2473+
process.nextTick(callback, null);
2474+
return;
2475+
}
2476+
}
2477+
23792478
if (permission.isEnabled()) {
23802479
callback(new ERR_ACCESS_DENIED('fchmod API is disabled when Permission Model is enabled.'));
23812480
return;
@@ -2393,6 +2492,12 @@ function fchmod(fd, mode, callback) {
23932492
* @returns {void}
23942493
*/
23952494
function fchmodSync(fd, mode) {
2495+
const h = vfsState.handlers;
2496+
if (h !== null) {
2497+
const result = h.fchmodSync(fd);
2498+
if (result !== undefined) return;
2499+
}
2500+
23962501
if (permission.isEnabled()) {
23972502
throw new ERR_ACCESS_DENIED('fchmod API is disabled when Permission Model is enabled.');
23982503
}
@@ -2503,6 +2608,16 @@ function lchown(path, uid, gid, callback) {
25032608
path = getValidatedPath(path);
25042609
validateInteger(uid, 'uid', -1, kMaxUserId);
25052610
validateInteger(gid, 'gid', -1, kMaxUserId);
2611+
2612+
const h = vfsState.handlers;
2613+
if (h !== null) {
2614+
const result = h.lchownSync(path);
2615+
if (result !== undefined) {
2616+
process.nextTick(callback, null);
2617+
return;
2618+
}
2619+
}
2620+
25062621
const req = new FSReqCallback();
25072622
req.oncomplete = callback;
25082623
binding.lchown(path, uid, gid, req);
@@ -2519,6 +2634,13 @@ function lchownSync(path, uid, gid) {
25192634
path = getValidatedPath(path);
25202635
validateInteger(uid, 'uid', -1, kMaxUserId);
25212636
validateInteger(gid, 'gid', -1, kMaxUserId);
2637+
2638+
const h = vfsState.handlers;
2639+
if (h !== null) {
2640+
const result = h.lchownSync(path);
2641+
if (result !== undefined) return;
2642+
}
2643+
25222644
binding.lchown(path, uid, gid);
25232645
}
25242646

@@ -2534,6 +2656,16 @@ function fchown(fd, uid, gid, callback) {
25342656
validateInteger(uid, 'uid', -1, kMaxUserId);
25352657
validateInteger(gid, 'gid', -1, kMaxUserId);
25362658
callback = makeCallback(callback);
2659+
2660+
const h = vfsState.handlers;
2661+
if (h !== null) {
2662+
const result = h.fchownSync(fd);
2663+
if (result !== undefined) {
2664+
process.nextTick(callback, null);
2665+
return;
2666+
}
2667+
}
2668+
25372669
if (permission.isEnabled()) {
25382670
callback(new ERR_ACCESS_DENIED('fchown API is disabled when Permission Model is enabled.'));
25392671
return;
@@ -2554,6 +2686,13 @@ function fchown(fd, uid, gid, callback) {
25542686
function fchownSync(fd, uid, gid) {
25552687
validateInteger(uid, 'uid', -1, kMaxUserId);
25562688
validateInteger(gid, 'gid', -1, kMaxUserId);
2689+
2690+
const h = vfsState.handlers;
2691+
if (h !== null) {
2692+
const result = h.fchownSync(fd);
2693+
if (result !== undefined) return;
2694+
}
2695+
25572696
if (permission.isEnabled()) {
25582697
throw new ERR_ACCESS_DENIED('fchown API is disabled when Permission Model is enabled.');
25592698
}
@@ -2576,6 +2715,15 @@ function chown(path, uid, gid, callback) {
25762715
validateInteger(uid, 'uid', -1, kMaxUserId);
25772716
validateInteger(gid, 'gid', -1, kMaxUserId);
25782717

2718+
const h = vfsState.handlers;
2719+
if (h !== null) {
2720+
const result = h.chownSync(path);
2721+
if (result !== undefined) {
2722+
process.nextTick(callback, null);
2723+
return;
2724+
}
2725+
}
2726+
25792727
const req = new FSReqCallback();
25802728
req.oncomplete = callback;
25812729
binding.chown(path, uid, gid, req);
@@ -2593,6 +2741,13 @@ function chownSync(path, uid, gid) {
25932741
path = getValidatedPath(path);
25942742
validateInteger(uid, 'uid', -1, kMaxUserId);
25952743
validateInteger(gid, 'gid', -1, kMaxUserId);
2744+
2745+
const h = vfsState.handlers;
2746+
if (h !== null) {
2747+
const result = h.chownSync(path);
2748+
if (result !== undefined) return;
2749+
}
2750+
25962751
binding.chown(path, uid, gid);
25972752
}
25982753

@@ -2666,6 +2821,15 @@ function futimes(fd, atime, mtime, callback) {
26662821
mtime = toUnixTimestamp(mtime, 'mtime');
26672822
callback = makeCallback(callback);
26682823

2824+
const h = vfsState.handlers;
2825+
if (h !== null) {
2826+
const result = h.futimesSync(fd);
2827+
if (result !== undefined) {
2828+
process.nextTick(callback, null);
2829+
return;
2830+
}
2831+
}
2832+
26692833
if (permission.isEnabled()) {
26702834
callback(new ERR_ACCESS_DENIED('futimes API is disabled when Permission Model is enabled.'));
26712835
return;
@@ -2686,6 +2850,12 @@ function futimes(fd, atime, mtime, callback) {
26862850
* @returns {void}
26872851
*/
26882852
function futimesSync(fd, atime, mtime) {
2853+
const h = vfsState.handlers;
2854+
if (h !== null) {
2855+
const result = h.futimesSync(fd);
2856+
if (result !== undefined) return;
2857+
}
2858+
26892859
if (permission.isEnabled()) {
26902860
throw new ERR_ACCESS_DENIED('futimes API is disabled when Permission Model is enabled.');
26912861
}
@@ -2710,6 +2880,15 @@ function lutimes(path, atime, mtime, callback) {
27102880
callback = makeCallback(callback);
27112881
path = getValidatedPath(path);
27122882

2883+
const h = vfsState.handlers;
2884+
if (h !== null) {
2885+
const result = h.lutimesSync(path);
2886+
if (result !== undefined) {
2887+
process.nextTick(callback, null);
2888+
return;
2889+
}
2890+
}
2891+
27132892
const req = new FSReqCallback();
27142893
req.oncomplete = callback;
27152894
binding.lutimes(
@@ -2729,8 +2908,16 @@ function lutimes(path, atime, mtime, callback) {
27292908
* @returns {void}
27302909
*/
27312910
function lutimesSync(path, atime, mtime) {
2911+
path = getValidatedPath(path);
2912+
2913+
const h = vfsState.handlers;
2914+
if (h !== null) {
2915+
const result = h.lutimesSync(path);
2916+
if (result !== undefined) return;
2917+
}
2918+
27322919
binding.lutimes(
2733-
getValidatedPath(path),
2920+
path,
27342921
toUnixTimestamp(atime),
27352922
toUnixTimestamp(mtime),
27362923
);

0 commit comments

Comments
 (0)