btrfsutil/error/
lib.rs

1use crate::error::GlueError;
2use crate::BtrfsUtilError;
3use crate::Result;
4
5#[cfg(feature = "enable-glue-errors")]
6use std::convert::Into;
7use std::convert::TryFrom;
8use std::ffi::CStr;
9use std::os::raw::c_char;
10
11use thiserror::Error;
12
13/// Error code returned by the [libbtrfsutil] C library.
14///
15/// [libbtrfsutil]: https://github.com/kdave/btrfs-progs/tree/master/libbtrfsutil
16pub(crate) type LibErrorCode = u32;
17
18/// Errors that can be raised by the [libbtrfsutil] C library itself.
19///
20/// [libbtrfsutil]: https://github.com/kdave/btrfs-progs/tree/master/libbtrfsutil
21#[derive(Clone, Debug, Eq, Error, PartialEq)]
22pub enum LibError {
23    /// Success
24    #[error("Success")]
25    Ok = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_OK as isize,
26    /// Stop iteration
27    #[error("Stop iteration")]
28    StopIteration = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STOP_ITERATION as isize,
29    /// Cannot allocate memory
30    #[error("Cannot allocate memory")]
31    NoMemory = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NO_MEMORY as isize,
32    /// Invalid argument
33    #[error("Invalid argument")]
34    InvalidArgument = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INVALID_ARGUMENT as isize,
35    /// Not a Btrfs filesystem
36    #[error("Not a Btrfs filesystem")]
37    NotBtrfs = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_BTRFS as isize,
38    /// Not a Btrfs subvolume
39    #[error("Not a Btrfs subvolume")]
40    NotSubvolume = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_SUBVOLUME as isize,
41    /// Subvolume not found
42    #[error("Subvolume not found")]
43    SubvolumeNotFound =
44        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND as isize,
45    /// Could not open
46    #[error("Could not open")]
47    OpenFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_OPEN_FAILED as isize,
48    /// Could nor rmdir
49    #[error("Could not rmdir")]
50    RmdirFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_RMDIR_FAILED as isize,
51    /// Could not unlink
52    #[error("Could not unlink")]
53    UnlinkFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_UNLINK_FAILED as isize,
54    /// Could not stat
55    #[error("Could not stat")]
56    StatFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STAT_FAILED as isize,
57    /// Could not statfs
58    #[error("Could not statfs")]
59    StatfsFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STATFS_FAILED as isize,
60    /// Could not search B-tree
61    #[error("Could not search B-tree")]
62    SearchFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SEARCH_FAILED as isize,
63    /// Could not lookup inode
64    #[error("Could not lookup inode")]
65    InoLookupFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_FAILED as isize,
66    /// Could not get subvolume flags
67    #[error("Could not get subvolume flags")]
68    SubvolGetflagsFailed =
69        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_GETFLAGS_FAILED as isize,
70    /// Could not set subvolume flags
71    #[error("Could not set subvolume flags")]
72    SubvolSetflagsFailed =
73        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_SETFLAGS_FAILED as isize,
74    /// Could not create subvolume
75    #[error("Could not create subvolume")]
76    SubvolCreateFailed =
77        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_CREATE_FAILED as isize,
78    /// Could not create snapshot
79    #[error("Could not create snapshot")]
80    SnapCreateFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_CREATE_FAILED as isize,
81    /// Could not destroy subvolume/snapshot
82    #[error("Could not destroy subvolume/snapshot")]
83    SnapDestroyFailed =
84        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_DESTROY_FAILED as isize,
85    /// Could not set default subvolume
86    #[error("Could not set default subvolume")]
87    DefaultSubvolFailed =
88        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_DEFAULT_SUBVOL_FAILED as isize,
89    /// Could not sync filesystem
90    #[error("Could not sync filesystem")]
91    SyncFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SYNC_FAILED as isize,
92    /// Could not start filesystem sync
93    #[error("Could not start filesystem sync")]
94    StartSyncFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_START_SYNC_FAILED as isize,
95    /// Could not wait for filesystem sync
96    #[error("Could not wait for filesystem sync")]
97    WaitSyncFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_WAIT_SYNC_FAILED as isize,
98    /// Could not get subvolume information with BTRFS_IOC_GET_SUBVOL_INFO
99    #[error("Could not get subvolume information with BTRFS_IOC_GET_SUBVOL_INFO")]
100    GetSubvolInfoFailed =
101        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_INFO_FAILED as isize,
102    /// Could not get rootref information with BTRFS_IOC_GET_SUBVOL_ROOTREF
103    #[error("Could not get rootref information with BTRFS_IOC_GET_SUBVOL_ROOTREF")]
104    GetSubvolRootrefFailed =
105        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_ROOTREF_FAILED as isize,
106    /// Could not resolve subvolume path with BTRFS_IOC_INO_LOOKUP_USER
107    #[error("Could not resolve subvolume path with BTRFS_IOC_INO_LOOKUP_USER")]
108    InoLookupUserFailed =
109        btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_USER_FAILED as isize,
110    /// Could not get filesystem information
111    #[error("Could not get filesystem information")]
112    FsInfoFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_FS_INFO_FAILED as isize,
113}
114
115impl LibError {
116    /// Get the string description of a [LibError], using the [btrfs_util_strerror()] function
117    /// provided by [libbtrfsutil].
118    ///
119    /// [LibError] provides an [std::fmt::Display] implementation provided by [thiserror]. This
120    /// function should not be the preferred mechanism for obtaining the error message.
121    ///
122    /// [LibError]: enum.LibError.html
123    /// [btrfs_util_strerror()]: ../bindings/fn.btrfs_util_strerror.html
124    /// [std::fmt::Display]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html
125    /// [thiserror]: https://docs.rs/thiserror/1.0.16/thiserror/
126    /// [libbtrfsutil]: https://github.com/kdave/btrfs-progs/tree/master/libbtrfsutil
127    pub fn strerror(&self) -> Result<&'static str> {
128        let err_str_ptr: *const c_char;
129
130        let errno = self.clone() as LibErrorCode;
131        unsafe {
132            err_str_ptr = btrfsutil_sys::btrfs_util_strerror(errno);
133        }
134
135        glue_error!(err_str_ptr.is_null(), GlueError::NullPointerReceived);
136
137        let cstr: &CStr = unsafe { CStr::from_ptr(err_str_ptr) };
138        match cstr.to_str() {
139            Ok(val) => Ok(val),
140            Err(e) => glue_error!(GlueError::Utf8Error(e)),
141        }
142    }
143}
144
145impl TryFrom<LibErrorCode> for LibError {
146    type Error = BtrfsUtilError;
147    fn try_from(errno: LibErrorCode) -> Result<Self> {
148        glue_error!(errno > 26, GlueError::UnknownErrno(errno));
149        match errno {
150            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_OK => Ok(LibError::Ok),
151            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STOP_ITERATION => {
152                Ok(LibError::StopIteration)
153            }
154            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NO_MEMORY => Ok(LibError::NoMemory),
155            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INVALID_ARGUMENT => {
156                Ok(LibError::InvalidArgument)
157            }
158            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_BTRFS => Ok(LibError::NotBtrfs),
159            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_SUBVOLUME => {
160                Ok(LibError::NotSubvolume)
161            }
162            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND => {
163                Ok(LibError::SubvolumeNotFound)
164            }
165            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_OPEN_FAILED => {
166                Ok(LibError::OpenFailed)
167            }
168            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_RMDIR_FAILED => {
169                Ok(LibError::RmdirFailed)
170            }
171            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_UNLINK_FAILED => {
172                Ok(LibError::UnlinkFailed)
173            }
174            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STAT_FAILED => {
175                Ok(LibError::StatFailed)
176            }
177            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STATFS_FAILED => {
178                Ok(LibError::StatfsFailed)
179            }
180            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SEARCH_FAILED => {
181                Ok(LibError::SearchFailed)
182            }
183            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_FAILED => {
184                Ok(LibError::InoLookupFailed)
185            }
186            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_GETFLAGS_FAILED => {
187                Ok(LibError::SubvolGetflagsFailed)
188            }
189            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_SETFLAGS_FAILED => {
190                Ok(LibError::SubvolSetflagsFailed)
191            }
192            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_CREATE_FAILED => {
193                Ok(LibError::SubvolCreateFailed)
194            }
195            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_CREATE_FAILED => {
196                Ok(LibError::SnapCreateFailed)
197            }
198            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_DESTROY_FAILED => {
199                Ok(LibError::SnapDestroyFailed)
200            }
201            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_DEFAULT_SUBVOL_FAILED => {
202                Ok(LibError::DefaultSubvolFailed)
203            }
204            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SYNC_FAILED => {
205                Ok(LibError::SyncFailed)
206            }
207            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_START_SYNC_FAILED => {
208                Ok(LibError::StartSyncFailed)
209            }
210            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_WAIT_SYNC_FAILED => {
211                Ok(LibError::WaitSyncFailed)
212            }
213            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_INFO_FAILED => {
214                Ok(LibError::GetSubvolInfoFailed)
215            }
216            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_ROOTREF_FAILED => {
217                Ok(LibError::GetSubvolRootrefFailed)
218            }
219            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_USER_FAILED => {
220                Ok(LibError::InoLookupUserFailed)
221            }
222            btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_FS_INFO_FAILED => {
223                Ok(LibError::FsInfoFailed)
224            }
225            _ => glue_error!(GlueError::UnknownErrno(errno)),
226        }
227    }
228}
229
230#[cfg(feature = "enable-glue-errors")]
231impl Into<BtrfsUtilError> for LibError {
232    fn into(self) -> BtrfsUtilError {
233        BtrfsUtilError::Lib(self)
234    }
235}