@@ -503,3 +503,137 @@ fn name_test_init_pid() {
503503 Err ( message) => assert ! ( true , message)
504504 }
505505}
506+
507+ // This trait is needed for polymorphism on listpidinfo types, also abstracting flavor in order to provide
508+ // type-guaranteed flavor correctness
509+ pub trait ListPIDInfo {
510+ type Item ;
511+ fn flavor ( ) -> PidInfoFlavor ;
512+ }
513+
514+ /// Returns the information of the process that match pid passed in.
515+ /// `max_len` is the maximum number of array to return.
516+ /// The length of return value: `Vec<T::Item>` may be less than `max_len`.
517+ ///
518+ /// # Examples
519+ ///
520+ /// ```
521+ /// use std::io::Write;
522+ /// use libproc::libproc::proc_pid::{listpidinfo, pidinfo, ListFDs, TaskAllInfo, ProcFDType};
523+ ///
524+ /// fn listpidinfo_test() {
525+ /// use std::process;
526+ /// let pid = process::id() as i32;
527+ ///
528+ /// if let Ok(info) = pidinfo::<TaskAllInfo>(pid, 0) {
529+ /// if let Ok(fds) = listpidinfo::<ListFDs>(pid, info.pbsd.pbi_nfiles as usize) {
530+ /// for fd in &fds {
531+ /// let fd_type = ProcFDType::from(fd.proc_fdtype);
532+ /// println!("File Descriptor: {}, Type: {:?}", fd.proc_fd, fd_type);
533+ /// }
534+ /// }
535+ /// }
536+ /// }
537+ /// ```
538+ pub fn listpidinfo < T : ListPIDInfo > ( pid : i32 , max_len : usize ) -> Result < Vec < T :: Item > , String > {
539+ let flavor = T :: flavor ( ) as i32 ;
540+ let buffer_size = mem:: size_of :: < T :: Item > ( ) as i32 * max_len as i32 ;
541+ let mut buffer = Vec :: < T :: Item > :: with_capacity ( max_len) ;
542+ let buffer_ptr = unsafe {
543+ buffer. set_len ( max_len) ;
544+ buffer. as_mut_ptr ( ) as * mut c_void
545+ } ;
546+
547+ let ret: i32 ;
548+
549+ unsafe {
550+ ret = proc_pidinfo ( pid, flavor, 0 , buffer_ptr, buffer_size) ;
551+ } ;
552+
553+ if ret <= 0 {
554+ Err ( get_errno_with_message ( ret) )
555+ } else {
556+ let actual_len = ret as usize / mem:: size_of :: < T :: Item > ( ) ;
557+ buffer. truncate ( actual_len) ;
558+ Ok ( buffer)
559+ }
560+ }
561+
562+ #[ test]
563+ fn listpidinfo_test ( ) {
564+ use std:: process;
565+ let pid = process:: id ( ) as i32 ;
566+
567+ match pidinfo :: < TaskAllInfo > ( pid, 0 ) {
568+ Ok ( info) => {
569+ match listpidinfo :: < ListThreads > ( pid, info. ptinfo . pti_threadnum as usize ) {
570+ Ok ( threads) => assert ! ( threads. len( ) >0 ) ,
571+ Err ( err) => assert ! ( false , "Error retrieving process info: {}" , err)
572+ }
573+ match listpidinfo :: < ListFDs > ( pid, info. pbsd . pbi_nfiles as usize ) {
574+ Ok ( fds) => assert ! ( fds. len( ) >0 ) ,
575+ Err ( err) => assert ! ( false , "Error retrieving process info: {}" , err)
576+ }
577+ } ,
578+ Err ( err) => assert ! ( false , "Error retrieving process info: {}" , err)
579+ } ;
580+ }
581+
582+ pub struct ListThreads ;
583+
584+ impl ListPIDInfo for ListThreads {
585+ type Item = uint64_t ;
586+ fn flavor ( ) -> PidInfoFlavor { PidInfoFlavor :: ListThreads }
587+ }
588+
589+ pub struct ListFDs ;
590+
591+ impl ListPIDInfo for ListFDs {
592+ type Item = ProcFDInfo ;
593+ fn flavor ( ) -> PidInfoFlavor { PidInfoFlavor :: ListFDs }
594+ }
595+
596+ #[ repr( C ) ]
597+ pub struct ProcFDInfo {
598+ pub proc_fd : int32_t ,
599+ pub proc_fdtype : uint32_t ,
600+ }
601+
602+ #[ derive( Copy , Clone , Debug ) ]
603+ pub enum ProcFDType {
604+ /// AppleTalk
605+ ATalk = 0 ,
606+ /// Vnode
607+ VNode = 1 ,
608+ /// Socket
609+ Socket = 2 ,
610+ /// POSIX shared memory
611+ PSHM = 3 ,
612+ /// POSIX semaphore
613+ PSEM = 4 ,
614+ /// Kqueue
615+ KQueue = 5 ,
616+ /// Pipe
617+ Pipe = 6 ,
618+ /// FSEvents
619+ FSEvents = 7 ,
620+ /// Unknown
621+ Unknown ,
622+ }
623+
624+ impl From < uint32_t > for ProcFDType {
625+ fn from ( value : uint32_t ) -> ProcFDType {
626+ match value {
627+ 0 => ProcFDType :: ATalk ,
628+ 1 => ProcFDType :: VNode ,
629+ 2 => ProcFDType :: Socket ,
630+ 3 => ProcFDType :: PSHM ,
631+ 4 => ProcFDType :: PSEM ,
632+ 5 => ProcFDType :: KQueue ,
633+ 6 => ProcFDType :: Pipe ,
634+ 7 => ProcFDType :: FSEvents ,
635+ _ => ProcFDType :: Unknown ,
636+ }
637+ }
638+ }
639+
0 commit comments