@zenfs/core 0.12.0 → 0.12.2
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/backend.d.ts +15 -5
- package/dist/backends/index/fs.d.ts +1 -0
- package/dist/backends/index/index.d.ts +5 -0
- package/dist/backends/index/index.js +1 -0
- package/dist/backends/overlay.js +1 -1
- package/dist/backends/port/fs.d.ts +3 -1
- package/dist/browser.min.js +4 -4
- package/dist/browser.min.js.map +4 -4
- package/dist/config.d.ts +33 -11
- package/dist/config.js +16 -7
- package/dist/emulation/async.d.ts +5 -4
- package/dist/emulation/async.js +3 -2
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/path.d.ts +4 -1
- package/dist/emulation/promises.d.ts +4 -4
- package/dist/emulation/promises.js +27 -27
- package/dist/emulation/shared.d.ts +6 -0
- package/dist/emulation/shared.js +19 -1
- package/dist/emulation/sync.d.ts +4 -4
- package/dist/emulation/sync.js +76 -38
- package/dist/file.d.ts +5 -10
- package/dist/file.js +38 -55
- package/dist/filesystem.d.ts +45 -3
- package/dist/filesystem.js +37 -8
- package/dist/stats.d.ts +16 -16
- package/dist/stats.js +42 -49
- package/package.json +2 -2
- package/src/backends/backend.ts +15 -6
- package/src/backends/index/index.ts +5 -0
- package/src/backends/overlay.ts +1 -1
- package/src/config.ts +62 -21
- package/src/emulation/async.ts +19 -18
- package/src/emulation/index.ts +1 -1
- package/src/emulation/path.ts +4 -1
- package/src/emulation/promises.ts +33 -31
- package/src/emulation/shared.ts +22 -1
- package/src/emulation/sync.ts +83 -54
- package/src/error.ts +1 -1
- package/src/file.ts +39 -57
- package/src/filesystem.ts +133 -51
- package/src/stats.ts +48 -60
package/dist/config.d.ts
CHANGED
|
@@ -1,25 +1,47 @@
|
|
|
1
|
-
import type { Backend, BackendConfiguration } from './backends/backend.js';
|
|
2
|
-
import { FileSystem } from './filesystem.js';
|
|
1
|
+
import type { Backend, BackendConfiguration, FilesystemOf } from './backends/backend.js';
|
|
3
2
|
import type { AbsolutePath } from './emulation/path.js';
|
|
4
3
|
/**
|
|
5
4
|
* Configuration for a specific mount point
|
|
6
5
|
*/
|
|
7
|
-
export type MountConfiguration<
|
|
6
|
+
export type MountConfiguration<T extends Backend> = FilesystemOf<T> | BackendConfiguration<T> | T;
|
|
8
7
|
/**
|
|
9
8
|
* Retrieve a file system with the given configuration.
|
|
10
9
|
* @param config A BackendConfig object.
|
|
11
10
|
*/
|
|
12
|
-
export declare function resolveMountConfig<
|
|
11
|
+
export declare function resolveMountConfig<T extends Backend>(config: MountConfiguration<T>, _depth?: number): Promise<FilesystemOf<T>>;
|
|
12
|
+
type ConfigMounts = {
|
|
13
|
+
[K in AbsolutePath]: Backend;
|
|
14
|
+
};
|
|
13
15
|
/**
|
|
14
16
|
* Configuration
|
|
15
17
|
*/
|
|
16
|
-
export interface Configuration {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
export interface Configuration<T extends ConfigMounts> {
|
|
19
|
+
/**
|
|
20
|
+
* An object mapping mount points to mount configuration
|
|
21
|
+
*/
|
|
22
|
+
mounts: {
|
|
23
|
+
[K in keyof T & AbsolutePath]: MountConfiguration<T[K]>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The uid to use
|
|
27
|
+
*/
|
|
28
|
+
uid: number;
|
|
29
|
+
/**
|
|
30
|
+
* The gid to use
|
|
31
|
+
*/
|
|
32
|
+
gid: number;
|
|
33
|
+
/**
|
|
34
|
+
* If set, disables the sync cache and sync operations on async file systems.
|
|
35
|
+
*/
|
|
36
|
+
disableAsyncCache: boolean;
|
|
20
37
|
}
|
|
21
38
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @see Configuration for more info on the configuration object.
|
|
39
|
+
* Configures ZenFS with single mount point /
|
|
24
40
|
*/
|
|
25
|
-
export declare function configure<T extends
|
|
41
|
+
export declare function configure<T extends Backend>(config: MountConfiguration<T>): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Configures ZenFS with the given configuration
|
|
44
|
+
* @see Configuration
|
|
45
|
+
*/
|
|
46
|
+
export declare function configure<T extends ConfigMounts>(config: Partial<Configuration<T>>): Promise<void>;
|
|
47
|
+
export {};
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ErrnoError, Errno } from './error.js';
|
|
2
1
|
import { checkOptions, isBackend, isBackendConfig } from './backends/backend.js';
|
|
3
2
|
import * as fs from './emulation/index.js';
|
|
4
3
|
import { setCred } from './emulation/shared.js';
|
|
4
|
+
import { Errno, ErrnoError } from './error.js';
|
|
5
5
|
import { FileSystem } from './filesystem.js';
|
|
6
6
|
function isMountConfig(arg) {
|
|
7
7
|
return isBackendConfig(arg) || isBackend(arg) || arg instanceof FileSystem;
|
|
@@ -40,13 +40,16 @@ export async function resolveMountConfig(config, _depth = 0) {
|
|
|
40
40
|
throw new ErrnoError(Errno.EPERM, 'Backend not available: ' + backend);
|
|
41
41
|
}
|
|
42
42
|
checkOptions(backend, config);
|
|
43
|
-
const mount = await backend.create(config);
|
|
43
|
+
const mount = (await backend.create(config));
|
|
44
|
+
if ('_disableSync' in mount) {
|
|
45
|
+
mount._disableSync = config.disableAsyncCache || false;
|
|
46
|
+
}
|
|
44
47
|
await mount.ready();
|
|
45
48
|
return mount;
|
|
46
49
|
}
|
|
47
50
|
/**
|
|
48
|
-
*
|
|
49
|
-
* @see Configuration
|
|
51
|
+
* Configures ZenFS with the given configuration
|
|
52
|
+
* @see Configuration
|
|
50
53
|
*/
|
|
51
54
|
export async function configure(config) {
|
|
52
55
|
const uid = 'uid' in config ? config.uid || 0 : 0;
|
|
@@ -55,12 +58,18 @@ export async function configure(config) {
|
|
|
55
58
|
// single FS
|
|
56
59
|
config = { mounts: { '/': config } };
|
|
57
60
|
}
|
|
58
|
-
|
|
61
|
+
setCred({ uid, gid, suid: uid, sgid: gid, euid: uid, egid: gid });
|
|
62
|
+
if (!config.mounts) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const [point, mountConfig] of Object.entries(config.mounts)) {
|
|
59
66
|
if (!point.startsWith('/')) {
|
|
60
67
|
throw new ErrnoError(Errno.EINVAL, 'Mount points must have absolute paths');
|
|
61
68
|
}
|
|
62
|
-
|
|
69
|
+
if (isBackendConfig(mountConfig)) {
|
|
70
|
+
mountConfig.disableAsyncCache ?? (mountConfig.disableAsyncCache = config.disableAsyncCache || false);
|
|
71
|
+
}
|
|
72
|
+
config.mounts[point] = await resolveMountConfig(mountConfig);
|
|
63
73
|
}
|
|
64
74
|
fs.mountObject(config.mounts);
|
|
65
|
-
setCred({ uid, gid, suid: uid, sgid: gid, euid: uid, egid: gid });
|
|
66
75
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
/// <reference types="node" resolution-mode="require"/>
|
|
4
|
+
import { Buffer } from 'buffer';
|
|
4
5
|
import type * as fs from 'node:fs';
|
|
5
6
|
import type { FileContents } from '../filesystem.js';
|
|
6
|
-
import { BigIntStats, type
|
|
7
|
+
import { BigIntStats, type Stats } from '../stats.js';
|
|
7
8
|
import { type Callback } from '../utils.js';
|
|
8
9
|
import { Dirent, type Dir } from './dir.js';
|
|
9
10
|
import * as promises from './promises.js';
|
|
@@ -440,12 +441,12 @@ export declare function opendir(path: fs.PathLike, cb: Callback<[Dir]>): void;
|
|
|
440
441
|
export declare function opendir(path: fs.PathLike, options: fs.OpenDirOptions, cb: Callback<[Dir]>): void;
|
|
441
442
|
export declare function cp(source: fs.PathLike, destination: fs.PathLike, callback: Callback): void;
|
|
442
443
|
export declare function cp(source: fs.PathLike, destination: fs.PathLike, opts: fs.CopyOptions, callback: Callback): void;
|
|
443
|
-
export declare function statfs(path: fs.PathLike, callback: Callback<[StatsFs]>): void;
|
|
444
|
+
export declare function statfs(path: fs.PathLike, callback: Callback<[fs.StatsFs]>): void;
|
|
444
445
|
export declare function statfs(path: fs.PathLike, options: fs.StatFsOptions & {
|
|
445
446
|
bigint?: false;
|
|
446
|
-
}, callback: Callback<[StatsFs]>): void;
|
|
447
|
+
}, callback: Callback<[fs.StatsFs]>): void;
|
|
447
448
|
export declare function statfs(path: fs.PathLike, options: fs.StatFsOptions & {
|
|
448
449
|
bigint: true;
|
|
449
|
-
}, callback: Callback<[BigIntStatsFs]>): void;
|
|
450
|
+
}, callback: Callback<[fs.BigIntStatsFs]>): void;
|
|
450
451
|
export declare function openAsBlob(path: fs.PathLike, options?: fs.OpenAsBlobOptions): Promise<Blob>;
|
|
451
452
|
export {};
|
package/dist/emulation/async.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
1
2
|
import { ErrnoError, Errno } from '../error.js';
|
|
2
3
|
import { BigIntStats } from '../stats.js';
|
|
3
4
|
import { nop, normalizeMode } from '../utils.js';
|
|
@@ -173,7 +174,7 @@ export function write(fd, data, cbPosOff, cbLenEnc, cbPos, cb = nop) {
|
|
|
173
174
|
case 'number':
|
|
174
175
|
// (fd, string, position, encoding?, cb?)
|
|
175
176
|
position = cbPosOff;
|
|
176
|
-
encoding =
|
|
177
|
+
encoding = typeof cbLenEnc === 'string' ? cbLenEnc : 'utf8';
|
|
177
178
|
cb = typeof cbPos === 'function' ? cbPos : cb;
|
|
178
179
|
break;
|
|
179
180
|
default:
|
|
@@ -197,7 +198,7 @@ export function write(fd, data, cbPosOff, cbLenEnc, cbPos, cb = nop) {
|
|
|
197
198
|
offset = cbPosOff;
|
|
198
199
|
length = cbLenEnc;
|
|
199
200
|
position = typeof cbPos === 'number' ? cbPos : null;
|
|
200
|
-
const _cb =
|
|
201
|
+
const _cb = typeof cbPos === 'function' ? cbPos : cb;
|
|
201
202
|
handle
|
|
202
203
|
.write(buffer, offset, length, position)
|
|
203
204
|
.then(({ bytesWritten }) => _cb(undefined, bytesWritten, buffer))
|
|
@@ -5,4 +5,4 @@ export * as constants from './constants.js';
|
|
|
5
5
|
export * from './streams.js';
|
|
6
6
|
export * from './dir.js';
|
|
7
7
|
export { mountObject, mounts, mount, umount } from './shared.js';
|
|
8
|
-
export { Stats,
|
|
8
|
+
export { Stats, StatsFs, BigIntStatsFs } from '../stats.js';
|
package/dist/emulation/index.js
CHANGED
|
@@ -5,4 +5,4 @@ export * as constants from './constants.js';
|
|
|
5
5
|
export * from './streams.js';
|
|
6
6
|
export * from './dir.js';
|
|
7
7
|
export { mountObject, mounts, mount, umount } from './shared.js';
|
|
8
|
-
export { Stats,
|
|
8
|
+
export { Stats, StatsFs, BigIntStatsFs } from '../stats.js';
|
package/dist/emulation/path.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type { ParsedPath } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* An absolute path
|
|
5
|
+
*/
|
|
3
6
|
export type AbsolutePath = `/${string}`;
|
|
4
7
|
export declare let cwd: string;
|
|
5
8
|
export declare function cd(path: string): void;
|
|
@@ -8,7 +11,7 @@ export declare function normalizeString(path: string, allowAboveRoot: boolean):
|
|
|
8
11
|
export declare function formatExt(ext: string): string;
|
|
9
12
|
export declare function resolve(...parts: string[]): AbsolutePath;
|
|
10
13
|
export declare function normalize(path: string): string;
|
|
11
|
-
export declare function isAbsolute(path: string):
|
|
14
|
+
export declare function isAbsolute(path: string): path is AbsolutePath;
|
|
12
15
|
export declare function join(...parts: string[]): string;
|
|
13
16
|
export declare function relative(from: string, to: string): string;
|
|
14
17
|
export declare function dirname(path: string): string;
|
|
@@ -14,7 +14,7 @@ import type { ReadableStream as TReadableStream } from 'node:stream/web';
|
|
|
14
14
|
import type { Interface as ReadlineInterface } from 'readline';
|
|
15
15
|
import { File } from '../file.js';
|
|
16
16
|
import type { FileContents } from '../filesystem.js';
|
|
17
|
-
import { BigIntStats, type
|
|
17
|
+
import { BigIntStats, type Stats } from '../stats.js';
|
|
18
18
|
import { Dir, Dirent } from './dir.js';
|
|
19
19
|
import { ReadStream, WriteStream } from './streams.js';
|
|
20
20
|
export * as constants from './constants.js';
|
|
@@ -437,8 +437,8 @@ export declare function cp(source: fs.PathLike, destination: fs.PathLike, opts?:
|
|
|
437
437
|
*/
|
|
438
438
|
export declare function statfs(path: fs.PathLike, opts?: fs.StatFsOptions & {
|
|
439
439
|
bigint?: false;
|
|
440
|
-
}): Promise<StatsFs>;
|
|
440
|
+
}): Promise<fs.StatsFs>;
|
|
441
441
|
export declare function statfs(path: fs.PathLike, opts: fs.StatFsOptions & {
|
|
442
442
|
bigint: true;
|
|
443
|
-
}): Promise<BigIntStatsFs>;
|
|
444
|
-
export declare function statfs(path: fs.PathLike, opts?: fs.StatFsOptions): Promise<StatsFs | BigIntStatsFs>;
|
|
443
|
+
}): Promise<fs.BigIntStatsFs>;
|
|
444
|
+
export declare function statfs(path: fs.PathLike, opts?: fs.StatFsOptions): Promise<fs.StatsFs | fs.BigIntStatsFs>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
|
-
import {
|
|
2
|
+
import { Errno, ErrnoError } from '../error.js';
|
|
3
3
|
import { ActionType, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
|
|
4
4
|
import { BigIntStats, FileType } from '../stats.js';
|
|
5
5
|
import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
6
6
|
import * as constants from './constants.js';
|
|
7
7
|
import { Dir, Dirent } from './dir.js';
|
|
8
8
|
import { dirname, join, parse } from './path.js';
|
|
9
|
-
import { cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
9
|
+
import { _statfs, cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
10
10
|
import { ReadStream, WriteStream } from './streams.js';
|
|
11
11
|
export * as constants from './constants.js';
|
|
12
12
|
export class FileHandle {
|
|
@@ -162,7 +162,7 @@ export class FileHandle {
|
|
|
162
162
|
if (typeof data === 'string') {
|
|
163
163
|
// Signature 1: (fd, string, [position?, [encoding?]])
|
|
164
164
|
position = typeof posOrOff === 'number' ? posOrOff : null;
|
|
165
|
-
const encoding =
|
|
165
|
+
const encoding = typeof lenOrEnc === 'string' ? lenOrEnc : 'utf8';
|
|
166
166
|
offset = 0;
|
|
167
167
|
buffer = Buffer.from(data, encoding);
|
|
168
168
|
length = buffer.length;
|
|
@@ -386,29 +386,7 @@ async function _open(path, _flag, _mode = 0o644, resolveSymlinks) {
|
|
|
386
386
|
const mode = normalizeMode(_mode, 0o644), flag = parseFlag(_flag);
|
|
387
387
|
path = resolveSymlinks && (await exists(path)) ? await realpath(path) : path;
|
|
388
388
|
const { fs, path: resolved } = resolveMount(path);
|
|
389
|
-
|
|
390
|
-
switch (pathExistsAction(flag)) {
|
|
391
|
-
case ActionType.THROW:
|
|
392
|
-
throw ErrnoError.With('EEXIST', path, '_open');
|
|
393
|
-
case ActionType.TRUNCATE:
|
|
394
|
-
/*
|
|
395
|
-
In a previous implementation, we deleted the file and
|
|
396
|
-
re-created it. However, this created a race condition if another
|
|
397
|
-
asynchronous request was trying to read the file, as the file
|
|
398
|
-
would not exist for a small period of time.
|
|
399
|
-
*/
|
|
400
|
-
const file = await fs.openFile(resolved, flag, cred);
|
|
401
|
-
await file.truncate(0);
|
|
402
|
-
await file.sync();
|
|
403
|
-
return new FileHandle(file);
|
|
404
|
-
case ActionType.NOP:
|
|
405
|
-
// Must await so thrown errors are caught by the catch below
|
|
406
|
-
return new FileHandle(await fs.openFile(resolved, flag, cred));
|
|
407
|
-
default:
|
|
408
|
-
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
catch (e) {
|
|
389
|
+
if (!(await fs.exists(path, cred))) {
|
|
412
390
|
switch (pathNotExistsAction(flag)) {
|
|
413
391
|
case ActionType.CREATE:
|
|
414
392
|
// Ensure parent exists.
|
|
@@ -423,6 +401,26 @@ async function _open(path, _flag, _mode = 0o644, resolveSymlinks) {
|
|
|
423
401
|
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
|
|
424
402
|
}
|
|
425
403
|
}
|
|
404
|
+
switch (pathExistsAction(flag)) {
|
|
405
|
+
case ActionType.THROW:
|
|
406
|
+
throw ErrnoError.With('EEXIST', path, '_open');
|
|
407
|
+
case ActionType.TRUNCATE:
|
|
408
|
+
/*
|
|
409
|
+
In a previous implementation, we deleted the file and
|
|
410
|
+
re-created it. However, this created a race condition if another
|
|
411
|
+
asynchronous request was trying to read the file, as the file
|
|
412
|
+
would not exist for a small period of time.
|
|
413
|
+
*/
|
|
414
|
+
const file = await fs.openFile(resolved, flag, cred);
|
|
415
|
+
await file.truncate(0);
|
|
416
|
+
await file.sync();
|
|
417
|
+
return new FileHandle(file);
|
|
418
|
+
case ActionType.NOP:
|
|
419
|
+
// Must await so thrown errors are caught by the catch below
|
|
420
|
+
return new FileHandle(await fs.openFile(resolved, flag, cred));
|
|
421
|
+
default:
|
|
422
|
+
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
|
|
423
|
+
}
|
|
426
424
|
}
|
|
427
425
|
/**
|
|
428
426
|
* Asynchronous file open.
|
|
@@ -847,5 +845,7 @@ export async function cp(source, destination, opts) {
|
|
|
847
845
|
}
|
|
848
846
|
cp;
|
|
849
847
|
export async function statfs(path, opts) {
|
|
850
|
-
|
|
848
|
+
path = normalizePath(path);
|
|
849
|
+
const { fs } = resolveMount(path);
|
|
850
|
+
return _statfs(fs, opts?.bigint);
|
|
851
851
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type { BigIntStatsFs, StatsFs } from 'node:fs';
|
|
1
3
|
import { Cred } from '../cred.js';
|
|
2
4
|
import type { File } from '../file.js';
|
|
3
5
|
import { FileSystem } from '../filesystem.js';
|
|
@@ -35,3 +37,7 @@ export declare function resolveMount(path: string): {
|
|
|
35
37
|
export declare function fixPaths(text: string, paths: Record<string, string>): string;
|
|
36
38
|
export declare function fixError<E extends Error>(e: E, paths: Record<string, string>): E;
|
|
37
39
|
export declare function mountObject(mounts: MountObject): void;
|
|
40
|
+
/**
|
|
41
|
+
* @hidden
|
|
42
|
+
*/
|
|
43
|
+
export declare function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? BigIntStatsFs : StatsFs;
|
package/dist/emulation/shared.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Utilities and shared data
|
|
2
|
-
import { ErrnoError, Errno } from '../error.js';
|
|
3
2
|
import { InMemory } from '../backends/memory.js';
|
|
4
3
|
import { rootCred } from '../cred.js';
|
|
4
|
+
import { Errno, ErrnoError } from '../error.js';
|
|
5
|
+
import { size_max } from '../inode.js';
|
|
6
|
+
import { ZenFsType } from '../stats.js';
|
|
5
7
|
import { normalizePath } from '../utils.js';
|
|
6
8
|
import { resolve } from './path.js';
|
|
7
9
|
// credentials
|
|
@@ -100,3 +102,19 @@ export function mountObject(mounts) {
|
|
|
100
102
|
mount(point, fs);
|
|
101
103
|
}
|
|
102
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* @hidden
|
|
107
|
+
*/
|
|
108
|
+
export function _statfs(fs, bigint) {
|
|
109
|
+
const md = fs.metadata();
|
|
110
|
+
const bs = md.blockSize || 4096;
|
|
111
|
+
return {
|
|
112
|
+
type: (bigint ? BigInt : Number)(md.type || ZenFsType),
|
|
113
|
+
bsize: (bigint ? BigInt : Number)(bs),
|
|
114
|
+
ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),
|
|
115
|
+
files: (bigint ? BigInt : Number)(md.totalNodes || size_max),
|
|
116
|
+
bavail: (bigint ? BigInt : Number)(md.freeSpace / bs),
|
|
117
|
+
bfree: (bigint ? BigInt : Number)(md.freeSpace / bs),
|
|
118
|
+
blocks: (bigint ? BigInt : Number)(md.totalSpace / bs),
|
|
119
|
+
};
|
|
120
|
+
}
|
package/dist/emulation/sync.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Buffer } from 'buffer';
|
|
5
5
|
import type * as fs from 'node:fs';
|
|
6
6
|
import { FileContents } from '../filesystem.js';
|
|
7
|
-
import { BigIntStats, type
|
|
7
|
+
import { BigIntStats, type Stats } from '../stats.js';
|
|
8
8
|
import { Dir, Dirent } from './dir.js';
|
|
9
9
|
/**
|
|
10
10
|
* Synchronous rename.
|
|
@@ -368,8 +368,8 @@ export declare function cpSync(source: fs.PathLike, destination: fs.PathLike, op
|
|
|
368
368
|
*/
|
|
369
369
|
export declare function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions & {
|
|
370
370
|
bigint?: false;
|
|
371
|
-
}): StatsFs;
|
|
371
|
+
}): fs.StatsFs;
|
|
372
372
|
export declare function statfsSync(path: fs.PathLike, options: fs.StatFsOptions & {
|
|
373
373
|
bigint: true;
|
|
374
|
-
}): BigIntStatsFs;
|
|
375
|
-
export declare function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions): StatsFs | BigIntStatsFs;
|
|
374
|
+
}): fs.BigIntStatsFs;
|
|
375
|
+
export declare function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions): fs.StatsFs | fs.BigIntStatsFs;
|
package/dist/emulation/sync.js
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
|
-
import {
|
|
2
|
+
import { Errno, ErrnoError } from '../error.js';
|
|
3
3
|
import { ActionType, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
|
|
4
4
|
import { BigIntStats, FileType } from '../stats.js';
|
|
5
5
|
import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
6
6
|
import { COPYFILE_EXCL, F_OK, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK } from './constants.js';
|
|
7
7
|
import { Dir, Dirent } from './dir.js';
|
|
8
8
|
import { dirname, join, parse } from './path.js';
|
|
9
|
-
import { cred, fd2file, fdMap,
|
|
10
|
-
function wrap(...[name, resolveSymlinks, path, ...args]) {
|
|
11
|
-
path = normalizePath(path);
|
|
12
|
-
const { fs, path: resolvedPath } = resolveMount(resolveSymlinks && existsSync(path) ? realpathSync(path) : path);
|
|
13
|
-
try {
|
|
14
|
-
// @ts-expect-error 2556 (since ...args is not correctly picked up as being a tuple)
|
|
15
|
-
return fs[name](resolvedPath, ...args);
|
|
16
|
-
}
|
|
17
|
-
catch (e) {
|
|
18
|
-
throw fixError(e, { [resolvedPath]: path });
|
|
19
|
-
}
|
|
20
|
-
}
|
|
9
|
+
import { _statfs, cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
21
10
|
/**
|
|
22
11
|
* Synchronous rename.
|
|
23
12
|
* @param oldPath
|
|
@@ -60,13 +49,27 @@ export function existsSync(path) {
|
|
|
60
49
|
}
|
|
61
50
|
existsSync;
|
|
62
51
|
export function statSync(path, options) {
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
path = normalizePath(path);
|
|
53
|
+
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
54
|
+
try {
|
|
55
|
+
const stats = fs.statSync(resolved, cred);
|
|
56
|
+
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
throw fixError(e, { [resolved]: path });
|
|
60
|
+
}
|
|
65
61
|
}
|
|
66
62
|
statSync;
|
|
67
63
|
export function lstatSync(path, options) {
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
path = normalizePath(path);
|
|
65
|
+
const { fs, path: resolved } = resolveMount(path);
|
|
66
|
+
try {
|
|
67
|
+
const stats = fs.statSync(resolved, cred);
|
|
68
|
+
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
throw fixError(e, { [resolved]: path });
|
|
72
|
+
}
|
|
70
73
|
}
|
|
71
74
|
lstatSync;
|
|
72
75
|
/**
|
|
@@ -89,32 +92,37 @@ truncateSync;
|
|
|
89
92
|
* @param path
|
|
90
93
|
*/
|
|
91
94
|
export function unlinkSync(path) {
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
unlinkSync;
|
|
95
|
-
function _openSync(_path, _flag, _mode, resolveSymlinks = true) {
|
|
96
|
-
const path = normalizePath(_path), mode = normalizeMode(_mode, 0o644), flag = parseFlag(_flag);
|
|
97
|
-
// Check if the path exists, and is a file.
|
|
98
|
-
let stats;
|
|
95
|
+
path = normalizePath(path);
|
|
96
|
+
const { fs, path: resolved } = resolveMount(path);
|
|
99
97
|
try {
|
|
100
|
-
|
|
98
|
+
return fs.unlinkSync(resolved, cred);
|
|
101
99
|
}
|
|
102
100
|
catch (e) {
|
|
103
|
-
|
|
101
|
+
throw fixError(e, { [resolved]: path });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
unlinkSync;
|
|
105
|
+
function _openSync(path, _flag, _mode, resolveSymlinks = true) {
|
|
106
|
+
path = normalizePath(path);
|
|
107
|
+
const mode = normalizeMode(_mode, 0o644), flag = parseFlag(_flag);
|
|
108
|
+
path = resolveSymlinks && existsSync(path) ? realpathSync(path) : path;
|
|
109
|
+
const { fs, path: resolved } = resolveMount(path);
|
|
110
|
+
if (!fs.existsSync(resolved, cred)) {
|
|
104
111
|
switch (pathNotExistsAction(flag)) {
|
|
105
112
|
case ActionType.CREATE:
|
|
106
113
|
// Ensure parent exists.
|
|
107
|
-
const parentStats =
|
|
114
|
+
const parentStats = fs.statSync(dirname(resolved), cred);
|
|
108
115
|
if (!parentStats.isDirectory()) {
|
|
109
116
|
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
|
|
110
117
|
}
|
|
111
|
-
return
|
|
118
|
+
return fs.createFileSync(resolved, flag, mode, cred);
|
|
112
119
|
case ActionType.THROW:
|
|
113
120
|
throw ErrnoError.With('ENOENT', path, '_open');
|
|
114
121
|
default:
|
|
115
122
|
throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
|
|
116
123
|
}
|
|
117
124
|
}
|
|
125
|
+
const stats = fs.statSync(resolved, cred);
|
|
118
126
|
if (!stats.hasAccess(mode, cred)) {
|
|
119
127
|
throw ErrnoError.With('EACCES', path, '_open');
|
|
120
128
|
}
|
|
@@ -124,16 +132,16 @@ function _openSync(_path, _flag, _mode, resolveSymlinks = true) {
|
|
|
124
132
|
throw ErrnoError.With('EEXIST', path, '_open');
|
|
125
133
|
case ActionType.TRUNCATE:
|
|
126
134
|
// Delete file.
|
|
127
|
-
|
|
135
|
+
fs.unlinkSync(resolved, cred);
|
|
128
136
|
/*
|
|
129
137
|
Create file. Use the same mode as the old file.
|
|
130
138
|
Node itself modifies the ctime when this occurs, so this action
|
|
131
139
|
will preserve that behavior if the underlying file system
|
|
132
140
|
supports those properties.
|
|
133
141
|
*/
|
|
134
|
-
return
|
|
142
|
+
return fs.createFileSync(resolved, flag, stats.mode, cred);
|
|
135
143
|
case ActionType.NOP:
|
|
136
|
-
return
|
|
144
|
+
return fs.openFileSync(resolved, flag, cred);
|
|
137
145
|
default:
|
|
138
146
|
throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
|
|
139
147
|
}
|
|
@@ -285,7 +293,7 @@ export function writeSync(fd, data, posOrOff, lenOrEnc, pos) {
|
|
|
285
293
|
if (typeof data === 'string') {
|
|
286
294
|
// Signature 1: (fd, string, [position?, [encoding?]])
|
|
287
295
|
position = typeof posOrOff === 'number' ? posOrOff : null;
|
|
288
|
-
const encoding =
|
|
296
|
+
const encoding = typeof lenOrEnc === 'string' ? lenOrEnc : 'utf8';
|
|
289
297
|
offset = 0;
|
|
290
298
|
buffer = Buffer.from(data, encoding);
|
|
291
299
|
length = buffer.byteLength;
|
|
@@ -355,18 +363,39 @@ futimesSync;
|
|
|
355
363
|
* @param path
|
|
356
364
|
*/
|
|
357
365
|
export function rmdirSync(path) {
|
|
358
|
-
|
|
366
|
+
path = normalizePath(path);
|
|
367
|
+
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
368
|
+
try {
|
|
369
|
+
fs.rmdirSync(resolved, cred);
|
|
370
|
+
}
|
|
371
|
+
catch (e) {
|
|
372
|
+
throw fixError(e, { [resolved]: path });
|
|
373
|
+
}
|
|
359
374
|
}
|
|
360
375
|
rmdirSync;
|
|
361
376
|
export function mkdirSync(path, options) {
|
|
362
|
-
const mode = typeof options == 'number' || typeof options == 'string' ? options : options?.mode;
|
|
377
|
+
const mode = normalizeMode(typeof options == 'number' || typeof options == 'string' ? options : options?.mode, 0o777);
|
|
363
378
|
const recursive = typeof options == 'object' && options?.recursive;
|
|
364
|
-
|
|
379
|
+
path = normalizePath(path);
|
|
380
|
+
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
381
|
+
try {
|
|
382
|
+
return fs.mkdirSync(resolved, mode, cred);
|
|
383
|
+
}
|
|
384
|
+
catch (e) {
|
|
385
|
+
throw fixError(e, { [resolved]: path });
|
|
386
|
+
}
|
|
365
387
|
}
|
|
366
388
|
mkdirSync;
|
|
367
389
|
export function readdirSync(path, options) {
|
|
368
390
|
path = normalizePath(path);
|
|
369
|
-
const
|
|
391
|
+
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
392
|
+
let entries;
|
|
393
|
+
try {
|
|
394
|
+
entries = fs.readdirSync(resolved, cred);
|
|
395
|
+
}
|
|
396
|
+
catch (e) {
|
|
397
|
+
throw fixError(e, { [resolved]: path });
|
|
398
|
+
}
|
|
370
399
|
for (const mount of mounts.keys()) {
|
|
371
400
|
if (!mount.startsWith(path)) {
|
|
372
401
|
continue;
|
|
@@ -396,8 +425,15 @@ readdirSync;
|
|
|
396
425
|
* @param newpath
|
|
397
426
|
*/
|
|
398
427
|
export function linkSync(existing, newpath) {
|
|
428
|
+
existing = normalizePath(existing);
|
|
399
429
|
newpath = normalizePath(newpath);
|
|
400
|
-
|
|
430
|
+
const { fs, path: resolved } = resolveMount(existing);
|
|
431
|
+
try {
|
|
432
|
+
return fs.linkSync(resolved, newpath, cred);
|
|
433
|
+
}
|
|
434
|
+
catch (e) {
|
|
435
|
+
throw fixError(e, { [resolved]: existing });
|
|
436
|
+
}
|
|
401
437
|
}
|
|
402
438
|
linkSync;
|
|
403
439
|
/**
|
|
@@ -673,5 +709,7 @@ export function cpSync(source, destination, opts) {
|
|
|
673
709
|
}
|
|
674
710
|
cpSync;
|
|
675
711
|
export function statfsSync(path, options) {
|
|
676
|
-
|
|
712
|
+
path = normalizePath(path);
|
|
713
|
+
const { fs } = resolveMount(path);
|
|
714
|
+
return _statfs(fs, options?.bigint);
|
|
677
715
|
}
|
package/dist/file.d.ts
CHANGED
|
@@ -204,7 +204,7 @@ export declare class PreloadFile<FS extends FileSystem> extends File {
|
|
|
204
204
|
readonly stats: Stats;
|
|
205
205
|
protected _buffer: Uint8Array;
|
|
206
206
|
protected _position: number;
|
|
207
|
-
protected
|
|
207
|
+
protected dirty: boolean;
|
|
208
208
|
/**
|
|
209
209
|
* Creates a file with the given path and, optionally, the given contents. Note
|
|
210
210
|
* that, if contents is specified, it will be mutated by the file!
|
|
@@ -259,14 +259,14 @@ export declare class PreloadFile<FS extends FileSystem> extends File {
|
|
|
259
259
|
statSync(): Stats;
|
|
260
260
|
/**
|
|
261
261
|
* Asynchronous truncate.
|
|
262
|
-
* @param
|
|
262
|
+
* @param length
|
|
263
263
|
*/
|
|
264
|
-
truncate(
|
|
264
|
+
truncate(length: number): Promise<void>;
|
|
265
265
|
/**
|
|
266
266
|
* Synchronous truncate.
|
|
267
|
-
* @param
|
|
267
|
+
* @param length
|
|
268
268
|
*/
|
|
269
|
-
truncateSync(
|
|
269
|
+
truncateSync(length: number): void;
|
|
270
270
|
/**
|
|
271
271
|
* Write buffer to the file.
|
|
272
272
|
* Note that it is unsafe to use fs.write multiple times on the same file
|
|
@@ -345,11 +345,6 @@ export declare class PreloadFile<FS extends FileSystem> extends File {
|
|
|
345
345
|
chownSync(uid: number, gid: number): void;
|
|
346
346
|
utimes(atime: Date, mtime: Date): Promise<void>;
|
|
347
347
|
utimesSync(atime: Date, mtime: Date): void;
|
|
348
|
-
protected isDirty(): boolean;
|
|
349
|
-
/**
|
|
350
|
-
* Resets the dirty bit. Should only be called after a sync has completed successfully.
|
|
351
|
-
*/
|
|
352
|
-
protected resetDirty(): void;
|
|
353
348
|
_setType(type: FileType): Promise<void>;
|
|
354
349
|
_setTypeSync(type: FileType): void;
|
|
355
350
|
}
|