use cfg_if::cfg_if;
use std::path::PathBuf;
use thiserror::Error;
use crate::bottle_cap::BottleType;
cfg_if! {
if #[cfg(feature = "argonautica")] {
type ArgonLibraryError = argonautica::Error;
} else {
type ArgonLibraryError = argon2::Error;
}
}
cfg_if! {
if #[cfg(feature = "lzma2")] {
type LzmaLibraryError = lzma::LzmaError;
} else {
type LzmaLibraryError = String;
}
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum BottleError {
#[error("I/O error: {:?}{}",
.0.kind(),
.0.get_ref().map(|inner| format!(": {inner}")).unwrap_or_else(|| "".to_string())
)]
IoError(#[from] std::io::Error),
#[error("{0}: {1:?}")]
FileError(PathBuf, std::io::ErrorKind),
#[error("Bad magic number")]
BadMagic,
#[error("Unknown bottle version")]
UnknownVersion,
#[error("Unknown bottle type")]
UnknownBottleType,
#[error("Bottle header too large")]
HeaderTooLarge,
#[error("Bad CRC32C: got {got:x}, expected {expected:x}")]
BadCrc { expected: u32, got: u32 },
#[error("Corrupt stream (bad signal)")]
CorruptStream,
#[error("Internal error: previous stream was not closed")]
InvalidBottleState,
#[error("Wrong bottle type: got {got:?}, expected {expected:?}")]
WrongBottleType { expected: BottleType, got: BottleType },
#[error("Corrupt bottle: incorrect stream type(s) for bottle")]
WrongStreamType,
#[error("Extra stream in bottle")]
UnexpectedStream,
#[error("Bottle is missing a mandatory header")]
MissingHeader,
#[error("Internal error: No stream has been opened in this bottle")]
NoStream,
#[error("Not an Ed25519 key")]
NotAnEd25519Key,
#[error("Error decoding ssh key format")]
SshEncodingError,
#[error("Can't decode ssh key on line {line_no}")]
SshKeyFormatError { path: PathBuf, line_no: usize },
#[error("Not an ssh key file: {0}")]
InvalidSshFile(PathBuf),
#[error("Unsupported encryption ({kind}) in ssh file: {path}")]
UnsupportedSshFileEncryption { path: PathBuf, kind: String },
#[error("Password required for this SSH key file")]
SshPasswordRequired,
#[error("Error encrypting message with Ed25519 key material")]
DryocBoxError,
#[error("Error signing message with Ed25519 key material")]
DryocSignError,
#[error("Unknown signature algorithm")]
UnknownSignatureAlgorithm,
#[error("No public key provided to verify signature")]
NoSignaturePublicKey,
#[error("Bad signature")]
BadSignature,
#[error("No acceptable signature from allowed public keys")]
NoAcceptableSignature,
#[error("Key commitment is missing (old archive? try --old)")]
NoKeyCommitment,
#[error("Generated key is incorrect (possibly shenanigans)")]
BadKeyCommitment,
#[error("Unknown compression")]
UnknownCompression,
#[error("Error compressing data")]
CompressionError,
#[error("LZMA error: {0}")]
Lzma2Error(LzmaLibraryError),
#[error("LZMA not supported (built without feature=lzma2)")]
LzmaFeatureMissing,
#[error("No CPRNG random bytes available")]
NoRandom,
#[error("Unknown encryption")]
UnknownEncryption,
#[error("Bad key size for encryption algorithm")]
BadKeySize,
#[error("No key or password provided for encrypted bottle")]
RequiresKey,
#[error("Password provided but encrypted bottle is not password protected")]
NotPasswordEncrypted,
#[error("Internal error: Argon2 key generation error: {0}")]
Argon2Error(ArgonLibraryError),
#[error("Public key in encrypted bottle is corrupted")]
CorruptPublicKey,
#[error("No public key that can decode this bottle (encrypted for: {})", .0.join(", "))]
NoMatchingPublicKey(Vec<String>),
#[error("Encryption engine failure (wrong password or key?)")]
CipherError,
#[error("File archive is missing some blocks (corrupted)")]
IncompleteFileArchive,
#[error("Unknown hash type for file blocking")]
UnknownHashType,
#[error("Invalid path for adding to archive (contains . or ..): {0:?}")]
InvalidAddPath(PathBuf),
#[error("Invalid path (failed to parse: OS error?)")]
BadPath,
#[error("Paths would resolve to the same relative path in the archive: {0:?}, {1:?}")]
DuplicatePaths(PathBuf, PathBuf),
}
impl BottleError {
pub fn to_io_error(self) -> std::io::Error {
std::io::Error::other(Box::new(self))
}
}
pub type BottleResult<T> = Result<T, BottleError>;