Files
k-os/crates/servers/storage-server/src/fs/fat16/fat.rs

65 lines
2.1 KiB
Rust

//! FAT table: cluster allocation and chains.
use super::Fat16;
use super::SECTOR_SIZE;
use port_block_device::{BlockDevice, SectorId};
impl<B: BlockDevice> Fat16<B> {
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<u16> {
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
}
}