Skip to content

Commit

Permalink
Correctly retrieve process root directory on mac
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Oct 14, 2023
1 parent a37d3c1 commit cb1465b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 74 deletions.
114 changes: 43 additions & 71 deletions src/unix/apple/macos/process.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use std::ffi::CStr;
use std::mem::{self, MaybeUninit};
use std::ops::Deref;
use std::path::{Path, PathBuf};
Expand All @@ -13,6 +12,7 @@ use crate::{DiskUsage, Gid, Pid, Process, ProcessRefreshKind, ProcessStatus, Sig

use crate::sys::process::ThreadStatus;
use crate::sys::system::Wrap;
use crate::unix::utils::cstr_to_rust_with_size;

pub(crate) struct ProcessInner {
pub(crate) name: String,
Expand Down Expand Up @@ -48,7 +48,13 @@ pub(crate) struct ProcessInner {
}

impl ProcessInner {
pub(crate) fn new_empty(pid: Pid, exe: PathBuf, name: String, cwd: PathBuf) -> Self {
pub(crate) fn new_empty(
pid: Pid,
exe: PathBuf,
name: String,
cwd: PathBuf,
root: PathBuf,
) -> Self {
Self {
name,
pid,
Expand All @@ -57,7 +63,7 @@ impl ProcessInner {
environ: Vec::new(),
exe,
cwd,
root: PathBuf::new(),
root,
memory: 0,
virtual_memory: 0,
cpu_usage: 0.,
Expand All @@ -79,16 +85,23 @@ impl ProcessInner {
}
}

pub(crate) fn new(pid: Pid, parent: Option<Pid>, start_time: u64, run_time: u64) -> Self {
pub(crate) fn new(
pid: Pid,
parent: Option<Pid>,
start_time: u64,
run_time: u64,
cwd: PathBuf,
root: PathBuf,
) -> Self {
Self {
name: String::new(),
pid,
parent,
cmd: Vec::new(),
environ: Vec::new(),
exe: PathBuf::new(),
cwd: PathBuf::new(),
root: PathBuf::new(),
cwd,
root,
memory: 0,
virtual_memory: 0,
cpu_usage: 0.,
Expand Down Expand Up @@ -319,17 +332,6 @@ fn check_if_pid_is_alive(pid: Pid, check_if_alive: bool) -> bool {
}
}

#[inline]
fn do_not_get_env_path(_: &str, _: &mut PathBuf, _: &mut bool) {}

#[inline]
fn do_get_env_path(env: &str, root: &mut PathBuf, check: &mut bool) {
if *check && env.starts_with("PATH=") {
*check = false;
*root = Path::new(&env[5..]).to_path_buf();
}
}

unsafe fn get_bsd_info(pid: Pid) -> Option<libc::proc_bsdinfo> {
let mut info = mem::zeroed::<libc::proc_bsdinfo>();

Expand All @@ -347,6 +349,18 @@ unsafe fn get_bsd_info(pid: Pid) -> Option<libc::proc_bsdinfo> {
}
}

unsafe fn convert_node_path_info(node: &libc::vnode_info_path) -> PathBuf {
if node.vip_vi.vi_stat.vst_dev == 0 {
return PathBuf::new();
}
cstr_to_rust_with_size(
node.vip_path.as_ptr() as _,
Some(node.vip_path.len() * node.vip_path[0].len()),
)
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::new())
}

unsafe fn create_new_process(
pid: Pid,
mut size: size_t,
Expand All @@ -362,15 +376,13 @@ unsafe fn create_new_process(
&mut vnodepathinfo as *mut _ as *mut _,
mem::size_of::<libc::proc_vnodepathinfo>() as _,
);
let cwd = if result > 0 {
let buffer = vnodepathinfo.pvi_cdir.vip_path;
let buffer = CStr::from_ptr(buffer.as_ptr() as _);
buffer
.to_str()
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::new())
let (cwd, root) = if result > 0 {
(
convert_node_path_info(&vnodepathinfo.pvi_cdir),
convert_node_path_info(&vnodepathinfo.pvi_rdir),
)
} else {
PathBuf::new()
(PathBuf::new(), PathBuf::new())
};

let info = match info {
Expand All @@ -392,7 +404,7 @@ unsafe fn create_new_process(
.unwrap_or("")
.to_owned();
return Ok(Some(Process {
inner: ProcessInner::new_empty(pid, exe, name, cwd),
inner: ProcessInner::new_empty(pid, exe, name, cwd, root),
}));
}
_ => {}
Expand Down Expand Up @@ -488,57 +500,33 @@ unsafe fn create_new_process(
}

#[inline]
unsafe fn get_environ<F: Fn(&str, &mut PathBuf, &mut bool)>(
ptr: *mut u8,
mut cp: *mut u8,
size: size_t,
mut root: PathBuf,
callback: F,
) -> (Vec<String>, PathBuf) {
unsafe fn get_environ(ptr: *mut u8, mut cp: *mut u8, size: size_t) -> Vec<String> {
let mut environ = Vec::with_capacity(10);
let mut start = cp;
let mut check = true;
while cp < ptr.add(size) {
if *cp == 0 {
if cp == start {
break;
}
let e = get_unchecked_str(cp, start);
callback(&e, &mut root, &mut check);
environ.push(e);
start = cp.offset(1);
}
cp = cp.offset(1);
}
(environ, root)
environ
}

let (environ, root) = if exe.is_absolute() {
if let Some(parent_path) = exe.parent() {
get_environ(
ptr,
cp,
size,
parent_path.to_path_buf(),
do_not_get_env_path,
)
} else {
get_environ(ptr, cp, size, PathBuf::new(), do_get_env_path)
}
} else {
get_environ(ptr, cp, size, PathBuf::new(), do_get_env_path)
};
let mut p = ProcessInner::new(pid, parent, start_time, run_time);
let environ = get_environ(ptr, cp, size);
let mut p = ProcessInner::new(pid, parent, start_time, run_time, cwd, root);

p.exe = exe;
p.name = name;
p.cwd = cwd;
p.cmd = parse_command_line(&cmd);
p.environ = environ;
p.root = root;
p
} else {
ProcessInner::new(pid, parent, start_time, run_time)
ProcessInner::new(pid, parent, start_time, run_time, cwd, root)
};

let task_info = get_task_info(pid);
Expand Down Expand Up @@ -699,19 +687,3 @@ fn parse_command_line<T: Deref<Target = str> + Borrow<str>>(cmd: &[T]) -> Vec<St
}
command
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_get_path() {
let mut path = PathBuf::new();
let mut check = true;

do_get_env_path("PATH=tadam", &mut path, &mut check);

assert!(!check);
assert_eq!(path, PathBuf::from("tadam"));
}
}
9 changes: 6 additions & 3 deletions src/unix/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ pub(crate) fn cstr_to_rust_with_size(c: *const c_char, size: Option<usize>) -> O
if c.is_null() {
return None;
}
let mut s = match size {
Some(len) => Vec::with_capacity(len),
None => Vec::new(),
let (mut s, max) = match size {
Some(len) => (Vec::with_capacity(len), len as isize),
None => (Vec::new(), isize::MAX),
};
let mut i = 0;
unsafe {
Expand All @@ -23,6 +23,9 @@ pub(crate) fn cstr_to_rust_with_size(c: *const c_char, size: Option<usize>) -> O
}
s.push(value);
i += 1;
if i >= max {
break;
}
}
String::from_utf8(s).ok()
}
Expand Down

0 comments on commit cb1465b

Please sign in to comment.