GPT (GUID) partition table: Go parsing library

This page hosts a formal specification of GPT (GUID) partition table using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Go source code to parse GPT (GUID) partition table

gpt_partition_table.go

// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.

import (
	"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
	"io"
	"golang.org/x/text/encoding/unicode"
	"bytes"
)


/**
 * @see <a href="https://en.wikipedia.org/wiki/GUID_Partition_Table">Source</a>
 */
type GptPartitionTable struct {
	_io *kaitai.Stream
	_root *GptPartitionTable
	_parent interface{}
	_f_sectorSize bool
	sectorSize int
	_f_primary bool
	primary *GptPartitionTable_PartitionHeader
	_f_backup bool
	backup *GptPartitionTable_PartitionHeader
}
func NewGptPartitionTable() *GptPartitionTable {
	return &GptPartitionTable{
	}
}

func (this *GptPartitionTable) Read(io *kaitai.Stream, parent interface{}, root *GptPartitionTable) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	return err
}
func (this *GptPartitionTable) SectorSize() (v int, err error) {
	if (this._f_sectorSize) {
		return this.sectorSize, nil
	}
	this.sectorSize = int(512)
	this._f_sectorSize = true
	return this.sectorSize, nil
}
func (this *GptPartitionTable) Primary() (v *GptPartitionTable_PartitionHeader, err error) {
	if (this._f_primary) {
		return this.primary, nil
	}
	thisIo := this._root._io
	_pos, err := thisIo.Pos()
	if err != nil {
		return nil, err
	}
	tmp1, err := this._root.SectorSize()
	if err != nil {
		return nil, err
	}
	_, err = thisIo.Seek(int64(tmp1), io.SeekStart)
	if err != nil {
		return nil, err
	}
	tmp2 := NewGptPartitionTable_PartitionHeader()
	err = tmp2.Read(thisIo, this, this._root)
	if err != nil {
		return nil, err
	}
	this.primary = tmp2
	_, err = thisIo.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	this._f_primary = true
	this._f_primary = true
	return this.primary, nil
}
func (this *GptPartitionTable) Backup() (v *GptPartitionTable_PartitionHeader, err error) {
	if (this._f_backup) {
		return this.backup, nil
	}
	thisIo := this._root._io
	_pos, err := thisIo.Pos()
	if err != nil {
		return nil, err
	}
	tmp3, err := this._io.Size()
	if err != nil {
		return nil, err
	}
	tmp4, err := this._root.SectorSize()
	if err != nil {
		return nil, err
	}
	_, err = thisIo.Seek(int64((tmp3 - tmp4)), io.SeekStart)
	if err != nil {
		return nil, err
	}
	tmp5 := NewGptPartitionTable_PartitionHeader()
	err = tmp5.Read(thisIo, this, this._root)
	if err != nil {
		return nil, err
	}
	this.backup = tmp5
	_, err = thisIo.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	this._f_backup = true
	this._f_backup = true
	return this.backup, nil
}
type GptPartitionTable_PartitionEntry struct {
	TypeGuid []byte
	Guid []byte
	FirstLba uint64
	LastLba uint64
	Attributes uint64
	Name string
	_io *kaitai.Stream
	_root *GptPartitionTable
	_parent *GptPartitionTable_PartitionHeader
}
func NewGptPartitionTable_PartitionEntry() *GptPartitionTable_PartitionEntry {
	return &GptPartitionTable_PartitionEntry{
	}
}

func (this *GptPartitionTable_PartitionEntry) Read(io *kaitai.Stream, parent *GptPartitionTable_PartitionHeader, root *GptPartitionTable) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp6, err := this._io.ReadBytes(int(16))
	if err != nil {
		return err
	}
	tmp6 = tmp6
	this.TypeGuid = tmp6
	tmp7, err := this._io.ReadBytes(int(16))
	if err != nil {
		return err
	}
	tmp7 = tmp7
	this.Guid = tmp7
	tmp8, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.FirstLba = uint64(tmp8)
	tmp9, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.LastLba = uint64(tmp9)
	tmp10, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Attributes = uint64(tmp10)
	tmp11, err := this._io.ReadBytes(int(72))
	if err != nil {
		return err
	}
	tmp11 = tmp11
	tmp12, err := kaitai.BytesToStr(tmp11, unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder())
	if err != nil {
		return err
	}
	this.Name = tmp12
	return err
}
type GptPartitionTable_PartitionHeader struct {
	Signature []byte
	Revision uint32
	HeaderSize uint32
	Crc32Header uint32
	Reserved uint32
	CurrentLba uint64
	BackupLba uint64
	FirstUsableLba uint64
	LastUsableLba uint64
	DiskGuid []byte
	EntriesStart uint64
	EntriesCount uint32
	EntriesSize uint32
	Crc32Array uint32
	_io *kaitai.Stream
	_root *GptPartitionTable
	_parent *GptPartitionTable
	_raw_entries [][]byte
	_f_entries bool
	entries []*GptPartitionTable_PartitionEntry
}
func NewGptPartitionTable_PartitionHeader() *GptPartitionTable_PartitionHeader {
	return &GptPartitionTable_PartitionHeader{
	}
}

func (this *GptPartitionTable_PartitionHeader) Read(io *kaitai.Stream, parent *GptPartitionTable, root *GptPartitionTable) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp13, err := this._io.ReadBytes(int(8))
	if err != nil {
		return err
	}
	tmp13 = tmp13
	this.Signature = tmp13
	if !(bytes.Equal(this.Signature, []uint8{69, 70, 73, 32, 80, 65, 82, 84})) {
		return kaitai.NewValidationNotEqualError([]uint8{69, 70, 73, 32, 80, 65, 82, 84}, this.Signature, this._io, "/types/partition_header/seq/0")
	}
	tmp14, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Revision = uint32(tmp14)
	tmp15, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.HeaderSize = uint32(tmp15)
	tmp16, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Crc32Header = uint32(tmp16)
	tmp17, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Reserved = uint32(tmp17)
	tmp18, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.CurrentLba = uint64(tmp18)
	tmp19, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.BackupLba = uint64(tmp19)
	tmp20, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.FirstUsableLba = uint64(tmp20)
	tmp21, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.LastUsableLba = uint64(tmp21)
	tmp22, err := this._io.ReadBytes(int(16))
	if err != nil {
		return err
	}
	tmp22 = tmp22
	this.DiskGuid = tmp22
	tmp23, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.EntriesStart = uint64(tmp23)
	tmp24, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.EntriesCount = uint32(tmp24)
	tmp25, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.EntriesSize = uint32(tmp25)
	tmp26, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Crc32Array = uint32(tmp26)
	return err
}
func (this *GptPartitionTable_PartitionHeader) Entries() (v []*GptPartitionTable_PartitionEntry, err error) {
	if (this._f_entries) {
		return this.entries, nil
	}
	thisIo := this._root._io
	_pos, err := thisIo.Pos()
	if err != nil {
		return nil, err
	}
	tmp27, err := this._root.SectorSize()
	if err != nil {
		return nil, err
	}
	_, err = thisIo.Seek(int64((this.EntriesStart * tmp27)), io.SeekStart)
	if err != nil {
		return nil, err
	}
	for i := 0; i < int(this.EntriesCount); i++ {
		_ = i
		tmp28, err := thisIo.ReadBytes(int(this.EntriesSize))
		if err != nil {
			return nil, err
		}
		tmp28 = tmp28
		this._raw_entries = append(this._raw_entries, tmp28)
		_io__raw_entries := kaitai.NewStream(bytes.NewReader(this._raw_entries[i]))
		tmp29 := NewGptPartitionTable_PartitionEntry()
		err = tmp29.Read(_io__raw_entries, this, this._root)
		if err != nil {
			return nil, err
		}
		this.entries = append(this.entries, tmp29)
	}
	_, err = thisIo.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	this._f_entries = true
	this._f_entries = true
	return this.entries, nil
}