44// file that was distributed with this source code.
55
66use regex:: Regex ;
7+ use std:: fs:: read_link;
78use std:: hash:: Hash ;
89use std:: sync:: LazyLock ;
910use std:: {
@@ -250,6 +251,17 @@ impl ProcessInformation {
250251 } )
251252 }
252253
254+ pub fn current_process_info ( ) -> Result < ProcessInformation , io:: Error > {
255+ use std:: str:: FromStr ;
256+
257+ #[ cfg( target_os = "linux" ) ]
258+ let pid = uucore:: process:: getpid ( ) ;
259+ #[ cfg( not( target_os = "linux" ) ) ]
260+ let pid = 0 ; // dummy
261+
262+ ProcessInformation :: try_new ( PathBuf :: from_str ( & format ! ( "/proc/{}" , pid) ) . unwrap ( ) )
263+ }
264+
253265 pub fn proc_status ( & self ) -> & str {
254266 & self . inner_status
255267 }
@@ -366,6 +378,11 @@ impl ProcessInformation {
366378 self . get_uid_or_gid_field ( "Gid" , 1 )
367379 }
368380
381+ // Root directory of the process (which can be changed by chroot)
382+ pub fn root ( & mut self ) -> Result < PathBuf , io:: Error > {
383+ read_link ( format ! ( "/proc/{}/root" , self . pid) )
384+ }
385+
369386 /// Fetch run state from [ProcessInformation::cached_stat]
370387 ///
371388 /// - [The /proc Filesystem: Table 1-4](https://docs.kernel.org/filesystems/proc.html#id10)
@@ -495,7 +512,9 @@ pub fn walk_threads() -> impl Iterator<Item = ProcessInformation> {
495512mod tests {
496513 use super :: * ;
497514 #[ cfg( target_os = "linux" ) ]
498- use std:: { collections:: HashSet , str:: FromStr } ;
515+ use std:: collections:: HashSet ;
516+ #[ cfg( target_os = "linux" ) ]
517+ use uucore:: process:: getpid;
499518
500519 #[ test]
501520 fn test_run_state_conversion ( ) {
@@ -515,41 +534,19 @@ mod tests {
515534 assert ! ( RunState :: try_from( "Rg" ) . is_err( ) ) ;
516535 }
517536
518- #[ cfg( target_os = "linux" ) ]
519- fn current_pid ( ) -> usize {
520- // Direct read link of /proc/self.
521- // It's result must be current programs pid.
522- fs:: read_link ( "/proc/self" )
523- . unwrap ( )
524- . to_str ( )
525- . unwrap ( )
526- . parse :: < usize > ( )
527- . unwrap ( )
528- }
529-
530- #[ cfg( target_os = "linux" ) ]
531- fn current_process_info ( ) -> ProcessInformation {
532- ProcessInformation :: try_new ( PathBuf :: from_str ( & format ! ( "/proc/{}" , current_pid( ) ) ) . unwrap ( ) )
533- . unwrap ( )
534- }
535-
536537 #[ test]
537538 #[ cfg( target_os = "linux" ) ]
538539 fn test_walk_pid ( ) {
539- let current_pid = current_pid ( ) ;
540-
541- let find = walk_process ( ) . find ( |it| it. pid == current_pid) ;
540+ let find = walk_process ( ) . find ( |it| it. pid == getpid ( ) as usize ) ;
542541
543542 assert ! ( find. is_some( ) ) ;
544543 }
545544
546545 #[ test]
547546 #[ cfg( target_os = "linux" ) ]
548547 fn test_pid_entry ( ) {
549- let current_pid = current_pid ( ) ;
550-
551- let pid_entry = current_process_info ( ) ;
552- let mut result = WalkDir :: new ( format ! ( "/proc/{}/fd" , current_pid) )
548+ let pid_entry = ProcessInformation :: current_process_info ( ) . unwrap ( ) ;
549+ let mut result = WalkDir :: new ( format ! ( "/proc/{}/fd" , getpid( ) ) )
553550 . into_iter ( )
554551 . flatten ( )
555552 . map ( DirEntry :: into_path)
@@ -569,7 +566,7 @@ mod tests {
569566 fn test_thread_ids ( ) {
570567 let main_tid = unsafe { uucore:: libc:: gettid ( ) } ;
571568 std:: thread:: spawn ( move || {
572- let mut pid_entry = current_process_info ( ) ;
569+ let mut pid_entry = ProcessInformation :: current_process_info ( ) . unwrap ( ) ;
573570 let thread_ids = pid_entry. thread_ids ( ) ;
574571
575572 assert ! ( thread_ids. contains( & ( main_tid as usize ) ) ) ;
@@ -599,7 +596,7 @@ mod tests {
599596 #[ test]
600597 #[ cfg( target_os = "linux" ) ]
601598 fn test_ids ( ) {
602- let mut pid_entry = current_process_info ( ) ;
599+ let mut pid_entry = ProcessInformation :: current_process_info ( ) . unwrap ( ) ;
603600 assert_eq ! (
604601 pid_entry. ppid( ) . unwrap( ) ,
605602 unsafe { uucore:: libc:: getppid( ) } as u64
@@ -615,10 +612,17 @@ mod tests {
615612 #[ test]
616613 #[ cfg( target_os = "linux" ) ]
617614 fn test_uid_gid ( ) {
618- let mut pid_entry = current_process_info ( ) ;
615+ let mut pid_entry = ProcessInformation :: current_process_info ( ) . unwrap ( ) ;
619616 assert_eq ! ( pid_entry. uid( ) . unwrap( ) , uucore:: process:: getuid( ) ) ;
620617 assert_eq ! ( pid_entry. euid( ) . unwrap( ) , uucore:: process:: geteuid( ) ) ;
621618 assert_eq ! ( pid_entry. gid( ) . unwrap( ) , uucore:: process:: getgid( ) ) ;
622619 assert_eq ! ( pid_entry. egid( ) . unwrap( ) , uucore:: process:: getegid( ) ) ;
623620 }
621+
622+ #[ test]
623+ #[ cfg( target_os = "linux" ) ]
624+ fn test_root ( ) {
625+ let mut pid_entry = ProcessInformation :: current_process_info ( ) . unwrap ( ) ;
626+ assert_eq ! ( pid_entry. root( ) . unwrap( ) , PathBuf :: from( "/" ) ) ;
627+ }
624628}
0 commit comments