@zenfs/core 1.0.11 → 1.1.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/file_index.js +3 -3
- package/dist/backends/overlay.js +3 -3
- package/dist/backends/store/fs.d.ts +5 -5
- package/dist/backends/store/fs.js +5 -5
- package/dist/config.d.ts +8 -0
- package/dist/config.js +10 -0
- package/dist/devices.d.ts +158 -0
- package/dist/devices.js +423 -0
- package/dist/emulation/constants.d.ts +5 -0
- package/dist/emulation/constants.js +5 -0
- package/dist/emulation/shared.js +3 -2
- package/dist/file.js +1 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/inode.d.ts +0 -5
- package/dist/inode.js +0 -5
- package/dist/stats.js +1 -2
- package/dist/utils.d.ts +14 -4
- package/dist/utils.js +28 -6
- package/package.json +1 -1
- package/readme.md +58 -2
- package/src/backends/file_index.ts +3 -3
- package/src/backends/overlay.ts +3 -3
- package/src/backends/store/fs.ts +10 -9
- package/src/config.ts +22 -0
- package/src/devices.ts +469 -0
- package/src/emulation/constants.ts +6 -0
- package/src/emulation/shared.ts +3 -2
- package/src/file.ts +1 -2
- package/src/index.ts +2 -0
- package/src/inode.ts +0 -6
- package/src/stats.ts +1 -2
- package/src/utils.ts +33 -6
package/dist/devices.js
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
function next() {
|
|
30
|
+
while (env.stack.length) {
|
|
31
|
+
var rec = env.stack.pop();
|
|
32
|
+
try {
|
|
33
|
+
var result = rec.dispose && rec.dispose.call(rec.value);
|
|
34
|
+
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
fail(e);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (env.hasError) throw env.error;
|
|
41
|
+
}
|
|
42
|
+
return next();
|
|
43
|
+
};
|
|
44
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
45
|
+
var e = new Error(message);
|
|
46
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
47
|
+
});
|
|
48
|
+
import { InMemoryStore } from './backends/memory.js';
|
|
49
|
+
import { StoreFS } from './backends/store/fs.js';
|
|
50
|
+
import { S_IFBLK, S_IFCHR } from './emulation/constants.js';
|
|
51
|
+
import { Errno, ErrnoError } from './error.js';
|
|
52
|
+
import { File } from './file.js';
|
|
53
|
+
import { Stats } from './stats.js';
|
|
54
|
+
import { basename, dirname } from './emulation/path.js';
|
|
55
|
+
/**
|
|
56
|
+
* The base class for device files
|
|
57
|
+
* This class only does some simple things:
|
|
58
|
+
* It implements `truncate` using `write` and it has non-device methods throw.
|
|
59
|
+
* It is up to device drivers to implement the rest of the functionality.
|
|
60
|
+
* @experimental
|
|
61
|
+
*/
|
|
62
|
+
export class DeviceFile extends File {
|
|
63
|
+
constructor(fs, path, device) {
|
|
64
|
+
super(fs, path);
|
|
65
|
+
this.fs = fs;
|
|
66
|
+
this.device = device;
|
|
67
|
+
this.position = 0;
|
|
68
|
+
}
|
|
69
|
+
get driver() {
|
|
70
|
+
return this.device.driver;
|
|
71
|
+
}
|
|
72
|
+
get stats() {
|
|
73
|
+
return { mode: (this.driver.isBuffered ? S_IFBLK : S_IFCHR) | 0o666 };
|
|
74
|
+
}
|
|
75
|
+
async stat() {
|
|
76
|
+
return Promise.resolve(new Stats(this.stats));
|
|
77
|
+
}
|
|
78
|
+
statSync() {
|
|
79
|
+
return new Stats(this.stats);
|
|
80
|
+
}
|
|
81
|
+
readSync(buffer, offset, length, position) {
|
|
82
|
+
return this.driver.read(this, buffer, offset, length, position);
|
|
83
|
+
}
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
85
|
+
async read(buffer, offset, length) {
|
|
86
|
+
return { bytesRead: this.readSync(buffer, offset, length), buffer };
|
|
87
|
+
}
|
|
88
|
+
writeSync(buffer, offset = 0, length = buffer.length, position) {
|
|
89
|
+
return this.driver.write(this, buffer, offset, length, position);
|
|
90
|
+
}
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
92
|
+
async write(buffer, offset, length, position) {
|
|
93
|
+
return this.writeSync(buffer, offset, length, position);
|
|
94
|
+
}
|
|
95
|
+
async truncate(length) {
|
|
96
|
+
const { size } = await this.stat();
|
|
97
|
+
const buffer = new Uint8Array(length > size ? length - size : 0);
|
|
98
|
+
await this.write(buffer, 0, buffer.length, length > size ? size : length);
|
|
99
|
+
}
|
|
100
|
+
truncateSync(length) {
|
|
101
|
+
const { size } = this.statSync();
|
|
102
|
+
const buffer = new Uint8Array(length > size ? length - size : 0);
|
|
103
|
+
this.writeSync(buffer, 0, buffer.length, length > size ? size : length);
|
|
104
|
+
}
|
|
105
|
+
closeSync() {
|
|
106
|
+
this.driver.close?.(this);
|
|
107
|
+
}
|
|
108
|
+
async close() {
|
|
109
|
+
this.closeSync();
|
|
110
|
+
}
|
|
111
|
+
syncSync() {
|
|
112
|
+
this.driver.sync?.(this);
|
|
113
|
+
}
|
|
114
|
+
async sync() {
|
|
115
|
+
this.syncSync();
|
|
116
|
+
}
|
|
117
|
+
chown() {
|
|
118
|
+
throw ErrnoError.With('ENOTSUP', this.path, 'chown');
|
|
119
|
+
}
|
|
120
|
+
chownSync() {
|
|
121
|
+
throw ErrnoError.With('ENOTSUP', this.path, 'chown');
|
|
122
|
+
}
|
|
123
|
+
chmod() {
|
|
124
|
+
throw ErrnoError.With('ENOTSUP', this.path, 'chmod');
|
|
125
|
+
}
|
|
126
|
+
chmodSync() {
|
|
127
|
+
throw ErrnoError.With('ENOTSUP', this.path, 'chmod');
|
|
128
|
+
}
|
|
129
|
+
utimes() {
|
|
130
|
+
throw ErrnoError.With('ENOTSUP', this.path, 'utimes');
|
|
131
|
+
}
|
|
132
|
+
utimesSync() {
|
|
133
|
+
throw ErrnoError.With('ENOTSUP', this.path, 'utimes');
|
|
134
|
+
}
|
|
135
|
+
_setType() {
|
|
136
|
+
throw ErrnoError.With('ENOTSUP', this.path, '_setType');
|
|
137
|
+
}
|
|
138
|
+
_setTypeSync() {
|
|
139
|
+
throw ErrnoError.With('ENOTSUP', this.path, '_setType');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @experimental
|
|
144
|
+
*/
|
|
145
|
+
export class DeviceFS extends StoreFS {
|
|
146
|
+
createDevice(path, driver) {
|
|
147
|
+
if (this.existsSync(path)) {
|
|
148
|
+
throw ErrnoError.With('EEXIST', path, 'mknod');
|
|
149
|
+
}
|
|
150
|
+
let ino = 1n;
|
|
151
|
+
while (this.store.has(ino))
|
|
152
|
+
ino++;
|
|
153
|
+
const dev = {
|
|
154
|
+
driver,
|
|
155
|
+
ino,
|
|
156
|
+
};
|
|
157
|
+
this.devices.set(path, dev);
|
|
158
|
+
return dev;
|
|
159
|
+
}
|
|
160
|
+
constructor() {
|
|
161
|
+
super(new InMemoryStore('devfs'));
|
|
162
|
+
this.devices = new Map();
|
|
163
|
+
}
|
|
164
|
+
async rename(oldPath, newPath) {
|
|
165
|
+
if (this.devices.has(oldPath)) {
|
|
166
|
+
throw ErrnoError.With('EPERM', oldPath, 'rename');
|
|
167
|
+
}
|
|
168
|
+
if (this.devices.has(newPath)) {
|
|
169
|
+
throw ErrnoError.With('EEXIST', newPath, 'rename');
|
|
170
|
+
}
|
|
171
|
+
return super.rename(oldPath, newPath);
|
|
172
|
+
}
|
|
173
|
+
renameSync(oldPath, newPath) {
|
|
174
|
+
if (this.devices.has(oldPath)) {
|
|
175
|
+
throw ErrnoError.With('EPERM', oldPath, 'rename');
|
|
176
|
+
}
|
|
177
|
+
if (this.devices.has(newPath)) {
|
|
178
|
+
throw ErrnoError.With('EEXIST', newPath, 'rename');
|
|
179
|
+
}
|
|
180
|
+
return super.renameSync(oldPath, newPath);
|
|
181
|
+
}
|
|
182
|
+
async stat(path) {
|
|
183
|
+
if (this.devices.has(path)) {
|
|
184
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
185
|
+
try {
|
|
186
|
+
const file = __addDisposableResource(env_1, await this.openFile(path, 'r'), true);
|
|
187
|
+
return file.stat();
|
|
188
|
+
}
|
|
189
|
+
catch (e_1) {
|
|
190
|
+
env_1.error = e_1;
|
|
191
|
+
env_1.hasError = true;
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
const result_1 = __disposeResources(env_1);
|
|
195
|
+
if (result_1)
|
|
196
|
+
await result_1;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return super.stat(path);
|
|
200
|
+
}
|
|
201
|
+
statSync(path) {
|
|
202
|
+
if (this.devices.has(path)) {
|
|
203
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
204
|
+
try {
|
|
205
|
+
const file = __addDisposableResource(env_2, this.openFileSync(path, 'r'), false);
|
|
206
|
+
return file.statSync();
|
|
207
|
+
}
|
|
208
|
+
catch (e_2) {
|
|
209
|
+
env_2.error = e_2;
|
|
210
|
+
env_2.hasError = true;
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
__disposeResources(env_2);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return super.statSync(path);
|
|
217
|
+
}
|
|
218
|
+
async openFile(path, flag) {
|
|
219
|
+
if (this.devices.has(path)) {
|
|
220
|
+
return new DeviceFile(this, path, this.devices.get(path));
|
|
221
|
+
}
|
|
222
|
+
return await super.openFile(path, flag);
|
|
223
|
+
}
|
|
224
|
+
openFileSync(path, flag) {
|
|
225
|
+
if (this.devices.has(path)) {
|
|
226
|
+
return new DeviceFile(this, path, this.devices.get(path));
|
|
227
|
+
}
|
|
228
|
+
return super.openFileSync(path, flag);
|
|
229
|
+
}
|
|
230
|
+
async createFile(path, flag, mode) {
|
|
231
|
+
if (this.devices.has(path)) {
|
|
232
|
+
throw ErrnoError.With('EEXIST', path, 'createFile');
|
|
233
|
+
}
|
|
234
|
+
return super.createFile(path, flag, mode);
|
|
235
|
+
}
|
|
236
|
+
createFileSync(path, flag, mode) {
|
|
237
|
+
if (this.devices.has(path)) {
|
|
238
|
+
throw ErrnoError.With('EEXIST', path, 'createFile');
|
|
239
|
+
}
|
|
240
|
+
return super.createFileSync(path, flag, mode);
|
|
241
|
+
}
|
|
242
|
+
async unlink(path) {
|
|
243
|
+
if (this.devices.has(path)) {
|
|
244
|
+
throw ErrnoError.With('EPERM', path, 'unlink');
|
|
245
|
+
}
|
|
246
|
+
return super.unlink(path);
|
|
247
|
+
}
|
|
248
|
+
unlinkSync(path) {
|
|
249
|
+
if (this.devices.has(path)) {
|
|
250
|
+
throw ErrnoError.With('EPERM', path, 'unlink');
|
|
251
|
+
}
|
|
252
|
+
return super.unlinkSync(path);
|
|
253
|
+
}
|
|
254
|
+
async rmdir(path) {
|
|
255
|
+
if (this.devices.has(path)) {
|
|
256
|
+
throw ErrnoError.With('ENOTDIR', path, 'rmdir');
|
|
257
|
+
}
|
|
258
|
+
return super.rmdir(path);
|
|
259
|
+
}
|
|
260
|
+
rmdirSync(path) {
|
|
261
|
+
if (this.devices.has(path)) {
|
|
262
|
+
throw ErrnoError.With('ENOTDIR', path, 'rmdir');
|
|
263
|
+
}
|
|
264
|
+
return super.rmdirSync(path);
|
|
265
|
+
}
|
|
266
|
+
async mkdir(path, mode) {
|
|
267
|
+
if (this.devices.has(path)) {
|
|
268
|
+
throw ErrnoError.With('EEXIST', path, 'mkdir');
|
|
269
|
+
}
|
|
270
|
+
return super.mkdir(path, mode);
|
|
271
|
+
}
|
|
272
|
+
mkdirSync(path, mode) {
|
|
273
|
+
if (this.devices.has(path)) {
|
|
274
|
+
throw ErrnoError.With('EEXIST', path, 'mkdir');
|
|
275
|
+
}
|
|
276
|
+
return super.mkdirSync(path, mode);
|
|
277
|
+
}
|
|
278
|
+
async readdir(path) {
|
|
279
|
+
if (this.devices.has(path)) {
|
|
280
|
+
throw ErrnoError.With('ENOTDIR', path, 'readdir');
|
|
281
|
+
}
|
|
282
|
+
const entries = await super.readdir(path);
|
|
283
|
+
for (const dev of this.devices.keys()) {
|
|
284
|
+
if (dirname(dev) == path) {
|
|
285
|
+
entries.push(basename(dev));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return entries;
|
|
289
|
+
}
|
|
290
|
+
readdirSync(path) {
|
|
291
|
+
if (this.devices.has(path)) {
|
|
292
|
+
throw ErrnoError.With('ENOTDIR', path, 'readdirSync');
|
|
293
|
+
}
|
|
294
|
+
const entries = super.readdirSync(path);
|
|
295
|
+
for (const dev of this.devices.keys()) {
|
|
296
|
+
if (dirname(dev) == path) {
|
|
297
|
+
entries.push(basename(dev));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return entries;
|
|
301
|
+
}
|
|
302
|
+
async link(target, link) {
|
|
303
|
+
if (this.devices.has(target)) {
|
|
304
|
+
throw ErrnoError.With('EPERM', target, 'rmdir');
|
|
305
|
+
}
|
|
306
|
+
if (this.devices.has(link)) {
|
|
307
|
+
throw ErrnoError.With('EEXIST', link, 'link');
|
|
308
|
+
}
|
|
309
|
+
return super.link(target, link);
|
|
310
|
+
}
|
|
311
|
+
linkSync(target, link) {
|
|
312
|
+
if (this.devices.has(target)) {
|
|
313
|
+
throw ErrnoError.With('EPERM', target, 'rmdir');
|
|
314
|
+
}
|
|
315
|
+
if (this.devices.has(link)) {
|
|
316
|
+
throw ErrnoError.With('EEXIST', link, 'link');
|
|
317
|
+
}
|
|
318
|
+
return super.linkSync(target, link);
|
|
319
|
+
}
|
|
320
|
+
async sync(path, data, stats) {
|
|
321
|
+
if (this.devices.has(path)) {
|
|
322
|
+
throw new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync');
|
|
323
|
+
}
|
|
324
|
+
return super.sync(path, data, stats);
|
|
325
|
+
}
|
|
326
|
+
syncSync(path, data, stats) {
|
|
327
|
+
if (this.devices.has(path)) {
|
|
328
|
+
throw new ErrnoError(Errno.EINVAL, 'Attempted to sync a device incorrectly (bug)', path, 'sync');
|
|
329
|
+
}
|
|
330
|
+
return super.syncSync(path, data, stats);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function defaultWrite(file, buffer, offset, length) {
|
|
334
|
+
file.position += length;
|
|
335
|
+
return length;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Simulates the `/dev/null` device.
|
|
339
|
+
* - Reads return 0 bytes (EOF).
|
|
340
|
+
* - Writes discard data, advancing the file position.
|
|
341
|
+
* @experimental
|
|
342
|
+
*/
|
|
343
|
+
export const nullDevice = {
|
|
344
|
+
name: 'null',
|
|
345
|
+
isBuffered: false,
|
|
346
|
+
read() {
|
|
347
|
+
return 0;
|
|
348
|
+
},
|
|
349
|
+
write: defaultWrite,
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Simulates the `/dev/zero` device
|
|
353
|
+
* Provides an infinite stream of zeroes when read.
|
|
354
|
+
* Discards any data written to it.
|
|
355
|
+
*
|
|
356
|
+
* - Reads fill the buffer with zeroes.
|
|
357
|
+
* - Writes discard data but update the file position.
|
|
358
|
+
* - Provides basic file metadata, treating it as a character device.
|
|
359
|
+
* @experimental
|
|
360
|
+
*/
|
|
361
|
+
export const zeroDevice = {
|
|
362
|
+
name: 'zero',
|
|
363
|
+
isBuffered: false,
|
|
364
|
+
read(file, buffer, offset = 0, length = buffer.byteLength) {
|
|
365
|
+
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
366
|
+
for (let i = offset; i < offset + length; i++) {
|
|
367
|
+
data[i] = 0;
|
|
368
|
+
}
|
|
369
|
+
file.position += length;
|
|
370
|
+
return length;
|
|
371
|
+
},
|
|
372
|
+
write: defaultWrite,
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* Simulates the `/dev/full` device.
|
|
376
|
+
* - Reads behave like `/dev/zero` (returns zeroes).
|
|
377
|
+
* - Writes always fail with ENOSPC (no space left on device).
|
|
378
|
+
* @experimental
|
|
379
|
+
*/
|
|
380
|
+
export const fullDevice = {
|
|
381
|
+
name: 'full',
|
|
382
|
+
isBuffered: false,
|
|
383
|
+
read(file, buffer, offset = 0, length = buffer.byteLength) {
|
|
384
|
+
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
385
|
+
for (let i = offset; i < offset + length; i++) {
|
|
386
|
+
data[i] = 0;
|
|
387
|
+
}
|
|
388
|
+
file.position += length;
|
|
389
|
+
return length;
|
|
390
|
+
},
|
|
391
|
+
write(file) {
|
|
392
|
+
throw ErrnoError.With('ENOSPC', file.path, 'write');
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
/**
|
|
396
|
+
* Simulates the `/dev/random` device.
|
|
397
|
+
* - Reads return random bytes.
|
|
398
|
+
* - Writes discard data, advancing the file position.
|
|
399
|
+
* @experimental
|
|
400
|
+
*/
|
|
401
|
+
export const randomDevice = {
|
|
402
|
+
name: 'random',
|
|
403
|
+
isBuffered: false,
|
|
404
|
+
read(file, buffer, offset = 0, length = buffer.byteLength) {
|
|
405
|
+
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
406
|
+
for (let i = offset; i < offset + length; i++) {
|
|
407
|
+
data[i] = Math.floor(Math.random() * 256);
|
|
408
|
+
}
|
|
409
|
+
file.position += length;
|
|
410
|
+
return length;
|
|
411
|
+
},
|
|
412
|
+
write: defaultWrite,
|
|
413
|
+
};
|
|
414
|
+
/**
|
|
415
|
+
* Shortcuts for importing.
|
|
416
|
+
* @experimental
|
|
417
|
+
*/
|
|
418
|
+
export default {
|
|
419
|
+
null: nullDevice,
|
|
420
|
+
zero: zeroDevice,
|
|
421
|
+
full: fullDevice,
|
|
422
|
+
random: randomDevice,
|
|
423
|
+
};
|
package/dist/emulation/shared.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Utilities and shared data
|
|
2
2
|
import { InMemory } from '../backends/memory.js';
|
|
3
3
|
import { Errno, ErrnoError } from '../error.js';
|
|
4
|
-
import { size_max } from '../inode.js';
|
|
5
4
|
import { normalizePath } from '../utils.js';
|
|
6
5
|
import { resolve } from './path.js';
|
|
6
|
+
import { size_max } from './constants.js';
|
|
7
7
|
// descriptors
|
|
8
8
|
export const fdMap = new Map();
|
|
9
9
|
let nextFd = 100;
|
|
@@ -56,7 +56,8 @@ export function umount(mountPoint) {
|
|
|
56
56
|
*/
|
|
57
57
|
export function resolveMount(path) {
|
|
58
58
|
path = normalizePath(path);
|
|
59
|
-
|
|
59
|
+
// Maybe do something for devices here
|
|
60
|
+
const sortedMounts = [...mounts].sort((a, b) => (a[0].length > b[0].length ? -1 : 1)); // descending order of the string length
|
|
60
61
|
for (const [mountPoint, fs] of sortedMounts) {
|
|
61
62
|
// We know path is normalized, so it would be a substring of the mount point.
|
|
62
63
|
if (mountPoint.length <= path.length && path.startsWith(mountPoint)) {
|
package/dist/file.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';
|
|
1
|
+
import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT, size_max } from './emulation/constants.js';
|
|
2
2
|
import { Errno, ErrnoError } from './error.js';
|
|
3
|
-
import { size_max } from './inode.js';
|
|
4
3
|
import { Stats } from './stats.js';
|
|
5
4
|
import './polyfills.js';
|
|
6
5
|
const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from './backends/store/store.js';
|
|
|
10
10
|
export * from './backends/backend.js';
|
|
11
11
|
export * from './config.js';
|
|
12
12
|
export * from './credentials.js';
|
|
13
|
+
export * from './devices.js';
|
|
14
|
+
export { default as devices } from './devices.js';
|
|
13
15
|
export * from './file.js';
|
|
14
16
|
export * from './filesystem.js';
|
|
15
17
|
export * from './inode.js';
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@ export * from './backends/store/store.js';
|
|
|
10
10
|
export * from './backends/backend.js';
|
|
11
11
|
export * from './config.js';
|
|
12
12
|
export * from './credentials.js';
|
|
13
|
+
export * from './devices.js';
|
|
14
|
+
export { default as devices } from './devices.js';
|
|
13
15
|
export * from './file.js';
|
|
14
16
|
export * from './filesystem.js';
|
|
15
17
|
export * from './inode.js';
|
package/dist/inode.d.ts
CHANGED
|
@@ -4,11 +4,6 @@ import { Stats, type StatsLike } from './stats.js';
|
|
|
4
4
|
* This will be helpful if in the future inode numbers/IDs are changed to strings or numbers.
|
|
5
5
|
*/
|
|
6
6
|
export type Ino = bigint;
|
|
7
|
-
/**
|
|
8
|
-
* Max 32-bit integer
|
|
9
|
-
* @hidden
|
|
10
|
-
*/
|
|
11
|
-
export declare const size_max: number;
|
|
12
7
|
/**
|
|
13
8
|
* Room inode
|
|
14
9
|
* @hidden
|
package/dist/inode.js
CHANGED
|
@@ -38,11 +38,6 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
|
|
|
38
38
|
};
|
|
39
39
|
import { Stats } from './stats.js';
|
|
40
40
|
import { types as t, struct, sizeof, serialize, deserialize } from 'utilium';
|
|
41
|
-
/**
|
|
42
|
-
* Max 32-bit integer
|
|
43
|
-
* @hidden
|
|
44
|
-
*/
|
|
45
|
-
export const size_max = 2 ** 32 - 1;
|
|
46
41
|
/**
|
|
47
42
|
* Room inode
|
|
48
43
|
* @hidden
|
package/dist/stats.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { credentials } from './credentials.js';
|
|
2
|
-
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
|
|
3
|
-
import { size_max } from './inode.js';
|
|
2
|
+
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU, size_max } from './emulation/constants.js';
|
|
4
3
|
/**
|
|
5
4
|
* Provides information about a particular entry in the file system.
|
|
6
5
|
* Common code used by both Stats and BigIntStats.
|
package/dist/utils.d.ts
CHANGED
|
@@ -17,20 +17,30 @@ export declare function mkdirpSync(path: string, mode: number, fs: FileSystem):
|
|
|
17
17
|
* @hidden
|
|
18
18
|
*/
|
|
19
19
|
export declare function levenshtein(a: string, b: string): number;
|
|
20
|
+
/** @hidden */
|
|
21
|
+
export declare const setImmediate: (callback: () => unknown) => void;
|
|
20
22
|
/**
|
|
21
|
-
*
|
|
23
|
+
* Encodes a string into a buffer
|
|
24
|
+
* @internal
|
|
22
25
|
*/
|
|
23
|
-
export declare
|
|
26
|
+
export declare function encodeRaw(input: string): Uint8Array;
|
|
27
|
+
/**
|
|
28
|
+
* Decodes a string from a buffer
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export declare function decodeRaw(input?: Uint8Array): string;
|
|
24
32
|
/**
|
|
25
33
|
* Encodes a string into a buffer
|
|
26
34
|
* @internal
|
|
27
35
|
*/
|
|
28
|
-
export declare function
|
|
36
|
+
export declare function encodeUTF8(input: string): Uint8Array;
|
|
37
|
+
export { /** @deprecated @hidden */ encodeUTF8 as encode };
|
|
29
38
|
/**
|
|
30
39
|
* Decodes a string from a buffer
|
|
31
40
|
* @internal
|
|
32
41
|
*/
|
|
33
|
-
export declare function
|
|
42
|
+
export declare function decodeUTF8(input?: Uint8Array): string;
|
|
43
|
+
export { /** @deprecated @hidden */ decodeUTF8 as decode };
|
|
34
44
|
/**
|
|
35
45
|
* Decodes a directory listing
|
|
36
46
|
* @hidden
|
package/dist/utils.js
CHANGED
|
@@ -83,45 +83,67 @@ export function levenshtein(a, b) {
|
|
|
83
83
|
}
|
|
84
84
|
return dd;
|
|
85
85
|
}
|
|
86
|
+
/** @hidden */
|
|
87
|
+
export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : (cb) => setTimeout(cb, 0);
|
|
86
88
|
/**
|
|
87
|
-
*
|
|
89
|
+
* Encodes a string into a buffer
|
|
90
|
+
* @internal
|
|
88
91
|
*/
|
|
89
|
-
export
|
|
92
|
+
export function encodeRaw(input) {
|
|
93
|
+
if (typeof input != 'string') {
|
|
94
|
+
throw new ErrnoError(Errno.EINVAL, 'Can not encode a non-string');
|
|
95
|
+
}
|
|
96
|
+
return new Uint8Array(Array.from(input).map(char => char.charCodeAt(0)));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Decodes a string from a buffer
|
|
100
|
+
* @internal
|
|
101
|
+
*/
|
|
102
|
+
export function decodeRaw(input) {
|
|
103
|
+
if (!(input instanceof Uint8Array)) {
|
|
104
|
+
throw new ErrnoError(Errno.EINVAL, 'Can not decode a non-Uint8Array');
|
|
105
|
+
}
|
|
106
|
+
return Array.from(input)
|
|
107
|
+
.map(char => String.fromCharCode(char))
|
|
108
|
+
.join('');
|
|
109
|
+
}
|
|
90
110
|
const encoder = new TextEncoder();
|
|
91
111
|
/**
|
|
92
112
|
* Encodes a string into a buffer
|
|
93
113
|
* @internal
|
|
94
114
|
*/
|
|
95
|
-
export function
|
|
115
|
+
export function encodeUTF8(input) {
|
|
96
116
|
if (typeof input != 'string') {
|
|
97
117
|
throw new ErrnoError(Errno.EINVAL, 'Can not encode a non-string');
|
|
98
118
|
}
|
|
99
119
|
return encoder.encode(input);
|
|
100
120
|
}
|
|
121
|
+
export { /** @deprecated @hidden */ encodeUTF8 as encode };
|
|
101
122
|
const decoder = new TextDecoder();
|
|
102
123
|
/**
|
|
103
124
|
* Decodes a string from a buffer
|
|
104
125
|
* @internal
|
|
105
126
|
*/
|
|
106
|
-
export function
|
|
127
|
+
export function decodeUTF8(input) {
|
|
107
128
|
if (!(input instanceof Uint8Array)) {
|
|
108
129
|
throw new ErrnoError(Errno.EINVAL, 'Can not decode a non-Uint8Array');
|
|
109
130
|
}
|
|
110
131
|
return decoder.decode(input);
|
|
111
132
|
}
|
|
133
|
+
export { /** @deprecated @hidden */ decodeUTF8 as decode };
|
|
112
134
|
/**
|
|
113
135
|
* Decodes a directory listing
|
|
114
136
|
* @hidden
|
|
115
137
|
*/
|
|
116
138
|
export function decodeDirListing(data) {
|
|
117
|
-
return JSON.parse(
|
|
139
|
+
return JSON.parse(decodeUTF8(data), (k, v) => (k == '' ? v : BigInt(v)));
|
|
118
140
|
}
|
|
119
141
|
/**
|
|
120
142
|
* Encodes a directory listing
|
|
121
143
|
* @hidden
|
|
122
144
|
*/
|
|
123
145
|
export function encodeDirListing(data) {
|
|
124
|
-
return
|
|
146
|
+
return encodeUTF8(JSON.stringify(data, (k, v) => (k == '' ? v : v.toString())));
|
|
125
147
|
}
|
|
126
148
|
/**
|
|
127
149
|
* converts Date or number to a integer UNIX timestamp
|