documentation
This commit is contained in:
parent
1e537b063c
commit
8f7155dcff
29
src/error.rs
29
src/error.rs
|
@ -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 {}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
pub mod superblock;
|
//!
|
||||||
|
|
||||||
pub mod block_group;
|
pub mod block_group;
|
||||||
pub mod inode;
|
pub mod inode;
|
||||||
|
pub mod superblock;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
use {
|
use {
|
||||||
alloc::{
|
alloc::{
|
||||||
borrow::{Cow, ToOwned},
|
borrow::{Cow, ToOwned},
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Reference in a new issue