diff --git a/ableos/src/filesystem/ext2.rs b/ableos/src/filesystem/ext2.rs index b1ad1c98..1430d2a0 100644 --- a/ableos/src/filesystem/ext2.rs +++ b/ableos/src/filesystem/ext2.rs @@ -9,7 +9,7 @@ use ext2::sector::SectorSize; use ext2::volume::Volume; use super::errors::FsError; -use super::{FsResult as Result, StorageDevice}; +use super::{FsResult as Result, StorageDevice, DirectoryEntry, FsNode, FileDescriptor}; pub struct Ext2StorageDevice where @@ -36,32 +36,32 @@ where S: SectorSize + Send, V: Volume + Send, { - fn open(&self, node: &super::FsNode /* TODO: flags */) -> Result { + fn open(&self, node: &super::FsNode /* TODO: flags */) -> Result { let inode = self .fs .inode_nth(node.inode as usize) .ok_or_else(|| FsError::InodeNotFound)?; - todo!() + Ok(FileDescriptor::new(node.flags, inode.size(), node.inode)) } fn close(&self, node: &super::FsNode) -> Result<()> { todo!() } - fn read(&self, node: &super::FsNode, offset: u32, size: u32) -> Result> { + fn read(&self, node: &super::FsNode, offset: usize, size: usize) -> Result> { todo!() } - fn write(&self, node: &super::FsNode, offset: u32, buffer: Box<[u8]>) -> Result<()> { + fn write(&self, node: &super::FsNode, offset: usize, buffer: Box<[u8]>) -> Result<()> { todo!() } - fn read_dir(&self, node: &super::FsNode, index: u32) -> Result { + fn read_dir(&self, node: &super::FsNode, index: usize) -> Result { todo!() } - fn find_dir(&self, node: &super::FsNode, name: &str) -> Result { + fn find_dir(&self, node: &super::FsNode, name: &str) -> Result { todo!() } } diff --git a/ableos/src/filesystem/mod.rs b/ableos/src/filesystem/mod.rs index f62122c7..2217d192 100644 --- a/ableos/src/filesystem/mod.rs +++ b/ableos/src/filesystem/mod.rs @@ -21,11 +21,11 @@ pub trait StorageDevice where Self: Send, { - fn open(&self, node: &FsNode /* TODO: flags */) -> Result; + fn open(&self, node: &FsNode /* TODO: flags */) -> Result; fn close(&self, node: &FsNode) -> Result<()>; - fn read(&self, node: &FsNode, offset: u32, size: u32) -> Result>; - fn write(&self, node: &FsNode, offset: u32, buffer: Box<[u8]>) -> Result<()>; - fn read_dir(&self, node: &FsNode, index: u32) -> Result; + fn read(&self, node: &FsNode, offset: usize, size: usize) -> Result>; + fn write(&self, node: &FsNode, offset: usize, buffer: Box<[u8]>) -> Result<()>; + fn read_dir(&self, node: &FsNode, index: usize) -> Result; fn find_dir(&self, node: &FsNode, name: &str) -> Result; } @@ -35,21 +35,21 @@ where /// opened. When there are no open file descriptors to a file, the associated /// VFS node is dropped. pub struct FsNode { - flags: FsNodeFlags, - length: u32, // in bytes - fd_count: u32, // count of open file descriptors - inode: u32, // implementation specific identifier for the node + flags: FsFlags, + length: usize, // in bytes + fd_count: usize, // count of open file descriptors + inode: usize, // implementation specific identifier for the node device_handle: Handle, // uniquely assigned device handle ptr: Weak, // used by mountpoints and symlinks - // todo: permissions mask - // todo: owning user/group + // TODO: permissions mask + // TODO: owning user/group } impl FsNode { pub fn new( - flags: FsNodeFlags, - length: u32, - inode: u32, + flags: FsFlags, + length: usize, + inode: usize, device_handle: Handle, ptr: Weak, ) -> Self { @@ -65,13 +65,16 @@ impl FsNode { /// This method opens a new file descriptor for this VFS node. // TODO: make this take flags - pub fn open(&self) -> Result { + pub fn open(&mut self) -> Result { let state = KERNEL_STATE.lock(); let device = state .get_storage_device(self.device_handle) .ok_or_else(|| FsError::InvalidDevice)?; + let fd = device.open(self)?; + let mut kernel_state = KERNEL_STATE.lock(); + let handle = kernel_state.add_file_descriptor(fd); - device.open(self) + Ok(handle) } /// This method is for closing the VFS node, which is done when no open file @@ -88,7 +91,7 @@ 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: u32, size: u32) -> Result> { + pub fn read(&self, offset: usize, size: usize) -> Result> { let state = KERNEL_STATE.lock(); let device = state .get_storage_device(self.device_handle) @@ -100,7 +103,7 @@ impl FsNode { /// 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: u32, buffer: Box<[u8]>) -> Result<()> { + pub fn write(&self, offset: usize, buffer: Box<[u8]>) -> Result<()> { let state = KERNEL_STATE.lock(); let device = state .get_storage_device(self.device_handle) @@ -109,7 +112,7 @@ impl FsNode { device.write(self, offset, buffer) } - pub fn read_dir(&self, index: u32) -> Result { + pub fn read_dir(&self, index: usize) -> Result { let state = KERNEL_STATE.lock(); let device = state .get_storage_device(self.device_handle) @@ -129,13 +132,13 @@ impl FsNode { } bitflags! { - /// Flags associated with VFS nodes. + /// Flags associated with VFS nodes and file descriptors /// /// 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 { + /// S is set when the file is a symbolic link + /// M is set if the file is an active mount point + pub struct FsFlags: u8 { const FILE = 0b00000000; const DIRECTORY = 0b00000001; const SYMBOLIC_LINK = 0b00000010; @@ -144,9 +147,28 @@ bitflags! { } /// A file descriptor. -pub struct FileDescriptor {} +pub struct FileDescriptor { + flags: FsFlags, + length: usize, // in bytes + inode: usize, // implementation specific identifier for the node + // TODO: permissions mask + // TODO: owning user/group + // TODO: read file position? + // FIXME: I'm not sure if this needs to have a ptr to the VFS node, + // figure that out. +} + +impl FileDescriptor { + fn new(flags: FsFlags, length: usize, inode: usize) -> Self { + Self { + flags, + length, + inode, + } + } +} pub struct DirectoryEntry { name: String, - inode: u32, + inode: usize, } diff --git a/ableos/src/kernel_state.rs b/ableos/src/kernel_state.rs index 29fcda5f..b66db2e1 100644 --- a/ableos/src/kernel_state.rs +++ b/ableos/src/kernel_state.rs @@ -2,7 +2,7 @@ use hashbrown::HashMap; use spin::Lazy; use crate::{ - filesystem::StorageDevice, + filesystem::{StorageDevice, FileDescriptor}, handle::{Handle, HandleResource}, }; @@ -12,6 +12,7 @@ pub static KERNEL_STATE: Lazy> = pub struct KernelInternalState { pub hostname: String, storage_devices: HashMap>, + fd_table: HashMap, should_shutdown: bool, } @@ -20,6 +21,7 @@ impl KernelInternalState { Self { should_shutdown: false, storage_devices: HashMap::new(), + fd_table: HashMap::new(), hostname: "".to_string(), } } @@ -28,15 +30,22 @@ impl KernelInternalState { self.hostname = hostname; } - pub fn add_storage_device(&mut self, device: impl StorageDevice + Send + 'static) { - self.storage_devices - .insert(Handle::new(HandleResource::StorageDevice), Box::new(device)); + pub fn add_storage_device(&mut self, device: impl StorageDevice + Send + 'static) -> Handle { + let handle = Handle::new(HandleResource::StorageDevice); + self.storage_devices.insert(handle, Box::new(device)); + handle } pub fn get_storage_device(&self, handle: Handle) -> Option<&dyn StorageDevice> { self.storage_devices.get(&handle).map(|d| &**d) } + pub fn add_file_descriptor(&mut self, fd: FileDescriptor) -> Handle { + let handle = Handle::new(HandleResource::FileDescriptor); + self.fd_table.insert(handle, fd); + handle + } + pub fn shutdown(&mut self) { self.should_shutdown = true; }