const fs = require('fs');
const { spawn } = require('child_process');
/**
* Searches for a pattern within a binary file, with a timeout.
*
* @param {string} filePath - The path to the binary file.
* @param {string} searchPattern - The pattern to search for (hex or byte sequence).
* @param {number} timeoutMs - The timeout in milliseconds.
* @returns {Promise<number|null>} - The starting byte index of the first match, or null if no match found within the timeout.
* @throws {Error} If the file does not exist.
*/
async function searchBinaryFile(filePath, searchPattern, timeoutMs) {
try {
if (!fs.existsSync(filePath)) {
throw new Error(`File not found: ${filePath}`);
}
return new Promise((resolve, reject) => {
const startTime = Date.now();
const search = (data, pattern, offset) => {
for (let i = 0; i <= data.length - pattern.length; i++) {
let match = true;
for (let j = 0; j < pattern.length; j++) {
if (data[i + j] !== pattern[j]) {
match = false;
break;
}
}
if (match) {
resolve(offset + i);
return;
}
}
resolve(null);
};
const stream = fs.createReadStream(filePath, { highWaterMark: 64 * 1024 }); // 64KB chunks
let buffer = '';
let bytesRead = 0;
stream.on('data', (chunk) => {
buffer += chunk;
bytesRead += chunk.length;
if (Date.now() - startTime > timeoutMs) {
stream.destroy(); // Stop reading if timeout
resolve(null);
return;
}
const hexPattern = pattern.startsWith('0x') ? pattern.substring(2).split('').map(Number) : pattern.split('').map(Number);
if(bytesRead >= hexPattern.length) {
search(buffer, hexPattern, 0);
}
});
stream.on('end', () => {
if (Date.now() - startTime > timeoutMs) {
resolve(null);
} else {
search(buffer, hexPattern, 0);
}
});
stream.on('error', (err) => {
stream.destroy();
reject(err);
});
});
} catch (error) {
throw error;
}
}
module.exports = searchBinaryFile;
Add your comment