Преглед на файлове

Merge pull request #22173 from amitkris/uprev_dbus

Update godbus/dbus to v4.0.0
Michael Crosby преди 9 години
родител
ревизия
24076ed4d9

+ 1 - 1
hack/vendor.sh

@@ -65,7 +65,7 @@ clone git github.com/opencontainers/specs 93ca97e83ca7fb4fba6d9e30d5470f99ddc02d
 clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
 clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
 clone git github.com/coreos/go-systemd v4
 clone git github.com/coreos/go-systemd v4
-clone git github.com/godbus/dbus v3
+clone git github.com/godbus/dbus v4.0.0
 clone git github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
 clone git github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
 clone git github.com/golang/protobuf 68415e7123da32b07eab49c96d2c4d6158360e9b
 clone git github.com/golang/protobuf 68415e7123da32b07eab49c96d2c4d6158360e9b
 
 

+ 25 - 16
vendor/src/github.com/godbus/dbus/conn.go

@@ -16,6 +16,7 @@ var (
 	systemBusLck  sync.Mutex
 	systemBusLck  sync.Mutex
 	sessionBus    *Conn
 	sessionBus    *Conn
 	sessionBusLck sync.Mutex
 	sessionBusLck sync.Mutex
+	sessionEnvLck sync.Mutex
 )
 )
 
 
 // ErrClosed is the error returned by calls on a closed connection.
 // ErrClosed is the error returned by calls on a closed connection.
@@ -46,7 +47,7 @@ type Conn struct {
 	calls    map[uint32]*Call
 	calls    map[uint32]*Call
 	callsLck sync.RWMutex
 	callsLck sync.RWMutex
 
 
-	handlers    map[ObjectPath]map[string]exportWithMapping
+	handlers    map[ObjectPath]map[string]exportedObj
 	handlersLck sync.RWMutex
 	handlersLck sync.RWMutex
 
 
 	out    chan *Message
 	out    chan *Message
@@ -91,6 +92,8 @@ func SessionBus() (conn *Conn, err error) {
 
 
 // SessionBusPrivate returns a new private connection to the session bus.
 // SessionBusPrivate returns a new private connection to the session bus.
 func SessionBusPrivate() (*Conn, error) {
 func SessionBusPrivate() (*Conn, error) {
+	sessionEnvLck.Lock()
+	defer sessionEnvLck.Unlock()
 	address := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
 	address := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
 	if address != "" && address != "autolaunch:" {
 	if address != "" && address != "autolaunch:" {
 		return Dial(address)
 		return Dial(address)
@@ -157,7 +160,7 @@ func newConn(tr transport) (*Conn, error) {
 	conn.transport = tr
 	conn.transport = tr
 	conn.calls = make(map[uint32]*Call)
 	conn.calls = make(map[uint32]*Call)
 	conn.out = make(chan *Message, 10)
 	conn.out = make(chan *Message, 10)
-	conn.handlers = make(map[ObjectPath]map[string]exportWithMapping)
+	conn.handlers = make(map[ObjectPath]map[string]exportedObj)
 	conn.nextSerial = 1
 	conn.nextSerial = 1
 	conn.serialUsed = map[uint32]bool{0: true}
 	conn.serialUsed = map[uint32]bool{0: true}
 	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
 	conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
@@ -499,9 +502,7 @@ func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
 // The caller has to make sure that ch is sufficiently buffered; if a message
 // The caller has to make sure that ch is sufficiently buffered; if a message
 // arrives when a write to c is not possible, it is discarded.
 // arrives when a write to c is not possible, it is discarded.
 //
 //
-// Multiple of these channels can be registered at the same time. Passing a
-// channel that already is registered will remove it from the list of the
-// registered channels.
+// Multiple of these channels can be registered at the same time.
 //
 //
 // These channels are "overwritten" by Eavesdrop; i.e., if there currently is a
 // These channels are "overwritten" by Eavesdrop; i.e., if there currently is a
 // channel for eavesdropped messages, this channel receives all signals, and
 // channel for eavesdropped messages, this channel receives all signals, and
@@ -512,6 +513,19 @@ func (conn *Conn) Signal(ch chan<- *Signal) {
 	conn.signalsLck.Unlock()
 	conn.signalsLck.Unlock()
 }
 }
 
 
+// RemoveSignal removes the given channel from the list of the registered channels.
+func (conn *Conn) RemoveSignal(ch chan<- *Signal) {
+	conn.signalsLck.Lock()
+	for i := len(conn.signals) - 1; i >= 0; i-- {
+		if ch == conn.signals[i] {
+			copy(conn.signals[i:], conn.signals[i+1:])
+			conn.signals[len(conn.signals)-1] = nil
+			conn.signals = conn.signals[:len(conn.signals)-1]
+		}
+	}
+	conn.signalsLck.Unlock()
+}
+
 // SupportsUnixFDs returns whether the underlying transport supports passing of
 // SupportsUnixFDs returns whether the underlying transport supports passing of
 // unix file descriptors. If this is false, method calls containing unix file
 // unix file descriptors. If this is false, method calls containing unix file
 // descriptors will return an error and emitted signals containing them will
 // descriptors will return an error and emitted signals containing them will
@@ -610,16 +624,11 @@ func dereferenceAll(vs []interface{}) []interface{} {
 
 
 // getKey gets a key from a the list of keys. Returns "" on error / not found...
 // getKey gets a key from a the list of keys. Returns "" on error / not found...
 func getKey(s, key string) string {
 func getKey(s, key string) string {
-	i := strings.Index(s, key)
-	if i == -1 {
-		return ""
-	}
-	if i+len(key)+1 >= len(s) || s[i+len(key)] != '=' {
-		return ""
-	}
-	j := strings.Index(s, ",")
-	if j == -1 {
-		j = len(s)
+	for _, keyEqualsValue := range strings.Split(s, ",") {
+		keyValue := strings.SplitN(keyEqualsValue, "=", 2)
+		if len(keyValue) == 2 && keyValue[0] == key {
+			return keyValue[1]
+		}
 	}
 	}
-	return s[i+len(key)+1 : j]
+	return ""
 }
 }

+ 5 - 1
vendor/src/github.com/godbus/dbus/conn_other.go

@@ -5,6 +5,7 @@ package dbus
 import (
 import (
 	"bytes"
 	"bytes"
 	"errors"
 	"errors"
+	"os"
 	"os/exec"
 	"os/exec"
 )
 )
 
 
@@ -23,5 +24,8 @@ func sessionBusPlatform() (*Conn, error) {
 		return nil, errors.New("dbus: couldn't determine address of session bus")
 		return nil, errors.New("dbus: couldn't determine address of session bus")
 	}
 	}
 
 
-	return Dial(string(b[i+1 : j]))
+	env, addr := string(b[0:i]), string(b[i+1:j])
+	os.Setenv(env, addr)
+
+	return Dial(addr)
 }
 }

+ 112 - 55
vendor/src/github.com/godbus/dbus/export.go

@@ -1,6 +1,7 @@
 package dbus
 package dbus
 
 
 import (
 import (
+	"bytes"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"reflect"
 	"reflect"
@@ -22,67 +23,60 @@ var (
 	}
 	}
 )
 )
 
 
-// exportWithMapping represents an exported struct along with a method name
-// mapping to allow for exporting lower-case methods, etc.
-type exportWithMapping struct {
-	export interface{}
-
-	// Method name mapping; key -> struct method, value -> dbus method.
-	mapping map[string]string
+// exportedObj represents an exported object. It stores a precomputed
+// method table that represents the methods exported on the bus.
+type exportedObj struct {
+	methods map[string]reflect.Value
 
 
 	// Whether or not this export is for the entire subtree
 	// Whether or not this export is for the entire subtree
 	includeSubtree bool
 	includeSubtree bool
 }
 }
 
 
+func (obj exportedObj) Method(name string) (reflect.Value, bool) {
+	out, exists := obj.methods[name]
+	return out, exists
+}
+
 // Sender is a type which can be used in exported methods to receive the message
 // Sender is a type which can be used in exported methods to receive the message
 // sender.
 // sender.
 type Sender string
 type Sender string
 
 
-func exportedMethod(export exportWithMapping, name string) reflect.Value {
-	if export.export == nil {
-		return reflect.Value{}
-	}
-
-	// If a mapping was included in the export, check the map to see if we
-	// should be looking for a different method in the export.
-	if export.mapping != nil {
-		for key, value := range export.mapping {
-			if value == name {
-				name = key
-				break
-			}
-
-			// Catch the case where a method is aliased but the client is calling
-			// the original, e.g. the "Foo" method was exported mapped to
-			// "foo," and dbus client called the original "Foo."
-			if key == name {
-				return reflect.Value{}
-			}
-		}
+func computeMethodName(name string, mapping map[string]string) string {
+	newname, ok := mapping[name]
+	if ok {
+		name = newname
 	}
 	}
+	return name
+}
 
 
-	value := reflect.ValueOf(export.export)
-	m := value.MethodByName(name)
-
-	// Catch the case of attempting to call an unexported method
-	method, ok := value.Type().MethodByName(name)
-
-	if !m.IsValid() || !ok || method.PkgPath != "" {
-		return reflect.Value{}
+func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
+	if in == nil {
+		return nil
 	}
 	}
-	t := m.Type()
-	if t.NumOut() == 0 ||
-		t.Out(t.NumOut()-1) != reflect.TypeOf(&errmsgInvalidArg) {
-
-		return reflect.Value{}
+	methods := make(map[string]reflect.Value)
+	val := reflect.ValueOf(in)
+	typ := val.Type()
+	for i := 0; i < typ.NumMethod(); i++ {
+		methtype := typ.Method(i)
+		method := val.Method(i)
+		t := method.Type()
+		// only track valid methods must return *Error as last arg
+		// and must be exported
+		if t.NumOut() == 0 ||
+			t.Out(t.NumOut()-1) != reflect.TypeOf(&errmsgInvalidArg) ||
+			methtype.PkgPath != "" {
+			continue
+		}
+		// map names while building table
+		methods[computeMethodName(methtype.Name, mapping)] = method
 	}
 	}
-	return m
+	return methods
 }
 }
 
 
 // searchHandlers will look through all registered handlers looking for one
 // searchHandlers will look through all registered handlers looking for one
 // to handle the given path. If a verbatim one isn't found, it will check for
 // to handle the given path. If a verbatim one isn't found, it will check for
 // a subtree registration for the path as well.
 // a subtree registration for the path as well.
-func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportWithMapping, bool) {
+func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportedObj, bool) {
 	conn.handlersLck.RLock()
 	conn.handlersLck.RLock()
 	defer conn.handlersLck.RUnlock()
 	defer conn.handlersLck.RUnlock()
 
 
@@ -93,10 +87,10 @@ func (conn *Conn) searchHandlers(path ObjectPath) (map[string]exportWithMapping,
 
 
 	// If handlers weren't found for this exact path, look for a matching subtree
 	// If handlers weren't found for this exact path, look for a matching subtree
 	// registration
 	// registration
-	handlers = make(map[string]exportWithMapping)
+	handlers = make(map[string]exportedObj)
 	path = path[:strings.LastIndex(string(path), "/")]
 	path = path[:strings.LastIndex(string(path), "/")]
 	for len(path) > 0 {
 	for len(path) > 0 {
-		var subtreeHandlers map[string]exportWithMapping
+		var subtreeHandlers map[string]exportedObj
 		subtreeHandlers, ok = conn.handlers[path]
 		subtreeHandlers, ok = conn.handlers[path]
 		if ok {
 		if ok {
 			for iface, handler := range subtreeHandlers {
 			for iface, handler := range subtreeHandlers {
@@ -133,6 +127,28 @@ func (conn *Conn) handleCall(msg *Message) {
 			conn.sendError(errmsgUnknownMethod, sender, serial)
 			conn.sendError(errmsgUnknownMethod, sender, serial)
 		}
 		}
 		return
 		return
+	} else if ifaceName == "org.freedesktop.DBus.Introspectable" && name == "Introspect" {
+		if _, ok := conn.handlers[path]; !ok {
+			subpath := make(map[string]struct{})
+			var xml bytes.Buffer
+			xml.WriteString("<node>")
+			for h, _ := range conn.handlers {
+				p := string(path)
+				if p != "/" {
+					p += "/"
+				}
+				if strings.HasPrefix(string(h), p) {
+					node_name := strings.Split(string(h[len(p):]), "/")[0]
+					subpath[node_name] = struct{}{}
+				}
+			}
+			for s, _ := range subpath {
+				xml.WriteString("\n\t<node name=\"" + s + "\"/>")
+			}
+			xml.WriteString("\n</node>")
+			conn.sendReply(sender, serial, xml.String())
+			return
+		}
 	}
 	}
 	if len(name) == 0 {
 	if len(name) == 0 {
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		conn.sendError(errmsgUnknownMethod, sender, serial)
@@ -146,19 +162,20 @@ func (conn *Conn) handleCall(msg *Message) {
 	}
 	}
 
 
 	var m reflect.Value
 	var m reflect.Value
+	var exists bool
 	if hasIface {
 	if hasIface {
 		iface := handlers[ifaceName]
 		iface := handlers[ifaceName]
-		m = exportedMethod(iface, name)
+		m, exists = iface.Method(name)
 	} else {
 	} else {
 		for _, v := range handlers {
 		for _, v := range handlers {
-			m = exportedMethod(v, name)
-			if m.IsValid() {
+			m, exists = v.Method(name)
+			if exists {
 				break
 				break
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	if !m.IsValid() {
+	if !exists {
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		conn.sendError(errmsgUnknownMethod, sender, serial)
 		return
 		return
 	}
 	}
@@ -303,7 +320,7 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
 // The keys in the map are the real method names (exported on the struct), and
 // The keys in the map are the real method names (exported on the struct), and
 // the values are the method names to be exported on DBus.
 // the values are the method names to be exported on DBus.
 func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
 func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
-	return conn.exportWithMap(v, mapping, path, iface, false)
+	return conn.export(getMethods(v, mapping), path, iface, false)
 }
 }
 
 
 // ExportSubtree works exactly like Export but registers the given value for
 // ExportSubtree works exactly like Export but registers the given value for
@@ -326,11 +343,48 @@ func (conn *Conn) ExportSubtree(v interface{}, path ObjectPath, iface string) er
 // The keys in the map are the real method names (exported on the struct), and
 // The keys in the map are the real method names (exported on the struct), and
 // the values are the method names to be exported on DBus.
 // the values are the method names to be exported on DBus.
 func (conn *Conn) ExportSubtreeWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
 func (conn *Conn) ExportSubtreeWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
-	return conn.exportWithMap(v, mapping, path, iface, true)
+	return conn.export(getMethods(v, mapping), path, iface, true)
+}
+
+// ExportMethodTable like Export registers the given methods as an object
+// on the message bus. Unlike Export the it uses a method table to define
+// the object instead of a native go object.
+//
+// The method table is a map from method name to function closure
+// representing the method. This allows an object exported on the bus to not
+// necessarily be a native go object. It can be useful for generating exposed
+// methods on the fly.
+//
+// Any non-function objects in the method table are ignored.
+func (conn *Conn) ExportMethodTable(methods map[string]interface{}, path ObjectPath, iface string) error {
+	return conn.exportMethodTable(methods, path, iface, false)
+}
+
+// Like ExportSubtree, but with the same caveats as ExportMethodTable.
+func (conn *Conn) ExportSubtreeMethodTable(methods map[string]interface{}, path ObjectPath, iface string) error {
+	return conn.exportMethodTable(methods, path, iface, true)
+}
+
+func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectPath, iface string, includeSubtree bool) error {
+	out := make(map[string]reflect.Value)
+	for name, method := range methods {
+		rval := reflect.ValueOf(method)
+		if rval.Kind() != reflect.Func {
+			continue
+		}
+		t := rval.Type()
+		// only track valid methods must return *Error as last arg
+		if t.NumOut() == 0 ||
+			t.Out(t.NumOut()-1) != reflect.TypeOf(&errmsgInvalidArg) {
+			continue
+		}
+		out[name] = rval
+	}
+	return conn.export(out, path, iface, includeSubtree)
 }
 }
 
 
 // exportWithMap is the worker function for all exports/registrations.
 // exportWithMap is the worker function for all exports/registrations.
-func (conn *Conn) exportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string, includeSubtree bool) error {
+func (conn *Conn) export(methods map[string]reflect.Value, path ObjectPath, iface string, includeSubtree bool) error {
 	if !path.IsValid() {
 	if !path.IsValid() {
 		return fmt.Errorf(`dbus: Invalid path name: "%s"`, path)
 		return fmt.Errorf(`dbus: Invalid path name: "%s"`, path)
 	}
 	}
@@ -339,7 +393,7 @@ func (conn *Conn) exportWithMap(v interface{}, mapping map[string]string, path O
 	defer conn.handlersLck.Unlock()
 	defer conn.handlersLck.Unlock()
 
 
 	// Remove a previous export if the interface is nil
 	// Remove a previous export if the interface is nil
-	if v == nil {
+	if methods == nil {
 		if _, ok := conn.handlers[path]; ok {
 		if _, ok := conn.handlers[path]; ok {
 			delete(conn.handlers[path], iface)
 			delete(conn.handlers[path], iface)
 			if len(conn.handlers[path]) == 0 {
 			if len(conn.handlers[path]) == 0 {
@@ -353,11 +407,14 @@ func (conn *Conn) exportWithMap(v interface{}, mapping map[string]string, path O
 	// If this is the first handler for this path, make a new map to hold all
 	// If this is the first handler for this path, make a new map to hold all
 	// handlers for this path.
 	// handlers for this path.
 	if _, ok := conn.handlers[path]; !ok {
 	if _, ok := conn.handlers[path]; !ok {
-		conn.handlers[path] = make(map[string]exportWithMapping)
+		conn.handlers[path] = make(map[string]exportedObj)
 	}
 	}
 
 
 	// Finally, save this handler
 	// Finally, save this handler
-	conn.handlers[path][iface] = exportWithMapping{export: v, mapping: mapping, includeSubtree: includeSubtree}
+	conn.handlers[path][iface] = exportedObj{
+		methods:        methods,
+		includeSubtree: includeSubtree,
+	}
 
 
 	return nil
 	return nil
 }
 }

+ 8 - 1
vendor/src/github.com/godbus/dbus/message.go

@@ -22,6 +22,13 @@ const (
 	// FlagNoAutoStart signals that the message bus should not automatically
 	// FlagNoAutoStart signals that the message bus should not automatically
 	// start an application when handling this message.
 	// start an application when handling this message.
 	FlagNoAutoStart
 	FlagNoAutoStart
+	// FlagAllowInteractiveAuthorization may be set on a method call
+	// message to inform the receiving side that the caller is prepared
+	// to wait for interactive authorization, which might take a
+	// considerable time to complete. For instance, if this flag is set,
+	// it would be appropriate to query the user for passwords or
+	// confirmation via Polkit or a similar framework.
+	FlagAllowInteractiveAuthorization
 )
 )
 
 
 // Type represents the possible types of a D-Bus message.
 // Type represents the possible types of a D-Bus message.
@@ -248,7 +255,7 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
 // IsValid checks whether msg is a valid message and returns an
 // IsValid checks whether msg is a valid message and returns an
 // InvalidMessageError if it is not.
 // InvalidMessageError if it is not.
 func (msg *Message) IsValid() error {
 func (msg *Message) IsValid() error {
-	if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected) != 0 {
+	if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected|FlagAllowInteractiveAuthorization) != 0 {
 		return InvalidMessageError("invalid flags")
 		return InvalidMessageError("invalid flags")
 	}
 	}
 	if msg.Type == 0 || msg.Type >= typeMax {
 	if msg.Type == 0 || msg.Type >= typeMax {

+ 10 - 0
vendor/src/github.com/godbus/dbus/object.go

@@ -27,6 +27,16 @@ func (o *Object) Call(method string, flags Flags, args ...interface{}) *Call {
 	return <-o.Go(method, flags, make(chan *Call, 1), args...).Done
 	return <-o.Go(method, flags, make(chan *Call, 1), args...).Done
 }
 }
 
 
+// AddMatchSignal subscribes BusObject to signals from specified interface and
+// method (member).
+func (o *Object) AddMatchSignal(iface, member string) *Call {
+	return o.Call(
+		"org.freedesktop.DBus.AddMatch",
+		0,
+		"type='signal',interface='"+iface+"',member='"+member+"'",
+	)
+}
+
 // Go calls a method with the given arguments asynchronously. It returns a
 // Go calls a method with the given arguments asynchronously. It returns a
 // Call structure representing this method call. The passed channel will
 // Call structure representing this method call. The passed channel will
 // return the same value once the call is done. If ch is nil, a new channel
 // return the same value once the call is done. If ch is nil, a new channel

+ 43 - 0
vendor/src/github.com/godbus/dbus/transport_tcp.go

@@ -0,0 +1,43 @@
+//+build !windows
+
+package dbus
+
+import (
+	"errors"
+	"net"
+)
+
+func init() {
+	transports["tcp"] = newTcpTransport
+}
+
+func tcpFamily(keys string) (string, error) {
+	switch getKey(keys, "family") {
+	case "":
+		return "tcp", nil
+	case "ipv4":
+		return "tcp4", nil
+	case "ipv6":
+		return "tcp6", nil
+	default:
+		return "", errors.New("dbus: invalid tcp family (must be ipv4 or ipv6)")
+	}
+}
+
+func newTcpTransport(keys string) (transport, error) {
+	host := getKey(keys, "host")
+	port := getKey(keys, "port")
+	if host == "" || port == "" {
+		return nil, errors.New("dbus: unsupported address (must set host and port)")
+	}
+
+	protocol, err := tcpFamily(keys)
+	if err != nil {
+		return nil, err
+	}
+	socket, err := net.Dial(protocol, net.JoinHostPort(host, port))
+	if err != nil {
+		return nil, err
+	}
+	return NewConn(socket)
+}

+ 1 - 1
vendor/src/github.com/godbus/dbus/transport_unix.go

@@ -1,4 +1,4 @@
-//+build !windows
+//+build !windows,!solaris
 
 
 package dbus
 package dbus