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 Compression (decmpfs)

Hierarchical File System (HFS) and Apple File System (APFS) use Apple File System Compression (decmpfs) to compress file contents.

decmpfs is sometimes referred to as AFSC (Apple File System Compression) or HFS/HFS+ compression and was introduced in Mac OS X 10.6 (Snow Leopard).

Overview

An Apple File System Compression (decmpfs) compressed file consists of:

  • an extended attribute named “com.apple.decmpfs”
  • compressed file content data

Characteristics

CharacteristicsDescription
Byte orderlittle-endian

decmpfs extended attribute

The decmpfs extended attribute consists of:

  • decmpfs header
  • optional compressed data

decmpfs header

The decmpfs header is 16 bytes in size and consists of:

OffsetSizeValueDescription
04"fpmc"Signature
44Compression method
88Uncompressed data size

Note that the signature is likely stored in little-endian and represents “cmpf”.

Compression methods

ValueIdentifierDescription
1CMP_Type1Unknown (uncompressed extended attribute data)
3kAFSCTypeZLibChunkzlib compressed extended attribute data, where the compressed data is stored in the extended attribute after the compressed data header
4kAFSCTypeZLib64k chunked zlib compressed resource fork, where the compressed data is stored in the resource fork
5Unknown (sparse compressed extended attribute data), where the uncompressed data contains 0-byte values. According to copyfile.c specifies de-dup within the generation store
6Unknown (unused)
Added in Mac OS X Yosemite (10.10)
7kAFSCTypeLZVNChunkLZVN compressed extended attribute data, where the compressed data is stored in the extended attribute after the compressed data header
8kAFSCTypeLZVN64k chunked LZVN compressed resource fork, where the compressed data is stored in the resource fork
9kAFSCTypeRawChunkUncompressed (raw) extended attribute data
10kAFSCTypeRaw64k chunked uncompressed (raw) data resource fork, where the compressed data is stored in the resource fork
Added in Mac OS X El Capitan (10.11)
11kAFSCTypeLZFSEChunkLZFSE compressed extended attribute data, where the compressed data is stored in the extended attribute after the compressed data header
12kAFSCTypeLZFSE64k chunked LZFSE compressed resource fork, where the compressed data is stored in the resource fork
Added in macOS Ventura (13.0)
13kAFSCTypeLZBitmapChunkLZBITMAP compressed extended attribute data, where the compressed data is stored in the extended attribute after the compressed data header
14kAFSCTypeLZBitmapLZBITMAP compressed resource fork, where the compressed data is stored in the resource fork
255CMP_MAXMaximum supported compression method
0x80000001DATALESS_CMPFS_TYPEUnknown (faulting file or dataless file or directory)
0x80000002DATALESS_PKG_CMPFS_TYPEUnknown (dataless package)

Note that copyfile.c indicates faulting files are deprecated since Mac OS X Yosemite (10.10).

Compressed file content data

The location of the compressed file content data depends on the compression method:

  • sparse data
  • compressed data stored in extended attribute
  • compressed data stored in resource fork

Sparse data

Compression method 5 has been observed to be used for sparse data, the file content data contains 0-byte values.

There are 12 bytes stored after the decmpfs compressed data header that consists of:

OffsetSizeValueDescription
04Unknown (Seen: 1)
44Unknown
84Unknown (Seen: 0)

Compressed data stored in extended attribute

Compression method 3, 5, 7, 9 and 11 store the compressed file content data in the extended attribute after the decmpfs compressed data header.

The compressed data consist of 1 compressed data block.

Compressed data stored in resource fork

Compression method 4, 8, 10 and 12 store the compressed file content data in the resource fork of the file.

The compressed data starts with metadata that contains the offsets of the compressed data blocks.

LZFSE compressed data

OffsetSizeValueDescription
04 x ...Array of compressed data block offsets, where an offset is relative from the start of the LZFSE compressed data
......LZFSE compressed data blocks

LZFSE compressed data block

If the first byte in the LZFSE compressed data block is 0xff, the block contains uncompressed data, otherwise the block should start with a LZFSE block marker.

LZVN compressed data

OffsetSizeValueDescription
04 x ...Array of compressed data block offsets, where an offset is relative from the start of the LZVN compressed data
......LZVN compressed data blocks

LZVN compressed data block

If the first byte in the LZVN compressed data block is 0x06 (end of stream oppcode), the block contains uncompressed data.

A compressed data block can contains a maximum of 65536 bytes of data. The compressed data block therefore should not exceed 65537 bytes in size.

Raw compressed data

OffsetSizeValueDescription
04 x ...Array of compressed data block offsets, where an offset is relative from the start of the raw compressed data
......raw compressed data blocks

Raw compressed data block

If the first byte in the raw compressed data block is 0xcc, the block contains uncompressed data.

The behavior of other byte values is unknown, it has been observed that Mac OS returns no data.

zlib compressed data

  • zlib compressed header
  • zlib compressed data block descriptors
  • zlib compressed data blocks
  • zlib compressed footer

zlib compressed header

The zlib compressed header is 260 bytes size and consists of:

OffsetSizeValueDescription
04256Unknown (header size or offset?)
44Compressed footer offset, where the offset is relative from the start of the zlib compressed data
84Unknown (total size - header size?)
12450Compressed footer size
16240Unknown (empty values)
2564Unknown

Note that the values in the zlib compressed header are stored in big-endian.

zlib compressed data block descriptors

The zlib compressed data block descriptors are variable size and consist of:

OffsetSizeValueDescription
04Number of block descriptors (offset and size tuples)
48 x ...Array of compressed data block descriptors

Note that the values in the zlib compressed data block descriptors are store in little-endian.

zlib compressed data block descriptor

The zlib compressed data block descriptor is 8 bytes in size and consists of:

OffsetSizeValueDescription
04Compressed block offset, where the offset is relative from the start of the zlib compressed data block descriptors
44Compressed block size

The zlib compressed footer is 50 bytes size and consists of:

OffsetSizeValueDescription
024Unknown (empty values)
242Unknown (signature offset?)
262Unknown (footer size?)
282Unknown
304"cmpf"signature (DECMPFS_MAGIC)
342Unknown (empty values?)
362Unknown
382Unknown
402Unknown (uncompressed block size?)
428Unknown (empty values)

Note that the values in the zlib compressed header are stored in big-endian.

zlib compressed data block

If the first byte in the zlib compressed data block is 0xff, the block contains uncompressed data, otherwise the block should start with 0x78.