diff --git a/rust/src/cliwrap/kernel_install.rs b/rust/src/cliwrap/kernel_install.rs index cc2a0077b0..5344094c34 100644 --- a/rust/src/cliwrap/kernel_install.rs +++ b/rust/src/cliwrap/kernel_install.rs @@ -1,15 +1,12 @@ // If not running on container continue the current path. // SPDX-License-Identifier: Apache-2.0 OR MIT -use crate::cliwrap; use crate::cliwrap::cliutil; -use anyhow::{anyhow, Context, Result}; +use anyhow::Result; use camino::Utf8Path; use cap_std::fs::FileType; use cap_std::fs_utf8::Dir as Utf8Dir; use cap_std_ext::cap_std; use fn_error_context::context; -use std::os::fd::AsRawFd; -use std::process::Command; /// Primary entrypoint to running our wrapped `kernel-install` handling. #[context("rpm-ostree kernel-install wrapper")] @@ -42,7 +39,7 @@ pub(crate) fn main(argv: &[&str]) -> Result<()> { } if let Some(k) = new_kernel { undo_systemctl_wrap()?; - run_dracut(&k)?; + crate::initramfs::run_dracut(&k)?; redo_systemctl_wrap()?; } Ok(()) @@ -63,50 +60,3 @@ fn redo_systemctl_wrap() -> Result<()> { bin_path.rename("systemctl.backup", &bin_path, "systemctl")?; Ok(()) } - -#[context("Running dracut")] -fn run_dracut(kernel_dir: &str) -> Result<()> { - let root_fs = Utf8Dir::open_ambient_dir("/", cap_std::ambient_authority())?; - let tmp_dir = tempfile::tempdir()?; - let tmp_initramfs_path = tmp_dir.path().join("initramfs.img"); - - let cliwrap_dracut = Utf8Path::new(cliwrap::CLIWRAP_DESTDIR).join("dracut"); - let dracut_path = cliwrap_dracut - .exists() - .then(|| cliwrap_dracut) - .unwrap_or_else(|| Utf8Path::new("dracut").to_owned()); - // If changing this, also look at changing rpmostree-kernel.cxx - let res = Command::new(dracut_path) - .args(&[ - "--no-hostonly", - "--kver", - kernel_dir, - "--reproducible", - "-v", - "--add", - "ostree", - "-f", - ]) - .arg(&tmp_initramfs_path) - .status()?; - if !res.success() { - return Err(anyhow!( - "Failed to generate initramfs (via dracut) for kernel: {kernel_dir}: {:?}", - res - )); - } - let f = std::fs::OpenOptions::new() - .write(true) - .append(true) - .open(&tmp_initramfs_path)?; - crate::initramfs::append_dracut_random_cpio(f.as_raw_fd())?; - drop(f); - let utf8_tmp_dir_path = Utf8Path::from_path(tmp_dir.path().strip_prefix("/")?) - .context("Error turning Path to Utf8Path")?; - root_fs.rename( - utf8_tmp_dir_path.join("initramfs.img"), - &root_fs, - (Utf8Path::new("lib/modules").join(kernel_dir)).join("initramfs.img"), - )?; - Ok(()) -} diff --git a/rust/src/initramfs.rs b/rust/src/initramfs.rs index 4b3c8135ad..465ef068f1 100644 --- a/rust/src/initramfs.rs +++ b/rust/src/initramfs.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::cxxrsutil::*; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use camino::Utf8Path; +use cap_std::fs_utf8::Dir as Utf8Dir; use cap_std::io_lifetimes::AsFilelike; use cap_std_ext::cap_std; use cap_std_ext::prelude::CapStdExtCommandExt; @@ -13,9 +14,11 @@ use rustix::fd::BorrowedFd; use std::collections::BTreeSet; use std::collections::HashSet; use std::io::prelude::*; +use std::os::fd::AsRawFd as _; use std::os::unix::io::IntoRawFd; use std::path::{Component, Path, PathBuf}; use std::pin::Pin; +use std::process::Command; use std::{fs, io}; fn list_files_recurse>( @@ -181,6 +184,53 @@ pub(crate) fn initramfs_overlay_generate( Ok(r.into_raw_fd()) } +#[context("Running dracut")] +pub(crate) fn run_dracut(kernel_dir: &str) -> Result<()> { + let root_fs = Utf8Dir::open_ambient_dir("/", cap_std::ambient_authority())?; + let tmp_dir = tempfile::tempdir()?; + let tmp_initramfs_path = tmp_dir.path().join("initramfs.img"); + + let cliwrap_dracut = Utf8Path::new(crate::cliwrap::CLIWRAP_DESTDIR).join("dracut"); + let dracut_path = cliwrap_dracut + .exists() + .then(|| cliwrap_dracut) + .unwrap_or_else(|| Utf8Path::new("dracut").to_owned()); + // If changing this, also look at changing rpmostree-kernel.cxx + let res = Command::new(dracut_path) + .args(&[ + "--no-hostonly", + "--kver", + kernel_dir, + "--reproducible", + "-v", + "--add", + "ostree", + "-f", + ]) + .arg(&tmp_initramfs_path) + .status()?; + if !res.success() { + return Err(anyhow!( + "Failed to generate initramfs (via dracut) for kernel: {kernel_dir}: {:?}", + res + )); + } + let f = std::fs::OpenOptions::new() + .write(true) + .append(true) + .open(&tmp_initramfs_path)?; + crate::initramfs::append_dracut_random_cpio(f.as_raw_fd())?; + drop(f); + let utf8_tmp_dir_path = Utf8Path::from_path(tmp_dir.path().strip_prefix("/")?) + .context("Error turning Path to Utf8Path")?; + root_fs.rename( + utf8_tmp_dir_path.join("initramfs.img"), + &root_fs, + (Utf8Path::new("lib/modules").join(kernel_dir)).join("initramfs.img"), + )?; + Ok(()) +} + #[cfg(test)] mod test { use super::*;