@@ -14,6 +14,7 @@ use bootc_internal_utils::CommandRunExt;
1414use camino:: { Utf8Path , Utf8PathBuf } ;
1515use cap_std:: fs:: Dir ;
1616use cap_std_ext:: cap_std;
17+ use cap_std_ext:: dirext:: CapStdExtDirExt ;
1718use chrono:: prelude:: * ;
1819use fn_error_context:: context;
1920use openat_ext:: OpenatDirExt ;
@@ -447,20 +448,42 @@ impl Component for Efi {
447448 }
448449
449450 fn generate_update_metadata ( & self , sysroot : & str ) -> Result < ContentMetadata > {
450- let sysroot_path = Utf8Path :: new ( sysroot) ;
451+ let sysroot_path = Path :: new ( sysroot) ;
451452
452- let efilib_path = sysroot_path. join ( EFILIB ) ;
453- let efi_comps = if efilib_path. exists ( ) {
454- get_efi_component_from_usr ( & sysroot_path, EFILIB ) ?
455- } else {
456- None
457- } ;
453+ let sysroot_dir = Dir :: open_ambient_dir ( sysroot_path, cap_std:: ambient_authority ( ) ) ?;
454+
455+ if let Some ( ostreeboot) = sysroot_dir
456+ . open_dir_optional ( ostreeutil:: BOOT_PREFIX )
457+ . context ( "Opening usr/lib/ostree-boot" ) ?
458+ {
459+ let cruft = [ "loader" , "grub2" ] ;
460+ for p in cruft. iter ( ) {
461+ ostreeboot. remove_all_optional ( p) ?;
462+ }
463+
464+ let efisrc = sysroot_path. join ( ostreeutil:: BOOT_PREFIX ) . join ( "efi/EFI" ) ;
465+ if efisrc. exists ( ) {
466+ let files = WalkDir :: new ( & efisrc)
467+ . into_iter ( )
468+ . filter_map ( Result :: ok)
469+ . filter ( |e| e. file_type ( ) . is_file ( ) )
470+ . map ( |e| e. path ( ) . to_path_buf ( ) )
471+ . collect :: < Vec < _ > > ( ) ;
472+
473+ if !files. is_empty ( ) {
474+ transfter_ostree_boot_to_usr ( sysroot_path, & files) ?;
475+ }
476+ // Remove usr/lib/ostree-boot/efi/EFI dir (after transfer) or if it is empty
477+ ostreeboot. remove_all_optional ( "efi/EFI" ) ?;
478+ }
479+ }
458480
459481 // copy EFI files to updates dir from usr/lib/efi
460- let meta = if let Some ( efi_components) = efi_comps {
482+ if let Some ( efi_components) =
483+ get_efi_component_from_usr ( Utf8Path :: from_path ( sysroot_path) . unwrap ( ) , EFILIB ) ?
484+ {
461485 let mut packages = Vec :: new ( ) ;
462486 let mut modules_vec: Vec < Module > = vec ! [ ] ;
463- let sysroot_dir = Dir :: open_ambient_dir ( sysroot_path, cap_std:: ambient_authority ( ) ) ?;
464487 for efi in efi_components {
465488 util:: copy_in_fd ( & sysroot_dir, & efi. path , crate :: model:: BOOTUPD_UPDATES_DIR ) ?;
466489 packages. push ( format ! ( "{}-{}" , efi. name, efi. version) ) ;
@@ -473,50 +496,16 @@ impl Component for Efi {
473496
474497 // change to now to workaround https://github.com/coreos/bootupd/issues/933
475498 let timestamp = std:: time:: SystemTime :: now ( ) ;
476- ContentMetadata {
499+ let meta = ContentMetadata {
477500 timestamp : chrono:: DateTime :: < Utc > :: from ( timestamp) ,
478501 version : packages. join ( "," ) ,
479502 versions : Some ( modules_vec) ,
480- }
503+ } ;
504+ write_update_metadata ( sysroot, self , & meta) ?;
505+ Ok ( meta)
481506 } else {
482- let ostreebootdir = sysroot_path. join ( ostreeutil:: BOOT_PREFIX ) ;
483-
484- // move EFI files to updates dir from /usr/lib/ostree-boot
485- if ostreebootdir. exists ( ) {
486- let cruft = [ "loader" , "grub2" ] ;
487- for p in cruft. iter ( ) {
488- let p = ostreebootdir. join ( p) ;
489- if p. exists ( ) {
490- std:: fs:: remove_dir_all ( & p) ?;
491- }
492- }
493-
494- let efisrc = ostreebootdir. join ( "efi/EFI" ) ;
495- if !efisrc. exists ( ) {
496- bail ! ( "Failed to find {:?}" , & efisrc) ;
497- }
498-
499- let dest_efidir = component_updatedir ( sysroot, self ) ;
500- let dest_efidir =
501- Utf8PathBuf :: from_path_buf ( dest_efidir) . expect ( "Path is invalid UTF-8" ) ;
502- // Fork off mv() because on overlayfs one can't rename() a lower level
503- // directory today, and this will handle the copy fallback.
504- Command :: new ( "mv" ) . args ( [ & efisrc, & dest_efidir] ) . run ( ) ?;
505-
506- let efidir = openat:: Dir :: open ( dest_efidir. as_std_path ( ) )
507- . with_context ( || format ! ( "Opening {}" , dest_efidir) ) ?;
508- let files = crate :: util:: filenames ( & efidir) ?. into_iter ( ) . map ( |mut f| {
509- f. insert_str ( 0 , "/boot/efi/EFI/" ) ;
510- f
511- } ) ;
512- query_files ( sysroot, files) ?
513- } else {
514- anyhow:: bail!( "Failed to find {ostreebootdir}" ) ;
515- }
516- } ;
517-
518- write_update_metadata ( sysroot, self , & meta) ?;
519- Ok ( meta)
507+ anyhow:: bail!( "Failed to find EFI components" ) ;
508+ }
520509 }
521510
522511 fn query_update ( & self , sysroot : & openat:: Dir ) -> Result < Option < ContentMetadata > > {
@@ -766,6 +755,44 @@ fn get_efi_component_from_usr<'a>(
766755 Ok ( Some ( components) )
767756}
768757
758+ fn transfter_ostree_boot_to_usr ( sysroot : & Path , ostreeboot_files : & Vec < PathBuf > ) -> Result < ( ) > {
759+ let ostreeboot = sysroot. join ( ostreeutil:: BOOT_PREFIX ) . join ( "efi" ) ;
760+ for entry in ostreeboot_files {
761+ // get path: EFI/{BOOT,<vendor>}/<file>
762+ let filepath = entry. strip_prefix ( & ostreeboot) ?;
763+ // get path: /boot/efi/EFI/{BOOT,<vendor>}/<file>
764+ let boot_filepath = Path :: new ( "/boot/efi" ) . join ( filepath) ;
765+
766+ // Run `rpm -qf <filepath>`
767+ let pkg = crate :: packagesystem:: query_file (
768+ sysroot. to_str ( ) . unwrap ( ) ,
769+ boot_filepath. to_str ( ) . unwrap ( ) ,
770+ ) ?;
771+
772+ if let Some ( ( name, evr) ) = pkg. split_once ( '/' ) {
773+ let component = name. splitn ( 2 , '-' ) . next ( ) . unwrap_or ( "" ) ;
774+ let version = evr. strip_prefix ( "(none):" ) . unwrap_or ( evr) ;
775+ let dest = Path :: new ( EFILIB )
776+ . join ( component)
777+ . join ( version)
778+ . join ( filepath) ;
779+
780+ let sysroot_dir = openat:: Dir :: open ( sysroot) ?;
781+ // Ensure parent directory exists
782+ if let Some ( parent) = sysroot. join ( & dest) . parent ( ) {
783+ sysroot_dir. ensure_dir_all ( parent, 0o755 ) ?;
784+ }
785+ let src = entry. strip_prefix ( sysroot) ?;
786+ sysroot_dir. copy_file ( src, & dest) ?;
787+
788+ println ! ( "Copied {:?} -> {:?}" , src, dest) ;
789+ } else {
790+ bail ! ( "Could not find split charater in {pkg}" ) ;
791+ }
792+ }
793+ Ok ( ( ) )
794+ }
795+
769796#[ cfg( test) ]
770797mod tests {
771798 use cap_std_ext:: dirext:: CapStdExtDirExt ;
0 commit comments