forked from M-Labs/rust-fatfs
Implemented basic FAT table support.
This commit is contained in:
parent
6b18dfd626
commit
3933a29078
13
src/fs.rs
13
src/fs.rs
@ -5,6 +5,7 @@ use std::str;
|
|||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
|
||||||
use file::FatFile;
|
use file::FatFile;
|
||||||
|
use table::{FatTable, FatTable12, FatTable16, FatTable32};
|
||||||
|
|
||||||
// FAT implementation based on:
|
// FAT implementation based on:
|
||||||
// http://wiki.osdev.org/FAT
|
// http://wiki.osdev.org/FAT
|
||||||
@ -23,6 +24,7 @@ pub struct FatFileSystem<T: Read+Seek> {
|
|||||||
first_fat_sector: u32,
|
first_fat_sector: u32,
|
||||||
pub(crate) first_data_sector: u32,
|
pub(crate) first_data_sector: u32,
|
||||||
pub(crate) root_dir_sectors: u32,
|
pub(crate) root_dir_sectors: u32,
|
||||||
|
pub(crate) table: Box<FatTable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -118,6 +120,16 @@ impl<T: Read+Seek> FatFileSystem<T> {
|
|||||||
println!("fat_type_label {}", fat_type_label_str);
|
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<FatTable> = 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 {
|
let fs = FatFileSystem {
|
||||||
rdr: rdr,
|
rdr: rdr,
|
||||||
fat_type: fat_type,
|
fat_type: fat_type,
|
||||||
@ -125,6 +137,7 @@ impl<T: Read+Seek> FatFileSystem<T> {
|
|||||||
first_data_sector: first_data_sector,
|
first_data_sector: first_data_sector,
|
||||||
first_fat_sector: first_fat_sector,
|
first_fat_sector: first_fat_sector,
|
||||||
root_dir_sectors: root_dir_sectors as u32,
|
root_dir_sectors: root_dir_sectors as u32,
|
||||||
|
table: table,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(fs)
|
Ok(fs)
|
||||||
|
@ -10,6 +10,7 @@ extern crate bitflags;
|
|||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod dir;
|
pub mod dir;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
|
pub mod table;
|
||||||
|
|
||||||
pub use fs::*;
|
pub use fs::*;
|
||||||
pub use dir::*;
|
pub use dir::*;
|
||||||
|
92
src/table.rs
Normal file
92
src/table.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use std::io::prelude::*;
|
||||||
|
use std::io;
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
|
||||||
|
pub(crate) struct FatTableData<T> {
|
||||||
|
table: Box<[T]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) type FatTable32 = FatTableData<u32>;
|
||||||
|
pub(crate) type FatTable16 = FatTableData<u16>;
|
||||||
|
pub(crate) type FatTable12 = FatTableData<u8>;
|
||||||
|
|
||||||
|
impl <T> FatTableData<T> {
|
||||||
|
pub fn new(data: Box<[T]>) -> FatTableData<T> {
|
||||||
|
FatTableData::<T> {
|
||||||
|
table: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FatTable12 {
|
||||||
|
pub fn read(rdr: &mut Read, size: usize) -> io::Result<Self> {
|
||||||
|
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<Self> {
|
||||||
|
let mut fat = Vec::with_capacity(size/2);
|
||||||
|
for _ in 0..size/2 {
|
||||||
|
fat.push(rdr.read_u16::<LittleEndian>()?);
|
||||||
|
}
|
||||||
|
Ok(FatTable16::new(fat.into_boxed_slice()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FatTable32 {
|
||||||
|
pub fn read(rdr: &mut Read, size: usize) -> io::Result<Self> {
|
||||||
|
let mut fat = Vec::with_capacity(size/4);
|
||||||
|
for _ in 0..size/4 {
|
||||||
|
fat.push(rdr.read_u32::<LittleEndian>()?);
|
||||||
|
}
|
||||||
|
Ok(FatTable32::new(fat.into_boxed_slice()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FatTable {
|
||||||
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FatTable for FatTable32 {
|
||||||
|
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
|
||||||
|
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<u32> {
|
||||||
|
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<u32> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user