diff options
Diffstat (limited to 'src/hasher.rs')
| -rw-r--r-- | src/hasher.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/hasher.rs b/src/hasher.rs index da00778..f2bf378 100644 --- a/src/hasher.rs +++ b/src/hasher.rs @@ -1,4 +1,5 @@ use std::ffi::OsString; +use std::path::Path; use std::process::Command; use anyhow::{Context, Result, bail}; @@ -54,6 +55,59 @@ impl CommandRunner for ProcessRunner { } } +/// Runs Hasher commands under the configured non-root Hasher account. +/// Root retains ownership of native rootfs finalization and packaging stages. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SudoUserRunner { + user: OsString, +} + +impl SudoUserRunner { + pub fn new(user: impl Into<OsString>) -> Self { + Self { user: user.into() } + } + + pub fn wrap(&self, invocation: Invocation) -> Invocation { + let mut arguments = vec![ + OsString::from("-n"), + OsString::from("-u"), + self.user.clone(), + ]; + arguments.push(invocation.program); + arguments.extend(invocation.arguments); + Invocation::new("sudo", arguments) + } + + pub fn prepare_workdir(&self, workdir: &Path) -> Invocation { + Invocation::new( + "sudo", + [ + "-n".into(), + "install".into(), + "-d".into(), + "-o".into(), + self.user.clone(), + "-g".into(), + self.user.clone(), + workdir.as_os_str().to_owned(), + ], + ) + } +} + +impl CommandRunner for SudoUserRunner { + fn run(&self, invocation: Invocation) -> Result<()> { + if let Some(workdir) = invocation + .arguments() + .windows(2) + .find_map(|pair| (pair[0] == "--workdir").then(|| Path::new(&pair[1]))) + { + ProcessRunner.run(self.prepare_workdir(workdir))?; + } + ProcessRunner.run(self.wrap(invocation)) + } +} + #[derive(Debug)] pub struct HasherInstaller<R> { runner: R, |