//! FAT table: cluster allocation and chains. use super::Fat16; use super::SECTOR_SIZE; use port_block_device::{BlockDevice, SectorId}; impl Fat16 { pub(super) fn read_fat_entry(&mut self, cluster: u16) -> u16 { let fat_offset = (cluster as u32) * 2; let sector = self.bpb.fat_start() + fat_offset / (SECTOR_SIZE as u32); let offset = (fat_offset % (SECTOR_SIZE as u32)) as usize; let mut buf = [0u8; SECTOR_SIZE]; if !self.device.read_sector(SectorId::new(sector), &mut buf) { return 0xFFFF; } u16::from_le_bytes([buf[offset], buf[offset + 1]]) } pub(super) fn write_fat_entry(&mut self, cluster: u16, value: u16) { let fat_offset = (cluster as u32) * 2; let sector = self.bpb.fat_start() + fat_offset / (SECTOR_SIZE as u32); let offset = (fat_offset % (SECTOR_SIZE as u32)) as usize; let mut buf = [0u8; SECTOR_SIZE]; self.device.read_sector(SectorId::new(sector), &mut buf); buf[offset] = value as u8; buf[offset + 1] = (value >> 8) as u8; self.device.write_sector(SectorId::new(sector), &buf); } pub(super) fn alloc_cluster(&mut self) -> Option { let max = self.bpb.total_sectors as u16 / self.bpb.sectors_per_cluster as u16; for i in 2..max { if self.read_fat_entry(i) == 0 { self.write_fat_entry(i, 0xFFFF); return Some(i); } } None } pub(super) fn free_chain(&mut self, start: u16) { let mut cluster = start; loop { if cluster < 2 || cluster >= 0xFFF8 { break; } let next = self.read_fat_entry(cluster); self.write_fat_entry(cluster, 0); cluster = next; } } pub(super) fn follow_chain(&mut self, start: u16, skip_clusters: usize) -> u16 { let mut cluster = start; for _ in 0..skip_clusters { let next = self.read_fat_entry(cluster); if next >= 0xFFF8 { return cluster; } cluster = next; } cluster } }