ghidra_worker_ctl/
config.rs1use std::path::{Path, PathBuf};
8use std::time::Duration;
9
10#[derive(Debug, Clone)]
11pub struct WorkerConfig {
12 pub ghidra_install_dir: PathBuf,
14 pub project_dir: PathBuf,
16 pub project_name: String,
17 pub bootstrap_program: String,
21 pub script_dir: PathBuf,
23 pub script_name: String,
25 pub max_heap: Option<String>,
27 pub boot_timeout: Duration,
29}
30
31impl WorkerConfig {
32 pub fn analyze_headless_path(&self) -> PathBuf {
34 #[cfg(windows)]
35 let name = "analyzeHeadless.bat";
36 #[cfg(not(windows))]
37 let name = "analyzeHeadless";
38 self.ghidra_install_dir.join("support").join(name)
39 }
40
41 pub fn build_argv(&self, port: u16, token_file: &Path) -> Vec<String> {
44 let mut argv = vec![
45 self.project_dir.to_string_lossy().into_owned(),
46 self.project_name.clone(),
47 "-process".to_string(),
48 self.bootstrap_program.clone(),
49 "-noanalysis".to_string(),
53 "-scriptPath".to_string(),
54 self.script_dir.to_string_lossy().into_owned(),
55 "-postScript".to_string(),
56 self.script_name.clone(),
57 port.to_string(),
58 token_file.to_string_lossy().into_owned(),
59 ];
60 argv.shrink_to_fit();
61 argv
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use std::path::PathBuf;
69 use std::time::Duration;
70
71 fn sample() -> WorkerConfig {
72 WorkerConfig {
73 ghidra_install_dir: PathBuf::from(r"C:\ghidra"),
74 project_dir: PathBuf::from(r"C:\proj"),
75 project_name: "p".to_string(),
76 bootstrap_program: "fixture".to_string(),
77 script_dir: PathBuf::from(r"C:\scripts"),
78 script_name: "GhidraMcpWorker.java".to_string(),
79 max_heap: None,
80 boot_timeout: Duration::from_secs(60),
81 }
82 }
83
84 #[test]
85 fn argv_has_process_writable_noanalysis_and_postscript_with_args() {
86 let argv = sample().build_argv(51000, std::path::Path::new(r"C:\t\x.token"));
87 assert_eq!(argv[0], r"C:\proj");
89 assert_eq!(argv[1], "p");
90 assert!(argv.iter().any(|a| a == "-process"));
94 assert!(argv.iter().any(|a| a == "fixture"));
95 assert!(!argv.iter().any(|a| a == "-readOnly"));
96 assert!(argv.iter().any(|a| a == "-noanalysis"));
97 let sp = argv.iter().position(|a| a == "-scriptPath").unwrap();
99 assert_eq!(argv[sp + 1], r"C:\scripts");
100 let ps = argv.iter().position(|a| a == "-postScript").unwrap();
101 assert_eq!(argv[ps + 1], "GhidraMcpWorker.java");
102 assert_eq!(argv[ps + 2], "51000");
103 assert_eq!(argv[ps + 3], r"C:\t\x.token");
104 }
105
106 #[test]
107 fn analyze_headless_path_is_platform_launcher_under_support() {
108 let p = sample().analyze_headless_path();
109 let s = p.to_string_lossy();
110 assert!(s.contains("support"));
111 #[cfg(windows)]
112 assert!(s.ends_with("analyzeHeadless.bat"));
113 #[cfg(not(windows))]
114 assert!(s.ends_with("analyzeHeadless"));
115 }
116}