@zenfs/core 0.12.1 → 0.12.3
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 +1 -1
- package/dist/backends/fetch.d.ts +1 -1
- package/dist/backends/index/fs.d.ts +2 -1
- package/dist/backends/index/index.d.ts +2 -1
- package/dist/backends/overlay.d.ts +4 -3
- package/dist/backends/overlay.js +1 -1
- package/dist/backends/port/fs.d.ts +5 -1
- package/dist/backends/port/fs.js +13 -10
- package/dist/browser.min.js +4 -8
- package/dist/browser.min.js.map +3 -3
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/cred.d.ts +2 -1
- package/dist/emulation/async.d.ts +6 -5
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/promises.d.ts +5 -5
- package/dist/emulation/promises.js +31 -51
- package/dist/emulation/shared.d.ts +8 -2
- package/dist/emulation/shared.js +18 -1
- package/dist/emulation/streams.d.ts +1 -1
- package/dist/emulation/sync.d.ts +5 -5
- package/dist/emulation/sync.js +94 -76
- package/dist/error.d.ts +1 -1
- package/dist/error.js +1 -1
- package/dist/file.d.ts +7 -23
- package/dist/file.js +33 -80
- package/dist/filesystem.d.ts +35 -31
- package/dist/filesystem.js +10 -14
- package/dist/stats.d.ts +17 -17
- package/dist/stats.js +42 -49
- package/dist/utils.d.ts +2 -2
- package/license.md +2 -26
- package/package.json +2 -2
- package/readme.md +1 -1
- package/src/backends/backend.ts +1 -1
- package/src/backends/fetch.ts +1 -1
- package/src/backends/index/fs.ts +2 -1
- package/src/backends/index/index.ts +2 -1
- package/src/backends/overlay.ts +7 -4
- package/src/backends/port/fs.ts +14 -10
- package/src/config.ts +1 -1
- package/src/cred.ts +2 -1
- package/src/emulation/async.ts +8 -7
- package/src/emulation/index.ts +1 -1
- package/src/emulation/promises.ts +40 -54
- package/src/emulation/shared.ts +24 -3
- package/src/emulation/streams.ts +1 -1
- package/src/emulation/sync.ts +100 -87
- package/src/error.ts +1 -1
- package/src/file.ts +35 -88
- package/src/filesystem.ts +40 -32
- package/src/stats.ts +47 -59
- package/src/utils.ts +2 -2
package/dist/utils.d.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
import type { OptionalTuple } from 'utilium';
|
|
4
4
|
import { ErrnoError } from './error.js';
|
|
5
|
-
import { Cred } from './cred.js';
|
|
5
|
+
import type { Cred } from './cred.js';
|
|
6
6
|
import { type AbsolutePath } from './emulation/path.js';
|
|
7
|
-
import { FileSystem } from './filesystem.js';
|
|
7
|
+
import type { FileSystem } from './filesystem.js';
|
|
8
8
|
import type * as fs from 'node:fs';
|
|
9
9
|
declare global {
|
|
10
10
|
function atob(data: string): string;
|
package/license.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Copyright (c)
|
|
2
|
-
|
|
1
|
+
Copyright (c) James P. and other ZenFS contributors.
|
|
3
2
|
Copyright (c) 2013-2023 John Vilk and other BrowserFS contributors.
|
|
3
|
+
Copyright (c) Joyent, Inc. and other Node contributors for `test/fixtures/node`.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
6
|
this software and associated documentation files (the "Software"), to deal in
|
|
@@ -19,27 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
-
|
|
23
|
-
This license applies to all parts of ZenFS, except for the following items:
|
|
24
|
-
|
|
25
|
-
- The test fixtures located in `test/fixtures/node`. Their license follows:
|
|
26
|
-
"""
|
|
27
|
-
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
28
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
29
|
-
of this software and associated documentation files (the "Software"), to
|
|
30
|
-
deal in the Software without restriction, including without limitation the
|
|
31
|
-
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
32
|
-
sell copies of the Software, and to permit persons to whom the Software is
|
|
33
|
-
furnished to do so, subject to the following conditions:
|
|
34
|
-
|
|
35
|
-
The above copyright notice and this permission notice shall be included in
|
|
36
|
-
all copies or substantial portions of the Software.
|
|
37
|
-
|
|
38
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
39
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
40
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
41
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
42
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
43
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
44
|
-
IN THE SOFTWARE.
|
|
45
|
-
"""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "A filesystem in your browser",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"scripts": {
|
|
39
39
|
"format": "prettier --write .",
|
|
40
40
|
"format:check": "prettier --check .",
|
|
41
|
-
"lint": "
|
|
41
|
+
"lint": "tsc -p tsconfig.json --noEmit && eslint src tests",
|
|
42
42
|
"test": "npm run build && tsc -p tests/tsconfig.json --noEmit && cross-env NODE_OPTIONS=--experimental-vm-modules npx jest",
|
|
43
43
|
"build": "node scripts/build.js --globalName=ZenFS --entry src/index.ts",
|
|
44
44
|
"build:docs": "typedoc --out docs --name ZenFS src/index.ts",
|
package/readme.md
CHANGED
|
@@ -4,7 +4,7 @@ ZenFS is a file system that emulates the [NodeJS filesystem API](http://nodejs.o
|
|
|
4
4
|
|
|
5
5
|
It works using a system of backends, which are used by ZenFS to store and retrieve data. ZenFS can also integrate with other tools.
|
|
6
6
|
|
|
7
|
-
ZenFS is a fork of [BrowserFS](https://github.com/jvilk/BrowserFS). If you are using ZenFS in a research paper, you may want to [cite BrowserFS](https://github.com/jvilk/BrowserFS
|
|
7
|
+
ZenFS is a fork of [BrowserFS](https://github.com/jvilk/BrowserFS). If you are using ZenFS in a research paper, you may want to [cite BrowserFS](https://github.com/jvilk/BrowserFS#citing).
|
|
8
8
|
|
|
9
9
|
## Backends
|
|
10
10
|
|
package/src/backends/backend.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RequiredKeys } from 'utilium';
|
|
2
2
|
import { ErrnoError, Errno } from '../error.js';
|
|
3
|
-
import { FileSystem } from '../filesystem.js';
|
|
3
|
+
import type { FileSystem } from '../filesystem.js';
|
|
4
4
|
import { levenshtein } from '../utils.js';
|
|
5
5
|
|
|
6
6
|
type OptionType = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function';
|
package/src/backends/fetch.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Errno, ErrnoError } from '../error.js';
|
|
2
2
|
import type { FileSystemMetadata } from '../filesystem.js';
|
|
3
|
-
import { Stats } from '../stats.js';
|
|
3
|
+
import type { Stats } from '../stats.js';
|
|
4
4
|
import type { Backend } from './backend.js';
|
|
5
5
|
import { IndexFS } from './index/fs.js';
|
|
6
6
|
import type { IndexData } from './index/index.js';
|
package/src/backends/index/fs.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { NoSyncFile, isWriteable, flagToMode } from '../../file.js';
|
|
|
4
4
|
import { Readonly, FileSystem } from '../../filesystem.js';
|
|
5
5
|
import type { Stats } from '../../stats.js';
|
|
6
6
|
import { decode } from '../../utils.js';
|
|
7
|
-
import {
|
|
7
|
+
import type { IndexData } from './index.js';
|
|
8
|
+
import { Index } from './index.js';
|
|
8
9
|
|
|
9
10
|
export abstract class IndexFS extends Readonly(FileSystem) {
|
|
10
11
|
protected index: Index = new Index();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isJSON } from 'utilium';
|
|
2
2
|
import { Errno, ErrnoError } from '../../error.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { StatsLike } from '../../stats.js';
|
|
4
|
+
import { Stats } from '../../stats.js';
|
|
4
5
|
import { encode } from '../../utils.js';
|
|
5
6
|
import { basename, dirname } from '../../emulation/path.js';
|
|
6
7
|
|
package/src/backends/overlay.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FileSystemMetadata } from '../filesystem.js';
|
|
2
|
+
import { FileSystem } from '../filesystem.js';
|
|
2
3
|
import { ErrnoError, Errno } from '../error.js';
|
|
3
|
-
import { File
|
|
4
|
+
import type { File } from '../file.js';
|
|
5
|
+
import { PreloadFile, parseFlag } from '../file.js';
|
|
4
6
|
import { Stats } from '../stats.js';
|
|
5
7
|
import { LockedFS } from './locked.js';
|
|
6
8
|
import { dirname } from '../emulation/path.js';
|
|
7
|
-
import { Cred
|
|
9
|
+
import type { Cred } from '../cred.js';
|
|
10
|
+
import { rootCred } from '../cred.js';
|
|
8
11
|
import { decode, encode } from '../utils.js';
|
|
9
12
|
import type { Backend } from './backend.js';
|
|
10
13
|
/**
|
|
@@ -201,7 +204,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
201
204
|
}
|
|
202
205
|
// Create an OverlayFile.
|
|
203
206
|
const file = this._readable.openFileSync(path, parseFlag('r'), cred);
|
|
204
|
-
const stats = Stats
|
|
207
|
+
const stats = new Stats(file.statSync());
|
|
205
208
|
const data = new Uint8Array(stats.size);
|
|
206
209
|
file.readSync(data);
|
|
207
210
|
return new PreloadFile(this, path, flag, stats, data);
|
package/src/backends/port/fs.ts
CHANGED
|
@@ -38,12 +38,16 @@ export class PortFile extends File {
|
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
protected _throwNoSync(syscall: string): never {
|
|
42
|
+
throw new ErrnoError(Errno.ENOTSUP, 'Syncrohnous operations not support on PortFile', this.path, syscall);
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
public stat(): Promise<Stats> {
|
|
42
46
|
return this.rpc('stat');
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
public statSync(): Stats {
|
|
46
|
-
|
|
50
|
+
this._throwNoSync('stat');
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
public truncate(len: number): Promise<void> {
|
|
@@ -51,7 +55,7 @@ export class PortFile extends File {
|
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
public truncateSync(): void {
|
|
54
|
-
|
|
58
|
+
this._throwNoSync('truncate');
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
public write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number> {
|
|
@@ -59,7 +63,7 @@ export class PortFile extends File {
|
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
public writeSync(): number {
|
|
62
|
-
|
|
66
|
+
this._throwNoSync('write');
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
public async read<TBuffer extends NodeJS.ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<FileReadResult<TBuffer>> {
|
|
@@ -68,7 +72,7 @@ export class PortFile extends File {
|
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
public readSync(): number {
|
|
71
|
-
|
|
75
|
+
this._throwNoSync('read');
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
public chown(uid: number, gid: number): Promise<void> {
|
|
@@ -76,7 +80,7 @@ export class PortFile extends File {
|
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
public chownSync(): void {
|
|
79
|
-
|
|
83
|
+
this._throwNoSync('chown');
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
public chmod(mode: number): Promise<void> {
|
|
@@ -84,7 +88,7 @@ export class PortFile extends File {
|
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
public chmodSync(): void {
|
|
87
|
-
|
|
91
|
+
this._throwNoSync('chmod');
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
public utimes(atime: Date, mtime: Date): Promise<void> {
|
|
@@ -92,7 +96,7 @@ export class PortFile extends File {
|
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
public utimesSync(): void {
|
|
95
|
-
|
|
99
|
+
this._throwNoSync('utimes');
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
public _setType(type: FileType): Promise<void> {
|
|
@@ -100,7 +104,7 @@ export class PortFile extends File {
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
public _setTypeSync(): void {
|
|
103
|
-
|
|
107
|
+
this._throwNoSync('_setType');
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
public close(): Promise<void> {
|
|
@@ -108,7 +112,7 @@ export class PortFile extends File {
|
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
public closeSync(): void {
|
|
111
|
-
|
|
115
|
+
this._throwNoSync('close');
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
public sync(): Promise<void> {
|
|
@@ -116,7 +120,7 @@ export class PortFile extends File {
|
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
public syncSync(): void {
|
|
119
|
-
|
|
123
|
+
this._throwNoSync('sync');
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
|
package/src/config.ts
CHANGED
|
@@ -18,7 +18,7 @@ function isMountConfig<T extends Backend>(arg: unknown): arg is MountConfigurati
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Retrieve a file system with the given configuration.
|
|
21
|
-
* @
|
|
21
|
+
* @see MountConfiguration
|
|
22
22
|
*/
|
|
23
23
|
export async function resolveMountConfig<T extends Backend>(config: MountConfiguration<T>, _depth = 0): Promise<FilesystemOf<T>> {
|
|
24
24
|
if (typeof config !== 'object' || config == null) {
|
package/src/cred.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Credentials used for various operations.
|
|
3
|
-
* Similar to Linux's cred struct.
|
|
3
|
+
* Similar to Linux's cred struct.
|
|
4
|
+
* @see https://github.com/torvalds/linux/blob/master/include/linux/cred.h
|
|
4
5
|
*/
|
|
5
6
|
export interface Cred {
|
|
6
7
|
uid: number;
|
package/src/emulation/async.ts
CHANGED
|
@@ -2,10 +2,11 @@ import { Buffer } from 'buffer';
|
|
|
2
2
|
import type * as fs from 'node:fs';
|
|
3
3
|
import { ErrnoError, Errno } from '../error.js';
|
|
4
4
|
import type { FileContents } from '../filesystem.js';
|
|
5
|
-
import { BigIntStats, type
|
|
5
|
+
import { BigIntStats, type Stats } from '../stats.js';
|
|
6
6
|
import { nop, normalizeMode, type Callback } from '../utils.js';
|
|
7
7
|
import { R_OK } from './constants.js';
|
|
8
|
-
import { Dirent
|
|
8
|
+
import type { Dirent } from './dir.js';
|
|
9
|
+
import { type Dir } from './dir.js';
|
|
9
10
|
import * as promises from './promises.js';
|
|
10
11
|
import { fd2file } from './shared.js';
|
|
11
12
|
import { ReadStream, WriteStream } from './streams.js';
|
|
@@ -882,14 +883,14 @@ export function cp(source: fs.PathLike, destination: fs.PathLike, opts: fs.CopyO
|
|
|
882
883
|
}
|
|
883
884
|
cp satisfies Omit<typeof fs.cp, '__promisify__'>;
|
|
884
885
|
|
|
885
|
-
export function statfs(path: fs.PathLike, callback: Callback<[StatsFs]>): void;
|
|
886
|
-
export function statfs(path: fs.PathLike, options: fs.StatFsOptions & { bigint?: false }, callback: Callback<[StatsFs]>): void;
|
|
887
|
-
export function statfs(path: fs.PathLike, options: fs.StatFsOptions & { bigint: true }, callback: Callback<[BigIntStatsFs]>): void;
|
|
888
|
-
export function statfs(path: fs.PathLike, options?: fs.StatFsOptions | Callback<[StatsFs]>, callback: Callback<[StatsFs]> | Callback<[BigIntStatsFs]> = nop): void {
|
|
886
|
+
export function statfs(path: fs.PathLike, callback: Callback<[fs.StatsFs]>): void;
|
|
887
|
+
export function statfs(path: fs.PathLike, options: fs.StatFsOptions & { bigint?: false }, callback: Callback<[fs.StatsFs]>): void;
|
|
888
|
+
export function statfs(path: fs.PathLike, options: fs.StatFsOptions & { bigint: true }, callback: Callback<[fs.BigIntStatsFs]>): void;
|
|
889
|
+
export function statfs(path: fs.PathLike, options?: fs.StatFsOptions | Callback<[fs.StatsFs]>, callback: Callback<[fs.StatsFs]> | Callback<[fs.BigIntStatsFs]> = nop): void {
|
|
889
890
|
callback = typeof options === 'function' ? options : callback;
|
|
890
891
|
promises
|
|
891
892
|
.statfs(path, typeof options === 'function' ? undefined : options)
|
|
892
|
-
.then(result => (callback as Callback<[StatsFs | BigIntStatsFs]>)(undefined, result))
|
|
893
|
+
.then(result => (callback as Callback<[fs.StatsFs | fs.BigIntStatsFs]>)(undefined, result))
|
|
893
894
|
.catch(callback);
|
|
894
895
|
}
|
|
895
896
|
statfs satisfies Omit<typeof fs.statfs, '__promisify__'>;
|
package/src/emulation/index.ts
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';
|
|
@@ -6,15 +6,16 @@ import type { Stream } from 'node:stream';
|
|
|
6
6
|
import type { ReadableStream as TReadableStream } from 'node:stream/web';
|
|
7
7
|
import type { Interface as ReadlineInterface } from 'readline';
|
|
8
8
|
import type { ReadableStreamController } from 'stream/web';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { Errno, ErrnoError } from '../error.js';
|
|
10
|
+
import type { File } from '../file.js';
|
|
11
|
+
import { isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
|
|
11
12
|
import type { FileContents } from '../filesystem.js';
|
|
12
|
-
import { BigIntStats, FileType, type
|
|
13
|
+
import { BigIntStats, FileType, type Stats } from '../stats.js';
|
|
13
14
|
import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
14
15
|
import * as constants from './constants.js';
|
|
15
16
|
import { Dir, Dirent } from './dir.js';
|
|
16
17
|
import { dirname, join, parse } from './path.js';
|
|
17
|
-
import { cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
18
|
+
import { _statfs, cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
18
19
|
import { ReadStream, WriteStream } from './streams.js';
|
|
19
20
|
export * as constants from './constants.js';
|
|
20
21
|
|
|
@@ -110,7 +111,7 @@ export class FileHandle implements promises.FileHandle {
|
|
|
110
111
|
throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
|
|
111
112
|
}
|
|
112
113
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding!) : data;
|
|
113
|
-
await this.file.write(encodedData, 0, encodedData.length
|
|
114
|
+
await this.file.write(encodedData, 0, encodedData.length);
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
/**
|
|
@@ -491,53 +492,36 @@ async function _open(path: fs.PathLike, _flag: fs.OpenMode, _mode: fs.Mode = 0o6
|
|
|
491
492
|
path = resolveSymlinks && (await exists(path)) ? await realpath(path) : path;
|
|
492
493
|
const { fs, path: resolved } = resolveMount(path);
|
|
493
494
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
throw ErrnoError.With('EEXIST', path, '_open');
|
|
498
|
-
case ActionType.TRUNCATE:
|
|
499
|
-
/*
|
|
500
|
-
In a previous implementation, we deleted the file and
|
|
501
|
-
re-created it. However, this created a race condition if another
|
|
502
|
-
asynchronous request was trying to read the file, as the file
|
|
503
|
-
would not exist for a small period of time.
|
|
504
|
-
*/
|
|
505
|
-
const file: File = await fs.openFile(resolved, flag, cred);
|
|
506
|
-
await file.truncate(0);
|
|
507
|
-
await file.sync();
|
|
508
|
-
return new FileHandle(file);
|
|
509
|
-
case ActionType.NOP:
|
|
510
|
-
// Must await so thrown errors are caught by the catch below
|
|
511
|
-
return new FileHandle(await fs.openFile(resolved, flag, cred));
|
|
512
|
-
default:
|
|
513
|
-
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
|
|
495
|
+
if (!(await fs.exists(path, cred))) {
|
|
496
|
+
if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
|
|
497
|
+
throw ErrnoError.With('ENOENT', path, '_open');
|
|
514
498
|
}
|
|
515
|
-
|
|
516
|
-
const
|
|
517
|
-
if (
|
|
518
|
-
throw
|
|
519
|
-
}
|
|
520
|
-
try {
|
|
521
|
-
switch (pathNotExistsAction(flag)) {
|
|
522
|
-
case ActionType.CREATE:
|
|
523
|
-
// Ensure parent exists.
|
|
524
|
-
const parentStats: Stats = await fs.stat(dirname(resolved), cred);
|
|
525
|
-
if (parentStats && !parentStats.isDirectory()) {
|
|
526
|
-
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
|
|
527
|
-
}
|
|
528
|
-
return new FileHandle(await fs.createFile(resolved, flag, mode, cred));
|
|
529
|
-
case ActionType.THROW:
|
|
530
|
-
throw ErrnoError.With('ENOENT', path, '_open');
|
|
531
|
-
default:
|
|
532
|
-
throw new ErrnoError(Errno.EINVAL, 'Invalid file flag');
|
|
533
|
-
}
|
|
534
|
-
} catch (_) {
|
|
535
|
-
const ex = _ as ErrnoError;
|
|
536
|
-
ex.stack += '\n<original>\n';
|
|
537
|
-
ex.stack += (original as Error).stack;
|
|
538
|
-
throw ex;
|
|
499
|
+
// Create the file
|
|
500
|
+
const parentStats: Stats = await fs.stat(dirname(resolved), cred);
|
|
501
|
+
if (parentStats && !parentStats.isDirectory()) {
|
|
502
|
+
throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
|
|
539
503
|
}
|
|
504
|
+
return new FileHandle(await fs.createFile(resolved, flag, mode, cred));
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (isExclusive(flag)) {
|
|
508
|
+
throw ErrnoError.With('EEXIST', path, '_open');
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (!isTruncating(flag)) {
|
|
512
|
+
return new FileHandle(await fs.openFile(resolved, flag, cred));
|
|
540
513
|
}
|
|
514
|
+
|
|
515
|
+
/*
|
|
516
|
+
In a previous implementation, we deleted the file and
|
|
517
|
+
re-created it. However, this created a race condition if another
|
|
518
|
+
asynchronous request was trying to read the file, as the file
|
|
519
|
+
would not exist for a small period of time.
|
|
520
|
+
*/
|
|
521
|
+
const file: File = await fs.openFile(resolved, flag, cred);
|
|
522
|
+
await file.truncate(0);
|
|
523
|
+
await file.sync();
|
|
524
|
+
return new FileHandle(file);
|
|
541
525
|
}
|
|
542
526
|
|
|
543
527
|
/**
|
|
@@ -1072,9 +1056,11 @@ cp satisfies typeof promises.cp;
|
|
|
1072
1056
|
* @since v18.15.0
|
|
1073
1057
|
* @return Fulfills with an {fs.StatFs} for the file system.
|
|
1074
1058
|
*/
|
|
1075
|
-
export async function statfs(path: fs.PathLike, opts?: fs.StatFsOptions & { bigint?: false }): Promise<StatsFs>;
|
|
1076
|
-
export async function statfs(path: fs.PathLike, opts: fs.StatFsOptions & { bigint: true }): Promise<BigIntStatsFs>;
|
|
1077
|
-
export async function statfs(path: fs.PathLike, opts?: fs.StatFsOptions): Promise<StatsFs | BigIntStatsFs>;
|
|
1078
|
-
export async function statfs(path: fs.PathLike, opts?: fs.StatFsOptions): Promise<StatsFs | BigIntStatsFs> {
|
|
1079
|
-
|
|
1059
|
+
export async function statfs(path: fs.PathLike, opts?: fs.StatFsOptions & { bigint?: false }): Promise<fs.StatsFs>;
|
|
1060
|
+
export async function statfs(path: fs.PathLike, opts: fs.StatFsOptions & { bigint: true }): Promise<fs.BigIntStatsFs>;
|
|
1061
|
+
export async function statfs(path: fs.PathLike, opts?: fs.StatFsOptions): Promise<fs.StatsFs | fs.BigIntStatsFs>;
|
|
1062
|
+
export async function statfs(path: fs.PathLike, opts?: fs.StatFsOptions): Promise<fs.StatsFs | fs.BigIntStatsFs> {
|
|
1063
|
+
path = normalizePath(path);
|
|
1064
|
+
const { fs } = resolveMount(path);
|
|
1065
|
+
return _statfs(fs, opts?.bigint);
|
|
1080
1066
|
}
|
package/src/emulation/shared.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// Utilities and shared data
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import type { BigIntStatsFs, StatsFs } from 'node:fs';
|
|
4
4
|
import { InMemory } from '../backends/memory.js';
|
|
5
|
-
import { Cred
|
|
5
|
+
import type { Cred } from '../cred.js';
|
|
6
|
+
import { rootCred } from '../cred.js';
|
|
7
|
+
import { Errno, ErrnoError } from '../error.js';
|
|
6
8
|
import type { File } from '../file.js';
|
|
7
|
-
import { FileSystem } from '../filesystem.js';
|
|
9
|
+
import type { FileSystem } from '../filesystem.js';
|
|
10
|
+
import { size_max } from '../inode.js';
|
|
8
11
|
import { normalizePath } from '../utils.js';
|
|
9
12
|
import { resolve, type AbsolutePath } from './path.js';
|
|
10
13
|
|
|
@@ -117,3 +120,21 @@ export function mountObject(mounts: MountObject): void {
|
|
|
117
120
|
mount(point, fs);
|
|
118
121
|
}
|
|
119
122
|
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @hidden
|
|
126
|
+
*/
|
|
127
|
+
export function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? BigIntStatsFs : StatsFs {
|
|
128
|
+
const md = fs.metadata();
|
|
129
|
+
const bs = md.blockSize || 4096;
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
type: (bigint ? BigInt : Number)(md.type),
|
|
133
|
+
bsize: (bigint ? BigInt : Number)(bs),
|
|
134
|
+
ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),
|
|
135
|
+
files: (bigint ? BigInt : Number)(md.totalNodes || size_max),
|
|
136
|
+
bavail: (bigint ? BigInt : Number)(md.freeSpace / bs),
|
|
137
|
+
bfree: (bigint ? BigInt : Number)(md.freeSpace / bs),
|
|
138
|
+
blocks: (bigint ? BigInt : Number)(md.totalSpace / bs),
|
|
139
|
+
} as T extends true ? BigIntStatsFs : StatsFs;
|
|
140
|
+
}
|
package/src/emulation/streams.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as Node from 'fs';
|
|
2
2
|
import { Readable, Writable } from 'readable-stream';
|
|
3
|
-
import { Callback } from '../utils.js';
|
|
3
|
+
import type { Callback } from '../utils.js';
|
|
4
4
|
import { ErrnoError, Errno } from '../error.js';
|
|
5
5
|
|
|
6
6
|
export class ReadStream extends Readable implements Node.ReadStream {
|