@@ -14,7 +14,6 @@ mod osbuild;
14
14
pub ( crate ) mod osconfig;
15
15
16
16
use std:: collections:: HashMap ;
17
- use std:: fmt:: write;
18
17
use std:: fs:: create_dir_all;
19
18
use std:: io:: { Read , Write } ;
20
19
use std:: os:: fd:: { AsFd , AsRawFd } ;
@@ -1640,25 +1639,36 @@ pub(crate) fn setup_composefs_bls_boot(
1640
1639
let path = boot_dir. join ( & id_hex) ;
1641
1640
create_dir_all ( & path) ?;
1642
1641
1643
- let vmlinuz_path = path. join ( "vmlinuz" ) ;
1644
- let initrd_path = path. join ( "initrd" ) ;
1642
+ let entries_dir =
1643
+ cap_std:: fs:: Dir :: open_ambient_dir ( & path, cap_std:: ambient_authority ( ) )
1644
+ . with_context ( || format ! ( "Opening {path}" ) ) ?;
1645
1645
1646
- std:: fs:: write (
1647
- & vmlinuz_path,
1648
- read_file ( & usr_lib_modules_vmlinuz. vmlinuz , & repo) . context ( "Reading vmlinuz" ) ?,
1649
- )
1650
- . context ( "Writing vmlinuz to path" ) ?;
1646
+ entries_dir
1647
+ . atomic_write (
1648
+ "vmlinuz" ,
1649
+ read_file ( & usr_lib_modules_vmlinuz. vmlinuz , & repo)
1650
+ . context ( "Reading vmlinuz" ) ?,
1651
+ )
1652
+ . context ( "Writing vmlinuz to path" ) ?;
1651
1653
1652
1654
if let Some ( initramfs) = & usr_lib_modules_vmlinuz. initramfs {
1653
- std:: fs:: write (
1654
- & initrd_path,
1655
- read_file ( initramfs, & repo) . context ( "Reading initramfs" ) ?,
1656
- )
1657
- . context ( "Writing initrd to path" ) ?;
1655
+ entries_dir
1656
+ . atomic_write (
1657
+ "initrd" ,
1658
+ read_file ( initramfs, & repo) . context ( "Reading initrd" ) ?,
1659
+ )
1660
+ . context ( "Writing initrd to path" ) ?;
1658
1661
} else {
1659
1662
anyhow:: bail!( "initramfs not found" ) ;
1660
1663
} ;
1661
1664
1665
+ // Can't call fsync on O_PATH fds, so re-open it as a non O_PATH fd
1666
+ let owned_fd = entries_dir
1667
+ . reopen_as_ownedfd ( )
1668
+ . context ( "Reopen as owned fd" ) ?;
1669
+
1670
+ rustix:: fs:: fsync ( owned_fd) . context ( "fsync" ) ?;
1671
+
1662
1672
BLSConfig {
1663
1673
title : Some ( id_hex. clone ( ) ) ,
1664
1674
version : 1 ,
@@ -1682,18 +1692,27 @@ pub(crate) fn setup_composefs_bls_boot(
1682
1692
1683
1693
create_dir_all ( & entries_path) . with_context ( || format ! ( "Creating {:?}" , entries_path) ) ?;
1684
1694
1685
- std:: fs:: write (
1686
- entries_path. join ( format ! ( "bootc-composefs-{}.conf" , bls_config. version) ) ,
1695
+ let loader_entries_dir =
1696
+ cap_std:: fs:: Dir :: open_ambient_dir ( & entries_path, cap_std:: ambient_authority ( ) )
1697
+ . with_context ( || format ! ( "Opening {entries_path}" ) ) ?;
1698
+
1699
+ loader_entries_dir. atomic_write (
1700
+ format ! ( "bootc-composefs-{}.conf" , bls_config. version) ,
1687
1701
bls_config. to_string ( ) . as_bytes ( ) ,
1688
1702
) ?;
1689
1703
1690
1704
if let Some ( booted_bls) = booted_bls {
1691
- std :: fs :: write (
1692
- entries_path . join ( format ! ( "bootc-composefs-{}.conf" , booted_bls. version) ) ,
1705
+ loader_entries_dir . atomic_write (
1706
+ format ! ( "bootc-composefs-{}.conf" , booted_bls. version) ,
1693
1707
booted_bls. to_string ( ) . as_bytes ( ) ,
1694
1708
) ?;
1695
1709
}
1696
1710
1711
+ let owned_loader_entries_fd = loader_entries_dir
1712
+ . reopen_as_ownedfd ( )
1713
+ . context ( "Reopening as owned fd" ) ?;
1714
+ rustix:: fs:: fsync ( owned_loader_entries_fd) . context ( "fsync" ) ?;
1715
+
1697
1716
Ok ( ( ) )
1698
1717
}
1699
1718
@@ -1801,11 +1820,23 @@ pub(crate) fn setup_composefs_uki_boot(
1801
1820
}
1802
1821
1803
1822
// Write the UKI to ESP
1804
- let efi_linux = mounted_esp. join ( "EFI/Linux" ) ;
1805
- create_dir_all ( & efi_linux) . context ( "Creating EFI/Linux" ) ?;
1823
+ let efi_linux_path = mounted_esp. join ( "EFI/Linux" ) ;
1824
+ create_dir_all ( & efi_linux_path) . context ( "Creating EFI/Linux" ) ?;
1825
+
1826
+ let efi_linux =
1827
+ cap_std:: fs:: Dir :: open_ambient_dir ( & efi_linux_path, cap_std:: ambient_authority ( ) )
1828
+ . with_context ( || format ! ( "Opening {efi_linux_path:?}" ) ) ?;
1806
1829
1807
- let final_uki_path = efi_linux. join ( format ! ( "{}.efi" , id. to_hex( ) ) ) ;
1808
- std:: fs:: write ( final_uki_path, uki) . context ( "Writing UKI to final path" ) ?;
1830
+ efi_linux
1831
+ . atomic_write ( format ! ( "{}.efi" , id. to_hex( ) ) , uki)
1832
+ . context ( "Writing UKI" ) ?;
1833
+
1834
+ rustix:: fs:: fsync (
1835
+ efi_linux
1836
+ . reopen_as_ownedfd ( )
1837
+ . context ( "Reopening as owned fd" ) ?,
1838
+ )
1839
+ . context ( "fsync" ) ?;
1809
1840
1810
1841
boot_label
1811
1842
}
@@ -1830,24 +1861,24 @@ pub(crate) fn setup_composefs_uki_boot(
1830
1861
let efi_uuid_source = get_efi_uuid_source ( ) ;
1831
1862
1832
1863
let user_cfg_name = if is_upgrade {
1833
- "grub2/ user.cfg.staged"
1864
+ "user.cfg.staged"
1834
1865
} else {
1835
- "grub2/ user.cfg"
1866
+ "user.cfg"
1836
1867
} ;
1837
- let user_cfg_path = boot_dir. join ( user_cfg_name) ;
1868
+
1869
+ let grub_dir =
1870
+ cap_std:: fs:: Dir :: open_ambient_dir ( boot_dir. join ( "grub2" ) , cap_std:: ambient_authority ( ) )
1871
+ . context ( "opening boot/grub2" ) ?;
1838
1872
1839
1873
// Iterate over all available deployments, and generate a menuentry for each
1840
1874
//
1841
1875
// TODO: We might find a staged deployment here
1842
1876
if is_upgrade {
1843
- let mut usr_cfg = std:: fs:: OpenOptions :: new ( )
1844
- . write ( true )
1845
- . create ( true )
1846
- . open ( user_cfg_path)
1847
- . with_context ( || format ! ( "Opening {user_cfg_name}" ) ) ?;
1877
+ let mut buffer = vec ! [ ] ;
1848
1878
1849
- usr_cfg. write_all ( efi_uuid_source. as_bytes ( ) ) ?;
1850
- usr_cfg. write_all ( get_user_config ( & boot_label, & id. to_hex ( ) ) . as_bytes ( ) ) ?;
1879
+ // Shouldn't really fail so no context here
1880
+ buffer. write_all ( efi_uuid_source. as_bytes ( ) ) ?;
1881
+ buffer. write_all ( get_user_config ( & boot_label, & id. to_hex ( ) ) . as_bytes ( ) ) ?;
1851
1882
1852
1883
// root_path here will be /sysroot
1853
1884
for entry in std:: fs:: read_dir ( root_path. join ( STATE_DIR_RELATIVE ) ) ? {
@@ -1857,39 +1888,41 @@ pub(crate) fn setup_composefs_uki_boot(
1857
1888
// SAFETY: Deployment file name shouldn't containg non UTF-8 chars
1858
1889
let depl_file_name = depl_file_name. to_string_lossy ( ) ;
1859
1890
1860
- usr_cfg . write_all ( get_user_config ( & boot_label, & depl_file_name) . as_bytes ( ) ) ?;
1891
+ buffer . write_all ( get_user_config ( & boot_label, & depl_file_name) . as_bytes ( ) ) ?;
1861
1892
}
1862
1893
1894
+ grub_dir
1895
+ . atomic_write ( user_cfg_name, buffer)
1896
+ . with_context ( || format ! ( "Writing to {user_cfg_name}" ) ) ?;
1897
+
1898
+ rustix:: fs:: fsync ( grub_dir. reopen_as_ownedfd ( ) ?) . context ( "fsync" ) ?;
1899
+
1863
1900
return Ok ( ( ) ) ;
1864
1901
}
1865
1902
1866
- let efi_uuid_file_path = format ! ( "grub2/{EFI_UUID_FILE}" ) ;
1867
-
1868
1903
// Open grub2/efiuuid.cfg and write the EFI partition fs-UUID in there
1869
1904
// This will be sourced by grub2/user.cfg to be used for `--fs-uuid`
1870
- let mut efi_uuid_file = std:: fs:: OpenOptions :: new ( )
1871
- . write ( true )
1872
- . create ( true )
1873
- . open ( boot_dir. join ( & efi_uuid_file_path) )
1874
- . with_context ( || format ! ( "Opening {efi_uuid_file_path}" ) ) ?;
1875
-
1876
1905
let esp_uuid = Task :: new ( "blkid for ESP UUID" , "blkid" )
1877
1906
. args ( [ "-s" , "UUID" , "-o" , "value" , & esp_device] )
1878
1907
. read ( ) ?;
1879
1908
1880
- efi_uuid_file
1881
- . write_all ( format ! ( "set EFI_PART_UUID=\" {}\" " , esp_uuid. trim( ) ) . as_bytes ( ) )
1882
- . with_context ( || format ! ( "Writing to {efi_uuid_file_path}" ) ) ?;
1909
+ grub_dir. atomic_write (
1910
+ EFI_UUID_FILE ,
1911
+ format ! ( "set EFI_PART_UUID=\" {}\" " , esp_uuid. trim( ) ) . as_bytes ( ) ,
1912
+ ) ?;
1883
1913
1884
1914
// Write to grub2/user.cfg
1885
- let mut usr_cfg = std:: fs:: OpenOptions :: new ( )
1886
- . write ( true )
1887
- . create ( true )
1888
- . open ( user_cfg_path)
1889
- . with_context ( || format ! ( "Opening {user_cfg_name}" ) ) ?;
1890
-
1891
- usr_cfg. write_all ( efi_uuid_source. as_bytes ( ) ) ?;
1892
- usr_cfg. write_all ( get_user_config ( & boot_label, & id. to_hex ( ) ) . as_bytes ( ) ) ?;
1915
+ let mut buffer = vec ! [ ] ;
1916
+
1917
+ // Shouldn't really fail so no context here
1918
+ buffer. write_all ( efi_uuid_source. as_bytes ( ) ) ?;
1919
+ buffer. write_all ( get_user_config ( & boot_label, & id. to_hex ( ) ) . as_bytes ( ) ) ?;
1920
+
1921
+ grub_dir
1922
+ . atomic_write ( user_cfg_name, buffer)
1923
+ . with_context ( || format ! ( "Writing to {user_cfg_name}" ) ) ?;
1924
+
1925
+ rustix:: fs:: fsync ( grub_dir. reopen_as_ownedfd ( ) ?) . context ( "fsync" ) ?;
1893
1926
1894
1927
Ok ( ( ) )
1895
1928
}
0 commit comments