1use anyhow::Result;
8use zerocopy::FromBytes;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11use zerocopy::KnownLayout;
12
13use crate::arena::Arena;
14use crate::arena::BlockId;
15use crate::blockgroup::BLOCK_SIZE;
16use crate::builder::Builder;
17use crate::inode::Inode;
18
19#[repr(C)]
25#[derive(Default, Debug, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
26pub(crate) struct SuperBlock {
27 pub inodes_count: u32,
28 pub blocks_count: u32,
29 _r_blocks_count: u32,
30 pub free_blocks_count: u32,
31 pub free_inodes_count: u32,
32 _first_data_block: u32,
33 _log_block_size: u32,
34 log_frag_size: u32,
35 pub blocks_per_group: u32,
36 frags_per_group: u32,
37 pub inodes_per_group: u32,
38 mtime: u32,
39 wtime: u32,
40 _mnt_count: u16,
41 _max_mnt_count: u16,
42 magic: u16,
43 state: u16,
44 errors: u16,
45 _minor_rev_level: u16,
46 _lastcheck: u32,
47 _checkinterval: u32,
48 _creator_os: u32,
49 rev_level: u32,
50 _def_resuid: u16,
51 _def_resgid: u16,
52 first_ino: u32,
53 pub inode_size: u16,
54 pub block_group_nr: u16,
55 feature_compat: u32,
56 feature_incompat: u32,
57 _feature_ro_compat: u32,
58 uuid: [u8; 16],
59 }
61
62impl SuperBlock {
63 pub fn new<'a>(arena: &'a Arena<'a>, cfg: &Builder) -> Result<&'a mut SuperBlock> {
64 const EXT2_MAGIC_NUMBER: u16 = 0xEF53;
65 const COMPAT_EXT_ATTR: u32 = 0x8;
66
67 let num_groups = cfg.size / (cfg.blocks_per_group * BLOCK_SIZE as u32);
68 let blocks_per_group = cfg.blocks_per_group;
69 let inodes_per_group = cfg.inodes_per_group;
70
71 let log_block_size = 2; let now = std::time::SystemTime::now()
74 .duration_since(std::time::UNIX_EPOCH)?
75 .as_secs() as u32;
76
77 let uuid = uuid::Uuid::new_v4().into_bytes();
78 let inodes_count = inodes_per_group * num_groups;
79 let blocks_count = blocks_per_group * num_groups;
80
81 let first_ino = 11;
84
85 let sb = arena.allocate::<SuperBlock>(BlockId::from(0), 1024)?;
87 *sb = Self {
88 inodes_count,
89 blocks_count,
90 free_blocks_count: 0, free_inodes_count: inodes_count, _log_block_size: log_block_size,
93 log_frag_size: log_block_size,
94 blocks_per_group,
95 frags_per_group: blocks_per_group,
96 inodes_per_group,
97 mtime: now,
98 wtime: now,
99 magic: EXT2_MAGIC_NUMBER,
100 state: 1, errors: 1, rev_level: 1, first_ino,
104 inode_size: Inode::INODE_RECORD_SIZE as u16,
105 block_group_nr: 1, feature_compat: COMPAT_EXT_ATTR,
107 feature_incompat: 0x2, uuid,
109 ..Default::default()
110 };
111
112 Ok(sb)
113 }
114
115 #[inline]
116 pub fn num_groups(&self) -> u16 {
117 (self.inodes_count / self.inodes_per_group) as u16
118 }
119}