forked from M-Labs/rust-fatfs
Fix seek for directory backed file.
This commit is contained in:
parent
da76625759
commit
e2374c08cc
23
src/dir.rs
23
src/dir.rs
@ -37,6 +37,21 @@ impl <'a, 'b> Read for DirRawStream<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <'a, 'b> Write for DirRawStream<'a, 'b> {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
&mut DirRawStream::File(ref mut file) => file.write(buf),
|
||||||
|
&mut DirRawStream::Root(ref mut raw) => raw.write(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
&mut DirRawStream::File(ref mut file) => file.flush(),
|
||||||
|
&mut DirRawStream::Root(ref mut raw) => raw.flush(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl <'a, 'b> Seek for DirRawStream<'a, 'b> {
|
impl <'a, 'b> Seek for DirRawStream<'a, 'b> {
|
||||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
match self {
|
match self {
|
||||||
@ -89,8 +104,12 @@ impl DirFileEntryData {
|
|||||||
self.first_cluster_lo = (n & 0xFFFF) as u16;
|
self.first_cluster_lo = (n & 0xFFFF) as u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn size(&self) -> u32 {
|
pub(crate) fn size(&self) -> Option<u32> {
|
||||||
self.size
|
if self.is_file() {
|
||||||
|
Some(self.size)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_size(&mut self, size: u32) {
|
pub(crate) fn set_size(&mut self, size: u32) {
|
||||||
|
31
src/file.rs
31
src/file.rs
@ -32,10 +32,11 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_size(&mut self) {
|
fn update_size(&mut self) {
|
||||||
|
let offset = self.offset;
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) => {
|
Some(ref mut e) => {
|
||||||
if self.offset > e.data.size() {
|
if e.data.size().map_or(false, |s| offset > s) {
|
||||||
e.data.set_size(self.offset);
|
e.data.set_size(offset);
|
||||||
self.entry_dirty = true;
|
self.entry_dirty = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -44,9 +45,10 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn truncate(&mut self) -> io::Result<()> {
|
pub fn truncate(&mut self) -> io::Result<()> {
|
||||||
|
let offset = self.offset;
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref mut e) => {
|
Some(ref mut e) => {
|
||||||
if e.data.size() == self.offset {
|
if e.data.size().map_or(false, |s| offset == s) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,13 +110,7 @@ impl <'a, 'b> File<'a, 'b> {
|
|||||||
|
|
||||||
fn bytes_left_in_file(&self) -> Option<usize> {
|
fn bytes_left_in_file(&self) -> Option<usize> {
|
||||||
match self.entry {
|
match self.entry {
|
||||||
Some(ref e) => {
|
Some(ref e) => e.data.size().map(|s| (s - self.offset) as usize),
|
||||||
if e.data.is_file() {
|
|
||||||
Some((e.data.size() - self.offset) as usize)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,15 +249,26 @@ impl<'a, 'b> Seek for File<'a, 'b> {
|
|||||||
let mut new_pos = match pos {
|
let mut new_pos = match pos {
|
||||||
SeekFrom::Current(x) => self.offset as i64 + x,
|
SeekFrom::Current(x) => self.offset as i64 + x,
|
||||||
SeekFrom::Start(x) => x as i64,
|
SeekFrom::Start(x) => x as i64,
|
||||||
SeekFrom::End(x) => self.entry.iter().next().expect("cannot seek from end if size is unknown").data.size() as i64 + x,
|
SeekFrom::End(x) => self.entry.iter().next().map_or(None, |e| e.data.size()).expect("cannot seek from end if size is unknown") as i64 + x,
|
||||||
};
|
};
|
||||||
if new_pos < 0 {
|
if new_pos < 0 {
|
||||||
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
||||||
}
|
}
|
||||||
new_pos = match self.entry {
|
new_pos = match self.entry {
|
||||||
Some(ref e) => cmp::min(new_pos, e.data.size() as i64),
|
Some(ref e) => {
|
||||||
|
if e.data.size().map_or(false, |s| new_pos > s as i64) {
|
||||||
|
info!("seek beyond end of file");
|
||||||
|
e.data.size().unwrap() as i64 // safe
|
||||||
|
} else {
|
||||||
|
new_pos
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => new_pos,
|
_ => new_pos,
|
||||||
};
|
};
|
||||||
|
trace!("file seek {} -> {} - entry {:?}", self.offset, new_pos, self.entry);
|
||||||
|
if new_pos == self.offset as i64 {
|
||||||
|
return Ok(self.offset as u64);
|
||||||
|
}
|
||||||
let cluster_size = self.fs.get_cluster_size();
|
let cluster_size = self.fs.get_cluster_size();
|
||||||
let new_cluster = if new_pos == 0 {
|
let new_cluster = if new_pos == 0 {
|
||||||
None
|
None
|
||||||
|
Loading…
Reference in New Issue
Block a user