Skip to content

Commit 2f6aab0

Browse files
Add support for proc_listpidspath() call added in 10.5
1 parent 8ccceb8 commit 2f6aab0

File tree

3 files changed

+95
-9
lines changed

3 files changed

+95
-9
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ libc = "^0.2.62"
1717
name = "libproc"
1818
path = "src/lib.rs"
1919

20+
[features]
21+
default = ["macosx_10_5", "macosx_10_7"]
22+
macosx_10_5 = []
23+
macosx_10_7 = ["macosx_10_5"]
24+
2025
[[bin]]
2126
name = "procinfo"
2227
path = "src/procinfo.rs"

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,25 @@ pub fn kmsgbuf() -> Result<String, String>
7575
- `dmesg` is a version of dmesg implemented in rust that uses libproc-rs.
7676

7777
# Platforms
78-
Mac OS X and work started on Linux.
78+
Mac OS X and Linux.
79+
80+
## Mac OS X Versions
81+
Calls were aded to libproc in Mac OS X 10.5 and again in 10.7.
82+
This library can be compiled to not include those calls by using rust `features`
83+
to enable/disable support for those versions.
84+
85+
The default build for Mac OS 10.7 or later includes both.
86+
See
87+
```toml
88+
[features]
89+
default = ["macosx_10_5", "macosx_10_7"]
90+
```
91+
in `Cargo.toml`
92+
93+
To build for versions prior to Mac OS 10.5 disable the default features by passing `--no-default-features` to `cargo`.
94+
95+
To build for Mac OS X 10.5 (or 10.6) you can enable that feature alone using
96+
`--no-default-features --features "macosx_10_5"`
7997

8098
# Build and Test
8199
`cargo test` should build and test as usual for rust projects.

src/libproc/proc_pid.rs

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::libproc::work_queue_info::WorkQueueInfo;
2828
#[cfg(target_os = "linux")]
2929
use 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 {
137137
extern {
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

Comments
 (0)