@zenfs/core 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backends/memory.d.ts +4 -4
- package/dist/backends/memory.js +4 -4
- package/dist/backends/overlay.d.ts +5 -2
- package/dist/backends/overlay.js +7 -10
- package/dist/backends/port/fs.js +1 -4
- package/dist/config.js +4 -8
- package/dist/context.d.ts +32 -0
- package/dist/context.js +23 -0
- package/dist/credentials.d.ts +5 -5
- package/dist/credentials.js +10 -6
- package/dist/emulation/async.d.ts +90 -89
- package/dist/emulation/async.js +76 -75
- package/dist/emulation/dir.d.ts +3 -1
- package/dist/emulation/dir.js +6 -7
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/promises.d.ts +50 -48
- package/dist/emulation/promises.js +78 -77
- package/dist/emulation/shared.d.ts +35 -8
- package/dist/emulation/shared.js +37 -11
- package/dist/emulation/sync.d.ts +63 -62
- package/dist/emulation/sync.js +72 -73
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stats.d.ts +2 -1
- package/dist/stats.js +5 -4
- package/package.json +3 -5
- package/scripts/test.js +78 -17
- package/tests/assignment.ts +1 -1
- package/tests/common/context.test.ts +19 -0
- package/tests/{devices.test.ts → common/devices.test.ts} +3 -3
- package/tests/{handle.test.ts → common/handle.test.ts} +1 -1
- package/tests/common/mounts.test.ts +36 -0
- package/tests/{mutex.test.ts → common/mutex.test.ts} +3 -3
- package/tests/common/path.test.ts +34 -0
- package/tests/common.ts +4 -3
- package/tests/fs/dir.test.ts +11 -11
- package/tests/fs/directory.test.ts +17 -17
- package/tests/fs/errors.test.ts +29 -39
- package/tests/fs/watch.test.ts +2 -2
- package/tests/setup/context.ts +9 -0
- package/tests/setup/cow+fetch.ts +1 -1
- package/tests/setup/memory.ts +1 -1
- package/tests/{setup/common.ts → setup.ts} +6 -5
- package/src/backends/backend.ts +0 -161
- package/src/backends/fetch.ts +0 -180
- package/src/backends/file_index.ts +0 -206
- package/src/backends/memory.ts +0 -45
- package/src/backends/overlay.ts +0 -560
- package/src/backends/port/fs.ts +0 -329
- package/src/backends/port/readme.md +0 -54
- package/src/backends/port/rpc.ts +0 -167
- package/src/backends/readme.md +0 -3
- package/src/backends/store/fs.ts +0 -667
- package/src/backends/store/readme.md +0 -9
- package/src/backends/store/simple.ts +0 -154
- package/src/backends/store/store.ts +0 -189
- package/src/config.ts +0 -227
- package/src/credentials.ts +0 -49
- package/src/devices.ts +0 -521
- package/src/emulation/async.ts +0 -834
- package/src/emulation/cache.ts +0 -86
- package/src/emulation/config.ts +0 -21
- package/src/emulation/constants.ts +0 -182
- package/src/emulation/dir.ts +0 -138
- package/src/emulation/index.ts +0 -8
- package/src/emulation/path.ts +0 -440
- package/src/emulation/promises.ts +0 -1140
- package/src/emulation/shared.ts +0 -172
- package/src/emulation/streams.ts +0 -34
- package/src/emulation/sync.ts +0 -863
- package/src/emulation/watchers.ts +0 -194
- package/src/error.ts +0 -307
- package/src/file.ts +0 -631
- package/src/filesystem.ts +0 -174
- package/src/index.ts +0 -35
- package/src/inode.ts +0 -128
- package/src/mixins/async.ts +0 -230
- package/src/mixins/index.ts +0 -5
- package/src/mixins/mutexed.ts +0 -257
- package/src/mixins/readonly.ts +0 -96
- package/src/mixins/shared.ts +0 -25
- package/src/mixins/sync.ts +0 -58
- package/src/polyfills.ts +0 -21
- package/src/stats.ts +0 -405
- package/src/utils.ts +0 -276
- package/tests/mounts.test.ts +0 -18
- package/tests/path.test.ts +0 -34
package/src/devices.ts
DELETED
|
@@ -1,521 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
This is a great resource: https://www.kernel.org/doc/html/latest/admin-guide/devices.html
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { FileReadResult } from 'node:fs/promises';
|
|
6
|
-
import { InMemoryStore } from './backends/memory.js';
|
|
7
|
-
import { StoreFS } from './backends/store/fs.js';
|
|
8
|
-
import { S_IFBLK, S_IFCHR } from './emulation/constants.js';
|
|
9
|
-
import { Errno, ErrnoError } from './error.js';
|
|
10
|
-
import { File } from './file.js';
|
|
11
|
-
import type { StatsLike } from './stats.js';
|
|
12
|
-
import { Stats } from './stats.js';
|
|
13
|
-
import { basename, dirname } from './emulation/path.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* A device
|
|
17
|
-
* @todo Maybe add major/minor number or some other device information, like a UUID?
|
|
18
|
-
* @privateRemarks
|
|
19
|
-
* UUIDs were considered, however they don't make sense without an easy mechanism for persistance
|
|
20
|
-
*/
|
|
21
|
-
export interface Device<TData = any> {
|
|
22
|
-
/**
|
|
23
|
-
* The device's driver
|
|
24
|
-
*/
|
|
25
|
-
driver: DeviceDriver;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Which inode the device is assigned
|
|
29
|
-
*/
|
|
30
|
-
ino: bigint;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Data associated with a device.
|
|
34
|
-
* This is meant to be used by device drivers.
|
|
35
|
-
* @experimental
|
|
36
|
-
*/
|
|
37
|
-
data: TData;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Major device number
|
|
41
|
-
* @experimental
|
|
42
|
-
*/
|
|
43
|
-
major: number;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Minor device number
|
|
47
|
-
* @experimental
|
|
48
|
-
*/
|
|
49
|
-
minor: number;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* A device driver
|
|
54
|
-
*/
|
|
55
|
-
export interface DeviceDriver<TData = any> {
|
|
56
|
-
/**
|
|
57
|
-
* The name of the device driver
|
|
58
|
-
*/
|
|
59
|
-
name: string;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Whether the device is buffered (a "block" device) or unbuffered (a "character" device)
|
|
63
|
-
* @default false
|
|
64
|
-
*/
|
|
65
|
-
isBuffered?: boolean;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Initializes a new device.
|
|
69
|
-
* @returns `Device.data`
|
|
70
|
-
* @experimental
|
|
71
|
-
*/
|
|
72
|
-
init?(ino: bigint): {
|
|
73
|
-
data?: TData;
|
|
74
|
-
minor?: number;
|
|
75
|
-
major?: number;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Synchronously read from the device
|
|
80
|
-
* @group File operations
|
|
81
|
-
*/
|
|
82
|
-
read(file: DeviceFile, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Synchronously write to the device
|
|
86
|
-
* @group File operations
|
|
87
|
-
*/
|
|
88
|
-
write(file: DeviceFile, buffer: Uint8Array, offset: number, length: number, position?: number): number;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Sync the device
|
|
92
|
-
* @group File operations
|
|
93
|
-
*/
|
|
94
|
-
sync?(file: DeviceFile): void;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Close the device
|
|
98
|
-
* @group File operations
|
|
99
|
-
*/
|
|
100
|
-
close?(file: DeviceFile): void;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* The base class for device files
|
|
105
|
-
* This class only does some simple things:
|
|
106
|
-
* It implements `truncate` using `write` and it has non-device methods throw.
|
|
107
|
-
* It is up to device drivers to implement the rest of the functionality.
|
|
108
|
-
*/
|
|
109
|
-
export class DeviceFile extends File {
|
|
110
|
-
public position = 0;
|
|
111
|
-
|
|
112
|
-
public constructor(
|
|
113
|
-
public fs: DeviceFS,
|
|
114
|
-
path: string,
|
|
115
|
-
public readonly device: Device
|
|
116
|
-
) {
|
|
117
|
-
super(fs, path);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
public get driver(): DeviceDriver {
|
|
121
|
-
return this.device.driver;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
protected get stats(): Partial<StatsLike> {
|
|
125
|
-
return { mode: (this.driver.isBuffered ? S_IFBLK : S_IFCHR) | 0o666 };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
public async stat(): Promise<Stats> {
|
|
129
|
-
return Promise.resolve(new Stats(this.stats));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public statSync(): Stats {
|
|
133
|
-
return new Stats(this.stats);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
public readSync(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number {
|
|
137
|
-
return this.driver.read(this, buffer, offset, length, position);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
141
|
-
public async read<TBuffer extends NodeJS.ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number): Promise<FileReadResult<TBuffer>> {
|
|
142
|
-
return { bytesRead: this.readSync(buffer, offset, length), buffer };
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
public writeSync(buffer: Uint8Array, offset = 0, length = buffer.length, position?: number): number {
|
|
146
|
-
return this.driver.write(this, buffer, offset, length, position);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
150
|
-
public async write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number> {
|
|
151
|
-
return this.writeSync(buffer, offset, length, position);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public async truncate(length: number): Promise<void> {
|
|
155
|
-
const { size } = await this.stat();
|
|
156
|
-
|
|
157
|
-
const buffer = new Uint8Array(length > size ? length - size : 0);
|
|
158
|
-
|
|
159
|
-
await this.write(buffer, 0, buffer.length, length > size ? size : length);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public truncateSync(length: number): void {
|
|
163
|
-
const { size } = this.statSync();
|
|
164
|
-
|
|
165
|
-
const buffer = new Uint8Array(length > size ? length - size : 0);
|
|
166
|
-
|
|
167
|
-
this.writeSync(buffer, 0, buffer.length, length > size ? size : length);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public closeSync(): void {
|
|
171
|
-
this.driver.close?.(this);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
public close(): Promise<void> {
|
|
175
|
-
this.closeSync();
|
|
176
|
-
return Promise.resolve();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
public syncSync(): void {
|
|
180
|
-
this.driver.sync?.(this);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
public sync(): Promise<void> {
|
|
184
|
-
this.syncSync();
|
|
185
|
-
return Promise.resolve();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
public chown(): Promise<void> {
|
|
189
|
-
throw ErrnoError.With('ENOTSUP', this.path, 'chown');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
public chownSync(): void {
|
|
193
|
-
throw ErrnoError.With('ENOTSUP', this.path, 'chown');
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
public chmod(): Promise<void> {
|
|
197
|
-
throw ErrnoError.With('ENOTSUP', this.path, 'chmod');
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
public chmodSync(): void {
|
|
201
|
-
throw ErrnoError.With('ENOTSUP', this.path, 'chmod');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
public utimes(): Promise<void> {
|
|
205
|
-
throw ErrnoError.With('ENOTSUP', this.path, 'utimes');
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
public utimesSync(): void {
|
|
209
|
-
throw ErrnoError.With('ENOTSUP', this.path, 'utimes');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
public _setType(): Promise<void> {
|
|
213
|
-
throw ErrnoError.With('ENOTSUP', this.path, '_setType');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
public _setTypeSync(): void {
|
|
217
|
-
throw ErrnoError.With('ENOTSUP', this.path, '_setType');
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* A temporary file system that manages and interfaces with devices
|
|
223
|
-
*/
|
|
224
|
-
export class DeviceFS extends StoreFS<InMemoryStore> {
|
|
225
|
-
protected readonly devices = new Map<string, Device>();
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Creates a new device at `path` relative to the `DeviceFS` root.
|
|
229
|
-
*/
|
|
230
|
-
public createDevice<TData = any>(path: string, driver: DeviceDriver<TData>): Device<TData | Record<string, never>> {
|
|
231
|
-
if (this.existsSync(path)) {
|
|
232
|
-
throw ErrnoError.With('EEXIST', path, 'mknod');
|
|
233
|
-
}
|
|
234
|
-
let ino = 1n;
|
|
235
|
-
while (this.store.has(ino)) ino++;
|
|
236
|
-
const dev = {
|
|
237
|
-
driver,
|
|
238
|
-
ino,
|
|
239
|
-
data: {},
|
|
240
|
-
minor: 0,
|
|
241
|
-
major: 0,
|
|
242
|
-
...driver.init?.(ino),
|
|
243
|
-
};
|
|
244
|
-
this.devices.set(path, dev);
|
|
245
|
-
return dev;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Adds default devices
|
|
250
|
-
*/
|
|
251
|
-
public addDefaults(): void {
|
|
252
|
-
this.createDevice('/null', nullDevice);
|
|
253
|
-
this.createDevice('/zero', zeroDevice);
|
|
254
|
-
this.createDevice('/full', fullDevice);
|
|
255
|
-
this.createDevice('/random', randomDevice);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
public constructor() {
|
|
259
|
-
super(new InMemoryStore('devfs'));
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
public async rename(oldPath: string, newPath: string): Promise<void> {
|
|
263
|
-
if (this.devices.has(oldPath)) {
|
|
264
|
-
throw ErrnoError.With('EPERM', oldPath, 'rename');
|
|
265
|
-
}
|
|
266
|
-
if (this.devices.has(newPath)) {
|
|
267
|
-
throw ErrnoError.With('EEXIST', newPath, 'rename');
|
|
268
|
-
}
|
|
269
|
-
return super.rename(oldPath, newPath);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
public renameSync(oldPath: string, newPath: string): void {
|
|
273
|
-
if (this.devices.has(oldPath)) {
|
|
274
|
-
throw ErrnoError.With('EPERM', oldPath, 'rename');
|
|
275
|
-
}
|
|
276
|
-
if (this.devices.has(newPath)) {
|
|
277
|
-
throw ErrnoError.With('EEXIST', newPath, 'rename');
|
|
278
|
-
}
|
|
279
|
-
return super.renameSync(oldPath, newPath);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
public async stat(path: string): Promise<Stats> {
|
|
283
|
-
if (this.devices.has(path)) {
|
|
284
|
-
await using file = await this.openFile(path, 'r');
|
|
285
|
-
return file.stat();
|
|
286
|
-
}
|
|
287
|
-
return super.stat(path);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
public statSync(path: string): Stats {
|
|
291
|
-
if (this.devices.has(path)) {
|
|
292
|
-
using file = this.openFileSync(path, 'r');
|
|
293
|
-
return file.statSync();
|
|
294
|
-
}
|
|
295
|
-
return super.statSync(path);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
public async openFile(path: string, flag: string): Promise<File> {
|
|
299
|
-
if (this.devices.has(path)) {
|
|
300
|
-
return new DeviceFile(this, path, this.devices.get(path)!);
|
|
301
|
-
}
|
|
302
|
-
return await super.openFile(path, flag);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
public openFileSync(path: string, flag: string): File {
|
|
306
|
-
if (this.devices.has(path)) {
|
|
307
|
-
return new DeviceFile(this, path, this.devices.get(path)!);
|
|
308
|
-
}
|
|
309
|
-
return super.openFileSync(path, flag);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
public async createFile(path: string, flag: string, mode: number): Promise<File> {
|
|
313
|
-
if (this.devices.has(path)) {
|
|
314
|
-
throw ErrnoError.With('EEXIST', path, 'createFile');
|
|
315
|
-
}
|
|
316
|
-
return super.createFile(path, flag, mode);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
public createFileSync(path: string, flag: string, mode: number): File {
|
|
320
|
-
if (this.devices.has(path)) {
|
|
321
|
-
throw ErrnoError.With('EEXIST', path, 'createFile');
|
|
322
|
-
}
|
|
323
|
-
return super.createFileSync(path, flag, mode);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
public async unlink(path: string): Promise<void> {
|
|
327
|
-
if (this.devices.has(path)) {
|
|
328
|
-
throw ErrnoError.With('EPERM', path, 'unlink');
|
|
329
|
-
}
|
|
330
|
-
return super.unlink(path);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
public unlinkSync(path: string): void {
|
|
334
|
-
if (this.devices.has(path)) {
|
|
335
|
-
throw ErrnoError.With('EPERM', path, 'unlink');
|
|
336
|
-
}
|
|
337
|
-
return super.unlinkSync(path);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
public async rmdir(path: string): Promise<void> {
|
|
341
|
-
return super.rmdir(path);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
public rmdirSync(path: string): void {
|
|
345
|
-
return super.rmdirSync(path);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
public async mkdir(path: string, mode: number): Promise<void> {
|
|
349
|
-
if (this.devices.has(path)) {
|
|
350
|
-
throw ErrnoError.With('EEXIST', path, 'mkdir');
|
|
351
|
-
}
|
|
352
|
-
return super.mkdir(path, mode);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
public mkdirSync(path: string, mode: number): void {
|
|
356
|
-
if (this.devices.has(path)) {
|
|
357
|
-
throw ErrnoError.With('EEXIST', path, 'mkdir');
|
|
358
|
-
}
|
|
359
|
-
return super.mkdirSync(path, mode);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
public async readdir(path: string): Promise<string[]> {
|
|
363
|
-
const entries = await super.readdir(path);
|
|
364
|
-
for (const dev of this.devices.keys()) {
|
|
365
|
-
if (dirname(dev) == path) {
|
|
366
|
-
entries.push(basename(dev));
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return entries;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
public readdirSync(path: string): string[] {
|
|
373
|
-
const entries = super.readdirSync(path);
|
|
374
|
-
for (const dev of this.devices.keys()) {
|
|
375
|
-
if (dirname(dev) == path) {
|
|
376
|
-
entries.push(basename(dev));
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
return entries;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
public async link(target: string, link: string): Promise<void> {
|
|
383
|
-
if (this.devices.has(target)) {
|
|
384
|
-
throw ErrnoError.With('EPERM', target, 'rmdir');
|
|
385
|
-
}
|
|
386
|
-
if (this.devices.has(link)) {
|
|
387
|
-
throw ErrnoError.With('EEXIST', link, 'link');
|
|
388
|
-
}
|
|
389
|
-
return super.link(target, link);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
public linkSync(target: string, link: string): void {
|
|
393
|
-
if (this.devices.has(target)) {
|
|
394
|
-
throw ErrnoError.With('EPERM', target, 'rmdir');
|
|
395
|
-
}
|
|
396
|
-
if (this.devices.has(link)) {
|
|
397
|
-
throw ErrnoError.With('EEXIST', link, 'link');
|
|
398
|
-
}
|
|
399
|
-
return super.linkSync(target, link);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
public async sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void> {
|
|
403
|
-
if (this.devices.has(path)) {
|
|
404
|
-
throw new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync');
|
|
405
|
-
}
|
|
406
|
-
return super.sync(path, data, stats);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
public syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void {
|
|
410
|
-
if (this.devices.has(path)) {
|
|
411
|
-
throw new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync');
|
|
412
|
-
}
|
|
413
|
-
return super.syncSync(path, data, stats);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
function defaultWrite(file: DeviceFile, buffer: Uint8Array, offset: number, length: number): number {
|
|
418
|
-
file.position += length;
|
|
419
|
-
return length;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Simulates the `/dev/null` device.
|
|
424
|
-
* - Reads return 0 bytes (EOF).
|
|
425
|
-
* - Writes discard data, advancing the file position.
|
|
426
|
-
* @experimental
|
|
427
|
-
*/
|
|
428
|
-
export const nullDevice: DeviceDriver = {
|
|
429
|
-
name: 'null',
|
|
430
|
-
init() {
|
|
431
|
-
return { major: 1, minor: 3 };
|
|
432
|
-
},
|
|
433
|
-
read(): number {
|
|
434
|
-
return 0;
|
|
435
|
-
},
|
|
436
|
-
write: defaultWrite,
|
|
437
|
-
};
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Simulates the `/dev/zero` device
|
|
441
|
-
* Provides an infinite stream of zeroes when read.
|
|
442
|
-
* Discards any data written to it.
|
|
443
|
-
*
|
|
444
|
-
* - Reads fill the buffer with zeroes.
|
|
445
|
-
* - Writes discard data but update the file position.
|
|
446
|
-
* - Provides basic file metadata, treating it as a character device.
|
|
447
|
-
* @experimental
|
|
448
|
-
*/
|
|
449
|
-
export const zeroDevice: DeviceDriver = {
|
|
450
|
-
name: 'zero',
|
|
451
|
-
init() {
|
|
452
|
-
return { major: 1, minor: 5 };
|
|
453
|
-
},
|
|
454
|
-
read(file: DeviceFile, buffer: ArrayBufferView, offset = 0, length = buffer.byteLength): number {
|
|
455
|
-
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
456
|
-
for (let i = offset; i < offset + length; i++) {
|
|
457
|
-
data[i] = 0;
|
|
458
|
-
}
|
|
459
|
-
file.position += length;
|
|
460
|
-
return length;
|
|
461
|
-
},
|
|
462
|
-
write: defaultWrite,
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* Simulates the `/dev/full` device.
|
|
467
|
-
* - Reads behave like `/dev/zero` (returns zeroes).
|
|
468
|
-
* - Writes always fail with ENOSPC (no space left on device).
|
|
469
|
-
* @experimental
|
|
470
|
-
*/
|
|
471
|
-
export const fullDevice: DeviceDriver = {
|
|
472
|
-
name: 'full',
|
|
473
|
-
init() {
|
|
474
|
-
return { major: 1, minor: 7 };
|
|
475
|
-
},
|
|
476
|
-
read(file: DeviceFile, buffer: ArrayBufferView, offset = 0, length = buffer.byteLength): number {
|
|
477
|
-
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
478
|
-
for (let i = offset; i < offset + length; i++) {
|
|
479
|
-
data[i] = 0;
|
|
480
|
-
}
|
|
481
|
-
file.position += length;
|
|
482
|
-
return length;
|
|
483
|
-
},
|
|
484
|
-
|
|
485
|
-
write(file: DeviceFile): number {
|
|
486
|
-
throw ErrnoError.With('ENOSPC', file.path, 'write');
|
|
487
|
-
},
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* Simulates the `/dev/random` device.
|
|
492
|
-
* - Reads return random bytes.
|
|
493
|
-
* - Writes discard data, advancing the file position.
|
|
494
|
-
* @experimental
|
|
495
|
-
*/
|
|
496
|
-
export const randomDevice: DeviceDriver = {
|
|
497
|
-
name: 'random',
|
|
498
|
-
init() {
|
|
499
|
-
return { major: 1, minor: 8 };
|
|
500
|
-
},
|
|
501
|
-
read(file: DeviceFile, buffer: ArrayBufferView, offset = 0, length = buffer.byteLength): number {
|
|
502
|
-
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
503
|
-
for (let i = offset; i < offset + length; i++) {
|
|
504
|
-
data[i] = Math.floor(Math.random() * 256);
|
|
505
|
-
}
|
|
506
|
-
file.position += length;
|
|
507
|
-
return length;
|
|
508
|
-
},
|
|
509
|
-
write: defaultWrite,
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* Shortcuts for importing.
|
|
514
|
-
* @experimental
|
|
515
|
-
*/
|
|
516
|
-
export default {
|
|
517
|
-
null: nullDevice,
|
|
518
|
-
zero: zeroDevice,
|
|
519
|
-
full: fullDevice,
|
|
520
|
-
random: randomDevice,
|
|
521
|
-
};
|