@zenfs/core 1.8.0 → 1.8.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/overlay.d.ts +3 -14
- package/dist/backends/overlay.js +10 -26
- package/dist/backends/passthrough.d.ts +6 -5
- package/dist/backends/passthrough.js +44 -28
- package/dist/backends/port/fs.d.ts +10 -9
- package/dist/backends/port/fs.js +13 -78
- package/dist/backends/port/rpc.d.ts +6 -2
- package/dist/backends/port/rpc.js +3 -3
- package/dist/backends/store/fs.d.ts +2 -18
- package/dist/backends/store/fs.js +21 -36
- package/dist/backends/store/index_fs.js +3 -3
- package/dist/backends/store/inode.d.ts +1 -1
- package/dist/devices.d.ts +39 -17
- package/dist/devices.js +75 -47
- package/dist/file.js +14 -30
- package/dist/filesystem.d.ts +24 -2
- package/dist/mixins/async.js +12 -6
- package/dist/mixins/mutexed.d.ts +3 -3
- package/dist/mixins/mutexed.js +5 -5
- package/dist/mixins/readonly.d.ts +17 -16
- package/dist/mixins/readonly.js +6 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +33 -0
- package/dist/vfs/async.js +1 -1
- package/dist/vfs/promises.js +2 -2
- package/eslint.shared.js +1 -0
- package/package.json +1 -1
- package/tests/fs/write.test.ts +6 -11
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ErrnoError } from '../../error.js';
|
|
2
|
-
import {
|
|
2
|
+
import { LazyFile } from '../../file.js';
|
|
3
3
|
import { Stats } from '../../stats.js';
|
|
4
4
|
import { S_IFREG } from '../../vfs/constants.js';
|
|
5
5
|
import { Index } from './file_index.js';
|
|
@@ -43,13 +43,13 @@ export class IndexFS extends StoreFS {
|
|
|
43
43
|
}
|
|
44
44
|
async createFile(path, flag, mode, options) {
|
|
45
45
|
const node = await this.commitNew(path, S_IFREG, { mode, ...options }, new Uint8Array(), 'createFile');
|
|
46
|
-
const file = new
|
|
46
|
+
const file = new LazyFile(this, path, flag, node.toStats());
|
|
47
47
|
this.index.set(path, node);
|
|
48
48
|
return file;
|
|
49
49
|
}
|
|
50
50
|
createFileSync(path, flag, mode, options) {
|
|
51
51
|
const node = this.commitNewSync(path, S_IFREG, { mode, ...options }, new Uint8Array(), 'createFile');
|
|
52
|
-
const file = new
|
|
52
|
+
const file = new LazyFile(this, path, flag, node.toStats());
|
|
53
53
|
this.index.set(path, node);
|
|
54
54
|
return file;
|
|
55
55
|
}
|
|
@@ -20,7 +20,7 @@ export declare const _inode_fields: readonly ["ino", "data", "size", "mode", "fl
|
|
|
20
20
|
* @todo [BREAKING] Remove 58 byte Inode upgrade path
|
|
21
21
|
*/
|
|
22
22
|
export declare class Inode implements InodeLike {
|
|
23
|
-
constructor(data?: ArrayBufferLike | ArrayBufferView | Readonly<InodeLike
|
|
23
|
+
constructor(data?: ArrayBufferLike | ArrayBufferView | Readonly<Partial<InodeLike>>);
|
|
24
24
|
data: number;
|
|
25
25
|
/** For future use */
|
|
26
26
|
__data_old: number;
|
package/dist/devices.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { InodeLike } from './backends/index.js';
|
|
1
|
+
import { Inode } from './backends/index.js';
|
|
3
2
|
import { InMemoryStore } from './backends/memory.js';
|
|
4
3
|
import { StoreFS } from './backends/store/fs.js';
|
|
4
|
+
import type { FileReadResult } from './file.js';
|
|
5
5
|
import { File } from './file.js';
|
|
6
6
|
import type { CreationOptions } from './filesystem.js';
|
|
7
7
|
import { Stats } from './stats.js';
|
|
@@ -15,7 +15,7 @@ export interface Device<TData = any> {
|
|
|
15
15
|
/**
|
|
16
16
|
* The device's driver
|
|
17
17
|
*/
|
|
18
|
-
driver: DeviceDriver
|
|
18
|
+
driver: DeviceDriver<TData>;
|
|
19
19
|
/**
|
|
20
20
|
* Which inode the device is assigned
|
|
21
21
|
*/
|
|
@@ -34,6 +34,12 @@ export interface Device<TData = any> {
|
|
|
34
34
|
*/
|
|
35
35
|
minor: number;
|
|
36
36
|
}
|
|
37
|
+
export interface DeviceInit<TData = any> {
|
|
38
|
+
data?: TData;
|
|
39
|
+
minor?: number;
|
|
40
|
+
major?: number;
|
|
41
|
+
name?: string;
|
|
42
|
+
}
|
|
37
43
|
/**
|
|
38
44
|
* A device driver
|
|
39
45
|
*/
|
|
@@ -56,22 +62,36 @@ export interface DeviceDriver<TData = any> {
|
|
|
56
62
|
* Initializes a new device.
|
|
57
63
|
* @returns `Device.data`
|
|
58
64
|
*/
|
|
59
|
-
init?(ino: number, options: object):
|
|
60
|
-
data?: TData;
|
|
61
|
-
minor?: number;
|
|
62
|
-
major?: number;
|
|
63
|
-
name?: string;
|
|
64
|
-
};
|
|
65
|
+
init?(ino: number, options: object): DeviceInit<TData>;
|
|
65
66
|
/**
|
|
66
|
-
* Synchronously read from
|
|
67
|
+
* Synchronously read from a device file
|
|
67
68
|
* @group File operations
|
|
69
|
+
* @deprecated
|
|
70
|
+
* @todo [BREAKING] Remove
|
|
71
|
+
*/
|
|
72
|
+
read?(file: DeviceFile<TData>, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
|
|
73
|
+
/**
|
|
74
|
+
* Synchronously read from a device.
|
|
75
|
+
* @privateRemarks
|
|
76
|
+
* For many devices there is no concept of an offset or end.
|
|
77
|
+
* For example, /dev/random will be "the same" regardless of where you read from- random data.
|
|
78
|
+
* @group File operations
|
|
79
|
+
* @todo [BREAKING] Rename to `read`
|
|
80
|
+
*/
|
|
81
|
+
readD(device: Device<TData>, buffer: Uint8Array, offset: number, end: number): void;
|
|
82
|
+
/**
|
|
83
|
+
* Synchronously write to a device file
|
|
84
|
+
* @group File operations
|
|
85
|
+
* @deprecated
|
|
86
|
+
* @todo [BREAKING] Remove
|
|
68
87
|
*/
|
|
69
|
-
|
|
88
|
+
write?(file: DeviceFile<TData>, buffer: Uint8Array, offset: number, length: number, position?: number): number;
|
|
70
89
|
/**
|
|
71
|
-
* Synchronously write to
|
|
90
|
+
* Synchronously write to a device
|
|
72
91
|
* @group File operations
|
|
92
|
+
* @todo [BREAKING] Rename to `write`
|
|
73
93
|
*/
|
|
74
|
-
|
|
94
|
+
writeD(device: Device<TData>, buffer: Uint8Array, offset: number): void;
|
|
75
95
|
/**
|
|
76
96
|
* Sync the device
|
|
77
97
|
* @group File operations
|
|
@@ -95,7 +115,7 @@ export declare class DeviceFile<TData = any> extends File {
|
|
|
95
115
|
position: number;
|
|
96
116
|
constructor(fs: DeviceFS, path: string, device: Device<TData>);
|
|
97
117
|
get driver(): DeviceDriver<TData>;
|
|
98
|
-
protected
|
|
118
|
+
protected stats: Inode;
|
|
99
119
|
stat(): Promise<Stats>;
|
|
100
120
|
statSync(): Stats;
|
|
101
121
|
readSync(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
|
|
@@ -114,8 +134,6 @@ export declare class DeviceFile<TData = any> extends File {
|
|
|
114
134
|
chmodSync(): void;
|
|
115
135
|
utimes(): Promise<void>;
|
|
116
136
|
utimesSync(): void;
|
|
117
|
-
_setType(): Promise<void>;
|
|
118
|
-
_setTypeSync(): void;
|
|
119
137
|
}
|
|
120
138
|
/**
|
|
121
139
|
* A temporary file system that manages and interfaces with devices
|
|
@@ -157,6 +175,10 @@ export declare class DeviceFS extends StoreFS<InMemoryStore> {
|
|
|
157
175
|
linkSync(target: string, link: string): void;
|
|
158
176
|
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
|
|
159
177
|
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
178
|
+
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
179
|
+
readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
|
|
180
|
+
write(path: string, data: Uint8Array, offset: number): Promise<void>;
|
|
181
|
+
writeSync(path: string, data: Uint8Array, offset: number): void;
|
|
160
182
|
}
|
|
161
183
|
/**
|
|
162
184
|
* Simulates the `/dev/null` device.
|
|
@@ -199,6 +221,6 @@ export declare const devices: {
|
|
|
199
221
|
full: DeviceDriver<any>;
|
|
200
222
|
random: DeviceDriver<any>;
|
|
201
223
|
console: DeviceDriver<{
|
|
202
|
-
output: (text: string) => unknown;
|
|
224
|
+
output: (text: string, offset: number) => unknown;
|
|
203
225
|
}>;
|
|
204
226
|
};
|
package/dist/devices.js
CHANGED
|
@@ -53,6 +53,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
53
53
|
var e = new Error(message);
|
|
54
54
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
55
55
|
});
|
|
56
|
+
import { Inode } from './backends/index.js';
|
|
56
57
|
import { InMemoryStore } from './backends/memory.js';
|
|
57
58
|
import { StoreFS } from './backends/store/fs.js';
|
|
58
59
|
import { Errno, ErrnoError } from './error.js';
|
|
@@ -73,28 +74,40 @@ export class DeviceFile extends File {
|
|
|
73
74
|
this.fs = fs;
|
|
74
75
|
this.device = device;
|
|
75
76
|
this.position = 0;
|
|
77
|
+
this.stats = new Inode({
|
|
78
|
+
mode: (this.driver.isBuffered ? S_IFBLK : S_IFCHR) | 0o666,
|
|
79
|
+
});
|
|
76
80
|
}
|
|
77
81
|
get driver() {
|
|
78
82
|
return this.device.driver;
|
|
79
83
|
}
|
|
80
|
-
get stats() {
|
|
81
|
-
return { mode: (this.driver.isBuffered ? S_IFBLK : S_IFCHR) | 0o666 };
|
|
82
|
-
}
|
|
83
84
|
async stat() {
|
|
84
85
|
return Promise.resolve(new Stats(this.stats));
|
|
85
86
|
}
|
|
86
87
|
statSync() {
|
|
87
88
|
return new Stats(this.stats);
|
|
88
89
|
}
|
|
89
|
-
readSync(buffer, offset, length, position) {
|
|
90
|
-
|
|
90
|
+
readSync(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
91
|
+
this.stats.atimeMs = Date.now();
|
|
92
|
+
const end = position + length;
|
|
93
|
+
this.position = end;
|
|
94
|
+
const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
95
|
+
this.driver.readD(this.device, uint8.subarray(offset, length), position, end);
|
|
96
|
+
return length;
|
|
91
97
|
}
|
|
92
98
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
93
99
|
async read(buffer, offset, length) {
|
|
94
100
|
return { bytesRead: this.readSync(buffer, offset, length), buffer };
|
|
95
101
|
}
|
|
96
|
-
writeSync(buffer, offset = 0, length = buffer.
|
|
97
|
-
|
|
102
|
+
writeSync(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
103
|
+
const end = position + length;
|
|
104
|
+
if (end > this.stats.size)
|
|
105
|
+
this.stats.size = end;
|
|
106
|
+
this.stats.mtimeMs = Date.now();
|
|
107
|
+
this.position = end;
|
|
108
|
+
const data = buffer.subarray(offset, offset + length);
|
|
109
|
+
this.driver.writeD(this.device, data, position);
|
|
110
|
+
return length;
|
|
98
111
|
}
|
|
99
112
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
100
113
|
async write(buffer, offset, length, position) {
|
|
@@ -144,12 +157,6 @@ export class DeviceFile extends File {
|
|
|
144
157
|
utimesSync() {
|
|
145
158
|
throw ErrnoError.With('ENOTSUP', this.path, 'utimes');
|
|
146
159
|
}
|
|
147
|
-
_setType() {
|
|
148
|
-
throw ErrnoError.With('ENOTSUP', this.path, '_setType');
|
|
149
|
-
}
|
|
150
|
-
_setTypeSync() {
|
|
151
|
-
throw ErrnoError.With('ENOTSUP', this.path, '_setType');
|
|
152
|
-
}
|
|
153
160
|
}
|
|
154
161
|
/**
|
|
155
162
|
* A temporary file system that manages and interfaces with devices
|
|
@@ -389,11 +396,41 @@ export class DeviceFS extends StoreFS {
|
|
|
389
396
|
}
|
|
390
397
|
return super.syncSync(path, data, stats);
|
|
391
398
|
}
|
|
399
|
+
async read(path, buffer, offset, end) {
|
|
400
|
+
const device = this.devices.get(path);
|
|
401
|
+
if (!device) {
|
|
402
|
+
await super.read(path, buffer, offset, end);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
device.driver.readD(device, buffer, offset, end);
|
|
406
|
+
}
|
|
407
|
+
readSync(path, buffer, offset, end) {
|
|
408
|
+
const device = this.devices.get(path);
|
|
409
|
+
if (!device) {
|
|
410
|
+
super.readSync(path, buffer, offset, end);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
device.driver.readD(device, buffer, offset, end);
|
|
414
|
+
}
|
|
415
|
+
async write(path, data, offset) {
|
|
416
|
+
const device = this.devices.get(path);
|
|
417
|
+
if (!device) {
|
|
418
|
+
return await super.write(path, data, offset);
|
|
419
|
+
}
|
|
420
|
+
device.driver.writeD(device, data, offset);
|
|
421
|
+
}
|
|
422
|
+
writeSync(path, data, offset) {
|
|
423
|
+
const device = this.devices.get(path);
|
|
424
|
+
if (!device) {
|
|
425
|
+
return super.writeSync(path, data, offset);
|
|
426
|
+
}
|
|
427
|
+
device.driver.writeD(device, data, offset);
|
|
428
|
+
}
|
|
392
429
|
}
|
|
393
|
-
function defaultWrite(
|
|
394
|
-
|
|
395
|
-
return length;
|
|
430
|
+
function defaultWrite(device, data, offset) {
|
|
431
|
+
return;
|
|
396
432
|
}
|
|
433
|
+
const emptyBuffer = new Uint8Array();
|
|
397
434
|
/**
|
|
398
435
|
* Simulates the `/dev/null` device.
|
|
399
436
|
* - Reads return 0 bytes (EOF).
|
|
@@ -409,7 +446,10 @@ export const nullDevice = {
|
|
|
409
446
|
read() {
|
|
410
447
|
return 0;
|
|
411
448
|
},
|
|
412
|
-
|
|
449
|
+
readD() {
|
|
450
|
+
return emptyBuffer;
|
|
451
|
+
},
|
|
452
|
+
writeD: defaultWrite,
|
|
413
453
|
};
|
|
414
454
|
/**
|
|
415
455
|
* Simulates the `/dev/zero` device
|
|
@@ -427,15 +467,10 @@ export const zeroDevice = {
|
|
|
427
467
|
init() {
|
|
428
468
|
return { major: 1, minor: 5 };
|
|
429
469
|
},
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
for (let i = offset; i < offset + length; i++) {
|
|
433
|
-
data[i] = 0;
|
|
434
|
-
}
|
|
435
|
-
file.position += length;
|
|
436
|
-
return length;
|
|
470
|
+
readD(device, buffer, offset, end) {
|
|
471
|
+
buffer.fill(0, offset, end);
|
|
437
472
|
},
|
|
438
|
-
|
|
473
|
+
writeD: defaultWrite,
|
|
439
474
|
};
|
|
440
475
|
/**
|
|
441
476
|
* Simulates the `/dev/full` device.
|
|
@@ -449,17 +484,15 @@ export const fullDevice = {
|
|
|
449
484
|
init() {
|
|
450
485
|
return { major: 1, minor: 7 };
|
|
451
486
|
},
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
for (let i = offset; i < offset + length; i++) {
|
|
455
|
-
data[i] = 0;
|
|
456
|
-
}
|
|
457
|
-
file.position += length;
|
|
458
|
-
return length;
|
|
487
|
+
readD(device, buffer, offset, end) {
|
|
488
|
+
buffer.fill(0, offset, end);
|
|
459
489
|
},
|
|
460
490
|
write(file) {
|
|
461
491
|
throw ErrnoError.With('ENOSPC', file.path, 'write');
|
|
462
492
|
},
|
|
493
|
+
writeD() {
|
|
494
|
+
throw ErrnoError.With('ENOSPC', undefined, 'write');
|
|
495
|
+
},
|
|
463
496
|
};
|
|
464
497
|
/**
|
|
465
498
|
* Simulates the `/dev/random` device.
|
|
@@ -473,15 +506,12 @@ export const randomDevice = {
|
|
|
473
506
|
init() {
|
|
474
507
|
return { major: 1, minor: 8 };
|
|
475
508
|
},
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
data[i] = Math.floor(Math.random() * 256);
|
|
509
|
+
readD(device, buffer) {
|
|
510
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
511
|
+
buffer[i] = Math.floor(Math.random() * 256);
|
|
480
512
|
}
|
|
481
|
-
file.position += length;
|
|
482
|
-
return length;
|
|
483
513
|
},
|
|
484
|
-
|
|
514
|
+
writeD: defaultWrite,
|
|
485
515
|
};
|
|
486
516
|
/**
|
|
487
517
|
* Simulates the `/dev/console` device.
|
|
@@ -490,17 +520,15 @@ export const randomDevice = {
|
|
|
490
520
|
const consoleDevice = {
|
|
491
521
|
name: 'console',
|
|
492
522
|
singleton: true,
|
|
493
|
-
init(ino, { output = console.log } = {}) {
|
|
523
|
+
init(ino, { output = text => console.log(text) } = {}) {
|
|
494
524
|
return { major: 5, minor: 1, data: { output } };
|
|
495
525
|
},
|
|
496
|
-
|
|
497
|
-
return
|
|
526
|
+
readD() {
|
|
527
|
+
return emptyBuffer;
|
|
498
528
|
},
|
|
499
|
-
|
|
500
|
-
const text = decodeUTF8(buffer
|
|
501
|
-
|
|
502
|
-
file.position += length;
|
|
503
|
-
return length;
|
|
529
|
+
writeD(device, buffer, offset) {
|
|
530
|
+
const text = decodeUTF8(buffer);
|
|
531
|
+
device.data.output(text, offset);
|
|
504
532
|
},
|
|
505
533
|
};
|
|
506
534
|
/**
|
package/dist/file.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Errno, ErrnoError } from './error.js';
|
|
2
2
|
import './polyfills.js';
|
|
3
3
|
import { _chown, Stats } from './stats.js';
|
|
4
|
+
import { growBuffer } from './utils.js';
|
|
4
5
|
import { config } from './vfs/config.js';
|
|
5
6
|
import * as c from './vfs/constants.js';
|
|
6
7
|
const maxByteLength = 0x100000; // 1 MiB
|
|
@@ -269,7 +270,7 @@ export class PreloadFile extends File {
|
|
|
269
270
|
}
|
|
270
271
|
this.stats.size = length;
|
|
271
272
|
// Truncate.
|
|
272
|
-
this._buffer = length ? this._buffer.
|
|
273
|
+
this._buffer = length ? this._buffer.subarray(0, length) : new Uint8Array();
|
|
273
274
|
}
|
|
274
275
|
async truncate(length) {
|
|
275
276
|
this._truncate(length);
|
|
@@ -289,28 +290,10 @@ export class PreloadFile extends File {
|
|
|
289
290
|
}
|
|
290
291
|
this.dirty = true;
|
|
291
292
|
const end = position + length;
|
|
292
|
-
const slice = buffer.
|
|
293
|
-
|
|
293
|
+
const slice = buffer.subarray(offset, offset + length);
|
|
294
|
+
this._buffer = growBuffer(this._buffer, end);
|
|
295
|
+
if (end > this.stats.size)
|
|
294
296
|
this.stats.size = end;
|
|
295
|
-
if (end > this._buffer.byteLength) {
|
|
296
|
-
const { buffer } = this._buffer;
|
|
297
|
-
if ('resizable' in buffer && buffer.resizable && buffer.maxByteLength <= end) {
|
|
298
|
-
buffer.resize(end);
|
|
299
|
-
}
|
|
300
|
-
else if ('growable' in buffer && buffer.growable && buffer.maxByteLength <= end) {
|
|
301
|
-
buffer.grow(end);
|
|
302
|
-
}
|
|
303
|
-
else if (config.unsafeBufferReplace) {
|
|
304
|
-
this._buffer = slice;
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
// Extend the buffer!
|
|
308
|
-
const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength }));
|
|
309
|
-
newBuffer.set(this._buffer);
|
|
310
|
-
this._buffer = newBuffer;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
297
|
this._buffer.set(slice, position);
|
|
315
298
|
this.stats.mtimeMs = Date.now();
|
|
316
299
|
this.position = position + slice.byteLength;
|
|
@@ -366,7 +349,7 @@ export class PreloadFile extends File {
|
|
|
366
349
|
// No copy/read. Return immediately for better performance
|
|
367
350
|
return bytesRead;
|
|
368
351
|
}
|
|
369
|
-
const slice = this._buffer.
|
|
352
|
+
const slice = this._buffer.subarray(position, end);
|
|
370
353
|
new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength).set(slice, offset);
|
|
371
354
|
return bytesRead;
|
|
372
355
|
}
|
|
@@ -589,10 +572,9 @@ export class LazyFile extends File {
|
|
|
589
572
|
}
|
|
590
573
|
this.dirty = true;
|
|
591
574
|
const end = position + length;
|
|
592
|
-
const slice = buffer.
|
|
593
|
-
if (end > this.stats.size)
|
|
575
|
+
const slice = buffer.subarray(offset, offset + length);
|
|
576
|
+
if (end > this.stats.size)
|
|
594
577
|
this.stats.size = end;
|
|
595
|
-
}
|
|
596
578
|
this.stats.mtimeMs = Date.now();
|
|
597
579
|
this._position = position + slice.byteLength;
|
|
598
580
|
return slice;
|
|
@@ -607,7 +589,7 @@ export class LazyFile extends File {
|
|
|
607
589
|
*/
|
|
608
590
|
async write(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
609
591
|
const slice = this.prepareWrite(buffer, offset, length, position);
|
|
610
|
-
await this.fs.write(this.path, slice,
|
|
592
|
+
await this.fs.write(this.path, slice, position);
|
|
611
593
|
if (config.syncImmediately)
|
|
612
594
|
await this.sync();
|
|
613
595
|
return slice.byteLength;
|
|
@@ -623,7 +605,7 @@ export class LazyFile extends File {
|
|
|
623
605
|
*/
|
|
624
606
|
writeSync(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
625
607
|
const slice = this.prepareWrite(buffer, offset, length, position);
|
|
626
|
-
this.fs.writeSync(this.path, slice,
|
|
608
|
+
this.fs.writeSync(this.path, slice, position);
|
|
627
609
|
if (config.syncImmediately)
|
|
628
610
|
this.syncSync();
|
|
629
611
|
return slice.byteLength;
|
|
@@ -656,7 +638,8 @@ export class LazyFile extends File {
|
|
|
656
638
|
*/
|
|
657
639
|
async read(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
658
640
|
const bytesRead = this.prepareRead(length, position);
|
|
659
|
-
new Uint8Array(buffer.buffer,
|
|
641
|
+
const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
642
|
+
await this.fs.read(this.path, uint8.subarray(offset, offset + length), position, bytesRead);
|
|
660
643
|
if (config.syncImmediately)
|
|
661
644
|
await this.sync();
|
|
662
645
|
return { bytesRead, buffer };
|
|
@@ -672,7 +655,8 @@ export class LazyFile extends File {
|
|
|
672
655
|
*/
|
|
673
656
|
readSync(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
674
657
|
const bytesRead = this.prepareRead(length, position);
|
|
675
|
-
new Uint8Array(buffer.buffer,
|
|
658
|
+
const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
659
|
+
this.fs.readSync(this.path, uint8.subarray(offset, offset + length), position, bytesRead);
|
|
676
660
|
if (config.syncImmediately)
|
|
677
661
|
this.syncSync();
|
|
678
662
|
return bytesRead;
|
package/dist/filesystem.d.ts
CHANGED
|
@@ -151,8 +151,30 @@ export declare abstract class FileSystem {
|
|
|
151
151
|
abstract linkSync(target: string, link: string): void;
|
|
152
152
|
abstract sync(path: string, data?: Uint8Array, stats?: Partial<Readonly<StatsLike>>): Promise<void>;
|
|
153
153
|
abstract syncSync(path: string, data?: Uint8Array, stats?: Partial<Readonly<StatsLike>>): void;
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Reads into a buffer
|
|
156
|
+
* @param buffer The buffer to read into. You must set the `byteOffset` and `byteLength` appropriately!
|
|
157
|
+
* @param offset The offset into the file to start reading from
|
|
158
|
+
* @param end The position in the file to stop reading
|
|
159
|
+
*/
|
|
160
|
+
abstract read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* Reads into a buffer
|
|
163
|
+
* @param buffer The buffer to read into. You must set the `byteOffset` and `byteLength` appropriately!
|
|
164
|
+
* @param offset The offset into the file to start reading from
|
|
165
|
+
* @param end The position in the file to stop reading
|
|
166
|
+
*/
|
|
167
|
+
abstract readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
|
|
168
|
+
/**
|
|
169
|
+
* Writes a buffer to a file
|
|
170
|
+
* @param buffer The buffer to write. You must set the `byteOffset` and `byteLength` appropriately!
|
|
171
|
+
* @param offset The offset in the file to start writing
|
|
172
|
+
*/
|
|
156
173
|
abstract write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Writes a buffer to a file
|
|
176
|
+
* @param buffer The buffer to write. You must set the `byteOffset` and `byteLength` appropriately!
|
|
177
|
+
* @param offset The offset in the file to start writing
|
|
178
|
+
*/
|
|
157
179
|
abstract writeSync(path: string, buffer: Uint8Array, offset: number): void;
|
|
158
180
|
}
|
package/dist/mixins/async.js
CHANGED
|
@@ -52,7 +52,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
52
52
|
});
|
|
53
53
|
import { StoreFS } from '../backends/store/fs.js';
|
|
54
54
|
import { Errno, ErrnoError } from '../error.js';
|
|
55
|
-
import {
|
|
55
|
+
import { LazyFile, parseFlag } from '../file.js';
|
|
56
56
|
import { join } from '../vfs/path.js';
|
|
57
57
|
/**
|
|
58
58
|
* Async() implements synchronous methods on an asynchronous file system
|
|
@@ -138,11 +138,8 @@ export function Async(FS) {
|
|
|
138
138
|
}
|
|
139
139
|
openFileSync(path, flag) {
|
|
140
140
|
this.checkSync(path, 'openFile');
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
const buffer = new Uint8Array(stats.size);
|
|
144
|
-
file.readSync(buffer);
|
|
145
|
-
return new PreloadFile(this, path, flag, stats, buffer);
|
|
141
|
+
const stats = this._sync.statSync(path);
|
|
142
|
+
return new LazyFile(this, path, flag, stats);
|
|
146
143
|
}
|
|
147
144
|
unlinkSync(path) {
|
|
148
145
|
this.checkSync(path, 'unlinkSync');
|
|
@@ -177,6 +174,15 @@ export function Async(FS) {
|
|
|
177
174
|
this.checkSync(path, 'exists');
|
|
178
175
|
return this._sync.existsSync(path);
|
|
179
176
|
}
|
|
177
|
+
readSync(path, buffer, offset, end) {
|
|
178
|
+
this.checkSync(path, 'read');
|
|
179
|
+
this._sync.readSync(path, buffer, offset, end);
|
|
180
|
+
}
|
|
181
|
+
writeSync(path, buffer, offset) {
|
|
182
|
+
this.checkSync(path, 'write');
|
|
183
|
+
this._sync.writeSync(path, buffer, offset);
|
|
184
|
+
this.queue('write', path, buffer, offset);
|
|
185
|
+
}
|
|
180
186
|
/**
|
|
181
187
|
* @internal
|
|
182
188
|
*/
|
package/dist/mixins/mutexed.d.ts
CHANGED
|
@@ -71,8 +71,8 @@ export declare class _MutexedFS<T extends FileSystem> implements FileSystem {
|
|
|
71
71
|
linkSync(srcpath: string, dstpath: string): void;
|
|
72
72
|
sync(path: string, data?: Uint8Array, stats?: Readonly<InodeLike>): Promise<void>;
|
|
73
73
|
syncSync(path: string, data?: Uint8Array, stats?: Readonly<InodeLike>): void;
|
|
74
|
-
read(path: string, offset: number,
|
|
75
|
-
readSync(path: string, offset: number,
|
|
74
|
+
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
75
|
+
readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
|
|
76
76
|
write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
|
|
77
77
|
writeSync(path: string, buffer: Uint8Array, offset: number): void;
|
|
78
78
|
}
|
|
@@ -81,7 +81,7 @@ export declare class _MutexedFS<T extends FileSystem> implements FileSystem {
|
|
|
81
81
|
* For example, on an OverlayFS instance with an async lower
|
|
82
82
|
* directory operations like rename and rmdir may involve multiple
|
|
83
83
|
* requests involving both the upper and lower file systems -- they
|
|
84
|
-
* are not executed in a single atomic step. OverlayFS
|
|
84
|
+
* are not executed in a single atomic step. OverlayFS used to use this
|
|
85
85
|
* to avoid having to reason about the correctness of
|
|
86
86
|
* multiple requests interleaving.
|
|
87
87
|
*
|
package/dist/mixins/mutexed.js
CHANGED
|
@@ -448,11 +448,11 @@ export class _MutexedFS {
|
|
|
448
448
|
__disposeResources(env_22);
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
|
-
async read(path, offset,
|
|
451
|
+
async read(path, buffer, offset, end) {
|
|
452
452
|
const env_23 = { stack: [], error: void 0, hasError: false };
|
|
453
453
|
try {
|
|
454
454
|
const _ = __addDisposableResource(env_23, await this.lock(path, 'read'), false);
|
|
455
|
-
return await this._fs.read(path, offset,
|
|
455
|
+
return await this._fs.read(path, buffer, offset, end);
|
|
456
456
|
}
|
|
457
457
|
catch (e_23) {
|
|
458
458
|
env_23.error = e_23;
|
|
@@ -462,11 +462,11 @@ export class _MutexedFS {
|
|
|
462
462
|
__disposeResources(env_23);
|
|
463
463
|
}
|
|
464
464
|
}
|
|
465
|
-
readSync(path, offset,
|
|
465
|
+
readSync(path, buffer, offset, end) {
|
|
466
466
|
const env_24 = { stack: [], error: void 0, hasError: false };
|
|
467
467
|
try {
|
|
468
468
|
const _ = __addDisposableResource(env_24, this.lockSync(path, 'read'), false);
|
|
469
|
-
return this._fs.readSync(path, offset,
|
|
469
|
+
return this._fs.readSync(path, buffer, offset, end);
|
|
470
470
|
}
|
|
471
471
|
catch (e_24) {
|
|
472
472
|
env_24.error = e_24;
|
|
@@ -510,7 +510,7 @@ export class _MutexedFS {
|
|
|
510
510
|
* For example, on an OverlayFS instance with an async lower
|
|
511
511
|
* directory operations like rename and rmdir may involve multiple
|
|
512
512
|
* requests involving both the upper and lower file systems -- they
|
|
513
|
-
* are not executed in a single atomic step. OverlayFS
|
|
513
|
+
* are not executed in a single atomic step. OverlayFS used to use this
|
|
514
514
|
* to avoid having to reason about the correctness of
|
|
515
515
|
* multiple requests interleaving.
|
|
516
516
|
*
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import type { File } from '../file.js';
|
|
2
1
|
import type { FileSystem, FileSystemMetadata } from '../filesystem.js';
|
|
3
|
-
import type {
|
|
2
|
+
import type { StatsLike } from '../stats.js';
|
|
4
3
|
import type { Mixin } from './shared.js';
|
|
5
4
|
/**
|
|
6
5
|
* @internal
|
|
7
6
|
*/
|
|
8
7
|
export interface ReadonlyMixin {
|
|
9
8
|
metadata(): FileSystemMetadata;
|
|
10
|
-
rename(oldPath: string, newPath: string): Promise<
|
|
11
|
-
renameSync(oldPath: string, newPath: string):
|
|
12
|
-
createFile(path: string, flag: string, mode: number): Promise<
|
|
13
|
-
createFileSync(path: string, flag: string, mode: number):
|
|
14
|
-
unlink(path: string): Promise<
|
|
15
|
-
unlinkSync(path: string):
|
|
16
|
-
rmdir(path: string): Promise<
|
|
17
|
-
rmdirSync(path: string):
|
|
18
|
-
mkdir(path: string, mode: number): Promise<
|
|
19
|
-
mkdirSync(path: string, mode: number):
|
|
20
|
-
link(srcpath: string, dstpath: string): Promise<
|
|
21
|
-
linkSync(srcpath: string, dstpath: string):
|
|
22
|
-
sync(path: string, data: Uint8Array, stats: Readonly<
|
|
23
|
-
syncSync(path: string, data: Uint8Array, stats: Readonly<
|
|
9
|
+
rename(oldPath: string, newPath: string): Promise<never>;
|
|
10
|
+
renameSync(oldPath: string, newPath: string): never;
|
|
11
|
+
createFile(path: string, flag: string, mode: number): Promise<never>;
|
|
12
|
+
createFileSync(path: string, flag: string, mode: number): never;
|
|
13
|
+
unlink(path: string): Promise<never>;
|
|
14
|
+
unlinkSync(path: string): never;
|
|
15
|
+
rmdir(path: string): Promise<never>;
|
|
16
|
+
rmdirSync(path: string): never;
|
|
17
|
+
mkdir(path: string, mode: number): Promise<never>;
|
|
18
|
+
mkdirSync(path: string, mode: number): never;
|
|
19
|
+
link(srcpath: string, dstpath: string): Promise<never>;
|
|
20
|
+
linkSync(srcpath: string, dstpath: string): never;
|
|
21
|
+
sync(path: string, data: Uint8Array, stats: Readonly<StatsLike<number>>): Promise<never>;
|
|
22
|
+
syncSync(path: string, data: Uint8Array, stats: Readonly<StatsLike<number>>): never;
|
|
23
|
+
write(path: string, buffer: Uint8Array, offset: number): Promise<never>;
|
|
24
|
+
writeSync(path: string, buffer: Uint8Array, offset: number): Promise<never>;
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
26
27
|
* Implements the non-readonly methods to throw `EROFS`
|
package/dist/mixins/readonly.js
CHANGED
package/dist/utils.d.ts
CHANGED
|
@@ -89,3 +89,9 @@ export declare function canary(path?: string, syscall?: string): () => void;
|
|
|
89
89
|
* @internal @hidden
|
|
90
90
|
*/
|
|
91
91
|
export declare function _throw(e: unknown): never;
|
|
92
|
+
/**
|
|
93
|
+
* Grows a buffer if it isn't large enough
|
|
94
|
+
* @returns The original buffer if resized successfully, or a newly created buffer
|
|
95
|
+
* @internal Not for external use!
|
|
96
|
+
*/
|
|
97
|
+
export declare function growBuffer<T extends ArrayBufferLike | ArrayBufferView>(buffer: T, newByteLength: number): T;
|