Improve code style using rustfmt

This commit is contained in:
Rafał Harabień 2018-06-28 18:13:07 +02:00
parent 98c0fa528c
commit 30f3f96537
13 changed files with 332 additions and 263 deletions

View File

@ -1,12 +1,12 @@
extern crate chrono;
extern crate fatfs;
extern crate fscommon;
extern crate chrono;
use std::env;
use std::fs::File;
use std::io;
use chrono::{DateTime, Local};
use chrono::{DateTime, Local};
use fatfs::{FileSystem, FsOptions};
use fscommon::BufStream;

View File

@ -2,6 +2,7 @@ extern crate fatfs;
extern crate fscommon;
use std::{fs, io};
use fatfs::{FileSystem, FsOptions};
use fscommon::{BufStream, StreamSlice};

View File

@ -13,7 +13,7 @@ fn main() -> io::Result<()> {
Err(err) => {
println!("Failed to open image!");
return Err(err);
}
},
};
let buf_stream = BufStream::new(img_file);
let options = FsOptions::new().update_accessed_date(true);

7
rustfmt.toml Normal file
View File

@ -0,0 +1,7 @@
max_width = 140
match_block_trailing_comma = true
use_field_init_shorthand = true
ignore = [
"src/byteorder_core_io.rs",
]
unstable_features = true

View File

@ -1,5 +1,5 @@
use io::{self, Result};
use core::slice;
use io::{self, Result};
use byteorder::ByteOrder;
@ -618,10 +618,7 @@ pub trait ReadBytesExt: io::Read {
/// ```
#[cfg(feature = "i128")]
#[inline]
fn read_u128_into<T: ByteOrder>(
&mut self,
dst: &mut [u128],
) -> Result<()> {
fn read_u128_into<T: ByteOrder>(&mut self, dst: &mut [u128]) -> Result<()> {
{
let mut buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf));
@ -768,10 +765,7 @@ pub trait ReadBytesExt: io::Read {
/// ```
#[cfg(feature = "i128")]
#[inline]
fn read_i128_into<T: ByteOrder>(
&mut self,
dst: &mut [i128],
) -> Result<()> {
fn read_i128_into<T: ByteOrder>(&mut self, dst: &mut [i128]) -> Result<()> {
{
let mut buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf));
@ -812,10 +806,7 @@ pub trait ReadBytesExt: io::Read {
/// assert_eq!([f32::consts::PI, 1.0], dst);
/// ```
#[inline]
fn read_f32_into<T: ByteOrder>(
&mut self,
dst: &mut [f32],
) -> Result<()> {
fn read_f32_into<T: ByteOrder>(&mut self, dst: &mut [f32]) -> Result<()> {
{
let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf));
@ -861,10 +852,7 @@ pub trait ReadBytesExt: io::Read {
/// ```
#[inline]
#[deprecated(since = "1.2.0", note = "please use `read_f32_into` instead")]
fn read_f32_into_unchecked<T: ByteOrder>(
&mut self,
dst: &mut [f32],
) -> Result<()> {
fn read_f32_into_unchecked<T: ByteOrder>(&mut self, dst: &mut [f32]) -> Result<()> {
self.read_f32_into::<T>(dst)
}
@ -900,10 +888,7 @@ pub trait ReadBytesExt: io::Read {
/// assert_eq!([f64::consts::PI, 1.0], dst);
/// ```
#[inline]
fn read_f64_into<T: ByteOrder>(
&mut self,
dst: &mut [f64],
) -> Result<()> {
fn read_f64_into<T: ByteOrder>(&mut self, dst: &mut [f64]) -> Result<()> {
{
let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf));
@ -955,10 +940,7 @@ pub trait ReadBytesExt: io::Read {
/// ```
#[inline]
#[deprecated(since = "1.2.0", note = "please use `read_f64_into` instead")]
fn read_f64_into_unchecked<T: ByteOrder>(
&mut self,
dst: &mut [f64],
) -> Result<()> {
fn read_f64_into_unchecked<T: ByteOrder>(&mut self, dst: &mut [f64]) -> Result<()> {
self.read_f64_into::<T>(dst)
}
}
@ -1159,11 +1141,7 @@ pub trait WriteBytesExt: io::Write {
/// If the given integer is not representable in the given number of bytes,
/// this method panics. If `nbytes > 8`, this method panics.
#[inline]
fn write_uint<T: ByteOrder>(
&mut self,
n: u64,
nbytes: usize,
) -> Result<()> {
fn write_uint<T: ByteOrder>(&mut self, n: u64, nbytes: usize) -> Result<()> {
let mut buf = [0; 8];
T::write_uint(&mut buf, n, nbytes);
self.write_all(&buf[0..nbytes])
@ -1182,11 +1160,7 @@ pub trait WriteBytesExt: io::Write {
/// If the given integer is not representable in the given number of bytes,
/// this method panics. If `nbytes > 8`, this method panics.
#[inline]
fn write_int<T: ByteOrder>(
&mut self,
n: i64,
nbytes: usize,
) -> Result<()> {
fn write_int<T: ByteOrder>(&mut self, n: i64, nbytes: usize) -> Result<()> {
let mut buf = [0; 8];
T::write_int(&mut buf, n, nbytes);
self.write_all(&buf[0..nbytes])
@ -1198,11 +1172,7 @@ pub trait WriteBytesExt: io::Write {
/// this method panics. If `nbytes > 16`, this method panics.
#[cfg(feature = "i128")]
#[inline]
fn write_uint128<T: ByteOrder>(
&mut self,
n: u128,
nbytes: usize,
) -> Result<()> {
fn write_uint128<T: ByteOrder>(&mut self, n: u128, nbytes: usize) -> Result<()> {
let mut buf = [0; 16];
T::write_uint128(&mut buf, n, nbytes);
self.write_all(&buf[0..nbytes])
@ -1214,11 +1184,7 @@ pub trait WriteBytesExt: io::Write {
/// this method panics. If `nbytes > 16`, this method panics.
#[cfg(feature = "i128")]
#[inline]
fn write_int128<T: ByteOrder>(
&mut self,
n: i128,
nbytes: usize,
) -> Result<()> {
fn write_int128<T: ByteOrder>(&mut self, n: i128, nbytes: usize) -> Result<()> {
let mut buf = [0; 16];
T::write_int128(&mut buf, n, nbytes);
self.write_all(&buf[0..nbytes])

View File

@ -1,20 +1,17 @@
#[cfg(feature = "alloc")]
use core::{slice, iter};
use core::{str, char, cmp, num};
use io::prelude::*;
use io;
use io::{ErrorKind, SeekFrom};
use fs::{FileSystem, DiskSlice, ReadWriteSeek};
use file::File;
use dir_entry::{DirEntry, DirEntryData, DirFileEntryData, DirLfnEntryData, FileAttributes, ShortName, DIR_ENTRY_SIZE};
#[cfg(feature = "alloc")]
use dir_entry::{LFN_PART_LEN, LFN_ENTRY_LAST_FLAG};
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::Vec;
use core::{char, cmp, num, str};
#[cfg(feature = "alloc")]
use core::{iter, slice};
use io;
use io::prelude::*;
use io::{ErrorKind, SeekFrom};
use dir_entry::{DirEntry, DirEntryData, DirFileEntryData, DirLfnEntryData, FileAttributes, ShortName, DIR_ENTRY_SIZE};
#[cfg(feature = "alloc")]
use dir_entry::{LFN_ENTRY_LAST_FLAG, LFN_PART_LEN};
use file::File;
use fs::{DiskSlice, FileSystem, ReadWriteSeek};
pub(crate) enum DirRawStream<'a, T: ReadWriteSeek + 'a> {
File(File<'a, T>),
@ -116,7 +113,12 @@ impl <'a, T: ReadWriteSeek + 'a> Dir<'a, T> {
}
}
fn find_entry(&self, name: &str, is_dir: Option<bool>, mut short_name_gen: Option<&mut ShortNameGenerator>) -> io::Result<DirEntry<'a, T>> {
fn find_entry(
&self,
name: &str,
is_dir: Option<bool>,
mut short_name_gen: Option<&mut ShortNameGenerator>,
) -> io::Result<DirEntry<'a, T>> {
for r in self.iter() {
let e = r?;
// compare name ignoring case
@ -311,7 +313,6 @@ impl <'a, T: ReadWriteSeek + 'a> Dir<'a, T> {
self.rename_internal(src_path, dst_dir, dst_path)
}
fn rename_internal(&self, src_name: &str, dst_dir: &Dir<T>, dst_name: &str) -> io::Result<()> {
trace!("moving {} to {}", src_name, dst_name);
// find existing file
@ -504,7 +505,7 @@ impl <'a, T: ReadWriteSeek> DirIter<'a, T> {
// Append to LFN buffer
#[cfg(feature = "alloc")]
lfn_buf.process(&data);
}
},
}
}
}
@ -551,9 +552,10 @@ fn validate_long_name(name: &str) -> io::Result<()> {
// check if there are only valid characters
for c in name.chars() {
match c {
'a'...'z' | 'A'...'Z' | '0'...'9' | '\u{80}'...'\u{FFFF}' |
'$' | '%' | '\'' | '-' | '_' | '@' | '~' | '`' | '!' | '(' | ')' | '{' | '}' |
'.' | ' ' | '+' | ',' | ';' | '=' | '[' | ']' => {},
'a'...'z' | 'A'...'Z' | '0'...'9' => {},
'\u{80}'...'\u{FFFF}' => {},
'$' | '%' | '\'' | '-' | '_' | '@' | '~' | '`' | '!' | '(' | ')' | '{' | '}' | '.' | ' ' | '+' | ',' | ';' | '=' | '['
| ']' => {},
_ => return Err(io::Error::new(ErrorKind::Other, "File name contains unsupported characters")),
}
}
@ -629,7 +631,13 @@ impl LongNameBuilder {
self.buf.resize(index as usize * LFN_PART_LEN, 0);
} else if self.index == 0 || index != self.index - 1 || data.checksum() != self.chksum {
// Corrupted entry
warn!("currupted lfn entry! {:x} {:x} {:x} {:x}", data.order(), self.index, data.checksum(), self.chksum);
warn!(
"currupted lfn entry! {:x} {:x} {:x} {:x}",
data.order(),
self.index,
data.checksum(),
self.chksum
);
self.clear();
return;
} else {
@ -710,7 +718,7 @@ impl<'a> Iterator for LfnEntriesGenerator<'a> {
// end of name
self.ended = true;
None
}
},
}
}
@ -751,11 +759,14 @@ impl ShortNameGenerator {
// no extension - copy name and leave extension empty
let (basename_len, basename_fits, basename_lossy) = Self::copy_short_name_part(&mut short_name[0..8], &name);
(basename_len, basename_fits, basename_lossy)
}
},
};
let chksum = Self::checksum(name);
Self {
short_name, chksum, name_fits, lossy_conv,
short_name,
chksum,
name_fits,
lossy_conv,
basename_len: basename_len as u8,
..Default::default()
}
@ -777,9 +788,8 @@ impl ShortNameGenerator {
continue;
},
// copy allowed characters
'A'...'Z' | 'a'...'z' | '0'...'9' |
'!' | '#' | '$' | '%' | '&' | '\'' | '(' | ')' |
'-' | '@' | '^' | '_' | '`' | '{' | '}' | '~' => c,
'A'...'Z' | 'a'...'z' | '0'...'9' => c,
'!' | '#' | '$' | '%' | '&' | '\'' | '(' | ')' | '-' | '@' | '^' | '_' | '`' | '{' | '}' | '~' => c,
// replace disallowed characters by underscore
_ => '_',
};
@ -800,7 +810,11 @@ impl ShortNameGenerator {
}
// check for long prefix form collision (TEXTFI~1.TXT)
let prefix_len = cmp::min(self.basename_len, 6) as usize;
let num_suffix = if short_name[prefix_len] as char == '~' { (short_name[prefix_len+1] as char).to_digit(10) } else { None };
let num_suffix = if short_name[prefix_len] as char == '~' {
(short_name[prefix_len + 1] as char).to_digit(10)
} else {
None
};
let ext_matches = short_name[8..] == self.short_name[8..];
if short_name[..prefix_len] == self.short_name[..prefix_len] && num_suffix.is_some() && ext_matches {
let num = num_suffix.unwrap(); // SAFE
@ -809,7 +823,11 @@ impl ShortNameGenerator {
// check for short prefix + checksum form collision (TE021F~1.TXT)
let prefix_len = cmp::min(self.basename_len, 2) as usize;
let num_suffix = if short_name[prefix_len+4] as char == '~' { (short_name[prefix_len+4+1] as char).to_digit(10) } else { None };
let num_suffix = if short_name[prefix_len + 4] as char == '~' {
(short_name[prefix_len + 4 + 1] as char).to_digit(10)
} else {
None
};
if short_name[..prefix_len] == self.short_name[..prefix_len] && num_suffix.is_some() && ext_matches {
let chksum_res = str::from_utf8(&short_name[prefix_len..prefix_len + 4]).map(|s| u16::from_str_radix(s, 16));
if chksum_res == Ok(Ok(self.chksum)) {
@ -881,7 +899,7 @@ impl ShortNameGenerator {
let c2 = char::from_digit((x as u32 >> 8) & 0xF, 16).unwrap().to_ascii_uppercase() as u8;
let c3 = char::from_digit((x as u32 >> 4) & 0xF, 16).unwrap().to_ascii_uppercase() as u8;
let c4 = char::from_digit((x as u32 >> 0) & 0xF, 16).unwrap().to_ascii_uppercase() as u8;
return [c1, c2, c3, c4]
return [c1, c2, c3, c4];
}
}
@ -902,8 +920,14 @@ mod tests {
assert_eq!(&ShortNameGenerator::new("Foo.b").generate().unwrap(), "FOO B ".as_bytes());
assert_eq!(&ShortNameGenerator::new("Foo.baR").generate().unwrap(), "FOO BAR".as_bytes());
assert_eq!(&ShortNameGenerator::new("Foo+1.baR").generate().unwrap(), "FOO_1~1 BAR".as_bytes());
assert_eq!(&ShortNameGenerator::new("ver +1.2.text").generate().unwrap(), "VER_12~1TEX".as_bytes());
assert_eq!(&ShortNameGenerator::new(".bashrc.swp").generate().unwrap(), "BASHRC~1SWP".as_bytes());
assert_eq!(
&ShortNameGenerator::new("ver +1.2.text").generate().unwrap(),
"VER_12~1TEX".as_bytes()
);
assert_eq!(
&ShortNameGenerator::new(".bashrc.swp").generate().unwrap(),
"BASHRC~1SWP".as_bytes()
);
}
#[test]
@ -913,7 +937,9 @@ mod tests {
#[test]
fn test_lfn_checksum_overflow() {
lfn_checksum(&[0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8]);
lfn_checksum(&[
0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8,
]);
}
#[test]

View File

@ -1,23 +1,22 @@
use core::{fmt, str};
use core::iter::FromIterator;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{String, Vec};
use core::char;
use io::prelude::*;
use core::iter::FromIterator;
use core::{fmt, str};
use io;
use io::prelude::*;
use io::Cursor;
use byteorder::{LittleEndian};
use byteorder_ext::{ReadBytesExt, WriteBytesExt};
#[cfg(feature = "chrono")]
use chrono::{TimeZone, Local, Datelike, Timelike};
use byteorder::LittleEndian;
use byteorder_ext::{ReadBytesExt, WriteBytesExt};
#[cfg(feature = "chrono")]
use chrono;
#[cfg(feature = "chrono")]
use chrono::{Datelike, Local, TimeZone, Timelike};
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{Vec, String};
use fs::{FileSystem, FatType, ReadWriteSeek, OemCpConverter};
use file::File;
use dir::{Dir, DirRawStream};
use file::File;
use fs::{FatType, FileSystem, OemCpConverter, ReadWriteSeek};
bitflags! {
/// A FAT file attributes.
@ -60,7 +59,11 @@ impl ShortName {
pub(crate) fn new(raw_name: &[u8; 11]) -> Self {
// get name components length by looking for space character
let name_len = raw_name[0..8].iter().rposition(|x| *x != Self::PADDING).map(|p| p + 1).unwrap_or(0);
let ext_len = raw_name[8..11].iter().rposition(|x| *x != Self::PADDING).map(|p| p + 1).unwrap_or(0);
let ext_len = raw_name[8..11]
.iter()
.rposition(|x| *x != Self::PADDING)
.map(|p| p + 1)
.unwrap_or(0);
let mut name = [Self::PADDING; 12];
name[..name_len].copy_from_slice(&raw_name[..name_len]);
let total_len = if ext_len > 0 {
@ -125,7 +128,8 @@ pub(crate) struct DirFileEntryData {
impl DirFileEntryData {
pub(crate) fn new(name: [u8; 11], attrs: FileAttributes) -> Self {
DirFileEntryData {
name, attrs,
name,
attrs,
..Default::default()
}
}
@ -157,9 +161,14 @@ impl DirFileEntryData {
}
pub(crate) fn first_cluster(&self, fat_type: FatType) -> Option<u32> {
let first_cluster_hi = if fat_type == FatType::Fat32 { self.first_cluster_hi } else { 0 };
let first_cluster_hi =
if fat_type == FatType::Fat32 { self.first_cluster_hi } else { 0 };
let n = ((first_cluster_hi as u32) << 16) | self.first_cluster_lo as u32;
if n == 0 { None } else { Some(n) }
if n == 0 {
None
} else {
Some(n)
}
}
pub(crate) fn set_first_cluster(&mut self, cluster: Option<u32>, fat_type: FatType) {
@ -314,7 +323,8 @@ pub(crate) struct DirLfnEntryData {
impl DirLfnEntryData {
pub(crate) fn new(order: u8, checksum: u8) -> Self {
DirLfnEntryData {
order, checksum,
order,
checksum,
attrs: FileAttributes::LFN,
..Default::default()
}
@ -394,10 +404,8 @@ impl DirEntryData {
Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => {
// entries can occupy all clusters of directory so there is no zero entry at the end
// handle it here by returning non-existing empty entry
return Ok(DirEntryData::File(DirFileEntryData {
..Default::default()
}));
}
return Ok(DirEntryData::File(DirFileEntryData { ..Default::default() }));
},
Err(err) => return Err(err),
_ => {},
}
@ -405,7 +413,8 @@ impl DirEntryData {
if attrs & FileAttributes::LFN == FileAttributes::LFN {
// read long name entry
let mut data = DirLfnEntryData {
attrs, ..Default::default()
attrs,
..Default::default()
};
// use cursor to divide name into order and LFN name_0
let mut cur = Cursor::new(&name);
@ -544,9 +553,12 @@ impl From<Date> for chrono::Date<Local> {
#[cfg(feature = "chrono")]
impl From<DateTime> for chrono::DateTime<Local> {
fn from(date_time: DateTime) -> Self {
chrono::Date::<Local>::from(date_time.date)
.and_hms_milli(date_time.time.hour as u32, date_time.time.min as u32,
date_time.time.sec as u32, date_time.time.millis as u32)
chrono::Date::<Local>::from(date_time.date).and_hms_milli(
date_time.time.hour as u32,
date_time.time.min as u32,
date_time.time.sec as u32,
date_time.time.millis as u32,
)
}
}
@ -585,10 +597,7 @@ pub(crate) struct DirEntryEditor {
impl DirEntryEditor {
fn new(data: DirFileEntryData, pos: u64) -> Self {
DirEntryEditor {
data, pos,
dirty: false,
}
DirEntryEditor { data, pos, dirty: false }
}
pub(crate) fn inner(&self) -> &DirFileEntryData {
@ -809,8 +818,14 @@ mod tests {
assert_eq!(ShortName::new(&raw_short_name).to_string(&LOSSY_OEM_CP_CONVERTER), "LOOK AT.M E");
raw_short_name[0] = 0x99;
raw_short_name[10] = 0x99;
assert_eq!(ShortName::new(&raw_short_name).to_string(&LOSSY_OEM_CP_CONVERTER), "\u{FFFD}OOK AT.M \u{FFFD}");
assert_eq!(ShortName::new(&raw_short_name).eq_ignore_case("\u{FFFD}OOK AT.M \u{FFFD}", &LOSSY_OEM_CP_CONVERTER), true);
assert_eq!(
ShortName::new(&raw_short_name).to_string(&LOSSY_OEM_CP_CONVERTER),
"\u{FFFD}OOK AT.M \u{FFFD}"
);
assert_eq!(
ShortName::new(&raw_short_name).eq_ignore_case("\u{FFFD}OOK AT.M \u{FFFD}", &LOSSY_OEM_CP_CONVERTER),
true
);
}
#[test]
@ -828,14 +843,23 @@ mod tests {
raw_short_name.copy_from_slice("LOOK AT M E".as_bytes());
raw_short_name[0] = 0x99;
raw_short_name[10] = 0x99;
assert_eq!(ShortName::new(&raw_short_name).eq_ignore_case("\u{FFFD}OOK AT.M \u{FFFD}", &LOSSY_OEM_CP_CONVERTER), true);
assert_eq!(ShortName::new(&raw_short_name).eq_ignore_case("\u{FFFD}ook AT.m \u{FFFD}", &LOSSY_OEM_CP_CONVERTER), true);
assert_eq!(
ShortName::new(&raw_short_name).eq_ignore_case("\u{FFFD}OOK AT.M \u{FFFD}", &LOSSY_OEM_CP_CONVERTER),
true
);
assert_eq!(
ShortName::new(&raw_short_name).eq_ignore_case("\u{FFFD}ook AT.m \u{FFFD}", &LOSSY_OEM_CP_CONVERTER),
true
);
}
#[test]
fn short_name_05_changed_to_e5() {
let raw_short_name = [0x05; 11];
assert_eq!(ShortName::new(&raw_short_name).as_bytes(), [0xE5, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, '.' as u8, 0x05, 0x05, 0x05]);
assert_eq!(
ShortName::new(&raw_short_name).as_bytes(),
[0xE5, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, '.' as u8, 0x05, 0x05, 0x05]
);
}
#[test]

View File

@ -1,11 +1,11 @@
use core::cmp;
use core;
use io::prelude::*;
use io::{SeekFrom, ErrorKind};
use core::cmp;
use io;
use io::prelude::*;
use io::{ErrorKind, SeekFrom};
use dir_entry::{Date, DateTime, DirEntryEditor};
use fs::{FileSystem, ReadWriteSeek};
use dir_entry::{DirEntryEditor, DateTime, Date};
const MAX_FILE_SIZE: u32 = core::u32::MAX;
@ -28,7 +28,9 @@ pub struct File<'a, T: ReadWriteSeek + 'a> {
impl<'a, T: ReadWriteSeek> File<'a, T> {
pub(crate) fn new(first_cluster: Option<u32>, entry: Option<DirEntryEditor>, fs: &'a FileSystem<T>) -> Self {
File {
first_cluster, entry, fs,
first_cluster,
entry,
fs,
current_cluster: None, // cluster before first one
offset: 0,
}
@ -290,7 +292,13 @@ impl<'a, T: ReadWriteSeek> Seek for File<'a, T> {
let mut new_pos = match pos {
SeekFrom::Current(x) => self.offset as i64 + x,
SeekFrom::Start(x) => x as i64,
SeekFrom::End(x) => self.entry.iter().next().map_or(None, |e| e.inner().size()).expect("cannot seek from end if size is unknown") as i64 + x,
SeekFrom::End(x) => {
self.entry
.iter()
.next()
.map_or(None, |e| e.inner().size())
.expect("cannot seek from end if size is unknown") as i64 + x
},
};
if new_pos < 0 {
return Err(io::Error::new(ErrorKind::InvalidInput, "Seek to a negative offset"));

View File

@ -1,20 +1,20 @@
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::String;
use core::cell::RefCell;
use core::cmp;
use core::char;
use core::cmp;
use core::iter::FromIterator;
use io;
use io::prelude::*;
use io::{Error, ErrorKind, SeekFrom};
use io;
use byteorder::LittleEndian;
use byteorder_ext::{ReadBytesExt, WriteBytesExt};
use file::File;
use dir::{DirRawStream, Dir};
use dir::{Dir, DirRawStream};
use dir_entry::DIR_ENTRY_SIZE;
use table::{ClusterIterator, alloc_cluster, read_fat_flags, count_free_clusters};
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::String;
use file::File;
use table::{alloc_cluster, count_free_clusters, read_fat_flags, ClusterIterator};
// FAT implementation based on:
// http://wiki.osdev.org/FAT
@ -68,11 +68,11 @@ impl FsStatusFlags {
/// A sum of `Read` and `Seek` traits.
pub trait ReadSeek: Read + Seek {}
impl<T> ReadSeek for T where T: Read + Seek {}
impl<T: Read + Seek> ReadSeek for T {}
/// A sum of `Read`, `Write` and `Seek` traits.
pub trait ReadWriteSeek: Read + Write + Seek {}
impl<T> ReadWriteSeek for T where T: Read + Write + Seek {}
impl<T: Read + Write + Seek> ReadWriteSeek for T {}
#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
@ -259,7 +259,8 @@ impl FsInfoSector {
return Err(Error::new(ErrorKind::Other, "invalid trail_sig in FsInfo sector"));
}
Ok(FsInfoSector {
free_cluster_count, next_free_cluster,
free_cluster_count,
next_free_cluster,
dirty: false,
})
}
@ -391,12 +392,16 @@ impl <T: ReadWriteSeek> FileSystem<T> {
return Err(Error::new(ErrorKind::Other, "Unknown FS version"));
}
let total_sectors =
if bpb.total_sectors_16 == 0 { bpb.total_sectors_32 }
else { bpb.total_sectors_16 as u32 };
let sectors_per_fat =
if bpb.sectors_per_fat_16 == 0 { bpb.sectors_per_fat_32 }
else { bpb.sectors_per_fat_16 as u32 };
let total_sectors = if bpb.total_sectors_16 == 0 {
bpb.total_sectors_32
} else {
bpb.total_sectors_16 as u32
};
let sectors_per_fat = if bpb.sectors_per_fat_16 == 0 {
bpb.sectors_per_fat_32
} else {
bpb.sectors_per_fat_16 as u32
};
let root_dir_bytes = bpb.root_entries as u32 * DIR_ENTRY_SIZE as u32;
let root_dir_sectors = (root_dir_bytes + (bpb.bytes_per_sector as u32 - 1)) / bpb.bytes_per_sector as u32;
let first_data_sector = bpb.reserved_sectors as u32 + (bpb.fats as u32 * sectors_per_fat) + root_dir_sectors;
@ -423,7 +428,7 @@ impl <T: ReadWriteSeek> FileSystem<T> {
disk: RefCell::new(disk),
options,
fat_type,
bpb: bpb,
bpb,
first_data_sector,
root_dir_sectors,
total_clusters,
@ -471,7 +476,11 @@ impl <T: ReadWriteSeek> FileSystem<T> {
let root_rdr = {
match self.fat_type {
FatType::Fat12 | FatType::Fat16 => DirRawStream::Root(DiskSlice::from_sectors(
self.first_data_sector - self.root_dir_sectors, self.root_dir_sectors, 1, self)),
self.first_data_sector - self.root_dir_sectors,
self.root_dir_sectors,
1,
self,
)),
_ => DirRawStream::File(File::new(Some(self.bpb.root_dir_first_cluster), None, self)),
}
};
@ -495,9 +504,11 @@ impl <T: ReadWriteSeek> FileSystem<T> {
}
fn fat_slice<'b>(&'b self) -> DiskSlice<'b, T> {
let sectors_per_fat =
if self.bpb.sectors_per_fat_16 == 0 { self.bpb.sectors_per_fat_32 }
else { self.bpb.sectors_per_fat_16 as u32 };
let sectors_per_fat = if self.bpb.sectors_per_fat_16 == 0 {
self.bpb.sectors_per_fat_32
} else {
self.bpb.sectors_per_fat_16 as u32
};
let mirroring_enabled = self.bpb.mirroring_enabled();
let (fat_first_sector, mirrors) = if mirroring_enabled {
(self.bpb.reserved_sectors as u32, self.bpb.fats)
@ -618,12 +629,23 @@ pub(crate) struct DiskSlice<'a, T: ReadWriteSeek + 'a> {
impl<'a, T: ReadWriteSeek> DiskSlice<'a, T> {
pub(crate) fn new(begin: u64, size: u64, mirrors: u8, fs: &'a FileSystem<T>) -> Self {
DiskSlice { begin, size, mirrors, fs, offset: 0 }
DiskSlice {
begin,
size,
mirrors,
fs,
offset: 0,
}
}
pub(crate) fn from_sectors(first_sector: u32, sector_count: u32, mirrors: u8, fs: &'a FileSystem<T>) -> Self {
let bytes_per_sector = fs.bpb.bytes_per_sector as u64;
Self::new(first_sector as u64 * bytes_per_sector, sector_count as u64 * bytes_per_sector, mirrors, fs)
Self::new(
first_sector as u64 * bytes_per_sector,
sector_count as u64 * bytes_per_sector,
mirrors,
fs,
)
}
pub(crate) fn abs_pos(&self) -> u64 {

View File

@ -54,10 +54,8 @@
#![crate_type = "lib"]
#![crate_name = "fatfs"]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
// Disable warnings to not clutter code with cfg too much
#![cfg_attr(not(feature = "alloc"), allow(dead_code, unused_imports))]
@ -78,28 +76,28 @@ extern crate core_io;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
extern crate alloc;
mod fs;
mod dir;
mod dir_entry;
mod file;
mod fs;
mod table;
#[cfg(not(feature = "std"))]
mod byteorder_core_io;
#[cfg(not(feature = "std"))]
use byteorder_core_io as byteorder_ext;
#[cfg(feature = "std")]
use byteorder as byteorder_ext;
#[cfg(feature = "std")]
use std as core;
#[cfg(not(feature = "std"))]
use byteorder_core_io as byteorder_ext;
#[cfg(not(feature = "std"))]
use core_io as io;
#[cfg(feature = "std")]
use std as core;
#[cfg(feature = "std")]
use std::io as io;
use std::io;
pub use fs::*;
pub use dir::*;
pub use dir_entry::*;
pub use file::*;
pub use fs::*;

View File

@ -1,7 +1,9 @@
use io;
use byteorder::LittleEndian;
use byteorder_ext::{ReadBytesExt, WriteBytesExt};
use fs::{ReadWriteSeek, ReadSeek, FatType, FsStatusFlags};
use fs::{FatType, FsStatusFlags, ReadSeek, ReadWriteSeek};
struct Fat<T> {
#[allow(dead_code)]
@ -63,7 +65,13 @@ fn find_free_cluster<T: ReadSeek>(fat: &mut T, fat_type: FatType, start_cluster:
}
}
pub(crate) fn alloc_cluster<T: ReadWriteSeek>(fat: &mut T, fat_type: FatType, prev_cluster: Option<u32>, hint: Option<u32>, total_clusters: u32) -> io::Result<u32> {
pub(crate) fn alloc_cluster<T: ReadWriteSeek>(
fat: &mut T,
fat_type: FatType,
prev_cluster: Option<u32>,
hint: Option<u32>,
total_clusters: u32,
) -> io::Result<u32> {
let end_cluster = total_clusters + RESERVED_FAT_ENTRIES;
let start_cluster = match hint {
Some(n) if n < end_cluster => n,
@ -99,9 +107,7 @@ pub(crate) fn read_fat_flags<T: ReadSeek>(fat: &mut T, fat_type: FatType) -> io:
FatType::Fat16 => val & (1 << 14) == 0,
FatType::Fat32 => val & (1 << 26) == 0,
};
Ok(FsStatusFlags {
dirty, io_error,
})
Ok(FsStatusFlags { dirty, io_error })
}
pub(crate) fn count_free_clusters<T: ReadSeek>(fat: &mut T, fat_type: FatType, total_clusters: u32) -> io::Result<u32> {
@ -417,7 +423,10 @@ mod tests {
// test reading from iterator
{
let iter = ClusterIterator::new(&mut cur, fat_type, 0x9);
assert_eq!(iter.map(|r| r.unwrap()).collect::<Vec<_>>(), vec![0xA, 0x14, 0x15, 0x16, 0x19, 0x1A]);
assert_eq!(
iter.map(|r| r.unwrap()).collect::<Vec<_>>(),
vec![0xA, 0x14, 0x15, 0x16, 0x19, 0x1A]
);
}
// test truncating a chain
{
@ -443,9 +452,9 @@ mod tests {
#[test]
fn test_fat12() {
let mut fat: Vec<u8> = vec![
0xF0, 0xFF, 0xFF, 0x03, 0x40, 0x00, 0x05, 0x60, 0x00, 0x07, 0x80, 0x00, 0xFF, 0xAF, 0x00, 0x14,
0xC0, 0x00, 0x0D, 0xE0, 0x00, 0x0F, 0x00, 0x01, 0x11, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, 0x15, 0x60,
0x01, 0x19, 0x70, 0xFF, 0xF7, 0xAF, 0x01, 0xFF, 0x0F, 0x00, 0x00, 0x70, 0xFF, 0x00, 0x00, 0x00,
0xF0, 0xFF, 0xFF, 0x03, 0x40, 0x00, 0x05, 0x60, 0x00, 0x07, 0x80, 0x00, 0xFF, 0xAF, 0x00, 0x14, 0xC0, 0x00, 0x0D, 0xE0, 0x00,
0x0F, 0x00, 0x01, 0x11, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, 0x15, 0x60, 0x01, 0x19, 0x70, 0xFF, 0xF7, 0xAF, 0x01, 0xFF, 0x0F, 0x00,
0x00, 0x70, 0xFF, 0x00, 0x00, 0x00,
];
test_fat(FatType::Fat12, io::Cursor::new(&mut fat));
}
@ -453,10 +462,10 @@ mod tests {
#[test]
fn test_fat16() {
let mut fat: Vec<u8> = vec![
0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00,
0xFF, 0xFF, 0x0A, 0x00, 0x14, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x10, 0x00,
0x11, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x16, 0x00, 0x19, 0x00, 0xF7, 0xFF,
0xF7, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0xFF, 0xFF, 0x0A, 0x00, 0x14,
0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x10, 0x00, 0x11, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00,
0x16, 0x00, 0x19, 0x00, 0xF7, 0xFF, 0xF7, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0x00, 0x00, 0x00,
0x00,
];
test_fat(FatType::Fat16, io::Cursor::new(&mut fat));
}
@ -464,14 +473,13 @@ mod tests {
#[test]
fn test_fat32() {
let mut fat: Vec<u8> = vec![
0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0x04, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x0F, 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F,
0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x0F,
0xF7, 0xFF, 0xFF, 0x0F, 0x1A, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00,
0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x15, 0x00, 0x00, 0x00,
0x16, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x0F, 0xF7, 0xFF, 0xFF, 0x0F, 0x1A, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
];
test_fat(FatType::Fat32, io::Cursor::new(&mut fat));
}

View File

@ -1,13 +1,13 @@
extern crate env_logger;
extern crate fatfs;
extern crate fscommon;
extern crate env_logger;
use std::fs;
use std::io::SeekFrom;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::str;
use fatfs::{FsOptions, FatType};
use fatfs::{FatType, FsOptions};
use fscommon::BufStream;
const TEST_TEXT: &str = "Rust is cool!\n";
@ -228,30 +228,39 @@ fn test_status_flags_fat32() {
#[test]
fn test_stats_fat12() {
call_with_fs(&|fs| {
call_with_fs(
&|fs| {
let stats = fs.stats().unwrap();
assert_eq!(stats.cluster_size(), 512);
assert_eq!(stats.total_clusters(), 1955); // 1000 * 1024 / 512 = 2000
assert_eq!(stats.free_clusters(), 1920);
}, FAT12_IMG)
},
FAT12_IMG,
)
}
#[test]
fn test_stats_fat16() {
call_with_fs(&|fs| {
call_with_fs(
&|fs| {
let stats = fs.stats().unwrap();
assert_eq!(stats.cluster_size(), 512);
assert_eq!(stats.total_clusters(), 4927); // 2500 * 1024 / 512 = 5000
assert_eq!(stats.free_clusters(), 4892);
}, FAT16_IMG)
},
FAT16_IMG,
)
}
#[test]
fn test_stats_fat32() {
call_with_fs(&|fs| {
call_with_fs(
&|fs| {
let stats = fs.stats().unwrap();
assert_eq!(stats.cluster_size(), 512);
assert_eq!(stats.total_clusters(), 66922); // 34000 * 1024 / 512 = 68000
assert_eq!(stats.free_clusters(), 66886);
}, FAT32_IMG)
},
FAT32_IMG,
)
}

View File

@ -1,10 +1,10 @@
extern crate env_logger;
extern crate fatfs;
extern crate fscommon;
extern crate env_logger;
use std::fs;
use std::io::prelude::*;
use std::io;
use std::io::prelude::*;
use std::str;
use fatfs::FsOptions;