Skip to content

Commit

Permalink
Be able to read any inode struct with inode number
Browse files Browse the repository at this point in the history
  • Loading branch information
BijanRegmi committed May 2, 2023
1 parent 37431bf commit 4eb78d1
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 40 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bitflags = "2.2.1"
dbg_hex = "0.1.1"
libc = "0.2.142"
94 changes: 94 additions & 0 deletions src/disk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::io::{Read, Seek};

use crate::ext4_structs::{self, Ext4GroupDesc, Ext4Inode, LoadAble};

pub struct Disk {
file: std::fs::File,
pub super_block: ext4_structs::Ext4SuperBlock,
pub block_size: u64,
pub groups_per_flex: u32,
}

impl Disk {
pub fn new(path: &str) -> Self {
let mut f = std::fs::File::open(path).expect("Failed to open file.");

let sb = ext4_structs::Ext4SuperBlock::from_file_offset(&mut f, 0x400)
.expect("Failed to read superblock");
let bs: u64 = (2 as u64).pow(10 + sb.s_log_block_size);
let gpf: u32 = (1 as u32) << sb.s_log_groups_per_flex;

Disk {
file: f,
super_block: sb,
block_size: bs,
groups_per_flex: gpf,
}
}

pub fn read_block(&mut self, block_num: u64) -> std::io::Result<Vec<u8>> {
let mut buf = vec![0u8; self.block_size as usize];
self.file
.seek(std::io::SeekFrom::Start(block_num * self.block_size))?;
self.file.read_exact(&mut buf)?;
Ok(buf)
}

pub fn get_group_desc(&mut self, group_num: u32) -> Ext4GroupDesc {
let primary_group_in_flex = group_num - (group_num % self.groups_per_flex);
let block_no = primary_group_in_flex * self.super_block.s_blocks_per_group
+ self.super_block.s_first_data_block
+ 1;
ext4_structs::Ext4GroupDesc::from_file_offset(
&mut self.file,
(block_no as u64) * (self.block_size as u64),
)
.expect("Cannot read group desc")
}

pub fn block_group_has_superblock(&self, bg_num: u32) -> bool {
if bg_num == 0 {
return true;
} else if self
.super_block
.s_feature_compat
.contains(ext4_structs::Ext4CompatibleFeatures::SPARSE_SUPER2)
{
unimplemented!("Check s_backup_bgs")
} else if bg_num <= 1 || !self.super_block.has_sparse_super_feature() {
true
} else if bg_num & 0x1 == 0 {
false
} else {
fn test_root(mut a: u32, b: u32) -> bool {
loop {
if a < b {
return false;
} else if a == b {
return true;
} else if (a % b) != 0 {
return false;
}
a = a / b;
}
}

test_root(bg_num, 3) || test_root(bg_num, 5) || test_root(bg_num, 7)
}
}

pub fn get_inode(&mut self, inode_num: u32) -> Ext4Inode {
// Block group that an inode lives in
let bg = (inode_num - 1) / self.super_block.s_inodes_per_group;
// Get group desc of bg block number
let gdesc = self.get_group_desc(bg);
let offset_within_flex = bg % self.groups_per_flex;
let inode_table_address = (gdesc.bg_inode_table_hi as u64) << 32
| (gdesc.bg_inode_table_lo as u64) + offset_within_flex as u64;
let inode_index_in_table = (inode_num - 1) % self.super_block.s_inodes_per_group;
let inode_offset_in_table = inode_index_in_table * self.super_block.s_inode_size as u32;
let inode_address = inode_table_address * self.block_size + inode_offset_in_table as u64;
ext4_structs::Ext4Inode::from_file_offset(&mut self.file, inode_address)
.expect("Failed to get inode")
}
}
12 changes: 6 additions & 6 deletions src/ext4_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ mod inode;
mod loadable;
mod superblock;

pub use block_group_descriptor::Ext4GroupDesc;
pub use directories::{Ext4DirEntry, Ext4DirEntry2, Ext4DirEntryHash};
pub use extents::{Ext4Extent, Ext4ExtentHeader, Ext4ExtentIdx, Ext4ExtentTail};
pub use inode::Ext4Inode;
pub use loadable::LoadAble;
pub use superblock::Ext4SuperBlock;
pub use block_group_descriptor::*;
pub use directories::*;
pub use extents::*;
pub use inode::*;
pub use loadable::*;
pub use superblock::*;
13 changes: 13 additions & 0 deletions src/ext4_structs/loadable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,17 @@ pub trait LoadAble: Sized {
}
Ok(result)
}

fn from_vec(buf: Vec<u8>) -> Self {
let size = size_of::<Self>();
let mut result = unsafe { std::mem::MaybeUninit::<Self>::uninit().assume_init() };
unsafe {
memcpy(
&mut result as *mut Self as *mut c_void,
buf.as_ptr() as *const c_void,
size,
);
}
result
}
}
25 changes: 16 additions & 9 deletions src/ext4_structs/superblock.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use bitflags::bitflags;

use super::loadable::LoadAble;
use bitflags::bitflags;

bitflags! {
#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Ext4Os: u32 {
const LINUX = 0;
const HURD = 1;
Expand All @@ -12,7 +11,7 @@ bitflags! {
const LITES = 4;
}

#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Ext4CompatibleFeatures: u32{
const DIR_PREALLOC = 0x0001;
const IMAGIC_INODES = 0x0002;
Expand All @@ -26,7 +25,7 @@ bitflags! {
const ORPHAN_FILE = 0x1000;
}

#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Ext4IncompatibleFeatures: u32 {
const COMPRESSION = 0x0001;
const FILETYPE = 0x0002;
Expand All @@ -46,7 +45,7 @@ bitflags! {
const CASEFOLD = 0x20000;
}

#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Ext4ROCompatibleFeatures: u32 {
const SPARSE_SUPER = 0x0001;
const LARGE_FILE = 0x0002;
Expand All @@ -64,7 +63,7 @@ bitflags! {
const ORPHAN_PRESENT = 0x10000;
}

#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct DxHash: u8 {
const LEGACY = 0;
const HALF_MD4 = 1;
Expand All @@ -76,7 +75,7 @@ bitflags! {
}

/// Default mount options
#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Ext4Defm: u32 {
const DEBUG = 0x0001;
const BSDGROUPS = 0x0002;
Expand Down Expand Up @@ -231,7 +230,7 @@ pub struct Ext4SuperBlock {
pub s_min_extra_isize: u16,
/// New inodes should reserve # bytes.
pub s_want_extra_isize: u16,
/// Miscellaneous flags.
/// Miscellaneous flags.
pub s_flags: u32,
/// RAID stride. This is the number of logical blocks read from or written to
/// the disk before moving to the next disk. This affects the placement of
Expand Down Expand Up @@ -341,4 +340,12 @@ pub struct Ext4SuperBlock {
/// Superblock checksum.
pub s_checksum: u32,
}

impl Ext4SuperBlock {
pub fn has_sparse_super_feature(&self) -> bool {
self.s_feature_ro_compat
.contains(Ext4ROCompatibleFeatures::SPARSE_SUPER)
}
}

impl LoadAble for Ext4SuperBlock {}
40 changes: 15 additions & 25 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
mod disk;
mod ext4_structs;
use dbg_hex::dbg_hex;
use ext4_structs::LoadAble;

use std::{fs::File, mem::size_of};

fn main() -> std::io::Result<()> {
let mut file = File::open("../iso/sda1.img")?;
let sb = ext4_structs::Ext4SuperBlock::from_file_offset(&mut file, 0x400)?;
let gd = ext4_structs::Ext4GroupDesc::from_file_offset(&mut file, 0x400 + 1024)?;

let block_size: u64 = (2 as u64).pow(10 + sb.s_log_block_size) as u64;
let _sda1 = "../iso/sda1.img";
let _nvme = "/dev/nvme0n1p3";
let mut d = disk::Disk::new(_nvme);

let inode_table_address: u64 =
((gd.bg_inode_table_hi as u64) << 8) + (gd.bg_inode_table_lo as u64) * block_size;
let i2 = d.get_inode(26);
dbg!(i2);

let inode_num = 2;
let inode_index_in_table = (inode_num - 1) % sb.s_inodes_per_group;
let inode_offset_in_table = inode_index_in_table * sb.s_inode_size as u32;
let inode_address = inode_table_address + (inode_offset_in_table as u64);
let i = ext4_structs::Ext4Inode::from_file_offset(&mut file, inode_address)?;
dbg!(sb.s_blocks_per_group, 8 * block_size);
dbg_hex!(
block_size,
inode_table_address,
inode_num,
inode_index_in_table,
inode_offset_in_table,
inode_address,
i
);
// let inode_table_address: u64 =
// ((gd.bg_inode_table_hi as u64) << 8) + (gd.bg_inode_table_lo as u64) * block_size;
// left shift hi by 32 bits then or with lo
//
// let inode_num = 2;
// let inode_index_in_table = (inode_num - 1) % sb.s_inodes_per_group;
// let inode_offset_in_table = inode_index_in_table * sb.s_inode_size as u32;
// let inode_address = inode_table_address + (inode_offset_in_table as u64);
// let i = ext4_structs::Ext4Inode::from_file_offset(&mut file, inode_address)?;
Ok(())
}

0 comments on commit 4eb78d1

Please sign in to comment.