This document is released under a dual Creative Commons Attribution 4.0 International License OR GNU General Public License (GPL) version 2 or any later version license.
|
Tip
|
Texts wrapped in tip admonitions like this paragraph are added for reference and for readers who want to have a deeper mastery of origination of format designs. They are not part of the specification and are non-normative. |
1. Introduction
Indexed Delegator Filesystem (IDTFS) is a kind of filesystem, which delegates accesses and modifications to files to one of some backing filesystems.
To determine the corresponding backing file of a given file path, an implementation has to lookup a mapping. The IDTFS file format is designed for representing and exchanging this kind of mapping tree.
What the Core Module defines is the most basic level of IDTFS which is a read-only filesystem and does not care about write transactions like item allocations.
2. Overview
The IDTFS file format consists of multiple modules, of which all implementers must implement all features of the Core Module.
IDTFS files are made up of blocks. The size of a block must be a power of 2 and the exponent must be greater than or equal to 8.
|
Tip
|
That is to say, the block size must be greater than or equal to 256, in order to reduce corner cases where the block size is too small and some fundamental structures like the superblock are placed across two or more blocks. |
|
Note
|
For image creators, it is recommended to prefer to a larger block size by default, such as 4096. |
IDTFS always stores integers in little endian format.
3. Superblock
An IDTFS image starts with a superblock and the superblock references other structures.
The superblock consists of two sections: a header and an attribute array.
3.1. Header
The header section is padded to 64 bytes using zero bytes.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
4 |
|
|
Must be set to |
0x04 |
4 |
|
|
CRC32-C checksum of the superblock, including attributes. When calculating the checksum, value of the checksum field is assumed to be zero. |
0x08 |
1 |
|
|
Must be set to 1. |
0x09 |
1 |
|
|
\(log_2(block\_size)\) |
0x0A |
2 |
|
|
Number of superblock attributes. |
0x0C |
4 |
reserved |
Must be filled with 0. |
|
0x10 |
16 |
|
|
128-bit UUID of this volume. |
0x20 |
8 |
|
|
Creation time of this filesystem in seconds since the UNIX epoch. |
0x28 |
24 |
reserved |
Must be filled with 0. |
3.2. Attributes
The header is immediately followed by the attribute array which consists of sb.hdr.sb_attrs entries.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
8 |
|
|
Identifier of this attribute. |
0x08 |
24 |
reserved |
Reserved for attribute data. |
An attribute is uniquely identified with its ID. ID range 0x00000000-0xFFFFFFFF and 0x80000000'00000000-0x80000000’FFFFFFFF are reserved for official modules.
Authors of extension modules may declare their own attribute ID. The ID for third-party modules should be picked randomly and must not conflict with the reserved range.
|
Tip
|
Authors of extension modules should introduce at least one new superblock attribute, if possible, even if the attribute data field is completely unused, as a "feature flag". |
If the MSB of id is set, then the attribute is "incompatible" and implementations that do not support the attribute must refuse to load this file. Otherwise, implementations may ignore the attribute.
4. Volume Label
Volume labels can be found using a specific superblock attribute.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
8 |
|
|
Must be set to 0x4B18. |
0x08 |
8 |
|
|
Absolute byte-aligned offset of the volume label string in this file. |
0x10 |
2 |
|
|
Length of the label. |
0x12 |
14 |
reserved |
Must be filled with 0. |
|
Tip
|
UTF-8 are recommended but not required. Same for file names. |
5. Inode Sources Array
Inodes may be read from different kinds of sources. These sources are stored as an array whose location can be found in an superblock attribute.
|
Tip
|
For example, directory entry may be stored in an IDTFS file itself, while inodes of regular files may be read from other underlying filesystems if they are to be delegated. Inodes from different sources may have different ways to read their file data. |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
8 |
|
|
Must be set to 0xD4EA. |
0x08 |
8 |
|
|
Image-relative byte-aligned offset of the inode sources array in this file. |
0x10 |
2 |
|
|
Number of inode sources |
0x12 |
14 |
reserved |
Must be filled with 0. |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Type of the inode source. |
0x02 |
30 |
reserved |
Reserved for source parameters. |
Each inode source has an index, starting from zero. The address of an inode source structure can be calculated with offset = inode_srcs_attr.off + (32 * i) where i is the index.
Type code 0x0000-0x7FFF are reserved for official modules.
6. Root Inode Entry
Each image must have a root inode attribute which contains parameters of the root directory inode.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
8 |
|
|
Must be set to 0x5340. |
0x08 |
8 |
reserved |
Must be filled with 0. |
|
0x10 |
16 |
directory entry record |
|
Directory entry record of the root directory.
File name related fields are unused and ignored. File type code must be |
7. Plain Inode Source
Plain source is used for inodes that are stored directly in the IDTFS file.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Must be set to 0x9AD0. |
0x02 |
2 |
reserved |
Must be filled with 0. |
|
0x04 |
4 |
|
|
Nanoseconds component in file modification time shared by all small inodes. |
0x08 |
8 |
|
|
File modification time shared by all small inodes in seconds since 00:00, Jan 1st, 1970 UTC. |
0x10 |
16 |
reserved |
Must be filled with 0. |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
reserved |
Must be filled with 0. |
|
0x02 |
8 |
|
|
Inode number. |
7.1. Inode Structure
The absolute offset of an inode can be calculated using its inode number (nid) with inode_offset = nid * 32.
Each inode contains these parts:
-
inode header
-
extended attributes (xattr) info, only present if
inode.flags.has_xattris set. -
xattr entries, if any
-
inlined data tail, if data layout requires one
There are two kinds of plain inode headers: small and extended. The small variant is smaller in size at the cost of smaller value ranges and losing per-file modification time.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Flags. |
0x02 |
2 |
|
|
File permission mode. |
0x04 |
4 |
|
|
Data location. |
0x08 |
8 |
|
|
File size in bytes. |
0x10 |
4 |
|
|
Owner UID. |
0x14 |
4 |
|
|
Owner GID. |
0x18 |
1 |
|
|
Hard link count. |
0x19 |
7 |
reserved |
Must be filled with 0. |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Flags. |
0x02 |
2 |
|
|
File permission mode. |
0x04 |
4 |
|
|
Data location. |
0x08 |
8 |
|
|
File size in bytes. |
0x10 |
4 |
|
|
Owner UID. |
0x14 |
4 |
|
|
Owner GID. |
0x18 |
4 |
|
|
Hard link count. |
0x1C |
4 |
|
|
Nanoseconds component in file modification time. |
0x20 |
8 |
|
|
File modification time in seconds since 00:00, Jan 1st, 1970 UTC. |
0x28 |
24 |
reserved |
Must be filled with 0. |
| Bit | Width | Name | Description |
|---|---|---|---|
0 |
2 |
|
0 for small inode. 1 for extended inode. 2 and 3 are reserved. |
2 |
4 |
|
Interpretation method for the |
6 |
1 |
|
1 if the file has any extended attribute, 0 if it has no xattr. |
7 |
9 |
reserved |
Must be filled with 0. |
Implementations must refuse unsupported or reserved values in plain inode flags.
| Value | Name | Description |
|---|---|---|
0 |
SPECIAL |
For device files, the meaning of |
1 |
FLAT |
For data files, it means that file contents are stored in the image file at block offset |
2 |
FLAT_INLINE |
For data files, it means that file contents are stored in the image file at block offset |
For empty files, inode.data is ignored and can be any value.
Data files include regular files, directories and symbolic links.
When an implementation encounters an invalid or unsupported data layout or a invalid or unsupported combination of data layout and file type, operations that need to interact with file contents must fail.
7.2. Inline Data Layout
To speed up file IO, inline data layout (FLAT_INLINE) places the last (inode.size % block_size) bytes ("tail chunk") of file contents right after the inode structure.
If the size of the tail chunk is 0, this layout behaves the same as the FLAT layout.
The tail chunk must be located in the same block as the last byte of the inode structure. Otherwise implementations may refuse IO operations.
If the file is smaller than one block (i.e. all data are within the tail chunk), inode.data is unused and can be any value.
7.3. Device Files
Character device and block device files use the SPECIAL layout only. inode.data is interpreted as platform-dependent device number and inode.size must be 0.
On Linux, the device number consists of major and minor device numbers that can be extracted as follows:
| Bit | Width | Name | Description |
|---|---|---|---|
0 |
20 |
|
Minor device number. |
20 |
12 |
|
Major device number. |
7.4. IPC Files
Both FIFO (named pipe) and socket files are IPC files and use the SPECIAL layout only. inode.size and inode.data must be 0.
7.5. Extended Attributes
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Size of xattr entry region logically shifted right by 2 bits. |
0x02 |
2 |
reserved |
Must be filled with 0. |
|
0x04 |
4 |
reserved |
Must be filled with 0. |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
1 |
|
|
Name prefix index. |
0x01 |
1 |
|
|
Byte-size of name suffix. |
0x02 |
2 |
|
|
Byte-size of xattr value. |
|
|
Bytes of xattr name suffix. |
||
|
|
Bytes of xattr value. |
||
padding |
Realigns the xattr entry to 4-byte-aligned. |
| Value | Name | Prefix |
|---|---|---|
0 |
NONE |
No prefix. |
1 |
USER |
|
2 |
SYS |
|
3 |
TRUSTED |
|
4 |
SECURITY |
|
5 |
SYS_POSIX_ACL_ACC |
|
6 |
SYS_POSIX_ACL_DEF |
|
8. Directories
The contents of a directory file consists of directory blocks, each block starts with an array of directory entry records.
Size of a directory file may be image-block-size-aligned. If not, the last file_size % block_size bytes are considered as a directory block ("tail block") whose size is not the image block size. The size of tail blocks is implementation-defined but must be greater than file_size % block_size
|
Tip
|
As the tail block size is implementation-defined, references (such as entry.name_off) to bytes after file_size % block_size are undefined behavior.
|
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Offset of the file name within this directory block. |
0x02 |
2 |
|
|
Byte-size of the file name. |
0x04 |
1 |
|
|
Entry flags and file type code. |
0x05 |
1 |
|
|
Index of inode source. |
0x06 |
10 |
inode parameters |
|
Reserved for inode sources. |
File name strings must be in the same directory block as the entry. The name of the first entry record in the array must be placed immediately after the last entry.
|
Tip
|
That is to say, the number of entries in a single directory block is entries[0].name_off >> 4.
|
| Bit | Width | Name | Description |
|---|---|---|---|
0 |
3 |
|
File type code. |
3 |
5 |
reserved |
Must be filled with 0. |
| Value | Name | Description |
|---|---|---|
0 |
REG_FILE |
Regular files. |
1 |
DIR |
Directories. |
2 |
CHRDEV |
Character devices. |
3 |
BLKDEV |
Block devices. |
4 |
FIFO |
Named pipe. |
5 |
SOCK |
Socket file. |
6 |
SYMLINK |
Symbolic link. |
For all directory entries referring to the same inode, flags.file_type must be the same. If not, the behavior is implementation-defined.
9. Delegation Inode Source
Delegation source is used to delegate accesses to inodes to an backing filesystem.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Must be set to 0x605B. |
0x02 |
1 |
|
|
Backing filesystem lookup mode. |
0x03 |
29 |
reserved |
Reserved |
| Value | Name | Description |
|---|---|---|
0 |
HASH |
Hash path lookup, such as |
1 |
PATH |
Custom path lookup, such as |
2 |
EXTERNAL_OPTS |
Passes all backing FS paths through mount options. |
9.1. Hash mode
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Must be set to 0x605B. |
0x02 |
1 |
|
|
Must be set to 0. |
0x03 |
1 |
reserved |
Must be filled with 0. |
|
0x04 |
4 |
|
|
Block-offset to the backing FS array. |
0x08 |
2 |
|
|
Count of backing filesystems. |
0x0A |
1 |
|
|
Byte-size of each path. |
0x0B |
1 |
|
|
Segmentation offset. |
0x0A |
20 |
reserved |
Reserved |
The backing filesystem path can be computed using the following steps:
-
Load the fixed-length hash string at image-relative offset
(path_blkoff << blksz_bits) + (path_len * i)whereiis the backing FS index (0 ⇐ i < fs_count). The length of the string ispath_len. -
If
sep_posis non-zero, separate the path into two components and concatenate them.path = string_concat(raw_path[0..sep_pos], PATH_SEPARATOR, raw_path[sep_pos..]).
9.2. Custom Path Mode
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Must be set to 0x605B. |
0x02 |
1 |
|
|
Must be set to 1. |
0x03 |
1 |
reserved |
Must be filled with 0. |
|
0x04 |
4 |
|
|
Block-offset to the backing path data. |
0x08 |
4 |
|
|
Byte-size of the backing path data. Must be greater than or equal to |
0x0C |
2 |
|
|
Count of backing filesystems. |
0x0E |
16 |
reserved |
Reserved |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
4 |
|
|
Backing-path-data-relative offset to the path string. Must be less than or equal to |
0x04 |
4 |
|
|
Byte-size of the string. |
The backing filesystem path can be computed using the following steps:
-
Load the path slice structure at image-relative offset
(path_blkoff << blksz_bits) + (8 * i)whereiis the backing FS index (0 ⇐ i < fs_count). -
Load the path string at image-relative offset
(path_blkoff << blksz_bits) + slice.off.
9.3. External Options Mode
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Must be set to 0x605B. |
0x02 |
1 |
|
|
Must be set to 2. |
0x03 |
1 |
reserved |
Must be filled with 0. |
|
0x04 |
2 |
|
|
Length of the backing FS array. |
0x06 |
26 |
reserved |
Reserved |
9.4. Directory Entry Record
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Index of backing filesystem. |
0x02 |
2 |
|
|
Offset of the backing file name within this directory block. |
0x04 |
2 |
|
|
Byte-size of the backing file name. |
0x06 |
4 |
reserved |
Must be filled with 0. |
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0x00 |
2 |
|
|
Index of backing filesystem. |
0x02 |
2 |
|
|
Must be set to 0. |
0x04 |
2 |
reserved |
Must be filled with 0. |
|
0x06 |
4 |
|
|
Index of the backing file. |
Backing file name strings must be in the same directory block as the entry.
For entries using compact backing file names, the backing file name is backing_file_idx encoded in lowercase ASCII hexadecimal and added "0"-s to the left to align to 8 characters.
Backing file names are relative to the root of the backing filesystem selected by fs.