use std::ffi::CStr;
use std::io;
use std::marker::PhantomData;
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use std::os::raw::c_int;
use crate::mount::ns::MountNsInfo;
use crate::open::OpenHow;
pub trait Kind {
const PROCFS_NAME: &'static CStr;
const PROCFS_PATH: &'static CStr;
const TYPE: c_int;
}
macro_rules! define_namespace {
($(
$(#[$doc:meta])+
($name:ident, $const:expr, $file:expr, $path:expr)
),+ $(,)?) => {
$(
$(#[$doc])+
pub struct $name;
impl Kind for $name {
const PROCFS_NAME: &'static ::std::ffi::CStr = $file;
const PROCFS_PATH: &'static ::std::ffi::CStr = $path;
const TYPE: ::std::os::raw::c_int = $const;
}
)+
};
}
pub const CLONE_NEWTIME: c_int = 0x80;
define_namespace! {
(CGroup, libc::CLONE_NEWCGROUP, c"cgroup", c"/proc/self/ns/cgroup"),
(Ipc, libc::CLONE_NEWIPC, c"ipc", c"/proc/self/ns/ipc"),
(Mnt, libc::CLONE_NEWNS, c"mnt", c"/proc/self/ns/mnt"),
(Net, libc::CLONE_NEWNET, c"net", c"/proc/self/ns/net"),
(Pid, libc::CLONE_NEWPID, c"pid", c"/proc/self/ns/pid"),
(Time, libc::CLONE_NEWTIME, c"time", c"/proc/self/ns/time"),
(User, libc::CLONE_NEWUSER, c"user", c"/proc/self/ns/user"),
(Uts, libc::CLONE_NEWUTS, c"uts", c"/proc/self/ns/uts"),
}
pub trait UnshareDirect {}
pub trait UnshareForChildren {}
impl UnshareDirect for CGroup {}
impl UnshareDirect for Ipc {}
impl UnshareDirect for Mnt {}
impl UnshareDirect for Net {}
impl UnshareDirect for User {}
impl UnshareDirect for Uts {}
impl UnshareForChildren for Time {}
impl UnshareForChildren for Pid {}
pub struct NsFd<K: Kind> {
fd: OwnedFd,
_kind: PhantomData<K>,
}
impl<K: Kind> AsRawFd for NsFd<K> {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
impl<K: Kind> AsFd for NsFd<K> {
fn as_fd(&self) -> BorrowedFd<'_> {
self.fd.as_fd()
}
}
impl<K: Kind> IntoRawFd for NsFd<K> {
fn into_raw_fd(self) -> RawFd {
self.fd.into_raw_fd()
}
}
impl<K: Kind> FromRawFd for NsFd<K> {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self {
fd: unsafe { OwnedFd::from_raw_fd(fd) },
_kind: PhantomData,
}
}
}
impl<K: Kind> NsFd<K> {
pub fn current() -> io::Result<Self> {
Ok(Self {
fd: OpenHow::new_read().open(K::PROCFS_PATH)?,
_kind: PhantomData,
})
}
}
impl NsFd<Mnt> {
pub fn mount_info(&self) -> io::Result<MountNsInfo> {
MountNsInfo::get_raw(self.as_raw_fd())
}
pub fn next_mount_info(&self) -> io::Result<(MountNsInfo, Self)> {
MountNsInfo::next_raw(self.as_raw_fd())
}
pub fn previous_mount_info(&self) -> io::Result<(MountNsInfo, Self)> {
MountNsInfo::previous_raw(self.as_raw_fd())
}
}