| use core::num::TryFromIntError; |
| use core::str::Utf8Error; |
| use std::io; |
| use std::os::raw::c_int; |
| use std::path::PathBuf; |
| |
| use selinux_sys::pid_t; |
| |
| /// Result of a fallible function. |
| pub type Result<T> = core::result::Result<T, Error>; |
| |
| /// Error. |
| #[derive(thiserror::Error, Debug)] |
| #[non_exhaustive] |
| pub enum Error { |
| /// Path is invalid. |
| #[error("path is invalid: '{}'", .0.display())] |
| PathIsInvalid(PathBuf), |
| |
| /// Input security contexts have different formats. |
| #[error("input security contexts have different formats")] |
| SecurityContextFormatMismatch, |
| |
| /// Security context has an expected format. |
| #[error("security context has an expected format")] |
| UnexpectedSecurityContextFormat, |
| |
| /// Lock was poisoned. |
| #[error("{operation} failed due to poisoned lock")] |
| LockPoisoned { |
| /// Operation. |
| operation: &'static str, |
| }, |
| |
| /// Input/Output operation failed. |
| #[error("{operation} failed")] |
| IO { |
| /// Cause. |
| source: io::Error, |
| /// Operation. |
| operation: &'static str, |
| }, |
| |
| /// Operation failed on a process. |
| #[error("{operation} failed on process with ID '{process_id}'")] |
| IO1Process { |
| /// Cause. |
| source: io::Error, |
| /// Operation. |
| operation: &'static str, |
| /// Process identifier. |
| process_id: pid_t, |
| }, |
| |
| /// Operation failed on a named object. |
| #[error("{operation} failed with '{name}'")] |
| IO1Name { |
| /// Cause. |
| source: io::Error, |
| /// Operation. |
| operation: &'static str, |
| /// Name. |
| name: String, |
| }, |
| |
| /// Operation failed on a file system object. |
| #[error("{operation} failed on path '{path}'")] |
| IO1Path { |
| /// Cause. |
| source: io::Error, |
| /// Operation. |
| operation: &'static str, |
| /// Path. |
| path: PathBuf, |
| }, |
| |
| /// Data is not encoded as UTF-8. |
| #[error(transparent)] |
| NotUTF8(#[from] Utf8Error), |
| |
| /// Integer is out of valid range. |
| #[error(transparent)] |
| IntegerOutOfRange(#[from] TryFromIntError), |
| } |
| |
| impl Error { |
| pub(crate) fn from_io(operation: &'static str, source: io::Error) -> Self { |
| Error::IO { source, operation } |
| } |
| |
| pub(crate) fn last_io_error(operation: &'static str) -> Self { |
| Error::IO { |
| source: io::Error::last_os_error(), |
| operation, |
| } |
| } |
| |
| pub(crate) fn from_io_pid( |
| operation: &'static str, |
| process_id: pid_t, |
| source: io::Error, |
| ) -> Self { |
| Error::IO1Process { |
| source, |
| operation, |
| process_id, |
| } |
| } |
| |
| pub(crate) fn from_io_path( |
| operation: &'static str, |
| path: impl Into<PathBuf>, |
| source: io::Error, |
| ) -> Self { |
| Error::IO1Path { |
| source, |
| operation, |
| path: path.into(), |
| } |
| } |
| |
| pub(crate) fn from_io_name( |
| operation: &'static str, |
| name: impl Into<String>, |
| source: io::Error, |
| ) -> Self { |
| Error::IO1Name { |
| source, |
| operation, |
| name: name.into(), |
| } |
| } |
| |
| pub(crate) fn set_errno(errno: c_int) { |
| unsafe { |
| *libc::__errno_location() = errno; |
| } |
| } |
| |
| pub(crate) fn clear_errno() { |
| Self::set_errno(0); |
| } |
| |
| #[allow(dead_code, reason = "used by unit tests")] |
| pub(crate) fn io_source(&self) -> Option<&io::Error> { |
| match self { |
| Self::IO { source, .. } |
| | Self::IO1Process { source, .. } |
| | Self::IO1Name { source, .. } |
| | Self::IO1Path { source, .. } => Some(source), |
| |
| Self::PathIsInvalid(_) |
| | Self::SecurityContextFormatMismatch |
| | Self::UnexpectedSecurityContextFormat |
| | Self::LockPoisoned { .. } |
| | Self::NotUTF8(_) |
| | Self::IntegerOutOfRange(_) => None, |
| } |
| } |
| } |