Apple File System Reference
Apple File System Reference
Developer
Contents
About Apple File System 6
General-Purpose Types 8
paddr_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
prange_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
uuid_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Objects 9
obj_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Supporting Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Object Identifier Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Object Type Masks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Object Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Object Type Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
EFI Jumpstart 20
Booting from an Apple File System Partition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
nx_efi_jumpstart_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Partition UUIDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Container 24
Mounting an Apple File System Partition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
nx_superblock_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Container Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Optional Container Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Read-Only Compatible Container Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Incompatible Container Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Block and Container Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
nx_counter_id_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
checkpoint_mapping_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
checkpoint_map_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Checkpoint Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
evict_mapping_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Object Map 41
omap_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
omap_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
omap_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
omap_snapshot_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Object Map Value Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Snapshot Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Object Map Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Object Map Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Object Map Reaper Phases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2
Volume 48
apfs_superblock_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
apfs_modified_by_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Volume Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Optional Volume Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Read-Only Compatible Volume Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Incompatible Volume Feature Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
File-System Objects 61
j_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
j_inode_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
j_inode_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
j_drec_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
j_drec_hashed_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
j_drec_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
j_dir_stats_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
j_dir_stats_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
j_xattr_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
j_xattr_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
File-System Constants 73
j_obj_types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
j_obj_kinds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
j_inode_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
j_xattr_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
dir_rec_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Inode Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Extended Attributes Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
File-System Object Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
File Extent Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
File Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Directory Entry File Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Data Streams 88
j_phys_ext_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
j_phys_ext_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
j_file_extent_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
j_file_extent_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
j_dstream_id_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
j_dstream_id_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
j_xattr_dstream_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
j_dstream_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Extended Fields 94
xf_blob_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
x_field_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Extended-Field Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Extended-Field Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3
Siblings 100
j_sibling_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
j_sibling_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
j_sibling_map_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
j_sibling_map_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
B-Tree 105
btree_node_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
btree_info_fixed_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
btree_info_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
nloc_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
kvloc_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
kvoff_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
B-Tree Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
B-Tree Table of Contents Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
B-Tree Node Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
B-Tree Node Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Reaper 120
nx_reaper_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
nx_reap_list_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
nx_reap_list_entry_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Volume Reaper States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Reaper Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Reaper List Entry Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Reaper List Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
omap_reap_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
omap_cleanup_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
apfs_reap_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
4
Encryption 125
j_crypto_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
j_crypto_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
crypto_flags_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
cp_key_class_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
cp_key_os_version_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
cp_key_revision_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
cpx_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
wrapped_crypto_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
wrapped_meta_crypto_state_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Protection Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Encryption Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Keybag 129
kb_locker_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
keybag_entry_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
media_keybag_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
mk_obj_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Keybag Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Keybag Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Fusion 134
fusion_wbc_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
fusion_wbc_list_entry_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
fusion_wbc_list_phys_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Address Markers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
fusion_mt_key_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
fusion_mt_val_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Fusion Middle-Tree Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
5
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 such as 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 im-
plementation 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
container layer organizes file-system layer information and stores higher level information, such as volume metadata,
snapshots of the volume, and encryption state. The file-system layer is made up of the data structures that store
information, such as 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.
6
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.
7
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.
8
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.
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
9
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
10
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
11
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.
12
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.
13
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
OBJECT_TYPE_SPACEMAN_BITMAP
OBJECT_TYPE_SPACEMAN_FREE_QUEUE
14
Objects
Object Types
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.
OBJECT_TYPE_BLOCKREFTREE
15
Objects
Object Types
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).
OBJECT_TYPE_NX_FUSION_WBC
OBJECT_TYPE_NX_FUSION_WBC_LIST
16
Objects
Object Type Flags
OBJECT_TYPE_ER_STATE
OBJECT_TYPE_GBITMAP
OBJECT_TYPE_GBITMAP_TREE
OBJECT_TYPE_GBITMAP_BLOCK
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.
17
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
OBJ_ENCRYPTED
An encrypted object.
OBJ_NONPERSISTENT
18
Objects
Object Type Flags
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.
19
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 1).
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.
20
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');
assert(jumpstart->nej_o.o_cksum == fletcher64_checksum(&jumpstart));
assert(jumpstart->nej_version == 1);
load_and_execute(efi_driver);
21
EFI Jumpstart
nx_efi_jumpstart_t
return 0;
}
nx_efi_jumpstart_t
Information about the embedded EFI driver thatʼs used to boot from an Apple File System partition.
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;
nej_num_extents
uint32_t nej_num_extents;
22
EFI Jumpstart
Partition UUIDs
nej_reserved
Reserved.
uint64_t nej_reserved[16];
Populate this field with 0 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.
23
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, con-
firm that its magic number and checksum are valid. That superblock and its checkpoint-mapping blocks com-
prise the latest valid checkpoint. The superblockʼs fields, such as 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.
24
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;
25
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;
}
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;
26
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;
27
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 0, 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 0, 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.
28
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 0 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 0 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 0 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 0 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 0 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;
29
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 0 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 0 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];
nx_counters
uint64_t nx_counters[NX_NUM_COUNTERS];
30
Container
nx_superblock_t
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 0 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 0, 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;
nx_fusion_uuid
The universally unique identifier of the containerʼs Fusion set, or 0 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 1 for the Fusion setʼs main device and 0 for the second-tier device.
31
Container
nx_superblock_t
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 0 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 0 if for non-Fusion drives.
oid_t nx_fusion_mt_oid;
nx_fusion_wbc_oid
The ephemeral object identifier of the Fusion write-back cache state (fusion_wbc_phys_t), or 0 for non-Fusion
drives.
oid_t nx_fusion_wbc_oid;
nx_fusion_wbc
The blocks used for the Fusion write-back cache area, or 0 for non-Fusion drives.
prange_t nx_fusion_wbc;
32
Container
nx_superblock_t
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
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
33
Container
Container Flags
Container Flags
The flags used for general information about a container.
NX_RESERVED_1
Reserved.
NX_RESERVED_2
Reserved.
Donʼt add this flag to a container. If this flag is already set, remove it when you modify the container, and preserve it
otherwise.
NX_CRYPTO_SW
NX_FEATURE_DEFRAG
34
Container
Read-Only Compatible Container Feature Flags
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
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.
35
Container
Block and Container Sizes
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
NX_SUPPORTED_INCOMPAT_MASK
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.
36
Container
nx_counter_id_t
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.
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;
};
37
Container
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.
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 0 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;
38
Container
checkpoint_map_phys_t
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;
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.
39
Container
evict_mapping_val_t
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));
typedef struct evict_mapping_val 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;
40
Object Map
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;
41
Object Map
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;
42
Object Map
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.
43
Object Map
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 0 when you create a new snapshot, and preserve its value when you modify an existing
snapshot.
oms_oid
Reserved.
oid_t oms_oid;
44
Object Map
Object Map Value Flags
Populate this field with 0 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.
45
Object Map
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
46
Object Map
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_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
47
Volume
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;
48
Volume
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;
};
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.
uint32_t apfs_magic;
apfs_fs_index
The index of this volumeʼs object identifier in the containerʼs array of volumes.
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.
49
Volume
apfs_superblock_t
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.
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
50
Volume
apfs_superblock_t
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
wrapped_meta_crypto_state_t apfs_meta_crypto
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
apfs_omap_oid
oid_t apfs_omap_oid
apfs_root_tree_oid
oid_t apfs_root_tree_oid
51
Volume
apfs_superblock_t
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 isnʼt 0, 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 0.
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 isnʼt 0, 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
apfs_num_files
uint64_t apfs_num_files
apfs_num_directories
uint64_t apfs_num_directories
52
Volume
apfs_superblock_t
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.
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.
53
Volume
apfs_superblock_t
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 0. 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 present in this field, you can update the field as usual (creating a dupli-
cate), or leave the fieldʼs value unmodified. Both behaviors are permitted.
apfs_volname
uint8_t apfs_volname[APFS_VOLNAME_LEN]
apfs_next_doc_id
uint32_t apfs_next_doc_id
After assigning a new document identifier, this field is incremented 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
54
Volume
apfs_modified_by_t
reserved
Reserved.
uint16_t reserved
Populate this field with 0 when you create a new volume, and preserve its value when you modify an existing volume.
apfs_root_to_xid
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 0 if no encryption
change is in progress.
oid_t apfs_er_state_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;
}
typedef struct apfs_modified_by apfs_modified_by_t;
#define APFS_MODIFIED_NAMELEN 32
55
Volume
Volume Flags
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.
APFS_FS_UNENCRYPTED
56
Volume
Volume Flags
APFS_FS_EFFACEABLE
APFS_RESERVED_4
Reserved.
APFS_FS_ONEKEY
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_FLAGS_VALID_MASK
APFS_FS_CRYPTOFLAGS
57
Volume
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_SUPPORTED_FEATURES_MASK
58
Volume
Read-Only Compatible Volume Feature Flags
These flags are used by the apfs_readonly_compatible_features field of apfs_superblock_t. There are
currently none defined.
APFS_SUPPORTED_ROCOMPAT_MASK
APFS_INCOMPAT_CASE_INSENSITIVE
APFS_INCOMPAT_DATALESS_SNAPS
APFS_INCOMPAT_ENC_ROLLED
APFS_INCOMPAT_NORMALIZATION_INSENSITIVE
59
Volume
Incompatible Volume Feature Flags
Normalization insensitivity is part of hashing filenames, as described in the name_len_and_hash field of j_drec_
hashed_key_t.
APFS_SUPPORTED_INCOMPAT_MASK
60
File-System Objects
A file-system object stores information about a part of the file system, such as 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, such as 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 of all 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
61
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.
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;
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.
62
File-System Objects
j_inode_key_t
OBJ_ID_MASK
OBJ_TYPE_MASK
OBJ_TYPE_SHIFT
#define OBJ_TYPE_SHIFT 60
j_inode_key_t
The key half of a directory-information record.
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.
uint64_t create_time;
uint64_t mod_time;
uint64_t change_time;
uint64_t access_time;
uint64_t internal_flags;
union {
int32_t nchildren;
63
File-System Objects
j_inode_val_t
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 pad2;
uint8_t xfields[];
} __attribute__((packed)) 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.
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.
64
File-System Objects
j_inode_val_t
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;
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;
65
File-System Objects
j_inode_val_t
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;
mode
mode_t mode;
pad1
Reserved.
uint16_t pad1;
Populate this field with 0 when you create a new inode, and preserve its value when you modify an existing inode.
pad2
Reserved.
uint64_t pad2;
Populate this field with 0 when you create a new inode, and preserve its value when you modify an existing inode.
66
File-System Objects
j_drec_key_t
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.
j_drec_key_t
The key half of a directory entry record.
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];
67
File-System Objects
j_drec_hashed_key_t
j_drec_hashed_key_t
The key half of a directory entry record, including a precomputed hash of its name.
hdr
j_key_t hdr;
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:
name
uint8_t name[0];
J_DREC_LEN_MASK
68
File-System Objects
j_drec_val_t
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.
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 0 when you create a new directory entry, and preserve their value when you modify an existing
directory entry.
69
File-System Objects
j_dir_stats_key_t
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.
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.
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.
70
File-System Objects
j_xattr_key_t
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.
j_xattr_key_t
The key half of an extended attribute record.
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.
71
File-System Objects
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.
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.
72
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_MAX_VALID = 12,
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
73
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
APFS_TYPE_FILE_EXTENT
APFS_TYPE_FILE_EXTENT = 8
74
File-System Constants
j_obj_kinds
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_MAX_VALID
APFS_TYPE_MAX_VALID = 12
APFS_TYPE_MAX
APFS_TYPE_MAX = 15
APFS_TYPE_INVALID
APFS_TYPE_INVALID = 15
j_obj_kinds
The kind of a file-system record.
75
File-System Constants
j_obj_kinds
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.
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.
76
File-System Constants
j_inode_flags
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_INHERITED_INTERNAL_FLAGS = (INODE_MAINTAIN_DIR_STATS),
INODE_CLONED_INTERNAL_FLAGS = (INODE_HAS_RSRC_FORK \
| INODE_NO_RSRC_FORK \
| INODE_HAS_FINDER_INFO),
} j_inode_flags;
77
File-System Constants
j_inode_flags
| INODE_NO_RSRC_FORK \
| INODE_ALLOCATION_SPILLEDOVER)
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 such as 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
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
78
File-System Constants
j_inode_flags
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:
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.
79
File-System Constants
j_inode_flags
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.
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_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)
80
File-System Constants
j_xattr_flags
INODE_CLONED_INTERNAL_FLAGS
INODE_CLONED_INTERNAL_FLAGS = (INODE_HAS_RSRC_FORK
| INODE_NO_RSRC_FORK \
| INODE_HAS_FINDER_INFO)
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
81
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 it 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.
82
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 MIN_USER_INO_NUM 16
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.
SNAP_DIR_INO_NUM
The inode number for the directory where snapshot metadata is stored.
#define SNAP_DIR_INO_NUM 6
83
File-System Constants
Extended Attributes Constants
MIN_USER_INO_NUM
#define MIN_USER_INO_NUM 16
XATTR_MAX_EMBEDDED_SIZE
The largest size, in bytes, of an extended attribute whose value is stored directly in the record.
SYMLINK_EA_NAME
The name of an extended attribute for a symbolic link whose value is the target file.
#define MIN_DOC_ID 3
MIN_DOC_ID
#define MIN_DOC_ID 3
84
File-System Constants
File Modes
File Modes
The values used by the mode field of j_inode_val_t to indicate a fileʼs mode.
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.
85
File-System Constants
Directory Entry File Types
S_IFBLK
A block-special file.
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
86
File-System Constants
Directory Entry File Types
DT_FIFO
A named pipe
#define DT_FIFO 1
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
87
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.
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.
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.
88
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 garbage collected when its reference count reaches zero.
PEXT_LEN_MASK
PEXT_KIND_MASK
PEXT_KIND_SHIFT
#define PEXT_LEN_SHIFT 60
j_file_extent_key_t
The key half of a file extent record.
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.
89
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.
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;
This value matches the obj_id field in the j_key_t key that corresponds to a j_crypto_val_t value.
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.
J_FILE_EXTENT_LEN_MASK
90
Data Streams
j_dstream_id_key_t
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.
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.
refcnt
uint32_t refcnt;
The data stream record can be garbage collected when its reference count reaches zero.
j_xattr_dstream_t
A data stream for extended attributes.
91
Data Streams
j_dstream_t
} 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.
size
uint64_t size;
alloced_size
The total space allocated for the data stream, including any unused space.
uint64_t alloced_size;
default_crypto_id
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.
This value is used as the default value by file extents (j_file_extent_val_t) that make up this data stream.
92
Data Streams
j_dstream_t
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.
93
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.
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.
94
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.
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
#define INO_EXT_TYPE_DELTA_TREE_OID 2
95
Extended Fields
Extended-Field Types
#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
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 such as 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.
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.
96
Extended Fields
Extended-Field Types
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
97
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>.
Extended-Field Flags
Flags used by the x_flags field of x_field_t.
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.
98
Extended Fields
Extended-Field Flags
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.
Extended fields with this flag set canʼt be removed or modified by a program running in user space.
XF_RESERVED_40
When sharing this file, omit this extended field from the shared copy.
XF_RESERVED_80
Reserved.
99
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 on 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.
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.
100
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.
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.
file_id
uint64_t file_id;
101
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.
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.
extentref_tree_oid
The virtual object identifier of the B-tree that stores extents information.
oid_t extentref_tree_oid;
sblock_oid
oid_t sblock_oid;
102
Snapshot Metadata
j_snap_name_key_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.
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
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];
j_snap_name_key_t
The key half of a snapshot name record.
103
Snapshot Metadata
j_snap_name_val_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.
snap_xid
xid_t snap_xid;
snap_meta_flags
No overview available.
typedef enum {
SNAP_META_PENDING_DATALESS = 0x00000001,
} snap_meta_flags;
104
B-Tree
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, such as 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 such as 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.
105
B-Tree
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[];
106
B-Tree
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 0 for a leaf node and 1 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;
107
B-Tree
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-tree.
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.
108
B-Tree
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 0, 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 0, 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;
109
B-Tree
nloc_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;
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.
110
B-Tree
kvloc_t
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;
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;
111
B-Tree
B-Tree Flags
B-Tree Flags
The flags used to describe configuration options for a B-tree.
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.
112
B-Tree
B-Tree Table of Contents Constants
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.
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.
#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
113
B-Tree
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_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.
114
B-Tree
B-Tree Node Constants
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:
Note
This requirement comes from logic in Appleʼs implementation that performs proactive splitting of B-tree nodes.
115
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_key_t
No overview available.
116
Space Manager
spaceman_free_queue_t
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;
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;
uint32_t sm_cibs_per_cab;
spaceman_device_t sm_dev[SD_COUNT];
uint32_t sm_flags;
uint32_t sm_ip_bm_tx_multiplier;
117
Space Manager
sfq
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
};
118
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
119
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.
120
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
121
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;
122
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 0, the structure has been allocated and zeroed, but doesnʼt yet contain valid data. If the
value is anything other than 0, 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;
123
Reaper
apfs_reap_state_t
} __attribute__((packed));
typedef struct apfs_reap_state apfs_reap_state_t;
124
Encryption
No overview available.
j_crypto_key_t
The key half of an encryption state record.
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 an encryption state record.
refcnt
int32_t refcnt;
The encryption state record can be garbage collected when its reference count reaches zero.
state
wrapped_crypto_state_t state;
crypto_flags_t
No overview available.
125
Encryption
cp_key_class_t
cp_key_class_t
No overview available.
cp_key_os_version_t
No overview available.
cp_key_revision_t
No overview available.
cpx_t
No overerview available.
wrapped_crypto_state_t
No overview available.
wrapped_meta_crypto_state_t
No overview available.
126
Encryption
Protection Class
uint16_t unused;
} __attribute__((aligned(2), packed)) wrapped_meta_crypto_state_t;
Protection Class
No overview available.
#define CP_IV_KEYSIZE 16
#define CP_MAX_KEYSIZE 32
#define CP_MAX_CACHEBUFLEN 64
#define CP_INITIAL_WRAPPEDKEYSIZE 40
#define CP_V2_WRAPPEDKEYSIZE 40
#define CP_V4_RESERVEDBYTES 16
#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
Encryption Identifiers
Identifiers used to indicate special encryption information.
#define CRYPTO_SW_ID 4
#define CRYPTO_VOLKEY_ID 5
These identifiers are used instead of the identifier of an encryption record (j_crypto_val_t).
CRYPTO_SW_ID
#define CRYPTO_SW_ID 4
127
Encryption
Encryption Identifiers
CRYPTO_VOLKEY_ID
#define CRYPTO_VOLKEY_ID 5
128
Keybag
No overview available.
kb_locker_t
No overview available.
keybag_entry_t
No overview available.
media_keybag_t
No overview available.
mk_obj_t
No overview available.
129
Keybag
Keybag Constants
Keybag Constants
No overview available.
#define APFS_KEYBAG_VERSION 2
Keybag Tags
No overview available.
enum {
KB_TAG_UNKNOWN = 0,
KB_TAG_WRAPPING_KEY,
KB_TAG_VOLUME_KEY,
KB_TAG_VOLUME_UNLOCK_RECORDS,
KB_TAG_VOLUME_PASSPHRASE_HINT,
KB_TAG_USER_PAYLOAD = 0xF8
};
130
Encryption Rolling
No overview available.
er_state_phys_t
No overview available.
struct er_state_phys {
obj_phys_t ersb_o;
uint32_t ersb_magic;
uint32_t ersb_version;
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_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 struct er_phase_enum er_phase_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;
131
Encryption Rolling
gbitmap_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;
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.
132
Encryption Rolling
Encryption-Rolling Constants
#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
133
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-
134
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;
135
Symbol Index
APFS_FEATURE_DEFRAG 58 APFS_SUPPORTED_INCOMPAT_MASK 60
APFS_FEATURE_DEFRAG_PRERELEASE 58 APFS_SUPPORTED_ROCOMPAT_MASK 59
APFS_FEATURE_HARDLINK_MAP_RECORDS 58 APFS_TYPE_ANY 73
APFS_FS_CRYPTOFLAGS 57 APFS_TYPE_CRYPTO_STATE 74
APFS_FS_EFFACEABLE 57 APFS_TYPE_DIR_REC 75
APFS_FS_FLAGS_VALID_MASK 57 APFS_TYPE_DIR_STATS 75
APFS_FS_ONEKEY 57 APFS_TYPE_DSTREAM_ID 74
APFS_FS_RUN_SPILLOVER_CLEANER 57 APFS_TYPE_EXTENT 74
APFS_FS_SPILLEDOVER 57 APFS_TYPE_FILE_EXTENT 74
APFS_FS_UNENCRYPTED 56 APFS_TYPE_INODE 74
APFS_GPT_PARTITION_UUID 23 APFS_TYPE_INVALID 75
APFS_INCOMPAT_CASE_INSENSITIVE 59 APFS_TYPE_MAX 75
APFS_INCOMPAT_DATALESS_SNAPS 59 APFS_TYPE_MAX_VALID 75
APFS_INCOMPAT_ENC_ROLLED 59 APFS_TYPE_SIBLING_LINK 74
APFS_INCOMPAT_NORMALIZATION_INSENSITIVE 59 APFS_TYPE_SIBLING_MAP 75
APFS_INODE_PINNED_MASK 81 APFS_TYPE_SNAP_METADATA 73
APFS_KIND_ANY 76 APFS_TYPE_SNAP_NAME 75
APFS_KIND_DEAD 76 APFS_TYPE_XATTR 74
APFS_KIND_INVALID 77 APFS_VALID_INTERNAL_INODE_FLAGS 81
APFS_KIND_NEW 76 APFS_VOLNAME_LEN 55
136
Symbol Index
dir_rec_flags 82 INO_EXT_TYPE_RESERVED_6 97
DREC_EXT_TYPE_SIBLING_ID 96 INO_EXT_TYPE_RESERVED_9 97
DREC_TYPE_MASK 82 INO_EXT_TYPE_SNAP_XID 96
DT_BLK 87 INO_EXT_TYPE_SPARSE_BYTES 98
DT_CHR 87 INODE_ACTIVE_FILE_TRIMMED 80
DT_DIR 87 INODE_ALLOCATION_SPILLEDOVER 80
DT_FIFO 87 INODE_BEING_TRUNCATED 79
DT_LNK 87 INODE_CLONED_INTERNAL_FLAGS 81
DT_REG 87 INODE_DIR_STATS_ORIGIN 78
137
Symbol Index
INODE_FLAG_UNUSED 79 j_file_extent_val_t 90
INODE_HAS_FINDER_INFO 79 j_inode_flags 77
INODE_HAS_RSRC_FORK 80 j_inode_key_t 63
INODE_HAS_SECURITY_EA 79 j_inode_val_t 63
INODE_INHERITED_INTERNAL_FLAGS 80 j_key_t 62
INODE_IS_APFS_PRIVATE 78 j_obj_kinds 75
INODE_IS_SPARSE 79 j_obj_types 73
INODE_MAINTAIN_DIR_STATS 78 j_phys_ext_key_t 88
INODE_NO_RSRC_FORK 80 j_phys_ext_val_t 88
j_dir_stats_key_t 70 j_xattr_dstream_t 91
j_dir_stats_val_t 70 j_xattr_flags 81
J_DREC_HASH_MASK 69 j_xattr_key_t 71
J_DREC_HASH_SHIFT 69 j_xattr_val_t 71
j_dstream_id_key_t 91 MAX_CKSUM_SIZE 10
j_dstream_t 92 MIN_DOC_ID 84
J_FILE_EXTENT_FLAG_MASK 91 MIN_USER_INO_NUM 84
138
Symbol Index
NX_CNTR_OBJ_CKSUM_FAIL 37 NX_TX_MIN_CHECKPOINT_COUNT 33
NX_CNTR_OBJ_CKSUM_SET 37 OBJ_ENCRYPTED 18
nx_counter_id_t 37 OBJ_EPHEMERAL 18
NX_CRYPTO_SW 34 OBJ_ID_MASK 63
NX_DEFAULT_BLOCK_SIZE 36 OBJ_NOHEADER 18
NX_EFI_JUMPSTART_MAGIC 23 OBJ_NONPERSISTENT 18
nx_efi_jumpstart_t 22 obj_phys_t 9
NX_EFI_JUMPSTART_VERSION 23 OBJ_PHYSICAL 18
NX_EPH_INFO_COUNT 33 OBJ_STORAGETYPE_MASK 13
NX_EPH_INFO_VERSION_1 33 OBJ_TYPE_MASK 63
NX_EPH_MIN_BLOCK_COUNT 33 OBJ_TYPE_SHIFT 63
NX_FEATURE_DEFRAG 34 OBJ_VIRTUAL 18
NX_FEATURE_LCFD 35 OBJECT_TYPE_BLOCKREFTREE 15
NX_INCOMPAT_FUSION 36 OBJECT_TYPE_BTREE 14
NX_INCOMPAT_VERSION1 35 OBJECT_TYPE_BTREE_NODE 14
NX_INCOMPAT_VERSION2 36 OBJECT_TYPE_CHECKPOINT_MAP 15
NX_MAGIC 33 OBJECT_TYPE_EFI_JUMPSTART 16
NX_MAX_FILE_SYSTEM_EPH_STRUCTS 33 OBJECT_TYPE_ER_STATE 17
NX_MAX_FILE_SYSTEMS 33 OBJECT_TYPE_EXTENT_LIST_TREE 15
NX_MAXIMUM_BLOCK_SIZE 36 OBJECT_TYPE_FLAGS_DEFINED_MASK 13
NX_MINIMUM_BLOCK_SIZE 36 OBJECT_TYPE_FLAGS_MASK 12
NX_MINIMUM_CONTAINER_SIZE 37 OBJECT_TYPE_FS 15
NX_NUM_COUNTERS 37 OBJECT_TYPE_FSTREE 15
NX_RESERVED_1 34 OBJECT_TYPE_GBITMAP_TREE 17
NX_RESERVED_2 34 OBJECT_TYPE_INVALID 17
nx_superblock_t 25 OBJECT_TYPE_MASK 12
NX_SUPPORTED_FEATURES_MASK 35 OBJECT_TYPE_NX_FUSION_WBC 16
NX_SUPPORTED_INCOMPAT_MASK 36 OBJECT_TYPE_NX_FUSION_WBC_LIST 16
139
Symbol Index
OBJECT_TYPE_NX_REAP_LIST 16 OMAP_VAL_ENCRYPTED 45
OBJECT_TYPE_NX_REAPER 16 OMAP_VAL_NOHEADER 45
OBJECT_TYPE_NX_SUPERBLOCK 14 OMAP_VAL_SAVED 45
OBJECT_TYPE_OMAP 15 omap_val_t 43
OBJECT_TYPE_OMAP_SNAPSHOT 16 paddr_t 8
OBJECT_TYPE_SNAPMETATREE 16 PEXT_KIND_MASK 89
OBJECT_TYPE_SPACEMAN 14 PEXT_KIND_SHIFT 89
OBJECT_TYPE_SPACEMAN_BITMAP 14 PEXT_LEN_MASK 89
OBJECT_TYPE_SPACEMAN_CAB 14 prange_t 8
OBJECT_TYPE_SPACEMAN_CIB 14 PRIV_DIR_INO_NUM 83
OBJECT_TYPE_SPACEMAN_FREE_QUEUE 14 RESERVED_10 82
OBJECT_TYPE_TEST 17 ROOT_DIR_INO_NUM 83
OID_INVALID 12 ROOT_DIR_PARENT 83
OID_NX_SUPERBLOCK 12 S_IFBLK 86
OID_RESERVED_COUNT 12 S_IFCHR 85
OMAP_CRYPTO_GENERATION 47 S_IFIFO 85
OMAP_DECRYPTING 46 S_IFLNK 86
OMAP_ENCRYPTING 46 S_IFMT 85
omap_key_t 43 S_IFREG 86
OMAP_KEYROLLING 47 S_IFSOCK 86
OMAP_MANUALLY_MANAGED 46 S_IFWHT 86
OMAP_REAP_PHASE_MAP_TREE 47 SNAP_DIR_INO_NUM 83
OMAP_VAL_CRYPTO_GENERATION 45 SYMLINK_EA_NAME 84
OMAP_VAL_DELETED 45 uuid_t 8
140
Symbol Index
XATTR_RESERVED_8 82 XF_SYSTEM_FIELD 99
xf_blob_t 94 XF_USER_FIELD 99
141
Revision History
2018-09-17
New document that describes the data structures used for read-only access to Apple File System on unencrypted,
non-Fusion storage.
142
Copyright and Notices
Apple Inc.
Copyright © 2018 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.
143