@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
|
@@ -62,7 +62,8 @@ import { ReadStream, WriteStream } from './streams.js';
|
|
|
62
62
|
import { FSWatcher, emitChange } from './watchers.js';
|
|
63
63
|
export * as constants from './constants.js';
|
|
64
64
|
export class FileHandle {
|
|
65
|
-
constructor(fdOrFile) {
|
|
65
|
+
constructor(fdOrFile, context) {
|
|
66
|
+
this.context = context;
|
|
66
67
|
const isFile = typeof fdOrFile != 'number';
|
|
67
68
|
this.fd = isFile ? file2fd(fdOrFile) : fdOrFile;
|
|
68
69
|
this.file = isFile ? fdOrFile : fd2file(fdOrFile);
|
|
@@ -219,7 +220,7 @@ export class FileHandle {
|
|
|
219
220
|
}
|
|
220
221
|
async stat(opts) {
|
|
221
222
|
const stats = await this.file.stat();
|
|
222
|
-
if (config.checkAccess && !stats.hasAccess(constants.R_OK)) {
|
|
223
|
+
if (config.checkAccess && !stats.hasAccess(constants.R_OK, this.context)) {
|
|
223
224
|
throw ErrnoError.With('EACCES', this.file.path, 'stat');
|
|
224
225
|
}
|
|
225
226
|
return opts?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -351,9 +352,9 @@ export class FileHandle {
|
|
|
351
352
|
export async function rename(oldPath, newPath) {
|
|
352
353
|
oldPath = normalizePath(oldPath);
|
|
353
354
|
newPath = normalizePath(newPath);
|
|
354
|
-
const src = resolveMount(oldPath);
|
|
355
|
-
const dst = resolveMount(newPath);
|
|
356
|
-
if (config.checkAccess && !(await stat(dirname(oldPath))).hasAccess(constants.W_OK)) {
|
|
355
|
+
const src = resolveMount(oldPath, this);
|
|
356
|
+
const dst = resolveMount(newPath, this);
|
|
357
|
+
if (config.checkAccess && !(await stat.call(this, dirname(oldPath))).hasAccess(constants.W_OK, this)) {
|
|
357
358
|
throw ErrnoError.With('EACCES', oldPath, 'rename');
|
|
358
359
|
}
|
|
359
360
|
try {
|
|
@@ -363,8 +364,8 @@ export async function rename(oldPath, newPath) {
|
|
|
363
364
|
emitChange('change', newPath.toString());
|
|
364
365
|
return;
|
|
365
366
|
}
|
|
366
|
-
await writeFile(newPath, await readFile(oldPath));
|
|
367
|
-
await unlink(oldPath);
|
|
367
|
+
await writeFile.call(this, newPath, await readFile(oldPath));
|
|
368
|
+
await unlink.call(this, oldPath);
|
|
368
369
|
emitChange('rename', oldPath.toString());
|
|
369
370
|
}
|
|
370
371
|
catch (e) {
|
|
@@ -377,7 +378,7 @@ rename;
|
|
|
377
378
|
*/
|
|
378
379
|
export async function exists(path) {
|
|
379
380
|
try {
|
|
380
|
-
const { fs, path: resolved } = resolveMount(await realpath(path));
|
|
381
|
+
const { fs, path: resolved } = resolveMount(await realpath.call(this, path), this);
|
|
381
382
|
return await fs.exists(resolved);
|
|
382
383
|
}
|
|
383
384
|
catch (e) {
|
|
@@ -389,10 +390,10 @@ export async function exists(path) {
|
|
|
389
390
|
}
|
|
390
391
|
export async function stat(path, options) {
|
|
391
392
|
path = normalizePath(path);
|
|
392
|
-
const { fs, path: resolved } = resolveMount(await realpath(path));
|
|
393
|
+
const { fs, path: resolved } = resolveMount(await realpath.call(this, path), this);
|
|
393
394
|
try {
|
|
394
395
|
const stats = await fs.stat(resolved);
|
|
395
|
-
if (config.checkAccess && !stats.hasAccess(constants.R_OK)) {
|
|
396
|
+
if (config.checkAccess && !stats.hasAccess(constants.R_OK, this)) {
|
|
396
397
|
throw ErrnoError.With('EACCES', resolved, 'stat');
|
|
397
398
|
}
|
|
398
399
|
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -404,7 +405,7 @@ export async function stat(path, options) {
|
|
|
404
405
|
stat;
|
|
405
406
|
export async function lstat(path, options) {
|
|
406
407
|
path = normalizePath(path);
|
|
407
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
408
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
408
409
|
try {
|
|
409
410
|
const stats = await fs.stat(resolved);
|
|
410
411
|
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -418,7 +419,7 @@ lstat;
|
|
|
418
419
|
export async function truncate(path, len = 0) {
|
|
419
420
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
420
421
|
try {
|
|
421
|
-
const handle = __addDisposableResource(env_1, await open(path, 'r+'), true);
|
|
422
|
+
const handle = __addDisposableResource(env_1, await open.call(this, path, 'r+'), true);
|
|
422
423
|
await handle.truncate(len);
|
|
423
424
|
}
|
|
424
425
|
catch (e_1) {
|
|
@@ -434,9 +435,9 @@ export async function truncate(path, len = 0) {
|
|
|
434
435
|
truncate;
|
|
435
436
|
export async function unlink(path) {
|
|
436
437
|
path = normalizePath(path);
|
|
437
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
438
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
438
439
|
try {
|
|
439
|
-
if (config.checkAccess && !(await (cache.stats.getAsync(path) || fs.stat(resolved))).hasAccess(constants.W_OK)) {
|
|
440
|
+
if (config.checkAccess && !(await (cache.stats.getAsync(path) || fs.stat(resolved))).hasAccess(constants.W_OK, this)) {
|
|
440
441
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
441
442
|
}
|
|
442
443
|
await fs.unlink(resolved);
|
|
@@ -454,8 +455,8 @@ unlink;
|
|
|
454
455
|
async function _open(path, _flag, _mode = 0o644, resolveSymlinks) {
|
|
455
456
|
path = normalizePath(path);
|
|
456
457
|
const mode = normalizeMode(_mode, 0o644), flag = parseFlag(_flag);
|
|
457
|
-
path = resolveSymlinks ? await realpath(path) : path;
|
|
458
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
458
|
+
path = resolveSymlinks ? await realpath.call(this, path) : path;
|
|
459
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
459
460
|
const stats = await fs.stat(resolved).catch(() => null);
|
|
460
461
|
if (!stats) {
|
|
461
462
|
if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
|
|
@@ -463,21 +464,21 @@ async function _open(path, _flag, _mode = 0o644, resolveSymlinks) {
|
|
|
463
464
|
}
|
|
464
465
|
// Create the file
|
|
465
466
|
const parentStats = await fs.stat(dirname(resolved));
|
|
466
|
-
if (config.checkAccess && !parentStats.hasAccess(constants.W_OK)) {
|
|
467
|
+
if (config.checkAccess && !parentStats.hasAccess(constants.W_OK, this)) {
|
|
467
468
|
throw ErrnoError.With('EACCES', dirname(path), '_open');
|
|
468
469
|
}
|
|
469
470
|
if (!parentStats.isDirectory()) {
|
|
470
471
|
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
|
|
471
472
|
}
|
|
472
|
-
return new FileHandle(await fs.createFile(resolved, flag, mode));
|
|
473
|
+
return new FileHandle(await fs.createFile(resolved, flag, mode), this);
|
|
473
474
|
}
|
|
474
|
-
if (config.checkAccess && !stats.hasAccess(flagToMode(flag))) {
|
|
475
|
+
if (config.checkAccess && !stats.hasAccess(flagToMode(flag), this)) {
|
|
475
476
|
throw ErrnoError.With('EACCES', path, '_open');
|
|
476
477
|
}
|
|
477
478
|
if (isExclusive(flag)) {
|
|
478
479
|
throw ErrnoError.With('EEXIST', path, '_open');
|
|
479
480
|
}
|
|
480
|
-
const handle = new FileHandle(await fs.openFile(resolved, flag));
|
|
481
|
+
const handle = new FileHandle(await fs.openFile(resolved, flag), this);
|
|
481
482
|
/*
|
|
482
483
|
In a previous implementation, we deleted the file and
|
|
483
484
|
re-created it. However, this created a race condition if another
|
|
@@ -496,14 +497,14 @@ async function _open(path, _flag, _mode = 0o644, resolveSymlinks) {
|
|
|
496
497
|
* @param mode Mode to use to open the file. Can be ignored if the filesystem doesn't support permissions.
|
|
497
498
|
*/
|
|
498
499
|
export async function open(path, flag = 'r', mode = 0o644) {
|
|
499
|
-
return await _open(path, flag, mode, true);
|
|
500
|
+
return await _open.call(this, path, flag, mode, true);
|
|
500
501
|
}
|
|
501
502
|
open;
|
|
502
503
|
export async function readFile(path, _options) {
|
|
503
504
|
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
504
505
|
try {
|
|
505
506
|
const options = normalizeOptions(_options, null, 'r', 0o644);
|
|
506
|
-
const handle = __addDisposableResource(env_2, typeof path == 'object' && 'fd' in path ? path : await open(path, options.flag, options.mode), true);
|
|
507
|
+
const handle = __addDisposableResource(env_2, typeof path == 'object' && 'fd' in path ? path : await open.call(this, path, options.flag, options.mode), true);
|
|
507
508
|
return await handle.readFile(options);
|
|
508
509
|
}
|
|
509
510
|
catch (e_2) {
|
|
@@ -529,7 +530,7 @@ export async function writeFile(path, data, _options) {
|
|
|
529
530
|
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
530
531
|
try {
|
|
531
532
|
const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
|
|
532
|
-
const handle = __addDisposableResource(env_3, path instanceof FileHandle ? path : await open(path.toString(), options.flag, options.mode), true);
|
|
533
|
+
const handle = __addDisposableResource(env_3, path instanceof FileHandle ? path : await open.call(this, path.toString(), options.flag, options.mode), true);
|
|
533
534
|
const _data = typeof data == 'string' ? data : data;
|
|
534
535
|
if (typeof _data != 'string' && !(_data instanceof Uint8Array)) {
|
|
535
536
|
throw new ErrnoError(Errno.EINVAL, 'Iterables and streams not supported', handle.file.path, 'writeFile');
|
|
@@ -565,7 +566,7 @@ export async function appendFile(path, data, _options) {
|
|
|
565
566
|
throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
|
|
566
567
|
}
|
|
567
568
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
568
|
-
const handle = __addDisposableResource(env_4, typeof path == 'object' && 'fd' in path ? path : await open(path, options.flag, options.mode), true);
|
|
569
|
+
const handle = __addDisposableResource(env_4, typeof path == 'object' && 'fd' in path ? path : await open.call(this, path, options.flag, options.mode), true);
|
|
569
570
|
await handle.appendFile(encodedData, options);
|
|
570
571
|
}
|
|
571
572
|
catch (e_4) {
|
|
@@ -581,8 +582,8 @@ export async function appendFile(path, data, _options) {
|
|
|
581
582
|
appendFile;
|
|
582
583
|
// DIRECTORY-ONLY METHODS
|
|
583
584
|
export async function rmdir(path) {
|
|
584
|
-
path = await realpath(path);
|
|
585
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
585
|
+
path = await realpath.call(this, path);
|
|
586
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
586
587
|
try {
|
|
587
588
|
const stats = await (cache.stats.getAsync(path) || fs.stat(resolved));
|
|
588
589
|
if (!stats) {
|
|
@@ -591,7 +592,7 @@ export async function rmdir(path) {
|
|
|
591
592
|
if (!stats.isDirectory()) {
|
|
592
593
|
throw ErrnoError.With('ENOTDIR', resolved, 'rmdir');
|
|
593
594
|
}
|
|
594
|
-
if (config.checkAccess && !stats.hasAccess(constants.W_OK)) {
|
|
595
|
+
if (config.checkAccess && !stats.hasAccess(constants.W_OK, this)) {
|
|
595
596
|
throw ErrnoError.With('EACCES', resolved, 'rmdir');
|
|
596
597
|
}
|
|
597
598
|
await fs.rmdir(resolved);
|
|
@@ -605,12 +606,12 @@ rmdir;
|
|
|
605
606
|
export async function mkdir(path, options) {
|
|
606
607
|
options = typeof options === 'object' ? options : { mode: options };
|
|
607
608
|
const mode = normalizeMode(options?.mode, 0o777);
|
|
608
|
-
path = await realpath(path);
|
|
609
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
609
|
+
path = await realpath.call(this, path);
|
|
610
|
+
const { fs, path: resolved, root } = resolveMount(path, this);
|
|
610
611
|
const errorPaths = { [resolved]: path };
|
|
611
612
|
try {
|
|
612
613
|
if (!options?.recursive) {
|
|
613
|
-
if (config.checkAccess && !(await fs.stat(dirname(resolved))).hasAccess(constants.W_OK)) {
|
|
614
|
+
if (config.checkAccess && !(await fs.stat(dirname(resolved))).hasAccess(constants.W_OK, this)) {
|
|
614
615
|
throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
|
|
615
616
|
}
|
|
616
617
|
await fs.mkdir(resolved, mode);
|
|
@@ -623,13 +624,13 @@ export async function mkdir(path, options) {
|
|
|
623
624
|
errorPaths[dir] = origDir;
|
|
624
625
|
}
|
|
625
626
|
for (const dir of dirs) {
|
|
626
|
-
if (config.checkAccess && !(await fs.stat(dirname(dir))).hasAccess(constants.W_OK)) {
|
|
627
|
+
if (config.checkAccess && !(await fs.stat(dirname(dir))).hasAccess(constants.W_OK, this)) {
|
|
627
628
|
throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
|
|
628
629
|
}
|
|
629
630
|
await fs.mkdir(dir, mode);
|
|
630
631
|
emitChange('rename', dir);
|
|
631
632
|
}
|
|
632
|
-
return dirs[0];
|
|
633
|
+
return root.length == 1 ? dirs[0] : dirs[0]?.slice(root.length);
|
|
633
634
|
}
|
|
634
635
|
catch (e) {
|
|
635
636
|
throw fixError(e, errorPaths);
|
|
@@ -638,18 +639,18 @@ export async function mkdir(path, options) {
|
|
|
638
639
|
mkdir;
|
|
639
640
|
export async function readdir(path, options) {
|
|
640
641
|
options = typeof options === 'object' ? options : { encoding: options };
|
|
641
|
-
path = await realpath(path);
|
|
642
|
+
path = await realpath.call(this, path);
|
|
642
643
|
const handleError = (e) => {
|
|
643
644
|
throw fixError(e, { [resolved]: path });
|
|
644
645
|
};
|
|
645
|
-
const { fs, path: resolved } = resolveMount(path);
|
|
646
|
+
const { fs, path: resolved } = resolveMount(path, this);
|
|
646
647
|
const _stats = cache.stats.getAsync(path) || fs.stat(resolved).catch(handleError);
|
|
647
648
|
cache.stats.setAsync(path, _stats);
|
|
648
649
|
const stats = await _stats;
|
|
649
650
|
if (!stats) {
|
|
650
651
|
throw ErrnoError.With('ENOENT', path, 'readdir');
|
|
651
652
|
}
|
|
652
|
-
if (config.checkAccess && !stats.hasAccess(constants.R_OK)) {
|
|
653
|
+
if (config.checkAccess && !stats.hasAccess(constants.R_OK, this)) {
|
|
653
654
|
throw ErrnoError.With('EACCES', path, 'readdir');
|
|
654
655
|
}
|
|
655
656
|
if (!stats.isDirectory()) {
|
|
@@ -675,7 +676,7 @@ export async function readdir(path, options) {
|
|
|
675
676
|
}
|
|
676
677
|
if (!options?.recursive || !entryStats?.isDirectory())
|
|
677
678
|
return;
|
|
678
|
-
for (const subEntry of await readdir(join(path, entry), { ...options, _isIndirect: true })) {
|
|
679
|
+
for (const subEntry of await readdir.call(this, join(path, entry), { ...options, _isIndirect: true })) {
|
|
679
680
|
if (subEntry instanceof Dirent) {
|
|
680
681
|
subEntry.path = join(entry, subEntry.path);
|
|
681
682
|
values.push(subEntry);
|
|
@@ -699,19 +700,19 @@ readdir;
|
|
|
699
700
|
export async function link(targetPath, linkPath) {
|
|
700
701
|
targetPath = normalizePath(targetPath);
|
|
701
702
|
linkPath = normalizePath(linkPath);
|
|
702
|
-
const { fs, path } = resolveMount(targetPath);
|
|
703
|
-
const link = resolveMount(linkPath);
|
|
703
|
+
const { fs, path } = resolveMount(targetPath, this);
|
|
704
|
+
const link = resolveMount(linkPath, this);
|
|
704
705
|
if (fs != link.fs) {
|
|
705
706
|
throw ErrnoError.With('EXDEV', linkPath, 'link');
|
|
706
707
|
}
|
|
707
708
|
try {
|
|
708
|
-
if (config.checkAccess && !(await fs.stat(dirname(targetPath))).hasAccess(constants.R_OK)) {
|
|
709
|
+
if (config.checkAccess && !(await fs.stat(dirname(targetPath))).hasAccess(constants.R_OK, this)) {
|
|
709
710
|
throw ErrnoError.With('EACCES', dirname(path), 'link');
|
|
710
711
|
}
|
|
711
|
-
if (config.checkAccess && !(await stat(dirname(linkPath))).hasAccess(constants.W_OK)) {
|
|
712
|
+
if (config.checkAccess && !(await stat.call(this, dirname(linkPath))).hasAccess(constants.W_OK, this)) {
|
|
712
713
|
throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
|
|
713
714
|
}
|
|
714
|
-
if (config.checkAccess && !(await fs.stat(path)).hasAccess(constants.R_OK)) {
|
|
715
|
+
if (config.checkAccess && !(await fs.stat(path)).hasAccess(constants.R_OK, this)) {
|
|
715
716
|
throw ErrnoError.With('EACCES', path, 'link');
|
|
716
717
|
}
|
|
717
718
|
return await fs.link(path, link.path);
|
|
@@ -733,10 +734,10 @@ export async function symlink(target, path, type = 'file') {
|
|
|
733
734
|
if (!['file', 'dir', 'junction'].includes(type)) {
|
|
734
735
|
throw new ErrnoError(Errno.EINVAL, 'Invalid symlink type: ' + type);
|
|
735
736
|
}
|
|
736
|
-
if (await exists(path)) {
|
|
737
|
+
if (await exists.call(this, path)) {
|
|
737
738
|
throw ErrnoError.With('EEXIST', path.toString(), 'symlink');
|
|
738
739
|
}
|
|
739
|
-
const handle = __addDisposableResource(env_5, await _open(path, 'w+', 0o644, false), true);
|
|
740
|
+
const handle = __addDisposableResource(env_5, await _open.call(this, path, 'w+', 0o644, false), true);
|
|
740
741
|
await handle.writeFile(target.toString());
|
|
741
742
|
await handle.file.chmod(constants.S_IFLNK);
|
|
742
743
|
}
|
|
@@ -754,7 +755,7 @@ symlink;
|
|
|
754
755
|
export async function readlink(path, options) {
|
|
755
756
|
const env_6 = { stack: [], error: void 0, hasError: false };
|
|
756
757
|
try {
|
|
757
|
-
const handle = __addDisposableResource(env_6, await _open(normalizePath(path), 'r', 0o644, false), true);
|
|
758
|
+
const handle = __addDisposableResource(env_6, await _open.call(this, normalizePath(path), 'r', 0o644, false), true);
|
|
758
759
|
const value = await handle.readFile();
|
|
759
760
|
const encoding = typeof options == 'object' ? options?.encoding : options;
|
|
760
761
|
return encoding == 'buffer' ? value : value.toString(encoding);
|
|
@@ -770,11 +771,10 @@ export async function readlink(path, options) {
|
|
|
770
771
|
}
|
|
771
772
|
}
|
|
772
773
|
readlink;
|
|
773
|
-
// PROPERTY OPERATIONS
|
|
774
774
|
export async function chown(path, uid, gid) {
|
|
775
775
|
const env_7 = { stack: [], error: void 0, hasError: false };
|
|
776
776
|
try {
|
|
777
|
-
const handle = __addDisposableResource(env_7, await open(path, 'r+'), true);
|
|
777
|
+
const handle = __addDisposableResource(env_7, await open.call(this, path, 'r+'), true);
|
|
778
778
|
await handle.chown(uid, gid);
|
|
779
779
|
}
|
|
780
780
|
catch (e_7) {
|
|
@@ -791,7 +791,7 @@ chown;
|
|
|
791
791
|
export async function lchown(path, uid, gid) {
|
|
792
792
|
const env_8 = { stack: [], error: void 0, hasError: false };
|
|
793
793
|
try {
|
|
794
|
-
const handle = __addDisposableResource(env_8, await _open(path, 'r+', 0o644, false), true);
|
|
794
|
+
const handle = __addDisposableResource(env_8, await _open.call(this, path, 'r+', 0o644, false), true);
|
|
795
795
|
await handle.chown(uid, gid);
|
|
796
796
|
}
|
|
797
797
|
catch (e_8) {
|
|
@@ -808,7 +808,7 @@ lchown;
|
|
|
808
808
|
export async function chmod(path, mode) {
|
|
809
809
|
const env_9 = { stack: [], error: void 0, hasError: false };
|
|
810
810
|
try {
|
|
811
|
-
const handle = __addDisposableResource(env_9, await open(path, 'r+'), true);
|
|
811
|
+
const handle = __addDisposableResource(env_9, await open.call(this, path, 'r+'), true);
|
|
812
812
|
await handle.chmod(mode);
|
|
813
813
|
}
|
|
814
814
|
catch (e_9) {
|
|
@@ -825,7 +825,7 @@ chmod;
|
|
|
825
825
|
export async function lchmod(path, mode) {
|
|
826
826
|
const env_10 = { stack: [], error: void 0, hasError: false };
|
|
827
827
|
try {
|
|
828
|
-
const handle = __addDisposableResource(env_10, await _open(path, 'r+', 0o644, false), true);
|
|
828
|
+
const handle = __addDisposableResource(env_10, await _open.call(this, path, 'r+', 0o644, false), true);
|
|
829
829
|
await handle.chmod(mode);
|
|
830
830
|
}
|
|
831
831
|
catch (e_10) {
|
|
@@ -845,7 +845,7 @@ lchmod;
|
|
|
845
845
|
export async function utimes(path, atime, mtime) {
|
|
846
846
|
const env_11 = { stack: [], error: void 0, hasError: false };
|
|
847
847
|
try {
|
|
848
|
-
const handle = __addDisposableResource(env_11, await open(path, 'r+'), true);
|
|
848
|
+
const handle = __addDisposableResource(env_11, await open.call(this, path, 'r+'), true);
|
|
849
849
|
await handle.utimes(atime, mtime);
|
|
850
850
|
}
|
|
851
851
|
catch (e_11) {
|
|
@@ -865,7 +865,7 @@ utimes;
|
|
|
865
865
|
export async function lutimes(path, atime, mtime) {
|
|
866
866
|
const env_12 = { stack: [], error: void 0, hasError: false };
|
|
867
867
|
try {
|
|
868
|
-
const handle = __addDisposableResource(env_12, await _open(path, 'r+', 0o644, false), true);
|
|
868
|
+
const handle = __addDisposableResource(env_12, await _open.call(this, path, 'r+', 0o644, false), true);
|
|
869
869
|
await handle.utimes(new Date(atime), new Date(mtime));
|
|
870
870
|
}
|
|
871
871
|
catch (e_12) {
|
|
@@ -881,12 +881,13 @@ export async function lutimes(path, atime, mtime) {
|
|
|
881
881
|
lutimes;
|
|
882
882
|
export async function realpath(path, options) {
|
|
883
883
|
path = normalizePath(path);
|
|
884
|
-
|
|
885
|
-
|
|
884
|
+
const ctx_path = (this?.root || '') + path;
|
|
885
|
+
if (cache.paths.hasAsync(ctx_path))
|
|
886
|
+
return cache.paths.getAsync(ctx_path);
|
|
886
887
|
const { base, dir } = parse(path);
|
|
887
|
-
const realDir = dir == '/' ? '/' : await (cache.paths.getAsync(dir) || realpath(dir));
|
|
888
|
+
const realDir = dir == '/' ? '/' : await (cache.paths.getAsync((this?.root || '') + dir) || realpath.call(this, dir));
|
|
888
889
|
const lpath = join(realDir, base);
|
|
889
|
-
const { fs, path: resolvedPath } = resolveMount(lpath);
|
|
890
|
+
const { fs, path: resolvedPath } = resolveMount(lpath, this);
|
|
890
891
|
try {
|
|
891
892
|
const _stats = cache.stats.getAsync(lpath) || fs.stat(resolvedPath);
|
|
892
893
|
cache.stats.setAsync(lpath, _stats);
|
|
@@ -894,9 +895,9 @@ export async function realpath(path, options) {
|
|
|
894
895
|
cache.paths.set(path, lpath);
|
|
895
896
|
return lpath;
|
|
896
897
|
}
|
|
897
|
-
const target = resolve(realDir, await readlink(lpath));
|
|
898
|
-
const real = cache.paths.getAsync(target) || realpath(target);
|
|
899
|
-
cache.paths.setAsync(
|
|
898
|
+
const target = resolve(realDir, (await readlink.call(this, lpath)).toString());
|
|
899
|
+
const real = cache.paths.getAsync((this?.root || '') + target) || realpath.call(this, target);
|
|
900
|
+
cache.paths.setAsync(ctx_path, real);
|
|
900
901
|
return await real;
|
|
901
902
|
}
|
|
902
903
|
catch (e) {
|
|
@@ -940,8 +941,8 @@ watch;
|
|
|
940
941
|
export async function access(path, mode = constants.F_OK) {
|
|
941
942
|
if (!config.checkAccess)
|
|
942
943
|
return;
|
|
943
|
-
const stats = await stat(path);
|
|
944
|
-
if (!stats.hasAccess(mode)) {
|
|
944
|
+
const stats = await stat.call(this, path);
|
|
945
|
+
if (!stats.hasAccess(mode, this)) {
|
|
945
946
|
throw new ErrnoError(Errno.EACCES);
|
|
946
947
|
}
|
|
947
948
|
}
|
|
@@ -953,7 +954,7 @@ access;
|
|
|
953
954
|
export async function rm(path, options) {
|
|
954
955
|
path = normalizePath(path);
|
|
955
956
|
const stats = await (cache.stats.getAsync(path) ||
|
|
956
|
-
|
|
957
|
+
lstat.call(this, path).catch((error) => {
|
|
957
958
|
if (error.code == 'ENOENT' && options?.force)
|
|
958
959
|
return undefined;
|
|
959
960
|
throw error;
|
|
@@ -965,17 +966,17 @@ export async function rm(path, options) {
|
|
|
965
966
|
switch (stats.mode & constants.S_IFMT) {
|
|
966
967
|
case constants.S_IFDIR:
|
|
967
968
|
if (options?.recursive) {
|
|
968
|
-
for (const entry of await readdir(path, { _isIndirect: true })) {
|
|
969
|
-
await rm(join(path, entry), { ...options, _isIndirect: true });
|
|
969
|
+
for (const entry of await readdir.call(this, path, { _isIndirect: true })) {
|
|
970
|
+
await rm.call(this, join(path, entry), { ...options, _isIndirect: true });
|
|
970
971
|
}
|
|
971
972
|
}
|
|
972
|
-
await rmdir(path);
|
|
973
|
+
await rmdir.call(this, path);
|
|
973
974
|
break;
|
|
974
975
|
case constants.S_IFREG:
|
|
975
976
|
case constants.S_IFLNK:
|
|
976
977
|
case constants.S_IFBLK:
|
|
977
978
|
case constants.S_IFCHR:
|
|
978
|
-
await unlink(path);
|
|
979
|
+
await unlink.call(this, path);
|
|
979
980
|
break;
|
|
980
981
|
case constants.S_IFIFO:
|
|
981
982
|
case constants.S_IFSOCK:
|
|
@@ -992,7 +993,7 @@ export async function mkdtemp(prefix, options) {
|
|
|
992
993
|
const encoding = typeof options === 'object' ? options?.encoding : options || 'utf8';
|
|
993
994
|
const fsName = `${prefix}${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
994
995
|
const resolvedPath = '/tmp/' + fsName;
|
|
995
|
-
await mkdir(resolvedPath);
|
|
996
|
+
await mkdir.call(this, resolvedPath);
|
|
996
997
|
return encoding == 'buffer' ? Buffer.from(resolvedPath) : resolvedPath;
|
|
997
998
|
}
|
|
998
999
|
mkdtemp;
|
|
@@ -1006,10 +1007,10 @@ mkdtemp;
|
|
|
1006
1007
|
export async function copyFile(src, dest, mode) {
|
|
1007
1008
|
src = normalizePath(src);
|
|
1008
1009
|
dest = normalizePath(dest);
|
|
1009
|
-
if (mode && mode & constants.COPYFILE_EXCL && (await exists(dest))) {
|
|
1010
|
+
if (mode && mode & constants.COPYFILE_EXCL && (await exists.call(this, dest))) {
|
|
1010
1011
|
throw new ErrnoError(Errno.EEXIST, 'Destination file already exists.', dest, 'copyFile');
|
|
1011
1012
|
}
|
|
1012
|
-
await writeFile(dest, await readFile(src));
|
|
1013
|
+
await writeFile.call(this, dest, await readFile.call(this, src));
|
|
1013
1014
|
emitChange('rename', dest.toString());
|
|
1014
1015
|
}
|
|
1015
1016
|
copyFile;
|
|
@@ -1022,7 +1023,7 @@ copyFile;
|
|
|
1022
1023
|
*/
|
|
1023
1024
|
export function opendir(path, options) {
|
|
1024
1025
|
path = normalizePath(path);
|
|
1025
|
-
return Promise.resolve(new Dir(path));
|
|
1026
|
+
return Promise.resolve(new Dir(path, this));
|
|
1026
1027
|
}
|
|
1027
1028
|
opendir;
|
|
1028
1029
|
/**
|
|
@@ -1040,8 +1041,8 @@ opendir;
|
|
|
1040
1041
|
export async function cp(source, destination, opts) {
|
|
1041
1042
|
source = normalizePath(source);
|
|
1042
1043
|
destination = normalizePath(destination);
|
|
1043
|
-
const srcStats = await lstat(source); // Use lstat to follow symlinks if not dereferencing
|
|
1044
|
-
if (opts?.errorOnExist && (await exists(destination))) {
|
|
1044
|
+
const srcStats = await lstat.call(this, source); // Use lstat to follow symlinks if not dereferencing
|
|
1045
|
+
if (opts?.errorOnExist && (await exists.call(this, destination))) {
|
|
1045
1046
|
throw new ErrnoError(Errno.EEXIST, 'Destination file or directory already exists.', destination, 'cp');
|
|
1046
1047
|
}
|
|
1047
1048
|
switch (srcStats.mode & constants.S_IFMT) {
|
|
@@ -1049,20 +1050,20 @@ export async function cp(source, destination, opts) {
|
|
|
1049
1050
|
if (!opts?.recursive) {
|
|
1050
1051
|
throw new ErrnoError(Errno.EISDIR, source + ' is a directory (not copied)', source, 'cp');
|
|
1051
1052
|
}
|
|
1052
|
-
const [entries] = await Promise.all([readdir(source, { withFileTypes: true }), mkdir(destination, { recursive: true })] // Ensure the destination directory exists
|
|
1053
|
+
const [entries] = await Promise.all([readdir.call(this, source, { withFileTypes: true }), mkdir.call(this, destination, { recursive: true })] // Ensure the destination directory exists
|
|
1053
1054
|
);
|
|
1054
1055
|
const _cp = async (dirent) => {
|
|
1055
1056
|
if (opts.filter && !opts.filter(join(source, dirent.name), join(destination, dirent.name))) {
|
|
1056
1057
|
return; // Skip if the filter returns false
|
|
1057
1058
|
}
|
|
1058
|
-
await cp(join(source, dirent.name), join(destination, dirent.name), opts);
|
|
1059
|
+
await cp.call(this, join(source, dirent.name), join(destination, dirent.name), opts);
|
|
1059
1060
|
};
|
|
1060
1061
|
await Promise.all(entries.map(_cp));
|
|
1061
1062
|
break;
|
|
1062
1063
|
}
|
|
1063
1064
|
case constants.S_IFREG:
|
|
1064
1065
|
case constants.S_IFLNK:
|
|
1065
|
-
await copyFile(source, destination);
|
|
1066
|
+
await copyFile.call(this, source, destination);
|
|
1066
1067
|
break;
|
|
1067
1068
|
case constants.S_IFBLK:
|
|
1068
1069
|
case constants.S_IFCHR:
|
|
@@ -1073,12 +1074,12 @@ export async function cp(source, destination, opts) {
|
|
|
1073
1074
|
}
|
|
1074
1075
|
// Optionally preserve timestamps
|
|
1075
1076
|
if (opts?.preserveTimestamps) {
|
|
1076
|
-
await utimes(destination, srcStats.atime, srcStats.mtime);
|
|
1077
|
+
await utimes.call(this, destination, srcStats.atime, srcStats.mtime);
|
|
1077
1078
|
}
|
|
1078
1079
|
}
|
|
1079
1080
|
cp;
|
|
1080
|
-
export function statfs(path, opts) {
|
|
1081
|
+
export async function statfs(path, opts) {
|
|
1081
1082
|
path = normalizePath(path);
|
|
1082
|
-
const { fs } = resolveMount(path);
|
|
1083
|
+
const { fs } = resolveMount(path, this);
|
|
1083
1084
|
return Promise.resolve(_statfs(fs, opts?.bigint));
|
|
1084
1085
|
}
|
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import type { BigIntStatsFs, StatsFs } from 'node:fs';
|
|
2
|
+
import { type BoundContext, type V_Context } from '../context.js';
|
|
2
3
|
import { ErrnoError } from '../error.js';
|
|
3
4
|
import type { File } from '../file.js';
|
|
4
5
|
import type { FileSystem } from '../filesystem.js';
|
|
5
6
|
import { type AbsolutePath } from './path.js';
|
|
7
|
+
/**
|
|
8
|
+
* @internal @hidden
|
|
9
|
+
*/
|
|
6
10
|
export declare const fdMap: Map<number, File>;
|
|
11
|
+
/**
|
|
12
|
+
* @internal @hidden
|
|
13
|
+
*/
|
|
7
14
|
export declare function file2fd(file: File): number;
|
|
15
|
+
/**
|
|
16
|
+
* @internal @hidden
|
|
17
|
+
*/
|
|
8
18
|
export declare function fd2file(fd: number): File;
|
|
19
|
+
/**
|
|
20
|
+
* @internal @hidden
|
|
21
|
+
*/
|
|
9
22
|
export type MountObject = Record<AbsolutePath, FileSystem>;
|
|
10
23
|
/**
|
|
11
24
|
* The map of mount points
|
|
@@ -14,6 +27,7 @@ export type MountObject = Record<AbsolutePath, FileSystem>;
|
|
|
14
27
|
export declare const mounts: Map<string, FileSystem>;
|
|
15
28
|
/**
|
|
16
29
|
* Mounts the file system at `mountPoint`.
|
|
30
|
+
* @internal
|
|
17
31
|
*/
|
|
18
32
|
export declare function mount(mountPoint: string, fs: FileSystem): void;
|
|
19
33
|
/**
|
|
@@ -21,13 +35,19 @@ export declare function mount(mountPoint: string, fs: FileSystem): void;
|
|
|
21
35
|
*/
|
|
22
36
|
export declare function umount(mountPoint: string): void;
|
|
23
37
|
/**
|
|
24
|
-
*
|
|
38
|
+
* @internal @hidden
|
|
25
39
|
*/
|
|
26
|
-
export
|
|
40
|
+
export interface ResolvedMount {
|
|
27
41
|
fs: FileSystem;
|
|
28
42
|
path: string;
|
|
29
43
|
mountPoint: string;
|
|
30
|
-
|
|
44
|
+
root: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the internal `FileSystem` for the path, then returns it along with the path relative to the FS' root
|
|
48
|
+
* @internal @hidden
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveMount(path: string, ctx: V_Context): ResolvedMount;
|
|
31
51
|
/**
|
|
32
52
|
* Wait for all file systems to be ready and synced.
|
|
33
53
|
* May be removed at some point.
|
|
@@ -36,25 +56,25 @@ export declare function resolveMount(path: string): {
|
|
|
36
56
|
export declare function _synced(): Promise<void>;
|
|
37
57
|
/**
|
|
38
58
|
* Reverse maps the paths in text from the mounted FileSystem to the global path
|
|
39
|
-
* @hidden
|
|
59
|
+
* @internal @hidden
|
|
40
60
|
*/
|
|
41
61
|
export declare function fixPaths(text: string, paths: Record<string, string>): string;
|
|
42
62
|
/**
|
|
43
63
|
* Fix paths in error stacks
|
|
44
|
-
* @hidden
|
|
64
|
+
* @internal @hidden
|
|
45
65
|
*/
|
|
46
66
|
export declare function fixError<E extends ErrnoError>(e: E, paths: Record<string, string>): E;
|
|
47
67
|
/**
|
|
48
|
-
* @deprecated
|
|
68
|
+
* @internal @deprecated
|
|
49
69
|
*/
|
|
50
70
|
export declare function mountObject(mounts: MountObject): void;
|
|
51
71
|
/**
|
|
52
|
-
* @hidden
|
|
72
|
+
* @internal @hidden
|
|
53
73
|
*/
|
|
54
74
|
export declare function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? BigIntStatsFs : StatsFs;
|
|
55
75
|
/**
|
|
56
76
|
* Options used for caching, among other things.
|
|
57
|
-
* @internal *UNSTABLE*
|
|
77
|
+
* @internal @hidden *UNSTABLE*
|
|
58
78
|
*/
|
|
59
79
|
export interface InternalOptions {
|
|
60
80
|
/**
|
|
@@ -68,3 +88,10 @@ export interface ReaddirOptions extends InternalOptions {
|
|
|
68
88
|
withFileTypes?: boolean;
|
|
69
89
|
recursive?: boolean;
|
|
70
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Change the root path
|
|
93
|
+
* @param inPlace if true, this changes the root for the current context instead of creating a new one (if associated with a context).
|
|
94
|
+
* @experimental
|
|
95
|
+
*/
|
|
96
|
+
export declare function chroot(this: V_Context, path: string, inPlace?: false): BoundContext;
|
|
97
|
+
export declare function chroot<T extends V_Context>(this: T, path: string, inPlace: true): T;
|