namespaces-rs 0.1.1

A wrapper of linux namespaces.
Documentation
use super::basic;
use anyhow::anyhow;
use ipc_channel::ipc;
use libc;
use nix::unistd;
use serde::{Deserialize, Serialize};
pub fn setns_spawn<F, T>(n: basic::Namespace, f: F) -> anyhow::Result<T>
where
    F: FnOnce() -> T,
    F: Send + 'static,
    T: Send + for<'de> Deserialize<'de> + Serialize + 'static + std::fmt::Debug,
{
    let (tx, rx) = ipc::channel().unwrap();
    match unistd::fork() {
        Ok(unistd::ForkResult::Parent { child, .. }) => {
            let res = match rx.recv() {
                Ok(res) => res,
                Err(e) => return Err(anyhow!("{:?}", e)),
            };
            return Ok(res);
        }
        Ok(unistd::ForkResult::Child) => unsafe {
            if libc::setns(n.get_fd().unwrap(), 0) == -1 {
                println!("{:?}", std::io::Error::last_os_error());
            }
            tx.send(f());
            libc::exit(0)
        },
        Err(e) => Err(anyhow!("{}", e)),
    }
}
pub fn setns_spawn_all<F, T>(
    ns: basic::Namespaces,
    f: F,
) -> anyhow::Result<std::collections::HashMap<String, T>>
where
    F: Fn() -> T,
    F: Send + 'static,
    T: Send + for<'de> Deserialize<'de> + Serialize + 'static + std::fmt::Debug,
{
    let (tx, rx) = ipc::channel().unwrap();
    match unistd::fork() {
        Ok(unistd::ForkResult::Parent { child, .. }) => {
            let res = match rx.recv() {
                Ok(res) => res,
                Err(e) => return Err(anyhow!("{:?}", e)),
            };
            return Ok(res);
        }
        Ok(unistd::ForkResult::Child) => unsafe {
            let mut res = std::collections::HashMap::new();
            let ori_fd = ns.get("origin").unwrap().get_fd().unwrap();
            for (k, v) in ns {
                let fd = match v.get_fd() {
                    Some(fd) => fd,
                    None => continue,
                };
                if libc::setns(fd, 0) == -1 {
                    println!("{:?}", std::io::Error::last_os_error());
                }
                res.insert(k, f());
                if libc::close(fd) == -1 {
                    println!("{:?}", std::io::Error::last_os_error());
                };
                if libc::setns(ori_fd, 0) == -1 {
                    println!("{:?}", std::io::Error::last_os_error());
                };
            }
            tx.send(res);
            libc::close(ori_fd);
            libc::exit(0)
        },
        Err(e) => Err(anyhow!("{}", e)),
    }
}