@@ -2224,6 +2224,36 @@ pub(crate) async fn install_to_existing_root(opts: InstallToExistingRootOpts) ->
22242224 install_to_filesystem ( opts, true , cleanup) . await
22252225}
22262226
2227+ /// Read the /boot entry from /etc/fstab, if it exists
2228+ fn read_boot_fstab_entry ( root : & Dir ) -> Result < Option < MountSpec > > {
2229+ let fstab_path = "etc/fstab" ;
2230+ let fstab = match root. open_optional ( fstab_path) ? {
2231+ Some ( f) => f,
2232+ None => return Ok ( None ) ,
2233+ } ;
2234+
2235+ let reader = std:: io:: BufReader :: new ( fstab) ;
2236+ for line in std:: io:: BufRead :: lines ( reader) {
2237+ let line = line?;
2238+ let line = line. trim ( ) ;
2239+
2240+ // Skip empty lines and comments
2241+ if line. is_empty ( ) || line. starts_with ( '#' ) {
2242+ continue ;
2243+ }
2244+
2245+ // Parse the mount spec
2246+ let spec = MountSpec :: from_str ( line) ?;
2247+
2248+ // Check if this is a /boot entry
2249+ if spec. target == "/boot" {
2250+ return Ok ( Some ( spec) ) ;
2251+ }
2252+ }
2253+
2254+ Ok ( None )
2255+ }
2256+
22272257pub ( crate ) async fn install_reset ( opts : InstallResetOpts ) -> Result < ( ) > {
22282258 let rootfs = & Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
22292259 if !opts. experimental {
@@ -2298,11 +2328,35 @@ pub(crate) async fn install_reset(opts: InstallResetOpts) -> Result<()> {
22982328 . collect :: < Vec < _ > > ( ) ;
22992329
23002330 let from = MergeState :: Reset {
2301- stateroot : target_stateroot,
2331+ stateroot : target_stateroot. clone ( ) ,
23022332 kargs,
23032333 } ;
23042334 crate :: deploy:: stage ( sysroot, from, & fetched, & spec, prog. clone ( ) ) . await ?;
23052335
2336+ // Copy /boot entry from /etc/fstab to the new stateroot if it exists
2337+ if let Some ( boot_spec) = read_boot_fstab_entry ( rootfs) ? {
2338+ let staged_deployment = ostree
2339+ . staged_deployment ( )
2340+ . ok_or_else ( || anyhow ! ( "No staged deployment found" ) ) ?;
2341+ let deployment_path = ostree. deployment_dirpath ( & staged_deployment) ;
2342+ let sysroot_dir = crate :: utils:: sysroot_dir ( ostree) ?;
2343+ let deployment_root = sysroot_dir. open_dir ( & deployment_path) ?;
2344+
2345+ // Write the /boot entry to /etc/fstab in the new deployment
2346+ crate :: lsm:: atomic_replace_labeled (
2347+ & deployment_root,
2348+ "etc/fstab" ,
2349+ 0o644 . into ( ) ,
2350+ None ,
2351+ |w| writeln ! ( w, "{}" , boot_spec. to_fstab( ) ) . map_err ( Into :: into) ,
2352+ ) ?;
2353+
2354+ tracing:: debug!(
2355+ "Copied /boot entry to new stateroot: {}" ,
2356+ boot_spec. to_fstab( )
2357+ ) ;
2358+ }
2359+
23062360 sysroot. update_mtime ( ) ?;
23072361
23082362 if opts. apply {
@@ -2436,4 +2490,46 @@ mod tests {
24362490
24372491 Ok ( ( ) )
24382492 }
2493+
2494+ #[ test]
2495+ fn test_read_boot_fstab_entry ( ) -> Result < ( ) > {
2496+ let td = cap_std_ext:: cap_tempfile:: TempDir :: new ( cap_std:: ambient_authority ( ) ) ?;
2497+
2498+ // Test with no /etc/fstab
2499+ assert ! ( read_boot_fstab_entry( & td) ?. is_none( ) ) ;
2500+
2501+ // Test with /etc/fstab but no /boot entry
2502+ td. create_dir ( "etc" ) ?;
2503+ td. write ( "etc/fstab" , "UUID=test-uuid / ext4 defaults 0 0\n " ) ?;
2504+ assert ! ( read_boot_fstab_entry( & td) ?. is_none( ) ) ;
2505+
2506+ // Test with /boot entry
2507+ let fstab_content = "\
2508+ # /etc/fstab
2509+ UUID=root-uuid / ext4 defaults 0 0
2510+ UUID=boot-uuid /boot ext4 ro 0 0
2511+ UUID=home-uuid /home ext4 defaults 0 0
2512+ " ;
2513+ td. write ( "etc/fstab" , fstab_content) ?;
2514+ let boot_spec = read_boot_fstab_entry ( & td) ?. unwrap ( ) ;
2515+ assert_eq ! ( boot_spec. source, "UUID=boot-uuid" ) ;
2516+ assert_eq ! ( boot_spec. target, "/boot" ) ;
2517+ assert_eq ! ( boot_spec. fstype, "ext4" ) ;
2518+ assert_eq ! ( boot_spec. options, Some ( "ro" . to_string( ) ) ) ;
2519+
2520+ // Test with /boot entry with comments
2521+ let fstab_content = "\
2522+ # /etc/fstab
2523+ # Created by anaconda
2524+ UUID=root-uuid / ext4 defaults 0 0
2525+ # Boot partition
2526+ UUID=boot-uuid /boot ext4 defaults 0 0
2527+ " ;
2528+ td. write ( "etc/fstab" , fstab_content) ?;
2529+ let boot_spec = read_boot_fstab_entry ( & td) ?. unwrap ( ) ;
2530+ assert_eq ! ( boot_spec. source, "UUID=boot-uuid" ) ;
2531+ assert_eq ! ( boot_spec. target, "/boot" ) ;
2532+
2533+ Ok ( ( ) )
2534+ }
24392535}
0 commit comments