From 529f58b5f46d4b4d85a89d670e0d46c16ded9668 Mon Sep 17 00:00:00 2001 From: pigeonmoelleux Date: Wed, 25 Oct 2023 19:31:35 +0200 Subject: [PATCH] * refactor(error): begin use of anyhow * feat(dev): begin of devices implementations --- Cargo.toml | 1 + src/dev/mod.rs | 3 ++ src/dev/sector.rs | 124 ++++++++++++++++++++++++++++++++++++++++++++++ src/error.rs | 36 -------------- src/ext2/error.rs | 23 +++++++++ src/ext2/mod.rs | 5 ++ src/fs.rs | 26 +++++----- src/lib.rs | 5 +- 8 files changed, 173 insertions(+), 50 deletions(-) create mode 100644 src/dev/mod.rs create mode 100644 src/dev/sector.rs delete mode 100644 src/error.rs create mode 100644 src/ext2/error.rs create mode 100644 src/ext2/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 321b4ae..bf78fe3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ name = "efs" path = "src/lib.rs" [dependencies] +anyhow = { version = "1", default-features = false } derive_more = "0.99" itertools = { version = "0.11", default-features = false, features = ["use_alloc"] } no_std_io = "0.6.0" diff --git a/src/dev/mod.rs b/src/dev/mod.rs new file mode 100644 index 0000000..f5771f8 --- /dev/null +++ b/src/dev/mod.rs @@ -0,0 +1,3 @@ +//! Everything related to the devices + +pub mod sector; diff --git a/src/dev/sector.rs b/src/dev/sector.rs new file mode 100644 index 0000000..4c45804 --- /dev/null +++ b/src/dev/sector.rs @@ -0,0 +1,124 @@ +//! General description of sectors. + +use core::fmt::{self, Debug}; +use core::marker::PhantomData; + +use anyhow::{anyhow, Error, Result}; + +/// General interface for sector sizes that are device-dependant. +pub trait Size: Clone + Copy + PartialEq + Eq { + /// Logarithm in base 2 of the sector size. + const LOG_SIZE: u32; + + /// Size of a sector. + const SIZE: u32 = 1 << Self::LOG_SIZE; + + /// Offset mask of the sector size. + const OFFSET_MASK: u32 = Self::SIZE - 1; +} + +/// Size sector of 512 bytes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Size512; + +impl Size for Size512 { + const LOG_SIZE: u32 = 9; +} + +/// Size sector of 1024 bytes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Size1024; + +impl Size for Size1024 { + const LOG_SIZE: u32 = 10; +} + +/// Size sector of 2048 bytes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Size2048; + +impl Size for Size2048 { + const LOG_SIZE: u32 = 11; +} + +/// Size sector of 4096 bytes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Size4096; + +impl Size for Size4096 { + const LOG_SIZE: u32 = 12; +} + +/// Address of a physical sector +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Address { + /// Sector in which the address is located. + sector: u32, + + /// Offset of this address in the sector. + offset: u32, + + /// Phantom data to store the sector size. + _phantom: PhantomData, +} + +impl Debug for Address { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter + .debug_struct("Address") + .field("sector", &self.sector) + .field("offset", &self.offset) + .finish() + } +} + +impl Address { + /// Returns a new [`Address`] with an offset such that `0 <= offset < S::SIZE` + /// + /// # Errors + /// + /// Returns an [`Error`](anyhow::Error) + #[inline] + pub fn new(sector: u32, offset: i32) -> Result { + let real_sector = TryInto::::try_into(TryInto::::try_into(sector).map_err(Error::msg)? + (offset >> S::LOG_SIZE)) + .map_err(Error::msg)?; + let real_offset = offset.unsigned_abs() & S::OFFSET_MASK; + if real_offset >= S::SIZE { + Err(anyhow!("Offset Out of Bounds: the offset {real_offset} is greater than the sector size {}", S::SIZE)) + } else { + Ok(Self { + sector: real_sector, + offset: real_offset, + _phantom: PhantomData, + }) + } + } + + /// Returns the sector containing this address. + #[inline] + #[must_use] + pub const fn sector(&self) -> u32 { + self.sector + } + + /// Returns the offset of this address in its sector. + #[inline] + #[must_use] + pub const fn offset(&self) -> u32 { + self.offset + } +} + +#[cfg(test)] +mod test { + use super::{Size, Size1024, Size2048, Size4096, Size512}; + + #[test] + fn sizes() { + assert_eq!(Size512::SIZE, 512); + assert_eq!(Size1024::SIZE, 1024); + assert_eq!(Size2048::SIZE, 2048); + assert_eq!(Size4096::SIZE, 4096); + } +} diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index 736c218..0000000 --- a/src/error.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Interface for `efs` possible errors - -use core::error; -use core::fmt::{self, Display}; - -use no_std_io::io; - -use crate::fs::FsError; -use crate::path::PathError; - -/// Enumeration of possible sources of error -#[allow(clippy::error_impl_error)] -#[derive(Debug)] -pub enum Error { - /// I/O error - IO(io::ErrorKind), - - /// Path error - Path(PathError), - - /// Filesystem error - Fs(FsError), -} - -impl Display for Error { - #[inline] - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::IO(io_error) => write!(formatter, "I/O Error: {io_error:?}"), - Self::Path(path_error) => write!(formatter, "Path Error: {path_error}"), - Self::Fs(fs_error) => write!(formatter, "Filesystem Error: {fs_error}"), - } - } -} - -impl error::Error for Error {} diff --git a/src/ext2/error.rs b/src/ext2/error.rs new file mode 100644 index 0000000..9d5b36d --- /dev/null +++ b/src/ext2/error.rs @@ -0,0 +1,23 @@ +//! Errors related to Ext2 manipulation. + +use core::error; +use core::fmt::{self, Display}; + +/// Enumeration of possible errors encountered with Ext2's manipulation. +#[allow(clippy::module_name_repetitions)] +#[derive(Debug, PartialEq, Eq)] +pub enum Ext2Error { + /// A bad magic number has been found during the superblock parsing. + BadMagic(u16), +} + +impl Display for Ext2Error { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::BadMagic(magic) => write!(formatter, "Bad Magic: {magic} has been found while TODO was expected"), + } + } +} + +impl error::Error for Ext2Error {} diff --git a/src/ext2/mod.rs b/src/ext2/mod.rs new file mode 100644 index 0000000..e312d7b --- /dev/null +++ b/src/ext2/mod.rs @@ -0,0 +1,5 @@ +//! Implementation of the Second Extended Filesystem (ext2fs) filesystem. +//! +//! See [its Wikipedia page](https://fr.wikipedia.org/wiki/Ext2) or [its OSDev page](https://wiki.osdev.org/Ext2) for more informations. + +pub mod error; diff --git a/src/fs.rs b/src/fs.rs index b1de814..a410e10 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -5,13 +5,14 @@ use alloc::boxed::Box; use alloc::string::{String, ToString}; use alloc::vec; use alloc::vec::Vec; +use core::error; use core::fmt::{self, Display}; use core::str::FromStr; +use anyhow::{anyhow, Error, Result}; use itertools::{Itertools, Position}; use no_std_io::io; -use crate::error::Error; use crate::file::{Directory, Type}; use crate::path::{Component, Path}; @@ -51,6 +52,8 @@ impl Display for FsError { } } +impl error::Error for FsError {} + /// A filesystem pub trait FileSystem { /// Returns the root directory of the filesystem. @@ -82,7 +85,7 @@ pub trait FileSystem { /// /// Returns an [`NoEnt`](FsError::NoEnt) error if an encountered symlink points to a non-existing file. #[inline] - fn pathname_resolution(&self, path: &Path, current_dir: Box, symlink_resolution: bool) -> Result + fn pathname_resolution(&self, path: &Path, current_dir: Box, symlink_resolution: bool) -> Result where Self: Sized, { @@ -95,11 +98,11 @@ pub trait FileSystem { mut current_dir: Box, symlink_resolution: bool, mut visited_symlinks: Vec, - ) -> Result { + ) -> Result { let canonical_path = path.canonical(); if canonical_path.len() > PATH_MAX { - return Err(Error::Fs(FsError::NameTooLong(canonical_path.to_string()))); + return Err(anyhow!(FsError::NameTooLong(canonical_path.to_string()))); } let trailing_blackslash = canonical_path.as_unix_str().has_trailing_backslash(); @@ -131,7 +134,7 @@ pub trait FileSystem { let children = current_dir.entries(); let Some(entry) = children.into_iter().find(|entry| entry.filename == filename).map(|entry| entry.file) else { - return Err(Error::IO(io::ErrorKind::NotFound)); + return Err(anyhow!(io::Error::from(io::ErrorKind::NotFound))); }; #[allow(clippy::wildcard_enum_match_arm)] @@ -159,7 +162,7 @@ pub trait FileSystem { { let pointed_file = symlink.pointed_file().to_owned(); if pointed_file.is_empty() { - return Err(Error::Fs(FsError::NoEnt(filename.to_string()))); + return Err(anyhow!(FsError::NoEnt(filename.to_string()))); }; symlink_encountered = Some(pointed_file); @@ -169,7 +172,7 @@ pub trait FileSystem { return if (pos == Position::Last || pos == Position::Only) && !trailing_blackslash { Ok(entry) } else { - Err(Error::Fs(FsError::NotDir(filename.to_string()))) + Err(anyhow!(FsError::NotDir(filename.to_string()))) }; }, } @@ -181,14 +184,11 @@ pub trait FileSystem { None => Ok(Type::Directory(current_dir)), Some(pointed_file) => { if visited_symlinks.contains(&pointed_file) { - return Err(Error::Fs(FsError::Loop(pointed_file))); + return Err(anyhow!(FsError::Loop(pointed_file))); } visited_symlinks.push(pointed_file.clone()); - let pointed_path = match Path::from_str(&pointed_file) { - Ok(path) => path, - Err(path_error) => return Err(Error::Path(path_error)), - }; + let pointed_path = Path::from_str(&pointed_file).map_err(Error::msg)?; let complete_path = match TryInto::::try_into(&components) { Ok(remaining_path) => pointed_path.join(&remaining_path), @@ -196,7 +196,7 @@ pub trait FileSystem { }; if complete_path.len() >= PATH_MAX { - Err(Error::Fs(FsError::NameTooLong(complete_path.to_string()))) + Err(anyhow!(FsError::NameTooLong(complete_path.to_string()))) } else { inner_resolution(fs, &complete_path, current_dir, symlink_resolution, visited_symlinks) } diff --git a/src/lib.rs b/src/lib.rs index 177bb40..ab40503 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,8 +63,11 @@ extern crate alloc; extern crate core; -pub mod error; pub mod file; pub mod fs; pub mod path; pub mod types; + +pub mod dev; + +pub mod ext2;