Support checking entire FAT table when hint points in the middle of it
This commit is contained in:
parent
4793d20977
commit
d094fd5d1d
@ -286,6 +286,7 @@ pub struct FileSystem<'a> {
|
|||||||
bpb: BiosParameterBlock,
|
bpb: BiosParameterBlock,
|
||||||
first_data_sector: u32,
|
first_data_sector: u32,
|
||||||
root_dir_sectors: u32,
|
root_dir_sectors: u32,
|
||||||
|
total_clusters: u32,
|
||||||
fs_info: Option<FsInfoSector>,
|
fs_info: Option<FsInfoSector>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,6 +339,7 @@ impl <'a> FileSystem<'a> {
|
|||||||
bpb: bpb,
|
bpb: bpb,
|
||||||
first_data_sector,
|
first_data_sector,
|
||||||
root_dir_sectors,
|
root_dir_sectors,
|
||||||
|
total_clusters,
|
||||||
fs_info,
|
fs_info,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -419,7 +421,7 @@ impl <'a> FileSystem<'a> {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let mut fat = self.fat_slice();
|
let mut fat = self.fat_slice();
|
||||||
alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint)
|
alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint, self.total_clusters)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_status_flags(&self) -> io::Result<FsStatusFlags> {
|
pub fn read_status_flags(&self) -> io::Result<FsStatusFlags> {
|
||||||
|
43
src/table.rs
43
src/table.rs
@ -24,7 +24,7 @@ enum FatValue {
|
|||||||
trait FatTrait {
|
trait FatTrait {
|
||||||
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue>;
|
fn get(fat: &mut ReadSeek, cluster: u32) -> io::Result<FatValue>;
|
||||||
fn set(fat: &mut DiskSlice, cluster: u32, value: FatValue) -> io::Result<()>;
|
fn set(fat: &mut DiskSlice, cluster: u32, value: FatValue) -> io::Result<()>;
|
||||||
fn find_free(fat: &mut ReadSeek, hint_cluster: u32) -> io::Result<u32>;
|
fn find_free(fat: &mut ReadSeek, start_cluster: u32, end_cluster: u32) -> io::Result<u32>;
|
||||||
fn get_raw(fat: &mut ReadSeek, cluster: u32) -> io::Result<u32>;
|
fn get_raw(fat: &mut ReadSeek, cluster: u32) -> io::Result<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,16 +53,24 @@ fn get_next_cluster(fat: &mut ReadSeek, fat_type: FatType, cluster: u32) -> io::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_free_cluster(fat: &mut ReadSeek, fat_type: FatType, cluster: u32) -> io::Result<u32> {
|
fn find_free_cluster(fat: &mut ReadSeek, fat_type: FatType, start_cluster: u32, end_cluster: u32) -> io::Result<u32> {
|
||||||
match fat_type {
|
match fat_type {
|
||||||
FatType::Fat12 => Fat12::find_free(fat, cluster),
|
FatType::Fat12 => Fat12::find_free(fat, start_cluster, end_cluster),
|
||||||
FatType::Fat16 => Fat16::find_free(fat, cluster),
|
FatType::Fat16 => Fat16::find_free(fat, start_cluster, end_cluster),
|
||||||
FatType::Fat32 => Fat32::find_free(fat, cluster),
|
FatType::Fat32 => Fat32::find_free(fat, start_cluster, end_cluster),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn alloc_cluster(fat: &mut DiskSlice, fat_type: FatType, prev_cluster: Option<u32>, hint: Option<u32>) -> io::Result<u32> {
|
pub(crate) fn alloc_cluster(fat: &mut DiskSlice, fat_type: FatType, prev_cluster: Option<u32>, hint: Option<u32>, total_clusters: u32) -> io::Result<u32> {
|
||||||
let new_cluster = find_free_cluster(fat, fat_type, hint.unwrap_or(2))?;
|
let start_cluster = match hint {
|
||||||
|
Some(n) if n < total_clusters => n,
|
||||||
|
_ => 2,
|
||||||
|
};
|
||||||
|
let new_cluster = match find_free_cluster(fat, fat_type, start_cluster, total_clusters) {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(_) if start_cluster > 2 => find_free_cluster(fat, fat_type, 2, start_cluster)?,
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
write_fat(fat, fat_type, new_cluster, FatValue::EndOfChain)?;
|
write_fat(fat, fat_type, new_cluster, FatValue::EndOfChain)?;
|
||||||
match prev_cluster {
|
match prev_cluster {
|
||||||
Some(n) => write_fat(fat, fat_type, n, FatValue::Data(new_cluster))?,
|
Some(n) => write_fat(fat, fat_type, n, FatValue::Data(new_cluster))?,
|
||||||
@ -136,8 +144,8 @@ impl FatTrait for Fat12 {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_free(fat: &mut ReadSeek, hint_cluster: u32) -> io::Result<u32> {
|
fn find_free(fat: &mut ReadSeek, start_cluster: u32, end_cluster: u32) -> io::Result<u32> {
|
||||||
let mut cluster = hint_cluster;
|
let mut cluster = start_cluster;
|
||||||
let fat_offset = cluster + (cluster / 2);
|
let fat_offset = cluster + (cluster / 2);
|
||||||
fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
|
fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
|
||||||
let mut packed_val = fat.read_u16::<LittleEndian>()?;
|
let mut packed_val = fat.read_u16::<LittleEndian>()?;
|
||||||
@ -150,6 +158,9 @@ impl FatTrait for Fat12 {
|
|||||||
return Ok(cluster);
|
return Ok(cluster);
|
||||||
}
|
}
|
||||||
cluster += 1;
|
cluster += 1;
|
||||||
|
if cluster == end_cluster {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "end of FAT reached"));
|
||||||
|
}
|
||||||
packed_val = match cluster & 1 {
|
packed_val = match cluster & 1 {
|
||||||
0 => fat.read_u16::<LittleEndian>()?,
|
0 => fat.read_u16::<LittleEndian>()?,
|
||||||
_ => {
|
_ => {
|
||||||
@ -189,8 +200,8 @@ impl FatTrait for Fat16 {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_free(fat: &mut ReadSeek, hint_cluster: u32) -> io::Result<u32> {
|
fn find_free(fat: &mut ReadSeek, start_cluster: u32, end_cluster: u32) -> io::Result<u32> {
|
||||||
let mut cluster = hint_cluster;
|
let mut cluster = start_cluster;
|
||||||
fat.seek(io::SeekFrom::Start((cluster*2) as u64))?;
|
fat.seek(io::SeekFrom::Start((cluster*2) as u64))?;
|
||||||
loop {
|
loop {
|
||||||
let val = fat.read_u16::<LittleEndian>()?;
|
let val = fat.read_u16::<LittleEndian>()?;
|
||||||
@ -198,6 +209,9 @@ impl FatTrait for Fat16 {
|
|||||||
return Ok(cluster);
|
return Ok(cluster);
|
||||||
}
|
}
|
||||||
cluster += 1;
|
cluster += 1;
|
||||||
|
if cluster == end_cluster {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "end of FAT reached"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,8 +244,8 @@ impl FatTrait for Fat32 {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_free(fat: &mut ReadSeek, hint_cluster: u32) -> io::Result<u32> {
|
fn find_free(fat: &mut ReadSeek, start_cluster: u32, end_cluster: u32) -> io::Result<u32> {
|
||||||
let mut cluster = hint_cluster;
|
let mut cluster = start_cluster;
|
||||||
fat.seek(io::SeekFrom::Start((cluster*4) as u64))?;
|
fat.seek(io::SeekFrom::Start((cluster*4) as u64))?;
|
||||||
loop {
|
loop {
|
||||||
let val = fat.read_u32::<LittleEndian>()? & 0x0FFFFFFF;
|
let val = fat.read_u32::<LittleEndian>()? & 0x0FFFFFFF;
|
||||||
@ -239,6 +253,9 @@ impl FatTrait for Fat32 {
|
|||||||
return Ok(cluster);
|
return Ok(cluster);
|
||||||
}
|
}
|
||||||
cluster += 1;
|
cluster += 1;
|
||||||
|
if cluster == end_cluster {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "end of FAT reached"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user