Documentation
¶
Overview ¶
Package disklayout parses and models GPT disk layouts for bare-metal backup/recovery (issue #67, docs/BARE_METAL_RECOVERY.md). It is pure parsing over an io.ReaderAt — device, image file, or byte slice — with no platform dependencies, so the whole package is testable on any OS against synthetic images.
Index ¶
- Constants
- func ApplyFit(l *DiskLayout, plan *FitPlan, capturedPrimary, capturedBackup []byte) (primary []byte, backupOffset int64, backup []byte, err error)
- func ListMachineManifests(repoPath string) ([]string, error)
- func MachineManifestPath(repoPath, snapshotID string) string
- func MarshalMachineManifest(m *MachineManifest) ([]byte, error)
- func RelocateGPT(l *DiskLayout, capturedPrimary, capturedBackup []byte, newDiskSize int64) (primary []byte, backupOffset int64, backup []byte, err error)
- func SaveMachineManifest(repoPath, snapshotID string, m *MachineManifest) error
- func TypeName(g GUID) string
- type DiskCapture
- type DiskLayout
- type FitOptions
- type FitPlan
- type GUID
- type MachineManifest
- type MemberKind
- type Partition
- type PartitionMember
- type PlannedPartition
- type Range
- type TargetGeometry
Constants ¶
const ( TypeESP = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" // EFI System Partition TypeMSR = "E3C9E316-0B5C-4DB8-817D-F92DF00215AE" // Microsoft Reserved TypeMSBasicData = "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" // Windows basic data (NTFS/exFAT) TypeWinRE = "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC" // Windows Recovery Environment TypeLinuxFS = "0FC63DAF-8483-4772-8E79-3D69D8477DE4" // Linux filesystem TypeLinuxSwap = "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" // Linux swap TypeBIOSBoot = "21686148-6449-6E6F-744E-656564454649" // GRUB BIOS boot TypeLinuxLVM = "E6D6D379-F507-44C2-A23C-238F2A3DF928" // Linux LVM PV TypeLinuxHome = "933AC7E1-2EB4-4F13-B844-0E14E2AEF915" // Linux /home TypeMSLDMMetadata = "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3" // Windows LDM metadata )
Well-known partition type GUIDs (canonical string form).
Variables ¶
This section is empty.
Functions ¶
func ApplyFit ¶ added in v0.2.0
func ApplyFit(l *DiskLayout, plan *FitPlan, capturedPrimary, capturedBackup []byte) (primary []byte, backupOffset int64, backup []byte, err error)
ApplyFit rewrites the captured boot structures for a plan: entries carry their new extents, the GPT headers their new last-usable and alternate LBAs, every CRC is recomputed, and every GUID is untouched. It returns the primary region for LBA0 onward and, for GPT, the backup structures and where they go. A plan with refusals is refused.
func ListMachineManifests ¶
ListMachineManifests returns the snapshot IDs of all machine manifests in a repo (for the recovery flow's listing).
func MachineManifestPath ¶
MachineManifestPath is the repo location of a machine snapshot manifest.
func MarshalMachineManifest ¶
func MarshalMachineManifest(m *MachineManifest) ([]byte, error)
MarshalMachineManifest validates and encodes a manifest in the CRC envelope used both for the local repo file and the S3 object (#70).
func RelocateGPT ¶
func RelocateGPT(l *DiskLayout, capturedPrimary, capturedBackup []byte, newDiskSize int64) (primary []byte, backupOffset int64, backup []byte, err error)
RelocateGPT adapts a captured disk's verbatim GPT regions to a LARGER target disk (#76): real drive replacements are rarely the same size, and a backup GPT header that is not at the last LBA is flagged as corruption by firmware and partitioning tools.
It returns:
- primary: the captured primary region with ONLY the header's AlternateLBA patched to the new last LBA (and the header CRC recomputed) — everything else, including the protective MBR, disk GUID, partition entries and their GUIDs, stays byte-identical, which is what keeps BCD/fstab references valid.
- backupOffset/backup: the rebuilt backup structures (entry-array copy + backup header) positioned at the true end of the new disk.
The extra space beyond the captured LastUsableLBA is left unallocated (partition growth is a deliberate non-goal here; growpart/ntfsresize on the recovery key cover it). Same-size targets pass through unchanged (verbatim backup at its captured offset). Smaller targets are refused.
func SaveMachineManifest ¶
func SaveMachineManifest(repoPath, snapshotID string, m *MachineManifest) error
SaveMachineManifest atomically writes the manifest (temp + fsync + rename + dir sync — the repo-wide durability pattern).
Types ¶
type DiskCapture ¶
type DiskCapture struct {
// Source identifies the disk on the origin machine (informational):
// "\\.\PhysicalDrive0", "/dev/sda", or an image path.
Source string `json:"source"`
Layout DiskLayout `json:"layout"`
// PrimaryGPT and BackupGPT are the verbatim bytes of the layout's
// PrimaryRegion / BackupRegion, restored byte-exactly so disk signatures
// and partition GUIDs (which BCD/fstab reference) are preserved.
PrimaryGPT []byte `json:"primary_gpt"`
BackupGPT []byte `json:"backup_gpt"`
// AuxBytes (#149): verbatim bytes of Layout.AuxRegions (the MBR EBR
// chain lives in inter-partition gaps no member covers).
AuxBytes [][]byte `json:"aux_bytes,omitempty"`
Members []PartitionMember `json:"members"`
}
DiskCapture is one whole disk in a machine snapshot: its parsed layout, the verbatim GPT metadata regions, and the per-partition member backups.
type DiskLayout ¶
type DiskLayout struct {
// Scheme is "gpt" or "mbr" (#149); "" in manifests written before MBR
// support means gpt.
Scheme string `json:"scheme,omitempty"`
SectorSize int `json:"sector_size"`
DiskSize int64 `json:"disk_size"`
DiskGUID string `json:"disk_guid"`
FirstUsableLBA uint64 `json:"first_usable_lba"`
LastUsableLBA uint64 `json:"last_usable_lba"`
AlternateLBA uint64 `json:"alternate_lba"` // backup header location
Partitions []Partition `json:"partitions"`
// AuxRegions (#149, MBR only): structural sectors OUTSIDE PrimaryRegion
// and all partitions — the EBR chain lives in inter-partition gaps and
// must restore verbatim or logical partitions vanish.
AuxRegions []Range `json:"aux_regions,omitempty"`
// PrimaryRegion covers LBA0 through the end of the primary partition entry
// array (protective MBR + primary header + entries): captured verbatim so a
// restore reproduces boot-relevant metadata byte-exactly.
PrimaryRegion Range `json:"primary_region"`
// BackupRegion covers the backup entry array + backup header at the end of
// the disk.
BackupRegion Range `json:"backup_region"`
}
DiskLayout is a parsed GPT disk.
func Parse ¶
func Parse(r io.ReaderAt, diskSize int64) (*DiskLayout, error)
Parse reads and validates a GPT layout from r. diskSize is the device/image size in bytes. The sector size is auto-detected (512 and 4096 probed) by locating a valid primary header; pass an explicit size via ParseWithSector when known.
func ParseWithSector ¶
ParseWithSector parses a GPT with a known sector size.
func (*DiskLayout) FindPartitionAt ¶
func (l *DiskLayout) FindPartitionAt(off int64) (Partition, bool)
FindPartitionAt returns the partition covering the given byte offset, if any.
func (*DiskLayout) VerifyBackupHeader ¶
func (l *DiskLayout) VerifyBackupHeader(r io.ReaderAt) error
VerifyBackupHeader cross-checks that the backup GPT header at AlternateLBA is present, valid, and agrees with the primary (same disk GUID). Damaged backup headers are common on cloned disks; callers decide whether to warn or fail.
type FitOptions ¶ added in v0.2.0
type FitOptions struct {
// Grow extends the last data partition into the space a larger target
// has beyond the captured layout.
Grow bool
// MoveRecoveryToEnd lets partitions that FOLLOW the last data partition
// (a Windows Recovery partition, typically) be moved to the end of the
// larger target so the data partition can grow; without it, growth is
// blocked and reported.
MoveRecoveryToEnd bool
// Realign moves every partition to a 1 MiB (or physical-sector) boundary.
// Off, only partitions the plan moves anyway are placed aligned; others
// keep their captured position and are reported when misaligned.
Realign bool
// MinSize, when set, answers "how small can this partition's filesystem
// go" in bytes (volumefs.MinimumSize). nil means unknown: a shrink is
// planned to whatever size fits and WARNED as unconfirmed.
MinSize func(p Partition) (minBytes int64, known bool)
}
FitOptions are the operator's choices.
type FitPlan ¶ added in v0.2.0
type FitPlan struct {
Scheme string
SectorSize int
TargetSize int64
NewLastUsableLBA uint64
Partitions []PlannedPartition // in disk order
Warnings []string // things the operator should know; the plan still applies
Refusals []string // reasons the plan MUST NOT be applied; empty means applicable
}
FitPlan is PlanFit's answer.
func PlanFit ¶ added in v0.2.0
func PlanFit(l *DiskLayout, tg TargetGeometry, opts FitOptions) (*FitPlan, error)
PlanFit fits l onto tg. It returns a plan whose Refusals say why it must not be applied, or whose Partitions say where everything lands. An error is only for inputs that are not a layout at all.
func (*FitPlan) Applicable ¶ added in v0.2.0
Applicable reports whether the plan may be applied.
type GUID ¶
type GUID [16]byte
GUID is a 16-byte GPT GUID in on-disk (mixed-endian) order: the first three fields are little-endian, the last two big-endian — so the canonical string form requires the byte swaps below (UEFI spec appendix A / RFC 4122).
type MachineManifest ¶
type MachineManifest struct {
Version int `json:"version"`
MachineID string `json:"machine_id"` // stable per machine (agent/host identity)
Hostname string `json:"hostname"`
OS string `json:"os"`
CreatedAt time.Time `json:"created_at"`
Disks []DiskCapture `json:"disks"`
}
MachineManifest groups one machine snapshot: every disk captured together, with identity for the recovery flow ("list machines → pick snapshot").
func LoadMachineManifest ¶
func LoadMachineManifest(repoPath, snapshotID string) (*MachineManifest, error)
LoadMachineManifest reads and validates a machine snapshot manifest.
func UnmarshalMachineManifest ¶
func UnmarshalMachineManifest(data []byte) (*MachineManifest, error)
UnmarshalMachineManifest decodes and validates an envelope-wrapped manifest.
type MemberKind ¶
type MemberKind string
MemberKind says how a partition's content was captured.
const ( // MemberVolume: the partition holds a filesystem backed up through the // normal volume pipeline (VSS on Windows) — content addressed by BackupID. MemberVolume MemberKind = "volume" // MemberRaw: the partition (ESP, MSR, unrecognized) was captured as raw // ranged reads of the disk — content addressed by BackupID of a raw-range // backup whose stream is exactly the partition bytes. MemberRaw MemberKind = "raw" // MemberSkipped: deliberately not captured (e.g. swap); restored as zeros. MemberSkipped MemberKind = "skipped" )
type Partition ¶
type Partition struct {
Index int `json:"index"` // 0-based slot in the entry array
TypeGUID string `json:"type_guid,omitempty"`
TypeName string `json:"type_name"`
PartGUID string `json:"part_guid,omitempty"`
Name string `json:"name,omitempty"` // UTF-16LE name, decoded (GPT)
FirstLBA uint64 `json:"first_lba"`
LastLBA uint64 `json:"last_lba"` // inclusive, per spec
Attributes uint64 `json:"attributes,omitempty"`
// MBR fields (#149): set when the disk's Scheme is "mbr".
MBRType byte `json:"mbr_type,omitempty"`
Bootable bool `json:"bootable,omitempty"`
}
Partition is one in-use GPT partition entry.
type PartitionMember ¶
type PartitionMember struct {
Index int `json:"index"` // GPT entry index (matches DiskLayout.Partitions)
Kind MemberKind `json:"kind"`
BackupID string `json:"backup_id,omitempty"` // empty for skipped
Reason string `json:"reason,omitempty"` // for skipped: why
}
PartitionMember maps one partition of a captured disk to its backing backup.
type PlannedPartition ¶ added in v0.2.0
type PlannedPartition struct {
Index int // slot in the entry array, as in Partition.Index
TypeName string // for messages
Name string
OldFirst uint64
OldLast uint64
NewFirst uint64
NewLast uint64
Shrink bool
Grow bool
Moved bool
MinBytes int64 // filesystem minimum the shrink was planned against; 0 = unknown
}
PlannedPartition is one partition's place on the target.
func (PlannedPartition) NewBytes ¶ added in v0.2.0
func (p PlannedPartition) NewBytes(ss int) int64
func (PlannedPartition) OldBytes ¶ added in v0.2.0
func (p PlannedPartition) OldBytes(ss int) int64
OldBytes and NewBytes are the partition's byte sizes before and after.
type TargetGeometry ¶ added in v0.2.0
type TargetGeometry struct {
Size int64 // bytes
LogicalSector int // 512 or 4096; 0 = assume the captured layout's
PhysicalSector int // 512 or 4096 (512e drives: logical 512, physical 4096); 0 = unknown
}
TargetGeometry describes the drive a layout is being fitted onto.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package gpttest builds synthetic, spec-valid GPT disk images for tests (correct header/entry CRCs, protective MBR, backup structures).
|
Package gpttest builds synthetic, spec-valid GPT disk images for tests (correct header/entry CRCs, protective MBR, backup structures). |