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