Zero new directory clusters after allocation.
This commit is contained in:
parent
9ec23f1234
commit
21bd2a0e8d
33
src/dir.rs
33
src/dir.rs
@ -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) => {
|
||||||
|
12
src/file.rs
12
src/file.rs
@ -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
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user