forked from M-Labs/rust-fatfs
Allow seeking beyond end of file as documented in Seek trait.
Also fix possible panic when seeking in file without clusters.
This commit is contained in:
parent
120c9b035c
commit
d32ae0eef9
18
src/file.rs
18
src/file.rs
@ -29,15 +29,18 @@ impl <'a, 'b> Read for File<'a, 'b> {
|
|||||||
let mut buf_offset: usize = 0;
|
let mut buf_offset: usize = 0;
|
||||||
let cluster_size = self.fs.get_cluster_size();
|
let cluster_size = self.fs.get_cluster_size();
|
||||||
loop {
|
loop {
|
||||||
|
let current_cluster = match self.current_cluster {
|
||||||
|
Some(n) => n,
|
||||||
|
None => break,
|
||||||
|
};
|
||||||
let offset_in_cluster = self.offset % cluster_size;
|
let offset_in_cluster = self.offset % cluster_size;
|
||||||
let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
|
let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
|
||||||
let bytes_left_in_file = self.size.map(|size| (size - self.offset) as usize).unwrap_or(bytes_left_in_cluster);
|
let bytes_left_in_file = self.size.map(|size| (size - self.offset) as usize).unwrap_or(bytes_left_in_cluster);
|
||||||
let bytes_left_in_buf = buf.len() - buf_offset;
|
let bytes_left_in_buf = buf.len() - buf_offset;
|
||||||
let read_size = cmp::min(cmp::min(bytes_left_in_buf, bytes_left_in_cluster), bytes_left_in_file);
|
let read_size = cmp::min(cmp::min(bytes_left_in_buf, bytes_left_in_cluster), bytes_left_in_file);
|
||||||
if read_size == 0 || self.current_cluster.is_none() {
|
if read_size == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let current_cluster = self.current_cluster.unwrap();
|
|
||||||
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
|
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
|
||||||
let read_bytes = {
|
let read_bytes = {
|
||||||
let mut rdr = self.fs.rdr.borrow_mut();
|
let mut rdr = self.fs.rdr.borrow_mut();
|
||||||
@ -67,19 +70,24 @@ impl <'a, 'b> Seek for File<'a, 'b> {
|
|||||||
let new_offset = match pos {
|
let new_offset = 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.size.unwrap() as i64 + x,
|
SeekFrom::End(x) => self.size.expect("cannot seek from end if size is unknown") as i64 + x,
|
||||||
};
|
};
|
||||||
if new_offset < 0 || (self.size.is_some() && new_offset as u64 > self.size.unwrap() as u64) {
|
if new_offset < 0 {
|
||||||
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
|
||||||
}
|
}
|
||||||
let cluster_size = self.fs.get_cluster_size();
|
let cluster_size = self.fs.get_cluster_size();
|
||||||
let cluster_count = (new_offset / cluster_size as i64) as usize;
|
let cluster_count = (new_offset / cluster_size as i64) as usize;
|
||||||
let new_cluster = if cluster_count > 0 {
|
let new_cluster = if cluster_count > 0 {
|
||||||
match self.fs.cluster_iter(self.first_cluster.unwrap()).skip(cluster_count).next() {
|
match self.first_cluster {
|
||||||
|
Some(n) => {
|
||||||
|
match self.fs.cluster_iter(n).skip(cluster_count).next() {
|
||||||
Some(Err(err)) => return Err(err),
|
Some(Err(err)) => return Err(err),
|
||||||
Some(Ok(n)) => Some(n),
|
Some(Ok(n)) => Some(n),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.first_cluster
|
self.first_cluster
|
||||||
};
|
};
|
||||||
|
@ -53,10 +53,14 @@ fn test_read_seek_short_file(fs: FileSystem) {
|
|||||||
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();
|
assert_eq!(short_file.seek(SeekFrom::Start(5)).unwrap(), 5);
|
||||||
let mut buf2 = [0; 5];
|
let mut buf2 = [0; 5];
|
||||||
short_file.read_exact(&mut buf2).unwrap();
|
short_file.read_exact(&mut buf2).unwrap();
|
||||||
assert_eq!(str::from_utf8(&buf2).unwrap(), &TEST_TEXT[5..10]);
|
assert_eq!(str::from_utf8(&buf2).unwrap(), &TEST_TEXT[5..10]);
|
||||||
|
|
||||||
|
assert_eq!(short_file.seek(SeekFrom::Start(1000)).unwrap(), 1000);
|
||||||
|
let mut buf2 = [0; 5];
|
||||||
|
assert_eq!(short_file.read(&mut buf2).unwrap(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -81,7 +85,7 @@ fn test_read_long_file(fs: FileSystem) {
|
|||||||
long_file.read_to_end(&mut buf).unwrap();
|
long_file.read_to_end(&mut buf).unwrap();
|
||||||
assert_eq!(str::from_utf8(&buf).unwrap(), TEST_TEXT.repeat(1000));
|
assert_eq!(str::from_utf8(&buf).unwrap(), TEST_TEXT.repeat(1000));
|
||||||
|
|
||||||
long_file.seek(SeekFrom::Start(2017)).unwrap();
|
assert_eq!(long_file.seek(SeekFrom::Start(2017)).unwrap(), 2017);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
let mut buf2 = [0; 10];
|
let mut buf2 = [0; 10];
|
||||||
long_file.read_exact(&mut buf2).unwrap();
|
long_file.read_exact(&mut buf2).unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user