@@ -9,7 +9,7 @@ use std::os::unix::io::AsRawFd;
99use std:: path:: { Path , PathBuf } ;
1010use std:: process:: Command ;
1111
12- use anyhow:: { bail, Context , Result } ;
12+ use anyhow:: { anyhow , bail, Context , Result } ;
1313use bootc_utils:: CommandRunExt ;
1414use cap_std:: fs:: Dir ;
1515use cap_std_ext:: cap_std;
@@ -455,39 +455,89 @@ impl Component for Efi {
455455 }
456456
457457 fn extend_payload ( & self , sysroot_path : & str , src_input : & str ) -> Result < Option < bool > > {
458- let ostreebootdir = Path :: new ( sysroot_path) . join ( ostreeutil:: BOOT_PREFIX ) ;
459- let dest_efidir = component_updatedir ( sysroot_path, self ) ;
458+ let dest_efidir_base = Path :: new ( sysroot_path) . join ( "usr/lib/efi" ) . join ( "firmware" ) ;
459+
460+ // Fetch version and release from the source input using query_files
461+ let src_input_path = Path :: new ( src_input) ;
462+ let meta_from_src = packagesystem:: query_files ( sysroot_path, [ src_input_path] )
463+ . context ( format ! ( "Querying RPM metadata for {:?}" , src_input_path) ) ?;
464+
465+ let version_string_part = meta_from_src. version . splitn ( 2 , ',' ) . next ( )
466+ . ok_or_else ( || anyhow ! (
467+ "RPM query returned an empty or malformed version string (no package name found in '{}')." ,
468+ meta_from_src. version
469+ ) ) ?;
470+
471+ let parts: Vec < & str > = version_string_part. split ( '-' ) . collect ( ) ;
472+
473+ let ( pkg_name, version_release_str) = if parts. len ( ) >= 3 {
474+ // Successfully extracted package name, version, and release
475+ let actual_pkg_name = parts[ 0 ] ;
476+ let version_part = parts[ parts. len ( ) - 2 ] ; // version, e.g., "1.0"
477+ let release_part = parts[ parts. len ( ) - 1 ]
478+ . split ( '.' )
479+ . next ( )
480+ . unwrap_or ( parts[ parts. len ( ) - 1 ] ) ; // release, e.g., "1" from "1.el8.noarch"
481+ (
482+ actual_pkg_name. to_string ( ) ,
483+ format ! ( "{}-{}" , version_part, release_part) ,
484+ )
485+ } else {
486+ return Err ( anyhow ! (
487+ "Unexpected RPM version string format: '{}'. Expected at least <pkg_name>-<version>-<release>." ,
488+ version_string_part
489+ ) ) ;
490+ } ;
460491
461- // move files to staged updates
462- if ostreebootdir. exists ( ) {
463- let cruft = [ "loader" , "grub2" ] ;
464- for p in cruft. iter ( ) {
465- let p = ostreebootdir. join ( p) ;
466- if p. exists ( ) {
467- std:: fs:: remove_dir_all ( & p) ?;
468- }
469- }
470- // mv src data to /usr/lib_bootupd/updates/EFI
471- let efisrc = ostreebootdir. join ( src_input) ;
472- if !efisrc. exists ( ) {
473- bail ! ( "Failed to find {:?}" , & efisrc) ;
474- }
475- Command :: new ( "mv" ) . args ( [ & efisrc, & dest_efidir] ) . run ( ) ?;
492+ let final_dest_efi_path = dest_efidir_base
493+ . join ( & pkg_name) // add the package name as a directory
494+ . join ( & version_release_str)
495+ . join ( "EFI/boot/efi" ) ;
496+
497+ // Ensure the destination directory exists
498+ std:: fs:: create_dir_all ( & final_dest_efi_path) . with_context ( || {
499+ format ! (
500+ "Failed to create destination directory {:?}" ,
501+ & final_dest_efi_path
502+ )
503+ } ) ?;
504+
505+ let src_metadata = std:: fs:: metadata ( src_input_path)
506+ . with_context ( || format ! ( "Failed to get metadata for {:?}" , src_input_path) ) ?;
507+
508+ if src_metadata. is_dir ( ) {
509+ log:: debug!(
510+ "Copying contents of directory {:?} to {:?}" ,
511+ src_input,
512+ & final_dest_efi_path
513+ ) ;
514+ Command :: new ( "cp" )
515+ . args ( [
516+ "-rp" ,
517+ & format ! ( "{}/." , src_input) ,
518+ final_dest_efi_path. to_str ( ) . unwrap ( ) ,
519+ ] )
520+ . run ( )
521+ . with_context ( || {
522+ format ! (
523+ "Failed to copy contents of {:?} to {:?}" ,
524+ src_input, & final_dest_efi_path
525+ )
526+ } ) ?;
527+ } else if src_metadata. is_file ( ) {
528+ log:: debug!( "Copying file {:?} to {:?}" , src_input, & final_dest_efi_path) ;
529+ Command :: new ( "cp" )
530+ . args ( [ "-p" , src_input, final_dest_efi_path. to_str ( ) . unwrap ( ) ] )
531+ . run ( )
532+ . with_context ( || {
533+ format ! (
534+ "Failed to copy file {:?} to {:?}" ,
535+ src_input, & final_dest_efi_path
536+ )
537+ } ) ?;
538+ } else {
539+ anyhow:: bail!( "Unsupported src_input type: {:?}" , src_input) ;
476540 }
477-
478- // canocinal path information parsed
479- let efidir = openat:: Dir :: open ( & dest_efidir)
480- . with_context ( || format ! ( "Opening {}" , dest_efidir. display( ) ) ) ?;
481- let files = crate :: util:: filenames ( & efidir) ?. into_iter ( ) . map ( |mut f| {
482- f. insert_str ( 0 , src_input) ;
483- f
484- } ) ;
485-
486- // writes EFI.JSON with the timestamp and version
487- let meta =
488- packagesystem:: query_files ( sysroot_path, files) . context ( "Querying RPM metadata" ) ?;
489- write_update_metadata ( sysroot_path, self , & meta) ?;
490-
491541 Ok ( Some ( true ) )
492542 }
493543
0 commit comments