1use crate::{
2 boot_sector::UnixEpochDuration,
3 disk::{ReadOffset, WriteSeek},
4};
5use alloc::sync::Arc;
6
7#[derive(Debug, thiserror::Error)]
8pub enum ExfatFormatError<T: UnixEpochDuration> {
9 #[error("Invalid bytes per sector. Must be a power of `2` and between `512` and `4096`: {0}.")]
10 InvalidBytesPerSector(u16),
11 #[error("Invalid volume size: {0}.")]
12 InvalidSize(u64),
13 #[error("Invalid partition offset: {0}.")]
14 InvalidPartitionOffset(u64),
15 #[error("Invalid number of FATs (must be 1 or 2): {0}.")]
16 InvalidNumberOfFats(u8),
17 #[error("Invalid cluster size: {0}. Must be a power of `2` and at most 32MB: {0}")]
18 InvlaidClusterSize(u32),
19 #[error("Boundary alignment is too big: {0}")]
20 BoundaryAlignemntTooBig(u32),
21 #[error("Unable to generate unique serial number. Error: {0}")]
22 NoSerial(#[source] T::Err),
23 #[error("Unable to pack bitmap.")]
24 CannotPackBitmap,
25 #[error("File size does not match exFAT size.")]
26 InvalidFileSize,
27}
28
29#[derive(Debug, thiserror::Error)]
30pub enum ExfatError<T: UnixEpochDuration, O: WriteSeek>
31where
32 T::Err: core::fmt::Debug,
33{
34 #[error("{0}")]
35 Format(#[from] ExfatFormatError<T>),
36 #[error("I/O error: {0}.")]
37 Io(#[source] O::Err),
38}
39
40#[derive(Debug, thiserror::Error)]
41pub enum RootError<O: ReadOffset> {
42 #[error("I/O error: {0}.")]
43 Io(O::Err),
44 #[error("The provided volume is not an exFAT filesystem.")]
45 WrongFs,
46 #[error("Invalid bytes per sector shift detected: {0}. Must be between `9` and `12`")]
47 InvalidBytesPerSectorShift(u8),
48 #[error("Invalid sectors per cluster shift detected: {0}.")]
49 InvalidSectorsPerClusterShift(u8),
50 #[error("Invalid number of FATs detected: {0}. Must be either `1` or `2`.")]
51 InvalidNumberOfFats(u8),
52 #[error("Fat could not be parsed: {0}.")]
53 Fat(#[from] FatLoadError<Arc<O>>),
54 #[error(
55 "Invalid index of root directory cluster detected: {0}. Must be bigger than `2` and at most `cluster_count + 1`"
56 )]
57 InvalidRootDirectoryClusterIndex(u32),
58 #[error("Cluster chain could not be parsed: {0}.")]
59 ClusterChain(#[from] ClusterChainError),
60 #[error("Entry Reader Error: {0}.")]
61 DirEntry(#[from] EntryReaderError<Arc<O>>),
62 #[error(
63 "All directory entries of the root directory must be of type `PRIMARY`. Detected entry type: {0}"
64 )]
65 RootEntryNotPrimary(u8),
66 #[error("More than 2 allocation bitmap root entry fields detected.")]
67 InvalidNumberOfAllocationBitmaps,
68 #[error("Corrupt allocation bitmap entry.")]
69 InvalidAllocationBitmap,
70 #[error("More than 1 upcase table root entry field detected.")]
71 InvalidNumberOfUpcaseTables,
72 #[error("Corrupt upcase table entry.")]
73 InvalidUpcaseTable,
74 #[error("More than 1 volume label root entry field detected.")]
75 InvalidNumberOfVolumeLabels,
76 #[error("Corrupt volume label entry.")]
77 InvalidVolumeLabel,
78 #[error("Unable to parse file entry: {0}")]
79 InvalidFileEntry(#[from] FileParserError<Arc<O>>),
80 #[error("Unexpected directory entry in root directory. Detected entry type: {0}")]
81 UnexpectedRootEntry(u8),
82}
83
84#[derive(Debug, thiserror::Error)]
85pub enum FatLoadError<O: ReadOffset> {
86 #[error("FAT starts at invalid offset.")]
87 InvalidOffset,
88 #[error("Read failed at: {0:#x}.")]
89 ReadFailed(u64, #[source] O::Err),
90}
91
92#[derive(Debug, thiserror::Error)]
93pub enum ClusterChainError {
94 #[error("Invalid starting cluster.")]
95 InvalidFirstCluster,
96 #[error("Invalid data length for cluster chain.")]
97 InvalidDataLength,
98}
99
100#[derive(Debug, thiserror::Error)]
101pub enum EntryReaderError<O: ReadOffset> {
102 #[error("Cannot read entry #{0} on cluster #{1}.")]
103 ReadFailed(usize, u32, #[source] O::Err),
104 #[error("{0}")]
105 Entry(#[from] DirEntryError),
106}
107
108#[derive(Debug, thiserror::Error)]
109pub enum DirEntryError {
110 #[error("Invalid directory entry detected: {0}.")]
111 InvalidEntry(u8),
112}
113
114#[derive(Debug, thiserror::Error)]
115pub enum FileParserError<O: ReadOffset>
116where
117 O::Err: core::fmt::Debug,
118{
119 #[error("File entry is missing stream extension.")]
120 NoStreamExtension,
121 #[error("File entry is missing file name.")]
122 NoFileName,
123 #[error("{0}")]
124 ReadFailed(#[from] EntryReaderError<O>),
125 #[error("Invalid stream extension entry detected.")]
126 InvalidStreamExtension,
127 #[error("Wrong number of file name entries detected.")]
128 WrongFileNameEntries,
129 #[error("Invalid file name entry detected.")]
130 InvalidFileName,
131}
132
133#[derive(Debug, thiserror::Error)]
134pub enum DirectoryError<O: ReadOffset>
135where
136 O::Err: core::fmt::Debug,
137{
138 #[error("Cannot create a clusters reader for allocation: {0}")]
139 CreateClustersReaderFailed(#[from] ClusterChainError),
140 #[error("Cannot read an entry: {0}")]
141 ReadEntryFailed(#[from] EntryReaderError<Arc<O>>),
142 #[error("Detected directory entry that is not `PRIMARY`. Detected entry type: {0}")]
143 NotPrimaryEntry(u8),
144 #[error("Detected directory entry that is not a file entry. Detected entry type: {0}")]
145 NotFileEntry(u8),
146 #[error("Unable to parse file entry: {0}")]
147 InvalidFileEntry(#[from] FileParserError<Arc<O>>),
148}