use super::Ext4Superblock;
use crate::{
checksum::{ext4_superblock_csum32, ext4_update_superblock_checksum},
config::*,
crc32c::ext4_superblock_has_metadata_csum,
error::*,
};
impl Ext4Superblock {
pub fn is_valid(&self) -> bool {
self.s_magic == Self::EXT4_SUPER_MAGIC
}
pub fn block_size(&self) -> u64 {
1024 << self.s_log_block_size
}
pub fn blocks_count(&self) -> u64 {
(self.s_blocks_count_hi as u64) << 32 | self.s_blocks_count_lo as u64
}
pub fn free_blocks_count(&self) -> u64 {
(self.s_free_blocks_count_hi as u64) << 32 | self.s_free_blocks_count_lo as u64
}
pub fn reserved_blocks_count(&self) -> u64 {
(self.s_r_blocks_count_hi as u64) << 32 | self.s_r_blocks_count_lo as u64
}
pub fn block_groups_count(&self) -> u32 {
let blocks = self.blocks_count();
let blocks_per_group = self.s_blocks_per_group as u64;
blocks.div_ceil(blocks_per_group) as u32
}
pub fn blocks_per_group(&self) -> u32 {
self.s_blocks_per_group
}
pub fn inodes_per_group(&self) -> u32 {
self.s_inodes_per_group
}
pub fn inode_size(&self) -> u16 {
self.s_inode_size
}
pub fn descs_per_block(&self) -> u32 {
let block_size = self.block_size() as u32;
let desc_size = self.s_desc_size as u32;
block_size.checked_div(desc_size).unwrap_or(0)
}
pub fn get_desc_size(&self) -> u16 {
if self.s_desc_size == 0 {
if self.has_feature_compat(Ext4Superblock::EXT4_FEATURE_INCOMPAT_64BIT) {
return GROUP_DESC_SIZE;
} else {
return GROUP_DESC_SIZE_OLD;
}
}
self.s_desc_size
}
pub fn inode_table_blocks(&self) -> u32 {
let block_size = self.block_size() as u32;
let inode_size = self.s_inode_size as u32;
let inodes_per_group = self.s_inodes_per_group;
if block_size == 0 {
0
} else {
(inodes_per_group * inode_size).div_ceil(block_size)
}
}
pub fn update_checksum(&mut self) {
if ext4_superblock_has_metadata_csum(self) {
ext4_update_superblock_checksum(self);
}
}
pub fn verify_superblock(&self) -> Ext4Result<Self> {
if ext4_superblock_has_metadata_csum(self)
&& self.s_checksum != ext4_superblock_csum32(self)
{
return Err(Ext4Error::checksum());
}
Ok(*self)
}
}