#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "windows")]
mod windows;
use std::path::PathBuf;
#[cfg(target_os = "linux")]
use linux as sys;
#[cfg(target_os = "macos")]
use macos as sys;
#[cfg(target_os = "windows")]
use windows as sys;
#[derive(Debug, Clone)]
pub struct MountInfo {
pub path: PathBuf,
pub avail: Option<u64>,
pub free: Option<u64>,
pub size: Option<u64>,
pub name: Option<String>,
pub format: Option<String>,
pub readonly: Option<bool>,
pub dummy: bool,
__priv: (),
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
WindowsUtf16Error,
WindowsVolumeIterError(u32),
WindowsMountIterError(u32),
LinuxIoError(std::io::Error),
LinuxPathParseError,
MacOsGetfsstatError(i32),
MacOsUtf8Error,
}
impl std::error::Error for Error {}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::WindowsUtf16Error => f.write_str("invalid utf16 path"),
Error::WindowsVolumeIterError(code) => {
write!(f, "unable to get list of volumes: {}", code)
}
Error::WindowsMountIterError(code) => {
write!(f, "unable to get list of mounts: {}", code)
}
Error::LinuxIoError(err) => write!(f, "failed to read /proc/mounts: {}", err),
Error::LinuxPathParseError => write!(f, "failed to parse path"),
Error::MacOsGetfsstatError(err) => write!(f, "getfsstat failed: {}", err),
Error::MacOsUtf8Error => write!(f, "invalid utf8 format"),
}
}
}
pub fn mountinfos() -> Result<Vec<MountInfo>, Error> {
sys::mountinfos()
}
pub fn mountpaths() -> Result<Vec<PathBuf>, Error> {
sys::mountpaths()
}
#[cfg(test)]
mod tests {
use std::path::Path;
use super::*;
fn root() -> &'static Path {
if cfg!(target_os = "windows") {
Path::new("C:\\")
} else {
Path::new("/")
}
}
#[test]
fn mountpaths_works() {
let paths = mountpaths().unwrap();
assert!(paths.len() > 0);
assert!(paths.iter().any(|p| p == root()));
for mountpath in &paths {
eprintln!("{:?}", mountpath);
}
}
#[test]
fn mountinfosworks() {
let infos = mountinfos().unwrap();
assert!(infos.len() > 0);
assert!(infos.iter().any(|i| if i.path == root() {
assert!(i.size.unwrap_or_default() > 1024 * 1024); assert!(i.avail.unwrap_or_default() < i.size.unwrap_or_default());
assert!(i.free.unwrap_or_default() < i.size.unwrap_or_default());
true
} else {
false
}));
for mountinfo in &infos {
eprintln!("{:?}", mountinfo);
}
}
}