Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. const { promisify } = require('util');
  2. const { exec } = require('child_process');
  3. const { promises: fs } = require('fs');
  4. const execAsync = promisify(exec);
  5. const debug = require('debug')('read-binary-file-arch');
  6. // https://nodejs.org/api/process.html#processarch
  7. const SUPPORTED_ARCH = [
  8. 'arm',
  9. 'arm64',
  10. 'ia32',
  11. 'loong64',
  12. 'mips',
  13. 'mipsel',
  14. 'ppc',
  15. 'ppc64',
  16. 'riscv64',
  17. 's390',
  18. 's390x',
  19. 'x64',
  20. ];
  21. async function readPEArch(filePath) {
  22. const DOS_HEADER_PE_OFFSET = 0x3c;
  23. const COFF_HEADER_MACHINE_OFFSET = 4; // Offset after 'PE\0\0'
  24. const BUFFER_SIZE = 1024; // Enough to cover DOS header, PE header, and COFF header
  25. const buffer = Buffer.alloc(BUFFER_SIZE);
  26. const fileHandle = await fs.open(filePath, 'r');
  27. await fileHandle.read(buffer, 0, BUFFER_SIZE, 0);
  28. // Find the PE header offset from the DOS header
  29. const peOffset = buffer.readUInt32LE(DOS_HEADER_PE_OFFSET);
  30. // Read the machine type from the COFF header
  31. let machineType;
  32. try {
  33. machineType = buffer.readUInt16LE(
  34. peOffset + COFF_HEADER_MACHINE_OFFSET
  35. );
  36. } catch (error) {
  37. debug('read error:', error.message);
  38. throw new Error('Invalid PE file');
  39. }
  40. // Mapping of machine types to architectures
  41. const MACHINE_TYPES = {
  42. 0x014c: 'ia32',
  43. 0x8664: 'x64',
  44. 0x01c0: 'arm',
  45. 0x01c4: 'arm', // ARMv7 Thumb-2 LE
  46. 0xaa64: 'arm64',
  47. };
  48. const arch = MACHINE_TYPES[machineType];
  49. debug('win32 arch:', arch);
  50. await fileHandle.close();
  51. return arch;
  52. }
  53. async function getArchUsingFileCommand(filePath) {
  54. const { stdout } = await execAsync(`file "${filePath}"`);
  55. const output = stdout.trim();
  56. debug('file command output:', output);
  57. const resultStart = filePath.length + 1; // skip 'filename:'
  58. const result = output.substring(resultStart).trim();
  59. debug('result:', result);
  60. // 'file' architectures => Node architectures
  61. const FILE_ARCH = {
  62. x64: 'x64',
  63. 'x86-64': 'x64',
  64. x86_64: 'x64',
  65. x86: 'ia32',
  66. i386: 'ia32',
  67. arm64: 'arm64',
  68. arm: 'arm',
  69. aarch64: 'arm64',
  70. ARMv7: 'arm',
  71. ppc_7400: 'ppc',
  72. // PE32 executable (console) Intel 80386, for MS Windows
  73. 'Intel 80386': 'ia32',
  74. // ELF 64-bit LSB executable, IA-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-ia64.so.2, for GNU/Linux 2.6.16
  75. 'IA-64': 'x64',
  76. // ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.6.32
  77. PowerPC: 'ppc',
  78. // ELF 32-bit MSB executable, MIPS, MIPS-IV version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.4.1
  79. MIPS: 'mips',
  80. };
  81. const fileArchRegexStr = Object.keys(FILE_ARCH)
  82. .map((arch) => `(?:${arch})`)
  83. .join('|');
  84. const fileArchRegex = new RegExp(fileArchRegexStr);
  85. const fileArchMatch = result.match(fileArchRegex);
  86. debug('archMatch:', fileArchMatch && fileArchMatch[0]);
  87. const fileArch = fileArchMatch ? fileArchMatch[0] : null;
  88. const arch = FILE_ARCH[fileArch];
  89. return arch;
  90. }
  91. async function readBinaryFileArch(filePath) {
  92. const stat = await fs.stat(filePath);
  93. if (!stat.isFile()) {
  94. throw new Error(`${filePath} is not a file.`);
  95. }
  96. let arch;
  97. if (process.platform === 'win32') {
  98. // Windows only supports reading the architecture of valid PE files since
  99. // 'file' is not available.
  100. arch = await readPEArch(filePath);
  101. } else {
  102. arch = await getArchUsingFileCommand(filePath);
  103. }
  104. return SUPPORTED_ARCH.includes(arch) ? arch : null;
  105. }
  106. module.exports = { readBinaryFileArch };