diff --git a/src/fs.rs b/src/fs.rs index b2b165c..68be2a8 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -410,7 +410,7 @@ impl FileSystem { if options.ignore_dirty_flag { warn!("BPB is dirty, clearing dirty flag."); bpb_status_flags.dirty = false; - write_bpb_status_flags(&mut disk, fat_type, bpb_status_flags)?; + Self::write_bpb_status_flags(&mut disk, fat_type, bpb_status_flags)?; bpb.set_status_flags(bpb_status_flags); } else { return Err(Error::DirtyFileSystem); @@ -590,9 +590,7 @@ impl FileSystem { Ok(free_cluster_count) } - /// Unmounts the filesystem. - /// - /// Updates the FS Information Sector if needed. + /// Updates the FS Information Sector if needed and unmounts the filesystem. /// /// # Errors /// @@ -606,6 +604,11 @@ impl FileSystem { Ok(disk) } + /// Updates the FS information sector if needed. + /// + /// # Errors + /// + /// `Error::Io` will be returned if the underlying storage object returned an I/O error. pub fn flush(&mut self) -> Result<(), Error> { self.flush_fs_info()?; self.set_dirty_flag(false)?; @@ -624,10 +627,40 @@ impl FileSystem { Ok(()) } + fn write_bpb_status_flags( + disk: &mut IO, + fat_type: FatType, + status_flags: FsStatusFlags, + ) -> Result<(), Error> { + let encoded = status_flags.encode(); + + // Note: only one field is written to avoid rewriting entire boot-sector which could be dangerous + // Compute reserver_1 field offset and write new flags + let offset = if fat_type == FatType::Fat32 { 0x041 } else { 0x025 }; + + disk.seek(io::SeekFrom::Start(offset))?; + disk.write_u8(encoded)?; + + Ok(()) + } + #[inline] pub(crate) fn set_dirty_flag(&self, dirty: bool) -> Result<(), Error> { let mut disk = self.disk.borrow_mut(); - set_dirty_flag(&mut *disk, self.fat_type(), &self.current_status_flags, dirty) + + let mut status_flags = self.current_status_flags.get(); + + if status_flags.dirty == dirty { + // Dirty flag did not change. + return Ok(()); + } + + status_flags.dirty = dirty; + + Self::write_bpb_status_flags(&mut *disk, self.fat_type(), status_flags)?; + self.current_status_flags.set(status_flags); + + Ok(()) } /// Returns a root directory object allowing for futher penetration of a filesystem structure. @@ -757,44 +790,6 @@ impl Clone for FsIoAdapter<'_, IO, TP, OCC> { } } -fn set_dirty_flag( - disk: &mut IO, - fat_type: FatType, - current_status_flags: &Cell, - dirty: bool, -) -> Result<(), Error> { - let mut status_flags = current_status_flags.get(); - - if status_flags.dirty == dirty { - // Dirty flag did not change. - return Ok(()); - } - - status_flags.dirty = dirty; - - write_bpb_status_flags(disk, fat_type, status_flags)?; - current_status_flags.set(status_flags); - - Ok(()) -} - -fn write_bpb_status_flags( - disk: &mut IO, - fat_type: FatType, - status_flags: FsStatusFlags, -) -> Result<(), Error> { - let encoded = status_flags.encode(); - - // Note: only one field is written to avoid rewriting entire boot-sector which could be dangerous - // Compute reserver_1 field offset and write new flags - let offset = if fat_type == FatType::Fat32 { 0x041 } else { 0x025 }; - - disk.seek(io::SeekFrom::Start(offset))?; - disk.write_u8(encoded)?; - - Ok(()) -} - fn fat_slice, E, S: ReadWriteSeek>(io: B, bpb: &BiosParameterBlock) -> DiskSlice { let sectors_per_fat = bpb.sectors_per_fat(); let mirroring_enabled = bpb.mirroring_enabled();