Merge pull request #5018 from opencontainers/dependabot/go_modules/github.com/godbus/dbus/v5-5.2.0

build(deps): bump github.com/godbus/dbus/v5 from 5.1.0 to 5.2.0
This commit is contained in:
lfbzhm
2025-11-20 09:51:28 +08:00
committed by GitHub
36 changed files with 662 additions and 388 deletions

2
go.mod
View File

@@ -8,7 +8,7 @@ require (
github.com/coreos/go-systemd/v22 v22.6.0
github.com/cyphar/filepath-securejoin v0.6.0
github.com/docker/go-units v0.5.0
github.com/godbus/dbus/v5 v5.1.0
github.com/godbus/dbus/v5 v5.2.0
github.com/moby/sys/capability v0.4.0
github.com/moby/sys/mountinfo v0.7.2
github.com/moby/sys/user v0.4.0

4
go.sum
View File

@@ -20,8 +20,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.2.0 h1:3WexO+U+yg9T70v9FdHr9kCxYlazaAXUhx2VMkbfax8=
github.com/godbus/dbus/v5 v5.2.0/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=

11
vendor/github.com/godbus/dbus/v5/.cirrus.yml generated vendored Normal file
View File

@@ -0,0 +1,11 @@
# See https://cirrus-ci.org/guide/FreeBSD/
freebsd_instance:
image_family: freebsd-14-2
task:
name: Test on FreeBSD
install_script: pkg install -y go122 dbus
test_script: |
/usr/local/etc/rc.d/dbus onestart && \
eval `dbus-launch --sh-syntax` && \
go122 test -v ./...

7
vendor/github.com/godbus/dbus/v5/.golangci.yml generated vendored Normal file
View File

@@ -0,0 +1,7 @@
# For documentation, see https://golangci-lint.run/usage/configuration/
linters:
enable:
- gofumpt
- unconvert
- unparam

View File

@@ -14,7 +14,7 @@ D-Bus message bus system.
### Installation
This packages requires Go 1.12 or later. It can be installed by running the command below:
This packages requires Go 1.20 or later. It can be installed by running the command below:
```
go get github.com/godbus/dbus/v5
@@ -23,7 +23,7 @@ go get github.com/godbus/dbus/v5
### Usage
The complete package documentation and some simple examples are available at
[godoc.org](http://godoc.org/github.com/godbus/dbus). Also, the
[pkg.go.dev](https://pkg.go.dev/github.com/godbus/dbus/v5). Also, the
[_examples](https://github.com/godbus/dbus/tree/master/_examples) directory
gives a short overview over the basic usage.
@@ -34,6 +34,7 @@ gives a short overview over the basic usage.
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
- [rpic](https://github.com/stephenhu/rpic) lightweight web app and RESTful API for managing a Raspberry Pi
Please note that the API is considered unstable for now and may change without
further notice.

13
vendor/github.com/godbus/dbus/v5/SECURITY.md generated vendored Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it at [security advisory](https://github.com/godbus/dbus/security/advisories/new).
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.

View File

@@ -54,7 +54,7 @@ type Auth interface {
func (conn *Conn) Auth(methods []Auth) error {
if methods == nil {
uid := strconv.Itoa(os.Geteuid())
methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())}
methods = getDefaultAuthMethods(uid)
}
in := bufio.NewReader(conn.transport)
err := conn.transport.SendNullByte()
@@ -83,9 +83,9 @@ func (conn *Conn) Auth(methods []Auth) error {
}
switch status {
case AuthOk:
err, ok = conn.tryAuth(m, waitingForOk, in)
ok, err = conn.tryAuth(m, waitingForOk, in)
case AuthContinue:
err, ok = conn.tryAuth(m, waitingForData, in)
ok, err = conn.tryAuth(m, waitingForData, in)
default:
panic("dbus: invalid authentication status")
}
@@ -125,21 +125,21 @@ func (conn *Conn) Auth(methods []Auth) error {
}
// tryAuth tries to authenticate with m as the mechanism, using state as the
// initial authState and in for reading input. It returns (nil, true) on
// success, (nil, false) on a REJECTED and (someErr, false) if some other
// initial authState and in for reading input. It returns (true, nil) on
// success, (false, nil) on a REJECTED and (false, someErr) if some other
// error occurred.
func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, bool) {
func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (bool, error) {
for {
s, err := authReadLine(in)
if err != nil {
return err, false
return false, err
}
switch {
case state == waitingForData && string(s[0]) == "DATA":
if len(s) != 2 {
err = authWriteLine(conn.transport, []byte("ERROR"))
if err != nil {
return err, false
return false, err
}
continue
}
@@ -149,7 +149,7 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
if len(data) != 0 {
err = authWriteLine(conn.transport, []byte("DATA"), data)
if err != nil {
return err, false
return false, err
}
}
if status == AuthOk {
@@ -158,66 +158,66 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
case AuthError:
err = authWriteLine(conn.transport, []byte("ERROR"))
if err != nil {
return err, false
return false, err
}
}
case state == waitingForData && string(s[0]) == "REJECTED":
return nil, false
return false, nil
case state == waitingForData && string(s[0]) == "ERROR":
err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil {
return err, false
return false, err
}
state = waitingForReject
case state == waitingForData && string(s[0]) == "OK":
if len(s) != 2 {
err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil {
return err, false
return false, err
}
state = waitingForReject
} else {
conn.uuid = string(s[1])
return nil, true
return true, nil
}
case state == waitingForData:
err = authWriteLine(conn.transport, []byte("ERROR"))
if err != nil {
return err, false
return false, err
}
case state == waitingForOk && string(s[0]) == "OK":
if len(s) != 2 {
err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil {
return err, false
return false, err
}
state = waitingForReject
} else {
conn.uuid = string(s[1])
return nil, true
return true, nil
}
case state == waitingForOk && string(s[0]) == "DATA":
err = authWriteLine(conn.transport, []byte("DATA"))
if err != nil {
return err, false
return false, nil
}
case state == waitingForOk && string(s[0]) == "REJECTED":
return nil, false
return false, nil
case state == waitingForOk && string(s[0]) == "ERROR":
err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil {
return err, false
return false, err
}
state = waitingForReject
case state == waitingForOk:
err = authWriteLine(conn.transport, []byte("ERROR"))
if err != nil {
return err, false
return false, err
}
case state == waitingForReject && string(s[0]) == "REJECTED":
return nil, false
return false, nil
case state == waitingForReject:
return errors.New("dbus: authentication protocol error"), false
return false, errors.New("dbus: authentication protocol error")
default:
panic("dbus: invalid auth state")
}

View File

@@ -0,0 +1,8 @@
//go:build !windows
// +build !windows
package dbus
func getDefaultAuthMethods(user string) []Auth {
return []Auth{AuthExternal(user)}
}

View File

@@ -0,0 +1,5 @@
package dbus
func getDefaultAuthMethods(user string) []Auth {
return []Auth{AuthCookieSha1(user, getHomeDir())}
}

View File

@@ -7,6 +7,7 @@ import (
"crypto/sha1"
"encoding/hex"
"os"
"os/user"
)
// AuthCookieSha1 returns an Auth that authenticates as the given user with the
@@ -100,3 +101,22 @@ func (a authCookieSha1) generateChallenge() []byte {
hex.Encode(enc, b)
return enc
}
// Get returns the home directory of the current user, which is usually the
// value of HOME environment variable. In case it is not set or empty, os/user
// package is used.
//
// If linking statically with cgo enabled against glibc, make sure the
// osusergo build tag is used.
//
// If needing to do nss lookups, do not disable cgo or set osusergo.
func getHomeDir() string {
homeDir := os.Getenv("HOME")
if homeDir != "" {
return homeDir
}
if u, err := user.Current(); err == nil {
return u.HomeDir
}
return "/"
}

View File

@@ -2,17 +2,14 @@ package dbus
import (
"context"
"errors"
)
var errSignature = errors.New("dbus: mismatched signature")
// Call represents a pending or completed method call.
type Call struct {
Destination string
Path ObjectPath
Method string
Args []interface{}
Args []any
// Strobes when the call is complete.
Done chan *Call
@@ -22,7 +19,7 @@ type Call struct {
Err error
// Holds the response once the call is done.
Body []interface{}
Body []any
// ResponseSequence stores the sequence number of the DBus message containing
// the call response (or error). This can be compared to the sequence number
@@ -55,7 +52,7 @@ func (c *Call) ContextCancel() {
// Store stores the body of the reply into the provided pointers. It returns
// an error if the signatures of the body and retvalues don't match, or if
// the error status is not nil.
func (c *Call) Store(retvalues ...interface{}) error {
func (c *Call) Store(retvalues ...any) error {
if c.Err != nil {
return c.Err
}

View File

@@ -3,6 +3,7 @@ package dbus
import (
"context"
"errors"
"fmt"
"io"
"os"
"strings"
@@ -76,7 +77,6 @@ func SessionBus() (conn *Conn, err error) {
func getSessionBusAddress(autolaunch bool) (string, error) {
if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
return address, nil
} else if address := tryDiscoverDbusSessionBusAddress(); address != "" {
os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
return address, nil
@@ -97,7 +97,7 @@ func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
return Dial(address, opts...)
}
// SessionBusPrivate returns a new private connection to the session bus. If
// SessionBusPrivateNoAutoStartup returns a new private connection to the session bus. If
// the session bus is not already open, do not attempt to launch it.
func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) {
address, err := getSessionBusAddress(false)
@@ -108,7 +108,7 @@ func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) {
return Dial(address, opts...)
}
// SessionBusPrivate returns a new private connection to the session bus.
// SessionBusPrivateHandler returns a new private connection to the session bus.
//
// Deprecated: use SessionBusPrivate with options instead.
func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Conn, error) {
@@ -485,7 +485,7 @@ func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
return &Object{conn, dest, path}
}
func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) error {
if msg.serial == 0 {
msg.serial = conn.getSerial()
}
@@ -498,14 +498,29 @@ func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
} else if msg.Type != TypeMethodCall {
conn.serialGen.RetireSerial(msg.serial)
}
return err
}
func isEncodingError(err error) bool {
switch err.(type) {
case FormatError:
return true
case InvalidMessageError:
return true
}
return false
}
func (conn *Conn) handleSendError(msg *Message, err error) {
if msg.Type == TypeMethodCall {
conn.calls.handleSendError(msg, err)
} else if msg.Type == TypeMethodReply {
if _, ok := err.(FormatError); ok {
conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
if isEncodingError(err) {
// Make sure that the caller gets some kind of error response if
// the application code tried to respond, but the resulting message
// was malformed in the end
returnedErr := fmt.Errorf("destination tried to respond with invalid message (%w)", err)
conn.sendError(returnedErr, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
}
}
conn.serialGen.RetireSerial(msg.serial)
@@ -560,7 +575,8 @@ func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
<-ctx.Done()
conn.calls.handleSendError(msg, ctx.Err())
}()
conn.sendMessageAndIfClosed(msg, func() {
// error is handled in handleSendError
_ = conn.sendMessageAndIfClosed(msg, func() {
conn.calls.handleSendError(msg, ErrClosed)
canceler()
})
@@ -568,7 +584,8 @@ func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
canceler()
call = &Call{Err: nil, Done: ch}
ch <- call
conn.sendMessageAndIfClosed(msg, func() {
// error is handled in handleSendError
_ = conn.sendMessageAndIfClosed(msg, func() {
call = &Call{Err: ErrClosed}
})
}
@@ -602,12 +619,13 @@ func (conn *Conn) sendError(err error, dest string, serial uint32) {
if len(e.Body) > 0 {
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(e.Body...))
}
conn.sendMessageAndIfClosed(msg, nil)
// not much we can do to handle a possible error here
_ = conn.sendMessageAndIfClosed(msg, nil)
}
// sendReply creates a method reply message corresponding to the parameters and
// sends it to conn.out.
func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
func (conn *Conn) sendReply(dest string, serial uint32, values ...any) {
msg := new(Message)
msg.Type = TypeMethodReply
msg.Headers = make(map[HeaderField]Variant)
@@ -619,7 +637,8 @@ func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
if len(values) > 0 {
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
}
conn.sendMessageAndIfClosed(msg, nil)
// not much we can do to handle a possible error here
_ = conn.sendMessageAndIfClosed(msg, nil)
}
// AddMatchSignal registers the given match rule to receive broadcast
@@ -630,7 +649,7 @@ func (conn *Conn) AddMatchSignal(options ...MatchOption) error {
// AddMatchSignalContext acts like AddMatchSignal but takes a context.
func (conn *Conn) AddMatchSignalContext(ctx context.Context, options ...MatchOption) error {
options = append([]MatchOption{withMatchType("signal")}, options...)
options = append([]MatchOption{withMatchTypeSignal()}, options...)
return conn.busObj.CallWithContext(
ctx,
"org.freedesktop.DBus.AddMatch", 0,
@@ -645,7 +664,7 @@ func (conn *Conn) RemoveMatchSignal(options ...MatchOption) error {
// RemoveMatchSignalContext acts like RemoveMatchSignal but takes a context.
func (conn *Conn) RemoveMatchSignalContext(ctx context.Context, options ...MatchOption) error {
options = append([]MatchOption{withMatchType("signal")}, options...)
options = append([]MatchOption{withMatchTypeSignal()}, options...)
return conn.busObj.CallWithContext(
ctx,
"org.freedesktop.DBus.RemoveMatch", 0,
@@ -694,10 +713,10 @@ func (conn *Conn) SupportsUnixFDs() bool {
// Error represents a D-Bus message of type Error.
type Error struct {
Name string
Body []interface{}
Body []any
}
func NewError(name string, body []interface{}) *Error {
func NewError(name string, body []any) *Error {
return &Error{name, body}
}
@@ -717,7 +736,7 @@ type Signal struct {
Sender string
Path ObjectPath
Name string
Body []interface{}
Body []any
Sequence Sequence
}
@@ -740,9 +759,7 @@ type transport interface {
SendMessage(*Message) error
}
var (
transports = make(map[string]func(string) (transport, error))
)
var transports = make(map[string]func(string) (transport, error))
func getTransport(address string) (transport, error) {
var err error
@@ -770,10 +787,10 @@ func getTransport(address string) (transport, error) {
// getKey gets a key from a the list of keys. Returns "" on error / not found...
func getKey(s, key string) string {
for _, keyEqualsValue := range strings.Split(s, ",") {
keyValue := strings.SplitN(keyEqualsValue, "=", 2)
if len(keyValue) == 2 && keyValue[0] == key {
val, err := UnescapeBusAddressValue(keyValue[1])
keyEq := key + "="
for _, kv := range strings.Split(s, ",") {
if v, ok := strings.CutPrefix(kv, keyEq); ok {
val, err := UnescapeBusAddressValue(v)
if err != nil {
// No way to return an error.
return ""
@@ -853,16 +870,19 @@ type nameTracker struct {
func newNameTracker() *nameTracker {
return &nameTracker{names: map[string]struct{}{}}
}
func (tracker *nameTracker) acquireUniqueConnectionName(name string) {
tracker.lck.Lock()
defer tracker.lck.Unlock()
tracker.unique = name
}
func (tracker *nameTracker) acquireName(name string) {
tracker.lck.Lock()
defer tracker.lck.Unlock()
tracker.names[name] = struct{}{}
}
func (tracker *nameTracker) loseName(name string) {
tracker.lck.Lock()
defer tracker.lck.Unlock()
@@ -874,12 +894,14 @@ func (tracker *nameTracker) uniqueNameIsKnown() bool {
defer tracker.lck.RUnlock()
return tracker.unique != ""
}
func (tracker *nameTracker) isKnownName(name string) bool {
tracker.lck.RLock()
defer tracker.lck.RUnlock()
_, ok := tracker.names[name]
return ok || name == tracker.unique
}
func (tracker *nameTracker) listKnownNames() []string {
tracker.lck.RLock()
defer tracker.lck.RUnlock()
@@ -941,18 +963,7 @@ func (tracker *callTracker) handleSendError(msg *Message, err error) {
}
}
// finalize was the only func that did not strobe Done
func (tracker *callTracker) finalize(sn uint32) {
tracker.lck.Lock()
defer tracker.lck.Unlock()
c, ok := tracker.calls[sn]
if ok {
delete(tracker.calls, sn)
c.ContextCancel()
}
}
func (tracker *callTracker) finalizeWithBody(sn uint32, sequence Sequence, body []interface{}) {
func (tracker *callTracker) finalizeWithBody(sn uint32, sequence Sequence, body []any) {
tracker.lck.Lock()
c, ok := tracker.calls[sn]
if ok {

View File

@@ -12,7 +12,6 @@ const defaultSystemBusAddress = "unix:path=/opt/local/var/run/dbus/system_bus_so
func getSessionBusPlatformAddress() (string, error) {
cmd := exec.Command("launchctl", "getenv", "DBUS_LAUNCHD_SESSION_BUS_SOCKET")
b, err := cmd.CombinedOutput()
if err != nil {
return "", err
}

View File

@@ -1,3 +1,4 @@
//go:build !darwin
// +build !darwin
package dbus
@@ -6,7 +7,6 @@ import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"os/user"
@@ -19,7 +19,6 @@ var execCommand = exec.Command
func getSessionBusPlatformAddress() (string, error) {
cmd := execCommand("dbus-launch")
b, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
@@ -42,10 +41,10 @@ func getSessionBusPlatformAddress() (string, error) {
// It tries different techniques employed by different operating systems,
// returning the first valid address it finds, or an empty string.
//
// * /run/user/<uid>/bus if this exists, it *is* the bus socket. present on
// Ubuntu 18.04
// * /run/user/<uid>/dbus-session: if this exists, it can be parsed for the bus
// address. present on Ubuntu 16.04
// - /run/user/<uid>/bus if this exists, it *is* the bus socket. present on
// Ubuntu 18.04
// - /run/user/<uid>/dbus-session: if this exists, it can be parsed for the bus
// address. present on Ubuntu 16.04
//
// See https://dbus.freedesktop.org/doc/dbus-launch.1.html
func tryDiscoverDbusSessionBusAddress() string {
@@ -61,14 +60,9 @@ func tryDiscoverDbusSessionBusAddress() string {
// text file // containing the address of the socket, e.g.:
// DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-E1c73yNqrG
if f, err := ioutil.ReadFile(runUserSessionDbusFile); err == nil {
fileContent := string(f)
prefix := "DBUS_SESSION_BUS_ADDRESS="
if strings.HasPrefix(fileContent, prefix) {
address := strings.TrimRight(strings.TrimPrefix(fileContent, prefix), "\n\r")
return address
if f, err := os.ReadFile(runUserSessionDbusFile); err == nil {
if addr, ok := strings.CutPrefix(string(f), "DBUS_SESSION_BUS_ADDRESS="); ok {
return strings.TrimRight(addr, "\n\r")
}
}
}

View File

@@ -1,8 +1,10 @@
//+build !windows,!solaris,!darwin
//go:build !windows && !solaris && !darwin
// +build !windows,!solaris,!darwin
package dbus
import (
"net"
"os"
)
@@ -15,3 +17,25 @@ func getSystemBusPlatformAddress() string {
}
return defaultSystemBusAddress
}
// DialUnix establishes a new private connection to the message bus specified by UnixConn.
func DialUnix(conn *net.UnixConn, opts ...ConnOption) (*Conn, error) {
tr := newUnixTransportFromConn(conn)
return newConn(tr, opts...)
}
func ConnectUnix(uconn *net.UnixConn, opts ...ConnOption) (*Conn, error) {
conn, err := DialUnix(uconn, opts...)
if err != nil {
return nil, err
}
if err = conn.Auth(conn.auth); err != nil {
_ = conn.Close()
return nil, err
}
if err = conn.Hello(); err != nil {
_ = conn.Close()
return nil, err
}
return conn, nil
}

View File

@@ -1,5 +1,3 @@
//+build windows
package dbus
import "os"

View File

@@ -10,11 +10,8 @@ import (
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))
intType = reflect.TypeOf(int(0))
uintType = reflect.TypeOf(uint(0))
int32Type = reflect.TypeOf(int32(0))
uint32Type = reflect.TypeOf(uint32(0))
int64Type = reflect.TypeOf(int64(0))
@@ -24,8 +21,8 @@ var (
signatureType = reflect.TypeOf(Signature{""})
objectPathType = reflect.TypeOf(ObjectPath(""))
variantType = reflect.TypeOf(Variant{Signature{""}, nil})
interfacesType = reflect.TypeOf([]interface{}{})
interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
interfacesType = reflect.TypeOf([]any{})
interfaceType = reflect.TypeOf((*any)(nil)).Elem()
unixFDType = reflect.TypeOf(UnixFD(0))
unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
errType = reflect.TypeOf((*error)(nil)).Elem()
@@ -45,7 +42,7 @@ func (e InvalidTypeError) Error() string {
// 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 {
func Store(src []any, dest ...any) error {
if len(src) != len(dest) {
return errors.New("dbus.Store: length mismatch")
}
@@ -58,7 +55,7 @@ func Store(src []interface{}, dest ...interface{}) error {
return nil
}
func storeInterfaces(src, dest interface{}) error {
func storeInterfaces(src, dest any) error {
return store(reflect.ValueOf(dest), reflect.ValueOf(src))
}
@@ -85,7 +82,7 @@ func storeBase(dest, src reflect.Value) error {
func setDest(dest, src reflect.Value) error {
if !isVariant(src.Type()) && isVariant(dest.Type()) {
//special conversion for dbus.Variant
// special conversion for dbus.Variant
dest.Set(reflect.ValueOf(MakeVariant(src.Interface())))
return nil
}
@@ -166,8 +163,8 @@ func storeMapIntoVariant(dest, src reflect.Value) error {
func storeMapIntoInterface(dest, src reflect.Value) error {
var dv reflect.Value
if isVariant(src.Type().Elem()) {
//Convert variants to interface{} recursively when converting
//to interface{}
// Convert variants to interface{} recursively when converting
// to interface{}
dv = reflect.MakeMap(
reflect.MapOf(src.Type().Key(), interfaceType))
} else {
@@ -200,7 +197,7 @@ func storeMapIntoMap(dest, src reflect.Value) error {
func storeSlice(dest, src reflect.Value) error {
switch {
case src.Type() == interfacesType && dest.Kind() == reflect.Struct:
//The decoder always decodes structs as slices of interface{}
// The decoder always decodes structs as slices of interface{}
return storeStruct(dest, src)
case !kindsAreCompatible(dest.Type(), src.Type()):
return fmt.Errorf(
@@ -225,7 +222,7 @@ func storeStruct(dest, src reflect.Value) error {
if isVariant(dest.Type()) {
return storeBase(dest, src)
}
dval := make([]interface{}, 0, dest.NumField())
dval := make([]any, 0, dest.NumField())
dtype := dest.Type()
for i := 0; i < dest.NumField(); i++ {
field := dest.Field(i)
@@ -245,7 +242,7 @@ func storeStruct(dest, src reflect.Value) error {
"enough fields need: %d have: %d",
src.Len(), len(dval))
}
return Store(src.Interface().([]interface{}), dval...)
return Store(src.Interface().([]any), dval...)
}
func storeSliceIntoVariant(dest, src reflect.Value) error {
@@ -260,8 +257,8 @@ func storeSliceIntoVariant(dest, src reflect.Value) error {
func storeSliceIntoInterface(dest, src reflect.Value) error {
var dv reflect.Value
if isVariant(src.Type().Elem()) {
//Convert variants to interface{} recursively when converting
//to interface{}
// Convert variants to interface{} recursively when converting
// to interface{}
dv = reflect.MakeSlice(reflect.SliceOf(interfaceType),
src.Len(), src.Cap())
} else {
@@ -334,7 +331,7 @@ func (o ObjectPath) IsValid() bool {
}
// A UnixFD is a Unix file descriptor sent over the wire. See the package-level
// documentation for more information about Unix file descriptor passsing.
// documentation for more information about Unix file descriptor passing.
type UnixFD int32
// A UnixFDIndex is the representation of a Unix file descriptor in a message.

View File

@@ -4,6 +4,7 @@ import (
"encoding/binary"
"io"
"reflect"
"unsafe"
)
type decoder struct {
@@ -11,6 +12,12 @@ type decoder struct {
order binary.ByteOrder
pos int
fds []int
// The following fields are used to reduce memory allocs.
conv *stringConverter
buf []byte
d float64
y [1]byte
}
// newDecoder returns a new decoder that reads values from in. The input is
@@ -20,29 +27,39 @@ func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
dec.in = in
dec.order = order
dec.fds = fds
dec.conv = newStringConverter(stringConverterBufferSize)
return dec
}
// Reset resets the decoder to be reading from in.
func (dec *decoder) Reset(in io.Reader, order binary.ByteOrder, fds []int) {
dec.in = in
dec.order = order
dec.pos = 0
dec.fds = fds
if dec.conv == nil {
dec.conv = newStringConverter(stringConverterBufferSize)
}
}
// align aligns the input to the given boundary and panics on error.
func (dec *decoder) align(n int) {
if dec.pos%n != 0 {
newpos := (dec.pos + n - 1) & ^(n - 1)
empty := make([]byte, newpos-dec.pos)
if _, err := io.ReadFull(dec.in, empty); err != nil {
panic(err)
}
dec.read2buf(newpos - dec.pos)
dec.pos = newpos
}
}
// Calls binary.Read(dec.in, dec.order, v) and panics on read errors.
func (dec *decoder) binread(v interface{}) {
func (dec *decoder) binread(v any) {
if err := binary.Read(dec.in, dec.order, v); err != nil {
panic(err)
}
}
func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
func (dec *decoder) Decode(sig Signature) (vs []any, err error) {
defer func() {
var ok bool
v := recover()
@@ -52,7 +69,7 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
}
}
}()
vs = make([]interface{}, 0)
vs = make([]any, 0)
s := sig.str
for s != "" {
err, rem := validSingle(s, &depthCounter{})
@@ -66,79 +83,89 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
return vs, nil
}
func (dec *decoder) decode(s string, depth int) interface{} {
// read2buf reads exactly n bytes from the reader dec.in into the buffer dec.buf
// to reduce memory allocs.
// The buffer grows automatically.
func (dec *decoder) read2buf(n int) {
if cap(dec.buf) < n {
dec.buf = make([]byte, n)
} else {
dec.buf = dec.buf[:n]
}
if _, err := io.ReadFull(dec.in, dec.buf); err != nil {
panic(err)
}
}
// decodeU decodes uint32 obtained from the reader dec.in.
// The goal is to reduce memory allocs.
func (dec *decoder) decodeU() uint32 {
dec.align(4)
dec.read2buf(4)
dec.pos += 4
return dec.order.Uint32(dec.buf)
}
func (dec *decoder) decode(s string, depth int) any {
dec.align(alignment(typeFor(s)))
switch s[0] {
case 'y':
var b [1]byte
if _, err := dec.in.Read(b[:]); err != nil {
if _, err := dec.in.Read(dec.y[:]); err != nil {
panic(err)
}
dec.pos++
return b[0]
return dec.y[0]
case 'b':
i := dec.decode("u", depth).(uint32)
switch {
case i == 0:
switch dec.decodeU() {
case 0:
return false
case i == 1:
case 1:
return true
default:
panic(FormatError("invalid value for boolean"))
}
case 'n':
var i int16
dec.binread(&i)
dec.read2buf(2)
dec.pos += 2
return i
return int16(dec.order.Uint16(dec.buf))
case 'i':
var i int32
dec.binread(&i)
dec.read2buf(4)
dec.pos += 4
return i
return int32(dec.order.Uint32(dec.buf))
case 'x':
var i int64
dec.binread(&i)
dec.read2buf(8)
dec.pos += 8
return i
return int64(dec.order.Uint64(dec.buf))
case 'q':
var i uint16
dec.binread(&i)
dec.read2buf(2)
dec.pos += 2
return i
return dec.order.Uint16(dec.buf)
case 'u':
var i uint32
dec.binread(&i)
dec.pos += 4
return i
return dec.decodeU()
case 't':
var i uint64
dec.binread(&i)
dec.read2buf(8)
dec.pos += 8
return i
return dec.order.Uint64(dec.buf)
case 'd':
var f float64
dec.binread(&f)
dec.binread(&dec.d)
dec.pos += 8
return f
return dec.d
case 's':
length := dec.decode("u", depth).(uint32)
b := make([]byte, int(length)+1)
if _, err := io.ReadFull(dec.in, b); err != nil {
panic(err)
}
dec.pos += int(length) + 1
return string(b[:len(b)-1])
length := dec.decodeU()
p := int(length) + 1
dec.read2buf(p)
dec.pos += p
return dec.conv.String(dec.buf[:len(dec.buf)-1])
case 'o':
return ObjectPath(dec.decode("s", depth).(string))
case 'g':
length := dec.decode("y", depth).(byte)
b := make([]byte, int(length)+1)
if _, err := io.ReadFull(dec.in, b); err != nil {
panic(err)
}
dec.pos += int(length) + 1
sig, err := ParseSignature(string(b[:len(b)-1]))
p := int(length) + 1
dec.read2buf(p)
dec.pos += p
sig, err := ParseSignature(
dec.conv.String(dec.buf[:len(dec.buf)-1]),
)
if err != nil {
panic(err)
}
@@ -163,7 +190,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
variant.value = dec.decode(sig.str, depth+1)
return variant
case 'h':
idx := dec.decode("u", depth).(uint32)
idx := dec.decodeU()
if int(idx) < len(dec.fds) {
return UnixFD(dec.fds[idx])
}
@@ -176,7 +203,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
if depth >= 63 {
panic(FormatError("input exceeds container depth limit"))
}
length := dec.decode("u", depth).(uint32)
length := dec.decodeU()
// Even for empty maps, the correct padding must be included
dec.align(8)
spos := dec.pos
@@ -195,7 +222,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
panic(FormatError("input exceeds container depth limit"))
}
sig := s[1:]
length := dec.decode("u", depth).(uint32)
length := dec.decodeU()
// capacity can be determined only for fixed-size element types
var capacity int
if s := sigByteSize(sig); s != 0 {
@@ -205,9 +232,9 @@ func (dec *decoder) decode(s string, depth int) interface{} {
// Even for empty arrays, the correct padding must be included
align := alignment(typeFor(s[1:]))
if len(s) > 1 && s[1] == '(' {
//Special case for arrays of structs
//structs decode as a slice of interface{} values
//but the dbus alignment does not match this
// Special case for arrays of structs
// structs decode as a slice of interface{} values
// but the dbus alignment does not match this
align = 8
}
dec.align(align)
@@ -222,7 +249,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
panic(FormatError("input exceeds container depth limit"))
}
dec.align(8)
v := make([]interface{}, 0)
v := make([]any, 0)
s = s[1 : len(s)-1]
for s != "" {
err, rem := validSingle(s, &depthCounter{})
@@ -290,3 +317,59 @@ type FormatError string
func (e FormatError) Error() string {
return "dbus: wire format error: " + string(e)
}
// stringConverterBufferSize defines the recommended buffer size of 4KB.
// It showed good results in a benchmark when decoding 35KB message,
// see https://github.com/marselester/systemd#testing.
const stringConverterBufferSize = 4096
func newStringConverter(capacity int) *stringConverter {
return &stringConverter{
buf: make([]byte, 0, capacity),
offset: 0,
}
}
// stringConverter converts bytes to strings with less allocs.
// The idea is to accumulate bytes in a buffer with specified capacity
// and create strings with unsafe package using bytes from a buffer.
// For example, 10 "fizz" strings written to a 40-byte buffer
// will result in 1 alloc instead of 10.
//
// Once a buffer is filled, a new one is created with the same capacity.
// Old buffers will be eventually GC-ed
// with no side effects to the returned strings.
type stringConverter struct {
// buf is a temporary buffer where decoded strings are batched.
buf []byte
// offset is a buffer position where the last string was written.
offset int
}
// String converts bytes to a string.
func (c *stringConverter) String(b []byte) string {
n := len(b)
if n == 0 {
return ""
}
// Must allocate because a string doesn't fit into the buffer.
if n > cap(c.buf) {
return string(b)
}
if len(c.buf)+n > cap(c.buf) {
c.buf = make([]byte, 0, cap(c.buf))
c.offset = 0
}
c.buf = append(c.buf, b...)
b = c.buf[c.offset:]
s := toString(b)
c.offset += n
return s
}
// toString converts a byte slice to a string without allocating.
func toString(b []byte) string {
return unsafe.String(&b[0], len(b))
}

View File

@@ -18,9 +18,9 @@ func newIntrospectIntf(h *defaultHandler) *exportedIntf {
return newExportedIntf(methods, true)
}
//NewDefaultHandler returns an instance of the default
//call handler. This is useful if you want to implement only
//one of the two handlers but not both.
// NewDefaultHandler returns an instance of the default
// call handler. This is useful if you want to implement only
// one of the two handlers but not both.
//
// Deprecated: this is the default value, don't use it, it will be unexported.
func NewDefaultHandler() *defaultHandler {
@@ -52,9 +52,9 @@ func (h *defaultHandler) introspectPath(path ObjectPath) string {
if p != "/" {
p += "/"
}
if strings.HasPrefix(string(obj), p) {
node_name := strings.Split(string(obj[len(p):]), "/")[0]
subpath[node_name] = struct{}{}
if after, ok := strings.CutPrefix(string(obj), p); ok {
name, _, _ := strings.Cut(after, "/")
subpath[name] = struct{}{}
}
}
for s := range subpath {
@@ -117,7 +117,7 @@ type exportedMethod struct {
reflect.Value
}
func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) {
func (m exportedMethod) Call(args ...any) ([]any, error) {
t := m.Type()
params := make([]reflect.Value, len(args))
@@ -143,12 +143,12 @@ func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) {
ret = ret[:t.NumOut()-1]
}
}
out := make([]interface{}, len(ret))
out := make([]any, len(ret))
for i, val := range ret {
out[i] = val.Interface()
}
if nilErr || err == nil {
//concrete type to interface nil is a special case
// concrete type to interface nil is a special case
return out, nil
}
return out, err
@@ -158,7 +158,7 @@ func (m exportedMethod) NumArguments() int {
return m.Value.Type().NumIn()
}
func (m exportedMethod) ArgumentValue(i int) interface{} {
func (m exportedMethod) ArgumentValue(i int) any {
return reflect.Zero(m.Type().In(i)).Interface()
}
@@ -166,7 +166,7 @@ func (m exportedMethod) NumReturns() int {
return m.Value.Type().NumOut()
}
func (m exportedMethod) ReturnValue(i int) interface{} {
func (m exportedMethod) ReturnValue(i int) any {
return reflect.Zero(m.Type().Out(i)).Interface()
}
@@ -215,10 +215,6 @@ func (obj *exportedObj) LookupMethod(name string) (Method, bool) {
return nil, false
}
func (obj *exportedObj) isFallbackInterface() bool {
return false
}
func newExportedIntf(methods map[string]Method, includeSubtree bool) *exportedIntf {
return &exportedIntf{
methods: methods,
@@ -242,9 +238,9 @@ func (obj *exportedIntf) isFallbackInterface() bool {
return obj.includeSubtree
}
//NewDefaultSignalHandler returns an instance of the default
//signal handler. This is useful if you want to implement only
//one of the two handlers but not both.
// NewDefaultSignalHandler returns an instance of the default
// signal handler. This is useful if you want to implement only
// one of the two handlers but not both.
//
// Deprecated: this is the default value, don't use it, it will be unexported.
func NewDefaultSignalHandler() *defaultSignalHandler {

View File

@@ -7,7 +7,7 @@ on remote objects and emit or receive signals. Using the Export method, you can
arrange D-Bus methods calls to be directly translated to method calls on a Go
value.
Conversion Rules
# Conversion Rules
For outgoing messages, Go types are automatically converted to the
corresponding D-Bus types. See the official specification at
@@ -15,25 +15,25 @@ https://dbus.freedesktop.org/doc/dbus-specification.html#type-system for more
information on the D-Bus type system. The following types are directly encoded
as their respective D-Bus equivalents:
Go type | D-Bus type
------------+-----------
byte | BYTE
bool | BOOLEAN
int16 | INT16
uint16 | UINT16
int | INT32
uint | UINT32
int32 | INT32
uint32 | UINT32
int64 | INT64
uint64 | UINT64
float64 | DOUBLE
string | STRING
ObjectPath | OBJECT_PATH
Signature | SIGNATURE
Variant | VARIANT
interface{} | VARIANT
UnixFDIndex | UNIX_FD
Go type | D-Bus type
------------+-----------
byte | BYTE
bool | BOOLEAN
int16 | INT16
uint16 | UINT16
int | INT32
uint | UINT32
int32 | INT32
uint32 | UINT32
int64 | INT64
uint64 | UINT64
float64 | DOUBLE
string | STRING
ObjectPath | OBJECT_PATH
Signature | SIGNATURE
Variant | VARIANT
interface{} | VARIANT
UnixFDIndex | UNIX_FD
Slices and arrays encode as ARRAYs of their element type.
@@ -57,7 +57,7 @@ of STRUCTs. Incoming STRUCTS are represented as a slice of empty interfaces
containing the struct fields in the correct order. The Store function can be
used to convert such values to Go structs.
Unix FD passing
# Unix FD passing
Handling Unix file descriptors deserves special mention. To use them, you should
first check that they are supported on a connection by calling SupportsUnixFDs.
@@ -66,6 +66,5 @@ UnixFD's to messages that are accompanied by the given file descriptors with the
UnixFD values being substituted by the correct indices. Similarly, the indices
of incoming messages are automatically resolved. It shouldn't be necessary to use
UnixFDIndex.
*/
package dbus

View File

@@ -59,7 +59,7 @@ func (enc *encoder) padding(offset, algn int) int {
}
// Calls binary.Write(enc.out, enc.order, v) and panics on write errors.
func (enc *encoder) binwrite(v interface{}) {
func (enc *encoder) binwrite(v any) {
if err := binary.Write(enc.out, enc.order, v); err != nil {
panic(err)
}
@@ -67,7 +67,7 @@ func (enc *encoder) binwrite(v interface{}) {
// Encode encodes the given values to the underlying reader. All written values
// are aligned properly as required by the D-Bus spec.
func (enc *encoder) Encode(vs ...interface{}) (err error) {
func (enc *encoder) Encode(vs ...any) (err error) {
defer func() {
err, _ = recover().(error)
}()

View File

@@ -11,47 +11,47 @@ import (
var (
ErrMsgInvalidArg = Error{
"org.freedesktop.DBus.Error.InvalidArgs",
[]interface{}{"Invalid type / number of args"},
[]any{"Invalid type / number of args"},
}
ErrMsgNoObject = Error{
"org.freedesktop.DBus.Error.NoSuchObject",
[]interface{}{"No such object"},
[]any{"No such object"},
}
ErrMsgUnknownMethod = Error{
"org.freedesktop.DBus.Error.UnknownMethod",
[]interface{}{"Unknown / invalid method"},
[]any{"Unknown / invalid method"},
}
ErrMsgUnknownInterface = Error{
"org.freedesktop.DBus.Error.UnknownInterface",
[]interface{}{"Object does not implement the interface"},
[]any{"Object does not implement the interface"},
}
)
func MakeNoObjectError(path ObjectPath) Error {
return Error{
"org.freedesktop.DBus.Error.NoSuchObject",
[]interface{}{fmt.Sprintf("No such object '%s'", string(path))},
[]any{fmt.Sprintf("No such object '%s'", string(path))},
}
}
func MakeUnknownMethodError(methodName string) Error {
return Error{
"org.freedesktop.DBus.Error.UnknownMethod",
[]interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
[]any{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
}
}
func MakeUnknownInterfaceError(ifaceName string) Error {
return Error{
"org.freedesktop.DBus.Error.UnknownInterface",
[]interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
[]any{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
}
}
func MakeFailedError(err error) *Error {
return &Error{
"org.freedesktop.DBus.Error.Failed",
[]interface{}{err.Error()},
[]any{err.Error()},
}
}
@@ -67,7 +67,7 @@ func computeMethodName(name string, mapping map[string]string) string {
return name
}
func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
func getMethods(in any, mapping map[string]string) map[string]reflect.Value {
if in == nil {
return nil
}
@@ -91,7 +91,7 @@ func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Va
return methods
}
func getAllMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
func getAllMethods(in any, mapping map[string]string) map[string]reflect.Value {
if in == nil {
return nil
}
@@ -107,9 +107,9 @@ func getAllMethods(in interface{}, mapping map[string]string) map[string]reflect
return methods
}
func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
pointers := make([]interface{}, m.NumArguments())
decode := make([]interface{}, 0, len(body))
func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []any) ([]any, error) {
pointers := make([]any, m.NumArguments())
decode := make([]any, 0, len(body))
for i := 0; i < m.NumArguments(); i++ {
tp := reflect.TypeOf(m.ArgumentValue(i))
@@ -135,7 +135,7 @@ func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []
return pointers, nil
}
func (conn *Conn) decodeArguments(m Method, sender string, msg *Message) ([]interface{}, error) {
func (conn *Conn) decodeArguments(m Method, sender string, msg *Message) ([]any, error) {
if decoder, ok := m.(ArgumentDecoder); ok {
return decoder.DecodeArguments(conn, sender, msg, msg.Body)
}
@@ -204,23 +204,21 @@ func (conn *Conn) handleCall(msg *Message) {
reply.Headers[FieldDestination] = msg.Headers[FieldSender]
}
reply.Headers[FieldReplySerial] = MakeVariant(msg.serial)
reply.Body = make([]interface{}, len(ret))
for i := 0; i < len(ret); i++ {
reply.Body[i] = ret[i]
}
reply.Body = make([]any, len(ret))
copy(reply.Body, ret)
reply.Headers[FieldSignature] = MakeVariant(SignatureOf(reply.Body...))
if err := reply.IsValid(); err != nil {
fmt.Fprintf(os.Stderr, "dbus: dropping invalid reply to %s.%s on obj %s: %s\n", ifaceName, name, path, err)
} else {
conn.sendMessageAndIfClosed(reply, nil)
if err := conn.sendMessageAndIfClosed(reply, nil); err != nil {
if _, ok := err.(FormatError); ok {
fmt.Fprintf(os.Stderr, "dbus: replacing invalid reply to %s.%s on obj %s: %s\n", ifaceName, name, path, err)
}
}
}
}
// Emit emits the given signal on the message bus. The name parameter must be
// formatted as "interface.member", e.g., "org.freedesktop.DBus.NameLost".
func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) error {
func (conn *Conn) Emit(path ObjectPath, name string, values ...any) error {
i := strings.LastIndex(name, ".")
if i == -1 {
return errors.New("dbus: invalid method name")
@@ -237,18 +235,15 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
if len(values) > 0 {
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
}
if err := msg.IsValid(); err != nil {
return err
}
var closed bool
conn.sendMessageAndIfClosed(msg, func() {
err := conn.sendMessageAndIfClosed(msg, func() {
closed = true
})
if closed {
return ErrClosed
}
return nil
return err
}
// Export registers the given value to be exported as an object on the
@@ -279,7 +274,7 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
// the given combination of path and interface.
//
// Export returns an error if path is not a valid path name.
func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
func (conn *Conn) Export(v any, path ObjectPath, iface string) error {
return conn.ExportWithMap(v, nil, path, iface)
}
@@ -291,7 +286,7 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
// type parameter to your method signature. If the error returned is not nil,
// it is sent back to the caller as an error. Otherwise, a method reply is
// sent with the other return values as its body.
func (conn *Conn) ExportAll(v interface{}, path ObjectPath, iface string) error {
func (conn *Conn) ExportAll(v any, path ObjectPath, iface string) error {
return conn.export(getAllMethods(v, nil), path, iface, false)
}
@@ -300,7 +295,7 @@ func (conn *Conn) ExportAll(v interface{}, path ObjectPath, iface string) error
//
// 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.
func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path ObjectPath, iface string) error {
func (conn *Conn) ExportWithMap(v any, mapping map[string]string, path ObjectPath, iface string) error {
return conn.export(getMethods(v, mapping), path, iface, false)
}
@@ -314,7 +309,7 @@ func (conn *Conn) ExportWithMap(v interface{}, mapping map[string]string, path O
// Note that more specific export paths take precedence over less specific. For
// example, a method call using the ObjectPath /foo/bar/baz will call a method
// exported on /foo/bar before a method exported on /foo.
func (conn *Conn) ExportSubtree(v interface{}, path ObjectPath, iface string) error {
func (conn *Conn) ExportSubtree(v any, path ObjectPath, iface string) error {
return conn.ExportSubtreeWithMap(v, nil, path, iface)
}
@@ -323,7 +318,7 @@ 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 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 any, mapping map[string]string, path ObjectPath, iface string) error {
return conn.export(getMethods(v, mapping), path, iface, true)
}
@@ -337,16 +332,16 @@ func (conn *Conn) ExportSubtreeWithMap(v interface{}, mapping map[string]string,
// 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 {
func (conn *Conn) ExportMethodTable(methods map[string]any, 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 {
func (conn *Conn) ExportSubtreeMethodTable(methods map[string]any, 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 {
func (conn *Conn) exportMethodTable(methods map[string]any, path ObjectPath, iface string, includeSubtree bool) error {
var out map[string]reflect.Value
if methods != nil {
out = make(map[string]reflect.Value)
@@ -443,6 +438,18 @@ const (
ReleaseNameReplyNotOwner
)
func (rep ReleaseNameReply) String() string {
switch rep {
case ReleaseNameReplyReleased:
return "released"
case ReleaseNameReplyNonExistent:
return "non existent"
case ReleaseNameReplyNotOwner:
return "not owner"
}
return "unknown"
}
// RequestNameFlags represents the possible flags for a RequestName call.
type RequestNameFlags uint32
@@ -461,3 +468,17 @@ const (
RequestNameReplyExists
RequestNameReplyAlreadyOwner
)
func (rep RequestNameReply) String() string {
switch rep {
case RequestNameReplyPrimaryOwner:
return "primary owner"
case RequestNameReplyInQueue:
return "in queue"
case RequestNameReplyExists:
return "exists"
case RequestNameReplyAlreadyOwner:
return "already owner"
}
return "unknown"
}

View File

@@ -1,25 +0,0 @@
package dbus
import (
"os"
"os/user"
)
// Get returns the home directory of the current user, which is usually the
// value of HOME environment variable. In case it is not set or empty, os/user
// package is used.
//
// If linking statically with cgo enabled against glibc, make sure the
// osusergo build tag is used.
//
// If needing to do nss lookups, do not disable cgo or set osusergo.
func getHomeDir() string {
homeDir := os.Getenv("HOME")
if homeDir != "" {
return homeDir
}
if u, err := user.Current(); err == nil {
return u.HomeDir
}
return "/"
}

View File

@@ -26,10 +26,10 @@ func WithMatchOption(key, value string) MatchOption {
return MatchOption{key, value}
}
// doesn't make sense to export this option because clients can only
// subscribe to messages with signal type.
func withMatchType(typ string) MatchOption {
return WithMatchOption("type", typ)
// It does not make sense to have a public WithMatchType function
// because clients can only subscribe to messages with signal type.
func withMatchTypeSignal() MatchOption {
return WithMatchOption("type", "signal")
}
// WithMatchSender sets sender match option.

View File

@@ -108,7 +108,7 @@ type Message struct {
Type
Flags
Headers map[HeaderField]Variant
Body []interface{}
Body []any
serial uint32
}
@@ -158,7 +158,9 @@ func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
if err != nil {
return nil, err
}
binary.Read(bytes.NewBuffer(b), order, &hlength)
if err := binary.Read(bytes.NewBuffer(b), order, &hlength); err != nil {
return nil, err
}
if hlength+length+16 > 1<<27 {
return nil, InvalidMessageError("message is too long")
}
@@ -186,7 +188,7 @@ func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
}
}
if err = msg.IsValid(); err != nil {
if err = msg.validateHeader(); err != nil {
return nil, err
}
sig, _ := msg.Headers[FieldSignature].value.(Signature)
@@ -230,7 +232,7 @@ func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds
if err := msg.validateHeader(); err != nil {
return nil, err
}
var vs [7]interface{}
var vs [7]any
switch order {
case binary.LittleEndian:
vs[0] = byte('l')
@@ -265,12 +267,14 @@ func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds
return
}
enc.align(8)
body.WriteTo(&buf)
if _, err := body.WriteTo(&buf); err != nil {
return nil, err
}
if buf.Len() > 1<<27 {
return make([]int, 0), InvalidMessageError("message is too long")
return nil, InvalidMessageError("message is too long")
}
if _, err := buf.WriteTo(out); err != nil {
return make([]int, 0), err
return nil, err
}
return enc.fds, nil
}
@@ -286,8 +290,7 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error)
// IsValid checks whether msg is a valid message and returns an
// InvalidMessageError or FormatError if it is not.
func (msg *Message) IsValid() error {
var b bytes.Buffer
return msg.EncodeTo(&b, nativeEndian)
return msg.EncodeTo(io.Discard, nativeEndian)
}
func (msg *Message) validateHeader() error {

View File

@@ -9,15 +9,15 @@ import (
// BusObject is the interface of a remote object on which methods can be
// invoked.
type BusObject interface {
Call(method string, flags Flags, args ...interface{}) *Call
CallWithContext(ctx context.Context, method string, flags Flags, args ...interface{}) *Call
Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call
GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call
Call(method string, flags Flags, args ...any) *Call
CallWithContext(ctx context.Context, method string, flags Flags, args ...any) *Call
Go(method string, flags Flags, ch chan *Call, args ...any) *Call
GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...any) *Call
AddMatchSignal(iface, member string, options ...MatchOption) *Call
RemoveMatchSignal(iface, member string, options ...MatchOption) *Call
GetProperty(p string) (Variant, error)
StoreProperty(p string, value interface{}) error
SetProperty(p string, v interface{}) error
StoreProperty(p string, value any) error
SetProperty(p string, v any) error
Destination() string
Path() ObjectPath
}
@@ -30,12 +30,12 @@ type Object struct {
}
// Call calls a method with (*Object).Go and waits for its reply.
func (o *Object) Call(method string, flags Flags, args ...interface{}) *Call {
func (o *Object) Call(method string, flags Flags, args ...any) *Call {
return <-o.createCall(context.Background(), method, flags, make(chan *Call, 1), args...).Done
}
// CallWithContext acts like Call but takes a context
func (o *Object) CallWithContext(ctx context.Context, method string, flags Flags, args ...interface{}) *Call {
func (o *Object) CallWithContext(ctx context.Context, method string, flags Flags, args ...any) *Call {
return <-o.createCall(ctx, method, flags, make(chan *Call, 1), args...).Done
}
@@ -46,7 +46,7 @@ func (o *Object) CallWithContext(ctx context.Context, method string, flags Flags
// Deprecated: use (*Conn) AddMatchSignal instead.
func (o *Object) AddMatchSignal(iface, member string, options ...MatchOption) *Call {
base := []MatchOption{
withMatchType("signal"),
withMatchTypeSignal(),
WithMatchInterface(iface),
WithMatchMember(member),
}
@@ -65,7 +65,7 @@ func (o *Object) AddMatchSignal(iface, member string, options ...MatchOption) *C
// Deprecated: use (*Conn) RemoveMatchSignal instead.
func (o *Object) RemoveMatchSignal(iface, member string, options ...MatchOption) *Call {
base := []MatchOption{
withMatchType("signal"),
withMatchTypeSignal(),
WithMatchInterface(iface),
WithMatchMember(member),
}
@@ -89,16 +89,16 @@ func (o *Object) RemoveMatchSignal(iface, member string, options ...MatchOption)
//
// If the method parameter contains a dot ('.'), the part before the last dot
// specifies the interface on which the method is called.
func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...interface{}) *Call {
func (o *Object) Go(method string, flags Flags, ch chan *Call, args ...any) *Call {
return o.createCall(context.Background(), method, flags, ch, args...)
}
// GoWithContext acts like Go but takes a context
func (o *Object) GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call {
func (o *Object) GoWithContext(ctx context.Context, method string, flags Flags, ch chan *Call, args ...any) *Call {
return o.createCall(ctx, method, flags, ch, args...)
}
func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch chan *Call, args ...interface{}) *Call {
func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch chan *Call, args ...any) *Call {
if ctx == nil {
panic("nil context")
}
@@ -136,7 +136,7 @@ func (o *Object) GetProperty(p string) (Variant, error) {
// StoreProperty calls org.freedesktop.DBus.Properties.Get on the given
// object. The property name must be given in interface.member notation.
// It stores the returned property into the provided value.
func (o *Object) StoreProperty(p string, value interface{}) error {
func (o *Object) StoreProperty(p string, value any) error {
idx := strings.LastIndex(p, ".")
if idx == -1 || idx+1 == len(p) {
return errors.New("dbus: invalid property " + p)
@@ -151,7 +151,14 @@ func (o *Object) StoreProperty(p string, value interface{}) error {
// SetProperty calls org.freedesktop.DBus.Properties.Set on the given
// object. The property name must be given in interface.member notation.
func (o *Object) SetProperty(p string, v interface{}) error {
// Panics if v is not a valid Variant type.
func (o *Object) SetProperty(p string, v any) error {
// v might already be a variant...
variant, ok := v.(Variant)
if !ok {
// Otherwise, make it into one.
variant = MakeVariant(v)
}
idx := strings.LastIndex(p, ".")
if idx == -1 || idx+1 == len(p) {
return errors.New("dbus: invalid property " + p)
@@ -160,7 +167,7 @@ func (o *Object) SetProperty(p string, v interface{}) error {
iface := p[:idx]
prop := p[idx+1:]
return o.Call("org.freedesktop.DBus.Properties.Set", 0, iface, prop, v).Err
return o.Call("org.freedesktop.DBus.Properties.Set", 0, iface, prop, variant).Err
}
// Destination returns the destination that calls on (o *Object) are sent to.

View File

@@ -93,7 +93,7 @@ func (scd *sequentialSignalChannelData) bufferSignals() {
var queue []*Signal
for {
if len(queue) == 0 {
signal, ok := <- scd.in
signal, ok := <-scd.in
if !ok {
return
}

View File

@@ -22,7 +22,7 @@ type Handler interface {
// of Interface lookup is up to the implementation of
// the ServerObject. The ServerObject implementation may
// choose to implement empty string as a valid interface
// represeting all methods or not per the D-Bus specification.
// representing all methods or not per the D-Bus specification.
type ServerObject interface {
LookupInterface(name string) (Interface, bool)
}
@@ -38,17 +38,17 @@ type Interface interface {
// A Method represents the exposed methods on D-Bus.
type Method interface {
// Call requires that all arguments are decoded before being passed to it.
Call(args ...interface{}) ([]interface{}, error)
Call(args ...any) ([]any, error)
NumArguments() int
NumReturns() int
// ArgumentValue returns a representative value for the argument at position
// it should be of the proper type. reflect.Zero would be a good mechanism
// to use for this Value.
ArgumentValue(position int) interface{}
ArgumentValue(position int) any
// ReturnValue returns a representative value for the return at position
// it should be of the proper type. reflect.Zero would be a good mechanism
// to use for this Value.
ReturnValue(position int) interface{}
ReturnValue(position int) any
}
// An Argument Decoder can decode arguments using the non-standard mechanism
@@ -65,7 +65,7 @@ type ArgumentDecoder interface {
// To decode the arguments of a method the sender and message are
// provided in case the semantics of the implementer provides access
// to these as part of the method invocation.
DecodeArguments(conn *Conn, sender string, msg *Message, args []interface{}) ([]interface{}, error)
DecodeArguments(conn *Conn, sender string, msg *Message, args []any) ([]any, error)
}
// A SignalHandler is responsible for delivering a signal.
@@ -93,7 +93,7 @@ type SignalRegistrar interface {
// "org.freedesktop.DBus.Error.Failed" error. By implementing this
// interface as well a custom encoding may be provided.
type DBusError interface {
DBusError() (string, []interface{})
DBusError() (string, []any)
}
// SerialGenerator is responsible for serials generation.

View File

@@ -31,7 +31,7 @@ type Signature struct {
// SignatureOf returns the concatenation of all the signatures of the given
// values. It panics if one of them is not representable in D-Bus.
func SignatureOf(vs ...interface{}) Signature {
func SignatureOf(vs ...any) Signature {
var s string
for _, v := range vs {
s += getSignature(reflect.TypeOf(v), &depthCounter{})
@@ -183,19 +183,19 @@ func (cnt *depthCounter) Valid() bool {
return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32
}
func (cnt depthCounter) EnterArray() *depthCounter {
func (cnt *depthCounter) EnterArray() *depthCounter {
cnt.arrayDepth++
return &cnt
return cnt
}
func (cnt depthCounter) EnterStruct() *depthCounter {
func (cnt *depthCounter) EnterStruct() *depthCounter {
cnt.structDepth++
return &cnt
return cnt
}
func (cnt depthCounter) EnterDictEntry() *depthCounter {
func (cnt *depthCounter) EnterDictEntry() *depthCounter {
cnt.dictEntryDepth++
return &cnt
return cnt
}
// Try to read a single type from this string. If it was successful, err is nil
@@ -221,6 +221,9 @@ func validSingle(s string, depth *depthCounter) (err error, rem string) {
i++
rem = s[i+1:]
s = s[2:i]
if len(s) == 0 {
return SignatureError{Sig: s, Reason: "empty dict"}, ""
}
if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil {
return err, ""
}

View File

@@ -1,11 +1,12 @@
//+build !windows
//go:build !windows
// +build !windows
package dbus
import (
"errors"
"io/ioutil"
"net"
"os"
)
func init() {
@@ -27,12 +28,14 @@ func newNonceTcpTransport(keys string) (transport, error) {
if err != nil {
return nil, err
}
b, err := ioutil.ReadFile(noncefile)
b, err := os.ReadFile(noncefile)
if err != nil {
socket.Close()
return nil, err
}
_, err = socket.Write(b)
if err != nil {
socket.Close()
return nil, err
}
return NewConn(socket)

View File

@@ -1,4 +1,5 @@
//+build !windows,!solaris
//go:build !windows && !solaris
// +build !windows,!solaris
package dbus
@@ -11,10 +12,29 @@ import (
"syscall"
)
// msghead represents the part of the message header
// that has a constant size (byte order + 15 bytes).
type msghead struct {
Type Type
Flags Flags
Proto byte
BodyLen uint32
Serial uint32
HeaderLen uint32
}
type oobReader struct {
conn *net.UnixConn
oob []byte
buf [4096]byte
// The following fields are used to reduce memory allocs.
headers []header
csheader []byte
b *bytes.Buffer
r *bytes.Reader
dec *decoder
msghead
}
func (o *oobReader) Read(b []byte) (n int, err error) {
@@ -35,6 +55,14 @@ type unixTransport struct {
hasUnixFDs bool
}
func newUnixTransportFromConn(conn *net.UnixConn) transport {
t := new(unixTransport)
t.UnixConn = conn
t.hasUnixFDs = true
return t
}
func newUnixTransport(keys string) (transport, error) {
var err error
@@ -70,28 +98,36 @@ func (t *unixTransport) EnableUnixFDs() {
}
func (t *unixTransport) ReadMessage() (*Message, error) {
var (
blen, hlen uint32
csheader [16]byte
headers []header
order binary.ByteOrder
unixfds uint32
)
// To be sure that all bytes of out-of-band data are read, we use a special
// reader that uses ReadUnix on the underlying connection instead of Read
// and gathers the out-of-band data in a buffer.
if t.rdr == nil {
t.rdr = &oobReader{conn: t.UnixConn}
t.rdr = &oobReader{
conn: t.UnixConn,
// This buffer is used to decode the part of the header that has a constant size.
csheader: make([]byte, 16),
b: &bytes.Buffer{},
// The reader helps to read from the buffer several times.
r: &bytes.Reader{},
dec: &decoder{},
}
} else {
t.rdr.oob = nil
t.rdr.oob = t.rdr.oob[:0]
t.rdr.headers = t.rdr.headers[:0]
}
var (
r = t.rdr.r
b = t.rdr.b
dec = t.rdr.dec
)
// read the first 16 bytes (the part of the header that has a constant size),
// from which we can figure out the length of the rest of the message
if _, err := io.ReadFull(t.rdr, csheader[:]); err != nil {
_, err := io.ReadFull(t.rdr, t.rdr.csheader)
if err != nil {
return nil, err
}
switch csheader[0] {
var order binary.ByteOrder
switch t.rdr.csheader[0] {
case 'l':
order = binary.LittleEndian
case 'B':
@@ -99,38 +135,62 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
default:
return nil, InvalidMessageError("invalid byte order")
}
// csheader[4:8] -> length of message body, csheader[12:16] -> length of
// header fields (without alignment)
binary.Read(bytes.NewBuffer(csheader[4:8]), order, &blen)
binary.Read(bytes.NewBuffer(csheader[12:]), order, &hlen)
r.Reset(t.rdr.csheader[1:])
if err := binary.Read(r, order, &t.rdr.msghead); err != nil {
return nil, err
}
msg := &Message{
Type: t.rdr.msghead.Type,
Flags: t.rdr.msghead.Flags,
serial: t.rdr.msghead.Serial,
}
// Length of header fields (without alignment).
hlen := t.rdr.msghead.HeaderLen
if hlen%8 != 0 {
hlen += 8 - (hlen % 8)
}
if hlen+t.rdr.msghead.BodyLen+16 > 1<<27 {
return nil, InvalidMessageError("message is too long")
}
// decode headers and look for unix fds
headerdata := make([]byte, hlen+4)
copy(headerdata, csheader[12:])
if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
// Decode headers and look for unix fds.
b.Reset()
if _, err = b.Write(t.rdr.csheader[12:]); err != nil {
return nil, err
}
dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
if _, err = io.CopyN(b, t.rdr, int64(hlen)); err != nil {
return nil, err
}
dec.Reset(b, order, nil)
dec.pos = 12
vs, err := dec.Decode(Signature{"a(yv)"})
if err != nil {
return nil, err
}
Store(vs, &headers)
for _, v := range headers {
if err = Store(vs, &t.rdr.headers); err != nil {
return nil, err
}
var unixfds uint32
for _, v := range t.rdr.headers {
if v.Field == byte(FieldUnixFDs) {
unixfds, _ = v.Variant.value.(uint32)
}
}
all := make([]byte, 16+hlen+blen)
copy(all, csheader[:])
copy(all[16:], headerdata[4:])
if _, err := io.ReadFull(t.rdr, all[16+hlen:]); err != nil {
msg.Headers = make(map[HeaderField]Variant)
for _, v := range t.rdr.headers {
msg.Headers[HeaderField(v.Field)] = v.Variant
}
dec.align(8)
body := make([]byte, t.rdr.BodyLen)
if _, err = io.ReadFull(t.rdr, body); err != nil {
return nil, err
}
r.Reset(body)
if unixfds != 0 {
if !t.hasUnixFDs {
return nil, errors.New("dbus: got unix fds on unsupported transport")
@@ -147,8 +207,8 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if err != nil {
return nil, err
}
msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
if err != nil {
dec.Reset(r, order, fds)
if err = decodeMessageBody(msg, dec); err != nil {
return nil, err
}
// substitute the values in the message body (which are indices for the
@@ -173,7 +233,27 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
}
return msg, nil
}
return DecodeMessage(bytes.NewBuffer(all))
dec.Reset(r, order, nil)
if err = decodeMessageBody(msg, dec); err != nil {
return nil, err
}
return msg, nil
}
func decodeMessageBody(msg *Message, dec *decoder) error {
if err := msg.validateHeader(); err != nil {
return err
}
sig, _ := msg.Headers[FieldSignature].value.(Signature)
if sig.str == "" {
return nil
}
var err error
msg.Body, err = dec.Decode(sig)
return err
}
func (t *unixTransport) SendMessage(msg *Message) error {

View File

@@ -7,39 +7,41 @@
package dbus
/*
const int sizeofPtr = sizeof(void*);
#define _WANT_UCRED
#include <sys/types.h>
#include <sys/ucred.h>
*/
import "C"
import (
"io"
"os"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
// http://golang.org/src/pkg/syscall/ztypes_linux_amd64.go
// https://golang.org/src/syscall/ztypes_freebsd_amd64.go
//
// Note: FreeBSD actually uses a 'struct cmsgcred' which starts with
// these fields and adds a list of the additional groups for the
// sender.
type Ucred struct {
Pid int32
Uid uint32
Gid uint32
Pid int32
Uid uint32
Euid uint32
Gid uint32
}
// http://golang.org/src/pkg/syscall/types_linux.go
// https://golang.org/src/syscall/types_freebsd.go
// https://github.com/freebsd/freebsd/blob/master/sys/sys/ucred.h
// https://github.com/freebsd/freebsd/blob/master/sys/sys/socket.h
//
// The cmsgcred structure contains the above four fields, followed by
// a uint16 count of additional groups, uint16 padding to align and a
// 16 element array of uint32 for the additional groups. The size is
// the same across all supported platforms.
const (
SizeofUcred = C.sizeof_struct_ucred
SizeofCmsgcred = 84 // 4*4 + 2*2 + 16*4
)
// http://golang.org/src/pkg/syscall/sockcmsg_unix.go
func cmsgAlignOf(salen int) int {
salign := C.sizeofPtr
salign := unix.SizeofPtr
return (salen + salign - 1) & ^(salign - 1)
}
@@ -54,11 +56,11 @@ func cmsgData(h *syscall.Cmsghdr) unsafe.Pointer {
// for sending to another process. This can be used for
// authentication.
func UnixCredentials(ucred *Ucred) []byte {
b := make([]byte, syscall.CmsgSpace(SizeofUcred))
b := make([]byte, syscall.CmsgSpace(SizeofCmsgcred))
h := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
h.Level = syscall.SOL_SOCKET
h.Type = syscall.SCM_CREDS
h.SetLen(syscall.CmsgLen(SizeofUcred))
h.SetLen(syscall.CmsgLen(SizeofCmsgcred))
*((*Ucred)(cmsgData(h))) = *ucred
return b
}

View File

@@ -11,17 +11,17 @@ import (
// Variant represents the D-Bus variant type.
type Variant struct {
sig Signature
value interface{}
value any
}
// MakeVariant converts the given value to a Variant. It panics if v cannot be
// represented as a D-Bus type.
func MakeVariant(v interface{}) Variant {
func MakeVariant(v any) Variant {
return MakeVariantWithSignature(v, SignatureOf(v))
}
// MakeVariantWithSignature converts the given value to a Variant.
func MakeVariantWithSignature(v interface{}, s Signature) Variant {
func MakeVariantWithSignature(v any, s Signature) Variant {
return Variant{s, v}
}
@@ -73,7 +73,7 @@ func (v Variant) format() (string, bool) {
}
rv := reflect.ValueOf(v.value)
switch rv.Kind() {
case reflect.Slice:
case reflect.Slice, reflect.Array:
if rv.Len() == 0 {
return "[]", false
}
@@ -119,6 +119,25 @@ func (v Variant) format() (string, bool) {
}
buf.WriteByte('}')
return buf.String(), unamb
case reflect.Struct:
if rv.NumField() == 0 {
return "()", false
}
unamb := true
var buf bytes.Buffer
buf.WriteByte('(')
for i := 0; i < rv.NumField(); i++ {
s, b := MakeVariant(rv.Field(i).Interface()).format()
unamb = unamb && b
buf.WriteString(s)
buf.WriteString(",")
if i != rv.NumField()-1 {
buf.WriteString(" ")
}
}
buf.WriteByte(')')
return buf.String(), unamb
}
return `"INVALID"`, true
}
@@ -139,12 +158,12 @@ func (v Variant) String() string {
}
// Value returns the underlying value of v.
func (v Variant) Value() interface{} {
func (v Variant) Value() any {
return v.value
}
// Store converts the variant into a native go type using the same
// mechanism as the "Store" function.
func (v Variant) Store(value interface{}) error {
func (v Variant) Store(value any) error {
return storeInterfaces(v.value, value)
}

View File

@@ -67,7 +67,7 @@ func (l *varLexer) emit(t varTokenType) {
l.start = l.pos
}
func (l *varLexer) errorf(format string, v ...interface{}) lexState {
func (l *varLexer) errorf(format string, v ...any) lexState {
l.tokens = append(l.tokens, varToken{
tokError,
fmt.Sprintf(format, v...),

View File

@@ -33,7 +33,7 @@ type varNode interface {
Infer() (Signature, error)
String() string
Sigs() sigSet
Value(Signature) (interface{}, error)
Value(Signature) (any, error)
}
func varMakeNode(p *varParser) (varNode, error) {
@@ -134,7 +134,7 @@ func (s sigSet) ToArray() sigSet {
type numNode struct {
sig Signature
str string
val interface{}
val any
}
var numSigSet = sigSet{
@@ -169,7 +169,7 @@ func (n numNode) Sigs() sigSet {
return numSigSet
}
func (n numNode) Value(sig Signature) (interface{}, error) {
func (n numNode) Value(sig Signature) (any, error) {
if n.sig.str != "" && n.sig != sig {
return nil, varTypeError{n.str, sig}
}
@@ -190,7 +190,7 @@ func varMakeNumNode(tok varToken, sig Signature) (varNode, error) {
return numNode{sig: sig, val: num}, nil
}
func varNumAs(s string, sig Signature) (interface{}, error) {
func varNumAs(s string, sig Signature) (any, error) {
isUnsigned := false
size := 32
switch sig.str {
@@ -220,20 +220,20 @@ func varNumAs(s string, sig Signature) (interface{}, error) {
return nil, varTypeError{s, sig}
}
base := 10
if strings.HasPrefix(s, "0x") {
if after, ok := strings.CutPrefix(s, "0x"); ok {
base = 16
s = s[2:]
s = after
}
if strings.HasPrefix(s, "0") && len(s) != 1 {
if after, ok := strings.CutPrefix(s, "0"); ok && len(s) != 1 {
base = 8
s = s[1:]
s = after
}
if isUnsigned {
i, err := strconv.ParseUint(s, base, size)
if err != nil {
return nil, err
}
var v interface{} = i
var v any = i
switch sig.str {
case "y":
v = byte(i)
@@ -248,7 +248,7 @@ func varNumAs(s string, sig Signature) (interface{}, error) {
if err != nil {
return nil, err
}
var v interface{} = i
var v any = i
switch sig.str {
case "n":
v = int16(i)
@@ -260,8 +260,8 @@ func varNumAs(s string, sig Signature) (interface{}, error) {
type stringNode struct {
sig Signature
str string // parsed
val interface{} // has correct type
str string // parsed
val any // has correct type
}
var stringSigSet = sigSet{
@@ -285,7 +285,7 @@ func (n stringNode) Sigs() sigSet {
return stringSigSet
}
func (n stringNode) Value(sig Signature) (interface{}, error) {
func (n stringNode) Value(sig Signature) (any, error) {
if n.sig.str != "" && n.sig != sig {
return nil, varTypeError{n.str, sig}
}
@@ -407,7 +407,7 @@ func (boolNode) Sigs() sigSet {
return boolSigSet
}
func (b boolNode) Value(sig Signature) (interface{}, error) {
func (b boolNode) Value(sig Signature) (any, error) {
if sig.str != "b" {
return nil, varTypeError{b.String(), sig}
}
@@ -417,7 +417,6 @@ func (b boolNode) Value(sig Signature) (interface{}, error) {
type arrayNode struct {
set sigSet
children []varNode
val interface{}
}
func (n arrayNode) Infer() (Signature, error) {
@@ -446,7 +445,7 @@ func (n arrayNode) Sigs() sigSet {
return n.set
}
func (n arrayNode) Value(sig Signature) (interface{}, error) {
func (n arrayNode) Value(sig Signature) (any, error) {
if n.set.Empty() {
// no type information whatsoever, so this must be an empty slice
return reflect.MakeSlice(typeFor(sig.str), 0, 0).Interface(), nil
@@ -537,7 +536,7 @@ func (variantNode) Sigs() sigSet {
return variantSet
}
func (n variantNode) Value(sig Signature) (interface{}, error) {
func (n variantNode) Value(sig Signature) (any, error) {
if sig.str != "v" {
return nil, varTypeError{n.String(), sig}
}
@@ -574,7 +573,6 @@ type dictEntry struct {
type dictNode struct {
kset, vset sigSet
children []dictEntry
val interface{}
}
func (n dictNode) Infer() (Signature, error) {
@@ -614,7 +612,7 @@ func (n dictNode) Sigs() sigSet {
return r
}
func (n dictNode) Value(sig Signature) (interface{}, error) {
func (n dictNode) Value(sig Signature) (any, error) {
set := n.Sigs()
if set.Empty() {
// no type information -> empty dict
@@ -749,7 +747,7 @@ func (b byteStringNode) Sigs() sigSet {
return byteStringSet
}
func (b byteStringNode) Value(sig Signature) (interface{}, error) {
func (b byteStringNode) Value(sig Signature) (any, error) {
if sig.str != "ay" {
return nil, varTypeError{b.String(), sig}
}

4
vendor/modules.txt vendored
View File

@@ -50,8 +50,8 @@ github.com/cyphar/filepath-securejoin/pathrs-lite/procfs
# github.com/docker/go-units v0.5.0
## explicit
github.com/docker/go-units
# github.com/godbus/dbus/v5 v5.1.0
## explicit; go 1.12
# github.com/godbus/dbus/v5 v5.2.0
## explicit; go 1.20
github.com/godbus/dbus/v5
# github.com/moby/sys/capability v0.4.0
## explicit; go 1.21