sysinfo/unix/
utils.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(feature = "user")]
4pub(crate) fn cstr_to_rust(c: *const libc::c_char) -> Option<String> {
5    cstr_to_rust_with_size(c, None)
6}
7
8#[cfg(any(feature = "disk", feature = "system", feature = "user"))]
9#[allow(dead_code)]
10pub(crate) fn cstr_to_rust_with_size(
11    c: *const libc::c_char,
12    size: Option<usize>,
13) -> Option<String> {
14    if c.is_null() {
15        return None;
16    }
17    let (mut s, max) = match size {
18        Some(len) => (Vec::with_capacity(len), len as isize),
19        None => (Vec::new(), isize::MAX),
20    };
21    let mut i = 0;
22    unsafe {
23        loop {
24            let value = *c.offset(i) as u8;
25            if value == 0 {
26                break;
27            }
28            s.push(value);
29            i += 1;
30            if i >= max {
31                break;
32            }
33        }
34        String::from_utf8(s).ok()
35    }
36}
37
38#[cfg(all(
39    feature = "system",
40    not(any(
41        target_os = "ios",
42        all(target_os = "macos", feature = "apple-sandbox",)
43    ))
44))]
45pub(crate) fn wait_process(pid: crate::Pid) -> Option<std::process::ExitStatus> {
46    use std::os::unix::process::ExitStatusExt;
47
48    let mut status = 0;
49    // attempt waiting
50    unsafe {
51        if retry_eintr!(libc::waitpid(pid.0, &mut status, 0)) < 0 {
52            // attempt failed (non-child process) so loop until process ends
53            let duration = std::time::Duration::from_millis(10);
54            while libc::kill(pid.0, 0) == 0 {
55                std::thread::sleep(duration);
56            }
57        }
58        Some(std::process::ExitStatus::from_raw(status))
59    }
60}