documentation

This commit is contained in:
Able 2022-02-07 23:23:44 -06:00
parent 1e537b063c
commit 8f7155dcff
11 changed files with 142 additions and 122 deletions

View file

@ -1,3 +1,4 @@
//! Errors
use { use {
alloc::string::String, alloc::string::String,
core::fmt::{self, Display}, core::fmt::{self, Display},
@ -9,39 +10,60 @@ use std::io;
/// The set of all possible errors /// The set of all possible errors
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
/// Generic error
Other(String), Other(String),
/// Bad magic number
BadMagic { BadMagic {
/// The magic number
magic: u16, magic: u16,
}, },
/// Out of bounds error
OutOfBounds { OutOfBounds {
/// index
index: usize, index: usize,
}, },
/// Address out of bounds
AddressOutOfBounds { AddressOutOfBounds {
///
sector: u32, sector: u32,
///
offset: u32, offset: u32,
///
size: usize, size: usize,
}, },
/// Bad block group count
BadBlockGroupCount { BadBlockGroupCount {
///
by_blocks: u32, by_blocks: u32,
///
by_inodes: u32, by_inodes: u32,
}, },
/// Inode Not Found
InodeNotFound { InodeNotFound {
/// inode number
inode: u32, inode: u32,
}, },
/// Inode is not a directory
NotADirectory { NotADirectory {
/// inode number
inode: u32, inode: u32,
/// inode name
name: String, name: String,
}, },
/// Not Absolute Path
NotAbsolute { NotAbsolute {
/// path name
name: String, name: String,
}, },
/// Not Found
NotFound { NotFound {
/// inode name
name: String, name: String,
}, },
#[cfg(any(test, not(feature = "no_std")))] #[cfg(any(test, not(feature = "no_std")))]
Io { Io { inner: io::Error },
inner: io::Error,
},
} }
impl Display for Error { impl Display for Error {
@ -98,4 +120,5 @@ impl From<io::Error> for Error {
} }
} }
/// Infalliable
pub enum Infallible {} pub enum Infallible {}

View file

@ -1,3 +1,5 @@
//!
use { use {
alloc::vec::Vec, alloc::vec::Vec,
core::mem, core::mem,
@ -34,6 +36,7 @@ pub struct Ext2<S: SectorSize, V: Volume<u8, S>> {
} }
impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> { impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> {
///
pub fn new(volume: V) -> Result<Ext2<S, V>, Error> { pub fn new(volume: V) -> Result<Ext2<S, V>, Error> {
let superblock = unsafe { Struct::from(Superblock::find(&volume)?) }; let superblock = unsafe { Struct::from(Superblock::find(&volume)?) };
let block_groups_offset = Address::with_block_size( let block_groups_offset = Address::with_block_size(
@ -63,14 +66,14 @@ impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> {
block_groups, block_groups,
}) })
} }
/// Return the version of the filesystem
pub fn version(&self) -> (u32, u16) { pub fn version(&self) -> (u32, u16) {
( (
self.superblock.inner.rev_major, self.superblock.inner.rev_major,
self.superblock.inner.rev_minor, self.superblock.inner.rev_minor,
) )
} }
/// Return inode size
pub fn inode_size(&self) -> usize { pub fn inode_size(&self) -> usize {
if self.version().0 == 0 { if self.version().0 == 0 {
mem::size_of::<RawInode>() mem::size_of::<RawInode>()
@ -79,15 +82,15 @@ impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> {
self.superblock.inner.inode_size as usize self.superblock.inner.inode_size as usize
} }
} }
///
pub fn inodes_count(&self) -> usize { pub fn inodes_count(&self) -> usize {
self.superblock.inner.inodes_per_group as _ self.superblock.inner.inodes_per_group as _
} }
///
pub fn total_inodes_count(&self) -> usize { pub fn total_inodes_count(&self) -> usize {
self.superblock.inner.inodes_count as _ self.superblock.inner.inodes_count as _
} }
///
pub fn block_group_count(&self) -> Result<usize, Error> { pub fn block_group_count(&self) -> Result<usize, Error> {
self.superblock self.superblock
.inner .inner
@ -98,27 +101,27 @@ impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> {
by_inodes: b, by_inodes: b,
}) })
} }
///
pub fn total_block_count(&self) -> usize { pub fn total_block_count(&self) -> usize {
self.superblock.inner.blocks_count as _ self.superblock.inner.blocks_count as _
} }
///
pub fn free_block_count(&self) -> usize { pub fn free_block_count(&self) -> usize {
self.superblock.inner.free_blocks_count as _ self.superblock.inner.free_blocks_count as _
} }
///
pub fn block_size(&self) -> usize { pub fn block_size(&self) -> usize {
self.superblock.inner.block_size() self.superblock.inner.block_size()
} }
///
pub fn log_block_size(&self) -> u32 { pub fn log_block_size(&self) -> u32 {
self.superblock.inner.log_block_size + 10 self.superblock.inner.log_block_size + 10
} }
///
pub fn sector_size(&self) -> usize { pub fn sector_size(&self) -> usize {
S::SIZE S::SIZE
} }
///
pub fn log_sector_size(&self) -> u32 { pub fn log_sector_size(&self) -> u32 {
S::LOG_SIZE S::LOG_SIZE
} }

View file

@ -1,3 +1,5 @@
//!
use { use {
super::Ext2, super::Ext2,
alloc::{ alloc::{
@ -16,18 +18,20 @@ use {
sys::inode::Inode as RawInode, sys::inode::Inode as RawInode,
volume::Volume, volume::Volume,
}; };
/// DOCME: what is this?
pub struct Synced<T> { pub struct Synced<T> {
inner: Arc<Mutex<T>>, inner: Arc<Mutex<T>>,
} }
impl<T> Synced<T> { impl<T> Synced<T> {
/// DOCME: what is this?
pub fn with_inner(inner: T) -> Synced<T> { pub fn with_inner(inner: T) -> Synced<T> {
Synced { Synced {
inner: Arc::new(Mutex::new(inner)), inner: Arc::new(Mutex::new(inner)),
} }
} }
/// DOCME: what is this?
pub fn inner<'a>(&'a self) -> MutexGuard<'a, T> { pub fn inner<'a>(&'a self) -> MutexGuard<'a, T> {
self.inner.lock() self.inner.lock()
} }
@ -42,22 +46,23 @@ impl<T> Clone for Synced<T> {
} }
impl<S: SectorSize, V: Volume<u8, S>> Synced<Ext2<S, V>> { impl<S: SectorSize, V: Volume<u8, S>> Synced<Ext2<S, V>> {
/// DOCME: what is this?
pub fn new(volume: V) -> Result<Synced<Ext2<S, V>>, Error> { pub fn new(volume: V) -> Result<Synced<Ext2<S, V>>, Error> {
Ext2::new(volume).map(|inner| Synced::with_inner(inner)) Ext2::new(volume).map(|inner| Synced::with_inner(inner))
} }
/// Get the root inode.
pub fn root_inode(&self) -> Inode<S, V> { pub fn root_inode(&self) -> Inode<S, V> {
self.inode_nth(2).unwrap() self.inode_nth(2).unwrap()
} }
/// Get the inode at the given index.
pub fn inode_nth(&self, index: usize) -> Option<Inode<S, V>> { pub fn inode_nth(&self, index: usize) -> Option<Inode<S, V>> {
self.inodes_nth(index).next() self.inodes_nth(index).next()
} }
/// DOCME: what is this?
pub fn inodes(&self) -> Inodes<S, V> { pub fn inodes(&self) -> Inodes<S, V> {
self.inodes_nth(1) self.inodes_nth(1)
} }
/// DOCME: what is this?
pub fn inodes_nth(&self, index: usize) -> Inodes<S, V> { pub fn inodes_nth(&self, index: usize) -> Inodes<S, V> {
assert!(index > 0, "inodes are 1-indexed"); assert!(index > 0, "inodes are 1-indexed");
let inner = self.inner(); let inner = self.inner();
@ -70,11 +75,11 @@ impl<S: SectorSize, V: Volume<u8, S>> Synced<Ext2<S, V>> {
index, index,
} }
} }
/// DOCME: what is this?
pub fn sector_size(&self) -> usize { pub fn sector_size(&self) -> usize {
S::SIZE S::SIZE
} }
/// DOCME: what is this?
pub fn log_sector_size(&self) -> u32 { pub fn log_sector_size(&self) -> u32 {
S::LOG_SIZE S::LOG_SIZE
} }
@ -256,6 +261,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Debug for Synced<Ext2<S, V>> {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/// A collection of inodes.
pub struct Inodes<S: SectorSize, V: Volume<u8, S>> { pub struct Inodes<S: SectorSize, V: Volume<u8, S>> {
fs: Synced<Ext2<S, V>>, fs: Synced<Ext2<S, V>>,
log_block_size: u32, log_block_size: u32,
@ -302,6 +308,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Iterator for Inodes<S, V> {
} }
#[derive(Debug)] #[derive(Debug)]
/// A single inode in an ext2 filesystem.
pub struct Inode<S: SectorSize, V: Volume<u8, S>> { pub struct Inode<S: SectorSize, V: Volume<u8, S>> {
fs: Synced<Ext2<S, V>>, fs: Synced<Ext2<S, V>>,
inner: RawInode, inner: RawInode,
@ -321,6 +328,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Clone for Inode<S, V> {
} }
impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> { impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
///
pub fn new( pub fn new(
fs: Synced<Ext2<S, V>>, fs: Synced<Ext2<S, V>>,
inner: RawInode, inner: RawInode,
@ -334,7 +342,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
num, num,
} }
} }
/// Read to the end of a buffer.
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize, Error> { pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize, Error> {
let total_size = self.size(); let total_size = self.size();
let capacity = buf.capacity(); let capacity = buf.capacity();
@ -358,14 +366,14 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
Err(err) Err(err)
}) })
} }
/// Return blocks on a sector
pub fn blocks(&self) -> InodeBlocks<S, V> { pub fn blocks(&self) -> InodeBlocks<S, V> {
InodeBlocks { InodeBlocks {
inode: self.clone(), inode: self.clone(),
index: 0, index: 0,
} }
} }
/// return a directory iterator
pub fn directory(&self) -> Option<Directory<S, V>> { pub fn directory(&self) -> Option<Directory<S, V>> {
if self.is_dir() { if self.is_dir() {
Some(Directory { Some(Directory {
@ -381,16 +389,16 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
None None
} }
} }
/// Determine if an inode is a directory
pub fn is_dir(&self) -> bool { pub fn is_dir(&self) -> bool {
use sys::inode::TypePerm; 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<NonZeroU32> { pub fn block(&self, index: usize) -> Option<NonZeroU32> {
self.try_block(index).ok().and_then(|block| block) self.try_block(index).ok().and_then(|block| block)
} }
/// Try to get a block
pub fn try_block( pub fn try_block(
&self, &self,
mut index: usize, mut index: usize,
@ -501,27 +509,27 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
Ok(None) Ok(None)
} }
///
pub fn in_use(&self) -> bool { pub fn in_use(&self) -> bool {
self.inner.hard_links > 0 self.inner.hard_links > 0
} }
/// return the uid
pub fn uid(&self) -> u16 { pub fn uid(&self) -> u16 {
self.inner.uid self.inner.uid
} }
///
pub fn sectors(&self) -> usize { pub fn sectors(&self) -> usize {
self.inner.sectors_count as usize self.inner.sectors_count as usize
} }
///
pub fn size32(&self) -> u32 { pub fn size32(&self) -> u32 {
self.inner.size_low self.inner.size_low
} }
///
pub fn size64(&self) -> u64 { pub fn size64(&self) -> u64 {
self.inner.size_low as u64 | (self.inner.size_high as u64) << 32 self.inner.size_low as u64 | (self.inner.size_high as u64) << 32
} }
///
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
#[inline] #[inline]
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
@ -576,6 +584,7 @@ impl<S: SectorSize, V: Volume<u8, S>> File for Inode<S, V> {
} }
} }
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct InodeBlocks<S: SectorSize, V: Volume<u8, S>> { pub struct InodeBlocks<S: SectorSize, V: Volume<u8, S>> {
inode: Inode<S, V>, inode: Inode<S, V>,
@ -611,6 +620,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Iterator for InodeBlocks<S, V> {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/// A directory structure
pub struct Directory<S: SectorSize, V: Volume<u8, S>> { pub struct Directory<S: SectorSize, V: Volume<u8, S>> {
blocks: InodeBlocks<S, V>, blocks: InodeBlocks<S, V>,
offset: usize, offset: usize,
@ -664,9 +674,13 @@ impl<S: SectorSize, V: Volume<u8, S>> Iterator for Directory<S, V> {
} }
#[derive(Clone)] #[derive(Clone)]
/// A directory entry
pub struct DirectoryEntry { pub struct DirectoryEntry {
/// The name of the entry
pub name: Vec<u8>, pub name: Vec<u8>,
/// The inode of the entry
pub inode: usize, pub inode: usize,
///
pub ty: u8, pub ty: u8,
} }

View file

@ -1,3 +1,6 @@
//! Ext2 crate for ableOS
#![deny(missing_docs)]
#![feature( #![feature(
min_specialization, min_specialization,
const_fn_trait_bound, const_fn_trait_bound,
@ -6,8 +9,8 @@
)] )]
#![cfg_attr(all(not(test), feature = "no_std"), no_std)] #![cfg_attr(all(not(test), feature = "no_std"), no_std)]
#[macro_use]
extern crate alloc; extern crate alloc;
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate genfs; extern crate genfs;

View file

@ -1,29 +1,35 @@
//! Sector data.
use core::{ use core::{
fmt::{self, Debug, Display, LowerHex}, fmt::{self, Debug, Display, LowerHex},
iter::Step, iter::Step,
marker::PhantomData, marker::PhantomData,
ops::{Add, Sub}, ops::{Add, Sub},
}; };
/// Size of a sector in bytes
pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd + 'static { pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd + 'static {
// log_sector_size = log_2(sector_size) /// DOCME: What is this?
const LOG_SIZE: u32; const LOG_SIZE: u32;
/// DOCME: What is this?
const SIZE: usize = 1 << Self::LOG_SIZE; const SIZE: usize = 1 << Self::LOG_SIZE;
/// DOCME: What is this?
const OFFSET_MASK: u32 = (Self::SIZE - 1) as u32; const OFFSET_MASK: u32 = (Self::SIZE - 1) as u32;
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
/// DOCME: What is this?
pub struct Size512; pub struct Size512;
impl SectorSize for Size512 { impl SectorSize for Size512 {
const LOG_SIZE: u32 = 9; const LOG_SIZE: u32 = 9;
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
/// DOCME: What is this?
pub struct Size1024; pub struct Size1024;
impl SectorSize for Size1024 { impl SectorSize for Size1024 {
const LOG_SIZE: u32 = 10; const LOG_SIZE: u32 = 10;
} }
/// DOCME: What is this?
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Size2048; pub struct Size2048;
impl SectorSize for Size2048 { impl SectorSize for Size2048 {
@ -31,13 +37,14 @@ impl SectorSize for Size2048 {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
/// DOCME: What is this?
pub struct Size4096; pub struct Size4096;
impl SectorSize for Size4096 { impl SectorSize for Size4096 {
const LOG_SIZE: u32 = 12; const LOG_SIZE: u32 = 12;
} }
/// Address in a physical sector /// 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<S: SectorSize> { pub struct Address<S: SectorSize> {
sector: u32, sector: u32,
offset: u32, offset: u32,
@ -45,6 +52,7 @@ pub struct Address<S: SectorSize> {
} }
impl<S: SectorSize> Address<S> { impl<S: SectorSize> Address<S> {
///
pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> { pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> {
assert!((offset as usize) < S::SIZE, "offset out of sector bounds"); assert!((offset as usize) < S::SIZE, "offset out of sector bounds");
let _phantom = PhantomData; let _phantom = PhantomData;
@ -54,13 +62,13 @@ impl<S: SectorSize> Address<S> {
_phantom, _phantom,
} }
} }
///
pub fn new(sector: u32, offset: i32) -> Address<S> { pub fn new(sector: u32, offset: i32) -> Address<S> {
let sector = (sector as i32 + (offset >> S::LOG_SIZE)) as u32; let sector = (sector as i32 + (offset >> S::LOG_SIZE)) as u32;
let offset = offset.abs() as u32 & S::OFFSET_MASK; let offset = offset.abs() as u32 & S::OFFSET_MASK;
unsafe { Address::new_unchecked(sector, offset) } unsafe { Address::new_unchecked(sector, offset) }
} }
///
pub fn with_block_size( pub fn with_block_size(
block: u32, block: u32,
offset: i32, offset: i32,
@ -75,23 +83,23 @@ impl<S: SectorSize> Address<S> {
let sector = block << log_diff | top_offset; let sector = block << log_diff | top_offset;
unsafe { Address::new_unchecked(sector, offset) } unsafe { Address::new_unchecked(sector, offset) }
} }
///
pub fn into_index(&self) -> u64 { pub fn into_index(&self) -> u64 {
((self.sector as u64) << S::LOG_SIZE) + self.offset as 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 { pub const fn sector_size(&self) -> usize {
S::SIZE S::SIZE
} }
/// DOCME: What is this?
pub const fn log_sector_size(&self) -> u32 { pub const fn log_sector_size(&self) -> u32 {
S::LOG_SIZE S::LOG_SIZE
} }
/// Return the sector number
pub fn sector(&self) -> u32 { pub fn sector(&self) -> u32 {
self.sector self.sector
} }
/// Return the offset in the sector
pub fn offset(&self) -> u32 { pub fn offset(&self) -> u32 {
self.offset self.offset
} }
@ -105,6 +113,7 @@ impl<S: SectorSize> Step for Address<S> {
None None
} }
} }
/* /*
fn replace_one(&mut self) -> Self { fn replace_one(&mut self) -> Self {
mem::replace(self, Address::new(1, 0)) mem::replace(self, Address::new(1, 0))
@ -129,22 +138,12 @@ impl<S: SectorSize> Step for Address<S> {
} }
*/ */
fn forward_checked(start: Self, count: usize) -> Option<Self> { fn forward_checked(_start: Self, count: usize) -> Option<Self> {
todo!("forward_checked") todo!("forward_checked: count: {}", count);
} }
fn backward_checked(start: Self, count: usize) -> Option<Self> { fn backward_checked(_start: Self, count: usize) -> Option<Self> {
todo!("backward_checked") todo!("backward_checked count: {}", count);
}
}
impl<S: SectorSize> Debug for Address<S> {
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()
} }
} }

View file

@ -1,9 +1,8 @@
//!
use { use {
alloc::vec::Vec, alloc::vec::Vec,
core::{ core::{fmt::Debug, mem},
fmt::{self, Debug},
mem,
},
error::Error, error::Error,
sector::{Address, SectorSize}, sector::{Address, SectorSize},
volume::Volume, volume::Volume,
@ -22,7 +21,7 @@ use {
/// Remember that blocks are numbered starting at 0, and that block numbers /// Remember that blocks are numbered starting at 0, and that block numbers
/// don't usually correspond to physical block addresses. /// don't usually correspond to physical block addresses.
#[repr(C, packed)] #[repr(C, packed)]
#[derive(Clone, Copy)] #[derive(Clone, Debug, Copy)]
pub struct BlockGroupDescriptor { pub struct BlockGroupDescriptor {
/// Block address of block usage bitmap /// Block address of block usage bitmap
pub block_usage_addr: u32, pub block_usage_addr: u32,
@ -40,20 +39,8 @@ pub struct BlockGroupDescriptor {
_reserved: [u8; 14], _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 { impl BlockGroupDescriptor {
/// Find a descriptor in a descriptor table
pub unsafe fn find_descriptor<S: SectorSize, V: Volume<u8, S>>( pub unsafe fn find_descriptor<S: SectorSize, V: Volume<u8, S>>(
haystack: &V, haystack: &V,
offset: Address<S>, offset: Address<S>,
@ -74,7 +61,7 @@ impl BlockGroupDescriptor {
Ok(descr) Ok(descr)
} }
/// find a descriptor table
pub unsafe fn find_descriptor_table<S: SectorSize, V: Volume<u8, S>>( pub unsafe fn find_descriptor_table<S: SectorSize, V: Volume<u8, S>>(
haystack: &V, haystack: &V,
offset: Address<S>, offset: Address<S>,

View file

@ -1,8 +1,7 @@
//!
use { use {
core::{ core::{fmt::Debug, mem},
fmt::{self, Debug},
mem,
},
error::Error, error::Error,
sector::{Address, SectorSize}, sector::{Address, SectorSize},
volume::Volume, volume::Volume,
@ -16,7 +15,7 @@ use {
/// array of inodes it is responsible for, and conversely every inode within a /// 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). /// file system belongs to one of such tables (and one of such block groups).
#[repr(C, packed)] #[repr(C, packed)]
#[derive(Clone, Copy)] #[derive(Clone, Debug, Copy)]
pub struct Inode { pub struct Inode {
/// Type and Permissions (see below) /// Type and Permissions (see below)
pub type_perm: TypePerm, pub type_perm: TypePerm,
@ -71,35 +70,8 @@ pub struct Inode {
pub _os_specific_2: [u8; 12], 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 { impl Inode {
/// Discover the inode location on the disk.
pub unsafe fn find_inode<S: SectorSize, V: Volume<u8, S>>( pub unsafe fn find_inode<S: SectorSize, V: Volume<u8, S>>(
haystack: &V, haystack: &V,
offset: Address<S>, offset: Address<S>,
@ -127,6 +99,7 @@ impl Inode {
} }
bitflags! { bitflags! {
///
pub struct TypePerm: u16 { pub struct TypePerm: u16 {
/// FIFO /// FIFO
const FIFO = 0x1000; const FIFO = 0x1000;
@ -170,6 +143,7 @@ bitflags! {
} }
bitflags! { bitflags! {
/// Flags
pub struct Flags: u32 { pub struct Flags: u32 {
/// Secure deletion (not used) /// Secure deletion (not used)
const SECURE_DEL = 0x00000001; const SECURE_DEL = 0x00000001;

View file

@ -1,3 +1,5 @@
pub mod superblock; //!
pub mod block_group; pub mod block_group;
pub mod inode; pub mod inode;
pub mod superblock;

View file

@ -1,8 +1,7 @@
//! Superblock information
use { use {
core::{ core::{fmt::Debug, mem},
fmt::{self, Debug},
mem,
},
error::Error, error::Error,
sector::{Address, SectorSize}, sector::{Address, SectorSize},
volume::Volume, 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 /// 512 byte sectors, the Superblock will begin at LBA 2 and will occupy all of
/// sector 2 and 3. /// sector 2 and 3.
#[repr(C, packed)] #[repr(C, packed)]
#[derive(Clone, Copy)] #[derive(Clone, Debug, Copy)]
pub struct Superblock { pub struct Superblock {
// taken from https://wiki.osdev.org/Ext2 // taken from https://wiki.osdev.org/Ext2
/// Total number of inodes in file system /// Total number of inodes in file system
@ -148,7 +147,7 @@ pub struct Superblock {
#[doc(hidden)] #[doc(hidden)]
_reserved: [u8; 788], _reserved: [u8; 788],
} }
/*
impl Debug for Superblock { impl Debug for Superblock {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Superblock") f.debug_struct("Superblock")
@ -196,8 +195,9 @@ impl Debug for Superblock {
.finish() .finish()
} }
} }
*/
impl Superblock { impl Superblock {
/// Discover the location of the superblock in the given block device.
pub unsafe fn find<S: SectorSize, V: Volume<u8, S>>( pub unsafe fn find<S: SectorSize, V: Volume<u8, S>>(
haystack: &V, haystack: &V,
) -> Result<(Superblock, Address<S>), Error> { ) -> Result<(Superblock, Address<S>), Error> {
@ -227,15 +227,17 @@ impl Superblock {
} }
#[inline] #[inline]
/// Return the block size
pub fn block_size(&self) -> usize { pub fn block_size(&self) -> usize {
1024 << self.log_block_size 1024 << self.log_block_size
} }
#[inline] #[inline]
/// Return the fragment size
pub fn frag_size(&self) -> usize { pub fn frag_size(&self) -> usize {
1024 << self.log_frag_size 1024 << self.log_frag_size
} }
/// Return the number of blocks per group
pub fn block_group_count(&self) -> Result<u32, (u32, u32)> { pub fn block_group_count(&self) -> Result<u32, (u32, u32)> {
let blocks_mod = self.blocks_count % self.blocks_per_group; let blocks_mod = self.blocks_count % self.blocks_per_group;
let inodes_mod = self.inodes_count % self.inodes_per_group; let inodes_mod = self.inodes_count % self.inodes_per_group;

View file

@ -1,3 +1,4 @@
#![allow(missing_docs)]
use { use {
alloc::{ alloc::{
borrow::{Cow, ToOwned}, borrow::{Cow, ToOwned},

View file

@ -1,3 +1,5 @@
//!
use { use {
core::{ core::{
cmp::Ordering, cmp::Ordering,
@ -7,19 +9,28 @@ use {
}; };
#[derive(Clone, Copy, Debug, Hash)] #[derive(Clone, Copy, Debug, Hash)]
/// A size
pub enum Size<S: SectorSize> { pub enum Size<S: SectorSize> {
/// An unbounded size
Unbounded, Unbounded,
/// A bounded size
Bounded(Address<S>), Bounded(Address<S>),
} }
impl<S: SectorSize> Size<S> { impl<S: SectorSize> Size<S> {
/// Try to get the length of the sector
pub fn try_len(&self) -> Option<Address<S>> { pub fn try_len(&self) -> Option<Address<S>> {
match *self { match *self {
Size::Unbounded => None, Size::Unbounded => None,
Size::Bounded(n) => Some(n), 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<S> { pub unsafe fn len(&self) -> Address<S> {
match *self { match *self {
Size::Unbounded => panic!( Size::Unbounded => panic!(
@ -31,6 +42,7 @@ impl<S: SectorSize> Size<S> {
} }
impl<S: SectorSize> Size<S> { impl<S: SectorSize> Size<S> {
/// Check if the size is unbounded
pub fn is_bounded(&self) -> bool { pub fn is_bounded(&self) -> bool {
match *self { match *self {
Size::Unbounded => false, Size::Unbounded => false,