Skip to content

Commit daeff47

Browse files
Merge pull request #7 from akhramov/feature/add-proc-pidinfo-support
Add support for proc_pidinfo
2 parents a82f3ee + f2e1cf8 commit daeff47

File tree

1 file changed

+77
-7
lines changed

1 file changed

+77
-7
lines changed

src/libproc/proc_pid.rs

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate errno;
33

44
use self::libc::{uint64_t, uint32_t, int32_t, c_void, c_int, uid_t, gid_t, c_char};
55
use 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
4141
const 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)]
4552
pub 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)]
6779
pub 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)]
93110
pub 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)]
99120
pub 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)]
113135
pub 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
121147
pub enum PidInfoFlavor {
122148
ListFDs = 1, // list of ints?
@@ -165,7 +191,7 @@ pub enum PidFDInfoFlavor {
165191
extern {
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+
181208
pub 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

247317
pub 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

Comments
 (0)