From d5c37f2af5f07c0318dd9c530f68204d358290f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Harabie=C5=84?= Date: Wed, 8 Nov 2017 20:26:50 +0100 Subject: [PATCH] Introduce FsOptions struct for providing options for library. Old read_only flag in FileSystem::new was misleading. --- README.md | 4 ++-- examples/cat.rs | 4 ++-- examples/ls.rs | 4 ++-- src/file.rs | 2 +- src/fs.rs | 41 +++++++++++++++++++++++++++++++++-------- tests/read.rs | 4 ++-- tests/write.rs | 6 +++--- 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a48c418..c78289a 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Put this in your crate root: You can start using library now: let img_file = File::open("fat.img").unwrap(); - let mut buf_stream = BufStream::new(img_file); - let fs = fatfs::FileSystem::new(&mut buf_stream, true).unwrap(); + let mut buf_stream = fatfs::BufStream::new(img_file); + let fs = fatfs::FileSystem::new(&mut buf_stream, fatfs::FsOptions::new()).unwrap(); let mut root_dir = fs.root_dir(); let mut file = root_dir.create_file("hello.txt").unwrap(); file.write_all(b"Hello World!").unwrap(); diff --git a/examples/cat.rs b/examples/cat.rs index d89adf7..2592f46 100644 --- a/examples/cat.rs +++ b/examples/cat.rs @@ -5,12 +5,12 @@ use std::fs::File; use std::io::prelude::*; use std::str; -use fatfs::{FileSystem, BufStream}; +use fatfs::{FileSystem, FsOptions, BufStream}; fn main() { let file = File::open("resources/fat32.img").unwrap(); 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 file = root_dir.open_file(&env::args().nth(1).unwrap()).unwrap(); let mut buf = vec![]; diff --git a/examples/ls.rs b/examples/ls.rs index b23e3c6..8281f2f 100644 --- a/examples/ls.rs +++ b/examples/ls.rs @@ -5,7 +5,7 @@ use std::env; use std::fs::File; use chrono::{DateTime, Local}; -use fatfs::{FileSystem, BufStream}; +use fatfs::{FileSystem, FsOptions, BufStream}; fn format_file_size(size: u64) -> String { const KB: u64 = 1024; @@ -25,7 +25,7 @@ fn format_file_size(size: u64) -> String { fn main() { let file = File::open("resources/fat32.img").unwrap(); 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 dir = match env::args().nth(1) { None => root_dir, diff --git a/src/file.rs b/src/file.rs index 41b8956..5ef3bb7 100644 --- a/src/file.rs +++ b/src/file.rs @@ -194,7 +194,7 @@ impl<'a, 'b> Read for File<'a, 'b> { self.current_cluster = Some(current_cluster); 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) diff --git a/src/fs.rs b/src/fs.rs index c5fb0e0..57a4b6e 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -129,6 +129,14 @@ impl BiosParameterBlock { } Ok(bpb) } + + fn mirroring_enabled(&self) -> bool { + self.extended_flags & 0x80 == 0 + } + + fn active_fat(&self) -> u16 { + self.extended_flags & 0x0F + } } #[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>; /// FAT filesystem main struct. pub struct FileSystem<'a> { pub(crate) disk: RefCell<&'a mut ReadWriteSeek>, - pub(crate) read_only: bool, + pub(crate) options: FsOptions, fat_type: FatType, bpb: BiosParameterBlock, first_data_sector: u32, @@ -184,12 +212,9 @@ pub struct FileSystem<'a> { impl <'a> FileSystem<'a> { /// 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 /// cause filesystem corruption. - pub fn new(disk: &'a mut T, read_only: bool) -> io::Result> { + pub fn new(disk: &'a mut T, options: FsOptions) -> io::Result> { let bpb = { let boot = BootRecord::deserialize(disk)?; if boot.boot_sig != [0x55, 0xAA] { @@ -214,7 +239,7 @@ impl <'a> FileSystem<'a> { Ok(FileSystem { disk: RefCell::new(disk), - read_only, + options, fat_type, bpb: bpb, first_data_sector, @@ -272,11 +297,11 @@ impl <'a> FileSystem<'a> { let sectors_per_fat = if self.bpb.sectors_per_fat_16 == 0 { self.bpb.sectors_per_fat_32 } 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 { (self.bpb.reserved_sectors as u32, self.bpb.fats) } 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; (fat_first_sector, 1) }; diff --git a/tests/read.rs b/tests/read.rs index 1661676..bad06e2 100644 --- a/tests/read.rs +++ b/tests/read.rs @@ -6,7 +6,7 @@ use std::io::SeekFrom; use std::io::prelude::*; 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 FAT12_IMG: &str = "resources/fat12.img"; @@ -17,7 +17,7 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str) { let _ = env_logger::init(); let file = fs::File::open(filename).unwrap(); 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); } diff --git a/tests/write.rs b/tests/write.rs index b23e43d..0fabc6b 100644 --- a/tests/write.rs +++ b/tests/write.rs @@ -6,8 +6,7 @@ use std::io::prelude::*; use std::io; use std::str; -use fatfs::FileSystem; -use fatfs::BufStream; +use fatfs::{FileSystem, FsOptions, BufStream}; const FAT12_IMG: &str = "fat12.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 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); } fs::remove_file(tmp_path).unwrap();