summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs213
1 files changed, 213 insertions, 0 deletions
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<B: ByteSlice + std::fmt::Debug>(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::<Superblock>() };
+        // 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::<BlockGroupDescriptor>() };
+        // 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::<Vec<_>>();
+
+        // 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<Vec<(usize, &str)>> {
+    //     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<Self::Item> {
+        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) });
+}