@@ -14,6 +14,7 @@ use anyhow::{bail, Context, Result};
14
14
use openat_ext:: OpenatDirExt ;
15
15
16
16
use chrono:: prelude:: * ;
17
+ use structopt:: lazy_static:: lazy_static;
17
18
18
19
use crate :: component:: * ;
19
20
use crate :: filetree;
@@ -22,27 +23,64 @@ use crate::ostreeutil;
22
23
use crate :: util;
23
24
use crate :: util:: CommandRunExt ;
24
25
25
- /// The path to the ESP mount
26
- pub ( crate ) const MOUNT_PATH : & str = "boot/efi" ;
26
+ /// The ESP partition label
27
+ pub ( crate ) const ESP_PART_LABEL : & str = "EFI-SYSTEM" ;
28
+
29
+ #[ macro_use]
30
+ lazy_static ! {
31
+ /// The path to a temporary ESP mount
32
+ static ref MOUNT_PATH : PathBuf = {
33
+ // Create new directory in /tmp with randomly generated name at runtime for ESP mount path.
34
+ tempfile:: tempdir_in( "/tmp" ) . expect( "Failed to create temp dir for EFI mount" ) . into_path( )
35
+ } ;
36
+ }
27
37
28
38
#[ derive( Default ) ]
29
39
pub ( crate ) struct EFI { }
30
40
31
41
impl EFI {
32
42
fn esp_path ( & self ) -> PathBuf {
33
- Path :: new ( MOUNT_PATH ) . join ( "EFI" )
43
+ Path :: new ( & * MOUNT_PATH ) . join ( "EFI" )
44
+ }
45
+
46
+ fn esp_device ( & self ) -> PathBuf {
47
+ Path :: new ( "/dev/disk/by-partlabel/" ) . join ( ESP_PART_LABEL )
34
48
}
35
49
36
50
fn open_esp_optional ( & self ) -> Result < Option < openat:: Dir > > {
51
+ self . ensure_mounted_esp ( ) ?;
37
52
let sysroot = openat:: Dir :: open ( "/" ) ?;
38
53
let esp = sysroot. sub_dir_optional ( & self . esp_path ( ) ) ?;
39
54
Ok ( esp)
40
55
}
41
56
fn open_esp ( & self ) -> Result < openat:: Dir > {
57
+ self . ensure_mounted_esp ( ) ?;
42
58
let sysroot = openat:: Dir :: open ( "/" ) ?;
43
59
let esp = sysroot. sub_dir ( & self . esp_path ( ) ) ?;
44
60
Ok ( esp)
45
61
}
62
+
63
+ fn ensure_mounted_esp ( & self ) -> Result < ( ) > {
64
+ let mount_point = & Path :: new ( "/" ) . join ( & * MOUNT_PATH ) ;
65
+ let output = std:: process:: Command :: new ( "mountpoint" )
66
+ . arg ( mount_point)
67
+ . output ( ) ?;
68
+ if !output. status . success ( ) {
69
+ let esp_device = & self . esp_device ( ) ;
70
+ if !esp_device. exists ( ) {
71
+ log:: error!( "Single ESP device not found; ESP on multiple independent filesystems currently unsupported" ) ;
72
+ anyhow:: bail!( "Could not find {:?}" , esp_device) ;
73
+ }
74
+ let status = std:: process:: Command :: new ( "mount" )
75
+ . arg ( & self . esp_device ( ) )
76
+ . arg ( mount_point)
77
+ . status ( ) ?;
78
+ if !status. success ( ) {
79
+ anyhow:: bail!( "Failed to mount {:?}" , esp_device) ;
80
+ }
81
+ } ;
82
+ Ok ( ( ) )
83
+ }
46
84
}
47
85
48
86
impl Component for EFI {
@@ -94,7 +132,6 @@ impl Component for EFI {
94
132
let updatef = filetree:: FileTree :: new_from_dir ( & updated) . context ( "reading update dir" ) ?;
95
133
// For adoption, we should only touch files that we know about.
96
134
let diff = updatef. relative_diff_to ( & esp) ?;
97
- ensure_writable_efi ( ) ?;
98
135
log:: trace!( "applying adoption diff: {}" , & diff) ;
99
136
filetree:: apply_diff ( & updated, & esp, & diff, None ) . context ( "applying filesystem changes" ) ?;
100
137
Ok ( InstalledContent {
@@ -112,7 +149,8 @@ impl Component for EFI {
112
149
} ;
113
150
let srcdir_name = component_updatedirname ( self ) ;
114
151
let ft = crate :: filetree:: FileTree :: new_from_dir ( & src_root. sub_dir ( & srcdir_name) ?) ?;
115
- let destdir = Path :: new ( dest_root) . join ( MOUNT_PATH ) ;
152
+ self . ensure_mounted_esp ( ) ?;
153
+ let destdir = Path :: new ( dest_root) . join ( & * MOUNT_PATH ) ;
116
154
{
117
155
let destd = openat:: Dir :: open ( & destdir)
118
156
. with_context ( || format ! ( "opening dest dir {}" , destdir. display( ) ) ) ?;
@@ -151,10 +189,9 @@ impl Component for EFI {
151
189
. context ( "opening update dir" ) ?;
152
190
let updatef = filetree:: FileTree :: new_from_dir ( & updated) . context ( "reading update dir" ) ?;
153
191
let diff = currentf. diff ( & updatef) ?;
154
- let destdir = openat :: Dir :: open ( & Path :: new ( "/" ) . join ( MOUNT_PATH ) . join ( "EFI" ) )
155
- . context ( "opening EFI dir" ) ?;
192
+ self . ensure_mounted_esp ( ) ? ;
193
+ let destdir = self . open_esp ( ) . context ( "opening EFI dir" ) ?;
156
194
validate_esp ( & destdir) ?;
157
- ensure_writable_efi ( ) ?;
158
195
log:: trace!( "applying diff: {}" , & diff) ;
159
196
filetree:: apply_diff ( & updated, & destdir, & diff, None )
160
197
. context ( "applying filesystem changes" ) ?;
@@ -256,7 +293,8 @@ impl Component for EFI {
256
293
. filetree
257
294
. as_ref ( )
258
295
. ok_or_else ( || anyhow:: anyhow!( "No filetree for installed EFI found!" ) ) ?;
259
- let efidir = openat:: Dir :: open ( & Path :: new ( "/" ) . join ( MOUNT_PATH ) . join ( "EFI" ) ) ?;
296
+ self . ensure_mounted_esp ( ) ?;
297
+ let efidir = self . open_esp ( ) ?;
260
298
let diff = currentf. relative_diff_to ( & efidir) ?;
261
299
let mut errs = Vec :: new ( ) ;
262
300
for f in diff. changes . iter ( ) {
@@ -282,7 +320,3 @@ fn validate_esp(dir: &openat::Dir) -> Result<()> {
282
320
} ;
283
321
Ok ( ( ) )
284
322
}
285
-
286
- fn ensure_writable_efi ( ) -> Result < ( ) > {
287
- util:: ensure_writable_mount ( & Path :: new ( "/" ) . join ( MOUNT_PATH ) )
288
- }
0 commit comments