diff --git a/src/fat/volume.rs b/src/fat/volume.rs index 8f44c6d9..00d0ed65 100644 --- a/src/fat/volume.rs +++ b/src/fat/volume.rs @@ -55,6 +55,9 @@ pub struct FatVolume { /// The block the FAT starts in. Relative to start of partition (so add /// `self.lba_offset` before passing to volume manager) pub(crate) fat_start: BlockCount, + /// The block the second FAT starts in (if present). Relative to start of + /// partition (so add `self.lba_offset` before passing to volume manager) + pub(crate) second_fat_start: Option, /// Expected number of free clusters pub(crate) free_clusters_count: Option, /// Number of the next expected free cluster @@ -118,10 +121,15 @@ impl FatVolume { { let mut blocks = [Block::new()]; let this_fat_block_num; + let mut second_fat_block_num = None; match &self.fat_specific_info { FatSpecificInfo::Fat16(_fat16_info) => { let fat_offset = cluster.0 * 2; this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset); + if let Some(fat_start) = self.second_fat_start { + second_fat_block_num = + Some(self.lba_start + fat_start.offset_bytes(fat_offset)); + } let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; block_device .read(&mut blocks, this_fat_block_num, "read_fat") @@ -143,6 +151,10 @@ impl FatVolume { // FAT32 => 4 bytes per entry let fat_offset = cluster.0 * 4; this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset); + if let Some(fat_start) = self.second_fat_start { + second_fat_block_num = + Some(self.lba_start + fat_start.offset_bytes(fat_offset)); + } let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; block_device .read(&mut blocks, this_fat_block_num, "read_fat") @@ -166,6 +178,11 @@ impl FatVolume { block_device .write(&blocks, this_fat_block_num) .map_err(Error::DeviceError)?; + if let Some(second_fat_block_num) = second_fat_block_num { + block_device + .write(&blocks, second_fat_block_num) + .map_err(Error::DeviceError)?; + } Ok(()) } @@ -1098,6 +1115,13 @@ where blocks_per_cluster: bpb.blocks_per_cluster(), first_data_block: (first_data_block), fat_start: BlockCount(u32::from(bpb.reserved_block_count())), + second_fat_start: if bpb.num_fats() == 2 { + Some(BlockCount( + u32::from(bpb.reserved_block_count()) + bpb.fat_size(), + )) + } else { + None + }, free_clusters_count: None, next_free_cluster: None, cluster_count: bpb.total_clusters(), @@ -1135,6 +1159,13 @@ where blocks_per_cluster: bpb.blocks_per_cluster(), first_data_block: BlockCount(first_data_block), fat_start: BlockCount(u32::from(bpb.reserved_block_count())), + second_fat_start: if bpb.num_fats() == 2 { + Some(BlockCount( + u32::from(bpb.reserved_block_count()) + bpb.fat_size(), + )) + } else { + None + }, free_clusters_count: info_sector.free_clusters_count(), next_free_cluster: info_sector.next_free_cluster(), cluster_count: bpb.total_clusters(), diff --git a/src/volume_mgr.rs b/src/volume_mgr.rs index 98b77814..c4fffd38 100644 --- a/src/volume_mgr.rs +++ b/src/volume_mgr.rs @@ -5,7 +5,7 @@ use byteorder::{ByteOrder, LittleEndian}; use core::convert::TryFrom; -use crate::fat::{self, BlockCache, FatType, OnDiskDirEntry, RESERVED_ENTRIES}; +use crate::fat::{self, BlockCache, OnDiskDirEntry, RESERVED_ENTRIES}; use crate::filesystem::{ Attributes, ClusterId, DirEntry, DirectoryInfo, FileInfo, Mode, RawDirectory, RawFile, @@ -324,6 +324,13 @@ where } let volume_idx = self.get_volume_by_id(volume)?; + + match &mut self.open_volumes[volume_idx].volume_type { + VolumeType::Fat(fat_volume) => { + fat_volume.update_info_sector(&self.block_device)?; + } + } + self.open_volumes.swap_remove(volume_idx); Ok(()) @@ -978,16 +985,13 @@ where ctime: now, attributes: att, // point at our parent - cluster: match fat_type { - FatType::Fat16 => { - // On FAT16, indicate parent is root using Cluster(0) - if parent_directory_info.cluster == ClusterId::ROOT_DIR { - ClusterId::EMPTY - } else { - parent_directory_info.cluster - } + cluster: { + // On FAT16, indicate parent is root using Cluster(0) + if parent_directory_info.cluster == ClusterId::ROOT_DIR { + ClusterId::EMPTY + } else { + parent_directory_info.cluster } - FatType::Fat32 => parent_directory_info.cluster, }, size: 0, entry_block: new_dir_start_block, @@ -1384,6 +1388,7 @@ mod tests { blocks_per_cluster: 8, first_data_block: BlockCount(15136), fat_start: BlockCount(32), + second_fat_start: Some(BlockCount(32 + 0x0000_1D80)), name: fat::VolumeName::new(*b"Pictures "), free_clusters_count: None, next_free_cluster: None,