@@ -3,7 +3,7 @@ extern crate errno;
33
44use self :: libc:: { uint64_t, uint32_t, int32_t, c_void, c_int, uid_t, gid_t, c_char} ;
55use self :: errno:: errno;
6- use std:: str ;
6+ use std:: mem ;
77
88// Since we cannot access C macros for constants from Rust - I have had to redefine this, based on Apple's source code
99// See http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
@@ -40,8 +40,15 @@ pub enum ProcType {
4040// from http://opensource.apple.com//source/xnu/xnu-1504.7.4/bsd/sys/param.h
4141const MAXCOMLEN : usize = 16 ;
4242
43+ // This trait is needed for polymorphism on pidinfo types, also abstracting flavor in order to provide
44+ // type-guaranteed flavor correctness
45+ pub trait PIDInfo : Default {
46+ fn flavor ( ) -> PidInfoFlavor ;
47+ }
48+
4349// structures from http://opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/proc_info.h
4450#[ repr( C ) ]
51+ #[ derive( Default ) ]
4552pub struct TaskInfo {
4653 pub pti_virtual_size : uint64_t , // virtual memory size (bytes)
4754 pub pti_resident_size : uint64_t , // resident memory size (bytes)
@@ -63,7 +70,12 @@ pub struct TaskInfo {
6370 pub pti_priority : int32_t // task priority
6471}
6572
73+ impl PIDInfo for TaskInfo {
74+ fn flavor ( ) -> PidInfoFlavor { PidInfoFlavor :: TaskInfo }
75+ }
76+
6677#[ repr( C ) ]
78+ #[ derive( Default ) ]
6779pub struct BSDInfo {
6880 pub pbi_flags : uint32_t , // 64bit; emulated etc
6981 pub pbi_status : uint32_t ,
@@ -89,12 +101,21 @@ pub struct BSDInfo {
89101 pub pbi_start_tvusec : uint64_t
90102}
91103
104+ impl PIDInfo for BSDInfo {
105+ fn flavor ( ) -> PidInfoFlavor { PidInfoFlavor :: TBSDInfo }
106+ }
107+
92108#[ repr( C ) ]
109+ #[ derive( Default ) ]
93110pub struct TaskAllInfo {
94111 pub pbsd : BSDInfo ,
95112 pub ptinfo : TaskInfo
96113}
97114
115+ impl PIDInfo for TaskAllInfo {
116+ fn flavor ( ) -> PidInfoFlavor { PidInfoFlavor :: TaskAllInfo }
117+ }
118+
98119#[ repr( C ) ]
99120pub struct ThreadInfo {
100121 pub pth_user_time : uint64_t , // user run time
@@ -110,13 +131,18 @@ pub struct ThreadInfo {
110131 pub pth_name : [ c_char ; MAXTHREADNAMESIZE ] // thread name, if any
111132}
112133
134+ #[ derive( Default ) ]
113135pub struct WorkQueueInfo {
114136 pub pwq_nthreads : uint32_t , // total number of workqueue threads
115137 pub pwq_runthreads : uint32_t , // total number of running workqueue threads
116138 pub pwq_blockedthreads : uint32_t , // total number of blocked workqueue threads
117139 pub reserved : [ uint32_t ; 1 ] // reserved for future use
118140}
119141
142+ impl PIDInfo for WorkQueueInfo {
143+ fn flavor ( ) -> PidInfoFlavor { PidInfoFlavor :: WorkQueueInfo }
144+ }
145+
120146// From http://opensource.apple.com/source/xnu/xnu-1504.7.4/bsd/kern/proc_info.c
121147pub enum PidInfoFlavor {
122148 ListFDs = 1 , // list of ints?
@@ -165,7 +191,7 @@ pub enum PidFDInfoFlavor {
165191extern {
166192 fn proc_listpids ( proc_type : uint32_t , typeinfo : uint32_t , buffer : * mut c_void , buffersize : uint32_t ) -> c_int ;
167193
168- // fn proc_pidinfo(pid : c_int, flavor : c_int, arg: uint64_t, buffer : *mut c_void, buffersize : c_int) -> c_int;
194+ fn proc_pidinfo ( pid : c_int , flavor : c_int , arg : uint64_t , buffer : * mut c_void , buffersize : c_int ) -> c_int ;
169195
170196// fn proc_pidfdinfo(pid : c_int, fd : c_int, flavor : c_int, buffer : *mut c_void, buffersize : c_int) -> c_int;
171197
@@ -178,6 +204,7 @@ extern {
178204 fn proc_libversion ( major : * mut c_int , minor : * mut c_int ) -> c_int ;
179205}
180206
207+
181208pub fn get_errno_with_message ( ret : i32 ) -> String {
182209 let e = errno ( ) ;
183210 let code = e. 0 as i32 ;
@@ -234,15 +261,58 @@ fn listpids_test() {
234261 }
235262}
236263
237- /// pidinfo to get information about a process
264+
265+ /// Returns the PIDs of the process that match pid passed in.
266+ ///
238267/// arg - is "geavily not documented" and need to look at code for each flavour here
239268/// http://opensource.apple.com/source/xnu/xnu-1504.7.4/bsd/kern/proc_info.c
240269/// to figure out what it's doing.... Pull-Requests welcome!
241270///
242- /* pub fn pidinfo(pid : u32, flavor : PidInfoFlavor, arg: uint64_t) -> Result<(), String> {
243- // , buffer : *mut c_void, buffersize : u32
244- Ok(())
245- } */
271+ /// # Examples
272+ ///
273+ /// ```
274+ /// use std::io::Write;
275+ /// use libproc::libproc::proc_pid::{pidinfo, BSDInfo};
276+ ///
277+ /// fn pidinfo_test() {
278+ /// use std::process;
279+ /// let pid = process::id() as i32;
280+ ///
281+ /// match pidinfo::<BSDInfo>(pid, 0) {
282+ /// Ok(info) => assert_eq!(info.pbi_pid as i32, pid),
283+ /// Err(err) => assert!(false, "Error retrieving process info: {}", err)
284+ /// };
285+ /// }
286+ /// ```
287+ ///
288+ pub fn pidinfo < T : PIDInfo > ( pid : i32 , arg : uint64_t ) -> Result < T , String > {
289+ let flavor = T :: flavor ( ) as i32 ;
290+ let buffer_size = mem:: size_of :: < T > ( ) as i32 ;
291+ let mut pidinfo = T :: default ( ) ;
292+ let buffer_ptr = & mut pidinfo as * mut _ as * mut c_void ;
293+ let ret: i32 ;
294+
295+ unsafe {
296+ ret = proc_pidinfo ( pid, flavor, arg, buffer_ptr, buffer_size) ;
297+ } ;
298+
299+ if ret <= 0 {
300+ Err ( get_errno_with_message ( ret) )
301+ } else {
302+ Ok ( pidinfo)
303+ }
304+ }
305+
306+ #[ test]
307+ fn pidinfo_test ( ) {
308+ use std:: process;
309+ let pid = process:: id ( ) as i32 ;
310+
311+ match pidinfo :: < BSDInfo > ( pid, 0 ) {
312+ Ok ( info) => assert_eq ! ( info. pbi_pid as i32 , pid) ,
313+ Err ( err) => assert ! ( false , "Error retrieving process info: {}" , err)
314+ } ;
315+ }
246316
247317pub fn regionfilename ( pid : i32 , address : u64 ) -> Result < String , String > {
248318 let mut regionfilenamebuf: Vec < u8 > = Vec :: with_capacity ( PROC_PIDPATHINFO_MAXSIZE - 1 ) ;
0 commit comments