forked from AbleOS/ableos
vfs+ext2: initial FsNode::read() implementation
The VFS side of things for read() should be done, however due to my limited ext2 knowledge, I've not implemented partially reading a file, and in this state only full files can be read.
This commit is contained in:
parent
600a81adf7
commit
91c1783b99
|
@ -7,6 +7,8 @@
|
|||
pub enum FsError {
|
||||
InodeNotFound,
|
||||
InvalidDevice,
|
||||
IsDirectory,
|
||||
EndOfFile,
|
||||
UnsupportedOperation,
|
||||
}
|
||||
|
||||
|
|
|
@ -51,11 +51,24 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn read(&self, _node: &FsNode, _offset: usize, _size: usize) -> Result<Box<[u8]>> {
|
||||
todo!()
|
||||
fn read(&self, node: &FsNode, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<()> {
|
||||
let inode = self
|
||||
.fs
|
||||
.inode_nth(node.inode as usize)
|
||||
.ok_or_else(|| FsError::InodeNotFound)?;
|
||||
|
||||
// FIXME: I don't really know how Ext2 works, so for now we don't
|
||||
// support non-zero offsets and buffer sizes that don't match
|
||||
// the file length. We always read the whole file.
|
||||
if offset > 0 || size != inode.size() {
|
||||
Err(FsError::UnsupportedOperation)?;
|
||||
}
|
||||
|
||||
fn write(&self, _node: &FsNode, _offset: usize, _buffer: Box<[u8]>) -> Result<()> {
|
||||
inode.read_to_end(buffer).map_err(|e| e.into())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&self, _node: &FsNode, _offset: usize, _buffer: &[u8]) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
pub mod errors;
|
||||
pub mod ext2;
|
||||
|
||||
use core::cmp;
|
||||
|
||||
use alloc::sync::{Weak, Arc};
|
||||
use bitflags::bitflags;
|
||||
|
||||
|
@ -17,14 +19,15 @@ use FsResult as Result;
|
|||
|
||||
pub type FsResult<T> = core::result::Result<T, FsError>;
|
||||
|
||||
/// The methods on this trait are to be used internally.
|
||||
pub trait StorageDevice
|
||||
where
|
||||
Self: Send,
|
||||
{
|
||||
fn open(&self, node: Arc<FsNode> /* TODO: flags */) -> Result<FileDescriptor>;
|
||||
fn release(&self, node: FsNode) -> Result<()>;
|
||||
fn read(&self, node: &FsNode, offset: usize, size: usize) -> Result<Box<[u8]>>;
|
||||
fn write(&self, node: &FsNode, offset: usize, buffer: Box<[u8]>) -> Result<()>;
|
||||
fn read(&self, node: &FsNode, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<()>;
|
||||
fn write(&self, node: &FsNode, offset: usize, buffer: &[u8]) -> Result<()>;
|
||||
fn read_dir(&self, node: &FsNode, index: usize) -> Result<DirectoryEntry>;
|
||||
fn find_dir(&self, node: &FsNode, name: &str) -> Result<FsNode>;
|
||||
}
|
||||
|
@ -94,19 +97,29 @@ impl FsNode {
|
|||
/// This method reads from the VFS node without opening a new file
|
||||
/// descriptor. This is intended to be used internally, if you're trying to
|
||||
/// read a file then you probably want to read from a file descriptor.
|
||||
pub fn read(&self, offset: usize, size: usize) -> Result<Box<[u8]>> {
|
||||
pub fn read(&self, offset: usize, size: usize, buffer: &mut Vec<u8>) -> Result<usize> {
|
||||
let state = KERNEL_STATE.lock();
|
||||
let device = state
|
||||
.get_storage_device(self.device_handle)
|
||||
.ok_or_else(|| FsError::InvalidDevice)?;
|
||||
|
||||
device.read(self, offset, size)
|
||||
if self.is_dir() {
|
||||
Err(FsError::IsDirectory)?;
|
||||
}
|
||||
|
||||
if offset > self.length {
|
||||
Err(FsError::EndOfFile)?;
|
||||
}
|
||||
|
||||
let readable_size = cmp::min(size, self.length - offset);
|
||||
device.read(self, offset, readable_size, buffer)?;
|
||||
Ok(readable_size)
|
||||
}
|
||||
|
||||
/// This method writes to the VFS node without opening a new file
|
||||
/// descriptor. This is intended to be used internally, if you're trying to
|
||||
/// write to a file then you probably want to write to a file descriptor.
|
||||
pub fn write(&self, offset: usize, buffer: Box<[u8]>) -> Result<()> {
|
||||
pub fn write(&self, offset: usize, buffer: &[u8]) -> Result<()> {
|
||||
let state = KERNEL_STATE.lock();
|
||||
let device = state
|
||||
.get_storage_device(self.device_handle)
|
||||
|
@ -132,6 +145,10 @@ impl FsNode {
|
|||
|
||||
device.find_dir(self, name)
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool {
|
||||
(self.flags & FsFlags::DIRECTORY) == FsFlags::DIRECTORY
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FsNode {
|
||||
|
|
Loading…
Reference in a new issue