93 lines
2.5 KiB
Rust

use alloc::sync::Arc;
use core::any::Any;
use libk::vfs::{CommonImpl, InstanceData, Metadata, Node, NodeFlags, NodeRef, RegularImpl};
use libk_util::sync::{spin_rwlock::IrqSafeRwLock, IrqSafeSpinlock};
use yggdrasil_abi::{error::Error, io::OpenOptions};
use crate::{block::BlockAllocator, bvec::BVec, MemoryFilesystem};
pub(crate) struct FileNode<A: BlockAllocator> {
pub(crate) data: IrqSafeSpinlock<BVec<'static, A>>,
pub(crate) metadata: IrqSafeRwLock<Metadata>,
}
impl<A: BlockAllocator> FileNode<A> {
pub fn new(fs: Arc<MemoryFilesystem<A>>, metadata: Metadata) -> NodeRef {
Node::regular(
Self {
data: IrqSafeSpinlock::new(BVec::new()),
metadata: IrqSafeRwLock::new(metadata),
},
NodeFlags::empty(),
None,
Some(fs),
)
}
}
impl<A: BlockAllocator> CommonImpl for FileNode<A> {
fn as_any(&self) -> &dyn Any {
self
}
fn size(&self, _node: &NodeRef) -> Result<u64, Error> {
Ok(self.data.lock().size() as u64)
}
fn metadata(&self, _node: &NodeRef) -> Result<Metadata, Error> {
Ok(*self.metadata.read())
}
fn set_metadata(&self, _node: &NodeRef, metadata: &Metadata) -> Result<(), Error> {
*self.metadata.write() = *metadata;
Ok(())
}
}
impl<A: BlockAllocator> RegularImpl for FileNode<A> {
fn open(
&self,
_node: &NodeRef,
opts: OpenOptions,
) -> Result<(u64, Option<InstanceData>), Error> {
// TODO provide APPEND by vfs driver instead
if opts.contains(OpenOptions::APPEND) {
Ok((self.data.lock().size() as u64, None))
} else {
Ok((0, None))
}
}
fn read(
&self,
_node: &NodeRef,
_instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
self.metadata.write().set_atime_now();
self.data.lock().read(pos, buf)
}
fn write(
&self,
_node: &NodeRef,
_instance: Option<&InstanceData>,
pos: u64,
buf: &[u8],
) -> Result<usize, Error> {
self.metadata.write().set_mtime_now();
self.data.lock().write(pos, buf)
}
fn truncate(&self, _node: &NodeRef, new_size: u64) -> Result<(), Error> {
self.metadata.write().set_mtime_now();
self.data.lock().truncate(new_size)
}
fn close(&self, _node: &NodeRef, _instance: Option<&InstanceData>) -> Result<(), Error> {
Ok(())
}
}