@bytecodealliance/preview2-shim 0.0.16 → 0.0.18
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/lib/browser/filesystem.js +4 -2
- package/lib/browser/index.js +3 -7
- package/lib/browser/io.js +8 -99
- package/lib/common/io.js +165 -0
- package/lib/http/wasi-http.js +346 -334
- package/lib/nodejs/cli.js +57 -18
- package/lib/nodejs/filesystem.js +420 -345
- package/lib/nodejs/http.js +4 -129
- package/lib/nodejs/index.js +4 -7
- package/package.json +5 -1
- package/types/interfaces/wasi-cli-terminal-input.d.ts +0 -11
- package/types/interfaces/wasi-cli-terminal-output.d.ts +0 -11
- package/types/interfaces/wasi-clocks-monotonic-clock.d.ts +1 -1
- package/types/interfaces/wasi-clocks-timezone.d.ts +2 -17
- package/types/interfaces/wasi-filesystem-types.d.ts +75 -67
- package/types/interfaces/wasi-io-poll.d.ts +30 -0
- package/types/interfaces/wasi-io-streams.d.ts +123 -143
- package/types/interfaces/wasi-random-random.d.ts +13 -11
- package/types/interfaces/wasi-sockets-ip-name-lookup.d.ts +10 -14
- package/types/interfaces/wasi-sockets-network.d.ts +15 -57
- package/types/interfaces/wasi-sockets-tcp-create-socket.d.ts +2 -3
- package/types/interfaces/wasi-sockets-tcp.d.ts +91 -93
- package/types/interfaces/wasi-sockets-udp-create-socket.d.ts +2 -3
- package/types/interfaces/wasi-sockets-udp.d.ts +49 -56
- package/types/wasi-cli-command.d.ts +1 -1
- package/lib/browser/logging.js +0 -14
- package/lib/http/error.js +0 -11
- package/lib/nodejs/io.js +0 -160
- package/lib/nodejs/logging.js +0 -14
- package/types/interfaces/wasi-poll-poll.d.ts +0 -39
package/lib/nodejs/filesystem.js
CHANGED
|
@@ -1,78 +1,437 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let preopenCnt = 4;
|
|
6
|
-
export let _descriptors = {
|
|
7
|
-
3: { type: 'directory', path: '/', parent: null, subpathTypes: {} }
|
|
8
|
-
};
|
|
9
|
-
let directories = [[3, '/']];
|
|
10
|
-
|
|
11
|
-
export function _setPreopens (preopens) {
|
|
12
|
-
_descriptors = {};
|
|
13
|
-
directories = [,,];
|
|
14
|
-
for (const [virtualPath, path] of Object.entries(preopens)) {
|
|
15
|
-
_descriptors[preopenCnt] = { type: 'directory', path, parent: null, subpathTypes: {} };
|
|
16
|
-
directories.push([preopenCnt++, virtualPath]);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
1
|
+
import { streams } from '../common/io.js';
|
|
2
|
+
import { environment } from './cli.js';
|
|
3
|
+
import { constants, readSync, openSync, opendirSync, closeSync, fstatSync, lstatSync, statSync, writeSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import { platform } from 'node:process';
|
|
19
5
|
|
|
20
|
-
|
|
21
|
-
let path = '';
|
|
22
|
-
while (fd) {
|
|
23
|
-
path = _descriptors[fd].path + path;
|
|
24
|
-
fd = _descriptors[fd].parent;
|
|
25
|
-
}
|
|
26
|
-
return path;
|
|
27
|
-
}
|
|
6
|
+
const { InputStream, OutputStream, Error: StreamError } = streams;
|
|
28
7
|
|
|
29
|
-
|
|
30
|
-
return _descriptors[fd].type;
|
|
31
|
-
}
|
|
8
|
+
const isWindows = platform === 'win32';
|
|
32
9
|
|
|
33
|
-
|
|
34
|
-
|
|
10
|
+
const nsMagnitude = 1_000_000_000_000n;
|
|
11
|
+
function nsToDateTime (ns) {
|
|
12
|
+
const seconds = ns / nsMagnitude;
|
|
13
|
+
const nanoseconds = Number(ns % seconds);
|
|
14
|
+
return { seconds, nanoseconds };
|
|
35
15
|
}
|
|
36
16
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
17
|
+
function lookupType (obj) {
|
|
18
|
+
if (obj.isFile())
|
|
19
|
+
return 'regular-file';
|
|
20
|
+
else if (obj.isSocket())
|
|
21
|
+
return 'socket';
|
|
22
|
+
else if (obj.isSymbolicLink())
|
|
23
|
+
return 'symbolic-link';
|
|
24
|
+
else if (obj.isFIFO())
|
|
25
|
+
return 'fifo';
|
|
26
|
+
else if (obj.isDirectory())
|
|
27
|
+
return 'directory';
|
|
28
|
+
else if (obj.isCharacterDevice())
|
|
29
|
+
return 'character-device';
|
|
30
|
+
else if (obj.isBlockDevice())
|
|
31
|
+
return 'block-device';
|
|
32
|
+
return 'unknown';
|
|
43
33
|
}
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {
|
|
37
|
+
* { hostPreopen: string } |
|
|
38
|
+
* { fullPath: string, fd: number }
|
|
39
|
+
* } DescriptorProps
|
|
40
|
+
*/
|
|
41
|
+
export class FileSystem {
|
|
42
|
+
// Note: This should implement per-segment semantics of openAt, but we cannot currently
|
|
43
|
+
// due to the lack of support for openat() in Node.js.
|
|
44
|
+
// Tracking issue: https://github.com/libuv/libuv/issues/4167
|
|
45
|
+
|
|
46
|
+
// TODO: support followSymlinks
|
|
47
|
+
getFullPath (descriptor, subpath, _followSymlinks) {
|
|
48
|
+
if (subpath.indexOf('\\') !== -1)
|
|
49
|
+
subpath = subpath.replace(/\\/g, '/');
|
|
50
|
+
if (subpath[0] === '/') {
|
|
51
|
+
let bestPreopenMatch = '';
|
|
52
|
+
for (const preopenEntry of this.preopenEntries) {
|
|
53
|
+
if (subpath.startsWith(preopenEntry[1]) && (!bestPreopenMatch || bestPreopenMatch.length < preopenEntry[1].length)) {
|
|
54
|
+
bestPreopenMatch = preopenEntry;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!bestPreopenMatch)
|
|
58
|
+
throw 'no-entry';
|
|
59
|
+
descriptor = bestPreopenMatch[0];
|
|
60
|
+
subpath = subpath.slice(bestPreopenMatch[1]);
|
|
61
|
+
if (subpath[0] === '/')
|
|
62
|
+
subpath = subpath.slice(1);
|
|
63
|
+
}
|
|
64
|
+
if (subpath.startsWith('.'))
|
|
65
|
+
subpath = subpath.slice(subpath[1] === '/' ? 2 : 1);
|
|
66
|
+
if (descriptor.hostPreopen)
|
|
67
|
+
return descriptor.hostPreopen + (descriptor.hostPreopen.endsWith('/') ? '' : '/') + subpath;
|
|
68
|
+
return descriptor.fullPath + '/' + subpath;
|
|
52
69
|
}
|
|
53
|
-
_descriptors[fd] = { path, type, parent: parentFd, subpathTypes: {} };
|
|
54
|
-
}
|
|
55
70
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @param {[string, string][]} preopens
|
|
74
|
+
* @param {import('./cli.js').environment} environment
|
|
75
|
+
* @returns
|
|
76
|
+
*/
|
|
77
|
+
constructor (preopens, environment) {
|
|
78
|
+
const fs = this;
|
|
79
|
+
this.cwd = environment.initialCwd();
|
|
80
|
+
|
|
81
|
+
class FileInputStream extends InputStream {
|
|
82
|
+
constructor (hostFd, position) {
|
|
83
|
+
super({
|
|
84
|
+
blockingRead (len) {
|
|
85
|
+
const buf = new Uint8Array(Number(len));
|
|
86
|
+
try {
|
|
87
|
+
var bytesRead = readSync(this.hostFd, buf, 0, buf.byteLength, this.position);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
throw { tag: 'last-operation-failed', val: new StreamError(e.message) };
|
|
90
|
+
}
|
|
91
|
+
this.position += bytesRead;
|
|
92
|
+
if (bytesRead < buf.byteLength) {
|
|
93
|
+
if (bytesRead === 0)
|
|
94
|
+
throw { tag: 'closed' };
|
|
95
|
+
return new Uint8Array(buf.buffer, 0, bytesRead);
|
|
96
|
+
}
|
|
97
|
+
return buf;
|
|
98
|
+
},
|
|
99
|
+
subscribe () {
|
|
100
|
+
// TODO
|
|
101
|
+
},
|
|
102
|
+
drop () {
|
|
103
|
+
// TODO
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
this.hostFd = hostFd;
|
|
107
|
+
this.position = Number(position);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
class FileOutputStream extends OutputStream {
|
|
112
|
+
constructor (hostFd, position) {
|
|
113
|
+
super({
|
|
114
|
+
write (contents) {
|
|
115
|
+
let totalWritten = 0;
|
|
116
|
+
while (totalWritten !== contents.byteLength) {
|
|
117
|
+
const bytesWritten = writeSync(this.hostFd, contents, null, null, this.position);
|
|
118
|
+
totalWritten += bytesWritten;
|
|
119
|
+
contents = new Uint8Array(contents.buffer, bytesWritten);
|
|
120
|
+
}
|
|
121
|
+
this.position += contents.byteLength;
|
|
122
|
+
},
|
|
123
|
+
blockingFlush () {
|
|
124
|
+
|
|
125
|
+
},
|
|
126
|
+
drop () {
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
this.hostFd = hostFd;
|
|
131
|
+
this.position = Number(position);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
class DirectoryEntryStream {
|
|
136
|
+
constructor (dir) {
|
|
137
|
+
this.dir = dir;
|
|
138
|
+
}
|
|
139
|
+
readDirectoryEntry () {
|
|
140
|
+
let entry;
|
|
141
|
+
try {
|
|
142
|
+
entry = this.dir.readSync();
|
|
143
|
+
} catch (e) {
|
|
144
|
+
throw convertFsError(e);
|
|
145
|
+
}
|
|
146
|
+
if (entry === null) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const name = entry.name;
|
|
150
|
+
const type = lookupType(entry);
|
|
151
|
+
return { name, type };
|
|
152
|
+
}
|
|
153
|
+
drop () {
|
|
154
|
+
this.dir.closeSync();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @implements {DescriptorProps}
|
|
160
|
+
*/
|
|
161
|
+
class Descriptor {
|
|
162
|
+
constructor () {
|
|
163
|
+
this.id = fs.descriptorCnt++;
|
|
164
|
+
}
|
|
165
|
+
readViaStream(offset) {
|
|
166
|
+
if (this.hostPreopen)
|
|
167
|
+
throw { tag: 'last-operation-failed', val: new StreamError };
|
|
168
|
+
return new FileInputStream(this.fd, offset);
|
|
169
|
+
}
|
|
170
|
+
writeViaStream(offset) {
|
|
171
|
+
if (this.hostPreopen)
|
|
172
|
+
throw 'is-directory';
|
|
173
|
+
return new FileOutputStream(this.fd, offset);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
appendViaStream() {
|
|
177
|
+
console.log(`[filesystem] APPEND STREAM ${this.id}`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
advise(offset, length, advice) {
|
|
181
|
+
console.log(`[filesystem] ADVISE`, this.id, offset, length, advice);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
syncData() {
|
|
185
|
+
console.log(`[filesystem] SYNC DATA ${this.id}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
getFlags() {
|
|
189
|
+
console.log(`[filesystem] FLAGS FOR ${this.id}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
getType() {
|
|
193
|
+
if (this.hostPreopen) return 'directory';
|
|
194
|
+
const stats = fstatSync(this.fd);
|
|
195
|
+
return lookupType(stats);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
setFlags(flags) {
|
|
199
|
+
console.log(`[filesystem] SET FLAGS ${this.id} ${JSON.stringify(flags)}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
setSize(size) {
|
|
203
|
+
console.log(`[filesystem] SET SIZE`, this.id, size);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
setTimes(dataAccessTimestamp, dataModificationTimestamp) {
|
|
207
|
+
console.log(`[filesystem] SET TIMES`, this.id, dataAccessTimestamp, dataModificationTimestamp);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
read(length, offset) {
|
|
211
|
+
if (!this.fullPath) throw 'bad-descriptor';
|
|
212
|
+
const buf = new Uint8Array(length);
|
|
213
|
+
const bytesRead = readSync(this.fd, buf, Number(offset), length, 0);
|
|
214
|
+
const out = new Uint8Array(buf.buffer, 0, bytesRead);
|
|
215
|
+
return [out, bytesRead === 0 ? 'ended' : 'open'];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
write(buffer, offset) {
|
|
219
|
+
if (!this.fullPath) throw 'bad-descriptor';
|
|
220
|
+
return BigInt(writeSync(this.fd, buffer, Number(offset), buffer.byteLength - offset, 0));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
readDirectory() {
|
|
224
|
+
if (!this.fullPath) throw 'bad-descriptor';
|
|
225
|
+
try {
|
|
226
|
+
const dir = opendirSync(isWindows ? this.fullPath.slice(1) : this.fullPath);
|
|
227
|
+
return new DirectoryEntryStream(dir);
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
throw convertFsError(e);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
sync() {
|
|
235
|
+
console.log(`[filesystem] SYNC`, this.id);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
createDirectoryAt(path) {
|
|
239
|
+
const fullPath = fs.getFullPath(this, path);
|
|
240
|
+
try {
|
|
241
|
+
mkdirSync(fullPath);
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
throw convertFsError(e);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
stat() {
|
|
249
|
+
if (this.hostPreopen) throw 'invalid';
|
|
250
|
+
let stats;
|
|
251
|
+
try {
|
|
252
|
+
stats = fstatSync(this.fd, { bigint: true });
|
|
253
|
+
}
|
|
254
|
+
catch (e) {
|
|
255
|
+
convertFsError(e);
|
|
256
|
+
}
|
|
257
|
+
const type = lookupType(stats);
|
|
258
|
+
return {
|
|
259
|
+
type,
|
|
260
|
+
linkCount: stats.nlink,
|
|
261
|
+
size: stats.size,
|
|
262
|
+
dataAccessTimestamp: nsToDateTime(stats.atimeNs),
|
|
263
|
+
dataModificationTimestamp: nsToDateTime(stats.mtimeNs),
|
|
264
|
+
statusChangeTimestamp: nsToDateTime(stats.ctimeNs),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
statAt(pathFlags, path) {
|
|
269
|
+
const fullPath = fs.getFullPath(this, path, false);
|
|
270
|
+
let stats;
|
|
271
|
+
try {
|
|
272
|
+
stats = (pathFlags.symlinkFollow ? statSync : lstatSync)(isWindows ? fullPath.slice(1) : fullPath, { bigint: true });
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
convertFsError(e);
|
|
276
|
+
}
|
|
277
|
+
const type = lookupType(stats);
|
|
278
|
+
return {
|
|
279
|
+
type,
|
|
280
|
+
linkCount: stats.nlink,
|
|
281
|
+
size: stats.size,
|
|
282
|
+
dataAccessTimestamp: nsToDateTime(stats.atimeNs),
|
|
283
|
+
dataModificationTimestamp: nsToDateTime(stats.mtimeNs),
|
|
284
|
+
statusChangeTimestamp: nsToDateTime(stats.ctimeNs),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
setTimesAt() {
|
|
289
|
+
console.log(`[filesystem] SET TIMES AT`, this.id);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
linkAt() {
|
|
293
|
+
console.log(`[filesystem] LINK AT`, this.id);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
openAt(pathFlags, path, openFlags, descriptorFlags, modes) {
|
|
297
|
+
const fullPath = fs.getFullPath(this, path, pathFlags.symlinkFollow);
|
|
298
|
+
let fsOpenFlags = 0x0;
|
|
299
|
+
if (openFlags.create)
|
|
300
|
+
fsOpenFlags |= constants.O_CREAT;
|
|
301
|
+
if (openFlags.directory)
|
|
302
|
+
fsOpenFlags |= constants.O_DIRECTORY;
|
|
303
|
+
if (openFlags.exclusive)
|
|
304
|
+
fsOpenFlags |= constants.O_EXCL;
|
|
305
|
+
if (openFlags.truncate)
|
|
306
|
+
fsOpenFlags |= constants.O_TRUNC;
|
|
307
|
+
|
|
308
|
+
if (descriptorFlags.read && descriptorFlags.write)
|
|
309
|
+
fsOpenFlags |= constants.O_RDWR;
|
|
310
|
+
else if (descriptorFlags.write)
|
|
311
|
+
fsOpenFlags |= constants.O_WRONLY;
|
|
312
|
+
// TODO:
|
|
313
|
+
// if (descriptorFlags.fileIntegritySync)
|
|
314
|
+
// if (descriptorFlags.dataIntegritySync)
|
|
315
|
+
// if (descriptorFlags.requestedWriteSync)
|
|
316
|
+
// if (descriptorFlags.mutateDirectory)
|
|
317
|
+
|
|
318
|
+
let fsMode = 0x0;
|
|
319
|
+
if (modes.readable)
|
|
320
|
+
fsMode |= 0o444;
|
|
321
|
+
if (modes.writeable)
|
|
322
|
+
fsMode |= 0o222;
|
|
323
|
+
if (modes.executable)
|
|
324
|
+
fsMode |= 0o111;
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
const fd = openSync(isWindows ? fullPath.slice(1) : fullPath, fsOpenFlags, fsMode);
|
|
328
|
+
return Object.assign(new Descriptor(), { fullPath, fd });
|
|
329
|
+
}
|
|
330
|
+
catch (e) {
|
|
331
|
+
throw convertFsError(e);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
readlinkAt() {
|
|
336
|
+
console.log(`[filesystem] READLINK AT`, this.id);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
removeDirectoryAt() {
|
|
340
|
+
console.log(`[filesystem] REMOVE DIR AT`, this.id);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
renameAt() {
|
|
344
|
+
console.log(`[filesystem] RENAME AT`, this.id);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
symlinkAt() {
|
|
348
|
+
console.log(`[filesystem] SYMLINK AT`, this.id);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
unlinkFileAt() {
|
|
352
|
+
console.log(`[filesystem] UNLINK FILE AT`, this.id);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
changeFilePermissionsAt() {
|
|
356
|
+
console.log(`[filesystem] CHANGE FILE PERMISSIONS AT`, this.id);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
changeDirectoryPermissionsAt() {
|
|
360
|
+
console.log(`[filesystem] CHANGE DIR PERMISSIONS AT`, this.id);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
lockShared() {
|
|
364
|
+
console.log(`[filesystem] LOCK SHARED`, this.id);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
lockExclusive() {
|
|
368
|
+
console.log(`[filesystem] LOCK EXCLUSIVE`, this.id);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
tryLockShared() {
|
|
372
|
+
console.log(`[filesystem] TRY LOCK SHARED`, this.id);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
tryLockExclusive() {
|
|
376
|
+
console.log(`[filesystem] TRY LOCK EXCLUSIVE`, this.id);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
unlock() {
|
|
380
|
+
console.log(`[filesystem] UNLOCK`, this.id);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
drop() {
|
|
384
|
+
if (this.fd)
|
|
385
|
+
closeSync(this.fd);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
metadataHash() {
|
|
389
|
+
if (this.hostPreopen)
|
|
390
|
+
return { upper: 0n, lower: BigInt(this.id) };
|
|
391
|
+
try {
|
|
392
|
+
const stats = fstatSync(this.fd, { bigint: true });
|
|
393
|
+
return { upper: stats.mtimeNs, lower: stats.ino };
|
|
394
|
+
}
|
|
395
|
+
catch (e) {
|
|
396
|
+
convertFsError(e);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
metadataHashAt(pathFlags, path) {
|
|
401
|
+
const fullPath = fs.getFullPath(this, path, false);
|
|
402
|
+
try {
|
|
403
|
+
const stats = (pathFlags.symlinkFollow ? statSync : lstatSync)(isWindows ? fullPath.slice(1) : fullPath, { bigint: true });
|
|
404
|
+
return { upper: stats.mtimeNs, lower: stats.ino };
|
|
405
|
+
}
|
|
406
|
+
catch (e) {
|
|
407
|
+
convertFsError(e);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
61
411
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
412
|
+
this.descriptorCnt = 3;
|
|
413
|
+
this.preopenEntries = [];
|
|
414
|
+
for (const [virtualPath, hostPreopen] of Object.entries(preopens)) {
|
|
415
|
+
const preopenEntry = [Object.assign(new Descriptor(), { hostPreopen }), virtualPath];
|
|
416
|
+
this.preopenEntries.push(preopenEntry);
|
|
417
|
+
}
|
|
418
|
+
this.preopens = {
|
|
419
|
+
Descriptor,
|
|
420
|
+
getDirectories () {
|
|
421
|
+
return fs.preopenEntries;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
this.types = {
|
|
425
|
+
Descriptor,
|
|
426
|
+
};
|
|
65
427
|
}
|
|
66
428
|
}
|
|
67
429
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const nanoseconds = Number(ns % seconds);
|
|
72
|
-
return { seconds, nanoseconds };
|
|
73
|
-
}
|
|
430
|
+
const _fs = new FileSystem({ '/': '/' }, environment);
|
|
431
|
+
|
|
432
|
+
export const { preopens, types } = _fs;
|
|
74
433
|
|
|
75
|
-
function
|
|
434
|
+
function convertFsError (e) {
|
|
76
435
|
switch (e.code) {
|
|
77
436
|
case 'EACCES': throw 'access';
|
|
78
437
|
case 'EAGAIN':
|
|
@@ -115,287 +474,3 @@ function _convertFsError (e) {
|
|
|
115
474
|
default: throw e;
|
|
116
475
|
}
|
|
117
476
|
}
|
|
118
|
-
|
|
119
|
-
function _lookupType (obj) {
|
|
120
|
-
if (obj.isFile())
|
|
121
|
-
return 'regular-file';
|
|
122
|
-
else if (obj.isSocket())
|
|
123
|
-
return 'socket';
|
|
124
|
-
else if (obj.isSymbolicLink())
|
|
125
|
-
return 'symbolic-link';
|
|
126
|
-
else if (obj.isFIFO())
|
|
127
|
-
return 'fifo';
|
|
128
|
-
else if (obj.isDirectory())
|
|
129
|
-
return 'directory';
|
|
130
|
-
else if (obj.isCharacterDevice())
|
|
131
|
-
return 'character-device';
|
|
132
|
-
else if (obj.isBlockDevice())
|
|
133
|
-
return 'block-device';
|
|
134
|
-
return 'unknown';
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export const types = {
|
|
138
|
-
readViaStream(fd, offset) {
|
|
139
|
-
if (Number(offset) !== 0)
|
|
140
|
-
throw new Error('Read streams with non-zero offset not currently supported');
|
|
141
|
-
const stream = _createFsStream(fd, 'file', { offset: 0 });
|
|
142
|
-
return stream;
|
|
143
|
-
},
|
|
144
|
-
|
|
145
|
-
writeViaStream(fd, offset) {
|
|
146
|
-
console.log(`[filesystem] WRITE STREAM ${fd} ${offset}`);
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
appendViaStream(fd) {
|
|
150
|
-
console.log(`[filesystem] APPEND STREAM ${fd}`);
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
advise(fd, offset, length, advice) {
|
|
154
|
-
console.log(`[filesystem] ADVISE`, fd, offset, length, advice);
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
syncData(fd) {
|
|
158
|
-
console.log(`[filesystem] SYNC DATA ${fd}`);
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
getFlags(fd) {
|
|
162
|
-
console.log(`[filesystem] FLAGS FOR ${fd}`);
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
getType(fd) {
|
|
166
|
-
let type = _getDescriptorType(fd);
|
|
167
|
-
if (type === null) {
|
|
168
|
-
types.stat(fd);
|
|
169
|
-
type = _getDescriptorType(fd);
|
|
170
|
-
}
|
|
171
|
-
return type;
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
setFlags(fd, flags) {
|
|
175
|
-
console.log(`[filesystem] SET FLAGS ${fd} ${JSON.stringify(flags)}`);
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
setSize(fd, size) {
|
|
179
|
-
console.log(`[filesystem] SET SIZE`, fd, size);
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
setTimes(fd, dataAccessTimestamp, dataModificationTimestamp) {
|
|
183
|
-
console.log(`[filesystem] SET TIMES`, fd, dataAccessTimestamp, dataModificationTimestamp);
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
read(fd, length, offset) {
|
|
187
|
-
console.log(`[filesystem] READ`, fd, length, offset);
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
write(fd, buffer, offset) {
|
|
191
|
-
console.log(`[filesystem] WRITE`, fd, buffer, offset);
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
readDirectory(fd) {
|
|
195
|
-
const fullPath = _getFullPath(fd);
|
|
196
|
-
let dirs;
|
|
197
|
-
try {
|
|
198
|
-
dirs = readdirSync(fullPath, { withFileTypes: true });
|
|
199
|
-
}
|
|
200
|
-
catch (e) {
|
|
201
|
-
_convertFsError(e);
|
|
202
|
-
}
|
|
203
|
-
return _createFsStream(fd, 'dir', { dirs, cursor: 0, fd });
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
sync(fd) {
|
|
207
|
-
console.log(`[filesystem] SYNC`, fd);
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
createDirectoryAt(fd, path) {
|
|
211
|
-
console.log(`[filesystem] CREATE DIRECTORY`, fd, path);
|
|
212
|
-
},
|
|
213
|
-
|
|
214
|
-
stat(fd) {
|
|
215
|
-
let stats;
|
|
216
|
-
try {
|
|
217
|
-
stats = fstatSync(fd, { bigint: true });
|
|
218
|
-
}
|
|
219
|
-
catch (e) {
|
|
220
|
-
_convertFsError(e);
|
|
221
|
-
}
|
|
222
|
-
const type = _lookupType(stats);
|
|
223
|
-
_setDescriptorType(fd, type);
|
|
224
|
-
return {
|
|
225
|
-
device: stats.dev,
|
|
226
|
-
inode: stats.ino,
|
|
227
|
-
type,
|
|
228
|
-
linkCount: stats.nlink,
|
|
229
|
-
size: stats.size,
|
|
230
|
-
dataAccessTimestamp: nsToDateTime(stats.atimeNs),
|
|
231
|
-
dataModificationTimestamp: nsToDateTime(stats.mtimeNs),
|
|
232
|
-
statusChangeTimestamp: nsToDateTime(stats.ctimeNs),
|
|
233
|
-
};
|
|
234
|
-
},
|
|
235
|
-
|
|
236
|
-
statAt(fd, { symlinkFollow }, path) {
|
|
237
|
-
const fullPath = _descriptors[fd].path + path;
|
|
238
|
-
let stats;
|
|
239
|
-
try {
|
|
240
|
-
stats = (symlinkFollow ? statSync : lstatSync)(fullPath, { bigint: true });
|
|
241
|
-
}
|
|
242
|
-
catch (e) {
|
|
243
|
-
_convertFsError(e);
|
|
244
|
-
}
|
|
245
|
-
const type = _lookupType(stats);
|
|
246
|
-
_setSubdescriptorType(fd, path, type);
|
|
247
|
-
return {
|
|
248
|
-
device: stats.dev,
|
|
249
|
-
inode: stats.ino,
|
|
250
|
-
type,
|
|
251
|
-
linkCount: stats.nlink,
|
|
252
|
-
size: stats.size,
|
|
253
|
-
dataAccessTimestamp: nsToDateTime(stats.atimeNs),
|
|
254
|
-
dataModificationTimestamp: nsToDateTime(stats.mtimeNs),
|
|
255
|
-
statusChangeTimestamp: nsToDateTime(stats.ctimeNs),
|
|
256
|
-
};
|
|
257
|
-
},
|
|
258
|
-
|
|
259
|
-
setTimesAt(fd) {
|
|
260
|
-
console.log(`[filesystem] SET TIMES AT`, fd);
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
linkAt(fd) {
|
|
264
|
-
console.log(`[filesystem] LINK AT`, fd);
|
|
265
|
-
},
|
|
266
|
-
|
|
267
|
-
openAt(fd, pathFlags, path, openFlags, descriptorFlags, modes) {
|
|
268
|
-
// TODO
|
|
269
|
-
// if (pathFlags.symlinkFollow) {
|
|
270
|
-
// // resolve symlink
|
|
271
|
-
// }
|
|
272
|
-
const fullPath = _descriptors[fd].path + path;
|
|
273
|
-
let fsOpenFlags = 0x0;
|
|
274
|
-
if (openFlags.create)
|
|
275
|
-
fsOpenFlags |= constants.O_CREAT;
|
|
276
|
-
if (openFlags.directory)
|
|
277
|
-
fsOpenFlags |= constants.O_DIRECTORY;
|
|
278
|
-
if (openFlags.exclusive)
|
|
279
|
-
fsOpenFlags |= constants.O_EXCL;
|
|
280
|
-
if (openFlags.truncate)
|
|
281
|
-
fsOpenFlags |= constants.O_TRUNC;
|
|
282
|
-
if (descriptorFlags.read && descriptorFlags.write)
|
|
283
|
-
fsOpenFlags |= constants.O_RDWR;
|
|
284
|
-
else if (descriptorFlags.write)
|
|
285
|
-
fsOpenFlags |= constants.O_WRONLY;
|
|
286
|
-
// if (descriptorFlags.fileIntegritySync)
|
|
287
|
-
// if (descriptorFlags.dataIntegritySync)
|
|
288
|
-
// if (descriptorFlags.requestedWriteSync)
|
|
289
|
-
// if (descriptorFlags.mutateDirectory)
|
|
290
|
-
let fsMode = 0x0;
|
|
291
|
-
if (modes.readable)
|
|
292
|
-
fsMode |= 0o444;
|
|
293
|
-
if (modes.writeable)
|
|
294
|
-
fsMode |= 0o222;
|
|
295
|
-
if (modes.executable)
|
|
296
|
-
fsMode |= 0o111;
|
|
297
|
-
let localFd;
|
|
298
|
-
try {
|
|
299
|
-
localFd = openSync(fullPath, fsOpenFlags, fsMode);
|
|
300
|
-
}
|
|
301
|
-
catch (e) {
|
|
302
|
-
_convertFsError(e);
|
|
303
|
-
}
|
|
304
|
-
_addOpenedDescriptor(localFd, path, fd);
|
|
305
|
-
return localFd;
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
readlinkAt(fd) {
|
|
309
|
-
console.log(`[filesystem] READLINK AT`, fd);
|
|
310
|
-
},
|
|
311
|
-
|
|
312
|
-
removeDirectoryAt(fd) {
|
|
313
|
-
console.log(`[filesystem] REMOVE DIR AT`, fd);
|
|
314
|
-
},
|
|
315
|
-
|
|
316
|
-
renameAt(fd) {
|
|
317
|
-
console.log(`[filesystem] RENAME AT`, fd);
|
|
318
|
-
},
|
|
319
|
-
|
|
320
|
-
symlinkAt(fd) {
|
|
321
|
-
console.log(`[filesystem] SYMLINK AT`, fd);
|
|
322
|
-
},
|
|
323
|
-
|
|
324
|
-
unlinkFileAt(fd) {
|
|
325
|
-
console.log(`[filesystem] UNLINK FILE AT`, fd);
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
changeFilePermissionsAt(fd) {
|
|
329
|
-
console.log(`[filesystem] CHANGE FILE PERMISSIONS AT`, fd);
|
|
330
|
-
},
|
|
331
|
-
|
|
332
|
-
changeDirectoryPermissionsAt(fd) {
|
|
333
|
-
console.log(`[filesystem] CHANGE DIR PERMISSIONS AT`, fd);
|
|
334
|
-
},
|
|
335
|
-
|
|
336
|
-
lockShared(fd) {
|
|
337
|
-
console.log(`[filesystem] LOCK SHARED`, fd);
|
|
338
|
-
},
|
|
339
|
-
|
|
340
|
-
lockExclusive(fd) {
|
|
341
|
-
console.log(`[filesystem] LOCK EXCLUSIVE`, fd);
|
|
342
|
-
},
|
|
343
|
-
|
|
344
|
-
tryLockShared(fd) {
|
|
345
|
-
console.log(`[filesystem] TRY LOCK SHARED`, fd);
|
|
346
|
-
},
|
|
347
|
-
|
|
348
|
-
tryLockExclusive(fd) {
|
|
349
|
-
console.log(`[filesystem] TRY LOCK EXCLUSIVE`, fd);
|
|
350
|
-
},
|
|
351
|
-
|
|
352
|
-
unlock(fd) {
|
|
353
|
-
console.log(`[filesystem] UNLOCK`, fd);
|
|
354
|
-
},
|
|
355
|
-
|
|
356
|
-
dropDescriptor(fd) {
|
|
357
|
-
_removeOpenedDescriptor(fd);
|
|
358
|
-
closeSync(fd);
|
|
359
|
-
},
|
|
360
|
-
|
|
361
|
-
readDirectoryEntry(stream) {
|
|
362
|
-
const streamValue = _getFsStreamContext(stream, 'dir');
|
|
363
|
-
if (streamValue.cursor === streamValue.dirs.length)
|
|
364
|
-
return null;
|
|
365
|
-
const dir = streamValue.dirs[streamValue.cursor++];
|
|
366
|
-
const type = _lookupType(dir);
|
|
367
|
-
_setSubdescriptorType(streamValue.fd, '/' + dir.name, type);
|
|
368
|
-
return { inode: null, type, name: dir.name };
|
|
369
|
-
},
|
|
370
|
-
|
|
371
|
-
dropDirectoryEntryStream(stream) {
|
|
372
|
-
_dropFsStream(stream);
|
|
373
|
-
},
|
|
374
|
-
|
|
375
|
-
metadataHash(fd) {
|
|
376
|
-
let stats;
|
|
377
|
-
try {
|
|
378
|
-
stats = fstatSync(fd, { bigint: true });
|
|
379
|
-
}
|
|
380
|
-
catch (e) {
|
|
381
|
-
_convertFsError(e);
|
|
382
|
-
}
|
|
383
|
-
const type = _lookupType(stats);
|
|
384
|
-
_setDescriptorType(fd, type);
|
|
385
|
-
return { upper: BigInt(stats.size), lower: stats.mtimeNs };
|
|
386
|
-
},
|
|
387
|
-
|
|
388
|
-
metadataHashAt(fd, { symlinkFollow }, path) {
|
|
389
|
-
const fullPath = _descriptors[fd].path + path;
|
|
390
|
-
let stats;
|
|
391
|
-
try {
|
|
392
|
-
stats = (symlinkFollow ? statSync : lstatSync)(fullPath, { bigint: true });
|
|
393
|
-
}
|
|
394
|
-
catch (e) {
|
|
395
|
-
_convertFsError(e);
|
|
396
|
-
}
|
|
397
|
-
const type = _lookupType(stats);
|
|
398
|
-
_setSubdescriptorType(fd, path, type);
|
|
399
|
-
return { upper: BigInt(stats.size), lower: stats.mtimeNs };
|
|
400
|
-
}
|
|
401
|
-
};
|