diff --git a/Cargo.lock b/Cargo.lock index 139530a..d533193 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,6 +130,26 @@ dependencies = [ "syn 2.0.60", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.5.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.60", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -413,6 +433,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "env_logger" version = "0.10.2" @@ -619,6 +645,24 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -653,6 +697,7 @@ dependencies = [ "serde_yaml", "sudo", "tera", + "tiffin", "tracing", "tracing-error", "tracing-subscriber", @@ -699,13 +744,24 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "loopdev-3" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90a97d7a5124296ee9124a815acdc3dc4a91f577b72812b3f1f99bb959b46e8d" +dependencies = [ + "bindgen 0.69.5", + "errno", + "libc", +] + [[package]] name = "loopdev-fyra" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cec8b1f0742ca0817982b8ab1f7764ccdb99f06a8c1aa4ce24b0361a1ef74774" dependencies = [ - "bindgen", + "bindgen 0.68.1", "errno", "libc", ] @@ -1178,6 +1234,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smart-default" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "strsim" version = "0.11.1" @@ -1216,6 +1283,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sys-mount" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6acb8bb63826062d5a44b68298cf2e25b84bc151bc0c31c35a83b61f818682a" +dependencies = [ + "bitflags 2.5.0", + "libc", + "loopdev-3", + "smart-default", + "thiserror", + "tracing", +] + [[package]] name = "tera" version = "1.19.1" @@ -1277,6 +1358,18 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiffin" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90a4f96511214f78312e53fcfdf332a3bc67693bc2f1c266aac7676ac71859c" +dependencies = [ + "itertools 0.13.0", + "nix", + "sys-mount", + "tracing", +] + [[package]] name = "tracing" version = "0.1.40" diff --git a/Cargo.toml b/Cargo.toml index 8c799e3..31ac09f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,3 +39,4 @@ uuid = { version = "1.4.1", features = ["v4", "serde"] } loopdev-fyra = { version = "0.5.0" } bytesize = { version = "1.3.0", features = ["serde"] } indexmap = "2.2.6" +tiffin = "0.3.2" diff --git a/src/builder.rs b/src/builder.rs index 630bdb7..e39033e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -381,9 +381,13 @@ impl RootBuilder for DnfRootBuilder { // While grub2-mkconfig may not return 0 it should still work // todo: figure out why it still wouldn't write the file to /boot/grub2/grub.cfg // but works when run inside a post script - let res = crate::run_cmd_prep_chroot!(&chroot, - unshare -R $chroot grub2-mkconfig -o /boot/grub2/grub.cfg; - ); + let res = crate::util::enter_chroot_run(&chroot, || { + std::process::Command::new("grub2-mkconfig") + .arg("-o") + .arg("/boot/grub2/grub.cfg") + .status()?; + Ok(()) + }); if let Err(e) = res { warn!(?e, "grub2-mkconfig not returning 0, continuing anyway"); @@ -407,7 +411,8 @@ pub fn run_script(script: Script, chroot: &Path, is_post: bool) -> Result<()> { let id = script.id.as_ref().map_or("", |s| s); bail_let!(Some(mut data) = script.load() => "Cannot load script `{id}`"); let name = script.name.as_ref().map_or("", |s| s); - info!(id, name, "Running script"); + + info!(id, name, in_chroot = script.chroot, "Running script"); let name = format!("script-{}", script.id.as_ref().map_or("untitled", |s| s)); // check if data has shebang @@ -416,13 +421,21 @@ pub fn run_script(script: Script, chroot: &Path, is_post: bool) -> Result<()> { data.insert_str(0, "#!/bin/sh\n"); } + let mut tiffin = tiffin::Container::new(chroot.to_path_buf()); + if script.chroot.unwrap_or(is_post) { - just_write(chroot.join("tmp").join(&name), data)?; - crate::run_cmd_prep_chroot!(chroot, - chmod +x $chroot/tmp/$name; - unshare -R $chroot /tmp/$name 2>&1; - rm -f $chroot/tmp/$name; - )?; + tiffin.run(|| -> Result<()> { + // just_write(chroot.join("tmp").join(&name), data)?; + just_write(PathBuf::from(format!("/tmp/{name}")), data)?; + + cmd_lib::run_cmd!( + chmod +x /tmp/$name; + /tmp/$name 2>&1; + rm -f /tmp/$name; + )?; + + Ok(()) + })??; } else { just_write(PathBuf::from(format!("katsu-work/{name}")), data)?; // export envar @@ -534,9 +547,12 @@ impl ImageBuilder for DiskImageBuilder { // Let's use grub2-install to bless the disk info!("Blessing disk image with MBR"); - cmd_lib::run_cmd!( - grub2-install --target=i386-pc --boot-directory=$chroot/boot $ldp 2>&1; - )?; + std::process::Command::new("grub2-install") + .arg("--target=i386-pc") + .arg(format!("--boot-directory={}", chroot.join("boot").display())) + .arg(ldp) + .output() + .map_err(|e| color_eyre::eyre::eyre!("Failed to execute grub2-install: {}", e))?; } disk.unmount_from_chroot(chroot)?; @@ -649,10 +665,14 @@ impl IsoBuilder { dr_args.push(&dr_omit); } - crate::run_cmd_prep_chroot!(root, - unshare -R $root env - DRACUT_SYSTEMD=0 dracut $[dr_args] - /boot/initramfs-$kver.img --kver $kver 2>&1; - )?; + + + crate::util::enter_chroot_run(root, || -> Result<()> { + cmd_lib::run_cmd!( + env - DRACUT_SYSTEMD=0 dracut $[dr_args] /boot/initramfs-$kver.img --kver $kver 2>&1; + )?; + Ok(()) + })?; Ok(()) } diff --git a/src/config.rs b/src/config.rs index e02e1a2..8b65dbe 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,4 @@ -use crate::{builder::Bootloader, cli::OutputFormat, run_cmd_prep_chroot}; +use crate::{builder::Bootloader, cli::OutputFormat, util::enter_chroot_run}; use bytesize::ByteSize; use color_eyre::Result; use serde::Deserialize; @@ -843,7 +843,11 @@ impl Auth { trace!(?args, "useradd args"); - run_cmd_prep_chroot!(chroot, unshare -R $chroot useradd $[args] 2>&1)?; + enter_chroot_run(chroot, || { + info!(?self, "Adding user to chroot"); + std::process::Command::new("useradd").args(&args).status()?; + Ok(()) + })?; // add ssh keys if !self.ssh_keys.is_empty() { diff --git a/src/util.rs b/src/util.rs index 799fed3..07f75a0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -18,6 +18,14 @@ macro_rules! run { }}; } +/// Enters a chroot environment using `tiffin`, then runs the function +pub fn enter_chroot_run(root: &Path, f: F) -> Result<()> +where + F: FnOnce() -> Result<()>, +{ + tiffin::Container::new(root.to_path_buf()).run(f)? +} + /// Macro for string feature flags. /// Should return the value of the environment variable if defined, else None. /// @@ -62,7 +70,7 @@ macro_rules! chroot_run { } /// Preps chroot, then wraps around cmd_lib::run_cmd! -/// +/// /// # ***DOES NOT ACTUALLY CHROOT INTO THE ENVIRONMENT!!! YOU NEED TO RUN `unshare -R` YOURSELF*** /// Example: /// @@ -85,9 +93,9 @@ macro_rules! run_cmd_prep_chroot { } /// Preps chroot, then wraps around cmd_lib::run_fun! -/// +/// /// # ***DOES NOT ACTUALLY CHROOT INTO THE ENVIRONMENT!!! YOU NEED TO RUN `unshare -R` YOURSELF*** -/// +/// #[macro_export] macro_rules! prep_chroot_run_fun { ($chroot:expr, $($cmd:tt)*) => {{