forked from proxmox-mirrors/proxmox
sys: get rid of Regex dependency
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
b294fb1314
commit
db83a675f0
@ -11,9 +11,7 @@ authors = [
|
|||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
lazy_static = "1.1"
|
lazy_static = "1.1"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
nix = "0.15"
|
|
||||||
proxmox-tools = { path = "../proxmox-tools" }
|
proxmox-tools = { path = "../proxmox-tools" }
|
||||||
regex = "1.0"
|
|
||||||
|
|
||||||
# Docs should be able to reference the proxmox crate.
|
# Docs should be able to reference the proxmox crate.
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -2,12 +2,11 @@ use std::collections::HashSet;
|
|||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use std::u32;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use libc;
|
use libc;
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
use proxmox_tools::fs::file_read_firstline;
|
use proxmox_tools::fs::file_read_firstline;
|
||||||
|
|
||||||
@ -40,34 +39,67 @@ pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<ProcFsPidStat, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_proc_pid_stat(pid: libc::pid_t, statstr: &str) -> Result<ProcFsPidStat, Error> {
|
fn parse_proc_pid_stat(pid: libc::pid_t, statstr: &str) -> Result<ProcFsPidStat, Error> {
|
||||||
lazy_static! {
|
// It starts with the pid followed by a '('.
|
||||||
static ref REGEX: Regex = Regex::new(concat!(
|
let cmdbeg = statstr
|
||||||
r"^(?P<pid>\d+) \(.*\) (?P<status>\S) -?\d+ -?\d+ -?\d+ -?\d+ -?\d+ \d+ \d+ \d+ \d+ \d+ ",
|
.find('(')
|
||||||
r"(?P<utime>\d+) (?P<stime>\d+) -?\d+ -?\d+ -?\d+ -?\d+ -?\d+ 0 ",
|
.ok_or_else(|| format_err!("missing '(' in /proc/PID/stat"))?;
|
||||||
r"(?P<starttime>\d+) (?P<vsize>\d+) (?P<rss>-?\d+) ",
|
|
||||||
r"\d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ \d+ -?\d+ -?\d+ \d+ \d+ \d+"
|
if !statstr[..=cmdbeg].ends_with(" (") {
|
||||||
)).unwrap();
|
bail!("bad /proc/PID/stat line before the '('");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cap) = REGEX.captures(&statstr) {
|
let stat_pid: u32 = statstr[..(cmdbeg - 1)]
|
||||||
if pid != cap["pid"].parse::<i32>().unwrap() {
|
.parse()
|
||||||
|
.map_err(|e| format_err!("bad pid in /proc/PID/stat: {}", e))?;
|
||||||
|
|
||||||
|
if (pid as u32) != stat_pid {
|
||||||
bail!(
|
bail!(
|
||||||
"unable to read pid stat for process '{}' - got wrong pid",
|
"unexpected pid for process: found pid {} in /proc/{}/stat",
|
||||||
|
stat_pid,
|
||||||
pid
|
pid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(ProcFsPidStat {
|
// After the '(' we have an arbitrary command name, then ')' and the remaining values
|
||||||
status: cap["status"].as_bytes()[0],
|
let cmdend = statstr
|
||||||
utime: cap["utime"].parse::<u64>().unwrap(),
|
.rfind(')')
|
||||||
stime: cap["stime"].parse::<u64>().unwrap(),
|
.ok_or_else(|| format_err!("missing ')' in /proc/PID/stat"))?;
|
||||||
starttime: cap["starttime"].parse::<u64>().unwrap(),
|
let mut parts = statstr[cmdend + 1..].trim_start().split_ascii_whitespace();
|
||||||
vsize: cap["vsize"].parse::<u64>().unwrap(),
|
|
||||||
rss: cap["rss"].parse::<i64>().unwrap() * 4096,
|
// helpers:
|
||||||
});
|
fn required<'a>(value: Option<&'a str>, what: &'static str) -> Result<&'a str, Error> {
|
||||||
|
value.ok_or_else(|| format_err!("missing '{}' in /proc/PID/stat", what))
|
||||||
}
|
}
|
||||||
|
|
||||||
bail!("unable to read pid stat for process '{}'", pid);
|
fn req_num<T>(value: Option<&str>, what: &'static str) -> Result<T, Error>
|
||||||
|
where
|
||||||
|
T: FromStr,
|
||||||
|
<T as FromStr>::Err: Into<Error>,
|
||||||
|
{
|
||||||
|
required(value, what)?.parse::<T>().map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn req_byte(value: Option<&str>, what: &'static str) -> Result<u8, Error> {
|
||||||
|
let value = required(value, what)?;
|
||||||
|
if value.len() != 1 {
|
||||||
|
bail!("invalid '{}' in /proc/PID/stat", what);
|
||||||
|
}
|
||||||
|
Ok(value.as_bytes()[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
let out = ProcFsPidStat {
|
||||||
|
status: req_byte(parts.next(), "status")?,
|
||||||
|
utime: req_num::<u64>(parts.nth(10), "utime")?,
|
||||||
|
stime: req_num::<u64>(parts.next(), "stime")?,
|
||||||
|
starttime: req_num::<u64>(parts.nth(6), "start_time")?,
|
||||||
|
vsize: req_num::<u64>(parts.next(), "vsize")?,
|
||||||
|
rss: req_num::<i64>(parts.next(), "rss")? * 4096,
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = req_num::<u64>(parts.next(), "it_real_value")?;
|
||||||
|
// and more...
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user