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
//! 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;