commit 958f207ce6b05a8e015be99cdceb2a45e506311b Author: Rafał Harabień Date: Fri Sep 22 02:13:29 2017 +0200 Implemented reading FAT Boot Sector. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..821c112 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,14 @@ +[root] +name = "rust-fat" +version = "0.1.0" +dependencies = [ + "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5ec99d0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rust-fat" +version = "0.1.0" +authors = ["Rafał Harabień "] + +[dependencies] +byteorder = "1" diff --git a/resources/floppy.img b/resources/floppy.img new file mode 100755 index 0000000..968794b Binary files /dev/null and b/resources/floppy.img differ diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b5594d8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,142 @@ +extern crate byteorder; + +use std::fs::File; +use std::io::prelude::*; +use std::io::BufReader; +use std::io; +use std::str; +use std::io::{Error, ErrorKind}; +use byteorder::{LittleEndian, ReadBytesExt}; + +// FAT implementation based on: +// http://wiki.osdev.org/FAT +// https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html + +#[derive(Debug, Copy, Clone)] +enum FatType { + Fat12, Fat16, Fat32, ExFat +} + +#[derive(Debug)] +struct FatFileSystem { + fat_type: FatType, + root_cluster: u32, + volume_id: u32, + volume_label: String, + first_data_sector: u32, + first_fat_sector: u32, +} + +impl FatFileSystem { + fn fat_type_from_clusters(total_clusters: u32) -> FatType { + if total_clusters < 4085 { + FatType::Fat12 + } else if total_clusters < 65525 { + FatType::Fat16 + } else if total_clusters < 268435445 { + FatType::Fat32 + } else { + FatType::ExFat + } + } + + pub fn new(rdr: &mut BufRead) -> io::Result { + let mut bootjmp = [0; 3]; + rdr.read(&mut bootjmp)?; + let mut oem_name: [u8; 8] = [0; 8]; + rdr.read(&mut oem_name)?; + let bytes_per_sector = rdr.read_u16::()? as u32; + let sectors_per_cluster = rdr.read_u8()? as u32; + let reserved_sector_count = rdr.read_u16::()? as u32; + let table_count = rdr.read_u8()? as u32; + let root_entry_count = rdr.read_u16::()? as u32; + let total_sectors_16 = rdr.read_u16::()? as u32; + rdr.read_u8()?; // media_type + let table_size_16 = rdr.read_u16::()? as u32; + rdr.read_u16::()?; // sectors_per_track + rdr.read_u16::()?; // head_side_count + rdr.read_u32::()?; // hidden_sector_count + let total_sectors_32 = rdr.read_u32::()? as u32; + + let (fat_size, fat_info, root_cluster, volume_id); + let mut volume_label = [0; 11]; + let mut fat_type_label = [0; 8]; + + if table_size_16 == 0 { + let table_size_32 = rdr.read_u32::()? as u32; + rdr.read_u16::()?; // extended_flags + rdr.read_u16::()?; // fat_version + root_cluster = rdr.read_u32::()?; + fat_info = rdr.read_u16::()? as u32; + rdr.read_u16::()?; // backup_bs_sector + let mut reserved_0 = [0; 12]; + rdr.read(&mut reserved_0)?; + rdr.read_u8()?; // drive_num + rdr.read_u8()?; // reserved_1 + rdr.read_u8()?; // ext_sig (0x29) + volume_id = rdr.read_u32::()?; + rdr.read(&mut volume_label)?; + rdr.read(&mut fat_type_label)?; + let mut boot_code = [0; 420]; + rdr.read(&mut boot_code)?; + + fat_size = table_size_32; + } else { + rdr.read_u8()?; // drive_num + rdr.read_u8()?; // reserved1 + rdr.read_u8()?; // ext_sig (0x29) + volume_id = rdr.read_u32::()?; + rdr.read(&mut volume_label)?; + rdr.read(&mut fat_type_label)?; + let mut boot_code = [0; 448]; + rdr.read(&mut boot_code)?; + + fat_size = table_size_16; + fat_info = 0; + root_cluster = 0; + } + let mut boot_sig = [0; 2]; + rdr.read(&mut boot_sig)?; + if boot_sig != [0x55, 0xAA] { + return Err(Error::new(ErrorKind::Other, "invalid signature")); + } + + let total_sectors = if total_sectors_16 == 0 { total_sectors_32 } else { total_sectors_16 }; + let root_dir_sectors = ((root_entry_count * 32) + (bytes_per_sector - 1)) / (bytes_per_sector); + let first_data_sector = reserved_sector_count + (table_count * fat_size) + root_dir_sectors; + let first_fat_sector = reserved_sector_count; + let data_sectors = total_sectors - (reserved_sector_count + (table_count * fat_size) + root_dir_sectors); + let total_clusters = data_sectors / sectors_per_cluster; + let fat_type = FatFileSystem::fat_type_from_clusters(total_clusters); + + let fs = FatFileSystem { + fat_type: fat_type, + root_cluster: root_cluster, + volume_id: volume_id, + volume_label: str::from_utf8(&volume_label).unwrap().to_string(), + first_data_sector: first_data_sector, + first_fat_sector: first_fat_sector, + }; + + println!("fat_type {:?}", fat_type); + println!("fat_info {}", fat_info); + println!("root_cluster {}", root_cluster); + println!("volume_id {}", volume_id); + println!("oem_name {}", str::from_utf8(&oem_name).unwrap()); + println!("volume_label {}", str::from_utf8(&volume_label).unwrap()); + println!("fat_type_label {}", str::from_utf8(&fat_type_label).unwrap()); + Ok(fs) + } +} + +fn fat_test() -> io::Result<()> { + let file = File::open("resources/floppy.img")?; + let mut buf_rdr = BufReader::new(file); + FatFileSystem::new(&mut buf_rdr)?; + Ok(()) +} + +fn main() { + println!("Hello, world!"); + fat_test().unwrap(); +}