frida-fs 3.0.2 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +10 -0
  2. package/index.js +97 -26
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -9,3 +9,13 @@ const fs = require('frida-fs');
9
9
 
10
10
  fs.createReadStream('/etc/hosts').pipe(networkStream);
11
11
  ```
12
+
13
+ ```js
14
+ const fs = require('frida-fs');
15
+
16
+ for (const elm of fs.list("/proc/self/")) {
17
+ console.log(JSON.stringify(elm));
18
+ }
19
+
20
+ console.log(fs.readFileSync("/etc/hosts"));
21
+ ```
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
- const stream = require('stream');
1
+ import {Buffer} from 'buffer';
2
+ import stream from 'stream';
2
3
 
3
4
  const {platform, pointerSize} = Process;
4
5
 
@@ -127,6 +128,7 @@ class ReadStream extends stream.Readable {
127
128
  .catch(error => {
128
129
  this._readRequest = null;
129
130
  this._closeInput();
131
+ this.emit('error', error);
130
132
  this.push(null);
131
133
  });
132
134
  }
@@ -412,6 +414,24 @@ const statSpecs = {
412
414
  'blksize': [ 48, 'S32' ],
413
415
  }
414
416
  },
417
+ 'linux-32-stat64': {
418
+ size: 104,
419
+ fields: {
420
+ 'dev': [ 0, 'U64' ],
421
+ 'mode': [ 16, 'U32' ],
422
+ 'nlink': [ 20, 'U32' ],
423
+ 'ino': [ 96, 'U64' ],
424
+ 'uid': [ 24, 'U32' ],
425
+ 'gid': [ 28, 'U32' ],
426
+ 'rdev': [ 32, 'U64' ],
427
+ 'atime': [ 72, readTimespec32 ],
428
+ 'mtime': [ 80, readTimespec32 ],
429
+ 'ctime': [ 88, readTimespec32 ],
430
+ 'size': [ 48, 'S64' ],
431
+ 'blocks': [ 64, 'S64' ],
432
+ 'blksize': [ 56, 'S32' ],
433
+ }
434
+ },
415
435
  'linux-64': {
416
436
  size: 144,
417
437
  fields: {
@@ -431,9 +451,34 @@ const statSpecs = {
431
451
  },
432
452
  },
433
453
  };
434
- const statSpec = statSpecs[`${platform}-${pointerSize * 8}`] || null;
454
+ let cachedStatSpec = null;
435
455
  const statBufSize = 256;
436
456
 
457
+ function getStatSpec() {
458
+ if (cachedStatSpec !== null)
459
+ return cachedStatSpec;
460
+
461
+ const api = getApi();
462
+ const stat64Impl = api.stat64 ?? api.__xstat64;
463
+
464
+ let platformId = `${platform}-${pointerSize * 8}`;
465
+ if (platformId === 'linux-32') {
466
+ if (stat64Impl !== undefined)
467
+ platformId += '-stat64';
468
+ }
469
+
470
+ const statSpec = statSpecs[platformId];
471
+ if (statSpec === undefined)
472
+ throw new Error('Current OS is not yet supported; please open a PR');
473
+
474
+ statSpec._stat = stat64Impl ?? api.stat;
475
+ statSpec._lstat = api.lstat64 ?? api.__lxstat64 ?? api.lstat;
476
+
477
+ cachedStatSpec = statSpec;
478
+
479
+ return statSpec;
480
+ }
481
+
437
482
  class Stats {
438
483
  isFile() {
439
484
  return (this.mode & S_IFMT) === S_IFREG;
@@ -465,21 +510,14 @@ class Stats {
465
510
  }
466
511
 
467
512
  function statSync(path) {
468
- const api = getApi();
469
- const impl = api.stat64 || api.stat;
470
- return performStat(impl, path);
513
+ return performStat(getStatSpec()._stat, path);
471
514
  }
472
515
 
473
516
  function lstatSync(path) {
474
- const api = getApi();
475
- const impl = api.lstat64 || api.lstat;
476
- return performStat(impl, path);
517
+ return performStat(getStatSpec()._lstat, path);
477
518
  }
478
519
 
479
520
  function performStat(impl, path) {
480
- if (statSpec === null)
481
- throw new Error('Current OS is not yet supported; please open a PR');
482
-
483
521
  const buf = Memory.alloc(statBufSize);
484
522
  const result = impl(Memory.allocUtf8String(path), buf);
485
523
  if (result.value !== 0)
@@ -529,7 +567,7 @@ function statsHasField(name) {
529
567
  }
530
568
 
531
569
  function statsReadField(name) {
532
- let field = statSpec.fields[name];
570
+ let field = getStatSpec().fields[name];
533
571
  if (field === undefined) {
534
572
  if (name === 'birthtime') {
535
573
  return statsReadField.call(this, 'ctime');
@@ -612,11 +650,18 @@ const apiSpec = [
612
650
  ['unlink', SF, 'int', ['pointer']],
613
651
  ['stat', SF, 'int', ['pointer', 'pointer']],
614
652
  ['stat64', SF, 'int', ['pointer', 'pointer']],
653
+ ['__xstat64', SF, 'int', ['int', 'pointer', 'pointer'], invokeXstat],
615
654
  ['lstat', SF, 'int', ['pointer', 'pointer']],
616
655
  ['lstat64', SF, 'int', ['pointer', 'pointer']],
656
+ ['__lxstat64', SF, 'int', ['int', 'pointer', 'pointer'], invokeXstat],
617
657
  ['strerror', NF, 'pointer', ['int']],
618
658
  ];
619
659
 
660
+ function invokeXstat(impl, path, buf) {
661
+ const STAT_VER_LINUX = 3;
662
+ return impl(STAT_VER_LINUX, path, buf);
663
+ }
664
+
620
665
  let cachedApi = null;
621
666
  function getApi() {
622
667
  if (cachedApi === null) {
@@ -634,13 +679,16 @@ function addApiPlaceholder(api, entry) {
634
679
  Object.defineProperty(api, name, {
635
680
  configurable: true,
636
681
  get() {
637
- const [, Ctor, retType, argTypes] = entry;
682
+ const [, Ctor, retType, argTypes, wrapper] = entry;
638
683
 
639
684
  let impl = null;
640
685
  const address = Module.findExportByName(null, name);
641
686
  if (address !== null)
642
687
  impl = new Ctor(address, retType, argTypes);
643
688
 
689
+ if (wrapper !== undefined)
690
+ impl = wrapper.bind(null, impl);
691
+
644
692
  Object.defineProperty(api, name, { value: impl });
645
693
 
646
694
  return impl;
@@ -648,26 +696,49 @@ function addApiPlaceholder(api, entry) {
648
696
  });
649
697
  }
650
698
 
651
- module.exports = {
699
+ export function createReadStream(path) {
700
+ return new ReadStream(path);
701
+ }
702
+
703
+ export function createWriteStream(path) {
704
+ return new WriteStream(path);
705
+ }
706
+
707
+ export const readdir = callbackify(readdirSync);
708
+ export const readFile = callbackify(readFileSync);
709
+ export const readlink = callbackify(readlinkSync);
710
+ export const unlink = callbackify(unlinkSync);
711
+ export const stat = callbackify(statSync);
712
+ export const lstat = callbackify(lstatSync);
713
+
714
+ export {
652
715
  constants,
653
- createReadStream(path) {
654
- return new ReadStream(path);
655
- },
656
- createWriteStream(path) {
657
- return new WriteStream(path);
658
- },
659
- readdir: callbackify(readdirSync),
660
716
  readdirSync,
661
717
  list,
662
- readFile: callbackify(readFileSync),
663
718
  readFileSync,
664
- readlink: callbackify(readlinkSync),
665
719
  readlinkSync,
666
- unlink: callbackify(unlinkSync),
667
720
  unlinkSync,
668
- stat: callbackify(statSync),
669
721
  statSync,
670
- lstat: callbackify(lstatSync),
722
+ lstatSync,
723
+ Stats,
724
+ };
725
+
726
+ export default {
727
+ constants,
728
+ createReadStream,
729
+ createWriteStream,
730
+ readdir,
731
+ readdirSync,
732
+ list,
733
+ readFile,
734
+ readFileSync,
735
+ readlink,
736
+ readlinkSync,
737
+ unlink,
738
+ unlinkSync,
739
+ stat,
740
+ statSync,
741
+ lstat,
671
742
  lstatSync,
672
743
  Stats,
673
744
  };
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "frida-fs",
3
- "version": "3.0.2",
3
+ "version": "4.0.2",
4
4
  "description": "Create a stream from a filesystem resource",
5
5
  "main": "index.js",
6
+ "type": "module",
6
7
  "files": [
7
8
  "/index.js"
8
9
  ],