package devicepath import ( "errors" "fmt" "strconv" "strings" "github.com/google/uuid" ) const ( hdLength uint16 = 2 hdPrefix string = "HD" ) func signatureTypeToStr(val uint8) string { switch val { case 1: return "MBR" default: return "GPT" } } func formatSignature(signature [16]byte, signatureType uint8) string { switch signatureType { case 1: // MBR return fmt.Sprintf("%x", signature[:4]) // only stored on the first 4 bytes default: // default is GPT parsedUID, _ := uuid.FromBytes(signature[:]) return parsedUID.String() } } type HardDriveDevicePath struct { partitionNumber uint32 partitionStart uint64 partitionSize uint64 partitionSignature [16]byte // partitionFormat uint8 signatureType uint8 } func (hp *HardDriveDevicePath) Type() DeviceNodeType { return MediaDevicePath } func (hp *HardDriveDevicePath) SubType() DeviceNodeSubType { return HardDriveSubType } func (hp *HardDriveDevicePath) String() string { return fmt.Sprintf("%s(%d,%s,%s,0x%x,0x%x)", hdPrefix, hp.partitionNumber, signatureTypeToStr(hp.signatureType), formatSignature(hp.partitionSignature, hp.signatureType), hp.partitionStart, hp.partitionSize) } func (hp *HardDriveDevicePath) ParseString(raw string) error { if !checkStringFormat(raw, hdPrefix, -1) { return ErrMalformedString } args := strings.Split(raw[len(hdPrefix)+1:len(raw)-1], ",") if len(args) != 5 { return errors.New("unexpected number of arguments") } if partNumber, err := strconv.ParseUint(args[0], 10, 32); err != nil { return err } else { hp.partitionNumber = uint32(partNumber) } switch args[1] { case "MBR": return errors.New("MBR partitions not yet supported") default: hp.signatureType = 2 } if uid, err := uuid.Parse(args[2]); err != nil { return err } else { if dat, err := uid.MarshalBinary(); err != nil { return err } else { hp.partitionSignature = [16]byte(dat) } } if start, err := strconv.ParseUint(args[3], 0, 64); err != nil { return err } else { hp.partitionStart = start } if size, err := strconv.ParseUint(args[4], 0, 64); err != nil { return err } else { hp.partitionSize = size } return nil }