1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use {std, memmap};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FATType {
FAT12,
FAT16,
FAT32
}
#[derive(Default, Debug)]
pub struct FAT {
mmap: Option<memmap::Mmap>,
ftype: Option<FATType>,
boot_sector: BootSector,
bios_parameter_block: BiosParameterBlock,
count_of_clusters: usize,
fat_sz: usize,
tot_sec: usize
}
#[derive(Default, Debug)]
pub struct BootSector {
jmp: [u8; 3],
oem_name: [u8; 8]
}
#[derive(Default, Debug)]
pub struct BiosParameterBlock {
bytes_per_sec: u16,
sec_per_clus: u8,
rsvd_sec_cnt: u16,
num_fats: u8,
root_ent_cnt: u16,
tot_sec_16: u16,
media: u8,
fat_sz_16: u16,
tot_sec_32: usize
}
impl FAT {
pub fn new(file: &std::fs::File) -> super::Result<FAT> {
let mmap = unsafe {
memmap::MmapOptions::new().map(file).map_err(super::error::Error::IOError)?
};
if mmap.len() >= 512 {
let mut fat = FAT {
mmap: Some(mmap),
..FAT::default()
};
fat.parse_boot_record()?;
Ok(fat)
} else {
Err(super::error::Error::InvalidFATFormat)
}
}
pub fn from_path(path: &str) -> super::Result<FAT> {
let file = std::fs::File::open(path).map_err(super::error::Error::IOError)?;
FAT::new(&file)
}
fn parse_boot_record(&mut self) -> super::Result<()> {
use super::util::FromSlice;
let mmap = self.mmap.as_ref().unwrap();
let bpb = &mut self.bios_parameter_block;
let bs = &mut self.boot_sector;
bs.jmp.copy_from_slice(&mmap[0x00 .. 0x03]);
if (bs.jmp[0x00] == 0xEB && bs.jmp[0x02] != 0x90)
|| (bs.jmp[0x00] != 0xEB && bs.jmp[0x00] != 0xE9) {
return Err(super::error::Error::InvalidFATFormat);
}
bs.oem_name.copy_from_slice(&mmap[0x03 .. 0x0B]);
bpb.bytes_per_sec = u16::from_slice(&mmap[0x0B .. 0x0D]);
bpb.sec_per_clus = mmap[0x0D];
bpb.rsvd_sec_cnt = u16::from_slice(&mmap[0x0E .. 0x10]);
bpb.num_fats = mmap[0x10];
bpb.root_ent_cnt = u16::from_slice(&mmap[0x11 .. 0x13]);
bpb.tot_sec_16 = u16::from_slice(&mmap[0x13 .. 0x15]);
bpb.tot_sec_32 = usize::from_slice(&mmap[0x20 .. 0x24]);
if bpb.tot_sec_16 == 0 && bpb.tot_sec_32 == 0 {
return Err(super::error::Error::InvalidFATFormat);
}
bpb.media = mmap[0x15];
if bpb.media < 0xF8 && bpb.media != 0xF0 {
return Err(super::error::Error::InvalidFATFormat);
}
bpb.fat_sz_16 = u16::from_slice(&mmap[0x16 .. 0x18]);
let rds = ((bpb.root_ent_cnt * 32) + (bpb.bytes_per_sec -1))
/ bpb.bytes_per_sec;
self.fat_sz = if bpb.fat_sz_16 != 0 {
bpb.fat_sz_16 as usize
} else {
usize::from_slice(&mmap[0x24 .. 0x28])
};
self.tot_sec = if bpb.tot_sec_16 != 0 {
bpb.tot_sec_16 as usize
} else {
bpb.tot_sec_32
};
let data_sec = self.tot_sec - (bpb.rsvd_sec_cnt as usize
+ ((bpb.num_fats as usize * self.fat_sz) as usize) + (rds as usize)) as usize;
self.count_of_clusters = data_sec / (bpb.sec_per_clus as usize);
self.ftype = if self.count_of_clusters < 4085 {
Some(FATType::FAT12)
} else if self.count_of_clusters < 65525 {
Some(FATType::FAT16)
} else {
Some(FATType::FAT32)
};
Ok(())
}
pub fn ftype(&self) -> FATType {
*self.ftype.as_ref().unwrap()
}
}