Skip to content

Commit 3d60084

Browse files
efi: Choose update layout depending on /usr/lib/efi
In #995 changes were made to move files from `usr/lib/ostree-boot/EFI` to `usr/lib/efi` instead of `usr/lib/bootupd` which caused issues with tools that expect the older layout. We now check for the existence of `usr/lib/efi`, and only use the new layout if we find it. Else, default back to the older layout at `usr/lib/bootupd`. Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent ab0d9a1 commit 3d60084

2 files changed

Lines changed: 89 additions & 91 deletions

File tree

src/efi.rs

Lines changed: 89 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -568,50 +568,49 @@ impl Component for Efi {
568568
}
569569

570570
fn generate_update_metadata(&self, sysroot: &str) -> Result<Option<ContentMetadata>> {
571-
let sysroot_path = Path::new(sysroot);
571+
let sysroot_path = Utf8Path::new(sysroot);
572572
let sysroot_dir = Dir::open_ambient_dir(sysroot_path, cap_std::ambient_authority())?;
573573

574-
if let Some(ostreeboot) = sysroot_dir
574+
let ostreeboot = sysroot_dir
575575
.open_dir_optional(ostreeutil::BOOT_PREFIX)
576-
.context("Opening usr/lib/ostree-boot")?
577-
{
576+
.context("Opening usr/lib/ostree-boot")?;
577+
578+
// Newer images >= F44 have boot entries in /usr/lib/efi, but older images
579+
// have them in /usr/lib/ostree-boot, which we move to /usr/lib/bootupd/updates/EFI
580+
let metadata = if sysroot_path.join(EFILIB).exists() {
581+
println!("Generating metadata from {EFILIB}");
582+
generate_meta_from_usr_efi(sysroot_path)?
583+
} else {
584+
match &ostreeboot {
585+
Some(..) => {
586+
println!(
587+
"Moving {}/efi/EFI to {BOOTUPD_UPDATES_DIR}/EFI",
588+
ostreeutil::BOOT_PREFIX
589+
);
590+
// Transfer usr/lib/ostree-boot/EFI files to usr/lib/bootupd/updates/EFI
591+
transfer_ostree_boot_to_bootupd_updates(sysroot_path, self)?
592+
}
593+
594+
// If /usr/lib/ostree-boot doesn't exist, assume /usr/lib/efi will
595+
None => anyhow::bail!("/usr/lib/ostree-boot and /usr/lib/efi not found"),
596+
}
597+
};
598+
599+
if let Some(ostreeboot) = ostreeboot {
578600
let cruft = ["loader", "grub2"];
579601
for p in cruft.iter() {
602+
println!("Removing {p} from {}", ostreeutil::BOOT_PREFIX);
580603
ostreeboot.remove_all_optional(p)?;
581604
}
582-
// Transfer ostree-boot EFI files to usr/lib/efi
583-
transfer_ostree_boot_to_usr(sysroot_path)?;
584605

606+
println!("Removing efi/EFI from {}", ostreeutil::BOOT_PREFIX);
585607
// Remove usr/lib/ostree-boot/efi/EFI dir (after transfer) or if it is empty
586608
ostreeboot.remove_all_optional("efi/EFI")?;
587-
}
609+
};
588610

589-
if let Some(efi_components) =
590-
get_efi_component_from_usr(Utf8Path::from_path(sysroot_path).unwrap(), EFILIB)?
591-
{
592-
let mut packages = Vec::new();
593-
let mut modules_vec: Vec<Module> = vec![];
594-
for efi in efi_components {
595-
packages.push(format!("{}-{}", efi.name, efi.version));
596-
modules_vec.push(Module {
597-
name: efi.name,
598-
rpm_evr: efi.version,
599-
});
600-
}
601-
modules_vec.sort_unstable();
602-
603-
// change to now to workaround https://github.com/coreos/bootupd/issues/933
604-
let timestamp = std::time::SystemTime::now();
605-
let meta = ContentMetadata {
606-
timestamp: chrono::DateTime::<Utc>::from(timestamp),
607-
version: packages.join(","),
608-
versions: Some(modules_vec),
609-
};
610-
write_update_metadata(sysroot, self, &meta)?;
611-
Ok(Some(meta))
612-
} else {
613-
anyhow::bail!("Failed to find EFI components");
614-
}
611+
write_update_metadata(sysroot_path.as_str(), self, &metadata)?;
612+
613+
Ok(Some(metadata))
615614
}
616615

617616
fn query_update(&self, sysroot: &openat::Dir) -> Result<Option<ContentMetadata>> {
@@ -801,6 +800,34 @@ fn find_file_recursive<P: AsRef<Path>>(dir: P, target_file: &str) -> Result<Vec<
801800
Ok(result)
802801
}
803802

803+
#[context("Generating metadata from usr/lib/efi")]
804+
fn generate_meta_from_usr_efi(sysroot_path: &Utf8Path) -> Result<ContentMetadata> {
805+
let Some(efi_components) = get_efi_component_from_usr(sysroot_path, EFILIB)? else {
806+
anyhow::bail!("Failed to find EFI components");
807+
};
808+
809+
let mut packages = Vec::new();
810+
let mut modules_vec: Vec<Module> = vec![];
811+
for efi in efi_components {
812+
packages.push(format!("{}-{}", efi.name, efi.version));
813+
modules_vec.push(Module {
814+
name: efi.name,
815+
rpm_evr: efi.version,
816+
});
817+
}
818+
modules_vec.sort_unstable();
819+
820+
// change to now to workaround https://github.com/coreos/bootupd/issues/933
821+
let timestamp = std::time::SystemTime::now();
822+
let meta = ContentMetadata {
823+
timestamp: chrono::DateTime::<Utc>::from(timestamp),
824+
version: packages.join(","),
825+
versions: Some(modules_vec),
826+
};
827+
828+
Ok(meta)
829+
}
830+
804831
#[derive(Debug, PartialEq, Eq)]
805832
pub struct EFIComponent {
806833
pub name: String,
@@ -851,57 +878,43 @@ fn get_efi_component_from_usr<'a>(
851878
Ok(Some(components))
852879
}
853880

854-
/// Copy files from usr/lib/ostree-boot/efi/EFI to /usr/lib/efi/<component>/<evr>/
855-
fn transfer_ostree_boot_to_usr(sysroot: &Path) -> Result<()> {
856-
let ostreeboot_efi = Path::new(ostreeutil::BOOT_PREFIX).join("efi");
857-
let ostreeboot_efi_path = sysroot.join(&ostreeboot_efi);
881+
/// Copies usr/lib/ostree-boot/EFI to usr/lib/bootupd/updates
882+
fn transfer_ostree_boot_to_bootupd_updates(
883+
sysroot: &Utf8Path,
884+
component: &Efi,
885+
) -> Result<ContentMetadata> {
886+
let ostreebootdir = sysroot.join(ostreeutil::BOOT_PREFIX);
858887

859-
let efi = ostreeboot_efi_path.join("EFI");
860-
if !efi.exists() {
861-
return Ok(());
888+
// move EFI files to updates dir from /usr/lib/ostree-boot
889+
if !ostreebootdir.exists() {
890+
anyhow::bail!("Failed to find {ostreebootdir}");
862891
}
863-
for entry in WalkDir::new(&efi) {
864-
let entry = entry?;
865892

866-
if entry.file_type().is_file() {
867-
let entry_path = entry.path();
893+
let efisrc = ostreebootdir.join("efi/EFI");
894+
if !efisrc.exists() {
895+
bail!("Failed to find {:?}", &efisrc);
896+
}
868897

869-
// get path EFI/{BOOT,<vendor>}/<file>
870-
let filepath = entry_path.strip_prefix(&ostreeboot_efi_path)?;
871-
// get path /boot/efi/EFI/{BOOT,<vendor>}/<file>
872-
let boot_filepath = Path::new("/boot/efi").join(filepath);
898+
let dest_efidir = component_updatedir(sysroot.as_str(), component);
899+
let dest_efidir = Utf8PathBuf::from_path_buf(dest_efidir).expect("Path is invalid UTF-8");
873900

874-
// Run `rpm -qf <filepath>`
875-
let pkg = crate::packagesystem::query_file(
876-
sysroot.to_str().unwrap(),
877-
boot_filepath.to_str().unwrap(),
878-
)?;
901+
// Fork off mv() because on overlayfs one can't rename() a lower level
902+
// directory today, and this will handle the copy fallback.
903+
Command::new("mv")
904+
.args([&efisrc, &dest_efidir])
905+
.run_capture_stderr()?;
879906

880-
let (name, evr) = pkg.split_once(' ').unwrap();
881-
let component = name.split('-').next().unwrap_or("");
882-
// get path usr/lib/efi/<component>/<evr>
883-
let efilib_path = Path::new(EFILIB).join(component).join(evr);
907+
let efidir = openat::Dir::open(dest_efidir.as_std_path())
908+
.with_context(|| format!("Opening {}", dest_efidir))?;
884909

885-
let sysroot_dir = openat::Dir::open(sysroot)?;
886-
// Ensure dest parent directory exists
887-
if let Some(parent) = efilib_path.join(filepath).parent() {
888-
sysroot_dir.ensure_dir_all(parent, 0o755)?;
889-
}
910+
let files = crate::util::filenames(&efidir)?.into_iter().map(|mut f| {
911+
f.insert_str(0, "/boot/efi/EFI");
912+
f
913+
});
890914

891-
// Source dir is usr/lib/ostree-boot/efi
892-
let src = sysroot_dir
893-
.sub_dir(&ostreeboot_efi)
894-
.context("Opening ostree-boot dir")?;
895-
// Dest dir is usr/lib/efi/<component>/<evr>
896-
let dest = sysroot_dir
897-
.sub_dir(&efilib_path)
898-
.context("Opening usr/lib/efi dir")?;
899-
// Copy file from ostree-boot to usr/lib/efi
900-
src.copy_file_at(filepath, &dest, filepath)
901-
.context("Copying file to usr/lib/efi")?;
902-
}
903-
}
904-
Ok(())
915+
let files = files.collect::<Vec<_>>();
916+
917+
query_files(sysroot.as_str(), files)
905918
}
906919

907920
#[cfg(test)]

src/packagesystem.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,6 @@ fn split_name_version(input: &str) -> Option<(String, String)> {
115115
Some((name.to_string(), format!("{version}-{release}")))
116116
}
117117

118-
/// Query the rpm database and get package "<name> <evr>"
119-
pub(crate) fn query_file(sysroot_path: &str, path: &str) -> Result<String> {
120-
let mut c = ostreeutil::rpm_cmd(sysroot_path)?;
121-
c.args(["-q", "--queryformat", "%{NAME} %{EVR}", "-f", path]);
122-
123-
let rpmout = c.output()?;
124-
if !rpmout.status.success() {
125-
std::io::stderr().write_all(&rpmout.stderr)?;
126-
bail!("Failed to invoke rpm -qf");
127-
}
128-
129-
let output = String::from_utf8(rpmout.stdout)?;
130-
Ok(output.trim().to_string())
131-
}
132-
133118
fn parse_evr(pkg: &str) -> Module {
134119
// assume it is "grub2-1:2.12-28.fc42" (from usr/lib/efi)
135120
if !pkg.ends_with(std::env::consts::ARCH) {

0 commit comments

Comments
 (0)