diff --git a/src/dir.rs b/src/dir.rs index fe6d8b4..fb84a1c 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -1,6 +1,5 @@ use std::io::prelude::*; use std::io; -use std::io::Cursor; use std::str; use byteorder::{LittleEndian, ReadBytesExt}; use chrono::{DateTime, Date, TimeZone, Local}; @@ -96,46 +95,37 @@ impl FatDir { pub fn list(&mut self) -> io::Result> { let mut entries = Vec::new(); - let cluster_size = self.state.borrow().get_cluster_size() as usize; - let mut buf = vec![0; cluster_size]; loop { - let size = self.rdr.read(&mut buf)?; - if size == 0 { - break; + let entry = self.read_dir_entry()?; + if entry.name[0] == 0 { + break; // end of dir } - - let mut cur = Cursor::new(&buf[..size]); - loop { - let entry = self.read_dir_entry(&mut cur)?; - if entry.name[0] == 0 { - break; // end of dir - } - if entry.name[0] == 0xE5 { - continue; // deleted - } - entries.push(entry); + if entry.name[0] == 0xE5 { + continue; // deleted } + entries.push(entry); } Ok(entries) } - fn read_dir_entry(&self, rdr: &mut Read) -> io::Result { + fn read_dir_entry(&mut self) -> io::Result { let mut name = [0; 11]; - rdr.read(&mut name)?; + self.rdr.read(&mut name)?; + let attrs = FatFileAttributes::from_bits(self.rdr.read_u8()?).expect("invalid attributes"); Ok(FatDirEntry { - name: name, - attrs: FatFileAttributes::from_bits(rdr.read_u8()?).unwrap(), - reserved_0: rdr.read_u8()?, - create_time_0: rdr.read_u8()?, - create_time_1: rdr.read_u16::()?, - create_date: rdr.read_u16::()?, - access_date: rdr.read_u16::()?, - first_cluster_hi: rdr.read_u16::()?, - modify_time: rdr.read_u16::()?, - modify_date: rdr.read_u16::()?, - first_cluster_lo: rdr.read_u16::()?, - size: rdr.read_u32::()?, + name, + attrs, + reserved_0: self.rdr.read_u8()?, + create_time_0: self.rdr.read_u8()?, + create_time_1: self.rdr.read_u16::()?, + create_date: self.rdr.read_u16::()?, + access_date: self.rdr.read_u16::()?, + first_cluster_hi: self.rdr.read_u16::()?, + modify_time: self.rdr.read_u16::()?, + modify_date: self.rdr.read_u16::()?, + first_cluster_lo: self.rdr.read_u16::()?, + size: self.rdr.read_u32::()?, state: self.state.clone(), }) } diff --git a/src/file.rs b/src/file.rs index c91d6d6..cf58527 100644 --- a/src/file.rs +++ b/src/file.rs @@ -7,35 +7,50 @@ use fs::FatSharedStateRef; #[allow(dead_code)] pub struct FatFile { - first_sector: u32, + first_cluster: u32, size: u32, offset: u32, + current_cluster: Option, state: FatSharedStateRef, } impl FatFile { pub(crate) fn new(first_cluster: u32, size: u32, state: FatSharedStateRef) -> FatFile { - let first_sector = state.borrow().sector_from_cluster(first_cluster); FatFile { - first_sector, size, state, offset: 0, + first_cluster, size, state, + current_cluster: Some(first_cluster), + offset: 0, } } } impl Read for FatFile { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let (offset, read_size) = { - let state = self.state.borrow(); - let offset = state.offset_from_sector(self.first_sector) + self.offset as u64; - let mut read_size = cmp::min((self.size - self.offset) as usize, buf.len()); - // FIXME: allow only one cluster for now - read_size = cmp::min(read_size, (state.get_cluster_size() - self.offset) as usize); - (offset, read_size) - }; + let mut buf_offset: usize = 0; + let cluster_size = self.state.borrow().get_cluster_size(); let mut state = self.state.borrow_mut(); - state.rdr.seek(SeekFrom::Start(offset))?; - let size = state.rdr.read(&mut buf[..read_size])?; - self.offset += size as u32; - Ok(size) + loop { + let offset_in_cluster = self.offset % cluster_size; + let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize; + let bytes_left_in_file = (self.size - self.offset) as usize; + let bytes_left_in_buf = buf.len() - buf_offset; + let read_size = cmp::min(cmp::min(bytes_left_in_file, bytes_left_in_cluster), bytes_left_in_buf); + if read_size == 0 { + break; + } + let current_cluster = self.current_cluster.unwrap(); + let offset_in_fs = state.offset_from_cluster(current_cluster) + (offset_in_cluster as u64); + state.rdr.seek(SeekFrom::Start(offset_in_fs))?; + let read_bytes = state.rdr.read(&mut buf[buf_offset..buf_offset+read_size])?; + if read_bytes == 0 { + break; + } + self.offset += read_bytes as u32; + buf_offset += read_bytes; + if self.offset % cluster_size == 0 { + self.current_cluster = state.table.get_next_cluster(current_cluster); + } + } + Ok(buf_offset) } } diff --git a/src/fs.rs b/src/fs.rs index d0d24fe..ed453e8 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -48,11 +48,8 @@ impl FatSharedState { self.boot.bpb.sectors_per_cluster as u32 * self.boot.bpb.bytes_per_sector as u32 } - pub(crate) fn get_root_dir_sector(&self) -> u32 { - match self.fat_type { - FatType::Fat12 | FatType::Fat16 => self.first_data_sector - self.root_dir_sectors, - _ => self.sector_from_cluster(self.boot.bpb.root_cluster) - } + pub(crate) fn offset_from_cluster(&self, cluser: u32) -> u64 { + self.offset_from_sector(self.sector_from_cluster(cluser)) } } @@ -242,10 +239,6 @@ impl FatFileSystem { Ok(boot) } - // pub(crate) fn offset_from_cluster(&self, cluser: u32) -> u64 { - // self.offset_from_sector(self.sector_from_cluster(cluser)) - // } - pub fn root_dir(&mut self) -> FatDir { let state = self.state.borrow(); let root_rdr: Box = match state.fat_type { @@ -277,12 +270,8 @@ impl FatSlice { impl Read for FatSlice { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let (offset, read_size) = { - let state = self.state.borrow(); - let offset = self.begin + self.offset; - let mut read_size = cmp::min((self.size - self.offset) as usize, buf.len()); - (offset, read_size) - }; + let offset = self.begin + self.offset; + let read_size = cmp::min((self.size - self.offset) as usize, buf.len()); let mut state = self.state.borrow_mut(); state.rdr.seek(SeekFrom::Start(offset))?; let size = state.rdr.read(&mut buf[..read_size])?;