diff --git a/src/dir.rs b/src/dir.rs index 5417c5b..e39d98d 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -225,7 +225,15 @@ impl DirEntryData { fn deserialize(rdr: &mut Read) -> io::Result { let mut name = [0; 11]; - rdr.read_exact(&mut name)?; + match rdr.read_exact(&mut name) { + Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => { + return Ok(DirEntryData::File(DirFileEntryData { + ..Default::default() + })); + } + Err(err) => return Err(err), + _ => {}, + } let attrs = FileAttributes::from_bits_truncate(rdr.read_u8()?); if attrs & FileAttributes::LFN == FileAttributes::LFN { let mut data = DirLfnEntryData { @@ -617,8 +625,14 @@ impl <'a, 'b> Dir<'a, 'b> { let mut num_free = 0; let mut i = 0; loop { - let data = DirEntryData::deserialize(&mut stream)?; - if data.is_free() { + let raw_entry = DirEntryData::deserialize(&mut stream)?; + if raw_entry.is_end() { + if num_free == 0 { + first_free = i; + } + stream.seek(io::SeekFrom::Start(first_free as u64 * DIR_ENTRY_SIZE))?; + return Ok(stream); + } else if raw_entry.is_free() { if num_free == 0 { first_free = i; } @@ -627,13 +641,6 @@ impl <'a, 'b> Dir<'a, 'b> { stream.seek(io::SeekFrom::Start(first_free as u64 * DIR_ENTRY_SIZE))?; return Ok(stream); } - } else if data.is_end() { - if num_free == 0 { - first_free = i; - } - stream.seek(io::SeekFrom::Start(first_free as u64 * DIR_ENTRY_SIZE))?; - // FIXME: make sure new allocated cluster is zeroed - return Ok(stream); } else { num_free = 0; } @@ -728,16 +735,12 @@ pub struct DirIter<'a, 'b: 'a> { } impl <'a, 'b> DirIter<'a, 'b> { - fn read_dir_entry_raw_data(&mut self) -> io::Result { - DirEntryData::deserialize(&mut self.stream) - } - fn read_dir_entry(&mut self) -> io::Result>> { let mut lfn_buf = LongNameBuilder::new(); let mut offset = self.stream.seek(SeekFrom::Current(0))?; let mut begin_offset = offset; loop { - let raw_entry = self.read_dir_entry_raw_data()?; + let raw_entry = DirEntryData::deserialize(&mut self.stream)?; offset += DIR_ENTRY_SIZE; match raw_entry { DirEntryData::File(data) => { diff --git a/src/file.rs b/src/file.rs index 81fcd37..0ad246c 100644 --- a/src/file.rs +++ b/src/file.rs @@ -217,9 +217,21 @@ impl<'a, 'b> Write for File<'a, 'b> { None => { // end of chain reached - allocate new cluster let new_cluster = self.fs.alloc_cluster(self.current_cluster)?; + trace!("allocated cluser {}", new_cluster); if self.first_cluster.is_none() { self.set_first_cluster(new_cluster); } + if self.entry.clone().map_or(true, |e| e.data.size().is_none()) { + // zero new directory cluster + trace!("zeroing directory cluser {}", 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 }, } diff --git a/tests/write.rs b/tests/write.rs index 433e08e..6908785 100644 --- a/tests/write.rs +++ b/tests/write.rs @@ -125,7 +125,7 @@ fn test_remove_fat32() { fn test_create_file(fs: FileSystem) { let mut root_dir = fs.root_dir(); - let dir = root_dir.open_dir("very/long/path").unwrap(); + let mut dir = root_dir.open_dir("very/long/path").unwrap(); let mut names = dir.iter().map(|r| r.unwrap().file_name()).collect::>(); assert_eq!(names, [".", "..", "test.txt"]); { @@ -140,6 +140,13 @@ fn test_create_file(fs: FileSystem) { file.read_to_string(&mut content).unwrap(); assert_eq!(&content, &TEST_STR); } + // Create enough entries to allocate next cluster + for i in 0..512/32 { + let name = format!("test{}", i); + dir.create_file(&name).unwrap(); + } + names = dir.iter().map(|r| r.unwrap().file_name()).collect::>(); + assert_eq!(names.len(), 4 + 512/32); } #[test]