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.
// 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
}