use std::ffi;
use std::io::Read;
use std::fs::File;
#[repr(C)]
pub struct LoadAvg {
pub one: f64,
pub five: f64,
pub fifteen: f64
}
#[repr(C)]
pub struct MemInfo {
pub total: u64,
pub free: u64,
pub avail: u64,
pub buffers: u64,
pub cached: u64,
pub swap_total: u64,
pub swap_free: u64
}
#[repr(C)]
pub struct DiskInfo {
pub total: u64,
pub free: u64
}
extern {
fn get_os_type() -> *const i8;
fn get_os_release() -> *const i8;
fn get_cpu_num() -> u32;
fn get_cpu_speed() -> u64;
fn get_loadavg() -> LoadAvg;
fn get_proc_total() -> u64;
fn get_mem_info() -> MemInfo;
fn get_disk_info() -> DiskInfo;
}
pub fn os_type() -> Result<String, String> {
if cfg!(target_os = "linux") {
let mut s = String::new();
let mut f = File::open("/proc/sys/kernel/ostype").unwrap();
let _ = f.read_to_string(&mut s).unwrap();
s.pop(); Ok(s)
} else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
unsafe { Ok(String::from_utf8_lossy(ffi::CStr::from_ptr(get_os_type())
.to_bytes()).into_owned()) }
} else {
Err("Unsupported system".to_string())
}
}
pub fn os_release() -> Result<String, String> {
if cfg!(target_os = "linux") {
let mut f = File::open("/proc/sys/kernel/osrelease").unwrap();
let mut s = String::new();
let _ = f.read_to_string(&mut s).unwrap();
s.pop();
Ok(s)
} else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
unsafe { Ok(String::from_utf8_lossy(
ffi::CStr::from_ptr(get_os_release()).to_bytes()).into_owned()) }
} else {
Err("Unsupported system".to_string())
}
}
pub fn cpu_num() -> Result<u32, String> {
if cfg!(unix) || cfg!(windows) {
unsafe { Ok(get_cpu_num()) }
} else {
Err("Unsupported system".to_string())
}
}
pub fn cpu_speed() -> Result<u64, String> {
if cfg!(target_os = "linux") {
let mut f = File::open("/proc/cpuinfo").unwrap();
let mut s = String::new();
let _ = f.read_to_string(&mut s).unwrap();
let mut lines = s.split('\n');
for _ in 0..7 {
lines.next();
}
let mut words = lines.next().unwrap().split(':');
words.next();
let s = words.next().unwrap().trim().trim_right_matches('\n');
Ok(s.parse::<f64>().unwrap() as u64)
} else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
unsafe { Ok(get_cpu_speed()) }
} else {
Err("Unsupported system".to_string())
}
}
pub fn loadavg() -> Result<LoadAvg, String> {
if cfg!(target_os = "linux") {
let mut f = File::open("/proc/loadavg").unwrap();
let mut s = String::new();
let _ = f.read_to_string(&mut s).unwrap();
let mut words = s.split(' ');
let one = words.next().unwrap().parse::<f64>().unwrap();
let five = words.next().unwrap().parse::<f64>().unwrap();
let fifteen = words.next().unwrap().parse::<f64>().unwrap();
Ok(LoadAvg { one: one, five: five, fifteen: fifteen} )
} else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
Ok(unsafe { get_loadavg() })
} else {
Err("Unsupported system".to_string())
}
}
pub fn proc_total() -> Result<u64, String> {
if cfg!(target_os = "linux") {
let mut f = File::open("/proc/loadavg").unwrap();
let mut s = String::new();
let _ = f.read_to_string(&mut s).unwrap();
Ok({
let mut words = s.splitn(3, ' ');
for _ in 0..3 {
words.next();
}
let mut words = words.next().unwrap().split('/');
words.next();
let mut words = words.next().unwrap().split(' ');
words.next().unwrap().parse::<u64>().unwrap()
})
} else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
Ok(unsafe { get_proc_total() })
} else {
Err("Unsupported system".to_string())
}
}
fn get_mem_num(line: &str) -> u64 {
let mut line = line.splitn(1, ' ');
line.next();
line.next().unwrap().trim_left().split(' ').next().unwrap()
.parse::<u64>().unwrap()
}
pub fn mem_info() -> Result<MemInfo, String> {
if cfg!(target_os = "linux") {
let mut f = File::open("/proc/meminfo").unwrap();
let mut s = String::new();
let _ = f.read_to_string(&mut s).unwrap();
let mut lines = s.split('\n');
let total = get_mem_num(lines.next().unwrap());
let free = get_mem_num(lines.next().unwrap());
let avail = get_mem_num(lines.next().unwrap());
let buffers = get_mem_num(lines.next().unwrap());
let cached = get_mem_num(lines.next().unwrap());
let swap_total = {
for _ in 0..9 {
lines.next();
}
get_mem_num(lines.next().unwrap())
};
let swap_free = get_mem_num(lines.next().unwrap());
Ok(MemInfo{ total: total, free: free, avail: avail,
buffers: buffers, cached: cached,
swap_total: swap_total, swap_free: swap_free})
} else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
Ok(unsafe { get_mem_info() })
} else {
Err("Unsupported system".to_string())
}
}
pub fn disk_info() -> Result<DiskInfo, String> {
if cfg!(target_os = "linux") ||
cfg!(target_os = "macos") ||
cfg!(target_os = "windows")
{
Ok(unsafe { get_disk_info() })
} else {
Err("Unsupported system".to_string())
}
}
pub fn hostname() -> Result<String, String> {
use std::process::Command;
if cfg!(unix) {
let output = match Command::new("hostname").output() {
Ok(o) => o,
Err(e) => return Err(format!("failed to execute process: {}", e)),
};
let mut s = String::from_utf8(output.stdout).unwrap();
s.pop(); Ok(s)
} else if cfg!(windows) {
let output = match Command::new("hostname").output() {
Ok(o) => o,
Err(e) => return Err(format!("failed to execute process: {}", e)),
};
let mut s = String::from_utf8(output.stdout).unwrap();
s.pop(); Ok(s)
} else {
Err("Unsupported system".to_string())
}
}