apfs

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Public entry points for opening APFS containers from images and readers.

The APFS B-tree definition

The APFS checkpoint map definition

The APFS chunk-info block definition

The APFS container definition

The APFS container superblock definition

The APFS data block data handle implementation

The APFS data block vector implementation

APFS definitions and constants

Deflate (zlib) (un)compression functions

io/fs adapter: Volume implements fs.FS, fs.ReadDirFS, fs.StatFS and fs.ReadFileFS, so volumes can be walked with fs.WalkDir, tested with testing/fstest and passed to anything that consumes an fs.FS.

Symlinks are never followed: Stat and Open return the link itself, like archive-backed file systems. Use Readlink to resolve targets.

The APFS Fusion middle tree definition

Huffman tree functions

Inode functions

Input/Output (IO) handle functions

The key encryption key (KEK) functions

The APFS keybag definitions

Debug tracing helpers. Output is enabled by the `debug` build tag, which sets DebugOutput; see debug.go and debug_stub.go.

The APFS object definition

The APFS object map definitions

Object map B-tree functions

Password functions for APFS encryption

Profiler stub functions (no-op implementations when profiling is disabled)

Snapshot functions

Snapshot metadata tree functions

Support functions for APFS

Volume functions

Unlocking an encrypted (FileVault) volume with a supplied password.

Nothing here decides how APFS encrypts anything: the format is the published one, and every primitive it needs already existed unused. The keys travel a fixed path, and this file is that path joined up:

container keybag  -- names where a volume's own keybag lives, and holds
                     that volume's master key wrapped by the volume key
volume keybag     -- holds the key-encryption keys, one per crypto user
password          -- unwraps a KEK (PBKDF2, then RFC 3394) to the volume key
volume key        -- unwraps the master key from the container keybag
master key        -- the AES-XTS key everything on the volume is read with

Volume feature flags and their descriptions

Volume status flags (apfs_fs_flags) and what they say about encryption.

Volume keybag functions

Volume roles (apfs_role) and their names.

A volume's role is what makes a multi-volume container legible: without it a macOS installer or system image presents as N similarly-named volumes with no indication which one holds the OS.

Index

Constants

View Source
const (
	ExtendedAttributeFlagDataStream = 0x0001
	ExtendedAttributeFlagEmbedded   = 0x0002
)

Extended attribute flags

View Source
const (
	BitStreamStorageTypeUnknown         = 0x00
	BitStreamStorageTypeByteFrontToBack = 0x01
	BitStreamStorageTypeByteBackToFront = 0x02
)

Bit stream storage types

View Source
const (
	KeybagEntryTypeUnknown         = 0
	KeybagEntryTypeVolumeKey       = 2 // Volume master key (encrypted)
	KeybagEntryTypeVolumeKeyExtent = 3 // Volume keybag extent location
)

Keybag entry types

View Source
const (
	ContainerSuperblockObjectType = 0x80000001
	ContainerSuperblockSignature  = "NXSB"
	ContainerSuperblockSize       = 4096
)

Container superblock constants

View Source
const (
	CompressionMethodNone    = decmpfs.MethodNone
	CompressionMethodDeflate = decmpfs.MethodDeflate
	CompressionMethodLZFSE   = decmpfs.MethodLZFSE
	CompressionMethodLZVN    = decmpfs.MethodLZVN

	// Deprecated: decmpfs type 5 marks de-duplication within the generation
	// store rather than a compression method, so nothing maps to this and no
	// handle can carry it. It was previously decoded as sparse and answered
	// with zeros, which silently returned the wrong contents.
	CompressionMethodUnknown5 = decmpfs.MethodUnknown5
)

Compression method constants.

View Source
const (
	// OpenRead opens for read access
	OpenRead = AccessFlagRead
	// OpenWrite opens for write access - Reserved: not supported yet
	OpenWrite = AccessFlagWrite
	// OpenReadWrite opens for read and write access - Reserved: not supported yet
	OpenReadWrite = AccessFlagRead | AccessFlagWrite
)

File access modes

View Source
const (
	// MaximumCacheEntriesBTreeNodes is the maximum number of cached B-tree nodes
	MaximumCacheEntriesBTreeNodes = 8192
	// MaximumCacheEntriesDataBlocks is the maximum number of cached data blocks
	MaximumCacheEntriesDataBlocks = 16
)

Cache size limits

View Source
const (
	// EndianBig represents big-endian byte order
	EndianBig = 1
	// EndianLittle represents little-endian byte order
	EndianLittle = 0
)

Byte order constants

View Source
const (
	DeflateBlockTypeUncompressed   = 0x00
	DeflateBlockTypeHuffmanFixed   = 0x01
	DeflateBlockTypeHuffmanDynamic = 0x02
	DeflateBlockTypeReserved       = 0x03
)

Deflate block types Corresponds to LIBFSAPFS_DEFLATE_BLOCK_TYPES

View Source
const (
	ExtentrefTreeType                = 0x40000002
	ExtentReferenceTreeObjectSubtype = 0x0000000F
)

Expected object type and subtype for extentref tree

View Source
const (
	FileSystemRecordTypeAny               uint8 = 0x00
	FileSystemRecordTypeSnapMetadata      uint8 = 0x01
	FileSystemRecordTypeExtent            uint8 = 0x02 // physical extent, not file extent
	FileSystemRecordTypeInode             uint8 = 0x03
	FileSystemRecordTypeExtendedAttribute uint8 = 0x04
	FileSystemRecordTypeSiblingLink       uint8 = 0x05
	FileSystemRecordTypeDStreamID         uint8 = 0x06
	FileSystemRecordTypeCryptoState       uint8 = 0x07
	FileSystemRecordTypeFileExtent        uint8 = 0x08
	FileSystemRecordTypeDirectoryEntry    uint8 = 0x09
	FileSystemRecordTypeDirectoryStats    uint8 = 0x0a
	FileSystemRecordTypeSnapshotName      uint8 = 0x0b
	FileSystemRecordTypeSiblingMap        uint8 = 0x0c
	FileSystemRecordTypeFileInfo          uint8 = 0x0d
	FileSystemRecordTypeMaxValid          uint8 = 0x0d
	FileSystemRecordTypeInvalid           uint8 = 0x0f
)

File-system record types (Apple: j_obj_types, "The type of a file-system record"). The value occupies the high 4 bits of j_key_t.obj_id_and_type.

View Source
const (
	InvalidInoNum uint64 = 0 // INVALID_INO_NUM
	RootDirParent uint64 = 1 // ROOT_DIR_PARENT, the root directory's parent
	RootDirInoNum uint64 = 2 // ROOT_DIR_INO_NUM
	PrivDirInoNum uint64 = 3 // PRIV_DIR_INO_NUM, the private directory
	MinUserInoNum uint64 = 16
)

Reserved inode numbers. All inode numbers below MinUserInoNum are reserved.

View Source
const (
	// Object types for object map B-tree nodes
	ObjectMapBTreeRootNodeType = 0x40000002 // OBJECT_TYPE_BTREE
	ObjectMapBTreeSubNodeType  = 0x40000003 // OBJECT_TYPE_BTREE_NODE

	// Object subtype for object map B-tree
	ObjectMapBTreeSubtype = 0x0000000b // OBJECT_SUBTYPE_OMAP

	// B-tree node flags
	BTreeNodeFlagRoot           = 0x0001
	BTreeNodeFlagLeaf           = 0x0002
	BTreeNodeFlagFixedKVSize    = 0x0004
	BTreeNodeFlagHashed         = 0x0008
	BTreeNodeFlagNoHeader       = 0x0010
	BTreeNodeFlagCheckKOffInval = 0x8000

	// Maximum B-tree recursion depth
	MaxObjectMapBTreeDepth = 32

	// Object map B-tree key and value sizes
	ObjectMapBTreeKeySize   = 16
	ObjectMapBTreeValueSize = 16
)
View Source
const (
	// SpaceManagerDeviceCount is the number of storage devices a space manager
	// describes: the main device and, on Fusion drives, the Tier2 device.
	SpaceManagerDeviceCount = 2
	// SpaceManagerFreeQueueCount is the number of free queues.
	SpaceManagerFreeQueueCount = 3

	// Device indexes (Apple: enum smdev).
	SpaceManagerDeviceMain  = 0 // SD_MAIN
	SpaceManagerDeviceTier2 = 1 // SD_TIER2

	// Free queue indexes (Apple: enum sfq).
	SpaceManagerFreeQueueIP    = 0 // SFQ_IP, the internal pool
	SpaceManagerFreeQueueMain  = 1 // SFQ_MAIN
	SpaceManagerFreeQueueTier2 = 2 // SFQ_TIER2

	// SpaceManagerDeviceSize is the on-disk size of spaceman_device_t.
	SpaceManagerDeviceSize = 48
	// SpaceManagerFreeQueueSize is the on-disk size of spaceman_free_queue_t.
	SpaceManagerFreeQueueSize = 40
	// SpaceManagerAllocationZoneSize is the on-disk size of one device's
	// allocation-zone array within sm_datazone.
	SpaceManagerAllocationZoneSize = 576

	// SpaceManagerObjectType is the object type of a space manager
	// (OBJECT_TYPE_SPACEMAN with OBJ_EPHEMERAL set).
	SpaceManagerObjectType = 0x80000005
)

Space manager constants (Apple: SD_COUNT, SFQ_COUNT).

View Source
const (
	VolumeFeatureDefragPrerelease     uint64 = 0x0000000000000001
	VolumeFeatureHardlinkMapRecords   uint64 = 0x0000000000000002
	VolumeFeatureDefrag               uint64 = 0x0000000000000004
	VolumeFeatureStrictAtime          uint64 = 0x0000000000000008
	VolumeFeatureVolgrpSystemInoSpace uint64 = 0x0000000000000010
)

Compatible features (can be ignored by older implementations)

View Source
const (
	VolumeIncompatCaseInsensitive     uint64 = 0x0000000000000001
	VolumeIncompatDatalessSnaps       uint64 = 0x0000000000000002
	VolumeIncompatEncRolled           uint64 = 0x0000000000000004
	VolumeIncompatNormalizationInsens uint64 = 0x0000000000000008
	VolumeIncompatIncompleteRestore   uint64 = 0x0000000000000010
	VolumeIncompatSealedVolume        uint64 = 0x0000000000000020
)

Incompatible features (must be understood by implementation)

View Source
const (
	// VolumeFlagUnencrypted means the volume's contents are stored in the
	// clear. Its absence is what marks a FileVault volume: the flag says
	// "unencrypted", so encryption is the default reading of a volume that
	// does not set it.
	VolumeFlagUnencrypted uint64 = 0x00000001
	// VolumeFlagOneKey means the whole volume is encrypted with a single key,
	// rather than a key per file. This is what FileVault produces.
	VolumeFlagOneKey uint64 = 0x00000008
	// VolumeFlagSpilledOver means the volume has run out of space on its
	// Fusion drive's solid-state half and spilled onto the rotational one.
	VolumeFlagSpilledOver uint64 = 0x00000010
	// VolumeFlagRunSpilloverCleaner means the spillover cleaner should run.
	VolumeFlagRunSpilloverCleaner uint64 = 0x00000020
	// VolumeFlagAlwaysCheckExtentref means the extent-reference tree must
	// always be consulted when deciding whether an extent is in use.
	VolumeFlagAlwaysCheckExtentref uint64 = 0x00000040
)

Volume flags, from the volume superblock's apfs_fs_flags field.

View Source
const (
	VolumeRoleNone      uint16 = 0x0000
	VolumeRoleSystem    uint16 = 0x0001
	VolumeRoleUser      uint16 = 0x0002
	VolumeRoleRecovery  uint16 = 0x0004
	VolumeRoleVM        uint16 = 0x0008
	VolumeRolePreboot   uint16 = 0x0010
	VolumeRoleInstaller uint16 = 0x0020

	VolumeRoleData       uint16 = 1 << VolumeRoleEnumShift  // 0x0040
	VolumeRoleBaseband   uint16 = 2 << VolumeRoleEnumShift  // 0x0080
	VolumeRoleUpdate     uint16 = 3 << VolumeRoleEnumShift  // 0x00c0
	VolumeRoleXART       uint16 = 4 << VolumeRoleEnumShift  // 0x0100
	VolumeRoleHardware   uint16 = 5 << VolumeRoleEnumShift  // 0x0140
	VolumeRoleBackup     uint16 = 6 << VolumeRoleEnumShift  // 0x0180
	VolumeRoleReserved7  uint16 = 7 << VolumeRoleEnumShift  // 0x01c0
	VolumeRoleReserved8  uint16 = 8 << VolumeRoleEnumShift  // 0x0200
	VolumeRoleEnterprise uint16 = 9 << VolumeRoleEnumShift  // 0x0240
	VolumeRoleReserved10 uint16 = 10 << VolumeRoleEnumShift // 0x0280
	VolumeRolePrelogin   uint16 = 11 << VolumeRoleEnumShift // 0x02c0
)

Volume roles. Although the low six values are written as single bits, a volume's role is a single value and not a bit field — roles are never combined, and every checker matches apfs_role against these values exactly. That is also why the values at or above VolumeRoleEnumShift are safe: VolumeRoleUpdate is 3 << 6 = 0x00c0, which as bits would read as VolumeRoleData|VolumeRoleBaseband but as a value is simply "update".

View Source
const (
	// BSDFlagCompressed is UF_COMPRESSED: the file's content is held by its
	// com.apple.decmpfs attribute rather than by its data fork, which is empty.
	//
	// macOS dispatches on this flag, so a file carrying the attribute without
	// it reads as empty rather than as its contents.
	BSDFlagCompressed uint32 = 0x00000020
)

BSD file flags (chflags(2)) as stored in an inode's bsd_flags field.

View Source
const BTreeInfoSize = 40

BTreeInfoSize is the size of the B-tree info in bytes

View Source
const BTreeNodeHeaderSize = 24

BTreeNodeHeaderSize is the size of the B-tree node header in bytes

View Source
const CheckpointMapSize = 40

CheckpointMapSize is the size of the checkpoint map header in bytes

View Source
const CheckpointMappingSize = 40

CheckpointMappingSize is the size of the checkpoint map entry in bytes

View Source
const ChunkInfoBlockSize = 4096

ChunkInfoBlockSize is the size of the chunk-info block in bytes

View Source
const CompressedDataHandleBlockSize = decmpfs.BlockSize

CompressedDataHandleBlockSize is the uncompressed size of one decmpfs chunk. It is unrelated to the container block size.

View Source
const CompressedDataHeaderSize = decmpfs.HeaderSize

CompressedDataHeaderSize is the size of the com.apple.decmpfs header in bytes.

View Source
const ContainerKeybagObjectType = 0x6b657973 // 'keys'

Container keybag object type

View Source
const (
	DirectoryEntryExtendedFieldTypeSiblingID = 1
)

DirectoryRecordExtendedFieldType constants

View Source
const FusionMiddleTreeSize = 40

FusionMiddleTreeSize is the size of the Fusion middle tree structure in bytes

View Source
const MaxBTreeNodeDepth = 256

MaxBTreeNodeDepth is the maximum B-tree node recursion depth

View Source
const MaxDataBlockSize = 1024 * 1024 * 1024 // 1GB

Maximum allocation size for data blocks (safety limit)

View Source
const ObjectHeaderSize = 32

ObjectHeaderSize is the size of an APFS object header in bytes

View Source
const ObjectMapObjectType = 0x4000000b

ObjectMapObjectType is the object type for an object map

View Source
const ObjectMapSize = 104

ObjectMapSize is the size of an object map in bytes

View Source
const PathSeparator = '/'

PathSeparator is the path segment separator

View Source
const ReaperObjectType = 0x80000011

Container reaper object type

View Source
const (
	SegmentFlagIsSparse = 0x1 // the extent is a sparse (unallocated) range
)

Segment flags

View Source
const UnifiedIDSpaceMark uint64 = 0x0800000000000000

UnifiedIDSpaceMark (UNIFIED_ID_SPACE_MARK) divides the inode-number space the two members of a volume group share: the data volume numbers below it, the system volume at or above it, so a number identifies a file across the pair.

The reserved numbers above are not shifted by it. The spec says they are, but fsck_apfs rejects a volume written that way; see inoBaseFor in pkg/apfswrite.

View Source
const Version = "1.0.0"

Version is the version of this package.

View Source
const VolumeRoleEnumShift = 6

VolumeRoleEnumShift is APFS_VOLUME_ENUM_SHIFT: the bit position at or above which a role is encoded as a small enumeration rather than as one of the low-numbered values.

Variables

View Source
var (
	ContainerSignature = [4]byte{'N', 'X', 'S', 'B'}
	VolumeSignature    = [4]byte{'A', 'P', 'S', 'B'}
)

Container and volume signatures

View Source
var CompressedDataHeaderSignature = decmpfs.HeaderSignature

CompressedDataHeaderSignature is the magic every com.apple.decmpfs attribute begins with.

View Source
var DebugOutput = false

Debug output enabled flag (always false in non-debug builds)

View Source
var WrappedKEKInitializationVector = [8]byte{0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6}

WrappedKEKInitializationVector is the expected IV for wrapped KEK

Functions

func AESKeyUnwrap

func AESKeyUnwrap(key []byte, keyBitSize int, wrappedData []byte) ([]byte, error)

AESKeyUnwrap unwraps data using AES Key Wrap (RFC 3394)

func BuildDynamicHuffmanTrees

func BuildDynamicHuffmanTrees(bitStream *BitStream, literalsTree *HuffmanTree, distancesTree *HuffmanTree) error

BuildDynamicHuffmanTrees initializes the dynamic Huffman trees

func BuildFixedHuffmanTrees

func BuildFixedHuffmanTrees(literalsTree *HuffmanTree, distancesTree *HuffmanTree) error

BuildFixedHuffmanTrees initializes the fixed Huffman trees

func CalculateAdler32

func CalculateAdler32(data []byte, dataSize int, initialValue uint32) (uint32, error)

CalculateAdler32 calculates the little-endian Adler-32 of a buffer It uses the initial value to calculate a new Adler-32

func CalculateFletcher64

func CalculateFletcher64(buffer []byte, initialValue uint64) (uint64, error)

CalculateFletcher64 calculates the Fletcher 64 checksum of a buffer of data

func CalculateNameHash

func CalculateNameHash(utf8String []byte, useCaseFolding bool) uint32

CalculateNameHash calculates the APFS name hash from a UTF-8 string

Note: This implementation uses Go's unicode.ToLower() and norm.NFD for case folding and normalization. The C library has special case mappings for certain Unicode characters (Greek letters, ligatures, etc.) that may not be handled identically by Go's standard library. For most use cases, the Go implementation should produce compatible results. If exact hash matching is required for edge cases, additional special case mapping tables from the C implementation may need to be added.

func CalculateNameHashFromUTF16

func CalculateNameHashFromUTF16(utf16String []uint16, useCaseFolding bool) uint32

CalculateNameHashFromUTF16 calculates the APFS name hash from a UTF-16 string

Note: This implementation uses Go's unicode.ToLower() and norm.NFD for case folding and normalization. See CalculateNameHash for details about special case handling.

func CheckContainerSignature

func CheckContainerSignature(filename string) (bool, error)

CheckContainerSignature determines if a file contains an APFS container signature Returns true if the file has a valid container signature, false otherwise

func CheckContainerSignatureReader

func CheckContainerSignatureReader(reader io.ReaderAt) (bool, error)

CheckContainerSignatureReader determines if a reader contains an APFS container signature Returns true if the reader has a valid container signature, false otherwise

func CheckVolumeSignature

func CheckVolumeSignature(filename string) (bool, error)

CheckVolumeSignature determines if a file contains an APFS volume signature Returns true if the file has a valid volume signature, false otherwise

func CheckVolumeSignatureReader

func CheckVolumeSignatureReader(reader io.ReaderAt) (bool, error)

CheckVolumeSignatureReader determines if a reader contains an APFS volume signature Returns true if the reader has a valid volume signature, false otherwise

func CompareFileSystemKeys

func CompareFileSystemKeys(key1Data []byte, key2Data []byte, dataType uint8) int

CompareFileSystemKeys compares two file system B-tree keys Returns <0 if key1 < key2, 0 if equal, >0 if key1 > key2

func CompareNamesWithUTF8

func CompareNamesWithUTF8(name1 []byte, name2 []byte, useCaseFolding bool) int

CompareNamesWithUTF8 compares two names using UTF-8 encoding with optional case folding Returns 0 if equal, <0 if name1 < name2, >0 if name1 > name2

func CompareNamesWithUTF16

func CompareNamesWithUTF16(name1 []uint16, name2 []uint16, useCaseFolding bool) int

CompareNamesWithUTF16 compares two names using UTF-16 encoding with optional case folding Returns 0 if equal, <0 if name1 < name2, >0 if name1 > name2

func CreateFileExtentKey

func CreateFileExtentKey(identifier uint64, logicalAddress uint64) []byte

CreateFileExtentKey creates a file extent key

func CreateFileSystemKey

func CreateFileSystemKey(identifier uint64, dataType uint8) uint64

CreateFileSystemKey creates a file system B-tree key with identifier and data type

func CreateInodeKey

func CreateInodeKey(identifier uint64) []byte

CreateInodeKey creates an inode key

func DecodeHuffman

func DecodeHuffman(bitStream *BitStream, literalsTree *HuffmanTree, distancesTree *HuffmanTree, uncompressedData []byte, uncompressedDataSize int, uncompressedDataOffset *int) error

DecodeHuffman decodes a Huffman compressed block

func DecompressData

func DecompressData(compressedData []byte, compressionMethod int, uncompressedData []byte, uncompressedDataSize *int) error

DecompressData decompresses one decmpfs chunk with the given method.

func DeflateDecompress

func DeflateDecompress(compressedData []byte, compressedDataSize int, uncompressedData []byte, uncompressedDataSize *int) error

DeflateDecompress decompresses data using deflate compression

func DeflateDecompressZlib

func DeflateDecompressZlib(compressedData []byte, compressedDataSize int, uncompressedData []byte, uncompressedDataSize *int) error

DeflateDecompressZlib decompresses data using zlib compression

func DirectoryEntryExtendedFieldTypeName

func DirectoryEntryExtendedFieldTypeName(extendedFieldType uint8) string

DirectoryEntryExtendedFieldTypeName returns the name of the directory entry record extended field type

func ExtractDataTypeFromKey

func ExtractDataTypeFromKey(keyData []byte) (uint8, error)

File system B-tree data types Based on APFS specification and verified against go-apfs implementation ExtractDataTypeFromKey extracts the data type from a file system B-tree key The data type is stored in the upper 4 bits of the file system identifier

func ExtractIdentifierFromKey

func ExtractIdentifierFromKey(keyData []byte) (uint64, error)

ExtractIdentifierFromKey extracts the object identifier from a file system B-tree key The identifier is stored in the lower 60 bits of the file system identifier

func FileSystemRecordTypeName

func FileSystemRecordTypeName(recordType uint8) string

FileSystemRecordTypeName returns Apple's j_obj_types constant name for a file-system record type, or "UNKNOWN" if the value is not one Apple defines.

func InodeExtendedFieldTypeName

func InodeExtendedFieldTypeName(extendedFieldType uint8) string

InodeExtendedFieldTypeName returns the name of the inode extended field type

func IsValidVolumeRole

func IsValidVolumeRole(role uint16) bool

IsValidVolumeRole reports whether a raw apfs_role value is one the format defines. Combinations are not valid: a volume has exactly one role.

func PBKDF2

func PBKDF2(password []byte, salt []byte, numberOfIterations uint32, outputSize int) ([]byte, error)

PBKDF2 computes a PBKDF2-derived key from the given input using HMAC-SHA256

Parameters:

  • password: The password to derive the key from
  • salt: The salt value
  • numberOfIterations: The number of PBKDF2 iterations
  • outputSize: The desired output key size in bytes

Returns the derived key or an error

func ParseFileExtentKey

func ParseFileExtentKey(data []byte) (identifier uint64, logicalAddress uint64, err error)

ParseFileExtentKey parses a file extent key from binary data

func ParseVolumeRole

func ParseVolumeRole(s string) (uint16, error)

ParseVolumeRole maps a role token, as VolumeRoleString produces, to its apfs_role value. Matching is case-insensitive. An empty string means no role.

func PrintBTreeFlags

func PrintBTreeFlags(btreeFlags uint32)

PrintBTreeFlags is a no-op in non-debug builds

func PrintBTreeNodeFlags

func PrintBTreeNodeFlags(btreeNodeFlags uint16)

PrintBTreeNodeFlags is a no-op in non-debug builds

func PrintCheckpointFlags

func PrintCheckpointFlags(checkpointFlags uint32)

PrintCheckpointFlags is a no-op in non-debug builds

func PrintContainerCompatibleFeaturesFlags

func PrintContainerCompatibleFeaturesFlags(compatibleFeaturesFlags uint64)

PrintContainerCompatibleFeaturesFlags is a no-op in non-debug builds

func PrintContainerIncompatibleFeaturesFlags

func PrintContainerIncompatibleFeaturesFlags(incompatibleFeaturesFlags uint64)

PrintContainerIncompatibleFeaturesFlags is a no-op in non-debug builds

func PrintContainerReadOnlyCompatibleFeaturesFlags

func PrintContainerReadOnlyCompatibleFeaturesFlags(readOnlyCompatibleFeaturesFlags uint64)

PrintContainerReadOnlyCompatibleFeaturesFlags is a no-op in non-debug builds

func PrintData

func PrintData(data []byte, groupData bool)

PrintData is a no-op in non-debug builds

func PrintDirectoryEntryFlags

func PrintDirectoryEntryFlags(directoryEntryFlags uint16)

PrintDirectoryEntryFlags is a no-op in non-debug builds

func PrintExtendedAttributeFlags

func PrintExtendedAttributeFlags(extendedAttributeFlags uint16)

PrintExtendedAttributeFlags is a no-op in non-debug builds

func PrintExtendedFieldFlags

func PrintExtendedFieldFlags(extendedFieldFlags uint8)

PrintExtendedFieldFlags is a no-op in non-debug builds

func PrintGUIDValue

func PrintGUIDValue(functionName, valueName string, byteStream []byte, byteOrder binary.ByteOrder) error

PrintGUIDValue is a no-op in non-debug builds

func PrintInodeFlags

func PrintInodeFlags(inodeFlags uint64)

PrintInodeFlags is a no-op in non-debug builds

func PrintPOSIXTimeValue

func PrintPOSIXTimeValue(functionName, valueName string, byteStream []byte, byteOrder binary.ByteOrder, valueType string) error

PrintPOSIXTimeValue is a no-op in non-debug builds

func PrintReadOffsets

func PrintReadOffsets(reader io.ReaderAt, offsets []struct{ Offset, Size int64 }) error

PrintReadOffsets is a no-op in non-debug builds

func PrintVolumeCompatibleFeaturesFlags

func PrintVolumeCompatibleFeaturesFlags(compatibleFeaturesFlags uint64)

PrintVolumeCompatibleFeaturesFlags is a no-op in non-debug builds

func PrintVolumeFlags

func PrintVolumeFlags(volumeFlags uint64)

PrintVolumeFlags is a no-op in non-debug builds

func PrintVolumeIncompatibleFeaturesFlags

func PrintVolumeIncompatibleFeaturesFlags(incompatibleFeaturesFlags uint64)

PrintVolumeIncompatibleFeaturesFlags is a no-op in non-debug builds

func PrintVolumeReadOnlyCompatibleFeaturesFlags

func PrintVolumeReadOnlyCompatibleFeaturesFlags(readOnlyCompatibleFeaturesFlags uint64)

PrintVolumeReadOnlyCompatibleFeaturesFlags is a no-op in non-debug builds

func ReadBlock

func ReadBlock(bitStream *BitStream, blockType uint8, fixedHuffmanLiteralsTree *HuffmanTree, fixedHuffmanDistancesTree *HuffmanTree, uncompressedData []byte, uncompressedDataSize int, uncompressedDataOffset *int) error

ReadBlock reads a block of compressed data

func ReadBlockHeader

func ReadBlockHeader(bitStream *BitStream, blockType *uint8, lastBlockFlag *uint8) error

ReadBlockHeader reads the header of a block of compressed data

func ReadDataHeader

func ReadDataHeader(compressedData []byte, compressedDataSize int, compressedDataOffset *int) error

ReadDataHeader reads the compressed data header

func StringToUTF16

func StringToUTF16(str string) []uint16

StringToUTF16 converts a UTF-8 string to a UTF-16 slice

func UTF16ToString

func UTF16ToString(utf16Data []uint16) string

UTF16ToString converts a UTF-16 slice to a UTF-8 string

func ValidateChecksum

func ValidateChecksum(data []byte) bool

ValidateChecksum validates the Fletcher 64 checksum of an APFS object Returns true if the checksum is valid (non-zero and correct)

func VolumeRoleName

func VolumeRoleName(role uint16) string

VolumeRoleName returns the human-readable name of a raw apfs_role value, or "" when the volume has no role. A value the format does not define is rendered as its number rather than dropped — forensic tooling needs to see that something was there, and Apple may define values this build predates.

func VolumeRoleString

func VolumeRoleString(role uint16) string

VolumeRoleString returns a lowercase token naming a raw apfs_role value, suitable for JSON output and the --volume selector, or "" when the volume has no role.

func VolumeRoleTokens

func VolumeRoleTokens() []string

VolumeRoleTokens returns every role token ParseVolumeRole accepts, sorted, for use in help text and error messages.

Types

type AccessFlags

type AccessFlags int

AccessFlags represents file access modes Corresponds to LIBFSAPFS_ACCESS_FLAGS

const (
	// AccessFlagRead indicates read access (bit 1)
	AccessFlagRead AccessFlags = 0x01
	// AccessFlagWrite indicates write access (bit 2) - Reserved: not supported yet
	AccessFlagWrite AccessFlags = 0x02
)

func AccessFlagsRead

func AccessFlagsRead() AccessFlags

AccessFlagsRead returns the access flags for reading

type AttributeValues

type AttributeValues struct {
	// The flags
	Flags uint16

	// The name (UTF-8 encoded)
	Name []byte

	// The value data
	ValueData []byte

	// Value data size
	ValueDataSize uint64

	// Value data stream identifier
	ValueDataStreamIdentifier uint64

	// The value data file extents
	ValueDataFileExtents []*FileExtent
}

AttributeValues represents extended attribute values

func NewAttributeValues

func NewAttributeValues() *AttributeValues

NewAttributeValues creates a new AttributeValues instance

func (*AttributeValues) CompareName

func (av *AttributeValues) CompareName(name string) int

CompareName compares the attribute name with a given string Returns -1 if less, 0 if equal, 1 if greater

func (*AttributeValues) DataStream

func (av *AttributeValues) DataStream(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	encryptionContext *EncryptionContext,
	fileSystemBTree *FileSystemBTree,
	xid uint64,
) (*DataStream, error)

DataStream retrieves the attribute value data stream

func (*AttributeValues) ExtentByIndex

func (av *AttributeValues) ExtentByIndex(index int) (*FileExtent, error)

ExtentByIndex retrieves a file extent by index

func (*AttributeValues) FileExtents

func (av *AttributeValues) FileExtents(
	reader io.ReaderAt,
	fileSystemBTree *FileSystemBTree,
	xid uint64,
) error

FileExtents retrieves the attribute value data file extents

func (*AttributeValues) NameString

func (av *AttributeValues) NameString() string

Name returns the attribute name as a string

func (*AttributeValues) NumberOfExtents

func (av *AttributeValues) NumberOfExtents() int

NumberOfExtents returns the number of file extents

func (*AttributeValues) ReadKeyData

func (av *AttributeValues) ReadKeyData(data []byte) error

ReadKeyData reads the attribute values key data

func (*AttributeValues) ReadValueData

func (av *AttributeValues) ReadValueData(data []byte) error

ReadValueData reads the attribute values value data

type BTreeEntry

type BTreeEntry struct {
	// The key data
	KeyData []byte

	// The value data
	ValueData []byte
}

BTreeEntry represents a B-tree entry (key-value pair)

func NewBTreeEntry

func NewBTreeEntry() *BTreeEntry

NewBTreeEntry creates a new B-tree entry

func (*BTreeEntry) SetKeyData

func (e *BTreeEntry) SetKeyData(keyData []byte) error

SetKeyData sets the key data for this entry

func (*BTreeEntry) SetValueData

func (e *BTreeEntry) SetValueData(valueData []byte) error

SetValueData sets the value data for this entry

type BTreeFixedSizeEntry

type BTreeFixedSizeEntry struct {
	// The key data offset
	// Consists of 2 bytes
	KeyDataOffset uint16

	// The value data offset
	// Consists of 2 bytes
	ValueDataOffset uint16
}

BTreeFixedSizeEntry represents the APFS B-tree fixed size entry structure

type BTreeInfo

type BTreeInfo struct {
	// The flags
	// Consists of 4 bytes
	Flags uint32

	// The node size
	// Consists of 4 bytes
	NodeSize uint32

	// The key size
	// Consists of 4 bytes
	KeySize uint32

	// The value size
	// Consists of 4 bytes
	ValueSize uint32

	// The maximum key size
	// Consists of 4 bytes
	MaximumKeySize uint32

	// The maximum value size
	// Consists of 4 bytes
	MaximumValueSize uint32

	// The total number of keys
	// Consists of 8 bytes
	TotalNumberOfKeys uint64

	// The total number of nodes
	// Consists of 8 bytes
	TotalNumberOfNodes uint64
}

BTreeInfo represents the APFS B-tree info structure

func NewBTreeInfo

func NewBTreeInfo() *BTreeInfo

NewBTreeInfo creates a new B-tree info

func (*BTreeInfo) HasFixedSizeKeys

func (f *BTreeInfo) HasFixedSizeKeys() bool

HasFixedSizeKeys returns true if keys are fixed size

func (*BTreeInfo) HasFixedSizeValues

func (f *BTreeInfo) HasFixedSizeValues() bool

HasFixedSizeValues returns true if values are fixed size

func (*BTreeInfo) ReadData

func (f *BTreeInfo) ReadData(data []byte) error

ReadData reads the B-tree info from binary data

func (*BTreeInfo) UsesHashes

func (f *BTreeInfo) UsesHashes() bool

UsesHashes returns true if the B-tree uses hashes

type BTreeNode

type BTreeNode struct {
	// The object type
	ObjectType uint32

	// The object subtype
	ObjectSubtype uint32

	// The B-tree node header
	NodeHeader *BTreeNodeHeader

	// The B-tree info (only present for root nodes)
	Info *BTreeInfo

	// The B-tree entries
	Entries []*BTreeEntry
}

BTreeNode represents a B-tree node

func NewBTreeNode

func NewBTreeNode() *BTreeNode

NewBTreeNode creates a new B-tree node

func ReadBTreeNode

func ReadBTreeNode(
	reader io.ReaderAt,
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	blockNumber uint64,
) (*BTreeNode, error)

ReadBTreeNode reads a B-tree node from a data block This is a convenience function that reads a block and then parses it as a B-tree node

func (*BTreeNode) EntryByIndex

func (n *BTreeNode) EntryByIndex(index int) (*BTreeEntry, error)

EntryByIndex returns the entry at the specified index

func (*BTreeNode) HasFixedKVSize

func (n *BTreeNode) HasFixedKVSize() bool

HasFixedKVSize returns true if this node has fixed key-value size

func (*BTreeNode) IsLeafNode

func (n *BTreeNode) IsLeafNode() bool

IsLeafNode returns true if this is a leaf node

func (*BTreeNode) IsRootNode

func (n *BTreeNode) IsRootNode() bool

IsRootNode returns true if this is a root node

func (*BTreeNode) NumberOfEntries

func (n *BTreeNode) NumberOfEntries() int

NumberOfEntries returns the number of entries in this node

func (*BTreeNode) ReadData

func (n *BTreeNode) ReadData(data []byte) error

ReadData reads the B-tree node from binary data

func (*BTreeNode) ReadObjectData

func (n *BTreeNode) ReadObjectData(data []byte) error

ReadObjectData reads the APFS object header from binary data

type BTreeNodeHeader

type BTreeNodeHeader struct {
	// The node flags
	// Consists of 2 bytes
	Flags uint16

	// The level
	// Consists of 2 bytes
	Level uint16

	// The number of keys
	// Consists of 4 bytes
	NumberOfKeys uint32

	// The entries data offset
	// Consists of 2 bytes
	EntriesDataOffset uint16

	// The entries data size
	// Consists of 2 bytes
	EntriesDataSize uint16

	// The unused data offset
	// Consists of 2 bytes
	UnusedDataOffset uint16

	// The unused data size
	// Consists of 2 bytes
	UnusedDataSize uint16

	// The key free list offset
	// Consists of 2 bytes
	KeyFreeListOffset uint16

	// The key free list size
	// Consists of 2 bytes
	KeyFreeListSize uint16

	// The value free list offset
	// Consists of 2 bytes
	ValueFreeListOffset uint16

	// The value free list size
	// Consists of 2 bytes
	ValueFreeListSize uint16
}

BTreeNodeHeader represents the APFS B-tree node header structure

func NewBTreeNodeHeader

func NewBTreeNodeHeader() *BTreeNodeHeader

NewBTreeNodeHeader creates a new B-tree node header

func (*BTreeNodeHeader) HasFixedKVSize

func (h *BTreeNodeHeader) HasFixedKVSize() bool

HasFixedKVSize returns true if keys and values are fixed size Corresponds to BTNODE_FIXED_KV_SIZE flag (0x0004)

func (*BTreeNodeHeader) HasFixedSizeKeys

func (h *BTreeNodeHeader) HasFixedSizeKeys() bool

HasFixedSizeKeys returns true if keys are fixed size

func (*BTreeNodeHeader) HasFixedSizeValues

func (h *BTreeNodeHeader) HasFixedSizeValues() bool

HasFixedSizeValues returns true if values are fixed size

func (*BTreeNodeHeader) IsLeaf

func (h *BTreeNodeHeader) IsLeaf() bool

IsLeaf returns true if this is a leaf node

func (*BTreeNodeHeader) IsRoot

func (h *BTreeNodeHeader) IsRoot() bool

IsRoot returns true if this is a root node

func (*BTreeNodeHeader) ReadData

func (h *BTreeNodeHeader) ReadData(data []byte) error

ReadData reads the B-tree node header from binary data

type BTreeVariableSizeEntry

type BTreeVariableSizeEntry struct {
	// The key data offset
	// Consists of 2 bytes
	KeyDataOffset uint16

	// The key data size
	// Consists of 2 bytes
	KeyDataSize uint16

	// The value data offset
	// Consists of 2 bytes
	ValueDataOffset uint16

	// The value data size
	// Consists of 2 bytes
	ValueDataSize uint16
}

BTreeVariableSizeEntry represents the APFS B-tree variable size entry structure

type BitStream

type BitStream struct {
	// The byte stream
	ByteStream []byte

	// The byte stream offset
	ByteStreamOffset int

	// The storage type
	StorageType uint8

	// The bit buffer
	BitBuffer uint32

	// The number of bits remaining in the bit buffer
	BitBufferSize uint8
}

BitStream represents a bit stream for reading individual bits from a byte stream

func NewBitStream

func NewBitStream(
	byteStream []byte,
	byteStreamOffset int,
	storageType uint8,
) (*BitStream, error)

NewBitStream creates a new bit stream

func (*BitStream) Value

func (bs *BitStream) Value(numberOfBits uint8) (uint32, error)

Value retrieves a value from the bit stream

type BufferDataHandle

type BufferDataHandle struct {
	// The current offset in the buffer
	CurrentOffset int64

	// The data buffer
	Data []byte
}

BufferDataHandle represents a buffer data handle for reading from a byte buffer

func NewBufferDataHandle

func NewBufferDataHandle(data []byte) (*BufferDataHandle, error)

NewBufferDataHandle creates a new buffer data handle

func (*BufferDataHandle) ReadSegmentData

func (bdh *BufferDataHandle) ReadSegmentData(
	segmentIndex int,
	segmentData []byte,
) (int, error)

ReadSegmentData reads data from the current offset into a buffer This is a callback function for the data stream

func (*BufferDataHandle) SeekSegmentOffset

func (bdh *BufferDataHandle) SeekSegmentOffset(
	segmentIndex int,
	segmentOffset int64,
) (int64, error)

SeekSegmentOffset seeks to a specific offset in the data This is a callback function for the data stream

type CheckpointMap

type CheckpointMap struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// The flags
	// Consists of 4 bytes
	Flags uint32

	// The number of entries
	// Consists of 4 bytes
	NumberOfEntries uint32

	// The entries array
	// Consists of 101 x 40 bytes
	EntriesArray [4040]byte

	// Parsed entries
	Entries []*CheckpointMapping
}

CheckpointMap represents the APFS checkpoint map structure

func NewCheckpointMap

func NewCheckpointMap() *CheckpointMap

NewCheckpointMap creates a new checkpoint map

func (*CheckpointMap) PhysicalAddressByObjectIdentifier

func (cm *CheckpointMap) PhysicalAddressByObjectIdentifier(oid uint64) (uint64, error)

PhysicalAddressByObjectIdentifier retrieves the physical address for a specific object identifier Returns the physical address and a boolean indicating if found

func (*CheckpointMap) ReadData

func (cm *CheckpointMap) ReadData(data []byte) error

ReadData reads the checkpoint map from binary data

func (*CheckpointMap) ReadFrom

func (cm *CheckpointMap) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the checkpoint map from a file handle at the specified offset

type CheckpointMapping

type CheckpointMapping struct {
	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// The size
	// Consists of 4 bytes
	Size uint32

	// Unknown
	// Consists of 4 bytes
	Unknown1 uint32

	// The file system object identifier
	// Consists of 8 bytes
	FileSystemObjectIdentifier uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The physical address
	// Consists of 8 bytes
	PhysicalAddress uint64
}

CheckpointMapping represents the APFS checkpoint map entry structure

func NewCheckpointMapping

func NewCheckpointMapping() *CheckpointMapping

NewCheckpointMapping creates a new checkpoint map entry

func (*CheckpointMapping) ReadData

func (cme *CheckpointMapping) ReadData(data []byte) error

ReadData reads the checkpoint map entry from binary data

type ChunkInfoBlock

type ChunkInfoBlock struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// Unknown
	// Consists of 4 bytes
	Unknown1 uint32
}

ChunkInfoBlock represents the APFS chunk-info block structure

func NewChunkInfoBlock

func NewChunkInfoBlock() *ChunkInfoBlock

NewChunkInfoBlock creates a new chunk-info block

func (*ChunkInfoBlock) ReadData

func (cib *ChunkInfoBlock) ReadData(data []byte) error

ReadData reads the chunk-info block from binary data

func (*ChunkInfoBlock) ReadFrom

func (cib *ChunkInfoBlock) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the chunk-info block from a file handle at the specified offset

type CompressedDataHandle

type CompressedDataHandle = decmpfs.Handle

CompressedDataHandle decodes one decmpfs stream.

func NewCompressedDataHandle

func NewCompressedDataHandle(compressedDataStream *DataStream, uncompressedDataSize uint64, compressionMethod int) (*CompressedDataHandle, error)

NewCompressedDataHandle creates a decoder for a compressed stream.

type CompressedDataHeader

type CompressedDataHeader = decmpfs.Header

CompressedDataHeader is the com.apple.decmpfs attribute header.

func ParseCompressedDataHeader

func ParseCompressedDataHeader(data []byte) (*CompressedDataHeader, error)

ParseCompressedDataHeader parses a com.apple.decmpfs header. It returns nil with no error when the signature does not match.

type CompressedDataSource added in v0.2.0

type CompressedDataSource = decmpfs.Source

CompressedDataSource is the compressed byte range a decmpfs stream lives in. *DataStream satisfies it.

type Container

type Container struct {
	// The container superblock
	Superblock *ContainerSuperblock

	// The Fusion middle tree (optional, used in Fusion drives)
	FusionMiddleTree *FusionMiddleTree

	// The checkpoint map
	CheckpointMap *CheckpointMap

	// The container data handle
	ContainerDataHandle *ContainerDataHandle

	// The object map B-tree
	ObjectMapBTree *ObjectMapBTree

	// The container keybag (optional, used for encryption)
	Keybag *ContainerKeybag

	// The space manager (optional, tracks block allocation)
	SpaceManager *SpaceManager

	// The IO handle
	IOHandle *IOHandle

	// The file IO handle
	Reader io.ReaderAt
	// contains filtered or unexported fields
}

Container represents an APFS container

func NewContainer

func NewContainer(ioHandle *IOHandle) (*Container, error)

NewContainer creates a new container

func Open

func Open(reader io.ReaderAt, opts *OpenOptions) (*Container, error)

Open opens an APFS container from a reader. The container superblock is expected at opts.Offset (0 when the reader is already partition-relative, as disk.OpenWithOffset returns for DMGs).

func OpenImage

func OpenImage(path string, opts *OpenOptions) (*Container, io.Closer, error)

OpenImage opens an APFS container from a disk image file. The image format (DMG, GPT-partitioned raw image, or bare container) is detected from content. The returned closer releases the underlying image reader and must be closed after the container is no longer needed.

func (*Container) Close

func (c *Container) Close() error

Close releases resources associated with the container

func (*Container) Identifier

func (c *Container) Identifier() ([]byte, error)

Identifier retrieves the container identifier (UUID)

func (*Container) IsLocked

func (c *Container) IsLocked() (bool, error)

IsLocked checks if the container is locked (encrypted)

func (*Container) NumberOfVolumes

func (c *Container) NumberOfVolumes() (int, error)

NumberOfVolumes retrieves the number of volumes in the container

func (*Container) OpenRead

func (c *Container) OpenRead(reader io.ReaderAt, fileOffset int64) error

OpenRead opens a container for reading

func (*Container) Size

func (c *Container) Size() (uint64, error)

Size retrieves the size of the container

func (*Container) Volume

func (c *Container) Volume(index int) (*Volume, error)

Volume retrieves a volume by index

func (*Container) VolumeBySelector

func (c *Container) VolumeBySelector(selector string) (*Volume, error)

VolumeBySelector returns a single volume selected by index ("0"), name ("Macintosh HD"), UUID, or role ("system", or "role:system" to select by role explicitly). An empty selector returns the first volume.

Name and UUID are matched before a bare role token, so a volume literally named "system" still wins; the "role:" prefix skips that check for callers that need to be unambiguous. A bare role token that matches several volumes is an error rather than a silent first-match: picking one arbitrarily is the wrong default for a tool used forensically.

func (*Container) VolumeObjectIdentifiers

func (c *Container) VolumeObjectIdentifiers() ([]uint64, error)

VolumeObjectIdentifiers retrieves all volume object identifiers

func (*Container) Volumes

func (c *Container) Volumes() ([]*Volume, error)

Volumes returns all volumes in the container. Encrypted volumes are unlocked with the passwords given at open time when possible.

type ContainerDataHandle

type ContainerDataHandle struct {
	// The IO handle
	IOHandle *IOHandle
}

ContainerDataHandle represents a handle for reading data blocks from the container

func NewContainerDataHandle

func NewContainerDataHandle(ioHandle *IOHandle) (*ContainerDataHandle, error)

NewContainerDataHandle creates a new container data handle

func (*ContainerDataHandle) ReadDataBlock

func (cdh *ContainerDataHandle) ReadDataBlock(
	reader io.ReaderAt,
	elementIndex int,
	elementDataFileIndex int,
	elementDataOffset int64,
	elementDataSize int64,
	elementDataFlags uint32,
) (*DataBlock, error)

ReadDataBlock reads a data block from the container This is a callback function for a data block vector

Parameters follow the segment-reader shape used by DataBlockVector.

  • reader: The file handle to read from
  • elementIndex: The index of the element in the vector (unused here)
  • elementDataFileIndex: The file index (unused for containers)
  • elementDataOffset: The offset in the file to read from
  • elementDataSize: The size of the data to read
  • elementDataFlags: Flags for the data (unused here)

Returns the data block read from the container

type ContainerKeybag

type ContainerKeybag struct {
	// The entries array
	Entries []*KeybagEntry

	// Value to indicate if the container keybag is locked
	IsLocked bool
}

ContainerKeybag represents an APFS container keybag

func NewContainerKeybag

func NewContainerKeybag() (*ContainerKeybag, error)

NewContainerKeybag creates a new container keybag

func (*ContainerKeybag) Close

func (ckb *ContainerKeybag) Close() error

Close releases resources associated with the container keybag

func (*ContainerKeybag) ReadData

func (ckb *ContainerKeybag) ReadData(data []byte) error

ReadData reads the container keybag from decrypted data

func (*ContainerKeybag) ReadFrom

func (ckb *ContainerKeybag) ReadFrom(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	fileOffset int64,
	dataSize uint64,
	containerIdentifier []byte,
) error

ReadFrom reads the container keybag from a file

func (*ContainerKeybag) VolumeKeybagExtentByIdentifier

func (ckb *ContainerKeybag) VolumeKeybagExtentByIdentifier(
	volumeIdentifier []byte,
) (blockNumber uint64, numberOfBlocks uint64, found bool, err error)

VolumeKeybagExtentByIdentifier retrieves the volume keybag extent for a specific volume Returns block number and number of blocks, or error

func (*ContainerKeybag) VolumeMasterKeyByIdentifier

func (ckb *ContainerKeybag) VolumeMasterKeyByIdentifier(
	volumeIdentifier []byte,
	volumeKey []byte,
) (masterKey []byte, found bool, err error)

VolumeMasterKeyByIdentifier retrieves the volume master key for a specific volume Returns the decrypted master key, or error

type ContainerSuperblock

type ContainerSuperblock struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// The file system signature
	// Consists of 4 bytes
	// Contains: "NXSB"
	Signature [4]byte

	// The block size
	// Consists of 4 bytes
	BlockSize uint32

	// The number of blocks
	// Consists of 8 bytes
	NumberOfBlocks uint64

	// Compatible features flags
	// Consists of 8 bytes
	CompatibleFeaturesFlags uint64

	// Read only compatible features flags
	// Consists of 8 bytes
	ReadOnlyCompatibleFeaturesFlags uint64

	// Incompatible features flags
	// Consists of 8 bytes
	IncompatibleFeaturesFlags uint64

	// The container identifier
	// Consists of 16 bytes
	// Contains an UUID
	UUID [16]byte

	// The next object identifier
	// Consists of 8 bytes
	NextOID uint64

	// The next transaction identifier
	// Consists of 8 bytes
	NextXID uint64

	// The checkpoint descriptor area number of blocks
	// Consists of 4 bytes
	XPDescBlocks uint32

	// The checkpoint data area number of blocks
	// Consists of 4 bytes
	XPDataBlocks uint32

	// The checkpoint descriptor area block number
	// Consists of 8 bytes
	XPDescBase uint64

	// The checkpoint data area block number
	// Consists of 8 bytes
	XPDataBase uint64

	// The next index in the checkpoint descriptor area to write to (nx_xp_desc_next)
	// Consists of 4 bytes
	XPDescNext uint32

	// The next index in the checkpoint data area to write to (nx_xp_data_next)
	// Consists of 4 bytes
	XPDataNext uint32

	// The index of the first valid item in the checkpoint descriptor area (nx_xp_desc_index)
	// Consists of 4 bytes
	XPDescIndex uint32

	// The number of blocks in the checkpoint descriptor area used by the checkpoint (nx_xp_desc_len)
	// Consists of 4 bytes
	XPDescLen uint32

	// The index of the first valid item in the checkpoint data area (nx_xp_data_index)
	// Consists of 4 bytes
	XPDataIndex uint32

	// The number of blocks in the checkpoint data area used by the checkpoint (nx_xp_data_len)
	// Consists of 4 bytes
	XPDataLen uint32

	// The space manager object identifier
	// Consists of 8 bytes
	SpacemanOID uint64

	// The object map block number
	// Consists of 8 bytes
	OmapOID uint64

	// The reaper object identifier
	// Consists of 8 bytes
	ReaperOID uint64

	// Reserved for testing; treated as zero on production volumes (nx_test_type)
	// Consists of 4 bytes
	TestType uint32

	// The maximum number of volumes
	// Consists of 4 bytes
	MaxVolumes uint32

	// The volume object identifiers
	// Consists of 100 x 8 bytes
	VolumeOIDs [800]byte

	// The counters
	// Consists of 32 x 8 bytes
	Counters [256]byte

	// The first block of the blocked-out range (nx_blocked_out_prange.pr_start_paddr)
	// Consists of 8 bytes
	BlockedOutStartPaddr uint64

	// The number of blocks in the blocked-out range (nx_blocked_out_prange.pr_block_count)
	// Consists of 8 bytes
	BlockedOutBlockCount uint64

	// The object identifier of the tree used to keep track of evicted objects (nx_evict_mapping_tree_oid)
	// Consists of 8 bytes
	EvictMappingTreeOID uint64

	// The container flags (nx_flags)
	// Consists of 8 bytes
	Flags uint64

	// The physical address of the embedded EFI driver (nx_efi_jumpstart)
	// Consists of 8 bytes
	EFIJumpstart uint64

	// The Fusion set identifier
	// Consists of 16 bytes
	// Contains an UUID
	FusionUUID [16]byte

	// The keybag block number
	// Consists of 8 bytes
	KeylockerStartPaddr uint64

	// The keybag number of blocks
	// Consists of 8 bytes
	KeylockerBlockCount uint64

	// Ephemeral object information (nx_ephemeral_info[NX_EPH_INFO_COUNT])
	// Consists of 4 x 8 bytes
	EphemeralInfo [32]byte

	// Reserved for testing (nx_test_oid)
	// Consists of 8 bytes
	TestOID uint64

	// The Fusion middle tree block number
	// Consists of 8 bytes
	FusionMtOID uint64

	// The Fusion write-back cache object identifier
	// Consists of 8 bytes
	FusionWbcOID uint64

	// The first block of the Fusion write-back cache range (nx_fusion_wbc.pr_start_paddr)
	// Consists of 8 bytes
	FusionWbcStartPaddr uint64

	// The number of blocks in the Fusion write-back cache range (nx_fusion_wbc.pr_block_count)
	// Consists of 8 bytes
	FusionWbcBlockCount uint64
}

ContainerSuperblock represents the APFS container superblock structure

func NewContainerSuperblock

func NewContainerSuperblock() (*ContainerSuperblock, error)

NewContainerSuperblock creates a new container superblock

func (*ContainerSuperblock) ContainerIdentifier

func (csb *ContainerSuperblock) ContainerIdentifier() ([]byte, error)

ContainerIdentifier retrieves the container identifier (UUID)

func (*ContainerSuperblock) ReadData

func (csb *ContainerSuperblock) ReadData(data []byte) error

ReadData reads the container superblock from data

func (*ContainerSuperblock) ReadFrom

func (csb *ContainerSuperblock) ReadFrom(
	reader io.ReaderAt,
	fileOffset int64,
) error

ReadFrom reads the container superblock from a file

func (*ContainerSuperblock) VolumeObjectIdentifiers

func (csb *ContainerSuperblock) VolumeObjectIdentifiers() ([]uint64, error)

VolumeObjectIdentifiers returns the array of volume object identifiers Returns a slice of uint64 values (non-zero entries only)

type CryptMode

type CryptMode int

CryptMode represents encryption/decryption modes Corresponds to LIBFSAPFS_ENCRYPTION_CRYPT_MODES

const (
	// CryptModeDecrypt indicates decryption mode
	CryptModeDecrypt CryptMode = 0
	// CryptModeEncrypt indicates encryption mode
	CryptModeEncrypt CryptMode = 1
)

type DataBlock

type DataBlock struct {
	// The data buffer
	Data []byte

	// The data size
	DataSize int
}

DataBlock represents a data block that can be read from disk

func NewDataBlock

func NewDataBlock(size int) (*DataBlock, error)

NewDataBlock creates a new data block with the specified size

func (*DataBlock) Clear

func (db *DataBlock) Clear() error

Clear clears the data in the block

func (*DataBlock) Close

func (db *DataBlock) Close() error

Close releases resources associated with the data block This method clears sensitive data before allowing garbage collection

func (*DataBlock) Read

func (db *DataBlock) Read(
	reader io.ReaderAt,
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	offset int64,
	encryptionIdentifier uint64,
) error

Read reads the data block from disk at the specified offset

type DataBlockDataHandle

type DataBlockDataHandle struct {
	// The current offset in the data stream
	CurrentOffset int64

	// The total data size
	DataSize uint64

	// The file system data handle
	FileSystemDataHandle *FileSystemDataHandle

	// The data block vector
	DataBlockVector *DataBlockVector
}

DataBlockDataHandle represents a data handle for reading data through data blocks This is used for reading file data that spans multiple data blocks

func NewDataBlockDataHandle

func NewDataBlockDataHandle(
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	fileExtents []*FileExtent,
	isSparse bool,
) (*DataBlockDataHandle, error)

NewDataBlockDataHandle creates a new data block data handle

func (*DataBlockDataHandle) Close

func (dh *DataBlockDataHandle) Close() error

Close releases resources associated with the data block data handle

func (*DataBlockDataHandle) ReadSegmentData

func (dh *DataBlockDataHandle) ReadSegmentData(
	reader io.ReaderAt,
	segmentIndex int,
	segmentFileIndex int,
	segmentData []byte,
	segmentDataSize int,
	segmentFlags uint32,
	readFlags uint8,
) (int, error)

ReadSegmentData reads data from the current offset into a buffer This is a callback function for the data stream

Parameters:

  • reader: The file handle to read from
  • segmentIndex: The index of the segment (unused in this context)
  • segmentFileIndex: The file index (unused in this context)
  • segmentData: The buffer to read data into
  • segmentDataSize: The size of the buffer
  • segmentFlags: Flags for the segment (unused)
  • readFlags: Flags for reading (unused)

Returns the number of bytes read or error

func (*DataBlockDataHandle) SeekSegmentOffset

func (dh *DataBlockDataHandle) SeekSegmentOffset(
	reader io.ReaderAt,
	segmentIndex int,
	segmentFileIndex int,
	segmentOffset int64,
) (int64, error)

SeekSegmentOffset seeks to a certain offset in the data This is a callback function for the data stream

Parameters:

  • reader: The file handle (unused)
  • segmentIndex: The index of the segment (unused)
  • segmentFileIndex: The file index (unused)
  • segmentOffset: The offset to seek to

Returns the new offset or error

func (*DataBlockDataHandle) Size

func (dh *DataBlockDataHandle) Size() uint64

Size returns the total data size

type DataBlockVector

type DataBlockVector struct {
	// The element size (block size)
	ElementSize uint64

	// The data handle for reading blocks
	DataHandle *FileSystemDataHandle

	// The segments
	Segments []*DataBlockVectorSegment

	// Total size
	TotalSize uint64
	// contains filtered or unexported fields
}

DataBlockVector represents a vector of data blocks from file extents

func NewDataBlockVector

func NewDataBlockVector(
	ioHandle *IOHandle,
	dataHandle *FileSystemDataHandle,
	fileExtents []*FileExtent,
	isSparse bool,
) (*DataBlockVector, error)

NewDataBlockVector creates a new data block vector

func (*DataBlockVector) Close

func (v *DataBlockVector) Close() error

Close releases resources associated with the vector

func (*DataBlockVector) ElementValueAtOffset

func (v *DataBlockVector) ElementValueAtOffset(
	reader io.ReaderAt,
	logicalOffset int64,
) (*DataBlock, int64, error)

ElementValueAtOffset retrieves the data block at a given logical offset Returns the data block and the offset within that block

func (*DataBlockVector) Size

func (v *DataBlockVector) Size() (uint64, error)

Size returns the total size of the data in the vector

type DataBlockVectorSegment

type DataBlockVectorSegment struct {
	// The file index (extent index)
	FileIndex int

	// The physical offset in the file
	Offset int64

	// The size of the segment
	Size uint64

	// Flags for the segment
	Flags uint32

	// The logical offset where this segment starts
	LogicalOffset uint64
}

DataBlockVectorSegment represents a segment in the data block vector Each segment corresponds to a file extent

type DataStream

type DataStream struct {
	// contains filtered or unexported fields
}

DataStream represents a data stream abstraction for APFS data This wraps various data sources (embedded data, file extents, compressed data)

func NewDataStreamFromCompressedDataStream

func NewDataStreamFromCompressedDataStream(
	compressedDataStream *DataStream,
	uncompressedSize uint64,
	compressionMethod int,
) (*DataStream, error)

NewDataStreamFromCompressedDataStream creates a data stream from compressed data Uses CompressedDataHandle to decompress data on-the-fly

func NewDataStreamFromData

func NewDataStreamFromData(data []byte) (*DataStream, error)

NewDataStreamFromData creates a data stream from embedded byte data

func NewDataStreamFromFileExtents

func NewDataStreamFromFileExtents(
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	fileExtents []*FileExtent,
	size uint64,
	isSparse bool,
) (*DataStream, error)

NewDataStreamFromFileExtents creates a data stream from file extents Uses DataBlockDataHandle to read blocks from disk with encryption support

func (*DataStream) Close

func (ds *DataStream) Close() error

Close closes the data stream

func (*DataStream) Read

func (ds *DataStream) Read(p []byte) (n int, err error)

Read implements io.Reader interface

func (*DataStream) ReadAt

func (ds *DataStream) ReadAt(p []byte, off int64) (n int, err error)

ReadAt implements io.ReaderAt interface

func (*DataStream) Seek

func (ds *DataStream) Seek(offset int64, whence int) (int64, error)

Seek implements io.Seeker interface

func (*DataStream) Size

func (ds *DataStream) Size() uint64

Size returns the size of the data stream

type DirectoryEntryRecord

type DirectoryEntryRecord struct {
	// Identifier (inode number of the directory entry)
	Identifier uint64

	// ParentIdentifier (from the key)
	ParentIdentifier uint64

	// NameSize is the size of the name in bytes
	NameSize uint16

	// Name is the UTF-8 encoded name
	Name []byte

	// NameHash is the optional name hash (if present in key)
	NameHash uint32

	// AddedTime is the time when entry was added (nanoseconds since Unix epoch)
	AddedTime uint64

	// Flags are the directory entry flags
	Flags uint16

	// ExtendedFields stores any parsed extended fields
	ExtendedFields []ExtendedField
}

DirectoryEntryRecord represents an APFS directory entry record (directory entry)

func NewDirectoryEntryRecord

func NewDirectoryEntryRecord() *DirectoryEntryRecord

NewDirectoryEntryRecord creates a new directory entry record

func (*DirectoryEntryRecord) Clone

Clone creates a deep copy of the directory entry record

func (*DirectoryEntryRecord) CompareName

func (dr *DirectoryEntryRecord) CompareName(name []byte, nameHash uint32, useCaseFolding bool) int

CompareName compares the directory entry record name with the given name (convenience method) Returns 0 if equal, <0 if dr.Name < name, >0 if dr.Name > name

func (*DirectoryEntryRecord) CompareNameWithUTF8String

func (dr *DirectoryEntryRecord) CompareNameWithUTF8String(utf8String []byte, nameHash uint32, useCaseFolding bool) int

CompareNameWithUTF8String compares an UTF-8 string with a directory entry record name Returns -1 if less, 0 if equal, 1 if greater

func (*DirectoryEntryRecord) CompareNameWithUTF16String

func (dr *DirectoryEntryRecord) CompareNameWithUTF16String(utf16String []uint16, nameHash uint32, useCaseFolding bool) int

CompareNameWithUTF16String compares an UTF-16 string with a directory entry record name Returns -1 if less, 0 if equal, 1 if greater

func (*DirectoryEntryRecord) IsDirectory

func (dr *DirectoryEntryRecord) IsDirectory() bool

IsDirectory returns true if this record represents a directory

func (*DirectoryEntryRecord) NameString

func (dr *DirectoryEntryRecord) NameString() string

Name returns the name as a string (convenience method)

func (*DirectoryEntryRecord) ReadKeyData

func (dr *DirectoryEntryRecord) ReadKeyData(data []byte) error

ReadKeyData reads the directory entry record key data from a B-tree entry

func (*DirectoryEntryRecord) ReadValueData

func (dr *DirectoryEntryRecord) ReadValueData(data []byte) error

ReadValueData reads the directory entry record value data from a B-tree entry

func (*DirectoryEntryRecord) UTF8Name

func (dr *DirectoryEntryRecord) UTF8Name() (string, error)

UTF8Name retrieves the UTF-8 encoded name

func (*DirectoryEntryRecord) UTF8NameSize

func (dr *DirectoryEntryRecord) UTF8NameSize() (int, error)

UTF8NameSize retrieves the size of the UTF-8 encoded name The returned size includes the end-of-string character

func (*DirectoryEntryRecord) UTF16Name

func (dr *DirectoryEntryRecord) UTF16Name() ([]uint16, error)

UTF16Name retrieves the UTF-16 encoded name

func (*DirectoryEntryRecord) UTF16NameSize

func (dr *DirectoryEntryRecord) UTF16NameSize() (int, error)

UTF16NameSize retrieves the size of the UTF-16 encoded name The returned size includes the end-of-string character

type EncryptionContext

type EncryptionContext struct {
	// Method is the encryption method
	Method uint32
	// contains filtered or unexported fields
}

EncryptionContext represents an APFS encryption context

func NewEncryptionContext

func NewEncryptionContext(method uint32) (*EncryptionContext, error)

NewEncryptionContext creates a new encryption context

func NewEncryptionContextForKey added in v0.2.0

func NewEncryptionContextForKey(masterKey []byte) (*EncryptionContext, error)

NewEncryptionContextForKey builds a context from a volume master key, choosing the cipher from the key's length.

An XTS key is two keys end to end — one for the data, one for the tweak — so a 32-byte master key is AES-128-XTS and a 64-byte one is AES-256-XTS. The length is what says which, because the volume superblock's crypto fields describe per-file keys rather than the whole-volume key FileVault uses.

func (*EncryptionContext) Crypt

func (ec *EncryptionContext) Crypt(
	mode CryptMode,
	inputData []byte,
	outputData []byte,
	sectorNumber uint64,
	bytesPerSector uint16,
) error

Crypt encrypts or decrypts a block of data

func (*EncryptionContext) Decrypt

func (ec *EncryptionContext) Decrypt(
	inputData []byte,
	outputData []byte,
	sectorNumber uint64,
	bytesPerSector uint16,
) error

Decrypt is a convenience wrapper for Crypt with decrypt mode

func (*EncryptionContext) SetKeys

func (ec *EncryptionContext) SetKeys(key []byte, tweakKey []byte) error

SetKeys sets the de- and encryption keys

type EncryptionMethod

type EncryptionMethod int

EncryptionMethod represents encryption methods Corresponds to LIBFSAPFS_ENCRYPTION_METHODS

const (
	// EncryptionMethodAES256XTS represents AES-256-XTS encryption
	EncryptionMethodAES256XTS EncryptionMethod = 0
	// EncryptionMethodAES128XTS represents AES-128-XTS encryption
	EncryptionMethodAES128XTS EncryptionMethod = 2
)

type ExtendedAttribute

type ExtendedAttribute struct {
	// IOHandle is the I/O handle
	IOHandle *IOHandle

	// FileHandle is the file I/O handle
	FileHandle io.ReaderAt

	// EncryptionContext is the encryption context
	EncryptionContext *EncryptionContext

	// FileSystemBTree is the file system B-tree
	FileSystemBTree *FileSystemBTree

	// Identifier is the file system identifier
	Identifier uint64

	// AttributeValues contains the attribute values
	AttributeValues *AttributeValues

	// XID is the transaction identifier
	XID uint64

	// DataStream is the data stream (lazily initialized)
	DataStream *DataStream
	// contains filtered or unexported fields
}

ExtendedAttribute represents an APFS extended attribute

func NewExtendedAttribute

func NewExtendedAttribute(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	encryptionContext *EncryptionContext,
	fileSystemBTree *FileSystemBTree,
	attributeValues *AttributeValues,
	xid uint64,
) (*ExtendedAttribute, error)

NewExtendedAttribute creates a new extended attribute

func (*ExtendedAttribute) ExtentByIndex

func (ea *ExtendedAttribute) ExtentByIndex(index int) (offset int64, size uint64, flags uint32, err error)

ExtentByIndex retrieves an extent by index

func (*ExtendedAttribute) NumberOfExtents

func (ea *ExtendedAttribute) NumberOfExtents() (int, error)

NumberOfExtents retrieves the number of extents

func (*ExtendedAttribute) Offset

func (ea *ExtendedAttribute) Offset() (int64, error)

Offset retrieves the current offset

func (*ExtendedAttribute) Read

func (ea *ExtendedAttribute) Read(buffer []byte) (int, error)

Read reads data at the current offset into a buffer

func (*ExtendedAttribute) ReadAt

func (ea *ExtendedAttribute) ReadAt(buffer []byte, offset int64) (int, error)

ReadAt reads data at a specific offset

func (*ExtendedAttribute) Seek

func (ea *ExtendedAttribute) Seek(offset int64, whence int) (int64, error)

Seek seeks to a certain offset

func (*ExtendedAttribute) Size

func (ea *ExtendedAttribute) Size() (uint64, error)

Size retrieves the size

func (*ExtendedAttribute) UTF8Name

func (ea *ExtendedAttribute) UTF8Name() (string, error)

UTF8Name retrieves the UTF-8 encoded name

func (*ExtendedAttribute) UTF8NameSize

func (ea *ExtendedAttribute) UTF8NameSize() (int, error)

UTF8NameSize retrieves the size of the UTF-8 encoded name The returned size includes the end-of-string character

func (*ExtendedAttribute) UTF16Name

func (ea *ExtendedAttribute) UTF16Name() ([]uint16, error)

UTF16Name retrieves the UTF-16 encoded name

func (*ExtendedAttribute) UTF16NameSize

func (ea *ExtendedAttribute) UTF16NameSize() (int, error)

UTF16NameSize retrieves the size of the UTF-16 encoded name The returned size includes the end-of-string character

type ExtendedField

type ExtendedField struct {
	Type  uint8
	Flags uint8
	Data  []byte
}

ExtendedField represents an extended field in a directory entry record

type ExtentrefTree

type ExtentrefTree struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// Unknown
	// Consists of 4 bytes
	Unknown1 uint32
}

ExtentrefTree represents the APFS extentref tree structure

func NewExtentrefTree

func NewExtentrefTree() *ExtentrefTree

NewExtentrefTree creates a new extentref tree

func (*ExtentrefTree) ReadData

func (ert *ExtentrefTree) ReadData(data []byte) error

ReadData reads the extentref tree from data

func (*ExtentrefTree) ReadFrom

func (ert *ExtentrefTree) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the extentref tree from a file at a specific offset

type FeatureDescription

type FeatureDescription struct {
	Flag        uint64
	Name        string
	Description string
}

FeatureDescription holds a feature flag and its description

type FileEntry

type FileEntry struct {
	// IOHandle is the I/O handle
	IOHandle *IOHandle

	// FileHandle is the file I/O handle
	FileHandle io.ReaderAt

	// EncryptionContext is the encryption context
	EncryptionContext *EncryptionContext

	// FileSystemBTree is the file system B-tree
	FileSystemBTree *FileSystemBTree

	// Inode contains the inode metadata
	Inode *Inode

	// DirectoryEntryRecord contains the directory entry record (may be nil for root)
	DirectoryEntryRecord *DirectoryEntryRecord

	// XID is the transaction identifier
	XID uint64

	// ExtendedAttributes is the array of extended attributes (lazily initialized)
	ExtendedAttributes []*AttributeValues

	// CompressedDataAttributeValues holds com.apple.decmpfs attribute
	CompressedDataAttributeValues *AttributeValues

	// CompressedDataHeader contains the compressed data header
	CompressedDataHeader *CompressedDataHeader

	// ResourceForkAttributeValues holds com.apple.ResourceFork attribute
	ResourceForkAttributeValues *AttributeValues

	// SymbolicLinkAttributeValues holds com.apple.fs.symlink attribute
	SymbolicLinkAttributeValues *AttributeValues

	// SymbolicLinkData contains the symbolic link target data
	SymbolicLinkData []byte

	// DirectoryEntries contains sub-directory entries (lazily initialized)
	DirectoryEntries []*DirectoryEntryRecord

	// FileExtents contains the file extents (lazily initialized)
	FileExtents []*FileExtent

	// DataStream is the data stream (lazily initialized)
	DataStream *DataStream
	// contains filtered or unexported fields
}

FileEntry represents an APFS file entry (file, directory, or special file)

func NewFileEntry

func NewFileEntry(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	encryptionContext *EncryptionContext,
	fileSystemBTree *FileSystemBTree,
	inode *Inode,
	directoryEntryRecord *DirectoryEntryRecord,
	xid uint64,
) (*FileEntry, error)

NewFileEntry creates a new file entry

func (*FileEntry) AccessTime

func (fe *FileEntry) AccessTime() (int64, error)

AccessTime retrieves the access time

func (*FileEntry) AddedTime

func (fe *FileEntry) AddedTime() (int64, error)

AddedTime retrieves the added time (from directory entry record)

func (*FileEntry) BSDFlags added in v0.2.0

func (fe *FileEntry) BSDFlags() (uint32, error)

BSDFlags retrieves the inode's chflags(2) flags. Test it against the BSDFlag* constants; BSDFlagCompressed is the one that says the content lives in com.apple.decmpfs rather than the data fork.

func (*FileEntry) CreationTime

func (fe *FileEntry) CreationTime() (int64, error)

CreationTime retrieves the creation time

func (*FileEntry) DataSize

func (fe *FileEntry) DataSize() (int64, error)

DataSize retrieves the data size (lazy calculation)

func (*FileEntry) DeviceIdentifier

func (fe *FileEntry) DeviceIdentifier() (uint32, error)

DeviceIdentifier retrieves the device identifier

func (*FileEntry) DeviceNumber

func (fe *FileEntry) DeviceNumber() (major uint32, minor uint32, err error)

DeviceNumber retrieves the major and minor device numbers

func (*FileEntry) ExtendedAttributeByIndex

func (fe *FileEntry) ExtendedAttributeByIndex(index int) (*ExtendedAttribute, error)

ExtendedAttributeByIndex retrieves an extended attribute by index

func (*FileEntry) ExtendedAttributeByName

func (fe *FileEntry) ExtendedAttributeByName(name string) (*ExtendedAttribute, error)

ExtendedAttributeByName retrieves an extended attribute by name

func (*FileEntry) ExtendedAttributeByUTF16Name

func (fe *FileEntry) ExtendedAttributeByUTF16Name(utf16Name []uint16) (*ExtendedAttribute, error)

ExtendedAttributeByUTF16Name retrieves an extended attribute by UTF-16 name

func (*FileEntry) ExtentByIndex

func (fe *FileEntry) ExtentByIndex(index int) (offset int64, size uint64, flags uint32, err error)

ExtentByIndex retrieves an extent by index

func (*FileEntry) FileMode

func (fe *FileEntry) FileMode() (uint16, error)

FileMode retrieves the file mode (permissions and type)

func (*FileEntry) GroupIdentifier

func (fe *FileEntry) GroupIdentifier() (uint32, error)

GroupIdentifier retrieves the group identifier (GID)

func (*FileEntry) HasExtendedAttributeByName

func (fe *FileEntry) HasExtendedAttributeByName(name string) (bool, error)

HasExtendedAttributeByName checks if an extended attribute exists by name

func (*FileEntry) HasExtendedAttributeByUTF16Name

func (fe *FileEntry) HasExtendedAttributeByUTF16Name(utf16Name []uint16) (bool, error)

HasExtendedAttributeByUTF16Name checks if an extended attribute exists by UTF-16 name

func (*FileEntry) Identifier

func (fe *FileEntry) Identifier() (uint64, error)

Identifier retrieves the identifier

func (*FileEntry) InodeChangeTime

func (fe *FileEntry) InodeChangeTime() (int64, error)

InodeChangeTime retrieves the inode change time

func (*FileEntry) ModificationTime

func (fe *FileEntry) ModificationTime() (int64, error)

ModificationTime retrieves the modification time

func (*FileEntry) NumberOfExtendedAttributes

func (fe *FileEntry) NumberOfExtendedAttributes() (int, error)

NumberOfExtendedAttributes retrieves the number of extended attributes

func (*FileEntry) NumberOfExtents

func (fe *FileEntry) NumberOfExtents() (int, error)

NumberOfExtents retrieves the number of extents

func (fe *FileEntry) NumberOfLinks() (uint32, error)

NumberOfLinks retrieves the number of hard links

func (*FileEntry) NumberOfSubFileEntries

func (fe *FileEntry) NumberOfSubFileEntries() (int, error)

NumberOfSubFileEntries retrieves the number of sub-file entries (directory children)

func (*FileEntry) Offset

func (fe *FileEntry) Offset() (int64, error)

Offset retrieves the current offset

func (*FileEntry) OwnerIdentifier

func (fe *FileEntry) OwnerIdentifier() (uint32, error)

OwnerIdentifier retrieves the owner identifier (UID)

func (*FileEntry) ParentFileEntry

func (fe *FileEntry) ParentFileEntry() (*FileEntry, error)

ParentFileEntry retrieves the parent file entry

func (*FileEntry) ParentIdentifier

func (fe *FileEntry) ParentIdentifier() (uint64, error)

ParentIdentifier retrieves the parent identifier

func (*FileEntry) Read

func (fe *FileEntry) Read(buffer []byte) (int, error)

Read reads data at the current offset into a buffer

func (*FileEntry) ReadAt

func (fe *FileEntry) ReadAt(buffer []byte, offset int64) (int, error)

ReadAt reads data at a specific offset

func (*FileEntry) Seek

func (fe *FileEntry) Seek(offset int64, whence int) (int64, error)

Seek seeks to a certain offset

func (*FileEntry) Size

func (fe *FileEntry) Size() (uint64, error)

Size retrieves the size

func (*FileEntry) SubFileEntryByIndex

func (fe *FileEntry) SubFileEntryByIndex(index int) (*FileEntry, error)

SubFileEntryByIndex retrieves a sub-file entry by index

func (*FileEntry) SubFileEntryByName

func (fe *FileEntry) SubFileEntryByName(name string) (*FileEntry, error)

SubFileEntryByName retrieves a sub-file entry by name

func (*FileEntry) SubFileEntryByUTF16Name

func (fe *FileEntry) SubFileEntryByUTF16Name(utf16Name []uint16) (*FileEntry, error)

SubFileEntryByUTF16Name retrieves a sub-file entry by UTF-16 name

func (*FileEntry) SymbolicLinkTarget

func (fe *FileEntry) SymbolicLinkTarget() (string, error)

SymbolicLinkTarget retrieves the symbolic link target

func (*FileEntry) SymbolicLinkTargetSize

func (fe *FileEntry) SymbolicLinkTargetSize() (int, error)

SymbolicLinkTargetSize retrieves the size of the symbolic link target

func (*FileEntry) SymbolicLinkTargetUTF16

func (fe *FileEntry) SymbolicLinkTargetUTF16() ([]uint16, error)

SymbolicLinkTargetUTF16 retrieves the UTF-16 encoded symbolic link target

func (*FileEntry) SymbolicLinkTargetUTF16Size

func (fe *FileEntry) SymbolicLinkTargetUTF16Size() (int, error)

SymbolicLinkTargetUTF16Size retrieves the size of the UTF-16 encoded symbolic link target

func (*FileEntry) UTF8Name

func (fe *FileEntry) UTF8Name() (string, error)

UTF8Name retrieves the UTF-8 encoded name

func (*FileEntry) UTF8NameSize

func (fe *FileEntry) UTF8NameSize() (int, error)

UTF8NameSize retrieves the size of the UTF-8 encoded name

func (*FileEntry) UTF16Name

func (fe *FileEntry) UTF16Name() ([]uint16, error)

UTF16Name retrieves the UTF-16 encoded name

func (*FileEntry) UTF16NameSize

func (fe *FileEntry) UTF16NameSize() (int, error)

UTF16NameSize retrieves the size of the UTF-16 encoded name

type FileExtent

type FileExtent struct {
	// The logical offset
	LogicalOffset uint64

	// The physical block number
	PhysicalBlockNumber uint64

	// Data size
	DataSize uint64

	// Encryption identifier
	EncryptionIdentifier uint64
}

FileExtent represents a file extent structure

func NewFileExtent

func NewFileExtent() *FileExtent

NewFileExtent creates a new file extent

func ParseFileExtentValue

func ParseFileExtentValue(data []byte) (*FileExtent, error)

ParseFileExtentValue parses a file extent value from binary data

func (*FileExtent) ReadKeyData

func (fe *FileExtent) ReadKeyData(data []byte) error

ReadKeyData reads the file extent key data

func (*FileExtent) ReadValueData

func (fe *FileExtent) ReadValueData(data []byte) error

ReadValueData reads the file extent value data

type FileSystemBTree

type FileSystemBTree struct {
	// The IO handle
	IOHandle *IOHandle

	// The encryption context
	EncryptionContext *EncryptionContext

	// The object map B-tree (for transaction identifier mapping)
	ObjectMapBTree *ObjectMapBTree

	// The block number of B-tree root node (actually a virtual OID)
	RootNodeOID uint64

	// The volume's transaction identifier (used for object map lookups)
	VolumeTransactionID uint64

	// Flag to indicate case folding should be used
	UseCaseFolding bool
}

FileSystemBTree represents the APFS file system B-tree

func NewFileSystemBTree

func NewFileSystemBTree(
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	objectMapBTree *ObjectMapBTree,
	rootNodeOID uint64,
	volumeTransactionID uint64,
	useCaseFolding bool,
) *FileSystemBTree

NewFileSystemBTree creates a new file system B-tree

func (*FileSystemBTree) AllRecordsForOID

func (bt *FileSystemBTree) AllRecordsForOID(
	reader io.ReaderAt,
	objectID uint64,
) ([]*BTreeEntry, error)

AllRecordsForOID retrieves ALL file system records for a given OID Implements the algorithm from go-apfs GetFSRecordsForOid with descent and walk phases

func (*FileSystemBTree) Attributes

func (bt *FileSystemBTree) Attributes(
	reader io.ReaderAt,
	identifier uint64,
	xid uint64,
) ([]*AttributeValues, error)

Attributes retrieves extended attributes for an identifier

func (*FileSystemBTree) DirectoryEntries

func (bt *FileSystemBTree) DirectoryEntries(
	reader io.ReaderAt,
	parentIdentifier uint64,
	xid uint64,
) ([]*DirectoryEntryRecord, error)

DirectoryEntries retrieves directory entries for a parent identifier

func (*FileSystemBTree) DirectoryEntryRecordByUTF8Name

func (bt *FileSystemBTree) DirectoryEntryRecordByUTF8Name(
	reader io.ReaderAt,
	parentIdentifier uint64,
	name string,
	xid uint64,
) (*DirectoryEntryRecord, error)

DirectoryEntryRecordByUTF8Name retrieves a directory entry record by UTF-8 name

func (*FileSystemBTree) DirectoryEntryRecordByUTF16Name

func (bt *FileSystemBTree) DirectoryEntryRecordByUTF16Name(
	reader io.ReaderAt,
	parentIdentifier uint64,
	name []uint16,
	xid uint64,
) (*DirectoryEntryRecord, error)

DirectoryEntryRecordByUTF16Name retrieves a directory entry record by UTF-16 name

func (*FileSystemBTree) EntryByIdentifier

func (bt *FileSystemBTree) EntryByIdentifier(
	reader io.ReaderAt,
	identifier uint64,
	dataType uint8,
	xid uint64,
) (*BTreeNode, *BTreeEntry, error)

EntryByIdentifier retrieves an entry by identifier and data type, navigating the tree

func (*FileSystemBTree) EntryFromNodeByIdentifier

func (bt *FileSystemBTree) EntryFromNodeByIdentifier(
	node *BTreeNode,
	identifier uint64,
	dataType uint8,
) (*BTreeEntry, error)

EntryFromNodeByIdentifier retrieves an entry from a node by identifier and data type

func (*FileSystemBTree) FileExtents

func (bt *FileSystemBTree) FileExtents(
	reader io.ReaderAt,
	identifier uint64,
	xid uint64,
) ([]*FileExtent, error)

FileExtents retrieves file extents for a given identifier

func (*FileSystemBTree) InodeByIdentifier

func (bt *FileSystemBTree) InodeByIdentifier(
	reader io.ReaderAt,
	identifier uint64,
	xid uint64,
) (*Inode, error)

InodeByIdentifier retrieves an inode by identifier

func (*FileSystemBTree) InodeByUTF8Name

func (bt *FileSystemBTree) InodeByUTF8Name(
	reader io.ReaderAt,
	parentIdentifier uint64,
	name string,
	xid uint64,
) (*Inode, *DirectoryEntryRecord, error)

InodeByUTF8Name retrieves an inode and directory entry record by UTF-8 name

func (*FileSystemBTree) InodeByUTF8Path

func (bt *FileSystemBTree) InodeByUTF8Path(
	reader io.ReaderAt,
	parentIdentifier uint64,
	path string,
	xid uint64,
) (*Inode, *DirectoryEntryRecord, error)

InodeByUTF8Path retrieves an inode and directory entry record by UTF-8 path

func (*FileSystemBTree) InodeByUTF16Name

func (bt *FileSystemBTree) InodeByUTF16Name(
	reader io.ReaderAt,
	parentIdentifier uint64,
	name []uint16,
	xid uint64,
) (*Inode, *DirectoryEntryRecord, error)

InodeByUTF16Name retrieves an inode and directory entry record by UTF-16 name

func (*FileSystemBTree) InodeByUTF16Path

func (bt *FileSystemBTree) InodeByUTF16Path(
	reader io.ReaderAt,
	parentIdentifier uint64,
	path []uint16,
	xid uint64,
) (*Inode, *DirectoryEntryRecord, error)

InodeByUTF16Path retrieves an inode and directory entry record by UTF-16 path

func (*FileSystemBTree) RootNode

func (bt *FileSystemBTree) RootNode(
	reader io.ReaderAt,
) (*BTreeNode, error)

RootNode retrieves the root node of the file system B-tree

func (*FileSystemBTree) SubNode

func (bt *FileSystemBTree) SubNode(
	reader io.ReaderAt,
	blockNumber uint64,
) (*BTreeNode, error)

SubNode retrieves a sub-node (child node) by block number The blockNumber can be either a physical block or virtual OID depending on the B-tree type

func (*FileSystemBTree) SubNodeOIDFromEntry

func (bt *FileSystemBTree) SubNodeOIDFromEntry(
	reader io.ReaderAt,
	entry *BTreeEntry,
) (uint64, error)

SubNodeOIDFromEntry extracts the sub-node block number from a branch entry In branch nodes, the value data contains the block number of the child node

type FileSystemDataHandle

type FileSystemDataHandle struct {
	// The IO handle
	IOHandle *IOHandle

	// The encryption context
	EncryptionContext *EncryptionContext

	// The file extents
	FileExtents []*FileExtent
}

FileSystemDataHandle represents a file system data handle for managing data blocks

func NewFileSystemDataHandle

func NewFileSystemDataHandle(
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	fileExtents []*FileExtent,
) (*FileSystemDataHandle, error)

NewFileSystemDataHandle creates a new file system data handle

func (*FileSystemDataHandle) ReadDataBlock

func (fsdh *FileSystemDataHandle) ReadDataBlock(
	reader io.ReaderAt,
	elementDataFileIndex int,
	elementDataOffset int64,
	elementDataSize int64,
	elementDataFlags uint32,
) (*DataBlock, error)

ReadDataBlock reads a data block from the file system This method corresponds to FileSystemDataHandle.ReadDataBlock Parameters follow the segment-reader shape used by DataBlockVector.

type FileType

type FileType uint16

FileType represents APFS file types Corresponds to LIBFSAPFS_FILE_TYPES

const (
	// FileTypeFIFO represents a FIFO/named pipe
	FileTypeFIFO FileType = 0x1000
	// FileTypeCharacterDevice represents a character device
	FileTypeCharacterDevice FileType = 0x2000
	// FileTypeDirectory represents a directory
	FileTypeDirectory FileType = 0x4000
	// FileTypeBlockDevice represents a block device
	FileTypeBlockDevice FileType = 0x6000
	// FileTypeRegularFile represents a regular file
	FileTypeRegularFile FileType = 0x8000
	// FileTypeSymbolicLink represents a symbolic link
	FileTypeSymbolicLink FileType = 0xa000
	// FileTypeSocket represents a socket
	FileTypeSocket FileType = 0xc000
)

type FusionMiddleTree

type FusionMiddleTree struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// Unknown
	// Consists of 4 bytes
	Unknown1 uint32
}

FusionMiddleTree represents the APFS Fusion middle tree structure

func NewFusionMiddleTree

func NewFusionMiddleTree() (*FusionMiddleTree, error)

NewFusionMiddleTree creates a new Fusion middle tree

func (*FusionMiddleTree) ReadData

func (f *FusionMiddleTree) ReadData(data []byte) error

ReadData reads the Fusion middle tree from binary data

func (*FusionMiddleTree) ReadFrom

func (f *FusionMiddleTree) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the Fusion middle tree from a file at the specified offset

type HuffmanTree

type HuffmanTree struct {
	// The maximum number of bits allowed for a Huffman code
	MaximumCodeSize uint8

	// The symbols array
	Symbols []uint16

	// The code size counts array
	CodeSizeCounts []int
}

HuffmanTree represents a Huffman tree for decompression

func NewHuffmanTree

func NewHuffmanTree(numberOfSymbols int, maximumCodeSize uint8) (*HuffmanTree, error)

NewHuffmanTree creates a new Huffman tree

func (*HuffmanTree) Build

func (ht *HuffmanTree) Build(codeSizesArray []uint8, numberOfCodeSizes int) (bool, error)

Build builds the Huffman tree from code sizes Returns true on success, false if the tree is empty

func (*HuffmanTree) Close

func (ht *HuffmanTree) Close() error

Close releases resources associated with the Huffman tree

func (*HuffmanTree) SymbolFromBitStream

func (ht *HuffmanTree) SymbolFromBitStream(bitStream *BitStream) (uint16, error)

SymbolFromBitStream retrieves a symbol based on the Huffman code read from the bit-stream

type IOHandle

type IOHandle struct {
	// The bytes per sector
	BytesPerSector uint16

	// The block size
	BlockSize uint32

	// The container size
	ContainerSize uint64

	// Value to indicate if abort was signalled
	Abort bool

	// The profiler (only available when built with profiler tag)
	Profiler *Profiler
	// contains filtered or unexported fields
}

IOHandle represents the Input/Output handle for APFS operations

func NewIOHandle

func NewIOHandle() (*IOHandle, error)

NewIOHandle creates a new IO handle with default values

func (*IOHandle) Clear

func (h *IOHandle) Clear() error

Clear resets the IO handle to default values

func (*IOHandle) Close

func (h *IOHandle) Close() error

Close releases resources associated with the IO handle

type Inode

type Inode struct {
	// The identifier
	Identifier uint64

	// The parent identifier
	ParentIdentifier uint64

	// The modification time (nanoseconds since Unix epoch)
	ModificationTime uint64

	// The creation time (nanoseconds since Unix epoch)
	CreationTime uint64

	// The inode change time (nanoseconds since Unix epoch)
	InodeChangeTime uint64

	// The access time (nanoseconds since Unix epoch)
	AccessTime uint64

	// The owner identifier (UID)
	OwnerIdentifier uint32

	// The group identifier (GID)
	GroupIdentifier uint32

	// Device identifier
	DeviceIdentifier uint32

	// The file mode (permissions and type)
	FileMode uint16

	// Number of (hard) links
	NumberOfLinks uint32

	// BSDFlags is the inode's chflags(2) flags (bsd_flags). Use the BSDFlag*
	// constants. UF_COMPRESSED is the one that changes how the file is read:
	// it says the content is held by com.apple.decmpfs rather than by the data
	// fork.
	BSDFlags uint32

	// The name
	Name []byte

	// The inode flags
	Flags uint64

	// The data stream identifier
	DataStreamIdentifier uint64

	// The data stream size
	DataStreamSize uint64
}

Inode represents an APFS inode (file or directory metadata)

func NewInode

func NewInode() (*Inode, error)

NewInode creates a new inode

func (*Inode) Close

func (i *Inode) Close() error

Close releases resources associated with the inode

func (*Inode) DeviceNumber

func (i *Inode) DeviceNumber() (uint32, uint32, error)

DeviceNumber retrieves the device number

func (*Inode) FileType

func (i *Inode) FileType() uint16

FileType returns the file type bits (upper 4 bits of file mode)

func (*Inode) IsDirectory

func (i *Inode) IsDirectory() bool

IsDirectory returns true if this inode represents a directory

func (*Inode) IsRegularFile

func (i *Inode) IsRegularFile() bool

IsRegularFile returns true if this inode represents a regular file

func (i *Inode) IsSymbolicLink() bool

IsSymbolicLink returns true if this inode represents a symbolic link

func (*Inode) Permissions

func (i *Inode) Permissions() uint16

Permissions returns the permission bits (lower 12 bits of file mode)

func (*Inode) ReadKeyData

func (i *Inode) ReadKeyData(data []byte) error

ReadKeyData reads the inode key data from a B-tree entry

func (*Inode) ReadValueData

func (i *Inode) ReadValueData(data []byte) error

ReadValueData reads the inode value data from a B-tree entry

func (*Inode) UTF8Name

func (i *Inode) UTF8Name() ([]byte, error)

UTF8Name retrieves the UTF-8 name

func (*Inode) UTF8NameSize

func (i *Inode) UTF8NameSize() (int, error)

UTF8NameSize retrieves the UTF-8 name size

type KeyEncryptionKey

type KeyEncryptionKey struct {
	// The identifier (UUID)
	Identifier [16]byte

	// The HMAC
	HMAC [32]byte

	// The number of iterations for PBKDF2
	NumberOfIterations uint64

	// The salt for PBKDF2
	Salt [16]byte

	// The encryption method
	EncryptionMethod uint32

	// The wrapped key encryption key (KEK)
	WrappedKEK [40]byte
}

KeyEncryptionKey represents an APFS key encryption key (KEK)

func NewKeyEncryptionKey

func NewKeyEncryptionKey() (*KeyEncryptionKey, error)

NewKeyEncryptionKey creates a new key encryption key

func (*KeyEncryptionKey) ReadData

func (kek *KeyEncryptionKey) ReadData(data []byte) error

ReadData reads the key encryption key from binary data

func (*KeyEncryptionKey) UnlockWithKey

func (kek *KeyEncryptionKey) UnlockWithKey(key []byte) ([]byte, error)

UnlockWithKey unlocks the key encryption key using a key Returns the unlocked key, or nil if unlocking failed

func (*KeyEncryptionKey) UnlockWithPassword

func (kek *KeyEncryptionKey) UnlockWithPassword(password []byte) ([]byte, error)

UnlockWithPassword unlocks the key encryption key using a password Returns the unlocked key, or nil if unlocking failed

type KeybagEntry

type KeybagEntry struct {
	// The identifier (UUID)
	Identifier [16]byte

	// The entry type
	Type uint16

	// The entry data
	Data []byte

	// The data size
	DataSize uint16

	// The total size including header
	Size int
}

KeybagEntry represents a single keybag entry

func NewKeybagEntry

func NewKeybagEntry() (*KeybagEntry, error)

NewKeybagEntry creates a new keybag entry

func (*KeybagEntry) ReadData

func (e *KeybagEntry) ReadData(data []byte) error

ReadData reads a keybag entry from binary data

type KeybagEntryHeader

type KeybagEntryHeader struct {
	// The identifier
	// Consists of 16 bytes
	// Contains an UUID
	Identifier [16]byte

	// The entry type
	// Consists of 2 bytes
	EntryType uint16

	// The entry data size
	// Consists of 2 bytes
	DataSize uint16

	// Unknown
	// Consists of 4 bytes
	Unknown1 uint32
}

KeybagEntryHeader represents the APFS keybag entry header structure

func NewKeybagEntryHeader

func NewKeybagEntryHeader() (*KeybagEntryHeader, error)

NewKeybagEntryHeader creates a new keybag entry header Corresponds to the entry header portion of keybag_entry_t

func (*KeybagEntryHeader) ReadData

func (h *KeybagEntryHeader) ReadData(data []byte) error

ReadData reads the keybag entry header from binary data Corresponds to reading the header portion in KeybagEntry.ReadData

type KeybagHeader

type KeybagHeader struct {
	// The format version
	// Consists of 2 bytes
	FormatVersion uint16

	// The number of entries
	// Consists of 2 bytes
	NumberOfEntries uint16

	// The data size
	// Consists of 4 bytes
	DataSize uint32

	// Unknown
	// Consists of 8 bytes
	Unknown1 uint64
}

KeybagHeader represents the APFS keybag header structure

func NewKeybagHeader

func NewKeybagHeader() (*KeybagHeader, error)

NewKeybagHeader creates a new keybag header

func (*KeybagHeader) ReadData

func (h *KeybagHeader) ReadData(data []byte) error

ReadData reads the keybag header from binary data

type ModifiedByInfo

type ModifiedByInfo struct {
	// ID/name of the software (32 bytes)
	ID [32]byte
	// Timestamp when modified (8 bytes)
	Timestamp uint64
	// Last transaction ID (8 bytes)
	LastTransactionID uint64
}

ModifiedByInfo represents who last formatted or modified the volume Corresponds to apfs_modified_by_t in APFS spec

type ObjectHeader

type ObjectHeader struct {
	// The checksum
	// Consists of 8 bytes
	Checksum uint64

	// The identifier
	// Consists of 8 bytes
	Identifier uint64

	// The transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The type
	// Consists of 4 bytes
	Type uint32

	// The subtype
	// Consists of 4 bytes
	Subtype uint32
}

Object represents the APFS object structure

func NewObjectHeader

func NewObjectHeader() (*ObjectHeader, error)

NewObjectHeader creates a new object

func (*ObjectHeader) ReadData

func (o *ObjectHeader) ReadData(data []byte) error

ReadData reads the object from binary data

func (*ObjectHeader) ReadFrom

func (o *ObjectHeader) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the object from a file at the specified offset

func (*ObjectHeader) TransactionIdentifier

func (o *ObjectHeader) TransactionIdentifier() (uint64, error)

TransactionIdentifier retrieves the transaction identifier

type ObjectMap

type ObjectMap struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// The flags
	// Consists of 4 bytes
	Flags uint32

	// The number of snapshots
	// Consists of 4 bytes
	SnapshotCount uint32

	// The B-tree type
	// Consists of 4 bytes
	TreeType uint32

	// The snapshots B-tree type
	// Consists of 4 bytes
	SnapshotTreeType uint32

	// The B-tree block number
	// Consists of 8 bytes
	TreeOID uint64

	// The snapshots B-tree block number
	// Consists of 8 bytes
	SnapshotTreeOID uint64

	// The most recent snapshot object identifier
	// Consists of 8 bytes
	MostRecentSnapXID uint64

	// Unknown
	// Consists of 8 bytes
	Unknown2 uint64

	// Unknown
	// Consists of 8 bytes
	Unknown3 uint64
}

ObjectMap represents the APFS object map structure

func NewObjectMap

func NewObjectMap() (*ObjectMap, error)

NewObjectMap creates a new object map

func (*ObjectMap) MostRecentSnapXIDValue

func (om *ObjectMap) MostRecentSnapXIDValue() (uint64, error)

MostRecentSnapXIDValue retrieves the most recent snapshot identifier

func (*ObjectMap) NumberOfSnapshots

func (om *ObjectMap) NumberOfSnapshots() (uint32, error)

NumberOfSnapshots retrieves the number of snapshots

func (*ObjectMap) ReadData

func (om *ObjectMap) ReadData(data []byte) error

ReadData reads the object map from binary data

func (*ObjectMap) ReadFrom

func (om *ObjectMap) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the object map from a file at the specified offset

func (*ObjectMap) SnapshotTreeOIDValue

func (om *ObjectMap) SnapshotTreeOIDValue() (uint64, error)

SnapshotTreeOIDValue retrieves the snapshots B-tree block number

func (*ObjectMap) TreeOIDValue

func (om *ObjectMap) TreeOIDValue() (uint64, error)

TreeOIDValue retrieves the B-tree block number

type ObjectMapBTree

type ObjectMapBTree struct {
	// The IO handle
	IOHandle *IOHandle

	// The encryption context
	EncryptionContext *EncryptionContext

	// The block number of B-tree root node
	RootNodeOID uint64
}

ObjectMapBTree represents the APFS object map B-tree This B-tree maps object identifiers and transaction identifiers to physical block numbers

func NewObjectMapBTree

func NewObjectMapBTree(
	ioHandle *IOHandle,
	encryptionContext *EncryptionContext,
	rootNodeOID uint64,
) (*ObjectMapBTree, error)

NewObjectMapBTree creates a new object map B-tree

func (*ObjectMapBTree) DescriptorByObjectIdentifier

func (bt *ObjectMapBTree) DescriptorByObjectIdentifier(
	reader io.ReaderAt,
	oid uint64,
	xid uint64,
) (*ObjectMapDescriptor, error)

DescriptorByObjectIdentifier retrieves the object map descriptor of a specific object identifier

func (*ObjectMapBTree) EntryByIdentifier

func (bt *ObjectMapBTree) EntryByIdentifier(
	reader io.ReaderAt,
	oid uint64,
	xid uint64,
) (*BTreeNode, *BTreeEntry, error)

EntryByIdentifier retrieves a B-tree entry by object and transaction identifier

func (*ObjectMapBTree) EntryFromNodeByIdentifier

func (bt *ObjectMapBTree) EntryFromNodeByIdentifier(
	node *BTreeNode,
	oid uint64,
	xid uint64,
) (*BTreeEntry, error)

GetEntryFromNodeByIdentifier finds an entry in a specific node by identifier

func (*ObjectMapBTree) PhysicalAddressForOID

func (bt *ObjectMapBTree) PhysicalAddressForOID(
	reader io.ReaderAt,
	oid uint64,
	xid uint64,
) (uint64, error)

PhysicalAddressForOID retrieves the physical block number for an object This is a convenience function that looks up an object in the object map

func (*ObjectMapBTree) RootNode

func (bt *ObjectMapBTree) RootNode(
	reader io.ReaderAt,
	rootNodeOID uint64,
) (*BTreeNode, error)

RootNode retrieves the root node of the B-tree

func (*ObjectMapBTree) SubNode

func (bt *ObjectMapBTree) SubNode(
	reader io.ReaderAt,
	subNodeOID uint64,
) (*BTreeNode, error)

SubNode retrieves a sub-node (child node) by block number

type ObjectMapDescriptor

type ObjectMapDescriptor struct {
	Key   *ObjectMapKey
	Value *ObjectMapValue
}

ObjectMapDescriptor contains both key and value data from an object map entry

func NewObjectMapDescriptor

func NewObjectMapDescriptor() (*ObjectMapDescriptor, error)

NewObjectMapDescriptor creates a new object map descriptor

func (*ObjectMapDescriptor) Flags

func (d *ObjectMapDescriptor) Flags() (uint32, error)

Flags returns the object flags

func (*ObjectMapDescriptor) Identifier

func (d *ObjectMapDescriptor) Identifier() (uint64, error)

Identifier returns the object identifier

func (*ObjectMapDescriptor) PhysicalAddress

func (d *ObjectMapDescriptor) PhysicalAddress() (uint64, error)

PhysicalAddress returns the physical address

func (*ObjectMapDescriptor) ReadKeyData

func (d *ObjectMapDescriptor) ReadKeyData(data []byte) error

ReadKeyData reads the object map descriptor B-tree key data

func (*ObjectMapDescriptor) ReadValueData

func (d *ObjectMapDescriptor) ReadValueData(data []byte) error

ReadValueData reads the object map descriptor B-tree value data

func (*ObjectMapDescriptor) Size

func (d *ObjectMapDescriptor) Size() (uint32, error)

Size returns the object size

func (*ObjectMapDescriptor) TransactionIdentifier

func (d *ObjectMapDescriptor) TransactionIdentifier() (uint64, error)

TransactionIdentifier returns the transaction identifier

type ObjectMapKey

type ObjectMapKey struct {
	OID uint64
	XID uint64
}

ObjectMapKey represents a key in the object map B-tree

func ParseObjectMapKey

func ParseObjectMapKey(data []byte) (*ObjectMapKey, error)

ParseObjectMapKey parses an object map key from binary data

type ObjectMapValue

type ObjectMapValue struct {
	ObjectFlags           uint32
	ObjectSize            uint32
	ObjectPhysicalAddress uint64
}

ObjectMapValue represents a value in the object map B-tree

func ParseObjectMapValue

func ParseObjectMapValue(data []byte) (*ObjectMapValue, error)

ParseObjectMapValue parses an object map value from binary data

type OpenOptions

type OpenOptions struct {
	// Offset is the byte offset of the container within the reader. For
	// OpenImage a non-zero value overrides the offset detected from the
	// image's partition table.
	Offset int64

	// Password unlocks encrypted volumes (user password).
	Password string

	// RecoveryPassword unlocks encrypted volumes (recovery password).
	RecoveryPassword string
}

OpenOptions configures Open and OpenImage.

type Profiler

type Profiler struct {
}

Profiler represents a performance profiler (stub when profiling is disabled)

func NewProfiler

func NewProfiler() (*Profiler, error)

NewProfiler creates a new profiler (no-op when profiling is disabled)

func (*Profiler) Close

func (p *Profiler) Close() error

Close closes the profiler output file (no-op when profiling is disabled)

func (*Profiler) Open

func (p *Profiler) Open(filename string) error

Open opens the profiler output file (no-op when profiling is disabled)

func (*Profiler) StartTiming

func (p *Profiler) StartTiming() (int64, error)

StartTiming captures the start timestamp (no-op when profiling is disabled)

func (*Profiler) StopTiming

func (p *Profiler) StopTiming(startTimestamp int64, name string, offset int64, size uint64) error

StopTiming captures the stop timestamp (no-op when profiling is disabled)

type Reaper

type Reaper struct {
	// contains filtered or unexported fields
}

Reaper represents an APFS reaper The reaper is used for tracking blocks to be freed

func NewReaper

func NewReaper() (*Reaper, error)

NewReaper creates a new reaper

func (*Reaper) ReadData

func (cr *Reaper) ReadData(data []byte) error

ReadData reads the reaper from data

func (*Reaper) ReadFrom

func (cr *Reaper) ReadFrom(
	reader io.ReaderAt,
	fileOffset int64,
) error

ReadFrom reads the reaper from a file

type RoleDescription

type RoleDescription struct {
	Value uint16
	Token string
	Name  string
}

RoleDescription holds one volume role, the token used to select it on the command line, and a human-readable name.

func LookupVolumeRole

func LookupVolumeRole(role uint16) (RoleDescription, bool)

LookupVolumeRole returns the description of a raw apfs_role value, and whether the value is one the format defines.

type Snapshot

type Snapshot struct {
	// The volume superblock
	VolumeSuperblock *VolumeSuperblock

	// The IO handle
	IOHandle *IOHandle

	// The file IO handle
	Reader io.ReaderAt

	// The snapshot metadata
	SnapshotMetadata *SnapshotMetadata
}

Snapshot represents an APFS snapshot

func NewSnapshot

func NewSnapshot(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	snapshotMetadata *SnapshotMetadata,
) (*Snapshot, error)

NewSnapshot creates a new snapshot

func (*Snapshot) Close

func (s *Snapshot) Close() error

Close closes a snapshot

func (*Snapshot) OpenRead

func (s *Snapshot) OpenRead(reader io.ReaderAt, fileOffset int64) error

OpenRead opens a snapshot for reading

func (*Snapshot) UTF8Name

func (s *Snapshot) UTF8Name() (string, error)

UTF8Name retrieves the UTF-8 encoded name

func (*Snapshot) UTF8NameSize

func (s *Snapshot) UTF8NameSize() (int, error)

UTF8NameSize retrieves the size of the UTF-8 encoded name The returned size includes the end of string character

func (*Snapshot) UTF16Name

func (s *Snapshot) UTF16Name() ([]uint16, error)

UTF16Name retrieves the UTF-16 encoded name

func (*Snapshot) UTF16NameSize

func (s *Snapshot) UTF16NameSize() (int, error)

UTF16NameSize retrieves the size of the UTF-16 encoded name The returned size includes the end of string character

type SnapshotMetadata

type SnapshotMetadata struct {
	// The transaction identifier of the snapshot. This is the object
	// identifier half of the snapshot metadata record's key (j_key_t.obj_id),
	// which for snapshot metadata records holds an xid rather than an oid.
	XID uint64
	// The physical object identifier of the snapshot's volume superblock
	// (j_snap_metadata_val_t.sblock_oid).
	VolumeSuperblockOID uint64
	// The physical object identifier of the snapshot's extentref tree
	// (j_snap_metadata_val_t.extentref_tree_oid).
	ExtentrefTreeOID uint64
	// Creation time, in nanoseconds since 1970-01-01 UTC (create_time).
	CreationTime uint64
	// Last-modified time, in nanoseconds since 1970-01-01 UTC (change_time).
	ChangeTime uint64
	Name       string
}

SnapshotMetadata represents snapshot metadata

func (*SnapshotMetadata) UTF8Name

func (m *SnapshotMetadata) UTF8Name() (string, error)

UTF8Name retrieves the UTF-8 encoded name from snapshot metadata

func (*SnapshotMetadata) UTF8NameSize

func (m *SnapshotMetadata) UTF8NameSize() (int, error)

UTF8NameSize retrieves the size of the UTF-8 encoded name from snapshot metadata The returned size includes the end of string character

func (*SnapshotMetadata) UTF16Name

func (m *SnapshotMetadata) UTF16Name() ([]uint16, error)

UTF16Name retrieves the UTF-16 encoded name from snapshot metadata

func (*SnapshotMetadata) UTF16NameSize

func (m *SnapshotMetadata) UTF16NameSize() (int, error)

UTF16NameSize retrieves the size of the UTF-16 encoded name from snapshot metadata The returned size includes the end of string character

type SnapshotMetadataTree

type SnapshotMetadataTree struct {
	IOHandle       *IOHandle
	ObjectMapBTree *ObjectMapBTree
	RootNodeOID    uint64
	// contains filtered or unexported fields
}

SnapshotMetadataTree represents the APFS snapshot metadata B-tree

func NewSnapshotMetadataTree

func NewSnapshotMetadataTree(
	ioHandle *IOHandle,
	objectMapBTree *ObjectMapBTree,
	rootNodeOID uint64,
) (*SnapshotMetadataTree, error)

NewSnapshotMetadataTree creates a new snapshot metadata tree

func (*SnapshotMetadataTree) Close

func (t *SnapshotMetadataTree) Close() error

Close releases resources associated with the snapshot metadata tree

func (*SnapshotMetadataTree) EntryByIdentifier

func (t *SnapshotMetadataTree) EntryByIdentifier(
	reader io.ReaderAt,
	oid uint64,
) (*BTreeNode, *BTreeEntry, error)

EntryByIdentifier retrieves a B-tree entry by object identifier

func (*SnapshotMetadataTree) EntryByIndex

func (t *SnapshotMetadataTree) EntryByIndex(reader io.ReaderAt, index int) (*SnapshotMetadata, error)

EntryByIndex retrieves a snapshot metadata entry by index

func (*SnapshotMetadataTree) EntryFromNodeByIdentifier

func (t *SnapshotMetadataTree) EntryFromNodeByIdentifier(
	node *BTreeNode,
	oid uint64,
) (*BTreeEntry, error)

EntryFromNodeByIdentifier retrieves a B-tree entry from a node by object identifier

func (*SnapshotMetadataTree) MetadataByObjectIdentifier

func (t *SnapshotMetadataTree) MetadataByObjectIdentifier(
	reader io.ReaderAt,
	oid uint64,
) (*SnapshotMetadata, error)

MetadataByObjectIdentifier retrieves snapshot metadata by object identifier

func (*SnapshotMetadataTree) NumberOfEntries

func (t *SnapshotMetadataTree) NumberOfEntries(reader io.ReaderAt) (int, error)

NumberOfEntries retrieves the number of snapshot entries in the tree

func (*SnapshotMetadataTree) RootNode

func (t *SnapshotMetadataTree) RootNode(
	reader io.ReaderAt,
	rootNodeOID uint64,
) (*BTreeNode, error)

RootNode retrieves the snapshot metadata tree root node

func (*SnapshotMetadataTree) Snapshots

func (t *SnapshotMetadataTree) Snapshots(
	reader io.ReaderAt,
	xid uint64,
) ([]*SnapshotMetadata, error)

Snapshots retrieves all snapshots from the tree

func (*SnapshotMetadataTree) SubNode

func (t *SnapshotMetadataTree) SubNode(
	reader io.ReaderAt,
	subNodeOID uint64,
) (*BTreeNode, error)

SubNode retrieves a snapshot metadata tree sub node

func (*SnapshotMetadataTree) SubNodeOIDFromEntry

func (t *SnapshotMetadataTree) SubNodeOIDFromEntry(
	reader io.ReaderAt,
	entry *BTreeEntry,
	xid uint64,
) (uint64, error)

SubNodeOIDFromEntry retrieves the sub node block number from a B-tree entry

type SpaceManager

type SpaceManager struct {
	// Object header (obj_phys_t).
	Checksum      uint64 // o_cksum
	OID           uint64 // o_oid
	XID           uint64 // o_xid
	ObjectType    uint32 // o_type
	ObjectSubtype uint32 // o_subtype

	BlockSize      uint32 // sm_block_size
	BlocksPerChunk uint32 // sm_blocks_per_chunk
	ChunksPerCIB   uint32 // sm_chunks_per_cib
	CIBsPerCAB     uint32 // sm_cibs_per_cab

	// Devices, indexed by SpaceManagerDeviceMain/Tier2 (sm_dev).
	Devices [SpaceManagerDeviceCount]SpaceManagerDevice

	Flags uint32 // sm_flags

	// Internal pool. Apple's field prefix is sm_ip_; the spec section is
	// titled "Internal-Pool Bitmap".
	IPBMTxMultiplier   uint32 // sm_ip_bm_tx_multiplier
	IPBlockCount       uint64 // sm_ip_block_count
	IPBMSizeInBlocks   uint32 // sm_ip_bm_size_in_blocks
	IPBMBlockCount     uint32 // sm_ip_bm_block_count
	IPBMBase           uint64 // sm_ip_bm_base (paddr_t)
	IPBase             uint64 // sm_ip_base (paddr_t)
	IPBMFreeHead       uint16 // sm_ip_bm_free_head
	IPBMFreeTail       uint16 // sm_ip_bm_free_tail
	IPBMXIDOffset      uint32 // sm_ip_bm_xid_offset
	IPBitmapOffset     uint32 // sm_ip_bitmap_offset
	IPBMFreeNextOffset uint32 // sm_ip_bm_free_next_offset

	FSReserveBlockCount uint64 // sm_fs_reserve_block_count
	FSReserveAllocCount uint64 // sm_fs_reserve_alloc_count

	// Free queues, indexed by SpaceManagerFreeQueueIP/Main/Tier2 (sm_fq).
	FreeQueues [SpaceManagerFreeQueueCount]SpaceManagerFreeQueue

	Version    uint32 // sm_version
	StructSize uint32 // sm_struct_size

	// Allocation-zone information for each device, undecoded (sm_datazone,
	// spaceman_datazone_info_phys_t).
	DataZone [SpaceManagerDeviceCount][SpaceManagerAllocationZoneSize]byte
}

SpaceManager allocates and frees the blocks where objects and file data are stored. There is exactly one of these in a container (Apple: spaceman_phys_t).

func NewSpaceManager

func NewSpaceManager() *SpaceManager

NewSpaceManager creates a new space manager

func (*SpaceManager) ReadData

func (sm *SpaceManager) ReadData(data []byte) error

ReadData reads the space manager from binary data

func (*SpaceManager) ReadFrom

func (sm *SpaceManager) ReadFrom(reader io.ReaderAt, fileOffset int64) error

ReadFrom reads the space manager from a reader at the specified offset

type SpaceManagerDevice

type SpaceManagerDevice struct {
	BlockCount uint64 // sm_block_count
	ChunkCount uint64 // sm_chunk_count
	CIBCount   uint32 // sm_cib_count
	CABCount   uint32 // sm_cab_count
	FreeCount  uint64 // sm_free_count
	AddrOffset uint32 // sm_addr_offset
	Reserved   uint32 // sm_reserved
	Reserved2  uint64 // sm_reserved2
}

SpaceManagerDevice describes one storage device managed by the space manager (Apple: spaceman_device_t).

type SpaceManagerFreeQueue

type SpaceManagerFreeQueue struct {
	Count         uint64 // sfq_count
	TreeOID       uint64 // sfq_tree_oid
	OldestXID     uint64 // sfq_oldest_xid
	TreeNodeLimit uint16 // sfq_tree_node_limit
	Pad16         uint16 // sfq_pad16
	Pad32         uint32 // sfq_pad32
	Reserved      uint64 // sfq_reserved
}

SpaceManagerFreeQueue is a queue of blocks that become free once the transactions still referring to them are no longer needed (Apple: spaceman_free_queue_t).

type Volume

type Volume struct {
	// The volume superblock
	Superblock *VolumeSuperblock

	// The volume object map B-tree
	ObjectMapBTree *ObjectMapBTree

	// The file system B-tree
	FileSystemBTree *FileSystemBTree

	// The extentref tree (optional)
	ExtentrefTree *ExtentrefTree

	// The snapshot metadata tree (optional)
	SnapshotMetadataTree *SnapshotMetadataTree

	// The volume's own keybag, holding the key-encryption keys a password
	// unwraps. Nil when the volume is not encrypted, or when its keybag could
	// not be located or parsed — in which case the volume stays locked.
	VolumeKeybag *VolumeKeybag

	// The encryption context (optional)
	EncryptionContext *EncryptionContext

	// The IO handle
	IOHandle *IOHandle

	// The file IO handle
	Reader io.ReaderAt

	// The container keybag reference
	ContainerKeybag *ContainerKeybag

	// The container data handle
	ContainerDataHandle *ContainerDataHandle

	// The user password (for encrypted volumes)
	UserPassword []byte

	// The recovery password (for encrypted volumes)
	RecoveryPassword []byte
	// contains filtered or unexported fields
}

Volume represents an APFS volume

func NewVolume

func NewVolume(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	containerKeybag *ContainerKeybag,
) (*Volume, error)

NewVolume creates a new volume

func (*Volume) Close

func (v *Volume) Close() error

Close closes a volume

func (*Volume) CompatibleFeatureNames

func (v *Volume) CompatibleFeatureNames() ([]string, error)

CompatibleFeatureNames returns human-readable names of set compatible features

func (*Volume) FeaturesFlags

func (v *Volume) FeaturesFlags() (compatible, incompatible, readOnlyCompatible uint64, err error)

FeaturesFlags retrieves the volume feature flags

func (*Volume) FileEntryByIdentifier

func (v *Volume) FileEntryByIdentifier(identifier uint64) (*FileEntry, error)

FileEntryByIdentifier retrieves a file entry by inode number

func (*Volume) FileEntryByPath

func (v *Volume) FileEntryByPath(path string) (*FileEntry, error)

FileEntryByPath retrieves a file entry by path

func (*Volume) HasEncryptionKeysRolled

func (v *Volume) HasEncryptionKeysRolled() (bool, error)

HasEncryptionKeysRolled checks if the volume's encryption keys have been changed

func (*Volume) Identifier

func (v *Volume) Identifier() ([16]byte, error)

Identifier retrieves the volume identifier (UUID)

func (*Volume) IncompatibleFeatureNames

func (v *Volume) IncompatibleFeatureNames() ([]string, error)

IncompatibleFeatureNames returns human-readable names of set incompatible features

func (*Volume) IsCaseInsensitive

func (v *Volume) IsCaseInsensitive() (bool, error)

IsCaseInsensitive checks if the volume uses case-insensitive filenames

func (*Volume) IsEncrypted added in v0.2.0

func (v *Volume) IsEncrypted() (bool, error)

IsEncrypted reports whether the volume's contents are encrypted.

It is the absence of APFS_FS_UNENCRYPTED that says so, which is worth stating because the sense is inverted from what the name suggests: a volume with no flags set at all is encrypted.

func (*Volume) IsInVolumeGroup

func (v *Volume) IsInVolumeGroup() (bool, error)

IsInVolumeGroup reports whether the volume belongs to a volume group — the System/Data pairing macOS has used since Catalina.

Membership is declared by the APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE feature flag, not by the group identifier: that flag is what checkers consult, and a volume carrying a group identifier without it is malformed.

func (*Volume) IsLocked

func (v *Volume) IsLocked() (bool, error)

IsLocked reports whether the volume is encrypted and has not been unlocked, so its contents cannot be read.

This is the check a caller must make before reading anything: a locked volume's metadata is ciphertext, and parsing it produces structural errors that say nothing about the real cause.

func (*Volume) IsNormalizationInsensitive

func (v *Volume) IsNormalizationInsensitive() (bool, error)

IsNormalizationInsensitive checks if the volume uses normalization-insensitive filenames

func (*Volume) IsSealed

func (v *Volume) IsSealed() (bool, error)

IsSealed checks if the volume is sealed

func (*Volume) NextFileEntryIdentifier

func (v *Volume) NextFileEntryIdentifier() (uint64, error)

NextFileEntryIdentifier retrieves the next file entry identifier

func (*Volume) NumberOfSnapshots

func (v *Volume) NumberOfSnapshots() (int, error)

NumberOfSnapshots retrieves the number of snapshots

func (*Volume) Open

func (v *Volume) Open(name string) (fs.File, error)

Open implements fs.FS.

func (*Volume) OpenRead

func (v *Volume) OpenRead(reader io.ReaderAt, fileOffset int64) error

OpenRead opens a volume for reading

func (*Volume) ReadDir

func (v *Volume) ReadDir(name string) ([]fs.DirEntry, error)

ReadDir implements fs.ReadDirFS. Entries are sorted by filename as the interface requires.

func (*Volume) ReadFile

func (v *Volume) ReadFile(name string) ([]byte, error)

ReadFile implements fs.ReadFileFS.

func (*Volume) ReadOnlyCompatibleFeatureNames

func (v *Volume) ReadOnlyCompatibleFeatureNames() ([]string, error)

ReadOnlyCompatibleFeatureNames returns human-readable names of set read-only compatible features

func (v *Volume) Readlink(name string) (string, error)

Readlink returns the target of the symbolic link at name.

func (*Volume) Role

func (v *Volume) Role() (uint16, error)

Role returns the volume's raw apfs_role value.

func (*Volume) RoleName

func (v *Volume) RoleName() (string, error)

RoleName returns the human-readable name of the volume's role, or "" when it has none.

func (*Volume) RoleString

func (v *Volume) RoleString() (string, error)

RoleString returns a lowercase token naming the volume's role, or "" when it has none.

func (*Volume) RootDirectory

func (v *Volume) RootDirectory() (*FileEntry, error)

RootDirectory retrieves the root directory file entry.

The root is ROOT_DIR_INO_NUM on every volume, including the system volume of a volume group: only the user inode numbers move into the group's upper half. See apfswrite.inoBaseFor for how that was established.

func (*Volume) SetUTF8Password

func (v *Volume) SetUTF8Password(password []byte) error

SetUTF8Password sets the user password for unlocking an encrypted volume This function must be called before Unlock() for password-based unlocking

func (*Volume) SetUTF8RecoveryPassword

func (v *Volume) SetUTF8RecoveryPassword(password []byte) error

SetUTF8RecoveryPassword sets the recovery password for unlocking an encrypted volume This function must be called before Unlock() for recovery password-based unlocking

func (*Volume) SetUTF16Password

func (v *Volume) SetUTF16Password(utf16Password []uint16) error

SetUTF16Password sets the user password from UTF-16 encoding

func (*Volume) SetUTF16RecoveryPassword

func (v *Volume) SetUTF16RecoveryPassword(utf16Password []uint16) error

SetUTF16RecoveryPassword sets the recovery password from UTF-16 encoding

func (*Volume) Size

func (v *Volume) Size() (uint64, error)

Size retrieves the size of the volume in bytes

func (*Volume) Snapshot

func (v *Volume) Snapshot(index int) (*Snapshot, error)

Snapshot retrieves a snapshot by index

func (*Volume) Stat

func (v *Volume) Stat(name string) (fs.FileInfo, error)

Stat implements fs.StatFS. Symlinks are not followed.

func (*Volume) UTF8Name

func (v *Volume) UTF8Name() (string, error)

UTF8Name retrieves the UTF-8 encoded volume name

func (*Volume) UTF8NameSize

func (v *Volume) UTF8NameSize() (int, error)

UTF8NameSize retrieves the size of the UTF-8 encoded volume name The returned size includes the end of string character

func (*Volume) UTF16Name

func (v *Volume) UTF16Name() ([]uint16, error)

UTF16Name retrieves the UTF-16 encoded volume name

func (*Volume) UTF16NameSize

func (v *Volume) UTF16NameSize() (int, error)

UTF16NameSize retrieves the size of the UTF-16 encoded volume name The returned size includes the end of string character

func (*Volume) Unlock

func (v *Volume) Unlock() (bool, error)

Unlock attempts to unlock an encrypted volume with the passwords already set on it. It reports whether the volume ended up unlocked.

An unencrypted volume, or one already unlocked, reports true and does nothing. A wrong password reports false with no error: failing to guess a password is an answer, not a failure.

func (*Volume) VolumeGroupIdentifier

func (v *Volume) VolumeGroupIdentifier() ([16]byte, error)

VolumeGroupIdentifier returns the identifier of the volume group this volume belongs to (apfs_volume_group_id). The zero UUID means it belongs to none.

func (*Volume) Xattrs

func (v *Volume) Xattrs(name string) (map[string][]byte, error)

Xattrs returns the extended attributes of the file at name.

type VolumeKeybag

type VolumeKeybag struct {
	Entries []*KeybagEntry
}

VolumeKeybag represents an APFS volume keybag

func NewVolumeKeybag

func NewVolumeKeybag() (*VolumeKeybag, error)

NewVolumeKeybag creates a new volume keybag

func NewVolumeKeybagOrNil added in v0.2.0

func NewVolumeKeybagOrNil() *VolumeKeybag

NewVolumeKeybagOrNil returns a new volume keybag, or nil if one cannot be made. It exists so openEncryption reads as one path rather than a ladder.

func (*VolumeKeybag) Close

func (v *VolumeKeybag) Close() error

Close releases resources associated with the volume keybag

func (*VolumeKeybag) ReadData

func (v *VolumeKeybag) ReadData(data []byte) error

ReadData reads the volume keybag from binary data

func (*VolumeKeybag) ReadFrom

func (v *VolumeKeybag) ReadFrom(
	ioHandle *IOHandle,
	reader io.ReaderAt,
	fileOffset int64,
	dataSize uint64,
	volumeIdentifier []byte,
) error

ReadFrom reads the volume keybag from a file at the specified offset

func (*VolumeKeybag) VolumeKey

func (v *VolumeKeybag) VolumeKey(
	userPassword []byte,
	recoveryPassword []byte,
) ([]byte, bool, error)

VolumeKey retrieves the volume key that can be unlocked with the given passwords Returns true and the key if successful, false if no key could be unlocked

type VolumeSuperblock

type VolumeSuperblock struct {
	// The object checksum
	// Consists of 8 bytes
	Checksum uint64

	// The object identifier
	// Consists of 8 bytes
	OID uint64

	// The object transaction identifier
	// Consists of 8 bytes
	XID uint64

	// The object type
	// Consists of 4 bytes
	ObjectType uint32

	// The object subtype
	// Consists of 4 bytes
	ObjectSubtype uint32

	// The file system signature
	// Consists of 4 bytes
	// Contains: "APSB"
	Signature [4]byte

	// The file system index (apfs_fs_index)
	// Consists of 4 bytes
	FSIndex uint32

	// Compatible features flags
	// Consists of 8 bytes
	CompatibleFeaturesFlags uint64

	// Read only compatible features flags
	// Consists of 8 bytes
	ReadOnlyCompatibleFeaturesFlags uint64

	// Incompatible features flags
	// Consists of 8 bytes
	IncompatibleFeaturesFlags uint64

	// Last unmount time (apfs_unmount_time) - nanoseconds since Unix epoch
	// Consists of 8 bytes
	UnmountTime uint64

	// The number of reserved blocks
	// Consists of 8 bytes
	NumberOfReservedBlocks uint64

	// The number of quota blocks
	// Consists of 8 bytes
	NumberOfQuotaBlocks uint64

	// The number of allocated blocks (apfs_fs_alloc_count)
	// Consists of 8 bytes
	NumberOfAllocatedBlocks uint64

	// Information about how the volume encryption key (VEK) is used to
	// encrypt a file (apfs_meta_crypto, wrapped_meta_crypto_state_t).
	// Consists of 20 bytes
	MetaCryptoMajorVersion    uint16
	MetaCryptoMinorVersion    uint16
	MetaCryptoFlags           uint32
	MetaCryptoPersistentClass uint32
	MetaCryptoKeyOSVersion    uint32
	MetaCryptoKeyRevision     uint16
	MetaCryptoUnused          uint16

	// The file system root tree object type
	// Consists of 4 bytes
	RootTreeType uint32

	// The extentref tree object type
	// Consists of 4 bytes
	ExtentrefTreeType uint32

	// The snapshot metadata tree object type
	// Consists of 4 bytes
	SnapMetaTreeType uint32

	// The object map block number
	// Consists of 8 bytes
	OmapOID uint64

	// The file system root object identifier
	// Consists of 8 bytes
	RootTreeOID uint64

	// The extentref tree block number
	// Consists of 8 bytes
	ExtentrefTreeOID uint64

	// The snapshot metadata tree block number
	// Consists of 8 bytes
	SnapMetaTreeOID uint64

	// Revert to transaction identifier (apfs_revert_to_xid)
	// Consists of 8 bytes
	RevertToXID uint64

	// Revert to superblock object identifier (apfs_revert_to_sblock_oid)
	// Consists of 8 bytes
	RevertToSblockOID uint64

	// The next file system object identifier
	// Consists of 8 bytes
	NextObjID uint64

	// Number of regular files (apfs_num_files)
	// Consists of 8 bytes
	NumberOfFiles uint64

	// Number of directories (apfs_num_directories)
	// Consists of 8 bytes
	NumberOfDirectories uint64

	// Number of symbolic links (apfs_num_symlinks)
	// Consists of 8 bytes
	NumberOfSymlinks uint64

	// Number of other file system objects (apfs_num_other_fsobjects)
	// Consists of 8 bytes
	NumberOfOtherFileSystemObjects uint64

	// Number of snapshots (apfs_num_snapshots)
	// Consists of 8 bytes
	SnapshotCount uint64

	// Total blocks allocated ever (apfs_total_block_alloced)
	// Consists of 8 bytes
	TotalBlocksAllocated uint64

	// Total blocks freed ever (apfs_total_blocks_freed)
	// Consists of 8 bytes
	TotalBlocksFreed uint64

	// The volume identifier
	// Consists of 16 bytes
	// Contains an UUID
	VolumeUUID [16]byte

	// The volume (last) modification date and time
	// Consists of 8 bytes
	ModificationTime uint64

	// The volume flags
	// Consists of 8 bytes
	VolumeFlags uint64

	// Who formatted the volume (apfs_formatted_by)
	// Offset 272-320, consists of 48 bytes (32 + 8 + 8)
	FormattedBy ModifiedByInfo

	// History of who modified the volume (apfs_modified_by)
	// Offset 320-704, consists of 8 * 48 = 384 bytes
	ModifiedBy [8]ModifiedByInfo

	// The volume name
	// Consists of 256 bytes
	VolumeName [256]byte

	// The next (available) document identifier
	// Consists of 4 bytes
	NextDocID uint32

	// The volume's role (apfs_role)
	// Consists of 2 bytes
	Role uint16

	// Reserved (reserved)
	// Consists of 2 bytes
	Reserved uint16

	// The transaction identifier of a snapshot that the volume will revert
	// to (apfs_root_to_xid)
	// Consists of 8 bytes
	RootToXID uint64

	// The object identifier of the encryption rolling state (apfs_er_state_oid)
	// Consists of 8 bytes
	ERStateOID uint64

	// The largest object identifier used by this volume at the time it was
	// last cloned (apfs_cloneinfo_id_epoch)
	// Consists of 8 bytes
	CloneinfoIDEpoch uint64

	// The transaction identifier matching CloneinfoIDEpoch (apfs_cloneinfo_xid)
	// Consists of 8 bytes
	CloneinfoXID uint64

	// The object identifier of the extended snapshot metadata
	// (apfs_snap_meta_ext_oid)
	// Consists of 8 bytes
	SnapMetaExtOID uint64

	// The identifier of the volume group this volume belongs to
	// (apfs_volume_group_id), or the zero UUID when it belongs to none.
	// Consists of 16 bytes
	VolumeGroupID [16]byte
	// contains filtered or unexported fields
}

VolumeSuperblock represents the APFS volume superblock structure

func NewVolumeSuperblock

func NewVolumeSuperblock() *VolumeSuperblock

NewVolumeSuperblock creates a new volume superblock

func (*VolumeSuperblock) FileSystemIndex

func (vs *VolumeSuperblock) FileSystemIndex() (uint32, error)

FileSystemIndex retrieves the file system index

func (*VolumeSuperblock) FormattedByString

func (vs *VolumeSuperblock) FormattedByString() string

FormattedByString retrieves who formatted this volume

func (*VolumeSuperblock) LastModifiedBy

func (vs *VolumeSuperblock) LastModifiedBy() string

LastModifiedBy retrieves who last modified this volume (most recent entry)

func (*VolumeSuperblock) ModifiedByHistory

func (vs *VolumeSuperblock) ModifiedByHistory() []string

ModifiedByHistory retrieves the full modification history Returns a slice of strings from most recent to oldest, excluding empty entries

func (*VolumeSuperblock) NumberOfSnapshots

func (vs *VolumeSuperblock) NumberOfSnapshots() (uint64, error)

NumberOfSnapshots retrieves the number of snapshots

func (*VolumeSuperblock) ReadData

func (vs *VolumeSuperblock) ReadData(data []byte, isSnapshot bool) error

ReadData reads the volume superblock from binary data

func (*VolumeSuperblock) ReadFrom

func (vs *VolumeSuperblock) ReadFrom(reader io.ReaderAt, fileOffset int64, isSnapshot bool) error

ReadFrom reads the volume superblock from a file at the specified offset

func (*VolumeSuperblock) RevertToSuperblockObjectIdentifier

func (vs *VolumeSuperblock) RevertToSuperblockObjectIdentifier() (uint64, error)

RevertToSuperblockObjectIdentifier retrieves the revert-to superblock object identifier

func (*VolumeSuperblock) RevertToTransactionIdentifier

func (vs *VolumeSuperblock) RevertToTransactionIdentifier() (uint64, error)

RevertToTransactionIdentifier retrieves the revert-to transaction identifier

func (*VolumeSuperblock) UTF8VolumeName

func (vs *VolumeSuperblock) UTF8VolumeName() (string, error)

UTF8VolumeName retrieves the UTF-8 encoded volume name

func (*VolumeSuperblock) UTF8VolumeNameSize

func (vs *VolumeSuperblock) UTF8VolumeNameSize() (int, error)

UTF8VolumeNameSize retrieves the size of the UTF-8 encoded volume name The returned size includes the end of string character

func (*VolumeSuperblock) UTF16VolumeName

func (vs *VolumeSuperblock) UTF16VolumeName() ([]uint16, error)

UTF16VolumeName retrieves the UTF-16 encoded volume name

func (*VolumeSuperblock) UTF16VolumeNameSize

func (vs *VolumeSuperblock) UTF16VolumeNameSize() (int, error)

UTF16VolumeNameSize retrieves the size of the UTF-16 encoded volume name The returned size includes the end of string character

func (*VolumeSuperblock) VolumeGroupIdentifier

func (vs *VolumeSuperblock) VolumeGroupIdentifier() ([16]byte, error)

VolumeGroupIdentifier retrieves the identifier of the volume group this volume belongs to (apfs_volume_group_id). The zero UUID means the volume belongs to no group.

func (*VolumeSuperblock) VolumeIdentifier

func (vs *VolumeSuperblock) VolumeIdentifier() ([16]byte, error)

VolumeIdentifier retrieves the volume identifier (UUID)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL