You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
5.0 KiB
JavaScript
164 lines
5.0 KiB
JavaScript
'use strict';
|
|
|
|
const split = require("split");
|
|
const through2 = require("through2");
|
|
const path = require("path");
|
|
const rightPad = require("right-pad");
|
|
const defaultValue = require("default-value");
|
|
|
|
let unfound = {};
|
|
let found = {};
|
|
let foundBase = {};
|
|
let probablyNotReallyMissing = {};
|
|
let ceaseProcessing = false;
|
|
|
|
let bannedPrefixes = [
|
|
"/dev/",
|
|
"/sys/",
|
|
"/run/"
|
|
]
|
|
|
|
function isLibrary(name) {
|
|
return (name.match(/\.so(?:\.[0-9]+)?$/) && !name.match(/\.so(?:\.[0-9]+)\.so$/));
|
|
}
|
|
|
|
function getLibraryName(name) {
|
|
let match = /^(.+)\.so(?:\.[0-9]+)?$/.exec(name);
|
|
|
|
if (match == null) {
|
|
throw new Error(`Library name regex failed for library: ${name}`);
|
|
} else {
|
|
return match[1];
|
|
}
|
|
}
|
|
|
|
process.stdin
|
|
.pipe(split())
|
|
.pipe(through2.obj(function(item, enc, cb) {
|
|
if (item.trim().length === 0) {
|
|
cb();
|
|
} else {
|
|
let match = /^\s*(?:\[pid\s*[0-9]+\] )?(?:open|stat)\("([^"]+)", ([A-Z_|]+|0x[0-9a-f]+|\{[^\}]+\})\) = (-?[0-9]+)(?: ([A-Z]+))?/.exec(item.toString());
|
|
|
|
if (match != null) {
|
|
let path = match[1];
|
|
|
|
if (!bannedPrefixes.some(prefix => path.indexOf(prefix) === 0)) {
|
|
this.push({
|
|
path: match[1],
|
|
flags: match[2].split("|"),
|
|
status: parseInt(match[3]),
|
|
error: match[4]
|
|
});
|
|
}
|
|
}
|
|
cb();
|
|
}
|
|
}))
|
|
.pipe(through2.obj(function(item, enc, cb) {
|
|
let basename = path.basename(item.path);
|
|
|
|
if (basename === "gdb") {
|
|
ceaseProcessing = true;
|
|
found["-- GDB ENCOUNTERED --"] = "";
|
|
unfound["-- GDB ENCOUNTERED --"] = "";
|
|
}
|
|
|
|
if (ceaseProcessing === false) {
|
|
if (item.status === -1) {
|
|
unfound[basename] = item.path;
|
|
} else {
|
|
delete unfound[basename];
|
|
found[basename] = item.path;
|
|
|
|
if (isLibrary(basename)) {
|
|
foundBase[getLibraryName(basename)] = item.path;
|
|
}
|
|
}
|
|
}
|
|
|
|
cb();
|
|
}))
|
|
.on("finish", () => {
|
|
Object.keys(unfound).forEach((basename) => {
|
|
function markNotMissing(reason) {
|
|
delete unfound[basename];
|
|
probablyNotReallyMissing[basename] = reason;
|
|
}
|
|
|
|
if (basename.match(/\.dll.so$/) && found[basename.slice(0, -3)]) {
|
|
markNotMissing("mono: is actually a DLL");
|
|
} else if (basename.match(/\.dll.so.la$/) && found[basename.slice(0, -6)]) {
|
|
markNotMissing("mono: is actually a DLL");
|
|
} else if (basename.match(/\.res(?:G|S)?$/)) {
|
|
markNotMissing("unity: .res / .resG / .resS file");
|
|
} else if (unfound[basename].match(/\/aot-cache\/[^\/]+\/[^\/]+$/)) {
|
|
markNotMissing("mono: is an AOT cache path");
|
|
} else if (isLibrary(basename) && foundBase[getLibraryName(basename)]) {
|
|
markNotMissing("other library version was already found")
|
|
}
|
|
});
|
|
|
|
function toArray(obj) {
|
|
return Object.keys(obj).map((key) => {
|
|
let value = obj[key];
|
|
|
|
return {
|
|
basename: key,
|
|
path: value
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
let foundItems = toArray(found);
|
|
let missingItems = toArray(unfound);
|
|
let probablyNotReallyMissingItems = toArray(probablyNotReallyMissing);
|
|
|
|
let missingLibraries = [];
|
|
let missingOther = [];
|
|
|
|
missingItems.forEach((item) => {
|
|
if (isLibrary(item.basename)) {
|
|
missingLibraries.push(item);
|
|
} else {
|
|
missingOther.push(item);
|
|
}
|
|
});
|
|
|
|
function printCategory(name, items, options = {}) {
|
|
let maxWidth = Math.max.apply(null, items.map(item => item.basename.length));
|
|
let cutoff = defaultValue(options.cutoff, 30);
|
|
let pathFormat = defaultValue(options.pathFormat, "%");
|
|
|
|
console.log(`\n${name}:`);
|
|
|
|
if (items.length === 0) {
|
|
console.log(" (none)");
|
|
} else {
|
|
items.slice(0, cutoff).forEach((item) => {
|
|
console.log(` ${rightPad(item.basename, maxWidth + 5)}${pathFormat.replace("%", item.path)}`);
|
|
});
|
|
|
|
if (items.length > cutoff) {
|
|
console.log(` (... ${items.length - cutoff} more ...)`);
|
|
}
|
|
}
|
|
}
|
|
|
|
printCategory("Found", foundItems);
|
|
|
|
printCategory("Probably found", probablyNotReallyMissingItems, {
|
|
pathFormat: "reason: %"
|
|
});
|
|
|
|
printCategory("Missing miscellaneous", missingOther, {
|
|
pathFormat: "(last attempted path: %)"
|
|
});
|
|
|
|
printCategory("MISSING LIBRARIES", missingLibraries, {
|
|
pathFormat: "(last attempted path: %)"
|
|
});
|
|
})
|
|
.pipe(process.stdout);
|