Logical Volume Manager version 2: Go parsing library

Building a test file

dd if=/dev/zero of=image.img bs=512 count=$(( 4 * 1024 * 2 ))
sudo losetup /dev/loop1 image.img
sudo pvcreate /dev/loop1
sudo vgcreate vg_test /dev/loop1
sudo lvcreate --name lv_test1 vg_test
sudo losetup -d /dev/loop1

Application

["linux", "grub2", "lvm tools", "libvslvm"]

KS implementation details

References

This page hosts a formal specification of Logical Volume Manager version 2 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 Logical Volume Manager version 2

lvm2.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"
	"bytes"
	"io"
)


/**
 * ### Building a test file
 * 
 * ```
 * dd if=/dev/zero of=image.img bs=512 count=$(( 4 * 1024 * 2 ))
 * sudo losetup /dev/loop1 image.img
 * sudo pvcreate /dev/loop1
 * sudo vgcreate vg_test /dev/loop1
 * sudo lvcreate --name lv_test1 vg_test
 * sudo losetup -d /dev/loop1
 * ```
 * @see <a href="https://github.com/libyal/libvslvm/blob/main/documentation/Logical%20Volume%20Manager%20(LVM)%20format.asciidoc">Source</a>
 */
type Lvm2 struct {
	Pv *Lvm2_PhysicalVolume
	_io *kaitai.Stream
	_root *Lvm2
	_parent kaitai.Struct
	_f_sectorSize bool
	sectorSize int
}
func NewLvm2() *Lvm2 {
	return &Lvm2{
	}
}

func (this Lvm2) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp1 := NewLvm2_PhysicalVolume()
	err = tmp1.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Pv = tmp1
	return err
}
func (this *Lvm2) SectorSize() (v int, err error) {
	if (this._f_sectorSize) {
		return this.sectorSize, nil
	}
	this._f_sectorSize = true
	this.sectorSize = int(512)
	return this.sectorSize, nil
}

/**
 * Physical volume
 */
type Lvm2_PhysicalVolume struct {
	EmptySector []byte
	Label *Lvm2_PhysicalVolume_Label
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2
}
func NewLvm2_PhysicalVolume() *Lvm2_PhysicalVolume {
	return &Lvm2_PhysicalVolume{
	}
}

func (this Lvm2_PhysicalVolume) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp2, err := this._root.SectorSize()
	if err != nil {
		return err
	}
	tmp3, err := this._io.ReadBytes(int(tmp2))
	if err != nil {
		return err
	}
	tmp3 = tmp3
	this.EmptySector = tmp3
	tmp4 := NewLvm2_PhysicalVolume_Label()
	err = tmp4.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Label = tmp4
	return err
}
type Lvm2_PhysicalVolume_Label struct {
	LabelHeader *Lvm2_PhysicalVolume_Label_LabelHeader
	VolumeHeader *Lvm2_PhysicalVolume_Label_VolumeHeader
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume
}
func NewLvm2_PhysicalVolume_Label() *Lvm2_PhysicalVolume_Label {
	return &Lvm2_PhysicalVolume_Label{
	}
}

func (this Lvm2_PhysicalVolume_Label) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp5 := NewLvm2_PhysicalVolume_Label_LabelHeader()
	err = tmp5.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.LabelHeader = tmp5
	tmp6 := NewLvm2_PhysicalVolume_Label_VolumeHeader()
	err = tmp6.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.VolumeHeader = tmp6
	return err
}
type Lvm2_PhysicalVolume_Label_LabelHeader struct {
	Signature []byte
	SectorNumber uint64
	Checksum uint32
	LabelHeader *Lvm2_PhysicalVolume_Label_LabelHeader_LabelHeader
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label
}
func NewLvm2_PhysicalVolume_Label_LabelHeader() *Lvm2_PhysicalVolume_Label_LabelHeader {
	return &Lvm2_PhysicalVolume_Label_LabelHeader{
	}
}

func (this Lvm2_PhysicalVolume_Label_LabelHeader) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp7, err := this._io.ReadBytes(int(8))
	if err != nil {
		return err
	}
	tmp7 = tmp7
	this.Signature = tmp7
	if !(bytes.Equal(this.Signature, []uint8{76, 65, 66, 69, 76, 79, 78, 69})) {
		return kaitai.NewValidationNotEqualError([]uint8{76, 65, 66, 69, 76, 79, 78, 69}, this.Signature, this._io, "/types/physical_volume/types/label/types/label_header/seq/0")
	}
	tmp8, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.SectorNumber = uint64(tmp8)
	tmp9, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Checksum = uint32(tmp9)
	tmp10 := NewLvm2_PhysicalVolume_Label_LabelHeader_LabelHeader()
	err = tmp10.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.LabelHeader = tmp10
	return err
}

/**
 * The sector number of the physical volume label header
 */

/**
 * CRC-32 for offset 20 to end of the physical volume label sector
 */
type Lvm2_PhysicalVolume_Label_LabelHeader_LabelHeader struct {
	DataOffset uint32
	TypeIndicator []byte
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label_LabelHeader
}
func NewLvm2_PhysicalVolume_Label_LabelHeader_LabelHeader() *Lvm2_PhysicalVolume_Label_LabelHeader_LabelHeader {
	return &Lvm2_PhysicalVolume_Label_LabelHeader_LabelHeader{
	}
}

func (this Lvm2_PhysicalVolume_Label_LabelHeader_LabelHeader) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp11, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.DataOffset = uint32(tmp11)
	tmp12, err := this._io.ReadBytes(int(8))
	if err != nil {
		return err
	}
	tmp12 = tmp12
	this.TypeIndicator = tmp12
	if !(bytes.Equal(this.TypeIndicator, []uint8{76, 86, 77, 50, 32, 48, 48, 49})) {
		return kaitai.NewValidationNotEqualError([]uint8{76, 86, 77, 50, 32, 48, 48, 49}, this.TypeIndicator, this._io, "/types/physical_volume/types/label/types/label_header/types/label_header_/seq/1")
	}
	return err
}

/**
 * The offset, in bytes, relative from the start of the physical volume label header where data is stored
 */
type Lvm2_PhysicalVolume_Label_VolumeHeader struct {
	Id string
	Size uint64
	DataAreaDescriptors []*Lvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor
	MetadataAreaDescriptors []*Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label
}
func NewLvm2_PhysicalVolume_Label_VolumeHeader() *Lvm2_PhysicalVolume_Label_VolumeHeader {
	return &Lvm2_PhysicalVolume_Label_VolumeHeader{
	}
}

func (this Lvm2_PhysicalVolume_Label_VolumeHeader) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp13, err := this._io.ReadBytes(int(32))
	if err != nil {
		return err
	}
	tmp13 = tmp13
	this.Id = string(tmp13)
	tmp14, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Size = uint64(tmp14)
	for i := 1;; i++ {
		tmp15 := NewLvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor()
		err = tmp15.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		_it := tmp15
		this.DataAreaDescriptors = append(this.DataAreaDescriptors, _it)
		if  ((_it.Size != 0) && (_it.Offset != 0))  {
			break
		}
	}
	for i := 1;; i++ {
		tmp16 := NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor()
		err = tmp16.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		_it := tmp16
		this.MetadataAreaDescriptors = append(this.MetadataAreaDescriptors, _it)
		if  ((_it.Size != 0) && (_it.Offset != 0))  {
			break
		}
	}
	return err
}

/**
 * Contains a UUID stored as an ASCII string. The physical volume identifier can be used to uniquely identify a physical volume. The physical volume identifier is stored as: 9LBcEB7PQTGIlLI0KxrtzrynjuSL983W but is equivalent to its formatted variant: 9LBcEB-7PQT-GIlL-I0Kx-rtzr-ynju-SL983W, which is used in the metadata.
 */

/**
 * Physical Volume size. Value in bytes
 */

/**
 * The last descriptor in the list is terminator and consists of 0-byte values.
 */
type Lvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor struct {
	Offset uint64
	Size uint64
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label_VolumeHeader
	_f_data bool
	data string
}
func NewLvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor() *Lvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor {
	return &Lvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor{
	}
}

func (this Lvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp17, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Offset = uint64(tmp17)
	tmp18, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Size = uint64(tmp18)
	return err
}
func (this *Lvm2_PhysicalVolume_Label_VolumeHeader_DataAreaDescriptor) Data() (v string, err error) {
	if (this._f_data) {
		return this.data, nil
	}
	this._f_data = true
	if (this.Size != 0) {
		_pos, err := this._io.Pos()
		if err != nil {
			return "", err
		}
		_, err = this._io.Seek(int64(this.Offset), io.SeekStart)
		if err != nil {
			return "", err
		}
		tmp19, err := this._io.ReadBytes(int(this.Size))
		if err != nil {
			return "", err
		}
		tmp19 = tmp19
		this.data = string(tmp19)
		_, err = this._io.Seek(_pos, io.SeekStart)
		if err != nil {
			return "", err
		}
	}
	return this.data, nil
}

/**
 * The offset, in bytes, relative from the start of the physical volume
 */

/**
 * Value in bytes. Can be 0. [yellow-background]*Does this represent all remaining available space?*
 */

/**
 * According to `[REDHAT]` the metadata area is a circular buffer. New metadata is appended to the old metadata and then the pointer to the start of it is updated. The metadata area, therefore, can contain copies of older versions of the metadata.
 */
type Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea struct {
	Header *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor
}
func NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea() *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea {
	return &Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea{
	}
}

func (this Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp20 := NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader()
	err = tmp20.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Header = tmp20
	return err
}
type Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader struct {
	Checksum *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader
	Signature []byte
	Version uint32
	MetadataAreaOffset uint64
	MetadataAreaSize uint64
	RawLocationDescriptors []*Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor
	_io *kaitai.Stream
	_root *Lvm2
	_parent kaitai.Struct
	_f_metadata bool
	metadata []byte
}
func NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader() *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader {
	return &Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader{
	}
}

func (this Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp21 := NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader()
	err = tmp21.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Checksum = tmp21
	tmp22, err := this._io.ReadBytes(int(16))
	if err != nil {
		return err
	}
	tmp22 = tmp22
	this.Signature = tmp22
	if !(bytes.Equal(this.Signature, []uint8{32, 76, 86, 77, 50, 32, 120, 91, 53, 65, 37, 114, 48, 78, 42, 62})) {
		return kaitai.NewValidationNotEqualError([]uint8{32, 76, 86, 77, 50, 32, 120, 91, 53, 65, 37, 114, 48, 78, 42, 62}, this.Signature, this._io, "/types/physical_volume/types/label/types/volume_header/types/metadata_area/types/metadata_area_header/seq/1")
	}
	tmp23, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Version = uint32(tmp23)
	tmp24, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.MetadataAreaOffset = uint64(tmp24)
	tmp25, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.MetadataAreaSize = uint64(tmp25)
	for i := 1;; i++ {
		tmp26 := NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor()
		err = tmp26.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		_it := tmp26
		this.RawLocationDescriptors = append(this.RawLocationDescriptors, _it)
		if  ((_it.Offset != 0) && (_it.Size != 0) && (_it.Checksum != 0))  {
			break
		}
	}
	return err
}
func (this *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader) Metadata() (v []byte, err error) {
	if (this._f_metadata) {
		return this.metadata, nil
	}
	this._f_metadata = true
	_pos, err := this._io.Pos()
	if err != nil {
		return nil, err
	}
	_, err = this._io.Seek(int64(this.MetadataAreaOffset), io.SeekStart)
	if err != nil {
		return nil, err
	}
	tmp27, err := this._io.ReadBytes(int(this.MetadataAreaSize))
	if err != nil {
		return nil, err
	}
	tmp27 = tmp27
	this.metadata = tmp27
	_, err = this._io.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	return this.metadata, nil
}

/**
 * CRC-32 for offset 4 to end of the metadata area header
 */

/**
 * The offset, in bytes, of the metadata area relative from the start of the physical volume
 */

/**
 * The last descriptor in the list is terminator and consists of 0-byte values.
 */

/**
 * The data area size can be 0. It is assumed it represents the remaining  available data.
 */

type Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags int
const (
	Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags__RawLocationIgnored Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags = 1
)
var values_Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags = map[Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags]struct{}{1: {}}
func (v Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags) isDefined() bool {
	_, ok := values_Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags[v]
	return ok
}
type Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor struct {
	Offset uint64
	Size uint64
	Checksum uint32
	Flags Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader
}
func NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor() *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor {
	return &Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor{
	}
}

func (this Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp28, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Offset = uint64(tmp28)
	tmp29, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Size = uint64(tmp29)
	tmp30, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Checksum = uint32(tmp30)
	tmp31, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Flags = Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea_MetadataAreaHeader_RawLocationDescriptor_RawLocationDescriptorFlags(tmp31)
	return err
}

/**
 * The data area offset, in bytes, relative from the start of the metadata area
 */

/**
 * data area size in bytes
 */

/**
 * CRC-32 of *TODO (metadata?)*
 */
type Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor struct {
	Offset uint64
	Size uint64
	_io *kaitai.Stream
	_root *Lvm2
	_parent *Lvm2_PhysicalVolume_Label_VolumeHeader
	_raw_data []byte
	_f_data bool
	data *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea
}
func NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor() *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor {
	return &Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor{
	}
}

func (this Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor) IO_() *kaitai.Stream {
	return this._io
}

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

	tmp32, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Offset = uint64(tmp32)
	tmp33, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.Size = uint64(tmp33)
	return err
}
func (this *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataAreaDescriptor) Data() (v *Lvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea, err error) {
	if (this._f_data) {
		return this.data, nil
	}
	this._f_data = true
	if (this.Size != 0) {
		_pos, err := this._io.Pos()
		if err != nil {
			return nil, err
		}
		_, err = this._io.Seek(int64(this.Offset), io.SeekStart)
		if err != nil {
			return nil, err
		}
		tmp34, err := this._io.ReadBytes(int(this.Size))
		if err != nil {
			return nil, err
		}
		tmp34 = tmp34
		this._raw_data = tmp34
		_io__raw_data := kaitai.NewStream(bytes.NewReader(this._raw_data))
		tmp35 := NewLvm2_PhysicalVolume_Label_VolumeHeader_MetadataArea()
		err = tmp35.Read(_io__raw_data, this, this._root)
		if err != nil {
			return nil, err
		}
		this.data = tmp35
		_, err = this._io.Seek(_pos, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	return this.data, nil
}

/**
 * The offset, in bytes, relative from the start of the physical volume
 */

/**
 * Value in bytes
 */