Skip to main content

pydmg

pydmg is a cross-platform Python library for reading, inspecting, extracting, and creating Apple DMG files. It uses the Rust crate apple-dmg under the hood and exposes a Pythonic API.

  • License: MIT
  • Core Rust dependency: apple-dmg (Apache-2.0 OR MIT, MIT-compatible)
  • DMG/HFS+/APFS backends: udif, hfsplus, and apfs (MIT)
  • Third-party notices: THIRD_PARTY_NOTICES.md
  • Build backend: maturin + pyo3
  • Platforms: macOS, Linux, Windows
  • Distribution: prebuilt wheels for major architectures + source distribution (sdist) for any architecture with Rust toolchain

Features

  • Read DMG trailer (koly) metadata and checksum fields.
  • Parse plist metadata and return a JSON-serializable structure.
  • Extract metadata candidates for:
    • creation and modification dates/timestamps
    • author/creator-like fields
    • creation application/tool fields
  • List partitions and their BLKX chunk tables.
  • Inspect GPT partition-table metadata when GPT is present in DMG partitions.
  • Inspect filesystem metadata for FAT12/16/32 partitions.
  • Auto-detect and inspect HFS+/APFS metadata through a bounded udif extraction adapter.
  • Decompress raw, zero-fill, zlib, bzip2, and LZFSE partition chunks with checked limits.
  • Verify data fork CRC32 checksum.
  • List and extract files from FAT32 DMG partitions.
  • List and extract files from auto-detected HFS+/APFS DMG filesystems.
  • Create new DMGs from a source directory.

Installation

From PyPI

pip install pydmg

From source (local development)

Requirements:

  • Python 3.9+
  • Rust 1.98.1 for reproducible repository builds (the crate's tested MSRV remains 1.88)
  • C/C++ compiler toolchain

Platform notes for source builds:

  • Linux: install build-essential, pkg-config, libbz2-dev, liblzma-dev
  • macOS: install Xcode Command Line Tools and pkg-config
  • Windows: install Visual Studio Build Tools (MSVC C++)
pip install -e ".[dev]"

Quick Start

from pathlib import Path
import pydmg

info = pydmg.inspect("example.dmg")
print(info["koly"]["version"])
print(info["checksum"]["data_fork_checksum_matches"])

parts = pydmg.list_partitions("example.dmg")
print([p["name"] for p in parts])

gpt_info = pydmg.inspect_gpt("example.dmg")
print(gpt_info["has_gpt"])

fat_entries = pydmg.list_fat32_entries("example.dmg", partition_index=1)
print(fat_entries[:5])

pydmg.extract_fat32("example.dmg", "./out", partition_index=1)

fs_info = pydmg.inspect_filesystems("example.dmg")
print(fs_info["fat_filesystems"])

# For HFS+/APFS DMGs:
# entries = pydmg.list_apple_entries("macos_installer.dmg", "/")
# pydmg.extract_apple_file("macos_installer.dmg", "/path/in/image.pkg", "./image.pkg")

pydmg.create_dmg(
    source_dir=Path("./payload"),
    output_path=Path("./payload.dmg"),
    volume_label="PAYLOAD",
    total_sectors=32768,
)

API Surface

Top-level functions

  • inspect(path)
  • inspect_filesystems(path)
  • list_partitions(path)
  • inspect_gpt(path, partition_index=None, strict=False)
  • read_partition(path, index)
  • extract_partition(path, index, output_path)
  • compute_data_checksum(path)
  • verify_data_checksum(path)
  • list_fat32_entries(path, partition_index=1)
  • extract_fat32(path, output_dir, partition_index=1, overwrite=False)
  • list_apple_entries(path, directory_path="/")
  • read_apple_file(path, file_path)
  • extract_apple_file(path, file_path, output_path)
  • create_dmg(source_dir, output_path, volume_label="PYDMG", total_sectors=32768)

Object API

DmgImage(path) provides convenience wrappers over the same operations.

Function Reference

All paths accept str or pathlib.Path.

Common error behavior:

  • Raises RuntimeError when parsing, decompression, or filesystem reads fail.
  • Raises IndexError when a requested partition index is outside the parsed partition list.
  • Raises ValueError for invalid user input (for example invalid create_dmg arguments).
  • Catches HFS+/APFS dependency panics and returns RuntimeError; Rust's panic hook may still emit a diagnostic to stderr for a malformed image.

DMG inspection and metadata

inspect(path) -> dict

  • Returns DMG-level details including:
  • koly trailer values
  • checksum fields and CRC comparison result
  • parsed plist
  • metadata_candidates (date/author/tool-like fields)
  • partition metadata and chunk tables

inspect_filesystems(path) -> dict

  • Returns detected filesystem metadata including:
  • fat_filesystems list (FAT12/16/32 metadata)
  • apple_filesystem (HFS+/APFS metadata when detected)
  • errors list for non-fatal detection failures

inspect_gpt(path, partition_index=None, strict=False) -> dict

  • Scans one partition or all partitions for GPT metadata.
  • If no GPT is found and strict=False, returns has_gpt: false.
  • If no GPT is found and strict=True, raises RuntimeError.

list_partitions(path) -> list[dict]

  • Returns parsed DMG partition records with BLKX chunk info.

Example:

import pydmg

info = pydmg.inspect("image.dmg")
print(info["metadata_candidates"])

fs = pydmg.inspect_filesystems("image.dmg")
print(fs["fat_filesystems"])
print(fs["apple_filesystem"])

gpt = pydmg.inspect_gpt("image.dmg", strict=False)
print(gpt["has_gpt"])

parts = pydmg.list_partitions("image.dmg")
print(len(parts))

Partition payload and checksums

read_partition(path, index) -> bytes

  • Reads and decompresses the partition payload at index.
  • Rejects partitions that expand beyond 512 MiB, compressed chunks larger than 256 MiB, expanded chunks larger than 64 MiB, and non-contiguous BLKX output layouts.
  • ADC-compressed chunks are unsupported by the upstream DMG decoders and raise RuntimeError.

extract_partition(path, index, output_path) -> int

  • Atomically replaces output_path only after the complete payload is written and synchronized.
  • Replaces a final symlink itself rather than following it to its target.

compute_data_checksum(path) -> int

  • Computes DMG data-fork CRC32.

verify_data_checksum(path) -> bool

  • Compares computed CRC32 to the trailer-declared checksum.

Example:

payload = pydmg.read_partition("image.dmg", 0)
print(len(payload))

written = pydmg.extract_partition("image.dmg", 0, "part0.bin")
print(written)

print(pydmg.compute_data_checksum("image.dmg"))
print(pydmg.verify_data_checksum("image.dmg"))

FAT32 filesystem helpers

list_fat32_entries(path, partition_index=1) -> list[dict]

  • Lists FAT entries with path/type/size metadata.

extract_fat32(path, output_dir, partition_index=1, overwrite=False) -> list[str]

  • Extracts files from the selected FAT partition.
  • Returns extracted relative paths.
  • Rejects a symlink output root, symlink path components, and symlink file destinations.
  • Stops after 100,000 entries, nesting deeper than 128, 512 MiB aggregate file data, 576 MiB of dependency reads, or 2,000,000 dependency read operations.
  • This bulk API writes image-derived names. The assessed deployment profile instead writes bytes only to caller-selected files; use this separate API only with a caller-controlled output tree.

Example:

entries = pydmg.list_fat32_entries("image.dmg", partition_index=1)
print(entries[:3])

files = pydmg.extract_fat32("image.dmg", "out/fat", partition_index=1, overwrite=True)
print(files[:3])

HFS+ and APFS filesystem helpers

list_apple_entries(path, directory_path="/") -> list[dict]

  • Auto-detects HFS+ or APFS and lists directory entries.
  • Preflights HFS+ allocation blocks and APFS block/checkpoint metadata before entering the third-party filesystem parsers.

read_apple_file(path, file_path) -> bytes

  • Reads a single file from detected HFS+/APFS filesystem.
  • Rejects output beyond 512 MiB.

extract_apple_file(path, file_path, output_path) -> int

  • Atomically replaces output_path after a complete bounded write and returns bytes written.
  • Failure preserves an existing destination.

Example:

entries = pydmg.list_apple_entries("mac_image.dmg", "/")
print(entries[:5])

data = pydmg.read_apple_file("mac_image.dmg", "/README.txt")
print(len(data))

written = pydmg.extract_apple_file("mac_image.dmg", "/README.txt", "out/README.txt")
print(written)

DMG creation

create_dmg(source_dir, output_path, volume_label="PYDMG", total_sectors=32768) -> None

  • Creates a DMG from a directory.
  • total_sectors uses 512-byte sectors.
  • The maximum created image is 1,048,576 sectors (512 MiB).
  • Creation uses a sibling temporary file and atomically replaces the final output on success.
  • The assessed threat model assumes the caller-controlled source tree remains immutable while the image is created.

Example:

from pathlib import Path
import pydmg

pydmg.create_dmg(
    source_dir=Path("payload"),
    output_path=Path("payload.dmg"),
    volume_label="PAYLOAD",
    total_sectors=32768,
)

DmgImage convenience object

DmgImage(path) wraps the same top-level APIs as instance methods.

Example:

img = pydmg.DmgImage("image.dmg")
print(img.inspect()["koly"]["version"])
print(img.inspect_filesystems()["apple_filesystem"])
print(img.checksum_valid())

Testing

pytest

The test suite covers:

  • DMG creation from a fixture directory
  • inspection payload completeness
  • checksum computation/verification
  • GPT inspection behavior (non-GPT reporting and strict mode)
  • partition read/extract
  • FAT32 listing and extraction
  • filesystem metadata inspection (FAT + HFS+/APFS auto-detect behavior)
  • HFS+ positive listing/read/extract using upstream hfsplus-rs fixture image
  • APFS positive listing/read/extract using non-malware linearmouse fixture image
  • partition index error behavior
  • BLKX count/truncation and checked range rejection
  • zlib, bzip2, and LZFSE decoding plus decompression ceilings
  • positive in-memory GPT parsing, GPT assertion/CRC preflight, and pre-allocation plist limits
  • FAT and direct-output symlink defenses and atomic failure behavior
  • FAT/HFS+/APFS dependency read budgets and panic containment

The current suite contains 22 Python tests and 18 cross-platform native Rust tests, plus one Unix path-panic regression. CI enforces 90% Python line coverage and 70% native Rust line coverage as separate measurements.

Performance

FAT filesystems are served through a bounded seekable BLKX reader, so directory listing and file extraction decompress only requested chunks instead of materializing an entire partition. Direct partition reads and atomic extraction stream into their final sink, with reusable LZFSE buffers and no per-chunk staging copy.

The release-mode benchmark method, raw samples, profiles, artifact-size tradeoffs, and dated before/after results are in PERFORMANCE.md. CI records five-sample evidence for each immutable revision, and the tag-gated release workflow records nine samples before building distribution artifacts.

Security, audit, and fuzzing

DMGs and embedded filesystem structures are untrusted binary input. Review the SECURITY.md threat model and safe-use guidance before processing images from an untrusted source. The dated coverage, dependency, CI, documentation, and security findings are in AUDIT.md; reproducible coverage-guided fuzzing instructions are in FUZZING.md.

Repository-owned range, decompression, plist pre-allocation, GPT, FAT-read, checksum, output-atomicity, lint, test, and CI findings have local remediations. APFS parser panics and APFS/HFS traversal-budget defects are bounded or contained where possible but remain open upstream; ADC decoding remains an explicit fail-closed compatibility limitation. The obsolete XAR dependency path was removed, so the locked graph uses patched quick-xml 0.41.0 with no advisory exceptions. The active threat model is a static attacker-crafted image, immutable during processing, with caller-selected output files and no hostile concurrent filesystem writer. CPU and memory exhaustion are deferred in the current assessment. Provenance is not required, and selected content is recorded only as inert bytes or text with no active execution. Sandbox and host limits remain broader defense in depth. A successful CRC32 check is not authenticity verification.

API Docs (pydoc)

Generate HTML API docs locally:

python scripts/build_pydoc.py

This writes pydmg.html in the current directory. CI also verifies that pydoc build succeeds.

GitHub Actions and PyPI

This repo includes workflows for:

  • CI: Python 3.9–3.13 and Rust tests, lint, strict typing, Bandit, dependency audits, MSRV, and separate Python/native coverage and release-performance evidence gates
  • Fuzz: required PR smoke and scheduled AddressSanitizer campaigns; sensitive failures remain on the runner for private reproduction rather than being uploaded from the public repository
  • Release: repeat quality/security/coverage/fuzz gates, build wheels and source distribution, then publish to PyPI through trusted publishing

Release workflow targets:

  • Linux: x86_64, aarch64
  • macOS: x86_64, arm64
  • Windows: x86_64
  • Plus sdist for architecture-independent source release

For publishing, configure PyPI trusted publishing for this repository and push a tag like v0.1.3.

Detailed release steps are documented in RELEASE.md.

Licensing Notes

  • Project license: MIT (LICENSE)
  • Third-party attribution and fixture provenance: THIRD_PARTY_NOTICES.md
  • Test fixture source details: tests/fixtures/README.md
  • No Paragon APFS SDK code is included

Notes on metadata completeness

DMG metadata fields vary by producer and format. pydmg returns:

  • parsed plist payload (JSON-compatible representation)
  • extracted metadata candidates based on key patterns

This gives broad coverage of creation dates, creators/authors, and creation applications when present.

Metadata

Release files for pydmg 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pydmg 0.1.3
File Size Uploaded Provenance Actions
pydmg-0.1.3.tar.gz 3.1 MB With provenance Details for pydmg-0.1.3.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for pydmg 0.1.3
File Actions
pydmg-0.1.3-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details for pydmg-0.1.3-cp39-abi3-win_amd64.whl
pydmg-0.1.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details for pydmg-0.1.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
pydmg-0.1.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details for pydmg-0.1.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
pydmg-0.1.3-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for pydmg-0.1.3-cp39-abi3-macosx_11_0_arm64.whl
pydmg-0.1.3-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details for pydmg-0.1.3-cp39-abi3-macosx_10_12_x86_64.whl

Total release size: 7.4 MB

Release files / pydmg-0.1.3.tar.gz

Download URL pydmg-0.1.3.tar.gz
Size 3.1 MB
Tags Source
SHA-256 checksum
How to use checksums
a7cdca2ec85e0bfb70a5dc8e84cdc2e1e264b27ac0a91c53b98503e783d438b0
BLAKE2b-256 checksum
How to use checksums
bd49afa807ae31510fbddd8e0562f2d47b897d179f50764d80c6e6dbb4d0425c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / pydmg-0.1.3-cp39-abi3-win_amd64.whl

Download URL pydmg-0.1.3-cp39-abi3-win_amd64.whl
Size 722.8 kB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
ac600e8a84ab988e1cfad8aacfc80044ba0e9b664f4ff28775e368f9e0568c6a
BLAKE2b-256 checksum
How to use checksums
f74b465b8750a825f703f581b97a5509ddd5c960706ec0142aa9b5db3ebf8525
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / pydmg-0.1.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pydmg-0.1.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 930.4 kB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
27055d1875c6ead8500fa0fc62856cf23698615db745359bf909e4212ed73485
BLAKE2b-256 checksum
How to use checksums
d4b4793af6e701e336afdc0022a7cd896665d75b6370f261921c6310fc6fc4fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / pydmg-0.1.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL pydmg-0.1.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 935.6 kB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
b1f1977fa7c4751a20bbe7c9a2484658c4cf4208c7053f5706dd9bd992190c92
BLAKE2b-256 checksum
How to use checksums
8c10dafd38bf6366c8e50fe5157d5108d633d6b34bf7b38ae59f246699ff9fd8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / pydmg-0.1.3-cp39-abi3-macosx_11_0_arm64.whl

Download URL pydmg-0.1.3-cp39-abi3-macosx_11_0_arm64.whl
Size 830.6 kB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
4828d8e8100dfb563050eb76000159b62bd791ea685baf419278c4e75641e848
BLAKE2b-256 checksum
How to use checksums
4c29b45ff2224a8a3d7fb5acf2c3eea24cbc510252389522649d2470bc754aca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / pydmg-0.1.3-cp39-abi3-macosx_10_12_x86_64.whl

Download URL pydmg-0.1.3-cp39-abi3-macosx_10_12_x86_64.whl
Size 821.8 kB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
cf180be7ab1e91e4a4df56e1a7b2e958599a3886376902d83dd3284c7ee2c6e8
BLAKE2b-256 checksum
How to use checksums
bbaefcbac467eaa333a73a9300ea1cb796df71284b08b06e4470586592acc9b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Security for pydmg 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for pydmg-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page