@@ -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;
@@ -454,6 +454,93 @@ impl Component for Efi {
454454 Ok ( meta)
455455 }
456456
457+ fn extend_payload ( & self , sysroot_path : & str , src_input : & str ) -> Result < Option < bool > > {
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 . split ( ',' ) . 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+ } ;
491+
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) ;
540+ }
541+ Ok ( Some ( true ) )
542+ }
543+
457544 fn query_update ( & self , sysroot : & openat:: Dir ) -> Result < Option < ContentMetadata > > {
458545 get_component_update ( sysroot, self )
459546 }
0 commit comments