From 6d791ba1e1c91c0f9a4d0b3165e34d4318c2287f Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Sun, 2 Jul 2017 05:15:03 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + find.js | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 17 ++++++ 3 files changed, 181 insertions(+) create mode 100644 .gitignore create mode 100644 find.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/find.js b/find.js new file mode 100644 index 0000000..254b7b0 --- /dev/null +++ b/find.js @@ -0,0 +1,163 @@ +'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); diff --git a/package.json b/package.json new file mode 100644 index 0000000..2a497cf --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "find-missing-files", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Sven Slootweg", + "license": "WTFPL", + "dependencies": { + "default-value": "^1.0.0", + "right-pad": "^1.0.1", + "split": "^1.0.0", + "through2": "^2.0.3" + } +}