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
//! `sys_metrics` is a crate used to get a system's information.

pub mod cpu;
pub mod disks;
pub mod memory;
pub mod miscs;
mod models;
pub mod network;
pub mod users;

pub use models::*;

#[cfg(target_os = "macos")]
use mach::vm_types::integer_t;
#[cfg(target_os = "linux")]
use std::fs;

use nix::sys;
use std::io::{Error, ErrorKind};
use std::path::Path;

#[allow(non_camel_case_types)]
#[cfg(target_os = "macos")]
type host_flavor_t = integer_t;
#[allow(non_camel_case_types)]
#[cfg(target_os = "macos")]
type host_info64_t = *mut integer_t;

// Static reference to the page_size for memory
#[cfg(target_os = "macos")]
lazy_static::lazy_static! {
    static ref PAGE_SIZE: u64 = {
        unsafe {
            libc::sysconf(libc::_SC_PAGESIZE) as u64
        }
    };
}

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

/// Detect if a filesysteme is for a physical drive or not.
/// This is not 100% true, but it's true enough for me.
pub(crate) fn is_physical_filesys(filesysteme: &str) -> bool {
    match filesysteme {
        "ext2" => true,
        "ext3" => true,
        "ext4" => true,
        "vfat" => true,
        "ntfs" => true,
        "zfs" => true,
        "hfs" => true,
        "reiserfs" => true,
        "reiser4" => true,
        "exfat" => true,
        "f2fs" => true,
        "hfsplus" => true,
        "jfs" => true,
        "btrfs" => true,
        "minix" => true,
        "nilfs" => true,
        "xfs" => true,
        "apfs" => true,
        "fuseblk" => true,
        _ => false,
    }
}

/// Return the total/free space of a Disk from it's path (mount_point).
/// For both Linux and macOS.
pub(crate) fn disk_usage<P>(path: P) -> Result<(u64, u64), Error>
where
    P: AsRef<Path>,
{
    let statvfs = match sys::statvfs::statvfs(path.as_ref()) {
        Ok(val) => val,
        Err(x) => return Err(Error::new(ErrorKind::Other, x)),
    };
    let total = statvfs.blocks() as u64 * statvfs.fragment_size() as u64;
    let free = statvfs.blocks_available() as u64 * statvfs.fragment_size() as u64;

    Ok((total, free))
}