@@ -1856,30 +1856,59 @@ fn remove_all_in_dir_no_xdev(d: &Dir, mount_err: bool) -> Result<()> {
18561856 anyhow:: Ok ( ( ) )
18571857}
18581858
1859+ #[ context( "Removing boot directory content except loader dir" ) ]
1860+ fn remove_all_except_loader_dirs ( bootdir : & Dir ) -> Result < ( ) > {
1861+ let entries = bootdir
1862+ . entries ( )
1863+ . context ( "Reading boot directory entries" ) ?;
1864+
1865+ for entry in entries {
1866+ let entry = entry. context ( "Reading directory entry" ) ?;
1867+ let file_name = entry. file_name ( ) ;
1868+ let file_name = if let Some ( n) = file_name. to_str ( ) {
1869+ n
1870+ } else {
1871+ anyhow:: bail!( "Invalid non-UTF8 filename: {file_name:?} in /boot" ) ;
1872+ } ;
1873+
1874+ // Skip any entry that starts with a protected prefix,
1875+ // as we also need to protect loader.0 or loader.1
1876+ if file_name. starts_with ( "loader" ) {
1877+ continue ;
1878+ }
1879+
1880+ let etype = entry. file_type ( ) ?;
1881+ if etype == FileType :: dir ( ) {
1882+ // Open the directory and remove its contents
1883+ if let Some ( subdir) = bootdir. open_dir_noxdev ( & file_name) ? {
1884+ remove_all_in_dir_no_xdev ( & subdir, false )
1885+ . with_context ( || format ! ( "Removing directory contents: {}" , file_name) ) ?;
1886+ }
1887+ } else {
1888+ bootdir
1889+ . remove_file_optional ( & file_name)
1890+ . with_context ( || format ! ( "Removing file: {}" , file_name) ) ?;
1891+ }
1892+ }
1893+ Ok ( ( ) )
1894+ }
1895+
18591896#[ context( "Removing boot directory content" ) ]
1860- fn clean_boot_directories ( rootfs : & Dir , is_ostree : bool ) -> Result < ( ) > {
1897+ fn clean_boot_directories ( rootfs : & Dir ) -> Result < ( ) > {
18611898 let bootdir =
18621899 crate :: utils:: open_dir_remount_rw ( rootfs, BOOT . into ( ) ) . context ( "Opening /boot" ) ?;
18631900
1864- if is_ostree {
1865- // On ostree systems, the boot directory already has our desired format, we should only
1866- // remove the bootupd-state.json file to avoid bootupctl complaining it already exists.
1867- bootdir
1868- . remove_file_optional ( "bootupd-state.json" )
1869- . context ( "removing bootupd-state.json" ) ?;
1870- } else {
1871- // This should not remove /boot/efi note.
1872- remove_all_in_dir_no_xdev ( & bootdir, false ) . context ( "Emptying /boot" ) ?;
1873- // TODO: Discover the ESP the same way bootupd does it; we should also
1874- // support not wiping the ESP.
1875- if ARCH_USES_EFI {
1876- if let Some ( efidir) = bootdir
1877- . open_dir_optional ( crate :: bootloader:: EFI_DIR )
1878- . context ( "Opening /boot/efi" ) ?
1879- {
1880- remove_all_in_dir_no_xdev ( & efidir, false )
1881- . context ( "Emptying EFI system partition" ) ?;
1882- }
1901+ // This should not remove /boot/efi note.
1902+ remove_all_except_loader_dirs ( & bootdir) . context ( "Emptying /boot but preserve loader" ) ?;
1903+
1904+ // TODO: Discover the ESP the same way bootupd does it; we should also
1905+ // support not wiping the ESP.
1906+ if ARCH_USES_EFI {
1907+ if let Some ( efidir) = bootdir
1908+ . open_dir_optional ( crate :: bootloader:: EFI_DIR )
1909+ . context ( "Opening /boot/efi" ) ?
1910+ {
1911+ remove_all_in_dir_no_xdev ( & efidir, false ) . context ( "Emptying EFI system partition" ) ?;
18831912 }
18841913 }
18851914
@@ -2084,9 +2113,7 @@ pub(crate) async fn install_to_filesystem(
20842113 tokio:: task:: spawn_blocking ( move || remove_all_in_dir_no_xdev ( & rootfs_fd, true ) )
20852114 . await ??;
20862115 }
2087- Some ( ReplaceMode :: Alongside ) => {
2088- clean_boot_directories ( & target_rootfs_fd, is_already_ostree) ?
2089- }
2116+ Some ( ReplaceMode :: Alongside ) => clean_boot_directories ( & target_rootfs_fd) ?,
20902117 None => require_empty_rootdir ( & rootfs_fd) ?,
20912118 }
20922119
0 commit comments