Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Apple File System (APFS)

The Apple File System (APFS) is a volume and file system mainly used on platforms such as Mac OS and iOS. APFS supersedes the Hierarchical File System (HFS) and was introduced in macOS High Sierra (10.13) and iOS 10.3.

Overview

APFS consists of:

  • A container
    • Zero or more logical volumes that contain a file system

Characteristics

CharacteristicsDescription
Byte orderlittle-endian
Date and time valuesnumber of nanoseconds since January 1, 1970 00:00:00 UTC (POSIX epoch), disregarding leap seconds
Character stringsUnicode strings are stored in UTF-8

Note that date and values are signed integers to represent dates before January 1, 1970. Other sources are known to claim the date and time values are unsigned including Apple’s own Apple File System Reference documentation.

Note that (some) sources claim that APFS uses Unicode version 9.0. Support for codepoints of more recent Unicode versions has been observed.

Terminology

TermDescription
Physical volumeA volume in which the APFS container is stored
Logical volumeA volume in which an APFS file system is stored

Keys

To encrypt storage media APFS uses different kind of keys.

Volume master key

The Volume Master Key (VMK) is used to encrypt the data of a specific volume.

Volume key

For every volume on an Mac OS system with APFS, APFS provides for a volume password to unlock the encrypted data. The volume password is used to determine a volume key.

Encryption methods

APFS uses the AES-XTS encryption method to encrypt the key bag, file system metadata and content data.

AES-XTS

The AES-XTS encryption method uses:

  • a primary key (key 1) to encrypt/decrypt the data (the whitened plaintext/ciphertext).
  • a secondary key (key 2) to encrypt/ decrypt the tweak value, also referred to as the tweak key. The encrypted tweak value is used to whiten the plaintext/ciphertext.
  • a tweak value

The cipher block size is 128 bytes.

The container key bag is encrypted using the “container identifier” of the container as both the primary and tweak key. The sector number, relative to the start of the container, is used as the tweak value.

Note that when a T2 chip is present, it is currently assumed that the T2 is used to encrypted the container key bag instead of the “container identifier”.

The unit size is the sector size, which is assumed to be 512 bytes also for 4 KiB sector media.

The volume key bag is encrypted using the “volume identifier” of the corresponding key bag entry, as both the primary and tweak key. The sector number, relative to the start of the container, is used as the tweak value.

The file system B-tree is encrypted using the volume master key and the sector number, relative to the start of the container, is used as the tweak value.

Objects

APFS uses the “object” data type to distinguish between different data types.

Object header

The object header (obj_phys_t) is 32 bytes in size and consists of:

OffsetSizeValueDescription
08Object checksum (o_cksum), which contains 0 if not set
88Object identifier (o_oid)
168Object transaction identifier (o_xid), which contains the identifier of the most recent transaction that this object was modified in
244Object type (o_type)
284Object subtype (o_subtype)

Object checksum

The checksum algorithm:

Fletcher-64 checksum of the data without the object checksum value and an initial value of 0
checksum_lower_32bit = 0xffffffff - ((fletcher_lower_32bit + fletcher_upper_32bit) mod 0xffffffff)
checksum_upper_32bit = 0xffffffff - ((fletcher_lower_32bit + checksum_lower_32bit) mod 0xffffffff)
checksum = (checksum_upper_32bit << 32) | checksum_lower_32bit

Object identifiers

  • For a physical object, its identifier is the logical block address on disk where the object is stored.
  • For an ephemeral object, its identifier is a number.
  • For a virtual object, its identifier is a number.
ValueIdentifierDescription
0OID_INVALIDInvalid
1OID_NX_SUPERBLOCKContainer superblock
1024OID_RESERVED_COUNTNumber of reserved object identifiers

Object types

The object type (o_type) value consists of a type and flags.

ValueIdentifierDescription
0x00000000OBJECT_TYPE_INVALIDInvalid. For a subtype this value represents not set or not specified
0x00000001OBJECT_TYPE_NX_SUPERBLOCKContainer superblock
0x00000002OBJECT_TYPE_BTREEB-tree (root)
0x00000003OBJECT_TYPE_BTREE_NODEB-tree node
0x00000004Unknown (MTree?)
0x00000005OBJECT_TYPE_SPACEMANSpace manager header
0x00000006OBJECT_TYPE_SPACEMAN_CABSpace manager chunk information address block
0x00000007OBJECT_TYPE_SPACEMAN_CIBSpace manager chunk information block
0x00000008OBJECT_TYPE_SPACEMAN_BITMAPSpace manager bitmap
0x00000009OBJECT_TYPE_SPACEMAN_FREE_QUEUESpace manager free queue
0x0000000aOBJECT_TYPE_EXTENT_LIST_TREEExtent list tree
0x0000000bOBJECT_TYPE_OMAPObject map
0x0000000cOBJECT_TYPE_CHECKPOINT_MAPCheckpoint map
0x0000000dOBJECT_TYPE_FSVolume (or file system) superblock
0x0000000eOBJECT_TYPE_FSFile system tree
0x0000000fOBJECT_TYPE_BLOCKREFTREEExtent-reference tree
0x00000010OBJECT_TYPE_SNAPMETATREESnapshot metadata tree
0x00000011OBJECT_TYPE_NX_REAPERReaper
0x00000012OBJECT_TYPE_NX_REAP_LISTReaper list
0x00000013OBJECT_TYPE_OMAP_SNAPSHOTObject map snapshot
0x00000014OBJECT_TYPE_EFI_JUMPSTARTEFI jumpstart
0x00000015OBJECT_TYPE_FUSION_MIDDLE_TREEFusion middle tree
0x00000016OBJECT_TYPE_NX_FUSION_WBCFusion write-back cache
0x00000017OBJECT_TYPE_NX_FUSION_WBC_LISTFusion write-back cache list
0x00000018OBJECT_TYPE_ER_STATEUnknown (ER state?)
0x00000019OBJECT_TYPE_GBITMAPUnknown (G Bitmap?)
0x0000001aOBJECT_TYPE_GBITMAP_TREEUnknown (G Bitmap tree?)
0x0000001bOBJECT_TYPE_GBITMAP_BLOCKUnknown (G Bitmap block?)
0x000000ffOBJECT_TYPE_TESTUnknown (test?)
0x0000ffffOBJECT_TYPE_MASKObject type bitmask
Flags used in combination with some of the object types
0x08000000OBJ_NONPERSISTENTUnknown (Non-persistent?)
0x10000000OBJ_ENCRYPTEDIs encrypted
0x20000000OBJ_NOHEADERHas no object (obj_phys_t) header
0x00000000OBJ_VIRTUALIs virtual object
0x40000000OBJ_PHYSICALIs physical object
0x80000000OBJ_EPHEMERALIs ephemeral object
0xffff0000OBJECT_TYPE_FLAGS_MASKObject type flags bitmask
0xc0000000OBJ_STORAGETYPE_MASKObject storage type bitmask
0xf8000000OBJECT_TYPE_FLAGS_DEFINED_MASKUnknown
Object types without flags
0x6b657973 ("syek")Container key bag
0x72656373 ("scer")Volume key bag

Object subtypes

The object subtype is used by specific object types such as:

  • B-tree root
  • B-tree node

The object subtypes are the same as the Object types.

B-tree

A B-tree consists of:

  • B-tree root object
    • Zero or more B-tree node objects

B-tree root or node object

A B-tree root or node (or object) consists of:

  • Object header
  • B-tree node header
  • B-tree entries (table of contents)
  • keys data, where the first key is stored after the entries in increasing order
  • Optional key free list
  • unused data
  • Optional value free list
  • values data, where the first value is stored before the footer in descending order
  • Optional B-tree footer, which is only stored in the root node

Note that the Apple File System Reference documentation combines the B-tree object and B-tree node header into a single structure referred to as btree_node_phys_t.

B-tree root object header

OffsetSizeValueDescription
Object header (btn_o)
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x00000002 or 0x40000002Object type
284Object subtype

Note that object type can be 0x00000000 if the B-tree is empty.

B-tree node object header

OffsetSizeValueDescription
Object header (btn_o)
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x00000003 or 0x40000003Object type
284Object subtype

B-tree node header

The B-tree node header is stored after the B-tree root or node object.

The B-tree node header is 24 bytes in size and consists of:

OffsetSizeValueDescription
02Flags (btn_flags)
22Level (btn_level)
44Number of keys in the node (btn_nkeys)
Table space (btn_table_space)
82Entries data offset, which contains an offset relative to the end of the B-tree node header or -1 (0xffff) if not set (invalid)
102Entries data size, in number of bytes
Free space (btn_free_space)
122Unused data offset, which contains an offset relative to the end of the entries data or -1 (0xffff) if not set (invalid)
142Unused data size, in number of bytes
Key free list (btn_key_free_list)
162Unused key list offset, which contains an offset relative to unknown or -1 (0xffff) if not set (invalid)
182Unused key list size, in number of bytes
Value free list (btn_val_free_list)
202Unused value list offset, which contains an offset relative to unknown or -1 (0xffff) if not set (invalid)
222Unused value list size, in number of bytes

B-tree node flags

ValueIdentifierDescription
0x0001BTNODE_ROOTIs root
0x0002BTNODE_LEAFIs leaf
0x0004BTNODE_FIXED_KV_SIZEHas a fixed-size entry (key and value)
0x0008BTNODE_HASHEDB-tree branch nodes contain a hash of their sub nodes
0x0010BTNODE_NOHEADERThe B-tree node are stored without object header, where the object header is filled with 0-byte values
0x8000BTNODE_CHECK_KOFF_INVALIn transient state, which is used for in-memory purposes only

B-tree entries

The B-tree entries are stored after the B-tree node header.

Fixed-size B-tree entry

The fixed-size B-tree entry is 4 bytes in size and consists of:

OffsetSizeValueDescription
02Key data offset (key_offs), which contains an offset relative to the end of the entries data
22Value data offset (value_offs), which contains a reversed offset relative to the start of the B-tree footer

Variable-size B-tree entry

The variable-size B-tree entry is 8 bytes in size and consists of:

OffsetSizeValueDescription
02Key data offset (key_offs), which contains an offset relative to the end of the entries data
22Key data size (key_len), in number of bytes
42Value data offset (value_offs), which contains a reversed offset relative to the start of the B-tree footer
62Value data size (value_len), in number of bytes

The B-tree footer is stored at the end of the block that contains the B-tree root object.

The B-tree footer (btree_info_t) is 40 bytes in size and consists of:

OffsetSizeValueDescription
Static information (btree_info_fixed_t)
04Flags (bt_flags)
44Node size (bt_node_size), in number of bytes
84Key size (bt_key_size), in number of bytes and is set to 0 if key has a variable size
124Value size (bt_val_size), in number of bytes and is set to 0 if value has a variable size
 
164Maximum key size (bt_longest_key), in number of bytes
204Maximum value size (bt_longest_val), in number of bytes
248Total number of keys (bt_key_count)
328Total number of nodes (bt_node_count)

B-tree flags

ValueIdentifierDescription
0x00000001BTREE_UINT64_KEYSUnknown
0x00000002BTREE_SEQUENTIAL_INSERTUnknown
0x00000004BTREE_ALLOW_GHOSTSUnknown
0x00000008BTREE_EPHEMERALUnknown
0x00000010BTREE_PHYSICALUnknown
0x00000020BTREE_NONPERSISTENTUnknown
0x00000040BTREE_KV_NONALIGNEDUnknown
0x00000080BTREE_HASHEDB-tree branch nodes contain a hash of their sub nodes
0x00000100BTREE_NOHEADERThe B-tree node are stored without object header, where the object header is filled with 0-byte values

The container

APFS stores volumes inside a container. The maximum number of volumes is dependent on the size of the container.

Container sizeMaximum number of volumes
1 GiB2
2 GiB4
5 GiB10
10 GiB20
20 GiB40
100 GiB100
12 TiB100
1.2 PiB100
7.5 EiB100

The container consists of:

  • current container superblock
  • stored in the container checkpoint descriptor area:
    • current checkpoint map
    • previous checkpoint map(s)
    • previous container superblock(s)
  • stored in the container:
    • space manager
    • container object map
    • reaper
    • crypto key
    • zero or more volumes
  • Unknown: backup of current container superblock?

Container superblock

The container superblock (nx_superblock_t) is 4096 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x80000001Object type
2840x00000000Object subtype
Object values
324"NXSB"Signature (nx_magix)
364Block size (nx_block_size), in number of bytes
408Number of blocks (nx_block_count)
488Container feature flags (nx_features)
568Read-only compatible feature flags (nx_readonly_compatible_features)
648Incompatible feature flags (nx_incompatible_features)
7216Container identifier (nx_uuid), which contains a big-endian UUID
888Next (available) object identifier (nx_next_oid)
968Next (available) transaction identifier (nx_next_xid)
1044Checkpoint descriptor area number of blocks (nx_xp_desc_blocks), which contains the size of the checkpoint descriptor area and the MSB is a flag
1084Checkpoint data area number of blocks (nx_xp_data_blocks), which contains the size of the checkpoint data area and the MSB is a flag
1128Checkpoint descriptor area block number (nx_xp_desc_base), where the block number is relative to the start of the container of the checkpoint descriptor area if the MSB of nx_xp_desc_blocks is not set, otherwise the value contains the physical object identifier of a checkpoint descriptor area B-tree
1208Checkpoint data area block number (nx_xp_data_base), where the block number is relative to the start of the container of the checkpoint data area if the MSB of nx_xp_data_blocks is not set
1284Next available index in the checkpoint descriptor area (nx_xp_desc_next)
1324Next available index in the checkpoint data area (nx_xp_data_next)
1364Index of the checkpoint in the checkpoint descriptor area (nx_xp_desc_index)
1404Size of the checkpoint in the checkpoint descriptor area, in number of blocks (nx_xp_desc_len)
1444Index of the checkpoint in the checkpoint data area (nx_xp_data_index)
1484Size of the checkpoint in the checkpoint data area, in number of blocks (nx_xp_data_len)
1528Space manager object identifier (nx_spaceman_oid), where the object identifier can be resolved in the checkpoint map
1608Object map block number (nx_omap_oid), where the block number is relative to the start of the container of the object map
1688Reaper object identifier (nx_reaper_oid), where the object identifier can be resolved in the checkpoint map
1764Unknown (reserved for testing) (nx_test_type)
1804Maximum number of volumes (nx_max_file_systems) supported by the container
184100 x 8 = 800Array of volume object identifiers (nx_fs_oid), which can be resolved to a "physical" location using the object map
98432 x 8 = 256Container counters (nx_counters)
Reserved (or blocked out) data area (nx_blocked_out_prange)
12408Reserved data area block number (nx_blocked_out_base), which contains a block number relative to the start of the container
12488Reserved data area number of blocks (nx_blocked_out_blocks)
 
12568Eviction tree (physical) object identifier (nx_evict_mapping_tree_oid)
12648Container flags (nx_flags)
12728EFI jumpstart (physical) object identifier (nx_efi_jumpstart), which contains a block number relative to the start of the container
128016Fusion set identifier (nx_fusion_uuid), which contains a big-endian UUID
Container key bag area (nx_keylocker)
12968Container key bag block number (nx_keybag_base), which contains a block number relative to the start of the container
13048Container key bag number of blocks (nx_keybag_blocks)
 
13124 x 8 = 32Ephemeral information (nx_ephemeral_info)
13448Unknown (reserved for testing) (nx_test_oid)
13528Fusion middle tree block number (nx_fusion_mt_oid), which contains a block number relative to the start of the container
13608Fusion write-back cache state object identifier (nx_fusion_wbc_oid), where the object identifier can be resolved in the checkpoint map
Fusion write-back cache area (nx_fusion_wbc)
13688Fusion write-back cache area block number (nx_fusion_wbc_base), which contains a block number relative to the start of the container
13768Fusion write-back cache area number of blocks (nx_fusion_wbc_blocks)
 
13848Newest version of software that mounted the container (nx_newest_mounted_version)
Media key area (nx_mkb_locker)
13928Media key area block number, which contains a block number relative to the start of the container
14008Media key area number of blocks
 
14082688Unknown (empty values)

Note that NXSB presumably is an abbreviation of NX superblock. At this point it is unclear what NX stands for.

Container flags

ValueIdentifierDescription
0x00000001NX_RESERVED_1Unknown (reserved)
0x00000002NX_RESERVED_2Unknown (reserved)
0x00000004NX_CRYPTO_SWThe encryption is performed in software

Container feature flags

ValueIdentifierDescription
0x0000000000000001NX_FEATURE_DEFRAGSupports defragmentation
0x0000000000000002NX_FEATURE_LCFDUses low-capacity Fusion Drive mode

Container read-only compatible feature flags

Current no read-only compatible feature flags are defined.

Container incompatible feature flags

ValueIdentifierDescription
0x0000000000000001NX_INCOMPAT_VERSION1Pre-release version 1 of APFS
0x0000000000000002NX_INCOMPAT_VERSION2Release version 2 of APFS
0x0000000000000100NX_INCOMPAT_FUSIONSupports Fusion Drives

Note that according to the Apple File System Reference documentation the pre-release version 1 and release version 2 are incompatble.

Container counters

ValueIdentifierDescription
0NX_CNTR_OBJ_CKSUM_SETNumber of times a checksum has been calculated when wrting to disk
1NX_CNTR_OBJ_CKSUM_FAILNumber of checksum errors when reading from disk

Note that the other 30 counters are presumed to be unused at this point.

Checkpoint map

The checkpoint map contains a mapping between container metadata object identifiers and their location in the container.

Note that multiple successive checkpoint map objects can be used to store a check point map.

Checkpoint map object

The checkpoint map object (checkpoint_map_phys_t) is 4096 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x4000000cObject type
2840x00000000Object subtype
Object values
324Flags (cpm_flags)
364Number of entries (cpm_count)
40101 x 40 = 4040Array of checkpoint map entries (cpm_map)
408016Unknown (empty values)

Checkpoint flags

ValueIdentifierDescription
0x00000001CHECKPOINT_MAP_LASTLast checkpoint map object

Checkpoint map entry

The checkpoint map entry (checkpoint_mapping_t) is 40 bytes in size and consists of:

OffsetSizeValueDescription
04Object type (cpm_type)
44Object subtype (cpm_subtype)
84Size (cpm_size), in number of bytes
124Unknown (padding) (cpm_pad)
168File system object identifier (cpm_fs_oid)
248(Container) object identifier (cpm_oid)
328Physical address (cpm_paddr), which contains a block number relative to the start of the container

Object map

The object map contains a mapping between object identifiers and their “physical” location.

The object map consists of:

  • object map (object)
  • object map B-tree

Object map object

The object map object (omap_phys_t) is 4096 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x4000000bObject type
2840x00000000Object subtype
Object values
324Flags (om_flags)
364Number of snapshots (om_snap_count)
404Object map B-tree type (om_tree_type)
444Object map snapshots B-tree type (om_snapshot_tree_type)
488Object map B-tree (root node) block number (om_tree_oid), which contains a block number relative to the start of the container
568Object map snapshots B-tree (root node) block number (om_snapshot_tree_oid), which contains a block number relative to the start of the container
648Most recent snapshot object identifier (om_most_recent_snap)
728Unknown transaction identifier (om_pending_revert_min)
808Unknown transaction identifier (om_pending_revert_max)
884008Unknown (empty values)

Object map flags

ValueIdentifierDescription
0x00000001OMAP_MANUALLY_MANAGEDNo snapshot support
0x00000002OMAP_ENCRYPTINGEncryption in progress
0x00000004OMAP_DECRYPTINGDecryption in progress
0x00000008OMAP_KEYROLLINGRe-encryption with new key in progress
0x00000010OMAP_CRYPTO_GENERATIONEncryption configuration has changed

Object map B-tree

The object map values are stored in a B-tree.

Object map B-tree key

The object map B-tree key (omap_key_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
08Key object identifier (ok_oid)
88Key object transaction identifier (ok_xid)

Object map B-tree branch node value

An object map B-tree node contains branch node values if BTNODE_LEAF is not set. The corresponding object map B-tree key represents the first key in the branch.

An object map B-tree branch node value is 8 bytes in size and consists of:

OffsetSizeValueDescription
08Sub node block number, which contains a block number relative to the start of the container

Object map value

An object map B-tree node contains object map values if BTNODE_LEAF is set.

The object map value (omap_val_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
04Value object flags (ov_flags)
44Value object size (ov_size), in number of bytes
88Value object physical address (ov_paddr), which contains a block number relative to the start of the container
Object map value flags
ValueIdentifierDescription
0x00000001OMAP_VAL_DELETEDUnknown
0x00000002OMAP_VAL_SAVEDUnknown
0x00000004OMAP_VAL_ENCRYPTEDUnknown
0x00000008OMAP_VAL_NOHEADERUnknown
0x00000010OMAP_VAL_CRYPTO_GENERATIONUnknown

Notes

TODO: document omap_snapshot_t TODO: document Object Map Reaper Phases

Space manager

The space manager (spaceman_phys_t) is of variable size and consists of:

OffsetSizeValueDescription
Object header (sm_o)
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x80000005Object type
2840x00000000Object subtype
Object values
324Block size (sm_block_size), in number of bytes
364Number of blocks per chunk (sm_blocks_per_chunk)
404Number of chunks per chunk information block (CIB) (sm_chunks_per_cib)
444Number of chunk information blocks (CIBs) per chunk information address block (CAB) (sm_cibs_per_cab)
Space manager devices (sm_dev)
4848Main device (SD_MAIN), which contains a Space manager device
9648Tier2 device (SD_TIER2), which contains a Space manager device
 
1444Flags
1484Unknown (sm_ip_bm_tx_multiplier)
1528Unknown (sm_ip_block_count)
1604Unknown (sm_ip_bm_size_in_blocks)
1644Unknown (sm_ip_bm_block_count)
1688Unknown (sm_ip_bm_base)
1768Unknown (sm_ip_base)
1848Unknown (sm_fs_reserve_block_count)
1928Unknown (sm_fs_reserve_alloc_count)
Space manager free queues (sm_fq)
20040Unknown space free queue (SFQ_IP)
24040Main space free queue (SFQ_MAIN)
28040Tier2 space free queue (SFQ_TIER2)
 
3202Unknown (sm_ip_bm_free_head)
3222Unknown (sm_ip_bm_free_tail)
3244Unknown (sm_ip_bm_xid_offset), which contains an offset in bytes relative to the start of the space manager
3284Unknown (sm_ip_bitmap_offset), which contains an offset in bytes relative to the start of the space manager
3324Unknown (sm_ip_bm_free_next_offset), which contains an offset in bytes relative to the start of the space manager
33641Unknown (sm_version)
3404Unknown (sm_struct_size)
Space manager data zone (sm_datazone)
3448 x 72Main allocation zones
9208 x 72Tier2 allocation zones
 
1492...Unknown (data)

Space manager flags

ValueIdentifierDescription
0x00000001SM_FLAG_VERSIONEDUnknown

Space manager device

A space manager device (spaceman_device_t) is 48 bytes in size and consists of:

OffsetSizeValueDescription
08Number of blocks (sm_block_count)
88Number of chunks (sm_chunk_count)
164Number of chunk information blocks (CIBs) (sm_cib_count)
204Number of chunk information address blocks (CABs) (sm_cab_count)
248Number of unused blocks (sm_free_count)
324Unknown (sm_addr_offset), which contains an offset in bytes relative to the start of the space manager
364Unknown (sm_reserved)
408Unknown (sm_reserved2)

Space manager free queue

A space manager free queue (spaceman_free_queue_t) is 40 bytes in size and consists of:

OffsetSizeValueDescription
08Unknown (sfq_count)
88Space manager free queue tree object identifier (sfq_tree_oid)
168Space manager free queue oldest transaction identifier (sfq_oldest_xid)
242Unknown (sfq_tree_node_limit)
262Unknown (sfq_pad16)
284Unknown (sfq_pad32)
328Unknown (sfq_reserved)

Space manager allocation zone

A space manager allocation zone (spaceman_allocation_zone_info_phys_t) is 72 bytes in size and consists of:

OffsetSizeValueDescription
08Current allocation zone boundaries (saz_current_boundaries)
87 x 8Previous allocation zone boundaries (saz_previous_boundaries)
642Unknown (saz_zone_id)
662Unknown (saz_previous_boundary_index)
684Unknown (saz_reserved)

Space manager zone_boundaries

A space manager zone boundaries (spaceman_allocation_zone_boundaries_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
08Unknown (saz_zone_start)
88Unknown (saz_zone_end)

Notes

sm_addr_offset points to block number which points to a OBJECT_TYPE_SPACEMAN_CIB block. Probably an OBJECT_TYPE_SPACEMAN_CAB block when necessary.

Chunk information address block

The chunk information address block (cib_addr_block_t) is of variable size and consists of:

OffsetSizeValueDescription
Object header (cab_o)
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x40000006Object type
2840x00000000Object subtype
Object values
324Unknown (cab_index)
364Number of chunk information blocks (CIBs) (cab_cib_count)
Chunk information block physical addresses (cab_cib_addr)
408 x Number of CIBsPhysical address of chunk information blocks (CIB)

Chunk information block

The chunk information block (chunk_info_block_t) is of variable size and consists of:

OffsetSizeValueDescription
Object header (cib_o)
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x40000007Object type
2840x00000000Object subtype
Object values
324Unknown (cib_index)
364Number of chunk information entries (cib_chunk_info_count)
Chunk information entries (cib_chunk_info)
408 x Number of entriesArray of chunk information entries

Chunk information entry

The chunk information entry (chunk_info_t) is 32 bytes in size and consists of:

OffsetSizeValueDescription
08Unknown (ci_xid)
88Unknown (ci_addr)
164Unknown (ci_block_count)
204Unknown (ci_free_count)
248Unknown (ci_bitmap_addr)

Reaper

The reaper is of unknown size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x80000011Object type
2840x00000000Object subtype
Object values
328Unknown
8Unknown
8Unknown
8Unknown
4Unknown
4Unknown
4Unknown
4Unknown
8Unknown
8Unknown
8Unknown
4Unknown
4Unknown

Reaper list

The reaper list entry is of unknown size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x80000012Object type
2840x00000000Object subtype
Object values
324Unknown
364Unknown
404Unknown
444Unknown (max_record_count)
484Unknown (record_count)
524Unknown (first_index)
564Unknown (last_index)
604Unknown (free_index)
64100 x ...Array of reaper list entries (nrle)

Reaper list entry

The reaper list entry is 40 bytes in size and consists of:

OffsetSizeValueDescription
04Forward link (fwlink)
44Unknown
84Type (type)
124Block size (blksize), in number of bytes
168Object identifier (oid)
248Physical address (paddr), which contains a block number relative to the start of the container
328Object transaction identifier (xid)

Key bag

The key bag consists of:

  • Container or volume key bag object
  • Key bag header
  • Key bag entries

Container key bag object

The container key bag object contains key data of the container.

The container key bag object is 32 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x6b657973 ("syek")Object type
2840x00000000Object subtype

Volume key bag object

The volume key bag object contains key data of a specific volume.

The volume key bag object is 32 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x72656373 ("scer")Object type
2840x00000000Object subtype

Key bag header

The key bag header (kb_locker_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
022Format version (kl_version)
22Number of entries (kl_nkeys)
44Key bag data size (kl_nbytes), in number of bytes and includes the size of key bag header
88Unknown (padding)

Key bag entries

A key bag entry consists of:

  • a key bag entry header
  • a key bag entry data
  • alignment padding

The key bag entry header specifies the type of the key bag entry data.

The key bag entries are 16-byte aligned.

Key bag entry header

The key bag entry header (keybag_entry_t) is 24 bytes in size and consists of:

OffsetSizeValueDescription
016Volume identifer (ke_uuid), which contains a big-endian UUID
162Entry type (ke_tag)
182Entry data size (ke_keylen), in number of bytes
204Unknown (padding)

Key bag entry types

Container key bag entry types
ValueIdentifierDescription
0x00KB_TAG_UNKNOWNUnknown
0x01KB_TAG_WRAPPING_KEY (or KB_TAG_RESERVED_1)Wrapping key
0x02KB_TAG_VOLUME_KEYVolume master key, which contains a Key encrypted key (KEK) packed object
0x03KB_TAG_VOLUME_UNLOCK_RECORDSVolume key bag extent
0x04KB_TAG_VOLUME_PASSPHRASE_HINTPassphrase hint
0x05KB_TAG_WRAPPING_M_KEYKey used to wrap a media key
0x06KB_TAG_VOLUME_M_KEYKey used to wrap a media key
0xf8KB_TAG_USER_PAYLOAD (or KB_TAG_RESERVED_F8)Unknown (user payload)

The volume master key is encryped with a volume key.

Volume key bag entry types
ValueIdentifierDescription
3Volume key, which contains a Key encrypted key (KEK) packed object
4Password hint, which contains a string without end-of-string character

The volume key is encryped with an user key.

Key bag packed object

The packed object consist of an object packed value that embeds attribute packed values.

Key bag packed value

The key bag packed value is of variable size and consists of:

OffsetSizeValueDescription
01Value tag (or value type), where the most-significant bit represents a flag
11Value data size, in number of bytes, where the most-significant bit represents a flag
......Value data

A packed value with a tag and size of 0 signifies the end of the packed values.

Note that the meaning of the value tags differ per packed object type.

Key encrypted key (KEK) packed object

The packed object value tag of a key encrypted key is 0x30 and contains the following attribute value tags:

ValueIdentifierDescription
0x80Unknown
0x81HMAC
0x82Unknown (salt?)
0xa3Wrapped Key Encryption Key (KEK) packed object
Wrapped Key Encryption Key (KEK) packed object

The packed object value tag of a wrapped kek encrypted key is 0xa3 and contains the following attribute value tags:

ValueIdentifierDescription
0x80Unknown
0x81Volume identifer, which contains a big-endian UUID
0x82Wrapped Key Encryption Key (KEK) metadata
0x83Wrapped Key Encryption Key (KEK) data
0x84Number of iterations for the PBKDF2 algorithm
0x85Salt for the PBKDF2 algorithm

Wrapped Key Encryption Key (KEK) metadata

The Wrapped Key Encryption Key (KEK) metadata is 8 bytes in size and consists of:

OffsetSizeValueDescription
04Encryption method
42Unknown
61Unknown
71Unknown
Encryption methods
ValueIdentifierDescription
0Unknown (AES-256)
2Unknown (AES-128 FVDE (CoreStorage FileVault) compatible)
16Unknown (AES-256), which has been observed in combination with recovery password protected volume key

Key bag data extent

The key bag data extent is 16 bytes in size and consists of:

OffsetSizeValueDescription
08Key bag block number
88Key bag number of blocks

Volume

The volume consists of:

  • volume superblock
  • volume object map

Note that an APFS volume has a corresponding “synthesized” device file though this cannot be directly read.

Volume superblock

The volume superblock (apfs_superblock_t) is 4096 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x0000000d or 0x4000000d (for snapshots)Object type
2840x00000000Object subtype
Object values
324"APSB"Signature (apfs_magic)
364File system index (apfs_fs_index)
408Volume feature flags (apfs_features)
488Read-only compatible feature flags (apfs_readonly_compatible_features)
568Incompatible feature flags (apfs_incompatible_features)
648(Last) unmount date and time (apfs_unmount_time), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
728Number of reserved blocks (apfs_reserve_block_count)
808Number of quota blocks (apfs_quota_block_count)
888Number of allocated blocks (apfs_fs_alloc_count)
9620Encryption state (apfs_meta_crypto)
1164File system root tree object type (apfs_root_tree_type)
1204Extent-reference tree object type (apfs_extentref_tree_type)
1244Snapshot metadata tree object type (apfs_snap_meta_tree_type)
1288Object map block number (apfs_omap_oid), which contains a block number relative to the start of the container of the object_map
1368File system root tree object identifier (apfs_root_tree_oid)
1448Extent-reference tree block number (apfs_extentref_tree_oid)
1528Snapshot metadata tree block number (apfs_snap_meta_tree_oid)
1608Rollback transaction identifier (apfs_revert_to_xid)
1688Rollback (physical) object identifier (apfs_revert_to_sblock_oid)
1768Next (available) file system object identifier (apfs_next_obj_id), where the upper 32-bit can contain 0xffffffff
1848Number of files (apfs_num_files)
1928Number of directories (apfs_num_directories)
2008Number of symbolic links (apfs_num_symlinks)
2088Number of other file system objects (apfs_num_other_fsobjects)
2168Number of snapshots (apfs_num_snapshots)
2248Total number of blocks allocated (apfs_total_blocks_alloced)
2328Total number of blocks freed (apfs_total_blocks_freed)
24016Volume identifier (apfs_vol_uuid), which contains a big-endian UUID
2568Modification date and time (apfs_last_mod_time), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
2648Volume flags (apfs_fs_flags)
27248Creation change information (apfs_formatted_by)
3208 x 48 = 3848 most recent modification change information (apfs_modified_by)
704256Volume label (or name) (apfs_volname)
9604Next (available) document identifier (apfs_next_doc_id)
9642Volume role flags (apfs_role)
9662Unknown (reserved)
9688Active snapshot transaction identifier (apfs_root_to_xid)
9768Encryption progress state (apfs_er_state_oid)
9848Largest clone object identifier (apfs_cloneinfo_id_epoch)
9928Largest clone transaction identifier (apfs_cloneinfo_xid)
10008Extended snapsnot metadata (virtual) object identifier (apfs_snap_meta_ext_oid)
100816Volume group identifier (apfs_volume_group_id), which contains a big-endian UUID
10248Integrity metadata (virtual) object identifier (apfs_integrity_meta_oid)
10328Extent tree (virtual) object identifier (apfs_fext_tree_oid)
10404Extent tree object type (apfs_fext_tree_type)
10444Unknown (reserved_type)
10488Unknown (reserved_oid)
105680Unknown
11362960Unknown (empty values)

Encryption state

The encryption state (wrapped_meta_crypto_state_t) is 20 bytes in size and consists of:

OffsetSizeValueDescription
02Major format version (major_version)
22Minor format version (minor_version)
44Flags (cpflags)
84Unknown (persistent_class)
124Unknown (key_os_version)
162Unknown (key_revision)
182Unknown (unused)

Encryption state flags

TODO: complete this section.

Change information

The change information (apfs_modified_by_t) is 48 bytes in size and consists of:

OffsetSizeValueDescription
032Application (id), which consist of a string with the first 31 characters of the name and version of the application that changed the file system and 0 if not set
328Change date and time (timestamp), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
408Change object transaction number (last_xid) or 0 if not set

Volume flags

ValueIdentifierDescription
0x0000000000000001APFS_FS_UNENCRYPTEDVolume is unencrypted
0x0000000000000002APFS_FS_EFFACEABLE (or APFS_FS_RESERVED_2)Unknown (Volume supports effaceable storage?)
0x0000000000000004APFS_FS_RESERVED_4Unknown (reserved)
0x0000000000000008APFS_FS_ONEKEYVolume uses software encryption with a single key (volume master key)
0x0000000000000010APFS_FS_SPILLEDOVERVolume has run out of allocated space on the solid-state drive
0x0000000000000020APFS_FS_RUN_SPILLOVER_CLEANERVolume has spilled over and the spillover cleaner must be run
0x0000000000000040APFS_FS_ALWAYS_CHECK_EXTENTREFVolume extent reference tree must be consulted before overwriting an extent
0x0000000000000080APFS_FS_RESERVED_80Unknown (reserved)
0x0000000000000080APFS_FS_RESERVED_100Unknown (reserved)

Volume features flags

ValueIdentifierDescription
0x0000000000000001APFS_FEATURE_DEFRAG_PRERELEASEUnknown
0x0000000000000002APFS_FEATURE_HARDLINK_MAP_RECORDSUnknown
0x0000000000000004APFS_FEATURE_DEFRAGUnknown
0x0000000000000008APFS_FEATURE_STRICTATIMEUnknown
0x0000000000000010APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACEUnknown

Volume read-only compatible feature flags

Current no read-only compatible feature flags are defined

Volume incompatible feature flags

ValueIdentifierDescription
0x0000000000000001APFS_INCOMPAT_CASE_INSENSITIVEFilenames are case insensitive
0x0000000000000002APFS_INCOMPAT_DATALESS_SNAPSVolume contains one or more snapshots without data
0x0000000000000004APFS_INCOMPAT_ENC_ROLLEDEncryption keys of the volume have been changed
0x0000000000000008APFS_INCOMPAT_NORMALIZATION_INSENSITIVEFilenames are normalization insensitive
0x0000000000000010APFS_INCOMPAT_INCOMPLETE_RESTOREUnknown
0x0000000000000020APFS_INCOMPAT_SEALED_VOLUMEUnknown
0x0000000000000040APFS_INCOMPAT_RESERVED_40Unknown

Volume role flags

ValueIdentifierDescription
0x0000APFS_VOL_ROLE_NONENone
0x0001APFS_VOL_ROLE_SYSTEMSystem
0x0002APFS_VOL_ROLE_USERUser
0x0004APFS_VOL_ROLE_RECOVERYRecovery
0x0008APFS_VOL_ROLE_VMVM
0x0010APFS_VOL_ROLE_PREBOOTPreboot
0x0020APFS_VOL_ROLE_INSTALLERInstaller

File system B-tree

The file system structures are stored in a B-tree.

The file system B-tree uses identifiers similar to catalog identifiers (CNIDs) on Hierarchical File System (HFS). In this document these identifiers are referred to as File System object identifiers (FSOIDs) to contrast other object identifiers (OIDs).

FSOIDIdentifierAssignment
0Unknown (Reserved)
1Parent identifier of the root directory (folder), nameless
2Directory identifier of the root directory (folder), named "root"
3Unknown, named "private-dir"

File system B-tree key

The file system B-tree key is of variable size and consists of:

OffsetSizeValueDescription
Object identifier and type (obj_id_and_type)
060 bitsFile system object identifier (FSOID)
7.44 bitsFile system data type
8...Optional additional key data dependent on the data type

File system data types

ValueIdentifierDescription
0x0APFS_TYPE_ANYUnknown (Any)
0x1APFS_TYPE_SNAP_METADATASnapshot metadata
0x2APFS_TYPE_EXTENTExtent
0x3APFS_TYPE_INODEInode
0x4APFS_TYPE_XATTRExtended attribute (xattr)
0x5APFS_TYPE_SIBLING_LINKSibling link
0x6APFS_TYPE_DSTREAM_IDData stream identifier
0x7APFS_TYPE_CRYPTO_STATEEncryption state
0x8APFS_TYPE_FILE_EXTENTFile extent
0x9APFS_TYPE_DIR_RECDirectory record
0xaAPFS_TYPE_DIR_STATSDirectory stats
0xbAPFS_TYPE_SNAP_NAMESnapshot name
0xcAPFS_TYPE_SIBLING_MAPSibling map
0xfAPFS_TYPE_INVALIDInvalid

File system B-tree branch node value

A file system B-tree node contains branch node values if BTNODE_LEAF is not set. The corresponding file system B-tree key represents the first key in the branch.

A file system B-tree branch node value is 8 bytes in size and consists of:

OffsetSizeValueDescription
08B-tree sub node object identifier, which can be resolved to a "physical" location using the object map

Snapshot metadata

The snapshot metadata value (j_snap_metadata_val_t) is of variable size and consists of:

OffsetSizeValueDescription
08Extent-reference tree block number, which contains a block number relative to the start of the container
88Volume superblock block number, which contains a block number relative to the start of the container
168Creation time, which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
248Change (or last modification) time, which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
328Unknown (inum)
404Extent-reference tree object type (extentref_tree_type)
444Flags
482Name string size (name_len), in number of bytes, which includes the size of the end-of-string character
50...Name string (name), which contains an UTF-8 encoded string with an end-of-string character

Snapshot metadata flags

ValueIdentifierDescription
0x00000001SNAP_META_PENDING_DATALESSUnknown

Extent

Extent key data

The extent key data (j_phys_ext_key_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x2File system data type

Extent value data

The extent value data (j_phys_ext_val_t) is 20 bytes in size and consists of:

OffsetSizeValueDescription
Extent size and data type (len_and_kind)
060 bitsExtent size, in number of bytes
7.44 bitsFile system data type
 
88File system object identifier of owner (owning_obj_id)
164Reference count (refcnt)

Inode

Inode key data

The inode key data (j_inode_key_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x3File system data type

Inode value data

The inode value data (j_inode_val_t) is of variable size and consists of:

OffsetSizeValueDescription
08Parent file system object identifier (parent_id)
88Data stream file system object identifier (private_id), which contains the file system object identifier of the file extents that make up the data stream
168Creation date and time (create_time), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
248Modification date and time (mod_time), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
328Inode change date and time (change_time), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
408Access date and time (access_time), which consists of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
488Inode flags (internal_flags)
564Number of children (nchildren) or number of (hard) links (nlink)
604Unknown (default_protection_class)
644Unknown (write_generation_counter)
684BSD file entry flags (bsd_flags)
724Owner user identifier (owner)
764Group identifier (gid)
802File mode
822Unknown (pad1)
848Unknown (pad2)
92...Extended fields (xfields)

Note that Mac OS stat command treats nchildren equivalent to nlink.

Inode flags
ValueIdentifierDescription
0x0000000000000001INODE_IS_APFS_PRIVATEThe inode is used internally, typically for a data stream
0x0000000000000002INODE_MAINTAIN_DIR_STATSThe inode tracks the size of all of its children
0x0000000000000004INODE_DIR_STATS_ORIGINThe inode has the INODE_MAINTAIN_DIR_STATS flag set explicitly, not due to inheritance
0x0000000000000008INODE_PROT_CLASS_EXPLICITThe inode data protection class was set explicitly when the inode was created
0x0000000000000010INODE_WAS_CLONEDThe inode was created by cloning another inode
0x0000000000000020INODE_FLAG_UNUSEDUnknown (Reserved)
0x0000000000000040INODE_HAS_SECURITY_EAThe inode has an access control list (security extended attribute)
0x0000000000000080INODE_BEING_TRUNCATEDThe inode was truncated
0x0000000000000100INODE_HAS_FINDER_INFOThe inode has a Finder info extended field
0x0000000000000200INODE_IS_SPARSEThe inode has a sparse byte count extended field
0x0000000000000400INODE_WAS_EVER_CLONEDThe inode has been cloned at least once
0x0000000000000800INODE_ACTIVE_FILE_TRIMMEDThe inode is an overprovisioning file that has been trimmed
0x0000000000001000INODE_PINNED_TO_MAINThe inode file content is always on the main storage device. This flag is used for Fusion drives where the main storage is a solid-state drive
0x0000000000002000INODE_PINNED_TO_TIER2The inode file content is always on the secondary storage device. This flag is used for Fusion drives where the secondary storage is a (magnetic) hard drive
0x0000000000004000INODE_HAS_RSRC_FORKThe inode has a resource fork
0x0000000000008000INODE_NO_RSRC_FORKThe inode does not have a resource fork
0x0000000000010000INODE_ALLOCATION_SPILLEDOVERThe inode file content has some space allocated outside of the preferred storage tier for that file
File modes
ValueIdentifierDescription
0xf000 (0170000)S_IFMTFile type bitmask
0x1000 (0010000)S_IFIFONamed pipe
0x2000 (0020000)S_IFCHRCharacter-special file (Character device)
0x4000 (0040000)S_IFDIRDirectory
0x6000 (0060000)S_IFBLKBlock-special file (Block device)
0x8000 (0100000)S_IFREGRegular file
0xa000 (0120000)S_IFLNKSymbolic link
0xc000 (0140000)S_IFSOCKSocket
0xe000 (0160000)S_IFWHTWhiteout

A whiteout is a file entry that covers up all entries of a particular name from lower branches.

BSD file entry flags

The BSD file entry flags are defined in the <sys/stat.h> header file.

ValueIdentifierDescription
0x0000ffffUF_SETTABLEbitmask of owner changeable flags
0x00000001UF_NODUMPdo not dump file entry
0x00000002UF_IMMUTABLEfile entry is immutable and may not be changed
0x00000004UF_APPENDwrites to file entry may only append
0x00000008UF_OPAQUEdirectory is opaque wrt. union
0x00000010UF_NOUNLINKfile entry may not be removed or renamed, which is not implement in Mac OS
0x00000020UF_COMPRESSEDfile entry is compressed
0x00000040UF_TRACKEDnotify about file entry changes
0x00000080UF_DATAVAULTentitlement required for reading and writing
0x00008000UF_HIDDENfile entry is hidden
0xffff0000SF_SETTABLEbitmask of superuser changeable flags
0x001f0000SF_SUPPORTEDbitmask of superuser supported flags
0x00010000SF_ARCHIVEDfile entry is archived
0x00020000SF_IMMUTABLEfile entry is immutable and may not be changed
0x00040000SF_APPENDwrites to file entry may only append
0x00080000SF_RESTRICTEDentitlement required for writing
0x00100000SF_NOUNLINKfile entry may not be removed, renamed or used as mount point
0x00200000SF_SNAPSHOTsnapshot inode, which is not implement in Mac OS

Extended attribute

Extended attribute key data

The extended attribute key data (j_xattr_key_t) is of variable size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x4File system data type
82Name string size (name_len), in number of bytes, which includes the size of the end-of-string character
10...Name string (name), which contains an UTF-8 encoded string with an end-of-string character

Note that the name of an extended attribute appears to be case senstive even on a case insensitive file system.

Extended attribute value data

The extended attribute value data (j_xattr_val_t) is of variable size and consists of:

OffsetSizeValueDescription
02Flags (flags)
22Extended attribute data size, in number of bytes
4...Extended attribute data

Note that extended attribute data size can contain 0 if the extended attribute flag XATTR_DATA_EMBEDDED is set.

Extended attribute names

NameDescription
com.apple.assetsd.dbRebuildInProgress
com.apple.assetsd.dbRebuildUuid
com.apple.assetsd.thumbnailCameraPreviewImageAssetID
com.apple.assetsd.UUID
com.apple.decmpfsApple File System Compression (decmpfs) extended attribute
com.apple.FinderInfo
com.apple.fs.symlinkSymbolic link
com.apple.genstore.info
com.apple.genstore.origdisplayname
com.apple.genstore.orig_perms_v1
com.apple.genstore.origposixname
com.apple.GeoServices.SHA1
com.apple.installd.installType
com.apple.installd.uniqueInstallID
com.apple.lastuseddate#PS
com.apple.metadata:_kMDItemUserTags
com.apple.metadata:com_apple_backup_excludeItem
com.apple.metadata:kMDItemDownloadedDate
com.apple.metadata:kMDItemWhereFroms
com.apple.metadata:kMDLabel_fwlfb7nbt2o7degof3q2o2btjy
com.apple.quarantine
com.apple.ResourceForkResource fork
com.apple.rootless
com.apple.system.Security
com.apple.TextEncoding
LastUpgradeCheck
lock
org.chromium.crashpad.database.initialized

Extended attribute flags

ValueIdentifierDescription
0x0001XATTR_DATA_STREAMExtended attribute data is stored in a data stream, where the attribute data contains an 8-byte file system object identifier of the corresponding data stream
0x0002XATTR_DATA_EMBEDDEDExtended attribute data is stored directly in the record
0x0004XATTR_FILE_SYSTEM_OWNEDExtended attribute is part of the file system, such as "com.apple.fs.symlink"
0x0008XATTR_RESERVED_8Unknown (Reserved)

Extended attribute data stream

The extended attribute data stream (j_xattr_dstream_t) is 48 bytes in size and consists of:

OffsetSizeValueDescription
08Data stream file system object identifier (xattr_obj_id), which contains the file system object identifier of the file extents that make up the data stream
840Data stream descriptor

The sibling link key data (j_sibling_key_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x4File system data type
88Sibling map identifier (sibling_id), which contains the file system object identifier of the sibling map record

The sibling link value data (j_sibling_val_t) is of variable size and consists of:

OffsetSizeValueDescription
08Parent file system object identifier (parent_id)
82Name string size (name_len), in number of bytes, which includes the size of the end-of-string character
10...Name string (name), which contains an UTF-8 encoded string with an end-of-string character

Data stream identifier

Data stream identifier key data

The data stream key data (j_dstream_id_key_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x6File system data type

Data stream identifier value data

The data stream value data (j_dstream_id_val_t) is 4 bytes in size and consists of:

OffsetSizeValueDescription
04Reference count (refcnt)

File extent

File extent key data

The file extent key data (j_file_extent_key_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x8File system data type
88Logical extent offset (or address) (logical_addr), which contains an offset relative to the start of the file entry data

File extent value data

The file extent value data (j_file_extent_val_t) is 24 bytes in size and consists of:

OffsetSizeValueDescription
Extent size and flags (len_and_flags)
07Extent size, in number of bytes
71Flags
 
88Physical block number (phys_block_num), which contains a block number relative to the start of the container
168Encryption identifier (crypto_id), which contains an unknown value and 0 if not set

File extent flags

ValueIdentifierDescription
0x01Unknown (Is encrypted?)

Note that according to the Apple File System Reference documentation there are currently no flags defined. The reference documentation also refers to len_and_flags as len_and_kind interchangeably.

Directory record

The directory record can have 2 different types of keys:

  • Key with name
  • Key with name and hash

Note that apprears that current APFS file system use a key with name and hash. Apple File System Reference documentation does not indicate how to distinguish between the two, but one method is to compare calculated and stored size of the key data.

Note that B-tree branch nodes are sorted using the case-sensitive name, even when the file system is case-insensitive.

Directory record key data with name

The directory record key data with name (j_drec_key_t) is of variable size and consists of:

OffsetSizeValueDescription
Object identifier and type (hdr)
060 bitsFile system object identifier (FSOID)
7.44 bits0x9File system data type
 
82Name string size (name_len), in number of bytes, which includes the size of the end-of-string character
10...Name string (name), which contains an UTF-8 encoded string with an end-of-string character

Directory record key data with name and hash

The directory record key data with name and hash (j_drec_hashed_key_t) is of variable size and consists of:

OffsetSizeValueDescription
Object identifier and type (hdr)
060 bitsFile system object identifier (FSOID)
7.44 bits0x9File system data type
Name string size and hash (name_len_and_hash)
811 bitsName string size, in number of bytes, which includes the size of the end-of-string character
9.321 bitsName hash
 
12...Name string (name), which contains an UTF-8 encoded string with an end-of-string character

Directory record value data

The directory record value data (j_drec_val_t) is of variable size and consists of:

OffsetSizeValueDescription
08File system object identifier of the directory entry (file_id)
88Date and time the directory entry was added (date_added), which consist of a signed integer that contains the number of nanoseconds since January 1, 1970 00:00:00 UTC or 0 if not set
162Directory entry flags
18...Extended fields (xfields)
Directory entry flags
ValueIdentifierDescription
0x0000DT_UNKNOWNUnknown
0x0001DT_FIFONamed pipe
0x0002DT_CHRCharacter-special file (Character device)
0x0004DT_DIRDirectory
0x0006DT_BLKBlock-special file (Block device)
0x0008DT_REGRegular file
0x000aDT_LNKSymbolic link
0x000cDT_SOCKSocket
0x000eDT_WHTWhiteout
0x000fDREC_TYPE_MASKDirectory type bitmask
0x0010RESERVED_10Unknown (reserved)

A whiteout is a file entry that covers up all entries of a particular name from lower branches.

Directory entry name hash

The name hash of a directory entry is calculated as following:

  • If the file system is case-insensitive represent the name in lower-case
  • Represent the name as an Unicode string in Normalization Form Canonical Decomposition (NFD)
  • Format the Unicode string as a little-endian UTF-32 stream without a byte-order-mark or end-of-string character
  • Calculate a CRC-32c checksum of the UTF-32 stream with an initial checksum of 0xffffffff (-1)
  • The lower 22-bits of checksum form the hash

The CRC-32 calculation uses the Castagnoli polynomial (0x1edc6f41), also known as CRC-32C (or CRC32-C). The CRC-32 calculation does not use the XOR with 0xffffffff before and after the calculation, which is also referred to as weak CRC-32 calculation.

Directory stats

Directory stats key data

The directory stats key data (j_dir_stats_key_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0xaFile system data type

Directory stats value data

The directory stats value data (j_dir_stats_val_t) is 32 bytes in size and consists of:

OffsetSizeValueDescription
08Number of children (num_children)
88Total size (total_size), in number of bytes
168Parent directory file system object identifier (chained_key)
248Generation count (gen_count)

Snapshot name

The snapshot name (j_snap_name_val_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsSnapshot metdata object identifier
7.44 bits0x1File system data type

Sibling map

Sibling map key data

The sibling map key data (j_sibling_map_key_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
060 bitsFile system object identifier (FSOID)
7.44 bits0x4File system data type

Sibling map value data

The sibling map value data (j_sibling_map_val_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
08File system object identifier (file_id)

Extended fields

Directory entries and inodes use extended fields to store additional attributes, such as the filename.

The extended fields (xf_blob_t) consists of:

OffsetSizeValueDescription
02Number of extended fields (xf_num_exts)
22Extended fields data size (xf_used_data), in number of bytes
Extended fields data (xf_data)
4...Array of extended field descriptors
......Extended fields data

Note that extended field values are stored 8-byte aligned in the extended field value data.

Extended field descriptor

An extended field descriptor (x_field_t) is 4 bytes in size and consists of:

OffsetSizeValueDescription
01Extended field type (x_type)
11Extended field flags (x_flags)
22Extended field data size (x_size), in number of bytes

Extended field types

Directory record extended field types
ValueIdentifierDescription
1DREC_EXT_TYPE_SIBLING_IDHard link sibling identifier, where the extended field data contains a 64-bit integer value
Inode extended field types
ValueIdentifierDescription
1INO_EXT_TYPE_SNAP_XIDTransaction identifier of a snapshot, where the extended field data contains a 64-bit integer value
2INO_EXT_TYPE_DELTA_TREE_OIDObject identifier of the snapshot extent delta list, where the extended field data contains a 64-bit integer value
3INO_EXT_TYPE_DOCUMENT_IDDocument identifier, where the extended field data contains a 32-bit integer value
4INO_EXT_TYPE_NAMEFilename, where the extended field data contains an UTF-8 string with end-of-string character
5INO_EXT_TYPE_PREV_FSIZEPrevious file size, in number of bytes, where the extended field data contains a 64-bit integer value
6INO_EXT_TYPE_RESERVED_6Unknown (Reserved)
7INO_EXT_TYPE_FINDER_INFOFinder information, where the extended field data contains a 32-bit integer value
8INO_EXT_TYPE_DSTREAMData stream, where the extended field data contains a data stream descriptor
9INO_EXT_TYPE_RESERVED_9Unknown (Reserved)
10INO_EXT_TYPE_DIR_STATS_KEYDirectory statistics; it is unknown if the extended field data contains an object identifier of the directory statistics or a j_dir_stats_val_t structure, seen 8 byte value
11INO_EXT_TYPE_FS_UUIDMounted file system identifier, where the extended field data contains a 128-bit UUID value
12INO_EXT_TYPE_RESERVED_12Unknown (Reserved)
13INO_EXT_TYPE_SPARSE_BYTESNumber of sparse bytes in the data stream, where the extended field data contains a 64-bit integer value
14INO_EXT_TYPE_RDEVBlock or character device identifier, where the extended field data contains a 32-bit integer value
15INO_EXT_TYPE_PURGEABLE_FLAGSInformation about a purgeable file; unknown, defined as reserved, seen 8 byte value
16INO_EXT_TYPE_ORIG_SYNC_ROOT_IDUnknown (Inode number of the sync-root hierarchy)

Extended field flags

ValueIdentifierDescription
0x01XF_DATA_DEPENDENTContents of the extended field is dependent on the data stream (file contents)
0x02XF_DO_NOT_COPYDo not duplicate the extended field when copied
0x04XF_RESERVED_4Unknown (Reserved)
0x08XF_CHILDREN_INHERITNewly created sub directory entries (children) inherit the extended field
0x10XF_USER_FIELDExtended field was added by an user-space program
0x20XF_SYSTEM_FIELDExtended field was added by the system (kernel)
0x40XF_RESERVED_40Unknown (Reserved)
0x80XF_RESERVED_80Unknown (Reserved)

Device identifier

The device identifier can be stored in different formats, such as: native, 386bsd, 4bsd, bsdos, freebsd, hpux, isc, linux, netbsd, osf1, sco, solaris, sunos, svr3, svr4 and ultrix.

The “native” and “hpux” device identifier is 4 bytes in size and consists of:

OffsetSizeValueDescription
01Major device number
120Unknown
31Minor device number

The “386bsd”, “4bsd”, “freebsd”, “isc”, “linux”, “netbsd”, “sco”, “sunos”, “svr3” and “ultrix” device identifier is 4 bytes in size and consists of:

OffsetSizeValueDescription
020Unknown
21Major device number
31Minor device number

The “solaris” and “svr4” device identifier is 4 bytes in size and consists of:

OffsetSizeValueDescription
0.018 bitsMinor device number
2.214 bitsMajor device number

The “bsdos” and “osf1” device identifier is 4 bytes in size and consists of:

OffsetSizeValueDescription
0.020 bitsMinor device number
2.412 bitsMajor device number

The “bsdos” alternative device identifier is 4 bytes in size and consists of:

OffsetSizeValueDescription
0.08 bitsSub unit number
1.012 bitsUnit number
2.412 bitsMajor device number

Data stream descriptor

The data stream descriptor (j_dstream_t) is 40 bytes in size and consist of:

OffsetSizeValueDescription
08Used size (size), in number of bytes
88Allocated size (alloced_size), in number of bytes
168(Default) encryption identifier (default_crypto_id)
248Total number of bytes written to data stream (total_bytes_written)
328Total number of bytes read from data stream (total_bytes_written)

File content

APFS supports multiple ways to store file content:

  • Data fork
  • Compressed data extended attribute
  • Compressed data extended attribute with resource fork
  • Resource fork
  • Extended attribute (named fork)

Data fork

The file content size is stored in an INO_EXT_TYPE_DSTREAM inode extended field type.

The file content data can be located through the file extents for the data stream file system object identifier in the file system tree.

If the volume is encrypted the file content is encrypted with the encryption identifier in defined by the file extent.

If the inode flag INODE_IS_SPARSE is set the file contains one or more spare file extents. A sparse file extent has a physical block number of 0.

Compressed data extended attribute

The file content data and size are stored in the compressed data header of a “com.apple.decmpfs” extended attribute.

Note it is currently assumed that the file entry either must not have a data fork or it the data fork must be of size 0.

Also see: Apple File System Compression (decmpfs).

Compressed data extended attribute with resource fork

The file content size is stored in the compressed data header of a “com.apple.decmpfs” extended attribute.

The file content data is stored in a “com.apple.ResourceFork” extended attribute.

Note it is currently assumed that the file entry either must not have a data fork or it the data fork must be of size 0.

Also see: Apple File System Compression (decmpfs).

Resource fork

TODO: complete this section.

Extended attribute (named fork)

TODO: complete this section.

EFI jumpstart

The EFI jumpstart (nx_efi_jumpstart_t) is of variable size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x00000014Object type
2840x00000000Object subtype
Object values
324"RDSJ"Signature (nej_magic)
3641Format version (nej_version)
404Unknown (nej_efi_file_len?)
444Number of extents (nej_num_extents)
4816 x 8Unknown (nej_reserved?)
176number of extents x 16EFI jumpstart extents (nej_rec_extents), which contains the location where the EFI driver is stored

EFI jumpstart extent

The EFI jumpstart extent (prange_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
08Block number
88Number of blocks

Extent-reference tree

TODO: complete this section.

Snapshots

TODO: complete this section.

Snapshot metadata tree

The snapshot metadata tree consists of:

  • snapshot metadata tree (object)
  • snapshot metadata B-tree

Snapshot metadata tree object

The snapshot metadata tree object is 32 bytes in size and consists of:

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x40000002 or 0x40000003Object type
2840x00000010Object subtype

Snapshot metadata B-tree

The object map values are stored in B-tree.

Snapshot metadata B-tree key

The snapshot metadata B-tree key (j_snap_metadata_key_t or j_snap_name_key_t) is of variable size and consists of:

OffsetSizeValueDescription
08Key object identifier (hdr)
If key object identifier data type is APFS_TYPE_SNAP_NAME
8...Snapshot name string, which contains an UTF-8 encoded string with an end-of-string character

Snapshot metadata B-tree branch node value

A snapshot metadata B-tree node contains branch node values if BTNODE_LEAF is not set. The corresponding inapshot metadata B-tree key represents the first key in the branch.

A snapshot metadata B-tree branch node value is 8 bytes in size and consists of:

OffsetSizeValueDescription
08Sub node block number, which contains a block number relative to the start of the container

Snapshot metadata B-tree leaf node value

The contents of a snapshot metadata B-tree leaf node depends on the file system data type of the key object identifier.

ValueDescription
APFS_TYPE_SNAP_METADATASnapshot metadata object identifier
APFS_TYPE_SNAP_NAMESnapshot name

Fusion drives

A Fusion drive consists of a main SSD and a tier2 magnetic disk that together form one logical APFS container.

Fusion middle tree

TODO: complete this section.

OffsetSizeValueDescription
Object header
08Object checksum, which contains 0 if not set
88Object identifier
168Object transaction identifier (xid)
2440x40000002Object type
2840x00000015Object subtype
Object values
......Unknown

Format edge cases and corruption scenarios

Container key bag is hardware encrypted but volume is not encrypted

Seen in APFS containers created by certain digital forensics tools. The container key bag is either hardware encrypted or contains random data but the volume is not encrypted.

Notes

TODO describe evict_mapping_val_t

References