22use alloc:: string:: String ;
33use core:: borrow:: BorrowMut ;
44use core:: cell:: { Cell , RefCell } ;
5- use core:: char;
5+ use core:: mem:: ManuallyDrop ;
6+ use core:: { char, ptr} ;
67use core:: cmp;
78use core:: convert:: TryFrom ;
89use core:: fmt:: Debug ;
@@ -256,7 +257,6 @@ impl FsOptions<DefaultTimeProvider, LossyOemCpConverter> {
256257
257258impl < TP : TimeProvider , OCC : OemCpConverter > FsOptions < TP , OCC > {
258259 /// If enabled accessed date field in directory entry is updated when reading or writing a file.
259- #[ must_use]
260260 pub fn update_accessed_date ( mut self , enabled : bool ) -> Self {
261261 self . update_accessed_date = enabled;
262262 self
@@ -436,10 +436,6 @@ impl<IO: Read + Write + Seek, TP, OCC> FileSystem<IO, TP, OCC> {
436436 & full_label_slice[ ..len]
437437 }
438438
439- fn offset_from_sector ( & self , sector : u32 ) -> u64 {
440- self . bpb . bytes_from_sectors ( sector)
441- }
442-
443439 fn sector_from_cluster ( & self , cluster : u32 ) -> u32 {
444440 self . first_data_sector + self . bpb . sectors_from_clusters ( cluster - RESERVED_FAT_ENTRIES )
445441 }
@@ -449,7 +445,7 @@ impl<IO: Read + Write + Seek, TP, OCC> FileSystem<IO, TP, OCC> {
449445 }
450446
451447 pub ( crate ) fn offset_from_cluster ( & self , cluster : u32 ) -> u64 {
452- self . offset_from_sector ( self . sector_from_cluster ( cluster) )
448+ self . bpb . bytes_from_sectors ( self . sector_from_cluster ( cluster) )
453449 }
454450
455451 pub ( crate ) fn bytes_from_clusters ( & self , clusters : u32 ) -> u64 {
@@ -551,32 +547,37 @@ impl<IO: Read + Write + Seek, TP, OCC> FileSystem<IO, TP, OCC> {
551547 Ok ( free_cluster_count)
552548 }
553549
554- /// Unmounts the filesystem.
555- ///
556- /// Updates the FS Information Sector if needed.
550+ /// Updates the FS Information Sector if needed and unmounts the filesystem.
557551 ///
558552 /// # Errors
559553 ///
560554 /// `Error::Io` will be returned if the underlying storage object returned an I/O error.
561- pub fn unmount ( self ) -> Result < ( ) , Error < IO :: Error > > {
562- self . unmount_internal ( )
563- }
555+ pub fn unmount ( mut self ) -> Result < IO , Error < IO :: Error > > {
556+ self . flush ( ) ?;
564557
565- fn unmount_internal ( & self ) -> Result < ( ) , Error < IO :: Error > > {
566- self . flush_fs_info ( ) ?;
567- self . set_dirty_flag ( false ) ?;
568- Ok ( ( ) )
558+ let mut fs = ManuallyDrop :: new ( self ) ;
559+ // SAFETY: The `disk` field is only dropped once.
560+ let mut disk = unsafe { ptr:: read ( fs. disk . get_mut ( ) ) } ;
561+ disk. seek ( SeekFrom :: Start ( 0 ) ) ?;
562+ Ok ( disk)
569563 }
570564
571- fn flush_fs_info ( & self ) -> Result < ( ) , Error < IO :: Error > > {
572- let mut fs_info = self . fs_info . borrow_mut ( ) ;
565+ /// Updates the FS information sector if needed.
566+ ///
567+ /// # Errors
568+ ///
569+ /// `Error::Io` will be returned if the underlying storage object returned an I/O error.
570+ pub fn flush ( & mut self ) -> Result < ( ) , Error < IO :: Error > > {
571+ let fs_info = self . fs_info . get_mut ( ) ;
573572 if self . fat_type == FatType :: Fat32 && fs_info. dirty {
574- let mut disk = self . disk . borrow_mut ( ) ;
575- let fs_info_sector_offset = self . offset_from_sector ( u32 :: from ( self . bpb . fs_info_sector ) ) ;
573+ let fs_info_sector_offset = self . bpb . bytes_from_sectors ( self . bpb . fs_info_sector . into ( ) ) ;
574+ let disk = self . disk . get_mut ( ) ;
576575 disk. seek ( SeekFrom :: Start ( fs_info_sector_offset) ) ?;
577- fs_info. serialize ( & mut * disk) ?;
576+ fs_info. serialize ( disk) ?;
578577 fs_info. dirty = false ;
579578 }
579+
580+ self . set_dirty_flag ( false ) ?;
580581 Ok ( ( ) )
581582 }
582583
@@ -685,7 +686,7 @@ impl<IO: ReadWriteSeek, TP: TimeProvider, OCC: OemCpConverter> FileSystem<IO, TP
685686/// `Drop` implementation tries to unmount the filesystem when dropping.
686687impl < IO : ReadWriteSeek , TP , OCC > Drop for FileSystem < IO , TP , OCC > {
687688 fn drop ( & mut self ) {
688- if let Err ( err) = self . unmount_internal ( ) {
689+ if let Err ( err) = self . flush ( ) {
689690 error ! ( "unmount failed {:?}" , err) ;
690691 }
691692 }
0 commit comments