@@ -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 cap_std:: fs:: Dir ;
1414use cap_std_ext:: cap_std;
1515use fn_error_context:: context;
@@ -416,39 +416,89 @@ impl Component for Efi {
416416 }
417417
418418 fn extend_payload ( & self , sysroot_path : & str , src_input : & str ) -> Result < Option < bool > > {
419- let ostreebootdir = Path :: new ( sysroot_path) . join ( ostreeutil:: BOOT_PREFIX ) ;
420- let dest_efidir = component_updatedir ( sysroot_path, self ) ;
419+ let dest_efidir_base = Path :: new ( sysroot_path) . join ( "usr/lib/efi" ) . join ( "firmware" ) ;
420+
421+ // Fetch version and release from the source input using query_files
422+ let src_input_path = Path :: new ( src_input) ;
423+ let meta_from_src = packagesystem:: query_files ( sysroot_path, [ src_input_path] )
424+ . context ( format ! ( "Querying RPM metadata for {:?}" , src_input_path) ) ?;
425+
426+ let version_string_part = meta_from_src. version . splitn ( 2 , ',' ) . next ( )
427+ . ok_or_else ( || anyhow ! (
428+ "RPM query returned an empty or malformed version string (no package name found in '{}')." ,
429+ meta_from_src. version
430+ ) ) ?;
431+
432+ let parts: Vec < & str > = version_string_part. split ( '-' ) . collect ( ) ;
433+
434+ let ( pkg_name, version_release_str) = if parts. len ( ) >= 3 {
435+ // Successfully extracted package name, version, and release
436+ let actual_pkg_name = parts[ 0 ] ;
437+ let version_part = parts[ parts. len ( ) - 2 ] ; // version, e.g., "1.0"
438+ let release_part = parts[ parts. len ( ) - 1 ]
439+ . split ( '.' )
440+ . next ( )
441+ . unwrap_or ( parts[ parts. len ( ) - 1 ] ) ; // release, e.g., "1" from "1.el8.noarch"
442+ (
443+ actual_pkg_name. to_string ( ) ,
444+ format ! ( "{}-{}" , version_part, release_part) ,
445+ )
446+ } else {
447+ return Err ( anyhow ! (
448+ "Unexpected RPM version string format: '{}'. Expected at least <pkg_name>-<version>-<release>." ,
449+ version_string_part
450+ ) ) ;
451+ } ;
421452
422- // move files to staged updates
423- if ostreebootdir. exists ( ) {
424- let cruft = [ "loader" , "grub2" ] ;
425- for p in cruft. iter ( ) {
426- let p = ostreebootdir. join ( p) ;
427- if p. exists ( ) {
428- std:: fs:: remove_dir_all ( & p) ?;
429- }
430- }
431- // mv src data to /usr/lib_bootupd/updates/EFI
432- let efisrc = ostreebootdir. join ( src_input) ;
433- if !efisrc. exists ( ) {
434- bail ! ( "Failed to find {:?}" , & efisrc) ;
435- }
436- Command :: new ( "mv" ) . args ( [ & efisrc, & dest_efidir] ) . run ( ) ?;
453+ let final_dest_efi_path = dest_efidir_base
454+ . join ( & pkg_name) // add the package name as a directory
455+ . join ( & version_release_str)
456+ . join ( "EFI/boot/efi" ) ;
457+
458+ // Ensure the destination directory exists
459+ std:: fs:: create_dir_all ( & final_dest_efi_path) . with_context ( || {
460+ format ! (
461+ "Failed to create destination directory {:?}" ,
462+ & final_dest_efi_path
463+ )
464+ } ) ?;
465+
466+ let src_metadata = std:: fs:: metadata ( src_input_path)
467+ . with_context ( || format ! ( "Failed to get metadata for {:?}" , src_input_path) ) ?;
468+
469+ if src_metadata. is_dir ( ) {
470+ log:: debug!(
471+ "Copying contents of directory {:?} to {:?}" ,
472+ src_input,
473+ & final_dest_efi_path
474+ ) ;
475+ Command :: new ( "cp" )
476+ . args ( [
477+ "-rp" ,
478+ & format ! ( "{}/." , src_input) ,
479+ final_dest_efi_path. to_str ( ) . unwrap ( ) ,
480+ ] )
481+ . run ( )
482+ . with_context ( || {
483+ format ! (
484+ "Failed to copy contents of {:?} to {:?}" ,
485+ src_input, & final_dest_efi_path
486+ )
487+ } ) ?;
488+ } else if src_metadata. is_file ( ) {
489+ log:: debug!( "Copying file {:?} to {:?}" , src_input, & final_dest_efi_path) ;
490+ Command :: new ( "cp" )
491+ . args ( [ "-p" , src_input, final_dest_efi_path. to_str ( ) . unwrap ( ) ] )
492+ . run ( )
493+ . with_context ( || {
494+ format ! (
495+ "Failed to copy file {:?} to {:?}" ,
496+ src_input, & final_dest_efi_path
497+ )
498+ } ) ?;
499+ } else {
500+ anyhow:: bail!( "Unsupported src_input type: {:?}" , src_input) ;
437501 }
438-
439- // canocinal path information parsed
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 , src_input) ;
444- f
445- } ) ;
446-
447- // writes EFI.JSON with the timestamp and version
448- let meta =
449- packagesystem:: query_files ( sysroot_path, files) . context ( "Querying RPM metadata" ) ?;
450- write_update_metadata ( sysroot_path, self , & meta) ?;
451-
452502 Ok ( Some ( true ) )
453503 }
454504
0 commit comments