ported to modern rust

master
Able 2022-02-07 22:18:39 -06:00
parent 1fe6dd820b
commit c28713c202
Signed by: able
GPG Key ID: D164AF5F5700BE51
11 changed files with 210 additions and 172 deletions

View File

@ -1,12 +1,14 @@
[package]
name = "ext2"
version = "0.1.0"
authors = ["Szymon Walter <walter.szymon.98@gmail.com>"]
version = "0.1.1"
authors = ["Szymon Walter <walter.szymon.98@gmail.com>",
"able <abl3theabove@gmail.com>"]
[dependencies]
bitflags = "1.0"
rlibc = { version = "1.0", optional = true }
spin = "0.4"
spin = "0.9.2"
genfs = "^0.1.4"
[features]

View File

@ -1,5 +1,7 @@
use core::fmt::{self, Display};
use alloc::String;
use {
alloc::string::String,
core::fmt::{self, Display},
};
#[cfg(any(test, not(feature = "no_std")))]
use std::io;

View File

@ -1,16 +1,18 @@
use core::mem;
use alloc::Vec;
use error::Error;
use sector::{Address, SectorSize};
use volume::Volume;
use sys::superblock::Superblock;
use sys::block_group::BlockGroupDescriptor;
use sys::inode::Inode as RawInode;
use {
alloc::vec::Vec,
core::mem,
error::Error,
sector::{Address, SectorSize},
sys::{
block_group::BlockGroupDescriptor, inode::Inode as RawInode,
superblock::Superblock,
},
volume::Volume,
};
pub mod sync;
#[allow(dead_code)]
pub(crate) struct Struct<T, S: SectorSize> {
pub inner: T,
pub offset: Address<S>,
@ -124,8 +126,8 @@ impl<S: SectorSize, V: Volume<u8, S>> Ext2<S, V> {
#[cfg(test)]
mod tests {
use std::fs::File;
use std::cell::RefCell;
use std::fs::File;
use sector::{Address, Size512};
use volume::Volume;
@ -145,7 +147,8 @@ mod tests {
file.slice_unchecked(
Address::<Size512>::from(1024_u64)
..Address::<Size512>::from(2048_u64),
).len()
)
.len()
},
1024
);

View File

@ -1,19 +1,21 @@
use core::fmt::{self, Debug};
use core::nonzero::NonZero;
use core::iter::Iterator;
use alloc::{String, Vec};
use alloc::arc::Arc;
use spin::{Mutex, MutexGuard};
use genfs::*;
use error::Error;
use sector::{Address, SectorSize};
use volume::Volume;
use sys::inode::Inode as RawInode;
use super::Ext2;
use {
super::Ext2,
alloc::{
sync::Arc,
{string::String, vec::Vec},
},
core::{
fmt::{self, Debug},
iter::Iterator,
num::NonZeroU32,
},
error::Error,
genfs::*,
sector::{Address, SectorSize},
spin::{Mutex, MutexGuard},
sys::inode::Inode as RawInode,
volume::Volume,
};
pub struct Synced<T> {
inner: Arc<Mutex<T>>,
@ -115,13 +117,16 @@ impl<S: SectorSize, V: Volume<u8, S>> Fs for Synced<Ext2<S, V>> {
name: String::from_utf8_lossy(abs_path).into_owned(),
})?;
let entry = dir.find(|entry| {
entry.is_err() || entry.as_ref().unwrap().name == name
}).ok_or_else(|| Error::NotFound {
name: String::from_utf8_lossy(abs_path).into_owned(),
})??;
let entry = dir
.find(|entry| {
entry.is_err() || entry.as_ref().unwrap().name == name
})
.ok_or_else(|| Error::NotFound {
name: String::from_utf8_lossy(abs_path).into_owned(),
})??;
let inode = fs.inode_nth(entry.inode)
let inode = fs
.inode_nth(entry.inode)
.ok_or(Error::InodeNotFound { inode: inode.num })?;
inner(fs, inode, path, abs_path)
@ -345,7 +350,8 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
buf.set_len(size);
}
Ok(size)
}).or_else(|err| {
})
.or_else(|err| {
unsafe {
buf.set_len(0);
}
@ -381,14 +387,14 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
unsafe { self.inner.type_perm.contains(TypePerm::DIRECTORY) }
}
pub fn block(&self, index: usize) -> Option<NonZero<u32>> {
pub fn block(&self, index: usize) -> Option<NonZeroU32> {
self.try_block(index).ok().and_then(|block| block)
}
pub fn try_block(
&self,
mut index: usize,
) -> Result<Option<NonZero<u32>>, Error> {
) -> Result<Option<NonZeroU32>, Error> {
// number of blocks in direct table: 12
// number of blocks in indirect table: block_size/4
// why?
@ -408,7 +414,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
block: u32,
index: usize,
log_block_size: u32,
) -> Result<Option<NonZero<u32>>, Error> {
) -> Result<Option<NonZeroU32>, Error> {
let offset = (index * 4) as i32;
let end = offset + 4;
let addr = Address::with_block_size(block, offset, log_block_size);
@ -416,7 +422,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
let block = volume.slice(addr..end);
match block {
Ok(block) => unsafe {
Ok(NonZero::new(block.dynamic_cast::<u32>().0))
Ok(NonZeroU32::new(block.dynamic_cast::<u32>().0))
},
Err(err) => Err(err.into()),
}
@ -428,7 +434,7 @@ impl<S: SectorSize, V: Volume<u8, S>> Inode<S, V> {
let log_block_size = fs.log_block_size();
if index < 12 {
return Ok(NonZero::new(self.inner.direct_pointer[index]));
return Ok(NonZeroU32::new(self.inner.direct_pointer[index]));
}
index -= 12;
@ -595,7 +601,8 @@ impl<S: SectorSize, V: Volume<u8, S>> Iterator for InodeBlocks<S, V> {
let offset = Address::with_block_size(block, 0, log_block_size);
let end = Address::with_block_size(block + 1, 0, log_block_size);
let slice = fs.volume
let slice = fs
.volume
.slice(offset..end)
.map(|slice| (slice.to_vec(), offset))
.map_err(|err| err.into());
@ -632,7 +639,8 @@ impl<S: SectorSize, V: Volume<u8, S>> Iterator for Directory<S, V> {
let buffer = &self.buffer.as_ref().unwrap()[self.offset..];
let inode = buffer[0] as u32 | (buffer[1] as u32) << 8
let inode = buffer[0] as u32
| (buffer[1] as u32) << 8
| (buffer[2] as u32) << 16
| (buffer[3] as u32) << 24;
if inode == 0 {
@ -688,8 +696,8 @@ impl DirEntry for DirectoryEntry {
#[cfg(test)]
mod tests {
use std::fs::File;
use std::cell::RefCell;
use std::fs::File;
use genfs::{File as GenFile, Fs, OpenOptions};

View File

@ -1,11 +1,9 @@
#![feature(alloc)]
#![feature(specialization)]
#![feature(swap_with_slice)]
#![feature(macro_lifetime_matcher)]
#![feature(const_fn)]
#![feature(step_trait)]
#![feature(nonzero)]
#![feature(associated_type_defaults)]
#![feature(
min_specialization,
const_fn_trait_bound,
step_trait,
associated_type_defaults
)]
#![cfg_attr(all(not(test), feature = "no_std"), no_std)]
#[macro_use]
@ -19,16 +17,16 @@ extern crate spin;
extern crate core;
pub mod error;
pub mod sys;
pub mod sector;
pub mod volume;
pub mod fs;
pub mod sector;
pub mod sys;
pub mod volume;
#[cfg(test)]
mod tests {
use sys::superblock::*;
use sys::block_group::*;
use sys::inode::*;
use sys::superblock::*;
#[test]
fn sizes() {

View File

@ -1,8 +1,9 @@
use core::mem;
use core::marker::PhantomData;
use core::ops::{Add, Sub};
use core::fmt::{self, Debug, Display, LowerHex};
use core::iter::Step;
use core::{
fmt::{self, Debug, Display, LowerHex},
iter::Step,
marker::PhantomData,
ops::{Add, Sub},
};
pub trait SectorSize: Clone + Copy + PartialEq + PartialOrd + 'static {
// log_sector_size = log_2(sector_size)
@ -104,7 +105,7 @@ impl<S: SectorSize> Step for Address<S> {
None
}
}
/*
fn replace_one(&mut self) -> Self {
mem::replace(self, Address::new(1, 0))
}
@ -123,8 +124,17 @@ impl<S: SectorSize> Step for Address<S> {
fn add_usize(&self, n: usize) -> Option<Self> {
self.sector
.checked_add(n as u32)
.map(|sector| Address::new(sector, 0))
.checked_add(n as u32)
.map(|sector| Address::new(sector, 0))
}
*/
fn forward_checked(start: Self, count: usize) -> Option<Self> {
todo!("forward_checked")
}
fn backward_checked(start: Self, count: usize) -> Option<Self> {
todo!("backward_checked")
}
}

View File

@ -1,11 +1,13 @@
use core::mem;
use core::fmt::{self, Debug};
use alloc::Vec;
use error::Error;
use sector::{Address, SectorSize};
use volume::Volume;
use {
alloc::vec::Vec,
core::{
fmt::{self, Debug},
mem,
},
error::Error,
sector::{Address, SectorSize},
volume::Volume,
};
/// The Block Group Descriptor Table contains a descriptor for each block group
/// within the file system. The number of block groups within the file system,
@ -41,12 +43,12 @@ pub struct BlockGroupDescriptor {
impl Debug for BlockGroupDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("BlockGroupDescriptor")
.field("block_usage_addr", unsafe { &self.block_usage_addr })
.field("inode_usage_addr", unsafe { &self.inode_usage_addr })
.field("inode_table_block", unsafe { &self.inode_table_block })
.field("free_blocks_count", unsafe { &self.free_blocks_count })
.field("free_inodes_count", unsafe { &self.free_inodes_count })
.field("dirs_count", unsafe { &self.dirs_count })
.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()
}
}
@ -103,8 +105,8 @@ impl BlockGroupDescriptor {
#[cfg(test)]
mod tests {
use sector::{Address, Size512};
use super::*;
use sector::{Address, Size512};
#[test]
fn find() {

View File

@ -1,9 +1,12 @@
use core::mem;
use core::fmt::{self, Debug};
use error::Error;
use sector::{Address, SectorSize};
use volume::Volume;
use {
core::{
fmt::{self, Debug},
mem,
},
error::Error,
sector::{Address, SectorSize},
volume::Volume,
};
/// An inode is a structure on the disk that represents a file, directory,
/// symbolic link, etc. Inodes do not contain the data of the file / directory /
@ -71,26 +74,26 @@ pub struct Inode {
impl Debug for Inode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Inode")
.field("type_perm", unsafe { &self.type_perm })
.field("uid", unsafe { &self.uid })
.field("size_low", unsafe { &self.size_low })
.field("atime", unsafe { &self.atime })
.field("ctime", unsafe { &self.ctime })
.field("mtime", unsafe { &self.mtime })
.field("dtime", unsafe { &self.dtime })
.field("gid", unsafe { &self.gid })
.field("hard_links", unsafe { &self.hard_links })
.field("sectors_count", unsafe { &self.sectors_count })
.field("flags", unsafe { &self.flags })
.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", unsafe { &self.direct_pointer })
.field("indirect_pointer", unsafe { &self.indirect_pointer })
.field("doubly_indirect", unsafe { &self.doubly_indirect })
.field("triply_indirect", unsafe { &self.triply_indirect })
.field("gen_number", unsafe { &self.gen_number })
.field("ext_attribute_block", unsafe { &self.ext_attribute_block })
.field("size_high", unsafe { &self.size_high })
.field("frag_block_addr", unsafe { &self.frag_block_addr })
.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()
}

View File

@ -1,9 +1,12 @@
use core::mem;
use core::fmt::{self, Debug};
use error::Error;
use sector::{Address, SectorSize};
use volume::Volume;
use {
core::{
fmt::{self, Debug},
mem,
},
error::Error,
sector::{Address, SectorSize},
volume::Volume,
};
/// Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a
/// volume
@ -149,47 +152,47 @@ pub struct Superblock {
impl Debug for Superblock {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Superblock")
.field("inodes_count", unsafe { &self.inodes_count })
.field("blocks_count", unsafe { &self.blocks_count })
.field("r_blocks_count", unsafe { &self.r_blocks_count })
.field("free_blocks_count", unsafe { &self.free_blocks_count })
.field("free_inodes_count", unsafe { &self.free_inodes_count })
.field("first_data_block", unsafe { &self.first_data_block })
.field("log_block_size", unsafe { &self.log_block_size })
.field("log_frag_size", unsafe { &self.log_frag_size })
.field("blocks_per_group", unsafe { &self.blocks_per_group })
.field("frags_per_group", unsafe { &self.frags_per_group })
.field("inodes_per_group", unsafe { &self.inodes_per_group })
.field("mtime", unsafe { &self.mtime })
.field("wtime", unsafe { &self.wtime })
.field("mnt_count", unsafe { &self.mnt_count })
.field("max_mnt_count", unsafe { &self.max_mnt_count })
.field("magic", unsafe { &self.magic })
.field("state", unsafe { &self.state })
.field("errors", unsafe { &self.errors })
.field("rev_minor", unsafe { &self.rev_minor })
.field("lastcheck", unsafe { &self.lastcheck })
.field("checkinterval", unsafe { &self.checkinterval })
.field("creator_os", unsafe { &self.creator_os })
.field("rev_major", unsafe { &self.rev_major })
.field("block_uid", unsafe { &self.block_uid })
.field("block_gid", unsafe { &self.block_gid })
.field("first_inode", unsafe { &self.first_inode })
.field("inode_size", unsafe { &self.inode_size })
.field("block_group", unsafe { &self.block_group })
.field("features_opt", unsafe { &self.features_opt })
.field("features_req", unsafe { &self.features_req })
.field("features_ronly", unsafe { &self.features_ronly })
.field("inodes_count", &self.inodes_count)
.field("blocks_count", &self.blocks_count)
.field("r_blocks_count", &self.r_blocks_count)
.field("free_blocks_count", &self.free_blocks_count)
.field("free_inodes_count", &self.free_inodes_count)
.field("first_data_block", &self.first_data_block)
.field("log_block_size", &self.log_block_size)
.field("log_frag_size", &self.log_frag_size)
.field("blocks_per_group", &self.blocks_per_group)
.field("frags_per_group", &self.frags_per_group)
.field("inodes_per_group", &self.inodes_per_group)
.field("mtime", &self.mtime)
.field("wtime", &self.wtime)
.field("mnt_count", &self.mnt_count)
.field("max_mnt_count", &self.max_mnt_count)
.field("magic", &self.magic)
.field("state", &self.state)
.field("errors", &self.errors)
.field("rev_minor", &self.rev_minor)
.field("lastcheck", &self.lastcheck)
.field("checkinterval", &self.checkinterval)
.field("creator_os", &self.creator_os)
.field("rev_major", &self.rev_major)
.field("block_uid", &self.block_uid)
.field("block_gid", &self.block_gid)
.field("first_inode", &self.first_inode)
.field("inode_size", &self.inode_size)
.field("block_group", &self.block_group)
.field("features_opt", &self.features_opt)
.field("features_req", &self.features_req)
.field("features_ronly", &self.features_ronly)
.field("fs_id", &self.fs_id)
.field("volume_name", &self.volume_name)
.field("last_mnt_path", &self.last_mnt_path.as_ref())
.field("compression", unsafe { &self.compression })
.field("compression", &self.compression)
.field("prealloc_blocks_files", &self.prealloc_blocks_files)
.field("prealloc_blocks_dirs", &self.prealloc_blocks_dirs)
.field("journal_id", &self.journal_id)
.field("journal_inode", unsafe { &self.journal_inode })
.field("journal_dev", unsafe { &self.journal_dev })
.field("journal_orphan_head", unsafe { &self.journal_orphan_head })
.field("journal_inode", &self.journal_inode)
.field("journal_dev", &self.journal_dev)
.field("journal_orphan_head", &self.journal_orphan_head)
.finish()
}
}
@ -295,8 +298,8 @@ bitflags! {
#[cfg(test)]
mod tests {
use sector::Size512;
use super::*;
use sector::Size512;
#[test]
fn find() {

View File

@ -1,13 +1,17 @@
use core::mem;
use core::slice;
use core::ops::{Deref, DerefMut, Range};
use alloc::Vec;
use alloc::boxed::Box;
use alloc::borrow::{Cow, ToOwned};
use error::Error;
use sector::{Address, SectorSize};
use {
alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
vec::Vec,
},
core::{
mem,
ops::{Deref, DerefMut, Range},
slice,
},
error::Error,
sector::{Address, SectorSize},
};
pub mod size;
use self::size::Size;
@ -257,15 +261,15 @@ impl_slice!(Box<[T]>);
#[cfg(any(test, not(feature = "no_std")))]
mod file {
use std::ops::Range;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::fs::File;
use std::cell::RefCell;
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::ops::Range;
use sector::{Address, SectorSize};
use super::{Volume, VolumeCommit, VolumeSlice};
use super::size::Size;
use super::{Volume, VolumeCommit, VolumeSlice};
impl<S: SectorSize> Volume<u8, S> for RefCell<File> {
type Error = io::Error;
@ -318,9 +322,9 @@ mod file {
range: Range<Address<S>>,
) -> Result<VolumeSlice<'a, u8, S>, Self::Error> {
let index = range.start;
let mut vec = Vec::with_capacity((range.end - range.start)
.into_index()
as usize);
let mut vec = Vec::with_capacity(
(range.end - range.start).into_index() as usize,
);
unsafe {
vec.set_len((range.end - range.start).into_index() as usize);
}
@ -335,8 +339,8 @@ mod file {
#[cfg(test)]
mod tests {
use sector::{Address, Size512};
use super::*;
use sector::{Address, Size512};
#[test]
fn volume() {

View File

@ -1,7 +1,10 @@
use core::fmt::{self, Display};
use core::cmp::Ordering;
use sector::{Address, SectorSize};
use {
core::{
cmp::Ordering,
fmt::{self, Display},
},
sector::{Address, SectorSize},
};
#[derive(Clone, Copy, Debug, Hash)]
pub enum Size<S: SectorSize> {