libglacierdisk/
kind.rs

1use std::{
2  fmt::Display,
3  path::{Path, PathBuf},
4};
5
6/// A struct representing the kind of disk (SSD, HDD, etc.)
7#[derive(Clone, PartialEq, Debug)]
8pub enum DiskKind {
9  SSD,
10  HDD,
11  NVME,
12  USB,
13}
14
15impl Display for DiskKind {
16  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17    match self {
18      DiskKind::SSD => write!(f, "SSD"),
19      DiskKind::HDD => write!(f, "HDD"),
20      DiskKind::NVME => write!(f, "NVME"),
21      DiskKind::USB => write!(f, "USB"),
22    }
23  }
24}
25
26/// Get the kind of disk from a path or [`super::Disk`]
27pub fn disk_class(disk: impl AsRef<Path>) -> DiskKind {
28  let disk = disk.as_ref();
29  let drive = disk
30    .file_name()
31    .unwrap_or_default()
32    .to_str()
33    .unwrap_or_default();
34
35  // Read disk type
36  if drive.starts_with("nvme") {
37    return DiskKind::NVME;
38  }
39
40  // Check first if it's a USB disk
41  let link = PathBuf::from(format!("/sys/block/{drive}"));
42  if link.exists() {
43    let link = std::fs::read_link(link).unwrap_or_default();
44    if link.to_str().unwrap_or_default().contains("/usb") {
45      return DiskKind::USB;
46    }
47  }
48
49  let sys_class = PathBuf::from(format!("/sys/class/block/{drive}/queue/rotational"));
50
51  // 1 = HDD, 0 = SSD
52  if sys_class.exists() {
53    let rotational = std::fs::read_to_string(sys_class).unwrap_or_default();
54    let rotational = rotational.trim();
55    if rotational == "1" {
56      return DiskKind::HDD;
57    }
58  }
59
60  DiskKind::SSD
61}