fix: clear directory returned from create_dir method

Previous implementation did not zero allocated cluster so created directory
could have garbage contents.
Bug exists in code since version 0.2 and all code using create_dir is
affected.
This commit also improves tests of volume formatting so a dirty partition
is used allowing to detect bugs like this.
This commit is contained in:
Rafał Harabień 2018-12-08 19:33:56 +01:00
parent 647ca9252a
commit cf3256bfda
4 changed files with 15 additions and 18 deletions

View File

@ -236,7 +236,7 @@ impl<'a, T: ReadWriteSeek + 'a> Dir<'a, T> {
// directory does not exist - create it // directory does not exist - create it
DirEntryOrShortName::ShortName(short_name) => { DirEntryOrShortName::ShortName(short_name) => {
// alloc cluster for directory data // alloc cluster for directory data
let cluster = self.fs.alloc_cluster(None)?; let cluster = self.fs.alloc_cluster(None, true)?;
// create entry in parent directory // create entry in parent directory
let sfn_entry = self.create_sfn_entry(short_name, FileAttributes::DIRECTORY, Some(cluster)); let sfn_entry = self.create_sfn_entry(short_name, FileAttributes::DIRECTORY, Some(cluster));
let entry = self.write_entry(name, sfn_entry)?; let entry = self.write_entry(name, sfn_entry)?;

View File

@ -261,22 +261,11 @@ impl<'a, T: ReadWriteSeek> Write for File<'a, T> {
Some(n) => n, Some(n) => n,
None => { None => {
// end of chain reached - allocate new cluster // end of chain reached - allocate new cluster
let new_cluster = self.fs.alloc_cluster(self.current_cluster)?; let new_cluster = self.fs.alloc_cluster(self.current_cluster, self.is_dir())?;
trace!("allocated cluser {}", new_cluster); trace!("allocated cluser {}", new_cluster);
if self.first_cluster.is_none() { if self.first_cluster.is_none() {
self.set_first_cluster(new_cluster); self.set_first_cluster(new_cluster);
} }
if self.is_dir() {
// zero new directory cluster
trace!("zeroing directory cluster {}", new_cluster);
let abs_pos = self.fs.offset_from_cluster(new_cluster);
let mut disk = self.fs.disk.borrow_mut();
disk.seek(SeekFrom::Start(abs_pos))?;
for _ in 0..cluster_size / 32 {
let zero = [0u8; 32];
disk.write(&zero)?;
}
}
new_cluster new_cluster
}, },
} }

View File

@ -472,11 +472,18 @@ impl<T: ReadWriteSeek> FileSystem<T> {
Ok(()) Ok(())
} }
pub(crate) fn alloc_cluster(&self, prev_cluster: Option<u32>) -> io::Result<u32> { pub(crate) fn alloc_cluster(&self, prev_cluster: Option<u32>, zero: bool) -> io::Result<u32> {
trace!("alloc_cluster"); trace!("alloc_cluster");
let hint = self.fs_info.borrow().next_free_cluster; let hint = self.fs_info.borrow().next_free_cluster;
let mut fat = self.fat_slice(); let cluster = {
let cluster = alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint, self.total_clusters)?; let mut fat = self.fat_slice();
alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint, self.total_clusters)?
};
if zero {
let mut disk = self.disk.borrow_mut();
disk.seek(SeekFrom::Start(self.offset_from_cluster(cluster)))?;
write_zeros(&mut *disk, self.cluster_size() as usize)?;
}
let mut fs_info = self.fs_info.borrow_mut(); let mut fs_info = self.fs_info.borrow_mut();
fs_info.set_next_free_cluster(cluster + 1); fs_info.set_next_free_cluster(cluster + 1);
fs_info.add_free_clusters(-1); fs_info.add_free_clusters(-1);

View File

@ -50,7 +50,8 @@ fn basic_fs_test(fs: &FileSystem) {
fn test_format_fs(opts: fatfs::FormatVolumeOptions, total_bytes: u64) -> FileSystem { fn test_format_fs(opts: fatfs::FormatVolumeOptions, total_bytes: u64) -> FileSystem {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
let storage_vec: Vec<u8> = Vec::with_capacity(total_bytes as usize); // Init storage to 0xD1 bytes (value has been choosen to be parsed as normal file)
let storage_vec: Vec<u8> = vec![0xD1u8; total_bytes as usize];
let storage_cur = io::Cursor::new(storage_vec); let storage_cur = io::Cursor::new(storage_vec);
let mut buffered_stream = BufStream::new(storage_cur); let mut buffered_stream = BufStream::new(storage_cur);
fatfs::format_volume(&mut buffered_stream, opts).expect("format volume"); fatfs::format_volume(&mut buffered_stream, opts).expect("format volume");
@ -86,7 +87,7 @@ fn test_format_50mb() {
#[test] #[test]
fn test_format_512mb() { fn test_format_512mb_512sec() {
let total_bytes = 2 * 1024 * MB; let total_bytes = 2 * 1024 * MB;
let opts = fatfs::FormatVolumeOptions::new((total_bytes / 512) as u32, 512); let opts = fatfs::FormatVolumeOptions::new((total_bytes / 512) as u32, 512);
let fs = test_format_fs(opts, total_bytes); let fs = test_format_fs(opts, total_bytes);