Skip to main content

hadris_cpio/
error.rs

1use core::fmt;
2
3/// Errors that can occur during CPIO archive operations.
4#[derive(Debug)]
5pub enum Error {
6    /// An I/O error occurred while reading or writing the archive.
7    Io(hadris_io::Error),
8    /// The header magic bytes are not `070701` or `070702`.
9    InvalidMagic {
10        /// Six bytes read from the archive magic field.
11        found: [u8; 6],
12    },
13    /// A header field contains non-hexadecimal characters.
14    InvalidHexField {
15        /// Name of the malformed header field.
16        field: &'static str,
17    },
18    /// The entry filename is empty or could not be read.
19    InvalidFilename,
20    /// A decoded header violates a newc field invariant.
21    InvalidHeader {
22        /// Description of the violated invariant.
23        reason: &'static str,
24    },
25    /// The archive ended without a `TRAILER!!!` sentinel.
26    MissingTrailer,
27    /// The CRC checksum in a `070702` entry does not match the computed value.
28    ChecksumMismatch {
29        /// Checksum stored in the entry header.
30        expected: u32,
31        /// Checksum computed from the entry contents.
32        computed: u32,
33    },
34    /// A caller-provided data buffer does not match the entry's file size.
35    BufferSizeMismatch {
36        /// The entry's file size in bytes.
37        expected: usize,
38        /// The length of the provided buffer.
39        actual: usize,
40    },
41    /// A hard link references a target path that was not seen earlier in the archive.
42    #[cfg(feature = "write")]
43    UnresolvedHardLink {
44        /// Inode number assigned to the unresolved target.
45        ino: u32,
46    },
47    /// The filename exceeds the maximum length representable in a newc header.
48    #[cfg(feature = "write")]
49    FilenameTooLong,
50    /// The file data exceeds the maximum size representable in a newc header (4 GiB).
51    #[cfg(feature = "write")]
52    FileTooLarge,
53}
54
55impl fmt::Display for Error {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        match self {
58            Self::Io(e) => write!(f, "I/O error: {e:?}"),
59            Self::InvalidMagic { found } => {
60                write!(
61                    f,
62                    "invalid CPIO magic: expected 070701 or 070702, found {:?}",
63                    core::str::from_utf8(found).unwrap_or("<invalid>")
64                )
65            }
66            Self::InvalidHexField { field } => {
67                write!(f, "invalid hex field: {field}")
68            }
69            Self::InvalidFilename => write!(f, "invalid filename"),
70            Self::InvalidHeader { reason } => write!(f, "invalid CPIO header: {reason}"),
71            Self::MissingTrailer => write!(f, "missing TRAILER!!! sentinel"),
72            Self::ChecksumMismatch { expected, computed } => {
73                write!(
74                    f,
75                    "checksum mismatch: expected {expected:#010x}, computed {computed:#010x}"
76                )
77            }
78            Self::BufferSizeMismatch { expected, actual } => {
79                write!(
80                    f,
81                    "buffer size mismatch: entry is {expected} bytes, buffer is {actual} bytes"
82                )
83            }
84            #[cfg(feature = "write")]
85            Self::UnresolvedHardLink { ino } => {
86                write!(f, "unresolved hard link: inode {ino}")
87            }
88            #[cfg(feature = "write")]
89            Self::FilenameTooLong => write!(f, "filename too long"),
90            #[cfg(feature = "write")]
91            Self::FileTooLarge => write!(f, "file too large"),
92        }
93    }
94}
95
96#[cfg(feature = "std")]
97impl std::error::Error for Error {}
98
99impl<E: hadris_io::IoError> From<hadris_io::Error<E>> for Error {
100    fn from(e: hadris_io::Error<E>) -> Self {
101        Self::Io(e.erase())
102    }
103}
104
105/// Convenience type alias for `core::result::Result<T, Error>`.
106pub type Result<T> = core::result::Result<T, Error>;