Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ anyhow = "1"
bitflags = "1"
byteorder = "1"
crc = "1"
derivative = "2.1.1"
positioned-io = "0.2"
thiserror = "1"

Expand Down
12 changes: 12 additions & 0 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
with import <nixpkgs> {};
stdenv.mkDerivation rec {
name = "env";
env = buildEnv { name = name; paths = buildInputs; };
buildInputs = [
fuse
#fuse3
#fuse-common
rustup
pkg-config
];
}
227 changes: 160 additions & 67 deletions src/block_groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,149 @@ struct Entry {
max_inode_number: u32,
}

#[derive(Debug)]
pub struct BlockGroup {
bg_block_bitmap_lo: u32, /* Blocks bitmap block */
bg_inode_bitmap_lo: u32, /* Inodes bitmap block */
bg_inode_table_lo: u32, /* Inodes table block */
bg_free_blocks_count_lo: u16, /* Free blocks count */
bg_free_inodes_count_lo: u16, /* Free inodes count */
bg_used_dirs_count_lo: u16, /* Directories count */
bg_flags: u16, /* EXT4_BG_flags (INODE_UNINIT, etc) */
bg_exclude_bitmap_lo: u32, /* Exclude bitmap for snapshots */
bg_block_bitmap_csum_lo: u16, /* crc32c(s_uuid+grp_num+bbitmap) LE */
bg_inode_bitmap_csum_lo: u16, /* crc32c(s_uuid+grp_num+ibitmap) LE */
bg_itable_unused_lo: u16, /* Unused inodes count */
bg_checksum: u16, /* crc16(sb_uuid+group+desc) */
bg_block_bitmap_hi: u32, /* Blocks bitmap block MSB */
bg_inode_bitmap_hi: u32, /* Inodes bitmap block MSB */
bg_inode_table_hi: u32, /* Inodes table block MSB */
bg_free_blocks_count_hi: u16, /* Free blocks count MSB */
bg_free_inodes_count_hi: u16, /* Free inodes count MSB */
bg_used_dirs_count_hi: u16, /* Directories count MSB */
bg_itable_unused_hi: u16, /* Unused inodes count MSB */
bg_exclude_bitmap_hi: u32, /* Exclude bitmap block MSB */
bg_block_bitmap_csum_hi: u16, /* crc32c(s_uuid+grp_num+bbitmap) BE */
bg_inode_bitmap_csum_hi: u16, /* crc32c(s_uuid+grp_num+ibitmap) BE */
bg_reserved: u32, /* Padding to 64 bytes */
}

impl BlockGroup {
pub fn new(buffer: Vec<u8>, s_desc_size: u16) -> Result<BlockGroup, Error> {
let mut inner = io::Cursor::new(buffer);

let bg_block_bitmap_lo = inner.read_u32::<LittleEndian>()?; /* Blocks bitmap block */
let bg_inode_bitmap_lo = inner.read_u32::<LittleEndian>()?; /* Inodes bitmap block */
let bg_inode_table_lo = inner.read_u32::<LittleEndian>()?; /* Inodes table block */
let bg_free_blocks_count_lo = inner.read_u16::<LittleEndian>()?; /* Free blocks count */
let bg_free_inodes_count_lo = inner.read_u16::<LittleEndian>()?; /* Free inodes count */
let bg_used_dirs_count_lo = inner.read_u16::<LittleEndian>()?; /* Directories count */
let bg_flags = inner.read_u16::<LittleEndian>()?; /* EXT4_BG_flags (INODE_UNINIT, etc) */
let bg_exclude_bitmap_lo = inner.read_u32::<LittleEndian>()?; /* Exclude bitmap for snapshots */
let bg_block_bitmap_csum_lo = inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) LE */
let bg_inode_bitmap_csum_lo = inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) LE */
let bg_itable_unused_lo = inner.read_u16::<LittleEndian>()?; /* Unused inodes count */
let bg_checksum = inner.read_u16::<LittleEndian>()?; /* crc16(sb_uuid+group+desc) */

// In ext2, ext3, and ext4 (when the 64bit feature is not enabled),
// the block group descriptor was only 32 bytes long and therefore ends at bg_checksum.
// On an ext4 filesystem with the 64bit feature enabled, the block group descriptor expands
// to at least the 64 bytes described below; the size is stored in the superblock.

let bg_block_bitmap_hi = if s_desc_size > 32 {
inner.read_u32::<LittleEndian>()?
} else {
0
};
let bg_inode_bitmap_hi = if s_desc_size > 32 {
inner.read_u32::<LittleEndian>()?
} else {
0
};
let bg_inode_table_hi = if s_desc_size > 32 {
inner.read_u32::<LittleEndian>()?
} else {
0
};

let bg_free_blocks_count_hi = if s_desc_size > 32 {
inner.read_u16::<LittleEndian>()?
} else {
0
};

let bg_free_inodes_count_hi = if s_desc_size > 32 {
inner.read_u16::<LittleEndian>()?
} else {
0
};

/* Directories count MSB */
let bg_used_dirs_count_hi = if s_desc_size > 32 {
inner.read_u16::<LittleEndian>()?
} else {
0
};
/* Unused inodes count MSB */
let bg_itable_unused_hi = if s_desc_size > 32 {
inner.read_u16::<LittleEndian>()?
} else {
0
};
/* Exclude bitmap block MSB */
let bg_exclude_bitmap_hi = if s_desc_size > 32 {
inner.read_u32::<LittleEndian>()?
} else {
0
};
/* crc32c(s_uuid+grp_num+bbitmap) BE */
let bg_block_bitmap_csum_hi = if s_desc_size > 32 {
inner.read_u16::<LittleEndian>()?
} else {
0
};
/* crc32c(s_uuid+grp_num+ibitmap) BE */
let bg_inode_bitmap_csum_hi = if s_desc_size > 32 {
inner.read_u16::<LittleEndian>()?
} else {
0
};

/* Padding to 64 bytes */
let bg_reserved = if s_desc_size > 32 {
inner.read_u32::<LittleEndian>()?
} else {
0
};

Ok(BlockGroup {
bg_block_bitmap_lo,
bg_inode_bitmap_lo,
bg_inode_table_lo,
bg_free_blocks_count_lo,
bg_free_inodes_count_lo,
bg_used_dirs_count_lo,
bg_flags,
bg_exclude_bitmap_lo,
bg_block_bitmap_csum_lo,
bg_inode_bitmap_csum_lo,
bg_itable_unused_lo,
bg_checksum,
bg_block_bitmap_hi,
bg_inode_bitmap_hi,
bg_inode_table_hi,
bg_free_blocks_count_hi,
bg_free_inodes_count_hi,
bg_used_dirs_count_hi,
bg_itable_unused_hi,
bg_exclude_bitmap_hi,
bg_block_bitmap_csum_hi,
bg_inode_bitmap_csum_hi,
bg_reserved,
})
}
}

#[derive(Debug)]
pub struct BlockGroups {
groups: Vec<Entry>,
Expand All @@ -42,78 +185,28 @@ impl BlockGroups {
let mut groups = Vec::with_capacity(blocks_count);

for block in 0..blocks_count {
// let bg_block_bitmap_lo =
inner.read_u32::<LittleEndian>()?; /* Blocks bitmap block */
// let bg_inode_bitmap_lo =
inner.read_u32::<LittleEndian>()?; /* Inodes bitmap block */
let bg_inode_table_lo = inner.read_u32::<LittleEndian>()?; /* Inodes table block */
// let bg_free_blocks_count_lo =
inner.read_u16::<LittleEndian>()?; /* Free blocks count */
let bg_free_inodes_count_lo = inner.read_u16::<LittleEndian>()?; /* Free inodes count */
// let bg_used_dirs_count_lo =
inner.read_u16::<LittleEndian>()?; /* Directories count */
let bg_flags = inner.read_u16::<LittleEndian>()?; /* EXT4_BG_flags (INODE_UNINIT, etc) */
// let bg_exclude_bitmap_lo =
inner.read_u32::<LittleEndian>()?; /* Exclude bitmap for snapshots */
// let bg_block_bitmap_csum_lo =
inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) LE */
// let bg_inode_bitmap_csum_lo =
inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) LE */
// let bg_itable_unused_lo =
inner.read_u16::<LittleEndian>()?; /* Unused inodes count */
// let bg_checksum =
inner.read_u16::<LittleEndian>()?; /* crc16(sb_uuid+group+desc) */

// let bg_block_bitmap_hi =
if s_desc_size < 4 {
None
} else {
Some(inner.read_u32::<LittleEndian>()?) /* Blocks bitmap block MSB */
};
// let bg_inode_bitmap_hi =
if s_desc_size < 4 + 4 {
None
} else {
Some(inner.read_u32::<LittleEndian>()?) /* Inodes bitmap block MSB */
};
let bg_inode_table_hi = if s_desc_size < 4 + 4 + 4 {
None
} else {
Some(inner.read_u32::<LittleEndian>()?) /* Inodes table block MSB */
};
// let bg_free_blocks_count_hi =
if s_desc_size < 4 + 4 + 4 + 2 {
None
// let mut entire_blockgroup = [0u8; s_desc_size];
let bufsize = if s_desc_size == 0 {
32
} else {
Some(inner.read_u16::<LittleEndian>()?) /* Free blocks count MSB */
};
let bg_free_inodes_count_hi = if s_desc_size < 4 + 4 + 4 + 2 + 2 {
None
} else {
Some(inner.read_u16::<LittleEndian>()?) /* Free inodes count MSB */
s_desc_size.into()
};
let mut entire_blockgroup = vec![0u8; bufsize];
inner.read_exact(&mut entire_blockgroup)?;
let blockgroup = BlockGroup::new(entire_blockgroup, s_desc_size)?;

// let bg_used_dirs_count_hi =
// inner.read_u16::<LittleEndian>()?; /* Directories count MSB */
// let bg_itable_unused_hi =
// inner.read_u16::<LittleEndian>()?; /* Unused inodes count MSB */
// let bg_exclude_bitmap_hi =
// inner.read_u32::<LittleEndian>()?; /* Exclude bitmap block MSB */
// let bg_block_bitmap_csum_hi =
// inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+bbitmap) BE */
// let bg_inode_bitmap_csum_hi =
// inner.read_u16::<LittleEndian>()?; /* crc32c(s_uuid+grp_num+ibitmap) BE */
if s_desc_size > 16 + 32 {
inner.seek(io::SeekFrom::Current(i64::from(s_desc_size - 32 - 16)))?;
}
// AA TODO What was this about?
// if s_desc_size > 16 + 32 {
// inner.seek(io::SeekFrom::Current(i64::from(s_desc_size - 32 - 16)))?;
// }

let inode_table_block =
u64::from(bg_inode_table_lo) | ((u64::from(bg_inode_table_hi.unwrap_or(0))) << 32);
let free_inodes_count = u32::from(bg_free_inodes_count_lo)
| ((u32::from(bg_free_inodes_count_hi.unwrap_or(0))) << 16);
let inode_table_block = u64::from(blockgroup.bg_inode_table_lo)
| ((u64::from(blockgroup.bg_inode_table_hi)) << 32);
let free_inodes_count = u32::from(blockgroup.bg_free_inodes_count_lo)
| ((u32::from(blockgroup.bg_free_inodes_count_hi)) << 16);

let unallocated = bg_flags & EXT4_BLOCK_GROUP_INODES_UNUSED != 0
|| bg_flags & EXT4_BLOCK_GROUP_BLOCKS_UNUSED != 0;
let unallocated = blockgroup.bg_flags & EXT4_BLOCK_GROUP_INODES_UNUSED != 0
|| blockgroup.bg_flags & EXT4_BLOCK_GROUP_BLOCKS_UNUSED != 0;

if free_inodes_count > s_inodes_per_group {
return Err(crate::parse_error(format!(
Expand Down
Loading