diff --git a/src/process/mod.rs b/src/process/mod.rs index ea186cf7..bfb1854c 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -76,6 +76,9 @@ pub use stat::*; mod mount; pub use mount::*; +mod namespaces; +pub use namespaces::*; + mod status; pub use status::*; diff --git a/src/process/namespaces.rs b/src/process/namespaces.rs new file mode 100644 index 00000000..59244fda --- /dev/null +++ b/src/process/namespaces.rs @@ -0,0 +1,75 @@ +use std::{ + ffi::{CString, OsString}, + fs::{self}, + os::unix::prelude::OsStrExt, + path::PathBuf, +}; + +use crate::ProcResult; + +use super::Process; + +impl Process { + /// Describes namespaces to which the process with the corresponding PID belongs. + /// Doc reference: https://man7.org/linux/man-pages/man7/namespaces.7.html + pub fn namespaces(&self) -> ProcResult> { + let ns = self.root.join("ns"); + let mut namespaces = Vec::new(); + for entry in fs::read_dir(ns)? { + let entry = entry?; + let path = entry.path(); + let ns_type = entry.file_name(); + let cstr = CString::new(path.as_os_str().as_bytes()).unwrap(); + + let mut stat = unsafe { std::mem::zeroed() }; + if unsafe { libc::stat(cstr.as_ptr(), &mut stat) } != 0 { + return Err(build_internal_error!(format!("Unable to stat {:?}", path))); + } + + namespaces.push(Namespace { + ns_type, + path, + identifier: stat.st_ino, + device_id: stat.st_dev, + }) + } + + Ok(namespaces) + } +} + +/// Information about a namespace +/// +/// See also the [Process::namespaces()] method +#[derive(Debug, Clone)] +pub struct Namespace { + /// Namespace type + pub ns_type: OsString, + /// Handle to the namespace + pub path: PathBuf, + /// Namespace identifier (inode number) + pub identifier: u64, + /// Device id of the namespace + pub device_id: u64, +} + +impl PartialEq for Namespace { + fn eq(&self, other: &Self) -> bool { + // see https://lore.kernel.org/lkml/87poky5ca9.fsf@xmission.com/ + self.identifier == other.identifier && self.device_id == other.device_id + } +} + +impl Eq for Namespace {} + +#[cfg(test)] +mod tests { + use crate::process::Process; + + #[test] + fn test_namespaces() { + let myself = Process::myself().unwrap(); + let namespaces = myself.namespaces().unwrap(); + print!("{:?}", namespaces); + } +} diff --git a/support.md b/support.md index 4337ebde..32fcfa4a 100644 --- a/support.md +++ b/support.md @@ -32,7 +32,7 @@ This is an approximate list of all the files under the `/proc` mount, and an ind * [x] `/proc/[pid]/mountinfo` * [ ] `/proc/[pid]/mounts` * [x] `/proc/[pid]/mountstats` - * [ ] `/proc/[pid]/ns/` + * [x] `/proc/[pid]/ns/` * [ ] `/proc/[pid]/numa_maps` * [ ] `/proc/[pid]/oom_adj` * [x] `/proc/[pid]/oom_score`