path_jail/
error.rs

1use std::error::Error;
2use std::fmt;
3use std::path::PathBuf;
4
5#[derive(Debug)]
6pub enum JailError {
7    /// Path would escape the jail root.
8    EscapedRoot { attempted: PathBuf, root: PathBuf },
9    /// Path contains a broken symlink (cannot verify target is safe).
10    BrokenSymlink(PathBuf),
11    /// Path is invalid (e.g., contains absolute components).
12    InvalidPath(String),
13    /// Underlying I/O error.
14    Io(std::io::Error),
15}
16
17impl fmt::Display for JailError {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        match self {
20            Self::EscapedRoot { attempted, root } => {
21                write!(
22                    f,
23                    "path '{}' escapes jail root '{}'",
24                    attempted.display(),
25                    root.display()
26                )
27            }
28            Self::BrokenSymlink(path) => {
29                write!(
30                    f,
31                    "broken symlink at '{}' (cannot verify target)",
32                    path.display()
33                )
34            }
35            Self::InvalidPath(reason) => write!(f, "invalid path: {}", reason),
36            Self::Io(err) => write!(f, "io error: {}", err),
37        }
38    }
39}
40
41impl std::error::Error for JailError {
42    fn source(&self) -> Option<&(dyn Error + 'static)> {
43        match self {
44            Self::Io(err) => Some(err),
45            _ => None,
46        }
47    }
48}
49
50impl From<std::io::Error> for JailError {
51    fn from(err: std::io::Error) -> Self {
52        JailError::Io(err)
53    }
54}