namespaces/
basic.rs

1use anyhow;
2use regex;
3#[derive(Debug, Clone)]
4pub enum NsType {
5    CGROUP,
6    PID,
7    USER,
8    UTS,
9    IPC,
10    MNT,
11    NET,
12    UNK,
13}
14#[derive(Debug, Clone)]
15pub struct Namespace {
16    genre: NsType,
17    procs: Vec<String>,
18}
19impl Namespace {
20    pub fn new(genre: String, proc: String) -> Self {
21        let genre = match genre.as_str() {
22            "cgroup" => NsType::CGROUP,
23            "pid" => NsType::PID,
24            "user" => NsType::USER,
25            "uts" => NsType::UTS,
26            "ipc" => NsType::IPC,
27            "mnt" => NsType::MNT,
28            "net" => NsType::NET,
29            _ => NsType::UNK,
30        };
31        let procs: Vec<String> = vec![proc];
32        Namespace { genre, procs }
33    }
34    pub fn get_fd(&self) -> Option<i32> {
35        for i in &self.procs {
36            unsafe {
37                let fd = libc::open(
38                    std::ffi::CString::new(i.as_str()).unwrap().as_ptr() as *const libc::c_char,
39                    libc::O_RDONLY,
40                );
41                if fd != -1 {
42                    return Some(fd);
43                }
44            }
45        }
46        None
47    }
48}
49pub type Namespaces = std::collections::HashMap<String, Namespace>;
50
51pub fn get_namespaces() -> anyhow::Result<Namespaces> {
52    let usize_pattern = regex::Regex::new(r"[1-9]\d*").unwrap();
53    let mut namespaces = Namespaces::new();
54    for proc_dir in std::fs::read_dir("/proc")?.filter_map(|f| match f {
55        Ok(f) => match f.file_name().to_str().unwrap_or_default().parse::<u64>() {
56            Ok(_) => Some(f),
57            Err(_) => None,
58        },
59        Err(_) => None,
60    }) {
61        let ns_dir = match std::fs::read_dir(proc_dir.path().to_str().unwrap().to_string() + "/ns")
62        {
63            Ok(dir) => dir,
64            Err(_) => continue,
65        };
66        for ns_file in ns_dir.filter_map(|f| match f {
67            Ok(f) => Some(f),
68            Err(_) => None,
69        }) {
70            let index = match std::fs::read_link(ns_file.path()) {
71                Ok(link) => usize_pattern
72                    .find(link.to_str().unwrap_or_default())
73                    .unwrap()
74                    .as_str()
75                    .to_owned(),
76                Err(_) => continue,
77            };
78            if namespaces.contains_key(&index) {
79                namespaces
80                    .get_mut(&index)
81                    .unwrap()
82                    .procs
83                    .push(ns_file.path().to_str().unwrap_or_default().to_string());
84            } else {
85                namespaces.insert(
86                    index,
87                    Namespace::new(
88                        ns_file.file_name().to_str().unwrap_or_default().to_string(),
89                        ns_file.path().to_str().unwrap_or_default().to_string(),
90                    ),
91                );
92            }
93        }
94    }
95    Ok(namespaces)
96}
97
98pub fn get_specific_namespaces(genre: NsType) -> anyhow::Result<Namespaces> {
99    let usize_pattern = regex::Regex::new(r"[1-9]\d*").unwrap();
100    let mut namespaces = Namespaces::new();
101    let ns_type = format!("{:?}", genre).to_lowercase();
102    for proc_dir in std::fs::read_dir("/proc")?.filter_map(|f| match f {
103        Ok(f) => match f.file_name().to_str().unwrap_or_default().parse::<u64>() {
104            Ok(_) => Some(f),
105            Err(_) => None,
106        },
107        Err(_) => None,
108    }) {
109        let index;
110        if proc_dir.file_name().to_str().unwrap() == "1" {
111            index = "origin".to_owned()
112        } else {
113            index = match std::fs::read_link(
114                proc_dir.path().to_str().unwrap().to_string() + "/ns/" + ns_type.as_str(),
115            ) {
116                Ok(link) => usize_pattern
117                    .find(link.to_str().unwrap_or_default())
118                    .unwrap()
119                    .as_str()
120                    .to_owned(),
121                Err(_) => continue,
122            };
123        }
124        if namespaces.contains_key(&index) {
125            namespaces
126                .get_mut(&index)
127                .unwrap()
128                .procs
129                .push(proc_dir.path().to_str().unwrap().to_string() + "/ns/" + ns_type.as_str());
130        } else {
131            namespaces.insert(
132                index,
133                Namespace::new(
134                    ns_type.clone(),
135                    proc_dir.path().to_str().unwrap().to_string() + "/ns/" + ns_type.as_str(),
136                ),
137            );
138        }
139    }
140    Ok(namespaces)
141}
142#[cfg(test)]
143mod tests {
144    use super::*;
145    #[test]
146    fn get_namespaces_test() {
147        println!("{:?}", get_namespaces().unwrap());
148    }
149    #[test]
150    fn get_specific_namespaces_test() {
151        println!("{:?}", get_specific_namespaces(NsType::MNT).unwrap());
152    }
153}