moon-qcow

    Read-only QCOW2 images, backing chains, snapshots and incremental backup ranges.

    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    2 hours ago
    Downloads
    1

    #MoonQCOW

    用 MoonBit 读取 QCOW2 虚拟磁盘,查询数据映射,并分块导出 RAW 镜像。

    这个库适合离线镜像转换、备份数据读取,以及文件系统工具的底层数据接入。QCOW2 的簇映射、backing 链、快照、引用计数和脏位图处理由 MoonBit 完成;文件命令行使用 Node.js 的同步随机 I/O。读取已有镜像时不会调用 QEMU,QEMU 只在独立对照测试中使用。

    源码仓库:xlyyyyyy112/moon-qcow。模块名为 xlyyyyyy112/moon-qcow,尚未发布到 Mooncakes。

    #运行

    验证使用 MoonBit 0.10.18+6c83a7f62、Node.js 24。47 组测试已在 wasm、wasm-gc、JavaScript、Linux native 的 Debug/Release 模式通过。CI 配置使用相同 MoonBit 版本和 Node.js 22。Python 3.12 用于运行外部对照测试。

    在项目目录执行:

    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 --help

    基础库不依赖文件系统,可以接入自定义 Source,面向 wasm、wasm-gc、JavaScript、native。nodeio 和命令行仅支持 JavaScript/Node.js。

    #使用镜像

    moon 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 changed

    带 backing 文件的镜像需要增加 --allow-backing。这会按镜像中保存的路径打开其他本地文件,只应对信任的离线镜像开启。相对路径按包含它的镜像所在目录解析,循环链和过深链会报错;自动解析要求镜像明确声明 backing 格式为 raw 或 qcow2。

    输出文件必须不存在,避免覆盖镜像或已有数据。稀疏导出只对新建、预设长度的零文件跳过零块;导出失败可能留下不完整文件,命令会返回非零退出码。不会修改 QCOW2 源文件。

    命令默认输出 JSON。偏移和容量使用十进制字符串,避免 JavaScript JSON 数字损失 64 位精度。read 等参数支持十进制、0x 十六进制和 KiB/MiB/GiB/TiB 后缀。退出码为:0 成功,1 比较不同或检查发现问题,2 参数、格式或 I/O 错误。

    #库接口

    在调用方 moon.pkg 中导入 "xlyyyyyy112/moon-qcow" @qcow。源码工作区中可以使用以下方式:

    let 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())

    大镜像应使用 open_source(Source::new(size, read_at)),而不是把整个文件读入内存。Source 回调必须返回精确长度,源内容必须在 Image 生命周期内保持稳定。核心库不会自动打开文件。磁盘字节读取、区间操作、导出进度、错误处理等接口可查 pkg.generated.mbti。

    CopyCursor 和 BackupCursor 只在写入回调成功后推进进度;失败的块可以对幂等的 write-at 目标重试。稀疏复制需要调用方保证目标原本为零。进度不是持久化事务,也不提供跨进程断点身份校验。

    #已实现范围

    • QCOW2 v2/v3、512 字节至 2 MiB 簇、64 位逻辑偏移。
    • 标准 L1/L2、扩展 L2 子簇分配、显式零簇和 backing EOF 补零。
    • raw/qcow2 backing 链;DEFLATE 压缩簇的有界解压。
    • 内部快照目录及按 ID 读取;活动映射和解析 backing 后的映射。
    • 元数据区域、反向引用、分配统计、1/2/4/8/16/32/64 位引用计数。
    • 持久化脏位图目录、有效性检查、变更区间和增量复制选择。
    • 分块 RAW 导出、逻辑字节比较、区间索引、扇区读取适配。
    • 配置化读缓冲、缓存、链深度和扫描上限,失败时返回类型化错误。

    不支持镜像写入、修复、AES/LUKS 加密、zstd 压缩、外部数据文件;遇到相应特性明确报错。dirty/corrupt 标志也会被拒绝,不尝试恢复活动中或损坏镜像。

    audit 检查活动映射、元数据重叠以及被引用簇的非零引用计数,不等同于 qemu-img check。check-refcounts 能重建无快照、无持久化位图、无 VM 状态分配的引用关系;不支持的所有权范围会拒绝检查,不会假报完整通过。内部快照的 VM 内存状态不属于导出的虚拟磁盘内容。

    Node 文件适配层要求物理文件大小和输出偏移不超过 2^53-1;核心地址模型为 UInt64。默认单次读取最多 16 MiB,缓存最多 8 MiB/4096 项,链深度最多 32,扫描数量也有上限。大型镜像可按需求配置 Limits,达到限制会报错,不会返回截断后冒充完整的结果。

    #测试

    MoonBit 测试包含读取边界、压缩/子簇、位图异常、快照、引用计数、复制失败重试、区间集合性质测试和固定种子的损坏头变异。

    真实镜像测试需安装 qemu-img 和 qemu-io,Linux 可安装 qemu-utils;Windows 脚本也支持调用 Ubuntu WSL 中的 QEMU:

    moon build --target js --release --deny-warn python scripts/interop.py --report reports/interop-local.json python scripts/count_lines.py

    脚本用 QEMU 生成测试镜像,以 RAW 文件或 QEMU 导出结果为独立对照,执行逐字节比较、非对齐读取、稀疏导出、backing 链、快照、脏位图及 4 GiB 以上偏移测试。测试数据在临时目录生成,不需要下载第三方磁盘镜像。具体记录见 reports/interop-local.json。CI 工作流已经配置,远端运行状态需在推送后确认。

    #来源与许可证

    本项目采用 Apache-2.0,独立依据 QEMU QCOW2 格式规范 和 持久化脏位图说明 实现。未复制 QEMU 的 GPL 实现代码或文档正文。

    设计参考 lima-vm/go-qcow2reader 的随机读取定位(Apache-2.0),不宣称与其全部功能等价。DEFLATE 解压复用 moonbit-community/flate 0.10.0(Apache-2.0),不将依赖代码计入本项目实现行数。QEMU 8.2.2 作为外部测试工具使用,不随库分发。

    QcowError

    pub(all) suberror QcowError {
    Invalid(String)
    Unsupported(String)
    OutOfBounds
    MissingBacking
    LimitExceeded
    Io(String)
    } derive(
    Debug
    )

    QcowError::message

    fn QcowError::message(self : QcowError) -> String

    QcowError::to_repr

    #deprecated("`QcowError::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
    fn QcowError::to_repr(QcowError) ->
    Repr

    AllocationStats

    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
    }

    AuditIssue

    pub(all) struct AuditIssue {
    severity : String
    code : String
    offset : UInt64
    message : String
    }

    AuditIssue::json

    AuditReport

    pub(all) struct AuditReport {
    issues : Array[AuditIssue]
    scanned_bytes : UInt64
    mappings : Int
    complete : Bool
    }

    AuditReport::json

    AuditReport::ok

    fn AuditReport::ok(self : AuditReport) -> Bool

    Backing

    pub(all) enum Backing {
    Raw(Source)
    Qcow(Image)
    }

    Paths are never opened by the core; backing sources are explicit.

    BackupCursor

    pub struct BackupCursor {
    image : Image
    plan : BackupPlan
    chunk_size : Int
    range_index : Int
    within : UInt64
    copied : UInt64
    busy : Bool
    }

    BackupCursor::progress

    fn BackupCursor::progress(self : BackupCursor) -> BackupProgress

    BackupCursor::step

    fn BackupCursor::step(self : BackupCursor, max_chunks : Int, sink : (UInt64, Bytes) -> Unit raise QcowError) -> BackupProgress raise QcowError

    Sink positions are absolute guest offsets; unselected bytes are untouched.

    BackupPlan

    pub struct BackupPlan {
    virtual_size : UInt64
    ranges : Array[Difference]
    total_bytes : UInt64
    }

    Validated, sorted, coalesced selection of logical ranges for partial backup. It contains no destination identity or durability guarantee.

    BackupPlan::aligned

    fn BackupPlan::aligned(self : BackupPlan, block_size : UInt64) -> BackupPlan raise QcowError

    BackupPlan::chunk_count

    fn BackupPlan::chunk_count(self : BackupPlan, chunk_size : UInt64) -> UInt64 raise QcowError

    BackupPlan::complement

    fn BackupPlan::complement(self : BackupPlan) -> BackupPlan raise QcowError

    Backup intervals outside the selected plan, clipped to virtual size.

    BackupPlan::contains

    fn BackupPlan::contains(self : BackupPlan, offset : UInt64) -> Bool

    BackupPlan::intersection

    fn BackupPlan::intersection(self : BackupPlan, other : BackupPlan) -> BackupPlan raise QcowError

    BackupPlan::json

    BackupPlan::new

    fn BackupPlan::new(virtual_size : UInt64, ranges : ArrayView[Difference]) -> BackupPlan raise QcowError

    BackupPlan::ranges

    fn BackupPlan::ranges(self : BackupPlan) -> Array[Difference]

    Returns a copy so callers cannot alter an already-validated plan.

    BackupPlan::subtract

    fn BackupPlan::subtract(self : BackupPlan, other : BackupPlan) -> BackupPlan raise QcowError

    BackupPlan::total_bytes

    fn BackupPlan::total_bytes(self : BackupPlan) -> UInt64

    BackupPlan::union

    fn BackupPlan::union(self : BackupPlan, other : BackupPlan) -> BackupPlan raise QcowError

    BackupPlan::virtual_size

    fn BackupPlan::virtual_size(self : BackupPlan) -> UInt64

    BackupPlan::window

    fn BackupPlan::window(self : BackupPlan, offset : UInt64, length : UInt64) -> BackupPlan raise QcowError

    BackupProgress

    pub(all) struct BackupProgress {
    range_index : Int
    next_offset : UInt64
    copied_bytes : UInt64
    total_bytes : UInt64
    complete : Bool
    }

    Progress includes only fully acknowledged chunks in the selected ranges.

    BitmapValidation

    pub(all) struct BitmapValidation {
    name : String
    granules : UInt64
    dirty_granules : UInt64
    allocated_blocks : UInt64
    }

    BlockCache

    pub struct BlockCache {
    blocks : Map[(UInt64, Int), Bytes]
    queue : Array[(UInt64, Int)]
    head : Int
    bytes : Int
    budget : Int
    hits : UInt64
    misses : UInt64
    }

    Byte-bounded FIFO with constant-time lookup. The entry cap also bounds per-entry overhead when images use the smallest legal cluster size.

    BlockDevice

    pub struct BlockDevice {
    image : Image
    sector_size : Int
    sector_count : UInt64
    }

    Sector-oriented adapter for filesystem and partition readers.

    BlockDevice::read_sectors

    fn BlockDevice::read_sectors(self : BlockDevice, lba : UInt64, count : Int) -> Bytes raise QcowError

    BlockDevice::sector_count

    fn BlockDevice::sector_count(self : BlockDevice) -> UInt64

    BlockDevice::sector_size

    fn BlockDevice::sector_size(self : BlockDevice) -> Int

    BlockDevice::slice

    fn BlockDevice::slice(self : BlockDevice, first_lba : UInt64, sectors : UInt64) -> BlockSlice raise QcowError

    BlockSlice

    pub struct BlockSlice {
    device : BlockDevice
    first_lba : UInt64
    sectors : UInt64
    }

    A bounded subdevice whose sector addresses start at zero.

    BlockSlice::read_sectors

    fn BlockSlice::read_sectors(self : BlockSlice, lba : UInt64, count : Int) -> Bytes raise QcowError

    BlockSlice::sector_count

    fn BlockSlice::sector_count(self : BlockSlice) -> UInt64

    ByteRange

    pub(all) struct ByteRange {
    offset : UInt64
    length : UInt64
    }

    ByteRange::end

    fn ByteRange::end(self : ByteRange) -> UInt64 raise QcowError

    ByteRange::intersection

    fn ByteRange::intersection(self : ByteRange, other : ByteRange) -> ByteRange? raise QcowError

    ByteRange::split

    fn ByteRange::split(self : ByteRange, chunk_size : UInt64, max_chunks : Int) -> Array[ByteRange] raise QcowError

    CacheStats

    pub(all) struct CacheStats {
    bytes : Int
    blocks : Int
    hits : UInt64
    misses : UInt64
    }

    CacheStats::json

    ChainLayer

    pub(all) struct ChainLayer {
    depth : Int
    format : String
    virtual_size : UInt64
    physical_size : UInt64
    backing_filename : String?
    version : Int
    }

    ChainLayer::json

    CompareReport

    pub(all) struct CompareReport {
    compared_bytes : UInt64
    different_bytes : UInt64
    ranges : Array[Difference]
    complete : Bool
    }

    CompareReport::json

    CopyCursor

    pub struct CopyCursor {
    image : Image
    start : UInt64
    end : UInt64
    chunk_size : Int
    sparse : Bool
    next : UInt64
    written : UInt64
    skipped : UInt64
    busy : Bool
    }

    Incremental operation state. Caller supplies a stable image and destination.

    CopyCursor::progress

    fn CopyCursor::progress(self : CopyCursor) -> CopyProgress

    CopyCursor::step

    fn CopyCursor::step(self : CopyCursor, max_chunks : Int, sink : (UInt64, Bytes) -> Unit raise QcowError) -> CopyProgress raise QcowError

    At most max_chunks are processed; sink offsets are absolute guest offsets. A throwing sink leaves that chunk unacknowledged and safe to retry at the same offset with an idempotent write-at sink.

    CopyProgress

    pub(all) struct CopyProgress {
    start : UInt64
    next_offset : UInt64
    end : UInt64
    written_bytes : UInt64
    skipped_zero_bytes : UInt64
    complete : Bool
    }

    Export progress is acknowledged only after the sink callback succeeds.

    CopyProgress::json

    Difference

    pub(all) struct Difference {
    offset : UInt64
    length : UInt64
    }

    Difference::json

    DirtyBitmap

    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
    }

    Persistent dirty bitmap directory entry. Only consistent type-1 bitmaps can be used to select backup ranges; stale metadata remains inspectable.

    DirtyBitmap::granularity

    fn DirtyBitmap::granularity(self : DirtyBitmap) -> UInt64

    DirtyBitmap::json

    Extent

    pub(all) struct Extent {
    offset : UInt64
    length : UInt64
    kind : ExtentKind
    physical : UInt64?
    stored_length : Int
    }

    Mapping is local to this image; backing resolution is a separate operation.

    Extent::json

    ExtentKind

    pub(all) enum ExtentKind {
    Data
    Zero
    Unallocated
    Compressed
    }

    ExtentKind::name

    fn ExtentKind::name(self : ExtentKind) -> String

    FeatureName

    pub(all) struct FeatureName {
    feature_type : Int
    bit : Int
    name : String
    }

    FeatureName::json

    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
    }

    Header fields are untrusted until inspect_header succeeds.

    Header::cluster_count

    fn Header::cluster_count(self : Header) -> UInt64

    Header::cluster_size

    fn Header::cluster_size(self : Header) -> Int

    Header::extended_l2

    fn Header::extended_l2(self : Header) -> Bool

    Header::json

    All byte offsets/counts are strings so JSON consumers preserve 64-bit values.

    Header::l2_entries

    fn Header::l2_entries(self : Header) -> UInt64

    HeaderExtension

    pub(all) struct HeaderExtension {
    kind : UInt64
    offset : UInt64
    data : Bytes
    }

    HostRegion

    pub(all) struct HostRegion {
    offset : UInt64
    length : UInt64
    role : String
    }

    HostRegion::json

    Image

    pub struct Image {
    source : Source
    header : Header
    backing : Backing?
    depth : Int
    limits : Limits
    cache : BlockCache
    }

    Image::allocation_stats

    fn Image::allocation_stats(self : Image) -> AllocationStats raise QcowError

    Statistics refer to the active mapping, not to all allocated host clusters.

    Image::as_source

    fn Image::as_source(self : Image) -> Source

    Expose an image as a stable logical source for generic random-access clients.

    Image::audit

    fn Image::audit(self : Image, verify_data? : Bool, max_issues? : Int) -> AuditReport raise QcowError

    Audit active guest mappings and metadata references without modifying bytes. This checks referenced counts are nonzero, not exact global refcount equality: VM-state and bitmap allocations are outside this audit's ownership model.

    Image::backup_cursor

    fn Image::backup_cursor(self : Image, plan : BackupPlan, chunk_size? : Int) -> BackupCursor raise QcowError

    Image::bitmap_dirty

    fn Image::bitmap_dirty(self : Image, name : String, offset : UInt64) -> Bool raise QcowError

    Query whether the bitmap granule containing a guest offset was modified.

    Image::bitmap_plan

    fn Image::bitmap_plan(self : Image, name : String) -> BackupPlan raise QcowError

    Image::bitmap_ranges

    fn Image::bitmap_ranges(self : Image, name : String) -> Array[Difference] raise QcowError

    Coalesced modified guest ranges. A single bitmap cluster is scanned once.

    Image::bitmap_regions

    fn Image::bitmap_regions(self : Image) -> Array[HostRegion] raise QcowError

    Every allocated bitmap block, including unused entries, is metadata.

    Image::bitmaps

    fn Image::bitmaps(self : Image) -> Array[DirtyBitmap] raise QcowError

    Image::block_device

    fn Image::block_device(self : Image, sector_size? : Int) -> BlockDevice raise QcowError

    Image::cache_stats

    fn Image::cache_stats(self : Image) -> CacheStats

    Image::chain

    fn Image::chain(self : Image) -> Array[ChainLayer] raise QcowError

    Describe attached sources without opening any additional files.

    Image::chain_depth

    fn Image::chain_depth(self : Image) -> Int

    Image::check_refcounts

    fn Image::check_refcounts(self : Image, max_mismatches? : Int) -> RefcountCheck raise QcowError

    Exact reference reconstruction for standalone allocation topology without snapshots, persistent bitmaps or VM state. Unsupported ownership is rejected, rather than claiming a complete check of allocations this model cannot count.

    Image::clear_cache

    fn Image::clear_cache(self : Image) -> Unit

    Image::cluster_size

    fn Image::cluster_size(self : Image) -> Int

    Image::compare_image

    fn Image::compare_image(self : Image, other : Image, chunk_size? : Int, max_ranges? : Int) -> CompareReport raise QcowError

    Compare two logical images, including their respective backing chains.

    Image::compare_raw

    fn Image::compare_raw(self : Image, expected : Source, chunk_size? : Int, max_ranges? : Int) -> CompareReport raise QcowError

    Compare a logical image against a RAW source, preserving exact byte ranges. If max_ranges is reached, complete=false; absence of more reported ranges is never interpreted as equality. Both inputs must remain stable.

    Image::copy_cursor

    fn Image::copy_cursor(self : Image, offset : UInt64, length : UInt64, chunk_size? : Int, sparse? : Bool) -> CopyCursor raise QcowError

    Sparse mode does not write zero chunks; destination must initially read zero and be sized by the caller. Never use sparse mode against existing dirty data.

    Image::copy_to

    fn Image::copy_to(self : Image, sink : (UInt64, Bytes) -> Unit raise QcowError, chunk_size? : Int, sparse? : Bool, cancelled? : () -> Bool) -> CopyProgress raise QcowError

    Full bounded-memory export. Cancellation is checked before every chunk. An interrupted export reports progress and must not be presented as complete.

    Image::extent_at

    fn Image::extent_at(self : Image, position : UInt64) -> Extent raise QcowError

    Return a mapping starting at position and ending at the next mapping boundary.

    Image::header

    fn Image::header(self : Image) -> Header

    Image::layout_issues

    fn Image::layout_issues(self : Image, max_issues? : Int) -> Array[AuditIssue] raise QcowError

    Validate metadata aliasing. Shared identical L1/L2/bitmap data blocks are allowed; overlap between unrelated structures is an error.

    Image::map_index

    fn Image::map_index(self : Image) -> MapIndex raise QcowError

    Image::map_range

    fn Image::map_range(self : Image, offset : UInt64, length : UInt64) -> Array[Extent] raise QcowError

    Collected, coalesced local map with a hard record limit.

    Image::metadata_at

    fn Image::metadata_at(self : Image, offset : UInt64) -> Array[HostRegion] raise QcowError

    Metadata role lookup for diagnostics at an exact host address.

    Image::metadata_regions

    fn Image::metadata_regions(self : Image) -> Array[HostRegion] raise QcowError

    Enumerate metadata ranges, including inactive snapshots and refcount blocks.

    Image::metadata_size

    fn Image::metadata_size(self : Image) -> UInt64 raise QcowError

    Image::open_snapshot

    fn Image::open_snapshot(self : Image, id : String) -> Image raise QcowError

    Select a snapshot by exact ID. The active image and cache remain unchanged.

    Image::physical_size

    fn Image::physical_size(self : Image) -> UInt64

    Image::read_at

    fn Image::read_at(self : Image, offset : UInt64, length : Int) -> Bytes raise QcowError

    Exact-length guest read. No result is returned if any segment is invalid.

    Image::read_many

    fn Image::read_many(self : Image, ranges : ArrayView[ByteRange], max_total? : UInt64) -> Array[Bytes] raise QcowError

    Batch reads validate all requests before touching the source. Returned data preserves caller order; one failed read fails the whole batch result.

    Image::reader

    fn Image::reader(self : Image, offset : UInt64, length : UInt64) -> Reader raise QcowError

    Image::refcount_at

    fn Image::refcount_at(self : Image, offset : UInt64) -> UInt64 raise QcowError

    Return the stored reference count for the host cluster containing offset. This is an inspection operation, not a repair or a full consistency verdict.

    Image::refcount_runs

    fn Image::refcount_runs(self : Image) -> Array[RefcountRun] raise QcowError

    Scan only existing host file clusters, bounded by max_scan_clusters.

    Image::refcount_stats

    fn Image::refcount_stats(self : Image) -> RefcountStats raise QcowError

    Image::references_to

    fn Image::references_to(self : Image, host_offset : UInt64, host_length : UInt64) -> Array[Reference] raise QcowError

    Reverse mapping of a host byte range to active local guest references. Backing data is not included because its addresses belong to other files.

    Image::resolve_at

    fn Image::resolve_at(self : Image, position : UInt64) -> ResolvedExtent raise QcowError

    Resolve backing fallthrough while preserving explicit zero overrides.

    Image::resolved_map

    fn Image::resolved_map(self : Image, offset : UInt64, length : UInt64) -> Array[ResolvedExtent] raise QcowError

    Image::snapshots

    fn Image::snapshots(self : Image) -> Array[Snapshot] raise QcowError

    Snapshot enumeration is bounded and does not follow snapshot data mappings.

    Image::source_at_depth

    fn Image::source_at_depth(self : Image, depth : Int) -> Source raise QcowError

    Obtain the host source corresponding to a resolved extent's depth.

    Image::validate_bitmap

    fn Image::validate_bitmap(self : Image, name : String) -> BitmapValidation raise QcowError

    Validate stored tail bits as well as pointers; a dirty bitmap must not claim changes beyond the virtual disk. Unused bitmap-table entries must be zero.

    Image::virtual_size

    fn Image::virtual_size(self : Image) -> UInt64

    Image::visit_extents

    fn Image::visit_extents(self : Image, offset : UInt64, length : UInt64, visit : (Extent) -> Bool raise QcowError) -> Bool raise QcowError

    Streaming local map. The callback returns false to stop early. Compressed records retain their original compressed location and are not merged.

    Limits

    pub(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
    }

    Limits::default

    fn Limits::default() -> Limits

    MapIndex

    pub struct MapIndex {
    virtual_size : UInt64
    records : Array[Extent]
    }

    Immutable index over a complete, ordered local extent map. Intended for repeated range queries; building it still scans the image once.

    MapIndex::json

    MapIndex::lookup

    fn MapIndex::lookup(self : MapIndex, position : UInt64) -> Extent raise QcowError

    MapIndex::new

    fn MapIndex::new(virtual_size : UInt64, records : ArrayView[Extent]) -> MapIndex raise QcowError

    MapIndex::query

    fn MapIndex::query(self : MapIndex, offset : UInt64, length : UInt64) -> Array[Extent] raise QcowError

    MapIndex::record_count

    fn MapIndex::record_count(self : MapIndex) -> Int

    MapIndex::records

    fn MapIndex::records(self : MapIndex) -> Array[Extent]

    The full output is copied so callers cannot invalidate the index.

    MapIndex::stored_plan

    fn MapIndex::stored_plan(self : MapIndex) -> BackupPlan raise QcowError

    Select guest ranges whose bytes are physically stored in this image.

    MapIndex::unallocated_plan

    fn MapIndex::unallocated_plan(self : MapIndex) -> BackupPlan raise QcowError

    Return holes in the local image, including ranges supplied by a backing file.

    Reader

    pub struct Reader {
    image : Image
    start : UInt64
    length : UInt64
    position : UInt64
    }

    A seekable bounded view, useful for stream consumers without a huge buffer.

    Reader::position

    fn Reader::position(self : Reader) -> UInt64

    Reader::read

    fn Reader::read(self : Reader, maximum : Int) -> Bytes raise QcowError

    Stream reads may return fewer bytes at EOF, unlike Image::read_at.

    Reader::remaining

    fn Reader::remaining(self : Reader) -> UInt64

    Reader::seek

    fn Reader::seek(self : Reader, offset : UInt64) -> Unit raise QcowError

    RefcountCheck

    pub(all) struct RefcountCheck {
    checked_clusters : UInt64
    mismatches : Array[RefcountMismatch]
    complete : Bool
    }

    RefcountCheck::json

    RefcountCheck::ok

    fn RefcountCheck::ok(self : RefcountCheck) -> Bool

    RefcountMismatch

    pub(all) struct RefcountMismatch {
    offset : UInt64
    stored : UInt64
    expected : UInt64
    }

    RefcountRun

    pub(all) struct RefcountRun {
    offset : UInt64
    length : UInt64
    count : UInt64
    }

    RefcountRun::json

    RefcountStats

    pub(all) struct RefcountStats {
    host_clusters : UInt64
    unreferenced_clusters : UInt64
    exclusive_clusters : UInt64
    shared_clusters : UInt64
    max_refcount : UInt64
    }

    RefcountStats::json

    Reference

    pub(all) struct Reference {
    guest_offset : UInt64
    guest_length : UInt64
    physical_offset : UInt64
    physical_length : UInt64
    compressed : Bool
    }

    Reference::json

    ResolvedExtent

    pub(all) struct ResolvedExtent {
    offset : UInt64
    length : UInt64
    kind : ExtentKind
    physical : UInt64?
    stored_length : Int
    depth : Int
    }

    Snapshot

    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
    }

    Snapshot::json

    Source

    pub struct Source {
    size : UInt64
    read : (UInt64, Int) -> Bytes raise QcowError
    }

    A stable, exact-length random access source. The caller owns its lifetime.

    Source::check_range

    fn Source::check_range(self : Source, offset : UInt64, length : UInt64) -> Unit raise QcowError

    Source::from_bytes

    fn Source::from_bytes(data : Bytes) -> Source

    Source::new

    fn Source::new(size : UInt64, read : (UInt64, Int) -> Bytes raise QcowError) -> Source

    A source callback must return exactly the requested number of bytes.

    Source::read_at

    fn Source::read_at(self : Source, offset : UInt64, count : Int) -> Bytes raise QcowError

    Source::size

    fn Source::size(self : Source) -> UInt64

    Source::slice

    fn Source::slice(self : Source, offset : UInt64, length : UInt64) -> Source raise QcowError

    A zero-copy subsource adapter: only requested bytes are materialized.

    SourceMetrics

    pub struct SourceMetrics {
    reads : UInt64
    bytes : UInt64
    failed : UInt64
    largest : Int
    }

    Counts physical I/O calls made through the wrapped source, without retaining payloads or changing the source's error semantics.

    SourceMetrics::json

    SourceMetrics::new

    SourceMetrics::reset

    fn SourceMetrics::reset(self : SourceMetrics) -> Unit

    SourceMetrics::wrap

    fn SourceMetrics::wrap(self : SourceMetrics, source : Source) -> Source

    backing_filename

    fn backing_filename(source : Source, limits? : Limits) -> String? raise QcowError

    backing_format

    fn backing_format(source : Source, limits? : Limits) -> String? raise QcowError

    bytes_are_zero

    fn bytes_are_zero(data : BytesView) -> Bool

    clip_extents

    fn clip_extents(extents : ArrayView[Extent], offset : UInt64, length : UInt64) -> Array[Extent] raise QcowError

    Intersect logical mappings with a caller-specified window.

    concatenate_sources

    fn concatenate_sources(sources : ArrayView[Source], max_sources? : Int) -> Source raise QcowError

    Concatenate sources without joining their bytes in memory.

    dirty_blocks

    fn dirty_blocks(differences : ArrayView[Difference], block_size : UInt64, virtual_size : UInt64) -> Array[Difference] raise QcowError

    Convert byte changes to aligned backup blocks, clipped to the virtual disk.

    feature_names

    fn feature_names(source : Source) -> Array[FeatureName] raise QcowError

    header_extensions

    fn header_extensions(source : Source, limits? : Limits) -> Array[HeaderExtension] raise QcowError

    hex_offset

    fn hex_offset(value : UInt64) -> String

    hexdump

    fn hexdump(data : BytesView, offset? : UInt64) -> String raise QcowError

    Bounded binary display. Arbitrary guest bytes are not decoded as UTF-8.

    inspect_header

    fn inspect_header(source : Source, limits? : Limits) -> Header raise QcowError

    merge_differences

    fn merge_differences(input : ArrayView[Difference]) -> Array[Difference] raise QcowError

    Merge adjacent or overlapping byte differences into minimal sorted ranges.

    open

    fn open(data : Bytes, backing? : Backing, limits? : Limits) -> Image raise QcowError

    open_source

    fn open_source(source : Source, backing? : Backing, limits? : Limits) -> Image raise QcowError

    parse_size

    fn parse_size(text : String) -> UInt64 raise QcowError

    Exact byte counts: unsigned decimal or hexadecimal and binary unit suffixes.

    region_union_size

    fn region_union_size(regions : ArrayView[HostRegion]) -> UInt64 raise QcowError

    Byte union of ranges; repeated references to a shared table count only once.

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io