1. const fs = require('fs');
  2. const { spawn } = require('child_process');
  3. /**
  4. * Searches for a pattern within a binary file, with a timeout.
  5. *
  6. * @param {string} filePath - The path to the binary file.
  7. * @param {string} searchPattern - The pattern to search for (hex or byte sequence).
  8. * @param {number} timeoutMs - The timeout in milliseconds.
  9. * @returns {Promise<number|null>} - The starting byte index of the first match, or null if no match found within the timeout.
  10. * @throws {Error} If the file does not exist.
  11. */
  12. async function searchBinaryFile(filePath, searchPattern, timeoutMs) {
  13. try {
  14. if (!fs.existsSync(filePath)) {
  15. throw new Error(`File not found: ${filePath}`);
  16. }
  17. return new Promise((resolve, reject) => {
  18. const startTime = Date.now();
  19. const search = (data, pattern, offset) => {
  20. for (let i = 0; i <= data.length - pattern.length; i++) {
  21. let match = true;
  22. for (let j = 0; j < pattern.length; j++) {
  23. if (data[i + j] !== pattern[j]) {
  24. match = false;
  25. break;
  26. }
  27. }
  28. if (match) {
  29. resolve(offset + i);
  30. return;
  31. }
  32. }
  33. resolve(null);
  34. };
  35. const stream = fs.createReadStream(filePath, { highWaterMark: 64 * 1024 }); // 64KB chunks
  36. let buffer = '';
  37. let bytesRead = 0;
  38. stream.on('data', (chunk) => {
  39. buffer += chunk;
  40. bytesRead += chunk.length;
  41. if (Date.now() - startTime > timeoutMs) {
  42. stream.destroy(); // Stop reading if timeout
  43. resolve(null);
  44. return;
  45. }
  46. const hexPattern = pattern.startsWith('0x') ? pattern.substring(2).split('').map(Number) : pattern.split('').map(Number);
  47. if(bytesRead >= hexPattern.length) {
  48. search(buffer, hexPattern, 0);
  49. }
  50. });
  51. stream.on('end', () => {
  52. if (Date.now() - startTime > timeoutMs) {
  53. resolve(null);
  54. } else {
  55. search(buffer, hexPattern, 0);
  56. }
  57. });
  58. stream.on('error', (err) => {
  59. stream.destroy();
  60. reject(err);
  61. });
  62. });
  63. } catch (error) {
  64. throw error;
  65. }
  66. }
  67. module.exports = searchBinaryFile;

Add your comment