@@ -37,14 +37,15 @@ use anyhow::Context;
3737use tempfile:: NamedTempFile ;
3838
3939pub use bootloader_boot_config:: BootConfig ;
40+ use crate :: file_data_source:: FileDataSource ;
4041
4142const KERNEL_FILE_NAME : & str = "kernel-x86_64" ;
4243const RAMDISK_FILE_NAME : & str = "ramdisk" ;
4344const CONFIG_FILE_NAME : & str = "boot.json" ;
4445
4546#[ derive( Clone ) ]
4647struct DiskImageFile {
47- source : PathBuf ,
48+ source : FileDataSource ,
4849 destination : String ,
4950}
5051
@@ -69,64 +70,48 @@ impl DiskImageBuilder {
6970
7071 /// Add or replace a kernel to be included in the final image.
7172 pub fn set_kernel ( & mut self , path : & Path ) -> & mut Self {
72- self . add_or_replace_file ( path, KERNEL_FILE_NAME )
73+ self . add_or_replace_file ( FileDataSource :: File ( path. to_path_buf ( ) ) , KERNEL_FILE_NAME )
7374 }
7475
7576 /// Add or replace a ramdisk to be included in the final image.
7677 pub fn set_ramdisk ( & mut self , path : & Path ) -> & mut Self {
77- self . add_or_replace_file ( path, RAMDISK_FILE_NAME )
78+ self . add_or_replace_file ( FileDataSource :: File ( path. to_path_buf ( ) ) , RAMDISK_FILE_NAME )
7879 }
7980
8081 /// Configures the runtime behavior of the bootloader.
8182 pub fn set_boot_config ( & mut self , boot_config : & BootConfig ) -> & mut Self {
8283 let json =
8384 serde_json:: to_string_pretty ( boot_config) . expect ( "failed to serialize BootConfig" ) ;
8485 let bytes = json. as_bytes ( ) ;
85- self . add_or_replace_file_byte_content ( bytes, CONFIG_FILE_NAME )
86+ self . add_or_replace_file ( FileDataSource :: Data ( bytes. to_vec ( ) ) , CONFIG_FILE_NAME )
8687 }
87-
88- /// Add or replace a file from a byte array
89- pub fn add_or_replace_file_byte_content ( & mut self , data : & [ u8 ] , target : & str ) -> & mut Self {
90- let temp_path = temp_dir ( ) ;
91- let file_name = temp_path. join ( "bytes.tmp" ) ;
92- fs:: create_dir_all ( temp_path) . expect ( "Failed to create temp directory" ) ;
93- let mut temp_file =
94- fs:: File :: create ( file_name. clone ( ) ) . expect ( "Failed to create temp file" ) ;
95- temp_file
96- . write_all ( data)
97- . expect ( "Failed to write data to temp file" ) ;
98- temp_file
99- . sync_all ( )
100- . expect ( "Failed to flush temp file to disk" ) ;
101-
102- self . add_or_replace_file ( & file_name, target)
103- }
104-
88+
10589 /// Add or replace arbitrary files.
106- /// NOTE: You can overwrite internal files if you choose, such as EFI/BOOT/BOOTX64.EFI
107- /// This can be useful in situations where you want to generate an image, but not use the provided bootloader.
108- pub fn add_or_replace_file ( & mut self , path : & Path , target : & str ) -> & mut Self {
90+ pub fn add_or_replace_file ( & mut self , file_data_source : FileDataSource , target : & str ) -> & mut Self {
10991 self . files . insert (
11092 0 ,
11193 DiskImageFile {
112- source : path . to_path_buf ( ) ,
94+ source : file_data_source ,
11395 destination : target. to_string ( ) ,
11496 } ,
11597 ) ;
11698 self
11799 }
118100 fn create_fat_filesystem_image (
119101 & self ,
120- internal_files : BTreeMap < & str , & Path > ,
102+ internal_files : BTreeMap < & str , FileDataSource > ,
121103 ) -> anyhow:: Result < NamedTempFile > {
122104 let mut local_map = BTreeMap :: new ( ) ;
123105
124- for k in internal_files {
125- local_map. insert ( k . 0 , k . 1 ) ;
106+ for f in self . files . as_slice ( ) {
107+ local_map. insert ( f . destination . as_str ( ) , f . source . clone ( ) ) ;
126108 }
127109
128- for f in self . files . as_slice ( ) {
129- local_map. insert ( & f. destination , f. source . as_path ( ) ) ;
110+
111+ for k in internal_files {
112+ if let Some ( _) = local_map. insert ( k. 0 , k. 1 ) {
113+ return Err ( anyhow:: Error :: msg ( format ! ( "Attempted to overwrite internal file: {}" , k. 0 ) ) ) ;
114+ }
130115 }
131116
132117 let out_file = NamedTempFile :: new ( ) . context ( "failed to create temp file" ) ?;
@@ -145,8 +130,8 @@ impl DiskImageBuilder {
145130 let stage_3_path = Path :: new ( env ! ( "BIOS_STAGE_3_PATH" ) ) ;
146131 let stage_4_path = Path :: new ( env ! ( "BIOS_STAGE_4_PATH" ) ) ;
147132 let mut internal_files = BTreeMap :: new ( ) ;
148- internal_files. insert ( BIOS_STAGE_3 , stage_3_path) ;
149- internal_files. insert ( BIOS_STAGE_4 , stage_4_path) ;
133+ internal_files. insert ( BIOS_STAGE_3 , FileDataSource :: File ( stage_3_path. to_path_buf ( ) ) ) ;
134+ internal_files. insert ( BIOS_STAGE_4 , FileDataSource :: File ( stage_4_path. to_path_buf ( ) ) ) ;
150135
151136 let fat_partition = self
152137 . create_fat_filesystem_image ( internal_files)
@@ -171,7 +156,7 @@ impl DiskImageBuilder {
171156 const UEFI_BOOT_FILENAME : & str = "efi/boot/bootx64.efi" ;
172157 let bootloader_path = Path :: new ( env ! ( "UEFI_BOOTLOADER_PATH" ) ) ;
173158 let mut internal_files = BTreeMap :: new ( ) ;
174- internal_files. insert ( UEFI_BOOT_FILENAME , bootloader_path) ;
159+ internal_files. insert ( UEFI_BOOT_FILENAME , FileDataSource :: File ( bootloader_path. to_path_buf ( ) ) ) ;
175160 let fat_partition = self
176161 . create_fat_filesystem_image ( internal_files)
177162 . context ( "failed to create FAT partition" ) ?;
@@ -189,11 +174,11 @@ impl DiskImageBuilder {
189174 pub fn create_uefi_tftp_folder ( & self , tftp_path : & Path ) -> anyhow:: Result < ( ) > {
190175 const UEFI_TFTP_BOOT_FILENAME : & str = "bootloader" ;
191176 let bootloader_path = Path :: new ( env ! ( "UEFI_BOOTLOADER_PATH" ) ) ;
192- std :: fs:: create_dir_all ( tftp_path)
177+ fs:: create_dir_all ( tftp_path)
193178 . with_context ( || format ! ( "failed to create out dir at {}" , tftp_path. display( ) ) ) ?;
194179
195180 let to = tftp_path. join ( UEFI_TFTP_BOOT_FILENAME ) ;
196- std :: fs:: copy ( bootloader_path, & to) . with_context ( || {
181+ fs:: copy ( bootloader_path, & to) . with_context ( || {
197182 format ! (
198183 "failed to copy bootloader from {} to {}" ,
199184 bootloader_path. display( ) ,
@@ -203,7 +188,15 @@ impl DiskImageBuilder {
203188
204189 for f in self . files . as_slice ( ) {
205190 let to = tftp_path. join ( f. destination . clone ( ) ) ;
206- std:: fs:: copy ( f. source . clone ( ) , to) ?;
191+
192+ let mut new_file = fs:: OpenOptions :: new ( )
193+ . read ( true )
194+ . write ( true )
195+ . create ( true )
196+ . truncate ( true )
197+ . open ( to) ?;
198+
199+ f. source . copy_to ( & mut new_file) ?;
207200 }
208201
209202 Ok ( ( ) )
0 commit comments