mirror of
https://github.com/kairos-io/kcrypt.git
synced 2025-04-28 03:30:07 +00:00
135 lines
3.5 KiB
Go
135 lines
3.5 KiB
Go
package partition_info
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/jaypipes/ghw/pkg/block"
|
|
"github.com/pkg/errors"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
const DefaultPartitionInfoFile = "/oem/partition_info.yaml"
|
|
|
|
// PartitionInfo maps a partition label to a partition UUID.
|
|
// It's used in order to be able to ask the kcrypt-challenger for the passphrase
|
|
// using the partition label, even when the label is not accessible (e.g. before
|
|
// decrypting the partition). The UUID can be used to lookup the partition label
|
|
// and make the request.
|
|
type PartitionInfo struct {
|
|
file string
|
|
mapping map[string]string
|
|
}
|
|
|
|
// NewPartitionInfoFromFile reads the given partition info file (if one exists)
|
|
// and returns a pointer to a PartitionInfo object.
|
|
// If a file doesn't exist, the function will create one and return an "empty"
|
|
// PartitionInfo object.
|
|
// The boolean return value indicates whether a file existed or not (true means,
|
|
// a file existed already).
|
|
func NewPartitionInfoFromFile(file string) (*PartitionInfo, bool, error) {
|
|
existed, err := createInfoFileIfNotExists(file)
|
|
if err != nil {
|
|
return nil, existed, err
|
|
}
|
|
|
|
mapping, err := ParsePartitionInfoFile(file)
|
|
if err != nil {
|
|
return nil, existed, err
|
|
}
|
|
|
|
return &PartitionInfo{
|
|
file: file,
|
|
mapping: mapping,
|
|
}, existed, nil
|
|
}
|
|
|
|
func (pi PartitionInfo) LookupUUIDForLabel(l string) string {
|
|
return pi.mapping[l]
|
|
}
|
|
|
|
func (pi PartitionInfo) LookupLabelForUUID(uuid string) string {
|
|
for k, v := range pi.mapping {
|
|
if v == uuid {
|
|
return k
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// UpdatePartitionLabelMapping takes partition information as a string argument
|
|
// the the form: `label:name:uuid` (that's what the `kcrypt encrypt` command returns
|
|
// on success. This function stores it in the PartitionInfoFile yaml file for
|
|
// later use.
|
|
func (pi PartitionInfo) UpdateMapping(partitionData string) error {
|
|
label, uuid := PartitionDataFromString(partitionData)
|
|
pi.mapping[label] = uuid
|
|
|
|
return pi.save()
|
|
}
|
|
|
|
func (pi PartitionInfo) IsMappingNil() bool {
|
|
return pi.mapping == nil
|
|
}
|
|
|
|
func (pi PartitionInfo) save() error {
|
|
data, err := yaml.Marshal(&pi.mapping)
|
|
if err != nil {
|
|
return errors.Wrap(err, "marshalling the new partition info to yaml")
|
|
}
|
|
err = ioutil.WriteFile(pi.file, data, 0)
|
|
if err != nil {
|
|
return errors.Wrap(err, "writing back the partition info file")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func PartitionToString(p *block.Partition) string {
|
|
return fmt.Sprintf("%s:%s:%s", p.Label, p.Name, p.UUID)
|
|
}
|
|
|
|
// Takes a partition info string (as returned by PartitionToString) and return
|
|
// the partition label and the UUID
|
|
func PartitionDataFromString(partitionStr string) (string, string) {
|
|
parts := strings.Split(partitionStr, ":")
|
|
|
|
return parts[0], parts[2]
|
|
}
|
|
|
|
func ParsePartitionInfoFile(file string) (map[string]string, error) {
|
|
var result map[string]string
|
|
|
|
yamlFile, err := ioutil.ReadFile(file)
|
|
if err != nil {
|
|
return result, errors.Wrap(err, "reading the partition info file")
|
|
}
|
|
|
|
err = yaml.Unmarshal(yamlFile, &result)
|
|
if err != nil {
|
|
return result, errors.Wrap(err, "unmarshalling partition info file")
|
|
}
|
|
if result == nil {
|
|
result = map[string]string{}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// createInfoFileIfNotExists returns true if file already exists or creates the
|
|
// the file if it doesn't exist and returns false.
|
|
func createInfoFileIfNotExists(fileName string) (bool, error) {
|
|
_, err := os.Stat(fileName)
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
if _, err := os.Create(fileName); err != nil {
|
|
return false, err
|
|
}
|
|
return false, nil
|
|
} else if err != nil {
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|