@@ -28,7 +28,7 @@ use crate::libproc::work_queue_info::WorkQueueInfo;
2828#[ cfg( target_os = "linux" ) ]
2929use self :: libc:: { c_char, readlink} ;
3030#[ cfg( target_os = "macos" ) ]
31- use self :: libc:: { c_int, c_void} ;
31+ use self :: libc:: { c_int, c_void, c_char } ;
3232
3333// Since we cannot access C macros for constants from Rust - I have had to redefine this, based on Apple's source code
3434// See http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
@@ -135,21 +135,18 @@ impl ListPIDInfo for ListThreads {
135135#[ cfg( target_os = "macos" ) ]
136136#[ link( name = "proc" , kind = "dylib" ) ]
137137extern {
138+ // All these methods are supported in the minimum version of Mac OS X which is 10.5
138139 fn proc_listpids ( proc_type : u32 , typeinfo : u32 , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
139-
140+ fn proc_listpidspath ( proc_type : u32 , typeinfo : u32 , path : * const c_char , pathflags : u32 , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
140141 fn proc_pidinfo ( pid : c_int , flavor : c_int , arg : u64 , buffer : * mut c_void , buffersize : c_int ) -> c_int ;
141-
142142 fn proc_name ( pid : c_int , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
143-
144- fn proc_regionfilename ( pid : c_int , address : u64 , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
145-
143+ fn proc_libversion ( major : * mut c_int , minor : * mut c_int ) -> c_int ;
146144 fn proc_pidpath ( pid : c_int , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
145+ fn proc_regionfilename ( pid : c_int , address : u64 , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
147146
148- fn proc_libversion ( major : * mut c_int , minor : * mut c_int ) -> c_int ;
149147}
150148
151-
152- /// Returns the PIDs of the processes active that match the ProcType passed in
149+ /// Returns the PIDs of the active processes that match the ProcType passed in
153150///
154151/// # Examples
155152///
@@ -214,6 +211,52 @@ pub fn listpids(proc_types: ProcType) -> Result<Vec<u32>, String> {
214211 }
215212}
216213
214+ // proc_listpidspath
215+ // Search through the current processes looking for open file references which match
216+ // a specified path or volume.
217+ //
218+ // @param type types of processes to be searched (see proc_listpids)
219+ // @param typeinfo adjunct information for type
220+ // @param path file or volume path
221+ // @param pathflags flags to control which files should be considered
222+ // during the process search.
223+ // @param buffer a C array of int-sized values to be filled with
224+ // process identifiers that hold an open file reference
225+ // matching the specified path or volume. Pass NULL to
226+ // obtain the minimum buffer size needed to hold the
227+ // currently active processes.
228+ // @param buffersize the size (in bytes) of the provided buffer.
229+ // @result the number of bytes of data returned in the provided buffer;
230+ // -1 if an error was encountered;
231+ #[ cfg( target_os = "macos" ) ]
232+ pub fn listpidspath ( proc_types : ProcType , path : String ) -> Result < Vec < u32 > , String > {
233+ let buffer_size = unsafe {
234+ proc_listpidspath ( proc_types as u32 , 0 , path. as_ptr ( ) as * const c_char , 0 , ptr:: null_mut ( ) , 0 )
235+ } ;
236+ if buffer_size <= 0 {
237+ return Err ( helpers:: get_errno_with_message ( buffer_size) ) ;
238+ }
239+
240+ let capacity = buffer_size as usize / mem:: size_of :: < u32 > ( ) ;
241+ let mut pids: Vec < u32 > = Vec :: with_capacity ( capacity) ;
242+ let buffer_ptr = pids. as_mut_ptr ( ) as * mut c_void ;
243+
244+ let ret = unsafe {
245+ proc_listpidspath ( proc_types as u32 , 0 , path. as_ptr ( ) as * const c_char , 0 , buffer_ptr, buffer_size as u32 )
246+ } ;
247+
248+ if ret <= 0 {
249+ Err ( helpers:: get_errno_with_message ( ret) )
250+ } else {
251+ let items_count = ret as usize / mem:: size_of :: < u32 > ( ) - 1 ;
252+ unsafe {
253+ pids. set_len ( items_count) ;
254+ }
255+
256+ Ok ( pids)
257+ }
258+ }
259+
217260/// Get info about a process
218261///
219262/// arg - is "heavily not documented" and need to look at code for each flavour
@@ -621,9 +664,8 @@ mod test {
621664
622665 #[ test]
623666 fn listpids_test ( ) {
624- if let Ok ( pids) = listpids ( ProcType :: ProcAllPIDS ) {
625- assert ! ( pids. len( ) > 1 ) ;
626- }
667+ let pids = listpids ( ProcType :: ProcAllPIDS ) . unwrap ( ) ;
668+ assert ! ( pids. len( ) > 1 ) ;
627669 }
628670
629671 #[ test]
@@ -699,4 +741,11 @@ mod test {
699741 assert ! ( procfile_field( "/proc/1/status" , "invalid" ) . is_err( ) ) ;
700742 }
701743 }
744+
745+ #[ test]
746+ #[ cfg( target_os = "macos" ) ]
747+ fn listpidspath_test ( ) {
748+ let pids = super :: listpidspath ( ProcType :: ProcAllPIDS , "/" . into ( ) ) . unwrap ( ) ;
749+ assert ! ( pids. len( ) > 1 ) ;
750+ }
702751}
0 commit comments