Skip to main content

arcbox_ext4/
constants.rs

1// ── Magic numbers ──
2
3pub const SUPERBLOCK_MAGIC: u16 = 0xEF53;
4pub const EXTENT_HEADER_MAGIC: u16 = 0xF30A;
5pub const XATTR_HEADER_MAGIC: u32 = 0xEA02_0000;
6
7// ── Reserved inode numbers ──
8
9pub const DEFECTIVE_BLOCK_INODE: u32 = 1;
10pub const ROOT_INODE: u32 = 2;
11pub const FIRST_INODE: u32 = 11;
12pub const LOST_AND_FOUND_INODE: u32 = 11;
13
14// ── Inode sizing ──
15
16/// Bytes used by inode metadata (before inline xattrs).
17pub const INODE_ACTUAL_SIZE: u32 = 160;
18/// Bytes available for inline extended attributes.
19pub const INODE_EXTRA_SIZE: u32 = 96;
20/// Total on-disk inode size (metadata + inline xattrs).
21pub const INODE_SIZE: u32 = 256;
22/// `extra_isize` field value (INODE_ACTUAL_SIZE - 128).
23pub const EXTRA_ISIZE: u16 = (INODE_ACTUAL_SIZE - 128) as u16;
24/// Size of the xattr header within an inode's inline area.
25pub const XATTR_INODE_HEADER_SIZE: u32 = 4;
26/// Size of the xattr header for a separate xattr block.
27pub const XATTR_BLOCK_HEADER_SIZE: u32 = 32;
28
29// ── Limits ──
30
31pub const MAX_LINKS: u32 = 65000;
32pub const MAX_BLOCKS_PER_EXTENT: u32 = 0x8000;
33pub const MAX_FILE_SIZE: u64 = 128 * 1024 * 1024 * 1024; // 128 GiB
34pub const SUPERBLOCK_OFFSET: u64 = 1024;
35
36// ── Inode block field size ──
37
38/// The `block` field in the inode is 60 bytes, used for extent tree or inline symlink.
39pub const INODE_BLOCK_SIZE: usize = 60;
40
41// ── Compatible feature flags ──
42
43pub mod compat {
44    pub const DIR_PREALLOC: u32 = 0x1;
45    pub const IMAGIC_INODES: u32 = 0x2;
46    pub const HAS_JOURNAL: u32 = 0x4;
47    pub const EXT_ATTR: u32 = 0x8;
48    pub const RESIZE_INODE: u32 = 0x10;
49    pub const DIR_INDEX: u32 = 0x20;
50    pub const LAZY_BG: u32 = 0x40;
51    pub const EXCLUDE_INODE: u32 = 0x80;
52    pub const EXCLUDE_BITMAP: u32 = 0x100;
53    pub const SPARSE_SUPER2: u32 = 0x200;
54}
55
56// ── Incompatible feature flags ──
57
58pub mod incompat {
59    pub const COMPRESSION: u32 = 0x1;
60    pub const FILETYPE: u32 = 0x2;
61    pub const RECOVER: u32 = 0x4;
62    pub const JOURNAL_DEV: u32 = 0x8;
63    pub const META_BG: u32 = 0x10;
64    pub const EXTENTS: u32 = 0x40;
65    pub const BIT64: u32 = 0x80;
66    pub const MMP: u32 = 0x100;
67    pub const FLEX_BG: u32 = 0x200;
68    pub const EA_INODE: u32 = 0x400;
69    pub const DIRDATA: u32 = 0x1000;
70    pub const CSUM_SEED: u32 = 0x2000;
71    pub const LARGEDIR: u32 = 0x4000;
72    pub const INLINE_DATA: u32 = 0x8000;
73    pub const ENCRYPT: u32 = 0x10000;
74}
75
76// ── Read-only compatible feature flags ──
77
78pub mod ro_compat {
79    pub const SPARSE_SUPER: u32 = 0x1;
80    pub const LARGE_FILE: u32 = 0x2;
81    pub const BTREE_DIR: u32 = 0x4;
82    pub const HUGE_FILE: u32 = 0x8;
83    pub const GDT_CSUM: u32 = 0x10;
84    pub const DIR_NLINK: u32 = 0x20;
85    pub const EXTRA_ISIZE: u32 = 0x40;
86    pub const HAS_SNAPSHOT: u32 = 0x80;
87    pub const QUOTA: u32 = 0x100;
88    pub const BIGALLOC: u32 = 0x200;
89    pub const METADATA_CSUM: u32 = 0x400;
90    pub const REPLICA: u32 = 0x800;
91    pub const READONLY: u32 = 0x1000;
92    pub const PROJECT: u32 = 0x2000;
93}
94
95// ── Block group flags ──
96
97pub mod bg_flags {
98    pub const INODE_UNINIT: u16 = 0x1;
99    pub const BLOCK_UNINIT: u16 = 0x2;
100    pub const INODE_ZEROED: u16 = 0x4;
101}
102
103// ── Inode flags ──
104
105pub mod inode_flags {
106    pub const SECRM: u32 = 0x1;
107    pub const UNRM: u32 = 0x2;
108    pub const COMPRESSED: u32 = 0x4;
109    pub const SYNC: u32 = 0x8;
110    pub const IMMUTABLE: u32 = 0x10;
111    pub const APPEND: u32 = 0x20;
112    pub const NODUMP: u32 = 0x40;
113    pub const NOATIME: u32 = 0x80;
114    pub const DIRTY_COMPRESSED: u32 = 0x100;
115    pub const COMPRESSED_CLUSTERS: u32 = 0x200;
116    pub const NO_COMPRESS: u32 = 0x400;
117    pub const ENCRYPTED: u32 = 0x800;
118    pub const HASHED_INDEX: u32 = 0x1000;
119    pub const MAGIC: u32 = 0x2000;
120    pub const JOURNAL_DATA: u32 = 0x4000;
121    pub const NO_TAIL: u32 = 0x8000;
122    pub const DIR_SYNC: u32 = 0x10000;
123    pub const TOP_DIR: u32 = 0x20000;
124    pub const HUGE_FILE: u32 = 0x40000;
125    pub const EXTENTS: u32 = 0x80000;
126    pub const EA_INODE: u32 = 0x200000;
127    pub const EOF_BLOCKS: u32 = 0x400000;
128    pub const SNAPFILE: u32 = 0x0100_0000;
129    pub const SNAPFILE_DELETED: u32 = 0x0400_0000;
130    pub const SNAPFILE_SHRUNK: u32 = 0x0800_0000;
131    pub const INLINE_DATA: u32 = 0x1000_0000;
132    pub const PROJECT_ID_INHERIT: u32 = 0x2000_0000;
133    pub const RESERVED: u32 = 0x8000_0000;
134}
135
136// ── File mode flags ──
137
138pub mod file_mode {
139    pub const S_IXOTH: u16 = 0x1;
140    pub const S_IWOTH: u16 = 0x2;
141    pub const S_IROTH: u16 = 0x4;
142    pub const S_IXGRP: u16 = 0x8;
143    pub const S_IWGRP: u16 = 0x10;
144    pub const S_IRGRP: u16 = 0x20;
145    pub const S_IXUSR: u16 = 0x40;
146    pub const S_IWUSR: u16 = 0x80;
147    pub const S_IRUSR: u16 = 0x100;
148    pub const S_ISVTX: u16 = 0x200;
149    pub const S_ISGID: u16 = 0x400;
150    pub const S_ISUID: u16 = 0x800;
151    pub const S_IFIFO: u16 = 0x1000;
152    pub const S_IFCHR: u16 = 0x2000;
153    pub const S_IFDIR: u16 = 0x4000;
154    pub const S_IFBLK: u16 = 0x6000;
155    pub const S_IFREG: u16 = 0x8000;
156    pub const S_IFLNK: u16 = 0xA000;
157    pub const S_IFSOCK: u16 = 0xC000;
158    pub const TYPE_MASK: u16 = 0xF000;
159}
160
161// ── Directory entry file types ──
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164#[repr(u8)]
165pub enum FileType {
166    Unknown = 0,
167    Regular = 1,
168    Directory = 2,
169    Character = 3,
170    Block = 4,
171    Fifo = 5,
172    Socket = 6,
173    SymbolicLink = 7,
174}
175
176impl FileType {
177    /// Derive the directory-entry file type from an inode mode.
178    pub fn from_mode(mode: u16) -> Self {
179        match mode & file_mode::TYPE_MASK {
180            file_mode::S_IFREG => FileType::Regular,
181            file_mode::S_IFDIR => FileType::Directory,
182            file_mode::S_IFCHR => FileType::Character,
183            file_mode::S_IFBLK => FileType::Block,
184            file_mode::S_IFIFO => FileType::Fifo,
185            file_mode::S_IFSOCK => FileType::Socket,
186            file_mode::S_IFLNK => FileType::SymbolicLink,
187            _ => FileType::Unknown,
188        }
189    }
190}
191
192// ── Mode helpers ──
193
194/// Compose a full inode mode from a type flag and permission bits.
195#[inline]
196pub const fn make_mode(file_type: u16, perm: u16) -> u16 {
197    file_type | perm
198}
199
200/// Check whether a mode represents a directory.
201#[inline]
202pub const fn is_dir(mode: u16) -> bool {
203    mode & file_mode::TYPE_MASK == file_mode::S_IFDIR
204}
205
206/// Check whether a mode represents a regular file.
207#[inline]
208pub const fn is_reg(mode: u16) -> bool {
209    mode & file_mode::TYPE_MASK == file_mode::S_IFREG
210}
211
212/// Check whether a mode represents a symbolic link.
213#[inline]
214pub const fn is_link(mode: u16) -> bool {
215    mode & file_mode::TYPE_MASK == file_mode::S_IFLNK
216}