1use std::io;
4
5#[derive(Debug)]
6pub enum Error {
7 Io(io::Error),
9 BadMagic { found: u16, expected: u16 },
11 BadChecksum { what: &'static str },
13 UnsupportedIncompat(u32),
15 UnsupportedRoCompat(u32),
17 NotFound,
19 NotADirectory,
21 IsADirectory,
25 AlreadyExists,
28 DirectoryNotEmpty,
31 ReadOnly,
33 NameTooLong,
36 NoSpaceLeftOnDevice,
39 InvalidArgument(&'static str),
43 InvalidInode(u32),
45 InvalidBlock(u64),
47 OutOfBounds,
49 CorruptExtentTree(&'static str),
51 CorruptDirEntry(&'static str),
53 Corrupt(&'static str),
55}
56
57impl From<io::Error> for Error {
58 fn from(e: io::Error) -> Self {
59 Error::Io(e)
60 }
61}
62
63impl std::fmt::Display for Error {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 match self {
66 Error::Io(e) => write!(f, "I/O error: {e}"),
67 Error::BadMagic { found, expected } => {
68 write!(f, "bad magic: 0x{found:04x} (expected 0x{expected:04x})")
69 }
70 Error::BadChecksum { what } => write!(f, "{what} checksum mismatch"),
71 Error::UnsupportedIncompat(bits) => {
72 write!(f, "unsupported INCOMPAT features: 0x{bits:08x}")
73 }
74 Error::UnsupportedRoCompat(bits) => {
75 write!(f, "unsupported RO_COMPAT features: 0x{bits:08x}")
76 }
77 Error::NotFound => write!(f, "not found"),
78 Error::NotADirectory => write!(f, "not a directory"),
79 Error::IsADirectory => write!(f, "is a directory"),
80 Error::AlreadyExists => write!(f, "already exists"),
81 Error::DirectoryNotEmpty => write!(f, "directory not empty"),
82 Error::ReadOnly => write!(f, "read-only filesystem"),
83 Error::NameTooLong => write!(f, "name too long"),
84 Error::NoSpaceLeftOnDevice => write!(f, "no space left on device"),
85 Error::InvalidArgument(msg) => write!(f, "invalid argument: {msg}"),
86 Error::InvalidInode(n) => write!(f, "invalid inode number {n}"),
87 Error::InvalidBlock(n) => write!(f, "invalid block number {n}"),
88 Error::OutOfBounds => write!(f, "out of bounds"),
89 Error::CorruptExtentTree(msg) => write!(f, "corrupt extent tree: {msg}"),
90 Error::CorruptDirEntry(msg) => write!(f, "corrupt directory entry: {msg}"),
91 Error::Corrupt(msg) => write!(f, "corrupt: {msg}"),
92 }
93 }
94}
95
96impl std::error::Error for Error {}
97
98pub type Result<T> = std::result::Result<T, Error>;
99
100impl Error {
101 pub fn to_errno(&self) -> i32 {
106 match self {
107 Error::Io(e) => e.raw_os_error().unwrap_or(EIO),
108 Error::NotFound => ENOENT,
109 Error::NotADirectory => ENOTDIR,
110 Error::IsADirectory => EISDIR,
111 Error::AlreadyExists => EEXIST,
112 Error::DirectoryNotEmpty => ENOTEMPTY,
113 Error::ReadOnly => EROFS,
114 Error::NameTooLong => ENAMETOOLONG,
115 Error::NoSpaceLeftOnDevice => ENOSPC,
116 Error::InvalidArgument(_) => EINVAL,
117 Error::InvalidInode(_) | Error::InvalidBlock(_) | Error::OutOfBounds => EINVAL,
118 Error::BadMagic { .. }
119 | Error::BadChecksum { .. }
120 | Error::CorruptExtentTree(_)
121 | Error::CorruptDirEntry(_)
122 | Error::Corrupt(_) => EIO,
123 Error::UnsupportedIncompat(_) | Error::UnsupportedRoCompat(_) => ENOTSUP,
124 }
125 }
126}
127
128pub mod errno {
131 pub const ENOENT: i32 = 2;
132 pub const EIO: i32 = 5;
133 pub const EEXIST: i32 = 17;
134 pub const ENOTDIR: i32 = 20;
135 pub const EISDIR: i32 = 21;
136 pub const EINVAL: i32 = 22;
137 pub const EROFS: i32 = 30;
138 pub const ENOSPC: i32 = 28;
139 pub const ENAMETOOLONG: i32 = 63; pub const ENOTSUP: i32 = 45;
141 pub const ENOTEMPTY: i32 = 66; pub const ENOSYS: i32 = 78; }
145
146use errno::*;