Skip to main content

ufs/
error.rs

1//! Error types for the UFS reader.
2
3use thiserror::Error;
4
5/// Errors surfaced while parsing UFS/FFS on-disk structures.
6///
7/// Every variant names the offending value so an "unknown/invalid" report hands
8/// the investigator the evidence (raw bytes / offset), never a bare "invalid".
9#[derive(Debug, Error, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum UfsError {
12    /// The buffer was too small to hold the structure being parsed.
13    #[error("buffer too small for {structure}: need {need} bytes, have {have}")]
14    Truncated {
15        /// Name of the structure that could not be read.
16        structure: &'static str,
17        /// Minimum byte length required.
18        need: usize,
19        /// Byte length actually available.
20        have: usize,
21    },
22
23    /// The superblock magic matched neither UFS1 (`0x00011954`) nor UFS2
24    /// (`0x19540119`) in either byte order.
25    ///
26    /// Carries the four bytes actually found at the magic offset in both
27    /// interpretations so the caller can identify what the image really is
28    /// (fail-loud with the offending value).
29    #[error(
30        "bad UFS superblock magic at offset {offset}: bytes {bytes:02x?} \
31         (LE {le:#010x}, BE {be:#010x}); expected UFS1 0x00011954 or UFS2 0x19540119"
32    )]
33    BadMagic {
34        /// Byte offset within the parsed buffer where the magic was read.
35        offset: usize,
36        /// The four raw bytes at the magic offset.
37        bytes: [u8; 4],
38        /// The value interpreted little-endian.
39        le: u32,
40        /// The value interpreted big-endian.
41        be: u32,
42    },
43
44    /// A cylinder-group header's magic did not match `CG_MAGIC` (`0x00090255`).
45    ///
46    /// Carries the value found and the byte order used, so the caller sees the
47    /// evidence rather than a bare "invalid cg".
48    #[error(
49        "bad cylinder-group magic: found {found:#010x} (endian {endian:?}), expected 0x00090255"
50    )]
51    BadCgMagic {
52        /// The 32-bit value read at the cg magic offset.
53        found: u32,
54        /// The byte order used to read it (from the superblock).
55        endian: crate::Endian,
56    },
57
58    /// A geometry field carried a value outside any sane bound for the image —
59    /// consistent with corruption or an allocation-bomb. Names the field, the
60    /// value, and the bound so the caller sees exactly what was rejected.
61    #[error("impossible geometry: {field} = {value} exceeds bound {limit}")]
62    ImpossibleGeometry {
63        /// The geometry field that was out of range.
64        field: &'static str,
65        /// The value read from the image.
66        value: u64,
67        /// The sane bound it exceeded.
68        limit: u64,
69    },
70
71    /// The requested inode number is past the filesystem's inode count
72    /// (`fs_ipg * fs_ncg`), so it cannot address a real dinode. Carries the
73    /// requested number and the exclusive upper bound so the caller sees exactly
74    /// what was rejected (fail-loud with the offending value).
75    #[error("inode {ino} out of range: filesystem has {count} inodes (0..{count})")]
76    InodeOutOfRange {
77        /// The inode number that was requested.
78        ino: u64,
79        /// The total inode count (`fs_ipg * fs_ncg`), the exclusive upper bound.
80        count: u64,
81    },
82}