1use core::{cell::Cell, fmt, mem, ops::Range};
2
3use alloc::{
4 boxed::Box,
5 collections::BTreeMap,
6 format,
7 string::{String, ToString},
8 sync::Arc,
9 vec,
10 vec::Vec,
11};
12
13use crate::{
14 devices::ide::IdeDevice,
15 io::NoDebug,
16 memory_management::memory_layout::{align_down, align_up},
17 sync::spin::mutex::Mutex,
18};
19
20use super::{
21 AccessHelper, BaseNode, DirTraverse, DirectoryNode, FileAttributes, FileNode, FileSystem,
22 FileSystemError, Node,
23};
24
25const DIRECTORY_ENTRY_SIZE: u32 = 32;
26
27fn file_attribute_from_fat(attributes: u8) -> FileAttributes {
28 let mut file_attributes = FileAttributes::EMPTY;
29 if attributes & attrs::READ_ONLY == attrs::READ_ONLY {
30 file_attributes |= FileAttributes::READ_ONLY;
31 }
32 if attributes & attrs::HIDDEN == attrs::HIDDEN {
33 file_attributes |= FileAttributes::HIDDEN;
34 }
35 if attributes & attrs::SYSTEM == attrs::SYSTEM {
36 file_attributes |= FileAttributes::SYSTEM;
37 }
38 if attributes & attrs::VOLUME_ID == attrs::VOLUME_ID {
39 file_attributes |= FileAttributes::VOLUME_LABEL;
40 }
41 if attributes & attrs::DIRECTORY == attrs::DIRECTORY {
42 file_attributes |= FileAttributes::DIRECTORY;
43 }
44 if attributes & attrs::ARCHIVE == attrs::ARCHIVE {
45 file_attributes |= FileAttributes::ARCHIVE;
46 }
47 file_attributes
48}
49
50fn file_attribute_to_fat(attributes: FileAttributes) -> u8 {
51 let mut fat_attributes = 0;
52 if attributes.contains(FileAttributes::READ_ONLY) {
53 fat_attributes |= attrs::READ_ONLY;
54 }
55 if attributes.contains(FileAttributes::HIDDEN) {
56 fat_attributes |= attrs::HIDDEN;
57 }
58 if attributes.contains(FileAttributes::SYSTEM) {
59 fat_attributes |= attrs::SYSTEM;
60 }
61 if attributes.contains(FileAttributes::VOLUME_LABEL) {
62 fat_attributes |= attrs::VOLUME_ID;
63 }
64 if attributes.contains(FileAttributes::DIRECTORY) {
65 fat_attributes |= attrs::DIRECTORY;
66 }
67 if attributes.contains(FileAttributes::ARCHIVE) {
68 fat_attributes |= attrs::ARCHIVE;
69 }
70 fat_attributes
71}
72
73fn long_entries_name_merge(entries: impl DoubleEndedIterator<Item = String>) -> String {
74 let mut name = String::new();
75 entries.rev().for_each(|s| name.push_str(&s));
76 name
77}
78
79fn create_dir_entries(
80 name: &str,
81 attributes: FileAttributes,
82) -> (DirectoryEntryNormal, Vec<DirectoryEntryLong>) {
83 let mut short_name = [0; 11];
85
86 let (mut filename, extension) = match name.find('.') {
87 Some(i) => {
88 let (filename, extension) = name.split_at(i);
89 (filename, &extension[1..])
90 }
91 None => (name, ""),
92 };
93
94 let mut more_than_8 = false;
95
96 if filename.len() > 8 {
97 filename = &filename[..6];
98 more_than_8 = true;
99 } else {
100 let len = filename.len().min(8);
101 filename = &filename[..len];
102 }
103 assert!(filename.len() <= 8);
104
105 for (i, c) in short_name.iter_mut().enumerate().take(8) {
106 *c = if i < filename.len() {
107 filename.as_bytes()[i].to_ascii_uppercase()
108 } else {
109 b' '
110 };
111 }
112 if more_than_8 {
113 short_name[6] = b'~';
114 short_name[7] = b'1';
115 }
116
117 for i in 0..3 {
118 short_name[8 + i] = if i < extension.len() {
119 extension.as_bytes()[i].to_ascii_uppercase()
120 } else {
121 b' '
122 };
123 }
124
125 let normal_entry = DirectoryEntryNormal {
127 short_name,
128 attributes: file_attribute_to_fat(attributes),
129 _nt_reserved: 0,
130 creation_time_tenths_of_seconds: 0,
131 creation_time: 0,
132 creation_date: 0,
133 last_access_date: 0,
134 first_cluster_hi: 0,
135 last_modification_time: 0,
136 last_modification_date: 0,
137 first_cluster_lo: 0,
138 file_size: 0,
139 };
140
141 let short_name_checksum = normal_entry.name_checksum();
142
143 let mut long_name_entries = Vec::new();
145 let mut sequence_number = 1;
146 let mut long_name = name;
147 loop {
148 if long_name.is_empty() {
149 break;
150 }
151
152 let len = long_name.len().min(13);
153 let mut name_part = long_name[..len].chars();
154
155 long_name = &long_name[len..];
156
157 let mut name1 = [0; 5];
158 let mut name2 = [0; 6];
159 let mut name3 = [0; 2];
160
161 for c in &mut name1 {
162 *c = name_part.next().unwrap_or('\0') as u16;
163 }
164 for c in &mut name2 {
165 *c = name_part.next().unwrap_or('\0') as u16;
166 }
167 for c in &mut name3 {
168 *c = name_part.next().unwrap_or('\0') as u16;
169 }
170
171 let mut entry = DirectoryEntryLong {
172 sequence_number,
173 name1,
174 attributes: attrs::LONG_NAME,
175 long_name_type: 0,
176 checksum: short_name_checksum,
177 name2,
178 _zero: 0,
179 name3,
180 };
181
182 sequence_number += 1;
183
184 if long_name.is_empty() {
186 entry.sequence_number |= 0x40;
187 }
188
189 long_name_entries.push(entry);
190 }
191
192 (normal_entry, long_name_entries)
193}
194
195fn increment_short_name(short_name: &mut [u8; 11]) {
196 let base_name = &mut short_name[..8];
197
198 let mut telda_pos = base_name
199 .iter()
200 .position(|c| *c == b'~')
201 .expect("Telda position be present");
202
203 assert!(telda_pos <= 6);
204 let current_num_size = 8 - telda_pos - 1;
205 let current_num = base_name[telda_pos + 1..].iter().fold(0u32, |acc, x| {
206 assert!(*x >= b'0' && *x <= b'9');
207 acc * 10 + (x - b'0') as u32
208 });
209
210 let new_num = current_num + 1;
211 if new_num > 999999 {
212 panic!("Short name exceeded limit 999999");
213 }
214
215 let new_num_str = format!("{new_num}");
216 if new_num_str.len() > current_num_size {
217 telda_pos -= 1;
218 }
219
220 assert_eq!(base_name[telda_pos + 1..].len(), new_num_str.len());
221 base_name[telda_pos + 1..].copy_from_slice(new_num_str.as_bytes());
222}
223
224#[derive(Debug)]
225pub enum FatError {
226 InvalidBootSector,
227 UnexpectedFatEntry,
228 NotEnoughSpace,
229}
230
231impl From<FatError> for FileSystemError {
232 fn from(e: FatError) -> Self {
233 FileSystemError::FatError(e)
234 }
235}
236
237pub fn load_fat_filesystem(
238 device: Arc<IdeDevice>,
239 start_lba: u32,
240 size_in_sectors: u32,
241) -> Result<FatFilesystem, FileSystemError> {
242 let size = align_up(
243 mem::size_of::<FatBootSectorRaw>(),
244 device.sector_size() as usize,
245 );
246 let mut sectors = vec![0; size];
247
248 device
249 .read_sync(start_lba as u64, &mut sectors)
250 .map_err(|e| FileSystemError::DiskReadError {
251 sector: start_lba as u64,
252 error: e,
253 })?;
254
255 let boot_sector = unsafe { sectors.as_ptr().cast::<FatBootSectorRaw>().read() };
257 let boot_sector = FatBootSector::new(boot_sector, size_in_sectors)?;
258
259 FatFilesystem::new(start_lba, size_in_sectors, boot_sector, device)
260}
261
262#[repr(C, packed)]
263#[derive(Debug, Copy, Clone)]
264struct Fat12_16ExtendedBootSector {
265 drive_number: u8,
266 reserved: u8,
267 boot_signature: u8,
268 volume_id: u32,
269 volume_label: [u8; 11],
270 file_system_type: [u8; 8],
271 boot_code: NoDebug<[u8; 448]>,
272 boot_signature_2: u16,
273}
274
275#[repr(C, packed)]
276#[derive(Debug, Copy, Clone)]
277struct Fat32ExtendedBootSector {
278 fat_size_32: u32,
279 ext_flags: u16,
280 fs_version: u16,
281 root_cluster: u32,
282 fs_info: u16,
283 backup_boot_sector: u16,
284 reserved: [u8; 12],
285 drive_number: u8,
286 reserved_2: u8,
287 boot_signature: u8,
288 volume_id: u32,
289 volume_label: [u8; 11],
290 file_system_type: [u8; 8],
291 boot_code: NoDebug<[u8; 420]>,
292 boot_signature_2: u16,
293}
294
295#[repr(C, packed)]
296#[derive(Copy, Clone)]
297union FatExtendedBootSector {
298 fat12_16: Fat12_16ExtendedBootSector,
299 fat32: Fat32ExtendedBootSector,
300}
301
302#[repr(C, packed)]
303#[derive(Copy, Clone)]
304struct FatBootSectorRaw {
305 jmp_boot: [u8; 3],
306 oem_name: [u8; 8],
307 bytes_per_sector: u16,
308 sectors_per_cluster: u8,
309 reserved_sectors_count: u16,
310 number_of_fats: u8,
311 root_entry_count: u16,
312 total_sectors_16: u16,
313 media_type: u8,
314 fat_size_16: u16,
315 sectors_per_track: u16,
316 number_of_heads: u16,
317 hidden_sectors: u32,
318 total_sectors_32: u32,
319 extended: FatExtendedBootSector,
320}
321
322impl fmt::Debug for FatBootSectorRaw {
323 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
324 let bytes_per_sector = self.bytes_per_sector;
325 let reserved_sectors_count = self.reserved_sectors_count;
326 let root_entry_count = self.root_entry_count;
327 let total_sectors_16 = self.total_sectors_16;
328 let fat_size_16 = self.fat_size_16;
329 let sectors_per_track = self.sectors_per_track;
330 let number_of_heads = self.number_of_heads;
331 let hidden_sectors = self.hidden_sectors;
332 let total_sectors_32 = self.total_sectors_32;
333
334 let is_fat32 = self.fat_size_16 == 0;
335
336 let mut s = f.debug_struct("FatBootSector");
337
338 s.field("jmp_boot", &self.jmp_boot)
339 .field("oem_name", &self.oem_name)
340 .field("bytes_per_sector", &bytes_per_sector)
341 .field("sectors_per_cluster", &self.sectors_per_cluster)
342 .field("reserved_sectors_count", &reserved_sectors_count)
343 .field("number_of_fats", &self.number_of_fats)
344 .field("root_entry_count", &root_entry_count)
345 .field("total_sectors_16", &total_sectors_16)
346 .field("media_type", &self.media_type)
347 .field("fat_size_16", &fat_size_16)
348 .field("sectors_per_track", §ors_per_track)
349 .field("number_of_heads", &number_of_heads)
350 .field("hidden_sectors", &hidden_sectors)
351 .field("total_sectors_32", &total_sectors_32);
352
353 if is_fat32 {
354 s.field("extended_fat32", unsafe { &self.extended.fat32 })
355 .finish()
356 } else {
357 s.field("extended_fat12_16", unsafe { &self.extended.fat12_16 })
358 .finish()
359 }
360 }
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq)]
364pub enum FatType {
365 Fat12,
366 Fat16,
367 Fat32,
368}
369
370#[derive(Debug, Clone, Copy, PartialEq, Eq)]
371enum FatEntry {
372 Free,
373 Next(u32),
375 EndOfChain,
377 Bad,
378 Reserved,
379}
380
381impl FatEntry {
382 pub fn from_u32(ty: FatType, entry: u32) -> FatEntry {
383 match ty {
384 FatType::Fat12 => {
385 if entry == 0 {
386 FatEntry::Free
387 } else if entry >= 0xFF8 {
388 FatEntry::EndOfChain
389 } else if entry == 0xFF7 {
390 FatEntry::Bad
391 } else if (0x002..=0xFF6).contains(&entry) {
392 FatEntry::Next(entry)
393 } else {
394 FatEntry::Reserved
395 }
396 }
397 FatType::Fat16 => {
398 if entry == 0 {
399 FatEntry::Free
400 } else if entry >= 0xFFF8 {
401 FatEntry::EndOfChain
402 } else if entry == 0xFFF7 {
403 FatEntry::Bad
404 } else if (0x002..=0xFFF6).contains(&entry) {
405 FatEntry::Next(entry)
406 } else {
407 FatEntry::Reserved
408 }
409 }
410 FatType::Fat32 => {
411 if entry == 0 {
412 FatEntry::Free
413 } else if entry >= 0x0FFF_FFF8 {
414 FatEntry::EndOfChain
415 } else if entry == 0x0FFF_FFF7 {
416 FatEntry::Bad
417 } else if (0x002..=0x0FFF_FFF6).contains(&entry) {
418 FatEntry::Next(entry)
419 } else {
420 FatEntry::Reserved
421 }
422 }
423 }
424 }
425
426 pub fn to_u32(self, ty: FatType) -> Option<u32> {
427 match self {
428 FatEntry::Free => Some(0),
429 FatEntry::EndOfChain => match ty {
430 FatType::Fat12 => Some(0xFF8),
431 FatType::Fat16 => Some(0xFFF8),
432 FatType::Fat32 => Some(0x0FFF_FFF8),
433 },
434 FatEntry::Bad => match ty {
435 FatType::Fat12 => Some(0xFF7),
436 FatType::Fat16 => Some(0xFFF7),
437 FatType::Fat32 => Some(0x0FFF_FFF7),
438 },
439 FatEntry::Next(entry) => match (ty, entry) {
440 (FatType::Fat12, 0x002..=0xFF6) => Some(entry),
441 (FatType::Fat16, 0x002..=0xFFF6) => Some(entry),
442 (FatType::Fat32, 0x002..=0x0FFF_FFF6) => Some(entry),
443 _ => None,
444 },
445 FatEntry::Reserved => None,
446 }
447 }
448}
449
450#[derive(Debug)]
451struct FatBootSector {
452 ty: FatType,
453 boot_sector: FatBootSectorRaw,
454}
455
456#[allow(dead_code)]
457impl FatBootSector {
458 fn new(boot_sector: FatBootSectorRaw, size_in_sectors: u32) -> Result<FatBootSector, FatError> {
459 if unsafe { boot_sector.extended.fat32.boot_signature_2 } != 0xAA55 {
460 return Err(FatError::InvalidBootSector);
461 }
462
463 let count_of_clusters = size_in_sectors / boot_sector.sectors_per_cluster as u32;
464
465 let fat_type = match count_of_clusters {
466 _ if boot_sector.fat_size_16 == 0 => FatType::Fat32,
467 0..=4084 => FatType::Fat12,
468 4085..=65524 => FatType::Fat16,
469 _ => FatType::Fat32,
470 };
471
472 Ok(FatBootSector {
473 ty: fat_type,
474 boot_sector,
475 })
476 }
477
478 pub fn bytes_per_sector(&self) -> u16 {
479 self.boot_sector.bytes_per_sector
480 }
481
482 pub fn sectors_per_cluster(&self) -> u8 {
483 self.boot_sector.sectors_per_cluster
484 }
485
486 pub fn bytes_per_cluster(&self) -> u32 {
487 self.boot_sector.sectors_per_cluster as u32 * self.boot_sector.bytes_per_sector as u32
488 }
489
490 pub fn reserved_sectors_count(&self) -> u16 {
491 self.boot_sector.reserved_sectors_count
492 }
493
494 pub fn total_sectors(&self) -> u32 {
495 if self.boot_sector.total_sectors_16 != 0 {
496 self.boot_sector.total_sectors_16 as u32
497 } else {
498 self.boot_sector.total_sectors_32
499 }
500 }
501
502 pub fn fat_size_in_sectors(&self) -> u32 {
503 if self.ty == FatType::Fat32 {
504 unsafe { self.boot_sector.extended.fat32.fat_size_32 }
505 } else {
506 self.boot_sector.fat_size_16 as u32
507 }
508 }
509
510 pub fn number_of_fats(&self) -> u8 {
511 self.boot_sector.number_of_fats
512 }
513
514 pub fn fat_start_sector(&self) -> u32 {
515 self.boot_sector.reserved_sectors_count as u32
516 }
517
518 pub fn root_dir_sectors(&self) -> u32 {
519 (self.boot_sector.root_entry_count as u32 * DIRECTORY_ENTRY_SIZE)
520 .div_ceil(self.boot_sector.bytes_per_sector as u32)
521 }
522
523 pub fn root_dir_start_sector(&self) -> u32 {
524 self.fat_start_sector() + self.number_of_fats() as u32 * self.fat_size_in_sectors()
525 }
526
527 pub fn data_start_sector(&self) -> u32 {
528 self.root_dir_start_sector() + self.root_dir_sectors()
529 }
530
531 pub fn data_sectors(&self) -> u32 {
532 self.total_sectors() - self.data_start_sector()
533 }
534
535 pub fn volume_label(&self) -> &[u8; 11] {
536 match self.ty {
537 FatType::Fat12 | FatType::Fat16 => unsafe {
538 &self.boot_sector.extended.fat12_16.volume_label
539 },
540 FatType::Fat32 => unsafe { &self.boot_sector.extended.fat32.volume_label },
541 }
542 }
543}
544
545#[allow(dead_code)]
546mod attrs {
547 pub const READ_ONLY: u8 = 0x01;
548 pub const HIDDEN: u8 = 0x02;
549 pub const SYSTEM: u8 = 0x04;
550 pub const VOLUME_ID: u8 = 0x08;
551 pub const DIRECTORY: u8 = 0x10;
552 pub const ARCHIVE: u8 = 0x20;
553 pub const LONG_NAME: u8 = READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID;
554}
555
556#[derive(Debug, Clone, Copy, PartialEq, Eq)]
557enum DirectoryEntryState {
558 Free,
559 FreeAndLast,
560 Used,
561}
562
563#[derive(Debug, Clone, PartialEq, Eq)]
564#[repr(C, packed)]
565struct DirectoryEntryNormal {
566 short_name: [u8; 11],
567 attributes: u8,
568 _nt_reserved: u8,
569 creation_time_tenths_of_seconds: u8,
570 creation_time: u16,
571 creation_date: u16,
572 last_access_date: u16,
573 first_cluster_hi: u16,
574 last_modification_time: u16,
575 last_modification_date: u16,
576 first_cluster_lo: u16,
577 file_size: u32,
578}
579
580impl DirectoryEntryNormal {
581 pub fn name(&self) -> String {
582 let base_name = &self.short_name[..8];
583 let base_name_end = 8 - base_name.iter().rev().position(|&c| c != 0x20).unwrap();
584 let extension = &self.short_name[8..11];
585
586 let mut name = String::with_capacity(13);
587 let mut i = 0;
588 while i < base_name_end {
589 name.push(base_name[i] as char);
590 i += 1;
591 }
592 let extension_present = extension[0] != 0x20;
593 if extension_present {
594 name.push('.');
595 i = 0;
596 while i < extension.len() && extension[i] != 0x20 {
597 name.push(extension[i] as char);
598 i += 1;
599 }
600 }
601 name
602 }
603
604 pub fn first_cluster(&self) -> u32 {
605 ((self.first_cluster_hi as u32) << 16) | self.first_cluster_lo as u32
606 }
607
608 pub fn name_checksum(&self) -> u8 {
609 let mut checksum = 0u8;
610 for &c in self.short_name.iter() {
611 checksum = ((checksum & 1) << 7)
612 .wrapping_add(checksum >> 1)
613 .wrapping_add(c);
614 }
615 checksum
616 }
617}
618
619#[derive(Debug, Clone)]
620#[repr(C, packed)]
621struct DirectoryEntryLong {
622 sequence_number: u8,
623 name1: [u16; 5],
624 attributes: u8,
625 long_name_type: u8,
626 checksum: u8,
627 name2: [u16; 6],
628 _zero: u16,
629 name3: [u16; 2],
630}
631
632impl DirectoryEntryLong {
633 pub fn name(&self) -> String {
634 let name1 = unsafe { &core::ptr::addr_of!(self.name1).read_unaligned() };
635 let name2 = unsafe { &core::ptr::addr_of!(self.name2).read_unaligned() };
636 let name3 = unsafe { &core::ptr::addr_of!(self.name3).read_unaligned() };
637
638 let name_iter = name1
640 .iter()
641 .chain(name2)
642 .chain(name3)
643 .cloned()
644 .take_while(|c| c != &0);
645
646 let mut name_part = String::with_capacity(13);
647 char::decode_utf16(name_iter)
648 .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
649 .for_each(|c| name_part.push(c));
650
651 name_part
652 }
653}
654
655enum DirectoryEntry<'a> {
656 Normal(&'a mut DirectoryEntryNormal),
657 Long(&'a mut DirectoryEntryLong),
658}
659
660impl<'a> DirectoryEntry<'a> {
661 pub fn from_raw(raw: &mut [u8]) -> DirectoryEntry<'_> {
662 assert_eq!(raw.len(), DIRECTORY_ENTRY_SIZE as usize);
663 let normal = unsafe {
664 raw.as_mut_ptr()
665 .cast::<DirectoryEntryNormal>()
666 .as_mut()
667 .unwrap()
668 };
669 let attributes = normal.attributes;
670 if attributes & attrs::LONG_NAME == attrs::LONG_NAME {
671 DirectoryEntry::Long(unsafe {
672 raw.as_mut_ptr()
673 .cast::<DirectoryEntryLong>()
674 .as_mut()
675 .unwrap()
676 })
677 } else {
678 DirectoryEntry::Normal(normal)
679 }
680 }
681
682 pub fn state(&self) -> DirectoryEntryState {
683 let first_byte = match self {
684 DirectoryEntry::Normal(entry) => entry.short_name[0],
685 DirectoryEntry::Long(entry) => entry.sequence_number,
686 };
687 match first_byte {
688 0x00 => DirectoryEntryState::FreeAndLast,
689 0xE5 => DirectoryEntryState::Free,
690 _ => DirectoryEntryState::Used,
691 }
692 }
693
694 pub fn as_normal(&self) -> &DirectoryEntryNormal {
695 match self {
696 DirectoryEntry::Normal(entry) => entry,
697 _ => panic!("expected normal entry"),
698 }
699 }
700
701 pub fn as_normal_mut(&mut self) -> &mut DirectoryEntryNormal {
702 match self {
703 DirectoryEntry::Normal(entry) => entry,
704 _ => panic!("expected normal entry"),
705 }
706 }
707
708 pub fn is_long(&self) -> bool {
709 matches!(self, DirectoryEntry::Long(_))
710 }
711
712 pub fn as_long(&self) -> &DirectoryEntryLong {
713 match self {
714 DirectoryEntry::Long(entry) => entry,
715 _ => panic!("expected long entry"),
716 }
717 }
718
719 fn write_long(&mut self, new_entry: DirectoryEntryLong) {
720 assert_eq!(new_entry.attributes & attrs::LONG_NAME, attrs::LONG_NAME);
721 match self {
722 DirectoryEntry::Long(entry) => {
723 **entry = new_entry;
724 }
725 DirectoryEntry::Normal(entry) => {
726 unsafe {
729 let long_entry = core::ptr::from_mut(*entry)
730 .cast::<DirectoryEntryLong>()
731 .as_mut()
732 .unwrap();
733 *long_entry = new_entry;
734 *self = DirectoryEntry::Long(long_entry);
735 }
736 }
737 }
738 }
739
740 fn write_normal(&mut self, new_entry: DirectoryEntryNormal) {
741 assert_ne!(new_entry.attributes & attrs::LONG_NAME, attrs::LONG_NAME);
742 match self {
743 DirectoryEntry::Normal(entry) => {
744 **entry = new_entry;
745 }
746 DirectoryEntry::Long(entry) => {
747 unsafe {
750 let normal_entry = core::ptr::from_mut(entry)
751 .cast::<DirectoryEntryNormal>()
752 .as_mut()
753 .unwrap();
754 *normal_entry = new_entry;
755 *self = DirectoryEntry::Normal(normal_entry);
756 }
757 }
758 }
759 }
760}
761
762pub struct FatNode {
764 normal_entry: DirectoryEntryNormal,
765 long_name: Option<String>,
766
767 parent_dir_sector: u64,
768 parent_dir_index: u16,
769}
770
771impl FatNode {
772 pub fn matches(&self, matcher: &str) -> bool {
773 if let Some(long_name) = &self.long_name {
775 if long_name.eq_ignore_ascii_case(matcher) {
776 return true;
777 }
778 }
779
780 let short_name = self.normal_entry.name();
782 short_name.eq_ignore_ascii_case(matcher)
783 }
784}
785
786impl From<FatNode> for Node {
787 fn from(value: FatNode) -> Self {
788 Node::new(
789 value.long_name.unwrap_or(value.normal_entry.name()),
790 file_attribute_from_fat(value.normal_entry.attributes),
791 value.normal_entry.first_cluster().into(),
792 value.normal_entry.file_size.into(),
793 value.parent_dir_sector,
794 value.parent_dir_index,
795 )
796 }
797}
798
799#[derive(Debug, Clone, Copy)]
800struct DirectoryIterSavedPosition {
801 cluster: u32,
802 sector: u32,
803 entry: u16,
804}
805
806#[derive(Debug, Clone)]
807enum Directory {
808 RootFat12_16 {
809 start_sector: u32,
810 size_in_sectors: u32,
811 },
812 Normal {
813 inode: DirectoryNode,
814 },
815}
816
817pub struct DirectoryIterator<'a> {
818 dir: Directory,
819 filesystem: &'a FatFilesystem,
820 current_sector: Vec<u8>,
822 current_sector_index: u32,
823 current_cluster: u32,
824 current_sector_dirty: bool,
825 entry_index_in_sector: u16,
826}
827
828impl DirectoryIterator<'_> {
829 fn new(
830 filesystem: &FatFilesystem,
831 dir: Directory,
832 ) -> Result<DirectoryIterator<'_>, FileSystemError> {
833 let (sector_index, current_cluster, current_sector) = match dir {
834 Directory::RootFat12_16 { start_sector, .. } => (
835 start_sector,
836 0,
837 filesystem.read_sectors_no_cache(start_sector, 1)?,
838 ),
839 Directory::Normal { ref inode } => {
840 if matches!(filesystem.fat_type(), FatType::Fat12 | FatType::Fat16)
841 && inode.start_cluster() == 0
842 {
843 return Self::new(filesystem, filesystem.open_root_dir()?);
845 }
846
847 let start_sector = filesystem.first_sector_of_cluster(inode.start_cluster() as u32);
848
849 (
850 start_sector,
851 inode.start_cluster() as u32,
852 filesystem.read_sectors_no_cache(start_sector, 1)?,
853 )
854 }
855 };
856 Ok(DirectoryIterator {
857 dir,
858 filesystem,
859 current_sector,
860 current_cluster,
861 current_sector_dirty: false,
862 current_sector_index: sector_index,
863 entry_index_in_sector: 0,
864 })
865 }
866
867 fn next_sector(&mut self) -> Result<bool, FileSystemError> {
869 self.flush_current_sector();
870
871 let mut next_sector_index = self.current_sector_index + 1;
873 match self.dir {
874 Directory::RootFat12_16 {
875 start_sector,
876 size_in_sectors,
877 } => {
878 if next_sector_index >= start_sector + size_in_sectors {
879 return Ok(false);
880 }
881 }
882 Directory::Normal { .. } => {
883 if next_sector_index
885 .is_multiple_of(self.filesystem.boot_sector.sectors_per_cluster() as u32)
886 {
887 let next_cluster = self.filesystem.fat.next_cluster(self.current_cluster);
889 match next_cluster {
890 Ok(Some(cluster)) => {
891 self.current_cluster = cluster;
892 next_sector_index =
893 cluster * self.filesystem.boot_sector.sectors_per_cluster() as u32;
894 }
895 Ok(None) => {
896 return Ok(false);
897 }
898 Err(_e) => {
899 return Err(FileSystemError::FileNotFound);
900 }
901 }
902 }
903 }
904 }
905
906 self.current_sector = self
907 .filesystem
908 .read_sectors_no_cache(next_sector_index, 1)?;
909 self.current_sector_index = next_sector_index;
910 self.entry_index_in_sector = 0;
911 Ok(true)
912 }
913
914 fn get_next_entry(&mut self) -> Result<DirectoryEntry<'_>, FileSystemError> {
915 let entry_start = self.entry_index_in_sector as usize * DIRECTORY_ENTRY_SIZE as usize;
916 let entry_end = entry_start + DIRECTORY_ENTRY_SIZE as usize;
917 if entry_end > self.current_sector.len() {
918 return if self.next_sector()? {
920 self.get_next_entry()
921 } else {
922 Err(FileSystemError::FileNotFound)
923 };
924 }
925 let entry = &mut self.current_sector[entry_start..entry_end];
926 self.entry_index_in_sector += 1;
927
928 assert_eq!(entry.len(), DIRECTORY_ENTRY_SIZE as usize);
929 Ok(DirectoryEntry::from_raw(entry))
930 }
931
932 fn mark_sector_dirty(&mut self) {
933 self.current_sector_dirty = true;
934 }
935
936 fn flush_current_sector(&mut self) {
937 if self.current_sector_dirty {
938 let start_sector = self.current_sector_index;
939 self.filesystem
940 .write_sectors(start_sector, &self.current_sector)
941 .unwrap();
942 self.current_sector_dirty = false;
943 }
944 }
945
946 fn restore_at(&mut self, saved_pos: DirectoryIterSavedPosition) -> Result<(), FileSystemError> {
947 self.current_cluster = saved_pos.cluster;
948 self.entry_index_in_sector = saved_pos.entry;
949 if self.current_sector_index != saved_pos.sector {
950 self.flush_current_sector();
951
952 self.current_sector_index = saved_pos.sector;
954 self.current_sector = self
955 .filesystem
956 .read_sectors_no_cache(self.current_sector_index, 1)?;
957 }
958 Ok(())
959 }
960
961 fn save_current(&self) -> DirectoryIterSavedPosition {
962 DirectoryIterSavedPosition {
963 cluster: self.current_cluster,
964 sector: self.current_sector_index,
965 entry: self.entry_index_in_sector.saturating_sub(1),
967 }
968 }
969
970 fn add_entry(
971 &mut self,
972 mut entry: DirectoryEntryNormal,
973 long_entries: Vec<DirectoryEntryLong>,
974 ) -> Result<Node, FileSystemError> {
975 let mut new_entry_short_name = entry.short_name;
977 let new_entry_long_name =
978 long_entries_name_merge(long_entries.iter().map(DirectoryEntryLong::name));
979
980 let needed_entries = long_entries.len() + 1;
981
982 let mut is_last = false;
983
984 let mut first_free = None;
985 let mut running_free = 0;
986 let mut current_long_entries_name = Vec::new();
987 let long_entries_require_free = Cell::new(false);
988
989 let mut is_already_exists = |entry: DirectoryEntry| -> bool {
990 if entry.is_long() {
991 if long_entries_require_free.get() {
992 long_entries_require_free.set(false);
993 current_long_entries_name.clear();
994 }
995 current_long_entries_name.push(entry.as_long().name());
996 } else {
997 let long_name = long_entries_name_merge(current_long_entries_name.drain(..));
998
999 if long_name.eq_ignore_ascii_case(&new_entry_long_name) {
1000 return true;
1001 }
1002 if entry.as_normal().short_name == new_entry_short_name {
1004 increment_short_name(&mut new_entry_short_name);
1005 }
1006 }
1007
1008 false
1009 };
1010
1011 loop {
1012 let entry = self.get_next_entry()?;
1013 match entry.state() {
1014 DirectoryEntryState::FreeAndLast => {
1015 long_entries_require_free.set(true);
1016
1017 is_last = true;
1018 if first_free.is_none() {
1020 first_free = Some(self.save_current());
1021 }
1022 break;
1023 }
1024 DirectoryEntryState::Free => {
1025 long_entries_require_free.set(true);
1026
1027 if first_free.is_none() {
1029 first_free = Some(self.save_current());
1030 }
1031 running_free += 1;
1032 if running_free == needed_entries {
1033 break;
1034 }
1035 }
1036 DirectoryEntryState::Used => {
1037 running_free = 0;
1039 first_free = None;
1040 if is_already_exists(entry) {
1041 return Err(FileSystemError::AlreadyExists);
1042 }
1043 }
1044 }
1045 }
1046
1047 if !is_last {
1048 loop {
1050 let entry = self.get_next_entry()?;
1051 match entry.state() {
1052 DirectoryEntryState::FreeAndLast => break,
1053 DirectoryEntryState::Used => {
1054 if is_already_exists(entry) {
1055 return Err(FileSystemError::AlreadyExists);
1056 }
1057 }
1058 _ => {}
1059 }
1060 }
1061 }
1062
1063 entry.short_name = new_entry_short_name;
1065
1066 assert!(first_free.is_some());
1067 let first_free = first_free.unwrap();
1068
1069 self.restore_at(first_free)?;
1070
1071 let mut current_entry = self.get_next_entry()?;
1073
1074 for long_entry in long_entries.into_iter().rev() {
1075 current_entry.write_long(long_entry);
1076 self.mark_sector_dirty();
1077 current_entry = self.get_next_entry()?;
1078 }
1079
1080 current_entry.write_normal(entry);
1082 self.mark_sector_dirty();
1083
1084 self.restore_at(first_free)?;
1086 let node = self.next();
1087
1088 if is_last {
1089 let pos = self.save_current();
1090 current_entry = self.get_next_entry()?;
1092 current_entry.as_normal_mut().short_name[0] = 0x00;
1093 self.mark_sector_dirty();
1094 self.restore_at(pos)?;
1096 }
1097
1098 Ok(node.expect("node should be created").into())
1099 }
1100}
1101
1102impl Iterator for DirectoryIterator<'_> {
1103 type Item = FatNode;
1104
1105 fn next(&mut self) -> Option<Self::Item> {
1106 let mut entry = self.get_next_entry().ok()?;
1107
1108 loop {
1109 match entry.state() {
1110 DirectoryEntryState::FreeAndLast => {
1111 return None;
1112 }
1113 DirectoryEntryState::Free => {
1114 entry = self.get_next_entry().ok()?;
1115 }
1116 _ => break,
1117 }
1118 }
1119
1120 let long_name = if entry.is_long() {
1121 let mut long_entry = entry.as_long().clone();
1122 assert_eq!(long_entry.sequence_number & 0x40, 0x40);
1125 let number_of_entries = long_entry.sequence_number & 0x3F;
1126 let mut long_name_entries = Vec::with_capacity(number_of_entries as usize);
1127 for i in 0..number_of_entries {
1129 let name_part = long_entry.name();
1130
1131 long_name_entries.push(name_part);
1133
1134 entry = self.get_next_entry().ok()?;
1136 if i + 1 < number_of_entries {
1137 long_entry = entry.as_long().clone();
1138 }
1139 }
1140
1141 Some(long_entries_name_merge(long_name_entries.into_iter()))
1142 } else {
1143 None
1144 };
1145
1146 let normal_entry = entry.as_normal().clone();
1147 assert!(self.entry_index_in_sector > 0);
1148
1149 Some(FatNode {
1150 normal_entry,
1151 long_name,
1152 parent_dir_sector: self.current_sector_index.into(),
1153 parent_dir_index: self.entry_index_in_sector - 1,
1154 })
1155 }
1156}
1157
1158impl Drop for DirectoryIterator<'_> {
1159 fn drop(&mut self) {
1160 self.flush_current_sector();
1161 }
1162}
1163
1164#[derive(Debug)]
1165struct ClusterCacheEntry {
1166 #[allow(dead_code)]
1167 cluster: u32,
1168 reference_count: u32,
1170 dirty_range: Option<Range<usize>>,
1171 data: NoDebug<Vec<u8>>,
1172}
1173
1174#[derive(Default, Debug)]
1175struct ClusterCache {
1176 entries: BTreeMap<u32, ClusterCacheEntry>,
1177}
1178
1179impl ClusterCache {
1180 pub fn try_get_cluster_mut(&mut self, cluster: u32) -> Option<&mut ClusterCacheEntry> {
1181 self.entries.get_mut(&cluster)
1182 }
1183
1184 pub fn try_get_cluster_locked(&mut self, cluster: u32) -> Option<&mut ClusterCacheEntry> {
1185 if let Some(entry) = self.entries.get_mut(&cluster) {
1186 entry.reference_count += 1;
1187 return Some(entry);
1188 }
1189 None
1190 }
1191
1192 pub fn insert_cluster(&mut self, cluster: u32, data: Vec<u8>) -> &mut ClusterCacheEntry {
1193 let entry = ClusterCacheEntry {
1194 cluster,
1195 reference_count: 1,
1196 data: NoDebug(data),
1197 dirty_range: None,
1198 };
1199 self.entries.entry(cluster).or_insert(entry)
1200 }
1201
1202 pub fn release_cluster(&mut self, cluster: u32) -> Option<ClusterCacheEntry> {
1203 match self.entries.entry(cluster) {
1204 alloc::collections::btree_map::Entry::Vacant(_) => None,
1205 alloc::collections::btree_map::Entry::Occupied(mut entry) => {
1206 let cluster = entry.get_mut();
1207 cluster.reference_count -= 1;
1208 if cluster.reference_count == 0 {
1209 return Some(entry.remove());
1210 }
1211 None
1212 }
1213 }
1214 }
1215
1216 pub fn release_all(&mut self) -> BTreeMap<u32, ClusterCacheEntry> {
1217 core::mem::take(&mut self.entries)
1218 }
1219}
1220
1221enum FileAccessBuffer<'a> {
1223 Read(&'a mut [u8]),
1224 Write(&'a [u8]),
1225}
1226
1227impl FileAccessBuffer<'_> {
1228 pub fn len(&self) -> usize {
1229 match self {
1230 FileAccessBuffer::Read(data) => data.len(),
1231 FileAccessBuffer::Write(data) => data.len(),
1232 }
1233 }
1234}
1235
1236#[derive(Debug)]
1238struct Fat {
1239 buffer: NoDebug<Vec<u8>>,
1240 sector_size: u16,
1241 fat_type: FatType,
1242 dirty: bool,
1243 dirty_bitmap: Vec<u64>,
1245}
1246
1247impl Fat {
1248 fn new() -> Self {
1250 Self {
1251 buffer: NoDebug(Vec::new()),
1252 sector_size: 0,
1253 fat_type: FatType::Fat12,
1254 dirty: false,
1255 dirty_bitmap: Vec::new(),
1256 }
1257 }
1258
1259 fn load(filesystem: &FatFilesystem) -> Result<Self, FileSystemError> {
1260 let fats_size_in_sectors = filesystem.boot_sector.fat_size_in_sectors()
1261 * filesystem.boot_sector.number_of_fats() as u32;
1262 let fat_start_sector = filesystem.boot_sector.fat_start_sector();
1263
1264 let buffer = filesystem.read_sectors_no_cache(fat_start_sector, fats_size_in_sectors)?;
1265 let fat_type = filesystem.fat_type();
1266
1267 Ok(Self {
1268 buffer: NoDebug(buffer),
1269 sector_size: filesystem.boot_sector.bytes_per_sector(),
1270 fat_type,
1271 dirty: false,
1272 dirty_bitmap: vec![0; (fats_size_in_sectors as usize).div_ceil(64)],
1273 })
1274 }
1275
1276 fn dirty_sectors(&self) -> Option<impl Iterator<Item = (u32, &[u8])>> {
1278 if !self.dirty {
1279 return None;
1280 }
1281
1282 Some(
1283 self.dirty_bitmap
1284 .iter()
1285 .enumerate()
1286 .filter_map(move |(i, dirty)| {
1287 if *dirty == 0 {
1288 return None;
1289 }
1290
1291 let mut dirty = *dirty;
1292 let mut bit = 0;
1293
1294 Some(core::iter::from_fn(move || {
1295 while dirty != 0 {
1296 if dirty & 1 != 0 {
1297 let sector = (i * 64 + bit) as u32;
1298 let sector_start = sector * self.sector_size as u32;
1299 let sector_end = sector_start + self.sector_size as u32;
1300 let data = &self.buffer[sector_start as usize..sector_end as usize];
1301 dirty >>= 1;
1302 bit += 1;
1303 return Some((sector, data));
1304 }
1305 dirty >>= 1;
1306 bit += 1;
1307 }
1308 None
1309 }))
1310 })
1311 .flatten(),
1312 )
1313 }
1314
1315 fn clear_dirty(&mut self) {
1316 if self.dirty {
1317 self.dirty = false;
1318 self.dirty_bitmap.iter_mut().for_each(|d| *d = 0);
1319 }
1320 }
1321
1322 fn read_fat_entry(&self, entry: u32) -> FatEntry {
1323 let fat_offset = match self.fat_type {
1324 FatType::Fat12 => entry * 3 / 2,
1325 FatType::Fat16 => entry * 2,
1326 FatType::Fat32 => entry * 4,
1327 } as usize;
1328 assert!(fat_offset < self.buffer.0.len(), "FAT entry out of bounds");
1329 let ptr = unsafe { self.buffer.0.as_ptr().add(fat_offset) };
1330
1331 let entry = match self.fat_type {
1332 FatType::Fat12 => {
1333 let byte1 = self.buffer.0[fat_offset];
1334 let byte2 = self.buffer.0[fat_offset + 1];
1335 if entry & 1 == 1 {
1336 ((byte2 as u32) << 4) | ((byte1 as u32) >> 4)
1337 } else {
1338 (((byte2 as u32) & 0xF) << 8) | (byte1 as u32)
1339 }
1340 }
1341 FatType::Fat16 => unsafe { (*(ptr as *const u16)) as u32 },
1342 FatType::Fat32 => unsafe { (*(ptr as *const u32)) & 0x0FFF_FFFF },
1343 };
1344
1345 FatEntry::from_u32(self.fat_type, entry)
1346 }
1347
1348 fn mark_sector_dirty(&mut self, sector: usize) {
1349 let index = sector / 64;
1350 let bit = sector % 64;
1351 self.dirty_bitmap[index] |= 1 << bit;
1352 }
1353
1354 fn write_fat_entry(&mut self, entry: u32, fat_entry: FatEntry) {
1355 let fat_offset = match self.fat_type {
1356 FatType::Fat12 => entry * 3 / 2,
1357 FatType::Fat16 => entry * 2,
1358 FatType::Fat32 => entry * 4,
1359 } as usize;
1360 assert!(fat_offset < self.buffer.0.len(), "FAT entry out of bounds");
1361 let ptr = unsafe { self.buffer.0.as_mut_ptr().add(fat_offset) };
1362
1363 let new_entry = fat_entry.to_u32(self.fat_type).expect("invalid FAT entry");
1364
1365 match self.fat_type {
1366 FatType::Fat12 => {
1367 if entry & 1 == 1 {
1368 self.buffer.0[fat_offset] =
1369 (self.buffer.0[fat_offset] & 0x0F) | (new_entry << 4) as u8;
1370 self.buffer.0[fat_offset + 1] = (new_entry >> 4) as u8;
1371 } else {
1372 self.buffer.0[fat_offset] = new_entry as u8;
1373 self.buffer.0[fat_offset + 1] =
1374 (self.buffer.0[fat_offset + 1] & 0xF0) | ((new_entry >> 8) as u8);
1375 }
1376 }
1377 FatType::Fat16 => unsafe { *(ptr as *mut u16) = new_entry as u16 },
1378 FatType::Fat32 => unsafe { *(ptr as *mut u32) = new_entry },
1379 }
1380
1381 self.mark_sector_dirty(fat_offset / self.sector_size as usize);
1382
1383 if self.fat_type == FatType::Fat12 {
1385 self.mark_sector_dirty((fat_offset + 1) / self.sector_size as usize);
1386 }
1387
1388 self.dirty = true;
1389 }
1390
1391 fn find_free_cluster(&self) -> Option<u32> {
1392 let fat_size = self.buffer.0.len();
1393
1394 let number_of_fat_entries = match self.fat_type {
1395 FatType::Fat12 => fat_size * 2 / 3,
1396 FatType::Fat16 => fat_size / 2,
1397 FatType::Fat32 => fat_size / 4,
1398 } as u32;
1399
1400 (2..number_of_fat_entries).find(|&i| self.read_fat_entry(i) == FatEntry::Free)
1401 }
1402
1403 fn next_cluster(&self, cluster: u32) -> Result<Option<u32>, FileSystemError> {
1404 match self.read_fat_entry(cluster) {
1405 FatEntry::Next(next_cluster) => Ok(Some(next_cluster)),
1406 FatEntry::EndOfChain => Ok(None),
1407 FatEntry::Bad => Err(FatError::UnexpectedFatEntry.into()),
1408 FatEntry::Reserved => Err(FatError::UnexpectedFatEntry.into()),
1409 FatEntry::Free => Err(FatError::UnexpectedFatEntry.into()),
1410 }
1411 }
1412}
1413
1414#[derive(Debug)]
1415pub struct FatFilesystem {
1416 start_lba: u32,
1417 #[allow(dead_code)]
1418 size_in_sectors: u32,
1419 boot_sector: Box<FatBootSector>,
1420 fat: Fat,
1421 device: NoDebug<Arc<IdeDevice>>,
1422 cluster_cache: ClusterCache,
1423}
1424
1425impl FatFilesystem {
1426 fn new(
1427 start_lba: u32,
1428 size_in_sectors: u32,
1429 boot_sector: FatBootSector,
1430 device: Arc<IdeDevice>,
1431 ) -> Result<Self, FileSystemError> {
1432 let mut s = FatFilesystem {
1433 start_lba,
1434 size_in_sectors,
1435 boot_sector: Box::new(boot_sector),
1436 fat: Fat::new(),
1437 device: NoDebug(device),
1438 cluster_cache: ClusterCache::default(),
1439 };
1440
1441 s.fat = Fat::load(&s)?;
1443
1444 Ok(s)
1445 }
1446
1447 pub fn volume_label(&self) -> String {
1448 let label = self.boot_sector.volume_label();
1449 let mut label = String::from_utf8_lossy(label).to_string();
1450 label.retain(|c| c != '\0');
1451 label
1452 }
1453
1454 pub fn fat_type(&self) -> FatType {
1455 self.boot_sector.ty
1456 }
1457
1458 fn first_sector_of_cluster(&self, cluster: u32) -> u32 {
1459 self.boot_sector.data_start_sector()
1460 + (cluster - 2) * self.boot_sector.sectors_per_cluster() as u32
1461 }
1462
1463 fn read_sectors_no_cache(
1464 &self,
1465 start_sector: u32,
1466 count: u32,
1467 ) -> Result<Vec<u8>, FileSystemError> {
1468 if count == 0 {
1469 return Ok(Vec::new());
1470 }
1471
1472 let sector_size = self.boot_sector.bytes_per_sector() as usize;
1473 let mut sectors = vec![0; sector_size * count as usize];
1474
1475 let start_lba = (self.start_lba + start_sector) as u64;
1476 self.device
1477 .read_sync(start_lba, &mut sectors)
1478 .map_err(|e| FileSystemError::DiskReadError {
1479 sector: start_lba,
1480 error: e,
1481 })?;
1482
1483 Ok(sectors)
1484 }
1485
1486 fn write_sectors(&self, start_sector: u32, data: &[u8]) -> Result<(), FileSystemError> {
1487 if data.is_empty() {
1488 return Ok(());
1489 }
1490 assert_eq!(data.len() % self.boot_sector.bytes_per_sector() as usize, 0);
1491 let start_lba = (self.start_lba + start_sector) as u64;
1492 self.device
1493 .write_sync(start_lba, data)
1494 .map_err(|e| FileSystemError::DiskReadError {
1495 sector: start_lba,
1496 error: e,
1497 })?;
1498 Ok(())
1499 }
1500
1501 fn get_cluster(&mut self, cluster: u32) -> Option<&mut ClusterCacheEntry> {
1502 self.cluster_cache.try_get_cluster_mut(cluster)
1503 }
1504
1505 fn lock_cluster(&mut self, cluster: u32) -> Result<&mut ClusterCacheEntry, FileSystemError> {
1506 if self.cluster_cache.try_get_cluster_mut(cluster).is_none() {
1509 let data = self.read_sectors_no_cache(
1510 self.first_sector_of_cluster(cluster),
1511 self.boot_sector.sectors_per_cluster().into(),
1512 )?;
1513 return Ok(self.cluster_cache.insert_cluster(cluster, data));
1514 }
1515
1516 Ok(self.cluster_cache.try_get_cluster_locked(cluster).unwrap())
1517 }
1518
1519 fn flush_cluster_dirty_range_file(
1521 &mut self,
1522 inode: &FileNode,
1523 cluster_data: &[u8],
1524 cluster_num: u32,
1525 dirty_range: Range<usize>,
1526 ) -> Result<(), FileSystemError> {
1527 self.flush_fat()?;
1528 self.update_directory_entry(inode, |entry| {
1529 entry.file_size = inode.size() as u32;
1530 })?;
1531
1532 self.flush_cluster_dirty_range(cluster_data, cluster_num, dirty_range)
1533 }
1534
1535 fn flush_cluster_dirty_range(
1536 &mut self,
1537 cluster_data: &[u8],
1538 cluster_num: u32,
1539 dirty_range: Range<usize>,
1540 ) -> Result<(), FileSystemError> {
1541 let start_byte_offset = align_down(
1542 dirty_range.start,
1543 self.boot_sector.bytes_per_sector() as usize,
1544 );
1545 let end_byte_offset = align_up(
1546 dirty_range.end,
1547 self.boot_sector.bytes_per_sector() as usize,
1548 );
1549 assert!(
1550 start_byte_offset < self.boot_sector.bytes_per_cluster() as usize,
1551 "start_byte_offset: {start_byte_offset} < {}",
1552 self.boot_sector.bytes_per_cluster()
1553 );
1554 assert!(
1555 end_byte_offset <= self.boot_sector.bytes_per_cluster() as usize,
1556 "end_byte_offset: {end_byte_offset} < {}",
1557 self.boot_sector.bytes_per_cluster()
1558 );
1559 assert!(
1560 start_byte_offset < end_byte_offset,
1561 "start_byte_offset, end_byte_offset {start_byte_offset} < {end_byte_offset}"
1562 );
1563
1564 let start_sector = self.first_sector_of_cluster(cluster_num)
1566 + (start_byte_offset as u32 / self.boot_sector.bytes_per_sector() as u32);
1567 self.write_sectors(
1568 start_sector,
1569 &cluster_data[start_byte_offset..end_byte_offset],
1570 )?;
1571
1572 Ok(())
1573 }
1574
1575 fn release_cluster(&mut self, inode: &FileNode, cluster: u32) -> Result<(), FileSystemError> {
1576 if let Some(cluster) = self.cluster_cache.release_cluster(cluster) {
1577 if let Some(dirty_range) = cluster.dirty_range {
1578 self.flush_cluster_dirty_range_file(
1579 inode,
1580 &cluster.data,
1581 cluster.cluster,
1582 dirty_range,
1583 )?;
1584 }
1585 }
1586 Ok(())
1587 }
1588
1589 fn flush_cluster(&mut self, inode: &FileNode, cluster: u32) -> Result<(), FileSystemError> {
1592 let mut cluster_data: Option<NoDebug<Vec<u8>>> = None;
1593
1594 if let Some(cluster) = self.cluster_cache.try_get_cluster_mut(cluster) {
1595 if let Some(dirty_range) = cluster.dirty_range.take() {
1596 let cluster_num = cluster.cluster;
1597 cluster_data = Some(NoDebug(Vec::new()));
1598 core::mem::swap(&mut cluster.data, cluster_data.as_mut().unwrap());
1599 self.flush_cluster_dirty_range_file(
1600 inode,
1601 cluster_data.as_ref().unwrap(),
1602 cluster_num,
1603 dirty_range,
1604 )?;
1605 }
1606 }
1607 if let Some(cluster) = self.cluster_cache.try_get_cluster_mut(cluster) {
1612 if let Some(cluster_data) = cluster_data.as_mut() {
1613 core::mem::swap(&mut cluster.data, cluster_data);
1614 }
1615 }
1616
1617 Ok(())
1618 }
1619
1620 fn flush_fat(&mut self) -> Result<(), FileSystemError> {
1621 if let Some(dirt_iter) = self.fat.dirty_sectors() {
1622 for (sector, data) in dirt_iter {
1623 self.write_sectors(self.boot_sector.fat_start_sector() + sector, data)?;
1624 }
1625 }
1626 self.fat.clear_dirty();
1627
1628 Ok(())
1629 }
1630
1631 fn open_root_dir(&self) -> Result<Directory, FileSystemError> {
1632 match self.fat_type() {
1633 FatType::Fat12 | FatType::Fat16 => Ok(Directory::RootFat12_16 {
1634 start_sector: self.boot_sector.root_dir_start_sector(),
1635 size_in_sectors: self.boot_sector.root_dir_sectors(),
1636 }),
1637 FatType::Fat32 => {
1638 let root_cluster =
1639 unsafe { self.boot_sector.boot_sector.extended.fat32.root_cluster };
1640 let inode = DirectoryNode::without_parent(
1641 String::from("/"),
1642 file_attribute_from_fat(attrs::DIRECTORY),
1643 root_cluster as u64,
1644 );
1645 Ok(Directory::Normal { inode })
1646 }
1647 }
1648 }
1649
1650 fn open_root_dir_inode(&self) -> Result<DirectoryNode, FileSystemError> {
1651 match self.fat_type() {
1652 FatType::Fat12 | FatType::Fat16 => {
1653 let inode = DirectoryNode::without_parent(
1655 String::from("/"),
1656 file_attribute_from_fat(attrs::DIRECTORY),
1657 0,
1658 );
1659
1660 Ok(inode)
1661 }
1662 FatType::Fat32 => {
1663 let root_cluster =
1664 unsafe { self.boot_sector.boot_sector.extended.fat32.root_cluster };
1665 let inode = DirectoryNode::without_parent(
1666 String::from("/"),
1667 file_attribute_from_fat(attrs::DIRECTORY),
1668 root_cluster as u64,
1669 );
1670 Ok(inode)
1671 }
1672 }
1673 }
1674
1675 pub fn open_dir_inode(
1676 &self,
1677 inode: &DirectoryNode,
1678 ) -> Result<DirectoryIterator<'_>, FileSystemError> {
1679 let dir = match self.fat_type() {
1680 FatType::Fat12 | FatType::Fat16 => {
1681 if inode.start_cluster() == 0 {
1684 self.open_root_dir()?
1685 } else {
1686 Directory::Normal {
1687 inode: inode.clone(),
1688 }
1689 }
1690 }
1691 FatType::Fat32 => Directory::Normal {
1692 inode: inode.clone(),
1693 },
1694 };
1695
1696 DirectoryIterator::new(self, dir)
1697 }
1698
1699 fn read_write_file(
1700 &mut self,
1701 inode: &FileNode,
1702 position: u32,
1703 mut buf: FileAccessBuffer,
1704 access_helper: &mut AccessHelper,
1705 ) -> Result<u64, FileSystemError> {
1706 if position >= inode.size() as u32 {
1707 return Ok(0);
1708 }
1709 let remaining_file = inode.size() as u32 - position;
1710 let max_to_access = (buf.len() as u32).min(remaining_file);
1711 let bytes_per_cluster = self.boot_sector.bytes_per_cluster();
1712 let mut position_in_cluster = position % bytes_per_cluster;
1713 let cluster_index = position / bytes_per_cluster;
1714
1715 if access_helper.cluster_index != cluster_index as u64 {
1717 if access_helper.current_cluster != 0 {
1718 self.release_cluster(inode, access_helper.current_cluster as u32)?;
1719 }
1720 access_helper.current_cluster = 0;
1721 }
1722
1723 let mut cluster_entry = if access_helper.current_cluster == 0 {
1725 let mut cluster = inode.start_cluster() as u32;
1726
1727 assert_ne!(cluster, 0);
1729
1730 for _ in 0..cluster_index {
1731 cluster = self
1732 .fat
1733 .next_cluster(cluster)?
1734 .ok_or(FatError::UnexpectedFatEntry)?;
1735 }
1736
1737 access_helper.current_cluster = cluster as u64;
1738 access_helper.cluster_index = cluster_index as u64;
1739 self.lock_cluster(access_helper.current_cluster as u32)?
1740 } else {
1741 self.get_cluster(access_helper.current_cluster as u32)
1742 .expect("This should be cached")
1743 };
1744 let mut cluster = access_helper.current_cluster as u32;
1745
1746 let mut accessed = 0;
1748 while accessed < max_to_access as usize {
1749 let remaining_in_cluster = &mut cluster_entry.data[position_in_cluster as usize..];
1750
1751 let to_access = core::cmp::min(
1752 remaining_in_cluster.len() as u32,
1753 max_to_access - accessed as u32,
1754 ) as usize;
1755 match buf {
1756 FileAccessBuffer::Read(ref mut buf) => {
1757 buf[accessed..accessed + to_access]
1758 .copy_from_slice(&remaining_in_cluster[..to_access]);
1759 }
1760 FileAccessBuffer::Write(buf) => {
1761 let range_start = position_in_cluster as usize;
1762 let range_end = range_start + to_access;
1763
1764 if let Some(dirty_range) = cluster_entry.dirty_range.as_mut() {
1765 dirty_range.start = dirty_range.start.min(range_start);
1766 dirty_range.end = dirty_range.end.max(range_end);
1767 } else {
1768 cluster_entry.dirty_range = Some(range_start..range_end);
1769 }
1770 remaining_in_cluster[..to_access]
1771 .copy_from_slice(&buf[accessed..accessed + to_access]);
1772 }
1773 }
1774
1775 accessed += to_access;
1776 position_in_cluster += to_access as u32;
1777 if position_in_cluster >= bytes_per_cluster {
1778 assert_eq!(position_in_cluster, bytes_per_cluster);
1779 position_in_cluster = 0;
1780 match self.fat.next_cluster(cluster)? {
1781 Some(next_cluster) => {
1782 self.release_cluster(inode, cluster)?;
1783 cluster = next_cluster;
1784 cluster_entry = self.lock_cluster(cluster)?;
1785 access_helper.current_cluster = cluster as u64;
1786 access_helper.cluster_index += 1;
1787 }
1788 None => {
1789 break;
1790 }
1791 };
1792 }
1793 }
1794
1795 Ok(accessed as u64)
1796 }
1797
1798 fn update_directory_entry(
1799 &mut self,
1800 inode: &BaseNode,
1801 mut update: impl FnMut(&mut DirectoryEntryNormal),
1802 ) -> Result<(), FileSystemError> {
1803 let mut sector = self.read_sectors_no_cache(inode.parent_dir_sector() as u32, 1)?;
1804 let entry_index = inode.parent_dir_index();
1805 let start = entry_index as usize * DIRECTORY_ENTRY_SIZE as usize;
1806 let end = start + DIRECTORY_ENTRY_SIZE as usize;
1807
1808 let mut entry = DirectoryEntry::from_raw(&mut sector[start..end]);
1809 assert_eq!(entry.state(), DirectoryEntryState::Used);
1810
1811 let entry = entry.as_normal_mut();
1812 let current = entry.clone();
1813 update(entry);
1814
1815 if current != *entry {
1816 self.write_sectors(inode.parent_dir_sector() as u32, §or)?;
1818 }
1819
1820 Ok(())
1821 }
1822
1823 fn add_directory_entry(
1824 &mut self,
1825 parent_inode: &DirectoryNode,
1826 name: &str,
1827 attributes: FileAttributes,
1828 ) -> Result<Node, FileSystemError> {
1829 let (mut normal_entry, long_name_entries) = create_dir_entries(name, attributes);
1830
1831 let cluster = self
1846 .fat
1847 .find_free_cluster()
1848 .ok_or(FatError::NotEnoughSpace)?;
1849 self.fat.write_fat_entry(cluster, FatEntry::EndOfChain);
1850 self.flush_fat()?;
1851 self.write_sectors(
1856 self.first_sector_of_cluster(cluster),
1857 &vec![0; self.boot_sector.bytes_per_sector() as usize],
1858 )?;
1859
1860 normal_entry.first_cluster_lo = (cluster & 0xFFFF) as u16;
1861 normal_entry.first_cluster_hi = (cluster >> 16) as u16;
1862
1863 let node = self
1864 .open_dir_inode(parent_inode)
1865 .and_then(|mut dir| dir.add_entry(normal_entry.clone(), long_name_entries));
1866
1867 let node = match node {
1868 Ok(node) => node,
1869 e @ Err(_) => {
1870 self.fat.write_fat_entry(cluster, FatEntry::Free);
1872 self.flush_fat()?;
1873 return e;
1874 }
1875 };
1876
1877 assert_eq!(node.name(), name, "node name: {:?}", node.name());
1878
1879 if attributes.directory() {
1881 assert_eq!(node.start_cluster(), cluster as u64);
1882 let mut dot_entry = DirectoryEntryNormal {
1883 short_name: [0x20; 11],
1884 _nt_reserved: 0,
1885 ..normal_entry
1886 };
1887 dot_entry.short_name[0] = b'.';
1888 let parent_cluster = parent_inode.start_cluster() as u32;
1889 let mut dot_dot_entry = DirectoryEntryNormal {
1890 short_name: [0x20; 11],
1891 _nt_reserved: 0,
1892 attributes: file_attribute_to_fat(parent_inode.attributes()),
1893 creation_time_tenths_of_seconds: 0,
1894 creation_time: 0,
1895 creation_date: 0,
1896 last_access_date: 0,
1897 first_cluster_lo: (parent_cluster & 0xFFFF) as u16,
1898 first_cluster_hi: (parent_cluster >> 16) as u16,
1899 last_modification_time: 0,
1900 last_modification_date: 0,
1901 file_size: 0,
1902 };
1903 dot_dot_entry.short_name[0] = b'.';
1904 dot_dot_entry.short_name[1] = b'.';
1905
1906 let dir_node = match node {
1907 Node::Directory(ref dir) => dir,
1908 _ => unreachable!(),
1909 };
1910
1911 let mut dir_iter = self.open_dir_inode(dir_node)?;
1912 let dot_node = dir_iter.add_entry(dot_entry, Vec::new())?;
1913 let dot_dot_node = dir_iter.add_entry(dot_dot_entry, Vec::new())?;
1914
1915 assert_eq!(dot_node.name(), ".", "dot node name: {:?}", dot_node.name());
1916 assert_eq!(
1917 dot_dot_node.name(),
1918 "..",
1919 "dot dot node name: {:?}",
1920 dot_dot_node.name()
1921 );
1922 }
1923
1924 Ok(node)
1925 }
1926
1927 fn set_file_size(&mut self, inode: &mut FileNode, size: u64) -> Result<(), FileSystemError> {
1928 let bytes_per_cluster = self.boot_sector.bytes_per_cluster() as u64;
1929 let current_size_in_clusters = inode.size().div_ceil(bytes_per_cluster);
1930 let new_size_in_clusters = size.div_ceil(bytes_per_cluster);
1931
1932 let current_size_in_clusters = current_size_in_clusters.max(1);
1934 let new_size_in_clusters = new_size_in_clusters.max(1);
1935
1936 if new_size_in_clusters != current_size_in_clusters {
1937 let to_keep = new_size_in_clusters.min(current_size_in_clusters);
1939
1940 let mut current_cluster = inode.start_cluster() as u32;
1941
1942 for _ in 0..to_keep.saturating_sub(1) {
1944 let next_cluster = self
1945 .fat
1946 .next_cluster(current_cluster)?
1947 .expect("next cluster");
1948 current_cluster = next_cluster;
1949 }
1950
1951 let mut last_cluster = current_cluster;
1952
1953 if current_size_in_clusters > new_size_in_clusters {
1954 let to_delete = current_size_in_clusters - new_size_in_clusters;
1956 let mut clusters = Vec::with_capacity(to_delete as usize);
1957
1958 for _ in 0..to_delete {
1959 let next_cluster = self
1960 .fat
1961 .next_cluster(current_cluster)?
1962 .expect("next cluster");
1963 clusters.push(next_cluster);
1964 current_cluster = next_cluster;
1965 }
1966
1967 for cluster in clusters.into_iter().rev() {
1969 self.fat.write_fat_entry(cluster, FatEntry::Free);
1970 }
1971
1972 self.fat.write_fat_entry(last_cluster, FatEntry::EndOfChain);
1974 } else {
1975 let to_add = new_size_in_clusters - current_size_in_clusters;
1978
1979 for _ in 0..to_add {
1980 let new_cluster = self
1981 .fat
1982 .find_free_cluster()
1983 .ok_or(FatError::NotEnoughSpace)?;
1984
1985 self.fat
1986 .write_fat_entry(last_cluster, FatEntry::Next(new_cluster));
1987 self.fat.write_fat_entry(new_cluster, FatEntry::EndOfChain);
1989
1990 last_cluster = new_cluster;
1991 }
1992 }
1993 }
1994
1995 inode.set_size(size);
1996
1997 Ok(())
1998 }
1999}
2000
2001impl FileSystem for Mutex<FatFilesystem> {
2002 fn open_root(&self) -> Result<DirectoryNode, FileSystemError> {
2003 self.lock().open_root_dir_inode()
2004 }
2005
2006 fn read_dir(
2007 &self,
2008 inode: &DirectoryNode,
2009 handler: &mut dyn FnMut(Node) -> DirTraverse,
2010 ) -> Result<(), FileSystemError> {
2011 for node in self.lock().open_dir_inode(inode)? {
2012 if let DirTraverse::Stop = handler(node.into()) {
2013 break;
2014 }
2015 }
2016
2017 Ok(())
2018 }
2019
2020 fn traverse_dir(&self, inode: &DirectoryNode, matcher: &str) -> Result<Node, FileSystemError> {
2021 for node in self.lock().open_dir_inode(inode)? {
2022 if node.matches(matcher) {
2023 return Ok(node.into());
2024 }
2025 }
2026
2027 Err(FileSystemError::FileNotFound)
2028 }
2029
2030 fn create_node(
2031 &self,
2032 parent: &DirectoryNode,
2033 name: &str,
2034 attributes: FileAttributes,
2035 ) -> Result<Node, FileSystemError> {
2036 self.lock().add_directory_entry(parent, name, attributes)
2037 }
2038
2039 fn read_file(
2040 &self,
2041 inode: &FileNode,
2042 position: u64,
2043 buf: &mut [u8],
2044 access_helper: &mut AccessHelper,
2045 ) -> Result<u64, FileSystemError> {
2046 assert!(position <= u32::MAX as u64);
2047 self.lock().read_write_file(
2048 inode,
2049 position as u32,
2050 FileAccessBuffer::Read(buf),
2051 access_helper,
2052 )
2053 }
2054
2055 fn write_file(
2056 &self,
2057 inode: &mut FileNode,
2058 position: u64,
2059 buf: &[u8],
2060 access_helper: &mut AccessHelper,
2061 ) -> Result<u64, FileSystemError> {
2062 assert!(position <= u32::MAX as u64);
2063
2064 let mut s = self.lock();
2065
2066 let current_size = inode.size();
2067 let new_size = position + buf.len() as u64;
2068
2069 if new_size > current_size {
2070 s.set_file_size(inode, new_size)
2071 .map_err(|_| FileSystemError::CouldNotSetFileLength)?;
2072 }
2073
2074 if position > current_size {
2077 let extend_size = position - current_size;
2078
2079 let zeros = vec![0; s.boot_sector.bytes_per_sector() as usize];
2080
2081 let mut written = 0;
2082 while written < extend_size {
2083 let to_write = zeros.len().min((extend_size - written) as usize);
2084 s.read_write_file(
2085 inode,
2086 (current_size + written) as u32,
2087 FileAccessBuffer::Write(&zeros[..to_write]),
2088 access_helper,
2089 )?;
2090 written += to_write as u64;
2091 }
2092 }
2093
2094 s.read_write_file(
2095 inode,
2096 position as u32,
2097 FileAccessBuffer::Write(buf),
2098 access_helper,
2099 )
2100 }
2101
2102 fn flush_file(
2103 &self,
2104 inode: &mut FileNode,
2105 access_helper: &mut AccessHelper,
2106 ) -> Result<(), FileSystemError> {
2107 self.lock()
2108 .flush_cluster(inode, access_helper.current_cluster as u32)
2109 }
2110
2111 fn close_file(
2112 &self,
2113 inode: &FileNode,
2114 access_helper: AccessHelper,
2115 ) -> Result<(), FileSystemError> {
2116 self.lock()
2117 .release_cluster(inode, access_helper.current_cluster as u32)
2118 }
2119
2120 fn set_file_size(&self, inode: &mut FileNode, size: u64) -> Result<(), FileSystemError> {
2121 let mut s = self.lock();
2122
2123 s.set_file_size(inode, size)?;
2124 s.flush_fat()?;
2125 s.update_directory_entry(inode, |entry| {
2126 entry.file_size = inode.size() as u32;
2127 })?;
2128
2129 Ok(())
2130 }
2131
2132 fn unmount(self: Arc<Self>) {
2133 let mut s = self.lock();
2134 s.flush_fat().expect("flush fat");
2135
2136 for cluster in s.cluster_cache.release_all().into_values() {
2137 if let Some(dirty_range) = cluster.dirty_range {
2138 s.flush_cluster_dirty_range(&cluster.data, cluster.cluster, dirty_range)
2139 .expect("flush cluster dirty range");
2140 }
2141 }
2142 }
2143}