diff --git a/src/file.rs b/src/file.rs index 7a67589..a2256ff 100644 --- a/src/file.rs +++ b/src/file.rs @@ -4,6 +4,7 @@ use std::io::{SeekFrom, ErrorKind}; use std::io; use fs::FatSharedStateRef; +use table::FatNextCluster; pub struct FatFile<'a, 'b: 'a> { diff --git a/src/fs.rs b/src/fs.rs index 5330a74..529c3ac 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -8,7 +8,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use file::FatFile; use dir::{FatDirReader, FatDir}; -use table::{FatTable, FatTable12, FatTable16, FatTable32}; +use table::FatTable; // FAT implementation based on: // http://wiki.osdev.org/FAT @@ -28,7 +28,7 @@ pub(crate) struct FatSharedState<'a> { pub(crate) boot: FatBootRecord, pub(crate) first_data_sector: u32, pub(crate) root_dir_sectors: u32, - pub(crate) table: Box, + pub(crate) table: FatTable, } impl <'a> FatSharedState<'a> { @@ -128,12 +128,7 @@ impl <'a> FatFileSystem<'a> { let fat_offset = boot.bpb.reserved_sector_count * boot.bpb.bytes_per_sector; rdr.seek(SeekFrom::Start(fat_offset as u64))?; let table_size_bytes = table_size * boot.bpb.bytes_per_sector as u32; - let table: Box = match fat_type { - FatType::Fat12 => Box::new(FatTable12::read(rdr, table_size_bytes as usize)?), - FatType::Fat16 => Box::new(FatTable16::read(rdr, table_size_bytes as usize)?), - FatType::Fat32 => Box::new(FatTable32::read(rdr, table_size_bytes as usize)?), - _ => panic!("TODO: exfat") - }; + let table = FatTable::from_read(rdr, fat_type, table_size_bytes as usize)?; let state = FatSharedState { rdr, diff --git a/src/table.rs b/src/table.rs index e9e858c..30032c3 100644 --- a/src/table.rs +++ b/src/table.rs @@ -1,83 +1,86 @@ use std::io::prelude::*; use std::io; use byteorder::{LittleEndian, ReadBytesExt}; +use fs::FatType; pub(crate) struct FatTableData { table: Box<[T]>, } -pub(crate) type FatTable32 = FatTableData; -pub(crate) type FatTable16 = FatTableData; -pub(crate) type FatTable12 = FatTableData; - impl FatTableData { - pub fn new(data: Box<[T]>) -> FatTableData { - FatTableData:: { + pub fn new(data: Box<[T]>) -> Self { + Self { table: data, } } } +pub(crate) type FatTable12 = FatTableData; +pub(crate) type FatTable16 = FatTableData; +pub(crate) type FatTable32 = FatTableData; + +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 { + 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; +} + +impl FatNextCluster for FatTable { + fn get_next_cluster(&self, cluster: u32) -> Option { + 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), + } + } +} + impl FatTable12 { - pub fn read(rdr: &mut Read, size: usize) -> io::Result { - let mut fat = vec![0;size as usize]; + pub fn from_read(rdr: &mut Read, size: usize) -> io::Result { + let mut fat = vec![0;size]; rdr.read_exact(fat.as_mut())?; - Ok(FatTable12::new(fat.into_boxed_slice())) + Ok(Self::new(fat.into_boxed_slice())) } } impl FatTable16 { - pub fn read(rdr: &mut Read, size: usize) -> io::Result { - let mut fat = Vec::with_capacity(size/2); - for _ in 0..size/2 { - fat.push(rdr.read_u16::()?); - } - Ok(FatTable16::new(fat.into_boxed_slice())) + pub fn from_read(rdr: &mut Read, size: usize) -> io::Result { + let mut fat = vec![0;size/2]; + rdr.read_u16_into::(fat.as_mut())?; + Ok(Self::new(fat.into_boxed_slice())) } } impl FatTable32 { - pub fn read(rdr: &mut Read, size: usize) -> io::Result { - let mut fat = Vec::with_capacity(size/4); - for _ in 0..size/4 { - fat.push(rdr.read_u32::()?); - } - Ok(FatTable32::new(fat.into_boxed_slice())) + pub fn from_read(rdr: &mut Read, size: usize) -> io::Result { + let mut fat = vec![0;size/4]; + rdr.read_u32_into::(fat.as_mut())?; + Ok(Self::new(fat.into_boxed_slice())) } } -pub trait FatTable { - fn get_next_cluster(&self, cluster: u32) -> Option; -} - -impl FatTable for FatTable32 { - fn get_next_cluster(&self, cluster: u32) -> Option { - let val = self.table[cluster as usize] & 0x0FFFFFFF; - if val <= 1 || val >= 0x0FFFFFF7 { - None - } else { - Some(val) - } - } -} - -impl FatTable for FatTable16 { - fn get_next_cluster(&self, cluster: u32) -> Option { - let val = self.table[cluster as usize]; - if val <= 1 || val >= 0xFFF7 { - None - } else { - Some(val as u32) - } - } -} - -impl FatTable for FatTable12 { +impl FatNextCluster for FatTable12 { fn get_next_cluster(&self, cluster: u32) -> Option { 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 { @@ -90,3 +93,25 @@ impl FatTable for FatTable12 { } } } + +impl FatNextCluster for FatTable16 { + fn get_next_cluster(&self, cluster: u32) -> Option { + let val = self.table[cluster as usize]; + if val <= 1 || val >= 0xFFF7 { + None + } else { + Some(val as u32) + } + } +} + +impl FatNextCluster for FatTable32 { + fn get_next_cluster(&self, cluster: u32) -> Option { + let val = self.table[cluster as usize] & 0x0FFFFFFF; + if val <= 1 || val >= 0x0FFFFFF7 { + None + } else { + Some(val) + } + } +}