1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
use nix::sched; use nix::unistd; use std::collections::HashSet; use std::fs::{self, File}; use std::os::unix::prelude::*; use std::path::PathBuf; use types::{Error, Result}; pub const MOUNT: Kind = Kind { name: "mnt" }; pub const UTS: Kind = Kind { name: "uts" }; pub const USER: Kind = Kind { name: "user" }; pub const PID: Kind = Kind { name: "pid" }; pub const NET: Kind = Kind { name: "net" }; pub const CGROUP: Kind = Kind { name: "cgroup" }; pub const IPC: Kind = Kind { name: "ipc" }; pub static ALL: &'static [Kind] = &[UTS, CGROUP, PID, NET, IPC, MOUNT, USER]; pub struct Kind { pub name: &'static str, } pub fn supported_namespaces() -> Result<HashSet<String>> { let mut namespaces = HashSet::new(); let entries = tryfmt!( fs::read_dir(PathBuf::from("/proc/self/ns")), "failed to open directory /proc/self/ns" ); for entry in entries { let entry = tryfmt!(entry, "failed to read directory /proc/self/ns"); if let Ok(name) = entry.file_name().into_string() { namespaces.insert(name); } } Ok(namespaces) } impl Kind { pub fn open(&'static self, pid: unistd::Pid) -> Result<Namespace> { let buf = self.path(pid); let path = buf.to_str().unwrap(); let file = tryfmt!(File::open(path), "failed to open namespace file '{}'", path); Ok(Namespace { kind: self, file }) } pub fn namespace_from_file(&'static self, file: File) -> Namespace { Namespace { kind: self, file } } pub fn is_same(&self, pid: unistd::Pid) -> bool { let path = self.path(pid); let path2 = self.path(unistd::getpid()); match fs::read_link(path) { Ok(dest) => { match fs::read_link(path2) { Ok(dest2) => dest == dest2, _ => false, } } _ => false, } } fn path(&self, pid: unistd::Pid) -> PathBuf { let mut buf = PathBuf::from("/proc/"); buf.push(pid.to_string()); buf.push("ns"); buf.push(self.name); buf } } pub struct Namespace { pub kind: &'static Kind, file: File, } impl Namespace { pub fn apply(&self) -> Result<()> { tryfmt!( sched::setns(self.file.as_raw_fd(), sched::CloneFlags::empty()), "setns" ); Ok(()) } pub fn file(&self) -> &File { &self.file } }