Skip to content

Commit b635467

Browse files
committed
efi: update the ESP by creating a tmpdir and RENAME_EXCHANGE
See Timothée's comment coreos#454 (comment) Fixes coreos#454
1 parent f90b45e commit b635467

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed

src/efi.rs

+46-5
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,41 @@ impl Component for Efi {
348348
.context("opening update dir")?;
349349
let updatef = filetree::FileTree::new_from_dir(&updated).context("reading update dir")?;
350350
let diff = currentf.diff(&updatef)?;
351-
self.ensure_mounted_esp(Path::new("/"))?;
352-
let destdir = self.open_esp().context("opening EFI dir")?;
353-
validate_esp(&destdir)?;
351+
352+
/* copy "lowest" directory that we need to make the change
353+
* e.g. we only affect EFI/fedora for example and not all of EFI
354+
*/
355+
let vendor = if let Some(v) = self.get_efi_vendor(&sysroot)? {
356+
v
357+
} else {
358+
bail!("Failed to get vendor dir");
359+
};
360+
361+
let esp = self.esp_path()?;
362+
let vendordir = esp.join(&vendor);
363+
let tmp_vendordir = esp.join(format!(".{vendor}.tmp"));
364+
// remove a previous directory if it exists in order to handle being interrupted in the middle.
365+
std::fs::remove_dir_all(&tmp_vendordir)?;
366+
copy_dir(&vendordir, &tmp_vendordir).context("copying existing files to temp dir")?;
367+
assert!(tmp_vendordir.exists());
368+
369+
let tmpdir = sysroot.sub_dir(&vendordir)?;
370+
validate_esp(&tmpdir)?;
354371
log::trace!("applying diff: {}", &diff);
355-
filetree::apply_diff(&updated, &destdir, &diff, None)
356-
.context("applying filesystem changes")?;
372+
filetree::apply_diff(&updated, &tmpdir, &diff, None)
373+
.context("applying filesystem changes to temp EFI")?;
374+
{
375+
let esp = self.open_esp()?;
376+
log::trace!(
377+
"doing local exchange for {} and {}",
378+
tmp_vendordir.display(),
379+
vendordir.display()
380+
);
381+
esp.local_exchange(&tmp_vendordir, &vendordir)?;
382+
// finally remove the temp dir
383+
std::fs::remove_dir_all(&tmp_vendordir)?;
384+
assert_eq!(tmp_vendordir.exists(), false);
385+
}
357386
let adopted_from = None;
358387
Ok(InstalledContent {
359388
meta: updatemeta,
@@ -580,6 +609,18 @@ fn find_file_recursive<P: AsRef<Path>>(dir: P, target_file: &str) -> Result<Vec<
580609
Ok(result)
581610
}
582611

612+
fn copy_dir(src: &Path, dst: &Path) -> Result<()> {
613+
let r = std::process::Command::new("cp")
614+
.args(["-a"])
615+
.arg(src)
616+
.arg(dst)
617+
.status()?;
618+
if !r.success() {
619+
anyhow::bail!("Failed to copy");
620+
}
621+
Ok(())
622+
}
623+
583624
#[cfg(test)]
584625
mod tests {
585626
use super::*;

0 commit comments

Comments
 (0)