diff --git a/ableos/src/filesystem/errors.rs b/ableos/src/filesystem/errors.rs index 238646911..49a08b053 100644 --- a/ableos/src/filesystem/errors.rs +++ b/ableos/src/filesystem/errors.rs @@ -10,6 +10,7 @@ pub enum FsError { InvalidDevice, IsDirectory, NotADirectory, + NotFound, UnsupportedOperation, } @@ -31,7 +32,7 @@ impl Into for ext2::error::Error { ext2::error::Error::InodeNotFound { inode: _ } => FsError::InodeNotFound, ext2::error::Error::NotADirectory { inode: _, name: _ } => FsError::NotADirectory, ext2::error::Error::NotAbsolute { name: _ } => todo!(), - ext2::error::Error::NotFound { name: _ } => todo!(), + ext2::error::Error::NotFound { name: _ } => FsError::NotFound, } } } diff --git a/ableos/src/filesystem/ext2.rs b/ableos/src/filesystem/ext2.rs index 0d351da2f..d0163a7e8 100644 --- a/ableos/src/filesystem/ext2.rs +++ b/ableos/src/filesystem/ext2.rs @@ -4,12 +4,16 @@ * SPDX-License-Identifier: MPL-2.0 */ +use alloc::sync::Weak; use ext2::fs::{sync::Synced, Ext2}; use ext2::sector::SectorSize; +use ext2::sys::inode::TypePerm; use ext2::volume::Volume; +use crate::handle::Handle; + use super::errors::FsError; -use super::{DirectoryEntry, FsNode, FsResult as Result, StorageDevice}; +use super::{DirectoryEntry, FsFlags, FsNode, FsResult as Result, StorageDevice}; pub struct Ext2StorageDevice where @@ -17,6 +21,7 @@ where V: Volume, { fs: Synced>, + device_handle: Handle, } impl Ext2StorageDevice @@ -24,9 +29,10 @@ where S: SectorSize, V: Volume, { - pub fn new(volume: V) -> Result { + pub fn new(volume: V, device_handle: Handle) -> Result { Ok(Self { fs: Synced::new(volume).map_err(|e| e.into())?, + device_handle, }) } } @@ -63,18 +69,64 @@ where .inode_nth(node.inode as usize) .ok_or_else(|| FsError::InodeNotFound)?; let mut dir = inode.directory().ok_or_else(|| FsError::NotADirectory)?; - let entry = dir.nth(index) + let entry = dir + .nth(index) .ok_or_else(|| FsError::InodeNotFound)? .map_err(|e| e.into())?; Ok(DirectoryEntry::new(entry.file_name_string(), entry.inode)) } - fn find_dir(&self, _node: &FsNode, _name: &str) -> Result { - todo!() + fn find_dir(&self, node: &FsNode, name: &str) -> Result { + let inode = self + .fs + .inode_nth(node.inode as usize) + .ok_or_else(|| FsError::InodeNotFound)?; + let dir = inode.directory().ok_or_else(|| FsError::NotADirectory)?; + let mut found_node = Err(FsError::NotFound); + for entry in dir { + if entry.is_err() { + continue; + } + + let entry = entry.unwrap(); + if entry.file_name_string() == name { + let inode = self + .fs + .inode_nth(entry.inode as usize) + .ok_or_else(|| FsError::InodeNotFound)?; + let flags = ext2_type_to_fs_flags(inode.type_perm()); + found_node = Ok(FsNode::new( + flags, + inode.size(), + entry.inode, + self.device_handle, + Weak::new(), + )) + } + } + + found_node } } +fn ext2_type_to_fs_flags(type_perm: TypePerm) -> FsFlags { + let is_directory = type_perm & TypePerm::DIRECTORY == TypePerm::DIRECTORY; + let is_symlink = type_perm & TypePerm::SYMLINK == TypePerm::SYMLINK; + let t = if is_directory { + FsFlags::DIRECTORY + } else { + FsFlags::FILE + }; + let s = if is_symlink { + FsFlags::SYMBOLIC_LINK + } else { + FsFlags::empty() + }; + + t | s +} + // fn load_fs() -> Arc>>> { // let mut volume = Vec::new(); // volume.extend_from_slice(include_bytes!("../../../userland/root_fs/ext2.img")); diff --git a/ableos/src/filesystem/mod.rs b/ableos/src/filesystem/mod.rs index dabf90d5c..6a37f5fad 100644 --- a/ableos/src/filesystem/mod.rs +++ b/ableos/src/filesystem/mod.rs @@ -9,7 +9,7 @@ pub mod ext2; use core::cmp; -use alloc::sync::{Weak, Arc}; +use alloc::sync::{Arc, Weak}; use bitflags::bitflags; use crate::{handle::Handle, KERNEL_STATE}; @@ -140,9 +140,9 @@ impl Drop for FsNode { bitflags! { /// Flags associated with VFS nodes and file descriptors /// - /// 0x00000MST - /// T is set to 0 for files, 1 for directories - /// S is set when the file is a symbolic link + /// 0x00000MST \ + /// T is set to 0 for files, 1 for directories \ + /// 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; @@ -159,9 +159,6 @@ pub struct DirectoryEntry { impl DirectoryEntry { fn new(name: String, inode: usize) -> Self { - Self { - name, - inode, - } + Self { name, inode } } } diff --git a/ableos/src/kernel_state.rs b/ableos/src/kernel_state.rs index 4cb693639..9d1236fe7 100644 --- a/ableos/src/kernel_state.rs +++ b/ableos/src/kernel_state.rs @@ -3,7 +3,7 @@ use hashbrown::HashMap; use spin::Lazy; use crate::{ - filesystem::{StorageDevice, FsNode}, + filesystem::{FsNode, StorageDevice}, handle::{Handle, HandleResource}, }; @@ -81,8 +81,6 @@ pub struct FileTableEntry { impl FileTableEntry { fn new(fs_node: Arc) -> Self { - Self { - fs_node - } + Self { fs_node } } } diff --git a/ext2-rs/src/fs/sync.rs b/ext2-rs/src/fs/sync.rs index d028b03e6..a5fc5584e 100644 --- a/ext2-rs/src/fs/sync.rs +++ b/ext2-rs/src/fs/sync.rs @@ -1,5 +1,7 @@ //! +use crate::sys::inode::TypePerm; + use { super::Ext2, alloc::{ @@ -543,6 +545,11 @@ impl> Inode { pub fn size(&self) -> usize { self.size32() as usize } + + /// ableOS: expose type_perm + pub fn type_perm(&self) -> TypePerm { + self.inner.type_perm + } } impl> File for Inode {