@@ -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
@@ -137,19 +137,28 @@ impl ListPIDInfo for ListThreads {
137137extern {
138138 fn proc_listpids ( proc_type : u32 , typeinfo : u32 , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
139139
140- fn proc_pidinfo ( pid : c_int , flavor : c_int , arg : u64 , buffer : * mut c_void , buffersize : c_int ) -> c_int ;
141-
142140 fn proc_name ( pid : c_int , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
143141
142+ fn proc_pidpath ( pid : c_int , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
143+
144+ fn proc_listpidspath ( proc_type : u32 , typeinfo : u32 ,
145+ path : * const c_char , pathflags : u32 ,
146+ buffer : * mut c_void , buffersize : u32 ) -> c_int ;
147+
144148 fn proc_regionfilename ( pid : c_int , address : u64 , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
145149
146- fn proc_pidpath ( pid : c_int , buffer : * mut c_void , buffersize : u32 ) -> c_int ;
150+ fn proc_pidinfo ( pid : c_int , flavor : c_int , arg : u64 , buffer : * mut c_void , buffersize : c_int ) -> c_int ;
147151
148152 fn proc_libversion ( major : * mut c_int , minor : * mut c_int ) -> c_int ;
149153}
150154
155+ //int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
156+ //int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
157+ //int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
158+ //int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
159+
151160
152- /// Returns the PIDs of the processes active that match the ProcType passed in
161+ /// Returns the PIDs of the active processes that match the ProcType passed in
153162///
154163/// # Examples
155164///
@@ -214,6 +223,53 @@ pub fn listpids(proc_types: ProcType) -> Result<Vec<u32>, String> {
214223 }
215224}
216225
226+ // proc_listpidspath
227+ // Search through the current processes looking for open file references which match
228+ // a specified path or volume.
229+ //
230+ // @param type types of processes to be searched (see proc_listpids)
231+ // @param typeinfo adjunct information for type
232+ // @param path file or volume path
233+ // @param pathflags flags to control which files should be considered
234+ // during the process search.
235+ // @param buffer a C array of int-sized values to be filled with
236+ // process identifiers that hold an open file reference
237+ // matching the specified path or volume. Pass NULL to
238+ // obtain the minimum buffer size needed to hold the
239+ // currently active processes.
240+ // @param buffersize the size (in bytes) of the provided buffer.
241+ // @result the number of bytes of data returned in the provided buffer;
242+ // -1 if an error was encountered;
243+ #[ cfg( target_os = "macos" ) ]
244+ #[ cfg( feature = "macosx_10_5" ) ]
245+ pub fn listpidspath ( proc_types : ProcType , path : String ) -> Result < Vec < u32 > , String > {
246+ let buffer_size = unsafe {
247+ proc_listpidspath ( proc_types as u32 , 0 , path. as_ptr ( ) as * const c_char , 0 , ptr:: null_mut ( ) , 0 )
248+ } ;
249+ if buffer_size <= 0 {
250+ return Err ( helpers:: get_errno_with_message ( buffer_size) ) ;
251+ }
252+
253+ let capacity = buffer_size as usize / mem:: size_of :: < u32 > ( ) ;
254+ let mut pids: Vec < u32 > = Vec :: with_capacity ( capacity) ;
255+ let buffer_ptr = pids. as_mut_ptr ( ) as * mut c_void ;
256+
257+ let ret = unsafe {
258+ proc_listpidspath ( proc_types as u32 , 0 , path. as_ptr ( ) as * const c_char , 0 , buffer_ptr, buffer_size as u32 )
259+ } ;
260+
261+ if ret <= 0 {
262+ Err ( helpers:: get_errno_with_message ( ret) )
263+ } else {
264+ let items_count = ret as usize / mem:: size_of :: < u32 > ( ) - 1 ;
265+ unsafe {
266+ pids. set_len ( items_count) ;
267+ }
268+
269+ Ok ( pids)
270+ }
271+ }
272+
217273/// Get info about a process
218274///
219275/// arg - is "heavily not documented" and need to look at code for each flavour
@@ -621,9 +677,8 @@ mod test {
621677
622678 #[ test]
623679 fn listpids_test ( ) {
624- if let Ok ( pids) = listpids ( ProcType :: ProcAllPIDS ) {
625- assert ! ( pids. len( ) > 1 ) ;
626- }
680+ let pids = listpids ( ProcType :: ProcAllPIDS ) . unwrap ( ) ;
681+ assert ! ( pids. len( ) > 1 ) ;
627682 }
628683
629684 #[ test]
@@ -699,4 +754,12 @@ mod test {
699754 assert ! ( procfile_field( "/proc/1/status" , "invalid" ) . is_err( ) ) ;
700755 }
701756 }
757+
758+ #[ test]
759+ #[ cfg( target_os = "macos" ) ]
760+ #[ cfg( feature = "macosx_10_5" ) ]
761+ fn listpidspath_test ( ) {
762+ let pids = super :: listpidspath ( ProcType :: ProcAllPIDS , "/" . into ( ) ) . unwrap ( ) ;
763+ assert ! ( pids. len( ) > 1 ) ;
764+ }
702765}
0 commit comments