use std::path::{Component, Path, PathBuf, Prefix};
use kernel::degradation::VolumeSpace;
use sysinfo::{Disk, Disks};
pub(crate) fn read(city: &Path) -> Option<VolumeSpace> {
space(&Disks::new_with_refreshed_list(), &resolved(city)?)
}
pub(crate) fn resolved(city: &Path) -> Option<PathBuf> {
std::fs::canonicalize(city)
.or_else(|_| std::path::absolute(city))
.ok()
.map(|city| without_verbatim_disk(&city))
}
fn without_verbatim_disk(path: &Path) -> PathBuf {
let mut components = path.components();
match components.next() {
Some(Component::Prefix(prefix)) => match prefix.kind() {
Prefix::VerbatimDisk(letter) => {
let mut plain = PathBuf::from(format!("{}:", char::from(letter)));
plain.extend(components);
plain
}
Prefix::Verbatim(_)
| Prefix::VerbatimUNC(..)
| Prefix::DeviceNS(_)
| Prefix::UNC(..)
| Prefix::Disk(_) => path.to_path_buf(),
},
Some(
Component::RootDir | Component::CurDir | Component::ParentDir | Component::Normal(_),
)
| None => path.to_path_buf(),
}
}
pub(crate) fn space(disks: &Disks, city: &Path) -> Option<VolumeSpace> {
holding(disks, city).map(|disk| VolumeSpace {
free_bytes: disk.available_space(),
total_bytes: disk.total_space(),
})
}
pub(crate) fn holding<'d>(disks: &'d Disks, city: &Path) -> Option<&'d Disk> {
disks
.list()
.iter()
.filter(|disk| city.starts_with(disk.mount_point()))
.max_by_key(|disk| disk.mount_point().components().count())
}
#[cfg(test)]
#[path = "volume/tests.rs"]
mod tests;