Re-introduce the VolumeContainer interface but with a different meaning: it is supposed to be implemented by all container that contain volumes and as a result have themselves a size, like eg LVM2, LUKS2 and PartitionTable (the latter is not yet included). The sole method on the interface for now is MetadataSize, which should return the metadata for the container itself. Use that new `VolumeContainer.MetadataSize` method when we up- date the sizes of elements in `resizeEntitybranch`.
160 lines
5 KiB
Go
160 lines
5 KiB
Go
// Disk package contains abstract data-types to define disk-related entities.
|
|
//
|
|
// The disk package is a collection of interfaces and structs that can be used
|
|
// to represent an disk image with its layout. Various concrete types, such as
|
|
// PartitionTable, Partition and Filesystem types are defined to model a given
|
|
// disk layout. These implement a collection of interfaces that can be used to
|
|
// navigate and operate on the various possible combinations of entities in a
|
|
// generic way. The entity data model is very generic so that it can represent
|
|
// all possible layouts, which can be arbitrarily complex, since technologies
|
|
// like logical volume management, LUKS2 container and file systems, that can
|
|
// have sub-volumes, allow for complex layouts.
|
|
// Entity and Container are the two main interfaces that are used to model the
|
|
// tree structure of a disk image layout. The other entity interfaces, such as
|
|
// Sizeable and Mountable, then describe various properties and capabilities
|
|
// of a given entity.
|
|
|
|
package disk
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"io"
|
|
"math/rand"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
const (
|
|
// Default sector size in bytes
|
|
DefaultSectorSize = 512
|
|
|
|
DefaultGrainBytes = uint64(1048576) // 1 MiB
|
|
|
|
// UUIDs
|
|
BIOSBootPartitionGUID = "21686148-6449-6E6F-744E-656564454649"
|
|
BIOSBootPartitionUUID = "FAC7F1FB-3E8D-4137-A512-961DE09A5549"
|
|
|
|
FilesystemDataGUID = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
|
|
FilesystemDataUUID = "CB07C243-BC44-4717-853E-28852021225B"
|
|
|
|
EFISystemPartitionGUID = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
|
|
EFISystemPartitionUUID = "68B2905B-DF3E-4FB3-80FA-49D1E773AA33"
|
|
EFIFilesystemUUID = "7B77-95E7"
|
|
|
|
LVMPartitionGUID = "E6D6D379-F507-44C2-A23C-238F2A3DF928"
|
|
PRePartitionGUID = "9E1A2D38-C612-4316-AA26-8B49521E5A8B"
|
|
|
|
RootPartitionUUID = "6264D520-3FB9-423F-8AB8-7A0A8E3D3562"
|
|
)
|
|
|
|
// Entity is the base interface for all disk-related entities.
|
|
type Entity interface {
|
|
// IsContainer indicates if the implementing type can
|
|
// contain any other entities.
|
|
IsContainer() bool
|
|
|
|
// Clone returns a deep copy of the entity.
|
|
Clone() Entity
|
|
}
|
|
|
|
// Container is the interface for entities that can contain other entities.
|
|
// Together with the base Entity interface this allows to model a generic
|
|
// entity tree of theoretically arbitrary depth and width.
|
|
type Container interface {
|
|
Entity
|
|
|
|
// GetItemCount returns the number of actual child entities.
|
|
GetItemCount() uint
|
|
|
|
// GetChild returns the child entity at the given index.
|
|
GetChild(n uint) Entity
|
|
}
|
|
|
|
// Sizeable is implemented by entities that carry size information.
|
|
type Sizeable interface {
|
|
// EnsureSize will resize the entity to the given size in case
|
|
// it is currently smaller. Returns if the size was changed.
|
|
EnsureSize(size uint64) bool
|
|
|
|
// GetSize returns the size of the entity in bytes.
|
|
GetSize() uint64
|
|
}
|
|
|
|
// A Mountable entity is an entity that can be mounted.
|
|
type Mountable interface {
|
|
|
|
// GetMountPoint returns the path of the mount point.
|
|
GetMountpoint() string
|
|
|
|
// GetFSType returns the file system type, e.g. 'xfs'.
|
|
GetFSType() string
|
|
|
|
// GetFSSpec returns the file system spec information.
|
|
GetFSSpec() FSSpec
|
|
|
|
// GetFSTabOptions returns options for mounting the entity.
|
|
GetFSTabOptions() FSTabOptions
|
|
}
|
|
|
|
// A MountpointCreator is a container that is able to create new volumes.
|
|
//
|
|
// CreateMountpoint creates a new mountpoint with the given size and
|
|
// returns the entity that represents the new mountpoint.
|
|
type MountpointCreator interface {
|
|
CreateMountpoint(mountpoint string, size uint64) (Entity, error)
|
|
}
|
|
|
|
// A UniqueEntity is an entity that can be uniquely identified via a UUID.
|
|
//
|
|
// GenUUID generates a UUID for the entity if it does not yet have one.
|
|
type UniqueEntity interface {
|
|
Entity
|
|
GenUUID(rng *rand.Rand)
|
|
}
|
|
|
|
// VolumeContainer is a specific container that contains volume entities
|
|
type VolumeContainer interface {
|
|
|
|
// MetadataSize returns the size of the container's metadata (in
|
|
// bytes), i.e. the storage space that needs to be reserved for
|
|
// the container itself, in contrast to the data it contains.
|
|
MetadataSize() uint64
|
|
}
|
|
|
|
// FSSpec for a filesystem (UUID and Label); the first field of fstab(5)
|
|
type FSSpec struct {
|
|
UUID string
|
|
Label string
|
|
}
|
|
|
|
type FSTabOptions struct {
|
|
// The fourth field of fstab(5); fs_mntops
|
|
MntOps string
|
|
// The fifth field of fstab(5); fs_freq
|
|
Freq uint64
|
|
// The sixth field of fstab(5); fs_passno
|
|
PassNo uint64
|
|
}
|
|
|
|
// uuid generator helpers
|
|
|
|
// GeneratesnewRandomUUIDFromReader generates a new random UUID (version
|
|
// 4 using) via the given random number generator.
|
|
func newRandomUUIDFromReader(r io.Reader) (uuid.UUID, error) {
|
|
var id uuid.UUID
|
|
_, err := io.ReadFull(r, id[:])
|
|
if err != nil {
|
|
return uuid.Nil, err
|
|
}
|
|
id[6] = (id[6] & 0x0f) | 0x40 // Version 4
|
|
id[8] = (id[8] & 0x3f) | 0x80 // Variant is 10
|
|
return id, nil
|
|
}
|
|
|
|
// NewRandomVolIDFromReader creates a random 32 bit hex string to use as a
|
|
// volume ID for FAT filesystems
|
|
func NewRandomVolIDFromReader(r io.Reader) (string, error) {
|
|
volid := make([]byte, 4)
|
|
_, err := r.Read(volid)
|
|
return hex.EncodeToString(volid), err
|
|
}
|