summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/runner/src/task.rs41
1 files changed, 36 insertions, 5 deletions
diff --git a/crates/runner/src/task.rs b/crates/runner/src/task.rs
index a6fbd25..08b9cb4 100644
--- a/crates/runner/src/task.rs
+++ b/crates/runner/src/task.rs
@@ -1,6 +1,6 @@
use std::{
collections::HashMap,
- io::BufWriter,
+ io::{self, BufWriter},
os::unix::prelude::CommandExt,
path::Path,
process::{self, Command, Stdio},
@@ -15,7 +15,7 @@ use nix::{
unistd::{self, Gid, Uid},
};
use serde::Serialize;
-use tee_readwrite::TeeWriter;
+use tee_readwrite::{TeeReader, TeeWriter};
use common::{error::*, string_hash::*, types::*};
@@ -156,9 +156,39 @@ fn cleanup_task(input_hash: &InputHash) -> Result<()> {
Ok(())
}
-fn unpack_dependency<P1: AsRef<Path>, P2: AsRef<Path>>(filename: P1, dest: P2) -> Result<()> {
- let file = fs::open(filename.as_ref())?;
- tar::unpack(file, dest.as_ref()).with_context(|| {
+fn unpack_dependency<P1: AsRef<Path>, P2: AsRef<Path>>(
+ filename: P1,
+ dest: P2,
+ expected_hash: &ArchiveHash,
+) -> Result<()> {
+ (|| -> Result<()> {
+ let file = fs::open(filename.as_ref())?;
+ let hasher = ArchiveHasher::new();
+ let buffered_hasher = BufWriter::with_capacity(16 * 1024 * 1024, hasher);
+ let mut reader = TeeReader::new(file, buffered_hasher, false);
+
+ tar::unpack(&mut reader, dest.as_ref())?;
+
+ // Read file to end to get the correct hash
+ io::copy(&mut reader, &mut io::sink())?;
+
+ let (_, buffered_hasher) = reader.into_inner();
+ let hasher = buffered_hasher.into_inner()?;
+
+ let actual_hash = ArchiveHash(StringHash(hasher.finalize().into()));
+
+ if &actual_hash != expected_hash {
+ return Err(Error::new(format!(
+ "Incorrect file hash for {:?} (expected: {}, actual: {})",
+ filename.as_ref(),
+ expected_hash,
+ actual_hash
+ )));
+ }
+
+ Ok(())
+ })()
+ .with_context(|| {
format!(
"Failed to unpack {:?} to {:?}",
filename.as_ref(),
@@ -189,6 +219,7 @@ fn unpack_dependencies(input_hash: &InputHash, task: &Task) -> Result<()> {
unpack_dependency(
paths::archive_filename(output),
paths::join(&[&depends_dir, path]),
+ output,
)?;
}
}