From 34ac18d20c13a78914d447fee83204811a27b1e4 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 25 Oct 2021 00:19:45 +0200 Subject: Move runner into separate crate --- crates/runner/src/tar.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 crates/runner/src/tar.rs (limited to 'crates/runner/src/tar.rs') diff --git a/crates/runner/src/tar.rs b/crates/runner/src/tar.rs new file mode 100644 index 0000000..9306775 --- /dev/null +++ b/crates/runner/src/tar.rs @@ -0,0 +1,87 @@ +use std::{ + fs::File, + io::{self, Read, Write}, + os::unix::prelude::CommandExt, + path::Path, + process::{self, Command, Stdio}, +}; + +use nix::{ + mount::{self, MsFlags}, + sched::CloneFlags, + sys::wait, +}; + +use common::error::*; + +use super::{ + ns, + util::{fs, Checkable}, +}; +use crate::paths; + +pub fn pack>(archive: &mut W, source: P) -> Result<()> { + let (mut piper, pipew) = fs::pipe()?; + + let exec_tar = |stdout: File| -> Result<()> { + // We are in our own mount namespace, so mounting into the shared ROOTFS_DIR is fine + let mount_target = paths::join(&[paths::ROOTFS_DIR, paths::TASK_BUILDDIR]); + mount::mount::<_, _, str, str>( + Some(source.as_ref()), + mount_target.as_str(), + None, + MsFlags::MS_BIND, + None, + )?; + + ns::pivot_root(paths::ROOTFS_DIR); + + let err = Command::new("tar") + .args(&[ + "-c", + "--sort=name", + "--numeric-owner", + "--owner=0", + "--group=0", + "--mtime=@0", + ".", + ]) + .stdin(Stdio::null()) + .stdout(stdout) + .current_dir(paths::TASK_BUILDDIR) + .env_clear() + .env("PATH", "/usr/sbin:/usr/bin:/sbin:/bin") + .exec(); + eprintln!("{}", err); + process::exit(127); + }; + + let (pid, pipew) = unsafe { + ns::spawn(CloneFlags::CLONE_NEWNS, pipew, |pipew| { + exec_tar(pipew).unwrap() + }) + } + .context("Failed to run tar")?; + + drop(pipew); + let result = io::copy(&mut piper, archive).context("Failed to write TAR archive"); + + wait::waitpid(pid, None)? + .check() + .context("tar did not exit successfully")?; + + result?; + Ok(()) +} + +pub fn unpack>(archive: R, dest: P) -> Result<()> { + fs::mkdir(&dest)?; + + let mut ar = tar::Archive::new(archive); + ar.set_preserve_permissions(true); + ar.set_preserve_mtime(true); + ar.set_unpack_xattrs(true); + ar.set_overwrite(false); + + ar.unpack(dest).context("Failed to unpack TAR archive") +} -- cgit v1.2.3