Skip to content

Commit 95c749c

Browse files
authored
Merge pull request #388 from Bluemangoo/feature/vmstat-impl
vmstat: implement most functions
2 parents 8b2addf + b1601a0 commit 95c749c

File tree

7 files changed

+542
-264
lines changed

7 files changed

+542
-264
lines changed

Cargo.lock

Lines changed: 2 additions & 66 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ nix = { version = "0.29", default-features = false, features = ["process"] }
5656
phf = "0.11.2"
5757
phf_codegen = "0.11.2"
5858
prettytable-rs = "0.10.0"
59-
procfs = "0.17.0"
6059
rand = { version = "0.9.0", features = ["small_rng"] }
6160
ratatui = "0.29.0"
6261
regex = "1.10.4"
6362
sysinfo = "0.34.0"
6463
tempfile = "3.10.1"
64+
terminal_size = "0.4.2"
6565
textwrap = { version = "0.16.1", features = ["terminal_size"] }
6666
thiserror = "2.0.4"
6767
uucore = "0.0.30"

src/uu/vmstat/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@ keywords = ["acl", "uutils", "cross-platform", "cli", "utility"]
1212
categories = ["command-line-utilities"]
1313

1414
[dependencies]
15-
uucore = { workspace = true }
15+
bytesize = { workspace = true }
1616
clap = { workspace = true }
17-
18-
[target.'cfg(target_os="linux")'.dependencies]
19-
procfs = { workspace = true }
17+
terminal_size = { workspace = true }
18+
uucore = { workspace = true }
2019

2120
[lib]
2221
path = "src/vmstat.rs"

src/uu/vmstat/src/parser.rs

Lines changed: 109 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,65 @@
44
// file that was distributed with this source code.
55

66
#[cfg(target_os = "linux")]
7-
pub fn parse_proc_file(path: &str) -> std::collections::HashMap<String, String> {
7+
use std::collections::HashMap;
8+
9+
#[cfg(target_os = "linux")]
10+
pub fn parse_proc_file(path: &str) -> HashMap<String, String> {
811
let file = std::fs::File::open(std::path::Path::new(path)).unwrap();
912
let content = std::io::read_to_string(file).unwrap();
10-
let mut map: std::collections::HashMap<String, String> = std::collections::HashMap::new();
13+
let mut map: HashMap<String, String> = HashMap::new();
1114

1215
for line in content.lines() {
1316
let parts = line.split_once(char::is_whitespace);
1417
if let Some(parts) = parts {
15-
map.insert(parts.0.to_string(), parts.1.trim_start().to_string());
18+
map.insert(
19+
parts.0.strip_suffix(":").unwrap_or(parts.0).to_string(),
20+
parts.1.trim_start().to_string(),
21+
);
1622
}
1723
}
1824

1925
map
2026
}
2127

28+
#[cfg(target_os = "linux")]
29+
pub struct ProcData {
30+
pub uptime: (f64, f64),
31+
pub stat: HashMap<String, String>,
32+
pub meminfo: HashMap<String, String>,
33+
pub vmstat: HashMap<String, String>,
34+
}
35+
#[cfg(target_os = "linux")]
36+
impl Default for ProcData {
37+
fn default() -> Self {
38+
Self::new()
39+
}
40+
}
41+
#[cfg(target_os = "linux")]
42+
impl ProcData {
43+
pub fn new() -> Self {
44+
let uptime = Self::get_uptime();
45+
let stat = parse_proc_file("/proc/stat");
46+
let meminfo = parse_proc_file("/proc/meminfo");
47+
let vmstat = parse_proc_file("/proc/vmstat");
48+
Self {
49+
uptime,
50+
stat,
51+
meminfo,
52+
vmstat,
53+
}
54+
}
55+
56+
fn get_uptime() -> (f64, f64) {
57+
let file = std::fs::File::open(std::path::Path::new("/proc/uptime")).unwrap();
58+
let content = std::io::read_to_string(file).unwrap();
59+
let mut parts = content.split_whitespace();
60+
let uptime = parts.next().unwrap().parse::<f64>().unwrap();
61+
let idle_time = parts.next().unwrap().parse::<f64>().unwrap();
62+
(uptime, idle_time)
63+
}
64+
}
65+
2266
#[cfg(target_os = "linux")]
2367
pub struct CpuLoad {
2468
pub user: f64,
@@ -35,18 +79,20 @@ pub struct CpuLoad {
3579

3680
#[cfg(target_os = "linux")]
3781
impl CpuLoad {
38-
pub fn current() -> CpuLoad {
82+
pub fn current() -> Self {
3983
let file = std::fs::File::open(std::path::Path::new("/proc/stat")).unwrap(); // do not use `parse_proc_file` here because only one line is used
4084
let content = std::io::read_to_string(file).unwrap();
41-
let load = content
42-
.lines()
43-
.next()
44-
.unwrap()
45-
.strip_prefix("cpu")
46-
.unwrap()
47-
.split(' ')
48-
.filter(|s| !s.is_empty())
49-
.collect::<Vec<_>>();
85+
let load_str = content.lines().next().unwrap().strip_prefix("cpu").unwrap();
86+
Self::from_str(load_str)
87+
}
88+
89+
pub fn from_proc_map(proc_map: &HashMap<String, String>) -> Self {
90+
let load_str = proc_map.get("cpu").unwrap();
91+
Self::from_str(load_str)
92+
}
93+
94+
fn from_str(s: &str) -> Self {
95+
let load = s.split(' ').filter(|s| !s.is_empty()).collect::<Vec<_>>();
5096
let user = load[0].parse::<f64>().unwrap();
5197
let nice = load[1].parse::<f64>().unwrap();
5298
let system = load[2].parse::<f64>().unwrap();
@@ -81,3 +127,53 @@ impl CpuLoad {
81127
}
82128
}
83129
}
130+
131+
#[cfg(target_os = "linux")]
132+
pub struct Meminfo {
133+
pub mem_total: bytesize::ByteSize,
134+
pub mem_free: bytesize::ByteSize,
135+
pub mem_available: bytesize::ByteSize,
136+
pub buffers: bytesize::ByteSize,
137+
pub cached: bytesize::ByteSize,
138+
pub swap_cached: bytesize::ByteSize,
139+
pub active: bytesize::ByteSize,
140+
pub inactive: bytesize::ByteSize,
141+
pub swap_total: bytesize::ByteSize,
142+
pub swap_free: bytesize::ByteSize,
143+
}
144+
#[cfg(target_os = "linux")]
145+
impl Meminfo {
146+
pub fn current() -> Self {
147+
let meminfo = parse_proc_file("/proc/meminfo");
148+
Self::from_proc_map(&meminfo)
149+
}
150+
151+
pub fn from_proc_map(proc_map: &HashMap<String, String>) -> Self {
152+
use std::str::FromStr;
153+
154+
let mem_total = bytesize::ByteSize::from_str(proc_map.get("MemTotal").unwrap()).unwrap();
155+
let mem_free = bytesize::ByteSize::from_str(proc_map.get("MemFree").unwrap()).unwrap();
156+
let mem_available =
157+
bytesize::ByteSize::from_str(proc_map.get("MemAvailable").unwrap()).unwrap();
158+
let buffers = bytesize::ByteSize::from_str(proc_map.get("Buffers").unwrap()).unwrap();
159+
let cached = bytesize::ByteSize::from_str(proc_map.get("Cached").unwrap()).unwrap();
160+
let swap_cached =
161+
bytesize::ByteSize::from_str(proc_map.get("SwapCached").unwrap()).unwrap();
162+
let active = bytesize::ByteSize::from_str(proc_map.get("Active").unwrap()).unwrap();
163+
let inactive = bytesize::ByteSize::from_str(proc_map.get("Inactive").unwrap()).unwrap();
164+
let swap_total = bytesize::ByteSize::from_str(proc_map.get("SwapTotal").unwrap()).unwrap();
165+
let swap_free = bytesize::ByteSize::from_str(proc_map.get("SwapFree").unwrap()).unwrap();
166+
Self {
167+
mem_total,
168+
mem_free,
169+
mem_available,
170+
buffers,
171+
cached,
172+
swap_cached,
173+
active,
174+
inactive,
175+
swap_total,
176+
swap_free,
177+
}
178+
}
179+
}

0 commit comments

Comments
 (0)