2017-09-23 20:16:02 +08:00
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::io;
|
|
|
|
use byteorder::{LittleEndian, ReadBytesExt};
|
2017-09-28 06:11:24 +08:00
|
|
|
use fs::FatType;
|
2017-09-23 20:16:02 +08:00
|
|
|
|
|
|
|
pub(crate) struct FatTableData<T> {
|
|
|
|
table: Box<[T]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <T> FatTableData<T> {
|
2017-09-28 06:11:24 +08:00
|
|
|
pub fn new(data: Box<[T]>) -> Self {
|
|
|
|
Self {
|
2017-09-23 20:16:02 +08:00
|
|
|
table: data,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-28 06:11:24 +08:00
|
|
|
pub(crate) type FatTable12 = FatTableData<u8>;
|
|
|
|
pub(crate) type FatTable16 = FatTableData<u16>;
|
|
|
|
pub(crate) type FatTable32 = FatTableData<u32>;
|
|
|
|
|
|
|
|
pub(crate) enum FatTable {
|
|
|
|
Fat12(FatTable12),
|
|
|
|
Fat16(FatTable16),
|
|
|
|
Fat32(FatTable32),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FatTable {
|
|
|
|
pub fn from_read(rdr: &mut Read, fat_type: FatType, size: usize) -> io::Result<FatTable> {
|
|
|
|
let table = match fat_type {
|
|
|
|
FatType::Fat12 => FatTable::Fat12(FatTable12::from_read(rdr, size)?),
|
|
|
|
FatType::Fat16 => FatTable::Fat16(FatTable16::from_read(rdr, size)?),
|
|
|
|
FatType::Fat32 => FatTable::Fat32(FatTable32::from_read(rdr, size)?),
|
|
|
|
_ => panic!("TODO: exfat")
|
|
|
|
};
|
|
|
|
Ok(table)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) trait FatNextCluster {
|
|
|
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FatNextCluster for FatTable {
|
|
|
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
|
|
|
|
match *self {
|
|
|
|
FatTable::Fat12(ref fat) => fat.get_next_cluster(cluster),
|
|
|
|
FatTable::Fat16(ref fat) => fat.get_next_cluster(cluster),
|
|
|
|
FatTable::Fat32(ref fat) => fat.get_next_cluster(cluster),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-23 20:16:02 +08:00
|
|
|
impl FatTable12 {
|
2017-09-28 06:11:24 +08:00
|
|
|
pub fn from_read(rdr: &mut Read, size: usize) -> io::Result<Self> {
|
|
|
|
let mut fat = vec![0;size];
|
2017-09-23 20:16:02 +08:00
|
|
|
rdr.read_exact(fat.as_mut())?;
|
2017-09-28 06:11:24 +08:00
|
|
|
Ok(Self::new(fat.into_boxed_slice()))
|
2017-09-23 20:16:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FatTable16 {
|
2017-09-28 06:11:24 +08:00
|
|
|
pub fn from_read(rdr: &mut Read, size: usize) -> io::Result<Self> {
|
|
|
|
let mut fat = vec![0;size/2];
|
|
|
|
rdr.read_u16_into::<LittleEndian>(fat.as_mut())?;
|
|
|
|
Ok(Self::new(fat.into_boxed_slice()))
|
2017-09-23 20:16:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FatTable32 {
|
2017-09-28 06:11:24 +08:00
|
|
|
pub fn from_read(rdr: &mut Read, size: usize) -> io::Result<Self> {
|
|
|
|
let mut fat = vec![0;size/4];
|
|
|
|
rdr.read_u32_into::<LittleEndian>(fat.as_mut())?;
|
|
|
|
Ok(Self::new(fat.into_boxed_slice()))
|
2017-09-23 20:16:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-28 06:11:24 +08:00
|
|
|
impl FatNextCluster for FatTable12 {
|
2017-09-23 20:16:02 +08:00
|
|
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
|
2017-09-28 06:11:24 +08:00
|
|
|
let fat_offset = cluster + (cluster / 2);
|
|
|
|
let val1 = self.table[fat_offset as usize] as u16;
|
|
|
|
let val2 = self.table[(fat_offset + 1) as usize] as u16;
|
|
|
|
|
|
|
|
let val = if cluster & 1 == 1 {
|
|
|
|
(val1 >> 4) | (val2 << 4)
|
|
|
|
} else {
|
|
|
|
val1 | (val2 & 0x0F)
|
|
|
|
};
|
|
|
|
if val <= 1 || val >= 0xFF7 {
|
2017-09-23 20:16:02 +08:00
|
|
|
None
|
|
|
|
} else {
|
2017-09-28 06:11:24 +08:00
|
|
|
Some(val as u32)
|
2017-09-23 20:16:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-28 06:11:24 +08:00
|
|
|
impl FatNextCluster for FatTable16 {
|
2017-09-23 20:16:02 +08:00
|
|
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
|
|
|
|
let val = self.table[cluster as usize];
|
2017-09-24 04:22:25 +08:00
|
|
|
if val <= 1 || val >= 0xFFF7 {
|
2017-09-23 20:16:02 +08:00
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(val as u32)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-28 06:11:24 +08:00
|
|
|
impl FatNextCluster for FatTable32 {
|
2017-09-23 20:16:02 +08:00
|
|
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
|
2017-09-28 06:11:24 +08:00
|
|
|
let val = self.table[cluster as usize] & 0x0FFFFFFF;
|
|
|
|
if val <= 1 || val >= 0x0FFFFFF7 {
|
2017-09-23 20:16:02 +08:00
|
|
|
None
|
|
|
|
} else {
|
2017-09-28 06:11:24 +08:00
|
|
|
Some(val)
|
2017-09-23 20:16:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|