Zero new directory clusters after allocation.

This commit is contained in:
Rafał Harabień 2017-10-27 15:03:54 +02:00
parent 9ec23f1234
commit 21bd2a0e8d
3 changed files with 38 additions and 16 deletions

View File

@ -225,7 +225,15 @@ impl DirEntryData {
fn deserialize(rdr: &mut Read) -> io::Result<DirEntryData> { fn deserialize(rdr: &mut Read) -> io::Result<DirEntryData> {
let mut name = [0; 11]; 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()?); let attrs = FileAttributes::from_bits_truncate(rdr.read_u8()?);
if attrs & FileAttributes::LFN == FileAttributes::LFN { if attrs & FileAttributes::LFN == FileAttributes::LFN {
let mut data = DirLfnEntryData { let mut data = DirLfnEntryData {
@ -617,8 +625,14 @@ impl <'a, 'b> Dir<'a, 'b> {
let mut num_free = 0; let mut num_free = 0;
let mut i = 0; let mut i = 0;
loop { loop {
let data = DirEntryData::deserialize(&mut stream)?; let raw_entry = DirEntryData::deserialize(&mut stream)?;
if data.is_free() { 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 { if num_free == 0 {
first_free = i; 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))?; stream.seek(io::SeekFrom::Start(first_free as u64 * DIR_ENTRY_SIZE))?;
return Ok(stream); 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 { } else {
num_free = 0; num_free = 0;
} }
@ -728,16 +735,12 @@ pub struct DirIter<'a, 'b: 'a> {
} }
impl <'a, 'b> DirIter<'a, 'b> { impl <'a, 'b> DirIter<'a, 'b> {
fn read_dir_entry_raw_data(&mut self) -> io::Result<DirEntryData> {
DirEntryData::deserialize(&mut self.stream)
}
fn read_dir_entry(&mut self) -> io::Result<Option<DirEntry<'a, 'b>>> { fn read_dir_entry(&mut self) -> io::Result<Option<DirEntry<'a, 'b>>> {
let mut lfn_buf = LongNameBuilder::new(); let mut lfn_buf = LongNameBuilder::new();
let mut offset = self.stream.seek(SeekFrom::Current(0))?; let mut offset = self.stream.seek(SeekFrom::Current(0))?;
let mut begin_offset = offset; let mut begin_offset = offset;
loop { loop {
let raw_entry = self.read_dir_entry_raw_data()?; let raw_entry = DirEntryData::deserialize(&mut self.stream)?;
offset += DIR_ENTRY_SIZE; offset += DIR_ENTRY_SIZE;
match raw_entry { match raw_entry {
DirEntryData::File(data) => { DirEntryData::File(data) => {

View File

@ -217,9 +217,21 @@ impl<'a, 'b> Write for File<'a, 'b> {
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)?;
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.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 new_cluster
}, },
} }

View File

@ -125,7 +125,7 @@ fn test_remove_fat32() {
fn test_create_file(fs: FileSystem) { fn test_create_file(fs: FileSystem) {
let mut root_dir = fs.root_dir(); 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::<Vec<String>>(); let mut names = dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
assert_eq!(names, [".", "..", "test.txt"]); assert_eq!(names, [".", "..", "test.txt"]);
{ {
@ -140,6 +140,13 @@ fn test_create_file(fs: FileSystem) {
file.read_to_string(&mut content).unwrap(); file.read_to_string(&mut content).unwrap();
assert_eq!(&content, &TEST_STR); 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::<Vec<String>>();
assert_eq!(names.len(), 4 + 512/32);
} }
#[test] #[test]