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}