1use arcbox_error::CommonError;
4use thiserror::Error;
5
6pub type Result<T> = std::result::Result<T, FsError>;
8
9#[derive(Debug, Error)]
11pub enum FsError {
12 #[error(transparent)]
14 Common(#[from] CommonError),
15
16 #[error("invalid path: {0}")]
18 InvalidPath(String),
19
20 #[error("operation not supported: {0}")]
22 NotSupported(String),
23
24 #[error("FUSE error: {0}")]
26 Fuse(String),
27
28 #[error("cache error: {0}")]
30 Cache(String),
31
32 #[error("invalid file handle: {0}")]
34 InvalidHandle(u64),
35}
36
37impl From<std::io::Error> for FsError {
38 fn from(err: std::io::Error) -> Self {
39 Self::Common(CommonError::from(err))
40 }
41}
42
43impl FsError {
44 #[must_use]
46 pub fn io(err: std::io::Error) -> Self {
47 Self::Common(CommonError::Io(err))
48 }
49
50 #[must_use]
52 pub fn not_found(path: impl Into<String>) -> Self {
53 Self::Common(CommonError::not_found(path))
54 }
55
56 #[must_use]
58 pub fn permission_denied(path: impl Into<String>) -> Self {
59 Self::Common(CommonError::permission_denied(path))
60 }
61
62 #[must_use]
64 pub fn is_not_found(&self) -> bool {
65 matches!(self, Self::Common(CommonError::NotFound(_)))
66 }
67
68 #[must_use]
70 pub fn to_errno(&self) -> i32 {
71 match self {
72 Self::Common(e) => Self::common_to_errno(e),
73 Self::InvalidPath(_) => libc::EINVAL,
74 Self::NotSupported(_) => libc::ENOSYS,
75 Self::Fuse(_) | Self::Cache(_) => libc::EIO,
76 Self::InvalidHandle(_) => libc::EBADF,
77 }
78 }
79
80 fn common_to_errno(err: &CommonError) -> i32 {
82 match err {
83 CommonError::Io(e) => {
84 let raw = e.raw_os_error().unwrap_or(libc::EIO);
85 Self::host_errno_to_linux(raw)
86 }
87 CommonError::NotFound(_) => libc::ENOENT,
88 CommonError::PermissionDenied(_) => libc::EACCES,
89 CommonError::AlreadyExists(_) => libc::EEXIST,
90 CommonError::Config(_)
91 | CommonError::InvalidState(_)
92 | CommonError::Timeout(_)
93 | CommonError::Internal(_) => libc::EIO,
94 }
95 }
96
97 #[cfg(target_os = "macos")]
103 fn host_errno_to_linux(errno: i32) -> i32 {
104 const MACOS_ENOATTR: i32 = 93;
109 const LINUX_ENODATA: i32 = 61;
110
111 match errno {
112 MACOS_ENOATTR => LINUX_ENODATA,
113 _ => errno,
114 }
115 }
116
117 #[cfg(not(target_os = "macos"))]
118 fn host_errno_to_linux(errno: i32) -> i32 {
119 errno
120 }
121}