2024-02-27 22:27:52 +08:00
|
|
|
use std::{
|
|
|
|
collections::BTreeSet,
|
|
|
|
ops::Bound::{Excluded, Unbounded},
|
|
|
|
pin::Pin,
|
|
|
|
ptr::null as nullptr,
|
2024-02-27 03:14:26 -08:00
|
|
|
};
|
|
|
|
|
2024-02-27 18:14:30 -08:00
|
|
|
use cxx::CxxString;
|
2024-02-27 22:27:52 +08:00
|
|
|
|
2024-02-27 18:14:30 -08:00
|
|
|
use base::{
|
|
|
|
cstr, debug,
|
|
|
|
libc::{chdir, chroot, mount, MS_MOVE},
|
|
|
|
parse_mount_info, raw_cstr, Directory, LibcReturn, LoggedResult, StringExt, Utf8CStr,
|
|
|
|
};
|
2024-02-27 22:27:52 +08:00
|
|
|
|
2024-02-27 03:14:26 -08:00
|
|
|
pub fn switch_root(path: &Utf8CStr) {
|
2025-02-01 22:27:36 +08:00
|
|
|
let res: LoggedResult<()> = try {
|
2024-02-27 22:27:52 +08:00
|
|
|
debug!("Switch root to {}", path);
|
|
|
|
let mut mounts = BTreeSet::new();
|
2024-02-27 03:14:26 -08:00
|
|
|
let mut rootfs = Directory::open(cstr!("/"))?;
|
2024-02-27 22:27:52 +08:00
|
|
|
for info in parse_mount_info("self") {
|
|
|
|
if info.target == "/" || info.target.as_str() == path.as_str() {
|
2024-02-27 03:14:26 -08:00
|
|
|
continue;
|
|
|
|
}
|
2024-02-27 22:27:52 +08:00
|
|
|
if let Some(last_mount) = mounts
|
|
|
|
.range::<String, _>((Unbounded, Excluded(&info.target)))
|
|
|
|
.last()
|
|
|
|
{
|
|
|
|
if info.target.starts_with(&format!("{}/", *last_mount)) {
|
2024-02-27 03:14:26 -08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2024-02-27 22:27:52 +08:00
|
|
|
let mut new_path = format!("{}/{}", path.as_str(), &info.target);
|
|
|
|
std::fs::create_dir(&new_path).ok();
|
|
|
|
|
2024-02-27 03:14:26 -08:00
|
|
|
unsafe {
|
2024-02-27 22:27:52 +08:00
|
|
|
let mut target = info.target.clone();
|
|
|
|
mount(
|
2024-02-27 03:14:26 -08:00
|
|
|
target.nul_terminate().as_ptr().cast(),
|
|
|
|
new_path.nul_terminate().as_ptr().cast(),
|
2024-02-27 22:27:52 +08:00
|
|
|
nullptr(),
|
|
|
|
MS_MOVE,
|
|
|
|
nullptr(),
|
2024-02-27 03:14:26 -08:00
|
|
|
)
|
|
|
|
.as_os_err()?;
|
|
|
|
}
|
|
|
|
|
2024-02-27 22:27:52 +08:00
|
|
|
mounts.insert(info.target);
|
2024-02-27 03:14:26 -08:00
|
|
|
}
|
|
|
|
unsafe {
|
2024-02-27 22:27:52 +08:00
|
|
|
chdir(path.as_ptr()).as_os_err()?;
|
|
|
|
mount(path.as_ptr(), raw_cstr!("/"), nullptr(), MS_MOVE, nullptr()).as_os_err()?;
|
|
|
|
chroot(raw_cstr!("."));
|
2024-02-27 03:14:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
debug!("Cleaning rootfs");
|
|
|
|
rootfs.remove_all()?;
|
2025-02-01 22:27:36 +08:00
|
|
|
};
|
|
|
|
res.ok();
|
2024-02-27 03:14:26 -08:00
|
|
|
}
|
|
|
|
|
2024-02-27 22:27:52 +08:00
|
|
|
pub fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool {
|
|
|
|
for mount in parse_mount_info("self") {
|
|
|
|
if mount.root == "/" && mount.device == dev {
|
|
|
|
target.push_str(&mount.target);
|
|
|
|
return true;
|
2024-02-27 03:14:26 -08:00
|
|
|
}
|
|
|
|
}
|
2024-02-27 22:27:52 +08:00
|
|
|
false
|
2024-02-27 03:14:26 -08:00
|
|
|
}
|