Files
yggdrasil/kernel/libk/src/vfs/node/traits.rs
T
2025-10-16 10:42:41 +03:00

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)
}
}