use crate::error::GlueError;
use crate::BtrfsUtilError;
use crate::Result;
#[cfg(feature = "enable-glue-errors")]
use std::convert::Into;
use std::convert::TryFrom;
use std::ffi::CStr;
use std::os::raw::c_char;
use thiserror::Error;
pub(crate) type LibErrorCode = u32;
#[derive(Clone, Debug, Eq, Error, PartialEq)]
pub enum LibError {
#[error("Success")]
Ok = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_OK as isize,
#[error("Stop iteration")]
StopIteration = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STOP_ITERATION as isize,
#[error("Cannot allocate memory")]
NoMemory = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NO_MEMORY as isize,
#[error("Invalid argument")]
InvalidArgument = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INVALID_ARGUMENT as isize,
#[error("Not a Btrfs filesystem")]
NotBtrfs = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_BTRFS as isize,
#[error("Not a Btrfs subvolume")]
NotSubvolume = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_SUBVOLUME as isize,
#[error("Subvolume not found")]
SubvolumeNotFound =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND as isize,
#[error("Could not open")]
OpenFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_OPEN_FAILED as isize,
#[error("Could not rmdir")]
RmdirFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_RMDIR_FAILED as isize,
#[error("Could not unlink")]
UnlinkFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_UNLINK_FAILED as isize,
#[error("Could not stat")]
StatFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STAT_FAILED as isize,
#[error("Could not statfs")]
StatfsFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STATFS_FAILED as isize,
#[error("Could not search B-tree")]
SearchFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SEARCH_FAILED as isize,
#[error("Could not lookup inode")]
InoLookupFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_FAILED as isize,
#[error("Could not get subvolume flags")]
SubvolGetflagsFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_GETFLAGS_FAILED as isize,
#[error("Could not set subvolume flags")]
SubvolSetflagsFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_SETFLAGS_FAILED as isize,
#[error("Could not create subvolume")]
SubvolCreateFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_CREATE_FAILED as isize,
#[error("Could not create snapshot")]
SnapCreateFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_CREATE_FAILED as isize,
#[error("Could not destroy subvolume/snapshot")]
SnapDestroyFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_DESTROY_FAILED as isize,
#[error("Could not set default subvolume")]
DefaultSubvolFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_DEFAULT_SUBVOL_FAILED as isize,
#[error("Could not sync filesystem")]
SyncFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SYNC_FAILED as isize,
#[error("Could not start filesystem sync")]
StartSyncFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_START_SYNC_FAILED as isize,
#[error("Could not wait for filesystem sync")]
WaitSyncFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_WAIT_SYNC_FAILED as isize,
#[error("Could not get subvolume information with BTRFS_IOC_GET_SUBVOL_INFO")]
GetSubvolInfoFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_INFO_FAILED as isize,
#[error("Could not get rootref information with BTRFS_IOC_GET_SUBVOL_ROOTREF")]
GetSubvolRootrefFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_ROOTREF_FAILED as isize,
#[error("Could not resolve subvolume path with BTRFS_IOC_INO_LOOKUP_USER")]
InoLookupUserFailed =
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_USER_FAILED as isize,
#[error("Could not get filesystem information")]
FsInfoFailed = btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_FS_INFO_FAILED as isize,
}
impl LibError {
pub fn strerror(&self) -> Result<&'static str> {
let err_str_ptr: *const c_char;
let errno = self.clone() as LibErrorCode;
unsafe {
err_str_ptr = btrfsutil_sys::btrfs_util_strerror(errno);
}
glue_error!(err_str_ptr.is_null(), GlueError::NullPointerReceived);
let cstr: &CStr = unsafe { CStr::from_ptr(err_str_ptr) };
match cstr.to_str() {
Ok(val) => Ok(val),
Err(e) => glue_error!(GlueError::Utf8Error(e)),
}
}
}
impl TryFrom<LibErrorCode> for LibError {
type Error = BtrfsUtilError;
fn try_from(errno: LibErrorCode) -> Result<Self> {
glue_error!(errno > 26, GlueError::UnknownErrno(errno));
match errno {
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_OK => Ok(LibError::Ok),
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STOP_ITERATION => {
Ok(LibError::StopIteration)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NO_MEMORY => Ok(LibError::NoMemory),
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INVALID_ARGUMENT => {
Ok(LibError::InvalidArgument)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_BTRFS => Ok(LibError::NotBtrfs),
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_NOT_SUBVOLUME => {
Ok(LibError::NotSubvolume)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND => {
Ok(LibError::SubvolumeNotFound)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_OPEN_FAILED => {
Ok(LibError::OpenFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_RMDIR_FAILED => {
Ok(LibError::RmdirFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_UNLINK_FAILED => {
Ok(LibError::UnlinkFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STAT_FAILED => {
Ok(LibError::StatFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_STATFS_FAILED => {
Ok(LibError::StatfsFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SEARCH_FAILED => {
Ok(LibError::SearchFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_FAILED => {
Ok(LibError::InoLookupFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_GETFLAGS_FAILED => {
Ok(LibError::SubvolGetflagsFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_SETFLAGS_FAILED => {
Ok(LibError::SubvolSetflagsFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SUBVOL_CREATE_FAILED => {
Ok(LibError::SubvolCreateFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_CREATE_FAILED => {
Ok(LibError::SnapCreateFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SNAP_DESTROY_FAILED => {
Ok(LibError::SnapDestroyFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_DEFAULT_SUBVOL_FAILED => {
Ok(LibError::DefaultSubvolFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_SYNC_FAILED => {
Ok(LibError::SyncFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_START_SYNC_FAILED => {
Ok(LibError::StartSyncFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_WAIT_SYNC_FAILED => {
Ok(LibError::WaitSyncFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_INFO_FAILED => {
Ok(LibError::GetSubvolInfoFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_GET_SUBVOL_ROOTREF_FAILED => {
Ok(LibError::GetSubvolRootrefFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_INO_LOOKUP_USER_FAILED => {
Ok(LibError::InoLookupUserFailed)
}
btrfsutil_sys::btrfs_util_error_BTRFS_UTIL_ERROR_FS_INFO_FAILED => {
Ok(LibError::FsInfoFailed)
}
_ => glue_error!(GlueError::UnknownErrno(errno)),
}
}
}
#[cfg(feature = "enable-glue-errors")]
impl Into<BtrfsUtilError> for LibError {
fn into(self) -> BtrfsUtilError {
BtrfsUtilError::Lib(self)
}
}