forked from M-Labs/rust-fatfs
Implement Seek trait for File and rewind method in Dir.
This commit is contained in:
parent
8d974a6ee4
commit
daa51e3540
14
src/dir.rs
14
src/dir.rs
@ -1,12 +1,12 @@
|
||||
use std::ascii::AsciiExt;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::{ErrorKind, SeekFrom};
|
||||
use std::str;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use chrono::{DateTime, Date, TimeZone, Local};
|
||||
|
||||
use fs::FatSharedStateRef;
|
||||
use fs::{FatSharedStateRef, ReadSeek};
|
||||
use file::FatFile;
|
||||
|
||||
bitflags! {
|
||||
@ -103,17 +103,18 @@ impl FatDirEntry {
|
||||
}
|
||||
|
||||
pub struct FatDir {
|
||||
rdr: Box<Read>,
|
||||
rdr: Box<ReadSeek>,
|
||||
state: FatSharedStateRef,
|
||||
}
|
||||
|
||||
impl FatDir {
|
||||
|
||||
pub(crate) fn new(rdr: Box<Read>, state: FatSharedStateRef) -> FatDir {
|
||||
pub(crate) fn new(rdr: Box<ReadSeek>, state: FatSharedStateRef) -> FatDir {
|
||||
FatDir { rdr, state }
|
||||
}
|
||||
|
||||
pub fn list(&mut self) -> io::Result<Vec<FatDirEntry>> {
|
||||
self.rewind();
|
||||
let mut entries = Vec::new();
|
||||
loop {
|
||||
let entry = self.read_dir_entry()?;
|
||||
@ -132,6 +133,10 @@ impl FatDir {
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
pub fn rewind(&mut self) {
|
||||
self.rdr.seek(SeekFrom::Start(0)).unwrap();
|
||||
}
|
||||
|
||||
fn read_dir_entry(&mut self) -> io::Result<FatDirEntry> {
|
||||
let mut name = [0; 11];
|
||||
self.rdr.read(&mut name)?;
|
||||
@ -161,7 +166,6 @@ impl FatDir {
|
||||
}
|
||||
|
||||
fn find_entry(&mut self, name: &str) -> io::Result<FatDirEntry> {
|
||||
// FIXME: we should seek to beggining here
|
||||
let entries: Vec<FatDirEntry> = self.list()?;
|
||||
for e in entries {
|
||||
if e.get_name().eq_ignore_ascii_case(name) {
|
||||
|
25
src/file.rs
25
src/file.rs
@ -1,6 +1,6 @@
|
||||
use std::cmp;
|
||||
use std::io::prelude::*;
|
||||
use std::io::SeekFrom;
|
||||
use std::io::{SeekFrom, ErrorKind};
|
||||
use std::io;
|
||||
|
||||
use fs::FatSharedStateRef;
|
||||
@ -54,3 +54,26 @@ impl Read for FatFile {
|
||||
Ok(buf_offset)
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for FatFile {
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
let new_offset = match pos {
|
||||
SeekFrom::Current(x) => self.offset as i64 + x,
|
||||
SeekFrom::Start(x) => x as i64,
|
||||
SeekFrom::End(x) => self.size.unwrap() as i64 + x,
|
||||
};
|
||||
if new_offset < 0 || (self.size.is_some() && new_offset as u64 > self.size.unwrap() as u64) {
|
||||
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
||||
}
|
||||
let cluster_size = self.state.borrow().get_cluster_size();
|
||||
let cluster_count = (new_offset / cluster_size as i64) as usize;
|
||||
let mut new_cluster = Some(self.first_cluster);
|
||||
let state = self.state.borrow_mut();
|
||||
for _ in 0..cluster_count {
|
||||
new_cluster = state.table.get_next_cluster(new_cluster.unwrap());
|
||||
}
|
||||
self.offset = new_offset as u32;
|
||||
self.current_cluster = new_cluster;
|
||||
Ok(self.offset as u64)
|
||||
}
|
||||
}
|
||||
|
18
src/fs.rs
18
src/fs.rs
@ -242,7 +242,7 @@ impl FatFileSystem {
|
||||
|
||||
pub fn root_dir(&mut self) -> FatDir {
|
||||
let state = self.state.borrow();
|
||||
let root_rdr: Box<Read> = match state.fat_type {
|
||||
let root_rdr: Box<ReadSeek> = match state.fat_type {
|
||||
FatType::Fat12 | FatType::Fat16 => Box::new(FatSlice::from_sectors(
|
||||
state.first_data_sector - state.root_dir_sectors, state.root_dir_sectors, self.state.clone())),
|
||||
_ => Box::new(FatFile::new(state.boot.bpb.root_cluster, None, self.state.clone())) // FIXME
|
||||
@ -280,3 +280,19 @@ impl Read for FatSlice {
|
||||
Ok(size)
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for FatSlice {
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
let new_offset = match pos {
|
||||
SeekFrom::Current(x) => self.offset as i64 + x,
|
||||
SeekFrom::Start(x) => x as i64,
|
||||
SeekFrom::End(x) => self.size as i64 + x,
|
||||
};
|
||||
if new_offset < 0 || new_offset as u64 > self.size {
|
||||
Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"))
|
||||
} else {
|
||||
self.offset = new_offset as u64;
|
||||
Ok(self.offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
extern crate rustfat;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::io::{BufReader, SeekFrom};
|
||||
use std::io::prelude::*;
|
||||
use std::str;
|
||||
|
||||
@ -15,16 +15,23 @@ fn test_img(name: &str) {
|
||||
let mut fs = FatFileSystem::new(Box::new(buf_rdr)).unwrap();
|
||||
let mut root_dir = fs.root_dir();
|
||||
let entries = root_dir.list().unwrap();
|
||||
assert_eq!(entries.len(), 3);
|
||||
assert_eq!(entries[0].get_name(), "LONG.TXT");
|
||||
assert_eq!(entries[1].get_name(), "SHORT.TXT");
|
||||
assert_eq!(entries[2].get_name(), "VERY");
|
||||
let names = entries.iter().map(|e| e.get_name()).collect::<Vec<String>>();
|
||||
assert_eq!(names, ["LONG.TXT", "SHORT.TXT", "VERY"]);
|
||||
// Try read again
|
||||
let entries = root_dir.list().unwrap();
|
||||
let names2 = entries.iter().map(|e| e.get_name()).collect::<Vec<String>>();
|
||||
assert_eq!(names2, names);
|
||||
|
||||
{
|
||||
let mut short_file = entries[1].get_file();
|
||||
let mut buf = Vec::new();
|
||||
short_file.read_to_end(&mut buf).unwrap();
|
||||
assert_eq!(str::from_utf8(&buf).unwrap(), TEST_TEXT);
|
||||
|
||||
short_file.seek(SeekFrom::Start(5)).unwrap();
|
||||
buf.clear();
|
||||
short_file.read_to_end(&mut buf).unwrap();
|
||||
assert_eq!(str::from_utf8(&buf).unwrap(), &TEST_TEXT[5..]);
|
||||
}
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user