use anyhow::Result;
use zerocopy::AsBytes;
use zerocopy_derive::FromBytes;
use zerocopy_derive::FromZeroes;
use crate::arena::Arena;
use crate::arena::BlockId;
use crate::blockgroup::BLOCK_SIZE;
use crate::builder::Builder;
use crate::inode::Inode;
#[repr(C)]
#[derive(Default, Debug, Copy, Clone, FromZeroes, FromBytes, AsBytes)]
pub(crate) struct SuperBlock {
pub inodes_count: u32,
pub blocks_count: u32,
_r_blocks_count: u32,
pub free_blocks_count: u32,
pub free_inodes_count: u32,
_first_data_block: u32,
_log_block_size: u32,
log_frag_size: u32,
pub blocks_per_group: u32,
frags_per_group: u32,
pub inodes_per_group: u32,
mtime: u32,
wtime: u32,
_mnt_count: u16,
_max_mnt_count: u16,
magic: u16,
state: u16,
errors: u16,
_minor_rev_level: u16,
_lastcheck: u32,
_checkinterval: u32,
_creator_os: u32,
rev_level: u32,
_def_resuid: u16,
_def_resgid: u16,
first_ino: u32,
pub inode_size: u16,
pub block_group_nr: u16,
feature_compat: u32,
feature_incompat: u32,
_feature_ro_compat: u32,
uuid: [u8; 16],
}
impl SuperBlock {
pub fn new<'a>(arena: &'a Arena<'a>, cfg: &Builder) -> Result<&'a mut SuperBlock> {
const EXT2_MAGIC_NUMBER: u16 = 0xEF53;
const COMPAT_EXT_ATTR: u32 = 0x8;
let num_groups = cfg.size / (cfg.blocks_per_group * BLOCK_SIZE as u32);
let blocks_per_group = cfg.blocks_per_group;
let inodes_per_group = cfg.inodes_per_group;
let log_block_size = 2; let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_secs() as u32;
let uuid = uuid::Uuid::new_v4().into_bytes();
let inodes_count = inodes_per_group * num_groups;
let blocks_count = blocks_per_group * num_groups;
let first_ino = 11;
let sb = arena.allocate::<SuperBlock>(BlockId::from(0), 1024)?;
*sb = Self {
inodes_count,
blocks_count,
free_blocks_count: 0, free_inodes_count: inodes_count, _log_block_size: log_block_size,
log_frag_size: log_block_size,
blocks_per_group,
frags_per_group: blocks_per_group,
inodes_per_group,
mtime: now,
wtime: now,
magic: EXT2_MAGIC_NUMBER,
state: 1, errors: 1, rev_level: 1, first_ino,
inode_size: Inode::INODE_RECORD_SIZE as u16,
block_group_nr: 1, feature_compat: COMPAT_EXT_ATTR,
feature_incompat: 0x2, uuid,
..Default::default()
};
Ok(sb)
}
#[inline]
pub fn num_groups(&self) -> u16 {
(self.inodes_count / self.inodes_per_group) as u16
}
}