use crate::CoreError;
use std::path::Path;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProcStatus {
pub name: String,
pub uid: u32,
}
pub fn read_proc_status(pid: i32) -> Result<ProcStatus, CoreError> {
read_proc_status_at("/proc", pid)
}
pub fn read_proc_status_at(proc_root: impl AsRef<Path>, pid: i32) -> Result<ProcStatus, CoreError> {
let path = proc_root.as_ref().join(pid.to_string()).join("status");
let content = std::fs::read_to_string(path).map_err(|err| io_error(err, "read_proc_status"))?;
parse_proc_status(&content)
}
pub fn read_proc_cmdline(pid: i32) -> Result<String, CoreError> {
read_proc_cmdline_at("/proc", pid)
}
pub fn read_proc_cmdline_at(proc_root: impl AsRef<Path>, pid: i32) -> Result<String, CoreError> {
let path = proc_root.as_ref().join(pid.to_string()).join("cmdline");
let bytes = std::fs::read(path).map_err(|err| io_error(err, "read_proc_cmdline"))?;
Ok(parse_proc_cmdline_bytes(&bytes))
}
pub(crate) fn parse_proc_cmdline_bytes(bytes: &[u8]) -> String {
String::from_utf8_lossy(bytes)
.trim_end_matches('\0')
.replace('\0', " ")
}
pub fn parse_proc_status(content: &str) -> Result<ProcStatus, CoreError> {
let mut name = None;
let mut uid = None;
for line in content.lines() {
if let Some(rest) = line.strip_prefix("Name:") {
name = Some(rest.trim().to_string());
} else if let Some(rest) = line.strip_prefix("Uid:") {
uid = rest
.split_whitespace()
.next()
.and_then(|value| value.parse::<u32>().ok());
}
if name.is_some() && uid.is_some() {
break;
}
}
match (name, uid) {
(Some(name), Some(uid)) => Ok(ProcStatus { name, uid }),
_ => Err(CoreError::sys(libc::EINVAL, "parse_proc_status")),
}
}
fn io_error(err: std::io::Error, op: &'static str) -> CoreError {
CoreError::sys(err.raw_os_error().unwrap_or(libc::EIO), op)
}
#[inline(always)]
pub fn clock_ticks_per_second() -> Result<u64, CoreError> {
let ticks = unsafe { libc::sysconf(libc::_SC_CLK_TCK) };
if ticks <= 0 {
let code = std::io::Error::last_os_error()
.raw_os_error()
.unwrap_or(libc::EINVAL);
Err(CoreError::sys(code, "sysconf(_SC_CLK_TCK)"))
} else {
Ok(ticks as u64)
}
}