diff --git a/Cargo.lock b/Cargo.lock index af5cb7a9..2892398a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -74,6 +80,7 @@ version = "0.2.20" dependencies = [ "anyhow", "bincode", + "cap-std-ext", "chrono", "clap", "env_logger", @@ -102,6 +109,58 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "cap-primitives" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d00bd8d26c4270d950eaaa837387964a2089a1c3c349a690a1fa03221d29531" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes", + "ipnet", + "maybe-owned", + "rustix", + "windows-sys 0.52.0", + "winx", +] + +[[package]] +name = "cap-std" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19eb8e3d71996828751c1ed3908a439639752ac6bdc874e41469ef7fc15fbd7f" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes", + "rustix", +] + +[[package]] +name = "cap-std-ext" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0279cf1f7b6cbeeb98e6946e8fea58136f691d4d0aa8c775f4439a05030a481" +dependencies = [ + "cap-primitives", + "cap-tempfile", + "rustix", +] + +[[package]] +name = "cap-tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53880047c3f37cd64947775f0526795498d614182603a718c792616b762ce777" +dependencies = [ + "cap-std", + "rand", + "rustix", + "uuid", +] + [[package]] name = "cc" version = "1.0.83" @@ -260,6 +319,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "fs-set-times" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" +dependencies = [ + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "fs2" version = "0.4.3" @@ -363,6 +433,28 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "io-extras" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9f046b9af244f13b3bd939f55d16830ac3a201e8a9ba9661bfcb03e2be72b9b" +dependencies = [ + "io-lifetimes", + "windows-sys 0.52.0", +] + +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.9" @@ -431,6 +523,12 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "memchr" version = "2.6.4" @@ -706,8 +804,10 @@ checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.4.1", "errno", + "itoa", "libc", "linux-raw-sys", + "once_cell", "windows-sys 0.52.0", ] @@ -867,6 +967,7 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ + "getrandom", "serde", ] @@ -1129,3 +1230,13 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.1", + "windows-sys 0.52.0", +] diff --git a/Cargo.toml b/Cargo.toml index 00611cda..45ab6a9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ path = "src/main.rs" [dependencies] anyhow = "1.0" bincode = "1.3.2" +cap-std-ext = "4.0.0" chrono = { version = "0.4.38", features = ["serde"] } clap = { version = "3.2", default-features = false, features = ["cargo", "derive", "std", "suggestions"] } env_logger = "0.10" diff --git a/src/efi.rs b/src/efi.rs index a3c2d57d..ecaee822 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -10,6 +10,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use anyhow::{bail, Context, Result}; +use cap_std::fs::Dir; +use cap_std_ext::cap_std; use fn_error_context::context; use openat_ext::OpenatDirExt; use os_release::OsRelease; @@ -139,7 +141,8 @@ impl Efi { log::debug!("Not booted via EFI, skipping firmware update"); return Ok(()); } - let product_name = get_product_name()?; + let sysroot = Dir::open_ambient_dir(&Path::new("/"), cap_std::ambient_authority())?; + let product_name = get_product_name(&sysroot)?; log::debug!("Get product name: {product_name}"); assert!(product_name.len() > 0); // clear all the boot entries that match the target name @@ -149,10 +152,10 @@ impl Efi { } #[context("Get product name")] -fn get_product_name() -> Result { - let file_path = Path::new("/etc/system-release"); - if file_path.exists() { - let content = std::fs::read_to_string(file_path)?; +fn get_product_name(sysroot: &Dir) -> Result { + let release_path = "etc/system-release"; + if sysroot.exists(release_path) { + let content = sysroot.read_to_string(release_path)?; let re = regex::Regex::new(r" *release.*").unwrap(); return Ok(re.replace_all(&content, "").to_string()); } @@ -597,6 +600,8 @@ fn find_file_recursive>(dir: P, target_file: &str) -> Result Result { + let tempdir = cap_std_ext::cap_tempfile::tempdir(cap_std::ambient_authority())?; + tempdir.create_dir("etc")?; + Ok(tempdir) + } #[test] fn test_get_product_name() -> Result<()> { - let name = get_product_name()?; - assert!(name.len() > 0); + let tmpd = fixture()?; + { + tmpd.atomic_write("etc/system-release", "Fedora release 40 (Forty)")?; + let name = get_product_name(&tmpd)?; + assert_eq!("Fedora", name); + } + { + tmpd.atomic_write("etc/system-release", "CentOS Stream release 9")?; + let name = get_product_name(&tmpd)?; + assert_eq!("CentOS Stream", name); + } + { + tmpd.atomic_write( + "etc/system-release", + "Red Hat Enterprise Linux CoreOS release 4", + )?; + let name = get_product_name(&tmpd)?; + assert_eq!("Red Hat Enterprise Linux CoreOS", name); + } + { + tmpd.remove_file("etc/system-release")?; + let name = get_product_name(&tmpd)?; + assert!(name.len() > 0); + } Ok(()) } }