Apple File System Reference
Apple File System Reference
Developer
Contents
About Apple File System 7
General-Purpose Types 9
paddr_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
prange_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
uuid_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Objects 10
obj_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Supporting Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Object Identifier Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Object Type Masks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Object Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Object Type Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
EFI Jumpstart 22
Booting from an Apple File System Partition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
nx_efi_jumpstart_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Partition UUIDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Container 26
Mounting an Apple File System Partition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
nx_superblock_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Container Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Optional Container Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Read-Only Compatible Container Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Incompatible Container Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Block and Container Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
nx_counter_id_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
checkpoint_mapping_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
checkpoint_map_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Checkpoint Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
evict_mapping_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Object Maps 44
omap_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
omap_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
omap_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
omap_snapshot_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Object Map Value Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Snapshot Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Object Map Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Object Map Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Object Map Reaper Phases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2
Volumes 51
apfs_superblock_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
apfs_modified_by_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Volume Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Volume Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Optional Volume Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Read-Only Compatible Volume Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Incompatible Volume Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
File-System Objects 71
j_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
j_inode_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
j_inode_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
j_drec_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
j_drec_hashed_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
j_drec_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
j_dir_stats_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
j_dir_stats_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
j_xattr_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
j_xattr_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
File-System Constants 84
j_obj_types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
j_obj_kinds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
j_inode_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
j_xattr_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
dir_rec_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Inode Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Extended Attributes Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
File-System Object Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
File Extent Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
File Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Directory Entry File Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
3
Siblings 115
j_sibling_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
j_sibling_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
j_sibling_map_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
j_sibling_map_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
B-Trees 122
btree_node_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
btree_info_fixed_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
btree_info_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
btn_index_node_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
nloc_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
kvloc_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
kvoff_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
B-Tree Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
B-Tree Table of Contents Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
B-Tree Node Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
B-Tree Node Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Encryption 135
Accessing Encrypted Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
j_crypto_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
j_crypto_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
wrapped_crypto_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
wrapped_meta_crypto_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Encryption Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Protection Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Encryption Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
kb_locker_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
keybag_entry_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
media_keybag_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Keybag Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
4
j_file_info_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
j_file_info_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
j_obj_file_info_type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
j_file_data_hash_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Reaper 164
nx_reaper_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
nx_reap_list_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
nx_reap_list_entry_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Volume Reaper States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Reaper Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Reaper List Entry Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Reaper List Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
omap_reap_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
omap_cleanup_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
apfs_reap_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Fusion 172
fusion_wbc_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
fusion_wbc_list_entry_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
fusion_wbc_list_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Address Markers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
5
fusion_mt_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
fusion_mt_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Fusion Middle-Tree Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
6
About Apple File System
Apple File System is the default file format used on Apple platforms. Apple File System is the successor to HFS
Plus, so some aspects of its design intentionally follow HFS Plus to enable data migration from HFS Plus to Apple File
System. Other aspects of its design address limitations with HFS Plus and enable features like cloning files, snapshots,
encryption, and sharing free space between volumes.
Most apps interact with the file system using high-level interfaces provided by Foundation, which means most de-
velopers donʼt need to read this document. This document is for developers of software that interacts with the file
system directly, without using any frameworks or the operating system — for example, a disk recovery utility or an
implementation of Apple File System on another platform. The on-disk data structures described in this document
make up the file system; software that interacts with them defines corresponding in-memory data structures.
Note
If you need to boot from an Apple File System volume, but donʼt need to mount the volume or interact with the
file system directly, read Booting from an Apple File System Partition.
Layered Design
The Apple File System is conceptually divided into two layers, the container layer and the file-system layer. The con-
tainer layer organizes file-system layer information and stores higher level information, like volume metadata, snap-
shots of the volume, and encryption state. The file-system layer is made up of the data structures that store informa-
tion, like directory structures, file metadata, and file content. Many types are prefixed with nx_ or j_, which indicates
that theyʼre part of the container layer or the file-system layer, respectively. The abbreviated prefixes donʼt have a
meaningful long form; theyʼre an artifact of how Appleʼs implementation was developed.
There are several design differences between the layers. Container objects are larger, with a typical size measured
in blocks, and contain padding fields that keep data aligned on 64-bit boundaries, to avoid the performance penalty
of unaligned memory access. File-system objects are smaller, with a typical size measured in bytes, and are almost
always packed to minimize space used.
Numbers in both layers are stored on disk in little-endian order. Objects in both layers begin with a common header
that enables object-oriented design patterns in implementations of Apple File System, although the layers have dif-
ferent headers. Container layer objects begin with an instance of obj_phys_t and file-system objects begin with an
instance of j_key_t,
Container Layer
Container objects have an object identifier that you use to locate the object; the steps vary depending on how the
object is stored:
The object map includes a B-tree whose keys contain a transaction identifier and an object identifier and whose values
contain a physical block address where the object is stored.
7
About Apple File System
An Apple File System partition has a single container, which provides space management and crash protection. A
container can contain multiple volumes (also known as file systems), each of which contains a directory structure for
files and folders. For example, the figure below shows a storage device that has one Apple File System partition, and
it shows the major divisions of the space inside that container.
Although thereʼs only one container, there are several copies of the container superblock (an instance of nx_super
block_t) stored on disk. These copies hold the state of the container at past points in time. Block zero contains
a copy of the container superblock thatʼs used as part of the mounting process to find the checkpoints. Block zero
is typically a copy of the latest container superblock, assuming the device was properly unmounted and was last
modified by a correct Apple File System implementation. However, in practice, you use the block zero copy only to
find the checkpoints and use the latest version from the checkpoint for everything else.
Within a container, the checkpoint mechanism and the copy-on-write approach to modifying objects enable crash pro-
tection. In-memory state is periodically written to disk in checkpoints, followed by a copy of the container superblock
at that point in time. Checkpoint information is stored in two regions: The checkpoint descriptor area contains in-
stances of checkpoint_map_phys_t and nx_superblock_t, and the checkpoint data area contains ephemeral
objects that represent the in-memory state at the point in time when the checkpoint was written to disk.
When mounting a device, you use the most recent checkpoint information thatʼs valid, as discussed in Mounting
an Apple File System Partition. If the process of writing a checkpoint is interrupted, that checkpoint is invalid and
therefore is ignored the next time the device is mounted, rolling the file system back to the last valid state. Because the
checkpoint stores in-memory state, mounting an Apple File System partition includes reading the ephemeral objects
from the checkpoint back into memory, re-creating that state in memory.
File-System Layer
File-system objects are made up of several records, and each record is stored as a key and value in a B-tree (an
instance of btree_node_phys_t). For example, a typical directory object is made up of an inode record, several
directory entry records, and an extended attributes record. A record contains an object identifier thatʼs used to find it
within the B-tree that contains it.
8
General-Purpose Types
Basic types that are used in a variety of contexts, and arenʼt associated with any particular functionality.
paddr_t
A physical address of an on-disk block.
Negative numbers arenʼt valid addresses. This value is modeled as a signed integer to match IOKit.
prange_t
A range of physical addresses.
struct prange {
paddr_t pr_start_paddr;
uint64_t pr_block_count;
};
typedef struct prange prange_t;
pr_start_paddr
paddr_t pr_start_paddr;
pr_block_count
uint64_t pr_block_count;
uuid_t
A universally unique identifier.
9
Objects
Depending on how theyʼre stored, objects have some differences, the most important of which is the way you use an
object identifier to find an object. At the container level, there are three storage methods for objects:
• Ephemeral objects are stored in memory for a mounted container, and are persisted across unmounts in a
checkpoint. Ephemeral objects for a mounted partition can be modified in place while theyʼre in memory, but
theyʼre always written back to disk as part of a new checkpoint. Theyʼre used for information thatʼs frequently
updated because of the performance benefits of in-place, in-memory changes.
• Physical objects are stored at a known block address on the disk, and are modified by writing the copy to a new
location on disk. Because the object identifier for a physical object is its physical address, this copy-on-write
behavior means that the modified copy has a different object identifier.
• Virtual objects are stored on disk at a block address that you look up using an object map. Virtual objects are
also copied when they are modified; however, both the original and the modified copy have the same object
identifier. When you look up a virtual object in an object map, you use a transaction identifier, in addition to the
object identifier, to specify the point in time that you want.
Regardless of their storage, objects on disk are never modified in place, and modified copies of an object are always
written to a new location on disk. To access an object, you need to know its storage and its identifier. For virtual objects,
you also need a transaction identifier. The storage for an object is almost always implicit from the context in which
that identifier appears. For example, the object identifier for the space manager is stored in the nx_spaceman_oid
field of nx_superblock_t, and the documentation for that field says that the space manager is always an ephemeral
object.
Object identifiers are unique inside the entire container, within their storage method. For example, no two virtual
objects can have the same identifier — even when stored in different object maps — because their storage methods
are the same. However, a virtual object and a physical object can have the same identifier because their storage
methods are different. For information about determining the identifier for a new object, see oid_t.
When writing a new object to disk, fill all unused space in the block with zeros. Future versions of Apple File System
add new fields at the end of a structure; zeroing out the uninitialized bytes makes it possible to determine whether data
has been stored in a field that was added later, such as the apfs_cloneinfo_xid field of apfs_superblock_t.
obj_phys_t
A header used at the beginning of all objects.
struct obj_phys {
uint8_t o_cksum[MAX_CKSUM_SIZE];
oid_t o_oid;
xid_t o_xid;
uint32_t o_type;
uint32_t o_subtype;
};
typedef struct obj_phys obj_phys_t;
#define MAX_CKSUM_SIZE 8
10
Objects
Supporting Data Types
o_cksum
uint8_t o_cksum[MAX_CKSUM_SIZE];
o_oid
oid_t o_oid;
o_xid
The identifier of the most recent transaction that this object was modified in.
xid_t o_xid;
o_type
uint32_t o_type;
An object type is a 32-bit value: The low 16 bits indicate the type using the values listed in Object Types, and the high
16 bits are flags using the values listed in Object Type Flags.
o_subtype
uint32_t o_subtype;
Subtypes indicate the type of data stored in a data structure such as a B-tree. For example, a node in a B-tree that
contains volume records has a type of OBJECT_TYPE_BTREE_NODE and a subtype of OBJECT_TYPE_FS.
MAX_CKSUM_SIZE
#define MAX_CKSUM_SIZE 8
11
Objects
Object Identifier Constants
oid_t
An object identifier.
• For a physical object, its identifier is the logical block address on disk where the object is stored.
For more information about physical, ephemeral, or virtual objects, see Objects.
To determine the identifier for a new physical object, find a free block using the space manager, and use that blockʼs
address. To determine the identifier for a new ephemeral or virtual object, check the value of nx_superblock_t.
nx_next_oid. New ephemeral and virtual object identifiers must be monotonically increasing.
Note
Although both ephemeral and virtual objects use nx_next_oid field of nx_superblock_t in Appleʼs imple-
mentation, this isnʼt guaranteed or required. Ephemeral and virtual objects are stored in different places, so itʼs
valid to encounter (or create) an ephemeral object and a virtual object that have the same identifier.
xid_t
A transaction identifier.
The number zero isnʼt a valid transaction identifier. Implementations of Apple File System can use it as a sentinel value
in memory — for example, to refer to the current transaction — but must not let it appear on disk.
This data type is sufficiently large that you arenʼt expected to ever run out of transaction identifiers. For example,
if you created 1,000,000 transactions per second, it would take more than 5,000 centuries to exhaust the available
transaction identifiers.
If a new transaction identifier isnʼt available, thatʼs an unrecoverable error. Identifiers arenʼt allowed to restart from
one or to be reused.
#define OID_NX_SUPERBLOCK 1
12
Objects
Object Type Masks
OID_NX_SUPERBLOCK
#define OID_NX_SUPERBLOCK 1
Although the container superblock is stored in memory like other ephemeral objects, it isnʼt saved on disk in the same
area. For details, see Mounting an Apple File System Partition.
OID_INVALID
OID_RESERVED_COUNT
The number of object identifiers that are reserved for objects with a fixed object identifier.
This range of identifiers is reserved for physical, virtual, and ephemeral objects.
Currently, the only object with a reserved identifier is the container superblock, as described in OID_NX_SUPERBLOCK.
All other object identifiers less than OID_RESERVED_COUNT are reserved by Apple.
OBJECT_TYPE_MASK
For the values that appear in this bit field, see Object Types.
OBJECT_TYPE_FLAGS_MASK
For the values that appear in this bit field, see Object Type Flags.
13
Objects
Object Types
OBJ_STORAGETYPE_MASK
The bit mask used to access the storage portion of the object type.
For the values that appear in this bit field, see Object Type Flags.
OBJECT_TYPE_FLAGS_DEFINED_MASK
Object Types
Values used as types and subtypes by the obj_phys_t structure.
14
Objects
Object Types
OBJECT_TYPE_NX_SUPERBLOCK
OBJECT_TYPE_BTREE
OBJECT_TYPE_BTREE_NODE
OBJECT_TYPE_SPACEMAN
OBJECT_TYPE_SPACEMAN_CAB
OBJECT_TYPE_SPACEMAN_CIB
15
Objects
Object Types
OBJECT_TYPE_SPACEMAN_BITMAP
OBJECT_TYPE_SPACEMAN_FREE_QUEUE
OBJECT_TYPE_EXTENT_LIST_TREE
The keys are an offset into the logical start of the extent, and the value is the physical location where that data is
stored.
OBJECT_TYPE_OMAP
As a type, an object map (omap_phys_t); as a subtype, a tree that stores the records of an object map (a mapping
from omap_key_t to omap_val_t).
OBJECT_TYPE_CHECKPOINT_MAP
OBJECT_TYPE_FS
A volume (apfs_superblock_t).
OBJECT_TYPE_FSTREE
The keys and values stored in the tree vary. Each key begins with j_key_t, which contains a field that indicates the
type of that key and its value.
16
Objects
Object Types
OBJECT_TYPE_BLOCKREFTREE
OBJECT_TYPE_SNAPMETATREE
A tree containing snapshot metadata for a volume (a mapping from j_snap_metadata_key_t to j_snap_
metadata_val_t).
OBJECT_TYPE_NX_REAPER
A reaper (nx_reaper_phys_t).
OBJECT_TYPE_NX_REAP_LIST
OBJECT_TYPE_OMAP_SNAPSHOT
A tree containing information about snapshots of an object map (a mapping from xid_t to omap_snapshot_t).
OBJECT_TYPE_EFI_JUMPSTART
OBJECT_TYPE_FUSION_MIDDLE_TREE
A tree used for Fusion devices to track blocks from the hard drive that are cached on the solid-state drive (a mapping
from fusion_mt_key_t to fusion_mt_val_t).
17
Objects
Object Types
OBJECT_TYPE_NX_FUSION_WBC
OBJECT_TYPE_NX_FUSION_WBC_LIST
OBJECT_TYPE_ER_STATE
OBJECT_TYPE_GBITMAP
OBJECT_TYPE_GBITMAP_TREE
OBJECT_TYPE_GBITMAP_BLOCK
OBJECT_TYPE_ER_RECOVERY_BLOCK
Information that can be used to recover from a system crash if one occurs during the encryption rolling process
(er_recovery_block_phys_t).
OBJECT_TYPE_SNAP_META_EXT
18
Objects
Object Types
OBJECT_TYPE_INTEGRITY_META
OBJECT_TYPE_FEXT_TREE
OBJECT_TYPE_RESERVED_20
Reserved.
OBJECT_TYPE_INVALID
OBJECT_TYPE_TEST
Donʼt create objects of this type on disk. If you find an object of this type in production, file a bug against the Apple
File System implementation.
This type isnʼt reserved by Apple; non-Apple implementations of Apple File System can use it during testing.
OBJECT_TYPE_CONTAINER_KEYBAG
OBJECT_TYPE_VOLUME_KEYBAG
OBJECT_TYPE_MEDIA_KEYBAG
19
Objects
Object Type Flags
The value of obj_phys_t.o_type & OBJECT_TYPE_FLAGS_MASK uses these constants. The value of obj_
phys_t.o_type & OBJ_STORAGETYPE_MASK uses only OBJ_VIRTUAL, OBJ_EPHEMERAL, and OBJ_PHYSICAL.
The flags on an objectʼs type must indicate whether the object is virtual, ephemeral, or physical by setting either the
OBJ_EPHEMERAL or OBJ_PHYSICAL flag, or setting neither flag. An object type that contains both flags is invalid.
The absence of both flags indicates a virtual object. The OBJ_VIRTUAL constant is defined to allow code that tests
for virtual objects to match code testing for physical or ephemeral objects, even though thereʼs no corresponding bit
set in the objectʼs type. For example:
OBJ_VIRTUAL
A virtual object.
OBJ_EPHEMERAL
An ephemeral object.
OBJ_PHYSICAL
A physical object.
OBJ_NOHEADER
20
Objects
Object Type Flags
OBJ_ENCRYPTED
An encrypted object.
OBJ_NONPERSISTENT
Objects with this flag never appear on disk. If you find an object of this type in production, file a bug against the Apple
File System implementation.
This flag isnʼt reserved by Apple; non-Apple implementations of Apple File System can mark their runtime-only data
structures with OBJ_NONPERSISTENT | OBJ_EPHEMERAL.
21
EFI Jumpstart
A partition formatted using the Apple File System contains an embedded EFI driver thatʼs used to boot a machine from
that partition.
1. Read physical block zero from the partition. This block contains a copy of the container superblock, which is
an instance of nx_superblock_t.
2. Read the nx_o field of the superblock, which is an instance of obj_phys_t. Then read the o_cksum field
of the nx_o field of the superblock, which contains the Fletcher 64 checksum of the object. Verify that the
checksum is correct.
3. Read the nx_magic field of the superblock. Verify that the fieldʼs value is NX_MAGIC (the four-character code
'BSXN').
4. Read the nx_efi_jumpstart field of the superblock. This field contains the physical block address
(also referred to as the physical object identifier) for the EFI jumpstart information, which is an instance of
nx_efi_jumpstart_t.
5. Read the nej_magic field of the EFI jumpstart information. Verify that the fieldʼs value is NX_EFI_JUMP
START_MAGIC (the four-character code 'RDSJ').
6. Read the nej_o field of the EFI jumpstart information, which is an instance of obj_phys_t. Then read the
o_cksum field of the nej_o field of the jumpstart information, which contains the Fletcher 64 checksum of the
object. Verify that the checksum is correct.
7. Read the nej_version field of the EFI jumpstart information. This field contains the EFI jumpstart version
number. Verify that the fieldʼs value is NX_EFI_JUMPSTART_VERSION (the number one).
8. Read the nej_efi_file_len field of the jumpstart information. This field contains the length, in bytes, of
the embedded EFI driver. Allocate a contiguous block of memory of at least that size, which youʼll later use to
store the EFI driver.
9. Read the nej_num_extents field of the jumpstart information, and then read that number of prange_t
records from the nej_rec_extents field.
10. Read each extent of the EFI driver into memory, contiguously, in the order theyʼre listed.
Implementation Outline
The code listing below shows one way to boot using the embedded EFI driver, assuming the functions listed at the
beginning are defined.
22
EFI Jumpstart
Booting from an Apple File System Partition
int main() {
nx_superblock_t* superblock = read_superblock(0);
assert(superblock->nx_o.o_cksum == fletcher64_checksum(&superblock));
assert(superblock->nx_magic == 'BSXN');
23
EFI Jumpstart
nx_efi_jumpstart_t
}
}
load_and_execute(efi_driver);
return 0;
}
nx_efi_jumpstart_t
Information about the embedded EFI driver thatʼs used to boot from an Apple File System partition.
struct nx_efi_jumpstart {
obj_phys_t nej_o;
uint32_t nej_magic;
uint32_t nej_version;
uint32_t nej_efi_file_len;
uint32_t nej_num_extents;
uint64_t nej_reserved[16];
prange_t nej_rec_extents[];
};
typedef struct nx_efi_jumpstart nx_efi_jumpstart_t;
#define NX_EFI_JUMPSTART_MAGIC 'RDSJ'
#define NX_EFI_JUMPSTART_VERSION 1
nej_o
obj_phys_t nej_o;
nej_magic
A number that can be used to verify that youʼre reading an instance of nx_efi_jumpstart_t.
uint32_t nej_magic;
nej_version
uint32_t nej_version;
nej_efi_file_len
uint32_t nej_efi_file_len;
24
EFI Jumpstart
Partition UUIDs
nej_num_extents
uint32_t nej_num_extents;
nej_reserved
Reserved.
uint64_t nej_reserved[16];
Populate this field with zero when you create a new instance, and preserve its value when you modify an existing
instance.
nej_rec_extents
prange_t nej_rec_extents[];
NX_EFI_JUMPSTART_MAGIC
This magic number was chosen because in hex dumps it appears as “JSDR”, which is an abbreviated form of jumpstart
driver record.
NX_EFI_JUMPSTART_VERSION
#define NX_EFI_JUMPSTART_VERSION 1
Partition UUIDs
Partition types used in GUID partition table entries.
APFS_GPT_PARTITION_UUID
The partition type for a partition that contains an Apple File System container.
25
Container
The container includes several top-level objects that are shared by all of the containerʼs volumes:
• Checkpoint description and data areas store ephemeral objects in a way that provides crash protection. At the
end of each transaction, new state is saved by writing a checkpoint.
• The space manager keeps track of available space within the container and is used to allocate and free blocks
that store objects and file data.
• The reaper manages the deletion of objects that are too large to be deleted in the time between transactions.
It keeps track of the deletion state so these objects can be deleted across multiple transactions.
Because a single container can have multiple volumes, configurations that would require multiple partitions under
other file systems can usually share a single partition with Apple File System. For example, a drive can be configured
with two bootable volumes — one with a shipping version of macOS and one with a beta version — as well as a user
data volume. All three of these volumes share free space, meaning you donʼt have to decide ahead of time how to
divide space between them.
1. Read block zero of the partition. This block contains a copy of the container superblock (an instance of
nx_superblock_t). It might be a copy of the latest version or an old version, depending on whether the
drive was unmounted cleanly.
2. Use the block-zero copy of the container superblock to locate the checkpoint descriptor area by reading the
nx_xp_desc_base field.
3. Read the entries in the checkpoint descriptor area, which are instances of checkpoint_map_phys_t or
nx_superblock_t.
4. Find the container superblock that has the largest transaction identifier and isnʼt malformed. For example,
confirm that its magic number and checksum are valid. That superblock and its checkpoint-mapping blocks
comprise the latest valid checkpoint. The superblockʼs fields, like nx_xp_desc_blocks and nx_data_len,
indicate which checkpoint-mapping blocks belong to that superblock.
Note
The checkpoint description area is a ring buffer stored as an array. Walking backward from the latest valid
superblock to read all of its checkpoint-mapping blocks sometimes requires wrapping around from the
first block to the last block.
5. Read the ephemeral objects listed in the checkpoint from the checkpoint data area into memory. If any of the
ephemeral objects is malformed, the checkpoint that contains that object is malformed; go back to the previous
step and mount from an older checkpoint.
26
Container
nx_superblock_t
The details of this step vary. For example, if youʼre mounting the partition read-only and performance isnʼt a
consideration, you can skip this step and read from the checkpoint every time you need to access an ephemeral
object.
6. Locate the container object map using the nx_omap_oid field of the container superblock.
7. Read the list of volumes from the nx_fs_oid field of the container superblock. If youʼre mounting only a
particular volume, you can ignore the virtual object identifiers for the other volumes.
8. For each volume, look up the specified virtual object identifier in the container object map to locate the volume
superblock (an instance of apfs_superblock_t). If youʼre mounting only a particular volume, you can skip
this step for the other volumes.
9. For each volume, read the root file system treeʼs virtual object identifier from the apfs_root_tree_oid field,
and then look it up in the volume object map indicated by the apfs_omap_oid field. If youʼre mounting only a
particular volume, you can skip this step for the other volumes.
10. Walk the root file system tree as needed by your implementation to mount the file system.
nx_superblock_t
A container superblock.
struct nx_superblock {
obj_phys_t nx_o;
uint32_t nx_magic;
uint32_t nx_block_size;
uint64_t nx_block_count;
uint64_t nx_features;
uint64_t nx_readonly_compatible_features;
uint64_t nx_incompatible_features;
uuid_t nx_uuid;
oid_t nx_next_oid;
xid_t nx_next_xid;
uint32_t nx_xp_desc_blocks;
uint32_t nx_xp_data_blocks;
paddr_t nx_xp_desc_base;
paddr_t nx_xp_data_base;
uint32_t nx_xp_desc_next;
uint32_t nx_xp_data_next;
uint32_t nx_xp_desc_index;
uint32_t nx_xp_desc_len;
uint32_t nx_xp_data_index;
uint32_t nx_xp_data_len;
oid_t nx_spaceman_oid;
oid_t nx_omap_oid;
27
Container
nx_superblock_t
oid_t nx_reaper_oid;
uint32_t nx_test_type;
uint32_t nx_max_file_systems;
oid_t nx_fs_oid[NX_MAX_FILE_SYSTEMS];
uint64_t nx_counters[NX_NUM_COUNTERS];
prange_t nx_blocked_out_prange;
oid_t nx_evict_mapping_tree_oid;
uint64_t nx_flags;
paddr_t nx_efi_jumpstart;
uuid_t nx_fusion_uuid;
prange_t nx_keylocker;
uint64_t nx_ephemeral_info[NX_EPH_INFO_COUNT];
oid_t nx_test_oid;
oid_t nx_fusion_mt_oid;
oid_t nx_fusion_wbc_oid;
prange_t nx_fusion_wbc;
uint64_t nx_newest_mounted_version;
prange_t nx_mkb_locker;
};
typedef struct nx_superblock nx_superblock_t;
#define NX_EPH_INFO_COUNT 4
#define NX_EPH_MIN_BLOCK_COUNT 8
#define NX_MAX_FILE_SYSTEM_EPH_STRUCTS 4
#define NX_TX_MIN_CHECKPOINT_COUNT 4
#define NX_EPH_INFO_VERSION_1 1
nx_o
obj_phys_t nx_o;
nx_magic
A number that can be used to verify that youʼre reading an instance of nx_superblock_t.
uint32_t nx_magic;
28
Container
nx_superblock_t
nx_block_size
The logical block size used in the Apple File System container.
uint32_t nx_block_size;
This size is often the same as the block size used by the underlying storage device, but it can also be an integer
multiple of the deviceʼs block size.
nx_block_count
uint64_t nx_block_count;
nx_features
uint64_t nx_features;
For the values used in this bit field, see Optional Container Feature Flags.
If your implementation doesnʼt implement an optional feature thatʼs in use, ignore that feature in this list and mount
the containerʼs volumes as usual.
nx_readonly_compatible_features
A bit field of the read-only compatible features being used by this container.
uint64_t nx_readonly_compatible_features;
For the values used in this bit field, see Read-Only Compatible Container Feature Flags.
If your implementation doesnʼt implement a read-only compatible feature thatʼs in use, mount the containerʼs volumes
as read-only.
nx_incompatible_features
uint64_t nx_incompatible_features;
For the values used in this bit field, see Incompatible Container Feature Flags.
If your implementation doesnʼt implement a read-only feature thatʼs in use, it must not mount the containerʼs volumes.
nx_uuid
uuid_t nx_uuid;
29
Container
nx_superblock_t
nx_next_oid
The next object identifier to be used for a new ephemeral or virtual object.
oid_t nx_next_oid;
nx_next_xid
xid_t nx_next_xid;
nx_xp_desc_blocks
uint32_t nx_xp_desc_blocks;
The highest bit of this number is used as a flag, as discussed in nx_xp_desc_base. Ignore that bit when accessing
this field as a count.
nx_xp_data_blocks
uint32_t nx_xp_data_blocks;
The highest bit of this number is used as a flag, as discussed in nx_xp_data_base. Ignore that bit when accessing
this field as a count.
nx_xp_desc_base
Either the base address of the checkpoint descriptor area or the physical object identifier of a tree that contains the
address information.
paddr_t nx_xp_desc_base;
If the highest bit of nx_xp_desc_blocks is zero, the checkpoint descriptor area is contiguous and this field contains
the address of the first block. Otherwise, the checkpoint descriptor area isnʼt contiguous and this field contains the
physical object identifier of a B-tree. The treeʼs keys are block offsets into the checkpoint descriptor area, and its
values are instances of prange_t that contain the fragmentʼs size and location.
nx_xp_data_base
Either the base address of the checkpoint data area or the physical object identifier of a tree that contains the address
information.
paddr_t nx_xp_data_base;
If the highest bit of nx_xp_data_blocks is zero, the checkpoint data area is contiguous and this field contains the
address of the first block. Otherwise, the checkpoint data area isnʼt contiguous and this field contains the object
identifier of a B-tree. The treeʼs keys are block offsets into the checkpoint data area, and its values are instances of
prange_t that contain the fragmentʼs size and location.
30
Container
nx_superblock_t
nx_xp_desc_next
uint32_t nx_xp_desc_next;
If the superblock is part of a checkpoint, this field must have a value. Otherwise, ignore the value of this field when
reading, and use zero as the value when creating a new instance. For example, this field has no meaning for the copy
of the superblock thatʼs stored in block zero.
nx_xp_data_next
uint32_t nx_xp_data_next;
If the superblock is part of a checkpoint, this field must have a value. Otherwise, ignore the value of this field when
reading, and use zero as the value when creating a new instance. For example, this field has no meaning for the copy
of the superblock thatʼs stored in block zero.
nx_xp_desc_index
The index of the first valid item in the checkpoint descriptor area.
uint32_t nx_xp_desc_index;
If the superblock is part of a checkpoint, this field must have a value. Otherwise, ignore the value of this field when
reading, and use zero as the value when creating a new instance. For example, this field has no meaning for the copy
of the superblock thatʼs stored in block zero.
nx_xp_desc_len
The number of blocks in the checkpoint descriptor area used by the checkpoint that this superblock belongs to.
uint32_t nx_xp_desc_len;
If the superblock is part of a checkpoint, this field must have a value. Otherwise, ignore the value of this field when
reading, and use zero as the value when creating a new instance. For example, this field has no meaning for the copy
of the superblock thatʼs stored in block zero.
nx_xp_data_index
The index of the first valid item in the checkpoint data area.
uint32_t nx_xp_data_index;
If the superblock is part of a checkpoint, this field must have a value. Otherwise, ignore the value of this field when
reading, and use zero as the value when creating a new instance. For example, this field has no meaning for the copy
of the superblock thatʼs stored in block zero.
nx_xp_data_len
The number of blocks in the checkpoint data area used by the checkpoint that this superblock belongs to.
uint32_t nx_xp_data_len;
31
Container
nx_superblock_t
If the superblock is part of a checkpoint, this field must have a value. Otherwise, ignore the value of this field when
reading, and use zero as the value when creating a new instance. For example, this field has no meaning for the copy
of the superblock thatʼs stored in block zero.
nx_spaceman_oid
oid_t nx_spaceman_oid;
nx_omap_oid
oid_t nx_omap_oid;
nx_reaper_oid
oid_t nx_reaper_oid;
nx_test_type
uint32_t nx_test_type;
This field never has a value other than zero on disk. If you find another value in production, file a bug against the Apple
File System implementation.
This field isnʼt reserved by Apple; non-Apple implementations of Apple File System can use it to store an object type
during testing.
nx_max_file_systems
uint32_t nx_max_file_systems;
To calculate this value, divide the size of the container by 512 MiB and round up. For example, a container with 1.3 GiB
of space can contain three volumes. This value must not be larger than the value of NX_MAX_FILE_SYSTEMS.
nx_fs_oid
oid_t nx_fs_oid[NX_MAX_FILE_SYSTEMS];
The objectsʼ types are all OBJECT_TYPE_BTREE and their subtypes are all OBJECT_TYPE_FSTREE.
32
Container
nx_superblock_t
nx_counters
uint64_t nx_counters[NX_NUM_COUNTERS];
These counters are primarily intended to help during development and debugging of Apple File System implementa-
tions. For the meaning of these counters, see nx_counter_id_t.
nx_blocked_out_prange
prange_t nx_blocked_out_prange;
This field is used with nx_evict_mapping_tree_oid while shrinking a partition. If nothing is currently blocked out,
the value of nx_blocked_out_prange.pr_block_count is zero and the value of nx_blocked_out_prange.
pr_start_paddr is ignored.
nx_evict_mapping_tree_oid
The physical object identifier of a tree used to keep track of objects that must be moved out of blocked-out storage.
oid_t nx_evict_mapping_tree_oid;
The keys in this tree are physical addresses of blocks that must be moved, and the values are instances of
evict_mapping_val_t that describe where the blocks are being moved to.
This identifier is valid only while shrinking a partition. First, the blocks to be removed from the partition are added to the
nx_blocked_out_prange field. Next, every object thatʼs stored in a blocked-out range is added to this tree. Finally,
every object in this tree has space allocated and is moved into the new space. Because the space manager honors
the blocked-out range, data is never moved from one blocked-out address to another address thatʼs also blocked out.
After all data has been removed from the blocked-out range and this tree is empty, the partition shrinks and the block
count of nx_blocked_out_prange is set to zero, which clears the field.
nx_flags
uint64_t nx_flags;
For the values used in this bit field, see Container Flags.
nx_efi_jumpstart
The physical object identifier of the object that contains EFI driver data extents.
paddr_t nx_efi_jumpstart;
33
Container
nx_superblock_t
nx_fusion_uuid
The universally unique identifier of the containerʼs Fusion set, or zero for non-Fusion containers.
uuid_t nx_fusion_uuid;
The hard drive and the solid-state drive each have a partition, which combine to make a single container. Each partition
has its own copy of the container superblock at block zero, and each copy has the same value for the low 127 bits of
this field. The highest bit is one for the Fusion setʼs main device and zero for the second-tier device.
nx_keylocker
prange_t nx_keylocker;
nx_ephemeral_info
uint64_t nx_ephemeral_info[NX_EPH_INFO_COUNT];
The first array entry records information about how the checkpoint data areaʼs size was chosen as follows:
The value of min_block_count depends on the size of the container. If the container is larger than 128 MiB, it takes
the value of NX_EPH_MIN_BLOCK_COUNT. Otherwise, it takes the value of spaceman_phys_t.sm_fq[SFQ_MAIN]
.sfq_tree_node_limit from the space manager.
nx_test_oid
oid_t nx_test_oid;
This field never has a value other than zero on disk. If you find another value in production, file a bug against the Apple
File System implementation.
This field isnʼt reserved by Apple; non-Apple implementations of Apple File System can use it to store an object iden-
tifier during testing.
nx_fusion_mt_oid
The physical object identifier of the Fusion middle tree (a B-tree mapping fusion_mt_key_t to fusion_mt_val_t),
or zero if for non-Fusion drives.
oid_t nx_fusion_mt_oid;
34
Container
nx_superblock_t
nx_fusion_wbc_oid
The ephemeral object identifier of the Fusion write-back cache state (fusion_wbc_phys_t), or zero for non-Fusion
drives.
oid_t nx_fusion_wbc_oid;
nx_fusion_wbc
The blocks used for the Fusion write-back cache area, or zero for non-Fusion drives.
prange_t nx_fusion_wbc;
nx_newest_mounted_version
Reserved.
uint64_t nx_newest_mounted_version;
Appleʼs implementation uses this field to record the newest version of the software that ever mounted the container.
Other implementations of the Apple file System must not modify this field.
This integer is understood as a fixed-point decimal number of the form aaaaaaa.bbb.ccc.ddd.eee where a is a
major version number and b, c, d, and e are minor versions.
nx_mkb_locker
prange_t nx_mkb_locker;
NX_MAGIC
This magic number was chosen because in hex dumps it appears as “NXSB”, which is an abbreviated form of NX
superblock.
NX_MAX_FILE_SYSTEMS
NX_EPH_INFO_COUNT
#define NX_EPH_INFO_COUNT 4
35
Container
Container Flags
NX_EPH_MIN_BLOCK_COUNT
The default minimum size, in blocks, for structures that contain ephemeral data.
#define NX_EPH_MIN_BLOCK_COUNT 8
This value is used when choosing the size for a new containerʼs checkpoint data area, and the value used is recorded
in the nx_ephemeral_info field.
NX_MAX_FILE_SYSTEM_EPH_STRUCTS
The number of structures that contain ephemeral data that a volume can have.
#define NX_MAX_FILE_SYSTEM_EPH_STRUCTS 4
This value is used when choosing the size for a new containerʼs checkpoint data area, and the value used is recorded
in the nx_ephemeral_info field.
NX_TX_MIN_CHECKPOINT_COUNT
The minimum number of checkpoints that can fit in the checkpoint data area.
#define NX_TX_MIN_CHECKPOINT_COUNT 4
This value is used when choosing the size for a new containerʼs checkpoint data area.
NX_EPH_INFO_VERSION_1
#define NX_EPH_INFO_VERSION_1 1
Container Flags
The flags used for general information about a container.
NX_RESERVED_1
Reserved.
36
Container
Optional Container Feature Flags
NX_RESERVED_2
Reserved.
Donʼt add this flag to a container. If this flag is set, preserve it when reading the container, and remove it when modi-
fying the container.
NX_CRYPTO_SW
If this flag is set, the crypto_id field on all instances of j_file_extent_val_t has a value of CRYPTO_SW_ID.
Note that a container that has no volumes never has this flag set, regardless of whether the container will use software
cryptography for new volumes. If you are creating a new volume in this scenario, determine whether to use software
or hardware cryptography by consulting the I/O Registry as discussed in IOKit Fundamentals.
NX_FEATURE_DEFRAG
NX_FEATURE_LCFD
Low-capacity Fusion Drive mode is enabled when the solid-state drive has a smaller capacity and so the cache must
be smaller.
NX_SUPPORTED_FEATURES_MASK
37
Container
Read-Only Compatible Container Feature Flags
These flags are used by the nx_readonly_compatible_features field of nx_superblock_t. There are cur-
rently none defined.
NX_SUPPORTED_ROCOMPAT_MASK
NX_INCOMPAT_VERSION1
The container uses version 1 of Apple File System, as implemented in macOS 10.12.
Important
Version 1 of the Apple File System was a prerelease thatʼs incompatible with later versions. This document
describes only version 2 and later.
NX_INCOMPAT_VERSION2
The container uses version 2 of Apple File System, as implemented in macOS 10.13 and iOS 10.3.
NX_INCOMPAT_FUSION
38
Container
Block and Container Sizes
NX_SUPPORTED_INCOMPAT_MASK
The block size for a container is defined by the nx_block_size field of nx_superblock_t.
NX_MINIMUM_BLOCK_SIZE
If you try to define a block size thatʼs too small, some data structures wonʼt be able to fit in a single block.
NX_DEFAULT_BLOCK_SIZE
NX_MAXIMUM_BLOCK_SIZE
If you try to define a block size thatʼs too large, parts of the block will be outside of the range of a 16-bit address.
NX_MINIMUM_CONTAINER_SIZE
This value is slightly less that the capacity of a floppy disk. For a container this size, statically allocated metadata
takes up about a third of the available space.
nx_counter_id_t
Indexes into a container superblockʼs array of counters.
39
Container
checkpoint_mapping_t
typedef enum {
NX_CNTR_OBJ_CKSUM_SET = 0,
NX_CNTR_OBJ_CKSUM_FAIL = 1,
NX_NUM_COUNTERS = 32
} nx_counter_id_t;
These values are used as indexes into the array stored in the nx_counters field of nx_superblock_t.
NX_CNTR_OBJ_CKSUM_SET
The number of times a checksum has been computed while writing objects to disk.
NX_CNTR_OBJ_CKSUM_SET = 0
NX_CNTR_OBJ_CKSUM_FAIL
The number of times an objectʼs checksum was invalid when reading from disk.
NX_CNTR_OBJ_CKSUM_FAIL = 1
NX_NUM_COUNTERS
NX_NUM_COUNTERS = 32
checkpoint_mapping_t
A mapping from an ephemeral object identifier to its physical address in the checkpoint data area.
struct checkpoint_mapping {
uint32_t cpm_type;
uint32_t cpm_subtype;
uint32_t cpm_size;
uint32_t cpm_pad;
oid_t cpm_fs_oid;
oid_t cpm_oid;
oid_t cpm_paddr;
};
typedef struct checkpoint_mapping checkpoint_mapping_t;
cpm_type
uint32_t cpm_type;
An object type is a 32-bit value: The low 16 bits indicate the type using the values listed in Object Types, and the high
16 bits are flags using the values listed in Object Type Flags.
This field has the same meaning and behavior as the o_type field of obj_phys_t.
40
Container
checkpoint_map_phys_t
cpm_subtype
uint32_t cpm_subtype;
Subtypes indicate the type of data stored in a data structure such as a B-tree. For example, a leaf node in a B-tree that
contains file-system records has a type of OBJECT_TYPE_BTREE_NODE and a subtype of OBJECT_TYPE_FSTREE.
This field has the same meaning and behavior as the o_subtype field of obj_phys_t.
cpm_size
uint32_t cpm_size;
cpm_pad
Reserved.
uint32_t cpm_pad;
Populate this field with zero when you create a new mapping, and preserve its value when you modify an existing
mapping.
cpm_fs_oid
The virtual object identifier of the volume that the object is associated with.
oid_t cpm_fs_oid;
cpm_oid
oid_t cpm_oid;
cpm_paddr
The address in the checkpoint data area where the object is stored.
oid_t cpm_paddr;
checkpoint_map_phys_t
A checkpoint-mapping block.
struct checkpoint_map_phys {
obj_phys_t cpm_o;
uint32_t cpm_flags;
41
Container
Checkpoint Flags
uint32_t cpm_count;
checkpoint_mapping_t cpm_map[];
};
If a checkpoint needs to store more mappings than a single block can hold, the checkpoint has multiple checkpoint-
mapping blocks stored contiguously in the checkpoint descriptor area. The last checkpoint-mapping block is marked
with the CHECKPOINT_MAP_LAST flag.
cpm_o
obj_phys_t cpm_o;
cpm_flags
A bit field that contains additional information about the list of checkpoint mappings.
uint32_t cpm_flags;
For the values used in this bit field, see Checkpoint Flags.
cpm_count
uint32_t cpm_count;
cpm_map
checkpoint_mapping_t cpm_map[];
Checkpoint Flags
The flags used by a checkpoint-mapping block.
CHECKPOINT_MAP_LAST
evict_mapping_val_t
A range of physical addresses that data is being moved into.
struct evict_mapping_val {
paddr_t dst_paddr;
uint64_t len;
} __attribute__((packed));
42
Container
evict_mapping_val_t
This data type is used by the evict-mapping tree, which is accessed through the nx_evict_mapping_tree_oid
field of nx_superblock_t.
dst_paddr
paddr_t dst_paddr;
len
uint64_t len;
43
Object Maps
An object map uses a B-tree to store a mapping from virtual object identifiers and transaction identifiers to the physical
addresses where those objects are stored. The keys in the B-tree are instances of omap_key_t and the values are
instances of paddr_t.
To access a virtual object using the object map, perform the following operations:
1. Determine which object map to use. Objects that are within a volume use that volumeʼs object map, and all
other objects use the containerʼs object map.
2. Locate the object map for the volume by reading the apfs_omap_oid field of apfs_superblock_t or the
nx_omap_oid field of nx_superblock_t.
3. Locate the B-tree for the object map by reading the om_tree_oid field of omap_phys_t.
4. Search the B-tree for a key whose object identifier is the same as the desired object identifier, and whose
transaction identifier is less than or equal to the desired transaction identifier. If there are multiple keys that
satisfy this test, use the key with the largest transaction identifier.
5. Using the table of contents entry, read the corresponding value for the key you found, which contains a physical
address.
For example, assume the object mapʼs B-tree contains the following mappings:
To access object 588 as of transaction 2300, you use the last entry — its object and transaction identifiers match
exactly — and read physical address 100.
To access object 588 as of transaction 2290, you use the second entry. Thereʼs no entry with the transaction identifier
2290, and 2202 is the largest transaction identifier in the object map thatʼs still less than 2290. That entry tells you
to read physical address 300.
omap_phys_t
An object map.
struct omap_phys {
obj_phys_t om_o;
uint32_t om_flags;
uint32_t om_snap_count;
uint32_t om_tree_type;
uint32_t om_snapshot_tree_type;
oid_t om_tree_oid;
oid_t om_snapshot_tree_oid;
xid_t om_most_recent_snap;
xid_t om_pending_revert_min;
44
Object Maps
omap_phys_t
xid_t om_pending_revert_max;
};
typedef struct omap_phys omap_phys_t;
om_o
obj_phys_t om_o;
om_flags
uint32_t om_flags;
For the values used in this bit field, see Object Map Flags.
om_tree_type
uint32_t om_tree_type;
om_tree_oid
The virtual object identifier of the tree being used for object mappings.
oid_t om_tree_oid;
om_snapshot_tree_oid
The virtual object identifier of the tree being used to hold snapshot information.
oid_t om_snapshot_tree_oid;
om_snapshot_tree_type
uint32_t om_snapshot_tree_type;
om_snap_count
uint32_t om_snap_count;
om_most_recent_snap
The transaction identifier of the most recent snapshot thatʼs stored in this object map.
xid_t om_most_recent_snap;
45
Object Maps
omap_key_t
om_pending_revert_min
xid_t om_pending_revert_min;
om_pending_revert_max
xid_t om_pending_revert_max;
omap_key_t
A key used to access an entry in the object map.
struct omap_key {
oid_t ok_oid;
xid_t ok_xid;
};
typedef struct omap_key omap_key_t;
ok_oid
oid_t ok_oid;
ok_xid
xid_t ok_xid;
omap_val_t
A value in the object map.
struct omap_val {
uint32_t ov_flags;
uint32_t ov_size;
paddr_t ov_paddr;
};
typedef struct omap_val omap_val_t;
ov_flags
uint32_t ov_flags;
For the values used in this bit field, see Object Map Value Flags.
46
Object Maps
omap_snapshot_t
ov_size
uint32_t ov_size;
This value must be a multiple of the containerʼs logical block size. If the object is smaller than one logical block, the
value of this field is the size of one logical block.
ov_paddr
paddr_t ov_paddr;
omap_snapshot_t
Information about a snapshot of an object map.
struct omap_snapshot {
uint32_t oms_flags;
uint32_t oms_pad;
oid_t oms_oid;
};
typedef struct omap_snapshot omap_snapshot_t;
When accessing or storing a snapshot in the snapshot tree, use the transaction identifier as the key. This structure is
the value stored in a snapshot tree.
oms_flags
uint32_t oms_flags;
For the values used in this bit field, see Snapshot Flags.
oms_pad
Reserved.
uint32_t oms_pad;
Populate this field with zero when you create a new snapshot, and preserve its value when you modify an existing
snapshot.
oms_oid
Reserved.
oid_t oms_oid;
47
Object Maps
Object Map Value Flags
Populate this field with zero when you create a new snapshot, and preserve its value when you modify an existing
snapshot.
OMAP_VAL_DELETED
OMAP_VAL_SAVED
This flag is used only on mappings in an object map thatʼs manually managed. In the current Apple implementation,
itʼs never used.
OMAP_VAL_ENCRYPTED
OMAP_VAL_NOHEADER
OMAP_VAL_CRYPTO_GENERATION
During the transition from an old encryption configuration to a new one, not all objects have been reencrypted using
the new configuration. When the encryption configuration is changed, the object mapʼs flag is toggled. After an object
is reencrypted, the objectʼs flag is also toggled.
If this flag doesnʼt match the flag on the object map, the encryption configuration has changed, but the object hasnʼt
been reencrypted yet. Use the previous encryption configuration to decrypt the object.
48
Object Maps
Snapshot Flags
Snapshot Flags
The flags used to describe the state of a snapshot.
OMAP_SNAPSHOT_DELETED
OMAP_SNAPSHOT_REVERTED
OMAP_MANUALLY_MANAGED
This flag must be set on the containerʼs object map and is invalid on a volumeʼs object map.
OMAP_ENCRYPTING
OMAP_DECRYPTING
49
Object Maps
Object Map Constants
OMAP_KEYROLLING
A transition is in progress from encrypted storage using an old key to encrypted storage using a new key.
OMAP_CRYPTO_GENERATION
For information about how this flag is used to track the old and new encryption configuration, see OMAP_VAL_
CRYPTO_GENERATION, which is used by the ov_flags field of omap_val_t.
OMAP_VALID_FLAGS
OMAP_MAX_SNAP_COUNT
#define OMAP_REAP_PHASE_MAP_TREE 1
#define OMAP_REAP_PHASE_SNAPSHOT_TREE 2
OMAP_REAP_PHASE_MAP_TREE
#define OMAP_REAP_PHASE_MAP_TREE 1
OMAP_REAP_PHASE_SNAPSHOT_TREE
#define OMAP_REAP_PHASE_SNAPSHOT_TREE 2
50
Volumes
A volume contains a file system, the files and metadata that make up that file system, and various supporting data
structures like an object map.
apfs_superblock_t
A volume superblock.
struct apfs_superblock {
obj_phys_t apfs_o;
uint32_t apfs_magic;
uint32_t apfs_fs_index;
uint64_t apfs_features;
uint64_t apfs_readonly_compatible_features;
uint64_t apfs_incompatible_features;
uint64_t apfs_unmount_time;
uint64_t apfs_fs_reserve_block_count;
uint64_t apfs_fs_quota_block_count;
uint64_t apfs_fs_alloc_count;
wrapped_meta_crypto_state_t apfs_meta_crypto;
uint32_t apfs_root_tree_type;
uint32_t apfs_extentref_tree_type;
uint32_t apfs_snap_meta_tree_type;
oid_t apfs_omap_oid;
oid_t apfs_root_tree_oid;
oid_t apfs_extentref_tree_oid;
oid_t apfs_snap_meta_tree_oid;
xid_t apfs_revert_to_xid;
oid_t apfs_revert_to_sblock_oid;
uint64_t apfs_next_obj_id;
uint64_t apfs_num_files;
uint64_t apfs_num_directories;
uint64_t apfs_num_symlinks;
uint64_t apfs_num_other_fsobjects;
uint64_t apfs_num_snapshots;
51
Volumes
apfs_superblock_t
uint64_t apfs_total_blocks_alloced;
uint64_t apfs_total_blocks_freed;
uuid_t apfs_vol_uuid;
uint64_t apfs_last_mod_time;
uint64_t apfs_fs_flags;
apfs_modified_by_t apfs_formatted_by;
apfs_modified_by_t apfs_modified_by[APFS_MAX_HIST];
uint8_t apfs_volname[APFS_VOLNAME_LEN];
uint32_t apfs_next_doc_id;
uint16_t apfs_role;
uint16_t reserved;
xid_t apfs_root_to_xid;
oid_t apfs_er_state_oid;
uint64_t apfs_cloneinfo_id_epoch;
uint64_t apfs_cloneinfo_xid;
oid_t apfs_snap_meta_ext_oid;
uuid_t apfs_volume_group_id;
oid_t apfs_integrity_meta_oid;
oid_t apfs_fext_tree_oid;
uint32_t apfs_fext_tree_type;
uint32_t reserved_type;
oid_t reserved_oid;
};
apfs_o
obj_phys_t apfs_o;
apfs_magic
A number that can be used to verify that youʼre reading an instance of apfs_superblock_t.
52
Volumes
apfs_superblock_t
uint32_t apfs_magic;
apfs_fs_index
The index of the object identifier for this volumeʼs file system in the containerʼs array of file systems.
uint32_t apfs_fs_index
When a volume is being deleted, itʼs removed from the containerʼs array of volumes before apfs_superblock_t
object is destroyed. If you read this field of a volume thatʼs being deleted, the specified entry in the array might have
already been reused for another volume.
apfs_features
uint64_t apfs_features;
For the values used in this bit field, see Optional Volume Feature Flags.
If your implementation doesnʼt support an optional feature thatʼs in use, ignore that feature in this list and mount the
volume as usual.
apfs_readonly_compatible_features
A bit field of the read-only compatible features being used by this volume.
uint64_t apfs_readonly_compatible_features;
For the values used in this bit field, see Read-Only Compatible Volume Feature Flags.
If your implementation doesnʼt support a read-only compatible feature thatʼs in use, mount the volume as read-only.
apfs_incompatible_features
uint64_t apfs_incompatible_features;
For the values used in this bit field, see Incompatible Volume Feature Flags.
If your implementation doesnʼt support a backward-incompatible feature thatʼs in use, it must not mount the volume.
apfs_unmount_time
uint64_t apfs_unmount_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
53
Volumes
apfs_superblock_t
apfs_fs_reserve_block_count
The number of blocks that have been reserved for this volume to allocate.
uint64_t apfs_fs_reserve_block_count;
apfs_fs_quota_block_count
uint64_t apfs_fs_quota_block_count;
apfs_fs_alloc_count
The number of blocks currently allocated for this volumeʼs file system.
uint64_t apfs_fs_alloc_count;
apfs_meta_crypto
Information about the key used to encrypt metadata for this volume.
wrapped_meta_crypto_state_t apfs_meta_crypto;
On devices running macOS, the volume encryption key (VEK) is used to encrypt the metadata, as discussed in Ac-
cessing Encrypted Objects.
apfs_root_tree_type
uint32_t apfs_root_tree_type
The value is typically OBJ_VIRTUAL | OBJECT_TYPE_BTREE, with a subtype of OBJECT_TYPE_FSTREE. For pos-
sible values, see Object Types.
apfs_extentref_tree_type
uint32_t apfs_extentref_tree_type
apfs_snap_meta_tree_type
uint32_t apfs_snap_meta_tree_type
54
Volumes
apfs_superblock_t
apfs_omap_oid
oid_t apfs_omap_oid;
apfs_root_tree_oid
oid_t apfs_root_tree_oid;
apfs_extentref_tree_oid
oid_t apfs_extentref_tree_oid;
When a snapshot is created, the current extent-reference tree is moved to the snapshot. A new, empty, extent-
reference tree is created and its object identifier becomes the new value of this field.
apfs_snap_meta_tree_oid
oid_t apfs_snap_meta_tree_oid;
apfs_revert_to_xid
The transaction identifier of a snapshot that the volume will revert to.
xid_t apfs_revert_to_xid;
When mounting a volume, if the value of this field nonzero, revert to the specified snapshot by deleting all snapshots
after the specified transaction identifier and deleting the current state, and then setting this field to zero.
apfs_revert_to_sblock_oid
The physical object identifier of a volume superblock that the volume will revert to.
oid_t apfs_revert_to_sblock_oid;
When mounting a volume, if the apfs_revert_to_xid field is nonzero, ignore the value of this field. Otherwise,
revert to the specified volume superblock.
apfs_next_obj_id
The next identifier that will be assigned to a file-system object in this volume.
uint64_t apfs_next_obj_id;
55
Volumes
apfs_superblock_t
apfs_num_files
uint64_t apfs_num_files;
apfs_num_directories
uint64_t apfs_num_directories;
apfs_num_symlinks
uint64_t apfs_num_symlinks;
apfs_num_other_fsobjects
uint64_t apfs_num_other_fsobjects;
The value of this field includes all files that arenʼt included in the apfs_num_symlinks, apfs_num_directories,
or apfs_num_files fields.
apfs_num_snapshots
uint64_t apfs_num_snapshots;
apfs_total_blocks_alloced
The total number of blocks that have been allocated by this volume.
uint64_t apfs_total_blocks_alloced;
The value of this field increases when blocks are allocated, but isnʼt modified when theyʼre freed. If the volume doesnʼt
contain any files, the value of this field matches apfs_total_blocks_freed.
apfs_total_blocks_freed
The total number of blocks that have been freed by this volume.
uint64_t apfs_total_blocks_freed;
The value of this field isnʼt modified when blocks are allocated, but increases when theyʼre freed. If the volume doesnʼt
contain any files, the value of this field matches apfs_total_blocks_alloced.
56
Volumes
apfs_superblock_t
apfs_vol_uuid
uuid_t apfs_vol_uuid;
apfs_last_mod_time
uint64_t apfs_last_mod_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
apfs_fs_flags
uint64_t apfs_fs_flags;
For the values used in this bit field, see Volume Flags.
apfs_formatted_by
apfs_modified_by_t apfs_formatted_by;
apfs_modified_by
apfs_modified_by_t apfs_modified_by[APFS_MAX_HIST]
The newest element in this array is stored at index zero. To update this field when you modify a volume, move each
element to the index thatʼs larger by one, and then write the new modification information. When you create a new
volume, fill the arrayʼs memory with zeros.
If the implementationʼs information is already the last entry in this field, you can update the field as usual (creating a
duplicate), or leave the fieldʼs value unmodified. Both behaviors are permitted.
apfs_volname
uint8_t apfs_volname[APFS_VOLNAME_LEN]
57
Volumes
apfs_superblock_t
apfs_next_doc_id
uint32_t apfs_next_doc_id
After assigning a new document identifier, increment this field by one. Valid document identifiers are greater than
MIN_DOC_ID and less than UINT32_MAX - 1. If a new document identifier isnʼt available, thatʼs an unrecoverable
error. Identifiers arenʼt allowed to restart from one or to be reused.
apfs_role
uint16_t apfs_role
reserved
Reserved.
uint16_t reserved
Populate this field with zero when you create a new volume, and preserve its value when you modify an existing volume.
apfs_root_to_xid
The transaction identifier of the snapshot to root from, or zero to root normally.
xid_t apfs_root_to_xid;
apfs_er_state_oid
The current state of encryption or decryption for a drive thatʼs being encrypted or decrypted, or zero if no encryption
change is in progress.
oid_t apfs_er_state_oid;
apfs_cloneinfo_id_epoch
The largest object identifier used by this volume at the time INODE_WAS_EVER_CLONED started storing valid infor-
mation.
uint64_t apfs_cloneinfo_id_epoch;
If the value of this field is zero, all information stored using INODE_WAS_EVER_CLONED is valid. For information about
how to this identifier is used, see INODE_WAS_EVER_CLONED.
This field was added to this data structure for macOS 10.13.3. Older implementations of Apple File System store zero in
this field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the structure.
Because zero is a valid value for this field, check the value of apfs_cloneinfo_xid – if that field is also zero, the
structure was created by an older implementation.
58
Volumes
apfs_superblock_t
apfs_cloneinfo_xid
uint64_t apfs_cloneinfo_xid;
When unmounting a volume, the value of this field is set to the latest transaction identifier, the same as the
apfs_modified_by field. For information about how to this identifier is used, see INODE_WAS_EVER_CLONED.
This field was added to this data structure for macOS 10.13.3. Older implementations of Apple File System store
zero in this field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the
structure.
apfs_snap_meta_ext_oid
oid_t apfs_snap_meta_ext_oid;
This field was added to this data structure for macOS 10.15. Older implementations of Apple File System store zero in
this field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the structure.
apfs_volume_group_id
uuid_t apfs_volume_group_id;
If the volume doesnʼt belong to a volume group, the value of this field is zero and the APFS_FEATURE_VOLGRP_
SYSTEM_INO_SPACE flag must not be set. Otherwise, the APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE flag
must be set and this field must have a nonzero value.
This field was added to this data structure for macOS 10.15. Older implementations of Apple File System store zero in
this field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the structure.
apfs_integrity_meta_oid
oid_t apfs_integrity_meta_oid;
If the value of this field is nonzero, the APFS_INCOMPAT_SEALED_VOLUME flag must also be set.
This field was added to this data structure for macOS 11. Older implementations of Apple File System store zero in this
field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the structure.
apfs_fext_tree_oid
oid_t apfs_fext_tree_oid;
If the value of this field is nonzero, the APFS_INCOMPAT_SEALED_VOLUME flag must also be set.
This field was added to this data structure for macOS 11. Older implementations of Apple File System store zero in this
field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the structure.
59
Volumes
apfs_modified_by_t
apfs_fext_tree_type
uint32_t apfs_fext_tree_type;
This field was added to this data structure for macOS 11. Older implementations of Apple File System store zero in this
field when initializing an instance of the structure, and they preserve the fieldʼs value when modifying the structure.
reserved_type
Reserved.
uint32_t reserved_type;
reserved_oid
Reserved.
oid_t reserved_oid;
APFS_MAGIC
This magic number was chosen because in hex dumps it appears as “APSB”, which is an abbreviated form of APFS
superblock.
APFS_MAX_HIST
#define APFS_MAX_HIST 8
APFS_VOLNAME_LEN
The maximum length of the volume name stored in the apfs_volname field.
apfs_modified_by_t
Information about a program that modified the volume.
struct apfs_modified_by {
uint8_t id[APFS_MODIFIED_NAMELEN];
uint64_t timestamp;
xid_t last_xid;
};
60
Volumes
Volume Flags
#define APFS_MODIFIED_NAMELEN 32
id
uint8_t id[APFS_MODIFIED_NAMELEN];
timestamp
uint64_t timestamp;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
last_xid
xid_t last_xid;
Volume Flags
The flags used to indicate volume status.
61
Volumes
Volume Flags
| APFS_FS_ONEKEY)
APFS_FS_UNENCRYPTED
APFS_FS_RESERVED_2
Reserved.
APFS_FS_RESERVED_4
Reserved.
APFS_FS_ONEKEY
Files on the volume are all encrypted using the volume encryption key (VEK).
This flag is used only on devices running macOS; devices running iOS always use per-file encryption keys. When this
flag is set, several encryption-related data structures store different information, as discussed in Accessing Encrypted
Objects.
APFS_FS_SPILLEDOVER
The volume has run out of allocated space on the solid-state drive.
APFS_FS_RUN_SPILLOVER_CLEANER
The volume has spilled over and the spillover cleaner must be run.
APFS_FS_ALWAYS_CHECK_EXTENTREF
The volumeʼs extent reference tree is always consulted when deciding whether to overwrite an extent.
62
Volumes
Volume Roles
APFS_FS_RESERVED_80
Reserved.
APFS_FS_RESERVED_100
Reserved.
APFS_FS_FLAGS_VALID_MASK
APFS_FS_CRYPTOFLAGS
Volume Roles
The values used to indicate a volumeʼs roles.
63
Volumes
Volume Roles
#define APFS_VOLUME_ENUM_SHIFT 6
These values are used by the apfs_role field of apfs_superblock_t. A volume has at most one role.
For historical reasons, the underlying values of these constants have two variations. The roles whose constants use
only the six least significant bits and the APFS_VOL_ROLE_DATA and APFS_VOL_ROLE_BASEBAND roles are sup-
ported by all versions of macOS and iOS. The remaining roles that are stored using the ten most significant bits are
supported only by devices running macOS 10.15, iOS 13, and later.
APFS_VOL_ROLE_NONE
A volume whose role doesnʼt have a constant defined doesnʼt have any flags set.
APFS_VOL_ROLE_SYSTEM
The file system for the system volume that contains the running OS is normally mounted at /. On devices running iOS
and macOS 10.15 or later, the system volume is mounted read-only.
See also APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE, which is used to mount the system and user data as a
single user-visible volume.
APFS_VOL_ROLE_USER
APFS_VOL_ROLE_RECOVERY
APFS_VOL_ROLE_VM
64
Volumes
Volume Roles
APFS_VOL_ROLE_PREBOOT
APFS_VOL_ROLE_INSTALLER
For example, the installer writes log files to this volume during the installation process.
APFS_VOL_ROLE_DATA
This role is used only on devices running iOS and macOS 10.15 or later. It contains both user data and mutable system
data. Immutable system data is stored on the volume with the APFS_VOL_ROLE_SYSTEM flag.
See also APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE, which is used to mount the system and user data as a
single user-visible volume.
APFS_VOL_ROLE_BASEBAND
APFS_VOL_ROLE_UPDATE
APFS_VOL_ROLE_XART
APFS_VOL_ROLE_HARDWARE
65
Volumes
Volume Roles
APFS_VOL_ROLE_BACKUP
APFS_VOL_ROLE_RESERVED_7
Reserved.
APFS_VOL_ROLE_RESERVED_8
Reserved.
APFS_VOL_ROLE_ENTERPRISE
For more information, see Managing Devices & Corporate Data on iOS.
APFS_VOL_ROLE_RESERVED_10
Reserved.
APFS_VOL_ROLE_PRELOGIN
This role is used only on devices running macOS. The prelogin volume lets the system boot to the login screen, at
which point the user can log in and the userʼs password can be used to mount encrypted volumes.
APFS_VOLUME_ENUM_SHIFT
The bit shift used to separate the old and new enumeration cases.
#define APFS_VOLUME_ENUM_SHIFT 6
66
Volumes
Optional Volume Feature Flags
APFS_FEATURE_DEFRAG_PRERELEASE
Reserved.
Warning
This flag enabled a prerelease version of the defragmentation system in macOS 10.13 versions. Itʼs ignored by
macOS 10.13.6 and later.
APFS_FEATURE_HARDLINK_MAP_RECORDS
APFS_FEATURE_DEFRAG
APFS_FEATURE_STRICTATIME
This volume updates file access times every time the file is read.
67
Volumes
Read-Only Compatible Volume Feature Flags
If this flag is set, the access_time field of j_inode_val_t is updated every time the file is read. Otherwise, that
field is updated when the file is read, but only if its value is prior to the timestamp stored in the mod_time field.
APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE
This volume supports mounting a system and data volume as a single user-visible volume.
This feature is used by macOS 10.15 and later to combine a read-only system volume with its corresponding
read-write user data volume. Both volumes have the same value for the apfs_volume_group_id field of apfs_
superblock_t, which indicates they form a volume group.
If this flag is set, inode numbers on those volumes are assigned as follows: The volume whose role is APFS_VOL_
ROLE_DATA uses inode numbers less than UNIFIED_ID_SPACE_MARK, and the volume whose role is APFS_VOL_
ROLE_SYSTEM uses inode numbers UNIFIED_ID_SPACE_MARK and larger. The first 16 inode numbers for both the
system and data volume are reserved, as described in Inode Numbers.
APFS_SUPPORTED_FEATURES_MASK
These flags are used by the apfs_readonly_compatible_features field of apfs_superblock_t. There are
currently none defined.
APFS_SUPPORTED_ROCOMPAT_MASK
68
Volumes
Incompatible Volume Feature Flags
APFS_INCOMPAT_CASE_INSENSITIVE
APFS_INCOMPAT_DATALESS_SNAPS
APFS_INCOMPAT_ENC_ROLLED
APFS_INCOMPAT_NORMALIZATION_INSENSITIVE
Normalization insensitivity is part of hashing filenames, as described in the name_len_and_hash field of j_drec_
hashed_key_t.
APFS_INCOMPAT_INCOMPLETE_RESTORE
This volume is being restored, or a restore operation to this volume was uncleanly aborted.
APFS_INCOMPAT_SEALED_VOLUME
69
Volumes
Incompatible Volume Feature Flags
APFS_INCOMPAT_RESERVED_40
Reserved.
APFS_SUPPORTED_INCOMPAT_MASK
70
File-System Objects
A file-system object stores information about a part of the file system, like a directory or a file on disk. These objects
are stored as one or more records. For example, the file-system object for a directory that contains two files is stored
as three records: a record of type APFS_TYPE_INODE for the inode, and two records of type APFS_TYPE_DIR_REC
for the directory entries. This record-based method of storing file-system objects helps make efficient use of disk
space.
File-system records are stored as key/value pairs in a B-tree. The key contains information, like the object identifier and
the record type, used to look up a record. Keys begin with an instance of j_key_t, and many records use j_key_t
as their entire key.
For sorting file-system records — for example, to keep them ordered in a B-tree — the following comparison rules are
used:
3. For extended attribute records and directory entry records, compare the names lexicographically:
j_drec_key_t.name
Because all of the records for a file-system object have the same object identifier, all of the records that make up a
single object are sorted next to each other.
The relationship between file-system objects and the records theyʼre made up from is as follows:
Files
• APFS_TYPE_INODE Required
• APFS_TYPE_CRYPTO_STATE
• APFS_TYPE_DSTREAM_ID
• APFS_TYPE_EXTENT
• APFS_TYPE_FILE_EXTENT
• APFS_TYPE_SIBLING_LINK
• APFS_TYPE_XATTR
Directories
• APFS_TYPE_INODE Required
• APFS_TYPE_CRYPTO_STATE
• APFS_TYPE_DIR_REC
• APFS_TYPE_DIR_STATS
• APFS_TYPE_XATTR
Symbolic Links
• APFS_TYPE_INODE Required
• APFS_TYPE_XATTR Required
71
File-System Objects
j_key_t
• APFS_TYPE_CRYPTO_STATE
• APFS_TYPE_DSTREAM_ID
• APFS_TYPE_EXTENT
• APFS_TYPE_FILE_EXTENT
There must be an extended attribute whose name is SYMLINK_EA_NAME and whose value is the path to the target
file.
Snapshots
• APFS_TYPE_SNAP_METADATA Required
• APFS_TYPE_SNAP_NAME Required
• APFS_TYPE_CRYPTO_STATE
• APFS_TYPE_EXTENT
Sibling Maps
• APFS_TYPE_SIBLING_MAP Required
Tip
To simplify manipulating file-system objects, define custom types that combine the key and value of a record,
and custom types that combine the objectʼs records.
j_key_t
A header used at the beginning of all file-system keys.
struct j_key {
uint64_t obj_id_and_type;
} __attribute__((packed));
typedef struct j_key j_key_t;
All file-system objects have a key that begins with this information. The key for some object types have additional
fields that follow this header, and other object types use j_key_t as their entire key.
The following record types use this structure as their key without adding any additional fields:
obj_id_and_type
A bit field that contains the objectʼs identifier and its type.
uint64_t obj_id_and_type;
72
File-System Objects
j_inode_key_t
The objectʼs identifier is a uint64_t value accessed as obj_id_and_type & OBJ_ID_MASK. The objectʼs type
is a uint8_t value accessed as (obj_id_and_type & OBJ_TYPE_MASK) >> OBJ_TYPE_SHIFT. The objectʼs
type is one of the constants defined by j_obj_types.
OBJ_ID_MASK
OBJ_TYPE_MASK
OBJ_TYPE_SHIFT
#define OBJ_TYPE_SHIFT 60
SYSTEM_OBJ_ID_MARK
In a volume group, objects with an identifier less than this number are part of the data volume, and objects with an
identifier greater than or equal to this number are part of the system volume.
j_inode_key_t
The key half of a directory-information record.
struct j_inode_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_inode_key_t j_inode_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier, also known as its inode number. The type in
the header is always APFS_TYPE_INODE.
j_inode_val_t
The value half of an inode record.
73
File-System Objects
j_inode_val_t
struct j_inode_val {
uint64_t parent_id;
uint64_t private_id;
uint64_t create_time;
uint64_t mod_time;
uint64_t change_time;
uint64_t access_time;
uint64_t internal_flags;
union {
int32_t nchildren;
int32_t nlink;
};
cp_key_class_t default_protection_class;
uint32_t write_generation_counter;
uint32_t bsd_flags;
uid_t owner;
gid_t group;
mode_t mode;
uint16_t pad1;
uint64_t uncompressed_size;
uint8_t xfields[];
} __attribute__((packed));
typedef struct j_inode_val j_inode_val_t;
parent_id
The identifier of the file system record for the parent directory.
uint64_t parent_id;
private_id
uint64_t private_id;
This identifier appears in the owning_obj_id field of j_phys_ext_val_t records that describe the extents where
the data is stored.
For an inode that doesnʼt have data, the value of this field is the file-system objectʼs identifier.
74
File-System Objects
j_inode_val_t
create_time
uint64_t create_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
mod_time
uint64_t mod_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
change_time
uint64_t change_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
access_time
uint64_t access_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
internal_flags
uint64_t internal_flags;
nchildren
int32_t nchildren;
75
File-System Objects
j_inode_val_t
nlink
int32_t nlink;
Inodes with multiple hard links — as indicated by a value greater than one in this field — have additional invariants:
• The parent_id field refers to the parent directory of the primary link.
default_protection_class
cp_key_class_t default_protection_class;
Files in this directory that have a protection class of PROTECTION_CLASS_DIR_NONE use the directoryʼs default
protection class.
write_generation_counter
A monotonically increasing counter thatʼs incremented each time this inode or its data is modified.
uint32_t write_generation_counter;
bsd_flags
uint32_t bsd_flags;
For information about these flags, see the chflags(2) man page and the <sys/stat.h> header file.
owner
uid_t owner;
group
gid_t group;
76
File-System Objects
j_inode_val_t
mode
mode_t mode;
pad1
Reserved.
uint16_t pad1;
Populate this field with zero when you create a new inode, and preserve its value when you modify an existing inode.
uncompressed_size
uint64_t uncompressed_size;
This field is populated only for files that have the INODE_HAS_UNCOMPRESSED_SIZE flag set on the internal_
flags field.
For files that donʼt have the flag set, this field is treated as padding: Populate this field with zero when you create a
new inode, and preserve its value when you modify an existing inode.
xfields
uint8_t xfields[];
This location on disk contains several pieces of data that have variable sizes. For information about reading extended
fields, see Extended Fields.
uid_t
A user identifier.
gid_t
A group identifier.
77
File-System Objects
j_drec_key_t
j_drec_key_t
The key half of a directory entry record.
struct j_drec_key {
j_key_t hdr;
uint16_t name_len;
uint8_t name[0];
} __attribute__((packed));
typedef struct j_drec_key j_drec_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always APFS_TYPE_
DIR_REC.
name_len_and_hash
The length of the name, including the final null character (U+0000).
uint32_t name_len_and_hash;
name
uint8_t name[0];
j_drec_hashed_key_t
The key half of a directory entry record, including a precomputed hash of its name.
struct j_drec_hashed_key {
j_key_t hdr;
uint32_t name_len_and_hash;
uint8_t name[0];
} __attribute__((packed));
typedef struct j_drec_hashed_key j_drec_hashed_key_t;
hdr
j_key_t hdr;
78
File-System Objects
j_drec_val_t
name_len_and_hash
uint32_t name_len_and_hash;
The length is a 10-bit unsigned integer, accessed as name_len_and_hash & J_DREC_LEN_MASK. The length in-
cludes the final null character (U+0000).
The hash is an unsigned 22-bit integer, accessed as (name_len_and_hash & J_DREC_HASH_MASK) >>
J_DREC_HASH_SHIFT. The hash is computed as follows:
If you implement your own CRC function, rather than calling one from a library, you can omit both the complement
operation thatʼs part of computing a CRC and the complement operation in the instructions above.
name
uint8_t name[0];
J_DREC_LEN_MASK
J_DREC_HASH_MASK
J_DREC_HASH_SHIFT
#define J_DREC_HASH_SHIFT 10
j_drec_val_t
The value half of a directory entry record.
struct j_drec_val {
uint64_t file_id;
uint64_t date_added;
uint16_t flags;
79
File-System Objects
j_dir_stats_key_t
uint8_t xfields[];
} __attribute__((packed));
typedef struct j_drec_val j_drec_val_t;
file_id
uint64_t file_id;
date_added
The time that this directory entry was added to the directory.
uint64_t date_added;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds. Itʼs not updated when modifying the directory entry — for example, by renaming a file without moving it to
a different directory.
flags
uint16_t flags;
The bits that are set in DREC_TYPE_MASK store the inodeʼs file type, and the remaining bits are reserved. Populate the
reserved bits with zeros when you create a new directory entry, and preserve their values when you modify an existing
directory entry.
xfields
uint8_t xfields[];
This location on disk contains several pieces of data that have variable sizes. For information about reading extended
fields, see Extended Fields.
j_dir_stats_key_t
The key half of a directory-information record.
struct j_dir_stats_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_dir_stats_key j_dir_stats_key_t;
80
File-System Objects
j_dir_stats_val_t
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always
APFS_TYPE_DIR_REC.
j_dir_stats_val_t
The value half of a directory-information record.
struct j_dir_stats_val {
uint64_t num_children;
uint64_t total_size;
uint64_t chained_key;
uint64_t gen_count;
} __attribute__((packed));
typedef struct j_dir_stats_val j_dir_stats_val_t;
num_children
uint64_t num_children;
total_size
The total size, in bytes, of all the files stored in this directory and all of this directoryʼs descendants.
uint64_t total_size;
Hard links contribute to the total_size of every directory they appear in.
chained_key
uint64_t chained_key;
gen_count
A monotonically increasing counter thatʼs incremented each time this inode or any of its children is modified.
uint64_t gen_count;
Modifying the contents of a file requires updating the inodeʼs modification time and write generation, which means
this counter must be incremented for the directory that contains the file.
81
File-System Objects
j_xattr_key_t
j_xattr_key_t
The key half of an extended attribute record.
struct j_xattr_key {
j_key_t hdr;
uint16_t name_len;
uint8_t name[0];
} __attribute__((packed));
typedef struct j_xattr_key j_xattr_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always
APFS_TYPE_XATTR.
name_len
The length of the extended attributeʼs name, including the final null character (U+0000).
uint16_t name_len;
name
uint8_t name[0];
j_xattr_val_t
The value half of an extended attribute record.
struct j_xattr_val {
uint16_t flags;
uint16_t xdata_len;
uint8_t xdata[0];
} __attribute__((packed));
typedef struct j_xattr_val j_xattr_val_t;
flags
uint16_t flags;
For the values used in this bit field, see j_xattr_flags. Either the XATTR_DATA_EMBEDDED or XATTR_DATA_
STREAM flag must be set.
82
File-System Objects
j_xattr_val_t
xdata_len
uint16_t xdata_len;
If the XATTR_DATA_EMBEDDED flag is set, this field is the length of the data in the xdata field. Otherwise, this field
is ignored.
xdata
The extended attribute data or the identifier of a data stream that contains the data.
uint8_t xdata[0];
If the XATTR_DATA_EMBEDDED flag is set, the extended attribute data is stored directly in this field. Otherwise, this
field contains the identifier (uint64_t) for a data stream record that stores the extended attribute data. See also
j_xattr_dstream_t.
83
File-System Constants
File-system objects use several groups of constants to define values for record types, reserved inode numbers, and
flags and bit masks used in bit fields.
j_obj_types
The type of a file-system record.
typedef enum {
APFS_TYPE_ANY = 0,
APFS_TYPE_SNAP_METADATA = 1,
APFS_TYPE_EXTENT = 2,
APFS_TYPE_INODE = 3,
APFS_TYPE_XATTR = 4,
APFS_TYPE_SIBLING_LINK = 5,
APFS_TYPE_DSTREAM_ID = 6,
APFS_TYPE_CRYPTO_STATE = 7,
APFS_TYPE_FILE_EXTENT = 8,
APFS_TYPE_DIR_REC = 9,
APFS_TYPE_DIR_STATS = 10,
APFS_TYPE_SNAP_NAME = 11,
APFS_TYPE_SIBLING_MAP = 12,
APFS_TYPE_FILE_INFO = 13,
APFS_TYPE_MAX_VALID = 13,
APFS_TYPE_MAX = 15,
APFS_TYPE_INVALID = 15,
} j_obj_types;
This value is stored in the type bits of a j_key_t structureʼs obj_id_and_type field.
APFS_TYPE_ANY
APFS_TYPE_ANY = 0
This enumeration case is used only in search queries and in tests when iterating over objects. Itʼs not valid as the type
of a file-system object.
APFS_TYPE_SNAP_METADATA
APFS_TYPE_SNAP_METADATA = 1
84
File-System Constants
j_obj_types
APFS_TYPE_EXTENT
APFS_TYPE_EXTENT = 2
APFS_TYPE_INODE
An inode.
APFS_TYPE_INODE = 3
APFS_TYPE_XATTR
An extended attribute.
APFS_TYPE_XATTR = 4
APFS_TYPE_SIBLING_LINK
A mapping from an inode to hard links that the inode is the target of.
APFS_TYPE_SIBLING_LINK = 5
APFS_TYPE_DSTREAM_ID
A data stream.
APFS_TYPE_DSTREAM_ID = 6
APFS_TYPE_CRYPTO_STATE
APFS_TYPE_CRYPTO_STATE = 7
The key is an instance of j_crypto_key_t and the value is an instance of j_crypto_val_t. This object type is
used only by iOS devices, except for a placeholder object whose identifier is always CRYPTO_SW_ID.
APFS_TYPE_FILE_EXTENT
APFS_TYPE_FILE_EXTENT = 8
85
File-System Constants
j_obj_types
APFS_TYPE_DIR_REC
A directory entry.
APFS_TYPE_DIR_REC = 9
APFS_TYPE_DIR_STATS
APFS_TYPE_DIR_STATS = 10
APFS_TYPE_SNAP_NAME
APFS_TYPE_SNAP_NAME = 11
APFS_TYPE_SIBLING_MAP
APFS_TYPE_SIBLING_MAP = 12
APFS_TYPE_FILE_INFO
APFS_TYPE_FILE_INFO = 13
APFS_TYPE_MAX_VALID
APFS_TYPE_MAX_VALID = 13
APFS_TYPE_MAX
APFS_TYPE_MAX = 15
86
File-System Constants
j_obj_kinds
APFS_TYPE_INVALID
APFS_TYPE_INVALID = 15
j_obj_kinds
The kind of a file-system record.
typedef enum {
APFS_KIND_ANY = 0,
APFS_KIND_NEW = 1,
APFS_KIND_UPDATE = 2,
APFS_KIND_DEAD = 3,
APFS_KIND_UPDATE_REFCNT = 4,
APFS_KIND_INVALID = 255
} j_obj_kinds;
This value is stored in the kind bits of a j_phys_ext_val_t structureʼs len_and_kind field.
APFS_KIND_ANY
APFS_KIND_ANY = 0
This value isnʼt valid as the kind of a file-system record on disk. However, implementations of Apple File System can
use it internally — for example, in search queries and in tests when iterating over objects.
APFS_KIND_NEW
A new record.
APFS_KIND_NEW = 1
APFS_KIND_UPDATE
An updated record.
APFS_KIND_UPDATE = 2
APFS_KIND_DEAD
APFS_KIND_DEAD = 3
This value isnʼt valid as the kind of a file-system record on disk. However, implementations of Apple File System can
use it internally.
87
File-System Constants
j_inode_flags
APFS_KIND_UPDATE_REFCNT
APFS_KIND_UPDATE_REFCNT = 4
This value isnʼt valid as the kind of a file-system record on disk. However, implementations of Apple File System can
use it internally.
APFS_KIND_INVALID
APFS_KIND_INVALID = 255
j_inode_flags
The flags used by inodes.
typedef enum {
INODE_IS_APFS_PRIVATE = 0x00000001,
INODE_MAINTAIN_DIR_STATS = 0x00000002,
INODE_DIR_STATS_ORIGIN = 0x00000004,
INODE_PROT_CLASS_EXPLICIT = 0x00000008,
INODE_WAS_CLONED = 0x00000010,
INODE_FLAG_UNUSED = 0x00000020,
INODE_HAS_SECURITY_EA = 0x00000040,
INODE_BEING_TRUNCATED = 0x00000080,
INODE_HAS_FINDER_INFO = 0x00000100,
INODE_IS_SPARSE = 0x00000200,
INODE_WAS_EVER_CLONED = 0x00000400,
INODE_ACTIVE_FILE_TRIMMED = 0x00000800,
INODE_PINNED_TO_MAIN = 0x00001000,
INODE_PINNED_TO_TIER2 = 0x00002000,
INODE_HAS_RSRC_FORK = 0x00004000,
INODE_NO_RSRC_FORK = 0x00008000,
INODE_ALLOCATION_SPILLEDOVER = 0x00010000,
INODE_FAST_PROMOTE = 0x00020000,
INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000,
INODE_IS_PURGEABLE = 0x00080000,
INODE_WANTS_TO_BE_PURGEABLE = 0x00100000,
INODE_IS_SYNC_ROOT = 0x00200000,
INODE_SNAPSHOT_COW_EXEMPTION = 0x00400000,
INODE_INHERITED_INTERNAL_FLAGS = (INODE_MAINTAIN_DIR_STATS \
| INODE_SNAPSHOT_COW_EXEMPTION),
INODE_CLONED_INTERNAL_FLAGS = (INODE_HAS_RSRC_FORK \
| INODE_NO_RSRC_FORK \
88
File-System Constants
j_inode_flags
| INODE_HAS_FINDER_INFO \
| INODE_SNAPSHOT_COW_EXEMPTION),
} j_inode_flags;
INODE_IS_APFS_PRIVATE
INODE_IS_APFS_PRIVATE = 0x00000001
Inodes with this flag set arenʼt considered part of the volume. They canʼt be cloned, renamed, or deleted. Theyʼre
ignored by operations like counting the number of files on disk, and theyʼre hidden from the user during operations
like listing the files of a directory.
This flag isnʼt reserved by Apple; implementations of the Apple File System must set this flag on any inodes they create
for their own record keeping. However, to prevent implementations from interfering with each other, an implementation
modifies inodes with this flag only if the implementation created that inode.
INODE_MAINTAIN_DIR_STATS
89
File-System Constants
j_inode_flags
INODE_MAINTAIN_DIR_STATS = 0x00000002
This flag is only valid on a directory, and must also be set on the directoryʼs subdirectories.
When removing the INODE_MAINTAIN_DIR_STATS flag from a directory, walk its subdirectories and remove it from
any directories that inherited it from this directory. Directories that have the INODE_DIR_STATS_ORIGIN flag set,
and subdirectories of those directories, continue to have the INODE_MAINTAIN_DIR_STATS flag set, because they
donʼt inherit it from this directory.
INODE_DIR_STATS_ORIGIN
The inode has the INODE_MAINTAIN_DIR_STATS flag set explicitly, not due to inheritance.
INODE_DIR_STATS_ORIGIN = 0x00000004
More than one directory in a hierarchy can have this flag set.
INODE_PROT_CLASS_EXPLICIT
The inodeʼs data protection class was set explicitly when the inode was created.
INODE_PROT_CLASS_EXPLICIT = 0x00000008
INODE_WAS_CLONED
INODE_WAS_CLONED = 0x00000010
INODE_FLAG_UNUSED
Reserved.
INODE_FLAG_UNUSED = 0x00000020
Leave this flag unset when you create a new inode, and preserve its value when you modify an existing inode.
INODE_HAS_SECURITY_EA
INODE_HAS_SECURITY_EA = 0x00000040
INODE_BEING_TRUNCATED
INODE_BEING_TRUNCATED = 0x00000080
This flag is used as follows to allow the truncation operation to complete after a crash:
90
File-System Constants
j_inode_flags
Note that after a crash, the truncation operation might not resume until the next time the inode is accessed.
INODE_HAS_FINDER_INFO
INODE_HAS_FINDER_INFO = 0x00000100
INODE_IS_SPARSE
INODE_IS_SPARSE = 0x00000200
INODE_WAS_EVER_CLONED
INODE_WAS_EVER_CLONED = 0x00000400
If this flag is set, the blocks on disk that store this inode might also be in use with another inode. For example, when
deleting this inode, you need to check reference counts before deallocating storage.
Versions of macOS prior to 10.13.3 had a known issue where this flag could be set incorrectly. Before reading this flag,
confirm that the inodeʼs object identifier is larger than the value stored in the apfs_cloneinfo_id_epoch field
of apfs_superblock_t. In addition, to ensure that the volume hasnʼt been modified by an older OS version, con-
firm that the value of the apfs_cloneinfo_xid field and the apfs_modified_by field of apfs_superblock_t
contain the same value.
INODE_ACTIVE_FILE_TRIMMED
INODE_ACTIVE_FILE_TRIMMED = 0x00000800
This file type is used only on devices running iOS. By allocating space for the file, but never writing to that space, extra
blocks are set aside for overprovisioning thatʼs performed by the underlying NAND storage.
INODE_PINNED_TO_MAIN
INODE_PINNED_TO_MAIN = 0x00001000
This flag is only valid for Fusion systems. The main storage is a solid-state drive.
91
File-System Constants
j_inode_flags
INODE_PINNED_TO_TIER2
INODE_PINNED_TO_TIER2 = 0x00002000
This flag is only valid for Fusion systems. The secondary storage is a hard drive.
INODE_HAS_RSRC_FORK
INODE_HAS_RSRC_FORK = 0x00004000
If this flag is set, INODE_NO_RSRC_FORK must not be set. Itʼs also valid for neither flag to be set, which implicitly
indicates that the inode doesnʼt have a resource fork.
INODE_NO_RSRC_FORK
INODE_NO_RSRC_FORK = 0x00008000
If this flag is set, INODE_HAS_RSRC_FORK must not be set. Itʼs also valid for neither flag to be set, which implicitly
indicates that the inode doesnʼt have a resource fork.
INODE_ALLOCATION_SPILLEDOVER
The inodeʼs file content has some space allocated outside of the preferred storage tier for that file.
INODE_ALLOCATION_SPILLEDOVER = 0x00010000
INODE_FAST_PROMOTE
This inode is scheduled for promotion from slow storage to fast storage.
INODE_FAST_PROMOTE = 0x00020000
The promotion between tiers will happen the first time this inode is read.
INODE_HAS_UNCOMPRESSED_SIZE
INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000
Prior to macOS 10.15 and iOS 13.1, this flag was ignored and Appleʼs implementation always treated the
uncompressed_size field as padding.
92
File-System Constants
j_inode_flags
INODE_IS_PURGEABLE
INODE_IS_PURGEABLE = 0x00080000
A purge is requested from user space by part of the operating system, and the process of deleting purgeable files is
the responsibility of the operating system.
INODE_WANTS_TO_BE_PURGEABLE
This inode should become purgeable when its link count drops to one.
INODE_WANTS_TO_BE_PURGEABLE = 0x00100000
INODE_IS_SYNC_ROOT
INODE_IS_SYNC_ROOT = 0x00200000
Donʼt add or remove this flag, but preserve the flag if it already exists.
To prevent data loss, Appleʼs implementation coordinates with fileproviderd during operations such as renaming a
file in a sync hierarchy, moving a file from inside a sync hierarchy out of that hierarchy, and moving a file from outside of
a sync hierarchy into that hierarchy. Other implementations of the Apple File System should treat requests to perform
these operations as errors.
INODE_SNAPSHOT_COW_EXEMPTION
This inode is exempt from copy-on-write behavior if the data is part of a snapshot.
INODE_SNAPSHOT_COW_EXEMPTION = 0x00400000
Donʼt add or remove this flag, but preserve the flag if it already exists.
The number of files with this flag is tracked by the APFS_COW_EXEMPT_COUNT_NAME extended attribute.
INODE_INHERITED_INTERNAL_FLAGS
A bit mask of the flags that are inherited by the files and subdirectories in a directory.
INODE_INHERITED_INTERNAL_FLAGS = (INODE_MAINTAIN_DIR_STATS \
| INODE_SNAPSHOT_COW_EXEMPTION)
INODE_CLONED_INTERNAL_FLAGS
INODE_CLONED_INTERNAL_FLAGS = (INODE_HAS_RSRC_FORK
| INODE_NO_RSRC_FORK \
| INODE_HAS_FINDER_INFO \
| INODE_SNAPSHOT_COW_EXEMPTION)
93
File-System Constants
j_xattr_flags
APFS_VALID_INTERNAL_INODE_FLAGS
APFS_INODE_PINNED_MASK
j_xattr_flags
The flags used in an extended attribute record to provide additional information.
typedef enum {
XATTR_DATA_STREAM = 0x00000001,
XATTR_DATA_EMBEDDED = 0x00000002,
XATTR_FILE_SYSTEM_OWNED = 0x00000004,
XATTR_RESERVED_8 = 0x00000008,
} j_xattr_flags;
XATTR_DATA_STREAM
XATTR_DATA_STREAM = 0x00000001
94
File-System Constants
dir_rec_flags
XATTR_DATA_EMBEDDED
XATTR_DATA_EMBEDDED = 0x00000002
If this flag is set, the size of the value be smaller than XATTR_MAX_EMBEDDED_SIZE, and XATTR_DATA_STREAM
must not be set.
XATTR_FILE_SYSTEM_OWNED
XATTR_FILE_SYSTEM_OWNED = 0x00000004
For example, this flag is used on symbolic links. The links have an extended attribute whose name is SYMLINK_EA_
NAME, and this flag is set on that attribute.
XATTR_RESERVED_8
Reserved.
XATTR_RESERVED_8 = 0x00000008
Donʼt add this flag to an extended attribute record, but preserve the flag if it already exists.
dir_rec_flags
The flags used by directory records.
typedef enum {
DREC_TYPE_MASK = 0x000f,
RESERVED_10 = 0x0010
} dir_rec_flags;
DREC_TYPE_MASK
DREC_TYPE_MASK = 0x000f
RESERVED_10
Reserved.
RESERVED_10 = 0x0010
Donʼt set this flag. If you find a directory record with this flag set in production, file a bug against the Apple File System
implementation.
95
File-System Constants
Inode Numbers
Inode Numbers
Inodes whose number is always the same.
#define INVALID_INO_NUM 0
#define ROOT_DIR_PARENT 1
#define ROOT_DIR_INO_NUM 2
#define PRIV_DIR_INO_NUM 3
#define SNAP_DIR_INO_NUM 6
#define PURGEABLE_DIR_INO_NUM 7
#define MIN_USER_INO_NUM 16
If the APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE flag is set on the volume, the system volume reserves each of
the inode numbers listed above but with UNIFIED_ID_SPACE_MARK added to them. For example, the inode number
0x0800000000000002ULL is equal to ROOT_DIR_INO_NUM + UNIFIED_ID_SPACE_MARK, meaning this inode
number is reserved for the system volumeʼs root directory.
INVALID_INO_NUM
#define INVALID_INO_NUM 0
ROOT_DIR_PARENT
#define ROOT_DIR_PARENT 1
This is a sentinel value; thereʼs no inode on disk with this inode number.
ROOT_DIR_INO_NUM
#define ROOT_DIR_INO_NUM 2
PRIV_DIR_INO_NUM
#define PRIV_DIR_INO_NUM 3
The private directoryʼs filename is “private-dir”. When creating a new volume, you must create a directory with this
name and inode number.
This directory isnʼt reserved by Apple; implementations of the Apple File System can use it to store their own record-
keeping information. However, to prevent implementations from interfering with each other, an implementation modi-
fies files in the private directory only if the implementation created the files.
96
File-System Constants
Extended Attributes Constants
SNAP_DIR_INO_NUM
The inode number for the directory where snapshot metadata is stored.
#define SNAP_DIR_INO_NUM 6
PURGEABLE_DIR_INO_NUM
#define PURGEABLE_DIR_INO_NUM 7
This inode number and the directory records that use it are reserved. Other implementations of the Apple File System
must not modify them.
Purgeable files have the INODE_IS_PURGEABLE flag set on the internal_flags field of j_inode_val_t.
MIN_USER_INO_NUM
#define MIN_USER_INO_NUM 16
UNIFIED_ID_SPACE_MARK
The smallest inode number used by the system volume in a volume group.
XATTR_MAX_EMBEDDED_SIZE
The largest size, in bytes, of an extended attribute whose value is stored directly in the record.
97
File-System Constants
File-System Object Constants
SYMLINK_EA_NAME
The name of an extended attribute for a symbolic link whose value is the target file on the data volume.
FIRMLINK_EA_NAME
The name of an extended attribute for a firm link whose value is the target file.
APFS_COW_EXEMPT_COUNT_NAME
The number of files on the volume that donʼt use copy on write.
Donʼt add this extended attribute or modify its value, but preserve the attribute if it already exists.
The inodes that are counted here have the INODE_SNAPSHOT_COW_EXEMPTION flag set. This number is used by
Time Machine when making snapshots.
#define MIN_DOC_ID 3
MIN_DOC_ID
#define MIN_DOC_ID 3
File Modes
The values used by the mode field of j_inode_val_t to indicate a fileʼs mode.
98
File-System Constants
File Modes
The names, values, and meanings of these constants are the same as the constants provided by <sys/stat.h>.
These values are the same as the values defined in Directory Entry File Types, except for a bit shift.
mode_t
A file mode.
S_IFMT
S_IFIFO
A named pipe.
S_IFCHR
A character-special file.
S_IFDIR
A directory.
S_IFBLK
A block-special file.
99
File-System Constants
Directory Entry File Types
S_IFREG
A regular file.
S_IFLNK
A symbolic link.
S_IFSOCK
A socket.
S_IFWHT
A whiteout.
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
These values are the same as the values defined in File Modes, except for a bit shift.
DT_UNKNOWN
#define DT_UNKNOWN 0
DT_FIFO
A named pipe
#define DT_FIFO 1
100
File-System Constants
Directory Entry File Types
DT_CHR
A character-special file.
#define DT_CHR 2
DT_DIR
A directory.
#define DT_DIR 4
DT_BLK
A block-special file.
#define DT_BLK 6
DT_REG
A regular file.
#define DT_REG 8
DT_LNK
A symbolic link.
#define DT_LNK 10
DT_SOCK
A socket.
#define DT_SOCK 12
DT_WHT
A whiteout.
#define DT_WHT 14
101
Data Streams
Short pieces of information like a fileʼs name are stored inside the data structures that contain metadata. Data thatʼs
too large to store inline is stored separately, in a data stream. This includes the contents of files, and the value of some
attributes.
j_phys_ext_key_t
The key half of a physical extent record.
struct j_phys_ext_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_phys_ext_key j_phys_ext_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the physical block address of the start of the extent. The type in the header is
always APFS_TYPE_EXTENT.
j_phys_ext_val_t
The value half of a physical extent record.
struct j_phys_ext_val {
uint64_t len_and_kind;
uint64_t owning_obj_id;
int32_t refcnt;
} __attribute__((packed));
typedef struct j_phys_ext_val j_phys_ext_val_t;
len_and_kind
A bit field that contains the length of the extent and its kind.
uint64_t len_and_kind;
The extentʼs length is a uint64_t value, accessed as len_and_kind & PEXT_LEN_MASK, and measured in
blocks. The extentʼs kind is a j_obj_kinds value, accessed as (len_and_kind & PEXT_KIND_MASK) >>
PEXT_KIND_SHIFT.
102
Data Streams
j_file_extent_key_t
owning_obj_id
The identifier of the file system record thatʼs using this extent.
uint64_t owning_obj_id;
If the owning record is an inode, this field contains the inodeʼs private identifier (the private_id field of
j_inode_val_t). If the owning record is an extended attribute, this field contains the extended attributeʼs
record identifier (the identifier from the hdr field of j_xattr_key_t).
refcnt
int32_t refcnt;
The extent can be deleted when its reference count reaches zero.
PEXT_LEN_MASK
PEXT_KIND_MASK
PEXT_KIND_SHIFT
#define PEXT_KIND_SHIFT 60
j_file_extent_key_t
The key half of a file extent record.
struct j_file_extent_key {
j_key_t hdr;
uint64_t logical_addr;
} __attribute__((packed));
typedef struct j_file_extent_key j_file_extent_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always
APFS_TYPE_FILE_EXTENT.
103
Data Streams
j_file_extent_val_t
logical_addr
The offset within the fileʼs data, in bytes, for the data stored in this extent.
uint64_t logical_addr;
j_file_extent_val_t
The value half of a file extent record.
struct j_file_extent_val {
uint64_t len_and_flags;
uint64_t phys_block_num;
uint64_t crypto_id;
} __attribute__((packed));
typedef struct j_file_extent_val j_file_extent_val_t;
len_and_flags
A bit field that contains the length of the extent and its flags.
uint64_t len_and_flags;
The extentʼs length is a uint64_t value, accessed as len_and_kind & J_FILE_EXTENT_LEN_MASK, and
measured in bytes. The length must be a multiple of the block size defined by the nx_block_size field of
nx_superblock_t. The extentʼs flags are accessed as (len_and_kind & J_FILE_EXTENT_FLAG_MASK) >>
J_FILE_EXTENT_FLAG_SHIFT.
phys_block_num
uint64_t phys_block_num;
crypto_id
uint64_t crypto_id;
If the APFS_FS_ONEKEY flag is set on the volume, this field contains the AES-XTS tweak value. Otherwise, this value
matches the obj_id field of the j_crypto_key_t record that contains information about how this file extent is
encrypted, including the per-file encryption key.
The default value for this field is the value of the default_crypto_id field of the j_dstream_t for the data stream
that this extent is part of.
104
Data Streams
j_dstream_id_key_t
J_FILE_EXTENT_LEN_MASK
J_FILE_EXTENT_FLAG_MASK
J_FILE_EXTENT_FLAG_SHIFT
#define J_FILE_EXTENT_FLAG_SHIFT 56
j_dstream_id_key_t
The key half of a directory-information record.
struct j_dstream_id_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_dstream_id_key j_dstream_id_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always
APFS_TYPE_DSTREAM_ID.
j_dstream_id_val_t
The value half of a data stream record.
struct j_dstream_id_val {
uint32_t refcnt;
} __attribute__((packed));
typedef struct j_dstream_id_val j_dstream_id_val_t;
refcnt
uint32_t refcnt;
The data stream record can be deleted when its reference count reaches zero.
105
Data Streams
j_xattr_dstream_t
j_xattr_dstream_t
A data stream for extended attributes.
struct j_xattr_dstream {
uint64_t xattr_obj_id;
j_dstream_t dstream;
};
typedef struct j_xattr_dstream j_xattr_dstream_t;
To access the data in the stream, read the object identifier and then find the corresponding extents.
xattr_obj_id
uint64_t xattr_obj_id;
This field contains the record identifier of the data stream that owns this record.
dstream
j_dstream_t dstream;
j_dstream_t
Information about a data stream.
struct j_dstream {
uint64_t size;
uint64_t alloced_size;
uint64_t default_crypto_id;
uint64_t total_bytes_written;
uint64_t total_bytes_read;
} __attribute__((aligned(8),packed));
typedef struct j_dstream j_dstream_t;
size
uint64_t size;
alloced_size
The total space allocated for the data stream, including any unused space.
uint64_t alloced_size;
106
Data Streams
j_dstream_t
default_crypto_id
The default encryption key or encryption tweak used in this data stream.
uint64_t default_crypto_id;
This value matches the obj_id field in the j_key_t key that corresponds to a j_crypto_val_t value. For a volume
that uses software encryption, the value of this field is always CRYPTO_SW_ID.
This value is used as the default value by file extents (j_file_extent_val_t) that make up this data stream.
total_bytes_written
The total number of bytes that have been written to this data stream.
uint64_t total_bytes_written;
The value of this field increases every time a write operation occurs. This value is allowed to overflow and restart from
zero.
total_bytes_read
The total number of bytes that have been read from this data stream.
uint64_t total_bytes_read;
The value of this field increases every time a read operation occurs. This value is allowed to overflow and restart from
zero.
107
Extended Fields
Directory entries and inodes use extended fields to store a dynamically extensible set of member fields.
To determine whether a directory entry or an inode has any extended fields, find the table of contents entry for the
file-system record, and then compare the recorded size to the size of the structure. For example:
Both j_drec_val_t and j_inode_val_t have an xfields field that contains several kinds of data, stored one
after another, ordered as follows:
1. An instance of xf_blob_t, which tells you how many extended fields there are, and how many bytes they take
up on disk.
2. An array of instances of x_field_t, one for each extended field, which tells you the fieldʼs type and size.
The arrays of extended-field metadata (x_field_t) and extended-field data are stored in the same order. The
extended-field dataʼs type depends on the field. For a list of field types, see Extended-Field Types.
xf_blob_t
A collection of extended attributes.
struct xf_blob {
uint16_t xf_num_exts;
uint16_t xf_used_data;
uint8_t xf_data[];
};
typedef struct xf_blob xf_blob_t;
Directory entries (j_drec_val_t) and inodes (j_inode_val_t) use this data type to store their extended fields.
xf_num_exts
uint16_t xf_num_exts;
xf_used_data
uint16_t xf_used_data;
This total includes both the space used to store metadata, as instances of x_field_t, and values.
108
Extended Fields
x_field_t
xf_data[]
uint8_t xf_data[];
This field contains an array of instances of x_field_t, followed by the extended field data.
x_field_t
An extended fieldʼs metadata.
struct x_field {
uint8_t x_type;
uint8_t x_flags;
uint16_t x_size;
};
typedef struct x_field x_field_t;
This type is used by xf_blob_t to store an array of extended fields. Within the array, each extended field must have
a unique type.
The extended fieldʼs data is stored outside of this structure, as part of the space set aside by the directory entry or
inode.
x_type
uint8_t x_type;
x_flags
uint8_t x_flags;
For the values used in this bit field, see Extended-Field Flags.
x_size
uint16_t x_size;
Extended-Field Types
Values used by the x_type field of x_field_t to indicate an extended fieldʼs type.
#define DREC_EXT_TYPE_SIBLING_ID 1
#define INO_EXT_TYPE_SNAP_XID 1
109
Extended Fields
Extended-Field Types
#define INO_EXT_TYPE_DELTA_TREE_OID 2
#define INO_EXT_TYPE_DOCUMENT_ID 3
#define INO_EXT_TYPE_NAME 4
#define INO_EXT_TYPE_PREV_FSIZE 5
#define INO_EXT_TYPE_RESERVED_6 6
#define INO_EXT_TYPE_FINDER_INFO 7
#define INO_EXT_TYPE_DSTREAM 8
#define INO_EXT_TYPE_RESERVED_9 9
#define INO_EXT_TYPE_DIR_STATS_KEY 10
#define INO_EXT_TYPE_FS_UUID 11
#define INO_EXT_TYPE_RESERVED_12 12
#define INO_EXT_TYPE_SPARSE_BYTES 13
#define INO_EXT_TYPE_RDEV 14
#define INO_EXT_TYPE_PURGEABLE_FLAGS 15
#define INO_EXT_TYPE_ORIG_SYNC_ROOT_ID 16
DREC_EXT_TYPE_SIBLING_ID
#define DREC_EXT_TYPE_SIBLING_ID 1
The corresponding sibling-link record has the same identifier in the sibling_id field of j_sibling_key_t.
INO_EXT_TYPE_SNAP_XID
#define INO_EXT_TYPE_SNAP_XID 1
INO_EXT_TYPE_DELTA_TREE_OID
The virtual object identifier of the file-system tree that corresponds to a snapshotʼs extent delta list (oid_t).
#define INO_EXT_TYPE_DELTA_TREE_OID 2
INO_EXT_TYPE_DOCUMENT_ID
#define INO_EXT_TYPE_DOCUMENT_ID 3
The document identifier lets applications keep track of the document during operations like atomic save, where one
folder replaces another. The document identifier remains associated with the full path, not just with the inode thatʼs
currently at that path. Implementations of Apple File System must preserve the document identifier when the inode
at that path is replaced.
Both documents that are stored as a bundle and documents that are stored as a single file can have a document
identifier assigned.
110
Extended Fields
Extended-Field Types
Valid document identifiers are greater than MIN_DOC_ID and less than UINT32_MAX - 1. For the next document
identifier that will be assigned, see the apfs_next_doc_id field of apfs_superblock_t.
INO_EXT_TYPE_NAME
#define INO_EXT_TYPE_NAME 4
This extended field is used only for hard links: The name stored in the inode is the name of the primary link to the file,
and the name of the hard link is stored in this extended field.
INO_EXT_TYPE_PREV_FSIZE
#define INO_EXT_TYPE_PREV_FSIZE 5
This extended field is used for recovering after a crash. If itʼs set on an inode, truncate the file back to the size contained
in this field.
INO_EXT_TYPE_RESERVED_6
Reserved.
#define INO_EXT_TYPE_RESERVED_6 6
Donʼt create extended fields of this type in your own code. Preserve the value of any extended fields of this type.
INO_EXT_TYPE_FINDER_INFO
#define INO_EXT_TYPE_FINDER_INFO 7
INO_EXT_TYPE_DSTREAM
#define INO_EXT_TYPE_DSTREAM 8
INO_EXT_TYPE_RESERVED_9
Reserved.
#define INO_EXT_TYPE_RESERVED_9 9
Donʼt create extended fields of this type. When you modify an existing volume, preserve the contents of any extended
fields of this type.
INO_EXT_TYPE_DIR_STATS_KEY
#define INO_EXT_TYPE_DIR_STATS_KEY 10
111
Extended Fields
Extended-Field Flags
INO_EXT_TYPE_FS_UUID
The UUID of a file system thatʼs automatically mounted in this directory (uuid_t).
#define INO_EXT_TYPE_FS_UUID 11
INO_EXT_TYPE_RESERVED_12
Reserved.
#define INO_EXT_TYPE_RESERVED_12 12
Donʼt create extended fields of this type. If you find an object of this type in production, file a bug against the Apple
File System implementation.
INO_EXT_TYPE_SPARSE_BYTES
#define INO_EXT_TYPE_SPARSE_BYTES 13
INO_EXT_TYPE_RDEV
#define INO_EXT_TYPE_RDEV 14
This extended field stores the same information as the st_rdev field of the stat structure defined in <sys/stat.h>.
INO_EXT_TYPE_PURGEABLE_FLAGS
#define INO_EXT_TYPE_PURGEABLE_FLAGS 15
The value of this extended field is reserved. Donʼt create new extended fields of this type. When duplicating a file or
directory, omit this extended field from the new copy.
Purgeable files have the INODE_IS_PURGEABLE flag set on the internal_flags field of j_inode_val_t.
INO_EXT_TYPE_ORIG_SYNC_ROOT_ID
The inode number of the sync-root hierarchy that this file originally belonged to.
#define INO_EXT_TYPE_ORIG_SYNC_ROOT_ID 16
Extended-Field Flags
The flags used by an extended fieldʼs metadata.
112
Extended Fields
Extended-Field Flags
XF_DATA_DEPENDENT
When the file data changes, this extended field must be updated to match the new data. If itʼs not possible to update
the field — for example, because the Apple File System implementation doesnʼt recognize the fieldʼs type — the field
must be removed.
XF_DO_NOT_COPY
When copying this file, omit this extended field from the copy.
XF_RESERVED_4
Reserved.
XF_CHILDREN_INHERIT
When creating a new entry in this directory, copy this extended field to the new directory entry.
XF_USER_FIELD
XF_SYSTEM_FIELD
This extended field was added by the kernel, by the implementation of Apple File System, or by another system com-
ponent.
113
Extended Fields
Extended-Field Flags
Extended fields with this flag set canʼt be removed or modified by a program running in user space.
XF_RESERVED_40
Reserved.
XF_RESERVED_80
Reserved.
114
Siblings
Hard links that all refer to the same inode are called siblings. Each sibling has its own identifier thatʼs used instead
of the shared inode number when siblings need to be distinguished. For example, some Carbon APIs in macOS use
sibling identifiers.
The sibling whose identifier is the lowest number is called the primary link. The other siblings copy various properties
of the primary link, as discussed in j_inode_val_t.
You use sibling links and sibling maps to convert between sibling identifiers and inode numbers. Sibling-link records
let you find all the hard links whose target is a given inode. Sibling-map records let you find the target inode of a given
hard link.
j_sibling_key_t
The key half of a sibling-link record.
struct j_sibling_key {
j_key_t hdr;
uint64_t sibling_id;
} __attribute__((packed));
typedef struct j_sibling_key j_sibling_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier, that is, its inode number. The type in the header
is always APFS_TYPE_SIBLING_LINK.
sibling_id
uint64_t sibling_id;
This value matches the object identifier for the sibling map record (j_sibling_key_t).
j_sibling_val_t
The value half of a sibling-link record.
struct j_sibling_val {
uint64_t parent_id;
uint16_t name_len;
uint8_t name[0];
} __attribute__((packed));
typedef struct j_sibling_val j_sibling_val_t;
115
Siblings
j_sibling_map_key_t
parent_id
The object identifier for the inode thatʼs the parent directory.
uint64_t parent_id;
name_len
The length of the name, including the final null character (U+0000).
uint16_t name_len;
name
uint8_t name[0];
j_sibling_map_key_t
The key half of a sibling-map record.
struct j_sibling_map_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_sibling_map_key j_sibling_map_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the siblingʼs unique identifier, which matches the sibling_id field of
j_sibling_key_t. The type in the header is always APFS_TYPE_SIBLING_MAP.
j_sibling_map_val_t
The value half of a sibling-map record.
struct j_sibling_map_val {
uint64_t file_id;
} __attribute__((packed));
typedef struct j_sibling_map_val j_sibling_map_val_t;
file_id
uint64_t file_id;
116
Snapshot Metadata
Snapshots let you get a stable, read-only copy of the filesystem at a given point in time — for example, while updating a
backup of the entire drive. Snapshots are designed to be fast and inexpensive to create; however, deleting a snapshot
involves more work.
j_snap_metadata_key_t
The key half of a record containing metadata about a snapshot.
struct j_snap_metadata_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_snap_metadata_key j_snap_metadata_key_t;
hdr
j_key_t hdr;
The object identifier in the header is the snapshotʼs transaction identifier. The type in the header is always
APFS_TYPE_SNAP_METADATA.
j_snap_metadata_val_t
The value half of a record containing metadata about a snapshot.
struct j_snap_metadata_val {
oid_t extentref_tree_oid;
oid_t sblock_oid;
uint64_t create_time;
uint64_t change_time;
uint64_t inum;
uint32_t extentref_tree_type;
uint32_t flags;
uint16_t name_len;
uint8_t name[0];
} __attribute__((packed));
typedef struct j_snap_metadata_val j_snap_metadata_val_t;
extentref_tree_oid
The physical object identifier of the B-tree that stores extents information.
oid_t extentref_tree_oid;
sblock_oid
117
Snapshot Metadata
j_snap_metadata_val_t
oid_t sblock_oid;
create_time
uint64_t create_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
change_time
uint64_t change_time;
This timestamp is represented as the number of nanoseconds since January 1, 1970 at 0 00 UTC, disregarding leap
seconds.
inum
No overview available.
uint64_t inum;
extentref_tree_type
uint32_t extentref_tree_type;
flags
A bit field that contains additional information about a snapshot metadata record.
uint32_t flags;
name_len
The length of the snapshotʼs name, including the final null character (U+0000).
uint16_t name_len;
name
uint8_t name[0];
118
Snapshot Metadata
j_snap_name_key_t
j_snap_name_key_t
The key half of a snapshot name record.
struct j_snap_name_key {
j_key_t hdr;
uint16_t name_len;
uint8_t name[0];
} __attribute__((packed));
typedef struct j_snap_name_key j_snap_name_key_t;
hdr
j_key_t hdr;
The object identifier in the header is always ~0ULL. The type in the header is always APFS_TYPE_SNAP_NAME.
name_len
The length of the extended attributeʼs name, including the final null character (U+0000).
uint16_t name_len;
name
uint8_t name[0];
j_snap_name_val_t
The value half of a snapshot name record.
struct j_snap_name_val {
xid_t snap_xid;
} __attribute__((packed));
typedef struct j_snap_name_val j_snap_name_val_t;
snap_xid
xid_t snap_xid;
snap_meta_flags
No overview available.
typedef enum {
SNAP_META_PENDING_DATALESS = 0x00000001,
SNAP_META_MERGE_IN_PROGRESS = 0x00000002,
119
Snapshot Metadata
snap_meta_ext_obj_phys_t
} snap_meta_flags;
snap_meta_ext_obj_phys_t
Additional metadata about snapshots.
struct snap_meta_ext_obj_phys {
obj_phys_t smeop_o;
snap_meta_ext_t smeop_sme;
}
typedef struct snap_meta_ext_obj_phys_t;
smeop_o
No overview available.
obj_phys_t smeop_o;
smeop_sme
No overview available.
snap_meta_ext_t smeop_sme;
snap_meta_ext_t
No overview available.
uint32_t sme_flags;
xid_t sme_snap_xid;
uuid_t sme_uuid;
uint64_t sme_token;
} __attribute__((packed))
typedef struct snap_meta_ext snap_meta_ext_t;
sme_version
uint32_t sme_version;
sme_flags
uint32_t sme_flags;
120
Snapshot Metadata
snap_meta_ext_t
sme_snap_xid
xid_t sme_snap_xid;
sme_uuid
uuid_t sme_uuid;
sme_token
Opaque metadata.
uint64_t sme_token;
121
B-Trees
The B-trees used in Apple File System are implemented using the btree_node_phys_t structure to represent a
node. The same structure is used for all nodes in a tree. Within a node, storage is divided into several areas:
The figure below shows the storage areas of a typical root node.
The instance of btree_node_phys_t stores information about this B-tree node, like its flags and the location of its
keys, and is always located at the beginning of the block. For a root node, an instance of btree_info_t is located
at the end of the block, and contains information like the sizes of keys and values, the total number of keys in the tree,
and the number of nodes in the tree. Nonroot nodes omit btree_info_t. The rest of the block (the btn_data field
of btree_node_phys_t) is organized dynamically.
Compared to other B-tree implementations, this data structure has some unique characteristics. Traversal is always
done from the root node because nodes donʼt have parent or sibling pointers. All values are stored in leaf nodes, which
makes these B+ trees, and the values in nonleaf nodes are object identifiers of child nodes. The keys, values, or both
can be of variable size; if the keys and values of a node are both fixed in size, some optimizations for the table of
contents are possible.
The keys and values are stored starting at opposite ends of the B-tree nodeʼs storage area, with free space thatʼs
available for new keys or values in the available portion of the storage area between them. The key and value areas
grow toward each other into their shared free space. Free space within the key area and within the value area is
organized using a free list. For example, free space appears outside the shared free space when an entry is removed
from a B-tree. The figure below shows free space for keys and values in a typical nonroot node.
The locations of keys and values are stored as offsets, which uses less on-disk space than storing the full location.
The offset to a key is counted from the beginning of the key area to the beginning of the key. The offset to a value is
counted from the end of the value area to the beginning of the value.
122
B-Trees
btree_node_phys_t
Keys and value are normally aligned to eight-byte boundaries when stored. The length recorded for a key or value in
the table of contents omits any padding needed for alignment. If the BTREE_KV_NONALIGNED flag is set, keys and
values are stored without padding.
If the BTREE_ALLOW_GHOSTS flag is set on the B-tree, the tree can contain keys that have no value.
Table of Contents
The table of contents stores the location of each key and value that form a key-value pair.
If the BTNODE_FIXED_KV_SIZE flag is set, the table of contents stores only the offsets for keys and values. Other-
wise, it stores both their offsets and lengths.
Free space within the table of contents is located at the end. If thereʼs no free space remaining, but a new entry
is needed, the table of contents area must be expanded. The entire key area is shifted to make space available,
using some of the shared free space for key space, and some space from the beginning of the key space for the
table of contents. Because the offset to a key is counted relative to the beginning of the key area, moving the en-
tire key area doesnʼt invalidate any of these offsets. Likewise, when the table of contents has too much unused
space, it shrinks, and the key area is shifted into the space from the table of contents. Appleʼs implementation uses
BTREE_TOC_ENTRY_INCREMENT and BTREE_TOC_ENTRY_MAX_UNUSED to determine when to expand or shrink the
table of contents.
Note
When the BTNODE_FIXED_KV_SIZE flag is set, Appleʼs implementation allocates enough space for the table of
contents to avoid the need to expand it later. This is possible because the maximum number of entries is known,
as well as the size of an entry. However, if the BTREE_ALLOW_GHOSTS flag is also set, the table of contents
might still need to expand.
Key Comparison
The entries in the table of contents are sorted by key. The comparison function used for sorting depends on the keyʼs
type. Object map B-trees are sorted by object identifier and then by transaction identifier. Free queue B-trees are
sorted by transaction identifier and then by physical address. File-system records are sorted according to the rules
listed in File-System Objects.
btree_node_phys_t
A B-tree node.
struct btree_node_phys {
obj_phys_t btn_o;
uint16_t btn_flags;
uint16_t btn_level;
uint32_t btn_nkeys;
nloc_t btn_table_space;
nloc_t btn_free_space;
nloc_t btn_key_free_list;
nloc_t btn_val_free_list;
uint64_t btn_data[];
123
B-Trees
btree_node_phys_t
};
typedef struct btree_node_phys btree_node_phys_t;
The locations of the key and value areas arenʼt stored explicitly. The key area begins after the end of the table of
contents and ends before the start of the shared free space. The value area begins after the end of shared free space
and ends at the end of the B-tree node (for nonroot nodes) or before the instance of btree_info_t thatʼs at the end
of a root node.
btn_o
obj_phys_t btn_o;
btn_flags
uint16_t btn_flags;
For the values used in this bit field, see B-Tree Node Flags.
btn_level
uint16_t btn_level;
For example, the value of this field is zero for a leaf node and one for the immediate parent of a leaf node. Likewise,
the height of a tree is one plus the value of this field on the treeʼs root node.
btn_nkeys
uint32_t btn_nkeys;
btn_table_space
nloc_t btn_table_space;
The offset for the table of contents is counted from the beginning of the nodeʼs btn_data field to the beginning of
the table of contents.
If the BTNODE_FIXED_KV_SIZE flag is set, the table of contents is an array of instances of kvoff_t; otherwise, itʼs
an array of instances of kvloc_t.
btn_free_space
The location of the shared free space for keys and values.
nloc_t btn_free_space;
124
B-Trees
btree_info_fixed_t
The locationʼs offset is counted from the beginning of the key area to the beginning of the free space.
btn_key_free_list
nloc_t btn_key_free_list;
The offset from the beginning of the key area to the first available space for a key is stored in the off field, and the
total amount of free key space is stored in the len field. Each free space stores an instance of nloc_t whose len
field indicates the size of that free space and whose off field contains the location of the next free space.
btn_val_free_list
nloc_t btn_val_free_list;
The offset from the end of the value area to the first available space for a value is stored in the off field, and the total
amount of free value space is stored in the len field. Each free space stores an instance of nloc_t whose len field
indicates the size of that free space and whose off field contains the location of the next free space.
btn_data
uint64_t btn_data[];
This area contains the table of contents, keys, free space, and values. A root node also has as an instance of
btree_info_t at the end of its storage area. For more information, see B-trees.
btree_info_fixed_t
Static information about a B-tree.
struct btree_info_fixed {
uint32_t bt_flags;
uint32_t bt_node_size;
uint32_t bt_key_size;
uint32_t bt_val_size;
};
typedef struct btree_info_fixed btree_info_fixed_t;
This information doesnʼt change over time as the B-tree is modified. Itʼs stored separately from the rest of the infor-
mation in btree_info_t, which does change, to enable this information to be cached more easily.
bt_flags
uint32_t bt_flags;
For the values used in this bit field, see B-Tree Flags.
125
B-Trees
btree_info_t
bt_node_size
uint32_t bt_node_size;
Leaf nodes, nonleaf nodes, and the root node are all the same size.
bt_key_size
uint32_t bt_key_size;
If this field has a value of zero, the btn_flags field of instances of btree_node_phys_t in this tree must not include
BTNODE_FIXED_KV_SIZE.
bt_val_size
uint32_t bt_val_size;
If this field has a value of zero, the btn_flags field of instances of btree_node_phys_t for leaf nodes in
this tree must not include BTNODE_FIXED_KV_SIZE. Nonleaf nodes in a tree with variable-size values include
BTNODE_FIXED_KV_SIZE, because the values stored in those nodes are the object identifiers of their child nodes,
and object identifiers have a fixed size.
btree_info_t
Information about a B-tree.
struct btree_info {
btree_info_fixed_t bt_fixed;
uint32_t bt_longest_key;
uint32_t bt_longest_val;
uint64_t bt_key_count;
uint64_t bt_node_count;
};
typedef struct btree_info btree_info_t;
This information appears only in a root node, stored at the end of the node.
btree_info_fixed_t
btree_info_fixed_t bt_fixed;
bt_longest_key
The length, in bytes, of the longest key that has ever been stored in the B-tree.
uint32_t bt_longest_key;
126
B-Trees
btn_index_node_val_t
bt_longest_val
The length, in bytes, of the longest value that has ever been stored in the B-tree.
uint32_t bt_longest_val;
bt_key_count
uint64_t bt_key_count;
bt_node_count
uint64_t bt_node_count;
btn_index_node_val_t
The value used by hashed B-trees for nonleaf nodes.
struct btn_index_node_val {
oid_t binv_child_oid;
uint8_t binv_child_hash[BTREE_NODE_HASH_SIZE_MAX];
};
typedef struct btn_index_node_val btn_index_node_val_t;
#define BTREE_NODE_HASH_SIZE_MAX 64
For nonhashed B-trees, instead of using this structure, the values are instances of oid_t. Because this structureʼs
oid_t field comes first, code thatʼs expecting only the object identifier of the child node as the B-tree value is still
able to read the hashed B-tree by ignoring the hashes.
binv_child_oid
oid_t binv_child_oid;
binv_child_hash
uint8_t binv_child_hash[BTREE_NODE_HASH_SIZE_MAX];
The hash algorithm used by this tree determines the length of the hash. See the im_hash_type field of integrity_
meta_phys_t, and the hash_size field of j_file_data_hash_val_t.
To compute the hash, use the entire child node object as the input for the hash algorithm specified for this tree. If the
output from that hash algorithm is smaller than the BTREE_NODE_HASH_SIZE_MAX bytes, treat the remaining bytes
as padding — set them to zero when you create a new node, and preserve their value when you modify an existing
node.
127
B-Trees
nloc_t
BTREE_NODE_HASH_SIZE_MAX
#define BTREE_NODE_HASH_SIZE_MAX 64
nloc_t
A location within a B-tree node.
struct nloc {
uint16_t off;
uint16_t len;
};
typedef struct nloc nloc_t;
off
uint16_t off;
Depending on the data type that contains this location, the offset is either implicitly positive or negative, and is counted
starting at different points in the B-tree node.
len
uint16_t len;
BTOFF_INVALID
An invalid offset.
This value is stored in the off field of nloc_t to indicate that thereʼs no offset. For example, the last entry in a free
list has no entry after it, so it uses this value for its off field.
kvloc_t
The location, within a B-tree node, of a key and value.
struct kvloc {
nloc_t k;
nloc_t v;
};
typedef struct kvloc kvloc_t;
128
B-Trees
kvoff_t
The B-tree nodeʼs table of contents uses this structure when the keys and values are not both fixed in size.
nloc_t
nloc_t k;
nloc_t
nloc_t v;
kvoff_t
The location, within a B-tree node, of a fixed-size key and value.
struct kvoff {
uint16_t k;
uint16_t v;
};
typedef struct kvoff kvoff_t;
The B-tree nodeʼs table of contents uses this structure when the keys and values are both fixed in size. The meaning
of the offsets stored in this structureʼs k and v fields is the same as the meaning of the off field in an instance of
nloc_t. This structure doesnʼt have a field thatʼs equivalent to the len field of nloc_t — the key and value lengths
are always the same, and omitting them from the table of contents saves space.
uint16_t k;
uint16_t v;
B-Tree Flags
The flags used to describe configuration options for a B-tree.
129
B-Trees
B-Tree Flags
BTREE_UINT64_KEYS
Code that works with the B-tree should enable optimizations to make comparison of keys fast.
BTREE_SEQUENTIAL_INSERT
Code that works with the B-tree should enable optimizations to keep the B-tree compact during sequential insertion
of entries.
Normally, nodes are split in half when they become almost full. With this flag set, a new node is added to provide the
needed space, instead of splitting a node thatʼs almost full. This yields a tree with nodes that are almost full instead
of nodes that are about half full.
BTREE_ALLOW_GHOSTS
The table of contents is allowed to contain keys that have no corresponding value.
In the table of contents, a ghost is indicated by a value whose location offset is BTOFF_INVALID.
The meaning of a ghost depends on context — it can indicate a key that has been deleted and should be ignored, or
a key whose value is implicit from context. For example, in the space managerʼs free queue, a ghost indicates a free
extent thatʼs one block long.
Using ghosts to store an implicit value allows more entries to be stored in some circumstances because no space in
the value area is used by the ghost.
BTREE_EPHEMERAL
The nodes in the B-tree use ephemeral object identifiers to link to child nodes.
If this flag is set, BTREE_PHYSICAL must not be set. If neither flag is set, nodes in the B-tree use virtual object
identifiers to link to their child nodes.
BTREE_PHYSICAL
The nodes in the B-tree use physical object identifiers to link to child nodes.
If this flag is set, BTREE_EPHEMERAL must not be set. If neither flag is set, nodes in the B-tree use virtual object
identifiers to link to their child nodes.
130
B-Trees
B-Tree Table of Contents Constants
BTREE_NONPERSISTENT
This flag is valid only when BTREE_EPHEMERAL is also set, and only on in-memory B-trees.
BTREE_KV_NONALIGNED
The keys and values in the B-tree arenʼt required to be aligned to eight-byte boundaries.
Aligning to eight-byte boundaries avoids unaligned reads on 64-bit platforms, which improves performance, but
wastes space on disk for structures whose size isnʼt a multiple of eight bytes.
BTREE_HASHED
The nonleaf nodes of this B-tree store a hash of their child nodes.
If this flag is set, all nodes of this B-tree have the BTNODE_HASHED flag set.
BTREE_NOHEADER
If this flag is set, all nodes of this B-tree have the BTNODE_NOHEADER flag set.
#define BTREE_TOC_ENTRY_INCREMENT 8
#define BTREE_TOC_ENTRY_MAX_UNUSED (2 * BTREE_TOC_ENTRY_INCREMENT)
These values are used by Appleʼs implementation; other implementations can choose different values. If you donʼt
use these values, profile your implementation to determine the performance impact of your chosen values.
BTREE_TOC_ENTRY_INCREMENT
The number of entries that are added or removed when changing the size of the table of contents.
#define BTREE_TOC_ENTRY_INCREMENT 8
BTREE_TOC_ENTRY_MAX_UNUSED
131
B-Trees
B-Tree Node Flags
BTNODE_ROOT
If this flag is set, the nodeʼs object type is OBJECT_TYPE_BTREE. If this is the treeʼs only node, both BTNODE_ROOT
and BTNODE_LEAF are set. Otherwise, the BTNODE_LEAF flag must not be set.
BTNODE_LEAF
If this is the treeʼs only node, the node objectʼs type is OBJECT_TYPE_BTREE, and both BTNODE_ROOT and
BTNODE_LEAF are set. Otherwise, the nodeʼs object type is OBJECT_TYPE_BTREE_NODE, and the BTNODE_ROOT
flag must not be set.
BTNODE_FIXED_KV_SIZE
The B-tree node has keys and values of a fixed size, and the table of contents omits their lengths.
If the keys and values both have a fixed size, this flag must be set.
Within the same B-tree, itʼs valid to have a mix of nodes that have this flag set and nodes that donʼt. For example,
consider a B-tree with fixed-sized keys and variable-sized values. Leaf nodes in that tree donʼt have this flag set
because of the variable-sized values. However, nonleaf nodes in in the same tree do have this flag set. The values
stored in nonleaf nodes are object identifiers, which are fixed-sized values; therefore, this flag can be applied to
nonleaf nodes of any tree with fixed-size keys.
BTNODE_HASHED
This flag is valid only on B-trees that have the BTREE_HASHED flag. You can this flag on a leaf node, for consistency
with the nonleaf nodes in the same tree, but it doesnʼt mean anything there and is ignored.
132
B-Trees
B-Tree Node Constants
BTNODE_NOHEADER
This flag is valid only on B-trees that have the BTREE_NOHEADER flag.
If this flag is set, the btn_o field of this instance of btree_node_phys_t is always zero.
BTNODE_CHECK_KOFF_INVAL
Objects with this flag never appear on disk. If you find an object of this type in production, file a bug against the Apple
File System implementation.
This flag isnʼt reserved by Apple; non-Apple implementations of Apple File System can set it on B-tree nodes in mem-
ory.
A node is almost always one logical block in size. Smaller nodes waste space, and larger nodes can experience allo-
cation issues when space is fragmented. For example, a five-block node requires five adjacent blocks to all be free,
but on a fragmented disk such a large free space might not exist.
BTREE_NODE_SIZE_DEFAULT
BTREE_NODE_MIN_ENTRY_COUNT
The minimum number of entries that must be able to fit in a nonleaf B-tree node.
#define BTREE_NODE_MIN_ENTRY_COUNT 4
To satisfy this requirement, reduce the size of the keys stored in the node. The maximum key size is computed as
follows:
133
B-Trees
B-Tree Node Constants
esize = sizeof(kvloc_t);
count = BTREE_TOC_ENTRY_INCREMENT;
kvspace = dataspace - (count * esize);
return ((kvspace / BTREE_NODE_MIN_ENTRY_COUNT) - sizeof(oid_t));
}
Note
This requirement comes from logic in Appleʼs implementation that performs proactive splitting of B-tree nodes.
134
Encryption
Apple File System supports encryption in the data structures used for containers, volumes, and files. When a volume
is encrypted, both its file-system tree and the contents of files in that volume are encrypted.
Depending on the deviceʼs capabilities, Apple File System uses either hardware or software encryption, which impacts
encryption process and the meaning of several data structures. Hardware encryption is used for internal storage
on devices that support it, including macOS (with T2 security chip) and iOS devices. Software encryption is used
for external storage, and for internal storage on devices that donʼt support hardware encryption. When hardware
encryption is in use, only the kernel can interact with internal storage.
Important
The keys used to access file data are stored on disk in a wrapped state. You access these keys through a chain of
key-unwrapping operations. The volume encryption key (VEK) is the default key used to access encrypted content on
the volume. The key encryption key (KEK) is used to unwrap the VEK. The KEK is unwrapped in one of several ways:
• User password. The user enters their password, which is used to unwrap the KEK.
• Personal recovery key. This key is generated when the drive is formatted and is saved by the user on a paper
printout. The string on that printout is used to unwrap the KEK.
• Institutional recovery key. This key is enabled by the user in Settings and allows the corresponding corporate
master key to unwrap the KEK.
• iCloud recovery key. This key is used by customers working with Apple Support, and isnʼt described in this
document.
For example, to access a file given the userʼs password on a volume that uses per-volume encryption, the chain of key
unwrapping and data decryption consists of the following high-level operations:
Keybag
On macOS devices, both the container and the volume have a keybag (an instance of kb_locker_t). The containerʼs
keybag is stored at the location indicated by the nx_keylocker field of nx_superblock_t. For each volume, the
containerʼs keybag stores the volumeʼs wrapped VEK and the location of the volumeʼs keybag. The volumeʼs keybag
contains several copies of the volumeʼs KEK, wrapped using user passwords and recovery keys.
135
Encryption
Accessing Encrypted Objects
Keybags are encrypted using the UUID of the container or volume, which makes it possible to quickly and securely
destroy the contents of an encrypted volume by changing or deleting the UUID. For a volume, destroying the UUID
by securely erasing a volume superblock makes the corresponding keybag unreadable, which in turn makes the en-
crypted content of that volume inaccessible. For a container superblock, you need to destroy all of the copies of that
block in the checkpoint descriptor area and the copy at block zero.
2. Unwrap the containerʼs keybag using the containerʼs UUID, according to the algorithm described in RFC 3394.
3. Find an entry in the containerʼs keybag whose UUID matches the volumeʼs UUID and whose tag is
KB_TAG_VOLUME_KEY. The key data for that entry is the wrapped VEK for this volume.
4. Find an entry in the containerʼs keybag whose UUID matches the volumeʼs UUID and whose tag is
KB_TAG_VOLUME_UNLOCK_RECORDS. The key data for that entry is the location of the volumeʼs keybag.
5. Unwrap the volumeʼs keybag using the volumeʼs UUID according to the algorithm described in RFC 3394.
6. Find an entry in the volumeʼs keybag whose UUID matches the userʼs Open Directory UUID and whose tag is
KB_TAG_VOLUME_UNLOCK_RECORDS. The key data for that entry is the wrapped KEK for this volume.
7. Unwrap the KEK using the userʼs password, and then unwrap the VEK using the KEK, both according to the
algorithm described in RFC 3394.
136
Encryption
j_crypto_key_t
The volumeʼs keybag might contain a passphrase hint for the user (KB_TAG_VOLUME_PASSPHRASE_HINT), which
you can display when prompting for the password. It also might contain an entry for a personal recovery key, using
APFS_FV_PERSONAL_RECOVERY_KEY_UUID as the UUID. You follow the same process for a personal recovery key
as you do for a password: Unwrap the KEK with the user-entered string, and then use the unwrapped KEK to unwrap
the VEK, both according to the algorithm described in RFC 3394.
1. Decrypt the blocks where the volumeʼs root file-system tree is stored, using the VEK as an AES-XTS key. The
file-system tree is accessed using the apfs_root_tree_oid field of apfs_superblock_t.
2. Find the file extent record (APFS_TYPE_FILE_EXTENT) for the encrypted file.
3. Find the encryption state record (APFS_TYPE_CRYPTO_STATE) whose identifier matches the crypto_id field
of j_file_extent_val_t.
4. Decrypt the blocks where the fileʼs data is stored, using the VEK as an AES-XTS key and the value of
crypto_id as the tweak.
j_crypto_key_t
The key half of a per-file encryption state record.
struct j_crypto_key {
j_key_t hdr;
} __attribute__((packed));
typedef struct j_crypto_key j_crypto_key_t;
Several encryption state objects always have the same identifier, as listed in Encryption Identifiers.
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always
APFS_TYPE_CRYPTO_STATE.
j_crypto_val_t
The value half of a per-file encryption state record.
struct j_crypto_val {
uint32_t refcnt;
wrapped_crypto_state_t state;
} __attribute__((aligned(4),packed));
typedef struct j_crypto_val j_crypto_val_t;
refcnt
int32_t refcnt;
137
Encryption
wrapped_crypto_state_t
The encryption state record can be deleted when its reference count reaches zero.
state
wrapped_crypto_state_t state;
If this encryption state record is used by the file-system tree rather than by a file, this field is an instance of
wrapped_meta_crypto_state_t and the key used is always the volume encryption key (VEK).
wrapped_crypto_state_t
A wrapped key used for per-file encryption.
struct wrapped_crypto_state {
uint16_t major_version;
uint16_t minor_version;
crypto_flags_t cpflags;
cp_key_class_t persistent_class;
cp_key_os_version_t key_os_version;
cp_key_revision_t key_revision;
uint16_t key_len;
uint8_t persistent_key[0];
} __attribute__((aligned(2), packed));
typedef struct wrapped_crypto_state wrapped_crypto_state_t;
major_version
uint16_t major_version;
The current value of this field is five. If backward-incompatible changes are made to this data structure in the future,
the major version number will be incremented.
This structure is equivalent to a structure used by iOS for per-file encryption on HFS-Plus; versions four and earlier
were used by previous versions of that structure.
minor_version
uint16_t minor_version;
The current value of this field is zero. If backward-compatible changes are made to this data structure in the future,
the minor version number will be incremented.
138
Encryption
wrapped_crypto_state_t
cpflags
crypto_flags_t cpflags;
persistent_class
cp_key_class_t persistent_class;
For possible values and the bit mask that must be used, see Protection Classes.
key_os_version
cp_key_os_version_t key_os_version;
This field is used as part of key rolling. For information about how the major version number, minor version number,
and build number are packed into 32 bits, see cp_key_os_version_t.
key_revision
cp_key_revision_t key_revision;
Set this field to one when creating a new instance, and increment it by one when rolling to a new key.
key_len
uint16_t key_len;
persistent_key
uint8_t persistent_key[0];
CP_MAX_WRAPPEDKEYSIZE
139
Encryption
wrapped_meta_crypto_state_t
wrapped_meta_crypto_state_t
Information about how the volume encryption key (VEK) is used to encrypt a file.
struct wrapped_meta_crypto_state {
uint16_t major_version;
uint16_t minor_version;
crypto_flags_t cpflags;
cp_key_class_t persistent_class;
cp_key_os_version_t key_os_version;
cp_key_revision_t key_revision;
uint16_t unused;
} __attribute__((aligned(2), packed));
typedef struct wrapped_meta_crypto_state wrapped_meta_crypto_state_t;
This structure is used inside of j_crypto_val_t. The fields in this structure are the same as wrapped_crypto_
state_t, except this structure doesnʼt contain a wrapped key.
major_version
uint16_t major_version;
The value of this field is always five. This structure is equivalent to a structure used by iOS for per-file encryption on
HFS-Plus; versions four and earlier were used by previous versions of that structure.
minor_version
uint16_t minor_version;
cpflags
crypto_flags_t cpflags;
persistent_class
cp_key_class_t persistent_class;
140
Encryption
Encryption Types
key_os_version
cp_key_os_version_t key_os_version;
For information about how the major version number, minor version number, and build number are packed into 32 bits,
see cp_key_os_version_t.
key_revision
cp_key_revision_t key_revision;
unused
Reserved.
uint16_t unused;
Populate this field with zero when you create a new instance of this structure, and preserve its value when you modify
an existing instance.
Encryption Types
Data types used in encryption-related structures.
cp_key_class_t
A protection class.
cp_key_os_version_t
141
Encryption
Protection Classes
1. Store the number 18 (0x12) in the highest two bytes, yielding 0x12000000.
2. Store the character A (0x41) in the next two bytes, yielding 0x12410000.
3. Store the number 391 (0x0187) in the lowest four bytes, yielding 0x12410187.
cp_key_revision_t
crypto_flags_t
These flags are used by the cpflags field of wrapped_crypto_state_t and wrapped_meta_crypto_state_t.
There are currently none defined.
Protection Classes
Constants that indicate the data protection class of a file.
#define PROTECTION_CLASS_DIR_NONE 0
#define PROTECTION_CLASS_A 1
#define PROTECTION_CLASS_B 2
#define PROTECTION_CLASS_C 3
#define PROTECTION_CLASS_D 4
#define PROTECTION_CLASS_F 6
#define PROTECTION_CLASS_M 14
For more information about protection classes, see iOS Security Guide and FileProtectionType.
PROTECTION_CLASS_DIR_NONE
Directory default.
#define PROTECTION_CLASS_DIR_NONE 0
Files with this protection class use their containing directoryʼs default protection class, which is set by the
default_protection_class field of j_inode_val_t.
PROTECTION_CLASS_A
Complete protection.
#define PROTECTION_CLASS_A 1
142
Encryption
Protection Classes
PROTECTION_CLASS_B
#define PROTECTION_CLASS_B 2
PROTECTION_CLASS_C
#define PROTECTION_CLASS_C 3
PROTECTION_CLASS_D
No protection.
#define PROTECTION_CLASS_D 4
PROTECTION_CLASS_F
#define PROTECTION_CLASS_F 6
The behavior of this protection class is the same as Class D, except the key isnʼt stored in any persistent way. This
protection class is suitable for temporary files that arenʼt needed after rebooting the device, such as a virtual machineʼs
swap file.
PROTECTION_CLASS_M
No overview available.
#define PROTECTION_CLASS_M 14
CP_EFFECTIVE_CLASSMASK
All other bits are reserved. Populate those bits with zero when you create a wrapped key, and preserve their value
when you modify an existing wrapped key.
143
Encryption
Encryption Identifiers
Encryption Identifiers
Encryption state objects whose identifier is always the same.
#define CRYPTO_SW_ID 4
#define CRYPTO_RESERVED_5 5
CRYPTO_SW_ID
The identifier of a placeholder encryption state used when software encryption is in use.
#define CRYPTO_SW_ID 4
There is no associated encryption key for this encryption state. All the fields of the corresponding j_crypto_val_t
structure have a value of zero.
CRYPTO_RESERVED_5
Reserved.
#define CRYPTO_RESERVED_5 5
Donʼt create an encryption state object with this identifier. If you find an object with this identifier in production, file a
bug against the Apple File System implementation.
APFS_UNASSIGNED_CRYPTO_ID
As a performance optimization when cloning a file, Appleʼs implementation sets this placeholder value on the clone
and continues to use the original fileʼs encryption state for both that file and its clone. If the clone is modified, a new
encryption state object is created for the clone. Creating a new encryption state object is relatively expensive, and
usually takes longer than the cloning process.
kb_locker_t
A keybag.
struct kb_locker {
uint16_t kl_version;
uint16_t kl_nkeys;
uint32_t kl_nbytes;
uint8_t padding[8];
keybag_entry_t kl_entries[];
};
typedef struct kb_locker kb_locker_t;
#define APFS_KEYBAG_VERSION 2
144
Encryption
kb_locker_t
A keybag stores wrapped encryption keys and information thatʼs needed to unwrap them. The container and each
volume have their own keybag.
The containerʼs keybag stores wrapped VEKs and the location of each volumeʼs keybag. A volumeʼs keybag stores
wrapped KEKs.
kl_version
uint16_t kl_version;
kl_nkeys
uint16_t kl_nkeys;
kl_nbytes
uint32_t kl_nbytes;
padding
Reserved.
uint8_t padding[8];
Populate this field with zero when you create a new keybag, and preserve its value when you modify an existing keybag.
kl_entries
The entries.
keybag_entry_t kl_entries[];
APFS_KEYBAG_VERSION
#define APFS_KEYBAG_VERSION 2
Version one was used during prototyping of Apple File System, and uses an incompatible, undocumented layout. If you
find a keybag in production whose version is less than two, file a bug against the Apple File System implementation.
145
Encryption
keybag_entry_t
keybag_entry_t
An entry in a keybag.
struct keybag_entry {
uuid_t ke_uuid;
uint16_t ke_tag;
uint16_t ke_keylen;
uint8_t padding[4];
uint8_t ke_keydata[];
};
typedef struct keybag_entry keybag_entry_t;
ke_uuid
In a containerʼs keybag, the UUID of a volume; in a volumeʼs keybag, the UUID of a user.
uuid_t ke_uuid;
ke_tag
uint16_t ke_tag;
ke_keylen
uint16_t ke_keylen;
padding
Reserved.
uint8_t padding[4];
Populate this field with zero when you create a new keybag entry, and preserve its value when you modify an existing
entry.
ke_keydata
uint8_t ke_keydata[];
146
Encryption
media_keybag_t
The data stored this field depends on the tag and whether this is an entry in a container or volumeʼs keybag, as
described in Keybag Tags.
APFS_VOL_KEYBAG_ENTRY_MAX_SIZE
APFS_FV_PERSONAL_RECOVERY_KEY_UUID
The user UUID used by a keybag record that contains a personal recovery key.
The personal recovery key is generated during the initial volume-encryption process, and itʼs stored by the user as a
paper printout. You use it the same way you use a userʼs password to unwrap the corresponding KEK.
media_keybag_t
A keybag, wrapped up as a container-layer object.
struct media_keybag {
obj_phys_t mk_obj;
kb_locker_t mk_locker;
};
typedef struct media_keybag media_keybag_t;
mk_obj
obj_phys_t mk_obj;
mk_locker
kb_locker_t mk_locker;
Keybag Tags
A description of what kind of information is stored by a keybag entry.
enum {
KB_TAG_UNKNOWN = 0,
KB_TAG_RESERVED_1 = 1,
KB_TAG_VOLUME_KEY = 2,
KB_TAG_VOLUME_UNLOCK_RECORDS = 3,
KB_TAG_VOLUME_PASSPHRASE_HINT = 4,
KB_TAG_WRAPPING_M_KEY = 5,
147
Encryption
Keybag Tags
KB_TAG_VOLUME_M_KEY = 6,
KB_TAG_RESERVED_F8 = 0xF8
};
KB_TAG_UNKNOWN
Reserved.
KB_TAG_UNKNOWN = 0
This tag never appears on disk. If you find a keybag entry with this tag in production, file a bug against the Apple File
System implementation.
This value isnʼt reserved by Apple; non-Apple implementations of Apple File System can use it in memory. For example,
Appleʼs implementation uses this value as a wildcard that matches any tag.
KB_TAG_RESERVED_1
Reserved.
KB_TAG_RESERVED_1 = 1
Donʼt create keybag entries with this tag, but preserve any existing entries.
KB_TAG_VOLUME_KEY
KB_TAG_VOLUME_KEY = 2
KB_TAG_VOLUME_UNLOCK_RECORDS
In a containerʼs keybag, the key data stores the location of the volumeʼs keybag; in a volume keybag, the key data
stores a wrapped KEK.
KB_TAG_VOLUME_UNLOCK_RECORDS = 3
The volumeʼs keybag location is stored as an instance of prange_t; the data at that location is an instance of
kb_locker_t.
KB_TAG_VOLUME_PASSPHRASE_HINT
KB_TAG_VOLUME_PASSPHRASE_HINT = 4
This tag is valid only in a volumeʼs keybag, and itʼs used only on devices running macOS.
148
Encryption
Keybag Tags
KB_TAG_WRAPPING_M_KEY
The key data stores a key thatʼs used to wrap a media key.
KB_TAG_WRAPPING_M_KEY = 5
KB_TAG_VOLUME_M_KEY
The key data stores a key thatʼs used to wrap media keys on this volume.
KB_TAG_VOLUME_M_KEY = 6
KB_TAG_RESERVED_F8
Reserved.
KB_TAG_RESERVED_F8 = 0xF8
Donʼt create keybag entries with this tag, but preserve any existing entries.
149
Sealed Volumes
Sealed volumes contain a hash of their file system, which can be compared to their current content to determine
whether the volume has been modified after it was sealed, or compared to a known value to determine whether the
volume contains the expected content. On a sealed volume, all of the following must be true:
The B-tree that stores the volumeʼs file system also stores a hash of its contents. A hashed B-tree differs from an
nonhashed B-tree as follows:
Conceptually, the hashed B-trees used by sealed volumes are similar to Merkle trees. However, unlike Merkle trees,
these hashed B-trees store data as well as a hash of that data.
integrity_meta_phys_t
Integrity metadata for a sealed volume.
struct integrity_meta_phys {
obj_phys_t im_o;
uint32_t im_version;
uint32_t im_flags;
apfs_hash_type_t im_hash_type;
uint32_t im_root_hash_offset;
xid_t im_broken_xid;
uint64_t im_reserved[9];
} __attribute__((packed));
typedef struct integrity_meta_phys integrity_meta_phys_t;
im_o
obj_phys_t im_o;
im_version
uint32_t im_version;
150
Sealed Volumes
Integrity Metadata Version Constants
The value of this field must be one of the constants listed in Integrity Metadata Version Constants.
im_flags
uint32_t im_flags;
For the values used in this bit field, see Integrity Metadata Flags.
im_hash_type
apfs_hash_type_t im_hash_type;
im_root_hash_offset
The offset, in bytes, of the root hash relative to the start of this integrity metadata object.
uint32_t im_root_hash_offset;
im_broken_xid
xid_t im_broken_xid;
When a sealed volume is modified, breaking its seal, that transaction identifier is recorded in this field and the
APFS_SEAL_BROKEN flag is set. Otherwise, the value of this field is zero.
im_reserved
Reserved.
uint64_t im_reserved[9];
enum {
INTEGRITY_META_VERSION_INVALID = 0,
INTEGRITY_META_VERSION_1 = 1,
INTEGRITY_META_VERSION_2 = 2,
INTEGRITY_META_VERSION_HIGHEST = INTEGRITY_META_VERSION_2
151
Sealed Volumes
Integrity Metadata Flags
};
These constants are used as the value of the im_version field of the integrity_meta_phys_t structure.
INTEGRITY_META_VERSION_INVALID
An invalid version.
INTEGRITY_META_VERSION_INVALID = 0
INTEGRITY_META_VERSION_1
INTEGRITY_META_VERSION_1 = 1
INTEGRITY_META_VERSION_1
INTEGRITY_META_VERSION_2 = 2
INTEGRITY_META_VERSION_HIGHEST
INTEGRITY_META_VERSION_HIGHEST = INTEGRITY_META_VERSION_2
APFS_SEAL_BROKEN
The volume was modified after being sealed, breaking its seal.
If this flag is set, the im_broken_xid field of integrity_meta_phys_t contains the transaction identifier for the
modification that broke the seal.
apfs_hash_type_t
Constants used to identify hash algorithms.
typedef enum {
APFS_HASH_INVALID = 0,
APFS_HASH_SHA256 = 0x1,
APFS_HASH_SHA512_256 = 0x2,
APFS_HASH_SHA384 = 0x3,
APFS_HASH_SHA512 = 0x4,
152
Sealed Volumes
apfs_hash_type_t
APFS_HASH_MIN = APFS_HASH_SHA256,
APFS_HASH_MAX = APFS_HASH_SHA512,
APFS_HASH_DEFAULT = APFS_HASH_SHA256,
} apfs_hash_type_t;
#define APFS_HASH_CCSHA256_SIZE 32
#define APFS_HASH_CCSHA512_256_SIZE 32
#define APFS_HASH_CCSHA384_SIZE 48
#define APFS_HASH_CCSHA512_SIZE 64
#define APFS_HASH_MAX_SIZE 64
These constants are used as the value of the im_hash_type field of the integrity_meta_phys_t structure. The
corresponding hash size is used as the value of the hash_size field of the j_file_data_hash_val_t structure.
APFS_HASH_INVALID
APFS_HASH_INVALID = 0
APFS_HASH_SHA256
APFS_HASH_SHA256 = 0x1
APFS_HASH_SHA512_256
APFS_HASH_SHA512_256 = 0x2,
APFS_HASH_SHA384
APFS_HASH_SHA384 = 0x3
APFS_HASH_SHA512
APFS_HASH_SHA512 = 0x4
APFS_HASH_MIN
APFS_HASH_MIN = APFS_HASH_SHA256
153
Sealed Volumes
fext_tree_key_t
APFS_HASH_MAX
APFS_HASH_MAX = APFS_HASH_SHA512
APFS_HASH_DEFAULT
APFS_HASH_DEFAULT = APFS_HASH_SHA256
APFS_HASH_CCSHA256_SIZE
#define APFS_HASH_CCSHA256_SIZE 32
APFS_HASH_CCSHA512_256_SIZE
#define APFS_HASH_CCSHA512_256_SIZE 32
APFS_HASH_CCSHA384_SIZE
#define APFS_HASH_CCSHA384_SIZE 48
APFS_HASH_CCSHA512_SIZE
#define APFS_HASH_CCSHA512_SIZE 64
APFS_HASH_MAX_SIZE
#define APFS_HASH_MAX_SIZE 64
fext_tree_key_t
The key half of a record from a file extent tree.
struct fext_tree_key {
uint64_t private_id;
uint64_t logical_addr;
} __attribute__((packed));
typedef struct fext_tree_key fext_tree_key_t;
154
Sealed Volumes
fext_tree_val_t
private_id
uint64_t private_id;
This value corresponds the object identifier portion of the obj_id_and_type field of j_key_t.
logical_addr
The offset within the fileʼs data, in bytes, for the data stored in this extent.
uint64_t logical_addr;
fext_tree_val_t
The value half of a record from a file extent tree.
struct fext_tree_val {
uint64_t len_and_flags;
uint64_t phys_block_num;
} __attribute__((packed));
typedef struct fext_tree_val fext_tree_val_t;
len_and_flags
A bit field that contains the length of the extent and its flags.
uint64_t len_and_flags;
The extentʼs length is a uint64_t value, accessed as len_and_kind & J_FILE_EXTENT_LEN_MASK, and
measured in bytes. The length must be a multiple of the block size defined by the nx_block_size field of
nx_superblock_t. The extentʼs flags are accessed as (len_and_kind & J_FILE_EXTENT_FLAG_MASK) >>
J_FILE_EXTENT_FLAG_SHIFT.
phys_block_num
uint64_t phys_block_num;
j_file_info_key_t
The key half of a file-info record.
struct j_file_info_key {
j_key_t hdr;
uint64_t info_and_lba;
} __attribute__((packed));
typedef struct j_key_t j_file_info_key_t;
155
Sealed Volumes
j_file_info_val_t
hdr
j_key_t hdr;
The object identifier in the header is the file-system objectʼs identifier. The type in the header is always
APFS_TYPE_FILE_INFO.
info_and_lba
uint64_t info_and_lba;
The address is a paddr_t value accessed as info_and_lba & J_FILE_INFO_LBA_MASK. The type is a
j_obj_file_info_type value accessed as (info_and_lba & J_FILE_INFO_TYPE_MASK) >> J_FILE_
INFO_TYPE_SHIFT.
J_FILE_INFO_LBA_MASK
J_FILE_INFO_TYPE_MASK
J_FILE_INFO_TYPE_SHIFT
#define J_FILE_INFO_TYPE_SHIFT 56
j_file_info_val_t
The value half of a file-info record.
struct j_file_info_val {
union {
j_file_data_hash_val_t dhash;
};
} __attribute__((packed));
typedef struct j_file_data_hash_val_t j_file_info_val_t;
Use the type stored in the j_file_info_key_t half of this record to determine which of the unionʼs fields to use.
156
Sealed Volumes
j_obj_file_info_type
dhash
j_file_data_hash_val_t dhash;
Use this field of the union if the type stored in the info_and_lba field of j_file_info_val_t is APFS_FILE_
INFO_DATA_HASH.
j_obj_file_info_type
The type of a file-info record.
typedef enum {
APFS_FILE_INFO_DATA_HASH = 1,
} j_obj_file_info_type;
These values are used by the info_and_lba field of j_file_info_key_t, to indicate how to interpret the data in
the corresponding j_file_info_val_t.
APFS_FILE_INFO_DATA_HASH
APFS_FILE_INFO_DATA_HASH = 1
j_file_data_hash_val_t
A hash of file data.
struct j_file_data_hash_val {
uint16_t hashed_len;
uint8_t hash_size;
uint8_t hash[0];
} __attribute__((packed));
typedef struct j_file_data_hash_val j_file_data_hash_val_t;
hashed_len
uint16_t hashed_len;
hash_size
uint8_t hash_size;
The value of this field must match the constant that corresponds to the hash algorithm specified in the im_hash_type
field of integrity_meta_phys_t. For a list of algorithms and hash sizes, see apfs_hash_type_t.
157
Sealed Volumes
j_file_data_hash_val_t
hash
uint8_t hash[0];
158
Space Manager
The space manager allocates and frees blocks where objects and file data can be stored. Thereʼs exactly one instance
of this structure in a container.
chunk_info_t
No overview available.
struct chunk_info {
uint64_t ci_xid;
uint64_t ci_addr;
uint32_t ci_block_count;
uint32_t ci_free_count;
paddr_t ci_bitmap_addr;
};
typedef struct chunk_info chunk_info_t;
chunk_info_block
A block that contains an array of chunk-info structures.
struct chunk_info_block {
obj_phys_t cib_o;
uint32_t cib_index;
uint32_t cib_chunk_info_count;
chunk_info_t cib_chunk_info[];
};
typedef struct chunk_info_block chunk_info_block_t;
No overview available.
cib_addr_block
A block that contains an array of chunk-info block addresses.
struct cib_addr_block {
obj_phys_t cab_o;
uint32_t cab_index;
uint32_t cab_cib_count;
paddr_t cab_cib_addr[];
};
typedef struct cib_addr_block cib_addr_block_t;
No overview available.
spaceman_free_queue_entry_t
No overview available.
159
Space Manager
spaceman_free_queue_key_t
struct spaceman_free_queue_entry {
spaceman_free_queue_key_t sfqe_key;
spaceman_free_queue_val_t sfqe_count;
};
typedef struct spaceman_free_queue_entry spaceman_free_queue_entry_t;
spaceman_free_queue_key_t
No overview available.
struct spaceman_free_queue_key {
xid_t sfqk_xid;
paddr_t sfqk_paddr;
};
typedef struct spaceman_free_queue_key spaceman_free_queue_key_t;
spaceman_free_queue_t
No overview available.
struct spaceman_free_queue {
uint64_t sfq_count;
oid_t sfq_tree_oid;
xid_t sfq_oldest_xid;
uint16_t sfq_tree_node_limit;
uint16_t sfq_pad16;
uint32_t sfq_pad32;
uint64_t sfq_reserved;
};
typedef struct spaceman_free_queue spaceman_free_queue_t;
spaceman_device_t
No overview available.
struct spaceman_device {
uint64_t sm_block_count;
uint64_t sm_chunk_count;
uint32_t sm_cib_count;
uint32_t sm_cab_count;
uint64_t sm_free_count;
uint32_t sm_addr_offset;
uint32_t sm_reserved;
uint64_t sm_reserved2;
};
typedef struct spaceman_device spaceman_device_t;
160
Space Manager
spaceman_allocation_zone_boundaries_t
spaceman_allocation_zone_boundaries_t
No overview available.
struct spaceman_allocation_zone_boundaries {
uint64_t saz_zone_start;
uint64_t saz_zone_end;
};
typedef struct spaceman_allocation_zone_boundaries
spaceman_allocation_zone_boundaries_t;
spaceman_allocation_zone_info_phys_t
No overview available.
struct spaceman_allocation_zone_info_phys {
spaceman_allocation_zone_boundaries_t saz_current_boundaries;
spaceman_allocation_zone_boundaries_t
saz_previous_boundaries[SM_ALLOCZONE_NUM_PREVIOUS_BOUNDARIES];
uint16_t saz_zone_id;
uint16_t saz_previous_boundary_index;
uint32_t saz_reserved;
};
typedef struct spaceman_allocation_zone_info_phys
spaceman_allocation_zone_info_phys_t;
#define SM_ALLOCZONE_INVALID_END_BOUNDARY 0
#define SM_ALLOCZONE_NUM_PREVIOUS_BOUNDARIES 7
spaceman_datazone_info_phys_t
No overview available.
struct spaceman_datazone_info_phys {
spaceman_allocation_zone_info_phys_t
sdz_allocation_zones[SD_COUNT][SM_DATAZONE_ALLOCZONE_COUNT];
};
typedef struct spaceman_datazone_info_phys spaceman_datazone_info_phys_t;
#define SM_DATAZONE_ALLOCZONE_COUNT 8
spaceman_phys_t
No overview available.
struct spaceman_phys {
obj_phys_t sm_o;
uint32_t sm_block_size;
uint32_t sm_blocks_per_chunk;
uint32_t sm_chunks_per_cib;
161
Space Manager
sfq
uint32_t sm_cibs_per_cab;
spaceman_device_t sm_dev[SD_COUNT];
uint32_t sm_flags;
uint32_t sm_ip_bm_tx_multiplier;
uint64_t sm_ip_block_count;
uint32_t sm_ip_bm_size_in_blocks;
uint32_t sm_ip_bm_block_count;
paddr_t sm_ip_bm_base;
paddr_t sm_ip_base;
uint64_t sm_fs_reserve_block_count;
uint64_t sm_fs_reserve_alloc_count;
spaceman_free_queue_t sm_fq[SFQ_COUNT];
uint16_t sm_ip_bm_free_head;
uint16_t sm_ip_bm_free_tail;
uint32_t sm_ip_bm_xid_offset;
uint32_t sm_ip_bitmap_offset;
uint32_t sm_ip_bm_free_next_offset;
uint32_t sm_version;
uint32_t sm_struct_size;
spaceman_datazone_info_phys_t sm_datazone;
};
typedef struct spaceman_phys spaceman_phys_t;
sfq
No overview available.
enum sfq {
SFQ_IP = 0,
SFQ_MAIN = 1,
SFQ_TIER2 = 2,
SFQ_COUNT = 3
};
smdev
No overview available.
enum smdev {
SD_MAIN = 0,
SD_TIER2 = 1,
SD_COUNT = 2
};
162
Space Manager
Internal-Pool Bitmap
Internal-Pool Bitmap
No overview available.
#define SPACEMAN_IP_BM_TX_MULTIPLIER 16
#define SPACEMAN_IP_BM_INDEX_INVALID 0xffff
#define SPACEMAN_IP_BM_BLOCK_COUNT_MAX 0xfffe
163
Reaper
The reaper is a mechanism that allows large objects to be deleted over a period spanning multiple transactions. Thereʼs
exactly one instance of this structure in a container.
nx_reaper_phys_t
No overview available.
struct nx_reaper_phys {
obj_phys_t nr_o;
uint64_t nr_next_reap_id;
uint64_t nr_completed_id;
oid_t nr_head;
oid_t nr_tail;
uint32_t nr_flags;
uint32_t nr_rlcount;
uint32_t nr_type;
uint32_t nr_size;
oid_t nr_fs_oid;
oid_t nr_oid;
xid_t nr_xid;
uint32_t nr_nrle_flags;
uint32_t nr_state_buffer_size;
uint8_t nr_state_buffer[];
};
typedef struct nx_reaper_phys nx_reaper_phys_t;
nx_reap_list_phys_t
No overview available.
struct nx_reap_list_phys {
obj_phys_t nrl_o;
oid_t nrl_next;
uint32_t nrl_flags;
uint32_t nrl_max;
uint32_t nrl_count;
uint32_t nrl_first;
uint32_t nrl_last;
uint32_t nrl_free;
nx_reap_list_entry_t nrl_entries[];
};
typedef struct nx_reap_list_phys nx_reap_list_phys_t;
nx_reap_list_entry_t
No overview available.
164
Reaper
Volume Reaper States
struct nx_reap_list_entry {
uint32_t nrle_next;
uint32_t nrle_flags;
uint32_t nrle_type;
uint32_t nrle_size;
oid_t nrle_fs_oid;
oid_t nrle_oid;
xid_t nrle_xid;
};
typedef struct nx_reap_list_entry nx_reap_list_entry_t;
enum {
APFS_REAP_PHASE_START = 0,
APFS_REAP_PHASE_SNAPSHOTS = 1,
APFS_REAP_PHASE_ACTIVE_FS = 2,
APFS_REAP_PHASE_DESTROY_OMAP = 3,
APFS_REAP_PHASE_DONE = 4
};
Reaper Flags
The flags used for general information about a reaper.
NR_BHM_FLAG
Reserved.
NR_CONTINUE
165
Reaper
Reaper List Flags
omap_reap_state_t
State used when reaping an object map.
struct omap_reap_state {
uint32_t omr_phase;
omap_key_t omr_ok;
};
typedef struct omap_reap_state omap_reap_state_t;
The reaper uses the state thatʼs stored in this structure to resume after an interruption.
omr_phase
uint32_t omr_phase;
For the values used in this field, see Object Map Reaper Phases.
omr_ok
The key of the most recently freed entry in the object map.
omap_key_t omr_ok;
This field allows the reaper to resume after the last entry it processed.
omap_cleanup_state_t
State used when reaping to clean up deleted snapshots.
struct omap_cleanup_state {
uint32_t omc_cleaning;
uint32_t omc_omsflags;
xid_t omc_sxidprev;
xid_t omc_sxidstart;
xid_t omc_sxidend;
xid_t omc_sxidnext;
omap_key_t omc_curkey;
};
typedef struct omap_cleanup_state omap_cleanup_state_t;
166
Reaper
apfs_reap_state_t
omc_cleaning
A flag that indicates whether the structure has valid data in it.
uint32_t omc_cleaning;
If the value of this field is zero, the structure has been allocated and zeroed, but doesnʼt yet contain valid data. Other-
wise, the structure is valid.
omc_omsflags
uint32_t omc_omsflags;
The value for this field is the same as the value of the snapshotʼs omap_snapshot_t.oms_flags field.
omc_sxidprev
The transaction identifier of the snapshot prior to the snapshots being deleted.
xid_t omc_sxidprev;
omc_sxidstart
xid_t omc_sxidstart;
omc_sxidend
xid_t omc_sxidend;
omc_sxidnext
The transaction identifier of the snapshot after the snapshots being deleted.
xid_t omc_sxidnext;
omc_curkey
omap_key_t omc_curkey;
apfs_reap_state_t
No overview available.
struct apfs_reap_state {
uint64_t last_pbn;
xid_t cur_snap_xid;
uint32_t phase;
167
Reaper
apfs_reap_state_t
} __attribute__((packed));
typedef struct apfs_reap_state apfs_reap_state_t;
168
Encryption Rolling
No overview available.
er_state_phys_t
No overview available.
struct er_state_phys {
er_state_phys_header_t ersb_header;
uint64_t ersb_flags;
uint64_t ersb_snap_xid;
uint64_t ersb_current_fext_obj_id;
uint64_t ersb_file_offset;
uint64_t ersb_progress;
uint64_t ersb_total_blk_to_encrypt;
oid_t ersb_blockmap_oid;
uint64_t ersb_tidemark_obj_id;
uint64_t ersb_recovery_extents_count;
oid_t ersb_recovery_list_oid;
uint64_t ersb_recovery_length;
};
typedef struct er_state_phys er_state_phys_t;
struct er_state_phys_v1 {
er_state_phys_header_t ersb_header;
uint64_t ersb_flags;
uint64_t ersb_snap_xid;
uint64_t ersb_current_fext_obj_id;
uint64_t ersb_file_offset;
uint64_t ersb_fext_pbn;
uint64_t ersb_paddr;
uint64_t ersb_progress;
uint64_t ersb_total_blk_to_encrypt;
uint64_t ersb_blockmap_oid;
uint32_t ersb_checksum_count;
uint32_t ersb_reserved;
uint64_t ersb_fext_cid;
uint8_t ersb_checksum[0];
};
typedef struct er_state_phys er_state_phys_v1_t;
struct er_state_phys_header {
obj_phys_t ersb_o;
uint32_t ersb_magic;
uint32_t ersb_version;
};
169
Encryption Rolling
er_phase_t
er_phase_t
No overview available.
enum er_phase_enum {
ER_PHASE_OMAP_ROLL = 1,
ER_PHASE_DATA_ROLL = 2,
ER_PHASE_SNAP_ROLL = 3,
};
typedef enum er_phase_enum er_phase_t;
er_recovery_block_phys_t
No overview available.
struct er_recovery_block_phys {
obj_phys_t erb_o;
uint64_t erb_offset;
oid_t erb_next_oid;
uint8_t erb_data[0];
};
typedef struct er_recovery_block_phys er_recovery_block_phys_t;
gbitmap_block_phys_t
No overview available.
struct gbitmap_block_phys {
obj_phys_t bmb_o;
uint64_t bmb_field[0];
};
typedef struct gbitmap_block_phys gbitmap_block_phys_t;
gbitmap_phys_t
No overview available.
struct gbitmap_phys {
obj_phys_t bm_o;
oid_t bm_tree_oid;
uint64_t bm_bit_count;
uint64_t bm_flags;
};
typedef struct gbitmap_phys gbitmap_phys_t;
170
Encryption Rolling
Encryption Rolling Flags
enum {
ER_512B_BLOCKSIZE = 0,
ER_2KiB_BLOCKSIZE = 1,
ER_4KiB_BLOCKSIZE = 2,
ER_8KiB_BLOCKSIZE = 3,
ER_16KiB_BLOCKSIZE = 4,
ER_32KiB_BLOCKSIZE = 5,
ER_64KiB_BLOCKSIZE = 6,
};
Encryption-Rolling Constants
No overview available.
#define ER_CHECKSUM_LENGTH 8
#define ER_MAGIC 'FLAB'
#define ER_VERSION 1
#define ER_MAX_CHECKSUM_COUNT_SHIFT 16
#define ER_CUR_CHECKSUM_COUNT_MASK 0x0000FFFF
171
Fusion
No overview available.
fusion_wbc_phys_t
No overview available.
typedef struct {
obj_phys_t fwp_objHdr;
uint64_t fwp_version;
oid_t fwp_listHeadOid;
oid_t fwp_listTailOid;
uint64_t fwp_stableHeadOffset;
uint64_t fwp_stableTailOffset;
uint32_t fwp_listBlocksCount;
uint32_t fwp_reserved;
uint64_t fwp_usedByRC;
prange_t fwp_rcStash;
} fusion_wbc_phys_t;
fusion_wbc_list_entry_t
No overview available.
typedef struct {
paddr_t fwle_wbcLba;
paddr_t fwle_targetLba;
uint64_t fwle_length;
} fusion_wbc_list_entry_t;
fusion_wbc_list_phys_t
No overview available.
typedef struct {
obj_phys_t fwlp_objHdr;
uint64_t fwlp_version;
uint64_t fwlp_tailOffset;
uint32_t fwlp_indexBegin;
uint32_t fwlp_indexEnd;
uint32_t fwlp_indexMax;
uint32_t fwlp_reserved;
fusion_wbc_list_entry_t fwlp_listEntries[];
} fusion_wbc_list_phys_t;
This mapping keeps track of data from the hard drive thatʼs cached on the solid-state drive. For read caching, the
same data is stored on both the hard drive and the solid-state drive. For write caching, the data is stored on the solid-
172
Fusion
Address Markers
state drive, but space for the data has been allocated on the hard drive, and the data will eventually be copied to that
space.
Address Markers
No overview available.
#define FUSION_TIER2_DEVICE_BLOCK_ADDR(_blksize) \
(FUSION_TIER2_DEVICE_BYTE_ADDR >> __builtin_ctzl(_blksize))
fusion_mt_key_t
No overview available.
fusion_mt_val_t
No overview available.
typedef struct {
paddr_t fmv_lba;
uint32_t fmv_length;
uint32_t fmv_flags;
} fusion_mt_val_t;
173
Symbol Index
APFS_COW_EXEMPT_COUNT_NAME 98 APFS_KIND_DEAD 87
APFS_FEATURE_DEFRAG 67 APFS_KIND_INVALID 88
APFS_FEATURE_DEFRAG_PRERELEASE 67 APFS_KIND_NEW 87
APFS_FEATURE_HARDLINK_MAP_RECORDS 67 APFS_KIND_UPDATE 87
APFS_FEATURE_STRICTATIME 67 APFS_KIND_UPDATE_REFCNT 88
APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE 68 APFS_MAGIC 60
APFS_FILE_INFO_DATA_HASH 157 APFS_MAX_HIST 60
APFS_FS_ALWAYS_CHECK_EXTENTREF 62 apfs_modified_by_t 60
APFS_FS_CRYPTOFLAGS 63 apfs_reap_state_t 167
APFS_FS_FLAGS_VALID_MASK 63 APFS_SEAL_BROKEN 152
APFS_FS_ONEKEY 62 apfs_superblock_t 51
APFS_FS_RESERVED_100 63 APFS_SUPPORTED_FEATURES_MASK 68
APFS_FS_RESERVED_2 62 APFS_SUPPORTED_INCOMPAT_MASK 70
APFS_FS_RESERVED_4 62 APFS_SUPPORTED_ROCOMPAT_MASK 68
APFS_FS_RESERVED_80 63 APFS_TYPE_ANY 84
APFS_FS_RUN_SPILLOVER_CLEANER 62 APFS_TYPE_CRYPTO_STATE 85
APFS_FS_SPILLEDOVER 62 APFS_TYPE_DIR_REC 86
APFS_FS_UNENCRYPTED 62 APFS_TYPE_DIR_STATS 86
APFS_FV_PERSONAL_RECOVERY_KEY_UUID 147 APFS_TYPE_DSTREAM_ID 85
APFS_GPT_PARTITION_UUID 25 APFS_TYPE_EXTENT 85
APFS_HASH_CCSHA256_SIZE 154 APFS_TYPE_FILE_EXTENT 85
APFS_HASH_CCSHA384_SIZE 154 APFS_TYPE_FILE_INFO 86
APFS_HASH_CCSHA512_256_SIZE 154 APFS_TYPE_INODE 85
APFS_HASH_CCSHA512_SIZE 154 APFS_TYPE_INVALID 87
APFS_HASH_DEFAULT 154 APFS_TYPE_MAX 86
APFS_HASH_INVALID 153 APFS_TYPE_MAX_VALID 86
APFS_HASH_MAX 154 APFS_TYPE_SIBLING_LINK 85
APFS_HASH_MAX_SIZE 154 APFS_TYPE_SIBLING_MAP 86
APFS_HASH_MIN 153 APFS_TYPE_SNAP_METADATA 84
APFS_HASH_SHA256 153 APFS_TYPE_SNAP_NAME 86
APFS_HASH_SHA384 153 APFS_TYPE_XATTR 85
APFS_HASH_SHA512 153 APFS_UNASSIGNED_CRYPTO_ID 144
APFS_HASH_SHA512_256 153 APFS_VALID_INTERNAL_INODE_FLAGS 94
apfs_hash_type_t 152 APFS_VOL_KEYBAG_ENTRY_MAX_SIZE 147
APFS_INCOMPAT_CASE_INSENSITIVE 69 APFS_VOL_ROLE_BACKUP 66
APFS_INCOMPAT_DATALESS_SNAPS 69 APFS_VOL_ROLE_BASEBAND 65
APFS_INCOMPAT_ENC_ROLLED 69 APFS_VOL_ROLE_DATA 65
APFS_INCOMPAT_INCOMPLETE_RESTORE 69 APFS_VOL_ROLE_ENTERPRISE 66
APFS_INCOMPAT_NORMALIZATION_INSENSITIVE 69 APFS_VOL_ROLE_HARDWARE 65
APFS_INCOMPAT_RESERVED_40 70 APFS_VOL_ROLE_INSTALLER 65
APFS_INCOMPAT_SEALED_VOLUME 69 APFS_VOL_ROLE_NONE 64
APFS_INODE_PINNED_MASK 94 APFS_VOL_ROLE_PREBOOT 65
APFS_KEYBAG_VERSION 145 APFS_VOL_ROLE_PRELOGIN 66
APFS_KIND_ANY 87 APFS_VOL_ROLE_RECOVERY 64
174
Symbol Index
175
Symbol Index
INODE_HAS_SECURITY_EA 90 j_inode_val_t 73
INODE_HAS_UNCOMPRESSED_SIZE 92 j_key_t 72
INODE_INHERITED_INTERNAL_FLAGS 93 j_obj_file_info_type 157
INODE_IS_APFS_PRIVATE 89 j_obj_kinds 87
INODE_IS_PURGEABLE 93 j_obj_types 84
INODE_IS_SPARSE 91 j_phys_ext_key_t 102
INODE_IS_SYNC_ROOT 93 j_phys_ext_val_t 102
INODE_MAINTAIN_DIR_STATS 89 j_sibling_key_t 115
INODE_NO_RSRC_FORK 92 j_sibling_map_key_t 116
INODE_PINNED_TO_MAIN 91 j_sibling_map_val_t 116
INODE_PINNED_TO_TIER2 92 j_sibling_val_t 115
INODE_PROT_CLASS_EXPLICIT 90 j_snap_metadata_key_t 117
INODE_SNAPSHOT_COW_EXEMPTION 93 j_snap_metadata_val_t 117
INODE_WANTS_TO_BE_PURGEABLE 93 j_snap_name_key_t 119
INODE_WAS_CLONED 90 j_snap_name_val_t 119
INODE_WAS_EVER_CLONED 91 j_xattr_dstream_t 106
integrity_meta_phys_t 150 j_xattr_flags 94
INTEGRITY_META_VERSION_1 152 j_xattr_key_t 82
INTEGRITY_META_VERSION_1 152 j_xattr_val_t 82
INTEGRITY_META_VERSION_HIGHEST 152 kb_locker_t 144
INTEGRITY_META_VERSION_INVALID 152 KB_TAG_RESERVED_1 148
INVALID_INO_NUM 96 KB_TAG_RESERVED_F8 149
j_crypto_key_t 137 KB_TAG_UNKNOWN 148
j_crypto_val_t 137 KB_TAG_VOLUME_KEY 148
j_dir_stats_key_t 80 KB_TAG_VOLUME_M_KEY 149
j_dir_stats_val_t 81 KB_TAG_VOLUME_PASSPHRASE_HINT 148
J_DREC_HASH_MASK 79 KB_TAG_VOLUME_UNLOCK_RECORDS 148
J_DREC_HASH_SHIFT 79 KB_TAG_WRAPPING_M_KEY 149
j_drec_hashed_key_t 78 keybag_entry_t 146
j_drec_key_t 78 kvloc_t 128
J_DREC_LEN_MASK 79 kvoff_t 129
j_drec_val_t 79 MAX_CKSUM_SIZE 11
j_dstream_id_key_t 105 media_keybag_t 147
j_dstream_id_val_t 105 MIN_DOC_ID 98
j_dstream_t 106 MIN_USER_INO_NUM 97
j_file_data_hash_val_t 157 nloc_t 128
J_FILE_EXTENT_FLAG_MASK 105 NR_BHM_FLAG 165
J_FILE_EXTENT_FLAG_SHIFT 105 NR_CONTINUE 165
j_file_extent_key_t 103 NX_CNTR_OBJ_CKSUM_FAIL 40
J_FILE_EXTENT_LEN_MASK 105 NX_CNTR_OBJ_CKSUM_SET 40
j_file_extent_val_t 104 nx_counter_id_t 39
j_file_info_key_t 155 NX_CRYPTO_SW 37
J_FILE_INFO_LBA_MASK 156 NX_DEFAULT_BLOCK_SIZE 39
J_FILE_INFO_TYPE_MASK 156 NX_EFI_JUMPSTART_MAGIC 25
J_FILE_INFO_TYPE_SHIFT 156 nx_efi_jumpstart_t 24
j_file_info_val_t 156 NX_EFI_JUMPSTART_VERSION 25
j_inode_flags 88 NX_EPH_INFO_COUNT 35
j_inode_key_t 73 NX_EPH_INFO_VERSION_1 36
176
Symbol Index
NX_EPH_MIN_BLOCK_COUNT 36 OBJECT_TYPE_FUSION_MIDDLE_TREE 17
NX_FEATURE_DEFRAG 37 OBJECT_TYPE_GBITMAP 18
NX_FEATURE_LCFD 37 OBJECT_TYPE_GBITMAP_BLOCK 18
NX_INCOMPAT_FUSION 38 OBJECT_TYPE_GBITMAP_TREE 18
NX_INCOMPAT_VERSION1 38 OBJECT_TYPE_INTEGRITY_META 19
NX_INCOMPAT_VERSION2 38 OBJECT_TYPE_INVALID 19
NX_MAGIC 35 OBJECT_TYPE_MASK 13
NX_MAX_FILE_SYSTEM_EPH_STRUCTS 36 OBJECT_TYPE_MEDIA_KEYBAG 19
NX_MAX_FILE_SYSTEMS 35 OBJECT_TYPE_NX_FUSION_WBC 18
NX_MAXIMUM_BLOCK_SIZE 39 OBJECT_TYPE_NX_FUSION_WBC_LIST 18
NX_MINIMUM_BLOCK_SIZE 39 OBJECT_TYPE_NX_REAP_LIST 17
NX_MINIMUM_CONTAINER_SIZE 39 OBJECT_TYPE_NX_REAPER 17
NX_NUM_COUNTERS 40 OBJECT_TYPE_NX_SUPERBLOCK 15
nx_reap_list_entry_t 164 OBJECT_TYPE_OMAP 16
nx_reap_list_phys_t 164 OBJECT_TYPE_OMAP_SNAPSHOT 17
nx_reaper_phys_t 164 OBJECT_TYPE_RESERVED_20 19
NX_RESERVED_1 36 OBJECT_TYPE_SNAP_META_EXT 18
NX_RESERVED_2 37 OBJECT_TYPE_SNAPMETATREE 17
nx_superblock_t 27 OBJECT_TYPE_SPACEMAN 15
NX_SUPPORTED_FEATURES_MASK 37 OBJECT_TYPE_SPACEMAN_BITMAP 16
NX_SUPPORTED_INCOMPAT_MASK 39 OBJECT_TYPE_SPACEMAN_CAB 15
NX_SUPPORTED_ROCOMPAT_MASK 38 OBJECT_TYPE_SPACEMAN_CIB 15
NX_TX_MIN_CHECKPOINT_COUNT 36 OBJECT_TYPE_SPACEMAN_FREE_QUEUE 16
OBJ_ENCRYPTED 21 OBJECT_TYPE_TEST 19
OBJ_EPHEMERAL 20 OBJECT_TYPE_VOLUME_KEYBAG 19
OBJ_ID_MASK 73 OID_INVALID 13
OBJ_NOHEADER 20 OID_NX_SUPERBLOCK 13
OBJ_NONPERSISTENT 21 OID_RESERVED_COUNT 13
obj_phys_t 10 omap_cleanup_state_t 166
OBJ_PHYSICAL 20 OMAP_CRYPTO_GENERATION 50
OBJ_STORAGETYPE_MASK 14 OMAP_DECRYPTING 49
OBJ_TYPE_MASK 73 OMAP_ENCRYPTING 49
OBJ_TYPE_SHIFT 73 omap_key_t 46
OBJ_VIRTUAL 20 OMAP_KEYROLLING 50
OBJECT_TYPE_BLOCKREFTREE 17 OMAP_MANUALLY_MANAGED 49
OBJECT_TYPE_BTREE 15 OMAP_MAX_SNAP_COUNT 50
OBJECT_TYPE_BTREE_NODE 15 omap_phys_t 44
OBJECT_TYPE_CHECKPOINT_MAP 16 OMAP_REAP_PHASE_MAP_TREE 50
OBJECT_TYPE_CONTAINER_KEYBAG 19 OMAP_REAP_PHASE_SNAPSHOT_TREE 50
OBJECT_TYPE_EFI_JUMPSTART 17 omap_reap_state_t 166
OBJECT_TYPE_ER_RECOVERY_BLOCK 18 OMAP_SNAPSHOT_DELETED 49
OBJECT_TYPE_ER_STATE 18 OMAP_SNAPSHOT_REVERTED 49
OBJECT_TYPE_EXTENT_LIST_TREE 16 omap_snapshot_t 47
OBJECT_TYPE_FEXT_TREE 19 OMAP_VAL_CRYPTO_GENERATION 48
OBJECT_TYPE_FLAGS_DEFINED_MASK 14 OMAP_VAL_DELETED 48
OBJECT_TYPE_FLAGS_MASK 13 OMAP_VAL_ENCRYPTED 48
OBJECT_TYPE_FS 16 OMAP_VAL_NOHEADER 48
OBJECT_TYPE_FSTREE 16 OMAP_VAL_SAVED 48
177
Symbol Index
178
Revision History
2020-06-22
APFS_COW_EXEMPT_COUNT_NAME BTNODE_NOHEADER
APFS_FS_RESERVED_100 btn_index_node_val_t
APFS_FS_RESERVED_80 BTREE_HASHED
APFS_INCOMPAT_SEALED_VOLUME BTREE_NOHEADER
apfs_superblock_t.apfs_fext_tree_oid INODE_SNAPSHOT_COW_EXEMPTION
apfs_superblock_t.apfs_fext_tree_type INO_EXT_TYPE_ORIG_SYNC_ROOT_ID
apfs_superblock_t.apfs_integrity_meta_oid nx_superblock_t.nx_mkb_locker
apfs_superblock_t.reserved_oid OBJECT_TYPE_FEXT_TREE
apfs_superblock_t.reserved_type OBJECT_TYPE_INTEGRITY_META
APFS_TYPE_FILE_INFO OBJECT_TYPE_MEDIA_KEYBAG
APFS_UNASSIGNED_CRYPTO_ID OBJECT_TYPE_RESERVED_20
APFS_VOL_ROLE_PRELOGIN spaceman_free_queue_entry_t
BTNODE_HASHED
2020-05-15
APFS_FEATURE_STRICTATIME INODE_IS_PURGEABLE
APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE INODE_IS_SYNC_ROOT
APFS_INCOMPAT_INCOMPLETE_RESTORE INODE_WANTS_TO_BE_PURGEABLE
apfs_superblock_t.apfs_cloneinfo_id_epoch INO_EXT_TYPE_PURGEABLE_FLAGS
apfs_superblock_t.apfs_cloneinfo_xid j_inode_val.uncompressed_size
apfs_superblock_t.apfs_snap_meta_ext_oid KB_TAG_VOLUME_M_KEY
apfs_superblock_t.apfs_volume_group_id KB_TAG_WRAPPING_M_KEY
APFS_VOL_ROLE_BACKUP nx_superblock_t.nx_newest_mounted_version
APFS_VOL_ROLE_ENTERPRISE OBJECT_TYPE_ER_RECOVERY_BLOCK
APFS_VOL_ROLE_HARDWARE OBJECT_TYPE_SNAP_META_EXT
APFS_VOL_ROLE_RESERVED_10 OMAP_VALID_FLAGS
APFS_VOL_ROLE_RESERVED_7 PROTECTION_CLASS_M
APFS_VOL_ROLE_RESERVED_8 PURGEABLE_DIR_INO_NUM
APFS_VOL_ROLE_UPDATE snap_meta_ext_obj_phys_t
APFS_VOL_ROLE_XART snap_meta_ext_t
FIRMLINK_EA_NAME SYSTEM_OBJ_ID_MARK
INODE_FAST_PROMOTE UNIFIED_ID_SPACE_MARK
INODE_HAS_UNCOMPRESSED_SIZE
2019-02-07
179
Corrected the discussion of object identifiers in j_snap_metadata_val_t. The extentref_tree_oid and
sblock_oid fields contain a physical object identifier, not a virtual object identifier.
2019-01-24
2018-09-17
New document that describes the data structures used for read-only access to Apple File System on unencrypted,
non-Fusion storage.
180
Copyright and Notices
Apple Inc.
Copyright © 2020 Apple Inc.
All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying,
recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation
on a single computer or device for personal use only and to print copies of documentation for personal use provided that the documentation contains Appleʼs
copyright notice.
No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights
associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-
branded products.
Apple Inc.
One Apple Park Way
Cupertino, CA 95014
USA
408-996-1010
Apple is a trademark of Apple Inc., registered in the U.S. and other countries.
APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY,
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED ”AS IS,” AND YOU, THE READER, ARE
ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY.
IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT,
ERROR OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages.
Some jurisdictions do not allow the exclusion of implied warranties or liability, so the above exclusion may not apply to you.
181