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
use {
    super::*,
    lazy_regex::*,
};

/// what we have most looking like a physical device
#[derive(Debug, Clone)]
pub struct Disk {
    /// a name, like "sda", "sdc", "nvme0n1", etc.
    pub name: String,

    /// true for HDD, false for SSD, None for unknown.
    /// This information isn't reliable for USB devices
    pub rotational: Option<bool>,

    /// whether the system thinks the media is removable.
    /// Seems reliable when not mapped
    pub removable: Option<bool>,

    /// whether it's a RAM disk
    pub ram: bool,

    /// whether it's on LVM
    pub lvm: bool,

    /// whether it's a crypted disk
    pub crypted: bool,
}

impl Disk {
    pub fn new(name: String) -> Self {
        let rotational = sys::read_file_as_bool(&format!("/sys/block/{}/queue/rotational", name));
        let removable = sys::read_file_as_bool(&format!("/sys/block/{}/removable", name));
        let ram = regex_is_match!(r#"^zram\d*$"#, &name);
        let dm_uuid = sys::read_file(&format!("/sys/block/{}/dm/uuid", name)).ok();
        let crypted = dm_uuid
            .as_ref()
            .map_or(false, |uuid| uuid.starts_with("CRYPT-"));
        let lvm = dm_uuid.map_or(false, |uuid| uuid.starts_with("LVM-"));
        Self {
            name,
            rotational,
            removable,
            ram,
            lvm,
            crypted,
        }
    }
    /// a synthetic code trying to express the essence of the type of media,
    /// an empty str being returned when information couldn't be gathered.
    /// This code is for humans and may change in future minor versions.
    pub fn disk_type(&self) -> &'static str {
        if self.ram {
            "RAM"
        } else if self.crypted {
            "crypt"
        } else if self.lvm {
            "LVM"
        } else {
            match (self.removable, self.rotational) {
                (Some(true), _) => "remov",
                (Some(false), Some(true)) => "HDD",
                (Some(false), Some(false)) => "SSD",
                _ => "",
            }
        }
    }
}