mirror of
https://github.com/storytold/craft-anything.git
synced 2026-11-05 20:47:45 +01:00
Find Ghidra installed from a Linux package
Linux packages put Ghidra in /opt/ghidra (Arch and its derivatives) or /usr/share/ghidra (Debian, Kali) with only a start script on PATH, so Deep mode said Ghidra wasn't there (#85). The engine table lists both folders and the Ghidra lookup falls back to them.
This commit is contained in:
@@ -26,7 +26,7 @@ pub fn can_install() -> bool {
|
||||
}
|
||||
|
||||
/// Ghidra's headless launcher: in the folder the person picked (Ghidra's own folder, or one that
|
||||
/// holds it), then the managed install, then PATH.
|
||||
/// holds it), then the managed install, then PATH, then where system packages put it.
|
||||
pub fn headless(install_dir: Option<&Path>, store: &Path) -> Option<PathBuf> {
|
||||
if let Some(dir) = install_dir {
|
||||
if dir.is_file() {
|
||||
@@ -36,7 +36,9 @@ pub fn headless(install_dir: Option<&Path>, store: &Path) -> Option<PathBuf> {
|
||||
return Some(p);
|
||||
}
|
||||
}
|
||||
in_child(&store.join(ID), launcher).or_else(|| crate::find_on_path(&["analyzeHeadless.bat", "analyzeHeadless"]))
|
||||
in_child(&store.join(ID), launcher)
|
||||
.or_else(|| crate::find_on_path(&["analyzeHeadless.bat", "analyzeHeadless"]))
|
||||
.or_else(|| crate::well_known(ID).into_iter().find(|p| p.is_file()))
|
||||
}
|
||||
|
||||
/// The Java runtime to run Ghidra with: the one the person set, else the managed one. `None` lets
|
||||
@@ -150,7 +152,9 @@ mod tests {
|
||||
let d = tempfile::tempdir().unwrap();
|
||||
let store = d.path().join("store");
|
||||
let exe = if cfg!(windows) { "analyzeHeadless.bat" } else { "analyzeHeadless" };
|
||||
assert!(headless(None, &store).is_none() || crate::find_on_path(&[exe]).is_some());
|
||||
// None, unless this computer has Ghidra on PATH or from a system package.
|
||||
let installed = crate::find_on_path(&[exe]).is_some() || crate::well_known(ID).iter().any(|p| p.is_file());
|
||||
assert!(headless(None, &store).is_none() || installed);
|
||||
// The managed install: the zip's own top folder under <store>/ghidra.
|
||||
let managed = store.join("ghidra/ghidra_12.1.4_PUBLIC/support").join(exe);
|
||||
touch(&managed);
|
||||
|
||||
@@ -82,7 +82,7 @@ fn in_managed(dir: &Path, exes: &[&str]) -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
/// Standard install locations for programs that don't put themselves on PATH (browsers on
|
||||
/// Windows and macOS), most common first.
|
||||
/// Windows and macOS, Ghidra from Linux packages), most common first.
|
||||
pub fn well_known(id: &str) -> Vec<PathBuf> {
|
||||
engine(id).map(ExternalEngine::known_install_paths).unwrap_or_default()
|
||||
}
|
||||
@@ -135,7 +135,9 @@ mod tests {
|
||||
// Nothing but folders: still none, not a panic.
|
||||
let empty = tempfile::tempdir().unwrap();
|
||||
std::fs::create_dir_all(empty.path().join("ghidra").join("ghidra_12.1.4_PUBLIC")).unwrap();
|
||||
assert!(locate("ghidra", &NoOverrides, empty.path()).is_none());
|
||||
// (Unless this computer has Ghidra on PATH or from a system package.)
|
||||
let installed = find_on_path(&[exe]).is_some() || well_known("ghidra").iter().any(|p| p.is_file());
|
||||
assert!(locate("ghidra", &NoOverrides, empty.path()).is_none() || installed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -146,5 +148,12 @@ mod tests {
|
||||
assert!(paths.iter().any(|p| p.to_string_lossy().contains("Chrome")));
|
||||
assert!(paths.iter().any(|p| p.to_string_lossy().contains("Edge")));
|
||||
}
|
||||
// #85: Linux packages put Ghidra in its own folder with only a start script on PATH.
|
||||
let ghidra = well_known("ghidra");
|
||||
if cfg!(target_os = "linux") {
|
||||
assert_eq!(ghidra, [PathBuf::from("/opt/ghidra/support/analyzeHeadless"), PathBuf::from("/usr/share/ghidra/support/analyzeHeadless")]);
|
||||
} else {
|
||||
assert!(ghidra.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,8 +144,16 @@ const fn mac(base: Base, rel: &'static str) -> KnownPath {
|
||||
KnownPath { os: "macos", base, rel }
|
||||
}
|
||||
|
||||
const fn linux(dir: &'static str, rel: &'static str) -> KnownPath {
|
||||
KnownPath { os: "linux", base: Base::Dir(dir), rel }
|
||||
}
|
||||
|
||||
const NO_PATHS: &[KnownPath] = &[];
|
||||
|
||||
/// Linux packages put Ghidra in a folder of its own and only a start script on PATH (`/usr/bin/ghidra`):
|
||||
/// Arch and its derivatives in `/opt/ghidra`, Debian and Kali in `/usr/share/ghidra` (#85).
|
||||
const GHIDRA_PATHS: &[KnownPath] = &[linux("/opt/ghidra", "support/analyzeHeadless"), linux("/usr/share/ghidra", "support/analyzeHeadless")];
|
||||
|
||||
/// Browsers on Windows and macOS rarely put themselves on PATH.
|
||||
const CHROMIUM_PATHS: &[KnownPath] = &[
|
||||
win("ProgramFiles", "Google/Chrome/Application/chrome.exe"),
|
||||
@@ -322,7 +330,7 @@ pub const ENGINES: &[ExternalEngine] = &[
|
||||
needed_for: "Deep mode: richer decompiled code",
|
||||
exes: &["analyzeHeadless"],
|
||||
exes_windows: &["analyzeHeadless.bat"],
|
||||
known_paths: NO_PATHS,
|
||||
known_paths: GHIDRA_PATHS,
|
||||
path_setting: false,
|
||||
install: Install::Guided { pins: GHIDRA_PINS, how: GHIDRA_SETUP },
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user