@bytecodealliance/preview2-shim 0.0.15 → 0.0.17

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