diff --git a/Cargo.lock b/Cargo.lock index a8a6807..f7a5548 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,6 +418,16 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -901,6 +911,7 @@ dependencies = [ "serde_yaml", "shell-escape", "sys-info", + "tar", "termios", "tokio", "unix_mode", @@ -1709,6 +1720,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", +] + [[package]] name = "tempfile" version = "3.27.0" diff --git a/Cargo.toml b/Cargo.toml index 91ecb99..71d57d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,3 +32,4 @@ openssl = "0.10.73" reqwest = { git = "https://github.com/mcluseau/rs-reqwest", version = "0.13.1", features = ["native-tls", "system-proxy", "socks"], default-features = false } glob = "0.3.3" hex = "0.4.3" +tar = { version = "0.4.46", default-features = false } diff --git a/src/cmd/init/bootstrap.rs b/src/cmd/init/bootstrap.rs index ff5dba1..933abc5 100644 --- a/src/cmd/init/bootstrap.rs +++ b/src/cmd/init/bootstrap.rs @@ -152,34 +152,42 @@ impl Verifier { } async fn seed_config( - base_dir: &str, + base_dir: impl Into, bs: &dkl::bootstrap::Bootstrap, verifier: &Verifier, ) -> Result> { - let cfg_path = &format!("{base_dir}/config.yaml"); + let base_dir = base_dir.into(); - if fs::try_exists(cfg_path).await? { - return verifier.verify_path(&cfg_path).await; + let cfg_path = base_dir.join("config.yaml"); + + if fs::try_exists(&cfg_path).await? { + return verifier.verify_path(cfg_path).await; } let bs_tar = "/bootstrap.tar"; - if !fs::try_exists(bs_tar).await? { + if !fs::try_exists(&bs_tar).await? { if bs.seed.is_none() { return Err(format_err!( - "no {cfg_path}, no {bs_tar} and no seed URL, can't bootstrap" + "no {}, no {bs_tar} and no seed URL, can't bootstrap", + cfg_path.display() )); } fetch_bootstrap(bs, bs_tar).await?; } - let tmp_dir = &format!("{base_dir}.new"); - fs::create_dir_all(tmp_dir).await?; + let tmp_dir = base_dir.with_added_extension("new"); + fs::create_dir_all(&tmp_dir).await?; - try_exec("tar", &["xf", bs_tar, "-C", tmp_dir]).await?; + untar(bs_tar, &tmp_dir) + .await + .map_err(|e| format_err!("untar failed: {e}"))?; - let cfg_path = &format!("{tmp_dir}/config.yaml"); - if !fs::try_exists(cfg_path).await? { - return Err(format_err!("{cfg_path} does not exist after seeding")); + let cfg_path = tmp_dir.join("config.yaml"); + if !fs::try_exists(&cfg_path).await? { + return Err(format_err!( + "{} does not exist after seeding", + cfg_path.display() + )); } let cfg_bytes = verifier.verify_path(&cfg_path).await?; @@ -236,6 +244,18 @@ async fn fetch_bootstrap(bs: &dkl::bootstrap::Bootstrap, output_file: &str) -> R Ok(()) } +async fn untar(arch: impl Into, target: impl Into) -> Result<()> { + let arch = arch.into(); + let target = target.into(); + tokio::task::spawn_blocking(move || { + let tar = std::fs::File::open(arch)?; + let mut tar = tar::Archive::new(tar); + tar.unpack(target) + }) + .await??; + Ok(()) +} + fn default_root_tmpfs_opts() -> Option { let mem = sys_info::mem_info() .inspect_err(|e| warn!("failed to get system memory info, using default tmpfs size: {e}"))