|
5 | 5 | */ |
6 | 6 |
|
7 | 7 | use std::cell::RefCell; |
8 | | -use std::os::unix::fs::MetadataExt; |
9 | 8 | use std::os::unix::io::AsRawFd; |
10 | 9 | use std::path::{Path, PathBuf}; |
11 | 10 | use std::process::Command; |
@@ -61,6 +60,23 @@ const STUB_INFO_VAR_STR: &str = "StubInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"; |
61 | 60 | /// The options of cp command for installation |
62 | 61 | const OPTIONS: &[&str] = &["-rp", "--reflink=auto"]; |
63 | 62 |
|
| 63 | +/// Check if the given path is a mount point via statx(MOUNT_ROOT). |
| 64 | +fn is_mount_point(path: &Path) -> Result<bool> { |
| 65 | + let parent = path.parent().unwrap_or(path); |
| 66 | + let parent = if parent.as_os_str().is_empty() { |
| 67 | + Path::new(".") |
| 68 | + } else { |
| 69 | + parent |
| 70 | + }; |
| 71 | + let parent_dir = Dir::open_ambient_dir(parent, cap_std::ambient_authority())?; |
| 72 | + let basename = path |
| 73 | + .file_name() |
| 74 | + .ok_or_else(|| anyhow::anyhow!("path has no file name: {path:?}"))?; |
| 75 | + parent_dir |
| 76 | + .is_mountpoint(basename)? |
| 77 | + .ok_or_else(|| anyhow::anyhow!("could not determine if {path:?} is a mount point")) |
| 78 | +} |
| 79 | + |
64 | 80 | /// Return `true` if the system is booted via EFI |
65 | 81 | pub(crate) fn is_efi_booted() -> Result<bool> { |
66 | 82 | Path::new("/sys/firmware/efi") |
@@ -91,9 +107,7 @@ impl Efi { |
91 | 107 | // different device than its parent. Without this check, a vfat |
92 | 108 | // subdirectory (e.g. /boot/efi on a vfat /boot) could be |
93 | 109 | // misidentified as a mounted ESP. |
94 | | - let path_dev = std::fs::metadata(&path)?.dev(); |
95 | | - let parent_dev = std::fs::metadata(path.parent().unwrap_or(&path))?.dev(); |
96 | | - if path_dev == parent_dev { |
| 110 | + if !is_mount_point(&path)? { |
97 | 111 | // Same device as parent - this is a subdirectory, not a mount point |
98 | 112 | log::debug!("Skipping {path:?}: vfat but not a mount point"); |
99 | 113 | continue; |
@@ -123,6 +137,18 @@ impl Efi { |
123 | 137 | if !mnt.exists() { |
124 | 138 | continue; |
125 | 139 | } |
| 140 | + |
| 141 | + // Check if the target is already a mounted ESP (e.g. the host |
| 142 | + // already has the ESP mounted when running install-to-filesystem). |
| 143 | + let st = rustix::fs::statfs(&mnt)?; |
| 144 | + if st.f_type == libc::MSDOS_SUPER_MAGIC { |
| 145 | + if is_mount_point(&mnt)? { |
| 146 | + log::debug!("ESP already mounted at {mnt:?}, reusing"); |
| 147 | + mountpoint = Some(mnt); |
| 148 | + break; |
| 149 | + } |
| 150 | + } |
| 151 | + |
126 | 152 | std::process::Command::new("mount") |
127 | 153 | .arg(&esp_device) |
128 | 154 | .arg(&mnt) |
|
0 commit comments