use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::OnceLock;
pub fn ensure_worker_signed(worker_path: &Path) -> Result<(), String> {
static IN_PROCESS_DONE: OnceLock<()> = OnceLock::new();
if IN_PROCESS_DONE.get().is_some() {
return Ok(());
}
let meta = std::fs::metadata(worker_path)
.map_err(|e| format!("stat {}: {e}", worker_path.display()))?;
let worker_size = meta.len();
let worker_mtime = meta
.modified()
.ok()
.and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok())
.map(|d| d.as_secs())
.unwrap_or(0);
let sentinel_marker = format!(
"size={}\nmtime={}\npath={}\n",
worker_size,
worker_mtime,
worker_path.display()
);
if let Some(sentinel) = sentinel_path() {
if let Ok(existing) = std::fs::read_to_string(&sentinel) {
if existing == sentinel_marker {
IN_PROCESS_DONE.set(()).ok();
return Ok(());
}
}
}
let plist = std::env::temp_dir().join(format!(
"supermachine-entitlements-{}.plist",
std::process::id()
));
std::fs::write(&plist, crate::assets::ENTITLEMENTS_PLIST)
.map_err(|e| format!("write entitlements plist: {e}"))?;
let status = Command::new("codesign")
.args(["-s", "-", "--entitlements"])
.arg(&plist)
.arg("--force")
.arg(worker_path)
.stdout(Stdio::null())
.stderr(Stdio::piped())
.status();
let _ = std::fs::remove_file(&plist);
match status {
Ok(s) if s.success() => {
if let Some(sentinel) = sentinel_path() {
if let Some(parent) = sentinel.parent() {
let _ = std::fs::create_dir_all(parent);
}
let _ = std::fs::write(&sentinel, sentinel_marker);
}
IN_PROCESS_DONE.set(()).ok();
Ok(())
}
Ok(s) => Err(format!(
"codesign exited with {:?} for {}",
s.code(),
worker_path.display()
)),
Err(e) => Err(format!(
"failed to spawn codesign for {}: {e}\n\
(codesign ships with macOS by default; if missing, \
reinstall Xcode Command Line Tools)",
worker_path.display()
)),
}
}
pub fn locate_worker_bin() -> Option<PathBuf> {
let exe = std::env::current_exe().ok()?;
if let Some(dir) = exe.parent() {
let sibling = dir.join("supermachine-worker");
if sibling.is_file() {
return Some(sibling);
}
}
for ancestor in exe.ancestors() {
let p = ancestor.join("target/release/supermachine-worker");
if p.is_file() {
return Some(p);
}
}
None
}
fn sentinel_path() -> Option<PathBuf> {
let base = if let Some(d) = std::env::var_os("XDG_DATA_HOME") {
PathBuf::from(d)
} else if let Some(h) = std::env::var_os("HOME") {
PathBuf::from(h).join(".local/share")
} else {
return None;
};
Some(
base.join("supermachine")
.join(format!("v{}", env!("CARGO_PKG_VERSION")))
.join(".worker-signed"),
)
}