198 lines
5.7 KiB
Rust
198 lines
5.7 KiB
Rust
use alloc::{boxed::Box, string::String};
|
|
use core::{any::Any, mem::MaybeUninit};
|
|
|
|
use yggdrasil_abi::{
|
|
error::Error,
|
|
io::{DirectoryEntry, OpenOptions},
|
|
};
|
|
|
|
use crate::vfs::{
|
|
file::{DirectoryOpenPosition, InstanceData},
|
|
Filename,
|
|
};
|
|
|
|
use super::{CreateInfo, Metadata, NodeRef};
|
|
|
|
/// Common interface shared by all filesystem nodes
|
|
pub trait CommonImpl: Send + Sync {
|
|
/// Returns `&self` as a reference to `dyn Any`
|
|
fn as_any(&self) -> &dyn Any {
|
|
unimplemented!();
|
|
}
|
|
|
|
/// Fetches the metadata of the file from underlying storage
|
|
fn metadata(&self, node: &NodeRef) -> Result<Metadata, Error> {
|
|
let _ = node;
|
|
unreachable!("Kernel bug: .metadata() not implemented and no IN_MEMORY_PROPS set")
|
|
}
|
|
|
|
fn set_metadata(&self, node: &NodeRef, metadata: &Metadata) -> Result<(), Error> {
|
|
let _ = node;
|
|
let _ = metadata;
|
|
unreachable!("Kernel bug: .set_metadata() not implemented and no IN_MEMORY_PROPS set")
|
|
}
|
|
|
|
/// Fetches the size of the file from underlying storage
|
|
fn size(&self, node: &NodeRef) -> Result<u64, Error> {
|
|
let _ = node;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
}
|
|
|
|
/// Regular file interface
|
|
pub trait RegularImpl: CommonImpl {
|
|
/// Opens the file for reading/writing and returns a `(start position, instance data)` tuple
|
|
fn open(
|
|
&self,
|
|
node: &NodeRef,
|
|
opts: OpenOptions,
|
|
) -> Result<(u64, Option<InstanceData>), Error> {
|
|
let _ = node;
|
|
let _ = opts;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Closes a file
|
|
fn close(&self, node: &NodeRef, instance: Option<&InstanceData>) -> Result<(), Error> {
|
|
let _ = node;
|
|
let _ = instance;
|
|
Ok(())
|
|
}
|
|
|
|
/// Reads data from the file into given buffer
|
|
fn read(
|
|
&self,
|
|
node: &NodeRef,
|
|
instance: Option<&InstanceData>,
|
|
pos: u64,
|
|
buf: &mut [u8],
|
|
) -> Result<usize, Error> {
|
|
let _ = node;
|
|
let _ = instance;
|
|
let _ = pos;
|
|
let _ = buf;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Writes data to the file from given buffer
|
|
fn write(
|
|
&self,
|
|
node: &NodeRef,
|
|
instance: Option<&InstanceData>,
|
|
pos: u64,
|
|
buf: &[u8],
|
|
) -> Result<usize, Error> {
|
|
let _ = node;
|
|
let _ = instance;
|
|
let _ = pos;
|
|
let _ = buf;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Resizes the file to requested size
|
|
fn truncate(&self, node: &NodeRef, new_size: u64) -> Result<(), Error> {
|
|
let _ = node;
|
|
let _ = new_size;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
}
|
|
|
|
/// Directory implementation
|
|
pub trait DirectoryImpl: CommonImpl {
|
|
/// Opens a directory for reading its entries. Returns [DirectoryOpenPosition] to specify the
|
|
/// starting position.
|
|
fn open(&self, node: &NodeRef) -> Result<DirectoryOpenPosition, Error> {
|
|
let _ = node;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Fetches entries from a directory into given buffer
|
|
fn read_entries(
|
|
&self,
|
|
node: &NodeRef,
|
|
pos: u64,
|
|
entries: &mut [MaybeUninit<DirectoryEntry>],
|
|
) -> Result<(usize, u64), Error> {
|
|
let _ = node;
|
|
let _ = pos;
|
|
let _ = entries;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Creates a child node, but does not associate it with the directory yet
|
|
fn create_node(&self, parent: &NodeRef, info: &CreateInfo) -> Result<NodeRef, Error> {
|
|
let _ = parent;
|
|
let _ = info;
|
|
Err(Error::ReadOnly)
|
|
}
|
|
|
|
/// Associates the given node with the directory, creating an entry for it inside
|
|
fn attach_node(&self, parent: &NodeRef, child: &NodeRef, name: &Filename) -> Result<(), Error> {
|
|
let _ = parent;
|
|
let _ = child;
|
|
let _ = name;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Removes an entry of the directory with given name
|
|
fn unlink_node(&self, parent: &NodeRef, child: &NodeRef, name: &Filename) -> Result<(), Error> {
|
|
let _ = parent;
|
|
let _ = child;
|
|
let _ = name;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
/// Fetches the child of the directory with given name
|
|
fn lookup(&self, node: &NodeRef, name: &Filename) -> Result<NodeRef, Error> {
|
|
let _ = node;
|
|
let _ = name;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
|
|
fn contains(&self, node: &NodeRef, name: &Filename) -> bool {
|
|
match self.lookup(node, name) {
|
|
Ok(_) => true,
|
|
Err(_) => false,
|
|
}
|
|
}
|
|
|
|
/// Returns the "length" of the directory in entries
|
|
fn len(&self, node: &NodeRef) -> Result<usize, Error> {
|
|
let _ = node;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
}
|
|
|
|
/// Symbolic link interface
|
|
pub trait SymlinkImpl: CommonImpl {
|
|
// /// Returns the target node (if such is available directly) of the link
|
|
// fn target(&self, node: &NodeRef) -> Result<NodeRef, Error> {
|
|
// Err(Error::NotImplemented)
|
|
// }
|
|
|
|
/// Fetches the contents of the symlink into a [String]
|
|
fn read_to_string(&self) -> Result<String, Error> {
|
|
let mut data = Box::new([0; 512]);
|
|
let len = self.read_link(data.as_mut())?;
|
|
if len == data.len() {
|
|
return Err(Error::InvalidFile);
|
|
}
|
|
let str = core::str::from_utf8(&data[..len]).map_err(|_| Error::InvalidFile)?;
|
|
Ok(String::from(str))
|
|
}
|
|
|
|
/// Fetches the contents of the symlink into a buffer
|
|
fn read_link(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
|
let _ = buf;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
}
|
|
|
|
/// Hard link interface
|
|
pub trait HardlinkImpl: Sync + Send {
|
|
fn target(&self, node: &NodeRef) -> Result<NodeRef, Error> {
|
|
let _ = node;
|
|
Err(Error::NotImplemented)
|
|
}
|
|
}
|