Skip to content

Commit

Permalink
Same Error type across targets
Browse files Browse the repository at this point in the history
  • Loading branch information
Speedy37 committed Sep 28, 2022
1 parent bef3a25 commit 358f105
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 68 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[package]
name = "mountpoints"
version = "0.1.1"
version = "0.2.0"
authors = ["Vincent Rouillé <[email protected]>"]
repository = "https://github.com/Speedy37/mountpoints-rs"
license = "MIT OR Apache-2.0"
edition = "2018"
description = """
List mount points (windows, linux, ...)
List mount points (windows, linux, macos)
"""

[target.'cfg(target_os = "windows")'.dependencies]
Expand Down
35 changes: 34 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,41 @@ pub struct MountInfo {
__priv: (),
}

pub use sys::{mountinfos, mountpaths, Error};
#[derive(Debug)]
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 {
Expand Down
28 changes: 6 additions & 22 deletions src/linux.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,17 @@
use crate::MountInfo;
use crate::{Error, MountInfo};
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fmt;
use std::fs;
use std::mem::MaybeUninit;
use std::os::raw::c_char;
use std::os::unix::prelude::OsStrExt;
use std::os::unix::prelude::OsStringExt;
use std::path::PathBuf;

#[derive(Debug)]
pub enum Error {
IoError(std::io::Error),
PathParseError,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::IoError(err) => write!(f, "failed to read /proc/mounts: {}", err),
Error::PathParseError => write!(f, "failed to parse path"),
}
}
}

fn _mounts(
mut cb: impl FnMut(PathBuf, bool, Option<&str>) -> Result<(), Error>,
) -> Result<(), Error> {
let mounts = fs::read("/proc/mounts").map_err(|err| Error::IoError(err))?;
let mounts = fs::read("/proc/mounts").map_err(|err| Error::LinuxIoError(err))?;
for mount in mounts.split(|b| *b == b'\n') {
// Each filesystem is described on a separate line. Fields on each
// line are separated by tabs or spaces. Lines starting with '#' are
Expand Down Expand Up @@ -98,14 +82,14 @@ fn unescape_path(path: &[u8]) -> Result<OsString, Error> {
vec.extend_from_slice(left);
loop {
if part.len() < 3 {
return Err(Error::PathParseError);
return Err(Error::LinuxPathParseError);
}
let escaped = part
.iter()
.take(3)
.try_fold(0u8, |acc, digit| match digit {
b'0'..=b'7' if acc < 0o40 => Ok(acc * 8 + (digit - b'0')),
_ => Err(Error::PathParseError),
_ => Err(Error::LinuxPathParseError),
})?;
vec.push(escaped);
vec.extend_from_slice(&part[3..]);
Expand Down Expand Up @@ -133,11 +117,11 @@ mod tests {
);
assert!(matches!(
unescape_path(b"\\54ab").unwrap_err(),
Error::PathParseError
Error::LinuxPathParseError
));
assert!(matches!(
unescape_path(b"\\666").unwrap_err(),
Error::PathParseError
Error::LinuxPathParseError
));
assert_eq!(
unescape_path(b"\\000\\377").unwrap(),
Expand Down
22 changes: 3 additions & 19 deletions src/macos.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
use crate::MountInfo;
use crate::{Error, MountInfo};
use std::ffi::{CStr, OsStr};
use std::fmt;
use std::os::raw::{c_char, c_int};
use std::os::unix::ffi::OsStrExt;
use std::path::PathBuf;

const MNT_RDONLY: u32 = libc::MNT_RDONLY as u32;

#[derive(Debug)]
pub enum Error {
GetMntInfo64(c_int),
Utf8Error,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::GetMntInfo64(err) => write!(f, "getmntinfo64 failed: {}", err),
Error::Utf8Error => write!(f, "invalid utf8 format"),
}
}
}

fn _mounts(mut cb: impl FnMut(&libc::statfs, PathBuf) -> Result<(), Error>) -> Result<(), Error> {
let mut n: i32 = unsafe { libc::getfsstat(std::ptr::null_mut(), 0, libc::MNT_NOWAIT) };
let mut mntbuf = Vec::<libc::statfs>::new();
Expand All @@ -34,7 +18,7 @@ fn _mounts(mut cb: impl FnMut(&libc::statfs, PathBuf) -> Result<(), Error>) -> R
}
}
if n < 0 {
return Err(Error::GetMntInfo64(unsafe { *libc::__error() }));
return Err(Error::MacOsGetfsstatError(unsafe { *libc::__error() }));
}
for p in &mntbuf {
let mountpath = OsStr::from_bytes(
Expand All @@ -57,7 +41,7 @@ pub fn mountinfos() -> Result<Vec<MountInfo>, Error> {
format: Some(
unsafe { CStr::from_ptr(stat.f_fstypename.as_ptr() as *const c_char) }
.to_str()
.map_err(|_| Error::Utf8Error)?
.map_err(|_| Error::MacOsUtf8Error)?
.into(),
),
readonly: Some((stat.f_flags & MNT_RDONLY) == MNT_RDONLY),
Expand Down
32 changes: 8 additions & 24 deletions src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::MountInfo;
use crate::{Error, MountInfo};
use std::ffi::OsString;
use std::fmt;
use std::os::windows::prelude::OsStringExt;
use std::path::PathBuf;
use winapi::shared::winerror;
Expand All @@ -13,30 +12,13 @@ use winapi::um::winnt::{FILE_READ_ONLY_VOLUME, ULARGE_INTEGER};

const MAX_PATH: usize = 32768;

#[derive(Debug)]
pub enum Error {
Utf16Error,
VolumeIterError(u32),
MountIterError(u32),
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Utf16Error => f.write_str("invalid utf16 path"),
Error::VolumeIterError(code) => write!(f, "unable to get list of volumes: {}", code),
Error::MountIterError(code) => write!(f, "unable to get list of mounts: {}", code),
}
}
}

fn _mounts(mut cb: impl FnMut(&[u16], PathBuf) -> Result<(), Error>) -> Result<(), Error> {
let mut ret = Ok(());
let mut name = [0u16; MAX_PATH];
let mut names_vec = Vec::<u16>::new();
let handle = unsafe { FindFirstVolumeW(name.as_mut_ptr(), name.len() as u32) };
if handle == INVALID_HANDLE_VALUE {
return Err(Error::VolumeIterError(unsafe { GetLastError() }));
return Err(Error::WindowsVolumeIterError(unsafe { GetLastError() }));
}
loop {
let mut names = [0u16; MAX_PATH];
Expand Down Expand Up @@ -66,7 +48,7 @@ fn _mounts(mut cb: impl FnMut(&[u16], PathBuf) -> Result<(), Error>) -> Result<(
if ok == 0 {
let err = unsafe { GetLastError() };
if err != winerror::ERROR_FILE_NOT_FOUND {
ret = Err(Error::MountIterError(err));
ret = Err(Error::WindowsMountIterError(err));
break;
}
} else {
Expand All @@ -80,7 +62,7 @@ fn _mounts(mut cb: impl FnMut(&[u16], PathBuf) -> Result<(), Error>) -> Result<(
if more == 0 {
let err = unsafe { GetLastError() };
if err != winerror::ERROR_NO_MORE_FILES {
ret = Err(Error::VolumeIterError(err));
ret = Err(Error::WindowsVolumeIterError(err));
}
break;
}
Expand Down Expand Up @@ -145,10 +127,12 @@ pub fn mountinfos() -> Result<Vec<MountInfo>, Error> {
};
if ok != 0 {
if let Some(slice) = name.split(|&c| c == 0).next() {
info.name = Some(String::from_utf16(slice).map_err(|_| Error::Utf16Error)?);
info.name =
Some(String::from_utf16(slice).map_err(|_| Error::WindowsUtf16Error)?);
}
if let Some(slice) = fsname.split(|&c| c == 0).next() {
info.format = Some(String::from_utf16(slice).map_err(|_| Error::Utf16Error)?);
info.format =
Some(String::from_utf16(slice).map_err(|_| Error::WindowsUtf16Error)?);
}
info.readonly = Some((flags & FILE_READ_ONLY_VOLUME) == FILE_READ_ONLY_VOLUME);
info.dummy = false;
Expand Down

0 comments on commit 358f105

Please sign in to comment.