2023-08-27 09:31:03 +00:00
|
|
|
package devicepath
|
|
|
|
|
2023-08-27 13:09:30 +00:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrUnknownSubType = errors.New("unknown device sub-type")
|
|
|
|
ErrMalformedString = errors.New("malformed device string")
|
|
|
|
)
|
|
|
|
|
|
|
|
type ErrInvalidArguments struct {
|
|
|
|
subErr error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ErrInvalidArguments) Error() string {
|
|
|
|
return fmt.Sprintf("invalid argument: %s", e.subErr.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
type ErrInvalidPath struct {
|
|
|
|
subErr error
|
|
|
|
node string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ErrInvalidPath) Error() string {
|
|
|
|
return fmt.Sprintf("invalid device path on section %q: %s", e.node, e.subErr.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
type nodeGenerator func() DevicePathNode
|
|
|
|
|
|
|
|
var prefixTypeAssociation = map[string]nodeGenerator{
|
|
|
|
sataPrefix: func() DevicePathNode { return &SataDevicePath{} },
|
|
|
|
pciPrefix: func() DevicePathNode { return &PCIDevicePath{} },
|
|
|
|
pciRootPrefix: func() DevicePathNode { return &PCIRootDevicePath{} },
|
2023-09-16 15:00:46 +00:00
|
|
|
hdPrefix: func() DevicePathNode { return &HardDriveDevicePath{} },
|
2023-08-27 13:09:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func Parsenode(raw string) (DevicePathNode, error) {
|
|
|
|
prefix := getPrefix(raw)
|
|
|
|
devGen, ok := prefixTypeAssociation[prefix]
|
|
|
|
if !ok {
|
|
|
|
return nil, ErrUnknownSubType
|
|
|
|
}
|
|
|
|
dev := devGen()
|
|
|
|
if err := dev.ParseString(raw); err != nil {
|
|
|
|
return nil, &ErrInvalidArguments{subErr: err}
|
|
|
|
}
|
|
|
|
return dev, nil
|
2023-08-27 09:31:03 +00:00
|
|
|
}
|
|
|
|
|
2023-08-27 13:09:30 +00:00
|
|
|
func ParseDevicePath(raw string) (*DevicePath, error) {
|
|
|
|
dp := DevicePath{}
|
|
|
|
for _, nodeStr := range strings.Split(raw, "/") {
|
|
|
|
node, err := Parsenode(nodeStr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, &ErrInvalidPath{subErr: err, node: nodeStr}
|
|
|
|
}
|
|
|
|
if err := dp.PushNode(node); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dp.PushNode(&FinalDevicePath{})
|
|
|
|
return &dp, nil
|
2023-08-27 09:31:03 +00:00
|
|
|
}
|