forensic_mount/
inode_map.rs1#![forbid(unsafe_code)]
2
3pub const FUSE_ROOT_INO: u64 = 1;
5pub const FUSE_RO_INO: u64 = 2;
6pub const FUSE_RW_INO: u64 = 3;
7pub const FUSE_DELETED_INO: u64 = 4;
8pub const FUSE_JOURNAL_INO: u64 = 5;
9pub const FUSE_METADATA_INO: u64 = 6;
10pub const FUSE_UNALLOCATED_INO: u64 = 7;
11pub const FUSE_SESSION_INO: u64 = 8;
12pub const FUSE_EVIDENCE_INO: u64 = 9;
13pub const FUSE_ORPHANS_INO: u64 = 10;
17
18const RO_INODE_OFFSET: u64 = 1_000;
20const RW_INODE_OFFSET: u64 = 10_000_000;
22const DELETED_INODE_OFFSET: u64 = 20_000_000;
24const METADATA_INODE_OFFSET: u64 = 30_000_000;
26const JOURNAL_INODE_OFFSET: u64 = 40_000_000;
28const EVIDENCE_INODE_OFFSET: u64 = 50_000_000;
30const UNALLOCATED_INODE_OFFSET: u64 = 60_000_000;
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum InodeNamespace {
36 Virtual(u64),
38 Ro(u64),
40 Rw(u64),
42 Deleted(u64),
44 Metadata(u64),
46 Journal(u64),
48 Evidence(u64),
50 Unallocated(u64),
52}
53
54pub fn decode_fuse_ino(ino: u64) -> InodeNamespace {
56 if ino <= FUSE_ORPHANS_INO {
57 InodeNamespace::Virtual(ino)
58 } else if ino >= UNALLOCATED_INODE_OFFSET {
59 InodeNamespace::Unallocated(ino - UNALLOCATED_INODE_OFFSET)
60 } else if ino >= EVIDENCE_INODE_OFFSET {
61 InodeNamespace::Evidence(ino - EVIDENCE_INODE_OFFSET)
62 } else if ino >= JOURNAL_INODE_OFFSET {
63 InodeNamespace::Journal(ino - JOURNAL_INODE_OFFSET)
64 } else if ino >= METADATA_INODE_OFFSET {
65 InodeNamespace::Metadata(ino - METADATA_INODE_OFFSET)
66 } else if ino >= DELETED_INODE_OFFSET {
67 InodeNamespace::Deleted(ino - DELETED_INODE_OFFSET)
68 } else if ino >= RW_INODE_OFFSET {
69 InodeNamespace::Rw(ino - RW_INODE_OFFSET)
70 } else {
71 InodeNamespace::Ro(ino - RO_INODE_OFFSET)
72 }
73}
74
75pub fn ro_ino(ext4_ino: u64) -> u64 {
77 ext4_ino.saturating_add(RO_INODE_OFFSET)
78}
79
80pub fn rw_ino(ext4_ino: u64) -> u64 {
82 ext4_ino.saturating_add(RW_INODE_OFFSET)
83}
84
85pub fn deleted_ino(ext4_ino: u64) -> u64 {
87 ext4_ino.saturating_add(DELETED_INODE_OFFSET)
88}
89
90pub fn metadata_ino(id: u64) -> u64 {
92 id.saturating_add(METADATA_INODE_OFFSET)
93}
94
95pub fn journal_ino(seq: u64) -> u64 {
97 seq.saturating_add(JOURNAL_INODE_OFFSET)
98}
99
100pub fn evidence_ino(ext4_ino: u64) -> u64 {
102 ext4_ino.saturating_add(EVIDENCE_INODE_OFFSET)
103}
104
105pub fn unallocated_ino(id: u64) -> u64 {
107 id.saturating_add(UNALLOCATED_INODE_OFFSET)
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn roundtrip_ro_inode() {
116 let ext4_ino = 42;
117 let fuse = ro_ino(ext4_ino);
118 assert_eq!(decode_fuse_ino(fuse), InodeNamespace::Ro(ext4_ino));
119 }
120
121 #[test]
122 fn roundtrip_rw_inode() {
123 let ext4_ino = 42;
124 let fuse = rw_ino(ext4_ino);
125 assert_eq!(decode_fuse_ino(fuse), InodeNamespace::Rw(ext4_ino));
126 }
127
128 #[test]
129 fn roundtrip_deleted_inode() {
130 let ext4_ino = 21;
131 let fuse = deleted_ino(ext4_ino);
132 assert_eq!(decode_fuse_ino(fuse), InodeNamespace::Deleted(ext4_ino));
133 }
134
135 #[test]
136 fn virtual_root() {
137 assert_eq!(decode_fuse_ino(FUSE_ROOT_INO), InodeNamespace::Virtual(1));
138 }
139
140 #[test]
141 fn virtual_dirs() {
142 assert_eq!(decode_fuse_ino(FUSE_RO_INO), InodeNamespace::Virtual(2));
143 assert_eq!(decode_fuse_ino(FUSE_RW_INO), InodeNamespace::Virtual(3));
144 assert_eq!(
145 decode_fuse_ino(FUSE_DELETED_INO),
146 InodeNamespace::Virtual(4)
147 );
148 }
149
150 #[test]
151 fn roundtrip_metadata_inode() {
152 let id = 1;
153 let fuse = metadata_ino(id);
154 assert_eq!(decode_fuse_ino(fuse), InodeNamespace::Metadata(id));
155 }
156
157 #[test]
158 fn roundtrip_journal_inode() {
159 let seq = 42;
160 let fuse = journal_ino(seq);
161 assert_eq!(decode_fuse_ino(fuse), InodeNamespace::Journal(seq));
162 }
163
164 #[test]
165 fn roundtrip_unallocated_inode() {
166 let id = 7;
167 let fuse = unallocated_ino(id);
168 assert_eq!(decode_fuse_ino(fuse), InodeNamespace::Unallocated(id));
169 }
170
171 #[test]
172 fn namespaces_do_not_overlap() {
173 let max_ro = ro_ino(9_000_000);
175 let min_rw = rw_ino(0);
176 assert!(max_ro < min_rw);
177 }
178}