Per-format implementation notes¶
What instar's parsers support for each disk image format, and the deliberate limits. For the qemu-img parity comparison and the coverage matrix, see format-coverage.md; for user-facing reference, see usage.md and the per-operation pages.
Format Support¶
Measurable target formats: raw, qcow2 (qemu-img-parity),
vmdk, vpc (VHD), vhdx (instar-only — qemu-img does not
implement measure for these targets).
Creatable target formats: raw (host-only —
open + ftruncate + posix_fallocate), qcow2 (qemu-img
info-equivalent modulo refcount_bits / compat / zstd
hardcodes), vmdk monolithicSparse + streamOptimized, vpc
dynamic + fixed (modulo CHS virtual_size rounding), vhdx
dynamic (modulo default block_size when unspecified).
Backing-file references supported on qcow2, vmdk, vpc, vhdx
(matches qemu-img's permission set). See
docs/create.md for the user reference and
docs/quirks.md for the documented writer
divergences.
qcow2¶
QEMU Copy-On-Write version 2/3. Supported features:
- Sparse allocation with cluster sizes 512B-2MB (cluster_bits 9-21)
- Compression (zlib, zstd) for clusters up to 2MB
- Backing file chains (automatic flattening)
- Refcount widths: 1, 2, 4, 8, 16, 32, 64 bits
- Extended L2 entries (16-byte with subcluster bitmaps;
full subcluster support — the bitmap is parsed for
per-subcluster data reading: Normal, Zero, and
Unallocated states; the read path narrows I/O for mixed-
subcluster clusters when sector_size ≤ subcluster_size).
Output with --extended-l2 writes 16-byte L2 entries with
incompatible_features bit 4 and per-subcluster sparse
bitmaps (compute_subcluster_bitmap()).
- Incompatible feature bit validation
- External data files (metadata/data separation, chain discovery with allowlist)
- Legacy AES-128-CBC encryption (crypt_method=1) decryption via --qcow2-password
- LUKS-in-QCOW2 encryption (crypt_method=2) decryption via --luks-passphrase
- LUKS-encrypted output (crypt_method=2) via --luks-encrypt-passphrase
(AES-256-XTS with PBKDF2-SHA256 key derivation, LUKS v1 headers)
- Snapshot table parsing, detection, and extraction via --snapshot
qcow2 write infrastructure¶
In-place mutation of an existing qcow2 (used by commit, rebase
safe mode and bench -w) runs on two shared no_std crates: the
crates/qcow2-write planner (pure, I/O-free, address-free —
turns a write into a typed step program; handles the envelope,
classification, allocate-on-write and copy-on-write) and the
crates/qcow2-write-exec executor (the literal step interpreter
plus the byte-range/device layer). Refcount growth is split the same
way across each crate's growth module. The maintainer reference for
this machinery — the step-program ABI, the write envelope, COW, growth
and the crash-ordering contract — is
docs/qcow2/qcow2-write-planner.md.
raw¶
Simple byte-for-byte disk representation. No metadata, just data.
vmdk¶
VMware Virtual Machine Disk. Supported sub-formats for input/output:
- monolithicSparse (input, output, check)
- streamOptimized (input, output with -c, check)
- monolithicFlat (input and output): two-file descriptor + flat extent.
The VMM detects the descriptor prefix on the host, parses the
extent line via vmdk::parse_descriptor_extents, validates
the flat path against the backing-file allowlist, and opens
the flat extent as a second virtio-block device. Guest
operations read content from that device through the same
ChainConfig.data_device_idx redirect used for QCOW2
external data files. Output via --subformat monolithicFlat.
- twoGbMaxExtentFlat (input): multi-extent flat descriptors with
multiple flat extent files. Each extent is opened as a separate
virtio-block device and reads are dispatched to the correct
device based on the extent offset map.
- monolithicFlat with parentFileNameHint= (input): descriptors
referencing a parent are followed as a backing chain, enabling
flat images in overlay hierarchies.
Detected but not yet supported for I/O: - twoGbMaxExtentSparse (multi-extent sparse, detected and rejected gracefully)
The check operation performs full structural validation: grain directory and grain table walk, grain offset bounds checking, compressed grain marker validation (LBA consistency and compressed size bounds), redundant grain directory (RGD) cross-check, overlap detection via 1-bit-per-grain bitmap, streamOptimized footer validation, fragmentation measurement, and multi-extent detection.
vhd¶
Microsoft Virtual Hard Disk. Supported sub-formats: - Fixed (type 2): raw data with 512-byte footer appended - Dynamic (type 3): BAT-based block allocation with 2 MiB blocks (input, output, check)
The check operation performs full structural validation: footer cookie and checksum, format version and feature flag validation, dynamic header cookie/checksum/version, BAT offset and entry bounds checking, overlap detection via 1-bit-per-block bitmap, fragmentation tracking, fixed VHD size validation, and footer copy consistency (start vs end of file).
vhdx¶
Microsoft VHDX Virtual Hard Disk v2 (Hyper-V). Supported: - Dynamic VHDX: BAT-based block allocation with 32 MiB blocks (input, output, check)
VHDX uses CRC-32C (Castagnoli) checksums, GUID-identified metadata, 64-bit BAT entries with interleaved sector bitmap entries, and 1MB-aligned structures. All on-disk fields are little-endian.
The check operation performs full structural validation: file identifier signature check, dual header CRC-32C validation with active header selection by sequence number, dirty log detection, region table 1 and 2 CRC-32C validation with cross-consistency check, GUID-based metadata parsing, BAT entry validation (offset bounds, 1MB alignment, overlap detection, state validation), and fragmentation tracking.
luks¶
LUKS encrypted containers (v1 and v2). The info operation parses: - Version, cipher name, cipher mode, hash algorithm - UUID, payload offset, master key length, active key slots - LUKS v2: JSON metadata area for cipher/hash extraction
With --luks-passphrase, LUKS v1 and v2 containers are decrypted inside
the KVM guest using pure-Rust RustCrypto crates (software AES, no
hardware acceleration needed in bare-metal). Key derivation uses PBKDF2
(v1) or Argon2id (v2, requires --max-guest-memory for the 1GB+ working
memory). The decrypted first block is passed through format detection to
report the inner format and virtual size.
The convert operation supports decrypting native LUKS containers
(--luks-passphrase) and LUKS-in-QCOW2 images (crypt_method=2). Both
use AES-XTS-plain64 for payload decryption. Native LUKS containers
wrapping QCOW2 images are transparently handled: the convert operation
detects the inner QCOW2 format and wraps the CallTable I/O function
pointers to offset and decrypt reads, allowing the qcow2 crate to
process the inner image without modification. LUKS v2 containers
using Argon2id KDF require --max-guest-memory to allocate the
working memory needed for key derivation.
vdi¶
VirtualBox Disk Image. Read-only input for convert / compare / dd /
bench (src/crates/vdi/, the PLAN-format-coverage work), both
dynamic and static images. Key structures: a single header
(validated against qemu's 12 open-time rules) plus a flat block
map, walked with an allocation-order lookup through the standard
sector-cached read path. Discarded and unallocated block-map
entries read as zeros, and reads at or past device capacity
zero-fill rather than error, matching qemu's lack of length
validation. check still refuses VDI (exit 63); map, measure,
and resize are unchanged refusals. See
docs/format-coverage.md and
docs/quirks.md for the full parity and quirks
detail.
parallels¶
Parallels disk images. Read-only input for convert / compare / dd /
bench (src/crates/parallels/, the PLAN-format-coverage work),
both the legacy "WithoutFreeSpace" (v1) and "WithouFreSpacExt"
(v2/ext) magics. Key structures: a header (tracks, catalog/BAT
size, ext_off) plus a per-magic BAT (sector-valued under v1,
cluster-valued under v2), walked through the standard sector-cached
read path. BAT value 0 and offsets beyond BAT coverage read as
zeros; ext_off != 0 is refused at init (a deliberate divergence —
instar does not parse the format extension). check still refuses
Parallels (exit 63); map, measure, and resize are unchanged
refusals. See docs/format-coverage.md
and docs/quirks.md for the full parity and
quirks detail.
qcow1 (qcow)¶
QEMU's original copy-on-write format ("qcow", superseded by qcow2
but not formally deprecated by qemu). Read-only input for convert /
compare / dd / bench (src/crates/qcow1/, the PLAN-format-coverage work), including backing chains and compressed clusters. Key
structures: a header plus two-level (L1/L2) block lookup, with
compressed clusters as raw DEFLATE (no zlib wrapper) — distinct
from qcow2's zlib-first decompression helper. QCOW1 is the first
non-QCOW2 backing format: unallocated clusters fall through to the
next chain device rather than zero-filling. check still refuses
QCOW1 (exit 63) — genuine parity, since qemu's own qcow driver also
refuses checks. map and measure stay refusals (a deliberate
divergence; qemu supports both on qcow1). See
docs/format-coverage.md and
docs/quirks.md for the full parity and quirks
detail.
dmg¶
Apple UDIF disk image. Read-only input for convert / compare / dd /
bench (src/crates/dmg/, the PLAN-format-coverage work). Key
structures: the koly trailer (shared trailer helpers), the
XML-plist or resource-fork chunk table, and per-sector chunk
lookup. Supports zlib, raw, ADC, bzip2, and LZFSE-compressed
chunks. The read-error model inverts every prior phase's posture:
most malformed inputs are refused rather than best-effort parsed.
DMG is supported at any backing-chain position. check still
refuses DMG (exit 63), but the refusal reports format "raw", not
"dmg", matching qemu-img's passthrough divergence. See
docs/format-coverage.md and
docs/quirks.md for the full parity and quirks
detail.