Inodes
The inode data structure is used to store the metadata for a file or directory. Inodes are located in inode tables, which are located in each of the block groups. The starting location of the inode table is defined in the group descriptor, and the number of inodes per group is defined in the superblock.
The basic inode data structure is 128 bytes in size. If the file system is a "dynamic" version, as defined in the superblock, the inode can be a dynamic size, which is given in the superblock. Larger inodes are not supported in the current Linux kernel, but the first 128 bytes will have the same fields as the standard inode [Ts'o and Tweedie 2002]. The basic inode has the fields given in Table 15.10.
Byte Range |
Description |
Essential |
---|---|---|
01 |
File mode (type and permissions) (see Tables 15.11, 15.12, and 15.13) |
Yes |
23 |
Lower 16 bits of user ID |
No |
47 |
Lower 32 bits of size in bytes |
Yes |
811 |
Access Time |
No |
1215 |
Change Time |
No |
1619 |
Modification time |
No |
2023 |
Deletion time |
No |
2425 |
Lower 16 bits of group ID |
No |
2627 |
Link count |
No |
2831 |
Sector count |
No |
3235 |
Flags (see Table 15.14) |
No |
3639 |
Unused |
No |
4087 |
12 direct block pointers |
Yes |
8891 |
1 single indirect block pointer |
Yes |
9295 |
1 double indirect block pointer |
Yes |
9699 |
1 triple indirect block pointer |
Yes |
100103 |
Generation number (NFS) |
No |
104107 |
Extended attribute block (File ACL) |
No |
108111 |
Upper 32 bits of size / Directory ACL Yes / |
No |
112115 |
Block address of fragment |
No |
116116 |
Fragment index in block |
No |
117117 |
Fragment size |
No |
118119 |
Unused |
No |
120121 |
Upper 16 bits of user ID |
No |
122123 |
Upper 16 bits of group ID |
No |
124127 |
Unused |
No |
As was mentioned in the overview, the size was originally only 32 bits, but it was made into a 64-bit value by using the directory ACL value at bytes 108 to 111. There should be a read only compatible feature set in the superblock if any file uses a 64-bit size.
The 16-bit file mode value is broken up into three sections. In the lower 9 bits are the permissions flags, and each bit corresponds to a permission. The permissions use the notion of user, group, and world where user is the user ID in the inode, group is the group ID in the inode, and world is all other users. Each of these collections of users can have read, write, or execute permissions. The flags for each of these permissions are given in Table 15.11.
Permission Flag |
Description |
---|---|
0x001 |
Otherexecute permission |
0x002 |
Otherwrite permission |
0x004 |
Otherread permission |
0x008 |
Groupexecute permission |
0x010 |
Groupwrite permission |
0x020 |
Groupread permission |
0x040 |
Userexecute permission |
0x080 |
Userwrite permission |
0x100 |
Userread permission |
The next three bits are for executable files and directories. If any of these are set, an executable will behave differently when it is run, or files in a directory will have special properties. These flags are given in Table 15.12.
Flag Value |
Description |
---|---|
0x200 |
Sticky bit |
0x400 |
Set group ID |
0x800 |
Set user ID |
Refer to the "Metadata Category" section in Chapter 14 for a description of these flags. Lastly, bits 12 to 15 identify the type of the file that the inode is for. These are values and not flags, so only one should be set. They are given in Table 15.13.
Type Value |
Description |
---|---|
0x1000 |
FIFO |
0x2000 |
Character device |
0x4000 |
Directory |
0x6000 |
Block device |
0x8000 |
Regular file |
0xA000 |
Symbolic link |
0xC000 |
Unix socket |
The four time values are each stored as the number of seconds since January 1, 1970 UTC, which will stop working in January 2038 because the value is only 32 bits. The flags field identifies the attributes that are set for the file. Recall from the previous section that not every OS supports some of these flag values. The values included in Table 15.14 are either discussed in the manual pages or are used in the current kernel source code.
Flag Value |
Description |
---|---|
0x00000001 |
Secure deletion (not used) |
0x00000002 |
Keep a copy of data when deleted (not used) |
0x00000004 |
File compression (not used) |
0x00000008 |
Synchronous updatesnew data is written immediately to disk |
0x00000010 |
Immutable filecontent cannot be changed |
0x00000020 |
Append only |
0x00000040 |
File is not included in 'dump' command |
0x00000080 |
A-time is not updated |
0x00001000 |
Hash indexed directory |
0x00002000 |
File data is journaled with Ext3 |
Let's look at inode entry 16 from the previous image. The first step is to identify the group of which it is a part. We know that each group has 16,288 inodes per group, which means that we need group 0. The starting address of the inode table is given in the group descriptor, and we previously saw that it starts in block 4, and each block is 4,096 bytes. To extract the data, we will use dd with a block size of 4096 to skip ahead to the inode table and then use dd with a block size of 128 to skip ahead to inode 16. The first inode is number 1, so we need to subtract 1 from our skip value.
# dd if=ext3.dd bs=4096 skip=4 | dd bs=128 skip=15 count=1 | xxd 0000000: a481 f401 0040 9c00 6d09 2a3f f607 2a3f .....@..m.*?..*? 0000016: 8107 2a3f 0000 0000 f401 0100 404e 0000 ..*?........@N.. 0000032: 0000 0000 0000 0000 2c38 0000 2d38 0000 ........,8..-8.. 0000048: 2e38 0000 2f38 0000 3038 0000 3138 0000 .8../8..08..18.. 0000064: 3238 0000 3338 0000 3438 0000 3538 0000 28..38..48..58.. 0000080: 3638 0000 3738 0000 3838 0000 393c 0000 68..78..88..9<.. 0000096: 0000 0000 ba94 ea0b 0000 0000 0000 0000 ................ 0000112: 0000 0000 0000 0000 0000 0000 0000 0000 ................
Bytes 0 to 1 show the mode, which is 0x81a4. These bits show us that everyone can read this file (0x004), the group can read (0x020), the user can write (0x080), and the user can read (0x100). The upper four bits show that it is a regular file (0x8000). Bytes 4 to 7 show that the size of the file is 10,240,000 bytes (0x009c4000). Bytes 8 to 11 show the A-time as 0x3f2a096d, which translates to August 1, 2003 at 06:32:13 UTC. Bytes 26 to 27 show the link count is 1, which means that there is a file name pointing to it. Bytes 32 to 35 show that there are no special flags or attributes set.
Bytes 40 to 43 are for the first direct block pointer, and they are for block 14,380 (0x0000382c). Bytes 44 to 47 are for the second direct pointer, and they are for block 14,381 (0x0000382d). Bytes 88 to 91 contain the address of a single indirect block pointer, which is in block 14,392 (0x00003838). Bytes 92 to 95 also show a double indirect block pointer in block 15,417 (0x00003c39). The contents of both of these blocks will be a list of 4-byte addresses. The single indirect block pointer contains a list of addresses where file content is stored:
# dcat f linux-ext3 ext3.dd 14392 | xxd 0000000: 3938 0000 3a38 0000 3b38 0000 3c38 0000 98..:8..;8..<8.. 0000016: 3d38 0000 3e38 0000 3f38 0000 4038 0000 =8..>8..?8..@8.. 0000032: 4138 0000 4238 0000 4338 0000 4438 0000 A8..B8..C8..D8.. [REMOVED]
The allocation status of an inode is stored in the inode bitmap, which is located in the same group as the inode. The group descriptor contains the block address of the inode bitmap, and our example image has its bitmap in block 3, whose contents are shown here:
# dcat f linux-ext3 ext3.dd 3 | xxd 0000000: fff7 fcff 1f00 0000 00c8 0000 0000 0000 ................
To determine the correct byte, we subtract 1 to account for the first inode of the group and divide by 8.
(16 1) / 8 = 1 remainder 7
The bit for inode 16 is the most significant bit in byte 1 (0xf7), which is a 1, so it is allocated.
We can get all the inode details from the istat command, and they are listed here for the inode that we just examined:
# istat f linux-ext3 ext3.dd 16 inode: 16 Allocated Group: 0 Generation Id: 199922874 uid / gid: 500 / 500 mode: -rw-r--r-- size: 10240000 num of links: 1
Inode Times: Accessed: Fri Aug 1 06:32:13 2003 File Modified: Fri Aug 1 06:24:01 2003 Inode Modified: Fri Aug 1 06:25:58 2003
Direct Blocks: 14380 14381 14382 14383 14384 14385 14386 14387 14388 14389 14390 14391 14393 14394 14395 14396 [REMOVED] 16880 16881 16882 16883
Indirect Blocks: 14392 15417 15418 16443