@zenfs/core 1.11.3 → 2.0.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/backend.d.ts +19 -15
- package/dist/backends/backend.js +31 -15
- package/dist/backends/cow.d.ts +20 -30
- package/dist/backends/cow.js +52 -142
- package/dist/backends/fetch.d.ts +1 -0
- package/dist/backends/fetch.js +3 -1
- package/dist/backends/index.d.ts +1 -1
- package/dist/backends/index.js +1 -1
- package/dist/backends/memory.d.ts +5 -7
- package/dist/backends/memory.js +2 -3
- package/dist/backends/passthrough.d.ts +19 -22
- package/dist/backends/passthrough.js +85 -160
- package/dist/backends/port.d.ts +207 -0
- package/dist/backends/port.js +297 -0
- package/dist/backends/single_buffer.d.ts +11 -5
- package/dist/backends/single_buffer.js +18 -12
- package/dist/backends/store/fs.d.ts +11 -27
- package/dist/backends/store/fs.js +67 -91
- package/dist/backends/store/store.d.ts +7 -12
- package/dist/config.d.ts +1 -10
- package/dist/config.js +7 -8
- package/dist/context.d.ts +8 -21
- package/dist/context.js +33 -10
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/contexts.d.ts +63 -0
- package/dist/internal/contexts.js +15 -0
- package/dist/internal/credentials.d.ts +2 -11
- package/dist/internal/credentials.js +0 -19
- package/dist/internal/devices.d.ts +18 -80
- package/dist/internal/devices.js +76 -279
- package/dist/internal/file_index.js +3 -3
- package/dist/internal/filesystem.d.ts +31 -89
- package/dist/internal/filesystem.js +21 -20
- package/dist/internal/index.d.ts +0 -1
- package/dist/internal/index.js +0 -1
- package/dist/internal/index_fs.d.ts +12 -30
- package/dist/internal/index_fs.js +23 -55
- package/dist/internal/inode.d.ts +147 -9
- package/dist/internal/inode.js +333 -25
- package/dist/internal/log.d.ts +19 -13
- package/dist/internal/log.js +81 -80
- package/dist/mixins/async.js +26 -90
- package/dist/mixins/mutexed.d.ts +17 -16
- package/dist/mixins/mutexed.js +29 -31
- package/dist/mixins/readonly.d.ts +7 -6
- package/dist/mixins/readonly.js +6 -0
- package/dist/mixins/sync.js +8 -8
- package/dist/{vfs/path.d.ts → path.d.ts} +3 -4
- package/dist/{vfs/path.js → path.js} +6 -9
- package/dist/readline.d.ts +134 -0
- package/dist/readline.js +623 -0
- package/dist/utils.d.ts +4 -35
- package/dist/utils.js +8 -73
- package/dist/vfs/acl.d.ts +42 -0
- package/dist/vfs/acl.js +249 -0
- package/dist/vfs/async.d.ts +7 -21
- package/dist/vfs/async.js +19 -19
- package/dist/vfs/config.d.ts +6 -18
- package/dist/vfs/config.js +8 -18
- package/dist/vfs/dir.d.ts +3 -3
- package/dist/vfs/dir.js +9 -8
- package/dist/vfs/file.d.ts +106 -0
- package/dist/vfs/file.js +235 -0
- package/dist/vfs/flags.d.ts +19 -0
- package/dist/vfs/flags.js +62 -0
- package/dist/vfs/index.d.ts +4 -10
- package/dist/vfs/index.js +4 -13
- package/dist/vfs/ioctl.d.ts +87 -0
- package/dist/vfs/ioctl.js +304 -0
- package/dist/vfs/promises.d.ts +78 -16
- package/dist/vfs/promises.js +273 -122
- package/dist/vfs/shared.d.ts +7 -26
- package/dist/vfs/shared.js +25 -53
- package/dist/{stats.d.ts → vfs/stats.d.ts} +14 -28
- package/dist/{stats.js → vfs/stats.js} +11 -66
- package/dist/vfs/streams.d.ts +1 -0
- package/dist/vfs/streams.js +24 -19
- package/dist/vfs/sync.d.ts +4 -3
- package/dist/vfs/sync.js +143 -128
- package/dist/vfs/watchers.d.ts +2 -2
- package/dist/vfs/watchers.js +6 -6
- package/dist/vfs/xattr.d.ts +116 -0
- package/dist/vfs/xattr.js +218 -0
- package/package.json +3 -3
- package/readme.md +1 -1
- package/tests/backend/config.worker.js +4 -1
- package/tests/backend/fetch.test.ts +3 -0
- package/tests/backend/port.test.ts +21 -35
- package/tests/backend/remote.worker.js +4 -1
- package/tests/backend/single-buffer.test.ts +24 -0
- package/tests/common/context.test.ts +1 -1
- package/tests/common/handle.test.ts +17 -12
- package/tests/common/path.test.ts +1 -1
- package/tests/common/readline.test.ts +104 -0
- package/tests/common.ts +4 -19
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fs/links.test.ts +1 -1
- package/tests/fs/permissions.test.ts +7 -6
- package/tests/fs/readFile.test.ts +3 -3
- package/tests/fs/stat.test.ts +6 -6
- package/tests/fs/streams.test.ts +2 -11
- package/tests/fs/times.test.ts +1 -1
- package/tests/fs/xattr.test.ts +85 -0
- package/tests/logs.js +22 -0
- package/tests/setup/context.ts +1 -1
- package/tests/setup/index.ts +3 -3
- package/tests/setup/port.ts +1 -1
- package/dist/backends/port/fs.d.ts +0 -84
- package/dist/backends/port/fs.js +0 -151
- package/dist/backends/port/rpc.d.ts +0 -77
- package/dist/backends/port/rpc.js +0 -100
- package/dist/backends/store/simple.d.ts +0 -20
- package/dist/backends/store/simple.js +0 -13
- package/dist/internal/file.d.ts +0 -351
- package/dist/internal/file.js +0 -739
package/dist/vfs/dir.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { isBlockDevice, isCharacterDevice, isDirectory, isFIFO, isFile, isSocket, isSymbolicLink } from '../internal/inode.js';
|
|
1
2
|
import { Errno, ErrnoError } from '../internal/error.js';
|
|
2
|
-
import { basename } from '
|
|
3
|
+
import { basename } from '../path.js';
|
|
3
4
|
import { readdir } from './promises.js';
|
|
4
5
|
import { readdirSync } from './sync.js';
|
|
5
6
|
export class Dirent {
|
|
@@ -14,25 +15,25 @@ export class Dirent {
|
|
|
14
15
|
return this.path;
|
|
15
16
|
}
|
|
16
17
|
isFile() {
|
|
17
|
-
return this.stats
|
|
18
|
+
return isFile(this.stats);
|
|
18
19
|
}
|
|
19
20
|
isDirectory() {
|
|
20
|
-
return this.stats
|
|
21
|
+
return isDirectory(this.stats);
|
|
21
22
|
}
|
|
22
23
|
isBlockDevice() {
|
|
23
|
-
return this.stats
|
|
24
|
+
return isBlockDevice(this.stats);
|
|
24
25
|
}
|
|
25
26
|
isCharacterDevice() {
|
|
26
|
-
return this.stats
|
|
27
|
+
return isCharacterDevice(this.stats);
|
|
27
28
|
}
|
|
28
29
|
isSymbolicLink() {
|
|
29
|
-
return this.stats
|
|
30
|
+
return isSymbolicLink(this.stats);
|
|
30
31
|
}
|
|
31
32
|
isFIFO() {
|
|
32
|
-
return this.stats
|
|
33
|
+
return isFIFO(this.stats);
|
|
33
34
|
}
|
|
34
35
|
isSocket() {
|
|
35
|
-
return this.stats
|
|
36
|
+
return isSocket(this.stats);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
/**
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { V_Context } from '../context.js';
|
|
2
|
+
import type { FileSystem, StreamOptions } from '../internal/filesystem.js';
|
|
3
|
+
import { type InodeLike } from '../internal/inode.js';
|
|
4
|
+
import '../polyfills.js';
|
|
5
|
+
/** @hidden */
|
|
6
|
+
export interface FileReadResult<T extends ArrayBufferView> {
|
|
7
|
+
bytesRead: number;
|
|
8
|
+
buffer: T;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare class SyncHandle {
|
|
14
|
+
readonly context: V_Context;
|
|
15
|
+
readonly path: string;
|
|
16
|
+
readonly fs: FileSystem;
|
|
17
|
+
readonly internalPath: string;
|
|
18
|
+
readonly flag: number;
|
|
19
|
+
readonly inode: InodeLike;
|
|
20
|
+
protected _buffer?: Uint8Array;
|
|
21
|
+
/**
|
|
22
|
+
* Current position
|
|
23
|
+
*/
|
|
24
|
+
protected _position: number;
|
|
25
|
+
/**
|
|
26
|
+
* Get the current file position.
|
|
27
|
+
*
|
|
28
|
+
* We emulate the following bug mentioned in the Node documentation:
|
|
29
|
+
*
|
|
30
|
+
* On Linux, positional writes don't work when the file is opened in append mode.
|
|
31
|
+
* The kernel ignores the position argument and always appends the data to the end of the file.
|
|
32
|
+
* @returns The current file position.
|
|
33
|
+
*/
|
|
34
|
+
get position(): number;
|
|
35
|
+
set position(value: number);
|
|
36
|
+
/**
|
|
37
|
+
* Whether the file has changes which have not been written to the FS
|
|
38
|
+
*/
|
|
39
|
+
protected dirty: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the file is open or closed
|
|
42
|
+
*/
|
|
43
|
+
protected closed: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a file with `path` and, optionally, the given contents.
|
|
46
|
+
* Note that, if contents is specified, it will be mutated by the file.
|
|
47
|
+
*/
|
|
48
|
+
constructor(context: V_Context, path: string, fs: FileSystem, internalPath: string, flag: number, inode: InodeLike);
|
|
49
|
+
[Symbol.dispose](): void;
|
|
50
|
+
private get _isSync();
|
|
51
|
+
sync(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Default implementation maps to `syncSync`.
|
|
54
|
+
*/
|
|
55
|
+
datasync(): void;
|
|
56
|
+
close(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Cleans up. This will *not* sync the file data to the FS
|
|
59
|
+
*/
|
|
60
|
+
protected dispose(force?: boolean): void;
|
|
61
|
+
stat(): InodeLike;
|
|
62
|
+
truncate(length: number): void;
|
|
63
|
+
/**
|
|
64
|
+
* Write buffer to the file.
|
|
65
|
+
* @param buffer Uint8Array containing the data to write to the file.
|
|
66
|
+
* @param offset Offset in the buffer to start reading data from.
|
|
67
|
+
* @param length The amount of bytes to write to the file.
|
|
68
|
+
* @param position Offset from the beginning of the file where this data should be written.
|
|
69
|
+
* If position is null, the data will be written at the current position.
|
|
70
|
+
* @returns bytes written
|
|
71
|
+
*/
|
|
72
|
+
write(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
|
|
73
|
+
/**
|
|
74
|
+
* Read data from the file.
|
|
75
|
+
* @param buffer The buffer that the data will be written to.
|
|
76
|
+
* @param offset The offset within the buffer where writing will start.
|
|
77
|
+
* @param length An integer specifying the number of bytes to read.
|
|
78
|
+
* @param position An integer specifying where to begin reading from in the file.
|
|
79
|
+
* If position is null, data will be read from the current file position.
|
|
80
|
+
* @returns number of bytes written
|
|
81
|
+
*/
|
|
82
|
+
read(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
|
|
83
|
+
chmod(mode: number): void;
|
|
84
|
+
chown(uid: number, gid: number): void;
|
|
85
|
+
/**
|
|
86
|
+
* Change the file timestamps of the file.
|
|
87
|
+
*/
|
|
88
|
+
utimes(atime: number, mtime: number): void;
|
|
89
|
+
/**
|
|
90
|
+
* Create a stream for reading the file.
|
|
91
|
+
*/
|
|
92
|
+
streamRead(options: StreamOptions): ReadableStream;
|
|
93
|
+
/**
|
|
94
|
+
* Create a stream for writing the file.
|
|
95
|
+
*/
|
|
96
|
+
streamWrite(options: StreamOptions): WritableStream;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* @internal @hidden
|
|
100
|
+
*/
|
|
101
|
+
export declare function toFD(file: SyncHandle): number;
|
|
102
|
+
/**
|
|
103
|
+
* @internal @hidden
|
|
104
|
+
*/
|
|
105
|
+
export declare function fromFD($: V_Context, fd: number): SyncHandle;
|
|
106
|
+
export declare function deleteFD($: V_Context, fd: number): boolean;
|
package/dist/vfs/file.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { defaultContext } from '../internal/contexts.js';
|
|
2
|
+
import { Errno, ErrnoError } from '../internal/error.js';
|
|
3
|
+
import { InodeFlags, isBlockDevice, isCharacterDevice } from '../internal/inode.js';
|
|
4
|
+
import '../polyfills.js';
|
|
5
|
+
import * as c from './constants.js';
|
|
6
|
+
import { _chown } from './stats.js';
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export class SyncHandle {
|
|
11
|
+
/**
|
|
12
|
+
* Get the current file position.
|
|
13
|
+
*
|
|
14
|
+
* We emulate the following bug mentioned in the Node documentation:
|
|
15
|
+
*
|
|
16
|
+
* On Linux, positional writes don't work when the file is opened in append mode.
|
|
17
|
+
* The kernel ignores the position argument and always appends the data to the end of the file.
|
|
18
|
+
* @returns The current file position.
|
|
19
|
+
*/
|
|
20
|
+
get position() {
|
|
21
|
+
return this.flag & c.O_APPEND ? this.inode.size : this._position;
|
|
22
|
+
}
|
|
23
|
+
set position(value) {
|
|
24
|
+
this._position = value;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates a file with `path` and, optionally, the given contents.
|
|
28
|
+
* Note that, if contents is specified, it will be mutated by the file.
|
|
29
|
+
*/
|
|
30
|
+
constructor(context, path, fs, internalPath, flag, inode) {
|
|
31
|
+
this.context = context;
|
|
32
|
+
this.path = path;
|
|
33
|
+
this.fs = fs;
|
|
34
|
+
this.internalPath = internalPath;
|
|
35
|
+
this.flag = flag;
|
|
36
|
+
this.inode = inode;
|
|
37
|
+
/**
|
|
38
|
+
* Current position
|
|
39
|
+
*/
|
|
40
|
+
this._position = 0;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the file has changes which have not been written to the FS
|
|
43
|
+
*/
|
|
44
|
+
this.dirty = false;
|
|
45
|
+
/**
|
|
46
|
+
* Whether the file is open or closed
|
|
47
|
+
*/
|
|
48
|
+
this.closed = false;
|
|
49
|
+
}
|
|
50
|
+
[Symbol.dispose]() {
|
|
51
|
+
this.close();
|
|
52
|
+
}
|
|
53
|
+
get _isSync() {
|
|
54
|
+
return !!(this.flag & c.O_SYNC || this.inode.flags & InodeFlags.Sync);
|
|
55
|
+
}
|
|
56
|
+
sync() {
|
|
57
|
+
if (this.closed)
|
|
58
|
+
throw ErrnoError.With('EBADF', this.path, 'sync');
|
|
59
|
+
if (!this.dirty)
|
|
60
|
+
return;
|
|
61
|
+
if (!this.fs.attributes.has('no_write'))
|
|
62
|
+
this.fs.touchSync(this.internalPath, this.inode);
|
|
63
|
+
this.dirty = false;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Default implementation maps to `syncSync`.
|
|
67
|
+
*/
|
|
68
|
+
datasync() {
|
|
69
|
+
return this.sync();
|
|
70
|
+
}
|
|
71
|
+
close() {
|
|
72
|
+
if (this.closed)
|
|
73
|
+
throw ErrnoError.With('EBADF', this.path, 'close');
|
|
74
|
+
this.sync();
|
|
75
|
+
this.dispose();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Cleans up. This will *not* sync the file data to the FS
|
|
79
|
+
*/
|
|
80
|
+
dispose(force) {
|
|
81
|
+
if (this.closed)
|
|
82
|
+
throw ErrnoError.With('EBADF', this.path, 'dispose');
|
|
83
|
+
if (this.dirty && !force)
|
|
84
|
+
throw ErrnoError.With('EBUSY', this.path, 'dispose');
|
|
85
|
+
this.closed = true;
|
|
86
|
+
}
|
|
87
|
+
stat() {
|
|
88
|
+
if (this.closed)
|
|
89
|
+
throw ErrnoError.With('EBADF', this.path, 'stat');
|
|
90
|
+
return this.inode;
|
|
91
|
+
}
|
|
92
|
+
truncate(length) {
|
|
93
|
+
if (this.closed)
|
|
94
|
+
throw ErrnoError.With('EBADF', this.path, 'truncate');
|
|
95
|
+
this.dirty = true;
|
|
96
|
+
if (!(this.flag & c.O_WRONLY || this.flag & c.O_RDWR)) {
|
|
97
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode', this.path, 'truncate');
|
|
98
|
+
}
|
|
99
|
+
this.inode.mtimeMs = Date.now();
|
|
100
|
+
this.inode.size = length;
|
|
101
|
+
this.inode.ctimeMs = Date.now();
|
|
102
|
+
if (this._isSync)
|
|
103
|
+
this.sync();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Write buffer to the file.
|
|
107
|
+
* @param buffer Uint8Array containing the data to write to the file.
|
|
108
|
+
* @param offset Offset in the buffer to start reading data from.
|
|
109
|
+
* @param length The amount of bytes to write to the file.
|
|
110
|
+
* @param position Offset from the beginning of the file where this data should be written.
|
|
111
|
+
* If position is null, the data will be written at the current position.
|
|
112
|
+
* @returns bytes written
|
|
113
|
+
*/
|
|
114
|
+
write(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
115
|
+
if (this.closed)
|
|
116
|
+
throw ErrnoError.With('EBADF', this.path, 'write');
|
|
117
|
+
if (!(this.flag & c.O_WRONLY || this.flag & c.O_RDWR))
|
|
118
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode');
|
|
119
|
+
if (this.inode.flags & InodeFlags.Immutable)
|
|
120
|
+
throw new ErrnoError(Errno.EPERM, 'File is immutable', this.path, 'write');
|
|
121
|
+
this.dirty = true;
|
|
122
|
+
const end = position + length;
|
|
123
|
+
const slice = buffer.subarray(offset, offset + length);
|
|
124
|
+
if (!isCharacterDevice(this.inode) && !isBlockDevice(this.inode) && end > this.inode.size)
|
|
125
|
+
this.inode.size = end;
|
|
126
|
+
this.inode.mtimeMs = Date.now();
|
|
127
|
+
this.inode.ctimeMs = Date.now();
|
|
128
|
+
this._position = position + slice.byteLength;
|
|
129
|
+
this.fs.writeSync(this.internalPath, slice, position);
|
|
130
|
+
if (this._isSync)
|
|
131
|
+
this.sync();
|
|
132
|
+
return slice.byteLength;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Read data from the file.
|
|
136
|
+
* @param buffer The buffer that the data will be written to.
|
|
137
|
+
* @param offset The offset within the buffer where writing will start.
|
|
138
|
+
* @param length An integer specifying the number of bytes to read.
|
|
139
|
+
* @param position An integer specifying where to begin reading from in the file.
|
|
140
|
+
* If position is null, data will be read from the current file position.
|
|
141
|
+
* @returns number of bytes written
|
|
142
|
+
*/
|
|
143
|
+
read(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
144
|
+
if (this.closed)
|
|
145
|
+
throw ErrnoError.With('EBADF', this.path, 'read');
|
|
146
|
+
if (this.flag & c.O_WRONLY)
|
|
147
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode');
|
|
148
|
+
if (!(this.inode.flags & InodeFlags.NoAtime)) {
|
|
149
|
+
this.dirty = true;
|
|
150
|
+
this.inode.atimeMs = Date.now();
|
|
151
|
+
}
|
|
152
|
+
let end = position + length;
|
|
153
|
+
if (!isCharacterDevice(this.inode) && !isBlockDevice(this.inode) && end > this.inode.size) {
|
|
154
|
+
end = position + Math.max(this.inode.size - position, 0);
|
|
155
|
+
}
|
|
156
|
+
this._position = end;
|
|
157
|
+
const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
158
|
+
this.fs.readSync(this.internalPath, uint8.subarray(offset, offset + length), position, end);
|
|
159
|
+
if (this._isSync)
|
|
160
|
+
this.sync();
|
|
161
|
+
return end - position;
|
|
162
|
+
}
|
|
163
|
+
chmod(mode) {
|
|
164
|
+
if (this.closed)
|
|
165
|
+
throw ErrnoError.With('EBADF', this.path, 'chmod');
|
|
166
|
+
this.dirty = true;
|
|
167
|
+
this.inode.mode = (this.inode.mode & (mode > c.S_IFMT ? ~c.S_IFMT : c.S_IFMT)) | mode;
|
|
168
|
+
if (this._isSync || mode > c.S_IFMT)
|
|
169
|
+
this.sync();
|
|
170
|
+
}
|
|
171
|
+
chown(uid, gid) {
|
|
172
|
+
if (this.closed)
|
|
173
|
+
throw ErrnoError.With('EBADF', this.path, 'chown');
|
|
174
|
+
this.dirty = true;
|
|
175
|
+
_chown(this.inode, uid, gid);
|
|
176
|
+
if (this._isSync)
|
|
177
|
+
this.sync();
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Change the file timestamps of the file.
|
|
181
|
+
*/
|
|
182
|
+
utimes(atime, mtime) {
|
|
183
|
+
if (this.closed)
|
|
184
|
+
throw ErrnoError.With('EBADF', this.path, 'utimes');
|
|
185
|
+
this.dirty = true;
|
|
186
|
+
this.inode.atimeMs = atime;
|
|
187
|
+
this.inode.mtimeMs = mtime;
|
|
188
|
+
if (this._isSync)
|
|
189
|
+
this.sync();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Create a stream for reading the file.
|
|
193
|
+
*/
|
|
194
|
+
streamRead(options) {
|
|
195
|
+
if (this.closed)
|
|
196
|
+
throw ErrnoError.With('EBADF', this.path, 'streamRead');
|
|
197
|
+
return this.fs.streamRead(this.internalPath, options);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Create a stream for writing the file.
|
|
201
|
+
*/
|
|
202
|
+
streamWrite(options) {
|
|
203
|
+
if (this.closed)
|
|
204
|
+
throw ErrnoError.With('EBADF', this.path, 'streamWrite');
|
|
205
|
+
if (this.inode.flags & InodeFlags.Immutable)
|
|
206
|
+
throw new ErrnoError(Errno.EPERM, 'File is immutable', this.path, 'streamWrite');
|
|
207
|
+
return this.fs.streamWrite(this.internalPath, options);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// descriptors
|
|
211
|
+
/**
|
|
212
|
+
* @internal @hidden
|
|
213
|
+
*/
|
|
214
|
+
export function toFD(file) {
|
|
215
|
+
var _a, _b;
|
|
216
|
+
const map = (_b = (_a = file.context) === null || _a === void 0 ? void 0 : _a.descriptors) !== null && _b !== void 0 ? _b : defaultContext.descriptors;
|
|
217
|
+
const fd = Math.max(map.size ? Math.max(...map.keys()) + 1 : 0, 4);
|
|
218
|
+
map.set(fd, file);
|
|
219
|
+
return fd;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* @internal @hidden
|
|
223
|
+
*/
|
|
224
|
+
export function fromFD($, fd) {
|
|
225
|
+
var _a;
|
|
226
|
+
const map = (_a = $ === null || $ === void 0 ? void 0 : $.descriptors) !== null && _a !== void 0 ? _a : defaultContext.descriptors;
|
|
227
|
+
const value = map.get(fd);
|
|
228
|
+
if (!value)
|
|
229
|
+
throw new ErrnoError(Errno.EBADF);
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
232
|
+
export function deleteFD($, fd) {
|
|
233
|
+
var _a;
|
|
234
|
+
return ((_a = $ === null || $ === void 0 ? void 0 : $.descriptors) !== null && _a !== void 0 ? _a : defaultContext.descriptors).delete(fd);
|
|
235
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const pattern: RegExp;
|
|
2
|
+
/**
|
|
3
|
+
* @internal @hidden
|
|
4
|
+
*/
|
|
5
|
+
export declare function parse(flag: string | number): number;
|
|
6
|
+
/**
|
|
7
|
+
* @internal @hidden
|
|
8
|
+
*/
|
|
9
|
+
export declare function toString(flag: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* @internal @hidden
|
|
12
|
+
*/
|
|
13
|
+
export declare function toNumber(flag: string): number;
|
|
14
|
+
/**
|
|
15
|
+
* Parses a flag as a mode (W_OK, R_OK, and/or X_OK)
|
|
16
|
+
* @param flag the flag to parse
|
|
17
|
+
* @internal @hidden
|
|
18
|
+
*/
|
|
19
|
+
export declare function toMode(flag: number): number;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Errno, ErrnoError } from '../internal/error.js';
|
|
2
|
+
import * as c from './constants.js';
|
|
3
|
+
export const pattern = /[rwasx]{1,2}\+?/;
|
|
4
|
+
/**
|
|
5
|
+
* @internal @hidden
|
|
6
|
+
*/
|
|
7
|
+
export function parse(flag) {
|
|
8
|
+
if (typeof flag == 'number')
|
|
9
|
+
return flag;
|
|
10
|
+
if (!pattern.test(flag)) {
|
|
11
|
+
throw new ErrnoError(Errno.EINVAL, 'Invalid flag string: ' + flag);
|
|
12
|
+
}
|
|
13
|
+
return toNumber(flag);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @internal @hidden
|
|
17
|
+
*/
|
|
18
|
+
export function toString(flag) {
|
|
19
|
+
let string = flag & c.O_RDONLY ? 'r' : flag & c.O_APPEND ? 'a' : flag & c.O_TRUNC ? 'w' : '';
|
|
20
|
+
if (flag & c.O_SYNC)
|
|
21
|
+
string += 's';
|
|
22
|
+
if (flag & c.O_EXCL)
|
|
23
|
+
string += 'x';
|
|
24
|
+
if (flag & c.O_RDWR)
|
|
25
|
+
string += '+';
|
|
26
|
+
return string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @internal @hidden
|
|
30
|
+
*/
|
|
31
|
+
export function toNumber(flag) {
|
|
32
|
+
if (!flag.includes('r') && !flag.includes('w') && !flag.includes('a')) {
|
|
33
|
+
throw new ErrnoError(Errno.EINVAL, 'Invalid flag string: ' + flag);
|
|
34
|
+
}
|
|
35
|
+
let n = flag.includes('r') ? c.O_RDONLY : c.O_CREAT;
|
|
36
|
+
if (flag.includes('w'))
|
|
37
|
+
n |= c.O_TRUNC;
|
|
38
|
+
if (flag.includes('a'))
|
|
39
|
+
n |= c.O_APPEND;
|
|
40
|
+
if (flag.includes('+'))
|
|
41
|
+
n |= c.O_RDWR;
|
|
42
|
+
else if (!flag.includes('r'))
|
|
43
|
+
n |= c.O_WRONLY;
|
|
44
|
+
if (flag.includes('s'))
|
|
45
|
+
n |= c.O_SYNC;
|
|
46
|
+
if (flag.includes('x'))
|
|
47
|
+
n |= c.O_EXCL;
|
|
48
|
+
return n;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parses a flag as a mode (W_OK, R_OK, and/or X_OK)
|
|
52
|
+
* @param flag the flag to parse
|
|
53
|
+
* @internal @hidden
|
|
54
|
+
*/
|
|
55
|
+
export function toMode(flag) {
|
|
56
|
+
let mode = 0;
|
|
57
|
+
if (!(flag & c.O_WRONLY))
|
|
58
|
+
mode |= c.R_OK;
|
|
59
|
+
if (flag & c.O_WRONLY || flag & c.O_RDWR)
|
|
60
|
+
mode |= c.W_OK;
|
|
61
|
+
return mode;
|
|
62
|
+
}
|
package/dist/vfs/index.d.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
export { BigIntStatsFs, Stats, StatsFs } from '../stats.js';
|
|
2
1
|
export * from './async.js';
|
|
3
2
|
export * as constants from './constants.js';
|
|
4
3
|
export * from './dir.js';
|
|
4
|
+
export * from './ioctl.js';
|
|
5
5
|
export * as promises from './promises.js';
|
|
6
|
-
export { chroot, mount,
|
|
7
|
-
|
|
8
|
-
* The map of mount points.
|
|
9
|
-
* Using `fs.mounts` instead of the `mounts` export is a security issue and not recommended.
|
|
10
|
-
* The deprecation here propagates to the correct `mounts` export for some reason.
|
|
11
|
-
* @todo [BREAKING] remove `fs.mounts` for security.
|
|
12
|
-
* @deprecated Use the `mounts` export that isn't an `fs` property!
|
|
13
|
-
*/
|
|
14
|
-
mounts, umount, } from './shared.js';
|
|
6
|
+
export { chroot, mount, umount } from './shared.js';
|
|
7
|
+
export { BigIntStatsFs, Stats, StatsFs } from './stats.js';
|
|
15
8
|
export * from './streams.js';
|
|
16
9
|
export * from './sync.js';
|
|
10
|
+
export * as xattr from './xattr.js';
|
package/dist/vfs/index.js
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
export { BigIntStatsFs, Stats, StatsFs } from '../stats.js';
|
|
2
1
|
export * from './async.js';
|
|
3
2
|
export * as constants from './constants.js';
|
|
4
3
|
export * from './dir.js';
|
|
4
|
+
export * from './ioctl.js';
|
|
5
5
|
export * as promises from './promises.js';
|
|
6
|
-
export { chroot, mount,
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The map of mount points.
|
|
10
|
-
* Using `fs.mounts` instead of the `mounts` export is a security issue and not recommended.
|
|
11
|
-
* The deprecation here propagates to the correct `mounts` export for some reason.
|
|
12
|
-
* @todo [BREAKING] remove `fs.mounts` for security.
|
|
13
|
-
* @deprecated Use the `mounts` export that isn't an `fs` property!
|
|
14
|
-
*/
|
|
15
|
-
mounts,
|
|
16
|
-
/* node:coverage enable */
|
|
17
|
-
umount, } from './shared.js';
|
|
6
|
+
export { chroot, mount, umount } from './shared.js';
|
|
7
|
+
export { BigIntStatsFs, Stats, StatsFs } from './stats.js';
|
|
18
8
|
export * from './streams.js';
|
|
19
9
|
export * from './sync.js';
|
|
10
|
+
export * as xattr from './xattr.js';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { V_Context } from '../context.js';
|
|
2
|
+
import { Inode } from '../internal/inode.js';
|
|
3
|
+
declare class fsxattr {
|
|
4
|
+
/** xflags field value */
|
|
5
|
+
xflags: number;
|
|
6
|
+
/** extsize field value */
|
|
7
|
+
extsize: number;
|
|
8
|
+
/** nextents field value */
|
|
9
|
+
nextents: number;
|
|
10
|
+
/** project identifier */
|
|
11
|
+
projid: number;
|
|
12
|
+
/** CoW extsize field value */
|
|
13
|
+
cowextsize: number;
|
|
14
|
+
protected pad: never[];
|
|
15
|
+
constructor(inode?: Inode);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `FS_IOC_*` commands for {@link ioctl | `ioctl`}
|
|
19
|
+
* @remarks
|
|
20
|
+
* These are computed from a script since constant values are needed for enum member types
|
|
21
|
+
*/
|
|
22
|
+
export declare enum IOC {
|
|
23
|
+
GetFlags = 2148034049,
|
|
24
|
+
SetFlags = 1074292226,
|
|
25
|
+
GetVersion = 2148038145,
|
|
26
|
+
SetVersion = 1074296322,
|
|
27
|
+
Fiemap = 3223348747,
|
|
28
|
+
GetXattr = 2149341215,
|
|
29
|
+
SetXattr = 1075599392,
|
|
30
|
+
GetLabel = 2164298801,
|
|
31
|
+
SetLabel = 1090556978,
|
|
32
|
+
GetUUID = 2148603136,
|
|
33
|
+
GetSysfsPath = 2155943169
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* `FS_IOC32_*` commands for {@link ioctl | `ioctl`}
|
|
37
|
+
* @remarks
|
|
38
|
+
* These are computed from a script since constant values are needed for enum member types
|
|
39
|
+
*/
|
|
40
|
+
export declare enum IOC32 {
|
|
41
|
+
GetFlags = 2147771905,
|
|
42
|
+
SetFlags = 1074030082,
|
|
43
|
+
GetVersion = 2147776001,
|
|
44
|
+
SetVersion = 1074034178
|
|
45
|
+
}
|
|
46
|
+
/** Used by `ioctl` for type inference */
|
|
47
|
+
interface _ioc_ops {
|
|
48
|
+
[IOC.GetFlags](): number;
|
|
49
|
+
[IOC.SetFlags](flags: number): void;
|
|
50
|
+
[IOC.GetVersion](): number;
|
|
51
|
+
[IOC.SetVersion](version: number): void;
|
|
52
|
+
[IOC.Fiemap](): never;
|
|
53
|
+
[IOC.GetXattr](name: string): fsxattr;
|
|
54
|
+
[IOC.SetXattr](name: string, value: fsxattr): never;
|
|
55
|
+
[IOC.GetLabel](): string;
|
|
56
|
+
[IOC.SetLabel](label: string): void;
|
|
57
|
+
[IOC.GetUUID](): string;
|
|
58
|
+
[IOC.GetSysfsPath](): string;
|
|
59
|
+
}
|
|
60
|
+
/** Used by `ioctl` for type inference */
|
|
61
|
+
interface _ioc32_ops extends Record<keyof IOC32, (...args: any[]) => any> {
|
|
62
|
+
[IOC32.GetFlags](): number;
|
|
63
|
+
[IOC32.SetFlags](flags: number): void;
|
|
64
|
+
[IOC32.GetVersion](): number;
|
|
65
|
+
[IOC32.SetVersion](version: number): void;
|
|
66
|
+
}
|
|
67
|
+
/** Used by `ioctl` for type inference */
|
|
68
|
+
type __ioctl_args__<T extends number> = T extends IOC ? Parameters<_ioc_ops[T]> : T extends IOC32 ? Parameters<_ioc32_ops[T]> : any[];
|
|
69
|
+
/** Used by `ioctl` for type inference */
|
|
70
|
+
type __ioctl_return__<T extends number> = T extends IOC ? ReturnType<_ioc_ops[T]> : T extends IOC32 ? ReturnType<_ioc32_ops[T]> : any;
|
|
71
|
+
/** Perform an `ioctl` on a file or file system. */
|
|
72
|
+
export declare function ioctl<const Command extends number, const Args extends __ioctl_args__<Command>, const Return extends __ioctl_return__<Command>>(this: V_Context,
|
|
73
|
+
/** The path to the file or file system to perform the `ioctl` on */
|
|
74
|
+
path: string,
|
|
75
|
+
/** The command to perform (uint32) */
|
|
76
|
+
command: Command,
|
|
77
|
+
/** The arguments to pass to the command */
|
|
78
|
+
...args: Args): Promise<Return>;
|
|
79
|
+
/** Perform an `ioctl` on a file or file system */
|
|
80
|
+
export declare function ioctlSync<const Command extends number, const Args extends __ioctl_args__<Command>, const Return extends __ioctl_return__<Command>>(this: V_Context,
|
|
81
|
+
/** The path to the file or file system to perform the `ioctl` on */
|
|
82
|
+
path: string,
|
|
83
|
+
/** The command to perform (uint32) */
|
|
84
|
+
command: Command,
|
|
85
|
+
/** The arguments to pass to the command */
|
|
86
|
+
...args: Args): Return;
|
|
87
|
+
export {};
|