Skip to content

Commit

Permalink
Merge pull request #59 from KMJ-007/main
Browse files Browse the repository at this point in the history
macos build issue resolved
  • Loading branch information
mihaigalos authored Dec 19, 2024
2 parents c1980e7 + ac410bd commit 99c0e9a
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 39 deletions.
89 changes: 57 additions & 32 deletions src/reader.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use clap::ArgMatches;
use nix::sys::statvfs::statvfs;
use std::cmp;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::process;
use std::process::Command;

use crate::procfields::ProcFields;
use crate::stats::Stats;
Expand All @@ -13,44 +11,71 @@ pub struct Reader;

impl Reader {
pub fn read(args: &ArgMatches) -> (Vec<Stats>, usize) {
let file = match File::open("/proc/mounts") {
Ok(f) => f,
Err(e) => {
println!("Error: Could not open /proc/mounts - {e}");
process::exit(1);
let mount_info = if cfg!(target_os = "macos") {
// on macOs, use mount command
match Command::new("mount").output() {
Ok(output) => String::from_utf8_lossy(&output.stdout).into_owned(),
Err(e) => {
println!("Error: Could not execute mount command - {e}");
process::exit(1);
}
}
} else {
// on Linux, read from /proc/mounts
match std::fs::read_to_string("/proc/mounts") {
Ok(contents) => contents,
Err(e) => {
println!("Error: Could not open /proc/mounts - {e}");
process::exit(1);
}
}
};
let reader = BufReader::new(&file);

let mut stats: Vec<Stats> = Vec::new();
let mut max_width = 0;

for line in reader.lines() {
match line {
Ok(line) => {
let fields: Vec<&str> = line.split_whitespace().collect();
let statvfs = match statvfs(fields[ProcFields::Mountpoint.upcast()]) {
Ok(s) => s,
Err(_) => continue, // i.e.: no permissions to read
};

if statvfs.blocks() == 0 {
continue;
}
let s = Stats::new(
fields[ProcFields::Filesystem.upcast()],
fields[ProcFields::Mountpoint.upcast()],
statvfs,
args,
);

max_width = cmp::max(max_width, s.filesystem.len());
stats.push(s);
for line in mount_info.lines() {
let fields: Vec<&str> = line.split_whitespace().collect();
if fields.len() < 2 {
continue;
}

let (filesystem, mountpoint) = if cfg!(target_os = "macos") {
// macOS mount output format: device_name on mount_point (options)
if !line.contains(" on ") {
continue;
}
let parts: Vec<&str> = line.split(" on ").collect();
if parts.len() != 2 {
continue;
}
Err(err) => println!("Error: {err}"),
let mount_parts: Vec<&str> = parts[1].split(" (").collect();
if mount_parts.is_empty() {
continue;
}
(parts[0], mount_parts[0])
} else {
// Linux format from /proc/mounts
(
fields[ProcFields::Filesystem.upcast()],
fields[ProcFields::Mountpoint.upcast()],
)
};

let statvfs = match statvfs(mountpoint) {
Ok(s) => s,
Err(_) => continue, // i.e.: no permissions to read
};

if statvfs.blocks() == 0 {
continue;
}
}

let s = Stats::new(filesystem, mountpoint, statvfs, args);

max_width = cmp::max(max_width, s.filesystem.len());
stats.push(s);
}
stats.sort();
(stats, max_width)
}
Expand Down
42 changes: 35 additions & 7 deletions src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,47 @@ pub struct Stats {

impl Stats {
pub fn new(fs: &str, mount: &str, statvfs: Statvfs, args: &ArgMatches) -> Stats {
let size_disk = statvfs.blocks() * statvfs.fragment_size();
let fragment_size = statvfs.fragment_size();
let blocks = statvfs.blocks();
let available_disk = statvfs.blocks_available() * statvfs.fragment_size();
let free_disk = statvfs.blocks_free() * statvfs.fragment_size();
// Get filesystem stats based on OS
let (blocks, blocks_available, blocks_free, total_inodes, available_inodes): (
u64,
u64,
u64,
u64,
u64,
) = {
#[cfg(target_os = "macos")]
{
(
statvfs.blocks().into(),
statvfs.blocks_available().into(),
statvfs.blocks_free().into(),
statvfs.files().into(),
statvfs.files_available().into(),
)
}
#[cfg(not(target_os = "macos"))]
{
(
statvfs.blocks(),
statvfs.blocks_available(),
statvfs.blocks_free(),
statvfs.files(),
statvfs.files_available(),
)
}
};

let total_inodes = statvfs.files();
let available_inodes = statvfs.files_available();
let fragment_size: u64 = statvfs.fragment_size();

// Calculate disk usage stats
let size_disk = blocks * fragment_size;
let available_disk = blocks_available * fragment_size;
let free_disk = blocks_free * fragment_size;
let used_disk = size_disk - free_disk;
let percent_disk = used_disk as f32 / size_disk as f32;
let pos = grouped_pos_by_length(fs);

// Calculate inode usage stats
let used_inodes = total_inodes - available_inodes;
let percent_inodes = used_inodes as f32 / total_inodes as f32;

Expand Down

0 comments on commit 99c0e9a

Please sign in to comment.