1use crate::core::cell::{Cell, RefCell};
2use crate::core::char;
3use crate::core::cmp;
4use crate::core::fmt::Debug;
5use crate::core::iter::FromIterator;
6use crate::core::u32;
7use crate::io;
8use crate::io::prelude::*;
9use crate::io::{Error, ErrorKind, SeekFrom};
10#[cfg(all(not(feature = "std"), feature = "alloc"))]
11use alloc::string::String;
12
13use crate::byteorder_ext::{ReadBytesExt, WriteBytesExt};
14use byteorder::LittleEndian;
15
16use crate::boot_sector::{format_boot_sector, BiosParameterBlock, BootSector};
17use crate::dir::{Dir, DirRawStream};
18use crate::dir_entry::{SFN_PADDING, SFN_SIZE};
19use crate::error::FatfsError;
20use crate::file::File;
21use crate::table::{
22 alloc_cluster, count_free_clusters, format_fat, read_fat_flags, ClusterIterator,
23 RESERVED_FAT_ENTRIES,
24};
25use crate::time::{DefaultTimeProvider, TimeProvider};
26use crate::transaction::TransactionManager;
27
28#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
36pub enum FatType {
37 Fat12,
39 Fat16,
41 Fat32,
43}
44
45impl FatType {
46 const FAT16_MIN_CLUSTERS: u32 = 4085;
47 const FAT32_MIN_CLUSTERS: u32 = 65525;
48 const FAT32_MAX_CLUSTERS: u32 = 0x0FFF_FFF4;
49
50 pub(crate) fn from_clusters(total_clusters: u32) -> FatType {
51 if total_clusters < Self::FAT16_MIN_CLUSTERS {
52 FatType::Fat12
53 } else if total_clusters < Self::FAT32_MIN_CLUSTERS {
54 FatType::Fat16
55 } else {
56 FatType::Fat32
57 }
58 }
59
60 pub(crate) fn bits_per_fat_entry(&self) -> u32 {
61 match self {
62 FatType::Fat12 => 12,
63 FatType::Fat16 => 16,
64 FatType::Fat32 => 32,
65 }
66 }
67
68 pub(crate) fn min_clusters(&self) -> u32 {
69 match self {
70 FatType::Fat12 => 0,
71 FatType::Fat16 => Self::FAT16_MIN_CLUSTERS,
72 FatType::Fat32 => Self::FAT32_MIN_CLUSTERS,
73 }
74 }
75
76 pub(crate) fn max_clusters(&self) -> u32 {
77 match self {
78 FatType::Fat12 => Self::FAT16_MIN_CLUSTERS - 1,
79 FatType::Fat16 => Self::FAT32_MIN_CLUSTERS - 1,
80 FatType::Fat32 => Self::FAT32_MAX_CLUSTERS,
81 }
82 }
83}
84
85#[derive(Copy, Clone, Eq, PartialEq, Debug)]
87pub struct FsStatusFlags {
88 pub(crate) dirty: bool,
89 pub(crate) io_error: bool,
90}
91
92impl FsStatusFlags {
93 pub fn dirty(&self) -> bool {
97 self.dirty
98 }
99
100 pub fn io_error(&self) -> bool {
102 self.io_error
103 }
104
105 fn encode(&self) -> u8 {
106 let mut res = 0u8;
107 if self.dirty {
108 res |= 1;
109 }
110 if self.io_error {
111 res |= 2;
112 }
113 res
114 }
115
116 pub(crate) fn decode(flags: u8) -> Self {
117 FsStatusFlags { dirty: flags & 1 != 0, io_error: flags & 2 != 0 }
118 }
119}
120
121pub trait ReadSeek: Read + Seek {}
123impl<T: Read + Seek> ReadSeek for T {}
124
125pub trait ReadWriteSeek: Read + Write + Seek {}
127impl<T: Read + Write + Seek> ReadWriteSeek for T {}
128
129#[derive(Clone, Default, Debug)]
130struct FsInfoSector {
131 free_cluster_count: Option<u32>,
132 next_free_cluster: Option<u32>,
133 dirty: bool,
134}
135
136impl FsInfoSector {
137 const LEAD_SIG: u32 = 0x41615252;
138 const STRUC_SIG: u32 = 0x61417272;
139 const TRAIL_SIG: u32 = 0xAA550000;
140
141 fn deserialize<R: Read>(rdr: &mut R) -> io::Result<FsInfoSector> {
142 let lead_sig = rdr.read_u32::<LittleEndian>()?;
143 if lead_sig != Self::LEAD_SIG {
144 return Err(Error::new(ErrorKind::Other, FatfsError::InvalidLeadSig));
145 }
146 let mut reserved = [0u8; 480];
147 rdr.read_exact(&mut reserved)?;
148 let struc_sig = rdr.read_u32::<LittleEndian>()?;
149 if struc_sig != Self::STRUC_SIG {
150 return Err(Error::new(ErrorKind::Other, FatfsError::InvalidStrucSig));
151 }
152 let free_cluster_count = match rdr.read_u32::<LittleEndian>()? {
153 0xFFFFFFFF => None,
154 n => Some(n),
156 };
157 let next_free_cluster = match rdr.read_u32::<LittleEndian>()? {
158 0xFFFFFFFF => None,
159 0 | 1 => {
160 warn!("invalid next_free_cluster in FsInfo sector (values 0 and 1 are reserved)");
161 None
162 }
163 n => Some(n),
165 };
166 let mut reserved2 = [0u8; 12];
167 rdr.read_exact(&mut reserved2)?;
168 let trail_sig = rdr.read_u32::<LittleEndian>()?;
169 if trail_sig != Self::TRAIL_SIG {
170 return Err(Error::new(ErrorKind::Other, FatfsError::InvalidTrailSig));
171 }
172 Ok(FsInfoSector { free_cluster_count, next_free_cluster, dirty: false })
173 }
174
175 fn serialize<W: Write>(&self, wrt: &mut W) -> io::Result<()> {
176 wrt.write_u32::<LittleEndian>(Self::LEAD_SIG)?;
177 let reserved = [0u8; 480];
178 wrt.write_all(&reserved)?;
179 wrt.write_u32::<LittleEndian>(Self::STRUC_SIG)?;
180 wrt.write_u32::<LittleEndian>(self.free_cluster_count.unwrap_or(0xFFFFFFFF))?;
181 wrt.write_u32::<LittleEndian>(self.next_free_cluster.unwrap_or(0xFFFFFFFF))?;
182 let reserved2 = [0u8; 12];
183 wrt.write_all(&reserved2)?;
184 wrt.write_u32::<LittleEndian>(Self::TRAIL_SIG)?;
185 Ok(())
186 }
187
188 fn validate_and_fix(&mut self, total_clusters: u32) {
189 let max_valid_cluster_number = total_clusters + RESERVED_FAT_ENTRIES;
190 if let Some(n) = self.free_cluster_count {
191 if n > total_clusters {
192 warn!(
193 "invalid free_cluster_count ({}) in fs_info exceeds total cluster count ({})",
194 n, total_clusters
195 );
196 self.free_cluster_count = None;
197 }
198 }
199 if let Some(n) = self.next_free_cluster {
200 if n > max_valid_cluster_number {
201 warn!(
202 "invalid free_cluster_count ({}) in fs_info exceeds maximum cluster number ({})",
203 n, max_valid_cluster_number
204 );
205 self.next_free_cluster = None;
206 }
207 }
208 }
209
210 fn add_free_clusters(&mut self, free_clusters: i32) {
211 if let Some(n) = self.free_cluster_count {
212 self.free_cluster_count = Some((n as i32 + free_clusters) as u32);
213 self.dirty = true;
214 }
215 }
216
217 fn set_next_free_cluster(&mut self, cluster: u32) {
218 self.next_free_cluster = Some(cluster);
219 self.dirty = true;
220 }
221
222 fn set_free_cluster_count(&mut self, free_cluster_count: u32) {
223 self.free_cluster_count = Some(free_cluster_count);
224 self.dirty = true;
225 }
226}
227
228#[derive(Copy, Clone, Debug)]
232pub struct FsOptions<TP, OCC> {
233 pub(crate) update_accessed_date: bool,
234 pub(crate) oem_cp_converter: OCC,
235 pub(crate) time_provider: TP,
236}
237
238impl FsOptions<DefaultTimeProvider, LossyOemCpConverter> {
239 pub fn new() -> Self {
241 FsOptions {
242 update_accessed_date: false,
243 oem_cp_converter: LossyOemCpConverter::new(),
244 time_provider: DefaultTimeProvider::new(),
245 }
246 }
247}
248
249impl<TP: TimeProvider, OCC: OemCpConverter> FsOptions<TP, OCC> {
250 pub fn update_accessed_date(mut self, enabled: bool) -> Self {
252 self.update_accessed_date = enabled;
253 self
254 }
255
256 pub fn oem_cp_converter<OCC2: OemCpConverter>(
258 self,
259 oem_cp_converter: OCC2,
260 ) -> FsOptions<TP, OCC2> {
261 FsOptions::<TP, OCC2> {
262 update_accessed_date: self.update_accessed_date,
263 oem_cp_converter,
264 time_provider: self.time_provider,
265 }
266 }
267
268 pub fn time_provider<TP2: TimeProvider>(self, time_provider: TP2) -> FsOptions<TP2, OCC> {
270 FsOptions::<TP2, OCC> {
271 update_accessed_date: self.update_accessed_date,
272 oem_cp_converter: self.oem_cp_converter,
273 time_provider,
274 }
275 }
276}
277
278#[derive(Copy, Clone, Eq, PartialEq, Debug)]
280pub struct FileSystemStats {
281 sector_size: u16,
282 cluster_size: u32,
283 total_clusters: u32,
284 free_clusters: u32,
285}
286
287impl FileSystemStats {
288 pub fn sector_size(&self) -> u16 {
290 self.sector_size
291 }
292
293 pub fn cluster_size(&self) -> u32 {
295 self.cluster_size
296 }
297
298 pub fn total_clusters(&self) -> u32 {
300 self.total_clusters
301 }
302
303 pub fn free_clusters(&self) -> u32 {
305 self.free_clusters
306 }
307}
308
309pub struct FileSystem<IO: ReadWriteSeek, TP, OCC> {
313 pub(crate) disk: RefCell<TransactionManager<IO>>,
314 pub(crate) options: FsOptions<TP, OCC>,
315 fat_type: FatType,
316 bpb: BiosParameterBlock,
317 first_data_sector: u32,
318 root_dir_sectors: u32,
319 total_clusters: u32,
320 fs_info: RefCell<FsInfoSector>,
321 current_status_flags: Cell<FsStatusFlags>,
322}
323
324impl<IO: ReadWriteSeek, TP, OCC> FileSystem<IO, TP, OCC> {
325 pub fn new(mut disk: IO, options: FsOptions<TP, OCC>) -> io::Result<Self> {
334 trace!("FileSystem::new");
336 debug_assert!(disk.seek(SeekFrom::Current(0))? == 0);
337
338 let bpb = {
340 let boot = BootSector::deserialize(&mut disk)?;
341 boot.validate()?;
342 boot.bpb
343 };
344
345 let root_dir_sectors = bpb.root_dir_sectors();
346 let first_data_sector = bpb.first_data_sector();
347 let total_clusters = bpb.total_clusters();
348 let fat_type = FatType::from_clusters(total_clusters);
349
350 let mut fs_info = if fat_type == FatType::Fat32 {
352 disk.seek(SeekFrom::Start(bpb.bytes_from_sectors(bpb.fs_info_sector())))?;
353 FsInfoSector::deserialize(&mut disk)?
354 } else {
355 FsInfoSector::default()
356 };
357
358 if bpb.status_flags().dirty {
360 fs_info.free_cluster_count = None;
361 }
362
363 fs_info.validate_and_fix(total_clusters);
365
366 let status_flags = bpb.status_flags();
368 trace!("FileSystem::new end");
369 Ok(FileSystem {
370 disk: RefCell::new(TransactionManager::new(disk)),
371 options,
372 fat_type,
373 bpb,
374 first_data_sector,
375 root_dir_sectors,
376 total_clusters,
377 fs_info: RefCell::new(fs_info),
378 current_status_flags: Cell::new(status_flags),
379 })
380 }
381
382 pub fn with_disk<F, T>(&self, func: F) -> T
383 where
384 F: FnOnce(&IO) -> T,
385 {
386 func(self.disk.borrow().borrow_inner())
387 }
388
389 pub fn fat_type(&self) -> FatType {
391 self.fat_type
392 }
393
394 pub fn volume_id(&self) -> u32 {
396 self.bpb.volume_id
397 }
398
399 pub fn volume_label_as_bytes(&self) -> &[u8] {
405 let full_label_slice = &self.bpb.volume_label;
406 let len =
407 full_label_slice.iter().rposition(|b| *b != SFN_PADDING).map(|p| p + 1).unwrap_or(0);
408 &full_label_slice[..len]
409 }
410
411 fn offset_from_sector(&self, sector: u32) -> u64 {
412 self.bpb.bytes_from_sectors(sector)
413 }
414
415 fn sector_from_cluster(&self, cluster: u32) -> Result<u32, FatfsError> {
416 if cluster < RESERVED_FAT_ENTRIES {
417 return Err(FatfsError::InvalidClusterNumber);
418 }
419
420 Ok(self
421 .first_data_sector
422 .checked_add(self.bpb.sectors_from_clusters(cluster - RESERVED_FAT_ENTRIES)?)
423 .ok_or(FatfsError::InvalidClusterNumber)?)
424 }
425
426 pub fn cluster_size(&self) -> u32 {
427 self.bpb.cluster_size()
428 }
429
430 pub(crate) fn offset_from_cluster(&self, cluster: u32) -> Result<u64, FatfsError> {
431 Ok(self.offset_from_sector(self.sector_from_cluster(cluster)?))
432 }
433
434 pub(crate) fn bytes_from_clusters(&self, clusters: u32) -> Result<u64, FatfsError> {
435 Ok(self.bpb.bytes_from_sectors(self.bpb.sectors_from_clusters(clusters)?))
436 }
437
438 pub(crate) fn clusters_from_bytes(&self, bytes: u64) -> u32 {
439 self.bpb.clusters_from_bytes(bytes)
440 }
441
442 fn fat_slice<'a>(&'a self) -> DiskSlice<FsIoAdapter<'a, IO, TP, OCC>> {
443 let io = FsIoAdapter { fs: self };
444 fat_slice(io, &self.bpb)
445 }
446
447 pub(crate) fn cluster_iter<'a>(
448 &'a self,
449 cluster: u32,
450 ) -> ClusterIterator<DiskSlice<FsIoAdapter<'a, IO, TP, OCC>>> {
451 let disk_slice = self.fat_slice();
452 ClusterIterator::new(disk_slice, self.fat_type, cluster)
453 }
454
455 pub(crate) fn truncate_cluster_chain(&self, cluster: u32) -> io::Result<()> {
456 let mut iter = self.cluster_iter(cluster);
457 let num_free = iter.truncate()?;
458 let mut fs_info = self.fs_info.borrow_mut();
459 fs_info.add_free_clusters(num_free as i32);
460 Ok(())
461 }
462
463 pub(crate) fn free_cluster_chain(&self, cluster: u32) -> io::Result<()> {
464 let mut iter = self.cluster_iter(cluster);
465 let num_free = iter.free()?;
466 let mut fs_info = self.fs_info.borrow_mut();
467 fs_info.add_free_clusters(num_free as i32);
468 Ok(())
469 }
470
471 pub(crate) fn alloc_cluster(&self, prev_cluster: Option<u32>, zero: bool) -> io::Result<u32> {
472 trace!("alloc_cluster");
473 let hint = self.fs_info.borrow().next_free_cluster;
474 let cluster = {
475 let mut fat = self.fat_slice();
476 alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint, self.total_clusters)?
477 };
478 if zero {
479 let mut disk = self.disk.borrow_mut();
480 disk.seek(SeekFrom::Start(self.offset_from_cluster(cluster)?))?;
481 write_zeros(&mut *disk, self.cluster_size() as u64)?;
482 }
483 let mut fs_info = self.fs_info.borrow_mut();
484 fs_info.set_next_free_cluster(cluster + 1);
485 fs_info.add_free_clusters(-1);
486 Ok(cluster)
487 }
488
489 pub fn read_status_flags(&self) -> io::Result<FsStatusFlags> {
491 let bpb_status = self.bpb.status_flags();
492 let fat_status = read_fat_flags(&mut self.fat_slice(), self.fat_type)?;
493 Ok(FsStatusFlags {
494 dirty: bpb_status.dirty || fat_status.dirty,
495 io_error: bpb_status.io_error || fat_status.io_error,
496 })
497 }
498
499 pub fn stats(&self) -> io::Result<FileSystemStats> {
504 let free_clusters_option = self.fs_info.borrow().free_cluster_count;
505 let free_clusters = match free_clusters_option {
506 Some(n) => n,
507 _ => self.recalc_free_clusters()?,
508 };
509 Ok(FileSystemStats {
510 sector_size: self.bpb.bytes_per_sector,
511 cluster_size: self.cluster_size(),
512 total_clusters: self.total_clusters,
513 free_clusters,
514 })
515 }
516
517 fn recalc_free_clusters(&self) -> io::Result<u32> {
519 let mut fat = self.fat_slice();
520 let free_cluster_count = count_free_clusters(&mut fat, self.fat_type, self.total_clusters)?;
521 self.fs_info.borrow_mut().set_free_cluster_count(free_cluster_count);
522 Ok(free_cluster_count)
523 }
524
525 pub fn unmount(self) -> io::Result<()> {
529 self.flush()
530 }
531
532 pub fn flush(&self) -> io::Result<()> {
534 self.flush_fs_info()?;
535 self.set_dirty_flag(false)?;
536 self.disk.borrow_mut().flush()?;
537 Ok(())
538 }
539
540 pub fn is_dirty(&self) -> bool {
545 self.current_status_flags.get().dirty()
546 }
547
548 fn flush_fs_info(&self) -> io::Result<()> {
549 let mut fs_info = self.fs_info.borrow_mut();
550 if self.fat_type == FatType::Fat32 && fs_info.dirty {
551 let mut disk = self.disk.borrow_mut();
552 disk.seek(SeekFrom::Start(self.offset_from_sector(self.bpb.fs_info_sector as u32)))?;
553 fs_info.serialize(&mut *disk)?;
554 fs_info.dirty = false;
555 }
556 Ok(())
557 }
558
559 pub(crate) fn set_dirty_flag(&self, dirty: bool) -> io::Result<()> {
560 let mut flags = self.bpb.status_flags();
562 flags.dirty |= dirty;
563 let current_flags = self.current_status_flags.get();
565 if flags == current_flags {
566 return Ok(());
568 }
569 let encoded = flags.encode();
570 let offset = if self.fat_type() == FatType::Fat32 { 0x041 } else { 0x025 };
573 let mut disk = self.disk.borrow_mut();
574 disk.seek(io::SeekFrom::Start(offset))?;
575 disk.write_u8(encoded)?;
576 self.current_status_flags.set(flags);
577 Ok(())
578 }
579
580 pub fn root_dir<'a>(&'a self) -> Dir<'a, IO, TP, OCC> {
582 trace!("root_dir");
583 let root_rdr = {
584 match self.fat_type {
585 FatType::Fat12 | FatType::Fat16 => DirRawStream::Root(DiskSlice::from_sectors(
586 self.first_data_sector - self.root_dir_sectors,
587 self.root_dir_sectors,
588 1,
589 &self.bpb,
590 FsIoAdapter { fs: self },
591 )),
592 _ => DirRawStream::File(Some(File::new(
593 Some(self.bpb.root_dir_first_cluster),
594 None,
595 self,
596 ))),
597 }
598 };
599 Dir::new(root_rdr, self, true)
600 }
601
602 pub(crate) fn begin_transaction(&self) -> Option<Transaction<'_, IO, TP, OCC>> {
603 if self.disk.borrow_mut().begin_transaction() {
604 Some(Transaction::new(self))
605 } else {
606 None
607 }
608 }
609
610 pub(crate) fn commit(&self, mut transaction: Transaction<'_, IO, TP, OCC>) -> io::Result<()> {
611 transaction.active = false;
612 self.disk.borrow_mut().commit()
613 }
614}
615
616impl<IO: ReadWriteSeek, TP, OCC: OemCpConverter> FileSystem<IO, TP, OCC> {
617 #[cfg(feature = "alloc")]
623 pub fn volume_label(&self) -> String {
624 let volume_label_iter = self.volume_label_as_bytes().iter().cloned();
626 let char_iter = volume_label_iter.map(|c| self.options.oem_cp_converter.decode(c));
627 String::from_iter(char_iter)
629 }
630}
631
632impl<IO: ReadWriteSeek, TP: TimeProvider, OCC: OemCpConverter> FileSystem<IO, TP, OCC> {
633 #[cfg(feature = "alloc")]
637 pub fn read_volume_label_from_root_dir(&self) -> io::Result<Option<String>> {
638 let volume_label_opt = self.read_volume_label_from_root_dir_as_bytes()?;
641 if let Some(volume_label) = volume_label_opt {
642 let len =
644 volume_label.iter().rposition(|b| *b != SFN_PADDING).map(|p| p + 1).unwrap_or(0);
645 let label_slice = &volume_label[..len];
646 let volume_label_iter = label_slice.iter().cloned();
648 let char_iter = volume_label_iter.map(|c| self.options.oem_cp_converter.decode(c));
649 Ok(Some(String::from_iter(char_iter)))
651 } else {
652 Ok(None)
653 }
654 }
655
656 pub fn read_volume_label_from_root_dir_as_bytes(&self) -> io::Result<Option<[u8; SFN_SIZE]>> {
661 let entry_opt = self.root_dir().find_volume_entry()?;
662 Ok(entry_opt.map(|e| *e.raw_short_name()))
663 }
664}
665
666impl<IO: ReadWriteSeek, TP, OCC> Drop for FileSystem<IO, TP, OCC> {
668 fn drop(&mut self) {
669 if let Err(err) = self.flush() {
670 error!("unmount failed {}", err);
671 }
672 }
673}
674
675pub(crate) struct FsIoAdapter<'a, IO: ReadWriteSeek, TP, OCC> {
676 fs: &'a FileSystem<IO, TP, OCC>,
677}
678
679impl<IO: ReadWriteSeek, TP, OCC> Read for FsIoAdapter<'_, IO, TP, OCC> {
680 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
681 self.fs.disk.borrow_mut().read(buf)
682 }
683}
684
685impl<IO: ReadWriteSeek, TP, OCC> Write for FsIoAdapter<'_, IO, TP, OCC> {
686 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
687 let size = self.fs.disk.borrow_mut().write(buf)?;
688 if size > 0 {
689 self.fs.set_dirty_flag(true)?;
690 }
691 Ok(size)
692 }
693
694 fn flush(&mut self) -> io::Result<()> {
695 self.fs.disk.borrow_mut().flush()
696 }
697}
698
699impl<IO: ReadWriteSeek, TP, OCC> Seek for FsIoAdapter<'_, IO, TP, OCC> {
700 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
701 self.fs.disk.borrow_mut().seek(pos)
702 }
703}
704
705impl<IO: ReadWriteSeek, TP, OCC> Clone for FsIoAdapter<'_, IO, TP, OCC> {
707 fn clone(&self) -> Self {
708 FsIoAdapter { fs: self.fs }
709 }
710}
711
712fn fat_slice<IO: ReadWriteSeek>(io: IO, bpb: &BiosParameterBlock) -> DiskSlice<IO> {
713 let sectors_per_fat = bpb.sectors_per_fat();
714 let mirroring_enabled = bpb.mirroring_enabled();
715 let (fat_first_sector, mirrors) = if mirroring_enabled {
716 (bpb.reserved_sectors(), bpb.fats)
717 } else {
718 let active_fat = bpb.active_fat() as u32;
719 let fat_first_sector = (bpb.reserved_sectors()) + active_fat * sectors_per_fat;
720 (fat_first_sector, 1)
721 };
722 DiskSlice::from_sectors(fat_first_sector, sectors_per_fat, mirrors, bpb, io)
723}
724
725pub(crate) struct DiskSlice<IO> {
726 begin: u64,
727 size: u64,
728 offset: u64,
729 mirrors: u8,
730 inner: IO,
731}
732
733impl<IO> DiskSlice<IO> {
734 pub(crate) fn new(begin: u64, size: u64, mirrors: u8, inner: IO) -> Self {
735 DiskSlice { begin, size, mirrors, inner, offset: 0 }
736 }
737
738 fn from_sectors(
739 first_sector: u32,
740 sector_count: u32,
741 mirrors: u8,
742 bpb: &BiosParameterBlock,
743 inner: IO,
744 ) -> Self {
745 Self::new(
746 bpb.bytes_from_sectors(first_sector),
747 bpb.bytes_from_sectors(sector_count),
748 mirrors,
749 inner,
750 )
751 }
752
753 pub(crate) fn abs_pos(&self) -> u64 {
754 self.begin + self.offset
755 }
756}
757
758impl<IO: Clone> Clone for DiskSlice<IO> {
760 fn clone(&self) -> Self {
761 DiskSlice {
762 begin: self.begin,
763 size: self.size,
764 offset: self.offset,
765 mirrors: self.mirrors,
766 inner: self.inner.clone(),
767 }
768 }
769}
770
771impl<IO: Read + Seek> Read for DiskSlice<IO> {
772 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
773 let offset = self.begin + self.offset;
774 let read_size = cmp::min((self.size - self.offset) as usize, buf.len());
775 self.inner.seek(SeekFrom::Start(offset))?;
776 let size = self.inner.read(&mut buf[..read_size])?;
777 self.offset += size as u64;
778 Ok(size)
779 }
780}
781
782impl<IO: Write + Seek> Write for DiskSlice<IO> {
783 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
784 let offset = self.begin + self.offset;
785 let write_size = cmp::min((self.size - self.offset) as usize, buf.len());
786 if write_size == 0 {
787 return Ok(0);
788 }
789 for i in 0..self.mirrors {
791 self.inner.seek(SeekFrom::Start(offset + i as u64 * self.size))?;
792 self.inner.write_all(&buf[..write_size])?;
793 }
794 self.offset += write_size as u64;
795 Ok(write_size)
796 }
797
798 fn flush(&mut self) -> io::Result<()> {
799 self.inner.flush()
800 }
801}
802
803impl<IO> Seek for DiskSlice<IO> {
804 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
805 let new_offset = match pos {
806 SeekFrom::Current(x) => self.offset as i64 + x,
807 SeekFrom::Start(x) => x as i64,
808 SeekFrom::End(x) => self.size as i64 + x,
809 };
810 if new_offset < 0 || new_offset as u64 > self.size {
811 Err(io::Error::new(ErrorKind::InvalidInput, "Seek to a negative offset"))
812 } else {
813 self.offset = new_offset as u64;
814 Ok(self.offset)
815 }
816 }
817}
818
819pub trait OemCpConverter: Debug {
824 fn decode(&self, oem_char: u8) -> char;
825 fn encode(&self, uni_char: char) -> Option<u8>;
826}
827
828#[derive(Debug, Clone, Copy)]
830pub struct LossyOemCpConverter {
831 _dummy: (),
832}
833
834impl LossyOemCpConverter {
835 pub fn new() -> Self {
836 Self { _dummy: () }
837 }
838}
839
840impl OemCpConverter for LossyOemCpConverter {
841 fn decode(&self, oem_char: u8) -> char {
842 if oem_char <= 0x7F {
843 oem_char as char
844 } else {
845 '\u{FFFD}'
846 }
847 }
848 fn encode(&self, uni_char: char) -> Option<u8> {
849 if uni_char <= '\x7F' {
850 Some(uni_char as u8)
851 } else {
852 None
853 }
854 }
855}
856
857pub(crate) fn write_zeros<IO: ReadWriteSeek>(mut disk: IO, mut len: u64) -> io::Result<()> {
858 const ZEROS: [u8; 512] = [0u8; 512];
859 while len > 0 {
860 let write_size = cmp::min(len, ZEROS.len() as u64) as usize;
861 disk.write_all(&ZEROS[..write_size])?;
862 len -= write_size as u64;
863 }
864 Ok(())
865}
866
867fn write_zeros_until_end_of_sector<IO: ReadWriteSeek>(
868 mut disk: IO,
869 bytes_per_sector: u16,
870) -> io::Result<()> {
871 let pos = disk.seek(SeekFrom::Current(0))?;
872 let total_bytes_to_write = bytes_per_sector as u64 - (pos % bytes_per_sector as u64);
873 if total_bytes_to_write != bytes_per_sector as u64 {
874 write_zeros(disk, total_bytes_to_write)?;
875 }
876 Ok(())
877}
878
879#[derive(Default, Debug, Clone)]
884pub struct FormatVolumeOptions {
885 pub(crate) bytes_per_sector: Option<u16>,
886 pub(crate) total_sectors: Option<u32>,
887 pub(crate) bytes_per_cluster: Option<u32>,
888 pub(crate) fat_type: Option<FatType>,
889 pub(crate) max_root_dir_entries: Option<u16>,
890 pub(crate) fats: Option<u8>,
891 pub(crate) media: Option<u8>,
892 pub(crate) sectors_per_track: Option<u16>,
893 pub(crate) heads: Option<u16>,
894 pub(crate) drive_num: Option<u8>,
895 pub(crate) volume_id: Option<u32>,
896 pub(crate) volume_label: Option<[u8; SFN_SIZE]>,
897}
898
899impl FormatVolumeOptions {
900 pub fn new() -> Self {
905 FormatVolumeOptions { ..Default::default() }
906 }
907
908 pub fn bytes_per_cluster(mut self, bytes_per_cluster: u32) -> Self {
914 assert!(
915 bytes_per_cluster.count_ones() == 1 && bytes_per_cluster >= 512,
916 "Invalid bytes_per_cluster"
917 );
918 self.bytes_per_cluster = Some(bytes_per_cluster);
919 self
920 }
921
922 pub fn fat_type(mut self, fat_type: FatType) -> Self {
929 self.fat_type = Some(fat_type);
930 self
931 }
932
933 pub fn bytes_per_sector(mut self, bytes_per_sector: u16) -> Self {
938 assert!(
939 bytes_per_sector.count_ones() == 1 && bytes_per_sector >= 512,
940 "Invalid bytes_per_sector"
941 );
942 self.bytes_per_sector = Some(bytes_per_sector);
943 self
944 }
945
946 pub fn total_sectors(mut self, total_sectors: u32) -> Self {
950 self.total_sectors = Some(total_sectors);
951 self
952 }
953
954 pub fn max_root_dir_entries(mut self, max_root_dir_entries: u16) -> Self {
961 self.max_root_dir_entries = Some(max_root_dir_entries);
962 self
963 }
964
965 pub fn fats(mut self, fats: u8) -> Self {
970 assert!(fats >= 1 && fats <= 2, "Invalid number of FATs");
971 self.fats = Some(fats);
972 self
973 }
974
975 pub fn media(mut self, media: u8) -> Self {
979 self.media = Some(media);
980 self
981 }
982
983 pub fn sectors_per_track(mut self, sectors_per_track: u16) -> Self {
987 self.sectors_per_track = Some(sectors_per_track);
988 self
989 }
990
991 pub fn heads(mut self, heads: u16) -> Self {
995 self.heads = Some(heads);
996 self
997 }
998
999 pub fn drive_num(mut self, drive_num: u8) -> Self {
1003 self.drive_num = Some(drive_num);
1004 self
1005 }
1006
1007 pub fn volume_id(mut self, volume_id: u32) -> Self {
1011 self.volume_id = Some(volume_id);
1012 self
1013 }
1014
1015 pub fn volume_label(mut self, volume_label: [u8; SFN_SIZE]) -> Self {
1019 self.volume_label = Some(volume_label);
1020 self
1021 }
1022}
1023
1024pub fn format_volume<IO: ReadWriteSeek>(
1033 mut disk: IO,
1034 options: FormatVolumeOptions,
1035) -> io::Result<()> {
1036 trace!("format_volume");
1037 debug_assert!(disk.seek(SeekFrom::Current(0))? == 0);
1038
1039 let bytes_per_sector = options.bytes_per_sector.unwrap_or(512);
1040 let total_sectors = if let Some(total_sectors) = options.total_sectors {
1041 total_sectors
1042 } else {
1043 let total_bytes: u64 = disk.seek(SeekFrom::End(0))?;
1044 let total_sectors_64 = total_bytes / u64::from(bytes_per_sector);
1045 disk.seek(SeekFrom::Start(0))?;
1046 if total_sectors_64 > u64::from(u32::MAX) {
1047 return Err(Error::new(ErrorKind::Other, FatfsError::TooManySectors));
1048 }
1049 total_sectors_64 as u32
1050 };
1051
1052 let (boot, fat_type) = format_boot_sector(&options, total_sectors, bytes_per_sector)?;
1054 boot.validate()?;
1055 boot.serialize(&mut disk)?;
1056 let bytes_per_sector = boot.bpb.bytes_per_sector;
1058 write_zeros_until_end_of_sector(&mut disk, bytes_per_sector)?;
1059
1060 if boot.bpb.is_fat32() {
1061 let fs_info_sector =
1063 FsInfoSector { free_cluster_count: None, next_free_cluster: None, dirty: false };
1064 disk.seek(SeekFrom::Start(boot.bpb.bytes_from_sectors(boot.bpb.fs_info_sector())))?;
1065 fs_info_sector.serialize(&mut disk)?;
1066 write_zeros_until_end_of_sector(&mut disk, bytes_per_sector)?;
1067
1068 disk.seek(SeekFrom::Start(boot.bpb.bytes_from_sectors(boot.bpb.backup_boot_sector())))?;
1070 boot.serialize(&mut disk)?;
1071 write_zeros_until_end_of_sector(&mut disk, bytes_per_sector)?;
1072 }
1073
1074 let reserved_sectors = boot.bpb.reserved_sectors();
1076 let fat_pos = boot.bpb.bytes_from_sectors(reserved_sectors);
1077 let sectors_per_all_fats = boot.bpb.sectors_per_all_fats();
1078 disk.seek(SeekFrom::Start(fat_pos))?;
1079 write_zeros(&mut disk, boot.bpb.bytes_from_sectors(sectors_per_all_fats))?;
1080 {
1081 let mut fat_slice = fat_slice(&mut disk, &boot.bpb);
1082 let sectors_per_fat = boot.bpb.sectors_per_fat();
1083 let bytes_per_fat = boot.bpb.bytes_from_sectors(sectors_per_fat);
1084 format_fat(
1085 &mut fat_slice,
1086 fat_type,
1087 boot.bpb.media,
1088 bytes_per_fat,
1089 boot.bpb.total_clusters(),
1090 )?;
1091 }
1092
1093 let root_dir_first_sector = reserved_sectors + sectors_per_all_fats;
1095 let root_dir_sectors = boot.bpb.root_dir_sectors();
1096 let root_dir_pos = boot.bpb.bytes_from_sectors(root_dir_first_sector);
1097 disk.seek(SeekFrom::Start(root_dir_pos))?;
1098 write_zeros(&mut disk, boot.bpb.bytes_from_sectors(root_dir_sectors))?;
1099 if fat_type == FatType::Fat32 {
1100 let root_dir_first_cluster = {
1101 let mut fat_slice = fat_slice(&mut disk, &boot.bpb);
1102 alloc_cluster(&mut fat_slice, fat_type, None, None, 1)?
1103 };
1104 assert!(root_dir_first_cluster == boot.bpb.root_dir_first_cluster);
1105 let first_data_sector = reserved_sectors + sectors_per_all_fats + root_dir_sectors;
1106 let root_dir_first_sector = first_data_sector
1107 + boot.bpb.sectors_from_clusters(root_dir_first_cluster - RESERVED_FAT_ENTRIES)?;
1108 let root_dir_pos = boot.bpb.bytes_from_sectors(root_dir_first_sector);
1109 disk.seek(SeekFrom::Start(root_dir_pos))?;
1110 write_zeros(&mut disk, boot.bpb.cluster_size() as u64)?;
1111 }
1112
1113 disk.seek(SeekFrom::Start(0))?;
1116 trace!("format_volume end");
1117 Ok(())
1118}
1119
1120pub(crate) struct Transaction<'a, IO: ReadWriteSeek, TP, OCC> {
1121 fs: &'a FileSystem<IO, TP, OCC>,
1122 original_fs_info: FsInfoSector,
1123 active: bool,
1124}
1125
1126impl<'a, IO: ReadWriteSeek, TP, OCC> Transaction<'a, IO, TP, OCC> {
1127 fn new(fs: &'a FileSystem<IO, TP, OCC>) -> Self {
1128 Transaction { fs, original_fs_info: fs.fs_info.borrow_mut().clone(), active: true }
1129 }
1130}
1131
1132impl<IO: ReadWriteSeek, TP, OCC> Drop for Transaction<'_, IO, TP, OCC> {
1133 fn drop(&mut self) {
1134 if self.active {
1135 self.fs.disk.borrow_mut().revert();
1136 *self.fs.fs_info.borrow_mut() = self.original_fs_info.clone();
1137 self.active = false;
1138 }
1139 }
1140}