Newer
Older
//! Interface with the Inodes
//!
//! See the [OSdev wiki](https://wiki.osdev.org/Ext2#Inodes) for more informations
use bitflags::bitflags;
use super::block::{BlockGroupDescriptor, Superblock};
use super::{read, SUPERBLOCK};
/// Inode index of the root
///
/// See the [OSdev wiki](https://wiki.osdev.org/Ext2#How_To_Read_the_Root_Directory) for more informations
pub const ROOT_INODE_INDEX: usize = 2;
/// General structure of an Ext2 inode
#[repr(packed)]
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
#[derive(Debug)]
pub struct Inode {
/// Type and Permissions
pub type_and_permissions: u16,
/// User ID
pub user_id: u16,
/// Lower 32 bits of size in bytes
pub lower_truncation_byte_size: u32,
/// Last Access Time (in POSIX time)
pub last_access_time: u32,
/// Creation Time (in POSIX time)
pub creation_time: u32,
/// Last Modification time (in POSIX time)
pub last_modification_time: u32,
/// Deletion time (in POSIX time)
pub deletion_time: u32,
/// Group ID
pub group_id: u16,
/// Count of hard links (directory entries) to this inode. When this reaches 0, the data blocks are marked as unallocated.
pub total_hard_links: u16,
/// Count of disk sectors (not Ext2 blocks) in use by this inode, not counting the actual inode structure nor directory entries
/// linking to the inode.
pub total_disk_sectors: u32,
/// Flags
pub flags: u32,
/// Operating System Specific value #1
pub os_specific_1: u32,
/// Direct Block Pointer 0
pub dbp00: u32,
/// Direct Block Pointer 1
pub dbp01: u32,
/// Direct Block Pointer 2
pub dbp02: u32,
/// Direct Block Pointer 3
pub dbp03: u32,
/// Direct Block Pointer 4
pub dbp04: u32,
/// Direct Block Pointer 5
pub dbp05: u32,
/// Direct Block Pointer 6
pub dbp06: u32,
/// Direct Block Pointer 7
pub dbp07: u32,
/// Direct Block Pointer 8
pub dbp08: u32,
/// Direct Block Pointer 9
pub dbp09: u32,
/// Direct Block Pointer 10
pub dbp10: u32,
/// Direct Block Pointer 11
pub dbp11: u32,
/// Singly Indirect Block Pointer (Points to a block that is a list of block pointers to data)
pub singly_indirect_block_pointer: u32,
/// Doubly Indirect Block Pointer (Points to a block that is a list of block pointers to Singly Indirect Blocks)
pub doubly_indirect_block_pointer: u32,
/// Triply Indirect Block Pointer (Points to a block that is a list of block pointers to Doubly Indirect Blocks)
pub triply_indirect_block_pointer: u32,
/// Generation number (Primarily used for NFS)
pub generation_number: u32,
/// In Ext2 version 0, this field is reserved. In version >= 1, Extended attribute block (File ACL).
pub extended_attribute_block: u32,
/// In Ext2 version 0, this field is reserved. In version >= 1, Upper 32 bits of file size (if feature bit set) if it's a file,
/// Directory ACL if it's a directory
pub higher_truncation_byte_size_or_directory_acl: u32,
/// Block address of fragment
pub fragment_block_address: u32,
/// Operating System Specific value #2
pub os_specific_2: [u8; 12],
}
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
impl Inode {
/// Returns the `n`th inode
///
/// Beware that the inode indexing starts at **1**
pub fn new(n: usize) -> Result<Self> {
let superblock = SUPERBLOCK.get().expect("The superblock has not been initialized yet");
let block_group = Self::block_group(superblock, n);
let block_group_descriptor = BlockGroupDescriptor::new(block_group)?;
let inode_table_starting_block = block_group_descriptor.inode_table_starting_block_address as usize;
let index = Self::group_index(superblock, n);
// SAFETY: if the superblock is well formed and the device contains an Ext2 filesystem, then this offset contain an inode
unsafe { read::<Self>(inode_table_starting_block * superblock.block_size() + index * superblock.inode_byte_size as usize) }
}
/// Returns the block group of the inode `n`
///
/// See the [OSdev wiki](https://wiki.osdev.org/Ext2#Determining_which_Block_Group_contains_an_Inode) for more informations
pub const fn block_group(superblock: &Superblock, n: usize) -> usize {
(n - 1) / superblock.inodes_per_group as usize
}
/// Returns the index of the inode `n` in its block group
///
/// See the [OSdev wiki](https://wiki.osdev.org/Ext2#Finding_an_inode_inside_of_a_Block_Group) for more informations
pub const fn group_index(superblock: &Superblock, n: usize) -> usize {
(n - 1) % superblock.inodes_per_group as usize
}
/// Returns the index of the block containing the inode `n`
///
/// See the [OSdev wiki](https://wiki.osdev.org/Ext2#Finding_an_inode_inside_of_a_Block_Group) for more informations
#[allow(unused)]
pub const fn containing_block(superblock: &Superblock, n: usize) -> usize {
(n * superblock.inode_byte_size as usize) / superblock.block_size()
}
}
bitflags! {
/// Indicators of the inode type and permissions
///
/// The type indicator occupies the top hex digit (bits 15 to 12).
///
/// The permission indicator occupies the bottom 12 bits.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
pub struct TypePermissions: u16 {
// Types
/// FIFO
const FIFO = 0x1000;
/// Character device
const CHARACTER_DEVICE = 0x2000;
/// Directory
const DIRECTORY = 0x4000;
/// Block device
const BLOCK_DEVICE = 0x6000;
/// Regular file
const FILE = 0x8000;
/// Symbolic link
const SYMBOLIC_LINK = 0xA000;
/// Unix socket
const SOCKET = 0xC000;
// Permissions
/// Other - execute permission
const OTHER_X = 0x0001;
/// Other - write permission
const OTHER_W = 0x0002;
/// Other - read permission
const OTHER_R = 0x0004;
/// Group - execute permission
const GROUP_X = 0x0008;
/// Group - write permission
const GROUP_W = 0x0010;
/// Group - read permission
const GROUP_R = 0x0020;
/// User - execute permission
const USER_X = 0x0040;
/// User - write permission
const USER_W = 0x0080;
/// User - read permission
const USER_R = 0x0100;
/// Sticky bit
const STICKY = 0x0200;
/// Set group ID
const SET_GROUP_ID = 0x0400;
/// Set user ID
const SET_USER_ID = 0x0800;
}
}
bitflags! {
/// Inode Flags
pub struct Flags: u32 {
/// Secure deletion (not used)
const SECURE_DELETION = 0x0000_0001;
/// Keep a copy of data when deleted (not used)
const DELETION_KEEP_DATA_COPY = 0x0000_0002;
/// File compression (not used)
const FILE_COMPRESSION = 0x0000_0004;
/// Synchronous updates—new data is written immediately to disk
const SYNCHRONOUS_UPDATES = 0x0000_0008;
/// Immutable file (content cannot be changed)
const IMMUTABLE_FILE = 0x0000_0010;
const APPEND_ONLY = 0x0000_0020;
/// File is not included in `dump` command
const DUMP_EXCLUDED = 0x0000_0040;
/// Last accessed time should not updated
const LAST_ACCESSED_TIME_UPDATE_DISABLE = 0x0000_0080;
/// Hash indexed directory
const HASHED_INDEXED_DIR = 0x0001_0000;
const AFS_DIR = 0x0002_0000;
/// Journal file data
const JOURNAL_FILE_DATA = 0x0004_0000;