qflash

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

qflash

Flash a qcow2 disk image directly to a raw block device or file.

Build

make                        # builds both targets
make clean                  # removes dist/

Output binaries:

Binary Platform
dist/qflash-darwin-arm64 macOS (Apple Silicon)
dist/qflash-linux-amd64 Linux (x86-64)

Usage

# Inspect image headers
qflash -src image.qcow2

# Write virtual disk contents to a block device (dd-style)
qflash -src image.qcow2 -dst /dev/sdX

# Write to a raw file instead
qflash -src image.qcow2 -dst output.raw

# List partitions in the virtual disk
qflash -src image.qcow2 -list-parts

# Write individual partitions to separate devices
qflash -src image.qcow2 -write-parts 1=/dev/sda1,2=/dev/sda2

Flags

Flag Description
-src Path to the source qcow2 image (required)
-dst Destination device or raw file to write to (optional)
-list-parts List partition table from the virtual disk
-write-parts Write individual partitions, e.g. 1=/dev/sda1,2=/dev/sda2
-debug Print QCOW2 internal details and diagnostics

Docs

The docs/ directory contains reference material used to guide the implementation of the qcow2 library functions.

How it works

qflash implements the qcow2 format natively in Go. For each virtual cluster it:

  1. Walks the two-level L1/L2 table to find the host cluster location
  2. Reads the cluster (decompressing if needed — raw deflate)
  3. Writes it to the destination at the corresponding virtual offset

Unallocated clusters are skipped; those bytes on the destination device are left unchanged (sparse write).

Supports qcow2 version 2 and 3, standard clusters, zero-flag clusters, and deflate-compressed clusters.

Documentation

Overview

Package qflash reads QCOW2 virtual disk images and writes them to block devices or files.

Index

Constants

This section is empty.

Variables

View Source
var DebugMode bool

DebugMode enables verbose QCOW2 internal diagnostics.

Functions

func HumanSize

func HumanSize(bytes uint64) string

func ListPartitions

func ListPartitions(chain []*QCOWLayer) error

ListPartitions prints the MBR or GPT partition table from the virtual disk.

func ReadVirtualBytes

func ReadVirtualBytes(chain []*QCOWLayer, offset, length uint64) ([]byte, error)

ReadVirtualBytes reads length bytes from the virtual disk starting at offset, spanning cluster boundaries as needed.

func WritePartitions

func WritePartitions(chain []*QCOWLayer, targets []PartitionTarget) error

WritePartitions writes each partition specified in targets from the virtual disk to its device.

func WriteToDevice

func WriteToDevice(chain []*QCOWLayer, dst *os.File) error

WriteToDevice streams the virtual disk contents through the layer chain to dst using a pool of parallel workers — one per logical CPU. ReadAt and WriteAt are safe for concurrent use (pread/pwrite), and decompression is CPU-bound, so the worker pool gives near-linear throughput scaling.

Types

type HTTPReaderAt added in v1.0.2

type HTTPReaderAt struct {
	// contains filtered or unexported fields
}

HTTPReaderAt implements io.ReaderAt against a remote URL using HTTP range requests. Fetched chunks are cached in memory to avoid redundant requests when the same region is read multiple times (e.g. repeated L2 table lookups).

func NewHTTPReaderAt added in v1.0.2

func NewHTTPReaderAt(url string) *HTTPReaderAt

NewHTTPReaderAt creates an HTTPReaderAt for the given URL using the default HTTP client and a 1 MiB chunk size.

func NewHTTPReaderAtWithClient added in v1.0.2

func NewHTTPReaderAtWithClient(url string, client *http.Client, chunkSize int64) *HTTPReaderAt

NewHTTPReaderAtWithClient creates an HTTPReaderAt with a custom HTTP client and chunk size.

func (*HTTPReaderAt) ReadAt added in v1.0.2

func (h *HTTPReaderAt) ReadAt(p []byte, off int64) (int, error)

ReadAt implements io.ReaderAt. It fetches the minimal set of chunks needed to satisfy the request, caching each chunk for future reads.

type L1Entry

type L1Entry struct {
	L2TableOffset uint64
	NeedsCOW      bool
}

L1Entry holds a parsed L1 table entry. L2TableOffset is a direct byte offset into the image file. NeedsCOW is true when bit 63 of the raw entry is 0 (refcount != 1).

type L2Entry

type L2Entry struct {
	// Standard cluster fields
	HostClusterOffset uint64 // direct byte offset; 0 = unallocated
	IsZero            bool   // cluster reads as all zeros (bit 0 of standard descriptor)

	// Compressed cluster fields
	IsCompressed      bool
	CompressedOffset  uint64
	AdditionalSectors uint64

	RawValue uint64
}

L2Entry holds a parsed L2 table entry for a guest cluster.

type PartitionInfo

type PartitionInfo struct {
	Num       int
	StartByte uint64
	SizeBytes uint64
}

PartitionInfo describes a partition in the virtual disk.

func GetPartitionTable

func GetPartitionTable(chain []*QCOWLayer) ([]PartitionInfo, error)

GetPartitionTable reads the MBR or GPT partition table from the virtual disk.

type PartitionTarget

type PartitionTarget struct {
	Num    int
	Device string
}

PartitionTarget maps a partition number (1-based) to a destination device or file.

type QCOWHeader

type QCOWHeader struct {
	Magic                 string
	Version               uint32
	BackingFileOffset     uint64
	BackingFileSize       uint32
	ClusterBits           uint32
	Size                  uint64
	CryptMethod           uint32
	ClusterSize           uint64
	L1Size                uint32
	L1TableOffset         uint64
	RefcountTableOffset   uint64
	RefcountTableClusters uint32
	NbSnapshots           uint32
	SnapshotsOffset       uint64
	IncompatibleFeatures  uint64
	CompatibleFeatures    uint64
	AutoclearFeatures     uint64
	RefcountOrder         uint32
	HeaderLength          uint32
	ExtL2                 bool  // true when incompatible feature bit 4 is set (128-bit L2 entries)
	CompressionType       uint8 // 0=deflate (default), 1=zstd; present at header offset 104 (v3+)
}

type QCOWLayer

type QCOWLayer struct {
	File   io.ReaderAt
	Path   string // source path, used to resolve relative backing file references
	Header *QCOWHeader
	L1     []L1Entry
	// contains filtered or unexported fields
}

QCOWLayer is one image in a backing-file chain (overlay → ... → base).

func OpenLayerChain

func OpenLayerChain(src io.ReaderAt, srcPath string) ([]*QCOWLayer, error)

OpenLayerChain opens src and recursively opens any backing files, returning the full chain with the overlay first and the base image last. srcPath is used to resolve relative backing file references; pass an empty string to disable backing file support (e.g. for HTTP sources).

func OpenLayerChainFromFile added in v1.0.2

func OpenLayerChainFromFile(f *os.File) ([]*QCOWLayer, error)

OpenLayerChainFromFile is a convenience wrapper for local qcow2 files.

Directories

Path Synopsis
cmd
qflash command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL