Skip to content

Commit

Permalink
efi: update the ESP by creating a tmpdir and RENAME_EXCHANGE
Browse files Browse the repository at this point in the history
See Timothée's comment #454 (comment)

Fixes #454
  • Loading branch information
HuijingHei committed Jun 21, 2024
1 parent 8a40a4e commit b8fd9a9
Showing 1 changed file with 51 additions and 4 deletions.
55 changes: 51 additions & 4 deletions src/efi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,46 @@ impl Component for Efi {
let updatef = filetree::FileTree::new_from_dir(&updated).context("reading update dir")?;
let diff = currentf.diff(&updatef)?;
self.ensure_mounted_esp(Path::new("/"))?;
let destdir = self.open_esp().context("opening EFI dir")?;
validate_esp(&destdir)?;

/* copy "lowest" directory that we need to make the change
* e.g. we only affect EFI/fedora for example and not all of EFI
*/
let vendor = if let Some(v) = self.get_efi_vendor(&sysroot)? {
v
} else {
bail!("Failed to get vendor dir");
};

let esp = self.esp_path()?;
let vendordir = esp.join(&vendor);
let tmp_vendordir = esp.join(format!(".{vendor}.tmp"));
// remove a previous directory if it exists in order to handle being interrupted in the middle.
if tmp_vendordir.exists() {
std::fs::remove_dir_all(&tmp_vendordir)?;
}
copy_dir(&vendordir, &tmp_vendordir)
.with_context(|| "copying existing files to temp dir")?;
assert!(tmp_vendordir.exists());

let tmpdir = sysroot.sub_dir(&tmp_vendordir)?;
validate_esp(&tmpdir)?;
log::trace!("applying diff: {}", &diff);
filetree::apply_diff(&updated, &destdir, &diff, None)
.context("applying filesystem changes")?;
filetree::apply_diff(&updated, &tmpdir, &diff, None)
.context("applying filesystem changes to temp EFI")?;
{
let esp = self.open_esp()?;
log::trace!(
"doing local exchange for {} and {}",
tmp_vendordir.display(),
vendordir.display()
);

esp.local_exchange(&tmp_vendordir, &vendordir)
.with_context(|| format!("exchange for {:?} and {:?}", tmp_vendordir, vendordir))?;
// finally remove the temp dir
std::fs::remove_dir_all(&tmp_vendordir).context("clean up temp")?;
assert!(!tmp_vendordir.exists());
}
let adopted_from = None;
Ok(InstalledContent {
meta: updatemeta,
Expand Down Expand Up @@ -584,6 +619,18 @@ fn find_file_recursive<P: AsRef<Path>>(dir: P, target_file: &str) -> Result<Vec<
Ok(result)
}

fn copy_dir(src: &Path, dst: &Path) -> Result<()> {
let r = std::process::Command::new("cp")
.args(["-a"])
.arg(src)
.arg(dst)
.status()?;
if !r.success() {
anyhow::bail!("Failed to copy");
}
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit b8fd9a9

Please sign in to comment.