frida-fs 5.0.1 → 5.2.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/index.js ADDED
@@ -0,0 +1,974 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _ReadStream_input, _ReadStream_readRequest, _WriteStream_output, _WriteStream_writeRequest;
13
+ import { Buffer } from "buffer";
14
+ import fsPath from "path";
15
+ import process from "process";
16
+ import stream from "stream";
17
+ const getWindowsApi = memoize(_getWindowsApi);
18
+ const getPosixApi = memoize(_getPosixApi);
19
+ const { platform, pointerSize } = Process;
20
+ const isWindows = platform === "windows";
21
+ const S_IFMT = 0xf000;
22
+ const S_IFREG = 0x8000;
23
+ const S_IFDIR = 0x4000;
24
+ const S_IFCHR = 0x2000;
25
+ const S_IFBLK = 0x6000;
26
+ const S_IFIFO = 0x1000;
27
+ const S_IFLNK = 0xa000;
28
+ const S_IFSOCK = 0xc000;
29
+ const universalConstants = {
30
+ S_IFMT,
31
+ S_IFREG,
32
+ S_IFDIR,
33
+ S_IFCHR,
34
+ S_IFBLK,
35
+ S_IFIFO,
36
+ S_IFLNK,
37
+ S_IFSOCK,
38
+ S_IRWXU: 448,
39
+ S_IRUSR: 256,
40
+ S_IWUSR: 128,
41
+ S_IXUSR: 64,
42
+ S_IRWXG: 56,
43
+ S_IRGRP: 32,
44
+ S_IWGRP: 16,
45
+ S_IXGRP: 8,
46
+ S_IRWXO: 7,
47
+ S_IROTH: 4,
48
+ S_IWOTH: 2,
49
+ S_IXOTH: 1,
50
+ DT_UNKNOWN: 0,
51
+ DT_FIFO: 1,
52
+ DT_CHR: 2,
53
+ DT_DIR: 4,
54
+ DT_BLK: 6,
55
+ DT_REG: 8,
56
+ DT_LNK: 10,
57
+ DT_SOCK: 12,
58
+ DT_WHT: 14,
59
+ };
60
+ const platformConstants = {
61
+ darwin: {
62
+ O_RDONLY: 0x0,
63
+ O_WRONLY: 0x1,
64
+ O_RDWR: 0x2,
65
+ O_CREAT: 0x200,
66
+ O_EXCL: 0x800,
67
+ O_NOCTTY: 0x20000,
68
+ O_TRUNC: 0x400,
69
+ O_APPEND: 0x8,
70
+ O_DIRECTORY: 0x100000,
71
+ O_NOFOLLOW: 0x100,
72
+ O_SYNC: 0x80,
73
+ O_DSYNC: 0x400000,
74
+ O_SYMLINK: 0x200000,
75
+ O_NONBLOCK: 0x4,
76
+ },
77
+ linux: {
78
+ O_RDONLY: 0x0,
79
+ O_WRONLY: 0x1,
80
+ O_RDWR: 0x2,
81
+ O_CREAT: 0x40,
82
+ O_EXCL: 0x80,
83
+ O_NOCTTY: 0x100,
84
+ O_TRUNC: 0x200,
85
+ O_APPEND: 0x400,
86
+ O_DIRECTORY: 0x10000,
87
+ O_NOATIME: 0x40000,
88
+ O_NOFOLLOW: 0x20000,
89
+ O_SYNC: 0x101000,
90
+ O_DSYNC: 0x1000,
91
+ O_DIRECT: 0x4000,
92
+ O_NONBLOCK: 0x800,
93
+ },
94
+ };
95
+ const constants = {
96
+ ...universalConstants,
97
+ ...platformConstants[platform]
98
+ };
99
+ const INVALID_HANDLE_VALUE = ptr(-1);
100
+ const GENERIC_READ = 0x80000000;
101
+ const GENERIC_WRITE = 0x40000000;
102
+ const FILE_SHARE_READ = 0x1;
103
+ const FILE_SHARE_WRITE = 0x2;
104
+ const FILE_SHARE_DELETE = 0x4;
105
+ const CREATE_ALWAYS = 2;
106
+ const OPEN_EXISTING = 3;
107
+ const FILE_ATTRIBUTE_NORMAL = 0x80;
108
+ const FILE_ATTRIBUTE_DIRECTORY = 0x10;
109
+ const FILE_ATTRIBUTE_REPARSE_POINT = 0x400;
110
+ const IO_REPARSE_TAG_MOUNT_POINT = 0xa0000003;
111
+ const IO_REPARSE_TAG_SYMLINK = 0xa000000c;
112
+ const FILE_FLAG_OVERLAPPED = 0x40000000;
113
+ const FILE_FLAG_BACKUP_SEMANTICS = 0x2000000;
114
+ const ERROR_NOT_ENOUGH_MEMORY = 8;
115
+ const ERROR_SHARING_VIOLATION = 32;
116
+ const SEEK_SET = 0;
117
+ const SEEK_CUR = 1;
118
+ const SEEK_END = 2;
119
+ const EINTR = 4;
120
+ class ReadStream extends stream.Readable {
121
+ constructor(path) {
122
+ super({
123
+ highWaterMark: 4 * 1024 * 1024
124
+ });
125
+ _ReadStream_input.set(this, null);
126
+ _ReadStream_readRequest.set(this, null);
127
+ if (isWindows) {
128
+ const api = getWindowsApi();
129
+ const result = api.CreateFileW(Memory.allocUtf16String(path), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
130
+ const handle = result.value;
131
+ if (handle.equals(INVALID_HANDLE_VALUE)) {
132
+ process.nextTick(() => {
133
+ this.destroy(makeWindowsError(result.lastError));
134
+ });
135
+ return;
136
+ }
137
+ __classPrivateFieldSet(this, _ReadStream_input, new Win32InputStream(handle, { autoClose: true }), "f");
138
+ }
139
+ else {
140
+ const api = getPosixApi();
141
+ const result = api.open(Memory.allocUtf8String(path), constants.O_RDONLY, 0);
142
+ const fd = result.value;
143
+ if (fd === -1) {
144
+ process.nextTick(() => {
145
+ this.destroy(makePosixError(result.errno));
146
+ });
147
+ return;
148
+ }
149
+ __classPrivateFieldSet(this, _ReadStream_input, new UnixInputStream(fd, { autoClose: true }), "f");
150
+ }
151
+ }
152
+ _destroy(error, callback) {
153
+ __classPrivateFieldGet(this, _ReadStream_input, "f")?.close();
154
+ __classPrivateFieldSet(this, _ReadStream_input, null, "f");
155
+ callback(error);
156
+ }
157
+ _read(size) {
158
+ if (__classPrivateFieldGet(this, _ReadStream_readRequest, "f") !== null)
159
+ return;
160
+ __classPrivateFieldSet(this, _ReadStream_readRequest, __classPrivateFieldGet(this, _ReadStream_input, "f").read(size)
161
+ .then(buffer => {
162
+ __classPrivateFieldSet(this, _ReadStream_readRequest, null, "f");
163
+ if (buffer.byteLength === 0) {
164
+ this.push(null);
165
+ return;
166
+ }
167
+ if (this.push(Buffer.from(buffer)))
168
+ this._read(size);
169
+ })
170
+ .catch(error => {
171
+ __classPrivateFieldSet(this, _ReadStream_readRequest, null, "f");
172
+ this.destroy(error);
173
+ }), "f");
174
+ }
175
+ }
176
+ _ReadStream_input = new WeakMap(), _ReadStream_readRequest = new WeakMap();
177
+ class WriteStream extends stream.Writable {
178
+ constructor(path) {
179
+ super({
180
+ highWaterMark: 4 * 1024 * 1024
181
+ });
182
+ _WriteStream_output.set(this, null);
183
+ _WriteStream_writeRequest.set(this, null);
184
+ if (isWindows) {
185
+ const api = getWindowsApi();
186
+ const result = api.CreateFileW(Memory.allocUtf16String(path), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
187
+ const handle = result.value;
188
+ if (handle.equals(INVALID_HANDLE_VALUE)) {
189
+ process.nextTick(() => {
190
+ this.destroy(makeWindowsError(result.lastError));
191
+ });
192
+ return;
193
+ }
194
+ __classPrivateFieldSet(this, _WriteStream_output, new Win32OutputStream(handle, { autoClose: true }), "f");
195
+ }
196
+ else {
197
+ const api = getPosixApi();
198
+ const pathStr = Memory.allocUtf8String(path);
199
+ const flags = constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC;
200
+ const mode = constants.S_IRUSR | constants.S_IWUSR | constants.S_IRGRP | constants.S_IROTH;
201
+ const result = api.open(pathStr, flags, mode);
202
+ const fd = result.value;
203
+ if (fd === -1) {
204
+ process.nextTick(() => {
205
+ this.destroy(makePosixError(result.errno));
206
+ });
207
+ return;
208
+ }
209
+ __classPrivateFieldSet(this, _WriteStream_output, new UnixOutputStream(fd, { autoClose: true }), "f");
210
+ }
211
+ }
212
+ _destroy(error, callback) {
213
+ __classPrivateFieldGet(this, _WriteStream_output, "f")?.close();
214
+ __classPrivateFieldSet(this, _WriteStream_output, null, "f");
215
+ callback(error);
216
+ }
217
+ _write(chunk, encoding, callback) {
218
+ if (__classPrivateFieldGet(this, _WriteStream_writeRequest, "f") !== null)
219
+ return;
220
+ __classPrivateFieldSet(this, _WriteStream_writeRequest, __classPrivateFieldGet(this, _WriteStream_output, "f").writeAll(chunk)
221
+ .then(size => {
222
+ __classPrivateFieldSet(this, _WriteStream_writeRequest, null, "f");
223
+ callback();
224
+ })
225
+ .catch(error => {
226
+ __classPrivateFieldSet(this, _WriteStream_writeRequest, null, "f");
227
+ callback(error);
228
+ }), "f");
229
+ }
230
+ }
231
+ _WriteStream_output = new WeakMap(), _WriteStream_writeRequest = new WeakMap();
232
+ const windowsBackend = {
233
+ enumerateDirectoryEntries(path, callback) {
234
+ enumerateWindowsDirectoryEntriesMatching(path + "\\*", callback);
235
+ },
236
+ readFileSync(path, options = {}) {
237
+ if (typeof options === "string")
238
+ options = { encoding: options };
239
+ const { encoding = null } = options;
240
+ const { CreateFileW, GetFileSizeEx, ReadFile, CloseHandle } = getWindowsApi();
241
+ const createRes = CreateFileW(Memory.allocUtf16String(path), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
242
+ const handle = createRes.value;
243
+ if (handle.equals(INVALID_HANDLE_VALUE))
244
+ throwWindowsError(createRes.lastError);
245
+ try {
246
+ const scratchBuf = Memory.alloc(8);
247
+ const fileSizeBuf = scratchBuf;
248
+ const getRes = GetFileSizeEx(handle, fileSizeBuf);
249
+ if (getRes.value === 0)
250
+ throwWindowsError(getRes.lastError);
251
+ const fileSize = fileSizeBuf.readU64().valueOf();
252
+ const buf = Memory.alloc(fileSize);
253
+ const numBytesReadBuf = scratchBuf;
254
+ const readRes = ReadFile(handle, buf, fileSize, numBytesReadBuf, NULL);
255
+ if (readRes.value === 0)
256
+ throwWindowsError(readRes.lastError);
257
+ const n = numBytesReadBuf.readU32();
258
+ if (n !== fileSize)
259
+ throw new Error("Short read");
260
+ return parseReadFileResult(buf, fileSize, encoding);
261
+ }
262
+ finally {
263
+ CloseHandle(handle);
264
+ }
265
+ },
266
+ readlinkSync(path) {
267
+ const { CreateFileW, GetFinalPathNameByHandleW, CloseHandle } = getWindowsApi();
268
+ const createRes = CreateFileW(Memory.allocUtf16String(path), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
269
+ const handle = createRes.value;
270
+ if (handle.equals(INVALID_HANDLE_VALUE))
271
+ throwWindowsError(createRes.lastError);
272
+ try {
273
+ let maxLength = 256;
274
+ while (true) {
275
+ const buf = Memory.alloc(maxLength * 2);
276
+ const { value, lastError } = GetFinalPathNameByHandleW(handle, buf, maxLength, 0);
277
+ if (value === 0)
278
+ throwWindowsError(lastError);
279
+ if (lastError === ERROR_NOT_ENOUGH_MEMORY) {
280
+ maxLength *= 2;
281
+ continue;
282
+ }
283
+ return buf.readUtf16String().substring(4);
284
+ }
285
+ }
286
+ finally {
287
+ CloseHandle(handle);
288
+ }
289
+ },
290
+ rmdirSync(path) {
291
+ const result = getWindowsApi().RemoveDirectoryW(Memory.allocUtf16String(path));
292
+ if (result.value === 0)
293
+ throwWindowsError(result.lastError);
294
+ },
295
+ unlinkSync(path) {
296
+ const result = getWindowsApi().DeleteFileW(Memory.allocUtf16String(path));
297
+ if (result.value === 0)
298
+ throwWindowsError(result.lastError);
299
+ },
300
+ statSync(path) {
301
+ const s = windowsBackend.lstatSync(path);
302
+ if (!s.isSymbolicLink())
303
+ return s;
304
+ const target = windowsBackend.readlinkSync(path);
305
+ return windowsBackend.lstatSync(target);
306
+ },
307
+ lstatSync(path) {
308
+ const getFileExInfoStandard = 0;
309
+ const buf = Memory.alloc(36);
310
+ const result = getWindowsApi().GetFileAttributesExW(Memory.allocUtf16String(path), getFileExInfoStandard, buf);
311
+ if (result.value === 0) {
312
+ if (result.lastError === ERROR_SHARING_VIOLATION) {
313
+ let fileAttrData;
314
+ enumerateWindowsDirectoryEntriesMatching(path, data => {
315
+ // WIN32_FIND_DATAW starts with the exact same fields as WIN32_FILE_ATTRIBUTE_DATA
316
+ fileAttrData = Memory.dup(data, 36);
317
+ });
318
+ return makeStatsProxy(path, fileAttrData);
319
+ }
320
+ throwWindowsError(result.lastError);
321
+ }
322
+ return makeStatsProxy(path, buf);
323
+ },
324
+ };
325
+ function enumerateWindowsDirectoryEntriesMatching(filename, callback) {
326
+ const { FindFirstFileW, FindNextFileW, FindClose } = getWindowsApi();
327
+ const data = Memory.alloc(592);
328
+ const result = FindFirstFileW(Memory.allocUtf16String(filename), data);
329
+ const handle = result.value;
330
+ if (handle.equals(INVALID_HANDLE_VALUE))
331
+ throwWindowsError(result.lastError);
332
+ try {
333
+ do {
334
+ callback(data);
335
+ } while (FindNextFileW(handle, data) !== 0);
336
+ }
337
+ finally {
338
+ FindClose(handle);
339
+ }
340
+ }
341
+ const posixBackend = {
342
+ enumerateDirectoryEntries(path, callback) {
343
+ const { opendir, opendir$INODE64, closedir, readdir, readdir$INODE64 } = getPosixApi();
344
+ const opendirImpl = opendir$INODE64 || opendir;
345
+ const readdirImpl = readdir$INODE64 || readdir;
346
+ const dir = opendirImpl(Memory.allocUtf8String(path));
347
+ const dirHandle = dir.value;
348
+ if (dirHandle.isNull())
349
+ throwPosixError(dir.errno);
350
+ try {
351
+ let entry;
352
+ while (!((entry = readdirImpl(dirHandle)).isNull())) {
353
+ callback(entry);
354
+ }
355
+ }
356
+ finally {
357
+ closedir(dirHandle);
358
+ }
359
+ },
360
+ readFileSync(path, options = {}) {
361
+ if (typeof options === "string")
362
+ options = { encoding: options };
363
+ const { encoding = null } = options;
364
+ const { open, close, lseek, read } = getPosixApi();
365
+ const openResult = open(Memory.allocUtf8String(path), constants.O_RDONLY, 0);
366
+ const fd = openResult.value;
367
+ if (fd === -1)
368
+ throwPosixError(openResult.errno);
369
+ try {
370
+ const fileSize = lseek(fd, 0, SEEK_END).valueOf();
371
+ lseek(fd, 0, SEEK_SET);
372
+ const buf = Memory.alloc(fileSize);
373
+ let readResult, n, readFailed;
374
+ do {
375
+ readResult = read(fd, buf, fileSize);
376
+ n = readResult.value.valueOf();
377
+ readFailed = n === -1;
378
+ } while (readFailed && readResult.errno === EINTR);
379
+ if (readFailed)
380
+ throwPosixError(readResult.errno);
381
+ if (n !== fileSize.valueOf())
382
+ throw new Error("Short read");
383
+ return parseReadFileResult(buf, fileSize, encoding);
384
+ }
385
+ finally {
386
+ close(fd);
387
+ }
388
+ },
389
+ readlinkSync(path) {
390
+ const pathStr = Memory.allocUtf8String(path);
391
+ const linkSize = posixBackend.lstatSync(path).size.valueOf();
392
+ const buf = Memory.alloc(linkSize);
393
+ const result = getPosixApi().readlink(pathStr, buf, linkSize);
394
+ const n = result.value.valueOf();
395
+ if (n === -1)
396
+ throwPosixError(result.errno);
397
+ return buf.readUtf8String(n);
398
+ },
399
+ rmdirSync(path) {
400
+ const result = getPosixApi().rmdir(Memory.allocUtf8String(path));
401
+ if (result.value === -1)
402
+ throwPosixError(result.errno);
403
+ },
404
+ unlinkSync(path) {
405
+ const result = getPosixApi().unlink(Memory.allocUtf8String(path));
406
+ if (result.value === -1)
407
+ throwPosixError(result.errno);
408
+ },
409
+ statSync(path) {
410
+ return performStatPosix(getStatSpec()._stat, path);
411
+ },
412
+ lstatSync(path) {
413
+ return performStatPosix(getStatSpec()._lstat, path);
414
+ },
415
+ };
416
+ function writeFileSync(path, data, options = {}) {
417
+ if (typeof options === "string")
418
+ options = { encoding: options };
419
+ const { encoding = null } = options;
420
+ let rawData;
421
+ if (typeof data === "string") {
422
+ if (encoding !== null && !encodingIsUtf8(encoding))
423
+ rawData = Buffer.from(data, encoding).buffer;
424
+ else
425
+ rawData = data;
426
+ }
427
+ else {
428
+ rawData = data.buffer;
429
+ }
430
+ const file = new File(path, "wb");
431
+ try {
432
+ file.write(rawData);
433
+ }
434
+ finally {
435
+ file.close();
436
+ }
437
+ }
438
+ function performStatPosix(impl, path) {
439
+ const buf = Memory.alloc(statBufSize);
440
+ const result = impl(Memory.allocUtf8String(path), buf);
441
+ if (result.value !== 0)
442
+ throwPosixError(result.errno);
443
+ return makeStatsProxy(path, buf);
444
+ }
445
+ function parseReadFileResult(buf, fileSize, encoding) {
446
+ if (encodingIsUtf8(encoding))
447
+ return buf.readUtf8String(fileSize);
448
+ const value = Buffer.from(buf.readByteArray(fileSize));
449
+ if (encoding !== null)
450
+ return value.toString(encoding);
451
+ return value;
452
+ }
453
+ function encodingIsUtf8(encoding) {
454
+ return encoding === "utf8" || encoding === "utf-8";
455
+ }
456
+ const backend = isWindows ? windowsBackend : posixBackend;
457
+ const { enumerateDirectoryEntries, readFileSync, readlinkSync, rmdirSync, unlinkSync, statSync, lstatSync, } = backend;
458
+ const direntSpecs = {
459
+ "windows": {
460
+ "d_name": [44, "Utf16String"],
461
+ "d_type": [0, readWindowsFileAttributes],
462
+ "atime": [12, readWindowsFileTime],
463
+ "mtime": [20, readWindowsFileTime],
464
+ "ctime": [4, readWindowsFileTime],
465
+ "size": [28, readWindowsFileSize],
466
+ },
467
+ "linux-32": {
468
+ "d_name": [11, "Utf8String"],
469
+ "d_type": [10, "U8"]
470
+ },
471
+ "linux-64": {
472
+ "d_name": [19, "Utf8String"],
473
+ "d_type": [18, "U8"]
474
+ },
475
+ "darwin-32": {
476
+ "d_name": [21, "Utf8String"],
477
+ "d_type": [20, "U8"]
478
+ },
479
+ "darwin-64": {
480
+ "d_name": [21, "Utf8String"],
481
+ "d_type": [20, "U8"]
482
+ }
483
+ };
484
+ const direntSpec = isWindows ? direntSpecs.windows : direntSpecs[`${platform}-${pointerSize * 8}`];
485
+ function readdirSync(path) {
486
+ const entries = [];
487
+ enumerateDirectoryEntries(path, entry => {
488
+ const name = readDirentField(entry, "d_name");
489
+ entries.push(name);
490
+ });
491
+ return entries;
492
+ }
493
+ function list(path) {
494
+ const extraFieldNames = Object.keys(direntSpec).filter(k => !k.startsWith("d_"));
495
+ const entries = [];
496
+ enumerateDirectoryEntries(path, entry => {
497
+ const name = readDirentField(entry, "d_name");
498
+ const type = readDirentField(entry, "d_type", fsPath.join(path, name));
499
+ const extras = {};
500
+ for (const f of extraFieldNames)
501
+ extras[f] = readDirentField(entry, f);
502
+ entries.push({
503
+ name,
504
+ type,
505
+ ...extras
506
+ });
507
+ });
508
+ return entries;
509
+ }
510
+ function readDirentField(entry, name, ...args) {
511
+ const fieldSpec = direntSpec[name];
512
+ const [offset, type] = fieldSpec;
513
+ const read = (typeof type === "string") ? NativePointer.prototype["read" + type] : type;
514
+ const value = read.call(entry.add(offset), ...args);
515
+ if (value instanceof Int64 || value instanceof UInt64)
516
+ return value.valueOf();
517
+ return value;
518
+ }
519
+ const statFields = new Set([
520
+ "dev",
521
+ "mode",
522
+ "nlink",
523
+ "uid",
524
+ "gid",
525
+ "rdev",
526
+ "blksize",
527
+ "ino",
528
+ "size",
529
+ "blocks",
530
+ "atimeMs",
531
+ "mtimeMs",
532
+ "ctimeMs",
533
+ "birthtimeMs",
534
+ "atime",
535
+ "mtime",
536
+ "ctime",
537
+ "birthtime",
538
+ ]);
539
+ const statSpecs = {
540
+ "windows": {
541
+ size: 36,
542
+ fields: {
543
+ "dev": [0, returnZero],
544
+ "mode": [0, readWindowsFileAttributes],
545
+ "nlink": [0, returnOne],
546
+ "ino": [0, returnZero],
547
+ "uid": [0, returnZero],
548
+ "gid": [0, returnZero],
549
+ "rdev": [0, returnZero],
550
+ "atime": [12, readWindowsFileTime],
551
+ "mtime": [20, readWindowsFileTime],
552
+ "ctime": [20, readWindowsFileTime],
553
+ "birthtime": [4, readWindowsFileTime],
554
+ "size": [28, readWindowsFileSize],
555
+ "blocks": [28, readWindowsFileSize],
556
+ "blksize": [0, returnOne],
557
+ },
558
+ },
559
+ "darwin-32": {
560
+ size: 108,
561
+ fields: {
562
+ "dev": [0, "S32"],
563
+ "mode": [4, "U16"],
564
+ "nlink": [6, "U16"],
565
+ "ino": [8, "U64"],
566
+ "uid": [16, "U32"],
567
+ "gid": [20, "U32"],
568
+ "rdev": [24, "S32"],
569
+ "atime": [28, readTimespec32],
570
+ "mtime": [36, readTimespec32],
571
+ "ctime": [44, readTimespec32],
572
+ "birthtime": [52, readTimespec32],
573
+ "size": [60, "S64"],
574
+ "blocks": [68, "S64"],
575
+ "blksize": [76, "S32"],
576
+ }
577
+ },
578
+ "darwin-64": {
579
+ size: 144,
580
+ fields: {
581
+ "dev": [0, "S32"],
582
+ "mode": [4, "U16"],
583
+ "nlink": [6, "U16"],
584
+ "ino": [8, "U64"],
585
+ "uid": [16, "U32"],
586
+ "gid": [20, "U32"],
587
+ "rdev": [24, "S32"],
588
+ "atime": [32, readTimespec64],
589
+ "mtime": [48, readTimespec64],
590
+ "ctime": [64, readTimespec64],
591
+ "birthtime": [80, readTimespec64],
592
+ "size": [96, "S64"],
593
+ "blocks": [104, "S64"],
594
+ "blksize": [112, "S32"],
595
+ }
596
+ },
597
+ "linux-32": {
598
+ size: 88,
599
+ fields: {
600
+ "dev": [0, "U64"],
601
+ "mode": [16, "U32"],
602
+ "nlink": [20, "U32"],
603
+ "ino": [12, "U32"],
604
+ "uid": [24, "U32"],
605
+ "gid": [28, "U32"],
606
+ "rdev": [32, "U64"],
607
+ "atime": [56, readTimespec32],
608
+ "mtime": [64, readTimespec32],
609
+ "ctime": [72, readTimespec32],
610
+ "size": [44, "S32"],
611
+ "blocks": [52, "S32"],
612
+ "blksize": [48, "S32"],
613
+ }
614
+ },
615
+ "linux-32-stat64": {
616
+ size: 104,
617
+ fields: {
618
+ "dev": [0, "U64"],
619
+ "mode": [16, "U32"],
620
+ "nlink": [20, "U32"],
621
+ "ino": [96, "U64"],
622
+ "uid": [24, "U32"],
623
+ "gid": [28, "U32"],
624
+ "rdev": [32, "U64"],
625
+ "atime": [72, readTimespec32],
626
+ "mtime": [80, readTimespec32],
627
+ "ctime": [88, readTimespec32],
628
+ "size": [48, "S64"],
629
+ "blocks": [64, "S64"],
630
+ "blksize": [56, "S32"],
631
+ }
632
+ },
633
+ "linux-64": {
634
+ size: 144,
635
+ fields: {
636
+ "dev": [0, "U64"],
637
+ "mode": [24, "U32"],
638
+ "nlink": [16, "U64"],
639
+ "ino": [8, "U64"],
640
+ "uid": [28, "U32"],
641
+ "gid": [32, "U32"],
642
+ "rdev": [40, "U64"],
643
+ "atime": [72, readTimespec64],
644
+ "mtime": [88, readTimespec64],
645
+ "ctime": [104, readTimespec64],
646
+ "size": [48, "S64"],
647
+ "blocks": [64, "S64"],
648
+ "blksize": [56, "S64"],
649
+ },
650
+ },
651
+ };
652
+ let cachedStatSpec = null;
653
+ const statBufSize = 256;
654
+ function getStatSpec() {
655
+ if (cachedStatSpec !== null)
656
+ return cachedStatSpec;
657
+ let statSpec;
658
+ if (isWindows) {
659
+ statSpec = statSpecs.windows;
660
+ }
661
+ else {
662
+ const api = getPosixApi();
663
+ const stat64Impl = api.stat64 ?? api.__xstat64;
664
+ let platformId = `${platform}-${pointerSize * 8}`;
665
+ if (platformId === "linux-32") {
666
+ if (stat64Impl !== undefined)
667
+ platformId += "-stat64";
668
+ }
669
+ statSpec = statSpecs[platformId];
670
+ if (statSpec === undefined)
671
+ throw new Error("Current OS is not yet supported; please open a PR");
672
+ statSpec._stat = stat64Impl ?? api.stat;
673
+ statSpec._lstat = api.lstat64 ?? api.__lxstat64 ?? api.lstat;
674
+ }
675
+ cachedStatSpec = statSpec;
676
+ return statSpec;
677
+ }
678
+ class Stats {
679
+ isFile() {
680
+ return (this.mode & S_IFMT) === S_IFREG;
681
+ }
682
+ isDirectory() {
683
+ return (this.mode & S_IFMT) === S_IFDIR;
684
+ }
685
+ isCharacterDevice() {
686
+ return (this.mode & S_IFMT) === S_IFCHR;
687
+ }
688
+ isBlockDevice() {
689
+ return (this.mode & S_IFMT) === S_IFBLK;
690
+ }
691
+ isFIFO() {
692
+ return (this.mode & S_IFMT) === S_IFIFO;
693
+ }
694
+ isSymbolicLink() {
695
+ return (this.mode & S_IFMT) === S_IFLNK;
696
+ }
697
+ isSocket() {
698
+ return (this.mode & S_IFMT) === S_IFSOCK;
699
+ }
700
+ }
701
+ function makeStatsProxy(path, buf) {
702
+ return new Proxy(new Stats(), {
703
+ has(target, property) {
704
+ if (typeof property === "symbol")
705
+ return property in target;
706
+ return statsHasField(property);
707
+ },
708
+ get(target, property, receiver) {
709
+ switch (property) {
710
+ case "prototype":
711
+ return undefined;
712
+ case "constructor":
713
+ case "toString":
714
+ return target[property];
715
+ case "hasOwnProperty":
716
+ return statsHasField;
717
+ case "valueOf":
718
+ return receiver;
719
+ case "buffer":
720
+ return buf;
721
+ default:
722
+ if (typeof property === "symbol" || property in target)
723
+ return target[property];
724
+ return statsReadField.call(receiver, property, path);
725
+ }
726
+ },
727
+ set(target, property, value, receiver) {
728
+ return false;
729
+ },
730
+ ownKeys(target) {
731
+ return Array.from(statFields);
732
+ },
733
+ getOwnPropertyDescriptor(target, property) {
734
+ return {
735
+ writable: false,
736
+ configurable: true,
737
+ enumerable: true
738
+ };
739
+ },
740
+ });
741
+ }
742
+ function statsHasField(name) {
743
+ return statFields.has(name);
744
+ }
745
+ function statsReadField(name, path) {
746
+ let field = getStatSpec().fields[name];
747
+ if (field === undefined) {
748
+ if (name === "birthtime") {
749
+ return statsReadField.call(this, "ctime", path);
750
+ }
751
+ const msPos = name.lastIndexOf("Ms");
752
+ if (msPos === name.length - 2) {
753
+ return statsReadField.call(this, name.substring(0, msPos), path).getTime();
754
+ }
755
+ return undefined;
756
+ }
757
+ const [offset, type] = field;
758
+ const read = (typeof type === "string") ? NativePointer.prototype["read" + type] : type;
759
+ const value = read.call(this.buffer.add(offset), path);
760
+ if (value instanceof Int64 || value instanceof UInt64)
761
+ return value.valueOf();
762
+ return value;
763
+ }
764
+ function readWindowsFileAttributes(path) {
765
+ const attributes = this.readU32();
766
+ let isLink = false;
767
+ if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) !== 0) {
768
+ enumerateWindowsDirectoryEntriesMatching(path, data => {
769
+ const reserved0 = data.add(36).readU32();
770
+ isLink = (reserved0 === IO_REPARSE_TAG_MOUNT_POINT || reserved0 === IO_REPARSE_TAG_SYMLINK);
771
+ });
772
+ }
773
+ const isDir = (attributes & FILE_ATTRIBUTE_DIRECTORY) !== 0;
774
+ let mode;
775
+ if (isLink)
776
+ mode = S_IFLNK;
777
+ else if (isDir)
778
+ mode = S_IFDIR;
779
+ else
780
+ mode = S_IFREG;
781
+ if (isDir)
782
+ mode |= 0x1ed;
783
+ else
784
+ mode |= 0x1a4;
785
+ return mode;
786
+ }
787
+ function readWindowsFileTime() {
788
+ const fileTime = BigInt(this.readU64().toString()).valueOf();
789
+ const ticksPerMsec = 10000n;
790
+ const msecToUnixEpoch = 11644473600000n;
791
+ const unixTime = (fileTime / ticksPerMsec) - msecToUnixEpoch;
792
+ return new Date(parseInt(unixTime.toString()));
793
+ }
794
+ function readWindowsFileSize() {
795
+ const high = this.readU32();
796
+ const low = this.add(4).readU32();
797
+ return uint64(high).shl(32).or(low);
798
+ }
799
+ function readTimespec32() {
800
+ const sec = this.readU32();
801
+ const nsec = this.add(4).readU32();
802
+ const msec = nsec / 1000000;
803
+ return new Date((sec * 1000) + msec);
804
+ }
805
+ function readTimespec64() {
806
+ // FIXME: Improve UInt64 to support division
807
+ const sec = this.readU64().valueOf();
808
+ const nsec = this.add(8).readU64().valueOf();
809
+ const msec = nsec / 1000000;
810
+ return new Date((sec * 1000) + msec);
811
+ }
812
+ function returnZero() {
813
+ return 0;
814
+ }
815
+ function returnOne() {
816
+ return 1;
817
+ }
818
+ function throwWindowsError(lastError) {
819
+ throw makeWindowsError(lastError);
820
+ }
821
+ function throwPosixError(errno) {
822
+ throw makePosixError(errno);
823
+ }
824
+ function makeWindowsError(lastError) {
825
+ const maxLength = 256;
826
+ const FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
827
+ const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
828
+ const buf = Memory.alloc(maxLength * 2);
829
+ getWindowsApi().FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lastError, 0, buf, maxLength, NULL);
830
+ return new Error(buf.readUtf16String());
831
+ }
832
+ function makePosixError(errno) {
833
+ const message = getPosixApi().strerror(errno).readUtf8String();
834
+ return new Error(message);
835
+ }
836
+ function callbackify(original) {
837
+ return function (...args) {
838
+ const numArgsMinusOne = args.length - 1;
839
+ const implArgs = args.slice(0, numArgsMinusOne);
840
+ const callback = args[numArgsMinusOne];
841
+ process.nextTick(function () {
842
+ try {
843
+ const result = original(...implArgs);
844
+ callback(null, result);
845
+ }
846
+ catch (e) {
847
+ callback(e);
848
+ }
849
+ });
850
+ };
851
+ }
852
+ const SF = SystemFunction;
853
+ const NF = NativeFunction;
854
+ const ssizeType = (pointerSize === 8) ? "int64" : "int32";
855
+ const sizeType = "u" + ssizeType;
856
+ const offsetType = (platform === "darwin" || pointerSize === 8) ? "int64" : "int32";
857
+ function _getWindowsApi() {
858
+ return makeApi([
859
+ ["CreateFileW", SF, "pointer", ["pointer", "uint", "uint", "pointer", "uint", "uint", "pointer"]],
860
+ ["DeleteFileW", SF, "uint", ["pointer"]],
861
+ ["GetFileSizeEx", SF, "uint", ["pointer", "pointer"]],
862
+ ["ReadFile", SF, "uint", ["pointer", "pointer", "uint", "pointer", "pointer"]],
863
+ ["RemoveDirectoryW", SF, "uint", ["pointer"]],
864
+ ["CloseHandle", NF, "uint", ["pointer"]],
865
+ ["FindFirstFileW", SF, "pointer", ["pointer", "pointer"]],
866
+ ["FindNextFileW", NF, "uint", ["pointer", "pointer"]],
867
+ ["FindClose", NF, "uint", ["pointer"]],
868
+ ["GetFileAttributesExW", SF, "uint", ["pointer", "uint", "pointer"]],
869
+ ["GetFinalPathNameByHandleW", SF, "uint", ["pointer", "pointer", "uint", "uint"]],
870
+ ["FormatMessageW", NF, "uint", ["uint", "pointer", "uint", "uint", "pointer", "uint", "pointer"]],
871
+ ]);
872
+ }
873
+ function _getPosixApi() {
874
+ return makeApi([
875
+ ["open", SF, "int", ["pointer", "int", "...", "int"]],
876
+ ["close", NF, "int", ["int"]],
877
+ ["lseek", NF, offsetType, ["int", offsetType, "int"]],
878
+ ["read", SF, ssizeType, ["int", "pointer", sizeType]],
879
+ ["opendir", SF, "pointer", ["pointer"]],
880
+ ["opendir$INODE64", SF, "pointer", ["pointer"]],
881
+ ["closedir", NF, "int", ["pointer"]],
882
+ ["readdir", NF, "pointer", ["pointer"]],
883
+ ["readdir$INODE64", NF, "pointer", ["pointer"]],
884
+ ["readlink", SF, ssizeType, ["pointer", "pointer", sizeType]],
885
+ ["rmdir", SF, "int", ["pointer"]],
886
+ ["unlink", SF, "int", ["pointer"]],
887
+ ["stat", SF, "int", ["pointer", "pointer"]],
888
+ ["stat64", SF, "int", ["pointer", "pointer"]],
889
+ ["__xstat64", SF, "int", ["int", "pointer", "pointer"], invokeXstat],
890
+ ["lstat", SF, "int", ["pointer", "pointer"]],
891
+ ["lstat64", SF, "int", ["pointer", "pointer"]],
892
+ ["__lxstat64", SF, "int", ["int", "pointer", "pointer"], invokeXstat],
893
+ ["strerror", NF, "pointer", ["int"]],
894
+ ]);
895
+ }
896
+ function invokeXstat(impl, path, buf) {
897
+ const STAT_VER_LINUX = 3;
898
+ return impl(STAT_VER_LINUX, path, buf);
899
+ }
900
+ function makeApi(spec) {
901
+ return spec.reduce((api, entry) => {
902
+ addApiPlaceholder(api, entry);
903
+ return api;
904
+ }, {});
905
+ }
906
+ const nativeOpts = (isWindows && pointerSize === 4) ? { abi: "stdcall" } : {};
907
+ function addApiPlaceholder(api, entry) {
908
+ const [name] = entry;
909
+ Object.defineProperty(api, name, {
910
+ configurable: true,
911
+ get() {
912
+ const [, Ctor, retType, argTypes, wrapper] = entry;
913
+ let impl = null;
914
+ const address = isWindows
915
+ ? Module.findExportByName("kernel32.dll", name)
916
+ : Module.findExportByName(null, name);
917
+ if (address !== null)
918
+ impl = new Ctor(address, retType, argTypes, nativeOpts);
919
+ if (wrapper !== undefined)
920
+ impl = wrapper.bind(null, impl);
921
+ Object.defineProperty(api, name, { value: impl });
922
+ return impl;
923
+ }
924
+ });
925
+ }
926
+ export function createReadStream(path) {
927
+ return new ReadStream(path);
928
+ }
929
+ export function createWriteStream(path) {
930
+ return new WriteStream(path);
931
+ }
932
+ export const readdir = callbackify(readdirSync);
933
+ export const readFile = callbackify(readFileSync);
934
+ export const writeFile = callbackify(writeFileSync);
935
+ export const readlink = callbackify(readlinkSync);
936
+ export const rmdir = callbackify(rmdirSync);
937
+ export const unlink = callbackify(unlinkSync);
938
+ export const stat = callbackify(statSync);
939
+ export const lstat = callbackify(lstatSync);
940
+ function memoize(compute) {
941
+ let value;
942
+ let computed = false;
943
+ return function (...args) {
944
+ if (!computed) {
945
+ value = compute(...args);
946
+ computed = true;
947
+ }
948
+ return value;
949
+ };
950
+ }
951
+ export { constants, readdirSync, list, readFileSync, writeFileSync, readlinkSync, rmdirSync, unlinkSync, statSync, lstatSync, Stats, };
952
+ export default {
953
+ constants,
954
+ createReadStream,
955
+ createWriteStream,
956
+ readdir,
957
+ readdirSync,
958
+ list,
959
+ readFile,
960
+ readFileSync,
961
+ writeFile,
962
+ writeFileSync,
963
+ readlink,
964
+ readlinkSync,
965
+ rmdir,
966
+ rmdirSync,
967
+ unlink,
968
+ unlinkSync,
969
+ stat,
970
+ statSync,
971
+ lstat,
972
+ lstatSync,
973
+ Stats,
974
+ };