@zenfs/core 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backends/memory.d.ts +4 -4
- package/dist/backends/memory.js +4 -4
- package/dist/backends/overlay.d.ts +5 -2
- package/dist/backends/overlay.js +7 -10
- package/dist/backends/port/fs.js +1 -4
- package/dist/config.js +4 -8
- package/dist/context.d.ts +32 -0
- package/dist/context.js +23 -0
- package/dist/credentials.d.ts +5 -5
- package/dist/credentials.js +10 -6
- package/dist/emulation/async.d.ts +90 -89
- package/dist/emulation/async.js +76 -75
- package/dist/emulation/dir.d.ts +3 -1
- package/dist/emulation/dir.js +6 -7
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/promises.d.ts +50 -48
- package/dist/emulation/promises.js +78 -77
- package/dist/emulation/shared.d.ts +35 -8
- package/dist/emulation/shared.js +37 -11
- package/dist/emulation/sync.d.ts +63 -62
- package/dist/emulation/sync.js +72 -73
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stats.d.ts +2 -1
- package/dist/stats.js +5 -4
- package/package.json +3 -5
- package/scripts/test.js +78 -17
- package/tests/assignment.ts +1 -1
- package/tests/common/context.test.ts +19 -0
- package/tests/{devices.test.ts → common/devices.test.ts} +3 -3
- package/tests/{handle.test.ts → common/handle.test.ts} +1 -1
- package/tests/common/mounts.test.ts +36 -0
- package/tests/{mutex.test.ts → common/mutex.test.ts} +3 -3
- package/tests/common/path.test.ts +34 -0
- package/tests/common.ts +4 -3
- package/tests/fs/dir.test.ts +11 -11
- package/tests/fs/directory.test.ts +17 -17
- package/tests/fs/errors.test.ts +29 -39
- package/tests/fs/watch.test.ts +2 -2
- package/tests/setup/context.ts +9 -0
- package/tests/setup/cow+fetch.ts +1 -1
- package/tests/setup/memory.ts +1 -1
- package/tests/{setup/common.ts → setup.ts} +6 -5
- package/src/backends/backend.ts +0 -161
- package/src/backends/fetch.ts +0 -180
- package/src/backends/file_index.ts +0 -206
- package/src/backends/memory.ts +0 -45
- package/src/backends/overlay.ts +0 -560
- package/src/backends/port/fs.ts +0 -329
- package/src/backends/port/readme.md +0 -54
- package/src/backends/port/rpc.ts +0 -167
- package/src/backends/readme.md +0 -3
- package/src/backends/store/fs.ts +0 -667
- package/src/backends/store/readme.md +0 -9
- package/src/backends/store/simple.ts +0 -154
- package/src/backends/store/store.ts +0 -189
- package/src/config.ts +0 -227
- package/src/credentials.ts +0 -49
- package/src/devices.ts +0 -521
- package/src/emulation/async.ts +0 -834
- package/src/emulation/cache.ts +0 -86
- package/src/emulation/config.ts +0 -21
- package/src/emulation/constants.ts +0 -182
- package/src/emulation/dir.ts +0 -138
- package/src/emulation/index.ts +0 -8
- package/src/emulation/path.ts +0 -440
- package/src/emulation/promises.ts +0 -1140
- package/src/emulation/shared.ts +0 -172
- package/src/emulation/streams.ts +0 -34
- package/src/emulation/sync.ts +0 -863
- package/src/emulation/watchers.ts +0 -194
- package/src/error.ts +0 -307
- package/src/file.ts +0 -631
- package/src/filesystem.ts +0 -174
- package/src/index.ts +0 -35
- package/src/inode.ts +0 -128
- package/src/mixins/async.ts +0 -230
- package/src/mixins/index.ts +0 -5
- package/src/mixins/mutexed.ts +0 -257
- package/src/mixins/readonly.ts +0 -96
- package/src/mixins/shared.ts +0 -25
- package/src/mixins/sync.ts +0 -58
- package/src/polyfills.ts +0 -21
- package/src/stats.ts +0 -405
- package/src/utils.ts +0 -276
- package/tests/mounts.test.ts +0 -18
- package/tests/path.test.ts +0 -34
package/dist/emulation/sync.js
CHANGED
|
@@ -60,9 +60,9 @@ import { emitChange } from './watchers.js';
|
|
|
60
60
|
export function renameSync(oldPath, newPath) {
|
|
61
61
|
oldPath = normalizePath(oldPath);
|
|
62
62
|
newPath = normalizePath(newPath);
|
|
63
|
-
const oldMount = resolveMount(oldPath);
|
|
64
|
-
const newMount = resolveMount(newPath);
|
|
65
|
-
if (config.checkAccess && !statSync(dirname(oldPath)).hasAccess(constants.W_OK)) {
|
|
63
|
+
const oldMount = resolveMount(oldPath, this);
|
|
64
|
+
const newMount = resolveMount(newPath, this);
|
|
65
|
+
if (config.checkAccess && !statSync.call(this, dirname(oldPath)).hasAccess(constants.W_OK, this)) {
|
|
66
66
|
throw ErrnoError.With('EACCES', oldPath, 'rename');
|
|
67
67
|
}
|
|
68
68
|
try {
|
|
@@ -72,8 +72,8 @@ export function renameSync(oldPath, newPath) {
|
|
|
72
72
|
emitChange('change', newPath.toString());
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
|
-
writeFileSync(newPath, readFileSync(oldPath));
|
|
76
|
-
unlinkSync(oldPath);
|
|
75
|
+
writeFileSync.call(this, newPath, readFileSync(oldPath));
|
|
76
|
+
unlinkSync.call(this, oldPath);
|
|
77
77
|
emitChange('rename', oldPath.toString());
|
|
78
78
|
}
|
|
79
79
|
catch (e) {
|
|
@@ -87,7 +87,7 @@ renameSync;
|
|
|
87
87
|
export function existsSync(path) {
|
|
88
88
|
path = normalizePath(path);
|
|
89
89
|
try {
|
|
90
|
-
const { fs, path: resolvedPath } = resolveMount(realpathSync(path));
|
|
90
|
+
const { fs, path: resolvedPath } = resolveMount(realpathSync.call(this, path), this);
|
|
91
91
|
return fs.existsSync(resolvedPath);
|
|
92
92
|
}
|
|
93
93
|
catch (e) {
|
|
@@ -100,10 +100,10 @@ export function existsSync(path) {
|
|
|
100
100
|
existsSync;
|
|
101
101
|
export function statSync(path, options) {
|
|
102
102
|
path = normalizePath(path);
|
|
103
|
-
const { fs, path: resolved } = resolveMount(realpathSync(path));
|
|
103
|
+
const { fs, path: resolved } = resolveMount(realpathSync.call(this, path), this);
|
|
104
104
|
try {
|
|
105
105
|
const stats = fs.statSync(resolved);
|
|
106
|
-
if (config.checkAccess && !stats.hasAccess(constants.R_OK)) {
|
|
106
|
+
if (config.checkAccess && !stats.hasAccess(constants.R_OK, this)) {
|
|
107
107
|
throw ErrnoError.With('EACCES', resolved, 'stat');
|
|
108
108
|
}
|
|
109
109
|
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -115,7 +115,7 @@ export function statSync(path, options) {
|
|
|
115
115
|
statSync;
|
|
116
116
|
export function lstatSync(path, options) {
|
|
117
117
|
path = normalizePath(path);
|
|
118
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
118
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
119
119
|
try {
|
|
120
120
|
const stats = fs.statSync(resolved);
|
|
121
121
|
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -128,7 +128,7 @@ lstatSync;
|
|
|
128
128
|
export function truncateSync(path, len = 0) {
|
|
129
129
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
130
130
|
try {
|
|
131
|
-
const file = __addDisposableResource(env_1, _openSync(path, 'r+'), false);
|
|
131
|
+
const file = __addDisposableResource(env_1, _openSync.call(this, path, 'r+'), false);
|
|
132
132
|
len || (len = 0);
|
|
133
133
|
if (len < 0) {
|
|
134
134
|
throw new ErrnoError(Errno.EINVAL);
|
|
@@ -146,9 +146,9 @@ export function truncateSync(path, len = 0) {
|
|
|
146
146
|
truncateSync;
|
|
147
147
|
export function unlinkSync(path) {
|
|
148
148
|
path = normalizePath(path);
|
|
149
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
149
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
150
150
|
try {
|
|
151
|
-
if (config.checkAccess && !(cache.stats.get(path) || fs.statSync(resolved)).hasAccess(constants.W_OK)) {
|
|
151
|
+
if (config.checkAccess && !(cache.stats.get(path) || fs.statSync(resolved)).hasAccess(constants.W_OK, this)) {
|
|
152
152
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
153
153
|
}
|
|
154
154
|
fs.unlinkSync(resolved);
|
|
@@ -162,8 +162,8 @@ unlinkSync;
|
|
|
162
162
|
function _openSync(path, _flag, _mode, resolveSymlinks = true) {
|
|
163
163
|
path = normalizePath(path);
|
|
164
164
|
const mode = normalizeMode(_mode, 0o644), flag = parseFlag(_flag);
|
|
165
|
-
path = resolveSymlinks ? realpathSync(path) : path;
|
|
166
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
165
|
+
path = resolveSymlinks ? realpathSync.call(this, path) : path;
|
|
166
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
167
167
|
let stats;
|
|
168
168
|
try {
|
|
169
169
|
stats = fs.statSync(resolved);
|
|
@@ -177,7 +177,7 @@ function _openSync(path, _flag, _mode, resolveSymlinks = true) {
|
|
|
177
177
|
}
|
|
178
178
|
// Create the file
|
|
179
179
|
const parentStats = fs.statSync(dirname(resolved));
|
|
180
|
-
if (config.checkAccess && !parentStats.hasAccess(constants.W_OK)) {
|
|
180
|
+
if (config.checkAccess && !parentStats.hasAccess(constants.W_OK, this)) {
|
|
181
181
|
throw ErrnoError.With('EACCES', dirname(path), '_open');
|
|
182
182
|
}
|
|
183
183
|
if (!parentStats.isDirectory()) {
|
|
@@ -185,7 +185,7 @@ function _openSync(path, _flag, _mode, resolveSymlinks = true) {
|
|
|
185
185
|
}
|
|
186
186
|
return fs.createFileSync(resolved, flag, mode);
|
|
187
187
|
}
|
|
188
|
-
if (config.checkAccess && (!stats.hasAccess(mode) || !stats.hasAccess(flagToMode(flag)))) {
|
|
188
|
+
if (config.checkAccess && (!stats.hasAccess(mode, this) || !stats.hasAccess(flagToMode(flag), this))) {
|
|
189
189
|
throw ErrnoError.With('EACCES', path, '_open');
|
|
190
190
|
}
|
|
191
191
|
if (isExclusive(flag)) {
|
|
@@ -202,7 +202,7 @@ function _openSync(path, _flag, _mode, resolveSymlinks = true) {
|
|
|
202
202
|
* @see http://www.manpagez.com/man/2/open/
|
|
203
203
|
*/
|
|
204
204
|
export function openSync(path, flag, mode = constants.F_OK) {
|
|
205
|
-
return file2fd(_openSync(path, flag, mode, true));
|
|
205
|
+
return file2fd(_openSync.call(this, path, flag, mode, true));
|
|
206
206
|
}
|
|
207
207
|
openSync;
|
|
208
208
|
/**
|
|
@@ -210,13 +210,13 @@ openSync;
|
|
|
210
210
|
* @internal
|
|
211
211
|
*/
|
|
212
212
|
export function lopenSync(path, flag, mode) {
|
|
213
|
-
return file2fd(_openSync(path, flag, mode, false));
|
|
213
|
+
return file2fd(_openSync.call(this, path, flag, mode, false));
|
|
214
214
|
}
|
|
215
215
|
function _readFileSync(fname, flag, resolveSymlinks) {
|
|
216
216
|
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
217
217
|
try {
|
|
218
218
|
// Get file.
|
|
219
|
-
const file = __addDisposableResource(env_2, _openSync(fname, flag, 0o644, resolveSymlinks), false);
|
|
219
|
+
const file = __addDisposableResource(env_2, _openSync.call(this, fname, flag, 0o644, resolveSymlinks), false);
|
|
220
220
|
const stat = file.statSync();
|
|
221
221
|
// Allocate buffer.
|
|
222
222
|
const data = new Uint8Array(stat.size);
|
|
@@ -237,7 +237,7 @@ export function readFileSync(path, _options = {}) {
|
|
|
237
237
|
if (!isReadable(flag)) {
|
|
238
238
|
throw new ErrnoError(Errno.EINVAL, 'Flag passed to readFile must allow for reading.');
|
|
239
239
|
}
|
|
240
|
-
const data = Buffer.from(_readFileSync(typeof path == 'number' ? fd2file(path).path : path.toString(), options.flag, true));
|
|
240
|
+
const data = Buffer.from(_readFileSync.call(this, typeof path == 'number' ? fd2file(path).path : path.toString(), options.flag, true));
|
|
241
241
|
return options.encoding ? data.toString(options.encoding) : data;
|
|
242
242
|
}
|
|
243
243
|
readFileSync;
|
|
@@ -256,7 +256,7 @@ export function writeFileSync(path, data, _options = {}) {
|
|
|
256
256
|
if (!encodedData) {
|
|
257
257
|
throw new ErrnoError(Errno.EINVAL, 'Data not specified');
|
|
258
258
|
}
|
|
259
|
-
const file = __addDisposableResource(env_3, _openSync(typeof path == 'number' ? fd2file(path).path : path.toString(), flag, options.mode, true), false);
|
|
259
|
+
const file = __addDisposableResource(env_3, _openSync.call(this, typeof path == 'number' ? fd2file(path).path : path.toString(), flag, options.mode, true), false);
|
|
260
260
|
file.writeSync(encodedData, 0, encodedData.byteLength, 0);
|
|
261
261
|
emitChange('change', path.toString());
|
|
262
262
|
}
|
|
@@ -287,7 +287,7 @@ export function appendFileSync(filename, data, _options = {}) {
|
|
|
287
287
|
throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
|
|
288
288
|
}
|
|
289
289
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
290
|
-
const file = __addDisposableResource(env_4, _openSync(typeof filename == 'number' ? fd2file(filename).path : filename.toString(), flag, options.mode, true), false);
|
|
290
|
+
const file = __addDisposableResource(env_4, _openSync.call(this, typeof filename == 'number' ? fd2file(filename).path : filename.toString(), flag, options.mode, true), false);
|
|
291
291
|
file.writeSync(encodedData, 0, encodedData.byteLength);
|
|
292
292
|
}
|
|
293
293
|
catch (e_4) {
|
|
@@ -392,13 +392,13 @@ export function futimesSync(fd, atime, mtime) {
|
|
|
392
392
|
futimesSync;
|
|
393
393
|
export function rmdirSync(path) {
|
|
394
394
|
path = normalizePath(path);
|
|
395
|
-
const { fs, path: resolved } = resolveMount(realpathSync(path));
|
|
395
|
+
const { fs, path: resolved } = resolveMount(realpathSync.call(this, path), this);
|
|
396
396
|
try {
|
|
397
397
|
const stats = cache.stats.get(path) || fs.statSync(resolved);
|
|
398
398
|
if (!stats.isDirectory()) {
|
|
399
399
|
throw ErrnoError.With('ENOTDIR', resolved, 'rmdir');
|
|
400
400
|
}
|
|
401
|
-
if (config.checkAccess && !stats.hasAccess(constants.W_OK)) {
|
|
401
|
+
if (config.checkAccess && !stats.hasAccess(constants.W_OK, this)) {
|
|
402
402
|
throw ErrnoError.With('EACCES', resolved, 'rmdir');
|
|
403
403
|
}
|
|
404
404
|
fs.rmdirSync(resolved);
|
|
@@ -412,12 +412,12 @@ rmdirSync;
|
|
|
412
412
|
export function mkdirSync(path, options) {
|
|
413
413
|
options = typeof options === 'object' ? options : { mode: options };
|
|
414
414
|
const mode = normalizeMode(options?.mode, 0o777);
|
|
415
|
-
path = realpathSync(path);
|
|
416
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
415
|
+
path = realpathSync.call(this, path);
|
|
416
|
+
const { fs, path: resolved, root } = resolveMount(path, this);
|
|
417
417
|
const errorPaths = { [resolved]: path };
|
|
418
418
|
try {
|
|
419
419
|
if (!options?.recursive) {
|
|
420
|
-
if (config.checkAccess && !fs.statSync(dirname(resolved)).hasAccess(constants.W_OK)) {
|
|
420
|
+
if (config.checkAccess && !fs.statSync(dirname(resolved)).hasAccess(constants.W_OK, this)) {
|
|
421
421
|
throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
|
|
422
422
|
}
|
|
423
423
|
return fs.mkdirSync(resolved, mode);
|
|
@@ -428,13 +428,13 @@ export function mkdirSync(path, options) {
|
|
|
428
428
|
errorPaths[dir] = original;
|
|
429
429
|
}
|
|
430
430
|
for (const dir of dirs) {
|
|
431
|
-
if (config.checkAccess && !fs.statSync(dirname(dir)).hasAccess(constants.W_OK)) {
|
|
431
|
+
if (config.checkAccess && !fs.statSync(dirname(dir)).hasAccess(constants.W_OK, this)) {
|
|
432
432
|
throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
|
|
433
433
|
}
|
|
434
434
|
fs.mkdirSync(dir, mode);
|
|
435
435
|
emitChange('rename', dir);
|
|
436
436
|
}
|
|
437
|
-
return dirs[0];
|
|
437
|
+
return root.length == 1 ? dirs[0] : dirs[0]?.slice(root.length);
|
|
438
438
|
}
|
|
439
439
|
catch (e) {
|
|
440
440
|
throw fixError(e, errorPaths);
|
|
@@ -444,12 +444,12 @@ mkdirSync;
|
|
|
444
444
|
export function readdirSync(path, options) {
|
|
445
445
|
options = typeof options === 'object' ? options : { encoding: options };
|
|
446
446
|
path = normalizePath(path);
|
|
447
|
-
const { fs, path: resolved } = resolveMount(realpathSync(path));
|
|
447
|
+
const { fs, path: resolved } = resolveMount(realpathSync.call(this, path), this);
|
|
448
448
|
let entries;
|
|
449
449
|
try {
|
|
450
450
|
const stats = cache.stats.get(path) || fs.statSync(resolved);
|
|
451
451
|
cache.stats.set(path, stats);
|
|
452
|
-
if (config.checkAccess && !stats.hasAccess(constants.R_OK)) {
|
|
452
|
+
if (config.checkAccess && !stats.hasAccess(constants.R_OK, this)) {
|
|
453
453
|
throw ErrnoError.With('EACCES', resolved, 'readdir');
|
|
454
454
|
}
|
|
455
455
|
if (!stats.isDirectory()) {
|
|
@@ -476,7 +476,7 @@ export function readdirSync(path, options) {
|
|
|
476
476
|
}
|
|
477
477
|
if (!entryStat.isDirectory() || !options?.recursive)
|
|
478
478
|
continue;
|
|
479
|
-
for (const subEntry of readdirSync(join(path, entry), { ...options, _isIndirect: true })) {
|
|
479
|
+
for (const subEntry of readdirSync.call(this, join(path, entry), { ...options, _isIndirect: true })) {
|
|
480
480
|
if (subEntry instanceof Dirent) {
|
|
481
481
|
subEntry.path = join(entry, subEntry.path);
|
|
482
482
|
values.push(subEntry);
|
|
@@ -495,23 +495,22 @@ export function readdirSync(path, options) {
|
|
|
495
495
|
return values;
|
|
496
496
|
}
|
|
497
497
|
readdirSync;
|
|
498
|
-
// SYMLINK METHODS
|
|
499
498
|
export function linkSync(targetPath, linkPath) {
|
|
500
499
|
targetPath = normalizePath(targetPath);
|
|
501
|
-
if (config.checkAccess && !statSync(dirname(targetPath)).hasAccess(constants.R_OK)) {
|
|
500
|
+
if (config.checkAccess && !statSync(dirname(targetPath)).hasAccess(constants.R_OK, this)) {
|
|
502
501
|
throw ErrnoError.With('EACCES', dirname(targetPath), 'link');
|
|
503
502
|
}
|
|
504
503
|
linkPath = normalizePath(linkPath);
|
|
505
|
-
if (config.checkAccess && !statSync(dirname(linkPath)).hasAccess(constants.W_OK)) {
|
|
504
|
+
if (config.checkAccess && !statSync(dirname(linkPath)).hasAccess(constants.W_OK, this)) {
|
|
506
505
|
throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
|
|
507
506
|
}
|
|
508
|
-
const { fs, path } = resolveMount(targetPath);
|
|
509
|
-
const link = resolveMount(linkPath);
|
|
507
|
+
const { fs, path } = resolveMount(targetPath, this);
|
|
508
|
+
const link = resolveMount(linkPath, this);
|
|
510
509
|
if (fs != link.fs) {
|
|
511
510
|
throw ErrnoError.With('EXDEV', linkPath, 'link');
|
|
512
511
|
}
|
|
513
512
|
try {
|
|
514
|
-
if (config.checkAccess && !fs.statSync(path).hasAccess(constants.R_OK)) {
|
|
513
|
+
if (config.checkAccess && !fs.statSync(path).hasAccess(constants.R_OK, this)) {
|
|
515
514
|
throw ErrnoError.With('EACCES', path, 'link');
|
|
516
515
|
}
|
|
517
516
|
return fs.linkSync(path, linkPath);
|
|
@@ -531,16 +530,16 @@ export function symlinkSync(target, path, type = 'file') {
|
|
|
531
530
|
if (!['file', 'dir', 'junction'].includes(type)) {
|
|
532
531
|
throw new ErrnoError(Errno.EINVAL, 'Invalid type: ' + type);
|
|
533
532
|
}
|
|
534
|
-
if (existsSync(path)) {
|
|
533
|
+
if (existsSync.call(this, path)) {
|
|
535
534
|
throw ErrnoError.With('EEXIST', path.toString(), 'symlink');
|
|
536
535
|
}
|
|
537
|
-
writeFileSync(path, target.toString());
|
|
538
|
-
const file = _openSync(path, 'r+', 0o644, false);
|
|
536
|
+
writeFileSync.call(this, path, target.toString());
|
|
537
|
+
const file = _openSync.call(this, path, 'r+', 0o644, false);
|
|
539
538
|
file.chmodSync(constants.S_IFLNK);
|
|
540
539
|
}
|
|
541
540
|
symlinkSync;
|
|
542
541
|
export function readlinkSync(path, options) {
|
|
543
|
-
const value = Buffer.from(_readFileSync(path.toString(), 'r', false));
|
|
542
|
+
const value = Buffer.from(_readFileSync.call(this, path.toString(), 'r', false));
|
|
544
543
|
const encoding = typeof options == 'object' ? options?.encoding : options;
|
|
545
544
|
if (encoding == 'buffer') {
|
|
546
545
|
return value;
|
|
@@ -548,27 +547,26 @@ export function readlinkSync(path, options) {
|
|
|
548
547
|
return value.toString(encoding);
|
|
549
548
|
}
|
|
550
549
|
readlinkSync;
|
|
551
|
-
// PROPERTY OPERATIONS
|
|
552
550
|
export function chownSync(path, uid, gid) {
|
|
553
|
-
const fd = openSync(path, 'r+');
|
|
551
|
+
const fd = openSync.call(this, path, 'r+');
|
|
554
552
|
fchownSync(fd, uid, gid);
|
|
555
553
|
closeSync(fd);
|
|
556
554
|
}
|
|
557
555
|
chownSync;
|
|
558
556
|
export function lchownSync(path, uid, gid) {
|
|
559
|
-
const fd = lopenSync(path, 'r+');
|
|
557
|
+
const fd = lopenSync.call(this, path, 'r+');
|
|
560
558
|
fchownSync(fd, uid, gid);
|
|
561
559
|
closeSync(fd);
|
|
562
560
|
}
|
|
563
561
|
lchownSync;
|
|
564
562
|
export function chmodSync(path, mode) {
|
|
565
|
-
const fd = openSync(path, 'r+');
|
|
563
|
+
const fd = openSync.call(this, path, 'r+');
|
|
566
564
|
fchmodSync(fd, mode);
|
|
567
565
|
closeSync(fd);
|
|
568
566
|
}
|
|
569
567
|
chmodSync;
|
|
570
568
|
export function lchmodSync(path, mode) {
|
|
571
|
-
const fd = lopenSync(path, 'r+');
|
|
569
|
+
const fd = lopenSync.call(this, path, 'r+');
|
|
572
570
|
fchmodSync(fd, mode);
|
|
573
571
|
closeSync(fd);
|
|
574
572
|
}
|
|
@@ -577,7 +575,7 @@ lchmodSync;
|
|
|
577
575
|
* Change file timestamps of the file referenced by the supplied path.
|
|
578
576
|
*/
|
|
579
577
|
export function utimesSync(path, atime, mtime) {
|
|
580
|
-
const fd = openSync(path, 'r+');
|
|
578
|
+
const fd = openSync.call(this, path, 'r+');
|
|
581
579
|
futimesSync(fd, atime, mtime);
|
|
582
580
|
closeSync(fd);
|
|
583
581
|
}
|
|
@@ -586,19 +584,20 @@ utimesSync;
|
|
|
586
584
|
* Change file timestamps of the file referenced by the supplied path.
|
|
587
585
|
*/
|
|
588
586
|
export function lutimesSync(path, atime, mtime) {
|
|
589
|
-
const fd = lopenSync(path, 'r+');
|
|
587
|
+
const fd = lopenSync.call(this, path, 'r+');
|
|
590
588
|
futimesSync(fd, atime, mtime);
|
|
591
589
|
closeSync(fd);
|
|
592
590
|
}
|
|
593
591
|
lutimesSync;
|
|
594
592
|
export function realpathSync(path, options) {
|
|
595
593
|
path = normalizePath(path);
|
|
596
|
-
|
|
597
|
-
|
|
594
|
+
const ctx_path = (this?.root || '') + path;
|
|
595
|
+
if (cache.paths.has(ctx_path))
|
|
596
|
+
return cache.paths.get(ctx_path);
|
|
598
597
|
const { base, dir } = parse(path);
|
|
599
|
-
const realDir = dir == '/' ? '/' : cache.paths.get(dir) || realpathSync(dir);
|
|
598
|
+
const realDir = dir == '/' ? '/' : cache.paths.get((this?.root || '') + dir) || realpathSync.call(this, dir);
|
|
600
599
|
const lpath = join(realDir, base);
|
|
601
|
-
const { fs, path: resolvedPath } = resolveMount(lpath);
|
|
600
|
+
const { fs, path: resolvedPath } = resolveMount(lpath, this);
|
|
602
601
|
try {
|
|
603
602
|
const stats = cache.stats.get(lpath) || fs.statSync(resolvedPath);
|
|
604
603
|
cache.stats.set(lpath, stats);
|
|
@@ -606,9 +605,9 @@ export function realpathSync(path, options) {
|
|
|
606
605
|
cache.paths.set(path, lpath);
|
|
607
606
|
return lpath;
|
|
608
607
|
}
|
|
609
|
-
const target = resolve(realDir, readlinkSync(lpath, options).toString());
|
|
610
|
-
const real = cache.paths.get(target) || realpathSync(target);
|
|
611
|
-
cache.paths.set(
|
|
608
|
+
const target = resolve(realDir, readlinkSync.call(this, lpath, options).toString());
|
|
609
|
+
const real = cache.paths.get((this?.root || '') + target) || realpathSync.call(this, target);
|
|
610
|
+
cache.paths.set(ctx_path, real);
|
|
612
611
|
return real;
|
|
613
612
|
}
|
|
614
613
|
catch (e) {
|
|
@@ -622,7 +621,7 @@ realpathSync;
|
|
|
622
621
|
export function accessSync(path, mode = 0o600) {
|
|
623
622
|
if (!config.checkAccess)
|
|
624
623
|
return;
|
|
625
|
-
if (!statSync(path).hasAccess(mode)) {
|
|
624
|
+
if (!statSync.call(this, path).hasAccess(mode, this)) {
|
|
626
625
|
throw new ErrnoError(Errno.EACCES);
|
|
627
626
|
}
|
|
628
627
|
}
|
|
@@ -635,7 +634,7 @@ export function rmSync(path, options) {
|
|
|
635
634
|
path = normalizePath(path);
|
|
636
635
|
let stats;
|
|
637
636
|
try {
|
|
638
|
-
stats = cache.stats.get(path) ||
|
|
637
|
+
stats = cache.stats.get(path) || lstatSync.bind(this)(path);
|
|
639
638
|
}
|
|
640
639
|
catch (error) {
|
|
641
640
|
if (error.code != 'ENOENT' || !options?.force)
|
|
@@ -648,17 +647,17 @@ export function rmSync(path, options) {
|
|
|
648
647
|
switch (stats.mode & constants.S_IFMT) {
|
|
649
648
|
case constants.S_IFDIR:
|
|
650
649
|
if (options?.recursive) {
|
|
651
|
-
for (const entry of readdirSync(path, { _isIndirect: true })) {
|
|
652
|
-
rmSync(join(path, entry), { ...options, _isIndirect: true });
|
|
650
|
+
for (const entry of readdirSync.call(this, path, { _isIndirect: true })) {
|
|
651
|
+
rmSync.call(this, join(path, entry), { ...options, _isIndirect: true });
|
|
653
652
|
}
|
|
654
653
|
}
|
|
655
|
-
rmdirSync(path);
|
|
654
|
+
rmdirSync.call(this, path);
|
|
656
655
|
break;
|
|
657
656
|
case constants.S_IFREG:
|
|
658
657
|
case constants.S_IFLNK:
|
|
659
658
|
case constants.S_IFBLK:
|
|
660
659
|
case constants.S_IFCHR:
|
|
661
|
-
unlinkSync(path);
|
|
660
|
+
unlinkSync.call(this, path);
|
|
662
661
|
break;
|
|
663
662
|
case constants.S_IFIFO:
|
|
664
663
|
case constants.S_IFSOCK:
|
|
@@ -675,7 +674,7 @@ export function mkdtempSync(prefix, options) {
|
|
|
675
674
|
const encoding = typeof options === 'object' ? options?.encoding : options || 'utf8';
|
|
676
675
|
const fsName = `${prefix}${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
677
676
|
const resolvedPath = '/tmp/' + fsName;
|
|
678
|
-
mkdirSync(resolvedPath);
|
|
677
|
+
mkdirSync.call(this, resolvedPath);
|
|
679
678
|
return encoding == 'buffer' ? Buffer.from(resolvedPath) : resolvedPath;
|
|
680
679
|
}
|
|
681
680
|
mkdtempSync;
|
|
@@ -690,7 +689,7 @@ export function copyFileSync(source, destination, flags) {
|
|
|
690
689
|
if (flags && flags & constants.COPYFILE_EXCL && existsSync(destination)) {
|
|
691
690
|
throw new ErrnoError(Errno.EEXIST, 'Destination file already exists.', destination, 'copyFile');
|
|
692
691
|
}
|
|
693
|
-
writeFileSync(destination, readFileSync(source));
|
|
692
|
+
writeFileSync.call(this, destination, readFileSync(source));
|
|
694
693
|
emitChange('rename', destination.toString());
|
|
695
694
|
}
|
|
696
695
|
copyFileSync;
|
|
@@ -735,7 +734,7 @@ writevSync;
|
|
|
735
734
|
*/
|
|
736
735
|
export function opendirSync(path, options) {
|
|
737
736
|
path = normalizePath(path);
|
|
738
|
-
return new Dir(path);
|
|
737
|
+
return new Dir(path, this);
|
|
739
738
|
}
|
|
740
739
|
opendirSync;
|
|
741
740
|
/**
|
|
@@ -753,8 +752,8 @@ opendirSync;
|
|
|
753
752
|
export function cpSync(source, destination, opts) {
|
|
754
753
|
source = normalizePath(source);
|
|
755
754
|
destination = normalizePath(destination);
|
|
756
|
-
const srcStats = lstatSync(source); // Use lstat to follow symlinks if not dereferencing
|
|
757
|
-
if (opts?.errorOnExist && existsSync(destination)) {
|
|
755
|
+
const srcStats = lstatSync.call(this, source); // Use lstat to follow symlinks if not dereferencing
|
|
756
|
+
if (opts?.errorOnExist && existsSync.call(this, destination)) {
|
|
758
757
|
throw new ErrnoError(Errno.EEXIST, 'Destination file or directory already exists.', destination, 'cp');
|
|
759
758
|
}
|
|
760
759
|
switch (srcStats.mode & constants.S_IFMT) {
|
|
@@ -762,17 +761,17 @@ export function cpSync(source, destination, opts) {
|
|
|
762
761
|
if (!opts?.recursive) {
|
|
763
762
|
throw new ErrnoError(Errno.EISDIR, source + ' is a directory (not copied)', source, 'cp');
|
|
764
763
|
}
|
|
765
|
-
mkdirSync(destination, { recursive: true }); // Ensure the destination directory exists
|
|
766
|
-
for (const dirent of readdirSync(source, { withFileTypes: true })) {
|
|
764
|
+
mkdirSync.call(this, destination, { recursive: true }); // Ensure the destination directory exists
|
|
765
|
+
for (const dirent of readdirSync.call(this, source, { withFileTypes: true })) {
|
|
767
766
|
if (opts.filter && !opts.filter(join(source, dirent.name), join(destination, dirent.name))) {
|
|
768
767
|
continue; // Skip if the filter returns false
|
|
769
768
|
}
|
|
770
|
-
cpSync(join(source, dirent.name), join(destination, dirent.name), opts);
|
|
769
|
+
cpSync.call(this, join(source, dirent.name), join(destination, dirent.name), opts);
|
|
771
770
|
}
|
|
772
771
|
break;
|
|
773
772
|
case constants.S_IFREG:
|
|
774
773
|
case constants.S_IFLNK:
|
|
775
|
-
copyFileSync(source, destination);
|
|
774
|
+
copyFileSync.call(this, source, destination);
|
|
776
775
|
break;
|
|
777
776
|
case constants.S_IFBLK:
|
|
778
777
|
case constants.S_IFCHR:
|
|
@@ -783,12 +782,12 @@ export function cpSync(source, destination, opts) {
|
|
|
783
782
|
}
|
|
784
783
|
// Optionally preserve timestamps
|
|
785
784
|
if (opts?.preserveTimestamps) {
|
|
786
|
-
utimesSync(destination, srcStats.atime, srcStats.mtime);
|
|
785
|
+
utimesSync.call(this, destination, srcStats.atime, srcStats.mtime);
|
|
787
786
|
}
|
|
788
787
|
}
|
|
789
788
|
cpSync;
|
|
790
789
|
export function statfsSync(path, options) {
|
|
791
790
|
path = normalizePath(path);
|
|
792
|
-
const { fs } = resolveMount(path);
|
|
791
|
+
const { fs } = resolveMount(path, this);
|
|
793
792
|
return _statfs(fs, options?.bigint);
|
|
794
793
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from './backends/store/simple.js';
|
|
|
9
9
|
export * from './backends/store/store.js';
|
|
10
10
|
export * from './backends/backend.js';
|
|
11
11
|
export * from './config.js';
|
|
12
|
+
export * from './context.js';
|
|
12
13
|
export * from './credentials.js';
|
|
13
14
|
export * from './devices.js';
|
|
14
15
|
export { default as devices } from './devices.js';
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export * from './backends/store/simple.js';
|
|
|
9
9
|
export * from './backends/store/store.js';
|
|
10
10
|
export * from './backends/backend.js';
|
|
11
11
|
export * from './config.js';
|
|
12
|
+
export * from './context.js';
|
|
12
13
|
export * from './credentials.js';
|
|
13
14
|
export * from './devices.js';
|
|
14
15
|
export { default as devices } from './devices.js';
|
package/dist/stats.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as Node from 'node:fs';
|
|
2
|
+
import type { V_Context } from './context.js';
|
|
2
3
|
import { S_IFDIR, S_IFLNK, S_IFREG } from './emulation/constants.js';
|
|
3
4
|
/**
|
|
4
5
|
* Indicates the type of a file. Applied to 'mode'.
|
|
@@ -138,7 +139,7 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
|
|
|
138
139
|
* @returns True if the request has access, false if the request does not
|
|
139
140
|
* @internal
|
|
140
141
|
*/
|
|
141
|
-
hasAccess(mode: number): boolean;
|
|
142
|
+
hasAccess(mode: number, context?: V_Context): boolean;
|
|
142
143
|
/**
|
|
143
144
|
* Change the mode of the file.
|
|
144
145
|
* We use this helper function to prevent messing up the type of the file.
|
package/dist/stats.js
CHANGED
|
@@ -108,12 +108,13 @@ export class StatsCommon {
|
|
|
108
108
|
* @returns True if the request has access, false if the request does not
|
|
109
109
|
* @internal
|
|
110
110
|
*/
|
|
111
|
-
hasAccess(mode) {
|
|
112
|
-
|
|
111
|
+
hasAccess(mode, context) {
|
|
112
|
+
const creds = context?.credentials || credentials;
|
|
113
|
+
if (this.isSymbolicLink() || creds.euid === 0 || creds.egid === 0)
|
|
113
114
|
return true;
|
|
114
115
|
let perm = 0;
|
|
115
116
|
// Owner permissions
|
|
116
|
-
if (
|
|
117
|
+
if (creds.uid === this.uid) {
|
|
117
118
|
if (this.mode & S_IRUSR)
|
|
118
119
|
perm |= R_OK;
|
|
119
120
|
if (this.mode & S_IWUSR)
|
|
@@ -122,7 +123,7 @@ export class StatsCommon {
|
|
|
122
123
|
perm |= X_OK;
|
|
123
124
|
}
|
|
124
125
|
// Group permissions
|
|
125
|
-
if (
|
|
126
|
+
if (creds.gid === this.gid || creds.groups.includes(Number(this.gid))) {
|
|
126
127
|
if (this.mode & S_IRGRP)
|
|
127
128
|
perm |= R_OK;
|
|
128
129
|
if (this.mode & S_IWGRP)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A filesystem, anywhere",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"zenfs-test": "scripts/test.js"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
|
-
"src",
|
|
22
21
|
"dist",
|
|
23
22
|
"tests",
|
|
24
23
|
"license.md",
|
|
@@ -49,14 +48,12 @@
|
|
|
49
48
|
"./mixins": "./dist/mixins/index.js",
|
|
50
49
|
"./path": "./dist/emulation/path.js",
|
|
51
50
|
"./eslint": "./eslint.shared.js",
|
|
52
|
-
"./tests/*": "./tests/*"
|
|
53
|
-
"./src/*": "./src/*"
|
|
51
|
+
"./tests/*": "./tests/*"
|
|
54
52
|
},
|
|
55
53
|
"scripts": {
|
|
56
54
|
"format": "prettier --write .",
|
|
57
55
|
"format:check": "prettier --check .",
|
|
58
56
|
"lint": "eslint src tests",
|
|
59
|
-
"test:common": "tsx --test --experimental-test-coverage 'tests/**/!(fs)/*.test.ts' 'tests/*.test.ts'",
|
|
60
57
|
"test": "tsx --test --experimental-test-coverage",
|
|
61
58
|
"pretest": "npm run build",
|
|
62
59
|
"build": "tsc -p tsconfig.json",
|
|
@@ -83,6 +80,7 @@
|
|
|
83
80
|
"devDependencies": {
|
|
84
81
|
"@eslint/js": "^9.8.0",
|
|
85
82
|
"@types/eslint__js": "^8.42.3",
|
|
83
|
+
"c8": "^10.1.2",
|
|
86
84
|
"eslint": "^9.8.0",
|
|
87
85
|
"globals": "^15.9.0",
|
|
88
86
|
"lint-staged": "^15.2.7",
|