package devicepath 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{} }, hdPrefix: func() DevicePathNode { return &HardDriveDevicePath{} }, filePrefix: func() DevicePathNode { return &FileDevicePath{} }, macPrefix: func() DevicePathNode { return &MacDevicePath{} }, ipv4Prefix: func() DevicePathNode { return &Ipv4DevicePath{} }, } 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 } 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 }