use anyhow::Result;
pub(crate) fn format_bytes(bytes: u64) -> String {
const UNITS: [&str; 5] = ["B", "KiB", "MiB", "GiB", "TiB"];
let mut value = bytes as f64;
let mut unit = 0usize;
while value >= 1024.0 && unit < UNITS.len() - 1 {
value /= 1024.0;
unit += 1;
}
if unit == 0 {
format!("{bytes} {}", UNITS[unit])
} else {
format!("{value:.1} {}", UNITS[unit])
}
}
pub(crate) fn chrono_humanize_timestamp(ts: u64) -> String {
use std::time::{Duration, SystemTime, UNIX_EPOCH};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or(Duration::ZERO)
.as_secs();
let diff = now.saturating_sub(ts);
if diff < 60 {
format!("{}s ago", diff)
} else if diff < 3600 {
format!("{}m ago", diff / 60)
} else if diff < 86400 {
format!("{}h ago", diff / 3600)
} else {
format!("{}d ago", diff / 86400)
}
}
#[cfg(unix)]
pub(crate) fn process_is_running(pid: u32) -> bool {
let Ok(pid) = i32::try_from(pid) else {
return false;
};
let result = unsafe { libc::kill(pid, 0) };
if result == 0 {
return true;
}
let err = std::io::Error::last_os_error();
match err.raw_os_error() {
Some(code) if code == libc::ESRCH => false,
Some(code) if code == libc::EPERM => true,
_ => false,
}
}
#[cfg(not(unix))]
pub(crate) fn process_is_running(_pid: u32) -> bool {
true
}
#[allow(dead_code)]
pub(crate) fn dir_size(path: &std::path::Path) -> Result<u64> {
let mut size = 0;
for entry in std::fs::read_dir(path)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
size += dir_size(&path)?;
} else {
size += entry.metadata()?.len();
}
}
Ok(size)
}