1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! `sys_metrics` is a crate used to get a system's information.
//!
//! It provide information about:
//!
//!  * CPU
//!  * Disks
//!  * Host
//!  * Memory
//!  * Network
//!  * Virtualization
//!
//! ## Quick start
//! ```
//! use sys_metrics::{cpu::*};
//!
//! // This is just a very basic example of the CPU part.
//! // Check the doc, this crate can do much more.
//! let cpufreq = get_cpufreq().unwrap();
//! println!("CPU Speed: {:13}MHz\n", cpufreq as u64);
//!
//! let cpu_logical = get_logical_count().unwrap();
//! let cpu_physical = get_physical_count().unwrap();
//!
//! println!("CPU Core: {:12}\nLogical processors: {}", cpu_physical, cpu_logical);
//!
//! let loadavg = get_loadavg().unwrap();
//! println!("Load average: {:10} {} {}", loadavg.one, loadavg.five, loadavg.fifteen);
//! ```

#[cfg(target_os = "linux")]
macro_rules! nth {
    ($a:expr, $b:expr) => {
        match $a.nth($b) {
            Some(val) => Ok(val),
            None => Err(Error::new(
                ErrorKind::Other,
                "The fields asked for does not exists",
            )),
        }
    };
}

/// CPU information
pub mod cpu;
/// Disks information
pub mod disks;
/// Host system information
pub mod host;
/// Memory information
pub mod memory;
/// Network information
pub mod network;
/// Virtualization information
pub mod virt;

#[cfg(target_os = "macos")]
pub mod macos_binding;
#[cfg(target_os = "macos")]
pub mod macos_utils;
#[cfg(target_os = "macos")]
pub(crate) use macos_binding as binding;
#[cfg(target_os = "macos")]
pub(crate) use macos_utils as utils;

use libc::c_char;
use std::ffi::CStr;
#[cfg(target_os = "linux")]
use std::fs;
use std::io::Error;

#[cfg(target_os = "macos")]
lazy_static::lazy_static! {
    static ref PAGE_SIZE: u64 = {
        unsafe {
            libc::sysconf(libc::_SC_PAGESIZE) as u64
        }
    };
}

/// Function used if you want to divide ticked value by the host's jiffies (USER_HZ) value. (like CpuStats)
///
/// See <https://en.wikipedia.org/wiki/Jiffy_(time)> for more information.
pub fn clock_ticks() -> Result<u64, Error> {
    let result = unsafe { libc::sysconf(libc::_SC_CLK_TCK) };

    if result > 0 {
        Ok(result as u64)
    } else {
        Err(Error::last_os_error())
    }
}

lazy_static::lazy_static! {
    /// Time units in jiffies (USER_HZ) (https://en.wikipedia.org/wiki/Jiffy_(time))
    pub(crate) static ref CLOCK_TICKS: u64 = clock_ticks().expect("Unable to determine CPU number of ticks per second");
}

/// Read from path to content, trim it and return the String
#[cfg(target_os = "linux")]
pub(crate) fn read_and_trim<P>(path: P) -> Result<String, Error>
where
    P: AsRef<std::path::Path>,
{
    let content = fs::read_to_string(path)?;
    Ok(content.trim().to_owned())
}

/// Convert c_char (string in C) to a str in Rust
#[inline]
pub(crate) fn to_str<'a>(s: *const c_char) -> &'a str {
    unsafe {
        let res = CStr::from_ptr(s).to_bytes();
        std::str::from_utf8_unchecked(res)
    }
}