Skip to content

Commit efa3b42

Browse files
committed
Extend generate-update-metadata() to read from /usr
In `generate-update-metadata()`, checks `/usr/lib/efi/(shim|grub) /%{version}-%{release}/EFI/` first for EFI path, for example: `usr/lib/efi/shim/1.2-3/EFI/`. If the path `/usr/lib/efi` doesn’t exist, falls back to the legacy OSTree location `/usr/lib/ostree-boot/efi/EFI/`. Then move existing EFI path to the `/usr/lib/bootupd/updates/`. See #926
1 parent 50adce8 commit efa3b42

File tree

2 files changed

+108
-13
lines changed

2 files changed

+108
-13
lines changed

src/efi.rs

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::path::{Path, PathBuf};
1010
use std::process::Command;
1111

1212
use anyhow::{bail, Context, Result};
13+
use bootc_utils::CommandRunExt;
1314
use cap_std::fs::Dir;
1415
use cap_std_ext::cap_std;
1516
use fn_error_context::context;
@@ -22,7 +23,7 @@ use widestring::U16CString;
2223
use crate::bootupd::RootContext;
2324
use crate::model::*;
2425
use crate::ostreeutil;
25-
use crate::util::{self, CommandRunExt};
26+
use crate::util;
2627
use crate::{blockdev, filetree};
2728
use crate::{component::*, packagesystem};
2829

@@ -381,10 +382,42 @@ impl Component for Efi {
381382
}
382383

383384
fn generate_update_metadata(&self, sysroot_path: &str) -> Result<ContentMetadata> {
384-
let ostreebootdir = Path::new(sysroot_path).join(ostreeutil::BOOT_PREFIX);
385385
let dest_efidir = component_updatedir(sysroot_path, self);
386386

387-
if ostreebootdir.exists() {
387+
// New EFI dir /usr/lib/efi
388+
let efi_lib = Path::new(sysroot_path).join("usr/lib/efi");
389+
// Legacy ostree-boot dir
390+
let ostreebootdir = Path::new(sysroot_path).join(ostreeutil::BOOT_PREFIX);
391+
392+
let meta = if efi_lib.exists() {
393+
// Get EFI paths like /usr/lib/efi/(shim|grub2)/<version>/EFI
394+
let efi_paths = find_all_efi_dirs(&efi_lib)
395+
.with_context(|| format!("Failed to find EFI path under {}", efi_lib.display()))?;
396+
397+
// Get all files under EFI paths
398+
let all_files: Result<Vec<String>> =
399+
efi_paths.iter().try_fold(Vec::new(), |mut acc, efi| {
400+
let efidir = openat::Dir::open(efi)
401+
.with_context(|| format!("Opening {}", efi.display()))?;
402+
403+
// Get all files path
404+
let mut files = crate::util::filenames(&efidir)?
405+
.into_iter()
406+
.map(|mut f| {
407+
f.insert_str(0, efi.to_str().unwrap());
408+
f
409+
})
410+
.collect::<Vec<String>>();
411+
412+
Command::new("mv")
413+
.arg(&efi)
414+
.arg(&dest_efidir)
415+
.run_with_cmd_context()?;
416+
acc.append(&mut files);
417+
Ok(acc)
418+
});
419+
packagesystem::query_files(sysroot_path, all_files?.into_iter())?
420+
} else if ostreebootdir.exists() {
388421
let cruft = ["loader", "grub2"];
389422
for p in cruft.iter() {
390423
let p = ostreebootdir.join(p);
@@ -400,17 +433,25 @@ impl Component for Efi {
400433

401434
// Fork off mv() because on overlayfs one can't rename() a lower level
402435
// directory today, and this will handle the copy fallback.
403-
Command::new("mv").args([&efisrc, &dest_efidir]).run()?;
404-
}
405-
406-
let efidir = openat::Dir::open(&dest_efidir)
407-
.with_context(|| format!("Opening {}", dest_efidir.display()))?;
408-
let files = crate::util::filenames(&efidir)?.into_iter().map(|mut f| {
409-
f.insert_str(0, "/boot/efi/EFI/");
410-
f
411-
});
436+
Command::new("mv")
437+
.args([&efisrc, &dest_efidir])
438+
.run_with_cmd_context()?;
439+
440+
let efidir = openat::Dir::open(&dest_efidir)
441+
.with_context(|| format!("Opening {}", dest_efidir.display()))?;
442+
let files = crate::util::filenames(&efidir)?.into_iter().map(|mut f| {
443+
f.insert_str(0, "/boot/efi/EFI/");
444+
f
445+
});
446+
packagesystem::query_files(sysroot_path, files)?
447+
} else {
448+
bail!(
449+
"No directories found {} or {}",
450+
efi_lib.display(),
451+
ostreebootdir.display()
452+
);
453+
};
412454

413-
let meta = packagesystem::query_files(sysroot_path, files)?;
414455
write_update_metadata(sysroot_path, self, &meta)?;
415456
Ok(meta)
416457
}
@@ -615,6 +656,29 @@ fn find_file_recursive<P: AsRef<Path>>(dir: P, target_file: &str) -> Result<Vec<
615656
Ok(result)
616657
}
617658

659+
// Find EFI dirs under usr/lib/efi
660+
// for exmaple: usr/lib/efi/shim/15.8-4/EFI, usr/lib/efi/grub2/2.12-34.fc42/EFI
661+
fn find_all_efi_dirs(sysroot_lib: &Path) -> Result<Vec<PathBuf>> {
662+
const LIBDIRS: &[&str] = &["grub2", "shim"];
663+
664+
LIBDIRS.iter().try_fold(Vec::new(), |mut acc, pkg| {
665+
let lib_path = sysroot_lib.join(pkg);
666+
if !lib_path.exists() {
667+
return Ok(acc);
668+
}
669+
670+
for entry in std::fs::read_dir(&lib_path)? {
671+
let entry = entry?;
672+
let version_dir = entry.path();
673+
let efi_path = version_dir.join("EFI");
674+
if efi_path.is_dir() {
675+
acc.push(efi_path);
676+
}
677+
}
678+
Ok(acc)
679+
})
680+
}
681+
618682
#[cfg(test)]
619683
mod tests {
620684
use cap_std_ext::dirext::CapStdExtDirExt;
@@ -735,4 +799,34 @@ Boot0003* test";
735799
}
736800
Ok(())
737801
}
802+
#[test]
803+
fn test_find_all_efi_dirs() -> Result<()> {
804+
let td = tempfile::tempdir()?;
805+
let tdp = td.path();
806+
let tdp_efi = tdp.join("usr/lib/efi");
807+
std::fs::create_dir_all(tdp_efi.join("grub2/2.12-34.fc42/EFI/fedora"))?;
808+
std::fs::create_dir_all(tdp_efi.join("shim/15.8-4/EFI/BOOT"))?;
809+
std::fs::create_dir_all(tdp_efi.join("grub/testdir/test"))?;
810+
{
811+
let dirs = find_all_efi_dirs(&tdp_efi)?;
812+
assert_eq!(2, dirs.len());
813+
}
814+
{
815+
let td = openat::Dir::open(&tdp_efi)?;
816+
td.remove_all("grub2")?;
817+
let dirs = find_all_efi_dirs(&tdp_efi)?;
818+
assert_eq!(1, dirs.len());
819+
820+
td.remove_all("shim")?;
821+
let dirs = find_all_efi_dirs(&tdp_efi)?;
822+
assert_eq!(0, dirs.len());
823+
}
824+
{
825+
std::fs::create_dir_all(tdp_efi.join("grub2/2.12-34.fc42"))?;
826+
std::fs::create_dir_all(tdp_efi.join("shim/15.8-4/EFI/BOOT"))?;
827+
let dirs = find_all_efi_dirs(&tdp_efi)?;
828+
assert_eq!(1, dirs.len());
829+
}
830+
Ok(())
831+
}
738832
}

src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::process::Command;
55
use anyhow::{bail, Context, Result};
66
use openat_ext::OpenatDirExt;
77

8+
#[allow(dead_code)]
89
pub(crate) trait CommandRunExt {
910
fn run(&mut self) -> Result<()>;
1011
}

0 commit comments

Comments
 (0)