From fec3af5e76e62c90cd33bc9e7c177b51bd844e65 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 17 Dec 2023 17:19:53 +0000 Subject: [PATCH 1/2] Add example which tries to totally fill the root directory. --- examples/big_dir.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 examples/big_dir.rs diff --git a/examples/big_dir.rs b/examples/big_dir.rs new file mode 100644 index 0000000..b355c3c --- /dev/null +++ b/examples/big_dir.rs @@ -0,0 +1,39 @@ +extern crate embedded_sdmmc; + +mod linux; +use linux::*; + +use embedded_sdmmc::{Error, VolumeManager}; + +fn main() -> Result<(), embedded_sdmmc::Error> { + env_logger::init(); + let mut args = std::env::args().skip(1); + let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into()); + let print_blocks = args.find(|x| x == "-v").map(|_| true).unwrap_or(false); + let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?; + let mut volume_mgr: VolumeManager = + VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000); + let mut volume = volume_mgr + .open_volume(embedded_sdmmc::VolumeIdx(1)) + .unwrap(); + println!("Volume: {:?}", volume); + let mut root_dir = volume.open_root_dir().unwrap(); + + let mut file_num = 0; + loop { + file_num += 1; + let file_name = format!("{}.da", file_num); + println!("opening file {file_name} for writing"); + let mut file = root_dir + .open_file_in_dir( + file_name.as_str(), + embedded_sdmmc::Mode::ReadWriteCreateOrTruncate, + ) + .unwrap(); + let buf = b"hello world, from rust"; + println!("writing to file"); + file.write(&buf[..]).unwrap(); + println!("closing file"); + drop(file); + } +} From 819a624488297ecbf7992c39753a6b7ccb0a307e Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 17 Dec 2023 17:21:45 +0000 Subject: [PATCH 2/2] Fix issue #74 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. --- src/fat/volume.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/fat/volume.rs b/src/fat/volume.rs index c946ec8..b6dd510 100644 --- a/src/fat/volume.rs +++ b/src/fat/volume.rs @@ -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; @@ -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; @@ -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) { @@ -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) } }