summaryrefslogtreecommitdiff
path: root/src/hasher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/hasher.rs')
-rw-r--r--src/hasher.rs54
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,