@@ -218,15 +218,19 @@ impl TryFrom<&str> for CgroupMembership {
218218 }
219219}
220220
221- // See https://www.man7.org/linux/man-pages/man7/namespaces.7.html
221+ /// See https://www.man7.org/linux/man-pages/man7/namespaces.7.html
222+ ///
223+ /// # Support status
224+ ///
225+ /// **_Linux only._**
222226#[ derive( Default ) ]
223227pub struct Namespace {
224- pub ipc : Option < String > ,
225- pub mnt : Option < String > ,
226- pub net : Option < String > ,
227- pub pid : Option < String > ,
228- pub user : Option < String > ,
229- pub uts : Option < String > ,
228+ pub ipc : Option < u64 > ,
229+ pub mnt : Option < u64 > ,
230+ pub net : Option < u64 > ,
231+ pub pid : Option < u64 > ,
232+ pub user : Option < u64 > ,
233+ pub uts : Option < u64 > ,
230234}
231235
232236impl Namespace {
@@ -241,28 +245,51 @@ impl Namespace {
241245 }
242246 }
243247
244- pub fn from_pid ( pid : usize ) -> Result < Self , io:: Error > {
245- let mut ns = Namespace :: new ( ) ;
246- let path = PathBuf :: from ( format ! ( "/proc/{pid}/ns" ) ) ;
247- for entry in fs:: read_dir ( path) ? {
248- let entry = entry?;
249- if let Some ( name) = entry. file_name ( ) . to_str ( ) {
250- if let Ok ( value) = read_link ( entry. path ( ) ) {
251- match name {
252- "ipc" => ns. ipc = Some ( value. to_str ( ) . unwrap_or_default ( ) . to_string ( ) ) ,
253- "mnt" => ns. mnt = Some ( value. to_str ( ) . unwrap_or_default ( ) . to_string ( ) ) ,
254- "net" => ns. net = Some ( value. to_str ( ) . unwrap_or_default ( ) . to_string ( ) ) ,
255- "pid" => ns. pid = Some ( value. to_str ( ) . unwrap_or_default ( ) . to_string ( ) ) ,
256- "user" => ns. user = Some ( value. to_str ( ) . unwrap_or_default ( ) . to_string ( ) ) ,
257- "uts" => ns. uts = Some ( value. to_str ( ) . unwrap_or_default ( ) . to_string ( ) ) ,
258- _ => { }
259- }
260- }
248+ #[ cfg( target_os = "linux" ) ]
249+ pub fn from_pid ( pid : usize ) -> io:: Result < Self > {
250+ use std:: os:: fd:: OwnedFd ;
251+
252+ use rustix:: fs:: { openat, statx, AtFlags , Mode , OFlags , StatxFlags , CWD } ;
253+
254+ let f = |name : & str , fd : & OwnedFd | {
255+ statx (
256+ fd,
257+ name,
258+ AtFlags :: empty ( ) , // NO FOLLOW LINKS
259+ StatxFlags :: INO , // INNODE ONLY
260+ )
261+ } ;
262+
263+ let ns_dir = openat (
264+ CWD ,
265+ PathBuf :: from ( format ! ( "/proc/{}/ns" , pid) ) ,
266+ OFlags :: RDONLY | OFlags :: CLOEXEC ,
267+ Mode :: empty ( ) ,
268+ ) ?;
269+ let mut ns = Namespace :: default ( ) ;
270+
271+ for ( name, slot) in [
272+ ( "ipc" , & mut ns. ipc ) ,
273+ ( "mnt" , & mut ns. mnt ) ,
274+ ( "net" , & mut ns. net ) ,
275+ ( "pid" , & mut ns. pid ) ,
276+ ( "user" , & mut ns. user ) ,
277+ ( "uts" , & mut ns. uts ) ,
278+ ] {
279+ match f ( name, & ns_dir) {
280+ Ok ( st) => * slot = Some ( st. stx_ino ) ,
281+ Err ( e) => return Err ( e. into ( ) ) ,
261282 }
262283 }
263284 Ok ( ns)
264285 }
265286
287+ /// TODO: implementation for other system
288+ #[ cfg( not( target_os = "linux" ) ) ]
289+ pub fn from_pid ( _pid : usize ) -> Result < Self , io:: Error > {
290+ Ok ( Namespace :: new ( ) )
291+ }
292+
266293 pub fn filter ( & mut self , filters : & [ & str ] ) {
267294 if !filters. contains ( & "ipc" ) {
268295 self . ipc = None ;
0 commit comments