Skip to main content

ext4_lwext4/
error.rs

1//! Error types for ext4-rs operations.
2
3use std::ffi::NulError;
4use thiserror::Error;
5
6/// Error type for ext4 filesystem operations.
7#[derive(Debug, Error)]
8pub enum Error {
9    /// I/O error
10    #[error("I/O error: {0}")]
11    Io(#[from] std::io::Error),
12
13    /// File or directory not found
14    #[error("not found: {0}")]
15    NotFound(String),
16
17    /// File or directory already exists
18    #[error("already exists: {0}")]
19    AlreadyExists(String),
20
21    /// Path is not a directory
22    #[error("not a directory: {0}")]
23    NotADirectory(String),
24
25    /// Path is a directory (when file expected)
26    #[error("is a directory: {0}")]
27    IsADirectory(String),
28
29    /// Directory is not empty
30    #[error("directory not empty: {0}")]
31    NotEmpty(String),
32
33    /// Permission denied
34    #[error("permission denied")]
35    PermissionDenied,
36
37    /// No space left on device
38    #[error("no space left on device")]
39    NoSpace,
40
41    /// Filesystem is read-only
42    #[error("read-only filesystem")]
43    ReadOnly,
44
45    /// Invalid argument
46    #[error("invalid argument: {0}")]
47    InvalidArgument(String),
48
49    /// Path contains null byte
50    #[error("path contains null byte")]
51    NulError(#[from] NulError),
52
53    /// Filesystem-level error with errno
54    #[error("filesystem error: {0}")]
55    Filesystem(i32),
56
57    /// Device not found or not registered
58    #[error("device not found")]
59    DeviceNotFound,
60
61    /// Mount point not found
62    #[error("mount point not found")]
63    MountPointNotFound,
64
65    /// Name too long
66    #[error("name too long")]
67    NameTooLong,
68
69    /// Too many open files
70    #[error("too many open files")]
71    TooManyOpenFiles,
72
73    /// Invalid filesystem
74    #[error("invalid filesystem")]
75    InvalidFilesystem,
76}
77
78/// Result type for ext4 filesystem operations.
79pub type Result<T> = std::result::Result<T, Error>;
80
81/// Convert lwext4 error code to Error
82impl From<i32> for Error {
83    fn from(errno: i32) -> Self {
84        match errno {
85            0 => panic!("attempted to convert success (0) to error"),
86            libc::ENOENT => Error::NotFound(String::new()),
87            libc::EEXIST => Error::AlreadyExists(String::new()),
88            libc::ENOTDIR => Error::NotADirectory(String::new()),
89            libc::EISDIR => Error::IsADirectory(String::new()),
90            libc::ENOTEMPTY => Error::NotEmpty(String::new()),
91            libc::EACCES | libc::EPERM => Error::PermissionDenied,
92            libc::ENOSPC => Error::NoSpace,
93            libc::EROFS => Error::ReadOnly,
94            libc::EINVAL => Error::InvalidArgument(String::new()),
95            libc::ENXIO | libc::ENODEV => Error::DeviceNotFound,
96            libc::ENAMETOOLONG => Error::NameTooLong,
97            libc::EMFILE | libc::ENFILE => Error::TooManyOpenFiles,
98            _ => Error::Filesystem(errno),
99        }
100    }
101}
102
103/// Check lwext4 return code and convert to Result
104pub(crate) fn check_errno(errno: i32) -> Result<()> {
105    if errno == 0 {
106        Ok(())
107    } else {
108        Err(Error::from(errno))
109    }
110}
111
112/// Check lwext4 return code with context for the error
113pub(crate) fn check_errno_with_path(errno: i32, path: &str) -> Result<()> {
114    if errno == 0 {
115        Ok(())
116    } else {
117        let err = match errno {
118            libc::ENOENT => Error::NotFound(path.to_string()),
119            libc::EEXIST => Error::AlreadyExists(path.to_string()),
120            libc::ENOTDIR => Error::NotADirectory(path.to_string()),
121            libc::EISDIR => Error::IsADirectory(path.to_string()),
122            libc::ENOTEMPTY => Error::NotEmpty(path.to_string()),
123            _ => Error::from(errno),
124        };
125        Err(err)
126    }
127}