| #[repr(C, packed)] |
| #[derive(Debug, Copy, Clone, Default)] |
| pub struct Superblock { |
| pub magic0: u64, |
| pub magic1: u64, |
| pub version: u32, |
| pub flags: u32, |
| pub block_size: u32, |
| pub unused: u32, |
| pub data_block_count: u64, |
| pub journal_block_count: u64, |
| pub inode_count: u64, |
| pub alloc_block_count: u64, |
| pub alloc_inode_count: u64, |
| } |
| |
| #[repr(C, packed)] |
| #[derive(Debug, Copy, Clone, Default)] |
| pub struct Extent { |
| pub size: u16, |
| pub offset_hi: u16, |
| pub offset_lo: u32, |
| } |
| |
| impl Extent { |
| pub fn offset(&self) -> usize { |
| //let hi = self.offset_hi as usize; |
| //let lo = self.offset_lo as usize; |
| //return (hi << 32) | lo; |
| return self.offset_lo as usize; |
| } |
| } |
| |
| #[repr(C, packed)] |
| #[derive(Debug, Copy, Clone, Default)] |
| pub struct NodeHeader { |
| pub flags: u16, |
| pub version: u16, |
| pub next_node: u32, |
| } |
| |
| impl NodeHeader { |
| pub const FLAG_INODE: u16 = 0b0000000000000001; |
| pub const FLAG_EXTENT: u16 = 0b0000000000000010; |
| } |
| |
| #[repr(C, packed)] |
| #[derive(Debug, Copy, Clone, Default)] |
| pub struct Inode { |
| pub header: NodeHeader, |
| pub hash0: u64, |
| pub hash1: u64, |
| pub hash2: u64, |
| pub hash3: u64, |
| pub blob_size: u64, |
| pub block_count: u32, |
| pub extent_count: u16, |
| pub padding: u16, |
| pub inline_extent: Extent, |
| } |
| |
| #[repr(C, packed)] |
| #[derive(Debug, Copy, Clone)] |
| pub struct ExtentContainer { |
| pub header: NodeHeader, |
| pub previous_node: u32, |
| pub extent_count: u16, |
| pub reserved: u16, |
| pub extents: [Extent; 6], |
| } |
| |
| #[repr(C, packed)] |
| #[derive(Debug, Copy, Clone)] |
| pub struct Transaction { |
| pub op: u16, |
| pub size: u16, |
| pub addr: u32, |
| } |
| |
| #[test] |
| fn size_check() { |
| use core::mem::*; |
| assert_eq!(size_of::<Extent>(), 8); |
| assert_eq!(size_of::<Inode>(), 64); |
| assert_eq!(size_of::<ExtentContainer>(), 64); |
| } |