1
0
Fork 0
forked from koniifer/ableos
ableos-framebuffer/ableos/src/filesystem/mod.rs

160 lines
4.4 KiB
Rust
Raw Normal View History

2022-08-03 04:53:02 -05:00
/*
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
*
* SPDX-License-Identifier: MPL-2.0
*/
pub mod errors;
use alloc::rc::Weak;
use bitflags::bitflags;
use ext2::{
fs::{
sync::{Inode, Synced},
Ext2,
},
sector::{SectorSize, Size1024},
volume::Volume,
};
use spin::Lazy;
2022-08-03 04:53:02 -05:00
use crate::handle::Handle;
use self::errors::FsError;
use FsResult as Result;
2022-08-03 04:53:02 -05:00
pub type FsResult<T> = core::result::Result<T, FsError>;
pub type FsOpenOperation = fn(node: &FsNode /* TODO: flags */) -> Result<Handle>;
pub type FsCloseOperation = fn(node: &FsNode) -> Result<()>;
pub type FsReadOperation = fn(node: &FsNode, offset: u32, size: u32)
-> Result<Box<[u8]>>;
pub type FsWriteOperation = fn(node: &FsNode, offset: u32, buffer: Box<[u8]>)
-> Result<()>;
pub type FsReaddirOperation = fn(node: &FsNode, index: u32) -> Result<DirectoryEntry>;
pub type FsFinddirOperation = fn(node: &FsNode, name: &str) -> Result<FsNode>;
2022-08-03 04:53:02 -05:00
/// A VFS node, that can either be a file or a directory.
pub struct FsNode {
// FIXME: move the file name into the directory listing to implement hard
// links
name: String,
flags: FsNodeFlags,
length: u32, // in bytes
inode: u32, // implementation specific identifier for the node
device_handle: Handle, // uniquely assigned device handle
ptr: Weak<FsNode>, // used by mountpoints and symlinks
open: Option<FsOpenOperation>,
close: Option<FsCloseOperation>,
read: Option<FsReadOperation>,
write: Option<FsWriteOperation>,
readdir: Option<FsReaddirOperation>,
finddir: Option<FsFinddirOperation>,
2022-08-03 04:53:02 -05:00
// todo: permissions mask
// todo: owning user/group
}
impl FsNode {
// TODO: make this take flags
fn open(&self) -> Result<Handle> {
2022-08-03 04:53:02 -05:00
if let Some(open) = self.open {
open(self)
2022-08-03 04:53:02 -05:00
} else {
Err(FsError::UnsupportedOperation)
}
}
fn close(&self) -> Result<()> {
2022-08-03 04:53:02 -05:00
if let Some(close) = self.close {
close(self)
2022-08-03 04:53:02 -05:00
} else {
Err(FsError::UnsupportedOperation)
}
}
fn read(&self, offset: u32, size: u32) -> Result<Box<[u8]>> {
2022-08-03 04:53:02 -05:00
if let Some(read) = self.read {
read(self, offset, size)
2022-08-03 04:53:02 -05:00
} else {
Err(FsError::UnsupportedOperation)
}
}
fn write(&self, offset: u32, buffer: Box<[u8]>) -> Result<()> {
2022-08-03 04:53:02 -05:00
if let Some(write) = self.write {
write(self, offset, buffer)
} else {
Err(FsError::UnsupportedOperation)
}
}
fn readdir(&self, index: u32) -> Result<DirectoryEntry> {
if let Some(readdir) = self.readdir {
readdir(self, index)
} else {
Err(FsError::UnsupportedOperation)
}
}
fn finddir(&self, name: &str) -> Result<FsNode> {
if let Some(finddir) = self.finddir {
finddir(self, name)
2022-08-03 04:53:02 -05:00
} else {
Err(FsError::UnsupportedOperation)
}
}
}
bitflags! {
/// Flags associated with VFS nodes.
///
/// 0x00000MST
/// T is set to 0 for files, 1 for directories
/// S is set when the node is a symbolic link
/// M is set if the node is an active mount point
pub struct FsNodeFlags: u8 {
const FILE = 0b00000000;
const DIRECTORY = 0b00000001;
const SYMBOLIC_LINK = 0b00000010;
const MOUNT_POINT = 0b00000100;
}
}
pub struct DirectoryEntry {
name: String,
inode: u32,
2022-08-03 04:53:02 -05:00
}
2022-04-11 17:23:11 -05:00
pub static FILE_SYSTEM: Lazy<spin::Mutex<Synced<Ext2<Size1024, Vec<u8>>>>> =
Lazy::new(|| spin::Mutex::new(load_fs()));
pub fn walk<S: SectorSize, V: Volume<u8, S>>(
fs: &Synced<Ext2<S, V>>,
inode: Inode<S, V>,
name: String,
) {
if let Some(dir) = inode.directory() {
for entry in dir {
assert!(entry.is_ok());
let entry = entry.unwrap();
let entry_name = String::from_utf8_lossy(&entry.name);
println!("{}/{} => {}", name, entry_name, entry.inode,);
if entry_name != "." && entry_name != ".." {
walk(
fs,
fs.inode_nth(entry.inode).unwrap(),
format!("{}/{}", name, entry_name),
);
}
}
}
}
2022-04-11 17:23:11 -05:00
fn load_fs() -> Synced<Ext2<Size1024, Vec<u8>>> {
let mut volume = Vec::new();
volume.extend_from_slice(include_bytes!("../../../userland/root_fs/ext2.img"));
Synced::<Ext2<Size1024, _>>::new(volume).unwrap()
}