namespaces/
advanced.rs

1use super::basic;
2use anyhow::anyhow;
3use ipc_channel::ipc;
4use libc;
5use nix::unistd;
6use serde::{Deserialize, Serialize};
7pub fn setns_spawn<F, T>(n: basic::Namespace, f: F) -> anyhow::Result<T>
8where
9    F: FnOnce() -> T,
10    F: Send + 'static,
11    T: Send + for<'de> Deserialize<'de> + Serialize + 'static + std::fmt::Debug,
12{
13    let (tx, rx) = ipc::channel().unwrap();
14    match unistd::fork() {
15        Ok(unistd::ForkResult::Parent { child, .. }) => {
16            let res = match rx.recv() {
17                Ok(res) => res,
18                Err(e) => return Err(anyhow!("{:?}", e)),
19            };
20            return Ok(res);
21        }
22        Ok(unistd::ForkResult::Child) => unsafe {
23            if libc::setns(n.get_fd().unwrap(), 0) == -1 {
24                println!("{:?}", std::io::Error::last_os_error());
25            }
26            tx.send(f());
27            libc::exit(0)
28        },
29        Err(e) => Err(anyhow!("{}", e)),
30    }
31}
32pub fn setns_spawn_all<F, T>(
33    ns: basic::Namespaces,
34    f: F,
35) -> anyhow::Result<std::collections::HashMap<String, T>>
36where
37    F: Fn() -> T,
38    F: Send + 'static,
39    T: Send + for<'de> Deserialize<'de> + Serialize + 'static + std::fmt::Debug,
40{
41    let (tx, rx) = ipc::channel().unwrap();
42    match unistd::fork() {
43        Ok(unistd::ForkResult::Parent { child, .. }) => {
44            let res = match rx.recv() {
45                Ok(res) => res,
46                Err(e) => return Err(anyhow!("{:?}", e)),
47            };
48            return Ok(res);
49        }
50        Ok(unistd::ForkResult::Child) => unsafe {
51            let mut res = std::collections::HashMap::new();
52            let ori_fd = ns.get("origin").unwrap().get_fd().unwrap();
53            for (k, v) in ns {
54                let fd = match v.get_fd() {
55                    Some(fd) => fd,
56                    None => continue,
57                };
58                if libc::setns(fd, 0) == -1 {
59                    println!("{:?}", std::io::Error::last_os_error());
60                }
61                res.insert(k, f());
62                if libc::close(fd) == -1 {
63                    println!("{:?}", std::io::Error::last_os_error());
64                };
65                if libc::setns(ori_fd, 0) == -1 {
66                    println!("{:?}", std::io::Error::last_os_error());
67                };
68            }
69            tx.send(res);
70            libc::close(ori_fd);
71            libc::exit(0)
72        },
73        Err(e) => Err(anyhow!("{}", e)),
74    }
75}