use bestool_kopia::{Elevation, LINUX_KOPIA_USER, find_kopia_binary, linux_elevation};
use miette::{Result, miette};
use tracing::debug;
use super::KopiaArgs;
pub fn kopia_binary(args: &KopiaArgs) -> Result<std::path::PathBuf> {
find_kopia_binary(args.kopia_bin.as_deref()).ok_or_else(|| {
miette!("could not find a `kopia` binary in PATH; install kopia or pass --kopia-bin")
})
}
pub fn current_hostname() -> Option<String> {
sysinfo::System::host_name()
}
pub fn maybe_reexec_as_kopia(args: &KopiaArgs) -> Result<()> {
if args.no_sudo {
return Ok(());
}
if !cfg!(target_os = "linux") {
return Ok(());
}
match linux_elevation() {
Elevation::Direct => Ok(()),
Elevation::Sudo => {
debug!("re-executing under sudo -u {LINUX_KOPIA_USER}");
exec_under_sudo(LINUX_KOPIA_USER)
}
Elevation::Skip(reason) => {
debug!("not re-executing under kopia: {reason}");
Ok(())
}
}
}
#[cfg(unix)]
fn exec_under_sudo(user: &str) -> Result<()> {
use std::os::unix::process::CommandExt;
let argv: Vec<std::ffi::OsString> = std::env::args_os().collect();
let Some((exe, rest)) = argv.split_first() else {
return Err(miette!("no argv to re-exec"));
};
let mut cmd = std::process::Command::new("sudo");
cmd.arg("-u").arg(user).arg("--").arg(exe).args(rest);
let err = cmd.exec();
Err(miette!("failed to re-exec under sudo: {err}"))
}
#[cfg(not(unix))]
fn exec_under_sudo(_user: &str) -> Result<()> {
Err(miette!("sudo re-exec only supported on Unix"))
}