mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-12-19 07:00:17 +01:00
33f99c4fc1
Uses godep to vendor dependencies. Godeps is not necessary during build, golang's new vendor support is used instead.
259 lines
6.2 KiB
Go
259 lines
6.2 KiB
Go
package dbus
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
byteType = reflect.TypeOf(byte(0))
|
|
boolType = reflect.TypeOf(false)
|
|
uint8Type = reflect.TypeOf(uint8(0))
|
|
int16Type = reflect.TypeOf(int16(0))
|
|
uint16Type = reflect.TypeOf(uint16(0))
|
|
int32Type = reflect.TypeOf(int32(0))
|
|
uint32Type = reflect.TypeOf(uint32(0))
|
|
int64Type = reflect.TypeOf(int64(0))
|
|
uint64Type = reflect.TypeOf(uint64(0))
|
|
float64Type = reflect.TypeOf(float64(0))
|
|
stringType = reflect.TypeOf("")
|
|
signatureType = reflect.TypeOf(Signature{""})
|
|
objectPathType = reflect.TypeOf(ObjectPath(""))
|
|
variantType = reflect.TypeOf(Variant{Signature{""}, nil})
|
|
interfacesType = reflect.TypeOf([]interface{}{})
|
|
unixFDType = reflect.TypeOf(UnixFD(0))
|
|
unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
|
|
)
|
|
|
|
// An InvalidTypeError signals that a value which cannot be represented in the
|
|
// D-Bus wire format was passed to a function.
|
|
type InvalidTypeError struct {
|
|
Type reflect.Type
|
|
}
|
|
|
|
func (e InvalidTypeError) Error() string {
|
|
return "dbus: invalid type " + e.Type.String()
|
|
}
|
|
|
|
// Store copies the values contained in src to dest, which must be a slice of
|
|
// pointers. It converts slices of interfaces from src to corresponding structs
|
|
// in dest. An error is returned if the lengths of src and dest or the types of
|
|
// their elements don't match.
|
|
func Store(src []interface{}, dest ...interface{}) error {
|
|
if len(src) != len(dest) {
|
|
return errors.New("dbus.Store: length mismatch")
|
|
}
|
|
|
|
for i := range src {
|
|
if err := store(src[i], dest[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func store(src, dest interface{}) error {
|
|
if reflect.TypeOf(dest).Elem() == reflect.TypeOf(src) {
|
|
reflect.ValueOf(dest).Elem().Set(reflect.ValueOf(src))
|
|
return nil
|
|
} else if hasStruct(dest) {
|
|
rv := reflect.ValueOf(dest).Elem()
|
|
switch rv.Kind() {
|
|
case reflect.Struct:
|
|
vs, ok := src.([]interface{})
|
|
if !ok {
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
t := rv.Type()
|
|
ndest := make([]interface{}, 0, rv.NumField())
|
|
for i := 0; i < rv.NumField(); i++ {
|
|
field := t.Field(i)
|
|
if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
|
|
ndest = append(ndest, rv.Field(i).Addr().Interface())
|
|
}
|
|
}
|
|
if len(vs) != len(ndest) {
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
err := Store(vs, ndest...)
|
|
if err != nil {
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
case reflect.Slice:
|
|
sv := reflect.ValueOf(src)
|
|
if sv.Kind() != reflect.Slice {
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
rv.Set(reflect.MakeSlice(rv.Type(), sv.Len(), sv.Len()))
|
|
for i := 0; i < sv.Len(); i++ {
|
|
if err := store(sv.Index(i).Interface(), rv.Index(i).Addr().Interface()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
case reflect.Map:
|
|
sv := reflect.ValueOf(src)
|
|
if sv.Kind() != reflect.Map {
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
keys := sv.MapKeys()
|
|
rv.Set(reflect.MakeMap(sv.Type()))
|
|
for _, key := range keys {
|
|
v := reflect.New(sv.Type().Elem())
|
|
if err := store(v, sv.MapIndex(key).Interface()); err != nil {
|
|
return err
|
|
}
|
|
rv.SetMapIndex(key, v.Elem())
|
|
}
|
|
default:
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
return nil
|
|
} else {
|
|
return errors.New("dbus.Store: type mismatch")
|
|
}
|
|
}
|
|
|
|
func hasStruct(v interface{}) bool {
|
|
t := reflect.TypeOf(v)
|
|
for {
|
|
switch t.Kind() {
|
|
case reflect.Struct:
|
|
return true
|
|
case reflect.Slice, reflect.Ptr, reflect.Map:
|
|
t = t.Elem()
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
// An ObjectPath is an object path as defined by the D-Bus spec.
|
|
type ObjectPath string
|
|
|
|
// IsValid returns whether the object path is valid.
|
|
func (o ObjectPath) IsValid() bool {
|
|
s := string(o)
|
|
if len(s) == 0 {
|
|
return false
|
|
}
|
|
if s[0] != '/' {
|
|
return false
|
|
}
|
|
if s[len(s)-1] == '/' && len(s) != 1 {
|
|
return false
|
|
}
|
|
// probably not used, but technically possible
|
|
if s == "/" {
|
|
return true
|
|
}
|
|
split := strings.Split(s[1:], "/")
|
|
for _, v := range split {
|
|
if len(v) == 0 {
|
|
return false
|
|
}
|
|
for _, c := range v {
|
|
if !isMemberChar(c) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// A UnixFD is a Unix file descriptor sent over the wire. See the package-level
|
|
// documentation for more information about Unix file descriptor passsing.
|
|
type UnixFD int32
|
|
|
|
// A UnixFDIndex is the representation of a Unix file descriptor in a message.
|
|
type UnixFDIndex uint32
|
|
|
|
// alignment returns the alignment of values of type t.
|
|
func alignment(t reflect.Type) int {
|
|
switch t {
|
|
case variantType:
|
|
return 1
|
|
case objectPathType:
|
|
return 4
|
|
case signatureType:
|
|
return 1
|
|
case interfacesType: // sometimes used for structs
|
|
return 8
|
|
}
|
|
switch t.Kind() {
|
|
case reflect.Uint8:
|
|
return 1
|
|
case reflect.Uint16, reflect.Int16:
|
|
return 2
|
|
case reflect.Uint32, reflect.Int32, reflect.String, reflect.Array, reflect.Slice, reflect.Map:
|
|
return 4
|
|
case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Struct:
|
|
return 8
|
|
case reflect.Ptr:
|
|
return alignment(t.Elem())
|
|
}
|
|
return 1
|
|
}
|
|
|
|
// isKeyType returns whether t is a valid type for a D-Bus dict.
|
|
func isKeyType(t reflect.Type) bool {
|
|
switch t.Kind() {
|
|
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
|
reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float64,
|
|
reflect.String:
|
|
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// isValidInterface returns whether s is a valid name for an interface.
|
|
func isValidInterface(s string) bool {
|
|
if len(s) == 0 || len(s) > 255 || s[0] == '.' {
|
|
return false
|
|
}
|
|
elem := strings.Split(s, ".")
|
|
if len(elem) < 2 {
|
|
return false
|
|
}
|
|
for _, v := range elem {
|
|
if len(v) == 0 {
|
|
return false
|
|
}
|
|
if v[0] >= '0' && v[0] <= '9' {
|
|
return false
|
|
}
|
|
for _, c := range v {
|
|
if !isMemberChar(c) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// isValidMember returns whether s is a valid name for a member.
|
|
func isValidMember(s string) bool {
|
|
if len(s) == 0 || len(s) > 255 {
|
|
return false
|
|
}
|
|
i := strings.Index(s, ".")
|
|
if i != -1 {
|
|
return false
|
|
}
|
|
if s[0] >= '0' && s[0] <= '9' {
|
|
return false
|
|
}
|
|
for _, c := range s {
|
|
if !isMemberChar(c) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isMemberChar(c rune) bool {
|
|
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
|
|
(c >= 'a' && c <= 'z') || c == '_'
|
|
}
|