From dd95456ec490d9119274f31e2f4fc4d1679477fc Mon Sep 17 00:00:00 2001 From: tzlil Date: Fri, 17 Feb 2023 13:25:23 +0200 Subject: initial commit --- src/main.rs | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/main.rs (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e1f68ce --- /dev/null +++ b/src/main.rs @@ -0,0 +1,213 @@ +#![feature(int_roundings)] + +mod structs; +use crate::structs::{Superblock,BlockGroupDescriptor,Inode,DirectoryEntry}; +use zerocopy::{ByteSlice}; +use uuid::Uuid; + +#[repr(C)] +#[derive(Debug)] +pub struct Ext2 { + pub superblock: &'static Superblock, + pub block_groups: &'static [BlockGroupDescriptor], + pub blocks: Vec<&'static [u8]>, + pub block_size: usize, + pub uuid: Uuid, +} + + +const EXT2_MAGIC: u16 = 0xef53; +const EXT2_SUPERBLOCK_OFFSET: usize = 2048; +impl Ext2 { + pub fn new(bytes: B) -> Ext2 { + // https://wiki.osdev.org/Ext2#Superblock + // parse into Ext2 struct without copying much + + + let x = bytes.split_at(EXT2_SUPERBLOCK_OFFSET); + // let y = x.0.split_at(1024).1; + // let (prefix, superblock, suffix) = unsafe { bytes.align_to::() }; + // println!("{:?}", x.len()); + let superblock = unsafe { &*(x.0.split_at(1024).1.as_ptr() as *const Superblock) }; + assert_eq!(superblock.magic, EXT2_MAGIC); + // println!("{:?} {:?}", prefix, suffix); + + let block_group_count = superblock + .blocks_count + .div_ceil(superblock.blocks_per_group) as usize + - 3; + // assert!(block_igroup_count <= MAX_BLOCK_GROUPS); + // let y = x.1, + // let (prefix, block_groups, suffix) = unsafe { bytes.align_to::() }; + // println!("{:?} {:?}", prefix, suffix); + let block_size: usize = 1024 << superblock.log_block_size; + let y = x.1.split_at(block_size); + + let block_groups = unsafe { + std::slice::from_raw_parts( + y.0.as_ptr() as *const BlockGroupDescriptor, + block_group_count, + ) + }; + + // i determined the root table to be at inode 5, but i need a better way of finding that + // let root_inode_group: usize = (5 - 1) / superblock.inodes_per_group as usize; + // let root_inode_index: usize = (5 - 1) % superblock.inodes_per_group as usize; + // let root_inode_block = (root_inode_index * superblock.inode_size as usize) as usize / block_size; + // println!("{:?}", root_inode_group); + // println!("{:?}", root_inode_index); + // println!("{:?}", root_inode_block); + + let blocks = unsafe { + std::slice::from_raw_parts( + y.1.as_ptr() as *const u8, + superblock.blocks_count as usize * block_size, + ) + } + .chunks(block_size) + .collect::>(); + + // let blocks = unsafe { std::slice::from_raw_parts( + // y.1.as_ptr() as *const [u8;1024], + // superblock.blocks_count as usize) }; + + // let inodes_per_block = block_size / superblock.inode_size as usize; + // let inode_table_block_count: usize = superblock.inodes_per_group as usize / inodes_per_block; + + // let inode_table = unsafe { std::slice::from_raw_parts( + // blocks[(block_groups[root_inode_group].inode_table_block-1) as usize].as_ptr() as *const Inode, + // inode_table_block_count) }; + + // boot block + group descriptors block + inode table blocks + // let data_blocks = unsafe { std::slice::from_raw_parts( + // blocks[1 + 1 + inode_table_block_count].as_ptr() as *const Inode, + // inode_table_block_count) }; + + // let root_inode = &inode_table[root_inode_index]; + // let test_inode = &inode_table[6]; + + // println!("{:?}", unsafe { std::ffi::CStr::from_ptr(blocks[test_inode.direct_pointer[0] as usize-3].as_ptr() as *const i8) }); + + // for inode in &inode_table[0..10] { + // println!("{:?}", inode); + // } + // for data_block in root_inode.direct_pointer { + // if data_block == 0 { break } + // println!("{:?}", blocks[data_block as usize-3]); + // } + + // for ptr in root_inode.direct_pointer { + // println!("{:?}", blocks[ptr as usize - 1]); + // } + + // let block_goups = <[BlockGroupDescriptor]>::read_from_prefix(x.1).unwrap(); + // println!("{:?}", y.1.split_at(block_size * (block_groups[root_inode_group].inode_table_block-1) as usize).1.split_at(block_size).0); + + let uuid = Uuid::from_bytes(superblock.fs_id); + Ext2 { + superblock, + block_groups, + blocks, + block_size, + uuid, + } + } + + // pub fn read_dir_inode(&self, inode: usize) -> std::io::Result> { + // for ptr in root.direct_pointer { + // println!("{:?}",ext2.blocks[ptr as usize - 4] ); + // } + // let directory = ext2.blocks[root.direct_pointer[0] as usize - 3].as_ptr() as *const DirectoryEntry; + // Ok(vec!["/"]) + // } + + // pub fn read_dir_inode(&self, inode: usize) { + // let dir = self.get_inode(inode); + + // } + + pub fn get_inode(&self, inode: usize) -> &Inode { + let group: usize = (inode - 1) / self.superblock.inodes_per_group as usize; + let index: usize = (inode - 1) % self.superblock.inodes_per_group as usize; + + let inode_table = unsafe { + std::slice::from_raw_parts( + self.blocks[(self.block_groups[group].inode_table_block - 1) as usize].as_ptr() + as *const Inode, + index + 1, + ) + }; + // dbg!(inode_table); + &inode_table[index] + } + + pub fn read_dir<'a>(&'a self, inode: &'a Inode) -> Directory<'_> { + Directory { inode, disk: self, offset: 0 } + } +} + +#[derive(Debug)] +pub struct Directory<'a> { + inode: &'a Inode, + disk: &'a Ext2, + offset: usize, +} + +impl<'a> Iterator for Directory<'a> { + type Item = &'a DirectoryEntry; + fn next(&mut self) -> Option { + if self.offset > 0 && self.offset % self.disk.block_size == 0 { + return None; + } + if self.inode.direct_pointer[self.offset / self.disk.block_size] == 0 { + return None; + } + let dir = unsafe { + &*(self.disk.blocks + [self.inode.direct_pointer[self.offset / self.disk.block_size] as usize - 4] + .as_ptr() + .add(self.offset % self.disk.block_size) as *const DirectoryEntry) + }; + self.offset += dir.entry_size as usize; + + Some(dir) + } +} + +fn main() { + let disk = include_bytes!("../ext2.img"); + let ext2 = Ext2::new(&disk[..]); + println!("{:?}", ext2.uuid); + + // root inode always starts at 2 + let root = ext2.get_inode(5); + dbg!(root); + + let dir: Vec<_> = ext2.read_dir(root).collect(); + // dbg!(dir); + + dbg!(dir.clone()); + let file = ext2.get_inode(7); + + dbg!(file); + println!("{:?}", unsafe { + std::ffi::CStr::from_ptr( + ext2.blocks[file.direct_pointer[0] as usize - 3].as_ptr() as *const i8 + ) + }); + // dbg!(dir.next()); + // dbg!(dir.next()); + + // let file = ext2.get_inode(dir.next().unwrap().inode as usize - 8); + // dbg!(file); + + // for ptr in root.direct_pointer { + // println!("{:?}",ext2.blocks[ptr as usize - 4] ); + + // } + // std::vec::Vec::from_raw_parts(ext2.blocks[root.direct_pointer[0] as usize - 4].as_ptr() as *const DirectoryEntry, 5, 5) + // let directory = ext2.blocks[root.direct_pointer[0] as usize - 4].as_ptr() as *const DirectoryEntry; + // dbg!( unsafe { &*directory } ); + // println!("{:?}",ext2.blocks[root.direct_pointer[0] as usize - 3] ); + // println!("{:?}", unsafe { std::ffi::CStr::from_ptr(ext2.blocks[root.direct_pointer[0] as usize - 3].as_ptr()+ as *const i8) }); +} -- cgit 1.4.1