proxmox-chroot: replace nix::(u)mount calls with external (u)mount

Comes with a reduction of 52 -> 40 in terms of crate dependencies for
proxmox-chroot, 198 -> 192 for a full workspace build.

Currently, this is done inconsistently anyway, i.e. there are calls to
the external mount(8) as well as mount(2) and umount(2) via `nix`.
Just switch over to calling the external programs completely, which in
turn allows to drop the `nix` crate dependency from the tree.

No functional changes.

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
This commit is contained in:
Christoph Heiss 2025-03-11 14:27:29 +01:00 committed by Thomas Lamprecht
parent 95f2bc3ee2
commit 1f74e8e9ff
3 changed files with 53 additions and 30 deletions

1
debian/control vendored
View File

@ -15,7 +15,6 @@ Build-Depends: cargo:native,
librust-glob-0.3-dev, librust-glob-0.3-dev,
librust-hex-0.4-dev, librust-hex-0.4-dev,
librust-native-tls-dev, librust-native-tls-dev,
librust-nix-0.26+default-dev,
librust-pretty-assertions-1.4-dev, librust-pretty-assertions-1.4-dev,
librust-regex-1+default-dev (>= 1.7~~), librust-regex-1+default-dev (>= 1.7~~),
librust-rustls-0.21+dangerous-configuration-dev, librust-rustls-0.21+dangerous-configuration-dev,

View File

@ -14,4 +14,3 @@ serde_json.workspace = true
regex.workspace = true regex.workspace = true
clap = { version = "4.0", features = ["derive"] } clap = { version = "4.0", features = ["derive"] }
nix = "0.26.1"

View File

@ -1,12 +1,11 @@
use std::{ use std::{
fs, io, fs, io,
path::{self, PathBuf}, path::{self, Path, PathBuf},
process::Command, process::Command,
}; };
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use clap::{Args, Parser, Subcommand, ValueEnum}; use clap::{Args, Parser, Subcommand, ValueEnum};
use nix::mount::{MsFlags, mount, umount};
use proxmox_installer_common::{ use proxmox_installer_common::{
RUNTIME_DIR, RUNTIME_DIR,
options::FsType, options::FsType,
@ -118,9 +117,7 @@ fn cleanup(args: &CommandCleanup) -> Result<()> {
match fs { match fs {
Filesystems::Zfs => umount_zpool(), Filesystems::Zfs => umount_zpool(),
Filesystems::Xfs => umount_fs()?, Filesystems::Btrfs | Filesystems::Xfs | Filesystems::Ext4 => umount(Path::new(TARGET_DIR))?,
Filesystems::Ext4 => umount_fs()?,
_ => (),
} }
println!("Chroot cleanup done. You can now reboot or leave the shell."); println!("Chroot cleanup done. You can now reboot or leave the shell.");
@ -213,7 +210,7 @@ fn mount_fs() -> Result<()> {
match Command::new("mount") match Command::new("mount")
.arg(format!("/dev/mapper/{product}-root")) .arg(format!("/dev/mapper/{product}-root"))
.arg("/target") .arg(TARGET_DIR)
.output() .output()
{ {
Err(e) => bail!("{e}"), Err(e) => bail!("{e}"),
@ -232,9 +229,25 @@ fn mount_fs() -> Result<()> {
Ok(()) Ok(())
} }
fn umount_fs() -> Result<()> { fn umount(path: &Path) -> Result<()> {
umount(TARGET_DIR)?; match Command::new("umount")
.arg("--recursive")
.arg("--verbose")
.arg(path)
.output()
{
Ok(output) => {
if output.status.success() {
Ok(()) Ok(())
} else {
bail!(
"unmounting of {path:?} failed: {}",
String::from_utf8(output.stderr)?
)
}
}
Err(err) => bail!("unmounting of {path:?} failed: {:#}", err),
}
} }
fn mount_btrfs(btrfs_uuid: Option<String>) -> Result<()> { fn mount_btrfs(btrfs_uuid: Option<String>) -> Result<()> {
@ -246,7 +259,7 @@ fn mount_btrfs(btrfs_uuid: Option<String>) -> Result<()> {
match Command::new("mount") match Command::new("mount")
.arg("--uuid") .arg("--uuid")
.arg(uuid) .arg(uuid)
.arg("/target") .arg(TARGET_DIR)
.output() .output()
{ {
Err(e) => bail!("{e}"), Err(e) => bail!("{e}"),
@ -303,36 +316,48 @@ fn get_btrfs_uuid() -> Result<String> {
Ok(uuids[0].into()) Ok(uuids[0].into())
} }
fn bindmount() -> Result<()> { fn do_bindmount(source: &Path, target: &Path) -> Result<()> {
println!("Bind mounting"); match Command::new("mount")
// https://github.com/nix-rust/nix/blob/7badbee1e388618457ed0d725c1091359f253012/test/test_mount.rs#L19 .arg("--bind")
// https://github.com/nix-rust/nix/blob/7badbee1e388618457ed0d725c1091359f253012/test/test_mount.rs#L146 .arg(source)
const NONE: Option<&'static [u8]> = None; .arg(target)
.output()
{
Ok(output) => {
if output.status.success() {
Ok(())
} else {
bail!(
"bind-mount of {source:?} to {target:?} failed: {}",
String::from_utf8(output.stderr)?
)
}
}
Err(err) => bail!("bind-mount of {source:?} to {target:?} failed: {:#}", err),
}
}
fn bindmount() -> Result<()> {
println!("Bind-mounting virtual filesystems");
let flags = MsFlags::MS_BIND;
for item in BINDMOUNTS { for item in BINDMOUNTS {
let source = path::Path::new("/").join(item); let source = path::Path::new("/").join(item);
let target = path::Path::new(TARGET_DIR).join(item); let target = path::Path::new(TARGET_DIR).join(item);
println!("Bindmount {source:?} to {target:?}"); println!("Bind-mounting {source:?} to {target:?}");
mount(Some(source.as_path()), target.as_path(), NONE, flags, NONE)?; do_bindmount(&source, &target)?;
} }
let answer_path = path::Path::new("/mnt").join(ANSWER_MP); let answer_path = path::Path::new("/mnt").join(ANSWER_MP);
if answer_path.exists() { if answer_path.exists() {
let target = path::Path::new(TARGET_DIR).join("mnt").join(ANSWER_MP); let target = path::Path::new(TARGET_DIR).join("mnt").join(ANSWER_MP);
println!("Create dir {target:?}"); println!("Creating target directory {target:?}");
fs::create_dir_all(&target)?; fs::create_dir_all(&target)?;
println!("Bindmount {answer_path:?} to {target:?}"); println!("Bind-mounting {answer_path:?} to {target:?}");
mount( do_bindmount(&answer_path, &target)?;
Some(answer_path.as_path()),
target.as_path(),
NONE,
flags,
NONE,
)?;
} }
Ok(()) Ok(())
} }
@ -349,7 +374,7 @@ fn bind_umount() -> Result<()> {
let answer_target = path::Path::new(TARGET_DIR).join("mnt").join(ANSWER_MP); let answer_target = path::Path::new(TARGET_DIR).join("mnt").join(ANSWER_MP);
if answer_target.exists() { if answer_target.exists() {
println!("Unmounting and removing answer mountpoint"); println!("Unmounting and removing answer mountpoint");
if let Err(e) = umount(answer_target.as_os_str()) { if let Err(e) = umount(&answer_target) {
eprintln!("{e}"); eprintln!("{e}");
} }
if let Err(e) = fs::remove_dir(answer_target) { if let Err(e) = fs::remove_dir(answer_target) {