diff --git a/CHANGELOG.md b/CHANGELOG.md index 67cceab..d7d2d5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Changelog ========= +0.3.5 (not released yet) +------------------------ +Bug fixes: +* Fix file-system corruption when creating multiple directory entries in non-root directory (directory size must + be greater or equal to cluster size for corruption to happen) + 0.3.4 (2020-07-20) ------------------ Bug fixes: diff --git a/src/file.rs b/src/file.rs index 065c217..5b8051a 100644 --- a/src/file.rs +++ b/src/file.rs @@ -76,8 +76,15 @@ impl<'a, T: ReadWriteSeek> File<'a, T> { match self.current_cluster { Some(n) => { let cluster_size = self.fs.cluster_size(); - let offset_in_cluster = self.offset % cluster_size; - let offset_in_fs = self.fs.offset_from_cluster(n) + (offset_in_cluster as u64); + let offset_mod_cluster_size = self.offset % cluster_size; + let offset_in_cluster = if offset_mod_cluster_size == 0 { + // position points between clusters - we are returning previous cluster so + // offset must be set to the cluster size + cluster_size + } else { + offset_mod_cluster_size + }; + let offset_in_fs = self.fs.offset_from_cluster(n) + u64::from(offset_in_cluster); Some(offset_in_fs) }, None => None, diff --git a/tests/write.rs b/tests/write.rs index 71610ec..f4a09bb 100644 --- a/tests/write.rs +++ b/tests/write.rs @@ -349,3 +349,36 @@ fn test_dirty_flag_fat16() { fn test_dirty_flag_fat32() { call_with_tmp_img(&test_dirty_flag, FAT32_IMG, 7) } + +fn test_multiple_files_in_directory(fs: FileSystem) { + let dir = fs.root_dir().create_dir("/TMP").unwrap(); + for i in 0..8 { + let name = format!("T{}.TXT", i); + let mut file = dir.create_file(&name).unwrap(); + file.write_all(TEST_STR.as_bytes()).unwrap(); + file.flush().unwrap(); + + let file = dir.iter() + .map(|r| r.unwrap()) + .filter(|e| e.file_name() == name) + .next() + .unwrap(); + + assert_eq!(TEST_STR.len() as u64, file.len(), "Wrong file len on iteration {}", i); + } +} + +#[test] +fn test_multiple_files_in_directory_fat12() { + call_with_fs(&test_multiple_files_in_directory, FAT12_IMG, 8) +} + +#[test] +fn test_multiple_files_in_directory_fat16() { + call_with_fs(&test_multiple_files_in_directory, FAT16_IMG, 8) +} + +#[test] +fn test_multiple_files_in_directory_fat32() { + call_with_fs(&test_multiple_files_in_directory, FAT32_IMG, 8) +}