Skip to content

Instantly share code, notes, and snippets.

@Demon000
Last active December 6, 2019 18:03
Show Gist options
  • Save Demon000/3952082a3825c6ab8c6b4a0ad5029a81 to your computer and use it in GitHub Desktop.
Save Demon000/3952082a3825c6ab8c6b4a0ad5029a81 to your computer and use it in GitHub Desktop.
#!/usr/bin/node
const DEBUG = false;
const relativeFilesDirectory = process.argv[2];
const relativeFileStart = process.argv[3];
const filesDirectory = path.resolve(relativeFilesDirectory);
const fileStart = path.join(filesDirectory, relativeFileStart);
const promisePool = [];
const foundPaths = []
function getRelativePath(from, to) {
return path.relative(from, to);
}
function finished() {
foundPaths.forEach(function(path) {
console.log(getRelativePath(filesDirectory, path));
});
}
function addNeededLibraries(path, filesDirectory) {
const promise = getNeededLibraries(path, filesDirectory);
promisePool.push(promise);
promise.then(function(allPaths) {
const promiseIndex = promisePool.indexOf(promise);
promisePool.splice(promiseIndex, 1);
const paths = [];
allPaths.forEach(function(path) {
if (!foundPaths.includes(path)) {
paths.push(path);
}
});
paths.forEach(function(path) {
foundPaths.push(path);
addNeededLibraries(path, filesDirectory);
});
if (DEBUG) {
console.log(promisePool, foundPaths);
}
if (promisePool.length == 0 && paths.length == 0) {
finished();
}
});
}
addNeededLibraries(fileStart, filesDirectory);
const path = require('path');
const exec = require('child_process').exec;
function execute(command, outputFn) {
return new Promise(function(resolve, reject) {
exec(command, {
maxBuffer: 1024 * 1024 * 512,
}, function(error, stdout, stderr) {
if (error) {
console.error(error);
stdout = '';
}
if (stderr) {
console.log(stderr);
}
resolve(stdout);
});
});
}
function isImportantLibrary(library) {
return true;
}
async function getLibraryStrings(path) {
const STRINGS_COMMAND = `strings "${path}" | grep -F ".so"`;
const output = await execute(STRINGS_COMMAND);
let libraries;
if (output == '') {
libraries = [];
} else {
libraries = output.trim().split('\n')
}
return libraries.filter(isImportantLibrary);
}
async function getFileArch(path, archFn) {
const FILE_COMMAND = `file ${path}`;
const ARCH_REGEX = /ELF \d{2}-bit/;
const output = await execute(FILE_COMMAND);
const arch = output.match(ARCH_REGEX)[0];
return arch;
}
function toLinuxWildcardLibrary(library) {
return library.replace('%s', '*');
}
async function getPathsForLibrary(library, filesDirectory) {
const wildcard = toLinuxWildcardLibrary(library);
const FIND_COMMAND = `find ${filesDirectory} -name "${wildcard}"`;
const output = await execute(FIND_COMMAND);
let paths = output.trim().split('\n');
if (output == '') {
paths = [];
} else {
paths = output.trim().split('\n')
}
return paths;
}
async function getPathsForLibraries(libraries, filesDirectory) {
let allPaths = [];
for (const library of libraries) {
const paths = await getPathsForLibrary(library, filesDirectory);
allPaths = allPaths.concat(paths);
}
return allPaths;
}
async function filterFilesWithArch(paths, targetArch) {
const matchingPaths = [];
for (const path of paths) {
const fileArch = await getFileArch(path);
if (fileArch == targetArch) {
matchingPaths.push(path);
}
}
return matchingPaths;
}
async function getNeededLibraries(path, filesDirectory) {
const fileArch = await getFileArch(path);
const libraries = await getLibraryStrings(path);
const allPaths = await getPathsForLibraries(libraries, filesDirectory);
const paths = await filterFilesWithArch(allPaths, fileArch);
return paths;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment