Read-only QCOW2 images, backing chains, snapshots and incremental backup ranges.
moon check --target all --deny-warn
moon test --target wasm,wasm-gc,js --deny-warn
moon run examples/basic
moon build --target js --release --deny-warn
node _build/js/release/build/cmd/main/main.js --helpmoon run --target js cmd/main -- info disk.qcow2
moon run --target js cmd/main -- map disk.qcow2 --resolved
moon run --target js cmd/main -- audit disk.qcow2 --verify-data
moon run --target js cmd/main -- export-raw disk.qcow2 restored.raw --sparse
moon run --target js cmd/main -- compare disk.qcow2 reference.raw
moon run --target js cmd/main -- read disk.qcow2 65523 257 fragment.bin
moon run --target js cmd/main -- snapshots disk.qcow2
moon run --target js cmd/main -- export-raw disk.qcow2 snapshot.raw --snapshot 1
moon run --target js cmd/main -- bitmaps disk.qcow2
moon run --target js cmd/main -- dirty disk.qcow2 changedlet image = @qcow.open(image_bytes)
let bytes = image.read_at(65523UL, 257)
let extents = image.map_range(0UL, image.virtual_size())
let cursor = image.copy_cursor(0UL, image.virtual_size())moon build --target js --release --deny-warn
python scripts/interop.py --report reports/interop-local.json
python scripts/count_lines.pypub(all) suberror QcowError {
Invalid(String)
Unsupported(String)
OutOfBounds
MissingBacking
LimitExceeded
Io(String)
} derive(Debug)pub(all) struct AllocationStats {
virtual_bytes : UInt64
physical_bytes : UInt64
local_data_bytes : UInt64
explicit_zero_bytes : UInt64
backing_or_hole_bytes : UInt64
compressed_guest_bytes : UInt64
compressed_storage_bytes : UInt64
mapped_records : Int
}pub(all) struct AuditIssue {
severity : String
code : String
offset : UInt64
message : String
}pub(all) struct AuditReport {
issues : Array[AuditIssue]
scanned_bytes : UInt64
mappings : Int
complete : Bool
}pub struct BackupCursor {
image : Image
plan : BackupPlan
chunk_size : Int
range_index : Int
within : UInt64
copied : UInt64
busy : Bool
}fn BackupCursor::step(self : BackupCursor, max_chunks : Int, sink : (UInt64, Bytes) -> Unit raise QcowError) -> BackupProgress raise QcowErrorfn BackupPlan::new(virtual_size : UInt64, ranges : ArrayView[Difference]) -> BackupPlan raise QcowErrorfn BackupPlan::window(self : BackupPlan, offset : UInt64, length : UInt64) -> BackupPlan raise QcowErrorpub(all) struct BackupProgress {
range_index : Int
next_offset : UInt64
copied_bytes : UInt64
total_bytes : UInt64
complete : Bool
}pub(all) struct BitmapValidation {
name : String
granules : UInt64
dirty_granules : UInt64
allocated_blocks : UInt64
}fn BlockDevice::read_sectors(self : BlockDevice, lba : UInt64, count : Int) -> Bytes raise QcowErrorfn BlockDevice::slice(self : BlockDevice, first_lba : UInt64, sectors : UInt64) -> BlockSlice raise QcowErrorpub(all) struct ByteRange {
offset : UInt64
length : UInt64
}pub(all) struct CacheStats {
bytes : Int
blocks : Int
hits : UInt64
misses : UInt64
}pub(all) struct ChainLayer {
depth : Int
format : String
virtual_size : UInt64
physical_size : UInt64
backing_filename : String?
version : Int
}pub(all) struct CompareReport {
compared_bytes : UInt64
different_bytes : UInt64
ranges : Array[Difference]
complete : Bool
}pub struct CopyCursor {
image : Image
start : UInt64
end : UInt64
chunk_size : Int
sparse : Bool
next : UInt64
written : UInt64
skipped : UInt64
busy : Bool
}fn CopyCursor::step(self : CopyCursor, max_chunks : Int, sink : (UInt64, Bytes) -> Unit raise QcowError) -> CopyProgress raise QcowErrorpub(all) struct CopyProgress {
start : UInt64
next_offset : UInt64
end : UInt64
written_bytes : UInt64
skipped_zero_bytes : UInt64
complete : Bool
}pub(all) struct Difference {
offset : UInt64
length : UInt64
}pub(all) struct DirtyBitmap {
name : String
table_offset : UInt64
table_entries : UInt64
flags : UInt64
granularity_bits : Int
extra_length : Int
directory_offset : UInt64
directory_length : UInt64
consistent : Bool
}pub(all) struct Extent {
offset : UInt64
length : UInt64
kind : ExtentKind
physical : UInt64?
stored_length : Int
}pub(all) enum ExtentKind {
Data
Zero
Unallocated
Compressed
}pub(all) struct FeatureName {
feature_type : Int
bit : Int
name : String
}pub(all) struct Header {
version : Int
backing_offset : UInt64
backing_name_length : Int
cluster_bits : Int
virtual_size : UInt64
l1_entries : UInt64
l1_offset : UInt64
refcount_offset : UInt64
refcount_clusters : UInt64
snapshot_count : Int
snapshot_offset : UInt64
incompatible : UInt64
compatible : UInt64
autoclear : UInt64
refcount_order : Int
header_length : Int
}pub(all) struct HeaderExtension {
kind : UInt64
offset : UInt64
data : Bytes
}pub(all) struct HostRegion {
offset : UInt64
length : UInt64
role : String
}pub struct Image {
source : Source
header : Header
backing : Backing?
depth : Int
limits : Limits
cache : BlockCache
}fn Image::audit(self : Image, verify_data? : Bool, max_issues? : Int) -> AuditReport raise QcowErrorfn Image::backup_cursor(self : Image, plan : BackupPlan, chunk_size? : Int) -> BackupCursor raise QcowErrorfn Image::compare_image(self : Image, other : Image, chunk_size? : Int, max_ranges? : Int) -> CompareReport raise QcowErrorfn Image::compare_raw(self : Image, expected : Source, chunk_size? : Int, max_ranges? : Int) -> CompareReport raise QcowErrorfn Image::copy_cursor(self : Image, offset : UInt64, length : UInt64, chunk_size? : Int, sparse? : Bool) -> CopyCursor raise QcowErrorfn Image::copy_to(self : Image, sink : (UInt64, Bytes) -> Unit raise QcowError, chunk_size? : Int, sparse? : Bool, cancelled? : () -> Bool) -> CopyProgress raise QcowErrorfn Image::resolved_map(self : Image, offset : UInt64, length : UInt64) -> Array[ResolvedExtent] raise QcowErrorpub(all) struct Limits {
max_read : Int
max_chain : Int
max_l1_entries : Int
max_extensions : Int
max_snapshots : Int
max_map_entries : Int
max_scan_clusters : Int
cache_bytes : Int
}pub(all) struct RefcountCheck {
checked_clusters : UInt64
mismatches : Array[RefcountMismatch]
complete : Bool
}pub(all) struct RefcountMismatch {
offset : UInt64
stored : UInt64
expected : UInt64
}pub(all) struct RefcountRun {
offset : UInt64
length : UInt64
count : UInt64
}pub(all) struct RefcountStats {
host_clusters : UInt64
unreferenced_clusters : UInt64
exclusive_clusters : UInt64
shared_clusters : UInt64
max_refcount : UInt64
}pub(all) struct Reference {
guest_offset : UInt64
guest_length : UInt64
physical_offset : UInt64
physical_length : UInt64
compressed : Bool
}pub(all) struct ResolvedExtent {
offset : UInt64
length : UInt64
kind : ExtentKind
physical : UInt64?
stored_length : Int
depth : Int
}pub(all) struct Snapshot {
index : Int
id : String
name : String
l1_offset : UInt64
l1_entries : UInt64
virtual_size : UInt64
date_seconds : UInt64
date_nanoseconds : UInt64
vm_clock_nanoseconds : UInt64
vm_state_size : UInt64
entry_offset : UInt64
entry_length : UInt64
}pub struct SourceMetrics {
reads : UInt64
bytes : UInt64
failed : UInt64
largest : Int
}fn dirty_blocks(differences : ArrayView[Difference], block_size : UInt64, virtual_size : UInt64) -> Array[Difference] raise QcowError