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::ascii::AsciiExt;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::ErrorKind;
|
use std::io::{ErrorKind, SeekFrom};
|
||||||
use std::str;
|
use std::str;
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use chrono::{DateTime, Date, TimeZone, Local};
|
use chrono::{DateTime, Date, TimeZone, Local};
|
||||||
|
|
||||||
use fs::FatSharedStateRef;
|
use fs::{FatSharedStateRef, ReadSeek};
|
||||||
use file::FatFile;
|
use file::FatFile;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
@ -103,17 +103,18 @@ impl FatDirEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct FatDir {
|
pub struct FatDir {
|
||||||
rdr: Box<Read>,
|
rdr: Box<ReadSeek>,
|
||||||
state: FatSharedStateRef,
|
state: FatSharedStateRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FatDir {
|
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 }
|
FatDir { rdr, state }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(&mut self) -> io::Result<Vec<FatDirEntry>> {
|
pub fn list(&mut self) -> io::Result<Vec<FatDirEntry>> {
|
||||||
|
self.rewind();
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
let entry = self.read_dir_entry()?;
|
let entry = self.read_dir_entry()?;
|
||||||
@ -132,6 +133,10 @@ impl FatDir {
|
|||||||
Ok(entries)
|
Ok(entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rewind(&mut self) {
|
||||||
|
self.rdr.seek(SeekFrom::Start(0)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn read_dir_entry(&mut self) -> io::Result<FatDirEntry> {
|
fn read_dir_entry(&mut self) -> io::Result<FatDirEntry> {
|
||||||
let mut name = [0; 11];
|
let mut name = [0; 11];
|
||||||
self.rdr.read(&mut name)?;
|
self.rdr.read(&mut name)?;
|
||||||
@ -161,7 +166,6 @@ impl FatDir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_entry(&mut self, name: &str) -> io::Result<FatDirEntry> {
|
fn find_entry(&mut self, name: &str) -> io::Result<FatDirEntry> {
|
||||||
// FIXME: we should seek to beggining here
|
|
||||||
let entries: Vec<FatDirEntry> = self.list()?;
|
let entries: Vec<FatDirEntry> = self.list()?;
|
||||||
for e in entries {
|
for e in entries {
|
||||||
if e.get_name().eq_ignore_ascii_case(name) {
|
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::cmp;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::SeekFrom;
|
use std::io::{SeekFrom, ErrorKind};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use fs::FatSharedStateRef;
|
use fs::FatSharedStateRef;
|
||||||
@ -54,3 +54,26 @@ impl Read for FatFile {
|
|||||||
Ok(buf_offset)
|
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 {
|
pub fn root_dir(&mut self) -> FatDir {
|
||||||
let state = self.state.borrow();
|
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(
|
FatType::Fat12 | FatType::Fat16 => Box::new(FatSlice::from_sectors(
|
||||||
state.first_data_sector - state.root_dir_sectors, state.root_dir_sectors, self.state.clone())),
|
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
|
_ => Box::new(FatFile::new(state.boot.bpb.root_cluster, None, self.state.clone())) // FIXME
|
||||||
@ -280,3 +280,19 @@ impl Read for FatSlice {
|
|||||||
Ok(size)
|
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;
|
extern crate rustfat;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::{BufReader, SeekFrom};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
@ -15,16 +15,23 @@ fn test_img(name: &str) {
|
|||||||
let mut fs = FatFileSystem::new(Box::new(buf_rdr)).unwrap();
|
let mut fs = FatFileSystem::new(Box::new(buf_rdr)).unwrap();
|
||||||
let mut root_dir = fs.root_dir();
|
let mut root_dir = fs.root_dir();
|
||||||
let entries = root_dir.list().unwrap();
|
let entries = root_dir.list().unwrap();
|
||||||
assert_eq!(entries.len(), 3);
|
let names = entries.iter().map(|e| e.get_name()).collect::<Vec<String>>();
|
||||||
assert_eq!(entries[0].get_name(), "LONG.TXT");
|
assert_eq!(names, ["LONG.TXT", "SHORT.TXT", "VERY"]);
|
||||||
assert_eq!(entries[1].get_name(), "SHORT.TXT");
|
// Try read again
|
||||||
assert_eq!(entries[2].get_name(), "VERY");
|
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 short_file = entries[1].get_file();
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
short_file.read_to_end(&mut buf).unwrap();
|
short_file.read_to_end(&mut buf).unwrap();
|
||||||
assert_eq!(str::from_utf8(&buf).unwrap(), TEST_TEXT);
|
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