84 lines
2.3 KiB
Rust
84 lines
2.3 KiB
Rust
use std::io;
|
|
|
|
use thiserror::Error;
|
|
|
|
/// The application-wide error type.
|
|
#[derive(Debug, Error)]
|
|
pub enum Error {
|
|
/// A command-line or configuration value was invalid.
|
|
#[error("configuration: {0}")]
|
|
Config(String),
|
|
/// A filesystem operation failed.
|
|
#[error("{context}: {source}")]
|
|
Io {
|
|
/// The operation being performed.
|
|
context: String,
|
|
/// The underlying error.
|
|
#[source]
|
|
source: io::Error,
|
|
},
|
|
/// TOML could not be decoded.
|
|
#[error("parse {path}: {source}")]
|
|
Toml {
|
|
/// The file being parsed.
|
|
path: String,
|
|
/// The parser error.
|
|
#[source]
|
|
source: toml::de::Error,
|
|
},
|
|
/// PAM rejected or could not complete an operation.
|
|
#[error("PAM {operation} failed with status {status}: {message}")]
|
|
Pam {
|
|
/// The PAM operation.
|
|
operation: &'static str,
|
|
/// The numeric PAM status.
|
|
status: i32,
|
|
/// The human-readable PAM message.
|
|
message: String,
|
|
},
|
|
/// A session process failed.
|
|
#[error("session: {0}")]
|
|
Session(String),
|
|
/// The terminal could not be initialized or restored.
|
|
#[error("terminal: {0}")]
|
|
Terminal(String),
|
|
/// An authentication worker request was cancelled or disconnected.
|
|
#[error("authentication worker: {0}")]
|
|
Worker(String),
|
|
}
|
|
|
|
impl Error {
|
|
/// Returns a PAM status when this error came directly from PAM.
|
|
pub fn pam_status(&self) -> Option<i32> {
|
|
match self {
|
|
Self::Pam { status, .. } => Some(*status),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/// Returns whether PAM requires a password change before login can finish.
|
|
pub fn requires_password_change(&self) -> bool {
|
|
matches!(self.pam_status(), Some(12 | 27))
|
|
}
|
|
}
|
|
|
|
/// Adds a stable operation label to an I/O error.
|
|
pub fn io_error(context: impl Into<String>, source: io::Error) -> Error {
|
|
Error::Io {
|
|
context: context.into(),
|
|
source,
|
|
}
|
|
}
|
|
|
|
/// Converts a failed result into an application error with context.
|
|
pub trait ResultExt<T> {
|
|
/// Adds context to an I/O operation.
|
|
fn io_context(self, context: impl Into<String>) -> Result<T, Error>;
|
|
}
|
|
|
|
impl<T> ResultExt<T> for io::Result<T> {
|
|
fn io_context(self, context: impl Into<String>) -> Result<T, Error> {
|
|
self.map_err(|source| io_error(context, source))
|
|
}
|
|
}
|