diff --git a/src/error.rs b/src/error.rs index 5092a26..10cb16f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,4 @@ +//! Errors use { alloc::string::String, core::fmt::{self, Display}, @@ -9,39 +10,60 @@ use std::io; /// The set of all possible errors #[derive(Debug)] pub enum Error { + /// Generic error Other(String), + /// Bad magic number BadMagic { + /// The magic number magic: u16, }, + /// Out of bounds error OutOfBounds { + /// index index: usize, }, + /// Address out of bounds AddressOutOfBounds { + /// sector: u32, + /// offset: u32, + + /// size: usize, }, + /// Bad block group count BadBlockGroupCount { + /// by_blocks: u32, + /// by_inodes: u32, }, + /// Inode Not Found InodeNotFound { + /// inode number inode: u32, }, + /// Inode is not a directory NotADirectory { + /// inode number inode: u32, + /// inode name name: String, }, + /// Not Absolute Path NotAbsolute { + /// path name name: String, }, + + /// Not Found NotFound { + /// inode name name: String, }, #[cfg(any(test, not(feature = "no_std")))] - Io { - inner: io::Error, - }, + Io { inner: io::Error }, } impl Display for Error { @@ -98,4 +120,5 @@ impl From for Error { } } +/// Infalliable pub enum Infallible {} diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 7634f5c..1844e31 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -1,3 +1,5 @@ +//! + use { alloc::vec::Vec, core::mem, @@ -34,6 +36,7 @@ pub struct Ext2> { } impl> Ext2 { + /// pub fn new(volume: V) -> Result, Error> { let superblock = unsafe { Struct::from(Superblock::find(&volume)?) }; let block_groups_offset = Address::with_block_size( @@ -63,14 +66,14 @@ impl> Ext2 { block_groups, }) } - + /// Return the version of the filesystem pub fn version(&self) -> (u32, u16) { ( self.superblock.inner.rev_major, self.superblock.inner.rev_minor, ) } - + /// Return inode size pub fn inode_size(&self) -> usize { if self.version().0 == 0 { mem::size_of::() @@ -79,15 +82,15 @@ impl> Ext2 { self.superblock.inner.inode_size as usize } } - + /// pub fn inodes_count(&self) -> usize { self.superblock.inner.inodes_per_group as _ } - + /// pub fn total_inodes_count(&self) -> usize { self.superblock.inner.inodes_count as _ } - + /// pub fn block_group_count(&self) -> Result { self.superblock .inner @@ -98,27 +101,27 @@ impl> Ext2 { by_inodes: b, }) } - + /// pub fn total_block_count(&self) -> usize { self.superblock.inner.blocks_count as _ } - + /// pub fn free_block_count(&self) -> usize { self.superblock.inner.free_blocks_count as _ } - + /// pub fn block_size(&self) -> usize { self.superblock.inner.block_size() } - + /// pub fn log_block_size(&self) -> u32 { self.superblock.inner.log_block_size + 10 } - + /// pub fn sector_size(&self) -> usize { S::SIZE } - + /// pub fn log_sector_size(&self) -> u32 { S::LOG_SIZE } diff --git a/src/fs/sync.rs b/src/fs/sync.rs index ebcbf7a..9d6e9b9 100644 --- a/src/fs/sync.rs +++ b/src/fs/sync.rs @@ -1,3 +1,5 @@ +//! + use { super::Ext2, alloc::{ @@ -16,18 +18,20 @@ use { sys::inode::Inode as RawInode, volume::Volume, }; - +/// DOCME: what is this? pub struct Synced { inner: Arc>, } impl Synced { + /// DOCME: what is this? pub fn with_inner(inner: T) -> Synced { Synced { inner: Arc::new(Mutex::new(inner)), } } + /// DOCME: what is this? pub fn inner<'a>(&'a self) -> MutexGuard<'a, T> { self.inner.lock() } @@ -42,22 +46,23 @@ impl Clone for Synced { } impl> Synced> { + /// DOCME: what is this? pub fn new(volume: V) -> Result>, Error> { Ext2::new(volume).map(|inner| Synced::with_inner(inner)) } - + /// Get the root inode. pub fn root_inode(&self) -> Inode { self.inode_nth(2).unwrap() } - + /// Get the inode at the given index. pub fn inode_nth(&self, index: usize) -> Option> { self.inodes_nth(index).next() } - + /// DOCME: what is this? pub fn inodes(&self) -> Inodes { self.inodes_nth(1) } - + /// DOCME: what is this? pub fn inodes_nth(&self, index: usize) -> Inodes { assert!(index > 0, "inodes are 1-indexed"); let inner = self.inner(); @@ -70,11 +75,11 @@ impl> Synced> { index, } } - + /// DOCME: what is this? pub fn sector_size(&self) -> usize { S::SIZE } - + /// DOCME: what is this? pub fn log_sector_size(&self) -> u32 { S::LOG_SIZE } @@ -256,6 +261,7 @@ impl> Debug for Synced> { } #[derive(Debug, Clone)] +/// A collection of inodes. pub struct Inodes> { fs: Synced>, log_block_size: u32, @@ -302,6 +308,7 @@ impl> Iterator for Inodes { } #[derive(Debug)] +/// A single inode in an ext2 filesystem. pub struct Inode> { fs: Synced>, inner: RawInode, @@ -321,6 +328,7 @@ impl> Clone for Inode { } impl> Inode { + /// pub fn new( fs: Synced>, inner: RawInode, @@ -334,7 +342,7 @@ impl> Inode { num, } } - + /// Read to the end of a buffer. pub fn read_to_end(&self, buf: &mut Vec) -> Result { let total_size = self.size(); let capacity = buf.capacity(); @@ -358,14 +366,14 @@ impl> Inode { Err(err) }) } - + /// Return blocks on a sector pub fn blocks(&self) -> InodeBlocks { InodeBlocks { inode: self.clone(), index: 0, } } - + /// return a directory iterator pub fn directory(&self) -> Option> { if self.is_dir() { Some(Directory { @@ -381,16 +389,16 @@ impl> Inode { None } } - + /// Determine if an inode is a directory pub fn is_dir(&self) -> bool { use sys::inode::TypePerm; - unsafe { self.inner.type_perm.contains(TypePerm::DIRECTORY) } + self.inner.type_perm.contains(TypePerm::DIRECTORY) } - + /// pub fn block(&self, index: usize) -> Option { self.try_block(index).ok().and_then(|block| block) } - + /// Try to get a block pub fn try_block( &self, mut index: usize, @@ -501,27 +509,27 @@ impl> Inode { Ok(None) } - + /// pub fn in_use(&self) -> bool { self.inner.hard_links > 0 } - + /// return the uid pub fn uid(&self) -> u16 { self.inner.uid } - + /// pub fn sectors(&self) -> usize { self.inner.sectors_count as usize } - + /// pub fn size32(&self) -> u32 { self.inner.size_low } - + /// pub fn size64(&self) -> u64 { self.inner.size_low as u64 | (self.inner.size_high as u64) << 32 } - + /// #[cfg(target_pointer_width = "64")] #[inline] pub fn size(&self) -> usize { @@ -576,6 +584,7 @@ impl> File for Inode { } } +/// #[derive(Debug, Clone)] pub struct InodeBlocks> { inode: Inode, @@ -611,6 +620,7 @@ impl> Iterator for InodeBlocks { } #[derive(Debug, Clone)] +/// A directory structure pub struct Directory> { blocks: InodeBlocks, offset: usize, @@ -664,9 +674,13 @@ impl> Iterator for Directory { } #[derive(Clone)] +/// A directory entry pub struct DirectoryEntry { + /// The name of the entry pub name: Vec, + /// The inode of the entry pub inode: usize, + /// pub ty: u8, } diff --git a/src/lib.rs b/src/lib.rs index e38f5fc..549af9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +//! Ext2 crate for ableOS + +#![deny(missing_docs)] #![feature( min_specialization, const_fn_trait_bound, @@ -6,8 +9,8 @@ )] #![cfg_attr(all(not(test), feature = "no_std"), no_std)] -#[macro_use] extern crate alloc; + #[macro_use] extern crate bitflags; extern crate genfs; diff --git a/src/sector.rs b/src/sector.rs index ba29779..eb4a392 100644 --- a/src/sector.rs +++ b/src/sector.rs @@ -1,29 +1,35 @@ +//! Sector data. + use core::{ fmt::{self, Debug, Display, LowerHex}, iter::Step, marker::PhantomData, ops::{Add, Sub}, }; - +/// Size of a sector in bytes pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd + 'static { - // log_sector_size = log_2(sector_size) + /// DOCME: What is this? const LOG_SIZE: u32; + /// DOCME: What is this? const SIZE: usize = 1 << Self::LOG_SIZE; + /// DOCME: What is this? const OFFSET_MASK: u32 = (Self::SIZE - 1) as u32; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +/// DOCME: What is this? pub struct Size512; impl SectorSize for Size512 { const LOG_SIZE: u32 = 9; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +/// DOCME: What is this? pub struct Size1024; impl SectorSize for Size1024 { const LOG_SIZE: u32 = 10; } - +/// DOCME: What is this? #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size2048; impl SectorSize for Size2048 { @@ -31,13 +37,14 @@ impl SectorSize for Size2048 { } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +/// DOCME: What is this? pub struct Size4096; impl SectorSize for Size4096 { const LOG_SIZE: u32 = 12; } /// Address in a physical sector -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Address { sector: u32, offset: u32, @@ -45,6 +52,7 @@ pub struct Address { } impl Address { + /// pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address { assert!((offset as usize) < S::SIZE, "offset out of sector bounds"); let _phantom = PhantomData; @@ -54,13 +62,13 @@ impl Address { _phantom, } } - + /// pub fn new(sector: u32, offset: i32) -> Address { let sector = (sector as i32 + (offset >> S::LOG_SIZE)) as u32; let offset = offset.abs() as u32 & S::OFFSET_MASK; unsafe { Address::new_unchecked(sector, offset) } } - + /// pub fn with_block_size( block: u32, offset: i32, @@ -75,23 +83,23 @@ impl Address { let sector = block << log_diff | top_offset; unsafe { Address::new_unchecked(sector, offset) } } - + /// pub fn into_index(&self) -> u64 { ((self.sector as u64) << S::LOG_SIZE) + self.offset as u64 } - + /// Get the size of the sector pub const fn sector_size(&self) -> usize { S::SIZE } - + /// DOCME: What is this? pub const fn log_sector_size(&self) -> u32 { S::LOG_SIZE } - + /// Return the sector number pub fn sector(&self) -> u32 { self.sector } - + /// Return the offset in the sector pub fn offset(&self) -> u32 { self.offset } @@ -105,6 +113,7 @@ impl Step for Address { None } } + /* fn replace_one(&mut self) -> Self { mem::replace(self, Address::new(1, 0)) @@ -129,22 +138,12 @@ impl Step for Address { } */ - fn forward_checked(start: Self, count: usize) -> Option { - todo!("forward_checked") + fn forward_checked(_start: Self, count: usize) -> Option { + todo!("forward_checked: count: {}", count); } - fn backward_checked(start: Self, count: usize) -> Option { - todo!("backward_checked") - } -} - -impl Debug for Address { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let name = format!("Address<{}>", S::SIZE); - f.debug_struct(&name) - .field("sector", &self.sector) - .field("offset", &self.offset) - .finish() + fn backward_checked(_start: Self, count: usize) -> Option { + todo!("backward_checked count: {}", count); } } diff --git a/src/sys/block_group.rs b/src/sys/block_group.rs index 8c4d4b9..90bf165 100644 --- a/src/sys/block_group.rs +++ b/src/sys/block_group.rs @@ -1,9 +1,8 @@ +//! + use { alloc::vec::Vec, - core::{ - fmt::{self, Debug}, - mem, - }, + core::{fmt::Debug, mem}, error::Error, sector::{Address, SectorSize}, volume::Volume, @@ -22,7 +21,7 @@ use { /// Remember that blocks are numbered starting at 0, and that block numbers /// don't usually correspond to physical block addresses. #[repr(C, packed)] -#[derive(Clone, Copy)] +#[derive(Clone, Debug, Copy)] pub struct BlockGroupDescriptor { /// Block address of block usage bitmap pub block_usage_addr: u32, @@ -40,20 +39,8 @@ pub struct BlockGroupDescriptor { _reserved: [u8; 14], } -impl Debug for BlockGroupDescriptor { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("BlockGroupDescriptor") - .field("block_usage_addr", &self.block_usage_addr) - .field("inode_usage_addr", &self.inode_usage_addr) - .field("inode_table_block", &self.inode_table_block) - .field("free_blocks_count", &self.free_blocks_count) - .field("free_inodes_count", &self.free_inodes_count) - .field("dirs_count", &self.dirs_count) - .finish() - } -} - impl BlockGroupDescriptor { + /// Find a descriptor in a descriptor table pub unsafe fn find_descriptor>( haystack: &V, offset: Address, @@ -74,7 +61,7 @@ impl BlockGroupDescriptor { Ok(descr) } - + /// find a descriptor table pub unsafe fn find_descriptor_table>( haystack: &V, offset: Address, diff --git a/src/sys/inode.rs b/src/sys/inode.rs index 44e7025..15e912f 100644 --- a/src/sys/inode.rs +++ b/src/sys/inode.rs @@ -1,8 +1,7 @@ +//! + use { - core::{ - fmt::{self, Debug}, - mem, - }, + core::{fmt::Debug, mem}, error::Error, sector::{Address, SectorSize}, volume::Volume, @@ -16,7 +15,7 @@ use { /// array of inodes it is responsible for, and conversely every inode within a /// file system belongs to one of such tables (and one of such block groups). #[repr(C, packed)] -#[derive(Clone, Copy)] +#[derive(Clone, Debug, Copy)] pub struct Inode { /// Type and Permissions (see below) pub type_perm: TypePerm, @@ -71,35 +70,8 @@ pub struct Inode { pub _os_specific_2: [u8; 12], } -impl Debug for Inode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Inode") - .field("type_perm", &self.type_perm) - .field("uid", &self.uid) - .field("size_low", &self.size_low) - .field("atime", &self.atime) - .field("ctime", &self.ctime) - .field("mtime", &self.mtime) - .field("dtime", &self.dtime) - .field("gid", &self.gid) - .field("hard_links", &self.hard_links) - .field("sectors_count", &self.sectors_count) - .field("flags", &self.flags) - .field("os_specific_1", &self._os_specific_1) - .field("direct_pointer", &self.direct_pointer) - .field("indirect_pointer", &self.indirect_pointer) - .field("doubly_indirect", &self.doubly_indirect) - .field("triply_indirect", &self.triply_indirect) - .field("gen_number", &self.gen_number) - .field("ext_attribute_block", &self.ext_attribute_block) - .field("size_high", &self.size_high) - .field("frag_block_addr", &self.frag_block_addr) - .field("os_specific_2", &self._os_specific_2) - .finish() - } -} - impl Inode { + /// Discover the inode location on the disk. pub unsafe fn find_inode>( haystack: &V, offset: Address, @@ -127,6 +99,7 @@ impl Inode { } bitflags! { + /// pub struct TypePerm: u16 { /// FIFO const FIFO = 0x1000; @@ -170,6 +143,7 @@ bitflags! { } bitflags! { + /// Flags pub struct Flags: u32 { /// Secure deletion (not used) const SECURE_DEL = 0x00000001; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 91552bd..32ec8fb 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -1,3 +1,5 @@ -pub mod superblock; +//! + pub mod block_group; pub mod inode; +pub mod superblock; diff --git a/src/sys/superblock.rs b/src/sys/superblock.rs index 8e04519..bf6e492 100644 --- a/src/sys/superblock.rs +++ b/src/sys/superblock.rs @@ -1,8 +1,7 @@ +//! Superblock information + use { - core::{ - fmt::{self, Debug}, - mem, - }, + core::{fmt::Debug, mem}, error::Error, sector::{Address, SectorSize}, volume::Volume, @@ -44,7 +43,7 @@ pub const OS_LITE: u32 = 4; /// 512 byte sectors, the Superblock will begin at LBA 2 and will occupy all of /// sector 2 and 3. #[repr(C, packed)] -#[derive(Clone, Copy)] +#[derive(Clone, Debug, Copy)] pub struct Superblock { // taken from https://wiki.osdev.org/Ext2 /// Total number of inodes in file system @@ -148,7 +147,7 @@ pub struct Superblock { #[doc(hidden)] _reserved: [u8; 788], } - +/* impl Debug for Superblock { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Superblock") @@ -196,8 +195,9 @@ impl Debug for Superblock { .finish() } } - +*/ impl Superblock { + /// Discover the location of the superblock in the given block device. pub unsafe fn find>( haystack: &V, ) -> Result<(Superblock, Address), Error> { @@ -227,15 +227,17 @@ impl Superblock { } #[inline] + /// Return the block size pub fn block_size(&self) -> usize { 1024 << self.log_block_size } #[inline] + /// Return the fragment size pub fn frag_size(&self) -> usize { 1024 << self.log_frag_size } - + /// Return the number of blocks per group pub fn block_group_count(&self) -> Result { let blocks_mod = self.blocks_count % self.blocks_per_group; let inodes_mod = self.inodes_count % self.inodes_per_group; diff --git a/src/volume/mod.rs b/src/volume/mod.rs index e8fc605..f1b134e 100644 --- a/src/volume/mod.rs +++ b/src/volume/mod.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use { alloc::{ borrow::{Cow, ToOwned}, diff --git a/src/volume/size.rs b/src/volume/size.rs index 61da531..b8b5b26 100644 --- a/src/volume/size.rs +++ b/src/volume/size.rs @@ -1,3 +1,5 @@ +//! + use { core::{ cmp::Ordering, @@ -7,19 +9,28 @@ use { }; #[derive(Clone, Copy, Debug, Hash)] +/// A size pub enum Size { + /// An unbounded size Unbounded, + /// A bounded size Bounded(Address), } impl Size { + /// Try to get the length of the sector pub fn try_len(&self) -> Option> { match *self { Size::Unbounded => None, Size::Bounded(n) => Some(n), } } - + /// Get the length of the sector unsafely + /// + /// # Safety + /// + /// This function is unsafe because it does not check that the size is + /// bounded. pub unsafe fn len(&self) -> Address { match *self { Size::Unbounded => panic!( @@ -31,6 +42,7 @@ impl Size { } impl Size { + /// Check if the size is unbounded pub fn is_bounded(&self) -> bool { match *self { Size::Unbounded => false,