From 3933a29078a33e196d8ff05ffe0f8427729d87c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Harabie=C5=84?= Date: Sat, 23 Sep 2017 14:16:02 +0200 Subject: [PATCH] Implemented basic FAT table support. --- src/fs.rs | 13 ++++++++ src/lib.rs | 1 + src/table.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/table.rs diff --git a/src/fs.rs b/src/fs.rs index ebe78d4..2e5af17 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -5,6 +5,7 @@ use std::str; use byteorder::{LittleEndian, ReadBytesExt}; use file::FatFile; +use table::{FatTable, FatTable12, FatTable16, FatTable32}; // FAT implementation based on: // http://wiki.osdev.org/FAT @@ -23,6 +24,7 @@ pub struct FatFileSystem { first_fat_sector: u32, pub(crate) first_data_sector: u32, pub(crate) root_dir_sectors: u32, + pub(crate) table: Box, } #[allow(dead_code)] @@ -118,6 +120,16 @@ impl FatFileSystem { println!("fat_type_label {}", fat_type_label_str); } + // FIXME: other versions + + 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 fs = FatFileSystem { rdr: rdr, fat_type: fat_type, @@ -125,6 +137,7 @@ impl FatFileSystem { first_data_sector: first_data_sector, first_fat_sector: first_fat_sector, root_dir_sectors: root_dir_sectors as u32, + table: table, }; Ok(fs) diff --git a/src/lib.rs b/src/lib.rs index c4a0b21..14d2320 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ extern crate bitflags; pub mod fs; pub mod dir; pub mod file; +pub mod table; pub use fs::*; pub use dir::*; diff --git a/src/table.rs b/src/table.rs new file mode 100644 index 0000000..ec7a016 --- /dev/null +++ b/src/table.rs @@ -0,0 +1,92 @@ +use std::io::prelude::*; +use std::io; +use byteorder::{LittleEndian, ReadBytesExt}; + +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:: { + table: data, + } + } +} + +impl FatTable12 { + pub fn read(rdr: &mut Read, size: usize) -> io::Result { + let mut fat = vec![0;size as usize]; + rdr.read_exact(fat.as_mut())?; + Ok(FatTable12::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())) + } +} + +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 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 >= 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 >= 0xFFF7 { + None + } else { + Some(val as u32) + } + } +} + +impl FatTable 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 { + val1 | (val2 & 0x0F) + }; + if val >= 0xFF7 { + None + } else { + Some(val as u32) + } + } +}