use arcbox_error::CommonError;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, FsError>;
#[derive(Debug, Error)]
pub enum FsError {
#[error(transparent)]
Common(#[from] CommonError),
#[error("invalid path: {0}")]
InvalidPath(String),
#[error("operation not supported: {0}")]
NotSupported(String),
#[error("FUSE error: {0}")]
Fuse(String),
#[error("cache error: {0}")]
Cache(String),
#[error("invalid file handle: {0}")]
InvalidHandle(u64),
}
impl From<std::io::Error> for FsError {
fn from(err: std::io::Error) -> Self {
Self::Common(CommonError::from(err))
}
}
impl FsError {
#[must_use]
pub fn io(err: std::io::Error) -> Self {
Self::Common(CommonError::Io(err))
}
#[must_use]
pub fn not_found(path: impl Into<String>) -> Self {
Self::Common(CommonError::not_found(path))
}
#[must_use]
pub fn permission_denied(path: impl Into<String>) -> Self {
Self::Common(CommonError::permission_denied(path))
}
#[must_use]
pub fn is_not_found(&self) -> bool {
matches!(self, Self::Common(CommonError::NotFound(_)))
}
#[must_use]
pub fn to_errno(&self) -> i32 {
match self {
Self::Common(e) => Self::common_to_errno(e),
Self::InvalidPath(_) => libc::EINVAL,
Self::NotSupported(_) => libc::ENOSYS,
Self::Fuse(_) | Self::Cache(_) => libc::EIO,
Self::InvalidHandle(_) => libc::EBADF,
}
}
fn common_to_errno(err: &CommonError) -> i32 {
match err {
CommonError::Io(e) => {
let raw = e.raw_os_error().unwrap_or(libc::EIO);
Self::host_errno_to_linux(raw)
}
CommonError::NotFound(_) => libc::ENOENT,
CommonError::PermissionDenied(_) => libc::EACCES,
CommonError::AlreadyExists(_) => libc::EEXIST,
CommonError::Config(_)
| CommonError::InvalidState(_)
| CommonError::Timeout(_)
| CommonError::Internal(_) => libc::EIO,
}
}
#[cfg(target_os = "macos")]
fn host_errno_to_linux(errno: i32) -> i32 {
const MACOS_ENOATTR: i32 = 93;
const LINUX_ENODATA: i32 = 61;
match errno {
MACOS_ENOATTR => LINUX_ENODATA,
_ => errno,
}
}
#[cfg(not(target_os = "macos"))]
fn host_errno_to_linux(errno: i32) -> i32 {
errno
}
}