Skip to content

Commit 7ed6189

Browse files
committed
Write to the second FAT, if it exists.
1 parent dfa1c3e commit 7ed6189

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

src/blockdevice.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ where
137137
)
138138
}
139139

140+
/// Write back a block you read with [`Self::read_mut`] and then modified, but to two locations.
141+
///
142+
/// This is useful for updating two File Allocation Tables.
143+
pub fn write_back_with_duplicate(&mut self, duplicate: BlockIdx) -> Result<(), D::Error> {
144+
self.block_device.write(
145+
&self.block,
146+
self.block_idx.expect("write_back with no read"),
147+
)?;
148+
self.block_device.write(&self.block, duplicate)?;
149+
Ok(())
150+
}
151+
140152
/// Access a blank sector
141153
pub fn blank_mut(&mut self, block_idx: BlockIdx) -> &mut Block {
142154
self.block_idx = Some(block_idx);

src/fat/volume.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ pub struct FatVolume {
149149
/// The block the FAT starts in. Relative to start of partition (so add
150150
/// `self.lba_offset` before passing to volume manager)
151151
pub(crate) fat_start: BlockCount,
152+
/// The block the second FAT starts in. Relative to start of partition (so add
153+
/// `self.lba_offset` before passing to volume manager)
154+
pub(crate) second_fat_start: Option<BlockCount>,
152155
/// Expected number of free clusters
153156
pub(crate) free_clusters_count: Option<u32>,
154157
/// Number of the next expected free cluster
@@ -211,11 +214,15 @@ impl FatVolume {
211214
where
212215
D: BlockDevice,
213216
{
214-
let this_fat_block_num;
217+
let mut second_fat_block_num = None;
215218
match &self.fat_specific_info {
216219
FatSpecificInfo::Fat16(_fat16_info) => {
217220
let fat_offset = cluster.0 * 2;
218-
this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
221+
let this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
222+
if let Some(second_fat_start) = self.second_fat_start {
223+
second_fat_block_num =
224+
Some(self.lba_start + second_fat_start.offset_bytes(fat_offset));
225+
}
219226
let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize;
220227
trace!("Reading FAT for update");
221228
let block = block_cache
@@ -237,7 +244,11 @@ impl FatVolume {
237244
FatSpecificInfo::Fat32(_fat32_info) => {
238245
// FAT32 => 4 bytes per entry
239246
let fat_offset = cluster.0 * 4;
240-
this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
247+
let this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset);
248+
if let Some(second_fat_start) = self.second_fat_start {
249+
second_fat_block_num =
250+
Some(self.lba_start + second_fat_start.offset_bytes(fat_offset));
251+
}
241252
let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize;
242253
trace!("Reading FAT for update");
243254
let block = block_cache
@@ -259,7 +270,11 @@ impl FatVolume {
259270
}
260271
}
261272
trace!("Updating FAT");
262-
block_cache.write_back()?;
273+
if let Some(duplicate) = second_fat_block_num {
274+
block_cache.write_back_with_duplicate(duplicate)?;
275+
} else {
276+
block_cache.write_back()?;
277+
}
263278
Ok(())
264279
}
265280

@@ -995,7 +1010,9 @@ impl FatVolume {
9951010
}
9961011
Err(e) => return Err(e),
9971012
};
1013+
// This new cluster is the end of the file's chain
9981014
self.update_fat(block_cache, new_cluster, ClusterId::END_OF_FILE)?;
1015+
// If there's something before this new one, update the FAT to point it at us
9991016
if let Some(cluster) = prev_cluster {
10001017
trace!(
10011018
"Updating old cluster {:?} to {:?} in FAT",
@@ -1132,6 +1149,12 @@ where
11321149
trace!("Reading BPB");
11331150
let block = block_cache.read(lba_start).map_err(Error::DeviceError)?;
11341151
let bpb = Bpb::create_from_bytes(block).map_err(Error::FormatError)?;
1152+
let fat_start = BlockCount(u32::from(bpb.reserved_block_count()));
1153+
let second_fat_start = if bpb.num_fats() == 2 {
1154+
Some(fat_start + BlockCount(bpb.fat_size()))
1155+
} else {
1156+
None
1157+
};
11351158
match bpb.fat_type {
11361159
FatType::Fat16 => {
11371160
if bpb.bytes_per_block() as usize != Block::LEN {
@@ -1141,7 +1164,6 @@ where
11411164
let root_dir_blocks = ((u32::from(bpb.root_entries_count()) * OnDiskDirEntry::LEN_U32)
11421165
+ (Block::LEN_U32 - 1))
11431166
/ Block::LEN_U32;
1144-
let fat_start = BlockCount(u32::from(bpb.reserved_block_count()));
11451167
let first_root_dir_block =
11461168
fat_start + BlockCount(u32::from(bpb.num_fats()) * bpb.fat_size());
11471169
let first_data_block = first_root_dir_block + BlockCount(root_dir_blocks);
@@ -1152,8 +1174,9 @@ where
11521174
contents: bpb.volume_label(),
11531175
},
11541176
blocks_per_cluster: bpb.blocks_per_cluster(),
1155-
first_data_block: (first_data_block),
1156-
fat_start: BlockCount(u32::from(bpb.reserved_block_count())),
1177+
first_data_block,
1178+
fat_start,
1179+
second_fat_start,
11571180
free_clusters_count: None,
11581181
next_free_cluster: None,
11591182
cluster_count: bpb.total_clusters(),
@@ -1166,9 +1189,8 @@ where
11661189
}
11671190
FatType::Fat32 => {
11681191
// FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz);
1169-
let first_data_block = u32::from(bpb.reserved_block_count())
1170-
+ (u32::from(bpb.num_fats()) * bpb.fat_size());
1171-
1192+
let first_data_block =
1193+
fat_start + BlockCount(u32::from(bpb.num_fats()) * bpb.fat_size());
11721194
// Safe to unwrap since this is a Fat32 Type
11731195
let info_location = bpb.fs_info_block().unwrap();
11741196
let mut volume = FatVolume {
@@ -1178,8 +1200,9 @@ where
11781200
contents: bpb.volume_label(),
11791201
},
11801202
blocks_per_cluster: bpb.blocks_per_cluster(),
1181-
first_data_block: BlockCount(first_data_block),
1182-
fat_start: BlockCount(u32::from(bpb.reserved_block_count())),
1203+
first_data_block,
1204+
fat_start,
1205+
second_fat_start,
11831206
free_clusters_count: None,
11841207
next_free_cluster: None,
11851208
cluster_count: bpb.total_clusters(),

src/volume_mgr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,7 @@ mod tests {
14931493
blocks_per_cluster: 8,
14941494
first_data_block: BlockCount(15136),
14951495
fat_start: BlockCount(32),
1496+
second_fat_start: Some(BlockCount(32 + 0x0000_1D80)),
14961497
name: fat::VolumeName::create_from_str("Pictures").unwrap(),
14971498
free_clusters_count: None,
14981499
next_free_cluster: None,

0 commit comments

Comments
 (0)