refactor(fs/fat32): move bpb to data.rs
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
use libcommon::{read_le16, read_le32};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bpb {
|
||||
sectors_per_cluster: u8,
|
||||
reserved_sectors: u16,
|
||||
fat_count: u8,
|
||||
sectors_per_fat: u32,
|
||||
}
|
||||
|
||||
impl Bpb {
|
||||
pub fn from_sector(data: &[u8]) -> Self {
|
||||
Self {
|
||||
fat_count: data[16],
|
||||
reserved_sectors: read_le16(&data[14..]),
|
||||
sectors_per_cluster: data[13],
|
||||
sectors_per_fat: read_le32(&data[36..]),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn cluster_base_sector(&self, cluster: u32) -> u32 {
|
||||
let first_data_sector =
|
||||
self.reserved_sectors as u32 + (self.fat_count as u32 * self.sectors_per_fat as u32);
|
||||
((cluster - 2) * self.sectors_per_cluster as u32) + first_data_sector
|
||||
}
|
||||
|
||||
pub const fn sectors_per_cluster(&self) -> u8 {
|
||||
self.sectors_per_cluster
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -49,7 +49,7 @@ impl VnodeImpl for DirectoryInode {
|
||||
let bpb: &Bpb = fs_data.as_ref().and_then(|e| e.downcast_ref()).unwrap();
|
||||
let sector = bpb.cluster_base_sector(self.cluster);
|
||||
|
||||
FatIterator::new(dev, sector, bpb.sectors_per_cluster)
|
||||
FatIterator::new(dev, sector, bpb.sectors_per_cluster())
|
||||
.find(|ent| ent.name == name)
|
||||
.ok_or(Errno::DoesNotExist)
|
||||
}?;
|
||||
|
||||
+12
-105
@@ -6,25 +6,19 @@ extern crate std;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{rc::Rc, boxed::Box};
|
||||
use alloc::{boxed::Box, rc::Rc};
|
||||
use core::any::Any;
|
||||
use core::cell::{Ref, RefCell};
|
||||
use error::Errno;
|
||||
use libcommon::{read_le16, read_le32};
|
||||
use libcommon::read_le32;
|
||||
use vfs::{BlockDevice, Filesystem, Vnode, VnodeKind, VnodeRef};
|
||||
|
||||
pub mod dir;
|
||||
pub use dir::{Dirent as FatEntry, FatIterator, DirectoryInode};
|
||||
pub use dir::{DirectoryInode, Dirent as FatEntry, FatIterator};
|
||||
pub mod file;
|
||||
pub use file::FileInode;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Bpb {
|
||||
sectors_per_cluster: u8,
|
||||
reserved_sectors: u16,
|
||||
fat_count: u8,
|
||||
sectors_per_fat: u32,
|
||||
}
|
||||
pub mod data;
|
||||
pub use data::Bpb;
|
||||
|
||||
pub struct Fat32 {
|
||||
bpb: RefCell<Bpb>,
|
||||
@@ -32,14 +26,6 @@ pub struct Fat32 {
|
||||
dev: &'static dyn BlockDevice,
|
||||
}
|
||||
|
||||
impl Bpb {
|
||||
pub const fn cluster_base_sector(&self, cluster: u32) -> u32 {
|
||||
let first_data_sector = self.reserved_sectors as u32
|
||||
+ (self.fat_count as u32 * self.sectors_per_fat as u32);
|
||||
((cluster - 2) * self.sectors_per_cluster as u32) + first_data_sector
|
||||
}
|
||||
}
|
||||
|
||||
impl Filesystem for Fat32 {
|
||||
fn root(self: Rc<Self>) -> Result<VnodeRef, Errno> {
|
||||
self.root.borrow().clone().ok_or(Errno::DoesNotExist)
|
||||
@@ -55,17 +41,6 @@ impl Filesystem for Fat32 {
|
||||
}
|
||||
|
||||
impl Fat32 {
|
||||
fn create_node(self: Rc<Self>, name: &str, kind: VnodeKind, cluster: u32) -> VnodeRef {
|
||||
let res = Vnode::new(name, kind, Vnode::SEEKABLE);
|
||||
|
||||
res.set_fs(self.clone());
|
||||
res.set_data(match kind {
|
||||
VnodeKind::Directory => Box::new(DirectoryInode { cluster }),
|
||||
_ => todo!(),
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
pub fn open(dev: &'static dyn BlockDevice) -> Result<Rc<Self>, Errno> {
|
||||
let mut buf = [0u8; 512];
|
||||
|
||||
@@ -78,86 +53,18 @@ impl Fat32 {
|
||||
let root_cluster = read_le32(&buf[44..]);
|
||||
|
||||
let res = Rc::new(Self {
|
||||
bpb: RefCell::new(Bpb {
|
||||
fat_count: buf[16],
|
||||
reserved_sectors: read_le16(&buf[14..]),
|
||||
sectors_per_cluster: buf[13],
|
||||
sectors_per_fat: read_le32(&buf[36..]),
|
||||
}),
|
||||
bpb: RefCell::new(Bpb::from_sector(&buf)),
|
||||
dev,
|
||||
root: RefCell::new(None),
|
||||
});
|
||||
|
||||
*res.root.borrow_mut() = Some(res.clone().create_node(
|
||||
"",
|
||||
VnodeKind::Directory,
|
||||
root_cluster,
|
||||
));
|
||||
let root = Vnode::new("", VnodeKind::Directory, Vnode::SEEKABLE);
|
||||
root.set_fs(res.clone());
|
||||
root.set_data(Box::new(DirectoryInode {
|
||||
cluster: root_cluster,
|
||||
}));
|
||||
*res.root.borrow_mut() = Some(root);
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::cell::RefCell;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use libcommon::{Read as LRead};
|
||||
use vfs::Ioctx;
|
||||
|
||||
struct FileBlockDevice {
|
||||
file: RefCell<Option<File>>,
|
||||
}
|
||||
|
||||
impl FileBlockDevice {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
file: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&self, path: &str) {
|
||||
*self.file.borrow_mut() = Some(File::open(path).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockDevice for FileBlockDevice {
|
||||
fn read(&self, pos: usize, buf: &mut [u8]) -> Result<(), Errno> {
|
||||
let mut borrow = self.file.borrow_mut();
|
||||
let file = borrow.as_mut().unwrap();
|
||||
file.seek(SeekFrom::Start(pos as u64)).unwrap();
|
||||
if file.read(buf).unwrap() != buf.len() {
|
||||
Err(Errno::InvalidArgument)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, _pos: usize, _buf: &[u8]) -> Result<(), Errno> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for FileBlockDevice {}
|
||||
|
||||
#[test]
|
||||
fn test_fat32_open() {
|
||||
static DEV: FileBlockDevice = FileBlockDevice::new();
|
||||
|
||||
DEV.open("test/test0.img");
|
||||
|
||||
let fs = Fat32::open(&DEV).unwrap();
|
||||
let root = fs.root().unwrap();
|
||||
let ioctx = Ioctx::new(root);
|
||||
|
||||
let mut buf = [0u8; 512];
|
||||
let node0 = ioctx.find(None, "FILENAME.TXT").unwrap();
|
||||
let mut file = node0.open().unwrap();
|
||||
|
||||
let count = file.read(&mut buf).unwrap();
|
||||
assert_eq!(count, 15);
|
||||
assert_eq!(&buf[..15], b"This is a file\n");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user