1io_transform! {
2
3use core::mem::size_of;
4
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7
8use crate::error::{Error, Result};
9#[cfg(feature = "write")]
10use super::io::Write;
11use super::io::{Read, Seek, SeekFrom};
12
13#[cfg(feature = "alloc")]
17const FAT_CACHE_WINDOW_SIZE: &str = env!("FAT_CACHE_WINDOW_SIZE_BYTES");
18
19#[cfg(feature = "alloc")]
22fn fat12_entry_from_buf(buf: &[u8], window_start: usize, cluster: usize) -> u16 {
23 let offset_in_fat = (cluster * 3) / 2;
24 let buffer_offset = offset_in_fat - window_start;
25 let bytes = &buf[buffer_offset..][..2];
26 if cluster.is_multiple_of(2) {
27 u16::from(bytes[0]) | (u16::from(bytes[1] & 0x0F) << 8)
28 } else {
29 (u16::from(bytes[0]) >> 4) | (u16::from(bytes[1]) << 4)
30 }
31}
32
33#[cfg(feature = "alloc")]
38#[allow(clippy::too_many_arguments)]
39async fn read_chain_wide<R>(
40 reader: &mut R,
41 fat_start: usize,
42 fat_size: usize,
43 start_cluster: u32,
44 max_clusters: usize,
45 entry_size: usize,
46 entry_mask: u32,
47 is_end_of_chain: impl Fn(u32) -> bool,
48 is_bad_cluster: impl Fn(u32) -> bool,
49 validate_cluster: impl Fn(u32) -> Result<()>,
50) -> Result<Vec<u32>>
51where
52 R: Read + Seek,
53{
54 assert!(
55 entry_size == 0 || entry_size == 2 || entry_size == 4,
56 "FAT entry_size must be 0 (FAT12), 2 (FAT16), or 4 (FAT32), got {entry_size}"
57 );
58
59 let cache_size = FAT_CACHE_WINDOW_SIZE.parse::<usize>().unwrap();
60 let mut fat_buf = alloc::vec![0u8; FAT_CACHE_WINDOW_SIZE.parse::<usize>().unwrap()];
61 let mut window_start = usize::MAX;
62 let mut valid_len = 0usize;
63
64 let mut chain = Vec::new();
65 let mut current = start_cluster as usize;
66 let mut iterations = 0;
67
68 while current >= 2 && iterations <= max_clusters {
69 chain.push(current as u32);
70 iterations += 1;
71
72 let (offset_in_fat, span) = if entry_size == 0 {
73 ((current * 3) / 2, 2)
74 } else {
75 (current * entry_size, entry_size)
76 };
77
78 if offset_in_fat < window_start || offset_in_fat + span > window_start + valid_len {
79 window_start = offset_in_fat;
80 valid_len = cache_size.min(fat_size.saturating_sub(window_start));
81 reader
82 .seek(SeekFrom::Start((fat_start + window_start) as u64))
83 .await?;
84 reader.read_exact(&mut fat_buf[..valid_len]).await?;
85 }
86
87 let buffer_offset = offset_in_fat - window_start;
88 let cluster_u32 = if entry_size == 0 {
89 fat12_entry_from_buf(&fat_buf, window_start, current) as u32 & entry_mask
90 } else if entry_size == 2 {
91 let raw = u16::from_le_bytes(
92 fat_buf[buffer_offset..][..2].try_into().unwrap(),
93 );
94 (raw as u32) & entry_mask
95 } else {
96 let raw = u32::from_le_bytes(
97 fat_buf[buffer_offset..][..4].try_into().unwrap(),
98 );
99 raw & entry_mask
100 };
101
102 if is_end_of_chain(cluster_u32) {
103 break;
104 }
105 if is_bad_cluster(cluster_u32) {
106 return Err(Error::BadCluster {
107 cluster: current as u32,
108 });
109 }
110 validate_cluster(cluster_u32)?;
111 current = cluster_u32 as usize;
112 }
113 Ok(chain)
114}
115
116pub enum Fat {
118 Fat12(Fat12),
120 Fat16(Fat16),
122 Fat32(Fat32),
124}
125
126impl Fat {
127 pub async fn next_cluster<T: Read + Seek>(
129 &self,
130 reader: &mut T,
131 cluster: usize,
132 ) -> Result<Option<u32>> {
133 match self {
134 Self::Fat12(fat12) => fat12.next_cluster(reader, cluster).await,
135 Self::Fat16(fat16) => fat16.next_cluster(reader, cluster).await,
136 Self::Fat32(fat32) => fat32.next_cluster(reader, cluster).await,
137 }
138 }
139
140 #[cfg(feature = "alloc")]
144 pub(crate) async fn read_chain<T: Read + Seek>(
145 &self,
146 reader: &mut T,
147 start_cluster: u32,
148 max_clusters: usize,
149 ) -> Result<Vec<u32>> {
150 match self {
151 Self::Fat12(fat12) => {
152 read_chain_wide(
153 reader,
154 fat12.start,
155 fat12.size,
156 start_cluster,
157 max_clusters,
158 0, 0x0FFF,
160 |v| Fat12::is_end_of_chain(v as u16),
161 |v| Fat12::is_bad_cluster(v as u16),
162 |v| fat12.validate_cluster(v as u16),
163 )
164 .await
165 }
166 Self::Fat16(fat16) => {
167 read_chain_wide(
168 reader,
169 fat16.start,
170 fat16.size,
171 start_cluster,
172 max_clusters,
173 2, 0xFFFF,
175 |v| Fat16::is_end_of_chain(v as u16),
176 |v| Fat16::is_bad_cluster(v as u16),
177 |v| fat16.validate_cluster(v as u16),
178 )
179 .await
180 }
181 Self::Fat32(fat32) => {
182 read_chain_wide(
183 reader,
184 fat32.start,
185 fat32.size,
186 start_cluster,
187 max_clusters,
188 4, Fat32::ENTRY_MASK,
190 Fat32::is_end_of_chain,
191 Fat32::is_bad_cluster,
192 |v| fat32.validate_cluster(v),
193 )
194 .await
195 }
196 }
197 }
198
199 pub fn fat_type(&self) -> FatType {
201 match self {
202 Self::Fat12(_) => FatType::Fat12,
203 Self::Fat16(_) => FatType::Fat16,
204 Self::Fat32(_) => FatType::Fat32,
205 }
206 }
207
208 pub fn max_cluster(&self) -> u32 {
213 match self {
214 Self::Fat12(f) => f.max_cluster as u32,
215 Self::Fat16(f) => f.max_cluster as u32,
216 Self::Fat32(f) => f.max_cluster,
217 }
218 }
219
220 pub async fn walk_chain<T, F>(
229 &self,
230 reader: &mut T,
231 start: u32,
232 max_steps: u32,
233 mut visit: F,
234 ) -> Result<u32>
235 where
236 T: Read + Seek,
237 F: FnMut(u32),
238 {
239 let mut current = start;
240 let mut steps: u32 = 0;
241 loop {
242 visit(current);
243 steps = steps.saturating_add(1);
244 if steps > max_steps {
245 return Err(Error::ClusterLoop { cluster: current });
246 }
247 match self.next_cluster(reader, current as usize).await? {
248 Some(next) => current = next,
249 None => return Ok(current),
250 }
251 }
252 }
253
254 #[cfg(feature = "write")]
261 pub async fn truncate_chain<T: Read + Write + Seek>(
262 &self,
263 rw: &mut T,
264 cluster: usize,
265 ) -> Result<u32> {
266 match self {
267 Self::Fat12(fat12) => fat12.truncate_chain(rw, cluster as u16).await,
268 Self::Fat16(fat16) => fat16.truncate_chain(rw, cluster as u16).await,
269 Self::Fat32(fat32) => fat32.truncate_chain(rw, cluster as u32).await,
270 }
271 }
272
273 #[cfg(feature = "write")]
275 pub async fn free_chain<T: Read + Write + Seek>(&self, rw: &mut T, cluster: usize) -> Result<u32> {
276 match self {
277 Self::Fat12(fat12) => fat12.free_chain(rw, cluster as u16).await,
278 Self::Fat16(fat16) => fat16.free_chain(rw, cluster as u16).await,
279 Self::Fat32(fat32) => fat32.free_chain(rw, cluster as u32).await,
280 }
281 }
282
283 #[cfg(feature = "write")]
289 pub async fn mark_bad<T: Read + Write + Seek>(&self, rw: &mut T, cluster: usize) -> Result<()> {
290 match self {
291 Self::Fat12(fat12) => fat12.mark_bad(rw, cluster as u16).await,
292 Self::Fat16(fat16) => fat16.mark_bad(rw, cluster as u16).await,
293 Self::Fat32(fat32) => fat32.mark_bad(rw, cluster as u32).await,
294 }
295 }
296
297 pub async fn read_status_flags<T: Read + Seek>(&self, reader: &mut T) -> Result<(bool, bool)> {
309 match self {
310 Self::Fat12(_) => Ok((false, false)),
311 Self::Fat16(f) => {
312 let offset = f.start + 2;
314 reader.seek(SeekFrom::Start(offset as u64)).await?;
315 let mut bytes = [0u8; 2];
316 reader.read_exact(&mut bytes).await?;
317 let val = u16::from_le_bytes(bytes);
318 Ok((val & 0x8000 == 0, val & 0x4000 == 0))
320 }
321 Self::Fat32(f) => {
322 let offset = f.start + 4;
324 reader.seek(SeekFrom::Start(offset as u64)).await?;
325 let mut bytes = [0u8; 4];
326 reader.read_exact(&mut bytes).await?;
327 let val = u32::from_le_bytes(bytes);
328 Ok((val & 0x0800_0000 == 0, val & 0x0400_0000 == 0))
332 }
333 }
334 }
335
336 pub fn fat_copy_count(&self) -> usize {
338 match self {
339 Self::Fat12(f) => f.count,
340 Self::Fat16(f) => f.count,
341 Self::Fat32(f) => f.count,
342 }
343 }
344
345 pub async fn compare_entry<T: Read + Seek>(
350 &self,
351 reader: &mut T,
352 cluster: usize,
353 ) -> Result<bool> {
354 if self.fat_copy_count() < 2 {
355 return Err(Error::UnsupportedFatType("no backup FAT copy available"));
356 }
357 match self {
358 Self::Fat12(f) => {
359 let a = f.read_clus_at(reader, cluster, 0).await?;
360 let b = f.read_clus_at(reader, cluster, 1).await?;
361 Ok(a == b)
362 }
363 Self::Fat16(f) => {
364 let a = f.read_clus_at(reader, cluster, 0).await?;
365 let b = f.read_clus_at(reader, cluster, 1).await?;
366 Ok(a == b)
367 }
368 Self::Fat32(f) => {
369 let a = f.read_clus_at(reader, cluster, 0).await?;
370 let b = f.read_clus_at(reader, cluster, 1).await?;
371 Ok(a == b)
372 }
373 }
374 }
375
376 pub async fn next_cluster_with_fallback<T: Read + Seek>(
381 &self,
382 reader: &mut T,
383 cluster: usize,
384 ) -> Result<Option<u32>> {
385 match self.next_cluster(reader, cluster).await {
386 Ok(result) => Ok(result),
387 Err(_primary_err) if self.fat_copy_count() >= 2 => {
388 match self {
390 Self::Fat12(f) => {
391 let entry = f.read_clus_at(reader, cluster, 1).await? & Fat12::ENTRY_MASK;
392 if Fat12::is_end_of_chain(entry) { return Ok(None); }
393 if Fat12::is_bad_cluster(entry) { return Err(Error::BadCluster { cluster: cluster as u32 }); }
394 f.validate_cluster(entry)?;
395 Ok(Some(entry as u32))
396 }
397 Self::Fat16(f) => {
398 let entry = f.read_clus_at(reader, cluster, 1).await?;
399 if Fat16::is_end_of_chain(entry) { return Ok(None); }
400 if Fat16::is_bad_cluster(entry) { return Err(Error::BadCluster { cluster: cluster as u32 }); }
401 f.validate_cluster(entry)?;
402 Ok(Some(entry as u32))
403 }
404 Self::Fat32(f) => {
405 let raw = f.read_clus_at(reader, cluster, 1).await?;
406 let entry = raw & Fat32::ENTRY_MASK;
407 if Fat32::is_end_of_chain(entry) { return Ok(None); }
408 if Fat32::is_bad_cluster(entry) { return Err(Error::BadCluster { cluster: cluster as u32 }); }
409 f.validate_cluster(entry)?;
410 Ok(Some(entry))
411 }
412 }
413 }
414 Err(e) => Err(e),
415 }
416 }
417}
418
419#[derive(Debug, Clone, Copy, PartialEq, Eq)]
421#[cfg_attr(feature = "defmt", derive(defmt::Format))]
422pub enum FatType {
423 Fat12,
425 Fat16,
427 Fat32,
429}
430
431impl core::fmt::Display for FatType {
432 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
433 match self {
434 Self::Fat12 => write!(f, "FAT12"),
435 Self::Fat16 => write!(f, "FAT16"),
436 Self::Fat32 => write!(f, "FAT32"),
437 }
438 }
439}
440
441pub struct Fat12 {
445 start: usize,
446 size: usize,
447 count: usize,
448 max_cluster: u16,
449}
450
451impl Fat12 {
452 const ENTRY_MASK: u16 = 0x0FFF;
454 const END_OF_CHAIN_MIN: u16 = 0x0FF8;
456 const BAD_CLUSTER: u16 = 0x0FF7;
458 const FIRST_DATA_CLUSTER: u16 = 2;
460
461 #[cfg(feature = "cache")]
464 pub(crate) fn cache_layout(&self) -> (usize, usize, usize) {
465 (self.start, self.size, self.count)
466 }
467
468 pub fn new(start: usize, size: usize, count: usize, max_cluster: u16) -> Self {
470 debug_assert!(count == 1 || count == 2);
471 Self {
472 start,
473 size,
474 count,
475 max_cluster,
476 }
477 }
478
479 pub fn max_cluster(&self) -> u16 {
481 self.max_cluster
482 }
483
484 sync_only! {
485 #[cfg(feature = "tool")]
487 pub(crate) fn entry_byte_offset(&self, cluster: usize) -> usize {
488 self.start + (cluster * 3) / 2
489 }
490 }
491
492 async fn read_clus<T: Read + Seek>(&self, reader: &mut T, cluster: usize) -> Result<u16> {
493 self.read_clus_at(reader, cluster, 0).await
494 }
495
496 async fn read_clus_at<T: Read + Seek>(&self, reader: &mut T, cluster: usize, fat_index: usize) -> Result<u16> {
498 let byte_offset = self.start + fat_index * self.size + (cluster * 3) / 2;
499 reader.seek(SeekFrom::Start(byte_offset as u64)).await?;
500
501 let mut bytes = [0u8; 2];
502 reader.read_exact(&mut bytes).await?;
503
504 let value = if cluster.is_multiple_of(2) {
505 u16::from(bytes[0]) | (u16::from(bytes[1] & 0x0F) << 8)
506 } else {
507 (u16::from(bytes[0]) >> 4) | (u16::from(bytes[1]) << 4)
508 };
509
510 Ok(value)
511 }
512
513 fn is_end_of_chain(value: u16) -> bool {
515 value >= Self::END_OF_CHAIN_MIN
516 }
517
518 fn is_bad_cluster(value: u16) -> bool {
520 value == Self::BAD_CLUSTER
521 }
522
523 fn validate_cluster(&self, cluster: u16) -> Result<()> {
525 if cluster < Self::FIRST_DATA_CLUSTER {
526 return Err(Error::ClusterOutOfBounds {
527 cluster: cluster as u32,
528 max: self.max_cluster as u32,
529 });
530 }
531 if cluster > self.max_cluster {
532 return Err(Error::ClusterOutOfBounds {
533 cluster: cluster as u32,
534 max: self.max_cluster as u32,
535 });
536 }
537 Ok(())
538 }
539
540 pub async fn next_cluster<T: Read + Seek>(
542 &self,
543 reader: &mut T,
544 cluster: usize,
545 ) -> Result<Option<u32>> {
546 let entry = self.read_clus(reader, cluster).await? & Self::ENTRY_MASK;
547
548 if Self::is_end_of_chain(entry) {
549 return Ok(None);
550 }
551
552 if Self::is_bad_cluster(entry) {
553 return Err(Error::BadCluster {
554 cluster: cluster as u32,
555 });
556 }
557
558 self.validate_cluster(entry)?;
559
560 Ok(Some(entry as u32))
561 }
562
563 #[cfg(feature = "write")]
565 const FREE_CLUSTER: u16 = 0x0000;
566 #[cfg(feature = "write")]
568 const END_OF_CHAIN: u16 = 0x0FF8;
569
570 #[cfg(feature = "write")]
572 async fn write_clus_at<T: Read + Write + Seek>(
573 &self,
574 rw: &mut T,
575 cluster: usize,
576 value: u16,
577 fat_index: usize,
578 ) -> Result<()> {
579 let byte_offset = self.start + fat_index * self.size + (cluster * 3) / 2;
580 rw.seek(SeekFrom::Start(byte_offset as u64)).await?;
581
582 let mut bytes = [0u8; 2];
584 rw.read_exact(&mut bytes).await?;
585
586 if cluster.is_multiple_of(2) {
588 bytes[0] = value as u8;
590 bytes[1] = (bytes[1] & 0xF0) | ((value >> 8) as u8 & 0x0F);
591 } else {
592 bytes[0] = (bytes[0] & 0x0F) | ((value << 4) as u8);
594 bytes[1] = (value >> 4) as u8;
595 }
596
597 rw.seek(SeekFrom::Start(byte_offset as u64)).await?;
599 rw.write_all(&bytes).await?;
600
601 Ok(())
602 }
603
604 #[cfg(feature = "write")]
606 pub async fn write_clus<T: Read + Write + Seek>(
607 &self,
608 rw: &mut T,
609 cluster: usize,
610 value: u16,
611 ) -> Result<()> {
612 for i in 0..self.count {
613 self.write_clus_at(rw, cluster, value, i).await?;
614 }
615 Ok(())
616 }
617
618 #[cfg(feature = "write")]
620 pub async fn allocate_cluster<T: Read + Write + Seek>(&self, rw: &mut T, hint: u16) -> Result<u16> {
621 let start = if hint >= Self::FIRST_DATA_CLUSTER && hint <= self.max_cluster {
622 hint
623 } else {
624 Self::FIRST_DATA_CLUSTER
625 };
626
627 for cluster in start..=self.max_cluster {
629 let entry = self.read_clus(rw, cluster as usize).await? & Self::ENTRY_MASK;
630 if entry == Self::FREE_CLUSTER {
631 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
632 return Ok(cluster);
633 }
634 }
635
636 for cluster in Self::FIRST_DATA_CLUSTER..start {
638 let entry = self.read_clus(rw, cluster as usize).await? & Self::ENTRY_MASK;
639 if entry == Self::FREE_CLUSTER {
640 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
641 return Ok(cluster);
642 }
643 }
644
645 Err(Error::NoFreeSpace)
646 }
647
648 #[cfg(feature = "write")]
655 pub async fn allocate_chain<T: Read + Write + Seek>(
656 &self,
657 rw: &mut T,
658 count: usize,
659 hint: u16,
660 ) -> Result<u16> {
661 if count == 0 {
662 return Err(Error::NoFreeSpace);
663 }
664 let first = self.allocate_cluster(rw, hint).await?;
665 let mut prev = first;
666 for _ in 1..count {
667 let next = self.allocate_cluster(rw, prev + 1).await?;
668 self.write_clus(rw, prev as usize, next).await?;
669 prev = next;
670 }
671 Ok(first)
672 }
673
674 #[cfg(feature = "write")]
679 pub async fn extend_chain<T: Read + Write + Seek>(
680 &self,
681 rw: &mut T,
682 last: u16,
683 count: usize,
684 hint: u16,
685 ) -> Result<u16> {
686 if count == 0 {
687 return Ok(last);
688 }
689 let first_new = self.allocate_chain(rw, count, hint).await?;
690 self.write_clus(rw, last as usize, first_new).await?;
691 Ok(first_new)
692 }
693
694 #[cfg(feature = "write")]
696 pub async fn free_chain<T: Read + Write + Seek>(&self, rw: &mut T, start: u16) -> Result<u32> {
697 let mut count = 0u32;
698 let mut current = start;
699
700 loop {
701 if current < Self::FIRST_DATA_CLUSTER || current > self.max_cluster {
702 break;
703 }
704
705 let next = self.read_clus(rw, current as usize).await? & Self::ENTRY_MASK;
706 self.write_clus(rw, current as usize, Self::FREE_CLUSTER).await?;
707 count += 1;
708
709 if Self::is_end_of_chain(next)
710 || Self::is_bad_cluster(next)
711 || next == Self::FREE_CLUSTER
712 {
713 break;
714 }
715
716 current = next;
717 }
718
719 Ok(count)
720 }
721
722 #[cfg(feature = "write")]
729 pub async fn truncate_chain<T: Read + Write + Seek>(&self, rw: &mut T, cluster: u16) -> Result<u32> {
730 if cluster < Self::FIRST_DATA_CLUSTER || cluster > self.max_cluster {
731 return Ok(0);
732 }
733
734 let next = self.read_clus(rw, cluster as usize).await? & Self::ENTRY_MASK;
736
737 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
739
740 if !Self::is_end_of_chain(next)
742 && next >= Self::FIRST_DATA_CLUSTER
743 && next <= self.max_cluster
744 {
745 self.free_chain(rw, next).await
746 } else {
747 Ok(0)
748 }
749 }
750
751 #[cfg(feature = "write")]
753 pub async fn mark_bad<T: Read + Write + Seek>(&self, rw: &mut T, cluster: u16) -> Result<()> {
754 self.write_clus(rw, cluster as usize, Self::BAD_CLUSTER).await
755 }
756}
757
758pub struct Fat16 {
760 start: usize,
761 size: usize,
762 count: usize,
763 max_cluster: u16,
764}
765
766impl Fat16 {
767 const END_OF_CHAIN_MIN: u16 = 0xFFF8;
769 const BAD_CLUSTER: u16 = 0xFFF7;
771 const FIRST_DATA_CLUSTER: u16 = 2;
773
774 #[cfg(feature = "cache")]
777 pub(crate) fn cache_layout(&self) -> (usize, usize, usize) {
778 (self.start, self.size, self.count)
779 }
780
781 pub fn new(start: usize, size: usize, count: usize, max_cluster: u16) -> Self {
783 debug_assert!(count == 1 || count == 2);
784 Self {
785 start,
786 size,
787 count,
788 max_cluster,
789 }
790 }
791
792 pub fn max_cluster(&self) -> u16 {
794 self.max_cluster
795 }
796
797 sync_only! {
798 #[cfg(feature = "tool")]
799 pub(crate) fn entry_offset(&self, cluster: usize) -> usize {
800 debug_assert!(cluster * size_of::<u16>() < self.size);
801 self.start + cluster * size_of::<u16>()
802 }
803 }
804
805 async fn read_clus<T: Read + Seek>(&self, reader: &mut T, cluster: usize) -> Result<u16> {
806 self.read_clus_at(reader, cluster, 0).await
807 }
808
809 async fn read_clus_at<T: Read + Seek>(&self, reader: &mut T, cluster: usize, fat_index: usize) -> Result<u16> {
811 let offset = self.start + fat_index * self.size + cluster * size_of::<u16>();
812 reader.seek(SeekFrom::Start(offset as u64)).await?;
813 let mut data = 0u16;
814 reader.read_exact(bytemuck::bytes_of_mut(&mut data)).await?;
815 Ok(u16::from_le(data))
816 }
817
818 fn is_end_of_chain(value: u16) -> bool {
820 value >= Self::END_OF_CHAIN_MIN
821 }
822
823 fn is_bad_cluster(value: u16) -> bool {
825 value == Self::BAD_CLUSTER
826 }
827
828 fn validate_cluster(&self, cluster: u16) -> Result<()> {
830 if cluster < Self::FIRST_DATA_CLUSTER {
831 return Err(Error::ClusterOutOfBounds {
832 cluster: cluster as u32,
833 max: self.max_cluster as u32,
834 });
835 }
836 if cluster > self.max_cluster {
837 return Err(Error::ClusterOutOfBounds {
838 cluster: cluster as u32,
839 max: self.max_cluster as u32,
840 });
841 }
842 Ok(())
843 }
844
845 pub async fn next_cluster<T: Read + Seek>(
847 &self,
848 reader: &mut T,
849 cluster: usize,
850 ) -> Result<Option<u32>> {
851 let entry = self.read_clus(reader, cluster).await?;
852
853 if Self::is_end_of_chain(entry) {
854 return Ok(None);
855 }
856
857 if Self::is_bad_cluster(entry) {
858 return Err(Error::BadCluster {
859 cluster: cluster as u32,
860 });
861 }
862
863 self.validate_cluster(entry)?;
864
865 Ok(Some(entry as u32))
866 }
867
868 #[cfg(feature = "write")]
870 const FREE_CLUSTER: u16 = 0x0000;
871 #[cfg(feature = "write")]
873 const END_OF_CHAIN: u16 = 0xFFF8;
874
875 #[cfg(feature = "write")]
877 async fn write_clus_at<T: Write + Seek>(
878 &self,
879 writer: &mut T,
880 cluster: usize,
881 value: u16,
882 fat_index: usize,
883 ) -> Result<()> {
884 let offset = self.start + fat_index * self.size + cluster * size_of::<u16>();
885 writer.seek(SeekFrom::Start(offset as u64)).await?;
886 writer.write_all(&value.to_le_bytes()).await?;
887 Ok(())
888 }
889
890 #[cfg(feature = "write")]
892 pub async fn write_clus<T: Write + Seek>(
893 &self,
894 writer: &mut T,
895 cluster: usize,
896 value: u16,
897 ) -> Result<()> {
898 for i in 0..self.count {
899 self.write_clus_at(writer, cluster, value, i).await?;
900 }
901 Ok(())
902 }
903
904 #[cfg(feature = "write")]
906 pub async fn allocate_cluster<T: Read + Write + Seek>(&self, rw: &mut T, hint: u16) -> Result<u16> {
907 let start = if hint >= Self::FIRST_DATA_CLUSTER && hint <= self.max_cluster {
908 hint
909 } else {
910 Self::FIRST_DATA_CLUSTER
911 };
912
913 for cluster in start..=self.max_cluster {
915 let entry = self.read_clus(rw, cluster as usize).await?;
916 if entry == Self::FREE_CLUSTER {
917 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
918 return Ok(cluster);
919 }
920 }
921
922 for cluster in Self::FIRST_DATA_CLUSTER..start {
924 let entry = self.read_clus(rw, cluster as usize).await?;
925 if entry == Self::FREE_CLUSTER {
926 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
927 return Ok(cluster);
928 }
929 }
930
931 Err(Error::NoFreeSpace)
932 }
933
934 #[cfg(feature = "write")]
941 pub async fn allocate_chain<T: Read + Write + Seek>(
942 &self,
943 rw: &mut T,
944 count: usize,
945 hint: u16,
946 ) -> Result<u16> {
947 if count == 0 {
948 return Err(Error::NoFreeSpace);
949 }
950 let first = self.allocate_cluster(rw, hint).await?;
951 let mut prev = first;
952 for _ in 1..count {
953 let next = self.allocate_cluster(rw, prev + 1).await?;
954 self.write_clus(rw, prev as usize, next).await?;
955 prev = next;
956 }
957 Ok(first)
958 }
959
960 #[cfg(feature = "write")]
965 pub async fn extend_chain<T: Read + Write + Seek>(
966 &self,
967 rw: &mut T,
968 last: u16,
969 count: usize,
970 hint: u16,
971 ) -> Result<u16> {
972 if count == 0 {
973 return Ok(last);
974 }
975 let first_new = self.allocate_chain(rw, count, hint).await?;
976 self.write_clus(rw, last as usize, first_new).await?;
977 Ok(first_new)
978 }
979
980 #[cfg(feature = "write")]
982 pub async fn free_chain<T: Read + Write + Seek>(&self, rw: &mut T, start: u16) -> Result<u32> {
983 let mut count = 0u32;
984 let mut current = start;
985
986 loop {
987 if current < Self::FIRST_DATA_CLUSTER || current > self.max_cluster {
988 break;
989 }
990
991 let next = self.read_clus(rw, current as usize).await?;
992 self.write_clus(rw, current as usize, Self::FREE_CLUSTER).await?;
993 count += 1;
994
995 if Self::is_end_of_chain(next)
996 || Self::is_bad_cluster(next)
997 || next == Self::FREE_CLUSTER
998 {
999 break;
1000 }
1001
1002 current = next;
1003 }
1004
1005 Ok(count)
1006 }
1007
1008 #[cfg(feature = "write")]
1015 pub async fn truncate_chain<T: Read + Write + Seek>(&self, rw: &mut T, cluster: u16) -> Result<u32> {
1016 if cluster < Self::FIRST_DATA_CLUSTER || cluster > self.max_cluster {
1017 return Ok(0);
1018 }
1019
1020 let next = self.read_clus(rw, cluster as usize).await?;
1022
1023 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
1025
1026 if !Self::is_end_of_chain(next)
1028 && next >= Self::FIRST_DATA_CLUSTER
1029 && next <= self.max_cluster
1030 {
1031 self.free_chain(rw, next).await
1032 } else {
1033 Ok(0)
1034 }
1035 }
1036
1037 #[cfg(feature = "write")]
1039 pub async fn mark_bad<T: Read + Write + Seek>(&self, rw: &mut T, cluster: u16) -> Result<()> {
1040 self.write_clus(rw, cluster as usize, Self::BAD_CLUSTER).await
1041 }
1042}
1043
1044pub struct Fat32 {
1046 start: usize,
1047 size: usize,
1048 count: usize,
1049 max_cluster: u32,
1050}
1051
1052impl Fat32 {
1053 const ENTRY_MASK: u32 = 0x0FFF_FFFF;
1055 const END_OF_CHAIN_MIN: u32 = 0x0FFF_FFF8;
1057 const BAD_CLUSTER: u32 = 0x0FFF_FFF7;
1059 const FIRST_DATA_CLUSTER: u32 = 2;
1061
1062 #[cfg(feature = "cache")]
1065 pub(crate) fn cache_layout(&self) -> (usize, usize, usize) {
1066 (self.start, self.size, self.count)
1067 }
1068
1069 pub fn new(start: usize, size: usize, count: usize, max_cluster: u32) -> Self {
1071 debug_assert!(count == 1 || count == 2);
1072 Self {
1073 start,
1074 size,
1075 count,
1076 max_cluster,
1077 }
1078 }
1079
1080 pub fn max_cluster(&self) -> u32 {
1082 self.max_cluster
1083 }
1084
1085 sync_only! {
1086 #[cfg(feature = "tool")]
1087 pub(crate) fn entry_offset(&self, cluster: usize) -> usize {
1088 debug_assert!(cluster * size_of::<u32>() < self.size);
1089 self.start + cluster * size_of::<u32>()
1090 }
1091 }
1092
1093 async fn read_clus<T: Read + Seek>(&self, reader: &mut T, cluster: usize) -> Result<u32> {
1094 self.read_clus_at(reader, cluster, 0).await
1095 }
1096
1097 async fn read_clus_at<T: Read + Seek>(&self, reader: &mut T, cluster: usize, fat_index: usize) -> Result<u32> {
1099 let offset = self.start + fat_index * self.size + cluster * size_of::<u32>();
1100 reader.seek(SeekFrom::Start(offset as u64)).await?;
1101 let mut data = 0u32;
1102 reader.read_exact(bytemuck::bytes_of_mut(&mut data)).await?;
1103 Ok(u32::from_le(data))
1104 }
1105
1106 fn is_end_of_chain(value: u32) -> bool {
1108 value >= Self::END_OF_CHAIN_MIN
1109 }
1110
1111 fn is_bad_cluster(value: u32) -> bool {
1113 value == Self::BAD_CLUSTER
1114 }
1115
1116 fn validate_cluster(&self, cluster: u32) -> Result<()> {
1118 if cluster < Self::FIRST_DATA_CLUSTER {
1119 return Err(Error::ClusterOutOfBounds {
1120 cluster,
1121 max: self.max_cluster,
1122 });
1123 }
1124 if cluster > self.max_cluster {
1125 return Err(Error::ClusterOutOfBounds {
1126 cluster,
1127 max: self.max_cluster,
1128 });
1129 }
1130 Ok(())
1131 }
1132
1133 pub async fn next_cluster<T: Read + Seek>(
1135 &self,
1136 reader: &mut T,
1137 cluster: usize,
1138 ) -> Result<Option<u32>> {
1139 let raw_entry = self.read_clus(reader, cluster).await?;
1141 let entry = raw_entry & Self::ENTRY_MASK;
1142
1143 if Self::is_end_of_chain(entry) {
1145 return Ok(None);
1146 }
1147
1148 if Self::is_bad_cluster(entry) {
1150 return Err(Error::BadCluster {
1151 cluster: cluster as u32,
1152 });
1153 }
1154
1155 self.validate_cluster(entry)?;
1157
1158 Ok(Some(entry))
1159 }
1160
1161 #[cfg(feature = "write")]
1163 async fn write_clus_at<T: Read + Write + Seek>(
1164 &self,
1165 io: &mut T,
1166 cluster: usize,
1167 value: u32,
1168 fat_index: usize,
1169 ) -> Result<()> {
1170 let offset = self.start + fat_index * self.size + cluster * size_of::<u32>();
1171 io.seek(SeekFrom::Start(offset as u64)).await?;
1172 let mut existing = [0_u8; size_of::<u32>()];
1173 io.read_exact(&mut existing).await?;
1174 let preserved = u32::from_le_bytes(existing) & !Self::ENTRY_MASK;
1175 let updated = preserved | (value & Self::ENTRY_MASK);
1176 io.seek(SeekFrom::Start(offset as u64)).await?;
1177 io.write_all(&updated.to_le_bytes()).await?;
1178 Ok(())
1179 }
1180
1181 #[cfg(feature = "write")]
1183 pub async fn write_clus<T: Read + Write + Seek>(
1184 &self,
1185 io: &mut T,
1186 cluster: usize,
1187 value: u32,
1188 ) -> Result<()> {
1189 for i in 0..self.count {
1190 self.write_clus_at(io, cluster, value, i).await?;
1191 }
1192 Ok(())
1193 }
1194
1195 #[cfg(feature = "write")]
1197 const FREE_CLUSTER: u32 = 0x00000000;
1198 #[cfg(feature = "write")]
1200 const END_OF_CHAIN: u32 = 0x0FFFFFF8;
1201
1202 #[cfg(feature = "write")]
1205 pub async fn allocate_cluster<T: Read + Write + Seek>(&self, rw: &mut T, hint: u32) -> Result<u32> {
1206 let start = if hint >= Self::FIRST_DATA_CLUSTER && hint <= self.max_cluster {
1208 hint
1209 } else {
1210 Self::FIRST_DATA_CLUSTER
1211 };
1212
1213 for cluster in start..=self.max_cluster {
1215 let entry = self.read_clus(rw, cluster as usize).await? & Self::ENTRY_MASK;
1216 if entry == Self::FREE_CLUSTER {
1217 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
1219 return Ok(cluster);
1220 }
1221 }
1222
1223 for cluster in Self::FIRST_DATA_CLUSTER..start {
1225 let entry = self.read_clus(rw, cluster as usize).await? & Self::ENTRY_MASK;
1226 if entry == Self::FREE_CLUSTER {
1227 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
1229 return Ok(cluster);
1230 }
1231 }
1232
1233 Err(Error::NoFreeSpace)
1234 }
1235
1236 #[cfg(feature = "write")]
1239 pub async fn allocate_chain<T: Read + Write + Seek>(
1240 &self,
1241 rw: &mut T,
1242 count: usize,
1243 hint: u32,
1244 ) -> Result<u32> {
1245 if count == 0 {
1246 return Err(Error::NoFreeSpace);
1247 }
1248
1249 let first = self.allocate_cluster(rw, hint).await?;
1250 let mut prev = first;
1251
1252 for _ in 1..count {
1253 let next = self.allocate_cluster(rw, prev + 1).await?;
1254 self.write_clus(rw, prev as usize, next).await?;
1256 prev = next;
1257 }
1258
1259 Ok(first)
1260 }
1261
1262 #[cfg(feature = "write")]
1264 pub async fn free_chain<T: Read + Write + Seek>(&self, rw: &mut T, start: u32) -> Result<u32> {
1265 let mut count = 0;
1266 let mut current = start;
1267
1268 loop {
1269 if current < Self::FIRST_DATA_CLUSTER || current > self.max_cluster {
1271 break;
1272 }
1273
1274 let raw_entry = self.read_clus(rw, current as usize).await?;
1276 let next = raw_entry & Self::ENTRY_MASK;
1277
1278 self.write_clus(rw, current as usize, Self::FREE_CLUSTER).await?;
1280 count += 1;
1281
1282 if Self::is_end_of_chain(next)
1284 || Self::is_bad_cluster(next)
1285 || next == Self::FREE_CLUSTER
1286 {
1287 break;
1288 }
1289
1290 current = next;
1291 }
1292
1293 Ok(count)
1294 }
1295
1296 #[cfg(feature = "write")]
1303 pub async fn truncate_chain<T: Read + Write + Seek>(&self, rw: &mut T, cluster: u32) -> Result<u32> {
1304 if cluster < Self::FIRST_DATA_CLUSTER || cluster > self.max_cluster {
1305 return Ok(0);
1306 }
1307
1308 let raw_entry = self.read_clus(rw, cluster as usize).await?;
1310 let next = raw_entry & Self::ENTRY_MASK;
1311
1312 self.write_clus(rw, cluster as usize, Self::END_OF_CHAIN).await?;
1314
1315 if !Self::is_end_of_chain(next)
1317 && next >= Self::FIRST_DATA_CLUSTER
1318 && next <= self.max_cluster
1319 {
1320 self.free_chain(rw, next).await
1321 } else {
1322 Ok(0)
1323 }
1324 }
1325
1326 #[cfg(feature = "write")]
1328 pub async fn mark_bad<T: Read + Write + Seek>(&self, rw: &mut T, cluster: u32) -> Result<()> {
1329 self.write_clus(rw, cluster as usize, Self::BAD_CLUSTER).await
1330 }
1331
1332 #[cfg(feature = "write")]
1335 pub async fn extend_chain<T: Read + Write + Seek>(
1336 &self,
1337 rw: &mut T,
1338 last: u32,
1339 count: usize,
1340 hint: u32,
1341 ) -> Result<u32> {
1342 if count == 0 {
1343 return Ok(last);
1344 }
1345
1346 let first_new = self.allocate_chain(rw, count, hint).await?;
1347 self.write_clus(rw, last as usize, first_new).await?;
1349 Ok(first_new)
1350 }
1351}
1352
1353}