use libc::{mount, umount, MS_BIND, MS_PRIVATE};
use std::ffi::CString;
use tracing::*;
#[derive(Debug)]
pub struct Mount {
target: Option<CString>,
}
pub fn make_root_private() -> Result<(), std::io::Error> {
unsafe {
let err = mount(
std::ptr::null(),
b"/\0".as_ptr() as *const i8,
std::ptr::null(),
MS_PRIVATE,
std::ptr::null(),
);
if err == 0 {
Ok(())
} else {
Err(std::io::Error::last_os_error())
}
}
}
impl Mount {
pub fn bind<S: AsRef<std::path::Path>, T: AsRef<std::path::Path>>(
source: S,
target: T,
) -> Result<Mount, std::io::Error> {
let target = target.as_ref().to_str().unwrap();
let target = CString::new(target).unwrap();
let source = source.as_ref().to_str().unwrap();
let source = CString::new(source).unwrap();
unsafe {
let err = mount(
source.as_ptr(),
target.as_ptr(),
std::ptr::null(),
MS_BIND,
std::ptr::null(),
);
if err == 0 {
return Ok(Mount {
target: Some(target),
});
}
Err(std::io::Error::last_os_error())
}
}
pub fn ramfs<T: AsRef<std::path::Path>>(target: T) -> Result<Mount, std::io::Error> {
let target = target.as_ref().to_str().unwrap();
let target = CString::new(target).unwrap();
unsafe {
let err = mount(
b"ramfs\0".as_ptr() as *const i8,
target.as_ptr(),
b"ramfs\0".as_ptr() as *const i8,
0,
std::ptr::null(),
);
if err == 0 {
Ok(Mount {
target: Some(target),
})
} else {
Err(std::io::Error::last_os_error())
}
}
}
}
impl Drop for Mount {
fn drop(&mut self) {
if let Some(target) = self.target.take() {
unsafe {
trace!("umount");
let r = umount(target.as_ptr());
trace!(
"umount done {:?} {:?} {:?}",
target,
r,
std::io::Error::last_os_error()
);
}
}
}
}