diff --git a/TODO.md b/TODO.md index 6389c20..732938d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ TODO ==== -* FsInfo sector handling * move file API * format volume API * better no_std support diff --git a/src/fs.rs b/src/fs.rs index bf7105f..acd5444 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -273,12 +273,14 @@ impl FsInfoSector { #[derive(Debug, Clone, Copy)] pub struct FsOptions { pub(crate) update_accessed_date: bool, + pub(crate) update_fs_info: bool, } impl FsOptions { pub fn new() -> Self { FsOptions { update_accessed_date: false, + update_fs_info: false, } } @@ -287,6 +289,12 @@ impl FsOptions { self.update_accessed_date = enabled; self } + + /// If enabled library updates FSInfo sector when unmounting + pub fn update_fs_info(mut self, enabled: bool) -> Self { + self.update_fs_info = enabled; + self + } } /// FAT filesystem statistics @@ -493,6 +501,35 @@ impl <'a> FileSystem<'a> { free_clusters, }) } + + /// Unmounts filesystem. Updates FSInfo sector if required in options. + pub fn unmount(self) -> io::Result<()> { + self.unmount_internal() + } + + fn unmount_internal(&self) -> io::Result<()> { + if self.options.update_fs_info { + self.flush_fs_info()?; + } + Ok(()) + } + + fn flush_fs_info(&self) -> io::Result<()> { + if self.fat_type == FatType::Fat32 { + let mut disk = self.disk.borrow_mut(); + disk.seek(SeekFrom::Start(self.bpb.fs_info_sector as u64 * 512))?; + self.fs_info.borrow().serialize(&mut *disk)?; + } + Ok(()) + } +} + +impl<'a> Drop for FileSystem<'a> { + fn drop(&mut self) { + if let Err(err) = self.unmount_internal() { + error!("unmount failed {}", err); + } + } } #[derive(Clone)] diff --git a/tests/write.rs b/tests/write.rs index 984c93b..b199d17 100644 --- a/tests/write.rs +++ b/tests/write.rs @@ -24,7 +24,7 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str, test_seq: u32) { { let file = fs::OpenOptions::new().read(true).write(true).open(&tmp_path).unwrap(); let mut buf_file = BufStream::new(file); - let options = FsOptions::new().update_accessed_date(true); + let options = FsOptions::new().update_accessed_date(true).update_fs_info(true); let fs = FileSystem::new(&mut buf_file, options).unwrap(); f(fs); }