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.2.

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.2

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.2
File Size Uploaded Provenance Actions
pydmg-0.1.2.tar.gz 3.1 MB With provenance Details for pydmg-0.1.2.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for pydmg 0.1.2
File Actions
pydmg-0.1.2-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details for pydmg-0.1.2-cp39-abi3-win_amd64.whl
pydmg-0.1.2-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.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
pydmg-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details for pydmg-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
pydmg-0.1.2-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for pydmg-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
pydmg-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details for pydmg-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl

Total release size: 7.4 MB

Release files / pydmg-0.1.2.tar.gz

Download URL pydmg-0.1.2.tar.gz
Size 3.1 MB
Tags Source
SHA-256 checksum
How to use checksums
94f9e264089b28eca8b20cfa13426f4d78302fa2bba5473d6b92757e3cc5d0ee
BLAKE2b-256 checksum
How to use checksums
b0fcb51ac7aaef5bc8dd5bd49b4b953e9e18b26cad6496f42836cfcb125de490
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.2-cp39-abi3-win_amd64.whl

Download URL pydmg-0.1.2-cp39-abi3-win_amd64.whl
Size 722.9 kB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
7e0e128bf612176db8326a3ebcbaf9be7e9a56967177905abc675e325cbdf9f2
BLAKE2b-256 checksum
How to use checksums
5c9d60858c52705e2999e6d97ffe5b973f43b32ee60e52b29c1dd513f9691ccd
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.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pydmg-0.1.2-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
f73a6436d37778948e023cdd9815ad82054717e1fe43e46a00a7ec7851d1e972
BLAKE2b-256 checksum
How to use checksums
234876fbd3414550c70908498029622bf7d2e2e7bde3d5fc027ef595f74c9e94
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.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL pydmg-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 934.7 kB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
981b3349387494ed58f84222a5b087ed5e7586141d6421b9d410ca40e4101d81
BLAKE2b-256 checksum
How to use checksums
e4eef8bd6032a3a44d495ec798f2de2a9188eb61988cf1f6a8c3d5f118760f37
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.2-cp39-abi3-macosx_11_0_arm64.whl

Download URL pydmg-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
Size 830.7 kB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
051ac54029cce19bdd352e608d5040104824875963f64f0cd0e880e17d2db7fe
BLAKE2b-256 checksum
How to use checksums
e268158276b24d71bffeb6ef53ab73aac154ccc0c37dc3854e3fe15f23d5456b
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.2-cp39-abi3-macosx_10_12_x86_64.whl

Download URL pydmg-0.1.2-cp39-abi3-macosx_10_12_x86_64.whl
Size 821.9 kB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
6eed028357f379ff137eebbaaf573c4ef9d106ccdeca81147f1fb979a013f0b1
BLAKE2b-256 checksum
How to use checksums
293494277e54e9b5770d5b17d356d773e479f8acb4744e47b8ede5a5717af76f
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.2

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.2.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