@@ -2245,6 +2245,36 @@ pub(crate) async fn install_to_existing_root(opts: InstallToExistingRootOpts) ->
22452245 install_to_filesystem ( opts, true , cleanup) . await
22462246}
22472247
2248+ /// Read the /boot entry from /etc/fstab, if it exists
2249+ fn read_boot_fstab_entry ( root : & Dir ) -> Result < Option < MountSpec > > {
2250+ let fstab_path = "etc/fstab" ;
2251+ let fstab = match root. open_optional ( fstab_path) ? {
2252+ Some ( f) => f,
2253+ None => return Ok ( None ) ,
2254+ } ;
2255+
2256+ let reader = std:: io:: BufReader :: new ( fstab) ;
2257+ for line in std:: io:: BufRead :: lines ( reader) {
2258+ let line = line?;
2259+ let line = line. trim ( ) ;
2260+
2261+ // Skip empty lines and comments
2262+ if line. is_empty ( ) || line. starts_with ( '#' ) {
2263+ continue ;
2264+ }
2265+
2266+ // Parse the mount spec
2267+ let spec = MountSpec :: from_str ( line) ?;
2268+
2269+ // Check if this is a /boot entry
2270+ if spec. target == "/boot" {
2271+ return Ok ( Some ( spec) ) ;
2272+ }
2273+ }
2274+
2275+ Ok ( None )
2276+ }
2277+
22482278pub ( crate ) async fn install_reset ( opts : InstallResetOpts ) -> Result < ( ) > {
22492279 let rootfs = & Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
22502280 if !opts. experimental {
@@ -2319,11 +2349,35 @@ pub(crate) async fn install_reset(opts: InstallResetOpts) -> Result<()> {
23192349 . collect :: < Vec < _ > > ( ) ;
23202350
23212351 let from = MergeState :: Reset {
2322- stateroot : target_stateroot,
2352+ stateroot : target_stateroot. clone ( ) ,
23232353 kargs,
23242354 } ;
23252355 crate :: deploy:: stage ( sysroot, from, & fetched, & spec, prog. clone ( ) ) . await ?;
23262356
2357+ // Copy /boot entry from /etc/fstab to the new stateroot if it exists
2358+ if let Some ( boot_spec) = read_boot_fstab_entry ( rootfs) ? {
2359+ let staged_deployment = ostree
2360+ . staged_deployment ( )
2361+ . ok_or_else ( || anyhow ! ( "No staged deployment found" ) ) ?;
2362+ let deployment_path = ostree. deployment_dirpath ( & staged_deployment) ;
2363+ let sysroot_dir = crate :: utils:: sysroot_dir ( ostree) ?;
2364+ let deployment_root = sysroot_dir. open_dir ( & deployment_path) ?;
2365+
2366+ // Write the /boot entry to /etc/fstab in the new deployment
2367+ crate :: lsm:: atomic_replace_labeled (
2368+ & deployment_root,
2369+ "etc/fstab" ,
2370+ 0o644 . into ( ) ,
2371+ None ,
2372+ |w| writeln ! ( w, "{}" , boot_spec. to_fstab( ) ) . map_err ( Into :: into) ,
2373+ ) ?;
2374+
2375+ tracing:: debug!(
2376+ "Copied /boot entry to new stateroot: {}" ,
2377+ boot_spec. to_fstab( )
2378+ ) ;
2379+ }
2380+
23272381 sysroot. update_mtime ( ) ?;
23282382
23292383 if opts. apply {
@@ -2457,4 +2511,46 @@ mod tests {
24572511
24582512 Ok ( ( ) )
24592513 }
2514+
2515+ #[ test]
2516+ fn test_read_boot_fstab_entry ( ) -> Result < ( ) > {
2517+ let td = cap_std_ext:: cap_tempfile:: TempDir :: new ( cap_std:: ambient_authority ( ) ) ?;
2518+
2519+ // Test with no /etc/fstab
2520+ assert ! ( read_boot_fstab_entry( & td) ?. is_none( ) ) ;
2521+
2522+ // Test with /etc/fstab but no /boot entry
2523+ td. create_dir ( "etc" ) ?;
2524+ td. write ( "etc/fstab" , "UUID=test-uuid / ext4 defaults 0 0\n " ) ?;
2525+ assert ! ( read_boot_fstab_entry( & td) ?. is_none( ) ) ;
2526+
2527+ // Test with /boot entry
2528+ let fstab_content = "\
2529+ # /etc/fstab
2530+ UUID=root-uuid / ext4 defaults 0 0
2531+ UUID=boot-uuid /boot ext4 ro 0 0
2532+ UUID=home-uuid /home ext4 defaults 0 0
2533+ " ;
2534+ td. write ( "etc/fstab" , fstab_content) ?;
2535+ let boot_spec = read_boot_fstab_entry ( & td) ?. unwrap ( ) ;
2536+ assert_eq ! ( boot_spec. source, "UUID=boot-uuid" ) ;
2537+ assert_eq ! ( boot_spec. target, "/boot" ) ;
2538+ assert_eq ! ( boot_spec. fstype, "ext4" ) ;
2539+ assert_eq ! ( boot_spec. options, Some ( "ro" . to_string( ) ) ) ;
2540+
2541+ // Test with /boot entry with comments
2542+ let fstab_content = "\
2543+ # /etc/fstab
2544+ # Created by anaconda
2545+ UUID=root-uuid / ext4 defaults 0 0
2546+ # Boot partition
2547+ UUID=boot-uuid /boot ext4 defaults 0 0
2548+ " ;
2549+ td. write ( "etc/fstab" , fstab_content) ?;
2550+ let boot_spec = read_boot_fstab_entry ( & td) ?. unwrap ( ) ;
2551+ assert_eq ! ( boot_spec. source, "UUID=boot-uuid" ) ;
2552+ assert_eq ! ( boot_spec. target, "/boot" ) ;
2553+
2554+ Ok ( ( ) )
2555+ }
24602556}
0 commit comments