The disk inside a DMG file is an ordinary disk. This page describes the structures the explorer follows to reach the files on it. APFS and HFS+ are both documented by Apple, in the Apple File System Reference and Technical Note TN1150; this page covers only the part needed to list and open files.
Partition maps
A device image starts with a partition map. Each block table in the property list holds one of its partitions.
| Map | Where it is | What it holds |
|---|---|---|
| Apple Partition Map | A driver descriptor map (ER) in sector 0, then one 512-byte entry (PM) from sector 1 | Each partition’s first block, block count, name and type, big-endian |
| GUID Partition Table | A protective MBR in sector 0, a header (EFI PART) in sector 1 | Partition entries with a type GUID, first and last LBA and a UTF-16 name, little-endian |
| MBR | Four 16-byte entries at byte 446 of sector 0, with 55 AA at byte 510 | Each partition’s type, first sector and sector count |
APFS
APFS numbers are little-endian. Every structure is an object: a 32-byte header holding a Fletcher-64 checksum (8 bytes), an object ID, a transaction ID, then a 32-bit type and a 32-bit subtype.
To reach the files, start with the container superblock (NXSB, at offset 32
of block 0), find the newest copy of it in the checkpoint descriptor area (the one with
the highest transaction ID and a good checksum), then follow the object map:
| Offset | Container superblock field |
|---|---|
| 32 | Magic, NXSB |
| 36 | Block size (usually 4096) |
| 40 | Block count |
| 72 | UUID |
| 104 | Checkpoint descriptor blocks (high bit set if not contiguous) |
| 112 | Checkpoint descriptor base block |
| 160 | Object map’s physical block |
| 180 | Maximum volumes |
| 184 | Volume object IDs, 8 bytes each, up to 100 |
An object map is a B-tree of (object ID, transaction ID) → (flags, size, physical block). A virtual object is found at the entry with its ID and the highest transaction ID not above the one wanted. A B-tree node has a 56-byte header, a table of contents, keys counted forward and values counted back from the end of the node; a root node ends with 40 bytes of tree information.
A volume superblock (APSB) gives:
| Offset | Volume superblock field |
|---|---|
| 32 | Magic, APSB |
| 56 | Incompatible features: 1 case-insensitive, 8 normalisation-insensitive, 0x20 sealed |
| 128 | Object map’s physical block |
| 136 | File system B-tree’s object ID |
| 152 | Snapshot metadata B-tree’s physical block |
| 184, 192, 200, 208 | Counts of files, folders, symbolic links and other objects |
| 264 | Flags; bit 0 is set when the volume is not encrypted |
| 704 | Volume name, 256 bytes, UTF-8 |
| 964 | Role |
| 1032 | A sealed volume’s file-extent B-tree |
An encrypted volume’s file system B-tree cannot be read without its key.
The file system B-tree
Every key starts with 8 bytes: an object ID in the low 60 bits and a type in the top 4. Keys are sorted by object ID, then type.
| Type | Record | Value holds |
|---|---|---|
| 1 | Snapshot metadata | Name, creation time and the snapshot’s superblock |
| 3 | Inode | Parent, private ID, four times, flags, link count, owner, mode, then extended fields including the data stream’s size |
| 4 | Extended attribute | Flags and either the data or a data stream ID |
| 5 | Sibling link | A hard link’s parent and name |
| 8 | File extent | Length, physical block, crypto ID; the key adds the offset in the stream |
| 9 | Directory record | The target’s inode number and date added; the key adds the name |
| 12 | Sibling map | The inode a sibling ID belongs to |
A file’s data extents are keyed by the inode’s private ID. A directory record’s key holds a hash and the name’s length (or just the length, on a volume that is neither case-insensitive nor normalisation-insensitive). The root folder is inode 2; a hard link shows up as several directory records for one inode.
HFS+ and HFSX
HFS+ numbers are big-endian. The volume header is at byte 1024 of the volume, with the
signature H+ (or HX for HFSX, which is case-sensitive). It
gives the allocation block size and the first extents of the catalogue, extents overflow
and attributes files, each a B-tree. A catalogue leaf record is a folder or file, keyed
by its parent’s ID and its name in UTF-16.
A file’s data and resource forks are its two lists of extents; a fork with more than
eight extents continues in the extents overflow file. A hard link is a file record of
type hlnk and creator hfs+; its special permission field names
the file iNodeN in the private metadata folder.
File compression (decmpfs)
A file compressed by the file system has an empty data fork and a
com.apple.decmpfs attribute. Apple has not published this; it comes from
the libfsapfs project’s documentation. The attribute has a 16-byte header:
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | Magic, the bytes fpmc |
| 4 | 4 | Method, little-endian |
| 8 | 8 | Uncompressed size, little-endian |
| Method | Data | Where |
|---|---|---|
| 1 | Uncompressed | Attribute |
| 3, 7, 11 | zlib, LZVN, LZFSE | Attribute |
| 9 | Uncompressed, with a marker byte 0xCC | Attribute |
| 4, 8, 12 | zlib, LZVN, LZFSE, in 64 KiB chunks | Resource fork |
| 10 | Uncompressed chunks, with marker byte 0xCC | Resource fork |
| 5 | Zeros | None |
| 13, 14 | LZBITMAP | Attribute, or resource fork |
A block’s first byte can mark it as stored, not compressed: 0xFF for zlib and
LZFSE, 0x06 for LZVN, followed by the raw data. In the resource fork:
- Method 4 uses a resource fork’s own structure: data starts at
0x100, at0x104the number of blocks (little-endian), then for each block an offset and size, both little-endian, counted from0x104. - Methods 8, 10 and 12 have a table of 4-byte little-endian offsets from the start of the fork; the first entry also gives the table’s length.
ISO 9660 and FAT
An ISO 9660 volume has volume descriptors from sector 16 (CD001), and its
directory records name extents of contiguous blocks. A Joliet supplementary descriptor
holds a second tree with long Unicode names; Rock Ridge adds names in the records’
system-use area.
A FAT volume’s boot sector gives the geometry; the cluster count decides whether the FAT is 12, 16 or 32 bits per entry. Directory entries are 32 bytes, with long names in the entries before the short one that owns them.
What this page does not cover
- APFS space management, the reaper and encryption keys (the Apple File System Reference covers them).
- LZBITMAP compression, which Apple has not published; files that use it are listed but cannot be opened.
- exFAT and NTFS are only identified, not read.