Skip to content

Commit

Permalink
Fix issue #74
Browse files Browse the repository at this point in the history
Map ROOT_DIR (0xFFFF_FFFC) to an actual cluster number, so if you go off the end of the first cluster of the root directory on FAT32, the code no longer crashes trying to convert the ROOT_DIR magic cluster number into a disk offset.
  • Loading branch information
thejpster committed Dec 17, 2023
1 parent a5f3a83 commit 7d93aa8
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/fat/volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ impl FatVolume {
where
D: BlockDevice,
{
if cluster.0 > (u32::MAX / 4) {
panic!("next_cluster called on invalid cluster {:x?}", cluster);
}
match &self.fat_specific_info {
FatSpecificInfo::Fat16(_fat16_info) => {
let fat_offset = cluster.0 * 2;
Expand Down Expand Up @@ -360,19 +363,24 @@ impl FatVolume {
FatSpecificInfo::Fat32(fat32_info) => {
// All directories on FAT32 have a cluster chain but the root
// dir starts in a specified cluster.
let mut first_dir_block_num = match dir.cluster {
ClusterId::ROOT_DIR => self.cluster_to_block(fat32_info.first_root_dir_cluster),
_ => self.cluster_to_block(dir.cluster),
let mut current_cluster = match dir.cluster {
ClusterId::ROOT_DIR => Some(fat32_info.first_root_dir_cluster),
_ => Some(dir.cluster),
};
let mut current_cluster = Some(dir.cluster);
let mut first_dir_block_num = self.cluster_to_block(dir.cluster);
let mut blocks = [Block::new()];

let dir_size = BlockCount(u32::from(self.blocks_per_cluster));
// Walk the cluster chain until we run out of clusters
while let Some(cluster) = current_cluster {
// Loop through the blocks in the cluster
for block in first_dir_block_num.range(dir_size) {
// Read a block of directory entries
block_device
.read(&mut blocks, block, "read_dir")
.map_err(Error::DeviceError)?;
// Are any entries in the block we just loaded blank? If so
// we can use them.
for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
let start = entry * OnDiskDirEntry::LEN;
let end = (entry + 1) * OnDiskDirEntry::LEN;
Expand All @@ -397,6 +405,8 @@ impl FatVolume {
}
}
}
// Well none of the blocks in that cluster had any space in
// them, let's fetch another one.
let mut block_cache = BlockCache::empty();
current_cluster =
match self.next_cluster(block_device, cluster, &mut block_cache) {
Expand All @@ -412,6 +422,8 @@ impl FatVolume {
_ => None,
};
}
// We ran out of clusters in the chain, and apparently we weren't
// able to make the chain longer, so the disk must be full.
Err(Error::NotEnoughSpace)
}
}
Expand Down

0 comments on commit 7d93aa8

Please sign in to comment.