1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Constants drawn from the ext2/3/4 on-disk format specification.
//!
//! References:
//! - linux/fs/ext4/ext4.h (canonical superblock + inode + dirent layout)
//! - linux/fs/ext2/ext2.h (the ext2 subset)
//! - e2fsprogs lib/ext2fs/ext2_fs.h
//!
//! Only the constants we actually use are defined. Add more as the writer
//! grows.
/// Superblock magic number at offset 0x38 of the superblock.
pub const EXT2_MAGIC: u16 = 0xEF53;
/// Byte offset of the primary superblock from the start of the device.
/// (Inside block 0 if `block_size >= 1024`, or in block 1 if 1 KiB blocks.)
pub const SUPERBLOCK_OFFSET: u64 = 1024;
/// Fixed superblock size — even if `s_inode_size` is larger than 128 the
/// superblock itself is always 1024 bytes.
pub const SUPERBLOCK_SIZE: usize = 1024;
/// Size of a group descriptor in classic ext2/3 (32 bytes). When the
/// `INCOMPAT_64BIT` feature is set, descriptors are 64 bytes and the
/// superblock's `s_desc_size` field records the actual size.
pub const GROUP_DESC_SIZE: usize = 32;
/// Size of a 64-bit (`INCOMPAT_64BIT`) group descriptor.
pub const GROUP_DESC_SIZE_64: usize = 64;
/// Default and minimum size of an inode in ext2 (the "good old" rev).
pub const INODE_SIZE_GOOD_OLD: u16 = 128;
/// Inode size used in DYNAMIC_REV (rev 1). 128 keeps us format-compatible
/// with ext2 tooling.
pub const INODE_SIZE_DYNAMIC: u16 = 128;
/// Revision levels.
pub const REV_GOOD_OLD: u32 = 0;
pub const REV_DYNAMIC: u32 = 1;
/// First non-reserved inode in dynamic rev. ext2 reserves inodes 1..=10.
pub const FIRST_INO_DYNAMIC: u32 = 11;
/// Reserved inode numbers.
pub const INO_BAD_BLOCKS: u32 = 1;
pub const INO_ROOT_DIR: u32 = 2;
pub const INO_USER_QUOTA: u32 = 3;
pub const INO_GROUP_QUOTA: u32 = 4;
pub const INO_BOOT_LOADER: u32 = 5;
pub const INO_UNDELETE_DIR: u32 = 6;
pub const INO_RESIZE: u32 = 7;
pub const INO_JOURNAL: u32 = 8;
/// Volume state bits.
pub const FS_VALID: u16 = 0x0001;
/// On-error behaviour.
pub const ERRORS_CONTINUE: u16 = 1;
/// Creator OS values.
pub const OS_LINUX: u32 = 0;
/// File mode bits (S_IFMT / S_IF*).
pub const S_IFMT: u16 = 0o170000;
pub const S_IFSOCK: u16 = 0o140000;
pub const S_IFLNK: u16 = 0o120000;
pub const S_IFREG: u16 = 0o100000;
pub const S_IFBLK: u16 = 0o060000;
pub const S_IFDIR: u16 = 0o040000;
pub const S_IFCHR: u16 = 0o020000;
pub const S_IFIFO: u16 = 0o010000;
/// Directory-entry filetype bytes (used only when the FILETYPE incompat
/// feature is enabled — not in our default ext2 build, but defined so we can
/// turn it on for ext4 later).
pub const DENT_UNKNOWN: u8 = 0;
pub const DENT_REG: u8 = 1;
pub const DENT_DIR: u8 = 2;
pub const DENT_CHR: u8 = 3;
pub const DENT_BLK: u8 = 4;
pub const DENT_FIFO: u8 = 5;
pub const DENT_SOCK: u8 = 6;
pub const DENT_LNK: u8 = 7;
/// Feature flag groups (defined for future ext3/ext4 wiring).
/// Inode flag `EXT4_EXTENTS_FL` — set on inodes whose `i_block` array
/// holds an ext4 extent tree rather than direct/indirect block pointers.
pub const EXT4_EXTENTS_FL: u32 = 0x0008_0000;
/// Number of direct block pointers in an inode (`i_block[0..12]`).
pub const N_DIRECT: usize = 12;
/// Index of the single-indirect block in `i_block`.
pub const IDX_INDIRECT: usize = 12;
/// Index of the double-indirect block in `i_block`.
pub const IDX_DOUBLE_INDIRECT: usize = 13;
/// Index of the triple-indirect block in `i_block`.
pub const IDX_TRIPLE_INDIRECT: usize = 14;
/// Total slots in `i_block`.
pub const N_BLOCKS: usize = 15;