Properly initialize file allocation table when formatting a volume
This commit is contained in:
parent
447c9dda35
commit
b9753248f7
@ -11,7 +11,7 @@ use dir_entry::{DirEntry, DirEntryData, DirFileEntryData, DirLfnEntryData, FileA
|
||||
#[cfg(feature = "alloc")]
|
||||
use dir_entry::{LFN_ENTRY_LAST_FLAG, LFN_PART_LEN};
|
||||
use file::File;
|
||||
use fs::{DiskSlice, FileSystem, ReadWriteSeek};
|
||||
use fs::{DiskSlice, FsIoAdapter, FileSystem, ReadWriteSeek};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
type LfnUtf16 = Vec<u16>;
|
||||
@ -20,7 +20,7 @@ type LfnUtf16 = ();
|
||||
|
||||
pub(crate) enum DirRawStream<'a, T: ReadWriteSeek + 'a> {
|
||||
File(File<'a, T>),
|
||||
Root(DiskSlice<'a, T>),
|
||||
Root(DiskSlice<FsIoAdapter<'a, T>>),
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> DirRawStream<'a, T> {
|
||||
|
135
src/fs.rs
135
src/fs.rs
@ -788,7 +788,8 @@ impl<T: ReadWriteSeek> FileSystem<T> {
|
||||
self.first_data_sector - self.root_dir_sectors,
|
||||
self.root_dir_sectors,
|
||||
1,
|
||||
self,
|
||||
&self.bpb,
|
||||
FsIoAdapter { fs: self },
|
||||
)),
|
||||
_ => DirRawStream::File(File::new(Some(self.bpb.root_dir_first_cluster), None, self)),
|
||||
}
|
||||
@ -812,20 +813,14 @@ impl<T: ReadWriteSeek> FileSystem<T> {
|
||||
self.offset_from_sector(self.sector_from_cluster(cluser))
|
||||
}
|
||||
|
||||
fn fat_slice<'b>(&'b self) -> DiskSlice<'b, T> {
|
||||
let sectors_per_fat = self.bpb.sectors_per_fat();
|
||||
let mirroring_enabled = self.bpb.mirroring_enabled();
|
||||
let (fat_first_sector, mirrors) = if mirroring_enabled {
|
||||
(self.bpb.reserved_sectors as u32, self.bpb.fats)
|
||||
} else {
|
||||
let active_fat = self.bpb.active_fat() as u32;
|
||||
let fat_first_sector = (self.bpb.reserved_sectors as u32) + active_fat * sectors_per_fat;
|
||||
(fat_first_sector, 1)
|
||||
fn fat_slice<'b>(&'b self) -> DiskSlice<FsIoAdapter<'b, T>> {
|
||||
let io = FsIoAdapter {
|
||||
fs: self,
|
||||
};
|
||||
DiskSlice::from_sectors(fat_first_sector, sectors_per_fat, mirrors, self)
|
||||
fat_slice(io, &self.bpb)
|
||||
}
|
||||
|
||||
pub(crate) fn cluster_iter<'b>(&'b self, cluster: u32) -> ClusterIterator<DiskSlice<'b, T>> {
|
||||
pub(crate) fn cluster_iter<'b>(&'b self, cluster: u32) -> ClusterIterator<DiskSlice<FsIoAdapter<'b, T>>> {
|
||||
let disk_slice = self.fat_slice();
|
||||
ClusterIterator::new(disk_slice, self.fat_type, cluster)
|
||||
}
|
||||
@ -946,32 +941,84 @@ impl<T: ReadWriteSeek> Drop for FileSystem<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct DiskSlice<'a, T: ReadWriteSeek + 'a> {
|
||||
pub(crate) struct FsIoAdapter<'a, T: ReadWriteSeek + 'a> {
|
||||
fs: &'a FileSystem<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> Read for FsIoAdapter<'a, T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.fs.disk.borrow_mut().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> Write for FsIoAdapter<'a, T> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let size = self.fs.disk.borrow_mut().write(buf)?;
|
||||
if size > 0 {
|
||||
self.fs.set_dirty_flag(true)?;
|
||||
}
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.fs.disk.borrow_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> Seek for FsIoAdapter<'a, T> {
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
self.fs.disk.borrow_mut().seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: derive cannot be used because of invalid bounds. See: https://github.com/rust-lang/rust/issues/26925
|
||||
impl<'a, T: ReadWriteSeek> Clone for FsIoAdapter<'a, T> {
|
||||
fn clone(&self) -> Self {
|
||||
FsIoAdapter {
|
||||
fs: self.fs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fat_slice<T: ReadWriteSeek>(io: T, bpb: &BiosParameterBlock) -> DiskSlice<T> {
|
||||
let sectors_per_fat = bpb.sectors_per_fat();
|
||||
let mirroring_enabled = bpb.mirroring_enabled();
|
||||
let (fat_first_sector, mirrors) = if mirroring_enabled {
|
||||
(bpb.reserved_sectors as u32, bpb.fats)
|
||||
} else {
|
||||
let active_fat = bpb.active_fat() as u32;
|
||||
let fat_first_sector = (bpb.reserved_sectors as u32) + active_fat * sectors_per_fat;
|
||||
(fat_first_sector, 1)
|
||||
};
|
||||
DiskSlice::from_sectors(fat_first_sector, sectors_per_fat, mirrors, bpb, io)
|
||||
}
|
||||
|
||||
pub(crate) struct DiskSlice<T> {
|
||||
begin: u64,
|
||||
size: u64,
|
||||
offset: u64,
|
||||
mirrors: u8,
|
||||
fs: &'a FileSystem<T>,
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> DiskSlice<'a, T> {
|
||||
pub(crate) fn new(begin: u64, size: u64, mirrors: u8, fs: &'a FileSystem<T>) -> Self {
|
||||
impl<T> DiskSlice<T> {
|
||||
pub(crate) fn new(begin: u64, size: u64, mirrors: u8, inner: T) -> Self {
|
||||
DiskSlice {
|
||||
begin,
|
||||
size,
|
||||
mirrors,
|
||||
fs,
|
||||
inner,
|
||||
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;
|
||||
fn from_sectors(first_sector: u32, sector_count: u32, mirrors: u8, bpb: &BiosParameterBlock, inner: T) -> Self {
|
||||
let bytes_per_sector = bpb.bytes_per_sector as u64;
|
||||
Self::new(
|
||||
first_sector as u64 * bytes_per_sector,
|
||||
sector_count as u64 * bytes_per_sector,
|
||||
mirrors,
|
||||
fs,
|
||||
inner,
|
||||
)
|
||||
}
|
||||
|
||||
@ -981,56 +1028,51 @@ impl<'a, T: ReadWriteSeek> DiskSlice<'a, T> {
|
||||
}
|
||||
|
||||
// Note: derive cannot be used because of invalid bounds. See: https://github.com/rust-lang/rust/issues/26925
|
||||
impl<'a, T: ReadWriteSeek> Clone for DiskSlice<'a, T> {
|
||||
impl<T: Clone> Clone for DiskSlice<T> {
|
||||
fn clone(&self) -> Self {
|
||||
DiskSlice {
|
||||
begin: self.begin,
|
||||
size: self.size,
|
||||
offset: self.offset,
|
||||
mirrors: self.mirrors,
|
||||
fs: self.fs,
|
||||
inner: self.inner.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> Read for DiskSlice<'a, T> {
|
||||
impl<'a, T: Read + Seek> Read for DiskSlice<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let offset = self.begin + self.offset;
|
||||
let read_size = cmp::min((self.size - self.offset) as usize, buf.len());
|
||||
let mut disk = self.fs.disk.borrow_mut();
|
||||
disk.seek(SeekFrom::Start(offset))?;
|
||||
let size = disk.read(&mut buf[..read_size])?;
|
||||
self.inner.seek(SeekFrom::Start(offset))?;
|
||||
let size = self.inner.read(&mut buf[..read_size])?;
|
||||
self.offset += size as u64;
|
||||
Ok(size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> Write for DiskSlice<'a, T> {
|
||||
impl<'a, T: Write + Seek> Write for DiskSlice<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let offset = self.begin + self.offset;
|
||||
let write_size = cmp::min((self.size - self.offset) as usize, buf.len());
|
||||
if write_size == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
// Mark the volume 'dirty'
|
||||
self.fs.set_dirty_flag(true)?;
|
||||
// Write data
|
||||
let mut disk = self.fs.disk.borrow_mut();
|
||||
for i in 0..self.mirrors {
|
||||
disk.seek(SeekFrom::Start(offset + i as u64 * self.size))?;
|
||||
disk.write_all(&buf[..write_size])?;
|
||||
self.inner.seek(SeekFrom::Start(offset + i as u64 * self.size))?;
|
||||
self.inner.write_all(&buf[..write_size])?;
|
||||
}
|
||||
self.offset += write_size as u64;
|
||||
Ok(write_size)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
let mut disk = self.fs.disk.borrow_mut();
|
||||
disk.flush()
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ReadWriteSeek> Seek for DiskSlice<'a, T> {
|
||||
impl<'a, T> Seek for DiskSlice<T> {
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
let new_offset = match pos {
|
||||
SeekFrom::Current(x) => self.offset as i64 + x,
|
||||
@ -1325,25 +1367,24 @@ pub fn format_volume<T: ReadWriteSeek>(mut disk: T, options: FormatOptions) -> i
|
||||
let sectors_per_fat: u32 = boot.bpb.sectors_per_fat();
|
||||
let bytes_per_fat: u32 = sectors_per_fat * bytes_per_sector as u32;
|
||||
let reserved_sectors = boot.bpb.reserved_sectors;
|
||||
let mut fat_pos = reserved_sectors as u64 * bytes_per_sector as u64;
|
||||
for _ in 0..boot.bpb.fats {
|
||||
disk.seek(SeekFrom::Start(fat_pos))?;
|
||||
write_zeros(&mut disk, bytes_per_fat as usize)?;
|
||||
disk.seek(SeekFrom::Start(fat_pos))?;
|
||||
format_fat(&mut disk, fat_type, boot.bpb.media)?;
|
||||
fat_pos += bytes_per_fat as u64;
|
||||
// TODO: mark entries at the end of FAT as used (after FAT but before sector end)
|
||||
// TODO: mark special entries 0x0FFFFFF0 - 0x0FFFFFFF as BAD if they exists on FAT32 volume
|
||||
let fat_pos = reserved_sectors as u64 * bytes_per_sector as u64;
|
||||
disk.seek(SeekFrom::Start(fat_pos))?;
|
||||
write_zeros(&mut disk, bytes_per_fat as usize * boot.bpb.fats as usize)?;
|
||||
{
|
||||
let mut fat_slice = fat_slice(&mut disk, &boot.bpb);
|
||||
format_fat(&mut fat_slice, fat_type, boot.bpb.media, bytes_per_fat, boot.bpb.total_clusters())?;
|
||||
}
|
||||
|
||||
// Root directory
|
||||
let root_dir_pos = fat_pos;
|
||||
let root_dir_pos = fat_pos + bytes_per_fat as u64 * boot.bpb.fats as u64;
|
||||
disk.seek(SeekFrom::Start(root_dir_pos))?;
|
||||
let root_dir_sectors: u32 = boot.bpb.root_dir_sectors();
|
||||
write_zeros(&mut disk, root_dir_sectors as usize * bytes_per_sector as usize)?;
|
||||
if fat_type == FatType::Fat32 {
|
||||
// FIXME: alloc_cluster needs FAT stream, not entire disk
|
||||
let root_dir_first_cluster = alloc_cluster(&mut disk, fat_type, None, None, 1)?;
|
||||
let root_dir_first_cluster = {
|
||||
let mut fat_slice = fat_slice(&mut disk, &boot.bpb);
|
||||
alloc_cluster(&mut fat_slice, fat_type, None, None, 1)?
|
||||
};
|
||||
assert!(root_dir_first_cluster == boot.bpb.root_dir_first_cluster);
|
||||
let first_data_sector = reserved_sectors as u32 + sectors_per_fat + root_dir_sectors;
|
||||
let sectors_per_cluster = boot.bpb.sectors_per_cluster;
|
||||
|
68
src/table.rs
68
src/table.rs
@ -1,5 +1,6 @@
|
||||
use byteorder::LittleEndian;
|
||||
use byteorder_ext::{ReadBytesExt, WriteBytesExt};
|
||||
use core::cmp;
|
||||
use io;
|
||||
|
||||
use fs::{FatType, FsStatusFlags, ReadSeek, ReadWriteSeek};
|
||||
@ -26,6 +27,7 @@ enum FatValue {
|
||||
trait FatTrait {
|
||||
fn get_raw<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<u32>;
|
||||
fn get<T: ReadSeek>(fat: &mut T, cluster: u32) -> io::Result<FatValue>;
|
||||
fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_value: u32) -> io::Result<()>;
|
||||
fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()>;
|
||||
fn find_free<T: ReadSeek>(fat: &mut T, start_cluster: u32, end_cluster: u32) -> io::Result<u32>;
|
||||
fn count_free<T: ReadSeek>(fat: &mut T, end_cluster: u32) -> io::Result<u32>;
|
||||
@ -109,8 +111,17 @@ pub(crate) fn read_fat_flags<T: ReadSeek>(fat: &mut T, fat_type: FatType) -> io:
|
||||
Ok(FsStatusFlags { dirty, io_error })
|
||||
}
|
||||
|
||||
pub(crate) fn format_fat<T: ReadWriteSeek>(fat: &mut T, fat_type: FatType, media: u8) -> io::Result<()> {
|
||||
// Note: cannot use any seeking function here because fat parameter is not a disk slice
|
||||
pub(crate) fn count_free_clusters<T: ReadSeek>(fat: &mut T, fat_type: FatType, total_clusters: u32) -> io::Result<u32> {
|
||||
let end_cluster = total_clusters + RESERVED_FAT_ENTRIES;
|
||||
match fat_type {
|
||||
FatType::Fat12 => Fat12::count_free(fat, end_cluster),
|
||||
FatType::Fat16 => Fat16::count_free(fat, end_cluster),
|
||||
FatType::Fat32 => Fat32::count_free(fat, end_cluster),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_fat<T: ReadWriteSeek>(fat: &mut T, fat_type: FatType, media: u8, bytes_per_fat: u32, total_clusters: u32) -> io::Result<()> {
|
||||
// init first two reserved entries to FAT ID
|
||||
match fat_type {
|
||||
FatType::Fat12 => {
|
||||
fat.write_u8(media)?;
|
||||
@ -125,16 +136,21 @@ pub(crate) fn format_fat<T: ReadWriteSeek>(fat: &mut T, fat_type: FatType, media
|
||||
fat.write_u32::<LittleEndian>(0xFFFFFFFF)?;
|
||||
},
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn count_free_clusters<T: ReadSeek>(fat: &mut T, fat_type: FatType, total_clusters: u32) -> io::Result<u32> {
|
||||
let end_cluster = total_clusters + RESERVED_FAT_ENTRIES;
|
||||
match fat_type {
|
||||
FatType::Fat12 => Fat12::count_free(fat, end_cluster),
|
||||
FatType::Fat16 => Fat16::count_free(fat, end_cluster),
|
||||
FatType::Fat32 => Fat32::count_free(fat, end_cluster),
|
||||
// mark entries at the end of FAT as used (after FAT but before sector end)
|
||||
const BITS_PER_BYTE: u32 = 8;
|
||||
let start_cluster = total_clusters + RESERVED_FAT_ENTRIES;
|
||||
let end_cluster = bytes_per_fat * BITS_PER_BYTE / fat_type.bits_per_fat_entry();
|
||||
for cluster in start_cluster..end_cluster {
|
||||
write_fat(fat, fat_type, cluster, FatValue::EndOfChain)?;
|
||||
}
|
||||
// mark special entries 0x0FFFFFF0 - 0x0FFFFFFF as BAD if they exists on FAT32 volume
|
||||
if end_cluster > 0x0FFFFFF0 {
|
||||
let end_bad_cluster = cmp::min(0x0FFFFFFF + 1, end_cluster);
|
||||
for cluster in 0x0FFFFFF0..end_bad_cluster {
|
||||
write_fat(fat, fat_type, cluster, FatValue::Bad)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl FatTrait for Fat12 {
|
||||
@ -165,13 +181,17 @@ impl FatTrait for Fat12 {
|
||||
FatValue::EndOfChain => 0xFFF,
|
||||
FatValue::Data(n) => n as u16,
|
||||
};
|
||||
Self::set_raw(fat, cluster, raw_val as u32)
|
||||
}
|
||||
|
||||
fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_val: u32) -> io::Result<()> {
|
||||
let fat_offset = cluster + (cluster / 2);
|
||||
fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
|
||||
let old_packed = fat.read_u16::<LittleEndian>()?;
|
||||
fat.seek(io::SeekFrom::Start(fat_offset as u64))?;
|
||||
let new_packed = match cluster & 1 {
|
||||
0 => (old_packed & 0xF000) | raw_val,
|
||||
_ => (old_packed & 0x000F) | (raw_val << 4),
|
||||
0 => (old_packed & 0xF000) | raw_val as u16,
|
||||
_ => (old_packed & 0x000F) | ((raw_val as u16) << 4),
|
||||
};
|
||||
fat.write_u16::<LittleEndian>(new_packed)?;
|
||||
Ok(())
|
||||
@ -248,16 +268,20 @@ impl FatTrait for Fat16 {
|
||||
})
|
||||
}
|
||||
|
||||
fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()> {
|
||||
fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_value: u32) -> io::Result<()> {
|
||||
fat.seek(io::SeekFrom::Start((cluster * 2) as u64))?;
|
||||
let raw_val = match value {
|
||||
fat.write_u16::<LittleEndian>(raw_value as u16)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()> {
|
||||
let raw_value = match value {
|
||||
FatValue::Free => 0,
|
||||
FatValue::Bad => 0xFFF7,
|
||||
FatValue::EndOfChain => 0xFFFF,
|
||||
FatValue::Data(n) => n as u16,
|
||||
};
|
||||
fat.write_u16::<LittleEndian>(raw_val)?;
|
||||
Ok(())
|
||||
Self::set_raw(fat, cluster, raw_value as u32)
|
||||
}
|
||||
|
||||
fn find_free<T: ReadSeek>(fat: &mut T, start_cluster: u32, end_cluster: u32) -> io::Result<u32> {
|
||||
@ -317,9 +341,14 @@ impl FatTrait for Fat32 {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_raw<T: ReadWriteSeek>(fat: &mut T, cluster: u32, raw_value: u32) -> io::Result<()> {
|
||||
fat.seek(io::SeekFrom::Start((cluster * 4) as u64))?;
|
||||
fat.write_u32::<LittleEndian>(raw_value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set<T: ReadWriteSeek>(fat: &mut T, cluster: u32, value: FatValue) -> io::Result<()> {
|
||||
let old_reserved_bits = Self::get_raw(fat, cluster)? & 0xF0000000;
|
||||
fat.seek(io::SeekFrom::Start((cluster * 4) as u64))?;
|
||||
|
||||
if value == FatValue::Free && cluster >= 0x0FFFFFF7 && cluster <= 0x0FFFFFFF {
|
||||
// NOTE: it is technically allowed for them to store FAT chain loops,
|
||||
@ -338,8 +367,7 @@ impl FatTrait for Fat32 {
|
||||
FatValue::Data(n) => n,
|
||||
};
|
||||
let raw_val = raw_val | old_reserved_bits; // must preserve original reserved values
|
||||
fat.write_u32::<LittleEndian>(raw_val)?;
|
||||
Ok(())
|
||||
Self::set_raw(fat, cluster, raw_val)
|
||||
}
|
||||
|
||||
fn find_free<T: ReadSeek>(fat: &mut T, start_cluster: u32, end_cluster: u32) -> io::Result<u32> {
|
||||
|
@ -11,17 +11,9 @@ const KB: u32 = 1024;
|
||||
const MB: u32 = KB * 1024;
|
||||
const TEST_STR: &str = "Hi there Rust programmer!\n";
|
||||
|
||||
#[test]
|
||||
fn test_format() {
|
||||
let _ = env_logger::try_init();
|
||||
let storage_vec: Vec<u8> = Vec::with_capacity((8 * MB) as usize);
|
||||
let storage_cur = io::Cursor::new(storage_vec);
|
||||
let mut buffered_stream = BufStream::new(storage_cur);
|
||||
let mut opts: fatfs::FormatOptions = Default::default();
|
||||
opts.total_sectors = 8 * MB / 512;
|
||||
fatfs::format_volume(&mut buffered_stream, opts).expect("format volume");
|
||||
type FileSystem = fatfs::FileSystem<BufStream<io::Cursor<Vec<u8>>>>;
|
||||
|
||||
let fs = fatfs::FileSystem::new(buffered_stream, fatfs::FsOptions::new()).expect("open fs");
|
||||
fn basic_fs_test(fs: &FileSystem) {
|
||||
let root_dir = fs.root_dir();
|
||||
let entries = root_dir.iter().map(|r| r.unwrap()).collect::<Vec<_>>();
|
||||
assert_eq!(entries.len(), 0);
|
||||
@ -33,3 +25,52 @@ fn test_format() {
|
||||
let entries = root_dir.iter().map(|r| r.unwrap()).collect::<Vec<_>>();
|
||||
assert_eq!(entries.len(), 1);
|
||||
}
|
||||
|
||||
fn test_format_fs(opts: fatfs::FormatOptions, total_bytes: u64) -> FileSystem {
|
||||
let _ = env_logger::try_init();
|
||||
let storage_vec: Vec<u8> = Vec::with_capacity(total_bytes as usize);
|
||||
let storage_cur = io::Cursor::new(storage_vec);
|
||||
let mut buffered_stream = BufStream::new(storage_cur);
|
||||
fatfs::format_volume(&mut buffered_stream, opts).expect("format volume");
|
||||
|
||||
let fs = fatfs::FileSystem::new(buffered_stream, fatfs::FsOptions::new()).expect("open fs");
|
||||
basic_fs_test(&fs);
|
||||
fs
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format_1mb() {
|
||||
let total_bytes = 1 * MB as u64;
|
||||
let mut opts: fatfs::FormatOptions = Default::default();
|
||||
opts.total_sectors = (total_bytes / 512) as u32;
|
||||
let fs = test_format_fs(opts, total_bytes);
|
||||
assert_eq!(fs.fat_type(), fatfs::FatType::Fat12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format_8mb() {
|
||||
let total_bytes = 8 * MB as u64;
|
||||
let mut opts: fatfs::FormatOptions = Default::default();
|
||||
opts.total_sectors = (total_bytes / 512) as u32;
|
||||
let fs = test_format_fs(opts, total_bytes);
|
||||
assert_eq!(fs.fat_type(), fatfs::FatType::Fat16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format_50mb() {
|
||||
let total_bytes = 50 * MB as u64;
|
||||
let mut opts: fatfs::FormatOptions = Default::default();
|
||||
opts.total_sectors = (total_bytes / 512) as u32;
|
||||
let fs = test_format_fs(opts, total_bytes);
|
||||
assert_eq!(fs.fat_type(), fatfs::FatType::Fat16);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_format_512mb() {
|
||||
let total_bytes = 2 * 1024 * MB as u64;
|
||||
let mut opts: fatfs::FormatOptions = Default::default();
|
||||
opts.total_sectors = (total_bytes / 512) as u32;
|
||||
let fs = test_format_fs(opts, total_bytes);
|
||||
assert_eq!(fs.fat_type(), fatfs::FatType::Fat32);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user