use std::path::{Path, PathBuf};
const WRAPPER: &str = r#"#!/bin/sh
# Written by the Isothrum runner: sends ovftool's ESXi target through its loopback relay.
n=$#; i=0
while [ "$i" -lt "$n" ]; do
a=$1; shift
case "$a" in
vi://*@127.0.0.1*) a=$(printf '%s' "$a" | /usr/bin/sed -E "s#@127\.0\.0\.1(/|\$)#@127.0.0.1:${ISOTHRUM_OVFTOOL_PORT}\1#") ;;
esac
set -- "$@" "$a"; i=$((i + 1))
done
exec "$ISOTHRUM_REAL_OVFTOOL" "$@"
"#;
const FUSION_OVFTOOL: &str = "/Applications/VMware Fusion.app/Contents/Library/VMware OVF Tool/ovftool";
pub(super) fn real(path: Option<&str>) -> Option<String> {
let on_path = path.and_then(|p| std::env::split_paths(p).map(|d| d.join("ovftool")).find(|f| f.is_file()));
on_path
.or_else(|| Some(PathBuf::from(FUSION_OVFTOOL)).filter(|f| f.is_file()))
.map(|p| p.display().to_string())
}
pub(super) fn wrapper_dir(home: &Path) -> std::io::Result<PathBuf> {
let dir = home.join("relay");
crate::store::private_dir(&dir)?;
let f = dir.join("ovftool");
if std::fs::read_to_string(&f).ok().as_deref() != Some(WRAPPER) {
crate::store::write_private(&f, WRAPPER.as_bytes())?;
}
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&f, std::fs::Permissions::from_mode(0o700))?;
}
Ok(dir)
}
#[cfg(all(test, unix))]
mod tests {
use super::*;
#[test]
fn the_wrapper_adds_the_relay_port_to_the_vi_target() {
let home = tempfile::tempdir().unwrap();
let dir = wrapper_dir(home.path()).unwrap();
let out = std::process::Command::new(dir.join("ovftool"))
.args(["--noSSLVerify", "box.vmx", "vi://root:p%40ss@127.0.0.1/pool"])
.env("ISOTHRUM_OVFTOOL_PORT", "40443")
.env("ISOTHRUM_REAL_OVFTOOL", "/bin/echo")
.output()
.unwrap();
assert_eq!(
String::from_utf8_lossy(&out.stdout).trim(),
"--noSSLVerify box.vmx vi://root:p%40ss@127.0.0.1:40443/pool"
);
}
}