1use crate::{
4 debug,
5 fat::{
6 lfn::LfnVisitor, Bpb, Fat16Info, Fat32Info, FatSpecificInfo, FatType, InfoSector,
7 OnDiskDirEntry, RESERVED_ENTRIES,
8 },
9 filesystem::ToShortFileName,
10 trace, warn, Attributes, Block, BlockCount, BlockDevice, BlockIdx, ClusterId, DirEntry,
11 DirectoryInfo, Error, ShortFileName, TimeSource, VolumeType,
12};
13use byteorder::{ByteOrder, LittleEndian};
14use core::convert::TryFrom;
15use core::ops::ControlFlow;
16
17use super::BlockCache;
18
19#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
21#[derive(Clone, PartialEq, Eq)]
22pub struct VolumeName {
23 data: [u8; 11],
24}
25
26impl VolumeName {
27 pub fn new(data: [u8; 11]) -> VolumeName {
29 VolumeName { data }
30 }
31}
32
33impl core::fmt::Debug for VolumeName {
34 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
35 match core::str::from_utf8(&self.data) {
36 Ok(s) => write!(fmt, "{:?}", s),
37 Err(_e) => write!(fmt, "{:?}", &self.data),
38 }
39 }
40}
41
42#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
44#[derive(Debug, PartialEq, Eq)]
45pub struct FatVolume {
46 pub(crate) lba_start: BlockIdx,
48 pub(crate) num_blocks: BlockCount,
50 pub(crate) name: VolumeName,
52 pub(crate) blocks_per_cluster: u8,
54 pub(crate) first_data_block: BlockCount,
57 pub(crate) fat_start: BlockCount,
60 pub(crate) free_clusters_count: Option<u32>,
62 pub(crate) next_free_cluster: Option<ClusterId>,
64 pub(crate) cluster_count: u32,
66 pub(crate) fat_specific_info: FatSpecificInfo,
68}
69
70impl FatVolume {
71 pub async fn update_info_sector<D>(&mut self, block_device: &D) -> Result<(), Error<D::Error>>
73 where
74 D: BlockDevice,
75 {
76 match &self.fat_specific_info {
77 FatSpecificInfo::Fat16(_) => {
78 }
80 FatSpecificInfo::Fat32(fat32_info) => {
81 if self.free_clusters_count.is_none() && self.next_free_cluster.is_none() {
82 return Ok(());
83 }
84 let mut blocks = [Block::new()];
85 block_device
86 .read(&mut blocks, fat32_info.info_location, "read_info_sector")
87 .await
88 .map_err(Error::DeviceError)?;
89 let block = &mut blocks[0];
90 if let Some(count) = self.free_clusters_count {
91 block[488..492].copy_from_slice(&count.to_le_bytes());
92 }
93 if let Some(next_free_cluster) = self.next_free_cluster {
94 block[492..496].copy_from_slice(&next_free_cluster.0.to_le_bytes());
95 }
96 block_device
97 .write(&blocks, fat32_info.info_location)
98 .await
99 .map_err(Error::DeviceError)?;
100 }
101 }
102 Ok(())
103 }
104
105 pub(crate) fn get_fat_type(&self) -> FatType {
107 match &self.fat_specific_info {
108 FatSpecificInfo::Fat16(_) => FatType::Fat16,
109 FatSpecificInfo::Fat32(_) => FatType::Fat32,
110 }
111 }
112
113 async fn update_fat<D>(
115 &mut self,
116 block_device: &D,
117 cluster: ClusterId,
118 new_value: ClusterId,
119 ) -> Result<(), Error<D::Error>>
120 where
121 D: BlockDevice,
122 {
123 let mut blocks = [Block::new()];
124 let this_fat_block_num;
125 match &self.fat_specific_info {
126 FatSpecificInfo::Fat16(_fat16_info) => {
127 let fat_offset = cluster.0 * 2;
128 this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
129 let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize;
130 block_device
131 .read(&mut blocks, this_fat_block_num, "read_fat")
132 .await
133 .map_err(Error::DeviceError)?;
134 let entry = match new_value {
136 ClusterId::INVALID => 0xFFF6,
137 ClusterId::BAD => 0xFFF7,
138 ClusterId::EMPTY => 0x0000,
139 ClusterId::END_OF_FILE => 0xFFFF,
140 _ => new_value.0 as u16,
141 };
142 LittleEndian::write_u16(
143 &mut blocks[0][this_fat_ent_offset..=this_fat_ent_offset + 1],
144 entry,
145 );
146 }
147 FatSpecificInfo::Fat32(_fat32_info) => {
148 let fat_offset = cluster.0 * 4;
150 this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
151 let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize;
152 block_device
153 .read(&mut blocks, this_fat_block_num, "read_fat")
154 .await
155 .map_err(Error::DeviceError)?;
156 let entry = match new_value {
157 ClusterId::INVALID => 0x0FFF_FFF6,
158 ClusterId::BAD => 0x0FFF_FFF7,
159 ClusterId::EMPTY => 0x0000_0000,
160 _ => new_value.0,
161 };
162 let existing = LittleEndian::read_u32(
163 &blocks[0][this_fat_ent_offset..=this_fat_ent_offset + 3],
164 );
165 let new = (existing & 0xF000_0000) | (entry & 0x0FFF_FFFF);
166 LittleEndian::write_u32(
167 &mut blocks[0][this_fat_ent_offset..=this_fat_ent_offset + 3],
168 new,
169 );
170 }
171 }
172 block_device
173 .write(&blocks, this_fat_block_num)
174 .await
175 .map_err(Error::DeviceError)?;
176 Ok(())
177 }
178
179 pub(crate) async fn next_cluster<D>(
181 &self,
182 block_device: &D,
183 cluster: ClusterId,
184 fat_block_cache: &mut BlockCache,
185 ) -> Result<ClusterId, Error<D::Error>>
186 where
187 D: BlockDevice,
188 {
189 match &self.fat_specific_info {
190 FatSpecificInfo::Fat16(_fat16_info) => {
191 let fat_offset = cluster.0 * 2;
192 let this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
193 let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize;
194 let block = fat_block_cache
195 .read(block_device, this_fat_block_num, "next_cluster")
196 .await?;
197 let fat_entry =
198 LittleEndian::read_u16(&block[this_fat_ent_offset..=this_fat_ent_offset + 1]);
199 match fat_entry {
200 0xFFF7 => {
201 Err(Error::BadCluster)
203 }
204 0xFFF8..=0xFFFF => {
205 Err(Error::EndOfFile)
207 }
208 f => {
209 Ok(ClusterId(u32::from(f)))
211 }
212 }
213 }
214 FatSpecificInfo::Fat32(_fat32_info) => {
215 let fat_offset = cluster.0 * 4;
216 let this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
217 let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize;
218 let block = fat_block_cache
219 .read(block_device, this_fat_block_num, "next_cluster")
220 .await?;
221 let fat_entry =
222 LittleEndian::read_u32(&block[this_fat_ent_offset..=this_fat_ent_offset + 3])
223 & 0x0FFF_FFFF;
224 match fat_entry {
225 0x0000_0000 => {
226 Err(Error::UnterminatedFatChain)
228 }
229 0x0FFF_FFF7 => {
230 Err(Error::BadCluster)
232 }
233 0x0000_0001 | 0x0FFF_FFF8..=0x0FFF_FFFF => {
234 Err(Error::EndOfFile)
236 }
237 f => {
238 Ok(ClusterId(f))
240 }
241 }
242 }
243 }
244 }
245
246 pub(crate) fn bytes_per_cluster(&self) -> u32 {
248 u32::from(self.blocks_per_cluster) * Block::LEN_U32
249 }
250
251 pub(crate) fn cluster_to_block(&self, cluster: ClusterId) -> BlockIdx {
255 match &self.fat_specific_info {
256 FatSpecificInfo::Fat16(fat16_info) => {
257 let block_num = match cluster {
258 ClusterId::ROOT_DIR => fat16_info.first_root_dir_block,
259 ClusterId(c) => {
260 let first_block_of_cluster =
262 BlockCount((c - 2) * u32::from(self.blocks_per_cluster));
263 self.first_data_block + first_block_of_cluster
264 }
265 };
266 self.lba_start + block_num
267 }
268 FatSpecificInfo::Fat32(fat32_info) => {
269 let cluster_num = match cluster {
270 ClusterId::ROOT_DIR => fat32_info.first_root_dir_cluster.0,
271 c => c.0,
272 };
273 let first_block_of_cluster =
275 BlockCount((cluster_num - 2) * u32::from(self.blocks_per_cluster));
276 self.lba_start + self.first_data_block + first_block_of_cluster
277 }
278 }
279 }
280
281 pub(crate) async fn write_new_directory_entry<D, T>(
284 &mut self,
285 block_device: &D,
286 time_source: &T,
287 dir: &DirectoryInfo,
288 name: ShortFileName,
289 attributes: Attributes,
290 ) -> Result<DirEntry, Error<D::Error>>
291 where
292 D: BlockDevice,
293 T: TimeSource,
294 {
295 match &self.fat_specific_info {
296 FatSpecificInfo::Fat16(fat16_info) => {
297 let mut current_cluster = Some(dir.cluster);
302 let mut first_dir_block_num = match dir.cluster {
303 ClusterId::ROOT_DIR => self.lba_start + fat16_info.first_root_dir_block,
304 _ => self.cluster_to_block(dir.cluster),
305 };
306 let dir_size = match dir.cluster {
307 ClusterId::ROOT_DIR => {
308 let len_bytes =
309 u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32;
310 BlockCount::from_bytes(len_bytes)
311 }
312 _ => BlockCount(u32::from(self.blocks_per_cluster)),
313 };
314
315 let mut blocks = [Block::new()];
317 while let Some(cluster) = current_cluster {
318 for block in first_dir_block_num.range(dir_size) {
319 block_device
320 .read(&mut blocks, block, "read_dir")
321 .await
322 .map_err(Error::DeviceError)?;
323 let entries_per_block = Block::LEN / OnDiskDirEntry::LEN;
324 for entry in 0..entries_per_block {
325 let start = entry * OnDiskDirEntry::LEN;
326 let end = (entry + 1) * OnDiskDirEntry::LEN;
327 let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
328 if !dir_entry.is_valid() {
330 let ctime = time_source.get_timestamp();
331 let entry = DirEntry::new(
332 name,
333 attributes,
334 ClusterId::EMPTY,
335 ctime,
336 block,
337 start as u32,
338 );
339 blocks[0][start..start + 32]
340 .copy_from_slice(&entry.serialize(FatType::Fat16)[..]);
341 block_device
342 .write(&blocks, block)
343 .await
344 .map_err(Error::DeviceError)?;
345 return Ok(entry);
346 }
347 }
348 }
349 if cluster != ClusterId::ROOT_DIR {
350 let mut block_cache = BlockCache::empty();
351 current_cluster = match self
352 .next_cluster(block_device, cluster, &mut block_cache)
353 .await
354 {
355 Ok(n) => {
356 first_dir_block_num = self.cluster_to_block(n);
357 Some(n)
358 }
359 Err(Error::EndOfFile) => {
360 let c = self
361 .alloc_cluster(block_device, Some(cluster), true)
362 .await?;
363 first_dir_block_num = self.cluster_to_block(c);
364 Some(c)
365 }
366 _ => None,
367 };
368 } else {
369 current_cluster = None;
370 }
371 }
372 Err(Error::NotEnoughSpace)
373 }
374 FatSpecificInfo::Fat32(fat32_info) => {
375 let mut first_dir_block_num = match dir.cluster {
378 ClusterId::ROOT_DIR => self.cluster_to_block(fat32_info.first_root_dir_cluster),
379 _ => self.cluster_to_block(dir.cluster),
380 };
381 let mut current_cluster = Some(dir.cluster);
382 let mut blocks = [Block::new()];
383
384 let dir_size = BlockCount(u32::from(self.blocks_per_cluster));
385 while let Some(cluster) = current_cluster {
386 for block in first_dir_block_num.range(dir_size) {
387 block_device
388 .read(&mut blocks, block, "read_dir")
389 .await
390 .map_err(Error::DeviceError)?;
391 for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
392 let start = entry * OnDiskDirEntry::LEN;
393 let end = (entry + 1) * OnDiskDirEntry::LEN;
394 let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
395 if !dir_entry.is_valid() {
397 let ctime = time_source.get_timestamp();
398 let entry = DirEntry::new(
399 name,
400 attributes,
401 ClusterId(0),
402 ctime,
403 block,
404 start as u32,
405 );
406 blocks[0][start..start + 32]
407 .copy_from_slice(&entry.serialize(FatType::Fat32)[..]);
408 block_device
409 .write(&blocks, block)
410 .await
411 .map_err(Error::DeviceError)?;
412 return Ok(entry);
413 }
414 }
415 }
416 let mut block_cache = BlockCache::empty();
417 current_cluster = match self
418 .next_cluster(block_device, cluster, &mut block_cache)
419 .await
420 {
421 Ok(n) => {
422 first_dir_block_num = self.cluster_to_block(n);
423 Some(n)
424 }
425 Err(Error::EndOfFile) => {
426 let c = self
427 .alloc_cluster(block_device, Some(cluster), true)
428 .await?;
429 first_dir_block_num = self.cluster_to_block(c);
430 Some(c)
431 }
432 _ => None,
433 };
434 }
435 Err(Error::NotEnoughSpace)
436 }
437 }
438 }
439
440 pub(crate) async fn iterate_dir<D, F, T>(
443 &self,
444 block_device: &D,
445 dir: &DirectoryInfo,
446 mut func: F,
447 ) -> Result<Option<T>, Error<D::Error>>
448 where
449 F: FnMut(&DirEntry) -> ControlFlow<T>,
450 D: BlockDevice,
451 {
452 self.iterate_dir_generic(block_device, dir, |_, dir_entry| match dir_entry {
453 Some(dir_entry) => func(&dir_entry),
454 None => ControlFlow::Continue(()),
455 })
456 .await
457 }
458
459 pub(crate) async fn iterate_lfn_dir<D, F, T>(
462 &self,
463 block_device: &D,
464 dir: &DirectoryInfo,
465 mut func: F,
466 ) -> Result<Option<T>, Error<D::Error>>
467 where
468 F: FnMut(Option<&str>, &DirEntry) -> ControlFlow<T>,
469 D: BlockDevice,
470 {
471 let mut lfn_visitor = LfnVisitor::default();
472 self.iterate_dir_generic(block_device, dir, |on_disk_entry, dir_entry| {
473 assert_eq!(on_disk_entry.is_lfn(), dir_entry.is_none());
474 match dir_entry {
475 Some(dir_entry) => {
476 let lfn = lfn_visitor.take(&dir_entry.name);
477 func(lfn, &dir_entry)
478 }
479 None => {
480 let lfn_entry = on_disk_entry.lfn_contents().unwrap();
481 lfn_visitor.visit(&lfn_entry);
482 ControlFlow::Continue(())
483 }
484 }
485 })
486 .await
487 }
488
489 pub(crate) async fn iterate_dir_generic<D, F, T>(
490 &self,
491 block_device: &D,
492 dir: &DirectoryInfo,
493 mut func: F,
494 ) -> Result<Option<T>, Error<D::Error>>
495 where
496 F: FnMut(&OnDiskDirEntry, Option<DirEntry>) -> ControlFlow<T>,
497 D: BlockDevice,
498 {
499 match &self.fat_specific_info {
500 FatSpecificInfo::Fat16(fat16_info) => {
501 let mut current_cluster = Some(dir.cluster);
506 let mut first_dir_block_num = match dir.cluster {
507 ClusterId::ROOT_DIR => self.lba_start + fat16_info.first_root_dir_block,
508 _ => self.cluster_to_block(dir.cluster),
509 };
510 let dir_size = match dir.cluster {
511 ClusterId::ROOT_DIR => {
512 let len_bytes =
513 u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32;
514 BlockCount::from_bytes(len_bytes)
515 }
516 _ => BlockCount(u32::from(self.blocks_per_cluster)),
517 };
518
519 let mut block_cache = BlockCache::empty();
520 while let Some(cluster) = current_cluster {
521 for block_idx in first_dir_block_num.range(dir_size) {
522 let block = block_cache
523 .read(block_device, block_idx, "read_dir")
524 .await?;
525 for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
526 let start = entry * OnDiskDirEntry::LEN;
527 let end = (entry + 1) * OnDiskDirEntry::LEN;
528 let dir_entry = OnDiskDirEntry::new(&block[start..end]);
529 if dir_entry.is_end() {
530 return Ok(None);
532 } else if dir_entry.is_valid() {
533 let entry = if dir_entry.is_lfn() {
534 None
535 } else {
536 let start = u32::try_from(start).unwrap();
538 Some(dir_entry.get_entry(FatType::Fat16, block_idx, start))
539 };
540 if let ControlFlow::Break(ret) = func(&dir_entry, entry) {
541 return Ok(Some(ret));
542 };
543 }
544 }
545 }
546 if cluster != ClusterId::ROOT_DIR {
547 current_cluster = match self
548 .next_cluster(block_device, cluster, &mut block_cache)
549 .await
550 {
551 Ok(n) => {
552 first_dir_block_num = self.cluster_to_block(n);
553 Some(n)
554 }
555 _ => None,
556 };
557 } else {
558 current_cluster = None;
559 }
560 }
561 Ok(None)
562 }
563 FatSpecificInfo::Fat32(fat32_info) => {
564 let mut current_cluster = match dir.cluster {
567 ClusterId::ROOT_DIR => Some(fat32_info.first_root_dir_cluster),
568 _ => Some(dir.cluster),
569 };
570 let mut blocks = [Block::new()];
571 let mut block_cache = BlockCache::empty();
572 while let Some(cluster) = current_cluster {
573 let block_idx = self.cluster_to_block(cluster);
574 for block in block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) {
575 block_device
576 .read(&mut blocks, block, "read_dir")
577 .await
578 .map_err(Error::DeviceError)?;
579 for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
580 let start = entry * OnDiskDirEntry::LEN;
581 let end = (entry + 1) * OnDiskDirEntry::LEN;
582 let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
583 if dir_entry.is_end() {
584 return Ok(None);
586 } else if dir_entry.is_valid() {
587 let entry = if dir_entry.is_lfn() {
588 None
589 } else {
590 let start = u32::try_from(start).unwrap();
592 Some(dir_entry.get_entry(FatType::Fat32, block, start))
593 };
594 if let ControlFlow::Break(ret) = func(&dir_entry, entry) {
595 return Ok(Some(ret));
596 };
597 }
598 }
599 }
600 current_cluster = match self
601 .next_cluster(block_device, cluster, &mut block_cache)
602 .await
603 {
604 Ok(n) => Some(n),
605 _ => None,
606 };
607 }
608 Ok(None)
609 }
610 }
611 }
612
613 pub(crate) async fn find_directory_entry<D>(
615 &self,
616 block_device: &D,
617 dir: &DirectoryInfo,
618 match_name: &ShortFileName,
619 ) -> Result<DirEntry, Error<D::Error>>
620 where
621 D: BlockDevice,
622 {
623 match &self.fat_specific_info {
624 FatSpecificInfo::Fat16(fat16_info) => {
625 let mut current_cluster = Some(dir.cluster);
630 let mut first_dir_block_num = match dir.cluster {
631 ClusterId::ROOT_DIR => self.lba_start + fat16_info.first_root_dir_block,
632 _ => self.cluster_to_block(dir.cluster),
633 };
634 let dir_size = match dir.cluster {
635 ClusterId::ROOT_DIR => {
636 let len_bytes =
637 u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32;
638 BlockCount::from_bytes(len_bytes)
639 }
640 _ => BlockCount(u32::from(self.blocks_per_cluster)),
641 };
642
643 let mut block_cache = BlockCache::empty();
644 while let Some(cluster) = current_cluster {
645 for block in first_dir_block_num.range(dir_size) {
646 match self
647 .find_entry_in_block(block_device, FatType::Fat16, match_name, block)
648 .await
649 {
650 Err(Error::FileNotFound) => continue,
651 x => return x,
652 }
653 }
654 if cluster != ClusterId::ROOT_DIR {
655 current_cluster = match self
656 .next_cluster(block_device, cluster, &mut block_cache)
657 .await
658 {
659 Ok(n) => {
660 first_dir_block_num = self.cluster_to_block(n);
661 Some(n)
662 }
663 _ => None,
664 };
665 } else {
666 current_cluster = None;
667 }
668 }
669 Err(Error::FileNotFound)
670 }
671 FatSpecificInfo::Fat32(fat32_info) => {
672 let mut current_cluster = match dir.cluster {
673 ClusterId::ROOT_DIR => Some(fat32_info.first_root_dir_cluster),
674 _ => Some(dir.cluster),
675 };
676 let mut block_cache = BlockCache::empty();
677 while let Some(cluster) = current_cluster {
678 let block_idx = self.cluster_to_block(cluster);
679 for block in block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) {
680 match self
681 .find_entry_in_block(block_device, FatType::Fat32, match_name, block)
682 .await
683 {
684 Err(Error::FileNotFound) => continue,
685 x => return x,
686 }
687 }
688 current_cluster = match self
689 .next_cluster(block_device, cluster, &mut block_cache)
690 .await
691 {
692 Ok(n) => Some(n),
693 _ => None,
694 }
695 }
696 Err(Error::FileNotFound)
697 }
698 }
699 }
700
701 async fn find_entry_in_block<D>(
703 &self,
704 block_device: &D,
705 fat_type: FatType,
706 match_name: &ShortFileName,
707 block: BlockIdx,
708 ) -> Result<DirEntry, Error<D::Error>>
709 where
710 D: BlockDevice,
711 {
712 let mut blocks = [Block::new()];
713 block_device
714 .read(&mut blocks, block, "read_dir")
715 .await
716 .map_err(Error::DeviceError)?;
717 for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
718 let start = entry * OnDiskDirEntry::LEN;
719 let end = (entry + 1) * OnDiskDirEntry::LEN;
720 let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
721 if dir_entry.is_end() {
722 break;
724 } else if dir_entry.matches(match_name) {
725 let start = u32::try_from(start).unwrap();
728 return Ok(dir_entry.get_entry(fat_type, block, start));
729 }
730 }
731 Err(Error::FileNotFound)
732 }
733
734 #[allow(missing_docs)]
735 pub(crate) async fn find_lfn_directory_entry<D>(
736 &self,
737 block_device: &D,
738 dir: &DirectoryInfo,
739 match_name: &str,
740 ) -> Result<DirEntry, Error<D::Error>>
741 where
742 D: BlockDevice,
743 {
744 self.iterate_lfn_dir(block_device, dir, |lfn, dir_entry| {
746 if match lfn {
747 Some(name) => name == match_name,
748 None => match_name
749 .to_short_filename()
750 .map(|name| name == dir_entry.name)
751 .unwrap_or(false),
752 } {
753 ControlFlow::Break(dir_entry.clone())
754 } else {
755 ControlFlow::Continue(())
756 }
757 })
758 .await?
759 .ok_or(Error::FileNotFound)
760 }
761
762 pub(crate) async fn delete_directory_entry<D>(
764 &self,
765 block_device: &D,
766 dir: &DirectoryInfo,
767 match_name: &ShortFileName,
768 ) -> Result<(), Error<D::Error>>
769 where
770 D: BlockDevice,
771 {
772 match &self.fat_specific_info {
773 FatSpecificInfo::Fat16(fat16_info) => {
774 let mut current_cluster = Some(dir.cluster);
779 let mut first_dir_block_num = match dir.cluster {
780 ClusterId::ROOT_DIR => self.lba_start + fat16_info.first_root_dir_block,
781 _ => self.cluster_to_block(dir.cluster),
782 };
783 let dir_size = match dir.cluster {
784 ClusterId::ROOT_DIR => {
785 let len_bytes =
786 u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32;
787 BlockCount::from_bytes(len_bytes)
788 }
789 _ => BlockCount(u32::from(self.blocks_per_cluster)),
790 };
791
792 while let Some(cluster) = current_cluster {
794 for block in first_dir_block_num.range(dir_size) {
796 match self
797 .delete_entry_in_block(block_device, match_name, block)
798 .await
799 {
800 Err(Error::FileNotFound) => {
801 }
803 x => {
804 return x;
807 }
808 }
809 }
810 if cluster != ClusterId::ROOT_DIR {
812 let mut block_cache = BlockCache::empty();
813 current_cluster = match self
814 .next_cluster(block_device, cluster, &mut block_cache)
815 .await
816 {
817 Ok(n) => {
818 first_dir_block_num = self.cluster_to_block(n);
819 Some(n)
820 }
821 _ => None,
822 };
823 } else {
824 current_cluster = None;
825 }
826 }
827 }
829 FatSpecificInfo::Fat32(fat32_info) => {
830 let mut current_cluster = match dir.cluster {
833 ClusterId::ROOT_DIR => Some(fat32_info.first_root_dir_cluster),
834 _ => Some(dir.cluster),
835 };
836 while let Some(cluster) = current_cluster {
838 let block_idx = self.cluster_to_block(cluster);
840 for block in block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) {
841 match self
842 .delete_entry_in_block(block_device, match_name, block)
843 .await
844 {
845 Err(Error::FileNotFound) => {
846 continue;
848 }
849 x => {
850 return x;
853 }
854 }
855 }
856 let mut block_cache = BlockCache::empty();
858 current_cluster = match self
859 .next_cluster(block_device, cluster, &mut block_cache)
860 .await
861 {
862 Ok(n) => Some(n),
863 _ => None,
864 }
865 }
866 }
868 }
869 Err(Error::FileNotFound)
872 }
873
874 async fn delete_entry_in_block<D>(
879 &self,
880 block_device: &D,
881 match_name: &ShortFileName,
882 block: BlockIdx,
883 ) -> Result<(), Error<D::Error>>
884 where
885 D: BlockDevice,
886 {
887 let mut blocks = [Block::new()];
888 block_device
889 .read(&mut blocks, block, "read_dir")
890 .await
891 .map_err(Error::DeviceError)?;
892 for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
893 let start = entry * OnDiskDirEntry::LEN;
894 let end = (entry + 1) * OnDiskDirEntry::LEN;
895 let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
896 if dir_entry.is_end() {
897 break;
899 } else if dir_entry.matches(match_name) {
900 let mut blocks = blocks;
901 blocks[0].contents[start] = 0xE5;
902 return block_device
903 .write(&blocks, block)
904 .await
905 .map_err(Error::DeviceError);
906 }
907 }
908 Err(Error::FileNotFound)
909 }
910
911 pub(crate) async fn find_next_free_cluster<D>(
913 &self,
914 block_device: &D,
915 start_cluster: ClusterId,
916 end_cluster: ClusterId,
917 ) -> Result<ClusterId, Error<D::Error>>
918 where
919 D: BlockDevice,
920 {
921 let mut blocks = [Block::new()];
922 let mut current_cluster = start_cluster;
923 match &self.fat_specific_info {
924 FatSpecificInfo::Fat16(_fat16_info) => {
925 while current_cluster.0 < end_cluster.0 {
926 trace!(
927 "current_cluster={:?}, end_cluster={:?}",
928 current_cluster,
929 end_cluster
930 );
931 let fat_offset = current_cluster.0 * 2;
932 trace!("fat_offset = {:?}", fat_offset);
933 let this_fat_block_num =
934 self.lba_start + self.fat_start.offset_bytes(fat_offset);
935 trace!("this_fat_block_num = {:?}", this_fat_block_num);
936 let mut this_fat_ent_offset = usize::try_from(fat_offset % Block::LEN_U32)
937 .map_err(|_| Error::ConversionError)?;
938 trace!("Reading block {:?}", this_fat_block_num);
939 block_device
940 .read(&mut blocks, this_fat_block_num, "next_cluster")
941 .await
942 .map_err(Error::DeviceError)?;
943
944 while this_fat_ent_offset <= Block::LEN - 2 {
945 let fat_entry = LittleEndian::read_u16(
946 &blocks[0][this_fat_ent_offset..=this_fat_ent_offset + 1],
947 );
948 if fat_entry == 0 {
949 return Ok(current_cluster);
950 }
951 this_fat_ent_offset += 2;
952 current_cluster += 1;
953 }
954 }
955 }
956 FatSpecificInfo::Fat32(_fat32_info) => {
957 while current_cluster.0 < end_cluster.0 {
958 trace!(
959 "current_cluster={:?}, end_cluster={:?}",
960 current_cluster,
961 end_cluster
962 );
963 let fat_offset = current_cluster.0 * 4;
964 trace!("fat_offset = {:?}", fat_offset);
965 let this_fat_block_num =
966 self.lba_start + self.fat_start.offset_bytes(fat_offset);
967 trace!("this_fat_block_num = {:?}", this_fat_block_num);
968 let mut this_fat_ent_offset = usize::try_from(fat_offset % Block::LEN_U32)
969 .map_err(|_| Error::ConversionError)?;
970 trace!("Reading block {:?}", this_fat_block_num);
971 block_device
972 .read(&mut blocks, this_fat_block_num, "next_cluster")
973 .await
974 .map_err(Error::DeviceError)?;
975
976 while this_fat_ent_offset <= Block::LEN - 4 {
977 let fat_entry = LittleEndian::read_u32(
978 &blocks[0][this_fat_ent_offset..=this_fat_ent_offset + 3],
979 ) & 0x0FFF_FFFF;
980 if fat_entry == 0 {
981 return Ok(current_cluster);
982 }
983 this_fat_ent_offset += 4;
984 current_cluster += 1;
985 }
986 }
987 }
988 }
989 warn!("Out of space...");
990 Err(Error::NotEnoughSpace)
991 }
992
993 pub(crate) async fn alloc_cluster<D>(
995 &mut self,
996 block_device: &D,
997 prev_cluster: Option<ClusterId>,
998 zero: bool,
999 ) -> Result<ClusterId, Error<D::Error>>
1000 where
1001 D: BlockDevice,
1002 {
1003 debug!("Allocating new cluster, prev_cluster={:?}", prev_cluster);
1004 let end_cluster = ClusterId(self.cluster_count + RESERVED_ENTRIES);
1005 let start_cluster = match self.next_free_cluster {
1006 Some(cluster) if cluster.0 < end_cluster.0 => cluster,
1007 _ => ClusterId(RESERVED_ENTRIES),
1008 };
1009 trace!(
1010 "Finding next free between {:?}..={:?}",
1011 start_cluster,
1012 end_cluster
1013 );
1014 let new_cluster = match self
1015 .find_next_free_cluster(block_device, start_cluster, end_cluster)
1016 .await
1017 {
1018 Ok(cluster) => cluster,
1019 Err(_) if start_cluster.0 > RESERVED_ENTRIES => {
1020 debug!(
1021 "Retrying, finding next free between {:?}..={:?}",
1022 ClusterId(RESERVED_ENTRIES),
1023 end_cluster
1024 );
1025 self.find_next_free_cluster(block_device, ClusterId(RESERVED_ENTRIES), end_cluster)
1026 .await?
1027 }
1028 Err(e) => return Err(e),
1029 };
1030 self.update_fat(block_device, new_cluster, ClusterId::END_OF_FILE)
1031 .await?;
1032 if let Some(cluster) = prev_cluster {
1033 trace!(
1034 "Updating old cluster {:?} to {:?} in FAT",
1035 cluster,
1036 new_cluster
1037 );
1038 self.update_fat(block_device, cluster, new_cluster).await?;
1039 }
1040 trace!(
1041 "Finding next free between {:?}..={:?}",
1042 new_cluster,
1043 end_cluster
1044 );
1045 self.next_free_cluster = match self
1046 .find_next_free_cluster(block_device, new_cluster, end_cluster)
1047 .await
1048 {
1049 Ok(cluster) => Some(cluster),
1050 Err(_) if new_cluster.0 > RESERVED_ENTRIES => {
1051 match self
1052 .find_next_free_cluster(block_device, ClusterId(RESERVED_ENTRIES), end_cluster)
1053 .await
1054 {
1055 Ok(cluster) => Some(cluster),
1056 Err(e) => return Err(e),
1057 }
1058 }
1059 Err(e) => return Err(e),
1060 };
1061 debug!("Next free cluster is {:?}", self.next_free_cluster);
1062 if let Some(ref mut number_free_cluster) = self.free_clusters_count {
1063 *number_free_cluster -= 1;
1064 };
1065 if zero {
1066 let blocks = [Block::new()];
1067 let first_block = self.cluster_to_block(new_cluster);
1068 let num_blocks = BlockCount(u32::from(self.blocks_per_cluster));
1069 for block in first_block.range(num_blocks) {
1070 block_device
1071 .write(&blocks, block)
1072 .await
1073 .map_err(Error::DeviceError)?;
1074 }
1075 }
1076 debug!("All done, returning {:?}", new_cluster);
1077 Ok(new_cluster)
1078 }
1079
1080 pub(crate) async fn truncate_cluster_chain<D>(
1082 &mut self,
1083 block_device: &D,
1084 cluster: ClusterId,
1085 ) -> Result<(), Error<D::Error>>
1086 where
1087 D: BlockDevice,
1088 {
1089 if cluster.0 < RESERVED_ENTRIES {
1090 return Ok(());
1092 }
1093 let mut next = {
1094 let mut block_cache = BlockCache::empty();
1095 match self
1096 .next_cluster(block_device, cluster, &mut block_cache)
1097 .await
1098 {
1099 Ok(n) => n,
1100 Err(Error::EndOfFile) => return Ok(()),
1101 Err(e) => return Err(e),
1102 }
1103 };
1104 if let Some(ref mut next_free_cluster) = self.next_free_cluster {
1105 if next_free_cluster.0 > next.0 {
1106 *next_free_cluster = next;
1107 }
1108 } else {
1109 self.next_free_cluster = Some(next);
1110 }
1111 self.update_fat(block_device, cluster, ClusterId::END_OF_FILE)
1112 .await?;
1113 loop {
1114 let mut block_cache = BlockCache::empty();
1115 match self
1116 .next_cluster(block_device, next, &mut block_cache)
1117 .await
1118 {
1119 Ok(n) => {
1120 self.update_fat(block_device, next, ClusterId::EMPTY)
1121 .await?;
1122 next = n;
1123 }
1124 Err(Error::EndOfFile) => {
1125 self.update_fat(block_device, next, ClusterId::EMPTY)
1126 .await?;
1127 break;
1128 }
1129 Err(e) => return Err(e),
1130 }
1131 if let Some(ref mut number_free_cluster) = self.free_clusters_count {
1132 *number_free_cluster += 1;
1133 };
1134 }
1135 Ok(())
1136 }
1137}
1138
1139pub async fn parse_volume<D>(
1142 block_device: &D,
1143 lba_start: BlockIdx,
1144 num_blocks: BlockCount,
1145) -> Result<VolumeType, Error<D::Error>>
1146where
1147 D: BlockDevice,
1148 D::Error: core::fmt::Debug,
1149{
1150 let mut blocks = [Block::new()];
1151 block_device
1152 .read(&mut blocks, lba_start, "read_bpb")
1153 .await
1154 .map_err(Error::DeviceError)?;
1155 let block = &blocks[0];
1156 let bpb = Bpb::create_from_bytes(block).map_err(Error::FormatError)?;
1157 match bpb.fat_type {
1158 FatType::Fat16 => {
1159 if bpb.bytes_per_block() as usize != Block::LEN {
1160 return Err(Error::BadBlockSize(bpb.bytes_per_block()));
1161 }
1162 let root_dir_blocks = ((u32::from(bpb.root_entries_count()) * OnDiskDirEntry::LEN_U32)
1164 + (Block::LEN_U32 - 1))
1165 / Block::LEN_U32;
1166 let fat_start = BlockCount(u32::from(bpb.reserved_block_count()));
1167 let first_root_dir_block =
1168 fat_start + BlockCount(u32::from(bpb.num_fats()) * bpb.fat_size());
1169 let first_data_block = first_root_dir_block + BlockCount(root_dir_blocks);
1170 let mut volume = FatVolume {
1171 lba_start,
1172 num_blocks,
1173 name: VolumeName { data: [0u8; 11] },
1174 blocks_per_cluster: bpb.blocks_per_cluster(),
1175 first_data_block: (first_data_block),
1176 fat_start: BlockCount(u32::from(bpb.reserved_block_count())),
1177 free_clusters_count: None,
1178 next_free_cluster: None,
1179 cluster_count: bpb.total_clusters(),
1180 fat_specific_info: FatSpecificInfo::Fat16(Fat16Info {
1181 root_entries_count: bpb.root_entries_count(),
1182 first_root_dir_block,
1183 }),
1184 };
1185 volume.name.data[..].copy_from_slice(bpb.volume_label());
1186 Ok(VolumeType::Fat(volume))
1187 }
1188 FatType::Fat32 => {
1189 let first_data_block = u32::from(bpb.reserved_block_count())
1191 + (u32::from(bpb.num_fats()) * bpb.fat_size());
1192
1193 let info_location = bpb.fs_info_block().unwrap();
1195 let mut info_blocks = [Block::new()];
1196 block_device
1197 .read(
1198 &mut info_blocks,
1199 lba_start + info_location,
1200 "read_info_sector",
1201 )
1202 .await
1203 .map_err(Error::DeviceError)?;
1204 let info_block = &info_blocks[0];
1205 let info_sector =
1206 InfoSector::create_from_bytes(info_block).map_err(Error::FormatError)?;
1207
1208 let mut volume = FatVolume {
1209 lba_start,
1210 num_blocks,
1211 name: VolumeName { data: [0u8; 11] },
1212 blocks_per_cluster: bpb.blocks_per_cluster(),
1213 first_data_block: BlockCount(first_data_block),
1214 fat_start: BlockCount(u32::from(bpb.reserved_block_count())),
1215 free_clusters_count: info_sector.free_clusters_count(),
1216 next_free_cluster: info_sector.next_free_cluster(),
1217 cluster_count: bpb.total_clusters(),
1218 fat_specific_info: FatSpecificInfo::Fat32(Fat32Info {
1219 info_location: lba_start + info_location,
1220 first_root_dir_cluster: ClusterId(bpb.first_root_dir_cluster()),
1221 }),
1222 };
1223 volume.name.data[..].copy_from_slice(bpb.volume_label());
1224 Ok(VolumeType::Fat(volume))
1225 }
1226 }
1227}