|
17 | 17 |
|
18 | 18 | use std::collections::BTreeMap; |
19 | 19 | use std::path::Path; |
20 | | -use std::process::Command; |
21 | 20 |
|
22 | 21 | use anyhow::{bail, Context, Result}; |
| 22 | +use cmd_lib::{run_cmd, run_fun}; |
23 | 23 | use dstack_types::volume::DstackVolumeHeader; |
24 | 24 | use fs_err as fs; |
25 | 25 | use sha2::{Digest, Sha256}; |
@@ -87,19 +87,13 @@ pub fn build_volume( |
87 | 87 | let data_path = tmp.path().join("data.fs"); |
88 | 88 |
|
89 | 89 | // 1. reproducible squashfs. |
90 | | - let mut cmd = Command::new("mksquashfs"); |
91 | | - cmd.arg(store).arg(&data_path); |
92 | | - cmd.args(compress.args()); |
93 | | - cmd.args([ |
94 | | - "-all-time", |
95 | | - EPOCH, |
96 | | - "-mkfs-time", |
97 | | - EPOCH, |
98 | | - "-noappend", |
99 | | - "-no-progress", |
100 | | - "-xattrs", |
101 | | - ]); |
102 | | - run(cmd, "mksquashfs")?; |
| 90 | + let compression_args = compress.args(); |
| 91 | + run_cmd!( |
| 92 | + mksquashfs $store $data_path $[compression_args] |
| 93 | + -all-time $EPOCH -mkfs-time $EPOCH -noappend -no-progress -xattrs |
| 94 | + >/dev/null |
| 95 | + ) |
| 96 | + .context("running mksquashfs")?; |
103 | 97 |
|
104 | 98 | // 2. the verity data region must be block-aligned; pad the squashfs up. |
105 | 99 | let bytes_used = squashfs_bytes_used(&data_path)?; |
@@ -147,20 +141,11 @@ fn seal_data_image( |
147 | 141 | // want the whole image reproducible, not just the root. The UUID sits in the |
148 | 142 | // hash tree, not the hashed data, so it never changes the root. |
149 | 143 | let uuid = uuid_from_data(data_path, data_size)?; |
150 | | - let mut cmd = Command::new("veritysetup"); |
151 | | - cmd.args([ |
152 | | - "format", |
153 | | - "--salt", |
154 | | - salt_hex, |
155 | | - "--uuid", |
156 | | - &uuid, |
157 | | - "--data-block-size", |
158 | | - "4096", |
159 | | - "--hash-block-size", |
160 | | - "4096", |
161 | | - ]); |
162 | | - cmd.arg(data_path).arg(&hash_path); |
163 | | - let out = capture(cmd, "veritysetup format")?; |
| 144 | + let out = run_fun!( |
| 145 | + veritysetup format --salt $salt_hex --uuid $uuid |
| 146 | + --data-block-size 4096 --hash-block-size 4096 $data_path $hash_path |
| 147 | + ) |
| 148 | + .context("running veritysetup format")?; |
164 | 149 | let verity_root = |
165 | 150 | parse_root_hash(&out).context("could not find the root hash in veritysetup output")?; |
166 | 151 |
|
@@ -406,42 +391,13 @@ fn parse_root_hash(output: &str) -> Option<String> { |
406 | 391 | } |
407 | 392 |
|
408 | 393 | fn require_tool(name: &str) -> Result<()> { |
409 | | - // spawning at all means the binary is on PATH; a non-zero exit from |
410 | | - // `--version` (some builds) still counts as present. |
411 | | - let present = Command::new(name) |
412 | | - .arg("--version") |
413 | | - .stdout(std::process::Stdio::null()) |
414 | | - .stderr(std::process::Stdio::null()) |
415 | | - .status() |
416 | | - .is_ok(); |
| 394 | + let present = run_cmd!(which $name >/dev/null 2>&1).is_ok(); |
417 | 395 | if !present { |
418 | 396 | bail!("`{name}` not found on PATH (install squashfs-tools / cryptsetup)"); |
419 | 397 | } |
420 | 398 | Ok(()) |
421 | 399 | } |
422 | 400 |
|
423 | | -fn run(mut cmd: Command, what: &str) -> Result<()> { |
424 | | - let status = cmd |
425 | | - .stdout(std::process::Stdio::null()) |
426 | | - .status() |
427 | | - .with_context(|| format!("running {what}"))?; |
428 | | - if !status.success() { |
429 | | - bail!("{what} failed with {status}"); |
430 | | - } |
431 | | - Ok(()) |
432 | | -} |
433 | | - |
434 | | -fn capture(mut cmd: Command, what: &str) -> Result<String> { |
435 | | - let out = cmd.output().with_context(|| format!("running {what}"))?; |
436 | | - if !out.status.success() { |
437 | | - bail!( |
438 | | - "{what} failed: {}", |
439 | | - String::from_utf8_lossy(&out.stderr).trim() |
440 | | - ); |
441 | | - } |
442 | | - Ok(String::from_utf8_lossy(&out.stdout).into_owned()) |
443 | | -} |
444 | | - |
445 | 401 | #[cfg(test)] |
446 | 402 | mod tests { |
447 | 403 | use super::*; |
|
0 commit comments