@@ -2,8 +2,13 @@ use std::fmt::Write;
2
2
use std:: path:: { Path , PathBuf } ;
3
3
4
4
use anyhow:: { anyhow, Context , Result } ;
5
+ use cap_std:: fs:: { Dir , DirBuilder , DirBuilderExt , MetadataExt } ;
6
+ use cap_std_ext:: cap_std;
7
+ use cap_std_ext:: cap_std:: fs:: { Permissions , PermissionsExt } ;
8
+ use cap_std_ext:: dirext:: CapStdExtDirExt ;
5
9
use fn_error_context:: context;
6
- use openat_ext:: OpenatDirExt ;
10
+
11
+ use crate :: util;
7
12
8
13
/// The subdirectory of /boot we use
9
14
const GRUB2DIR : & str = "grub2" ;
@@ -17,27 +22,34 @@ pub(crate) fn install(
17
22
installed_efi_vendor : Option < & str > ,
18
23
write_uuid : bool ,
19
24
) -> Result < ( ) > {
20
- let bootdir = & target_root. sub_dir ( "boot" ) . context ( "Opening /boot" ) ?;
25
+ let target_root = & util:: reopen_dir ( target_root) ?;
26
+ let bootdir = & target_root. open_dir ( "boot" ) . context ( "Opening /boot" ) ?;
21
27
let boot_is_mount = {
22
- let root_dev = target_root. self_metadata ( ) ?. stat ( ) . st_dev ;
23
- let boot_dev = bootdir. self_metadata ( ) ?. stat ( ) . st_dev ;
28
+ let root_dev = target_root. dir_metadata ( ) ?. dev ( ) ;
29
+ let boot_dev = bootdir. dir_metadata ( ) ?. dev ( ) ;
24
30
log:: debug!( "root_dev={root_dev} boot_dev={boot_dev}" ) ;
25
31
root_dev != boot_dev
26
32
} ;
27
33
28
- if !bootdir. exists ( GRUB2DIR ) ? {
29
- bootdir. create_dir ( GRUB2DIR , 0o700 ) ?;
34
+ if !bootdir. try_exists ( GRUB2DIR ) ? {
35
+ let mut db = DirBuilder :: new ( ) ;
36
+ db. mode ( 0o700 ) ;
37
+ bootdir. create_dir_with ( GRUB2DIR , & db) ?;
30
38
}
31
39
32
40
let mut config = std:: fs:: read_to_string ( Path :: new ( CONFIGDIR ) . join ( "grub-static-pre.cfg" ) ) ?;
33
41
34
- let dropindir = openat:: Dir :: open ( & Path :: new ( CONFIGDIR ) . join ( DROPINDIR ) ) ?;
42
+ let dropindir = Dir :: open_ambient_dir (
43
+ & Path :: new ( CONFIGDIR ) . join ( DROPINDIR ) ,
44
+ cap_std:: ambient_authority ( ) ,
45
+ ) ?;
35
46
// Sort the files for reproducibility
36
47
let mut entries = dropindir
37
- . list_dir ( "." ) ?
48
+ . entries ( ) ?
38
49
. map ( |e| e. map_err ( anyhow:: Error :: msg) )
39
50
. collect :: < Result < Vec < _ > > > ( ) ?;
40
- entries. sort_by ( |a, b| a. file_name ( ) . cmp ( b. file_name ( ) ) ) ;
51
+ // cc https://github.com/rust-lang/rust/issues/85573#issuecomment-2195271304
52
+ entries. sort_by ( |a, b| a. file_name ( ) . cmp ( & b. file_name ( ) ) ) ;
41
53
for ent in entries {
42
54
let name = ent. file_name ( ) ;
43
55
let name = name
@@ -49,7 +61,7 @@ pub(crate) fn install(
49
61
}
50
62
writeln ! ( config, "source $prefix/{name}" ) ?;
51
63
dropindir
52
- . copy_file_at ( name, bootdir, format ! ( "{GRUB2DIR}/{name}" ) )
64
+ . copy ( name, bootdir, format ! ( "{GRUB2DIR}/{name}" ) )
53
65
. with_context ( || format ! ( "Copying {name}" ) ) ?;
54
66
println ! ( "Installed {name}" ) ;
55
67
}
@@ -59,21 +71,27 @@ pub(crate) fn install(
59
71
config. push_str ( post. as_str ( ) ) ;
60
72
}
61
73
74
+ let rperms = Permissions :: from_mode ( 0o644 ) ;
62
75
bootdir
63
- . write_file_contents ( format ! ( "{GRUB2DIR}/grub.cfg" ) , 0o644 , config. as_bytes ( ) )
76
+ . atomic_write_with_perms (
77
+ format ! ( "{GRUB2DIR}/grub.cfg" ) ,
78
+ config. as_bytes ( ) ,
79
+ rperms. clone ( ) ,
80
+ )
64
81
. context ( "Copying grub-static.cfg" ) ?;
65
82
println ! ( "Installed: grub.cfg" ) ;
66
83
67
84
let uuid_path = if write_uuid {
68
85
let target_fs = if boot_is_mount { bootdir } else { target_root } ;
69
- let bootfs_meta = crate :: filesystem:: inspect_filesystem ( target_fs, "." ) ?;
86
+ let target_fs_dir = & util:: reopen_legacy_dir ( target_fs) ?;
87
+ let bootfs_meta = crate :: filesystem:: inspect_filesystem ( target_fs_dir, "." ) ?;
70
88
let bootfs_uuid = bootfs_meta
71
89
. uuid
72
90
. ok_or_else ( || anyhow:: anyhow!( "Failed to find UUID for boot" ) ) ?;
73
91
let grub2_uuid_contents = format ! ( "set BOOT_UUID=\" {bootfs_uuid}\" \n " ) ;
74
92
let uuid_path = format ! ( "{GRUB2DIR}/bootuuid.cfg" ) ;
75
93
bootdir
76
- . write_file_contents ( & uuid_path, 0o644 , grub2_uuid_contents )
94
+ . atomic_write_with_perms ( & uuid_path, grub2_uuid_contents , rperms )
77
95
. context ( "Writing bootuuid.cfg" ) ?;
78
96
Some ( uuid_path)
79
97
} else {
@@ -85,19 +103,23 @@ pub(crate) fn install(
85
103
let vendor = PathBuf :: from ( vendordir) ;
86
104
let target = & vendor. join ( "grub.cfg" ) ;
87
105
let dest_efidir = target_root
88
- . sub_dir_optional ( "boot/efi/EFI" )
106
+ . open_dir_optional ( "boot/efi/EFI" )
89
107
. context ( "Opening /boot/efi/EFI" ) ?;
90
108
if let Some ( efidir) = dest_efidir {
91
109
efidir
92
- . copy_file ( & Path :: new ( CONFIGDIR ) . join ( "grub-static-efi.cfg" ) , target)
110
+ . copy (
111
+ & Path :: new ( CONFIGDIR ) . join ( "grub-static-efi.cfg" ) ,
112
+ & efidir,
113
+ target,
114
+ )
93
115
. context ( "Copying static EFI" ) ?;
94
116
println ! ( "Installed: {target:?}" ) ;
95
117
if let Some ( uuid_path) = uuid_path {
96
118
// SAFETY: we always have a filename
97
119
let filename = Path :: new ( & uuid_path) . file_name ( ) . unwrap ( ) ;
98
120
let target = & vendor. join ( filename) ;
99
121
bootdir
100
- . copy_file_at ( uuid_path, & efidir, target)
122
+ . copy ( uuid_path, & efidir, target)
101
123
. context ( "Writing bootuuid.cfg to efi dir" ) ?;
102
124
}
103
125
}
@@ -109,6 +131,7 @@ pub(crate) fn install(
109
131
#[ cfg( test) ]
110
132
mod tests {
111
133
use super :: * ;
134
+ use openat_ext:: OpenatDirExt ;
112
135
113
136
#[ test]
114
137
#[ ignore]
0 commit comments