Introduce FsOptions struct for providing options for library.

Old read_only flag in FileSystem::new was misleading.
This commit is contained in:
Rafał Harabień 2017-11-08 20:26:50 +01:00
parent 8a8ee3c51a
commit d5c37f2af5
7 changed files with 45 additions and 20 deletions

View File

@ -31,8 +31,8 @@ Put this in your crate root:
You can start using library now: You can start using library now:
let img_file = File::open("fat.img").unwrap(); let img_file = File::open("fat.img").unwrap();
let mut buf_stream = BufStream::new(img_file); let mut buf_stream = fatfs::BufStream::new(img_file);
let fs = fatfs::FileSystem::new(&mut buf_stream, true).unwrap(); let fs = fatfs::FileSystem::new(&mut buf_stream, fatfs::FsOptions::new()).unwrap();
let mut root_dir = fs.root_dir(); let mut root_dir = fs.root_dir();
let mut file = root_dir.create_file("hello.txt").unwrap(); let mut file = root_dir.create_file("hello.txt").unwrap();
file.write_all(b"Hello World!").unwrap(); file.write_all(b"Hello World!").unwrap();

View File

@ -5,12 +5,12 @@ use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::str; use std::str;
use fatfs::{FileSystem, BufStream}; use fatfs::{FileSystem, FsOptions, BufStream};
fn main() { fn main() {
let file = File::open("resources/fat32.img").unwrap(); let file = File::open("resources/fat32.img").unwrap();
let mut buf_rdr = BufStream::new(file); let mut buf_rdr = BufStream::new(file);
let fs = FileSystem::new(&mut buf_rdr, true).unwrap(); let fs = FileSystem::new(&mut buf_rdr, FsOptions::new()).unwrap();
let mut root_dir = fs.root_dir(); let mut root_dir = fs.root_dir();
let mut file = root_dir.open_file(&env::args().nth(1).unwrap()).unwrap(); let mut file = root_dir.open_file(&env::args().nth(1).unwrap()).unwrap();
let mut buf = vec![]; let mut buf = vec![];

View File

@ -5,7 +5,7 @@ use std::env;
use std::fs::File; use std::fs::File;
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use fatfs::{FileSystem, BufStream}; use fatfs::{FileSystem, FsOptions, BufStream};
fn format_file_size(size: u64) -> String { fn format_file_size(size: u64) -> String {
const KB: u64 = 1024; const KB: u64 = 1024;
@ -25,7 +25,7 @@ fn format_file_size(size: u64) -> String {
fn main() { fn main() {
let file = File::open("resources/fat32.img").unwrap(); let file = File::open("resources/fat32.img").unwrap();
let mut buf_rdr = BufStream::new(file); let mut buf_rdr = BufStream::new(file);
let fs = FileSystem::new(&mut buf_rdr, true).unwrap(); let fs = FileSystem::new(&mut buf_rdr, FsOptions::new()).unwrap();
let mut root_dir = fs.root_dir(); let mut root_dir = fs.root_dir();
let dir = match env::args().nth(1) { let dir = match env::args().nth(1) {
None => root_dir, None => root_dir,

View File

@ -194,7 +194,7 @@ impl<'a, 'b> Read for File<'a, 'b> {
self.current_cluster = Some(current_cluster); self.current_cluster = Some(current_cluster);
match self.entry { match self.entry {
Some(ref mut e) if !self.fs.read_only => e.reset_accessed(), Some(ref mut e) if self.fs.options.update_accessed_date => e.reset_accessed(),
_ => {}, _ => {},
} }
Ok(read_bytes) Ok(read_bytes)

View File

@ -129,6 +129,14 @@ impl BiosParameterBlock {
} }
Ok(bpb) Ok(bpb)
} }
fn mirroring_enabled(&self) -> bool {
self.extended_flags & 0x80 == 0
}
fn active_fat(&self) -> u16 {
self.extended_flags & 0x0F
}
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -169,12 +177,32 @@ impl Default for BootRecord {
} }
} }
/// FAT filesystem options.
#[derive(Debug, Clone, Copy)]
pub struct FsOptions {
pub(crate) update_accessed_date: bool,
}
impl FsOptions {
pub fn new() -> Self {
FsOptions {
update_accessed_date: false,
}
}
/// If enabled library updates accessed date field in directory entry when reading
pub fn update_accessed_date(mut self, enabled: bool) -> Self {
self.update_accessed_date = enabled;
self
}
}
pub(crate) type FileSystemRef<'a, 'b: 'a> = &'a FileSystem<'b>; pub(crate) type FileSystemRef<'a, 'b: 'a> = &'a FileSystem<'b>;
/// FAT filesystem main struct. /// FAT filesystem main struct.
pub struct FileSystem<'a> { pub struct FileSystem<'a> {
pub(crate) disk: RefCell<&'a mut ReadWriteSeek>, pub(crate) disk: RefCell<&'a mut ReadWriteSeek>,
pub(crate) read_only: bool, pub(crate) options: FsOptions,
fat_type: FatType, fat_type: FatType,
bpb: BiosParameterBlock, bpb: BiosParameterBlock,
first_data_sector: u32, first_data_sector: u32,
@ -184,12 +212,9 @@ pub struct FileSystem<'a> {
impl <'a> FileSystem<'a> { impl <'a> FileSystem<'a> {
/// Creates new filesystem object instance. /// Creates new filesystem object instance.
/// ///
/// read_only argument is a hint for library. It doesnt prevent user from writing to file.
/// For now it prevents accessed date field automatic update in dir entry.
///
/// Note: creating multiple filesystem objects with one underlying device/disk image can /// Note: creating multiple filesystem objects with one underlying device/disk image can
/// cause filesystem corruption. /// cause filesystem corruption.
pub fn new<T: ReadWriteSeek>(disk: &'a mut T, read_only: bool) -> io::Result<FileSystem<'a>> { pub fn new<T: ReadWriteSeek>(disk: &'a mut T, options: FsOptions) -> io::Result<FileSystem<'a>> {
let bpb = { let bpb = {
let boot = BootRecord::deserialize(disk)?; let boot = BootRecord::deserialize(disk)?;
if boot.boot_sig != [0x55, 0xAA] { if boot.boot_sig != [0x55, 0xAA] {
@ -214,7 +239,7 @@ impl <'a> FileSystem<'a> {
Ok(FileSystem { Ok(FileSystem {
disk: RefCell::new(disk), disk: RefCell::new(disk),
read_only, options,
fat_type, fat_type,
bpb: bpb, bpb: bpb,
first_data_sector, first_data_sector,
@ -272,11 +297,11 @@ impl <'a> FileSystem<'a> {
let sectors_per_fat = let sectors_per_fat =
if self.bpb.sectors_per_fat_16 == 0 { self.bpb.sectors_per_fat_32 } if self.bpb.sectors_per_fat_16 == 0 { self.bpb.sectors_per_fat_32 }
else { self.bpb.sectors_per_fat_16 as u32 }; else { self.bpb.sectors_per_fat_16 as u32 };
let mirroring_enabled = self.bpb.extended_flags & 0x80 == 0; let mirroring_enabled = self.bpb.mirroring_enabled();
let (fat_first_sector, mirrors) = if mirroring_enabled { let (fat_first_sector, mirrors) = if mirroring_enabled {
(self.bpb.reserved_sectors as u32, self.bpb.fats) (self.bpb.reserved_sectors as u32, self.bpb.fats)
} else { } else {
let active_fat = (self.bpb.extended_flags & 0x0F) as u32; let active_fat = self.bpb.active_fat() as u32;
let fat_first_sector = (self.bpb.reserved_sectors as u32) + active_fat * sectors_per_fat; let fat_first_sector = (self.bpb.reserved_sectors as u32) + active_fat * sectors_per_fat;
(fat_first_sector, 1) (fat_first_sector, 1)
}; };

View File

@ -6,7 +6,7 @@ use std::io::SeekFrom;
use std::io::prelude::*; use std::io::prelude::*;
use std::str; use std::str;
use fatfs::{FileSystem, FatType, DirEntry, BufStream}; use fatfs::{FileSystem, FsOptions, FatType, DirEntry, BufStream};
const TEST_TEXT: &str = "Rust is cool!\n"; const TEST_TEXT: &str = "Rust is cool!\n";
const FAT12_IMG: &str = "resources/fat12.img"; const FAT12_IMG: &str = "resources/fat12.img";
@ -17,7 +17,7 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str) {
let _ = env_logger::init(); let _ = env_logger::init();
let file = fs::File::open(filename).unwrap(); let file = fs::File::open(filename).unwrap();
let mut buf_file = BufStream::new(file); let mut buf_file = BufStream::new(file);
let fs = FileSystem::new(&mut buf_file, true).unwrap(); let fs = FileSystem::new(&mut buf_file, FsOptions::new()).unwrap();
f(fs); f(fs);
} }

View File

@ -6,8 +6,7 @@ use std::io::prelude::*;
use std::io; use std::io;
use std::str; use std::str;
use fatfs::FileSystem; use fatfs::{FileSystem, FsOptions, BufStream};
use fatfs::BufStream;
const FAT12_IMG: &str = "fat12.img"; const FAT12_IMG: &str = "fat12.img";
const FAT16_IMG: &str = "fat16.img"; const FAT16_IMG: &str = "fat16.img";
@ -25,7 +24,8 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str, test_seq: u32) {
{ {
let file = fs::OpenOptions::new().read(true).write(true).open(&tmp_path).unwrap(); let file = fs::OpenOptions::new().read(true).write(true).open(&tmp_path).unwrap();
let mut buf_file = BufStream::new(file); let mut buf_file = BufStream::new(file);
let fs = FileSystem::new(&mut buf_file, false).unwrap(); let options = FsOptions::new().update_accessed_date(true);
let fs = FileSystem::new(&mut buf_file, options).unwrap();
f(fs); f(fs);
} }
fs::remove_file(tmp_path).unwrap(); fs::remove_file(tmp_path).unwrap();