Sync computers
This commit is contained in:
157
crates/bffs/src/lib.rs
Normal file
157
crates/bffs/src/lib.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
#![feature(iterator_try_collect, iter_order_by)]
|
||||
#![cfg_attr(any(not(feature = "std"), target_arch = "riscv64"), no_std)]
|
||||
|
||||
use core::cell::RefCell;
|
||||
use core::fmt::Display;
|
||||
|
||||
use crate::{
|
||||
boot_sector::Fat32BootSector,
|
||||
consts::FAT32_CLUSTER_MASK,
|
||||
dir::Dir,
|
||||
entry::{DirEntry, FatEntry},
|
||||
error::Error,
|
||||
file::{File, RawFile},
|
||||
io::{Read, ReadLeExt, Seek, Write},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
pub mod boot_sector;
|
||||
pub mod consts;
|
||||
pub mod dir;
|
||||
pub mod entry;
|
||||
pub mod error;
|
||||
pub mod file;
|
||||
pub mod io;
|
||||
pub mod path;
|
||||
|
||||
pub trait ReadSeek: Read + Seek {}
|
||||
impl<T: Read + Seek> ReadSeek for T {}
|
||||
pub trait WriteSeek: Write + Seek {}
|
||||
impl<T: Write + Seek> WriteSeek for T {}
|
||||
pub trait ReadWriteSeek: Read + Write + Seek {}
|
||||
impl<T: Read + Write + Seek> ReadWriteSeek for T {}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Fat32FsInfo {
|
||||
pub lead_signature: u32,
|
||||
pub reserved1: [u8; 480],
|
||||
pub struct_signature: u32,
|
||||
pub free_count: u32,
|
||||
pub next_free: u32,
|
||||
pub reserved2: [u8; 12],
|
||||
pub trail_signature: u32,
|
||||
}
|
||||
|
||||
impl Fat32FsInfo {
|
||||
pub fn deserialize<T: Read>(disk: &mut T) -> Result<Self, Error<T::Error>> {
|
||||
let lead_signature = disk.read_u32_le()?;
|
||||
let mut reserved1 = [0u8; _];
|
||||
disk.read_exact(&mut reserved1)?;
|
||||
let struct_signature = disk.read_u32_le()?;
|
||||
let free_count = disk.read_u32_le()?;
|
||||
let next_free = disk.read_u32_le()?;
|
||||
let mut reserved2 = [0u8; _];
|
||||
disk.read_exact(&mut reserved2)?;
|
||||
let trail_signature = disk.read_u32_le()?;
|
||||
Ok(Self {
|
||||
lead_signature,
|
||||
reserved1,
|
||||
struct_signature,
|
||||
free_count,
|
||||
next_free,
|
||||
reserved2,
|
||||
trail_signature,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Fat32FileSystem<T> {
|
||||
device: RefCell<T>,
|
||||
pub boot_sector: Fat32BootSector,
|
||||
}
|
||||
|
||||
impl<T> Display for Fat32FileSystem<T> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
self.boot_sector.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ReadSeek> Fat32FileSystem<T> {
|
||||
pub fn new(mut device: T) -> Result<Self, Error<T::Error>> {
|
||||
device.seek(io::SeekFrom::Start(0))?;
|
||||
|
||||
let boot_sector = Fat32BootSector::deserialize(&mut device)?;
|
||||
Ok(Self {
|
||||
device: device.into(),
|
||||
boot_sector,
|
||||
})
|
||||
}
|
||||
/// Get the next cluster from the current one
|
||||
fn get_next_cluster(&self, current_cluster: u32) -> Result<u32, Error<T::Error>> {
|
||||
let fat_offset =
|
||||
self.fat_start_offset() + (current_cluster as u64 * size_of::<FatEntry>() as u64);
|
||||
self.device
|
||||
.borrow_mut()
|
||||
.seek(io::SeekFrom::Start(fat_offset))?;
|
||||
|
||||
let next = self.device.borrow_mut().read_u32_le()? & FAT32_CLUSTER_MASK;
|
||||
Ok(next)
|
||||
}
|
||||
}
|
||||
impl<T> Fat32FileSystem<T> {
|
||||
/// Start offset of the FAT
|
||||
pub fn fat_start_offset(&self) -> u64 {
|
||||
(self.boot_sector.reserved_sector_count as u64) * (self.boot_sector.bytes_per_sector as u64)
|
||||
}
|
||||
/// Start offset for data
|
||||
fn data_start_offset(&self) -> u64 {
|
||||
let fat_size = self.boot_sector.fat_size_32 as u64;
|
||||
let fats = (self.boot_sector.num_fats as u64) * fat_size;
|
||||
|
||||
fats * self.boot_sector.bytes_per_sector as u64 + self.fat_start_offset()
|
||||
}
|
||||
|
||||
/// Convert a cluster number to an offset
|
||||
fn cluster_to_offset(&self, cluster: u32) -> u64 {
|
||||
let cluster_offset = (cluster.saturating_sub(2)) as u64
|
||||
* self.boot_sector.sectors_per_cluster as u64
|
||||
* self.boot_sector.bytes_per_sector as u64;
|
||||
|
||||
self.data_start_offset() + cluster_offset
|
||||
}
|
||||
|
||||
fn cluster_size(&self) -> u64 {
|
||||
(self.boot_sector.sectors_per_cluster as u64) * (self.boot_sector.bytes_per_sector as u64)
|
||||
}
|
||||
|
||||
pub fn root_directory(&self) -> Dir<'_, T> {
|
||||
Dir::new(
|
||||
RawFile::new(self, self.boot_sector.root_cluster, None),
|
||||
self,
|
||||
)
|
||||
}
|
||||
}
|
||||
impl<T: ReadSeek> Fat32FileSystem<T> {
|
||||
pub fn open_entry<'b, P: Into<Path<'b>>>(
|
||||
&self,
|
||||
path: P,
|
||||
) -> Result<DirEntry<'_, T>, Error<T::Error>> {
|
||||
let path = path.into().as_str().trim_start_matches("/");
|
||||
self.root_directory().open_entry(path)
|
||||
}
|
||||
pub fn open_dir<'b, P: Into<Path<'b>>>(&self, path: P) -> Result<Dir<'_, T>, Error<T::Error>> {
|
||||
let path = path.into().as_str().trim_start_matches("/");
|
||||
self.root_directory().open_dir(path)
|
||||
}
|
||||
pub fn open_file<'b, P: Into<Path<'b>>>(
|
||||
&self,
|
||||
path: P,
|
||||
) -> Result<File<'_, T>, Error<T::Error>> {
|
||||
let path = path.into().as_str().trim_start_matches("/");
|
||||
self.root_directory().open_file(path)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user