#![cfg(any(target_os = "linux", target_os = "macos"))]
use std::io;
use std::path::Path;
use std::process::Command;
pub fn inject_env_name() -> &'static str {
#[cfg(target_os = "linux")]
{
"LD_PRELOAD"
}
#[cfg(target_os = "macos")]
{
"DYLD_INSERT_LIBRARIES"
}
}
pub fn inject_via_env<'a>(
command: &'a mut Command,
interposer_path: &Path,
) -> io::Result<&'a mut Command> {
let meta = std::fs::metadata(interposer_path).map_err(|e| {
io::Error::new(
e.kind(),
format!(
"interposer library not accessible at {}: {e}",
interposer_path.display()
),
)
})?;
if !meta.is_file() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"interposer path must be a regular file, got {}",
interposer_path.display()
),
));
}
command.env(inject_env_name(), interposer_path);
Ok(command)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
use std::os::unix::fs::PermissionsExt;
fn stub_lib() -> (tempfile::TempDir, std::path::PathBuf) {
let dir = tempfile::tempdir().expect("tempdir");
let p = dir.path().join("lib_interposer.stub");
let mut f = std::fs::File::create(&p).expect("create");
f.write_all(b"stub").expect("write");
let mut perms = std::fs::metadata(&p).expect("stat").permissions();
perms.set_mode(0o644);
std::fs::set_permissions(&p, perms).expect("chmod");
(dir, p)
}
#[test]
fn inject_env_name_matches_platform() {
#[cfg(target_os = "linux")]
assert_eq!(inject_env_name(), "LD_PRELOAD");
#[cfg(target_os = "macos")]
assert_eq!(inject_env_name(), "DYLD_INSERT_LIBRARIES");
}
#[test]
fn inject_via_env_sets_the_env_var() {
let (_guard, lib) = stub_lib();
let mut cmd = Command::new("/bin/true");
let returned = inject_via_env(&mut cmd, &lib).expect("inject");
let _ = returned;
}
#[test]
fn inject_via_env_rejects_missing_path() {
let mut cmd = Command::new("/bin/true");
let err = inject_via_env(
&mut cmd,
std::path::Path::new("/nonexistent/path/to/lib.so"),
)
.expect_err("expected NotFound");
assert_eq!(err.kind(), io::ErrorKind::NotFound);
}
#[test]
fn inject_via_env_rejects_directory() {
let dir = tempfile::tempdir().expect("tempdir");
let mut cmd = Command::new("/bin/true");
let err = inject_via_env(&mut cmd, dir.path()).expect_err("expected InvalidInput");
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
}
}