summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Szyndela <adrian.s@samsung.com>2020-04-16 12:36:37 +0200
committerAdrian Szyndela <adrian.s@samsung.com>2020-04-16 12:38:07 +0200
commit039155ecf6e61dc17705aa033756ec621003c5af (patch)
tree8bcc1262f84fc29f2bbaa60b944464590ea9453c
parent4255f571aea9dbd7eba3accd1144c7df53958a7d (diff)
parentfafbca9f7ec2d004024547dda3df32becc46cf56 (diff)
downloaddbus-039155ecf6e61dc17705aa033756ec621003c5af.tar.gz
dbus-039155ecf6e61dc17705aa033756ec621003c5af.tar.bz2
dbus-039155ecf6e61dc17705aa033756ec621003c5af.zip
Merge dbus-1.12.16 into tizensubmit/tizen/20200417.133959
Change-Id: Ie55319b9a3075a1f1f12afadecc6c06c39e3dd3b
-rw-r--r--.gitignore6
-rw-r--r--.gitlab-ci.yml147
-rw-r--r--.travis.yml46
-rw-r--r--CONTRIBUTING.md392
-rw-r--r--Doxyfile.in1
-rw-r--r--HACKING356
-rw-r--r--Makefile.am28
-rw-r--r--Makefile.cvs8
-rw-r--r--NEWS1149
-rw-r--r--README3
-rw-r--r--README.cmake36
-rwxr-xr-xautogen.sh5
-rw-r--r--bus/Makefile.am87
-rw-r--r--bus/activation-helper.c2
-rw-r--r--bus/activation-helper.h2
-rw-r--r--bus/activation.c413
-rw-r--r--bus/activation.h1
-rw-r--r--bus/apparmor.c43
-rw-r--r--bus/audit.c5
-rw-r--r--bus/bus.c193
-rw-r--r--bus/bus.h8
-rw-r--r--bus/config-loader-expat.c25
-rw-r--r--bus/config-parser-common.c7
-rw-r--r--bus/config-parser-trivial.c72
-rw-r--r--bus/config-parser-trivial.h2
-rw-r--r--bus/config-parser.c988
-rw-r--r--bus/config-parser.h21
-rw-r--r--bus/connection.c170
-rw-r--r--bus/connection.h4
-rw-r--r--bus/dbus.service.in2
-rw-r--r--bus/desktop-file.c14
-rw-r--r--bus/desktop-file.h1
-rw-r--r--bus/dir-watch-inotify.c6
-rw-r--r--bus/dir-watch-kqueue.c8
-rw-r--r--bus/dispatch.c323
-rw-r--r--bus/driver.c808
-rw-r--r--bus/driver.h24
-rw-r--r--bus/main.c84
-rw-r--r--bus/messagebus-config.in178
-rwxr-xr-xbus/messagebus.in92
-rw-r--r--bus/policy.c64
-rw-r--r--bus/policy.h12
-rw-r--r--bus/rc.messagebus.in79
-rw-r--r--bus/selinux.c88
-rw-r--r--bus/selinux.h3
-rw-r--r--bus/services.c20
-rw-r--r--bus/signals.c34
-rw-r--r--bus/stats.c46
-rw-r--r--bus/system.conf.in26
-rw-r--r--bus/systemd-user/dbus.service.in2
-rw-r--r--bus/systemd-user/dbus.socket.in2
-rw-r--r--bus/sysusers.d/dbus.conf.in5
-rw-r--r--bus/test-launch-helper.c25
-rw-r--r--bus/test-main.c21
-rw-r--r--bus/test-system.c21
-rw-r--r--bus/test.c8
-rw-r--r--bus/tmpfiles.d/dbus.conf.in9
-rw-r--r--cmake/CMakeLists.txt308
-rw-r--r--cmake/ConfigureChecks.cmake20
-rw-r--r--cmake/DBus1Config.cmake.in37
-rw-r--r--cmake/DBus1Config.pkgconfig.in75
-rw-r--r--cmake/DBus1ConfigVersion.cmake.in11
-rw-r--r--cmake/bus/CMakeLists.txt67
-rw-r--r--cmake/config.h.cmake27
-rw-r--r--cmake/dbus/CMakeLists.txt48
-rw-r--r--cmake/i686-w64-mingw32.cmake20
-rw-r--r--cmake/modules/CPackInstallConfig.cmake2
-rw-r--r--cmake/modules/CheckForAbstractSockets.c33
-rw-r--r--cmake/modules/Macros.cmake89
-rw-r--r--cmake/modules/MacrosAutotools.cmake2
-rw-r--r--cmake/test/CMakeLists.txt8
-rw-r--r--cmake/tools/CMakeLists.txt19
-rw-r--r--cmake/x86_64-w64-mingw32.cmake19
-rw-r--r--configure.ac541
-rw-r--r--dbus-1.pc.in3
-rw-r--r--dbus/Makefile.am51
-rw-r--r--dbus/dbus-address.c16
-rw-r--r--dbus/dbus-address.h21
-rw-r--r--dbus/dbus-asv-util.c6
-rw-r--r--dbus/dbus-asv-util.h18
-rw-r--r--dbus/dbus-auth-script.c173
-rw-r--r--dbus/dbus-auth-util.c8
-rw-r--r--dbus/dbus-auth.c57
-rw-r--r--dbus/dbus-auth.h7
-rw-r--r--dbus/dbus-bus.c8
-rw-r--r--dbus/dbus-connection.c19
-rw-r--r--dbus/dbus-connection.h30
-rw-r--r--dbus/dbus-credentials.c6
-rw-r--r--dbus/dbus-dataslot.c2
-rw-r--r--dbus/dbus-errors.h2
-rw-r--r--dbus/dbus-file-win.c2
-rw-r--r--dbus/dbus-hash.c345
-rw-r--r--dbus/dbus-hash.h14
-rw-r--r--dbus/dbus-internals.c86
-rw-r--r--dbus/dbus-internals.h29
-rw-r--r--dbus/dbus-keyring.c8
-rw-r--r--dbus/dbus-list.c55
-rw-r--r--dbus/dbus-macros.h23
-rw-r--r--dbus/dbus-mainloop.c9
-rw-r--r--dbus/dbus-marshal-basic.c52
-rw-r--r--dbus/dbus-marshal-basic.h1
-rw-r--r--dbus/dbus-marshal-byteswap-util.c2
-rw-r--r--dbus/dbus-marshal-byteswap.c4
-rw-r--r--dbus/dbus-marshal-header.c4
-rw-r--r--dbus/dbus-marshal-recursive-util.c138
-rw-r--r--dbus/dbus-marshal-recursive.c29
-rw-r--r--dbus/dbus-marshal-validate-util.c99
-rw-r--r--dbus/dbus-marshal-validate.c64
-rw-r--r--dbus/dbus-marshal-validate.h6
-rw-r--r--dbus/dbus-memory.c23
-rw-r--r--dbus/dbus-memory.h1
-rw-r--r--dbus/dbus-message-factory.c25
-rw-r--r--dbus/dbus-message-internal.h34
-rw-r--r--dbus/dbus-message-util.c117
-rw-r--r--dbus/dbus-message.c653
-rw-r--r--dbus/dbus-message.h62
-rw-r--r--dbus/dbus-misc.c65
-rw-r--r--dbus/dbus-misc.h3
-rw-r--r--dbus/dbus-nonce.c55
-rw-r--r--dbus/dbus-object-tree.c44
-rw-r--r--dbus/dbus-pending-call-internal.h7
-rw-r--r--dbus/dbus-pending-call.c38
-rw-r--r--dbus/dbus-pending-call.h19
-rw-r--r--dbus/dbus-server-protected.h1
-rw-r--r--dbus/dbus-server-socket.c28
-rw-r--r--dbus/dbus-server-unix.c33
-rw-r--r--dbus/dbus-server.c43
-rw-r--r--dbus/dbus-server.h19
-rw-r--r--dbus/dbus-sha.c15
-rw-r--r--dbus/dbus-shell.c14
-rw-r--r--dbus/dbus-signature.c3
-rw-r--r--dbus/dbus-socket-set-epoll.c26
-rw-r--r--dbus/dbus-spawn-test.c288
-rw-r--r--dbus/dbus-spawn-win.c392
-rw-r--r--dbus/dbus-spawn.c373
-rw-r--r--dbus/dbus-spawn.h9
-rw-r--r--dbus/dbus-string-util.c16
-rw-r--r--dbus/dbus-string.h25
-rw-r--r--dbus/dbus-sysdeps-pthread.c2
-rw-r--r--dbus/dbus-sysdeps-thread-win.c2
-rw-r--r--dbus/dbus-sysdeps-unix.c450
-rw-r--r--dbus/dbus-sysdeps-unix.h17
-rw-r--r--dbus/dbus-sysdeps-util-unix.c422
-rw-r--r--dbus/dbus-sysdeps-util-win.c266
-rw-r--r--dbus/dbus-sysdeps-util.c6
-rw-r--r--dbus/dbus-sysdeps-win.c568
-rw-r--r--dbus/dbus-sysdeps-win.h4
-rw-r--r--dbus/dbus-sysdeps.c26
-rw-r--r--dbus/dbus-sysdeps.h108
-rw-r--r--dbus/dbus-test-main.c3
-rw-r--r--dbus/dbus-test.c4
-rw-r--r--dbus/dbus-timeout.c6
-rwxr-xr-xdbus/dbus-transport-kdbus.c2
-rw-r--r--dbus/dbus-transport-socket.c30
-rw-r--r--dbus/dbus-transport.c41
-rw-r--r--dbus/dbus-userdb-util.c2
-rw-r--r--dbus/dbus-userdb.c12
-rw-r--r--dbus/dbus-uuidgen.h3
-rw-r--r--dbus/dbus-watch.c8
-rw-r--r--dbus/dbus.h4
-rw-r--r--dbus/versioninfo.rc.in32
-rw-r--r--doc/.gitignore2
-rw-r--r--doc/Makefile.am36
-rw-r--r--doc/dbus-api-design.duck45
-rw-r--r--doc/dbus-daemon.1.xml.in446
-rw-r--r--doc/dbus-launch.1.xml.in34
-rw-r--r--doc/dbus-send.1.xml.in2
-rw-r--r--doc/dbus-specification.xml1900
-rw-r--r--doc/dbus-test-tool.1.xml.in4
-rw-r--r--doc/doxygen_to_devhelp.xsl10
-rw-r--r--doc/introspect.dtd2
-rw-r--r--doc/introspect.xsl8
-rw-r--r--doc/system-activation.txt3
-rw-r--r--m4/ax_ac_append_to_file.m432
-rw-r--r--m4/ax_ac_print_to_file.m432
-rw-r--r--m4/ax_add_am_macro_static.m428
-rw-r--r--m4/ax_am_macros_static.m438
-rw-r--r--m4/ax_code_coverage.m4272
-rw-r--r--m4/ax_file_escapes.m430
-rw-r--r--m4/compiler.m467
-rw-r--r--m4/tp-compiler-flag.m443
-rw-r--r--m4/tp-compiler-warnings.m449
-rw-r--r--packaging/coverage.txt2
-rw-r--r--packaging/dbus.spec16
-rw-r--r--test/Makefile.am193
-rw-r--r--test/break-loader.c762
-rw-r--r--test/corrupt.c37
-rw-r--r--test/data/auth/cookie-sha1-username.auth-script12
-rw-r--r--test/data/auth/cookie-sha1.auth-script11
-rw-r--r--test/data/dbus-installed-tests.aaprofile.in98
-rw-r--r--test/data/invalid-config-files/impossible-send.conf6
-rw-r--r--test/data/invalid-config-files/send-and-receive.conf6
-rw-r--r--test/data/systemd-activation/com.example.ReceiveDeniedByAppArmorLabel.service.in5
-rw-r--r--test/data/systemd-activation/com.example.SendDeniedByAppArmorLabel.service.in5
-rw-r--r--test/data/systemd-activation/com.example.SendDeniedByAppArmorName.service4
-rw-r--r--test/data/systemd-activation/com.example.SendDeniedByNonexistentAppArmorLabel.service.in6
-rw-r--r--test/data/systemd-activation/com.example.SystemdActivatable3.service4
-rw-r--r--test/data/systemd-activation/com.example.SystemdActivatable3.service.in7
-rw-r--r--test/data/valid-config-files/as-another-user.conf.in28
-rw-r--r--test/data/valid-config-files/count-fds.conf.in22
-rw-r--r--test/data/valid-config-files/forbidding.conf.in10
-rw-r--r--test/data/valid-config-files/incoming-limit.conf.in3
-rw-r--r--test/data/valid-config-files/max-completed-connections.conf.in18
-rw-r--r--test/data/valid-config-files/max-connections-per-user.conf.in18
-rw-r--r--test/data/valid-config-files/max-match-rules-per-connection.conf.in18
-rw-r--r--test/data/valid-config-files/max-names-per-connection.conf.in18
-rw-r--r--test/data/valid-config-files/max-replies-per-connection.conf.in18
-rw-r--r--test/data/valid-config-files/pending-fd-timeout.conf.in20
-rw-r--r--test/data/valid-config-files/standard-session-dirs.conf8
-rw-r--r--test/data/valid-config-files/systemd-activation.conf.in2
-rw-r--r--test/data/valid-introspection-files/lots-of-types.xml93
-rw-r--r--test/dbus-daemon-eavesdrop.c30
-rw-r--r--test/dbus-daemon.c1659
-rw-r--r--test/fdpass.c42
-rw-r--r--test/integration/transient-services.sh191
-rw-r--r--test/internals/printf.c4
-rw-r--r--test/internals/refs.c13
-rw-r--r--test/internals/server-oom.c140
-rw-r--r--test/internals/syslog.c62
-rw-r--r--test/internals/variant.c572
-rw-r--r--test/loopback.c170
-rw-r--r--test/manual-backtrace.c62
-rw-r--r--test/manual-dir-iter.c4
-rw-r--r--test/manual-paths.c53
-rw-r--r--test/message.c311
-rw-r--r--test/monitor.c451
-rw-r--r--test/name-test/Makefile.am34
-rwxr-xr-xtest/name-test/run-test.sh16
-rw-r--r--test/name-test/test-activation-forking.py8
-rw-r--r--test/name-test/test-autolaunch.c10
-rw-r--r--test/name-test/test-ids.c30
-rw-r--r--test/name-test/test-pending-call-dispatch.c45
-rw-r--r--test/name-test/test-pending-call-timeout.c22
-rw-r--r--test/name-test/test-privserver-client.c17
-rw-r--r--test/name-test/test-privserver.c22
-rw-r--r--test/name-test/test-shutdown.c13
-rw-r--r--test/name-test/test-threads-init.c38
-rwxr-xr-xtest/name-test/test-wait-for-echo.py6
-rw-r--r--test/name-test/tmp-session-like-system.conf2
-rw-r--r--test/relay.c39
-rw-r--r--test/sd-activation.c468
-rw-r--r--test/shell-test.c32
-rw-r--r--test/spawn-test.c6
-rw-r--r--test/test-apparmor-activation.sh57
-rwxr-xr-xtest/test-dbus-daemon-fork.sh106
-rwxr-xr-xtest/test-dbus-launch-eval.sh74
-rwxr-xr-xtest/test-dbus-launch-x11.sh267
-rw-r--r--test/test-names.c2
-rw-r--r--test/test-segfault.c29
-rw-r--r--test/test-service.c7
-rw-r--r--test/test-shell-service.c2
-rw-r--r--test/test-utils-glib.c258
-rw-r--r--test/test-utils-glib.h25
-rw-r--r--test/test-utils.c2
-rw-r--r--test/thread-blocking.c299
-rw-r--r--test/uid-permissions.c2
-rwxr-xr-xtest/unused-code-gc.py242
-rw-r--r--tools/Makefile.am21
-rw-r--r--tools/Win32.Manifest10
-rw-r--r--tools/ci-Dockerfile.in10
-rwxr-xr-xtools/ci-build.sh315
-rwxr-xr-xtools/ci-install.sh188
-rw-r--r--tools/dbus-cleanup-sockets.c1
-rw-r--r--tools/dbus-echo.c6
-rw-r--r--tools/dbus-launch-win.c6
-rw-r--r--tools/dbus-launch-x11.c9
-rw-r--r--tools/dbus-launch.c173
-rw-r--r--tools/dbus-launch.h4
-rw-r--r--tools/dbus-monitor.c14
-rw-r--r--tools/dbus-print-message.c33
-rw-r--r--tools/dbus-run-session.c12
-rw-r--r--tools/dbus-send.c110
-rw-r--r--tools/dbus-spam.c15
-rw-r--r--tools/dbus-update-activation-environment.c13
-rw-r--r--tools/dbus-uuidgen.c7
-rw-r--r--tools/lcov.am43
-rwxr-xr-xtools/run-with-tmp-session-bus.sh5
277 files changed, 17628 insertions, 7241 deletions
diff --git a/.gitignore b/.gitignore
index 8d746822..e1a8c337 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
*.rej
*.o
*~
+/.ccache/
+/aminclude_static.am
/build-aux/
compile
config.cache
@@ -37,6 +39,10 @@ config.h.in
*.gcda
*.gcno
tags
+/bus/tmpfiles.d/dbus.conf
+/dbus-1.*-coverage.info
+/dbus-1.*-coverage.info.tmp
+/dbus-1.*-coverage/
/dbus-1.*/
/dbus-1.*.tar.*
/lcov.html/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 00000000..5c88527a
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,147 @@
+# Copyright © 2015-2018 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+image: debian:stretch-slim
+
+stages:
+ - build
+
+before_script:
+ - ./tools/ci-install.sh
+ - mkdir -p .ccache
+ - export CCACHE_BASEDIR="$(pwd)"
+ - export CCACHE_DIR="$CCACHE_BASEDIR/.ccache"
+ # Debian's ccache package creates symlinks here for all supported
+ # compilers
+ - export PATH="/usr/lib/ccache:$PATH"
+
+cache:
+ key: dbus-1.12-${CI_JOB_NAME}
+ paths:
+ - .ccache/
+
+variables:
+ ci_in_docker: "yes"
+ ci_parallel: "2"
+ ci_sudo: "yes"
+ ci_distro: "debian"
+ ci_suite: "stretch"
+
+build:production:
+ stage: build
+ image: "debian:stretch-slim"
+ variables:
+ ci_variant: "production"
+ script: &script
+ - chown -R user .
+ - runuser -u user ./tools/ci-build.sh
+
+build:debug:
+ stage: build
+ image: "debian:stretch-slim"
+ variables:
+ ci_variant: "debug"
+ script: *script
+
+build:reduced:
+ stage: build
+ when: manual
+ image: "debian:stretch-slim"
+ variables:
+ ci_variant: "reduced"
+ script: *script
+
+build:legacy:
+ stage: build
+ when: manual
+ image: "debian:stretch-slim"
+ variables:
+ ci_variant: "legacy"
+ script: *script
+
+build:cmake:
+ stage: build
+ image: "debian:stretch-slim"
+ variables:
+ ci_buildsys: "cmake"
+ script: *script
+
+build:i686-w64-mingw32-debug:
+ stage: build
+ image: "debian:stretch-slim"
+ variables:
+ ci_host: "i686-w64-mingw32"
+ ci_variant: "debug"
+ script: *script
+
+build:i686-w64-mingw32-cmake:
+ stage: build
+ when: manual
+ image: "debian:stretch-slim"
+ variables:
+ ci_buildsys: "cmake"
+ ci_host: "i686-w64-mingw32"
+ script: *script
+
+build:x86_64-w64-mingw32:
+ stage: build
+ image: "debian:stretch-slim"
+ variables:
+ ci_host: "i686-w64-mingw32"
+ script: *script
+
+build:x86_64-w64-mingw32-cmake-debug:
+ stage: build
+ when: manual
+ image: "debian:stretch-slim"
+ variables:
+ ci_buildsys: "cmake"
+ ci_host: "i686-w64-mingw32"
+ ci_variant: "debug"
+ script: *script
+
+build:jessie:
+ when: manual
+ stage: build
+ image: "debian:jessie-slim"
+ variables:
+ ci_suite: "jessie"
+ script: *script
+
+build:buster:
+ when: manual
+ stage: build
+ image: "debian:buster-slim"
+ variables:
+ ci_suite: "buster"
+ script: *script
+
+build:xenial:
+ when: manual
+ stage: build
+ image: "ubuntu:xenial"
+ variables:
+ ci_distro: "ubuntu"
+ ci_suite: "xenial"
+ script: *script
+
+# vim:set sw=2 sts=2 et:
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..9e68d013
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,46 @@
+# Copyright © 2015-2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+sudo: required
+dist: xenial
+language: c
+script:
+ - ./tools/ci-install.sh
+ # python-dbus and python-gi aren't available to Travis's version of
+ # Python in /opt, which it uses as a default
+ - PYTHON=/usr/bin/python ci_parallel=2 ci_sudo=yes ./tools/ci-build.sh
+
+env:
+ - ci_variant=production
+ - ci_variant=debug
+ - ci_variant=reduced
+ - ci_variant=legacy
+ - ci_buildsys=cmake
+ - ci_host=i686-w64-mingw32
+ - ci_host=i686-w64-mingw32 ci_buildsys=cmake ci_variant=debug
+ - ci_host=x86_64-w64-mingw32 ci_variant=debug
+ - ci_host=x86_64-w64-mingw32 ci_buildsys=cmake
+ - ci_docker=debian:jessie-slim ci_distro=debian ci_suite=jessie
+ - ci_docker=debian:stretch-slim ci_distro=debian ci_suite=stretch
+ - ci_docker=debian:buster-slim ci_distro=debian ci_suite=buster
+
+# vim:set sw=2 sts=2 et:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..87c602ed
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,392 @@
+# Contributing to dbus
+
+The guidelines in this file are the ideals; it's better to send a
+not-fully-following-guidelines patch than no patch at all, though. We
+can always polish it up.
+
+## Source code and issue tracking
+
+Source code and issue tracking for the D-Bus specification and its
+reference implementation 'dbus' are provided by freedesktop.org Gitlab:
+<https://gitlab.freedesktop.org/dbus/dbus>.
+
+## Reporting security vulnerabilities
+
+If you find a security vulnerability that is not known to the public,
+please report it privately to dbus-security@lists.freedesktop.org
+or by reporting a Gitlab issue at
+https://gitlab.freedesktop.org/dbus/dbus/issues/new and marking it
+as "confidential".
+
+## Mailing list
+
+The D-Bus mailing list is dbus@lists.freedesktop.org; discussion of
+protocol enhancements, new implementations, etc. should go there.
+
+## Code of Conduct
+
+As a freedesktop.org project, dbus follows the Contributor Covenant,
+found at: https://www.freedesktop.org/wiki/CodeOfConduct
+
+Please conduct yourself in a respectful and civilised manner when
+interacting with community members on mailing lists, IRC, or bug
+trackers. The community represents the project as a whole, and abusive
+or bullying behaviour is not tolerated by the project.
+
+## Development
+
+D-Bus uses Git as its version control system. The main repository is
+hosted on freedesktop.org Gitlab. To clone D-Bus, execute one of the
+following commands:
+
+ git clone https://gitlab.freedesktop.org/dbus/dbus.git
+ git clone git@gitlab.freedesktop.org:dbus/dbus.git
+
+The second form is the one that allows pushing, but it also requires
+an SSH account on the server. The first form allows anonymous
+checkouts.
+
+### Branches
+
+D-Bus development happens in multiple branches in parallel. The main
+branches are the current stable branch, with an even minor number (like
+1.0, 1.2 and 1.4), and the next development branch, with the next odd
+number. At the time of writing, the stable branch is dbus 1.12.x and
+the development branch is dbus 1.13.x, leading to a new 1.14.x stable
+branch in future.
+
+Stable branches are named after the version number itself (`dbus-1.2`,
+`dbus-1.4`), whereas the development branch is simply known as
+`master`.
+
+New features, enhancements, minor bug fixes, and bug fixes that are
+unusually intrusive should always be based on the `master` branch.
+
+Fixes for significant bugs should be developed on the `master` branch
+and cherry-picked to the most recent stable branch.
+
+Depending on the release cycles of various Linux distributions, some
+older stable branches might continue to receive fixes for security
+vulnerabilities (and sometimes major non-security bugs) for a time.
+These are announced on the D-Bus mailing list.
+
+Old development branches are not supported at all, and will not receive
+any bug fixes - not even for security vulnerabilities. Please do not
+use a development branch like 1.13.x in your OS distribution, unless
+you can guarantee that you will upgrade to the next stable branch such
+as 1.14.x when it becomes available.
+
+### Commits
+
+If you are making changes that you wish to be incorporated upstream,
+please do as small commits to your local git tree that are individually
+correct, so there is a good history of your changes.
+
+The first line of the commit message should be a single sentence that
+describes the change, optionally with a prefix that identifies the
+area of the code that is affected.
+
+The body of the commit message should describe what the patch changes
+and why, and also note any particular side effects. This shouldn't be
+empty on most of the cases. It shouldn't take a lot of effort to write a
+commit message for an obvious change, so an empty commit message body is
+only acceptable if the questions "What?" and "Why?" are already answered
+on the one-line summary.
+
+The lines of the commit message should have at most 76 characters,
+to cope with the way git log presents them.
+
+See [notes on commit messages](https://who-t.blogspot.com/2009/12/on-commit-messages.html),
+[A Note About Git Commit Messages](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
+or [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/)
+for recommended reading on writing high-quality commit messages.
+
+Your patches should also include a Signed-off-by line with your name and
+email address, indicating that your contribution follows the [Developer's
+Certificate of Origin](https://developercertificate.org/). If you're
+not the patch's original author, you should also gather S-o-b's by
+them (and/or whomever gave the patch to you.) The significance of this
+is that it certifies that you created the patch, that it was created
+under an appropriate open source license, or provided to you under those
+terms. This lets us indicate a chain of responsibility for the copyright
+status of the code.
+
+We won't reject patches that lack S-o-b, but it is strongly recommended.
+
+### Sending a merge request
+
+When you consider your changes to be ready for merging to mainline:
+
+* create a personal fork of <https://gitlab.freedesktop.org/dbus/dbus>
+ on freedesktop.org Gitlab
+* push your changes to your personal fork as a branch
+* create a merge request at
+ <https://gitlab.freedesktop.org/dbus/dbus/merge_requests>
+
+### Security guidelines
+
+Most of D-Bus is security sensitive. Guidelines related to that:
+
+ - avoid `memcpy()`, `sprintf()`, `strlen()`, `snprintf()`, `strlcat()`,
+ `strstr()`, `strtok()`, or any of this stuff. Use `DBusString`.
+ If `DBusString` doesn't have the feature you need, add it
+ to `DBusString`.
+
+ There are some exceptions, for example
+ if your strings are just used to index a hash table
+ and you don't do any parsing/modification of them, perhaps
+ `DBusString` is wasteful and wouldn't help much. But definitely
+ if you're doing any parsing, reallocation, etc. use `DBusString`.
+
+ - do not include system headers outside of `dbus-memory.c`,
+ `dbus-sysdeps.c`, and other places where they are already
+ included. This gives us one place to audit all external
+ dependencies on features in libc, etc.
+
+ - do not use libc features that are "complicated"
+ and may contain security holes. For example, you probably shouldn't
+ try to use `regcomp()` to compile an untrusted regular expression.
+ Regular expressions are just too complicated, and there are many
+ different libc implementations out there.
+
+ - we need to design the message bus daemon (and any similar features)
+ to use limited privileges, run in a chroot jail, and so on.
+
+http://vsftpd.beasts.org/ has other good security suggestions.
+
+### Coding Style
+
+ - Please follow the coding style and indentation of nearby code.
+
+ - C code uses GNU coding conventions (approximately "gnu" style in
+ Emacs), with GLib-like extensions (e.g. lining up function arguments).
+
+ - Write docs for all non-static functions and structs and so on. try
+ `doxygen Doxyfile` prior to commit and try not to cause any new
+ warnings.
+
+ - All external interfaces (network protocols, file formats, etc.)
+ should have documented specifications sufficient to allow an
+ alternative implementation to be written. Our implementation should
+ be strict about specification compliance (should not for example
+ heuristically parse a file and accept not-well-formed
+ data). Avoiding heuristics is also important for security reasons;
+ if it looks funny, ignore it (or exit, or disconnect).
+
+### Licensing
+
+Please match the existing licensing (a dual-license: AFL-2.1 or GPL-2+,
+recipient's choice). Entirely new modules can be placed under a more
+permissive license: to avoid license proliferation, our preferred
+permissive license is the variant of the MIT/X11 license used by the
+Expat XML library (for example see the top of tools/ci-build.sh).
+
+### Build systems
+
+The primary build system for dbus uses the GNU Autotools suite (Autoconf,
+Automake and Libtool). This build system is strongly recommended for
+Unix OS integrators. It can also be used to compile dbus for Windows
+using the mingw-w64 compiler suite, either by cross-compiling on a Unix
+system or by using an environment like MSYS2 on Windows.
+
+There is also a CMake build system. This is primarily there to make it
+easier to build dbus on Windows, using either a MSYS2/mingw environment
+or the MSVC compiler from Microsoft Visual Studio. It can also be used
+on a GNU/Linux system, but this is not recommended for OS integrators.
+
+Changes contributed to dbus must not break the build for either of these
+build systems. It is OK for the CMake build system to support fewer
+options, support fewer operating systems, have less test coverage or
+build fewer non-essential programs, but it must continue to work on at
+least GNU/Linux and Windows.
+
+### Environment variables
+
+These are some of the environment variables that are used by the D-Bus
+client library.
+
+* `DBUS_VERBOSE=1`
+
+ Turns on printing verbose messages. This only works if D-Bus has been
+ compiled with `--enable-verbose-mode`.
+
+* `DBUS_MALLOC_FAIL_NTH=n`
+
+ Can be set to a number, causing every *n*th call to `dbus_alloc` or
+ `dbus_realloc` to fail. This only works if D-Bus has been compiled with
+ `--enable-embedded-tests`.
+
+* `DBUS_MALLOC_FAIL_GREATER_THAN=n`
+
+ Can be set to a number, causing every call to `dbus_alloc` or
+ `dbus_realloc` to fail if the number of bytes to be allocated is greater
+ than the specified number. This only works if D-Bus has been compiled with
+ `--enable-embedded-tests`.
+
+* `DBUS_TEST_MALLOC_FAILURES=n`
+
+ Many of the D-Bus tests will run over and over, once for each `malloc`
+ involved in the test. Each run will fail a different `malloc`, plus some
+ number of `malloc`s following that malloc (because a fair number of bugs
+ only happen if two or more `malloc`s fail in a row, e.g. error recovery
+ that itself involves `malloc`). This environment variable sets the
+ number of consecutive `malloc`s to fail.
+
+ Here's why you care: If set to 0, then the `malloc` checking is skipped,
+ which makes the test suite a lot faster. Just run with this
+ environment variable unset before you commit.
+
+### Tests
+
+Please try to write test coverage for all new functionality.
+We have two broad categories of tests.
+
+The *modular tests* are enabled by configuring with
+`--enable-modular-tests`. These mostly use GLib's GTest framework,
+and are standalone programs that do not affect the contents of the
+production dbus library and programs. Most of them can be installed
+alongside the library and programs by configuring with
+`--enable-installed-tests`.
+
+The *embedded tests* are enabled by configuring with
+`--enable-embedded-tests`. Unlike the modular tests, enabling the
+embedded tests adds special code to libdbus and dbus-daemon, some of
+which may harm performance or security. A production version of dbus
+that will be included in an operating system should never have the
+embedded tests enabled.
+
+If possible, new test coverage should be provided via modular tests,
+preferably using GLib's GTest framework. `test/dbus-daemon.c` is a good
+example.
+
+## Information for maintainers
+
+This section is not directly relevant to infrequent contributors.
+
+### Releasing
+
+To make a release of D-Bus, do the following:
+
+ - check out a fresh copy from Git
+
+ - verify that the libtool versioning/library soname is
+ changed if it needs to be, or not changed if not
+
+ - update the file NEWS based on the git history
+
+ - verify that the version number of dbus-specification.xml is
+ changed if it needs to be; if changes have been made, update the
+ release date in that file
+
+ - update the AUTHORS file with "make update-authors" if necessary
+
+ - the version number should have major.minor.micro, even
+ if micro is 0, i.e. "1.0.0" and "1.2.0" not "1.0"/"1.2"; the micro
+ version should be even for releases, and odd for intermediate snapshots
+
+ - "make distcheck" (DO NOT just "make dist" - pass the check!)
+
+ - if make distcheck fails, fix it.
+
+ - once distcheck succeeds, "git commit -a". This is the version
+ of the tree that corresponds exactly to the released tarball.
+
+ - tag the tree with "git tag -s -m 'Released X.Y.Z' dbus-X.Y.Z"
+ where X.Y.Z is the version of the release. If you can't sign
+ then simply created an unsigned annotated tag:
+ "git tag -a -m 'Released X.Y.Z' dbus-X.Y.Z".
+
+ - bump the version number up in configure.ac (so the micro version is odd),
+ and commit it. Make sure you do this *after* tagging the previous
+ release! The idea is that git has a newer version number
+ than anything released. Similarly, bump the version number of
+ dbus-specification.xml and set the release date to "(not finalized)".
+
+ - merge the branch you've released to the chronologically-later
+ branch (usually "master"). You'll probably have to fix a merge
+ conflict in configure.ac (the version number).
+
+ - push your changes and the tag to the central repository with
+ git push origin master dbus-X.Y dbus-X.Y.Z
+
+ - scp your tarball to freedesktop.org server and copy it to
+ dbus.freedesktop.org:/srv/dbus.freedesktop.org/www/releases/dbus/dbus-X.Y.Z.tar.gz.
+ This should be possible if you're in group "dbus"
+
+ - Update the online documentation with `make -C doc maintainer-upload-docs`.
+
+ - update the wiki page http://www.freedesktop.org/Software/dbus by
+ adding the new release under the Download heading. Then, cut the
+ link and changelog for the previous that was there.
+
+ - post to dbus@lists.freedesktop.org announcing the release.
+
+### Making a ".0" stable release
+
+We create a branch for each stable release. The branch name should be
+dbus-X.Y which is a branch that has releases versioned X.Y.Z;
+changes on a stable branch should be limited to significant bug fixes.
+
+Because we won't make minor changes like keeping up with the latest
+deprecations on a stable branch, stable branches should turn off the
+gcc warning for deprecated declarations (e.g. see commit 4ebb275ab7).
+
+Be extra-careful not to merge master (or any branch based on master) into a
+stable branch.
+
+To branch:
+
+ git branch dbus-X.Y
+
+and upload the branch tag to the server:
+
+ git push origin dbus-X.Y
+
+To develop in this branch:
+
+ git checkout dbus-X.Y
+
+### Code reviews
+
+The commit rules are approximately these:
+
+ - Fixes that don't affect API or protocol can be committed
+ if any one qualified reviewer other than patch author
+ reviews and approves
+
+ - For fixes that do affect API or protocol, two people
+ in the reviewer group have to review and approve the commit.
+
+ - If there's a live unresolved controversy about a change,
+ don't commit it while the argument is still raging.
+
+ - At their discretion, members of the reviewer group may also commit
+ branches/patches under these conditions:
+
+ - the branch does not add or change API, ABI or wire-protocol
+
+ - the branch solves a known problem and is covered by the regression tests
+
+ - there are no objections from the rest of the review group within
+ a week of the merge request being opened
+
+ - the committer gets a positive review on the merge request from someone
+ they consider qualified to review the change (e.g. a colleague with D-Bus
+ experience; not necessarily a member of the reviewer group)
+
+ - Regardless of reviews, to commit a patch:
+
+ - `make check` must pass
+ - the test suite must be extended to cover the new code
+ as much as reasonably feasible (see Tests above)
+ - the patch has to follow the portability, security, and
+ style guidelines
+ - the patch should as much as reasonable do one thing,
+ not many unrelated changes
+
+ No reviewer should approve a patch without these attributes, and
+ failure on these points is grounds for reverting the patch.
+
+The reviewer group that can approve patches consists of the members
+of <https://gitlab.freedesktop.org/dbus/dbus/project_members> with
+"Maintainer" or "Owner" status.
diff --git a/Doxyfile.in b/Doxyfile.in
index f0a37eda..dbbdb4f7 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -102,6 +102,7 @@ DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
+HTML_TIMESTAMP = NO
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
diff --git a/HACKING b/HACKING
deleted file mode 100644
index 2fed9e6c..00000000
--- a/HACKING
+++ /dev/null
@@ -1,356 +0,0 @@
-The guidelines in this file are the ideals; it's better to send a
-not-fully-following-guidelines patch than no patch at all, though. We
-can always polish it up.
-
-Mailing list
-===
-
-The D-Bus mailing list is dbus@lists.freedesktop.org; discussion
-of patches, etc. should go there.
-
-Security
-===
-
-If you find a security vulnerability that is not known to the public,
-please report it privately to dbus-security@lists.freedesktop.org
-or by reporting a freedesktop.org bug that is marked as
-restricted to the "D-BUS security group".
-
-Most of D-Bus is security sensitive. Guidelines related to that:
-
- - avoid memcpy(), sprintf(), strlen(), snprintf, strlcat(),
- strstr(), strtok(), or any of this stuff. Use DBusString.
- If DBusString doesn't have the feature you need, add it
- to DBusString.
-
- There are some exceptions, for example
- if your strings are just used to index a hash table
- and you don't do any parsing/modification of them, perhaps
- DBusString is wasteful and wouldn't help much. But definitely
- if you're doing any parsing, reallocation, etc. use DBusString.
-
- - do not include system headers outside of dbus-memory.c,
- dbus-sysdeps.c, and other places where they are already
- included. This gives us one place to audit all external
- dependencies on features in libc, etc.
-
- - do not use libc features that are "complicated"
- and may contain security holes. For example, you probably shouldn't
- try to use regcomp() to compile an untrusted regular expression.
- Regular expressions are just too complicated, and there are many
- different libc's out there.
-
- - we need to design the message bus daemon (and any similar features)
- to use limited privileges, run in a chroot jail, and so on.
-
-http://vsftpd.beasts.org/ has other good security suggestions.
-
-Coding Style
-===
-
- - The C library uses GNU coding conventions, with GLib-like
- extensions (e.g. lining up function arguments). The
- Qt wrapper uses KDE coding conventions.
-
- - Write docs for all non-static functions and structs and so on. try
- "doxygen Doxyfile" prior to commit and be sure there are no
- warnings printed.
-
- - All external interfaces (network protocols, file formats, etc.)
- should have documented specifications sufficient to allow an
- alternative implementation to be written. Our implementation should
- be strict about specification compliance (should not for example
- heuristically parse a file and accept not-well-formed
- data). Avoiding heuristics is also important for security reasons;
- if it looks funny, ignore it (or exit, or disconnect).
-
-Development
-===
-
-D-Bus uses Git as its version control system. The main repository is
-hosted at git.freedesktop.org/dbus/dbus. To clone D-Bus, execute the
-following command:
-
- git clone git://git.freedesktop.org/dbus/dbus
-OR
- git clone git.freedesktop.org:dbus/dbus
-
-The latter form is the one that allows pushing, but it also requires
-an SSH account on the server. The former form allows anonymous
-checkouts.
-
-D-Bus development happens in two branches in parallel: the current
-stable branch, with an even minor number (like 1.0, 1.2 and 1.4), and
-the next development branch, with the next odd number.
-
-The stable branch is named after the version number itself (dbus-1.2,
-dbus-1.4), whereas the development branch is simply known as "master".
-
-When making a change to D-Bus, do the following:
-
- - check out the earliest branch of D-Bus that makes sense to have
- your change in. If it's a bugfix, it's normally the current stable
- branch; if it's a feature, it's normally the "master" branch. If
- you have an important security fix, you may want to apply to older
- branches too.
-
- - for large changes:
- if you're developing a new, large feature, it's recommended
- to create a new branch and do your development there. Publish
- your branch at a suitable place and ask others to help you
- develop and test it. Once your feature is considered finalised,
- you may merge it into the "master" branch.
-
-- for small changes:
- . make your change to the source code
- . execute tests to guarantee that you're not introducing a
- regression. For that, execute: make check
- (if possible, add a new test to check the fix you're
- introducing)
- . commit your change using "git commit"
- in the commit message, write a short sentence describing what
- you did in the first line. Then write a longer description in
- the next paragraph(s).
- . repeat the previous steps if necessary to have multiple commits
-
- - extract your patches and send to the D-Bus mailing list for
- review or post them to the D-Bus Bugzilla, attaching them to a bug
- report. To extract the patches, execute:
- git format-patch origin/master
-
- - once your code has been reviewed, you may push it to the Git
- server:
- git push origin my-branch:remote
- OR
- git push origin dbus-X.Y
- OR
- git push origin master
- (consult the Git manual to know which command applies)
-
- - (Optional) if you've not worked on "master", merge your changes to
- that branch. If you've worked on an earlier branch than the current
- stable, merge your changes upwards towards the stable branch, then
- from there into "master".
-
- . execute: git checkout master
- . ensure that you have the latest "master" from the server, update
- if you don't
- . execute: git merge dbus-X.Y
- . if you have any conflicts, resolve them, git add the conflicted
- files and then git commit
- . push the "master" branch to the server as well
-
- Executing this merge is recommended, but not necessary for all
- changes. You should do this step if your bugfix is critical for the
- development in "master", or if you suspect that conflicts will arise
- (you're usually the best person to resolve conflicts introduced by
- your own code), or if it has been too long since the last merge.
-
-
-Making a release
-===
-
-To make a release of D-Bus, do the following:
-
- - check out a fresh copy from Git
-
- - verify that the libtool versioning/library soname is
- changed if it needs to be, or not changed if not
-
- - update the file NEWS based on the git history
-
- - verify that the version number of dbus-specification.xml is
- changed if it needs to be; if changes have been made, update the
- release date in that file
-
- - update the AUTHORS file with "make update-authors" if necessary
-
- - the version number should have major.minor.micro, even
- if micro is 0, i.e. "1.0.0" and "1.2.0" not "1.0"/"1.2"; the micro
- version should be even for releases, and odd for intermediate snapshots
-
- - "make distcheck" (DO NOT just "make dist" - pass the check!)
-
- - if make distcheck fails, fix it.
-
- - once distcheck succeeds, "git commit -a". This is the version
- of the tree that corresponds exactly to the released tarball.
-
- - tag the tree with "git tag -s -m 'Released X.Y.Z' dbus-X.Y.Z"
- where X.Y.Z is the version of the release. If you can't sign
- then simply created an unsigned annotated tag:
- "git tag -a -m 'Released X.Y.Z' dbus-X.Y.Z".
-
- - bump the version number up in configure.ac (so the micro version is odd),
- and commit it. Make sure you do this *after* tagging the previous
- release! The idea is that git has a newer version number
- than anything released. Similarly, bump the version number of
- dbus-specification.xml and set the release date to "(not finalized)".
-
- - merge the branch you've released to the chronologically-later
- branch (usually "master"). You'll probably have to fix a merge
- conflict in configure.ac (the version number).
-
- - push your changes and the tag to the central repository with
- git push origin master dbus-X.Y dbus-X.Y.Z
-
- - scp your tarball to freedesktop.org server and copy it to
- dbus.freedesktop.org:/srv/dbus.freedesktop.org/www/releases/dbus/dbus-X.Y.Z.tar.gz.
- This should be possible if you're in group "dbus"
-
- - Update the online documentation with `make -C doc maintainer-upload-docs`.
-
- - update the wiki page http://www.freedesktop.org/Software/dbus by
- adding the new release under the Download heading. Then, cut the
- link and changelog for the previous that was there.
-
- - update the wiki page
- http://www.freedesktop.org/Software/DbusReleaseArchive pasting the
- previous release. Note that bullet points for each of the changelog
- items must be indented three more spaces to conform to the
- formatting of the other releases there.
-
- - post to dbus@lists.freedesktop.org announcing the release.
-
-
-Making a ".0" stable release
-===
-
-We create a branch for each stable release. The branch name should be
-dbus-X.Y which is a branch that has releases versioned X.Y.Z;
-changes on a stable branch should be limited to significant bug fixes.
-
-Because we won't make minor changes like keeping up with the latest
-deprecations on a stable branch, stable branches should turn off the
-gcc warning for deprecated declarations (e.g. see commit 4ebb275ab7).
-
-Be extra-careful not to merge master (or any branch based on master) into a
-stable branch.
-
-To branch:
- git branch dbus-X.Y
-and upload the branch tag to the server:
- git push origin dbus-X.Y
-
-To develop in this branch:
- git checkout dbus-X.Y
-
-Environment variables
-===
-
-These are the environment variables that are used by the D-Bus client library
-
-DBUS_VERBOSE=1
-Turns on printing verbose messages. This only works if D-Bus has been
-compiled with --enable-verbose-mode
-
-DBUS_MALLOC_FAIL_NTH=n
-Can be set to a number, causing every nth call to dbus_alloc or
-dbus_realloc to fail. This only works if D-Bus has been compiled with
---enable-tests.
-
-DBUS_MALLOC_FAIL_GREATER_THAN=n
-Can be set to a number, causing every call to dbus_alloc or
-dbus_realloc to fail if the number of bytes to be allocated is greater
-than the specified number. This only works if D-Bus has been compiled with
---enable-tests.
-
-DBUS_TEST_MALLOC_FAILURES=n
-Many of the D-Bus tests will run over and over, once for each malloc
-involved in the test. Each run will fail a different malloc, plus some
-number of mallocs following that malloc (because a fair number of bugs
-only happen if two or more mallocs fail in a row, e.g. error recovery
-that itself involves malloc). This env variable sets the number of
-mallocs to fail.
-Here's why you care: If set to 0, then the malloc checking is skipped,
-which makes the test suite a heck of a lot faster. Just run with this
-env variable unset before you commit.
-
-Tests
-===
-
-These are the test programs that are built if dbus is compiled using
---enable-tests.
-
-dbus/test-dbus
-This is the main unit test program that tests all aspects of the D-Bus
-client library.
-
-dbus/bus-test
-This it the unit test program for the message bus.
-
-test/break-loader
-A test that tries to break the message loader by passing it randomly
-created invalid messages.
-
-test/name-test/*
-This is a suite of programs which are run with a temporary session bus.
-If your test involves multiple processes communicating, your best bet
-is to add a test in here.
-
-"make check" runs all the deterministic test programs (i.e. not break-loader).
-
-"make lcov-check" is available if you configure with --enable-compiler-coverage
-and gives a complete report on test suite coverage.
-
-Patches
-===
-
-Please file them at http://bugzilla.freedesktop.org under component
-dbus, and also post to the mailing list for discussion. The commit
-rules are:
-
- - for fixes that don't affect API or protocol, they can be committed
- if any one qualified reviewer other than patch author
- reviews and approves
-
- - for fixes that do affect API or protocol, two people
- in the reviewer group have to review and approve the commit, and
- posting to the list is definitely mandatory
-
- - if there's a live unresolved controversy about a change,
- don't commit it while the argument is still raging.
-
- - at their discretion, members of the reviewer group may also commit
- branches/patches under these conditions:
-
- - the branch does not add or change API, ABI or wire-protocol
-
- - the branch solves a known problem and is covered by the regression tests
-
- - there are no objections from the rest of the review group within
- a week of the patches being attached to Bugzilla
-
- - the committer gets a positive review on Bugzilla from someone they
- consider qualified to review the change (e.g. a colleague with D-Bus
- experience; not necessarily a member of the reviewer group)
-
- - regardless of reviews, to commit a patch:
- - make check must pass
- - the test suite must be extended to cover the new code
- as much as reasonably feasible (see Tests above)
- - the patch has to follow the portability, security, and
- style guidelines
- - the patch should as much as reasonable do one thing,
- not many unrelated changes
- No reviewer should approve a patch without these attributes, and
- failure on these points is grounds for reverting the patch.
-
-The reviewer group that can approve patches:
-
-Havoc Pennington <hp@pobox.net>
-Michael Meeks <michael.meeks@novell.com>
-Alexander Larsson <alexl@redhat.com>
-Zack Rusin <zack@kde.org>
-Joe Shaw <joe@assbarn.com>
-Mikael Hallendal <micke@imendio.com>
-Richard Hult <richard@imendio.com>
-Owen Fraser-Green <owen@discobabe.net>
-Olivier Andrieu <oliv__a@users.sourceforge.net>
-Colin Walters <walters@verbum.org>
-Thiago Macieira <thiago@kde.org>
-John Palmieri <johnp@redhat.com>
-Scott James Remnant <scott@netsplit.com>
-Will Thompson <will.thompson@collabora.co.uk>
-Simon McVittie <simon.mcvittie@collabora.co.uk>
-David Zeuthen <davidz@redhat.com>
diff --git a/Makefile.am b/Makefile.am
index 756ab8b9..45183cb0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,24 +3,41 @@ SUBDIRS=dbus bus tools test doc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = dbus-1.pc
-DISTCLEANFILES = \
- dbus-1.pc
+cmakeconfigdir = $(libdir)/cmake/DBus1
+cmakeconfig_DATA = cmake/DBus1Config.cmake \
+ cmake/DBus1ConfigVersion.cmake
EXTRA_DIST = \
autogen.sh \
- HACKING \
+ CONTRIBUTING.md \
dbus-1.pc.in \
cleanup-man-pages.sh \
ChangeLog.pre-1-0 \
NEWS.pre-1-0 \
ChangeLog.pre-1-2 \
NEWS.pre-1-2 \
+ README.cmake \
README.valgrind \
README.win \
README.wince \
README.cygwin \
README.launchd \
- cmake
+ cmake/CMakeLists.txt \
+ cmake/ConfigureChecks.cmake \
+ cmake/DBus1Config.cmake.in \
+ cmake/DBus1Config.pkgconfig.in \
+ cmake/DBus1ConfigVersion.cmake.in \
+ cmake/bus \
+ cmake/bus-test.bat.cmake \
+ cmake/config.h.cmake \
+ cmake/dbus \
+ cmake/dbus-env.bat.cmake \
+ cmake/doc \
+ cmake/i686-w64-mingw32.cmake \
+ cmake/modules \
+ cmake/test \
+ cmake/tools \
+ $(NULL)
all-local: Doxyfile
@@ -33,4 +50,5 @@ DISTCHECK_CONFIGURE_FLAGS = \
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
-include tools/lcov.am
+# Add rules for code-coverage testing, as defined by AX_CODE_COVERAGE
+include $(top_srcdir)/aminclude_static.am
diff --git a/Makefile.cvs b/Makefile.cvs
deleted file mode 100644
index d44e5654..00000000
--- a/Makefile.cvs
+++ /dev/null
@@ -1,8 +0,0 @@
-## -*- makefile -*-
-
-configure:
- ./autogen.sh --no-configure
-
-.SILENT:
-
-.PHONY: configure
diff --git a/NEWS b/NEWS
index 727663c4..07a933a4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,1152 @@
+dbus 1.12.16 (2019-06-11)
+=========================
+
+The “tree cat” release.
+
+Security fixes:
+
+• CVE-2019-12749: Do not attempt to carry out DBUS_COOKIE_SHA1
+ authentication for identities that differ from the user running the
+ DBusServer. Previously, a local attacker could manipulate symbolic
+ links in their own home directory to bypass authentication and connect
+ to a DBusServer with elevated privileges. The standard system and
+ session dbus-daemons in their default configuration were immune to this
+ attack because they did not allow DBUS_COOKIE_SHA1, but third-party
+ users of DBusServer such as Upstart could be vulnerable.
+ Thanks to Joe Vennix of Apple Information Security.
+ (dbus#269, Simon McVittie)
+
+dbus 1.12.14 (2019-05-17)
+=========================
+
+The “reclaimed floorboards” release.
+
+Enhancements:
+
+• Raise soft fd limit to match hard limit, even if unprivileged.
+ This makes session buses with many clients, or with clients that make
+ heavy use of fd-passing, less likely to suffer from fd exhaustion.
+ (dbus!103, Simon McVittie)
+
+Fixes:
+
+• If a privileged dbus-daemon has a hard fd limit greater than 64K, don't
+ reduce it to 64K, ensuring that we can put back the original fd limits
+ when carrying out traditional (non-systemd) activation. This fixes a
+ regression with systemd >= 240 in which system services inherited
+ dbus-daemon's hard and soft limit of 64K fds, instead of the intended
+ soft limit of 1K and hard limit of 512K or 1M.
+ (dbus!103, Debian#928877; Simon McVittie)
+
+• Fix build failures caused by an AX_CODE_COVERAGE API change in newer
+ autoconf-archive versions (dbus#249, dbus!88; Simon McVittie)
+
+• Fix build failures with newer autoconf-archive versions that include
+ AX_-prefixed shell variable names (dbus#249, dbus!86; Simon McVittie)
+
+• Parse section/group names in .service files according to the syntax
+ from the Desktop Entry Specification, rejecting control characters
+ and non-ASCII in section/group names (dbus#208, David King)
+
+• Fix various -Wlogical-op issues that cause build failure with newer
+ gcc versions (dbus#225, dbus!109; David King)
+
+• Don't assume we can set permissions on a directory, for the benefit of
+ MSYS and Cygwin builds (dbus#216, dbus!110; Simon McVittie)
+
+• Don't overwrite PKG_CONFIG_PATH and related environment variables when
+ the pkg-config-based version of DBus1Config is used in a CMake project
+ (dbus#267, dbus!96; Clemens Lang)
+
+dbus 1.12.12 (2018-12-04)
+=========================
+
+The “draconic disciple” release.
+
+dbus version control is now hosted on freedesktop.org's Gitlab
+installation, and bug reports and feature requests have switched from
+Bugzilla bugs (indicated by "fd.o #nnn") to Gitlab issues ("dbus#nnn")
+and merge requests ("dbus!nnn").
+
+Enhancements:
+
+• Reference the freedesktop.org Code of Conduct (Simon McVittie)
+
+Fixes:
+
+• Stop the dbus-daemon leaking memory (an error message) if delivering
+ the message that triggered auto-activation is forbidden. This is
+ technically a denial of service because the dbus-daemon will
+ run out of memory eventually, but it's a very slow and noisy one,
+ because all the rejected messages are also very likely to have
+ been logged to the system log, and its scope is typically limited by
+ the finite number of activatable services available.
+ (dbus#234, Simon McVittie)
+
+• Remove __attribute__((__malloc__)) attribute on dbus_realloc(),
+ which does not meet the criteria for that attribute in gcc 4.7+,
+ potentially leading to miscompilation (fd.o #107741, Simon McVittie)
+
+• Fix some small O(1) memory leaks (fd.o #107320, Simon McVittie)
+
+• Fix printf formats for pointer-sized integers on 64-bit Windows
+ (fd.o #105662, Ralf Habacker)
+
+• Always use select()-based poll() emulation on Darwin-based OSs
+ (macOS, etc.) and on Interix, similar to what libcurl does
+ (dbus#232, dbus!19; Simon McVittie)
+
+• Extend a test timeout to avoid spurious failures in CI
+ (dbus!26, Simon McVittie)
+
+Tests and CI:
+
+• Add Travis-CI builds for 64-bit Windows using mingw-w64
+ (fd.o #105662, Ralf Habacker)
+
+• Add Gitlab-CI integration (fd.o #108177, Simon McVittie)
+
+dbus 1.12.10 (2018-08-02)
+=========================
+
+The “beam deflection” release.
+
+Fixes:
+
+• Prevent reading up to 3 bytes beyond the end of a truncated message.
+ This could in principle be an information leak or denial of service
+ on the system bus, but is not believed to be exploitable to crash
+ the system bus or leak interesting information in practice.
+ (fd.o #107332, Simon McVittie)
+
+• Fix build with gcc 8 -Werror=cast-function-type
+ (fd.o #107349, Simon McVittie)
+
+• Fix warning from gcc 8 about suspicious use of strncpy() when
+ populating struct sockaddr_un (fd.o #107350, Simon McVittie)
+
+• Fix a minor memory leak when a DBusServer listens on a new address
+ (fd.o #107194, Simon McVittie)
+
+• Fix an invalid NULL argument to rmdir() if a nonce-tcp DBusServer
+ runs out of memory (fd.o #107194, Simon McVittie)
+
+• Don't use misleading errno-derived error names if getaddrinfo() or
+ getnameinfo() fails with a code other than EAI_SYSTEM
+ (fd.o #106395, Simon McVittie)
+
+• Skip tests that require working TCP if we are in a container environment
+ where 127.0.0.1 cannot be resolved (fd.o #106812, Simon McVittie)
+
+dbus 1.12.8 (2018-04-30)
+========================
+
+The “golden super-velociraptor” release.
+
+Enhancements:
+
+• The Devhelp documentation index is now in version 2 format
+ (fd.o #106186, Simon McVittie)
+
+• Give the dbus-daemon man page some scarier warnings about
+ <allow_anonymous/> and non-local TCP, which are insecure and should
+ not be used, particularly for the standard system and session buses
+ (fd.o #106004, Simon McVittie)
+
+Fixes:
+
+• Fix installation of Ducktype documentation with newer yelp-build
+ versions (fd.o #106171, Simon McVittie)
+
+dbus 1.12.6 (2018-03-01)
+========================
+
+The “just the one swan, actually” release.
+
+Fixes:
+
+• Increase system dbus-daemon's RLIMIT_NOFILE rlimit before it drops
+ privileges, because it won't have permission afterwards. This fixes a
+ regression in dbus 1.10.18 and 1.11.0 which made the standard system bus
+ more susceptible to deliberate or accidental denial of service.
+ (fd.o #105165, David King)
+
+dbus 1.12.4 (2018-02-08)
+========================
+
+The “Stria Campania 115” release.
+
+Fixes:
+
+• When iterating the DBusConnection while blocking on a pending call,
+ don't wait for I/O if that pending call already has a result; and make
+ sure that whether it has a result is propagated in a thread-safe way.
+ This prevents certain multi-threaded calling patterns from blocking
+ until their timeout even when they should have succeeded sooner.
+ (fd.o #102839; Manish Narang, Michael Searle)
+
+• Report the correct error if OOM is reached while trying to listen
+ on a TCP socket (fd.o #89104, Simon McVittie)
+
+• Fix assertion failures in recovery from OOM while setting up a
+ DBusServer (fd.o #89104, Simon McVittie)
+
+• Add a missing space to a warning message (fd.o #103729, Thomas Zajic)
+
+• Expand ${bindir} correctly when pkg-config is asked for dbus_daemondir
+ (fd.o #104265, Benedikt Heine)
+
+• On Linux systems with systemd < 237, if ${localstatedir}/dbus doesn't
+ exist, create it before trying to create ${localstatedir}/dbus/machine-id
+ (fd.o #104577, Chris Lesiak)
+
+• Fix escaping in dbus-api-design document (fd.o #104925, Philip Withnall)
+
+dbus 1.12.2 (2017-11-13)
+========================
+
+The “spider pumpkin” release.
+
+Enhancements:
+
+• Log a warning if a new connection cannot be accepted due to an
+ out-of-memory condition or failure to identify its AppArmor or
+ SELinux context (fd.o #103592, Simon McVittie)
+
+Fixes:
+
+• Make use of $(MKDIR_P) compatible with install-sh, fixing build when a
+ GNU-compatible `mkdir -p` is not available (fd.o #103521, ilovezfs)
+
+• When building for Windows with Autotools, avoid `echo -e`, fixing
+ cross-compilation on non-GNU platforms like macOS
+ (fd.o #103493, Tony Theodore)
+
+• Fix crashes in the server side of the nonce-tcp: transport under
+ various error conditions. This transport should normally only be used
+ on Windows, where AF_UNIX sockets are unavailable; the unix: transport
+ is the only one recommended for production use on Unix platforms.
+ (fd.o #103597, Simon McVittie)
+
+Internal changes:
+
+• Improve test coverage on Travis-CI (Simon McVittie)
+
+dbus 1.12.0 (2017-10-30)
+========================
+
+The “gingerbread skull” release.
+
+1.12.x is a new stable branch, recommended for use in OS
+distributions.
+
+Summary of major changes between 1.10.x and 1.12.0
+--------------------------------------------------
+
+Dependencies:
+
+• Expat >= 2.1.0 is required.
+• GLib >= 2.40 is required if full test coverage is enabled.
+• [Linux] libselinux >= 2.0.86 is required if SELinux support is
+ enabled.
+• [Unix] dbus now requires an <inttypes.h> that defines C99 constants
+ such as PRId64 and PRIu64, except when building for Windows.
+• [Autotools] Building from git (but not from tarballs) with Autotools
+ now requires macros from the GNU Autoconf Archive.
+• [CMake] Builds done using CMake now require CMake 3.0.2.
+
+Build-time configuration changes:
+
+• Expat is now found using pkg-config. See the release notes for
+ 1.11.14.
+• The --disable-compiler-optimisations and --enable-compiler-coverage
+ options no longer exist. See the release notes for 1.11.4 and 1.11.8.
+• [Unix] The --enable-abstract-sockets and --disable-abstract-sockets
+ options no longer exist. See the release notes for 1.11.20.
+• [Unix] Flag files in /var/run/console/${username} are no longer
+ checked for at_console by default. See the release notes for 1.11.18.
+• [Unix, Cygwin] Init scripts are no longer provided by upstream dbus,
+ and packagers will now need to add these downstream (most already do).
+ See the release notes for 1.11.18.
+• [Unix] The process ID file no longer has a different default location
+ on Red Hat derivatives. See the release notes for 1.11.18.
+• [Unix] ${runstatedir} is now independent of ${localstatedir} with
+ recent Autotools versions. See the release notes for 1.11.16.
+• [Windows] The WINDRES variable is no longer used. See the release
+ notes for 1.11.22.
+
+Deprecations:
+
+• Eavesdropping is officially deprecated in favour of BecomeMonitor.
+ See the release notes for spec version 0.31 (in dbus 1.11.14).
+• [Unix] Flag files in /var/run/console/${username} are deprecated.
+ See the release notes for 1.11.18.
+
+New APIs:
+
+• <allow> and <deny> rules in dbus-daemon configuration can now
+ include send_broadcast="true", send_broadcast="false",
+ max_unix_fds="N", min_unix_fds="N" (for some integer N).
+ See the release notes for 1.11.18.
+• dbus_try_get_local_machine_id() is like
+ dbus_get_local_machine_id(), but returns a DBusError.
+• New APIs around DBusMessageIter to simplify cleanup.
+ See the release notes for 1.11.16.
+• The message bus daemon now implements the standard Introspectable,
+ Peer and Properties interfaces. See the release notes for
+ dbus 1.11.14 and spec version 0.31.
+• DTDs for introspection XML and bus configuration are installed.
+• dbus can be compiled to be relocatable, making it more suitable for
+ binary bundling with other software. On Windows, this is on by
+ default.
+• [Unix] A new unix:dir=… address family resembles unix:tmpdir=… but
+ never uses Linux abstract sockets, which is advantageous for
+ containers. On non-Linux it is equivalent to unix:tmpdir=….
+ See the release notes for dbus 1.11.14 and spec version 0.31.
+• [Unix] New option "dbus-launch --exit-with-x11".
+• [Unix] Session managers can create transient .service files in
+ $XDG_RUNTIME_DIR/dbus-1/services. See the release notes for 1.11.12.
+• [Unix] A sysusers.d snippet can create the messagebus user on-demand.
+
+Miscellaneous behaviour changes:
+
+• [Unix] The session bus now logs to syslog if it was started by
+ dbus-launch.
+• [Unix] Internal warnings are logged to syslog if configured.
+• [Unix] Exceeding an anti-DoS limit is logged to syslog if configured,
+ or to stderr.
+
+Changes since 1.11.22 release candidate
+---------------------------------------
+
+Standard stable-branch changes:
+
+• Disable warnings about use of deprecated functions (Simon McVittie)
+
+Fixes:
+
+• Don't distribute files generated by ./configure in the source tarball
+ (fd.o #103420, Simon McVittie)
+
+Internal changes:
+
+• Remove some unused files from the git repository
+ (fd.o #103420, Simon McVittie)
+
+D-Bus 1.11.22 (2017-10-23)
+==========================
+
+The “fire surface” release.
+
+This is the first release-candidate for the 1.12.0 stable release.
+
+Build-time configuration changes:
+
+• When building for Windows with Autotools, setting the WINDRES variable
+ no longer works to select a non-standard resource compiler. Use
+ libtool's standard RC variable instead, for example
+ "./configure RC=i686-w64-mingw32-windres"
+
+Dependencies:
+
+• Builds done using CMake now require CMake 3.0.2.
+
+Enhancements:
+
+• When building for Windows, improve quality of metadata in
+ libdbus-1-3.dll (fd.o #103015, Ralf Habacker)
+
+Fixes:
+
+• Fix a typo "uint 16" in dbus-send(1) man page
+ (fd.o #103075, David King)
+
+• When building for Windows, libdbus-1-3.dll always includes version
+ information. Previously, this was missing if using CMake and any
+ non-MSVC compiler. (fd.o #103015, Ralf Habacker)
+
+• Fix the build with MSVC, which regressed with the #102558 fix in
+ 1.11.20. (fd.o #102558, Ralf Habacker)
+
+Internal changes:
+
+• Simplify Windows resource embedding
+ (fd.o #103015, Simon McVittie)
+
+D-Bus 1.11.20 (2017-10-03)
+==
+
+The “wraith stun” release.
+
+Build-time configuration changes:
+
+• The --enable-abstract-sockets and --disable-abstract-sockets options
+ no longer exist. Support for Linux's abstract AF_UNIX sockets is now
+ unconditionally enabled on Linux and disabled everywhere else.
+ (fd.o #34905, Simon McVittie)
+
+Enhancements:
+
+• Make slower tests less likely to time out, and improve diagnostics if
+ tests do time out (fd.o #103009, Simon McVittie)
+
+• On Windows, don't compile an unused stub implementation of
+ _dbus_set_signal_handler() (fd.o #103010, Simon McVittie)
+
+Fixes:
+
+• Be more careful to save and restore errno in POSIX async signal
+ handlers (fd.o #103010, Simon McVittie)
+
+• On Windows, embed a manifest in dbus-update-activation-environment.exe
+ so that the heuristics used for UAC do not assume it needs elevated
+ privileges due to its name containing "update"
+ (fd.o #102558, Ralf Habacker)
+
+• On Windows with Automake, embed version information in libdbus-1,
+ as was meant to happen in all versions since 2009
+ (fd.o #103015, Simon McVittie)
+
+D-Bus 1.11.18 (2017-09-25)
+==
+
+The “vampire conquistador” release.
+
+Build-time configuration changes:
+
+• By default, dbus-daemon on Unix no longer checks for flag files
+ /var/run/console/${username} created by the obsolete pam_console and
+ pam_foreground PAM modules when deciding whether ${username} is
+ currently at the console. The old default behaviour can be restored
+ by specifying --with-console-auth-dir=/var/run/console in the
+ recommended Autotools build system, or
+ -DDBUS_CONSOLE_AUTH_DIR=/var/run/console in CMake. This feature is
+ now deprecated, and will be removed in dbus 1.13 unless feedback via
+ fd.o #101629 indicates that this would be problematic.
+ (fd.o #101629, Simon McVittie)
+
+• LSB-style init scripts for Red Hat and Slackware, and a non-LSB init
+ script for Cygwin, are no longer provided in the upstream dbus
+ source. We recommend that distributors who support non-systemd service
+ management should maintain their own init scripts or other service
+ manager integration as part of their downstream packaging, similar to
+ the way Debian distributes a Debian-specific LSB init script for dbus.
+
+ The systemd unit continues to be maintained as part of the upstream
+ dbus source, because it receives regular testing and maintenance.
+
+ (fd.o #101706, Simon McVittie)
+
+• The process ID file created by the system bus is no longer influenced
+ by the --with-init-scripts=redhat configure option or the presence of
+ /etc/redhat-release at build time. If your OS's init script or other
+ service management relies on the Red Hat-style pid file, it can be
+ restored by specifying --with-system-pid-file=/run/messagebus.pid at
+ configure time or using the <pidfile> directive in bus configuration.
+
+ Note that the upstream-supplied systemd unit runs dbus-daemon with
+ the --nopidfile option, so it does not normally write a pid file,
+ regardless of whether the OS is Red-Hat-derived or not.
+
+ (fd.o #101706, Simon McVittie)
+
+Enhancements:
+
+• <allow> and <deny> rules in dbus-daemon configuration can now
+ include send_broadcast="true" or send_broadcast="false", which make
+ the rule only match broadcast signals, or only match messages that
+ are not broadcast signals, respectively.
+ (fd.o #29853, Simon McVittie)
+
+• <allow> and <deny> rules can now be configured to apply only to
+ messages with or without Unix file descriptors attached. This would
+ typically be used in rules like these:
+ <allow send_destination="..." max_unix_fds="0"/>
+ <deny send_destination="..." min_unix_fds="1"/>
+ <deny receive_sender="..." min_unix_fds="1"/>
+ but can also be used to set a nonzero upper limit on the number of
+ file descriptors:
+ <allow send_destination="..." max_unix_fds="4"/>
+ (fd.o #101848, Simon McVittie)
+
+• On Unix platforms, the DBUS_COOKIE_SHA1 authentication mechanism
+ now respects the HOME environment variable on the client side, and
+ on the server side when the uid attempting to connect is the same
+ as the uid of the server. This allows the automated tests to pass in
+ environments where the user's "official" home directory in /etc/passwd
+ is nonexistent, such as Debian autobuilders.
+ (fd.o #101960, Simon McVittie)
+
+Fixes:
+
+• When parsing dbus-daemon configuration, tell Expat not to use
+ cryptographic-quality entropy as a salt for its hash tables: we trust
+ the configuration files, so we are not concerned about algorithmic
+ complexity attacks via hash table collisions. This prevents
+ dbus-daemon --system from holding up the boot process (and causing
+ early-boot system services like systemd, logind, networkd to time
+ out) on entropy-starved embedded systems.
+ (fd.o #101858, Simon McVittie)
+
+• Avoid a -Werror=declaration-after-statement build failure on Solaris
+ (fd.o #102145, Alan Coopersmith)
+
+• On Unix platform, drop DBUS_SYSTEM_LOG_INFO messages from LOG_NOTICE
+ to LOG_INFO, matching how we use this log level in practice
+ (fd.o #102686, Simon McVittie)
+
+D-Bus 1.11.16 (2017-07-27)
+==
+
+The “south facing garden” release.
+
+Build-time configuration changes:
+
+• The Autotools build system now supports varying ${runstatedir}
+ independently of ${localstatedir}, if using an Autoconf version
+ that has that feature; version 2.70 will eventually have this, but
+ many Linux distributions add it to version 2.69 as a patch.
+ A typical use is to set prefix=/usr, sysconfdir=/etc, localstatedir=/var
+ and runstatedir=/run. (fd.o #101569, Simon McVittie)
+
+Enhancements:
+
+• New APIs DBUS_MESSAGE_ITER_INIT_CLOSED, dbus_message_iter_init_closed()
+ and dbus_message_iter_abandon_container_if_open() simplify the
+ single-exit-point ("goto out") style of resource cleanup. The API
+ documentation around DBusMessageIter and containers has also been
+ clarified. (fd.o #101568, Simon McVittie)
+
+Fixes:
+
+• Fix the implementation of re-enabling a timeout (again) so that its
+ countdown is always restarted as intended. (fd.o #95619,
+ Michal Koutný)
+
+• Make the dbus-daemon's Properties interface, as introduced in 1.11.14,
+ available to all users on the system bus (fd.o #101700, Simon McVittie)
+
+• dbus_message_iter_append_basic() no longer leaks memory if it fails to
+ append a file descriptor to a message. (fd.o #101568, Simon McVittie)
+
+• dbus_message_iter_open_container() no longer leaks memory if it runs out
+ of memory. (fd.o #101568, Simon McVittie)
+
+• dbus_message_append_args_valist() no longer leaks memory if given an
+ unsupported type. This situation is still considered to be a programming
+ error which needs to be corrected by the user of libdbus.
+ (fd.o #101568, Simon McVittie)
+
+• dbus_message_iter_append_basic() and dbus_message_iter_open_container()
+ will no longer report that their arguments were invalid if they run out
+ of memory at exactly the wrong time. (fd.o #101568, Simon McVittie)
+
+• Ensure that tests fail if they would otherwise have tried to connect to
+ the real session bus (fd.o #101698, Simon McVittie)
+
+• Make build-time tests cope with finding Python 3, but not Python 2
+ (fd.o #101716, Simon McVittie)
+
+Internal changes relevant to dbus developers:
+
+• DBusVariant is a new mechanism to copy single values from a message into
+ a buffer without copying the entire message (fd.o #101568, Simon McVittie)
+
+• DBUS_SYSTEM_LOG_FATAL has been replaced by DBUS_SYSTEM_LOG_ERROR.
+ Logging an ERROR message does not make the process exit; the caller
+ is responsible for calling abort() or exit(), whichever is more appropriate.
+ (fd.o #101568, Simon McVittie)
+
+• Better test coverage (fd.o #101568, Simon McVittie)
+
+D-Bus 1.11.14 (2017-06-29)
+==
+
+The “irrational fear of bees” release.
+
+Dependencies:
+
+• Expat >= 2.1.0 is always required
+• libselinux >= 2.0.86 is required if SELinux support is enabled
+• GLib >= 2.40 is required if full test coverage is enabled
+
+Build-time configuration changes:
+
+• We now use pkg-config to find libexpat in Autotools builds. This requires
+ Expat 2.1.0 (March 2012) or later. In particular, this should remove the
+ need to configure with LDFLAGS=-L/usr/local/lib on OpenBSD, which can
+ itself cause compilation failures.
+
+ As with all pkg-config-based configure checks, you can use
+ PKG_CONFIG_PATH=/whatever/lib/pkgconfig to find expat.pc in a
+ non-standard prefix, or EXPAT_CFLAGS="-I/whatever/include" and
+ EXPAT_LIBS="-L/whatever/lib -lexpat" to avoid needing a .pc file
+ at all.
+
+ (fd.o #69801, Simon McVittie)
+
+• Similarly, we now use pkg-config to find libselinux. Version 2.0.86
+ is required due to the removal of explicit refcounting for SIDs.
+ (fd.o #100912, Laurent Bigonville)
+
+Behaviour changes:
+
+• Previously, /etc/machine-id could be copied to /var/lib/dbus/machine-id
+ as a side-effect of a sufficiently privileged process merely reading the
+ machine ID. It is no longer copied as a side-effect of reading.
+ Running dbus-uuidgen --ensure, which should be done after installing dbus,
+ continues to copy /etc/machine-id to /var/lib/dbus/machine-id if the
+ former exists and the latter does not.
+ (fd.o #101257, Simon McVittie)
+
+• The undocumented Verbose interface, and the GetAllMatchRules method on
+ the undocumented Stats interface, must now be used via the object path
+ /org/freedesktop/DBus. Previously, they existed on all object paths.
+ (fd.o #101257, Simon McVittie)
+
+• AddMatch() with a match rule containing eavesdrop='true' will now fail
+ unless called by either the same user as the dbus-daemon, or Unix uid 0
+ (root), matching the restrictions applied to the newer BecomeMonitor()
+ method. On the session bus this has no practical effect. On the system
+ bus this will prevent certain configurations that already did not
+ work well in practice. (fd.o #101567, Simon McVittie)
+
+Enhancements:
+
+• D-Bus Specification version 0.31
+ · Don't require implementation-specific search paths to be lowest
+ priority
+ · Correct regex syntax for optionally-escaped bytes in addresses so it
+ includes hyphen-minus, forward slash and underscore as intended
+ · Describe all message bus methods in the same section
+ · Clarify the correct object path for method calls to the message bus
+ (/org/freedesktop/DBus, DBUS_PATH_DBUS in the reference implementation)
+ · Document that the message bus implements Introspectable, Peer and
+ Properties
+ · Add new Features and Interfaces properties for message bus
+ feature-discovery
+ · Add unix:dir=..., which resembles unix:tmpdir=... but never uses
+ abstract sockets
+ · Don't require eavesdrop='true' to be accepted from connections not
+ sufficiently privileged to use it successfully
+ · Formally deprecate eavesdropping in favour of BecomeMonitor
+ (fd.o #99825, #100686, #100795, #101256, #101257, #101567;
+ Simon McVittie, Tom Gundersen)
+
+• Implement the Properties and Peer interfaces in dbus-daemon
+ (fd.o #101257, Simon McVittie)
+
+• New function dbus_try_get_local_machine_id() is like
+ dbus_get_local_machine_id(), but returning a DBusError. Other code
+ that needs the machine ID will now report a recoverable error (instead
+ of logging to stderr and aborting) if no machine ID is available.
+ Generating a machine ID is still considered to be a required part of
+ installing dbus correctly. (fd.o #13194, Simon McVittie)
+
+• Implement GetConnectionSELinuxSecurityContext("org.freedesktop.DBus")
+ (fd.o #101315, Laurent Bigonville)
+
+• Avoid deprecated API calls when using SELinux
+ (fd.o #100912, Laurent Bigonville)
+
+• Switch a test from the deprecated g_test_trap_fork() to
+ g_test_trap_subprocess(), for Windows support and better robustness
+ on Unix (fd.o #101362, Simon McVittie)
+
+• On systemd systems, if ${localstatedir}/dbus/machine-id doesn't exist,
+ instruct systemd-tmpfiles to make it a symbolic link to /etc/machine-id.
+ This prevents the two files from going out of sync on stateless or live
+ images without needing to run dbus-uuidgen, and supports older D-Bus
+ implementations that do not necessarily read /etc/machine-id themselves.
+ (fd.o #101570, Simon McVittie)
+
+• Implement unix:dir=..., which resembles unix:tmpdir=... but never uses
+ abstract sockets. This is preferable when used with Linux containers.
+ (fd.o #101567, Simon McVittie)
+
+Fixes:
+
+• Fix a reference leak when blocking on a pending call on a connection
+ that has been disconnected (fd.o #101481, Shin-ichi MORITA)
+
+• Don't put timestamps in the Doxygen-generated documentation,
+ or hard-code the build directory into builds with embedded tests,
+ for reproducible builds (fd.o #100692, Simon McVittie)
+
+• Fix some integration test issues (fd.o #100686, Simon McVittie)
+
+• Fix memory leaks in the tests (fd.o #101257, Simon McVittie)
+
+• If we somehow get an autolaunch address with multiple semicolon-separated
+ components, and they don't work, don't invalidly "pile up" errors
+ (fd.o #101257, Simon McVittie)
+
+Documentation:
+
+• Update git URIs in HACKING document to sync up with cgit.freedesktop.org
+ (fd.o #100715, Simon McVittie)
+
+D-Bus 1.11.12 (2017-04-07)
+==
+
+The “it's something humans do” release.
+
+Enhancements:
+
+• The session dbus-daemon now supports transient .service files
+ in $XDG_RUNTIME_DIR/dbus-1/services. Unlike the other standard
+ service directories, this directory is not monitored with inotify
+ or similar, and the service files must be named exactly
+ ${bus_name}.service. (fd.o #99825, Simon McVittie)
+
+• dbus can be configured with --enable-relocation when building with
+ Autotools, or with -DDBUS_RELOCATABLE=ON when building with cmake,
+ to make the pkg-config metadata relocatable. This is useful for
+ non-standard prefixes, and in particular for Windows installations.
+ However, it is not recommended for system-wide installations into
+ /usr, because it interferes with pkg-config's ability to filter out
+ compiler default linker directories.
+
+ With Autotools, the default is --enable-relocation when building
+ for Windows or --disable-relocation otherwise. With CMake, the default
+ is -DDBUS_RELOCATABLE=ON.
+
+ (fd.o #99721; Ralf Habacker, Simon McVittie)
+
+• Users of CMake ≥ 2.6 can now link to libdbus without providing their
+ own FindDBus.cmake macros, whether dbus was compiled with Autotools
+ or with CMake. See the end of README.cmake for more information.
+ (fd.o #99721; Ralf Habacker, Simon McVittie)
+
+Fixes:
+
+• Always read service file directories in the intended order
+ (fd.o #99825, Simon McVittie)
+
+• When tests are skipped, don't try to kill nonexistent process 0
+ (fd.o #99825, Simon McVittie)
+
+• Avoid valgrind false positives (fd.o #88808, Philip Withnall)
+
+• Fix a harmless read overflow and some memory leaks in a unit test
+ (fd.o #100568, Philip Withnall)
+
+• Fix some typos in test code
+ (fd.o #99999, Coverity #141876, #141877; Philip Withnall)
+
+• Clarify the roles of /etc/dbus-1/s*.d and /usr/share/dbus-1/s*.d
+ in documentation (fd.o #99901, Philip Withnall)
+
+• Fix and enable compiler warnings related to -Wswitch
+ (fd.o #98191; Thomas Zimmermann, Simon McVittie)
+
+• Fix writing off the end of a fd_set when testing with valgrind
+ (fd.o #99839, Philip Withnall)
+
+D-Bus 1.11.10 (2017-02-16)
+==
+
+The “purple hair gives you telekinesis?” release.
+
+Dependencies:
+
+• AppArmor support requires at least libapparmor 2.8.95, reduced
+ from 2.10 in previous versions. One test requires 2.10 and is
+ skipped if building with an older version.
+
+Enhancements:
+
+• Do the Travis-CI build in Docker containers for Ubuntu LTS, Debian
+ stable and Debian testing in addition to the older Ubuntu that is
+ the default (fd.o #98889, Simon McVittie)
+
+• Avoid some deprecated CMake functions (fd.o #99586, Ralf Habacker)
+
+• Silence many -Wswitch-enum and -Wswitch-default warnings
+ (fd.o #98191; Thomas Zimmermann, Simon McVittie)
+
+• Install a sysusers.d snippet so `dbus-daemon --system` can be used
+ with an unpopulated /etc (fd.o #99162, Lennart Poettering)
+
+• Install pkg-config metadata on Unix even if building with CMake
+ (fd.o #99752, Ralf Habacker)
+
+• Exclude auth mechanisms from REJECTED message if they are supported
+ in the code but but configured to be disallowed (fd.o #99621,
+ Ralf Habacker)
+
+Fixes:
+
+• Prevent symlink attacks in the nonce-tcp transport on Unix that could
+ allow an attacker to overwrite a file named "nonce", in a directory
+ that the user running dbus-daemon can write, with a random value
+ known only to the user running dbus-daemon. This is unlikely to be
+ exploitable in practice, particularly since the nonce-tcp transport
+ is really only useful on Windows.
+
+ On Unix systems we strongly recommend using only the unix: and systemd:
+ transports, together with EXTERNAL authentication. These are the only
+ transports and authentication mechanisms enabled by default.
+
+ (fd.o #99828, Simon McVittie)
+
+• Avoid symlink attacks in the "embedded tests", which are not enabled
+ by default and should never be enabled in production builds of dbus.
+ (fd.o #99828, Simon McVittie)
+
+• Fix the implementation of re-enabling a timeout so that its
+ countdown is restarted as intended, instead of continually
+ decreasing. (fd.o #95619; Michal Koutný, Simon McVittie)
+
+• When receiving a message with file descriptors, do not start reading
+ the beginning of the next message, so that only one such message
+ is processed at a time. In conjunction with the fix for #95619
+ this means that processes sending many file descriptors, such as
+ systemd-logind on a system that receives very rapid ssh connections,
+ are not treated as abusive and kicked off the bus. Revert the previous
+ workaround that special-cased uid 0.
+ (fd.o #95263, LP#1591411; Simon McVittie)
+
+• Do not require TMPDIR, TEMP or TMP to be set when cross-compiling
+ for Windows with CMake (fd.o #99586, Ralf Habacker)
+
+• Do not set Unix-specific variables when targeting Windows
+ (fd.o #99586, Ralf Habacker)
+
+• Install Unix executables to ${CMAKE_INSTALL_PREFIX}/bin as intended,
+ not ${CMAKE_INSTALL_PREFIX}/lib (fd.o #99752, Ralf Habacker)
+
+• Use relative install locations in CMake on Unix to respect DESTDIR,
+ and use GNU-style install layout (fd.o #99721, #99752; Ralf Habacker)
+
+• Install dbus-arch-deps.h correctly when using CMake
+ (fd.o #99586, #99721; Ralf Habacker)
+
+• Improve argument validation for `dbus-test-tool spam`
+ (ffd.o #99693, Coverity #54759; Philip Withnall)
+
+• Don't shift by a negative integer if a hash table becomes monstrously
+ large (fd.o #99641, Coverity #54682; Philip Withnall)
+
+• Don't leak LSM label if dbus-daemon runs out of memory when dealing with
+ a new connection (fd.o #99612, Coverity #141058; Philip Withnall)
+
+• Remove an unnecessary NULL check
+ (fd.o #99642, Coverity #141062; Philip Withnall)
+
+• Improve error handling in unit tests and dbus-send
+ (fd.o #99643, #99694, #99712, #99722, #99723, #99724, #99758,
+ #99759, #99793, Coverity #54688, #54692, #54693, #54697, #54701,
+ #54710, #54711, #54714, #54715, #54718, #54721, #54724, #54726,
+ #54730, #54740, #54822, #54823, #54824, #54825; Philip Withnall)
+
+• Do not print verbose messages' timestamps to stderr if the actual message
+ has been redirected to the Windows debug port (fd.o #99749, Ralf Habacker)
+
+D-Bus 1.11.8 (2016-11-28)
+==
+
+The “panics in the face of breakfast foods” release.
+
+Build-time configuration:
+
+• The new --enable-debug configure option provides an easy way to
+ enable debug symbols, disable optimization and/or enable profiling.
+
+• The --enable-compile-warnings configure option can be used to control
+ compiler warnings.
+
+• The --disable-compiler-optimisations configure option is no longer
+ supported. Use --enable-debug=yes or CFLAGS=-O0 instead.
+
+Enhancements:
+
+• D-Bus Specification version 0.30
+ · Define the jargon term "activation" more clearly
+ · Define the jargon term "auto-starting", which is one form of activation
+ · Document the optional SystemdService key in service files
+ · Use versioned interface and bus names in most examples
+ · Clarify intended behaviour of Properties.GetAll
+ (fd.o #36190, fd.o #98671; Philip Withnall, Simon McVittie)
+
+• Fix and enable a lot of compiler warnings to improve future code
+ quality. This might incidentally also fix some environment variable
+ accesses on OS X.
+ · In particular, printf-style functions in the libdbus API are now annotated
+ with __attribute__((__format__(__printf__, *, *))) when compiling with
+ gcc or clang. This might make printf bugs in other software visible
+ at compile time.
+ (fd.o #97357, fd.o #98192, fd.o #98195, fd.o #98658;
+ Thomas Zimmermann, Simon McVittie)
+
+• When running with AppArmor mediation (for example using Ubuntu's patched
+ Linux kernel), clients can no longer auto-start services unless they would
+ have been able to send the auto-starting message to the service after it
+ starts. StartServiceByName() is unaffected, and continues to be allowed by
+ default in AppArmor's <abstractions/dbus-strict> and
+ <abstractions/dbus-session-strict>. (fd.o #98666, Simon McVittie)
+
+Fixes:
+
+• Work around an undesired effect of the fix for CVE-2014-3637
+ (fd.o #80559), in which processes that frequently send fds, such as
+ logind during a flood of new PAM sessions, can get disconnected for
+ continuously having at least one fd "in flight" for too long;
+ dbus-daemon interprets that as a potential denial of service attack.
+ The workaround is to disable that check for uid 0 process such as
+ logind, with a message in the system log. The bug remains open while
+ we look for a more general solution.
+ (fd.o #95263, LP#1591411; Simon McVittie)
+
+• Don't run the test test-dbus-launch-x11.sh if X11 autolaunching
+ was disabled at compile time. That test is not expected to work
+ in that configuration. (fd.o #98665, Simon McVittie)
+
+D-Bus 1.11.6 (2016-10-10)
+==
+
+The “darkly whimsical” release.
+
+Security fixes:
+
+• Do not treat ActivationFailure message received from root-owned systemd
+ name as a format string. In principle this is a security vulnerability,
+ but we do not believe it is exploitable in practice, because only
+ privileged processes can own the org.freedesktop.systemd1 bus name, and
+ systemd does not appear to send activation failures that contain "%".
+
+ Please note that this probably *was* exploitable in dbus versions
+ older than 1.6.30, 1.8.16 and 1.9.10 due to a missing check which at
+ the time was only thought to be a denial of service vulnerability
+ (CVE-2015-0245). If you are still running one of those versions,
+ patch or upgrade immediately.
+
+ (fd.o #98157, Simon McVittie)
+
+Enhancements:
+
+• D-Bus Specification version 0.29
+ · Recommend not using '/' for object paths (fd.o #37095, Philip Withnall)
+ · Allow <annotation> in <arg> elements (fd.o #86162, Philip Withnall)
+
+• Log to syslog when we exceed various anti-DoS limits, and add test
+ coverage for them (fd.o #86442, Simon McVittie)
+
+• Improve syslog handling so that _dbus_warn() and similar warnings
+ go to syslog, add dbus-daemon --syslog|--nosyslog|--syslog-only options,
+ and log to syslog (instead of /dev/null) when dbus-daemon is started by
+ dbus-launch. (fd.o #97009, Simon McVittie)
+
+• Install introspect.dtd and busconfig.dtd to ${datadir}/xml/dbus-1
+ (fd.o #89011, Philip Withnall)
+
+• When logging messages about service activation, mention which peer
+ requested the activation (fd.o #68212, Philip Withnall)
+
+• On Linux, mention the LSM label (if available) whenever we print
+ debug information about a peer (fd.o #68212, Philip Withnall)
+
+Other fixes:
+
+• Harden dbus-daemon against malicious or incorrect ActivationFailure
+ messages by rejecting them if they do not come from a privileged
+ process, or if systemd activation is not enabled
+ (fd.o #98157, Simon McVittie)
+
+• Avoid undefined behaviour when setting reply serial number without going
+ via union DBusBasicValue (fd.o #98035, Marc Mutz)
+
+• Fix CMake build for Unix platforms that do not have -lrt, such as Android,
+ or that do need -lsocket, such as QNX (fd.o #94096, Ralf Habacker)
+
+• autogen.sh: fail cleanly if autoconf fails (Simon McVittie)
+
+D-Bus 1.11.4 (2016-08-15)
+==
+
+The “copper pickaxe” release.
+
+Dependencies:
+
+• Building from git (but not from tarballs) now requires
+ macros from the GNU Autoconf Archive, for example the autoconf-archive
+ package in Debian or Fedora derivatives.
+
+Build-time configuration:
+
+• The option to enable coverage instrumentation has changed from
+ --enable-compiler-coverage to --enable-code-coverage.
+
+Enhancements:
+
+• D-Bus Specification version 0.28
+ · Clarify some details of serialization (fd.o #93382, Philip Withnall)
+
+• Increase listen() backlog of AF_UNIX sockets to the maximum possible,
+ minimizing failed connections under heavy load
+ (fd.o #95264, Lennart Poettering)
+
+• Add a new dbus-launch --exit-with-x11 option (fd.o #39197, Simon McVittie)
+
+• Use the same regression tests for subprocess starting on Unix and Windows
+ (fd.o #95191, Ralf Habacker)
+
+• Print timestamps and thread IDs in verbose messages
+ (fd.o #95191, Ralf Habacker)
+
+• On Unix, unify the various places that reopen stdin, stdout and/or stderr
+ pointing to /dev/null (fd.o #97008, Simon McVittie)
+
+• Use AX_CODE_COVERAGE instead of our own COMPILER_COVERAGE
+ (fd.o #88922, Thomas Zimmermann)
+
+Fixes:
+
+• On Windows, fix a memory leak in replacing the installation prefix
+ (fd.o #95191, Ralf Habacker)
+
+• On Linux, when dbus-daemon is run with reduced susceptibility to the
+ OOM killer (typically via systemd), do not let child processes inherit
+ that setting (fd.o #32851; Kimmo Hämäläinen, WaLyong Cho)
+
+• On Unix, make dbus-launch and dbus-daemon --fork work as intended
+ even if a parent process incorrectly starts them with stdin, stdout
+ and/or stderr closed (fd.o #97008, Simon McVittie)
+
+• Output valid shell syntax in ~/.dbus/session-bus/ if the bus address
+ contains a semicolon (fd.o #94746, Thiago Macieira)
+
+• Fix memory leaks and thread safety in subprocess starting on Windows
+ (fd.o #95191, Ralf Habacker)
+
+• Stop test-dbus-daemon incorrectly failing on platforms that cannot
+ discover the process ID of clients (fd.o #96653, Руслан Ижбулатов)
+
+• In tests that exercise correct handling of crashing D-Bus services,
+ suppress Windows crash handler (fd.o #95155; Yiyang Fei, Ralf Habacker)
+
+• Explicitly check for stdint.h (Ioan-Adrian Ratiu)
+
+• In tests, add an invalid DBusAuthState to avoid undefined behaviour
+ in some test cases (fd.o #93909, Nick Lewycky)
+
+• Add assertions to reassure a static analysis tool
+ (fd.o #93210, Deepika Aggarwal)
+
+• Be explicit about enum comparison when loading XML
+ (fd.o #93205, Deepika Aggarwal)
+
+• update-activation-environment: produce better diagnostics on error
+ (fd.o #96653, Simon McVittie)
+
+• Avoid various compiler warnings with gcc 6
+ (fd.o #97282; Thomas Zimmermann, Simon McVittie)
+
+• On Unix when configured to use the system log, report as "dbus-daemon",
+ not as "dbus" (fd.o #97009, Simon McVittie)
+
+• During unit tests, reduce the amount we write to the system log
+ (fd.o #97009, Simon McVittie)
+
+D-Bus 1.11.2 (2016-03-07)
+==
+
+The “pneumatic drill vs. Iron Maiden” release.
+
+Fixes:
+
+• Enable "large file support" on systems where it exists: dbus-daemon
+ is not expected to open large files, but it might need to stat files
+ that happen to have large inode numbers (fd.o #93545, Hongxu Jia)
+
+• Eliminate padding inside DBusMessageIter on 64-bit platforms,
+ which might result in a pedantic C compiler not copying the entire contents
+ of a DBusMessageIter; statically assert that this is not an ABI change
+ in practice (fd.o #94136, Simon McVittie)
+
+• Document dbus-test-tool echo --sleep-ms=N instead of incorrect --sleep=N
+ (fd.o #94244, Dmitri Iouchtchenko)
+
+• Correctly report test failures in C tests from run-test.sh
+ (fd.o #93379; amit tewari, Simon McVittie)
+
+• When tests are enabled, run all the marshal-validate tests, not just
+ the even-numbered ones (fd.o #93908, Nick Lewycky)
+
+• Correct the expected error from one marshal-validate test, which was
+ previously not run due to the above bug (fd.o #93908, Simon McVittie)
+
+• Fix compilation under CMake when embedded tests are disabled
+ (fd.o #94094, eric.hyer)
+
+Internal changes:
+
+• Fix all -Wpointer-sign (signed/unsigned mismatch) warnings, and enable the
+ warning (fd.o #93069; Ralf Habacker, Simon McVittie)
+
+• When building with CMake, use the same gcc/clang warnings as under Autotools,
+ or MSVC warnings that are broadly similar (fd.o #93069, Ralf Habacker)
+
+• test/name-test: make C tests produce TAP output and run them directly, not
+ via run-test.sh (fd.o #92899, Simon McVittie)
+
+• Under CMake when cross-compiling for Windows on Unix, run the tests
+ under Wine even if binfmt_misc support is not available
+ (fd.o #88966, Ralf Habacker)
+
+• The DBUS_USE_TEST_BINARY environment variable is no longer used by builds with
+ embedded tests; DBUS_TEST_DBUS_LAUNCH replaces it (fd.o #92899, Simon McVittie)
+
+• Factor out some functions that will be needed in future for a Windows
+ implementation of dbus-run-session (fd.o #92899, Ralf Habacker)
+
+D-Bus 1.11.0 (2015-12-02)
+==
+
+The “peppermint deer” release.
+
+Dependencies:
+
+• On non-Windows platforms, dbus now requires an <inttypes.h> that defines
+ C99 constants such as PRId64 and PRIu64.
+
+Enhancements:
+
+• D-Bus Specification version 0.27
+ · Specify that services should not reply if NO_REPLY_EXPECTED was used
+ (fd.o #75749, Lars Uebernickel)
+
+• Add a script to do continuous-integration builds, and metadata to run it
+ on travis-ci.org. To use this, clone the dbus git repository on GitHub
+ and set it up with travis-ci.org; the only special setting needed is
+ "only build branches with a .travis.yml". (fd.o #93194, Simon McVittie)
+
+• If dbus-daemon is run with --systemd-activation, do not require
+ org.freedesktop.systemd1.service to exist (fd.o #93194, Simon McVittie)
+
+Fixes:
+
+• Re-order dbus-daemon startup so that on SELinux systems, the thread
+ that reads AVC notifications retains the ability to write to the
+ audit log (fd.o #92832, Laurent Bigonville)
+
+• Print 64-bit integers on non-GNU Unix platforms (fd.o #92043, Natanael Copa)
+
+• When using the Monitoring interface, match messages' destinations
+ (fd.o #92074, Simon McVittie)
+
+• On Linux with systemd, stop installing a reference to the obsolete
+ dbus.target, and enable dbus.socket statically (fd.o #78412, #92402;
+ Simon McVittie)
+
+• On Windows, when including configuration files with <include> or
+ <includedir>, apply the same relocation as for the Exec paths
+ in .service files (fd.o #92028, Simon McVittie)
+
+• Add support for backtraces on Windows (fd.o #92721, Ralf Habacker)
+
+• Fix many -Wpointer-sign warnings (fd.o #93069, Ralf Habacker)
+
D-Bus 1.10.6 (2015-12-01)
==
diff --git a/README b/README
index 0257e69d..8fa009ef 100644
--- a/README
+++ b/README
@@ -18,7 +18,8 @@ The "and coordination" part is important; D-Bus provides a bus daemon that does
See http://www.freedesktop.org/software/dbus/ for lots of documentation,
mailing lists, etc.
-See also the file HACKING for notes of interest to developers working on D-Bus.
+See also the file CONTRIBUTING.md for notes of interest to developers
+working on D-Bus.
If you're considering D-Bus for use in a project, you should be aware
that D-Bus was designed for a couple of specific use cases, a "system
diff --git a/README.cmake b/README.cmake
index c3c6a170..69012fbe 100644
--- a/README.cmake
+++ b/README.cmake
@@ -2,7 +2,7 @@ This file describes how to compile dbus using the cmake build system
Requirements
------------
-- cmake version >= 2.4.4 see http://www.cmake.org
+- cmake version >= 2.6.0 see http://www.cmake.org
- installed libexpat see http://sourceforge.net/projects/expat/
unsupported RelWithDebInfo builds could be fetched
from http://sourceforge.net/projects/kde-windows/files/expat/
@@ -123,9 +123,6 @@ DBUS_ENABLE_VERBOSE_MODE:BOOL=ON
// build XML documentation (requires xmlto or meinproc4)
DBUS_ENABLE_XML_DOCS:BOOL=ON
-// Some atomic integer implementation present
-DBUS_HAVE_ATOMIC_INT:BOOL=OFF
-
// install required system libraries
DBUS_INSTALL_SYSTEM_LIBS:BOOL=OFF
@@ -138,9 +135,6 @@ DBUS_SESSION_BUS_CONNECT_ADDRESS:STRING=autolaunch:
// system bus default address (only useful on Unix)
DBUS_SYSTEM_BUS_DEFAULT_ADDRESS:STRING=unix:path=/var/run/dbus/system_bus_socket
-// Use atomic integer implementation for 486
-DBUS_USE_ATOMIC_INT_486:BOOL=OFF
-
win32 only:
// enable win32 debug port for message output
DBUS_USE_OUTPUT_DEBUG_STRING:BOOL=OFF
@@ -164,10 +158,6 @@ DBUS_BUS_ENABLE_INOTIFY:BOOL=ON
// enable kqueue as dir watch backend
DBUS_BUS_ENABLE_KQUEUE:BOOL=ON
-not available on windows:
-// enable abstract socket transport
-DBUS_ENABLE_ABSTRACT_SOCKETS:BOOL=ON
-
x11 only:
// Build with X11 auto launch support
DBUS_BUILD_X11:BOOL=ON
@@ -177,3 +167,27 @@ Note: The above mentioned options could be extracted after
configuring from the output of running "<maketool> help-options"
in the build directory. The related entries start with
CMAKE_ or DBUS_.
+
+
+How to compile in dbus into clients with cmake
+----------------------------------------------
+
+To compile dbus library into a client application with cmake
+the following cmake commands are required:
+
+1. call find_package to find dbus package
+
+find_package(DBus1)
+
+2. after specifing targets link dbus into target
+
+add_executable(test test.c)
+target_link_libraries(test ${DBus1_LIBRARIES})
+
+Adding ${DBus1_LIBRARIES} to targets also adds required dbus
+include dirs and compiler definitions by default. There is
+no need to add them with include_directories and add_definitions.
+
+To compile against dbus installed in a non standard location
+specify -DDBus1_DIR=<dbus-install-root>/lib[64]/cmake/DBus1
+on cmake command line.
diff --git a/autogen.sh b/autogen.sh
index 91d4b09d..6de735f0 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -81,7 +81,10 @@ $ACLOCAL -I m4 $ACLOCAL_FLAGS
(autoheader --version) < /dev/null > /dev/null 2>&1 && autoheader
$AUTOMAKE -a $am_opt
-autoconf || echo "autoconf failed - version 2.5x is probably required"
+if ! autoconf; then
+ echo "autoconf failed - version 2.5x is probably required" >&2
+ exit 1
+fi
cd $ORIGDIR
diff --git a/bus/Makefile.am b/bus/Makefile.am
index 5f28a25f..a82db939 100644
--- a/bus/Makefile.am
+++ b/bus/Makefile.am
@@ -1,9 +1,13 @@
dbusdatadir=$(datadir)/dbus-1
legacydbusdatadir=$(sysconfdir)/dbus-1
dbus_daemon_execdir = $(DBUS_DAEMONDIR)
+# Always lib, even if ${libdir} is lib64 or lib/x86_64-linux-gnu
+systemdtmpfilesdir = $(prefix)/lib/tmpfiles.d
+systemdsysusersdir = $(prefix)/lib/sysusers.d
DBUS_BUS_LIBS = \
- $(XML_LIBS) \
+ $(CODE_COVERAGE_LIBS) \
+ $(EXPAT_LIBS) \
$(SELINUX_LIBS) \
$(APPARMOR_LIBS) \
$(THREAD_LIBS) \
@@ -13,15 +17,17 @@ DBUS_BUS_LIBS = \
$(NULL)
DBUS_LAUNCHER_LIBS = \
- $(XML_LIBS) \
+ $(CODE_COVERAGE_LIBS) \
+ $(EXPAT_LIBS) \
$(THREAD_LIBS) \
$(NETWORK_libs) \
$(NULL)
AM_CPPFLAGS = \
+ $(CODE_COVERAGE_CPPFLAGS) \
-I$(top_srcdir) \
$(DBUS_STATIC_BUILD_CPPFLAGS) \
- $(XML_CFLAGS) \
+ $(EXPAT_CFLAGS) \
$(APPARMOR_CFLAGS) \
-DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \
-DDBUS_COMPILATION \
@@ -31,9 +37,13 @@ AM_CPPFLAGS = \
# if assertions are enabled, improve backtraces
AM_LDFLAGS = @R_DYNAMIC_LDFLAG@ -Wl,-z,relro,-z,now
+AM_CFLAGS = \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(NULL)
+
EFENCE=
-CONFIG_IN_FILES= \
+EXTRA_DIST = \
session.conf.in \
system.conf.in \
legacy-config/session.conf.in \
@@ -62,8 +72,6 @@ agentdir=$(LAUNCHD_AGENT_DIR)
agent_DATA=org.freedesktop.dbus-session.plist
endif
-XML_SOURCES=config-loader-expat.c
-
if DBUS_BUS_ENABLE_KQUEUE
DIR_WATCH_SOURCE=dir-watch-kqueue.c
else
@@ -86,6 +94,7 @@ BUS_SOURCES= \
bus.h \
check.c \
check.h \
+ config-loader-expat.c \
config-parser.c \
config-parser.h \
config-parser-common.c \
@@ -118,7 +127,7 @@ BUS_SOURCES= \
test.h \
utils.c \
utils.h \
- $(XML_SOURCES)
+ $(NULL)
dbus_daemon_SOURCES= \
$(BUS_SOURCES) \
@@ -131,7 +140,7 @@ dbus_daemon_LDADD= \
$(DBUS_BUS_LIBS)
LAUNCH_HELPER_SOURCES= \
- $(XML_SOURCES) \
+ config-loader-expat.c \
config-parser-common.c \
config-parser-common.h \
config-parser-trivial.c \
@@ -214,7 +223,7 @@ endif DBUS_UNIX
endif DBUS_ENABLE_EMBEDDED_TESTS
test_bus_system_SOURCES= \
- $(XML_SOURCES) \
+ config-loader-expat.c \
config-parser-common.c \
config-parser-common.h \
config-parser-trivial.c \
@@ -239,10 +248,6 @@ test_bus_LDADD = \
$(DBUS_BUS_LIBS) \
$(NULL)
-## mop up the gcov files
-clean-local:
- /bin/rm *.bb *.bbg *.da *.gcov || true
-
install-data-hook:
$(mkinstalldirs) $(DESTDIR)$(dbusdatadir)/session.d
$(mkinstalldirs) $(DESTDIR)$(dbusdatadir)/services
@@ -255,8 +260,6 @@ if HAVE_SYSTEMD
# Install dbus.socket as default implementation of a D-Bus stack.
# Deliberately not using $(LN_S) here: ln -fs is not universally portable,
# but neither is systemd, so it's OK to assume here that ln complies with SUS.
- $(mkinstalldirs) $(DESTDIR)$(systemdsystemunitdir)/dbus.target.wants
- ln -fs ../dbus.socket $(DESTDIR)$(systemdsystemunitdir)/dbus.target.wants/dbus.socket
# Unconditionally enable D-Bus on systemd installations
$(mkinstalldirs) $(DESTDIR)$(systemdsystemunitdir)/sockets.target.wants
ln -fs ../dbus.socket $(DESTDIR)$(systemdsystemunitdir)/sockets.target.wants/dbus.socket
@@ -277,53 +280,26 @@ install-exec-hook:
fi
endif
-#### Init scripts fun
-SCRIPT_IN_FILES=messagebus.in \
- messagebus-config.in \
- rc.messagebus.in
-
-## Red Hat start
-if DBUS_INIT_SCRIPTS_RED_HAT
-
-initddir=$(sysconfdir)/rc.d/init.d
-
-initd_SCRIPTS= \
- messagebus
-
-endif
- ## Red Hat end
-
-## Slackware start
-if DBUS_INIT_SCRIPTS_SLACKWARE
-
-initddir=$(sysconfdir)/rc.d/
-
-initd_SCRIPTS= \
- rc.messagebus
-
-endif
-## Slackware end
-
-## Cygwin start
-if DBUS_INIT_SCRIPTS_CYGWIN
-
-bin_SCRIPTS= \
- messagebus-config
-
-endif
-## Cygwin end
-
-if HAVE_SYSTEMD
-SCRIPT_IN_FILES += \
+EXTRA_DIST += \
dbus.service.in \
dbus.socket.in \
systemd-user/dbus.service.in \
systemd-user/dbus.socket.in \
+ sysusers.d/dbus.conf.in \
+ tmpfiles.d/dbus.conf.in \
$(NULL)
+if HAVE_SYSTEMD
systemdsystemunit_DATA = \
dbus.service \
dbus.socket
+
+nodist_systemdsysusers_DATA = \
+ sysusers.d/dbus.conf
+
+nodist_systemdtmpfiles_DATA = \
+ tmpfiles.d/dbus.conf \
+ $(NULL)
endif
if DBUS_ENABLE_USER_SESSION
@@ -333,6 +309,5 @@ systemduserunit_DATA = \
$(NULL)
endif
-#### Extra dist
-
-EXTRA_DIST=$(CONFIG_IN_FILES) $(SCRIPT_IN_FILES)
+# Add rules for code-coverage testing, as defined by AX_CODE_COVERAGE
+include $(top_srcdir)/aminclude_static.am
diff --git a/bus/activation-helper.c b/bus/activation-helper.c
index 394f3938..5b6a0908 100644
--- a/bus/activation-helper.c
+++ b/bus/activation-helper.c
@@ -80,7 +80,7 @@ desktop_file_for_name (BusConfigParser *parser,
goto out;
}
- service_dirs = bus_config_parser_get_service_dirs (parser);
+ service_dirs = bus_config_parser_get_service_paths (parser);
for (link = _dbus_list_get_first_link (service_dirs);
link != NULL;
link = _dbus_list_get_next_link (service_dirs, link))
diff --git a/bus/activation-helper.h b/bus/activation-helper.h
index 361a4c6a..43e7b150 100644
--- a/bus/activation-helper.h
+++ b/bus/activation-helper.h
@@ -25,6 +25,8 @@
#ifndef BUS_ACTIVATION_HELPER_H
#define BUS_ACTIVATION_HELPER_H
+#include <dbus/dbus.h>
+
dbus_bool_t run_launch_helper (const char *bus_name, DBusError *error);
diff --git a/bus/activation.c b/bus/activation.c
index 99b3554a..ef1aa18c 100644
--- a/bus/activation.c
+++ b/bus/activation.c
@@ -26,6 +26,7 @@
#include <config.h>
#include "activation.h"
#include "activation-exit-codes.h"
+#include "config-parser.h"
#include "desktop-file.h"
#include "dispatch.h"
#include "services.h"
@@ -54,7 +55,7 @@ struct BusActivation
* i.e. number of pending activation requests, not pending
* activations per se
*/
- DBusHashTable *directories;
+ DBusList *directories;
DBusHashTable *environment;
};
@@ -62,6 +63,7 @@ typedef struct
{
int refcount;
char *dir_c;
+ BusServiceDirFlags flags;
DBusHashTable *entries;
} BusServiceDirectory;
@@ -72,6 +74,7 @@ struct BusActivationEntry
char *exec;
char *user;
char *systemd_service;
+ char *assumed_apparmor_label;
unsigned long mtime;
BusServiceDirectory *s_dir;
char *filename;
@@ -247,6 +250,7 @@ bus_activation_entry_unref (BusActivationEntry *entry)
dbus_free (entry->user);
dbus_free (entry->filename);
dbus_free (entry->systemd_service);
+ dbus_free (entry->assumed_apparmor_label);
dbus_free (entry);
}
@@ -259,11 +263,13 @@ update_desktop_file_entry (BusActivation *activation,
DBusError *error)
{
char *name, *exec, *user, *exec_tmp, *systemd_service;
+ char *assumed_apparmor_label;
BusActivationEntry *entry;
DBusStat stat_buf;
DBusString file_path;
DBusError tmp_error;
dbus_bool_t retval;
+ DBusString str;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -274,6 +280,7 @@ update_desktop_file_entry (BusActivation *activation,
exec_tmp = NULL;
entry = NULL;
systemd_service = NULL;
+ assumed_apparmor_label = NULL;
dbus_error_init (&tmp_error);
@@ -311,9 +318,18 @@ update_desktop_file_entry (BusActivation *activation,
error))
goto out;
- exec = _dbus_strdup (_dbus_replace_install_prefix (exec_tmp));
- dbus_free (exec_tmp);
- exec_tmp = NULL;
+ if (!_dbus_string_init (&str))
+ goto out;
+
+ if (!_dbus_string_append (&str, exec_tmp) ||
+ !_dbus_replace_install_prefix (&str) ||
+ !_dbus_string_steal_data (&str, &exec))
+ {
+ _dbus_string_free (&str);
+ goto out;
+ }
+
+ _dbus_string_free (&str);
/* user is not _required_ unless we are using system activation */
if (!bus_desktop_file_get_string (desktop_file,
@@ -360,6 +376,28 @@ update_desktop_file_entry (BusActivation *activation,
}
}
+ /* assumed AppArmor label is never required */
+ if (!bus_desktop_file_get_string (desktop_file,
+ DBUS_SERVICE_SECTION,
+ DBUS_SERVICE_ASSUMED_APPARMOR_LABEL,
+ &assumed_apparmor_label, &tmp_error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+ /* if we got OOM, then exit */
+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_move_error (&tmp_error, error);
+ goto out;
+ }
+ else
+ {
+ /* if we have error because we didn't find anything then continue */
+ dbus_error_free (&tmp_error);
+ dbus_free (assumed_apparmor_label);
+ assumed_apparmor_label = NULL;
+ }
+ }
+
_DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
entry = _dbus_hash_table_lookup_string (s_dir->entries,
@@ -367,8 +405,69 @@ update_desktop_file_entry (BusActivation *activation,
if (entry == NULL) /* New file */
{
+ DBusString expected_name;
+
+ if (!_dbus_string_init (&expected_name))
+ {
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ if (!_dbus_string_append (&expected_name, name) ||
+ !_dbus_string_append (&expected_name, ".service"))
+ {
+ _dbus_string_free (&expected_name);
+ BUS_SET_OOM (error);
+ goto out;
+ }
+
+ if (_dbus_string_equal (&expected_name, filename))
+ {
+ _dbus_verbose ("Name of \"%s\" is as expected\n",
+ _dbus_string_get_const_data (&file_path));
+ }
+ else if (s_dir->flags & BUS_SERVICE_DIR_FLAGS_STRICT_NAMING)
+ {
+ bus_context_log_and_set_error (activation->context,
+ DBUS_SYSTEM_LOG_WARNING, error,
+ DBUS_ERROR_FAILED,
+ "Service file \"%s\" should have "
+ "been named \"%s\": not loading it",
+ _dbus_string_get_const_data (&file_path),
+ _dbus_string_get_const_data (&expected_name));
+ _dbus_string_free (&expected_name);
+ goto out;
+ }
+ else if (bus_context_get_servicehelper (activation->context) != NULL)
+ {
+ bus_context_log (activation->context, DBUS_SYSTEM_LOG_WARNING,
+ "Service file \"%s\" should have been named \"%s\" "
+ "and will not work with system bus activation",
+ _dbus_string_get_const_data (&file_path),
+ _dbus_string_get_const_data (&expected_name));
+ /* We don't actually error out here, because *technically* it could
+ * still work on systemd systems, where we tell systemd to start the
+ * SystemdService instead of launching dbus-daemon-launch-helper
+ * ourselves. But maybe we should:
+ * https://bugs.freedesktop.org/show_bug.cgi?id=99874 */
+ }
+ else
+ {
+ /* We could maybe log mismatched names for session services in
+ * a user-visible way too, but not until
+ * https://lintian.debian.org/tags/dbus-session-service-wrong-name.html
+ * is a bit shorter.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=99873 */
+ _dbus_verbose ("Name of \"%s\" should canonically be \"%s\"\n",
+ _dbus_string_get_const_data (&file_path),
+ _dbus_string_get_const_data (&expected_name));
+ }
+
+ _dbus_string_free (&expected_name);
+
/* FIXME we need a better-defined algorithm for which service file to
* pick than "whichever one is first in the directory listing"
+ * See also https://bugs.freedesktop.org/show_bug.cgi?id=99874
*/
if (_dbus_hash_table_lookup_string (activation->entries, name))
{
@@ -388,6 +487,7 @@ update_desktop_file_entry (BusActivation *activation,
entry->exec = exec;
entry->user = user;
entry->systemd_service = systemd_service;
+ entry->assumed_apparmor_label = assumed_apparmor_label;
entry->refcount = 1;
/* ownership has been transferred to entry, do not free separately */
@@ -395,6 +495,7 @@ update_desktop_file_entry (BusActivation *activation,
exec = NULL;
user = NULL;
systemd_service = NULL;
+ assumed_apparmor_label = NULL;
entry->s_dir = s_dir;
entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename));
@@ -452,6 +553,10 @@ update_desktop_file_entry (BusActivation *activation,
entry->systemd_service = systemd_service;
systemd_service = NULL;
+ dbus_free (entry->assumed_apparmor_label);
+ entry->assumed_apparmor_label = assumed_apparmor_label;
+ assumed_apparmor_label = NULL;
+
if (!_dbus_hash_table_insert_string (activation->entries,
entry->name, bus_activation_entry_ref(entry)))
{
@@ -469,10 +574,12 @@ update_desktop_file_entry (BusActivation *activation,
out:
/* if these have been transferred into entry, the variables will be NULL */
+ dbus_free (exec_tmp);
dbus_free (name);
dbus_free (exec);
dbus_free (user);
dbus_free (systemd_service);
+ dbus_free (assumed_apparmor_label);
_dbus_string_free (&file_path);
if (entry)
@@ -732,9 +839,6 @@ update_directory (BusActivation *activation,
static dbus_bool_t
populate_environment (BusActivation *activation)
{
- DBusString key;
- DBusString value;
- int i;
char **environment;
dbus_bool_t retval = FALSE;
@@ -743,50 +847,7 @@ populate_environment (BusActivation *activation)
if (environment == NULL)
return FALSE;
- if (!_dbus_string_init (&key))
- {
- dbus_free_string_array (environment);
- return FALSE;
- }
-
- if (!_dbus_string_init (&value))
- {
- _dbus_string_free (&key);
- dbus_free_string_array (environment);
- return FALSE;
- }
-
- for (i = 0; environment[i] != NULL; i++)
- {
- if (!_dbus_string_append (&key, environment[i]))
- break;
-
- if (_dbus_string_split_on_byte (&key, '=', &value))
- {
- char *hash_key, *hash_value;
-
- if (!_dbus_string_steal_data (&key, &hash_key))
- break;
-
- if (!_dbus_string_steal_data (&value, &hash_value))
- break;
-
- if (!_dbus_hash_table_insert_string (activation->environment,
- hash_key, hash_value))
- break;
- }
- _dbus_string_set_length (&key, 0);
- _dbus_string_set_length (&value, 0);
- }
-
- if (environment[i] != NULL)
- goto out;
-
- retval = TRUE;
-out:
-
- _dbus_string_free (&key);
- _dbus_string_free (&value);
+ retval = _dbus_hash_table_from_array (activation->environment, environment, '=');
dbus_free_string_array (environment);
return retval;
@@ -819,23 +880,19 @@ bus_activation_reload (BusActivation *activation,
goto failed;
}
- if (activation->directories != NULL)
- _dbus_hash_table_unref (activation->directories);
- activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
- (DBusFreeFunction)bus_service_directory_unref);
-
- if (activation->directories == NULL)
- {
- BUS_SET_OOM (error);
- goto failed;
- }
+ _dbus_list_foreach (&activation->directories,
+ (DBusForeachFunction) bus_service_directory_unref, NULL);
+ _dbus_list_clear (&activation->directories);
link = _dbus_list_get_first_link (directories);
while (link != NULL)
{
+ BusConfigServiceDir *config = link->data;
BusServiceDirectory *s_dir;
- dir = _dbus_strdup ((const char *) link->data);
+ _dbus_assert (config->path != NULL);
+
+ dir = _dbus_strdup (config->path);
if (!dir)
{
BUS_SET_OOM (error);
@@ -852,6 +909,7 @@ bus_activation_reload (BusActivation *activation,
s_dir->refcount = 1;
s_dir->dir_c = dir;
+ s_dir->flags = config->flags;
s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
(DBusFreeFunction)bus_activation_entry_unref);
@@ -863,7 +921,7 @@ bus_activation_reload (BusActivation *activation,
goto failed;
}
- if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
+ if (!_dbus_list_append (&activation->directories, s_dir))
{
bus_service_directory_unref (s_dir);
BUS_SET_OOM (error);
@@ -970,8 +1028,11 @@ bus_activation_unref (BusActivation *activation)
_dbus_hash_table_unref (activation->entries);
if (activation->pending_activations)
_dbus_hash_table_unref (activation->pending_activations);
- if (activation->directories)
- _dbus_hash_table_unref (activation->directories);
+
+ _dbus_list_foreach (&activation->directories,
+ (DBusForeachFunction) bus_service_directory_unref, NULL);
+ _dbus_list_clear (&activation->directories);
+
if (activation->environment)
_dbus_hash_table_unref (activation->environment);
@@ -1213,6 +1274,7 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation
entry->activation_message);
}
+ dbus_error_free (&error);
link = next;
continue;
case BUS_RESULT_LATER:
@@ -1473,7 +1535,8 @@ pending_activation_finished_cb (DBusBabysitter *babysitter,
{
BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
- if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
+ if (p != pending_activation && p->exec != NULL &&
+ strcmp (p->exec, pending_activation->exec) == 0)
pending_activation_failed (p, &error);
}
@@ -1522,7 +1585,12 @@ static dbus_bool_t
pending_activation_timed_out (void *data)
{
BusPendingActivation *pending_activation = data;
+ BusContext *context;
DBusError error;
+ int timeout;
+
+ context = pending_activation->activation->context;
+ timeout = bus_context_get_activation_timeout (context);
/* Kill the spawned process, since it sucks
* (not sure this is what we want to do, but
@@ -1533,10 +1601,11 @@ pending_activation_timed_out (void *data)
dbus_error_init (&error);
- bus_context_log_and_set_error (pending_activation->activation->context,
- DBUS_SYSTEM_LOG_INFO, &error, DBUS_ERROR_TIMED_OUT,
- "Failed to activate service '%s': timed out",
- pending_activation->service_name);
+ bus_context_log_and_set_error (context, DBUS_SYSTEM_LOG_WARNING, &error,
+ DBUS_ERROR_TIMED_OUT,
+ "Failed to activate service '%s': timed out "
+ "(service_start_timeout=%dms)",
+ pending_activation->service_name, timeout);
pending_activation_failed (pending_activation, &error);
@@ -1587,15 +1656,14 @@ add_cancel_pending_to_transaction (BusTransaction *transaction,
static dbus_bool_t
update_service_cache (BusActivation *activation, DBusError *error)
{
- DBusHashIter iter;
+ DBusList *iter;
- _dbus_hash_iter_init (activation->directories, &iter);
- while (_dbus_hash_iter_next (&iter))
+ for (iter = _dbus_list_get_first_link (&activation->directories);
+ iter != NULL;
+ iter = _dbus_list_get_next_link (&activation->directories, iter))
{
DBusError tmp_error;
- BusServiceDirectory *s_dir;
-
- s_dir = _dbus_hash_iter_get_value (&iter);
+ BusServiceDirectory *s_dir = iter->data;
dbus_error_init (&tmp_error);
if (!update_directory (activation, s_dir, &tmp_error))
@@ -1654,51 +1722,7 @@ activation_find_entry (BusActivation *activation,
static char **
bus_activation_get_environment (BusActivation *activation)
{
- char **environment;
- int i, length;
- DBusString entry;
- DBusHashIter iter;
-
- length = _dbus_hash_table_get_n_entries (activation->environment);
-
- environment = dbus_new0 (char *, length + 1);
-
- if (environment == NULL)
- return NULL;
-
- i = 0;
- _dbus_hash_iter_init (activation->environment, &iter);
-
- if (!_dbus_string_init (&entry))
- {
- dbus_free_string_array (environment);
- return NULL;
- }
-
- while (_dbus_hash_iter_next (&iter))
- {
- const char *key, *value;
-
- key = (const char *) _dbus_hash_iter_get_string_key (&iter);
- value = (const char *) _dbus_hash_iter_get_value (&iter);
-
- if (!_dbus_string_append_printf (&entry, "%s=%s", key, value))
- break;
-
- if (!_dbus_string_steal_data (&entry, environment + i))
- break;
- i++;
- }
-
- _dbus_string_free (&entry);
-
- if (i != length)
- {
- dbus_free_string_array (environment);
- environment = NULL;
- }
-
- return environment;
+ return _dbus_hash_table_to_array (activation->environment, '=');
}
dbus_bool_t
@@ -1788,21 +1812,36 @@ bus_activation_activate_service (BusActivation *activation,
BusResult retval = BUS_RESULT_FALSE;
dbus_bool_t was_pending_activation;
DBusString command;
+ int limit;
+ DBusSpawnFlags flags = DBUS_SPAWN_NONE;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (activation->n_pending_activations >=
- bus_context_get_max_pending_activations (activation->context))
+ limit = bus_context_get_max_pending_activations (activation->context);
+
+ if (activation->n_pending_activations >= limit)
{
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
- "The maximum number of pending activations has been reached, activation of %s failed",
- service_name);
+ "The maximum number of pending activations has been "
+ "reached, activation of %s failed "
+ "(max_pending_service_starts=%d)",
+ service_name, limit);
return BUS_RESULT_FALSE;
}
- entry = activation_find_entry (activation, service_name, error);
- if (!entry)
- return BUS_RESULT_FALSE;
+ if (bus_context_get_systemd_activation (activation->context) &&
+ strcmp (service_name, "org.freedesktop.systemd1") == 0)
+ {
+ /* if we're doing systemd activation, we assume systemd will connect
+ * eventually, and it does not need a .service file */
+ entry = NULL;
+ }
+ else
+ {
+ entry = activation_find_entry (activation, service_name, error);
+ if (!entry)
+ return BUS_RESULT_FALSE;
+ }
if (auto_activation && entry != NULL)
{
@@ -1936,17 +1975,20 @@ bus_activation_activate_service (BusActivation *activation,
return BUS_RESULT_FALSE;
}
- pending_activation->exec = _dbus_strdup (entry->exec);
- if (!pending_activation->exec)
+ if (entry != NULL)
{
- _dbus_verbose ("Failed to copy service exec for pending activation\n");
- BUS_SET_OOM (error);
- bus_pending_activation_unref (pending_activation);
- bus_pending_activation_entry_free (pending_activation_entry);
- return FALSE;
+ pending_activation->exec = _dbus_strdup (entry->exec);
+ if (!pending_activation->exec)
+ {
+ _dbus_verbose ("Failed to copy service exec for pending activation\n");
+ BUS_SET_OOM (error);
+ bus_pending_activation_unref (pending_activation);
+ bus_pending_activation_entry_free (pending_activation_entry);
+ return FALSE;
+ }
}
- if (entry->systemd_service)
+ if (entry != NULL && entry->systemd_service != NULL)
{
pending_activation->systemd_service = _dbus_strdup (entry->systemd_service);
if (!pending_activation->systemd_service)
@@ -2036,6 +2078,7 @@ bus_activation_activate_service (BusActivation *activation,
DBusString service_string;
BusService *service;
BusRegistry *registry;
+ DBusConnection *systemd = NULL;
/* OK, we have a systemd service configured for this entry,
hence let's enqueue an activation request message. This
@@ -2084,11 +2127,14 @@ bus_activation_activate_service (BusActivation *activation,
_dbus_string_init_const (&service_string, "org.freedesktop.systemd1");
service = bus_registry_lookup (registry, &service_string);
+ if (service)
+ systemd = bus_service_get_primary_owners_connection (service);
+
/* Following the general principle of "log early and often",
* we capture that we *want* to send the activation message, even if
* systemd is not actually there to receive it yet */
if (!bus_transaction_capture (activation_transaction,
- NULL, message))
+ NULL, systemd, message))
{
dbus_message_unref (message);
BUS_SET_OOM (error);
@@ -2098,22 +2144,25 @@ bus_activation_activate_service (BusActivation *activation,
if (service != NULL)
{
bus_context_log (activation->context,
- DBUS_SYSTEM_LOG_INFO, "Activating via systemd: service name='%s' unit='%s'",
+ DBUS_SYSTEM_LOG_INFO, "Activating via systemd: service name='%s' unit='%s' requested by '%s' (%s)",
service_name,
- entry->systemd_service);
+ entry->systemd_service,
+ bus_connection_get_name (connection),
+ bus_connection_get_loginfo (connection));
/* Wonderful, systemd is connected, let's just send the msg */
retval = bus_dispatch_matches (activation_transaction, NULL,
- bus_service_get_primary_owners_connection (service),
- message, NULL, error);
+ systemd, message, NULL, error);
if (BUS_RESULT_LATER == retval)
_dbus_verbose("Unexpectedly need time to check message from bus driver to systemd - dropping the message.\n");
}
else
{
bus_context_log (activation->context,
- DBUS_SYSTEM_LOG_INFO, "Activating systemd to hand-off: service name='%s' unit='%s'",
+ DBUS_SYSTEM_LOG_INFO, "Activating systemd to hand-off: service name='%s' unit='%s' requested by '%s' (%s)",
service_name,
- entry->systemd_service);
+ entry->systemd_service,
+ bus_connection_get_name (connection),
+ bus_connection_get_loginfo (connection));
/* systemd is not around, let's "activate" it. */
retval = bus_activation_activate_service (activation, NULL, activation_transaction, TRUE,
message, "org.freedesktop.systemd1", error, deferred_message);
@@ -2141,6 +2190,11 @@ bus_activation_activate_service (BusActivation *activation,
proceed with traditional activation. */
}
+ /* If entry was NULL, it would be because we were doing systemd activation
+ * and activating systemd itself; but we already handled that case with
+ * an early-return */
+ _dbus_assert (entry != NULL);
+
/* use command as system and session different */
if (!_dbus_string_init (&command))
{
@@ -2220,19 +2274,27 @@ bus_activation_activate_service (BusActivation *activation,
_dbus_verbose ("Spawning %s ...\n", argv[0]);
if (servicehelper != NULL)
bus_context_log (activation->context,
- DBUS_SYSTEM_LOG_INFO, "Activating service name='%s' (using servicehelper)",
- service_name);
+ DBUS_SYSTEM_LOG_INFO, "Activating service name='%s' requested by '%s' (%s) (using servicehelper)",
+ service_name,
+ bus_connection_get_name (connection),
+ bus_connection_get_loginfo (connection));
else
bus_context_log (activation->context,
- DBUS_SYSTEM_LOG_INFO, "Activating service name='%s'",
- service_name);
+ DBUS_SYSTEM_LOG_INFO, "Activating service name='%s' requested by '%s' (%s)",
+ service_name,
+ bus_connection_get_name (connection),
+ bus_connection_get_loginfo (connection));
dbus_error_init (&tmp_error);
+ if (bus_context_get_using_syslog (activation->context))
+ flags |= DBUS_SPAWN_REDIRECT_OUTPUT;
+
if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter,
service_name,
argv,
envp,
+ flags,
child_setup,
activation,
&tmp_error))
@@ -2341,7 +2403,7 @@ dbus_activation_systemd_failure (BusActivation *activation,
DBUS_TYPE_STRING, &code,
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID))
- dbus_set_error(&error, code, str);
+ dbus_set_error (&error, code, "%s", str);
if (unit)
@@ -2370,13 +2432,19 @@ dbus_activation_systemd_failure (BusActivation *activation,
return TRUE;
}
+const char *
+bus_activation_entry_get_assumed_apparmor_label (BusActivationEntry *entry)
+{
+ return entry->assumed_apparmor_label;
+}
+
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
#include <stdio.h>
-#define SERVICE_NAME_1 "MyService1"
-#define SERVICE_NAME_2 "MyService2"
-#define SERVICE_NAME_3 "MyService3"
+#define SERVICE_NAME_1 "com.example.MyService1"
+#define SERVICE_NAME_2 "org.example.MyService2"
+#define SERVICE_NAME_3 "net.example.MyService3"
#define SERVICE_FILE_1 "service-1.service"
#define SERVICE_FILE_2 "service-2.service"
@@ -2503,21 +2571,8 @@ out:
static dbus_bool_t
init_service_reload_test (DBusString *dir)
{
- DBusStat stat_buf;
-
- if (!_dbus_stat (dir, &stat_buf, NULL))
- {
- if (!_dbus_create_directory (dir, NULL))
- return FALSE;
- }
- else
- {
- if (!test_remove_directory (dir))
- return FALSE;
-
- if (!_dbus_create_directory (dir, NULL))
- return FALSE;
- }
+ if (!_dbus_create_directory (dir, NULL))
+ return FALSE;
/* Create one initial file */
if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
@@ -2596,9 +2651,13 @@ do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
}
static dbus_bool_t
-do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
+do_service_reload_test (const DBusString *test_data_dir,
+ DBusString *dir,
+ dbus_bool_t oom_test)
{
BusActivation *activation;
+ BusConfigServiceDir config;
+ BusContext *context;
DBusString address;
DBusList *directories;
CheckData d;
@@ -2606,10 +2665,18 @@ do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
directories = NULL;
_dbus_string_init_const (&address, "");
- if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
+ config.path = _dbus_string_get_data (dir);
+ config.flags = BUS_SERVICE_DIR_FLAGS_NONE;
+
+ if (!_dbus_list_append (&directories, &config))
return FALSE;
- activation = bus_activation_new (NULL, &address, &directories, NULL);
+ context = bus_context_new_test (test_data_dir,
+ "valid-config-files/debug-allow-all.conf");
+ if (context == NULL)
+ return FALSE;
+
+ activation = bus_activation_new (context, &address, &directories, NULL);
if (!activation)
return FALSE;
@@ -2670,6 +2737,7 @@ do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
bus_activation_unref (activation);
_dbus_list_clear (&directories);
+ bus_context_unref (context);
return TRUE;
}
@@ -2700,16 +2768,19 @@ bus_activation_service_reload_test (const DBusString *test_data_dir)
if (!init_service_reload_test (&directory))
_dbus_assert_not_reached ("could not initiate service reload test");
- if (!do_service_reload_test (&directory, FALSE))
+ if (!do_service_reload_test (test_data_dir, &directory, FALSE))
{
/* Do nothing? */
}
+ if (!cleanup_service_reload_test (&directory))
+ goto out;
+
/* Do OOM tests */
if (!init_service_reload_test (&directory))
_dbus_assert_not_reached ("could not initiate service reload test");
- if (!do_service_reload_test (&directory, TRUE))
+ if (!do_service_reload_test (test_data_dir, &directory, TRUE))
{
/* Do nothing? */
}
diff --git a/bus/activation.h b/bus/activation.h
index c24f85d3..bd91954f 100644
--- a/bus/activation.h
+++ b/bus/activation.h
@@ -65,5 +65,6 @@ dbus_bool_t bus_activation_send_pending_auto_activation_messages (BusActivati
BusService *service,
BusTransaction *transaction);
+const char *bus_activation_entry_get_assumed_apparmor_label (BusActivationEntry *entry);
#endif /* BUS_ACTIVATION_H */
diff --git a/bus/apparmor.c b/bus/apparmor.c
index 46725dbf..471fb551 100644
--- a/bus/apparmor.c
+++ b/bus/apparmor.c
@@ -46,6 +46,7 @@
#include <libaudit.h>
#endif /* HAVE_LIBAUDIT */
+#include "activation.h"
#include "audit.h"
#include "connection.h"
#include "utils.h"
@@ -606,7 +607,9 @@ bus_apparmor_allows_acquire_service (DBusConnection *connection,
BusAppArmorConfinement *con = NULL;
DBusString qstr, auxdata;
dbus_bool_t free_auxdata = FALSE;
- dbus_bool_t allow = FALSE, audit = TRUE;
+ /* the AppArmor API uses pointers to int for pointers to boolean, and
+ * int is not strictly guaranteed to be the same as dbus_bool_t */
+ int allow = FALSE, audit = TRUE;
unsigned long pid;
int res, serrno = 0;
@@ -743,13 +746,15 @@ bus_apparmor_allows_send (DBusConnection *sender,
#ifdef HAVE_APPARMOR
BusAppArmorConfinement *src_con = NULL, *dst_con = NULL;
DBusString qstr, auxdata;
- dbus_bool_t src_allow = FALSE, dst_allow = FALSE;
- dbus_bool_t src_audit = TRUE, dst_audit = TRUE;
+ int src_allow = FALSE, dst_allow = FALSE;
+ int src_audit = TRUE, dst_audit = TRUE;
dbus_bool_t free_auxdata = FALSE;
unsigned long pid;
int len, res, src_errno = 0, dst_errno = 0;
uint32_t src_perm = AA_DBUS_SEND, dst_perm = AA_DBUS_RECEIVE;
const char *msgtypestr = dbus_message_type_to_string(msgtype);
+ const char *dst_label = NULL;
+ const char *dst_mode = NULL;
if (!apparmor_enabled)
return TRUE;
@@ -766,12 +771,22 @@ bus_apparmor_allows_send (DBusConnection *sender,
{
dst_con = bus_connection_dup_apparmor_confinement (proposed_recipient);
}
+ else if (activation_entry != NULL)
+ {
+ dst_label = bus_activation_entry_get_assumed_apparmor_label (activation_entry);
+ }
else
{
dst_con = bus_con;
bus_apparmor_confinement_ref (dst_con);
}
+ if (dst_con != NULL)
+ {
+ dst_label = dst_con->label;
+ dst_mode = dst_con->mode;
+ }
+
/* map reply messages to initial send and receive permission. That is
* permission to receive a message from X grants permission to reply to X.
* And permission to send a message to Y grants permission to receive a reply
@@ -799,7 +814,7 @@ bus_apparmor_allows_send (DBusConnection *sender,
goto oom;
if (!build_message_query (&qstr, src_con->label, bustype, destination,
- dst_con->label, path, interface, member))
+ dst_label, path, interface, member))
{
_dbus_string_free (&qstr);
goto oom;
@@ -818,7 +833,11 @@ bus_apparmor_allows_send (DBusConnection *sender,
}
}
- if (is_unconfined (dst_con->label, dst_con->mode))
+ /* When deciding whether we can activate a service, we only check that
+ * we are allowed to send a message to it, not that it is allowed to
+ * receive that message from us.
+ */
+ if (activation_entry != NULL || is_unconfined (dst_label, dst_mode))
{
dst_allow = TRUE;
dst_audit = FALSE;
@@ -828,7 +847,7 @@ bus_apparmor_allows_send (DBusConnection *sender,
if (!_dbus_string_init (&qstr))
goto oom;
- if (!build_message_query (&qstr, dst_con->label, bustype, source,
+ if (!build_message_query (&qstr, dst_label, bustype, source,
src_con->label, path, interface, member))
{
_dbus_string_free (&qstr);
@@ -851,7 +870,7 @@ bus_apparmor_allows_send (DBusConnection *sender,
/* Don't fail operations on profiles in complain mode */
if (modestr_is_complain (src_con->mode))
src_allow = TRUE;
- if (modestr_is_complain (dst_con->mode))
+ if (modestr_is_complain (dst_mode))
dst_allow = TRUE;
if (!src_allow || !dst_allow)
@@ -922,8 +941,8 @@ bus_apparmor_allows_send (DBusConnection *sender,
!_dbus_append_pair_uint (&auxdata, "peer_pid", pid))
goto oom;
- if (dst_con->label &&
- !_dbus_append_pair_str (&auxdata, "peer_label", dst_con->label))
+ if (dst_label &&
+ !_dbus_append_pair_str (&auxdata, "peer_label", dst_label))
goto oom;
if (src_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (src_errno)))
@@ -950,8 +969,8 @@ bus_apparmor_allows_send (DBusConnection *sender,
!_dbus_append_pair_uint (&auxdata, "pid", pid))
goto oom;
- if (dst_con->label &&
- !_dbus_append_pair_str (&auxdata, "label", dst_con->label))
+ if (dst_label &&
+ !_dbus_append_pair_str (&auxdata, "label", dst_label))
goto oom;
if (sender && dbus_connection_get_unix_process_id (sender, &pid) &&
@@ -1011,7 +1030,7 @@ bus_apparmor_allows_eavesdropping (DBusConnection *connection,
#ifdef HAVE_APPARMOR
BusAppArmorConfinement *con = NULL;
DBusString qstr, auxdata;
- dbus_bool_t allow = FALSE, audit = TRUE;
+ int allow = FALSE, audit = TRUE;
dbus_bool_t free_auxdata = FALSE;
unsigned long pid;
int res, serrno = 0;
diff --git a/bus/audit.c b/bus/audit.c
index 7705e425..91f2c5cf 100644
--- a/bus/audit.c
+++ b/bus/audit.c
@@ -166,8 +166,9 @@ _dbus_change_to_daemon_user (const char *user,
_dbus_strerror (errno));
break;
case -5:
- _dbus_warn ("Failed to drop supplementary groups: %s\n",
- _dbus_strerror (errno));
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to drop supplementary groups: %s",
+ _dbus_strerror (errno));
break;
case -6:
dbus_set_error (error, _dbus_error_from_errno (errno),
diff --git a/bus/bus.c b/bus/bus.c
index 1063d7b2..eb932f66 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -25,6 +25,7 @@
#include "bus.h"
#include <stdio.h>
+#include <stdlib.h>
#include "activation.h"
#include "connection.h"
@@ -38,6 +39,7 @@
#include "audit.h"
#include "dir-watch.h"
#include "check.h"
+#include <dbus/dbus-auth.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-credentials.h>
@@ -92,19 +94,15 @@ server_get_context (DBusServer *server)
BusContext *context;
BusServerData *bd;
- if (!dbus_server_allocate_data_slot (&server_data_slot))
- return NULL;
+ /* this data slot was allocated by the BusContext */
+ _dbus_assert (server_data_slot >= 0);
bd = BUS_SERVER_DATA (server);
- if (bd == NULL)
- {
- dbus_server_free_data_slot (&server_data_slot);
- return NULL;
- }
- context = bd->context;
+ /* every DBusServer in the dbus-daemon has gone through setup_server() */
+ _dbus_assert (bd != NULL);
- dbus_server_free_data_slot (&server_data_slot);
+ context = bd->context;
return context;
}
@@ -176,10 +174,9 @@ new_connection_callback (DBusServer *server,
{
BusContext *context = data;
+ /* If this fails it logs a warning, so we don't need to do that */
if (!bus_connections_setup_connection (context->connections, new_connection))
{
- _dbus_verbose ("No memory to setup new connection\n");
-
/* if we don't do this, it will get unref'd without
* being disconnected... kind of strange really
* that we have to do this, people won't get it right
@@ -287,6 +284,7 @@ process_config_first_time_only (BusContext *context,
DBusList **auth_mechanisms_list;
int len;
dbus_bool_t retval;
+ DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -294,7 +292,27 @@ process_config_first_time_only (BusContext *context,
auth_mechanisms = NULL;
pidfile = NULL;
- _dbus_init_system_log (TRUE);
+ if (flags & BUS_CONTEXT_FLAG_SYSLOG_ALWAYS)
+ {
+ context->syslog = TRUE;
+ log_flags |= DBUS_LOG_FLAGS_SYSTEM_LOG;
+
+ if (flags & BUS_CONTEXT_FLAG_SYSLOG_ONLY)
+ log_flags &= ~DBUS_LOG_FLAGS_STDERR;
+ }
+ else if (flags & BUS_CONTEXT_FLAG_SYSLOG_NEVER)
+ {
+ context->syslog = FALSE;
+ }
+ else
+ {
+ context->syslog = bus_config_parser_get_syslog (parser);
+
+ if (context->syslog)
+ log_flags |= DBUS_LOG_FLAGS_SYSTEM_LOG;
+ }
+
+ _dbus_init_system_log ("dbus-daemon", log_flags);
if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
context->systemd_activation = TRUE;
@@ -414,6 +432,26 @@ process_config_first_time_only (BusContext *context,
link = _dbus_list_get_first_link (auth_mechanisms_list);
while (link != NULL)
{
+ DBusString name;
+ _dbus_string_init_const (&name, link->data);
+ if (!_dbus_auth_is_supported_mechanism (&name))
+ {
+ DBusString list;
+ if (!_dbus_string_init (&list))
+ goto oom;
+
+ if (!_dbus_auth_dump_supported_mechanisms (&list))
+ {
+ _dbus_string_free (&list);
+ goto oom;
+ }
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Unsupported auth mechanism \"%s\" in bus config file detected. Supported mechanisms are \"%s\".",
+ (char*)link->data,
+ _dbus_string_get_const_data (&list));
+ _dbus_string_free (&list);
+ goto failed;
+ }
auth_mechanisms[i] = _dbus_strdup (link->data);
if (auth_mechanisms[i] == NULL)
goto oom;
@@ -476,7 +514,6 @@ process_config_first_time_only (BusContext *context,
}
context->fork = bus_config_parser_get_fork (parser);
- context->syslog = bus_config_parser_get_syslog (parser);
context->keep_umask = bus_config_parser_get_keep_umask (parser);
context->allow_anonymous = bus_config_parser_get_allow_anonymous (parser);
@@ -635,32 +672,6 @@ process_config_every_time (BusContext *context,
return retval;
}
-static dbus_bool_t
-list_concat_new (DBusList **a,
- DBusList **b,
- DBusList **result)
-{
- DBusList *link;
-
- *result = NULL;
-
- for (link = _dbus_list_get_first_link (a); link; link = _dbus_list_get_next_link (a, link))
- {
- if (!_dbus_list_append (result, link->data))
- goto oom;
- }
- for (link = _dbus_list_get_first_link (b); link; link = _dbus_list_get_next_link (b, link))
- {
- if (!_dbus_list_append (result, link->data))
- goto oom;
- }
-
- return TRUE;
-oom:
- _dbus_list_clear (result);
- return FALSE;
-}
-
static void
raise_file_descriptor_limit (BusContext *context)
{
@@ -684,11 +695,11 @@ raise_file_descriptor_limit (BusContext *context)
/* We used to compute a suitable rlimit based on the configured number
* of connections, but that breaks down as soon as we allow fd-passing,
* because each connection is allowed to pass 64 fds to us, and if
- * they all did, we'd hit kernel limits. We now hard-code 64k as a
- * good limit, like systemd does: that's enough to avoid DoS from
- * anything short of multiple uids conspiring against us.
+ * they all did, we'd hit kernel limits. We now hard-code a good
+ * limit that is enough to avoid DoS from anything short of multiple
+ * uids conspiring against us, much like systemd does.
*/
- if (!_dbus_rlimit_raise_fd_limit_if_privileged (65536, &error))
+ if (!_dbus_rlimit_raise_fd_limit (&error))
{
bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
"%s: %s", error.name, error.message);
@@ -706,8 +717,6 @@ process_config_postinit (BusContext *context,
DBusHashTable *service_context_table;
DBusList *watched_dirs = NULL;
- raise_file_descriptor_limit (context);
-
service_context_table = bus_config_parser_steal_service_context_table (parser);
if (!bus_registry_set_service_context_table (context->registry,
service_context_table))
@@ -721,9 +730,7 @@ process_config_postinit (BusContext *context,
/* We need to monitor both the configuration directories and directories
* containing .service files.
*/
- if (!list_concat_new (bus_config_parser_get_conf_dirs (parser),
- bus_config_parser_get_service_dirs (parser),
- &watched_dirs))
+ if (!bus_config_parser_get_watched_dirs (parser, &watched_dirs))
{
BUS_SET_OOM (error);
return FALSE;
@@ -933,9 +940,38 @@ bus_context_new (const DBusString *config_file,
!_dbus_pipe_is_stdout_or_stderr (print_pid_pipe))
_dbus_pipe_close (print_pid_pipe, NULL);
+ /* Raise the file descriptor limits before dropping the privileges
+ * required to do so.
+ */
+ raise_file_descriptor_limit (context);
+
+ /* Here we change our credentials if required,
+ * as soon as we've set up our sockets and pidfile.
+ * This must be done before initializing LSMs, so that the netlink
+ * monitoring thread started by avc_init() will not lose CAP_AUDIT_WRITE
+ * when the main thread calls setuid().
+ * https://bugs.freedesktop.org/show_bug.cgi?id=92832
+ */
+ if (context->user != NULL)
+ {
+ if (!_dbus_change_to_daemon_user (context->user, error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ goto failed;
+ }
+ }
+
+ /* Auditing should be initialized before LSMs, so that the LSMs are able
+ * to log audit-events that happen during their initialization.
+ */
+ bus_audit_init (context);
+
if (!bus_selinux_full_init ())
{
- bus_context_log (context, DBUS_SYSTEM_LOG_FATAL, "SELinux enabled but D-Bus initialization failed; check system log\n");
+ bus_context_log (context, DBUS_SYSTEM_LOG_ERROR,
+ "SELinux enabled but D-Bus initialization failed; "
+ "check system log");
+ exit (1);
}
if (!bus_apparmor_full_init (error))
@@ -952,6 +988,11 @@ bus_context_new (const DBusString *config_file,
"AppArmor D-Bus mediation is enabled\n");
}
+ /* When SELinux is used, this must happen after bus_selinux_full_init()
+ * so that it has access to the access vector cache, which is required
+ * to process <associate/> elements.
+ * http://lists.freedesktop.org/archives/dbus/2008-October/010491.html
+ */
if (!process_config_postinit (context, parser, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
@@ -964,20 +1005,6 @@ bus_context_new (const DBusString *config_file,
parser = NULL;
}
- /* Here we change our credentials if required,
- * as soon as we've set up our sockets and pidfile
- */
- if (context->user != NULL)
- {
- if (!_dbus_change_to_daemon_user (context->user, error))
- {
- _DBUS_ASSERT_ERROR_IS_SET (error);
- goto failed;
- }
- }
-
- bus_audit_init (context);
-
context->check = bus_check_new(context, error);
if (context->check == NULL)
goto failed;
@@ -1356,25 +1383,17 @@ bus_context_get_initial_fd_limit (BusContext *context)
return context->initial_fd_limit;
}
+dbus_bool_t
+bus_context_get_using_syslog (BusContext *context)
+{
+ return context->syslog;
+}
+
void
bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...)
{
va_list args;
- if (!context->syslog)
- {
- /* we're not syslogging; just output to stderr */
- va_start (args, msg);
- vfprintf (stderr, msg, args);
- fprintf (stderr, "\n");
- va_end (args);
-
- if (severity == DBUS_SYSTEM_LOG_FATAL)
- _dbus_exit (1);
-
- return;
- }
-
va_start (args, msg);
if (context->log_prefix)
@@ -1388,12 +1407,12 @@ bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char
if (!_dbus_string_append_printf_valist (&full_msg, msg, args))
goto oom_out;
- _dbus_system_log (severity, "%s", _dbus_string_get_const_data (&full_msg));
+ _dbus_log (severity, "%s", _dbus_string_get_const_data (&full_msg));
oom_out:
_dbus_string_free (&full_msg);
}
else
- _dbus_system_logv (severity, msg, args);
+ _dbus_logv (severity, msg, args);
out:
va_end (args);
@@ -1411,19 +1430,7 @@ bus_context_log_literal (BusContext *context,
DBusSystemLogSeverity severity,
const char *msg)
{
- if (!context->syslog)
- {
- fputs (msg, stderr);
- fputc ('\n', stderr);
-
- if (severity == DBUS_SYSTEM_LOG_FATAL)
- _dbus_exit (1);
- }
- else
- {
- _dbus_system_log (severity, "%s%s", nonnull (context->log_prefix, ""),
- msg);
- }
+ _dbus_log (severity, "%s%s", nonnull (context->log_prefix, ""), msg);
}
void
@@ -1728,7 +1735,7 @@ bus_context_check_security_policy (BusContext *context,
}
else
{
- _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus\n");
+ _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus");
recipient_policy = NULL;
}
}
diff --git a/bus/bus.h b/bus/bus.h
index 6382b188..6562d376 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -92,7 +92,10 @@ typedef enum
BUS_CONTEXT_FLAG_FORK_ALWAYS = (1 << 1),
BUS_CONTEXT_FLAG_FORK_NEVER = (1 << 2),
BUS_CONTEXT_FLAG_WRITE_PID_FILE = (1 << 3),
- BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION = (1 << 4)
+ BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION = (1 << 4),
+ BUS_CONTEXT_FLAG_SYSLOG_ALWAYS = (1 << 5),
+ BUS_CONTEXT_FLAG_SYSLOG_NEVER = (1 << 6),
+ BUS_CONTEXT_FLAG_SYSLOG_ONLY = (1 << 7)
} BusContextFlags;
BusContext* bus_context_new (const DBusString *config_file,
@@ -139,6 +142,7 @@ int bus_context_get_max_match_rules_per_connection (BusContext
int bus_context_get_max_replies_per_connection (BusContext *context);
int bus_context_get_reply_timeout (BusContext *context);
DBusRLimit * bus_context_get_initial_fd_limit (BusContext *context);
+dbus_bool_t bus_context_get_using_syslog (BusContext *context);
void bus_context_log (BusContext *context,
DBusSystemLogSeverity severity,
const char *msg,
@@ -152,7 +156,6 @@ void bus_context_log_and_set_error (BusContext
const char *name,
const char *msg,
...) _DBUS_GNUC_PRINTF (5, 6);
-void bus_context_check_all_watches (BusContext *context);
BusResult bus_context_check_security_policy (BusContext *context,
BusTransaction *transaction,
DBusConnection *sender,
@@ -162,6 +165,7 @@ BusResult bus_context_check_security_policy (BusContext
BusActivationEntry *activation_entry,
DBusError *error,
BusDeferredMessage **deferred_message);
+void bus_context_check_all_watches (BusContext *context);
dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context,
DBusConnection *recipient,
diff --git a/bus/config-loader-expat.c b/bus/config-loader-expat.c
index b571fda3..6cbd37eb 100644
--- a/bus/config-loader-expat.c
+++ b/bus/config-loader-expat.c
@@ -203,6 +203,20 @@ bus_config_load (const DBusString *file,
goto failed;
}
+ /* We do not need protection against hash collisions (CVE-2012-0876)
+ * because we are only parsing trusted XML; and if we let Expat block
+ * waiting for the CSPRNG to be initialized, as it does by default to
+ * defeat CVE-2012-0876, it can cause timeouts during early boot on
+ * entropy-starved embedded devices.
+ *
+ * TODO: When Expat gets a more explicit API for this than
+ * XML_SetHashSalt, check for that too, and use it preferentially.
+ * https://github.com/libexpat/libexpat/issues/91 */
+#if defined(HAVE_XML_SETHASHSALT)
+ /* Any nonzero number will do. https://xkcd.com/221/ */
+ XML_SetHashSalt (expat, 4);
+#endif
+
if (!_dbus_string_get_dirname (file, &dirname))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
@@ -242,7 +256,7 @@ bus_config_load (const DBusString *file,
data_str = _dbus_string_get_const_data (&data);
- if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
+ if (XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE) == XML_STATUS_ERROR)
{
if (context.error != NULL &&
!dbus_error_is_set (context.error))
@@ -254,10 +268,13 @@ bus_config_load (const DBusString *file,
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
else
dbus_set_error (error, DBUS_ERROR_FAILED,
- "Error in file %s, line %d, column %d: %s\n",
+ "Error in file %s, line %lu, column %lu: %s\n",
filename,
- XML_GetCurrentLineNumber (expat),
- XML_GetCurrentColumnNumber (expat),
+ /* The XML_Size type varies according to
+ * build options, so cast to something we can
+ * cope with. */
+ (unsigned long) XML_GetCurrentLineNumber (expat),
+ (unsigned long) XML_GetCurrentColumnNumber (expat),
XML_ErrorString (e));
}
diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c
index ea25f5e6..e2f253d8 100644
--- a/bus/config-parser-common.c
+++ b/bus/config-parser-common.c
@@ -193,10 +193,9 @@ bus_config_parser_element_type_to_name (ElementType type)
return "allow_anonymous";
case ELEMENT_APPARMOR:
return "apparmor";
+ default:
+ _dbus_assert_not_reached ("bad element type");
+ return NULL;
}
-
- _dbus_assert_not_reached ("bad element type");
-
- return NULL;
}
diff --git a/bus/config-parser-trivial.c b/bus/config-parser-trivial.c
index 03ad8382..dd65c6d4 100644
--- a/bus/config-parser-trivial.c
+++ b/bus/config-parser-trivial.c
@@ -162,6 +162,7 @@ bus_config_parser_start_element (BusConfigParser *parser,
switch (parser->type)
{
+ case ELEMENT_SERVICEDIR:
case ELEMENT_SERVICEHELPER:
case ELEMENT_USER:
case ELEMENT_CONFIGTYPE:
@@ -185,6 +186,26 @@ bus_config_parser_start_element (BusConfigParser *parser,
break;
}
+ case ELEMENT_NONE:
+ case ELEMENT_BUSCONFIG:
+ case ELEMENT_INCLUDE:
+ case ELEMENT_LISTEN:
+ case ELEMENT_AUTH:
+ case ELEMENT_POLICY:
+ case ELEMENT_LIMIT:
+ case ELEMENT_ALLOW:
+ case ELEMENT_DENY:
+ case ELEMENT_FORK:
+ case ELEMENT_PIDFILE:
+ case ELEMENT_INCLUDEDIR:
+ case ELEMENT_SELINUX:
+ case ELEMENT_ASSOCIATE:
+ case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+ case ELEMENT_KEEP_UMASK:
+ case ELEMENT_SYSLOG:
+ case ELEMENT_ALLOW_ANONYMOUS:
+ case ELEMENT_APPARMOR:
+ /* fall through */
default:
{
/* we really don't care about the others... */
@@ -286,6 +307,28 @@ bus_config_parser_content (BusConfigParser *parser,
}
}
break;
+
+ case ELEMENT_NONE:
+ case ELEMENT_BUSCONFIG:
+ case ELEMENT_INCLUDE:
+ case ELEMENT_LISTEN:
+ case ELEMENT_AUTH:
+ case ELEMENT_POLICY:
+ case ELEMENT_LIMIT:
+ case ELEMENT_ALLOW:
+ case ELEMENT_DENY:
+ case ELEMENT_FORK:
+ case ELEMENT_PIDFILE:
+ case ELEMENT_INCLUDEDIR:
+ case ELEMENT_SELINUX:
+ case ELEMENT_ASSOCIATE:
+ case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+ case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
+ case ELEMENT_KEEP_UMASK:
+ case ELEMENT_SYSLOG:
+ case ELEMENT_ALLOW_ANONYMOUS:
+ case ELEMENT_APPARMOR:
+ /* fall through */
default:
{
/* we don't care about the others... really */
@@ -324,8 +367,11 @@ bus_config_parser_get_type (BusConfigParser *parser)
return _dbus_string_get_const_data (&parser->bus_type);
}
+/*
+ * @returns A list of strings, owned by the BusConfigParser
+ */
DBusList**
-bus_config_parser_get_service_dirs (BusConfigParser *parser)
+bus_config_parser_get_service_paths (BusConfigParser *parser)
{
return &parser->service_dirs;
}
@@ -370,14 +416,14 @@ check_return_values (const DBusString *full_path)
user = bus_config_parser_get_user (parser);
if (user == NULL)
{
- _dbus_warn ("User was NULL!\n");
+ _dbus_warn ("User was NULL!");
goto finish;
}
#if 0
/* the username can be configured in configure.in so this test doesn't work */
if (strcmp (user, "dbus") != 0)
{
- _dbus_warn ("User was invalid; '%s'!\n", user);
+ _dbus_warn ("User was invalid; '%s'!", user);
goto finish;
}
printf (" <user>dbus</user> OKAY!\n");
@@ -387,21 +433,21 @@ check_return_values (const DBusString *full_path)
type = bus_config_parser_get_type (parser);
if (type == NULL)
{
- _dbus_warn ("Type was NULL!\n");
+ _dbus_warn ("Type was NULL!");
goto finish;
}
if (strcmp (type, "system") != 0)
{
- _dbus_warn ("Type was invalid; '%s'!\n", user);
+ _dbus_warn ("Type was invalid; '%s'!", user);
goto finish;
}
printf (" <type>system</type> OKAY!\n");
/* check dirs return value is okay */
- dirs = bus_config_parser_get_service_dirs (parser);
+ dirs = bus_config_parser_get_service_paths (parser);
if (dirs == NULL)
{
- _dbus_warn ("Service dirs are NULL!\n");
+ _dbus_warn ("Service dirs are NULL!");
goto finish;
}
printf (" <standard_system_service_dirs/> OKAY!\n");
@@ -440,7 +486,7 @@ do_load (const DBusString *full_path,
}
else if (validity == VALID)
{
- _dbus_warn ("Failed to load valid file but still had memory: %s\n",
+ _dbus_warn ("Failed to load valid file but still had memory: %s",
error.message);
dbus_error_free (&error);
@@ -460,7 +506,7 @@ do_load (const DBusString *full_path,
if (validity == INVALID)
{
- _dbus_warn ("Accepted invalid file\n");
+ _dbus_warn ("Accepted invalid file");
return FALSE;
}
@@ -497,7 +543,7 @@ process_test_valid_subdir (const DBusString *test_base_dir,
dir = NULL;
if (!_dbus_string_init (&test_directory))
- _dbus_assert_not_reached ("didn't allocate test_directory\n");
+ _dbus_assert_not_reached ("didn't allocate test_directory");
_dbus_string_init_const (&filename, subdir);
@@ -510,13 +556,13 @@ process_test_valid_subdir (const DBusString *test_base_dir,
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
- _dbus_assert_not_reached ("didn't allocate filename string\n");
+ _dbus_assert_not_reached ("didn't allocate filename string");
dbus_error_init (&error);
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
- _dbus_warn ("Could not open %s: %s\n",
+ _dbus_warn ("Could not open %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -576,7 +622,7 @@ process_test_valid_subdir (const DBusString *test_base_dir,
if (dbus_error_is_set (&error))
{
- _dbus_warn ("Could not get next file in %s: %s\n",
+ _dbus_warn ("Could not get next file in %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
diff --git a/bus/config-parser-trivial.h b/bus/config-parser-trivial.h
index 31ddef6b..abe41fdf 100644
--- a/bus/config-parser-trivial.h
+++ b/bus/config-parser-trivial.h
@@ -59,7 +59,7 @@ dbus_bool_t bus_config_parser_finished (BusConfigParser *parser,
/* Functions for extracting the parse results */
const char* bus_config_parser_get_user (BusConfigParser *parser);
const char* bus_config_parser_get_type (BusConfigParser *parser);
-DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser);
+DBusList** bus_config_parser_get_service_paths (BusConfigParser *parser);
/* Loader functions (backended off one of the XML parsers). Returns a
* finished ConfigParser.
diff --git a/bus/config-parser.c b/bus/config-parser.c
index 00005cc7..42218547 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -100,7 +100,7 @@ struct BusConfigParser
DBusList *mechanisms; /**< Auth mechanisms */
- DBusList *service_dirs; /**< Directories to look for session services in */
+ DBusList *service_dirs; /**< BusConfigServiceDirs to look for session services in */
DBusList *conf_dirs; /**< Directories to look for policy configuration in */
@@ -232,7 +232,33 @@ merge_service_context_hash (DBusHashTable *dest,
return FALSE;
}
-static dbus_bool_t
+/*
+ * Create a new BusConfigServiceDir. Takes ownership of path if #TRUE is returned.
+ *
+ * @returns #FALSE on OOM
+ */
+static BusConfigServiceDir *
+bus_config_service_dir_new_take (char *path,
+ BusServiceDirFlags flags)
+{
+ BusConfigServiceDir *self = dbus_new0 (BusConfigServiceDir, 1);
+
+ if (self == NULL)
+ return NULL;
+
+ self->path = path; /* take ownership */
+ self->flags = flags;
+ return self;
+}
+
+static void
+bus_config_service_dir_free (BusConfigServiceDir *self)
+{
+ dbus_free (self->path);
+ dbus_free (self);
+}
+
+static BusConfigServiceDir *
service_dirs_find_dir (DBusList **service_dirs,
const char *dir)
{
@@ -242,42 +268,81 @@ service_dirs_find_dir (DBusList **service_dirs,
for (link = *service_dirs; link; link = _dbus_list_get_next_link(service_dirs, link))
{
- const char *link_dir;
-
- link_dir = (const char *)link->data;
- if (strcmp (dir, link_dir) == 0)
- return TRUE;
- }
+ BusConfigServiceDir *link_dir = link->data;
- return FALSE;
-}
-
-static dbus_bool_t
-service_dirs_append_unique_or_free (DBusList **service_dirs,
- char *dir)
-{
- if (!service_dirs_find_dir (service_dirs, dir))
- return _dbus_list_append (service_dirs, dir);
+ if (strcmp (dir, link_dir->path) == 0)
+ return link_dir;
+ }
- dbus_free (dir);
- return TRUE;
+ return NULL;
}
-static void
+static void
service_dirs_append_link_unique_or_free (DBusList **service_dirs,
DBusList *dir_link)
{
- if (!service_dirs_find_dir (service_dirs, dir_link->data))
+ BusConfigServiceDir *dir = dir_link->data;
+ BusConfigServiceDir *already = service_dirs_find_dir (service_dirs,
+ dir->path);
+
+ if (already == NULL)
{
_dbus_list_append_link (service_dirs, dir_link);
}
else
{
- dbus_free (dir_link->data);
+ /* BusServiceDirFlags are chosen such that the compatible thing to do
+ * is to "and" the flags. For example, if a directory is explicitly
+ * added as a <servicedir> (which is watched with inotify) and is also
+ * the transient service directory (which should not be watched),
+ * the compatible thing to do is to watch it. */
+ already->flags &= dir->flags;
+ bus_config_service_dir_free (dir_link->data);
_dbus_list_free_link (dir_link);
}
}
+/*
+ * Consume links from dirs (a list of paths), converting them into links in
+ * service_dirs (a list of unique BusServiceDir).
+ *
+ * On success, return TRUE. dirs will be empty, and every original entry in
+ * dirs will have a corresponding service_dirs entry.
+ *
+ * On OOM, return FALSE. Each original entry of dirs has either been
+ * appended to service_dirs or left in dirs.
+ */
+static dbus_bool_t
+service_dirs_absorb_string_list (DBusList **service_dirs,
+ DBusList **dirs,
+ BusServiceDirFlags flags)
+{
+ DBusList *link;
+
+ _dbus_assert (service_dirs != NULL);
+ _dbus_assert (dirs != NULL);
+
+ while ((link = _dbus_list_pop_first_link (dirs)))
+ {
+ char *path = link->data;
+ BusConfigServiceDir *dir = bus_config_service_dir_new_take (path, flags);
+
+ if (dir == NULL)
+ {
+ /* OOM - roll back (this does not need to allocate memory) */
+ _dbus_list_prepend_link (service_dirs, link);
+ return FALSE;
+ }
+
+ /* Ownership of path has been taken by dir */
+ link->data = dir;
+ service_dirs_append_link_unique_or_free (service_dirs, link);
+ }
+
+ _dbus_assert (*dirs == NULL);
+ return TRUE;
+}
+
static dbus_bool_t
merge_included (BusConfigParser *parser,
BusConfigParser *included,
@@ -515,7 +580,7 @@ bus_config_parser_unref (BusConfigParser *parser)
_dbus_list_clear (&parser->listen_on);
_dbus_list_foreach (&parser->service_dirs,
- (DBusForeachFunction) dbus_free,
+ (DBusForeachFunction) bus_config_service_dir_free,
NULL);
_dbus_list_clear (&parser->service_dirs);
@@ -583,7 +648,7 @@ locate_attributes (BusConfigParser *parser,
const char *name;
const char **retloc;
int n_attrs;
-#define MAX_ATTRS 24
+#define MAX_ATTRS 25
LocateAttr attrs[MAX_ATTRS];
dbus_bool_t retval;
int i;
@@ -832,9 +897,8 @@ start_busconfig_child (BusConfigParser *parser,
}
else if (element_type == ELEMENT_STANDARD_SESSION_SERVICEDIRS)
{
- DBusList *link;
- DBusList *dirs;
- dirs = NULL;
+ DBusError local_error = DBUS_ERROR_INIT;
+ DBusList *dirs = NULL;
if (!check_no_attributes (parser, "standard_session_servicedirs", attribute_names, attribute_values, error))
return FALSE;
@@ -845,20 +909,54 @@ start_busconfig_child (BusConfigParser *parser,
return FALSE;
}
+ if (_dbus_set_up_transient_session_servicedirs (&dirs, &local_error))
+ {
+ if (!service_dirs_absorb_string_list (&parser->service_dirs, &dirs,
+ BUS_SERVICE_DIR_FLAGS_NO_WATCH |
+ BUS_SERVICE_DIR_FLAGS_STRICT_NAMING))
+ {
+ BUS_SET_OOM (error);
+ _dbus_list_foreach (&dirs, (DBusForeachFunction) dbus_free,
+ NULL);
+ _dbus_list_clear (&dirs);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Failing to set these up isn't fatal */
+ _dbus_warn ("Unable to set up transient service directory: %s",
+ local_error.message);
+ dbus_error_free (&local_error);
+ }
+
+ _dbus_assert (dirs == NULL);
+
if (!_dbus_get_standard_session_servicedirs (&dirs))
{
BUS_SET_OOM (error);
return FALSE;
}
- while ((link = _dbus_list_pop_first_link (&dirs)))
- service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+ /* We have traditionally watched the standard session service
+ * directories with inotify, and allowed service files whose names do not
+ * match the bus name */
+ if (!service_dirs_absorb_string_list (&parser->service_dirs, &dirs,
+ BUS_SERVICE_DIR_FLAGS_NONE))
+ {
+ BUS_SET_OOM (error);
+ _dbus_list_foreach (&dirs, (DBusForeachFunction) dbus_free,
+ NULL);
+ _dbus_list_clear (&dirs);
+ return FALSE;
+ }
+
+ _dbus_assert (dirs == NULL);
return TRUE;
}
else if (element_type == ELEMENT_STANDARD_SYSTEM_SERVICEDIRS)
{
- DBusList *link;
DBusList *dirs;
dirs = NULL;
@@ -877,8 +975,19 @@ start_busconfig_child (BusConfigParser *parser,
return FALSE;
}
- while ((link = _dbus_list_pop_first_link (&dirs)))
- service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+ /* We have traditionally watched the standard system service
+ * directories with inotify, and allowed service files whose names do not
+ * match the bus name (the servicehelper won't successfully activate
+ * them, but we do still parse them) */
+ if (!service_dirs_absorb_string_list (&parser->service_dirs, &dirs,
+ BUS_SERVICE_DIR_FLAGS_NONE))
+ {
+ BUS_SET_OOM (error);
+ _dbus_list_foreach (&dirs, (DBusForeachFunction) dbus_free,
+ NULL);
+ _dbus_list_clear (&dirs);
+ return FALSE;
+ }
return TRUE;
}
@@ -1049,7 +1158,7 @@ start_busconfig_child (BusConfigParser *parser,
&e->d.policy.gid_uid_or_at_console))
e->d.policy.type = POLICY_USER;
else
- _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
+ _dbus_warn ("Unknown username \"%s\" in message bus configuration file",
user);
}
else if (group != NULL)
@@ -1061,7 +1170,7 @@ start_busconfig_child (BusConfigParser *parser,
&e->d.policy.gid_uid_or_at_console))
e->d.policy.type = POLICY_GROUP;
else
- _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
+ _dbus_warn ("Unknown group \"%s\" in message bus configuration file",
group);
}
else if (at_console != NULL)
@@ -1167,6 +1276,43 @@ start_busconfig_child (BusConfigParser *parser,
}
}
+/*
+ * Parse an attribute named name, whose content is content, or NULL if
+ * missing. It is meant to be a (long) integer between min and max inclusive.
+ * If it is missing, use def as the default value (which does not
+ * necessarily need to be between min and max).
+ */
+static dbus_bool_t
+parse_int_attribute (const char *name,
+ const char *content,
+ long min,
+ long max,
+ long def,
+ long *value,
+ DBusError *error)
+{
+ DBusString parse_string;
+
+ *value = def;
+
+ if (content == NULL)
+ return TRUE;
+
+ _dbus_string_init_const (&parse_string, content);
+
+ if (!_dbus_string_parse_int (&parse_string, 0, value, NULL) ||
+ *value < min || *value > max)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Bad value \"%s\" for %s attribute, must be an "
+ "integer in range %ld to %ld inclusive",
+ content, name, min, max);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static dbus_bool_t
append_rule_from_element (BusConfigParser *parser,
const char *element_name,
@@ -1176,6 +1322,8 @@ append_rule_from_element (BusConfigParser *parser,
DBusError *error)
{
const char *log;
+
+ /* Group: send_ attributes */
const char *send_interface;
const char *send_member;
const char *send_error;
@@ -1183,15 +1331,32 @@ append_rule_from_element (BusConfigParser *parser,
const char *send_destination_prefix;
const char *send_path;
const char *send_type;
+ const char *send_requested_reply;
+ const char *send_broadcast;
+ /* TRUE if any send_ attribute is present */
+ dbus_bool_t any_send_attribute;
+
+ /* Group: receive_ attributes */
const char *receive_interface;
const char *receive_member;
const char *receive_error;
const char *receive_sender;
const char *receive_path;
const char *receive_type;
- const char *eavesdrop;
- const char *send_requested_reply;
const char *receive_requested_reply;
+ /* TRUE if any receive_ attribute is present */
+ dbus_bool_t any_receive_attribute;
+
+ /* Group: message-matching modifiers that can go on send_ or receive_ */
+ const char *eavesdrop;
+ const char *max_fds_attr;
+ long max_fds = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
+ const char *min_fds_attr;
+ long min_fds = 0;
+ /* TRUE if any message-matching modifier is present */
+ dbus_bool_t any_message_attribute;
+
+ /* Non-message-related attributes */
const char *own;
const char *own_prefix;
const char *user;
@@ -1199,7 +1364,7 @@ append_rule_from_element (BusConfigParser *parser,
const char *privilege;
BusPolicyRule *rule;
-
+
if (!locate_attributes (parser, element_name,
attribute_names,
attribute_values,
@@ -1211,6 +1376,7 @@ append_rule_from_element (BusConfigParser *parser,
"send_destination_prefix", &send_destination_prefix,
"send_path", &send_path,
"send_type", &send_type,
+ "send_broadcast", &send_broadcast,
"receive_interface", &receive_interface,
"receive_member", &receive_member,
"receive_error", &receive_error,
@@ -1218,6 +1384,8 @@ append_rule_from_element (BusConfigParser *parser,
"receive_path", &receive_path,
"receive_type", &receive_type,
"eavesdrop", &eavesdrop,
+ "max_fds", &max_fds_attr,
+ "min_fds", &min_fds_attr,
"send_requested_reply", &send_requested_reply,
"receive_requested_reply", &receive_requested_reply,
"own", &own,
@@ -1229,12 +1397,36 @@ append_rule_from_element (BusConfigParser *parser,
NULL))
return FALSE;
- if (!(send_interface || send_member || send_error ||
- send_destination || send_destination_prefix ||
- send_type || send_path ||
- receive_interface || receive_member || receive_error || receive_sender ||
- receive_type || receive_path || eavesdrop ||
- send_requested_reply || receive_requested_reply ||
+ any_send_attribute = (send_destination != NULL ||
+ send_destination_prefix != NULL ||
+ send_broadcast != NULL ||
+ send_path != NULL ||
+ send_type != NULL ||
+ send_interface != NULL ||
+ send_member != NULL ||
+ send_error != NULL ||
+ send_requested_reply != NULL);
+ any_receive_attribute = (receive_sender != NULL ||
+ receive_path != NULL ||
+ receive_type != NULL ||
+ receive_interface != NULL ||
+ receive_member != NULL ||
+ receive_error != NULL ||
+ receive_requested_reply != NULL ||
+ /* <allow eavesdrop="true"/> means the same as
+ * <allow receive_sender="*" eavesdrop="true"/>,
+ * but <allow send_anything="anything"/> can also
+ * take the eavesdrop attribute and still counts
+ * as a send rule. */
+ (!any_send_attribute && eavesdrop != NULL));
+ any_message_attribute = (any_send_attribute ||
+ any_receive_attribute ||
+ eavesdrop != NULL ||
+ max_fds_attr != NULL ||
+ min_fds_attr != NULL);
+
+ if (!(any_send_attribute ||
+ any_receive_attribute ||
privilege ||
own || own_prefix || user || group))
{
@@ -1284,124 +1476,57 @@ append_rule_from_element (BusConfigParser *parser,
* interface + member
* error
*
- * base send_ can combine with send_destination, send_destination_prefix, send_path, send_type, send_requested_reply
+ * base send_ can combine with send_destination, send_destination_prefix, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop
* send_destination must not occur with send_destination_prefix
* base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
*
* user, group, own, own_prefix must occur alone
- *
- * Pretty sure the below stuff is broken, FIXME think about it more.
*/
- if ((send_interface && (send_error ||
- receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_member && (send_error ||
- receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_error && (receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_destination && (send_destination_prefix ||
- receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_destination_prefix && (receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_type && (receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_path && (receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (send_requested_reply && (receive_interface ||
- receive_member ||
- receive_error ||
- receive_sender ||
- receive_requested_reply ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (receive_interface && (receive_error ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (receive_member && (receive_error ||
- own || own_prefix ||
- user ||
- group)) ||
-
- (receive_error && (own || own_prefix ||
- user ||
- group)) ||
-
- (eavesdrop && (own || own_prefix ||
- user ||
- group)) ||
-
- (receive_requested_reply && (own || own_prefix ||
- user ||
- group)) ||
-
- (own && (own_prefix || user || group)) ||
-
- (own_prefix && (own || user || group)) ||
-
- (user && group))
+ if (any_message_attribute +
+ ((own != NULL) +
+ (own_prefix != NULL) +
+ (user != NULL) +
+ (group != NULL)) > 1)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
- "Invalid combination of attributes on element <%s>",
+ "Invalid combination of attributes on element <%s>: "
+ "own, own_prefix, user, group and the message-related "
+ "attributes cannot be combined",
element_name);
return FALSE;
}
-
+
+ if (any_send_attribute && any_receive_attribute)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Invalid combination of attributes on element <%s>: "
+ "send and receive attributes cannot be combined",
+ element_name);
+ return FALSE;
+ }
+
+ if ((send_member != NULL || send_interface != NULL) && send_error != NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Invalid combination of attributes on element <%s>: "
+ "send_error cannot be combined with send_member or "
+ "send_interface",
+ element_name);
+ return FALSE;
+ }
+
+ if ((receive_member != NULL || receive_interface != NULL) &&
+ receive_error != NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Invalid combination of attributes on element <%s>: "
+ "receive_error cannot be combined with receive_member "
+ "or receive_interface",
+ element_name);
+ return FALSE;
+ }
+
rule = NULL;
/* In BusPolicyRule, NULL represents wildcard.
@@ -1409,8 +1534,7 @@ append_rule_from_element (BusConfigParser *parser,
*/
#define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
- if (send_interface || send_member || send_error || send_destination || send_destination_prefix ||
- send_path || send_type || send_requested_reply)
+ if (any_send_attribute)
{
int message_type;
@@ -1450,6 +1574,29 @@ append_rule_from_element (BusConfigParser *parser,
return FALSE;
}
+ if (send_broadcast &&
+ !(strcmp (send_broadcast, "true") == 0 ||
+ strcmp (send_broadcast, "false") == 0))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Bad value \"%s\" for %s attribute, must be true or false",
+ send_broadcast, "send_broadcast");
+ return FALSE;
+ }
+
+ if (send_destination != NULL &&
+ send_broadcast != NULL &&
+ strcmp (send_broadcast, "true") == 0)
+ {
+ /* Broadcast messages have no destination, so this cannot
+ * possibly match */
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Rule with send_broadcast=\"true\" and "
+ "send_destination=\"%s\" cannot match anything",
+ send_destination);
+ return FALSE;
+ }
+
if (send_requested_reply &&
!(strcmp (send_requested_reply, "true") == 0 ||
strcmp (send_requested_reply, "false") == 0))
@@ -1459,7 +1606,19 @@ append_rule_from_element (BusConfigParser *parser,
"send_requested_reply", send_requested_reply);
return FALSE;
}
-
+
+ /* Matching only messages with DBUS_MAXIMUM_MESSAGE_UNIX_FDS or fewer
+ * fds is the same as matching all messages, so we always set a maximum,
+ * but perhaps an unrealistically high one. */
+ if (!parse_int_attribute ("max_fds", max_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS,
+ DBUS_MAXIMUM_MESSAGE_UNIX_FDS, &max_fds,
+ error) ||
+ !parse_int_attribute ("min_fds", min_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS, 0, &min_fds,
+ error))
+ return FALSE;
+
rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access);
if (rule == NULL)
goto nomem;
@@ -1473,6 +1632,18 @@ append_rule_from_element (BusConfigParser *parser,
if (send_requested_reply)
rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0);
+ if (send_broadcast)
+ {
+ if (strcmp (send_broadcast, "true") == 0)
+ rule->d.send.broadcast = BUS_POLICY_TRISTATE_TRUE;
+ else
+ rule->d.send.broadcast = BUS_POLICY_TRISTATE_FALSE;
+ }
+ else
+ {
+ rule->d.send.broadcast = BUS_POLICY_TRISTATE_ANY;
+ }
+
rule->d.send.message_type = message_type;
rule->d.send.path = _dbus_strdup (send_path);
rule->d.send.interface = _dbus_strdup (send_interface);
@@ -1488,6 +1659,9 @@ append_rule_from_element (BusConfigParser *parser,
rule->d.send.destination = _dbus_strdup (send_destination_prefix);
rule->d.send.destination_prefix = 1;
}
+ rule->d.send.max_fds = max_fds;
+ rule->d.send.min_fds = min_fds;
+
if (send_path && rule->d.send.path == NULL)
goto nomem;
if (send_interface && rule->d.send.interface == NULL)
@@ -1499,8 +1673,7 @@ append_rule_from_element (BusConfigParser *parser,
if ((send_destination || send_destination_prefix) && rule->d.send.destination == NULL)
goto nomem;
}
- else if (receive_interface || receive_member || receive_error || receive_sender ||
- receive_path || receive_type || eavesdrop || receive_requested_reply)
+ else if (any_receive_attribute)
{
int message_type;
@@ -1550,7 +1723,16 @@ append_rule_from_element (BusConfigParser *parser,
"receive_requested_reply", receive_requested_reply);
return FALSE;
}
-
+
+ if (!parse_int_attribute ("max_fds", max_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS,
+ DBUS_MAXIMUM_MESSAGE_UNIX_FDS, &max_fds,
+ error) ||
+ !parse_int_attribute ("min_fds", min_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS, 0, &min_fds,
+ error))
+ return FALSE;
+
rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access);
if (rule == NULL)
goto nomem;
@@ -1567,6 +1749,8 @@ append_rule_from_element (BusConfigParser *parser,
rule->d.receive.member = _dbus_strdup (receive_member);
rule->d.receive.error = _dbus_strdup (receive_error);
rule->d.receive.origin = _dbus_strdup (receive_sender);
+ rule->d.receive.max_fds = max_fds;
+ rule->d.receive.min_fds = min_fds;
if (receive_path && rule->d.receive.path == NULL)
goto nomem;
@@ -1630,7 +1814,7 @@ append_rule_from_element (BusConfigParser *parser,
}
else
{
- _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
+ _dbus_warn ("Unknown username \"%s\" on element <%s>",
user, element_name);
}
}
@@ -1662,7 +1846,7 @@ append_rule_from_element (BusConfigParser *parser,
}
else
{
- _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
+ _dbus_warn ("Unknown group \"%s\" on element <%s>",
group, element_name);
}
}
@@ -1685,6 +1869,7 @@ append_rule_from_element (BusConfigParser *parser,
switch (pe->d.policy.type)
{
case POLICY_IGNORED:
+ default:
/* drop the rule on the floor */
break;
@@ -2121,6 +2306,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
switch (e->type)
{
case ELEMENT_NONE:
+ default:
_dbus_assert_not_reached ("element in stack has no type");
break;
@@ -2189,7 +2375,8 @@ make_full_path (const DBusString *basedir,
{
if (_dbus_path_is_absolute (filename))
{
- return _dbus_string_copy (filename, 0, full_path, 0);
+ if (!_dbus_string_copy (filename, 0, full_path, 0))
+ return FALSE;
}
else
{
@@ -2198,9 +2385,12 @@ make_full_path (const DBusString *basedir,
if (!_dbus_concat_dir_and_file (full_path, filename))
return FALSE;
-
- return TRUE;
}
+
+ if (!_dbus_replace_install_prefix (full_path))
+ return FALSE;
+
+ return TRUE;
}
static dbus_bool_t
@@ -2373,15 +2563,17 @@ include_dir (BusConfigParser *parser,
{
if (dbus_error_is_set (error))
{
- /* We log to syslog unconditionally here, because this is
+ /* We use both syslog and stderr here, because this is
* the configuration parser, so we don't yet know whether
- * this bus is going to want to write to syslog! (There's
- * also some layer inversion going on, if we want to use
- * the bus context.) */
- _dbus_system_log (DBUS_SYSTEM_LOG_INFO,
- "Encountered error '%s' while parsing '%s'\n",
- error->message,
- _dbus_string_get_const_data (&full_path));
+ * this bus is going to want to write to syslog! Err on
+ * the side of making sure the message gets to the sysadmin
+ * somehow. */
+ _dbus_init_system_log ("dbus-daemon",
+ DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG);
+ _dbus_log (DBUS_SYSTEM_LOG_INFO,
+ "Encountered error '%s' while parsing '%s'",
+ error->message,
+ _dbus_string_get_const_data (&full_path));
dbus_error_free (error);
}
}
@@ -2457,6 +2649,7 @@ bus_config_parser_content (BusConfigParser *parser,
switch (top_element_type (parser))
{
case ELEMENT_NONE:
+ default:
_dbus_assert_not_reached ("element at top of stack has no type");
return FALSE;
@@ -2662,8 +2855,10 @@ bus_config_parser_content (BusConfigParser *parser,
case ELEMENT_SERVICEDIR:
{
char *s;
+ BusConfigServiceDir *dir;
DBusString full_path;
-
+ DBusList *link;
+
e->had_content = TRUE;
if (!_dbus_string_init (&full_path))
@@ -2681,14 +2876,29 @@ bus_config_parser_content (BusConfigParser *parser,
goto nomem;
}
- /* _only_ extra session directories can be specified */
- if (!service_dirs_append_unique_or_free (&parser->service_dirs, s))
+ /* <servicedir/> has traditionally implied that we watch the
+ * directory with inotify, and allow service files whose names do not
+ * match the bus name */
+ dir = bus_config_service_dir_new_take (s, BUS_SERVICE_DIR_FLAGS_NONE);
+
+ if (dir == NULL)
{
_dbus_string_free (&full_path);
dbus_free (s);
goto nomem;
}
+ link = _dbus_list_alloc_link (dir);
+
+ if (link == NULL)
+ {
+ _dbus_string_free (&full_path);
+ bus_config_service_dir_free (dir);
+ goto nomem;
+ }
+
+ /* cannot fail */
+ service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
_dbus_string_free (&full_path);
}
break;
@@ -2858,6 +3068,51 @@ bus_config_parser_steal_service_context_table (BusConfigParser *parser)
return table;
}
+/*
+ * Return a list of the directories that should be watched with inotify,
+ * as strings. The list might be empty and is in arbitrary order.
+ *
+ * The list must be empty on entry. On success, the links are owned by the
+ * caller and must be freed, but the data in each link remains owned by
+ * the BusConfigParser and must not be freed: in GObject-Introspection
+ * notation, it is (transfer container).
+ */
+dbus_bool_t
+bus_config_parser_get_watched_dirs (BusConfigParser *parser,
+ DBusList **watched_dirs)
+{
+ DBusList *link;
+
+ _dbus_assert (*watched_dirs == NULL);
+
+ for (link = _dbus_list_get_first_link (&parser->conf_dirs);
+ link != NULL;
+ link = _dbus_list_get_next_link (&parser->conf_dirs, link))
+ {
+ if (!_dbus_list_append (watched_dirs, link->data))
+ goto oom;
+ }
+
+ for (link = _dbus_list_get_first_link (&parser->service_dirs);
+ link != NULL;
+ link = _dbus_list_get_next_link (&parser->service_dirs, link))
+ {
+ BusConfigServiceDir *dir = link->data;
+
+ if (dir->flags & BUS_SERVICE_DIR_FLAGS_NO_WATCH)
+ continue;
+
+ if (!_dbus_list_append (watched_dirs, dir->path))
+ goto oom;
+ }
+
+ return TRUE;
+
+oom:
+ _dbus_list_clear (watched_dirs);
+ return FALSE;
+}
+
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
#include <stdio.h>
@@ -2872,7 +3127,7 @@ static dbus_bool_t
do_check_own_rules (BusPolicy *policy)
{
const struct {
- char *name;
+ const char *name;
dbus_bool_t allowed;
} checks[] = {
{"org.freedesktop", FALSE},
@@ -2902,12 +3157,12 @@ do_check_own_rules (BusPolicy *policy)
ret ? "allowed" : "not allowed");
if (checks[i].allowed && !ret)
{
- _dbus_warn ("Cannot own %s\n", checks[i].name);
+ _dbus_warn ("Cannot own %s", checks[i].name);
return FALSE;
}
if (!checks[i].allowed && ret)
{
- _dbus_warn ("Can own %s\n", checks[i].name);
+ _dbus_warn ("Can own %s", checks[i].name);
return FALSE;
}
_dbus_string_free (&service_name);
@@ -2945,7 +3200,7 @@ do_load (const DBusString *full_path,
}
else if (validity == VALID)
{
- _dbus_warn ("Failed to load valid file but still had memory: %s\n",
+ _dbus_warn ("Failed to load valid file but still had memory: %s",
error.message);
dbus_error_free (&error);
@@ -2970,7 +3225,7 @@ do_load (const DBusString *full_path,
if (validity == INVALID)
{
- _dbus_warn ("Accepted invalid file\n");
+ _dbus_warn ("Accepted invalid file");
return FALSE;
}
@@ -3008,7 +3263,7 @@ process_test_valid_subdir (const DBusString *test_base_dir,
dir = NULL;
if (!_dbus_string_init (&test_directory))
- _dbus_assert_not_reached ("didn't allocate test_directory\n");
+ _dbus_assert_not_reached ("didn't allocate test_directory");
_dbus_string_init_const (&filename, subdir);
@@ -3021,13 +3276,13 @@ process_test_valid_subdir (const DBusString *test_base_dir,
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
- _dbus_assert_not_reached ("didn't allocate filename string\n");
+ _dbus_assert_not_reached ("didn't allocate filename string");
dbus_error_init (&error);
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
- _dbus_warn ("Could not open %s: %s\n",
+ _dbus_warn ("Could not open %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -3089,7 +3344,7 @@ process_test_valid_subdir (const DBusString *test_base_dir,
if (dbus_error_is_set (&error))
{
- _dbus_warn ("Could not get next file in %s: %s\n",
+ _dbus_warn ("Could not get next file in %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -3158,8 +3413,29 @@ elements_equal (const Element *a,
return FALSE;
break;
+ case ELEMENT_NONE:
+ case ELEMENT_BUSCONFIG:
+ case ELEMENT_USER:
+ case ELEMENT_LISTEN:
+ case ELEMENT_AUTH:
+ case ELEMENT_ALLOW:
+ case ELEMENT_DENY:
+ case ELEMENT_FORK:
+ case ELEMENT_PIDFILE:
+ case ELEMENT_SERVICEDIR:
+ case ELEMENT_SERVICEHELPER:
+ case ELEMENT_INCLUDEDIR:
+ case ELEMENT_CONFIGTYPE:
+ case ELEMENT_SELINUX:
+ case ELEMENT_ASSOCIATE:
+ case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+ case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
+ case ELEMENT_KEEP_UMASK:
+ case ELEMENT_SYSLOG:
+ case ELEMENT_ALLOW_ANONYMOUS:
+ case ELEMENT_APPARMOR:
default:
- /* do nothing */
+ /* do nothing: nothing in the Element struct for these types */
break;
}
@@ -3210,6 +3486,34 @@ lists_of_c_strings_equal (DBusList *a,
}
static dbus_bool_t
+lists_of_service_dirs_equal (DBusList *a,
+ DBusList *b)
+{
+ DBusList *ia;
+ DBusList *ib;
+
+ ia = a;
+ ib = b;
+
+ while (ia != NULL && ib != NULL)
+ {
+ BusConfigServiceDir *da = ia->data;
+ BusConfigServiceDir *db = ib->data;
+
+ if (strcmp (da->path, db->path))
+ return FALSE;
+
+ if (da->flags != db->flags)
+ return FALSE;
+
+ ia = _dbus_list_get_next_link (&a, ia);
+ ib = _dbus_list_get_next_link (&b, ib);
+ }
+
+ return ia == NULL && ib == NULL;
+}
+
+static dbus_bool_t
limits_equal (const BusLimits *a,
const BusLimits *b)
{
@@ -3252,7 +3556,7 @@ config_parsers_equal (const BusConfigParser *a,
if (!lists_of_c_strings_equal (a->mechanisms, b->mechanisms))
return FALSE;
- if (!lists_of_c_strings_equal (a->service_dirs, b->service_dirs))
+ if (!lists_of_service_dirs_equal (a->service_dirs, b->service_dirs))
return FALSE;
/* FIXME: compare policy */
@@ -3300,7 +3604,7 @@ all_are_equiv (const DBusString *target_directory)
dir = _dbus_directory_open (target_directory, &error);
if (dir == NULL)
{
- _dbus_warn ("Could not open %s: %s\n",
+ _dbus_warn ("Could not open %s: %s",
_dbus_string_get_const_data (target_directory),
error.message);
dbus_error_free (&error);
@@ -3337,7 +3641,7 @@ all_are_equiv (const DBusString *target_directory)
if (parser == NULL)
{
- _dbus_warn ("Could not load file %s: %s\n",
+ _dbus_warn ("Could not load file %s: %s",
_dbus_string_get_const_data (&full_path),
error.message);
_dbus_string_free (&full_path);
@@ -3406,7 +3710,7 @@ process_test_equiv_subdir (const DBusString *test_base_dir,
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
- _dbus_warn ("Could not open %s: %s\n",
+ _dbus_warn ("Could not open %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -3451,52 +3755,79 @@ process_test_equiv_subdir (const DBusString *test_base_dir,
static const char *test_session_service_dir_matches[] =
{
-#ifdef DBUS_UNIX
- "/testhome/foo/.testlocal/testshare/dbus-1/services",
- "/testusr/testlocal/testshare/dbus-1/services",
- "/testusr/testshare/dbus-1/services",
- DBUS_DATADIR"/dbus-1/services",
-#endif
/* will be filled in test_default_session_servicedirs() */
#ifdef DBUS_WIN
- NULL,
- NULL,
+ NULL, /* install root-based */
+ NULL, /* CommonProgramFiles-based */
+#else
+ NULL, /* XDG_RUNTIME_DIR-based */
+ NULL, /* XDG_DATA_HOME-based */
+ NULL, /* XDG_DATA_DIRS-based */
+ NULL, /* XDG_DATA_DIRS-based */
+ DBUS_DATADIR "/dbus-1/services",
#endif
NULL
};
static dbus_bool_t
-test_default_session_servicedirs (void)
+test_default_session_servicedirs (const DBusString *test_base_dir)
{
- DBusList *dirs;
+ BusConfigParser *parser = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusList **dirs;
+ DBusList *watched_dirs = NULL;
DBusList *link;
+ DBusString tmp;
+ DBusString full_path;
DBusString progs;
DBusString install_root_based;
+ DBusString runtime_dir_based;
+ DBusString data_home_based;
+ DBusString data_dirs_based;
+ DBusString data_dirs_based2;
int i;
dbus_bool_t ret = FALSE;
#ifdef DBUS_WIN
- const char *tmp;
const char *common_progs;
+#else
+ const char *dbus_test_builddir;
+ const char *xdg_data_home;
+ const char *xdg_runtime_dir;
#endif
- /* On Unix we don't actually use these, but it's easier to handle the
- * deallocation if we always allocate them, whether needed or not */
- if (!_dbus_string_init (&progs) ||
- !_dbus_string_init (&install_root_based))
+ /* On each platform we don't actually use all of these, but it's easier to
+ * handle the deallocation if we always allocate them, whether needed or
+ * not */
+ if (!_dbus_string_init (&full_path) ||
+ !_dbus_string_init (&progs) ||
+ !_dbus_string_init (&install_root_based) ||
+ !_dbus_string_init (&runtime_dir_based) ||
+ !_dbus_string_init (&data_home_based) ||
+ !_dbus_string_init (&data_dirs_based) ||
+ !_dbus_string_init (&data_dirs_based2))
_dbus_assert_not_reached ("OOM allocating strings");
+ if (!_dbus_string_copy (test_base_dir, 0,
+ &full_path, 0))
+ _dbus_assert_not_reached ("couldn't copy test_base_dir to full_path");
+
+ _dbus_string_init_const (&tmp, "valid-config-files");
+
+ if (!_dbus_concat_dir_and_file (&full_path, &tmp))
+ _dbus_assert_not_reached ("couldn't allocate full path");
+
+ _dbus_string_init_const (&tmp, "standard-session-dirs.conf");
+
+ if (!_dbus_concat_dir_and_file (&full_path, &tmp))
+ _dbus_assert_not_reached ("couldn't allocate full path");
+
#ifdef DBUS_WIN
if (!_dbus_string_append (&install_root_based, DBUS_DATADIR) ||
- !_dbus_string_append (&install_root_based, "/dbus-1/services"))
+ !_dbus_string_append (&install_root_based, "/dbus-1/services") ||
+ !_dbus_replace_install_prefix (&install_root_based))
goto out;
- tmp = _dbus_replace_install_prefix (
- _dbus_string_get_const_data (&install_root_based));
-
- if (tmp == NULL ||
- !_dbus_string_set_length (&install_root_based, 0) ||
- !_dbus_string_append (&install_root_based, tmp))
- goto out;
+ _dbus_assert (_dbus_path_is_absolute (&install_root_based));
test_session_service_dir_matches[0] = _dbus_string_get_const_data (
&install_root_based);
@@ -3513,72 +3844,143 @@ test_default_session_servicedirs (void)
test_session_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
}
+#else
+ dbus_test_builddir = _dbus_getenv ("DBUS_TEST_BUILDDIR");
+ xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
+ xdg_runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
+
+ if (dbus_test_builddir == NULL || xdg_data_home == NULL ||
+ xdg_runtime_dir == NULL)
+ {
+ printf ("Not testing default session service directories because a "
+ "build-time testing environment variable is not set: "
+ "see AM_TESTS_ENVIRONMENT in tests/Makefile.am\n");
+ ret = TRUE;
+ goto out;
+ }
+
+ if (!_dbus_string_append (&data_dirs_based, dbus_test_builddir) ||
+ !_dbus_string_append (&data_dirs_based, "/XDG_DATA_DIRS/dbus-1/services") ||
+ !_dbus_string_append (&data_dirs_based2, dbus_test_builddir) ||
+ !_dbus_string_append (&data_dirs_based2, "/XDG_DATA_DIRS2/dbus-1/services") ||
+ !_dbus_string_append (&runtime_dir_based, xdg_runtime_dir) ||
+ !_dbus_string_append (&data_home_based, xdg_data_home) ||
+ !_dbus_string_append (&data_home_based, "/dbus-1/services"))
+ _dbus_assert_not_reached ("out of memory");
+
+ if (!_dbus_ensure_directory (&runtime_dir_based, NULL))
+ _dbus_assert_not_reached ("Unable to create fake XDG_RUNTIME_DIR");
+
+ if (!_dbus_string_append (&runtime_dir_based, "/dbus-1/services"))
+ _dbus_assert_not_reached ("out of memory");
+
+ /* Sanity check: the Makefile sets this up. We assume that if this is
+ * right, the XDG_DATA_DIRS will be too. */
+ if (!_dbus_string_starts_with_c_str (&data_home_based, dbus_test_builddir))
+ _dbus_assert_not_reached ("$XDG_DATA_HOME should start with $DBUS_TEST_BUILDDIR");
+
+ if (!_dbus_string_starts_with_c_str (&runtime_dir_based, dbus_test_builddir))
+ _dbus_assert_not_reached ("$XDG_RUNTIME_DIR should start with $DBUS_TEST_BUILDDIR");
+
+ test_session_service_dir_matches[0] = _dbus_string_get_const_data (
+ &runtime_dir_based);
+ test_session_service_dir_matches[1] = _dbus_string_get_const_data (
+ &data_home_based);
+ test_session_service_dir_matches[2] = _dbus_string_get_const_data (
+ &data_dirs_based);
+ test_session_service_dir_matches[3] = _dbus_string_get_const_data (
+ &data_dirs_based2);
#endif
- dirs = NULL;
- printf ("Testing retrieving the default session service directories\n");
- if (!_dbus_get_standard_session_servicedirs (&dirs))
- _dbus_assert_not_reached ("couldn't get stardard dirs");
+ parser = bus_config_load (&full_path, TRUE, NULL, &error);
- /* make sure our defaults end with share/dbus-1/service */
- while ((link = _dbus_list_pop_first_link (&dirs)))
+ if (parser == NULL)
+ _dbus_assert_not_reached (error.message);
+
+ dirs = bus_config_parser_get_service_dirs (parser);
+
+ for (link = _dbus_list_get_first_link (dirs), i = 0;
+ link != NULL;
+ link = _dbus_list_get_next_link (dirs, link), i++)
{
- DBusString path;
-
- printf (" default service dir: %s\n", (char *)link->data);
- _dbus_string_init_const (&path, (char *)link->data);
- if (!_dbus_string_ends_with_c_str (&path, "dbus-1/services"))
+ BusConfigServiceDir *dir = link->data;
+ BusServiceDirFlags expected = BUS_SERVICE_DIR_FLAGS_NONE;
+
+ printf (" test service dir: '%s'\n", dir->path);
+ printf (" current standard service dir: '%s'\n", test_session_service_dir_matches[i]);
+ if (test_session_service_dir_matches[i] == NULL)
{
- printf ("error with default session service directories\n");
- dbus_free (link->data);
- _dbus_list_free_link (link);
+ printf ("more directories parsed than in match set\n");
goto out;
}
- dbus_free (link->data);
- _dbus_list_free_link (link);
+ if (strcmp (test_session_service_dir_matches[i], dir->path) != 0)
+ {
+ printf ("'%s' directory does not match '%s' in the match set\n",
+ dir->path, test_session_service_dir_matches[i]);
+ goto out;
+ }
+
+#ifndef DBUS_WIN
+ /* On Unix we expect the first directory in the search path to be
+ * in the XDG_RUNTIME_DIR, and we expect it to have special flags */
+ if (i == 0)
+ expected = (BUS_SERVICE_DIR_FLAGS_NO_WATCH |
+ BUS_SERVICE_DIR_FLAGS_STRICT_NAMING);
+#endif
+
+ if (dir->flags != expected)
+ {
+ printf ("'%s' directory has flags 0x%x, should be 0x%x\n",
+ dir->path, dir->flags, expected);
+ goto out;
+ }
+ }
+
+ if (test_session_service_dir_matches[i] != NULL)
+ {
+ printf ("extra data %s in the match set was not matched\n",
+ test_session_service_dir_matches[i]);
+ goto out;
}
-#ifdef DBUS_UNIX
- if (!dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
- _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
+ if (!bus_config_parser_get_watched_dirs (parser, &watched_dirs))
+ _dbus_assert_not_reached ("out of memory");
- if (!dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
- _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
+#ifdef DBUS_WIN
+ /* We expect all directories to be watched (not that it matters on Windows,
+ * because we don't know how) */
+ i = 0;
+#else
+ /* We expect all directories except the first to be watched, because
+ * the first one is transient */
+ i = 1;
#endif
- if (!_dbus_get_standard_session_servicedirs (&dirs))
- _dbus_assert_not_reached ("couldn't get stardard dirs");
- /* make sure we read and parse the env variable correctly */
- i = 0;
- while ((link = _dbus_list_pop_first_link (&dirs)))
+ for (link = _dbus_list_get_first_link (&watched_dirs);
+ link != NULL;
+ link = _dbus_list_get_next_link (&watched_dirs, link), i++)
{
- printf (" test service dir: %s\n", (char *)link->data);
+ printf (" watched service dir: '%s'\n", (const char *) link->data);
+ printf (" current standard service dir: '%s'\n",
+ test_session_service_dir_matches[i]);
+
if (test_session_service_dir_matches[i] == NULL)
{
printf ("more directories parsed than in match set\n");
- dbus_free (link->data);
- _dbus_list_free_link (link);
goto out;
}
-
- if (strcmp (test_session_service_dir_matches[i],
- (char *)link->data) != 0)
+
+ if (strcmp (test_session_service_dir_matches[i],
+ (const char *) link->data) != 0)
{
- printf ("%s directory does not match %s in the match set\n",
- (char *)link->data,
+ printf ("'%s' directory does not match '%s' in the match set\n",
+ (const char *) link->data,
test_session_service_dir_matches[i]);
- dbus_free (link->data);
- _dbus_list_free_link (link);
goto out;
}
-
- ++i;
-
- dbus_free (link->data);
- _dbus_list_free_link (link);
}
-
+
if (test_session_service_dir_matches[i] != NULL)
{
printf ("extra data %s in the match set was not matched\n",
@@ -3589,25 +3991,27 @@ test_default_session_servicedirs (void)
ret = TRUE;
out:
+ if (parser != NULL)
+ bus_config_parser_unref (parser);
+
+ _dbus_list_clear (&watched_dirs);
+ _dbus_string_free (&full_path);
_dbus_string_free (&install_root_based);
_dbus_string_free (&progs);
+ _dbus_string_free (&runtime_dir_based);
+ _dbus_string_free (&data_home_based);
+ _dbus_string_free (&data_dirs_based);
+ _dbus_string_free (&data_dirs_based2);
return ret;
}
+#ifndef DBUS_WIN
static const char *test_system_service_dir_matches[] =
{
-#ifdef DBUS_UNIX
"/usr/local/share/dbus-1/system-services",
"/usr/share/dbus-1/system-services",
-#endif
DBUS_DATADIR"/dbus-1/system-services",
-#ifdef DBUS_UNIX
"/lib/dbus-1/system-services",
-#endif
-
-#ifdef DBUS_WIN
- NULL,
-#endif
NULL
};
@@ -3616,69 +4020,10 @@ test_default_system_servicedirs (void)
{
DBusList *dirs;
DBusList *link;
- DBusString progs;
-#ifndef DBUS_UNIX
- const char *common_progs;
-#endif
int i;
- /* On Unix we don't actually use this variable, but it's easier to handle the
- * deallocation if we always allocate it, whether needed or not */
- if (!_dbus_string_init (&progs))
- _dbus_assert_not_reached ("OOM allocating progs");
-
-#ifndef DBUS_UNIX
- common_progs = _dbus_getenv ("CommonProgramFiles");
-
- if (common_progs)
- {
- if (!_dbus_string_append (&progs, common_progs))
- {
- _dbus_string_free (&progs);
- return FALSE;
- }
-
- if (!_dbus_string_append (&progs, "/dbus-1/system-services"))
- {
- _dbus_string_free (&progs);
- return FALSE;
- }
- test_system_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
- }
-#endif
dirs = NULL;
- printf ("Testing retrieving the default system service directories\n");
- if (!_dbus_get_standard_system_servicedirs (&dirs))
- _dbus_assert_not_reached ("couldn't get stardard dirs");
-
- /* make sure our defaults end with share/dbus-1/system-service */
- while ((link = _dbus_list_pop_first_link (&dirs)))
- {
- DBusString path;
-
- printf (" default service dir: %s\n", (char *)link->data);
- _dbus_string_init_const (&path, (char *)link->data);
- if (!_dbus_string_ends_with_c_str (&path, "dbus-1/system-services"))
- {
- printf ("error with default system service directories\n");
- dbus_free (link->data);
- _dbus_list_free_link (link);
- _dbus_string_free (&progs);
- return FALSE;
- }
-
- dbus_free (link->data);
- _dbus_list_free_link (link);
- }
-
-#ifdef DBUS_UNIX
- if (!dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
- _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
-
- if (!dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
- _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
-#endif
if (!_dbus_get_standard_system_servicedirs (&dirs))
_dbus_assert_not_reached ("couldn't get stardard dirs");
@@ -3692,7 +4037,6 @@ test_default_system_servicedirs (void)
printf ("more directories parsed than in match set\n");
dbus_free (link->data);
_dbus_list_free_link (link);
- _dbus_string_free (&progs);
return FALSE;
}
@@ -3704,7 +4048,6 @@ test_default_system_servicedirs (void)
test_system_service_dir_matches[i]);
dbus_free (link->data);
_dbus_list_free_link (link);
- _dbus_string_free (&progs);
return FALSE;
}
@@ -3719,13 +4062,12 @@ test_default_system_servicedirs (void)
printf ("extra data %s in the match set was not matched\n",
test_system_service_dir_matches[i]);
- _dbus_string_free (&progs);
return FALSE;
}
- _dbus_string_free (&progs);
return TRUE;
}
+#endif
dbus_bool_t
bus_config_parser_test (const DBusString *test_data_dir)
@@ -3737,7 +4079,7 @@ bus_config_parser_test (const DBusString *test_data_dir)
return TRUE;
}
- if (!test_default_session_servicedirs())
+ if (!test_default_session_servicedirs (test_data_dir))
return FALSE;
#ifdef DBUS_WIN
diff --git a/bus/config-parser.h b/bus/config-parser.h
index ba5bf749..a24e74b2 100644
--- a/bus/config-parser.h
+++ b/bus/config-parser.h
@@ -73,6 +73,8 @@ DBusList** bus_config_parser_get_conf_dirs (BusConfigParser *parser);
BusPolicy* bus_config_parser_steal_policy (BusConfigParser *parser);
void bus_config_parser_get_limits (BusConfigParser *parser,
BusLimits *limits);
+dbus_bool_t bus_config_parser_get_watched_dirs (BusConfigParser *parser,
+ DBusList **watched_dirs);
DBusHashTable* bus_config_parser_steal_service_context_table (BusConfigParser *parser);
@@ -84,4 +86,23 @@ BusConfigParser* bus_config_load (const DBusString *file,
const BusConfigParser *parent,
DBusError *error);
+/*
+ * These are chosen such that if we configure a directory twice with different
+ * flags, we have to do an "and" operation on the flags - the compatible
+ * thing to do is to have no flags.
+ */
+typedef enum
+{
+ BUS_SERVICE_DIR_FLAGS_NO_WATCH = (1 << 0),
+ BUS_SERVICE_DIR_FLAGS_STRICT_NAMING = (1 << 1),
+ /* Keep this one at the end to reduce diffs when adding new entries */
+ BUS_SERVICE_DIR_FLAGS_NONE = 0
+} BusServiceDirFlags;
+
+typedef struct
+{
+ BusServiceDirFlags flags;
+ char *path;
+} BusConfigServiceDir;
+
#endif /* BUS_CONFIG_PARSER_H */
diff --git a/bus/connection.c b/bus/connection.c
index 7253c98e..e1802e7d 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -454,9 +454,6 @@ free_connection_data (void *data)
if (d->policy)
bus_client_policy_unref (d->policy);
- if (d->selinux_id)
- bus_selinux_id_unref (d->selinux_id);
-
if (d->apparmor_confinement)
bus_apparmor_confinement_unref (d->apparmor_confinement);
@@ -601,7 +598,7 @@ cache_peer_loginfo_string (BusConnectionData *d,
DBusString loginfo_buf;
unsigned long uid;
unsigned long pid;
- char *windows_sid;
+ char *windows_sid = NULL, *security_label = NULL;
dbus_bool_t prev_added;
if (!_dbus_string_init (&loginfo_buf))
@@ -630,16 +627,48 @@ cache_peer_loginfo_string (BusConnectionData *d,
_dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL);
if (!_dbus_string_append_byte (&loginfo_buf, '"'))
goto oom;
+ else
+ prev_added = TRUE;
}
if (dbus_connection_get_windows_user (connection, &windows_sid))
{
dbus_bool_t did_append;
+
+ if (prev_added)
+ {
+ if (!_dbus_string_append_byte (&loginfo_buf, ' '))
+ goto oom;
+ }
+
did_append = _dbus_string_append_printf (&loginfo_buf,
- "sid=\"%s\" ", windows_sid);
+ "sid=\"%s\"", windows_sid);
dbus_free (windows_sid);
+ windows_sid = NULL;
+ if (!did_append)
+ goto oom;
+ else
+ prev_added = TRUE;
+ }
+
+ if (_dbus_connection_get_linux_security_label (connection, &security_label))
+ {
+ dbus_bool_t did_append;
+
+ if (prev_added)
+ {
+ if (!_dbus_string_append_byte (&loginfo_buf, ' '))
+ goto oom;
+ }
+
+ did_append = _dbus_string_append_printf (&loginfo_buf,
+ "label=\"%s\"", security_label);
+ dbus_free (security_label);
+ security_label = NULL;
if (!did_append)
goto oom;
+ else
+ prev_added = TRUE;
}
if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string)))
@@ -650,6 +679,11 @@ cache_peer_loginfo_string (BusConnectionData *d,
return TRUE;
oom:
_dbus_string_free (&loginfo_buf);
+ if (security_label != NULL)
+ dbus_free (security_label);
+ if (windows_sid != NULL)
+ dbus_free (windows_sid);
+
return FALSE;
}
@@ -687,6 +721,18 @@ static dbus_bool_t
pending_unix_fds_timeout_cb (void *data)
{
DBusConnection *connection = data;
+ BusConnectionData *d = BUS_CONNECTION_DATA (connection);
+ int limit;
+
+ _dbus_assert (d != NULL);
+ limit = bus_context_get_pending_fd_timeout (d->connections->context);
+ bus_context_log (d->connections->context, DBUS_SYSTEM_LOG_WARNING,
+ "Connection \"%s\" (%s) has had Unix fds pending for too long, "
+ "closing it (pending_fd_timeout=%d ms)",
+ d->name != NULL ? d->name : "(null)",
+ bus_connection_get_loginfo (connection),
+ limit);
+
dbus_connection_close (connection);
return TRUE;
}
@@ -696,15 +742,13 @@ bus_connections_setup_connection (BusConnections *connections,
DBusConnection *connection)
{
- BusConnectionData *d;
- dbus_bool_t retval;
+ BusConnectionData *d = NULL;
DBusError error;
-
d = dbus_new0 (BusConnectionData, 1);
if (d == NULL)
- return FALSE;
+ goto oom;
d->connections = connections;
d->connection = connection;
@@ -718,39 +762,35 @@ bus_connections_setup_connection (BusConnections *connections,
connection_data_slot,
d, free_connection_data))
{
+ /* We have to free d explicitly, because this is the only code
+ * path where it's non-NULL but dbus_connection_set_data() hasn't
+ * taken responsibility for freeing it. */
dbus_free (d);
- return FALSE;
+ d = NULL;
+ goto oom;
}
dbus_connection_set_route_peer_messages (connection, TRUE);
-
- retval = FALSE;
dbus_error_init (&error);
d->selinux_id = bus_selinux_init_connection_id (connection,
&error);
if (dbus_error_is_set (&error))
{
- /* This is a bit bogus because we pretend all errors
- * are OOM; this is done because we know that in bus.c
- * an OOM error disconnects the connection, which is
- * the same thing we want on any other error.
- */
+ bus_context_log (connections->context, DBUS_SYSTEM_LOG_WARNING,
+ "Unable to set up new connection: %s", error.message);
dbus_error_free (&error);
- goto out;
+ goto error;
}
d->apparmor_confinement = bus_apparmor_init_connection_confinement (connection,
&error);
if (dbus_error_is_set (&error))
{
- /* This is a bit bogus because we pretend all errors
- * are OOM; this is done because we know that in bus.c
- * an OOM error disconnects the connection, which is
- * the same thing we want on any other error.
- */
+ bus_context_log (connections->context, DBUS_SYSTEM_LOG_WARNING,
+ "Unable to set up new connection: %s", error.message);
dbus_error_free (&error);
- goto out;
+ goto error;
}
if (!dbus_connection_set_watch_functions (connection,
@@ -759,14 +799,14 @@ bus_connections_setup_connection (BusConnections *connections,
toggle_connection_watch,
connection,
NULL))
- goto out;
+ goto oom;
if (!dbus_connection_set_timeout_functions (connection,
add_connection_timeout,
remove_connection_timeout,
NULL,
connection, NULL))
- goto out;
+ goto oom;
/* For now we don't need to set a Windows user function because
* there are no policies in the config file controlling what
@@ -784,18 +824,18 @@ bus_connections_setup_connection (BusConnections *connections,
d->link_in_connection_list = _dbus_list_alloc_link (connection);
if (d->link_in_connection_list == NULL)
- goto out;
+ goto oom;
/* Setup the connection with the dispatcher */
if (!bus_dispatch_add_connection (connection))
- goto out;
+ goto oom;
if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
{
if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
{
bus_dispatch_remove_connection (connection);
- goto out;
+ goto oom;
}
}
@@ -804,12 +844,12 @@ bus_connections_setup_connection (BusConnections *connections,
pending_unix_fds_timeout_cb,
connection, NULL);
if (d->pending_unix_fds_timeout == NULL)
- goto out;
+ goto oom;
_dbus_timeout_disable (d->pending_unix_fds_timeout);
if (!_dbus_loop_add_timeout (bus_context_get_loop (connections->context),
d->pending_unix_fds_timeout))
- goto out;
+ goto oom;
_dbus_connection_set_pending_fds_function (connection,
(DBusPendingFdsChangeFunction) check_pending_fds_cb,
@@ -832,13 +872,15 @@ bus_connections_setup_connection (BusConnections *connections,
* stop accept()ing any more, to avert a DoS. See fd.o #80919 */
bus_context_check_all_watches (d->connections->context);
- retval = TRUE;
+ return TRUE;
- out:
- if (!retval)
+oom:
+ bus_context_log (connections->context, DBUS_SYSTEM_LOG_WARNING,
+ "No memory to set up new connection");
+ /* fall through */
+error:
+ if (d != NULL)
{
- if (d->selinux_id)
- bus_selinux_id_unref (d->selinux_id);
d->selinux_id = NULL;
if (d->apparmor_confinement)
@@ -889,7 +931,7 @@ bus_connections_setup_connection (BusConnections *connections,
/* "d" has now been freed */
}
- return retval;
+ return FALSE;
}
void
@@ -1697,13 +1739,23 @@ bus_connection_get_name (DBusConnection *connection)
dbus_bool_t
bus_connections_check_limits (BusConnections *connections,
DBusConnection *requesting_completion,
+ const char **limit_name_out,
+ int *limit_out,
DBusError *error)
{
unsigned long uid;
+ int limit;
+
+ limit = bus_context_get_max_completed_connections (connections->context);
- if (connections->n_completed >=
- bus_context_get_max_completed_connections (connections->context))
+ if (connections->n_completed >= limit)
{
+ if (limit_name_out != NULL)
+ *limit_name_out = "max_completed_connections";
+
+ if (limit_out != NULL)
+ *limit_out = limit;
+
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
"The maximum number of active connections has been reached");
return FALSE;
@@ -1711,9 +1763,16 @@ bus_connections_check_limits (BusConnections *connections,
if (dbus_connection_get_unix_user (requesting_completion, &uid))
{
- if (get_connections_for_uid (connections, uid) >=
- bus_context_get_max_connections_per_user (connections->context))
+ limit = bus_context_get_max_connections_per_user (connections->context);
+
+ if (get_connections_for_uid (connections, uid) >= limit)
{
+ if (limit_name_out != NULL)
+ *limit_name_out = "max_connections_per_user";
+
+ if (limit_out != NULL)
+ *limit_out = limit;
+
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
"The maximum number of active connections for UID %lu has been reached",
uid);
@@ -1933,6 +1992,7 @@ bus_connections_expect_reply (BusConnections *connections,
DBusList *link;
CancelPendingReplyData *cprd;
int count;
+ int limit;
_dbus_assert (will_get_reply != NULL);
_dbus_assert (will_send_reply != NULL);
@@ -1963,10 +2023,19 @@ bus_connections_expect_reply (BusConnections *connections,
if (pending->will_get_reply == will_get_reply)
++count;
}
-
- if (count >=
- bus_context_get_max_replies_per_connection (connections->context))
+
+ limit = bus_context_get_max_replies_per_connection (connections->context);
+
+ if (count >= limit)
{
+ bus_context_log (connections->context, DBUS_SYSTEM_LOG_WARNING,
+ "The maximum number of pending replies for "
+ "\"%s\" (%s) has been reached "
+ "(max_replies_per_connection=%d)",
+ bus_connection_get_name (will_get_reply),
+ bus_connection_get_loginfo (will_get_reply),
+ limit);
+
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
"The maximum number of pending replies per connection has been reached");
return FALSE;
@@ -2246,6 +2315,7 @@ bus_transaction_get_context (BusTransaction *transaction)
dbus_bool_t
bus_transaction_capture (BusTransaction *transaction,
DBusConnection *sender,
+ DBusConnection *addressed_recipient,
DBusMessage *message)
{
BusConnections *connections;
@@ -2265,8 +2335,8 @@ bus_transaction_capture (BusTransaction *transaction,
* There's little point, since there is up to 1 per process. */
_dbus_assert (mm != NULL);
- if (!bus_matchmaker_get_recipients (mm, connections, sender, NULL, message,
- &recipients))
+ if (!bus_matchmaker_get_recipients (mm, connections, sender,
+ addressed_recipient, message, &recipients))
goto out;
for (link = _dbus_list_get_first_link (&recipients);
@@ -2288,6 +2358,7 @@ out:
dbus_bool_t
bus_transaction_capture_error_reply (BusTransaction *transaction,
+ DBusConnection *addressed_recipient,
const DBusError *error,
DBusMessage *in_reply_to)
{
@@ -2314,7 +2385,7 @@ bus_transaction_capture_error_reply (BusTransaction *transaction,
if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
goto out;
- ret = bus_transaction_capture (transaction, NULL, reply);
+ ret = bus_transaction_capture (transaction, NULL, addressed_recipient, reply);
out:
dbus_message_unref (reply);
@@ -2357,7 +2428,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
/* Capture it for monitors, even if the real recipient's receive policy
* does not allow it to receive this message from us (which would be odd).
*/
- if (!bus_transaction_capture (transaction, NULL, message))
+ if (!bus_transaction_capture (transaction, NULL, connection, message))
return FALSE;
/* If security policy doesn't allow the message, we would silently
@@ -2374,7 +2445,8 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
case BUS_RESULT_TRUE:
break;
case BUS_RESULT_FALSE:
- if (!bus_transaction_capture_error_reply (transaction, &error, message))
+ if (!bus_transaction_capture_error_reply (transaction, connection,
+ &error, message))
{
bus_context_log (transaction->context, DBUS_SYSTEM_LOG_WARNING,
"message from dbus-daemon rejected but not enough "
diff --git a/bus/connection.h b/bus/connection.h
index 6c6fca8d..ba7ce2f3 100644
--- a/bus/connection.h
+++ b/bus/connection.h
@@ -58,6 +58,8 @@ BusSELinuxID* bus_connection_get_selinux_id (DBusConnection
BusAppArmorConfinement* bus_connection_dup_apparmor_confinement (DBusConnection *connection);
dbus_bool_t bus_connections_check_limits (BusConnections *connections,
DBusConnection *requesting_completion,
+ const char **limit_name_out,
+ int *limit_out,
DBusError *error);
void bus_connections_expire_incomplete (BusConnections *connections);
@@ -158,8 +160,10 @@ dbus_bool_t bus_transaction_send (BusTransaction *
dbus_bool_t deferred_dispatch);
dbus_bool_t bus_transaction_capture (BusTransaction *transaction,
DBusConnection *connection,
+ DBusConnection *addressed_recipient,
DBusMessage *message);
dbus_bool_t bus_transaction_capture_error_reply (BusTransaction *transaction,
+ DBusConnection *addressed_recipient,
const DBusError *error,
DBusMessage *in_reply_to);
dbus_bool_t bus_transaction_send_from_driver (BusTransaction *transaction,
diff --git a/bus/dbus.service.in b/bus/dbus.service.in
index 9686f362..21ea6769 100644
--- a/bus/dbus.service.in
+++ b/bus/dbus.service.in
@@ -6,7 +6,7 @@ Requires=dbus.socket
[Service]
Type=notify
-ExecStart=@EXPANDED_BINDIR@/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
+ExecStart=@EXPANDED_BINDIR@/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
ExecReload=@EXPANDED_BINDIR@/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
OOMScoreAdjust=-900
User=dbus
diff --git a/bus/desktop-file.c b/bus/desktop-file.c
index bfeb72e2..fd4f0d31 100644
--- a/bus/desktop-file.c
+++ b/bus/desktop-file.c
@@ -88,7 +88,7 @@ static unsigned char valid[256] = {
};
static void report_error (BusDesktopFileParser *parser,
- char *message,
+ const char *message,
const char *error_name,
DBusError *error);
@@ -378,12 +378,16 @@ parse_comment_or_blank (BusDesktopFileParser *parser)
static dbus_bool_t
is_valid_section_name (const char *name)
{
- /* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'. */
+ /* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'.
+ *
+ * We don't use isprint() here because it's locale-dependent. ASCII
+ * characters <= 0x1f and 0x7f are control characters, and bytes with
+ * values >= 0x80 aren't ASCII. 0x20 is a space, which we must allow,
+ * not least because DBUS_SERVICE_SECTION contains one. */
while (*name)
{
- if (!((*name >= 'A' && *name <= 'Z') || (*name >= 'a' || *name <= 'z') ||
- *name == '\n' || *name == '\t'))
+ if (*name <= 0x1f || *name >= 0x7f || *name == '[' || *name == ']')
return FALSE;
name++;
@@ -579,7 +583,7 @@ parse_key_value (BusDesktopFileParser *parser, DBusError *error)
static void
report_error (BusDesktopFileParser *parser,
- char *message,
+ const char *message,
const char *error_name,
DBusError *error)
{
diff --git a/bus/desktop-file.h b/bus/desktop-file.h
index e405625c..14477387 100644
--- a/bus/desktop-file.h
+++ b/bus/desktop-file.h
@@ -35,6 +35,7 @@
#define DBUS_SERVICE_EXEC "Exec"
#define DBUS_SERVICE_USER "User"
#define DBUS_SERVICE_SYSTEMD_SERVICE "SystemdService"
+#define DBUS_SERVICE_ASSUMED_APPARMOR_LABEL "AssumedAppArmorLabel"
typedef struct BusDesktopFile BusDesktopFile;
diff --git a/bus/dir-watch-inotify.c b/bus/dir-watch-inotify.c
index a287f0ba..447dc2db 100644
--- a/bus/dir-watch-inotify.c
+++ b/bus/dir-watch-inotify.c
@@ -157,7 +157,7 @@ _set_watched_dirs_internal (DBusList **directories)
/* Not all service directories need to exist. */
if (errno != ENOENT)
{
- _dbus_warn ("Cannot setup inotify for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
+ _dbus_warn ("Cannot setup inotify for '%s'; error '%s'", new_dirs[i], _dbus_strerror (errno));
goto out;
}
else
@@ -236,7 +236,7 @@ _init_inotify (BusContext *context)
#endif
if (inotify_fd <= 0)
{
- _dbus_warn ("Cannot initialize inotify\n");
+ _dbus_warn ("Cannot initialize inotify");
goto out;
}
@@ -252,7 +252,7 @@ _init_inotify (BusContext *context)
if (watch == NULL)
{
- _dbus_warn ("Unable to create inotify watch\n");
+ _dbus_warn ("Unable to create inotify watch");
goto out;
}
diff --git a/bus/dir-watch-kqueue.c b/bus/dir-watch-kqueue.c
index c1e83245..9b1784e8 100644
--- a/bus/dir-watch-kqueue.c
+++ b/bus/dir-watch-kqueue.c
@@ -137,7 +137,7 @@ _init_kqueue (BusContext *context)
kq = kqueue ();
if (kq < 0)
{
- _dbus_warn ("Cannot create kqueue; error '%s'\n", _dbus_strerror (errno));
+ _dbus_warn ("Cannot create kqueue; error '%s'", _dbus_strerror (errno));
goto out;
}
@@ -149,7 +149,7 @@ _init_kqueue (BusContext *context)
if (watch == NULL)
{
- _dbus_warn ("Unable to create kqueue watch\n");
+ _dbus_warn ("Unable to create kqueue watch");
goto out1;
}
@@ -276,7 +276,7 @@ bus_set_watched_dirs (BusContext *context, DBusList **directories)
{
if (errno != ENOENT)
{
- _dbus_warn ("Cannot open directory '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
+ _dbus_warn ("Cannot open directory '%s'; error '%s'", new_dirs[i], _dbus_strerror (errno));
goto out;
}
else
@@ -297,7 +297,7 @@ bus_set_watched_dirs (BusContext *context, DBusList **directories)
NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_RENAME, 0, 0);
if (kevent (kq, &ev, 1, NULL, 0, NULL) == -1)
{
- _dbus_warn ("Cannot setup a kevent for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
+ _dbus_warn ("Cannot setup a kevent for '%s'; error '%s'", new_dirs[i], _dbus_strerror (errno));
close (fd);
goto out;
}
diff --git a/bus/dispatch.c b/bus/dispatch.c
index f4dea605..3cdae9f9 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -75,8 +75,8 @@ send_one_message (DBusConnection *connection,
if (result == BUS_RESULT_FALSE)
{
- if (!bus_transaction_capture_error_reply (transaction, &stack_error,
- message))
+ if (!bus_transaction_capture_error_reply (transaction, sender,
+ &stack_error, message))
{
bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
"broadcast rejected, but not enough "
@@ -96,8 +96,8 @@ send_one_message (DBusConnection *connection,
bus_connection_get_name (connection),
bus_connection_get_loginfo (connection));
- if (!bus_transaction_capture_error_reply (transaction, &stack_error,
- message))
+ if (!bus_transaction_capture_error_reply (transaction, sender,
+ &stack_error, message))
{
bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
"broadcast with Unix fd not delivered, but not "
@@ -483,17 +483,17 @@ bus_dispatch (DBusConnection *connection,
*/
service_name = dbus_message_get_destination (message);
- if (!bus_transaction_capture (transaction, connection, message))
- {
- BUS_SET_OOM (&error);
- goto out;
- }
-
if (service_name &&
strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
{
BusDeferredMessage *deferred_message;
+ if (!bus_transaction_capture (transaction, connection, NULL, message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
+
switch (bus_context_check_security_policy (context, transaction,
connection, NULL, NULL, message,
NULL, &error,
@@ -530,6 +530,12 @@ bus_dispatch (DBusConnection *connection,
}
else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
{
+ if (!bus_transaction_capture (transaction, connection, NULL, message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
+
_dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
dbus_connection_close (connection);
goto out;
@@ -552,6 +558,13 @@ bus_dispatch (DBusConnection *connection,
BusActivation *activation;
BusDeferredMessage *deferred_message;
+ if (!bus_transaction_capture (transaction, connection, NULL,
+ message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
+
activation = bus_connection_get_activation (connection);
/* This will do as much of a security policy check as it can.
@@ -581,6 +594,13 @@ bus_dispatch (DBusConnection *connection,
}
else if (service == NULL)
{
+ if (!bus_transaction_capture (transaction, connection,
+ NULL, message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
+
dbus_set_error (&error,
DBUS_ERROR_NAME_HAS_NO_OWNER,
"Name \"%s\" does not exist",
@@ -591,6 +611,21 @@ bus_dispatch (DBusConnection *connection,
{
addressed_recipient = bus_service_get_primary_owners_connection (service);
_dbus_assert (addressed_recipient != NULL);
+
+ if (!bus_transaction_capture (transaction, connection,
+ addressed_recipient, message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
+ }
+ }
+ }
+ else /* service_name == NULL */
+ {
+ if (!bus_transaction_capture (transaction, connection, NULL, message))
+ {
+ BUS_SET_OOM (&error);
+ goto out;
}
}
@@ -769,7 +804,7 @@ warn_unexpected_real (DBusConnection *connection,
int line)
{
if (message)
- _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
+ _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s",
function, line,
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) : "(unset)",
@@ -780,7 +815,7 @@ warn_unexpected_real (DBusConnection *connection,
connection,
expected);
else
- _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
+ _dbus_warn ("%s:%d received no message on %p, expecting %s",
function, line, connection, expected);
}
@@ -840,7 +875,7 @@ check_service_owner_changed_foreach (DBusConnection *connection,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a message on %p, expecting %s\n",
+ _dbus_warn ("Did not receive a message on %p, expecting %s",
connection, "NameOwnerChanged");
goto out;
}
@@ -876,7 +911,7 @@ check_service_owner_changed_foreach (DBusConnection *connection,
}
else
{
- _dbus_warn ("Did not get the expected arguments\n");
+ _dbus_warn ("Did not get the expected arguments");
goto out;
}
}
@@ -885,13 +920,13 @@ check_service_owner_changed_foreach (DBusConnection *connection,
|| (d->expected_kind == OWNER_CHANGED && (!old_owner[0] || !new_owner[0]))
|| (d->expected_kind == SERVICE_DELETED && (!old_owner[0] || new_owner[0])))
{
- _dbus_warn ("inconsistent NameOwnerChanged arguments\n");
+ _dbus_warn ("inconsistent NameOwnerChanged arguments");
goto out;
}
if (strcmp (service_name, d->expected_service_name) != 0)
{
- _dbus_warn ("expected info on service %s, got info on %s\n",
+ _dbus_warn ("expected info on service %s, got info on %s",
d->expected_service_name,
service_name);
goto out;
@@ -900,7 +935,7 @@ check_service_owner_changed_foreach (DBusConnection *connection,
if (*service_name == ':' && new_owner[0]
&& strcmp (service_name, new_owner) != 0)
{
- _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
+ _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])",
service_name, old_owner, new_owner);
goto out;
}
@@ -1112,7 +1147,7 @@ check_hello_message (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Hello", serial, connection);
goto out;
}
@@ -1121,7 +1156,7 @@ check_hello_message (BusContext *context,
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -1171,7 +1206,7 @@ check_hello_message (BusContext *context,
else
{
_dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected single string argument to hello\n");
+ _dbus_warn ("Did not get the expected single string argument to hello");
goto out;
}
}
@@ -1203,7 +1238,7 @@ check_hello_message (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Expecting %s, got nothing\n",
+ _dbus_warn ("Expecting %s, got nothing",
"NameAcquired");
goto out;
}
@@ -1211,7 +1246,7 @@ check_hello_message (BusContext *context,
if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
"NameAcquired"))
{
- _dbus_warn ("Expecting %s, got smthg else\n",
+ _dbus_warn ("Expecting %s, got smthg else",
"NameAcquired");
goto out;
}
@@ -1231,7 +1266,7 @@ check_hello_message (BusContext *context,
else
{
_dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
+ _dbus_warn ("Did not get the expected single string argument to ServiceAcquired");
goto out;
}
}
@@ -1240,7 +1275,7 @@ check_hello_message (BusContext *context,
if (strcmp (acquired, name) != 0)
{
- _dbus_warn ("Acquired name is %s but expected %s\n",
+ _dbus_warn ("Acquired name is %s but expected %s",
acquired, name);
goto out;
}
@@ -1323,7 +1358,7 @@ check_double_hello_message (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Hello", serial, connection);
goto out;
}
@@ -1332,7 +1367,7 @@ check_double_hello_message (BusContext *context,
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -1425,7 +1460,7 @@ check_get_connection_unix_user (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"GetConnectionUnixUser", serial, connection);
goto out;
}
@@ -1481,7 +1516,7 @@ check_get_connection_unix_user (BusContext *context,
else
{
_dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
+ _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser");
goto out;
}
}
@@ -1570,7 +1605,7 @@ check_get_connection_unix_process_id (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"GetConnectionUnixProcessID", serial, connection);
goto out;
}
@@ -1644,7 +1679,7 @@ check_get_connection_unix_process_id (BusContext *context,
else
{
_dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
+ _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID");
goto out;
}
}
@@ -1660,7 +1695,7 @@ check_get_connection_unix_process_id (BusContext *context,
if (pid != (dbus_uint32_t) _dbus_getpid ())
{
_dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
+ _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid");
goto out;
}
}
@@ -1755,7 +1790,7 @@ check_add_match (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"AddMatch", serial, connection);
goto out;
}
@@ -1764,7 +1799,7 @@ check_add_match (BusContext *context,
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -1880,7 +1915,7 @@ check_get_all_match_rules (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"AddMatch", serial, connection);
goto out;
}
@@ -1889,7 +1924,7 @@ check_get_all_match_rules (BusContext *context,
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -2047,7 +2082,7 @@ check_nonexistent_service_no_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"StartServiceByName", serial, connection);
goto out;
}
@@ -2058,7 +2093,7 @@ check_nonexistent_service_no_auto_start (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -2082,7 +2117,7 @@ check_nonexistent_service_no_auto_start (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully activate %s\n",
+ _dbus_warn ("Did not expect to successfully activate %s",
NONEXISTENT_SERVICE_NAME);
goto out;
}
@@ -2140,7 +2175,7 @@ check_nonexistent_service_auto_start (BusContext *context,
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -2151,7 +2186,7 @@ check_nonexistent_service_auto_start (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -2175,7 +2210,7 @@ check_nonexistent_service_auto_start (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully activate %s\n",
+ _dbus_warn ("Did not expect to successfully activate %s",
NONEXISTENT_SERVICE_NAME);
goto out;
}
@@ -2235,7 +2270,7 @@ check_base_service_activated (BusContext *context,
}
else
{
- _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ _dbus_warn ("Message %s doesn't have a service name: %s",
"NameOwnerChanged (creation)",
error.message);
goto out;
@@ -2244,21 +2279,21 @@ check_base_service_activated (BusContext *context,
if (*base_service != ':')
{
- _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
+ _dbus_warn ("Expected base service activation, got \"%s\" instead",
base_service);
goto out;
}
if (strcmp (base_service, base_service_from_bus) != 0)
{
- _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
+ _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"",
base_service, base_service_from_bus);
goto out;
}
if (old_owner[0])
{
- _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n",
+ _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"",
old_owner);
goto out;
}
@@ -2340,7 +2375,7 @@ check_service_activated (BusContext *context,
}
else
{
- _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ _dbus_warn ("Message %s doesn't have a service name: %s",
"NameOwnerChanged (creation)",
error.message);
goto out;
@@ -2349,21 +2384,21 @@ check_service_activated (BusContext *context,
if (strcmp (service_name, activated_name) != 0)
{
- _dbus_warn ("Expected to see service %s created, saw %s instead\n",
+ _dbus_warn ("Expected to see service %s created, saw %s instead",
activated_name, service_name);
goto out;
}
if (strcmp (base_service_name, base_service_from_bus) != 0)
{
- _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead\n",
+ _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead",
base_service_from_bus, base_service_name);
goto out;
}
if (old_owner[0])
{
- _dbus_warn ("expected a %s, got a %s\n",
+ _dbus_warn ("expected a %s, got a %s",
"NameOwnerChanged (creation)",
"NameOwnerChanged (change)");
goto out;
@@ -2389,7 +2424,7 @@ check_service_activated (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Expected a reply to %s, got nothing\n",
+ _dbus_warn ("Expected a reply to %s, got nothing",
"StartServiceByName");
goto out;
}
@@ -2415,7 +2450,7 @@ check_service_activated (BusContext *context,
{
if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
{
- _dbus_warn ("Did not have activation result first argument to %s: %s\n",
+ _dbus_warn ("Did not have activation result first argument to %s: %s",
"StartServiceByName", error.message);
goto out;
}
@@ -2430,7 +2465,7 @@ check_service_activated (BusContext *context,
; /* Good also */
else
{
- _dbus_warn ("Activation result was %u, no good.\n",
+ _dbus_warn ("Activation result was %u, no good.",
activation_result);
goto out;
}
@@ -2441,7 +2476,7 @@ check_service_activated (BusContext *context,
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after verifying existent activation results\n");
+ _dbus_warn ("Messages were left over after verifying existent activation results");
goto out;
}
@@ -2493,7 +2528,7 @@ check_service_auto_activated (BusContext *context,
}
else
{
- _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ _dbus_warn ("Message %s doesn't have a service name: %s",
"NameOwnerChanged",
error.message);
dbus_error_free (&error);
@@ -2503,7 +2538,7 @@ check_service_auto_activated (BusContext *context,
if (strcmp (service_name, activated_name) != 0)
{
- _dbus_warn ("Expected to see service %s created, saw %s instead\n",
+ _dbus_warn ("Expected to see service %s created, saw %s instead",
activated_name, service_name);
goto out;
}
@@ -2725,7 +2760,7 @@ check_send_exit_to_service (BusContext *context,
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after %s\n",
+ _dbus_warn ("Messages were left over after %s",
_DBUS_FUNCTION_NAME);
goto out;
}
@@ -2757,7 +2792,7 @@ check_got_error (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not get an expected error\n");
+ _dbus_warn ("Did not get an expected error");
goto out;
}
@@ -2785,7 +2820,7 @@ check_got_error (BusContext *context,
if (!error_found)
{
- _dbus_warn ("Expected error %s or other, got %s instead\n",
+ _dbus_warn ("Expected error %s or other, got %s instead",
first_error_name,
dbus_message_get_error_name (message));
goto out;
@@ -2840,7 +2875,7 @@ check_got_service_info (DBusMessage *message)
}
else
{
- _dbus_warn ("unexpected arguments for NameOwnerChanged message\n");
+ _dbus_warn ("unexpected arguments for NameOwnerChanged message");
message_kind = GOT_SOMETHING_ELSE;
}
}
@@ -2929,7 +2964,7 @@ check_existent_service_no_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+ _dbus_warn ("Did not receive any messages after %s %d on %p",
"StartServiceByName", serial, connection);
goto out;
}
@@ -2941,7 +2976,7 @@ check_existent_service_no_auto_start (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -2963,7 +2998,7 @@ check_existent_service_no_auto_start (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect error %s\n",
+ _dbus_warn ("Did not expect error %s",
dbus_message_get_error_name (message));
goto out;
}
@@ -2985,7 +3020,7 @@ check_existent_service_no_auto_start (BusContext *context,
message = dbus_connection_borrow_message (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after base service creation notification\n");
+ _dbus_warn ("Did not receive any messages after base service creation notification");
goto out;
}
@@ -2997,6 +3032,7 @@ check_existent_service_no_auto_start (BusContext *context,
switch (message_kind)
{
case GOT_SOMETHING_ELSE:
+ default:
_dbus_warn ("Unexpected message after ActivateService "
"(should be an error or a service announcement");
goto out;
@@ -3056,7 +3092,7 @@ check_existent_service_no_auto_start (BusContext *context,
if (message == NULL)
{
_dbus_warn ("Failed to pop message we just put back! "
- "should have been a NameOwnerChanged (creation)\n");
+ "should have been a NameOwnerChanged (creation)");
goto out;
}
@@ -3069,7 +3105,7 @@ check_existent_service_no_auto_start (BusContext *context,
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after successful activation\n");
+ _dbus_warn ("Messages were left over after successful activation");
goto out;
}
@@ -3151,7 +3187,7 @@ check_segfault_service_no_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"StartServiceByName", serial, connection);
goto out;
}
@@ -3162,7 +3198,7 @@ check_segfault_service_no_auto_start (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -3203,7 +3239,7 @@ check_segfault_service_no_auto_start (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully activate segfault service\n");
+ _dbus_warn ("Did not expect to successfully activate segfault service");
goto out;
}
@@ -3260,7 +3296,7 @@ check_segfault_service_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -3271,7 +3307,7 @@ check_segfault_service_auto_start (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -3304,7 +3340,7 @@ check_segfault_service_auto_start (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully activate segfault service\n");
+ _dbus_warn ("Did not expect to successfully activate segfault service");
goto out;
}
@@ -3367,13 +3403,13 @@ check_existent_hello_from_self (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message\n");
+ _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message");
return FALSE;
}
if (dbus_message_get_reply_serial (message) != serial)
{
- _dbus_warn ("Wrong reply serial\n");
+ _dbus_warn ("Wrong reply serial");
dbus_message_unref (message);
return FALSE;
}
@@ -3420,20 +3456,20 @@ check_existent_ping (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Failed to pop message! Should have been reply from Ping message\n");
+ _dbus_warn ("Failed to pop message! Should have been reply from Ping message");
return FALSE;
}
if (dbus_message_get_reply_serial (message) != serial)
{
- _dbus_warn ("Wrong reply serial\n");
+ _dbus_warn ("Wrong reply serial");
dbus_message_unref (message);
return FALSE;
}
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
{
- _dbus_warn ("Unexpected message return during Ping\n");
+ _dbus_warn ("Unexpected message return during Ping");
dbus_message_unref (message);
return FALSE;
}
@@ -3451,10 +3487,21 @@ static dbus_bool_t
check_existent_get_machine_id (BusContext *context,
DBusConnection *connection)
{
+ DBusError error = DBUS_ERROR_INIT;
DBusMessage *message;
dbus_uint32_t serial;
+ DBusGUID uuid;
const char *machine_id;
+ if (!_dbus_read_local_machine_uuid (&uuid, FALSE, &error))
+ {
+ /* Unable to test further: either we ran out of memory, or neither
+ * dbus nor systemd was ever correctly installed on this machine */
+ _dbus_verbose ("Machine UUID not available: %s", error.message);
+ dbus_error_free (&error);
+ return TRUE;
+ }
+
message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
"/org/freedesktop/TestSuite",
"org.freedesktop.DBus.Peer",
@@ -3482,20 +3529,20 @@ check_existent_get_machine_id (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
+ _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message");
return FALSE;
}
if (dbus_message_get_reply_serial (message) != serial)
{
- _dbus_warn ("Wrong reply serial\n");
+ _dbus_warn ("Wrong reply serial");
dbus_message_unref (message);
return FALSE;
}
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
{
- _dbus_warn ("Unexpected message return during GetMachineId\n");
+ _dbus_warn ("Unexpected message return during GetMachineId");
dbus_message_unref (message);
return FALSE;
}
@@ -3503,14 +3550,14 @@ check_existent_get_machine_id (BusContext *context,
machine_id = NULL;
if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
{
- _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
+ _dbus_warn ("Did not get a machine ID in reply to GetMachineId");
dbus_message_unref (message);
return FALSE;
}
if (machine_id == NULL || strlen (machine_id) != 32)
{
- _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
+ _dbus_warn ("Machine id looks bogus: '%s'", machine_id ? machine_id : "null");
dbus_message_unref (message);
return FALSE;
}
@@ -3586,7 +3633,7 @@ check_existent_service_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
+ _dbus_warn ("Did not receive any messages after auto start %d on %p",
serial, connection);
goto out;
}
@@ -3616,7 +3663,7 @@ check_existent_service_auto_start (BusContext *context,
if (message == NULL)
{
_dbus_warn ("No message after auto activation "
- "(should be a service announcement)\n");
+ "(should be a service announcement)");
dbus_connection_return_message (connection, message);
message = NULL;
goto out;
@@ -3634,7 +3681,7 @@ check_existent_service_auto_start (BusContext *context,
if (message == NULL)
{
_dbus_warn ("Failed to pop message we just put back! "
- "should have been a NameOwnerChanged (creation)\n");
+ "should have been a NameOwnerChanged (creation)");
goto out;
}
@@ -3672,7 +3719,8 @@ check_existent_service_auto_start (BusContext *context,
case GOT_ERROR:
case GOT_SOMETHING_ELSE:
- _dbus_warn ("Unexpected message after auto activation\n");
+ default:
+ _dbus_warn ("Unexpected message after auto activation");
goto out;
}
}
@@ -3689,13 +3737,13 @@ check_existent_service_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+ _dbus_warn ("Failed to pop message! Should have been reply from echo message");
goto out;
}
if (dbus_message_get_reply_serial (message) != serial)
{
- _dbus_warn ("Wrong reply serial\n");
+ _dbus_warn ("Wrong reply serial");
goto out;
}
@@ -3773,7 +3821,7 @@ check_launch_service_file_missing (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -3784,7 +3832,7 @@ check_launch_service_file_missing (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -3810,7 +3858,7 @@ check_launch_service_file_missing (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ _dbus_warn ("Did not expect to successfully auto-start missing service");
goto out;
}
@@ -3823,6 +3871,8 @@ check_launch_service_file_missing (BusContext *context,
return retval;
}
+#ifndef DBUS_WIN
+
#define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser"
/* returns TRUE if the correct thing happens,
@@ -3860,7 +3910,7 @@ check_launch_service_user_missing (BusContext *context,
if (!dbus_connection_get_is_connected (connection))
{
- _dbus_warn ("connection was disconnected\n");
+ _dbus_warn ("connection was disconnected");
return TRUE;
}
@@ -3869,7 +3919,7 @@ check_launch_service_user_missing (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -3880,7 +3930,7 @@ check_launch_service_user_missing (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -3906,7 +3956,7 @@ check_launch_service_user_missing (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ _dbus_warn ("Did not expect to successfully auto-start missing service");
goto out;
}
@@ -3956,7 +4006,7 @@ check_launch_service_exec_missing (BusContext *context,
if (!dbus_connection_get_is_connected (connection))
{
- _dbus_warn ("connection was disconnected\n");
+ _dbus_warn ("connection was disconnected");
return TRUE;
}
@@ -3965,7 +4015,7 @@ check_launch_service_exec_missing (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -3976,7 +4026,7 @@ check_launch_service_exec_missing (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -4010,7 +4060,7 @@ check_launch_service_exec_missing (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ _dbus_warn ("Did not expect to successfully auto-start missing service");
goto out;
}
@@ -4060,7 +4110,7 @@ check_launch_service_service_missing (BusContext *context,
if (!dbus_connection_get_is_connected (connection))
{
- _dbus_warn ("connection was disconnected\n");
+ _dbus_warn ("connection was disconnected");
return TRUE;
}
@@ -4069,7 +4119,7 @@ check_launch_service_service_missing (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -4080,7 +4130,7 @@ check_launch_service_service_missing (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -4114,7 +4164,7 @@ check_launch_service_service_missing (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+ _dbus_warn ("Did not expect to successfully auto-start missing service");
goto out;
}
@@ -4126,6 +4176,7 @@ check_launch_service_service_missing (BusContext *context,
return retval;
}
+#endif
#define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
@@ -4172,7 +4223,7 @@ check_shell_fail_service_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
"Echo message (auto activation)", serial, connection);
goto out;
}
@@ -4183,7 +4234,7 @@ check_shell_fail_service_auto_start (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -4209,7 +4260,7 @@ check_shell_fail_service_auto_start (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect to successfully auto-start shell fail service\n");
+ _dbus_warn ("Did not expect to successfully auto-start shell fail service");
goto out;
}
@@ -4276,7 +4327,7 @@ check_shell_service_success_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
+ _dbus_warn ("Did not receive any messages after auto start %d on %p",
serial, connection);
goto out;
}
@@ -4306,7 +4357,7 @@ check_shell_service_success_auto_start (BusContext *context,
if (message == NULL)
{
_dbus_warn ("No message after auto activation "
- "(should be a service announcement)\n");
+ "(should be a service announcement)");
dbus_connection_return_message (connection, message);
message = NULL;
goto out;
@@ -4324,7 +4375,7 @@ check_shell_service_success_auto_start (BusContext *context,
if (message == NULL)
{
_dbus_warn ("Failed to pop message we just put back! "
- "should have been a NameOwnerChanged (creation)\n");
+ "should have been a NameOwnerChanged (creation)");
goto out;
}
@@ -4362,7 +4413,8 @@ check_shell_service_success_auto_start (BusContext *context,
case GOT_ERROR:
case GOT_SOMETHING_ELSE:
- _dbus_warn ("Unexpected message after auto activation\n");
+ default:
+ _dbus_warn ("Unexpected message after auto activation");
goto out;
}
}
@@ -4379,13 +4431,13 @@ check_shell_service_success_auto_start (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+ _dbus_warn ("Failed to pop message! Should have been reply from echo message");
goto out;
}
if (dbus_message_get_reply_serial (message) != serial)
{
- _dbus_warn ("Wrong reply serial\n");
+ _dbus_warn ("Wrong reply serial");
goto out;
}
@@ -4399,7 +4451,7 @@ check_shell_service_success_auto_start (BusContext *context,
DBUS_TYPE_STRING, &argv[6],
DBUS_TYPE_INVALID))
{
- _dbus_warn ("Error getting arguments from return\n");
+ _dbus_warn ("Error getting arguments from return");
goto out;
}
@@ -4408,42 +4460,42 @@ check_shell_service_success_auto_start (BusContext *context,
*/
if (strcmp("-test", argv[1]) != 0)
{
- _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n",
+ _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)",
"-test", argv[1]);
goto out;
}
if (strcmp("that", argv[2]) != 0)
{
- _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)\n",
+ _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)",
"that", argv[2]);
goto out;
}
if (strcmp("we get", argv[3]) != 0)
{
- _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n",
+ _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)",
"we get", argv[3]);
goto out;
}
if (strcmp("back", argv[4]) != 0)
{
- _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n",
+ _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)",
"back", argv[4]);
goto out;
}
if (strcmp("--what", argv[5]) != 0)
{
- _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n",
+ _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)",
"--what", argv[5]);
goto out;
}
if (strcmp("we put in", argv[6]) != 0)
{
- _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n",
+ _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)",
"we put in", argv[6]);
goto out;
}
@@ -4484,7 +4536,7 @@ check_oom_check1_func (void *data)
if (!check_no_leftovers (d->context))
{
- _dbus_warn ("Messages were left over, should be covered by test suite\n");
+ _dbus_warn ("Messages were left over, should be covered by test suite");
return FALSE;
}
@@ -4561,7 +4613,7 @@ check_get_services (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ _dbus_warn ("Did not receive a reply to %s %d on %p",
method, serial, connection);
goto out;
}
@@ -4613,7 +4665,7 @@ check_get_services (BusContext *context,
else
{
_dbus_assert (dbus_error_is_set (&error));
- _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method);
+ _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s", method);
goto out;
}
} else {
@@ -4662,7 +4714,7 @@ check_list_services (BusContext *context,
if (!_dbus_string_array_contains ((const char **)services, existent))
{
- _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent);
+ _dbus_warn ("Did not get the expected %s from ListActivatableNames", existent);
dbus_free_string_array (services);
return FALSE;
}
@@ -4720,7 +4772,7 @@ check_list_services (BusContext *context,
message = pop_message_waiting_for_memory (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+ _dbus_warn ("Did not receive any messages after %s %d on %p",
"StartServiceByName", serial, connection);
goto out;
}
@@ -4732,7 +4784,7 @@ check_list_services (BusContext *context,
{
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
- _dbus_warn ("Message has wrong sender %s\n",
+ _dbus_warn ("Message has wrong sender %s",
dbus_message_get_sender (message) ?
dbus_message_get_sender (message) : "(none)");
goto out;
@@ -4754,7 +4806,7 @@ check_list_services (BusContext *context,
}
else
{
- _dbus_warn ("Did not expect error %s\n",
+ _dbus_warn ("Did not expect error %s",
dbus_message_get_error_name (message));
goto out;
}
@@ -4776,7 +4828,7 @@ check_list_services (BusContext *context,
message = dbus_connection_borrow_message (connection);
if (message == NULL)
{
- _dbus_warn ("Did not receive any messages after base service creation notification\n");
+ _dbus_warn ("Did not receive any messages after base service creation notification");
goto out;
}
@@ -4790,8 +4842,9 @@ check_list_services (BusContext *context,
case GOT_SOMETHING_ELSE:
case GOT_ERROR:
case GOT_SERVICE_DELETED:
+ default:
_dbus_warn ("Unexpected message after ActivateService "
- "(should be an error or a service announcement)\n");
+ "(should be an error or a service announcement)");
goto out;
case GOT_SERVICE_CREATED:
@@ -4799,7 +4852,7 @@ check_list_services (BusContext *context,
if (message == NULL)
{
_dbus_warn ("Failed to pop message we just put back! "
- "should have been a NameOwnerChanged (creation)\n");
+ "should have been a NameOwnerChanged (creation)");
goto out;
}
@@ -4812,7 +4865,7 @@ check_list_services (BusContext *context,
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after successful activation\n");
+ _dbus_warn ("Messages were left over after successful activation");
goto out;
}
@@ -4827,7 +4880,7 @@ check_list_services (BusContext *context,
if (!_dbus_string_array_contains ((const char **)services, existent))
{
- _dbus_warn ("Did not get the expected %s from ListNames\n", existent);
+ _dbus_warn ("Did not get the expected %s from ListNames", existent);
goto out;
}
@@ -4866,7 +4919,7 @@ check_oom_check2_func (void *data)
if (!check_no_leftovers (d->context))
{
- _dbus_warn ("Messages were left over, should be covered by test suite\n");
+ _dbus_warn ("Messages were left over, should be covered by test suite");
return FALSE;
}
@@ -4888,7 +4941,7 @@ check2_try_iterations (BusContext *context,
if (!_dbus_test_oom_handling (description, check_oom_check2_func,
&d))
{
- _dbus_warn ("%s failed during oom\n", description);
+ _dbus_warn ("%s failed during oom", description);
_dbus_assert_not_reached ("test failed");
}
}
@@ -5019,7 +5072,7 @@ bus_dispatch_test_conf (const DBusString *test_data_dir,
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after setting up initial connections\n");
+ _dbus_warn ("Messages were left over after setting up initial connections");
_dbus_assert_not_reached ("initial connection setup failed");
}
@@ -5077,6 +5130,7 @@ bus_dispatch_test_conf (const DBusString *test_data_dir,
return TRUE;
}
+#ifndef DBUS_WIN
static dbus_bool_t
bus_dispatch_test_conf_fail (const DBusString *test_data_dir,
const char *filename)
@@ -5133,6 +5187,7 @@ bus_dispatch_test_conf_fail (const DBusString *test_data_dir,
return TRUE;
}
+#endif
typedef struct {
DBusTimeout *timeout;
@@ -5316,7 +5371,7 @@ bus_dispatch_sha1_test (const DBusString *test_data_dir)
if (!check_no_leftovers (context))
{
- _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
+ _dbus_warn ("Messages were left over after setting up initial SHA-1 connection");
_dbus_assert_not_reached ("initial connection setup failed");
}
diff --git a/bus/driver.c b/bus/driver.c
index d5c662cb..c468fe58 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -43,13 +43,6 @@
#include <dbus/dbus-marshal-validate.h>
#include <string.h>
-typedef enum
-{
- BUS_DRIVER_FOUND_SELF,
- BUS_DRIVER_FOUND_PEER,
- BUS_DRIVER_FOUND_ERROR,
-} BusDriverFound;
-
static inline const char *
nonnull (const char *maybe_null,
const char *if_null)
@@ -75,7 +68,7 @@ bus_driver_get_owner_of_name (DBusConnection *connection,
return bus_service_get_primary_owners_connection (serv);
}
-static BusDriverFound
+BusDriverFound
bus_driver_get_conn_helper (DBusConnection *connection,
DBusMessage *message,
const char *what_we_want,
@@ -257,7 +250,7 @@ bus_driver_send_service_owner_changed (const char *service_name,
_dbus_assert (dbus_message_has_signature (message, "sss"));
- if (!bus_transaction_capture (transaction, NULL, message))
+ if (!bus_transaction_capture (transaction, NULL, NULL, message))
goto oom;
switch (bus_dispatch_matches (transaction, NULL, NULL, message, NULL, error))
@@ -441,6 +434,9 @@ bus_driver_handle_hello (DBusConnection *connection,
BusResult retval;
BusRegistry *registry;
BusConnections *connections;
+ DBusError tmp_error;
+ int limit;
+ const char *limit_name;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -458,11 +454,19 @@ bus_driver_handle_hello (DBusConnection *connection,
* incomplete connections. It's even OK if the connection wants to
* retry the hello message, we support that.
*/
+ dbus_error_init (&tmp_error);
connections = bus_connection_get_connections (connection);
if (!bus_connections_check_limits (connections, connection,
- error))
+ &limit_name, &limit,
+ &tmp_error))
{
- _DBUS_ASSERT_ERROR_IS_SET (error);
+ BusContext *context;
+
+ _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+ context = bus_connection_get_context (connection);
+ bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, "%s (%s=%d)",
+ tmp_error.message, limit_name, limit);
+ dbus_move_error (&tmp_error, error);
return BUS_RESULT_FALSE;
}
@@ -983,11 +987,11 @@ bus_driver_handle_activate_service (DBusConnection *connection,
return retval;
}
-static dbus_bool_t
-send_ack_reply (DBusConnection *connection,
- BusTransaction *transaction,
- DBusMessage *message,
- DBusError *error)
+dbus_bool_t
+bus_driver_send_ack_reply (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
{
DBusMessage *reply;
@@ -1047,7 +1051,7 @@ bus_driver_send_or_activate (BusTransaction *transaction,
activation = bus_context_get_activation (context);
- if (!bus_transaction_capture (transaction, NULL, message))
+ if (!bus_transaction_capture (transaction, NULL, NULL, message))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory for bus_transaction_capture()");
@@ -1100,21 +1104,6 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!bus_driver_check_message_is_for_us (message, error))
- return FALSE;
-
-#ifdef DBUS_UNIX
- {
- /* UpdateActivationEnvironment is basically a recipe for privilege
- * escalation so let's be extra-careful: do not allow the sysadmin
- * to shoot themselves in the foot.
- */
- if (!bus_driver_check_caller_is_privileged (connection, transaction,
- message, error))
- return FALSE;
- }
-#endif
-
context = bus_connection_get_context (connection);
if (bus_context_get_servicehelper (context) != NULL)
@@ -1298,8 +1287,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
}
}
- if (!send_ack_reply (connection, transaction,
- message, error))
+ if (!bus_driver_send_ack_reply (connection, transaction, message, error))
goto out;
retval = BUS_RESULT_TRUE;
@@ -1322,6 +1310,7 @@ bus_driver_handle_add_match (DBusConnection *connection,
const char *text, *bustype;
DBusString str;
BusMatchmaker *matchmaker;
+ int limit;
BusContext *context;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1329,15 +1318,25 @@ bus_driver_handle_add_match (DBusConnection *connection,
text = NULL;
rule = NULL;
- if (bus_connection_get_n_match_rules (connection) >=
- bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
+ context = bus_transaction_get_context (transaction);
+ limit = bus_context_get_max_match_rules_per_connection (context);
+
+ if (bus_connection_get_n_match_rules (connection) >= limit)
{
- dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+ DBusError tmp_error;
+
+ dbus_error_init (&tmp_error);
+ dbus_set_error (&tmp_error, DBUS_ERROR_LIMITS_EXCEEDED,
"Connection \"%s\" is not allowed to add more match rules "
- "(increase limits in configuration file if required)",
+ "(increase limits in configuration file if required; "
+ "max_match_rules_per_connection=%d)",
bus_connection_is_active (connection) ?
bus_connection_get_name (connection) :
- "(inactive)");
+ "(inactive)",
+ limit);
+ bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, "%s",
+ tmp_error.message);
+ dbus_move_error (&tmp_error, error);
goto failed;
}
@@ -1355,11 +1354,17 @@ bus_driver_handle_add_match (DBusConnection *connection,
if (rule == NULL)
goto failed;
- context = bus_transaction_get_context (transaction);
- bustype = context ? bus_context_get_type (context) : NULL;
- if (bus_match_rule_get_client_is_eavesdropping (rule) &&
- !bus_apparmor_allows_eavesdropping (connection, bustype, error))
- goto failed;
+ bustype = bus_context_get_type (context);
+
+ if (bus_match_rule_get_client_is_eavesdropping (rule))
+ {
+ if (!bus_driver_check_caller_is_privileged (connection,
+ transaction,
+ message,
+ error) ||
+ !bus_apparmor_allows_eavesdropping (connection, bustype, error))
+ goto failed;
+ }
matchmaker = bus_connection_get_matchmaker (connection);
@@ -1369,8 +1374,7 @@ bus_driver_handle_add_match (DBusConnection *connection,
goto failed;
}
- if (!send_ack_reply (connection, transaction,
- message, error))
+ if (!bus_driver_send_ack_reply (connection, transaction, message, error))
{
bus_matchmaker_remove_rule (matchmaker, rule);
goto failed;
@@ -1420,8 +1424,7 @@ bus_driver_handle_remove_match (DBusConnection *connection,
/* Send the ack before we remove the rule, since the ack is undone
* on transaction cancel, but rule removal isn't.
*/
- if (!send_ack_reply (connection, transaction,
- message, error))
+ if (!bus_driver_send_ack_reply (connection, transaction, message, error))
goto failed;
matchmaker = bus_connection_get_matchmaker (connection);
@@ -1528,6 +1531,8 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
DBusMessage *message,
DBusError *error)
{
+ static const char dbus_service_name[] = DBUS_SERVICE_DBUS;
+
const char *text;
DBusList *base_names;
DBusList *link;
@@ -1536,7 +1541,6 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
BusService *service;
DBusMessage *reply;
DBusMessageIter iter, array_iter;
- char *dbus_service_name = DBUS_SERVICE_DBUS;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1557,7 +1561,7 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection,
_dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
{
/* ORG_FREEDESKTOP_DBUS owns itself */
- if (! _dbus_list_append (&base_names, dbus_service_name))
+ if (! _dbus_list_append (&base_names, (char *) dbus_service_name))
goto oom;
}
else if (service == NULL)
@@ -1658,6 +1662,8 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
uid = DBUS_UID_UNSET;
break;
case BUS_DRIVER_FOUND_ERROR:
+ /* fall through */
+ default:
goto failed;
}
@@ -1725,6 +1731,8 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
pid = DBUS_PID_UNSET;
break;
case BUS_DRIVER_FOUND_ERROR:
+ /* fall through */
+ default:
goto failed;
}
@@ -1772,7 +1780,7 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
DBusConnection *conn;
DBusMessage *reply;
void *data = NULL;
- dbus_uint32_t data_size;
+ dbus_int32_t data_size;
const char *service;
BusDriverFound found;
@@ -1852,8 +1860,9 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne
if (reply == NULL)
goto oom;
- /* FIXME: Obtain the SELinux security context for the bus daemon itself */
- if (found == BUS_DRIVER_FOUND_PEER)
+ if (found == BUS_DRIVER_FOUND_SELF)
+ context = bus_selinux_get_self ();
+ else if (found == BUS_DRIVER_FOUND_PEER)
context = bus_connection_get_selinux_id (conn);
else
context = NULL;
@@ -1922,6 +1931,8 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
ulong_uid = DBUS_UID_UNSET;
break;
case BUS_DRIVER_FOUND_ERROR:
+ /* fall through */
+ default:
goto failed;
}
@@ -2193,18 +2204,11 @@ bus_driver_handle_become_monitor (DBusConnection *connection,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!bus_driver_check_message_is_for_us (message, error))
- goto out;
-
context = bus_transaction_get_context (transaction);
bustype = context ? bus_context_get_type (context) : NULL;
if (!bus_apparmor_allows_eavesdropping (connection, bustype, error))
goto out;
- if (!bus_driver_check_caller_is_privileged (connection, transaction,
- message, error))
- goto out;
-
if (!dbus_message_get_args (message, error,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &match_rules, &n_match_rules,
DBUS_TYPE_UINT32, &flags,
@@ -2263,7 +2267,7 @@ bus_driver_handle_become_monitor (DBusConnection *connection,
/* Send the ack before we remove the rule, since the ack is undone
* on transaction cancel, but becoming a monitor isn't.
*/
- if (!send_ack_reply (connection, transaction, message, error))
+ if (!bus_driver_send_ack_reply (connection, transaction, message, error))
goto out;
if (!bus_connection_be_monitor (connection, transaction, &rules, error))
@@ -2288,6 +2292,109 @@ out:
return ret;
}
+static dbus_bool_t
+bus_driver_handle_get_machine_id (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ DBusMessage *reply = NULL;
+ DBusString uuid;
+ const char *str;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ if (!_dbus_string_init (&uuid))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
+ goto fail;
+
+ reply = dbus_message_new_method_return (message);
+
+ if (reply == NULL)
+ goto oom;
+
+ str = _dbus_string_get_const_data (&uuid);
+
+ if (!dbus_message_append_args (reply,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID))
+ goto oom;
+
+ _dbus_assert (dbus_message_has_signature (reply, "s"));
+
+ if (!bus_transaction_send_from_driver (transaction, connection, reply))
+ goto oom;
+
+ _dbus_string_free (&uuid);
+ dbus_message_unref (reply);
+ return TRUE;
+
+oom:
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ BUS_SET_OOM (error);
+
+fail:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ _dbus_string_free (&uuid);
+ return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_ping (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ return bus_driver_send_ack_reply (connection, transaction, message, error);
+}
+
+static dbus_bool_t bus_driver_handle_get (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+
+static dbus_bool_t bus_driver_handle_get_all (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+
+static dbus_bool_t bus_driver_handle_set (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+
+static dbus_bool_t features_getter (BusContext *context,
+ DBusMessageIter *variant_iter);
+static dbus_bool_t interfaces_getter (BusContext *context,
+ DBusMessageIter *variant_iter);
+
+typedef enum
+{
+ /* Various older methods were available at every object path. We have to
+ * preserve that behaviour for backwards compatibility, but we can at least
+ * stop doing that for newly added methods.
+ * The special Peer interface should also work at any object path.
+ * <https://bugs.freedesktop.org/show_bug.cgi?id=101256> */
+ METHOD_FLAG_ANY_PATH = (1 << 0),
+
+ /* If set, callers must be privileged. On Unix, the uid of the connection
+ * must either be the uid of this process, or 0 (root). On Windows,
+ * the SID of the connection must be the SID of this process. */
+ METHOD_FLAG_PRIVILEGED = (1 << 1),
+
+ METHOD_FLAG_NONE = 0
+} MethodFlags;
+
typedef struct
{
const char *name;
@@ -2297,8 +2404,17 @@ typedef struct
BusTransaction *transaction,
DBusMessage *message,
DBusError *error);
+ MethodFlags flags;
} MessageHandler;
+typedef struct
+{
+ const char *name;
+ const char *type;
+ dbus_bool_t (* getter) (BusContext *context,
+ DBusMessageIter *variant_iter);
+} PropertyHandler;
+
/* For speed it might be useful to sort this in order of
* frequency of use (but doesn't matter with only a few items
* anyhow)
@@ -2307,114 +2423,178 @@ static const MessageHandler dbus_message_handlers[] = {
{ "Hello",
"",
DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_hello },
+ bus_driver_handle_hello,
+ METHOD_FLAG_ANY_PATH },
{ "RequestName",
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
- bus_driver_handle_acquire_service },
+ bus_driver_handle_acquire_service,
+ METHOD_FLAG_ANY_PATH },
{ "ReleaseName",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
- bus_driver_handle_release_service },
+ bus_driver_handle_release_service,
+ METHOD_FLAG_ANY_PATH },
{ "StartServiceByName",
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
- bus_driver_handle_activate_service },
+ bus_driver_handle_activate_service,
+ METHOD_FLAG_ANY_PATH },
{ "UpdateActivationEnvironment",
DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
"",
- bus_driver_handle_update_activation_environment },
+ bus_driver_handle_update_activation_environment,
+ METHOD_FLAG_PRIVILEGED },
{ "NameHasOwner",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_BOOLEAN_AS_STRING,
- bus_driver_handle_service_exists },
+ bus_driver_handle_service_exists,
+ METHOD_FLAG_ANY_PATH },
{ "ListNames",
"",
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_list_services },
+ bus_driver_handle_list_services,
+ METHOD_FLAG_ANY_PATH },
{ "ListActivatableNames",
"",
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_list_activatable_services },
+ bus_driver_handle_list_activatable_services,
+ METHOD_FLAG_ANY_PATH },
{ "AddMatch",
DBUS_TYPE_STRING_AS_STRING,
"",
- bus_driver_handle_add_match },
+ bus_driver_handle_add_match,
+ METHOD_FLAG_ANY_PATH },
{ "RemoveMatch",
DBUS_TYPE_STRING_AS_STRING,
"",
- bus_driver_handle_remove_match },
+ bus_driver_handle_remove_match,
+ METHOD_FLAG_ANY_PATH },
{ "GetNameOwner",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_get_service_owner },
+ bus_driver_handle_get_service_owner,
+ METHOD_FLAG_ANY_PATH },
{ "ListQueuedOwners",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_list_queued_owners },
+ bus_driver_handle_list_queued_owners,
+ METHOD_FLAG_ANY_PATH },
{ "GetConnectionUnixUser",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
- bus_driver_handle_get_connection_unix_user },
+ bus_driver_handle_get_connection_unix_user,
+ METHOD_FLAG_ANY_PATH },
{ "GetConnectionUnixProcessID",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
- bus_driver_handle_get_connection_unix_process_id },
+ bus_driver_handle_get_connection_unix_process_id,
+ METHOD_FLAG_ANY_PATH },
{ "GetAdtAuditSessionData",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
- bus_driver_handle_get_adt_audit_session_data },
+ bus_driver_handle_get_adt_audit_session_data,
+ METHOD_FLAG_ANY_PATH },
{ "GetConnectionSELinuxSecurityContext",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
- bus_driver_handle_get_connection_selinux_security_context },
+ bus_driver_handle_get_connection_selinux_security_context,
+ METHOD_FLAG_ANY_PATH },
{ "ReloadConfig",
"",
"",
- bus_driver_handle_reload_config },
+ bus_driver_handle_reload_config,
+ METHOD_FLAG_ANY_PATH },
{ "GetId",
"",
DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_get_id },
+ bus_driver_handle_get_id,
+ METHOD_FLAG_ANY_PATH },
{ "GetConnectionCredentials", "s", "a{sv}",
- bus_driver_handle_get_connection_credentials },
+ bus_driver_handle_get_connection_credentials,
+ METHOD_FLAG_ANY_PATH },
{ NULL, NULL, NULL, NULL }
};
+static const PropertyHandler dbus_property_handlers[] = {
+ { "Features", "as", features_getter },
+ { "Interfaces", "as", interfaces_getter },
+ { NULL, NULL, NULL }
+};
+
static BusResult bus_driver_handle_introspect (DBusConnection *,
BusTransaction *, DBusMessage *, DBusError *);
+static const MessageHandler properties_message_handlers[] = {
+ { "Get", "ss", "v", bus_driver_handle_get, METHOD_FLAG_NONE },
+ { "GetAll", "s", "a{sv}", bus_driver_handle_get_all, METHOD_FLAG_NONE },
+ { "Set", "ssv", "", bus_driver_handle_set, METHOD_FLAG_NONE },
+ { NULL, NULL, NULL, NULL }
+};
+
static const MessageHandler introspectable_message_handlers[] = {
- { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
+ { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect,
+ METHOD_FLAG_ANY_PATH },
{ NULL, NULL, NULL, NULL }
};
static const MessageHandler monitoring_message_handlers[] = {
- { "BecomeMonitor", "asu", "", bus_driver_handle_become_monitor },
+ { "BecomeMonitor", "asu", "", bus_driver_handle_become_monitor,
+ METHOD_FLAG_PRIVILEGED },
{ NULL, NULL, NULL, NULL }
};
#ifdef DBUS_ENABLE_VERBOSE_MODE
static const MessageHandler verbose_message_handlers[] = {
- { "EnableVerbose", "", "", bus_driver_handle_enable_verbose},
- { "DisableVerbose", "", "", bus_driver_handle_disable_verbose},
+ { "EnableVerbose", "", "", bus_driver_handle_enable_verbose,
+ METHOD_FLAG_NONE },
+ { "DisableVerbose", "", "", bus_driver_handle_disable_verbose,
+ METHOD_FLAG_NONE },
{ NULL, NULL, NULL, NULL }
};
#endif
#ifdef DBUS_ENABLE_STATS
static const MessageHandler stats_message_handlers[] = {
- { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
- { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
- { "GetAllMatchRules", "", "a{sas}", bus_stats_handle_get_all_match_rules },
+ { "GetStats", "", "a{sv}", bus_stats_handle_get_stats,
+ METHOD_FLAG_NONE },
+ { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats,
+ METHOD_FLAG_NONE },
+ { "GetAllMatchRules", "", "a{sas}", bus_stats_handle_get_all_match_rules,
+ METHOD_FLAG_NONE },
{ NULL, NULL, NULL, NULL }
};
#endif
+static const MessageHandler peer_message_handlers[] = {
+ { "GetMachineId", "", "s", bus_driver_handle_get_machine_id,
+ METHOD_FLAG_ANY_PATH },
+ { "Ping", "", "", bus_driver_handle_ping, METHOD_FLAG_ANY_PATH },
+ { NULL, NULL, NULL, NULL }
+};
+
+typedef enum
+{
+ /* Various older interfaces were available at every object path. We have to
+ * preserve that behaviour for backwards compatibility, but we can at least
+ * stop doing that for newly added interfaces:
+ * <https://bugs.freedesktop.org/show_bug.cgi?id=101256>
+ * Introspectable and Peer are also useful at all object paths. */
+ INTERFACE_FLAG_ANY_PATH = (1 << 0),
+
+ /* Set this flag for interfaces that should not show up in the
+ * Interfaces property. */
+ INTERFACE_FLAG_UNINTERESTING = (1 << 1),
+
+ INTERFACE_FLAG_NONE = 0
+} InterfaceFlags;
+
typedef struct {
const char *name;
const MessageHandler *message_handlers;
const char *extra_introspection;
+ InterfaceFlags flags;
+ const PropertyHandler *property_handlers;
} InterfaceHandler;
/* These should ideally be sorted by frequency of use, although it
@@ -2431,15 +2611,42 @@ static InterfaceHandler interface_handlers[] = {
" </signal>\n"
" <signal name=\"NameAcquired\">\n"
" <arg type=\"s\"/>\n"
- " </signal>\n" },
- { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
- { DBUS_INTERFACE_MONITORING, monitoring_message_handlers, NULL },
+ " </signal>\n",
+ /* Not in the Interfaces property because if you can get the properties
+ * of the o.fd.DBus interface, then you certainly have the o.fd.DBus
+ * interface, so there is little point in listing it explicitly.
+ * Partially available at all paths for backwards compatibility. */
+ INTERFACE_FLAG_ANY_PATH | INTERFACE_FLAG_UNINTERESTING,
+ dbus_property_handlers },
+ { DBUS_INTERFACE_PROPERTIES, properties_message_handlers,
+ " <signal name=\"PropertiesChanged\">\n"
+ " <arg type=\"s\" name=\"interface_name\"/>\n"
+ " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"
+ " <arg type=\"as\" name=\"invalidated_properties\"/>\n"
+ " </signal>\n",
+ /* Not in the Interfaces property because if you can get the properties
+ * of the o.fd.DBus interface, then you certainly have Properties. */
+ INTERFACE_FLAG_UNINTERESTING },
+ { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL,
+ /* Not in the Interfaces property because introspection isn't really a
+ * feature in the same way as e.g. Monitoring.
+ * Available at all paths so tools like d-feet can start from "/". */
+ INTERFACE_FLAG_ANY_PATH | INTERFACE_FLAG_UNINTERESTING },
+ { DBUS_INTERFACE_MONITORING, monitoring_message_handlers, NULL,
+ INTERFACE_FLAG_NONE },
#ifdef DBUS_ENABLE_VERBOSE_MODE
- { DBUS_INTERFACE_VERBOSE, verbose_message_handlers, NULL },
+ { DBUS_INTERFACE_VERBOSE, verbose_message_handlers, NULL,
+ INTERFACE_FLAG_NONE },
#endif
#ifdef DBUS_ENABLE_STATS
- { BUS_INTERFACE_STATS, stats_message_handlers, NULL },
+ { BUS_INTERFACE_STATS, stats_message_handlers, NULL,
+ INTERFACE_FLAG_NONE },
#endif
+ { DBUS_INTERFACE_PEER, peer_message_handlers, NULL,
+ /* Not in the Interfaces property because it's a pseudo-interface
+ * on all object paths of all connections, rather than a feature of the
+ * bus driver object. */
+ INTERFACE_FLAG_ANY_PATH | INTERFACE_FLAG_UNINTERESTING },
{ NULL, NULL, NULL }
};
@@ -2479,10 +2686,13 @@ write_args_for_direction (DBusString *xml,
}
dbus_bool_t
-bus_driver_generate_introspect_string (DBusString *xml)
+bus_driver_generate_introspect_string (DBusString *xml,
+ dbus_bool_t is_canonical_path,
+ DBusMessage *message)
{
const InterfaceHandler *ih;
const MessageHandler *mh;
+ const PropertyHandler *ph;
if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
return FALSE;
@@ -2491,6 +2701,9 @@ bus_driver_generate_introspect_string (DBusString *xml)
for (ih = interface_handlers; ih->name != NULL; ih++)
{
+ if (!(is_canonical_path || (ih->flags & INTERFACE_FLAG_ANY_PATH)))
+ continue;
+
if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
ih->name))
return FALSE;
@@ -2511,6 +2724,20 @@ bus_driver_generate_introspect_string (DBusString *xml)
return FALSE;
}
+ for (ph = ih->property_handlers; ph != NULL && ph->name != NULL; ph++)
+ {
+ /* We only have constant properties so far, so hard-code that bit */
+ if (!_dbus_string_append_printf (xml,
+ " <property name=\"%s\" type=\"%s\" access=\"read\">\n",
+ ph->name, ph->type))
+ return FALSE;
+
+ if (!_dbus_string_append (xml,
+ " <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n"
+ " </property>\n"))
+ return FALSE;
+ }
+
if (ih->extra_introspection != NULL &&
!_dbus_string_append (xml, ih->extra_introspection))
return FALSE;
@@ -2519,6 +2746,28 @@ bus_driver_generate_introspect_string (DBusString *xml)
return FALSE;
}
+ if (message != NULL)
+ {
+ /* Make the bus driver object path discoverable */
+ if (dbus_message_has_path (message, "/"))
+ {
+ if (!_dbus_string_append (xml,
+ " <node name=\"org/freedesktop/DBus\"/>\n"))
+ return FALSE;
+ }
+ else if (dbus_message_has_path (message, "/org"))
+ {
+ if (!_dbus_string_append (xml,
+ " <node name=\"freedesktop/DBus\"/>\n"))
+ return FALSE;
+ }
+ else if (dbus_message_has_path (message, "/org/freedesktop"))
+ {
+ if (!_dbus_string_append (xml, " <node name=\"DBus\"/>\n"))
+ return FALSE;
+ }
+ }
+
if (!_dbus_string_append (xml, "</node>\n"))
return FALSE;
@@ -2534,6 +2783,7 @@ bus_driver_handle_introspect (DBusConnection *connection,
DBusString xml;
DBusMessage *reply;
const char *v_STRING;
+ dbus_bool_t is_canonical_path;
_dbus_verbose ("Introspect() on bus driver\n");
@@ -2554,7 +2804,9 @@ bus_driver_handle_introspect (DBusConnection *connection,
return BUS_RESULT_FALSE;
}
- if (!bus_driver_generate_introspect_string (&xml))
+ is_canonical_path = dbus_message_has_path (message, DBUS_PATH_DBUS);
+
+ if (!bus_driver_generate_introspect_string (&xml, is_canonical_path, message))
goto oom;
v_STRING = _dbus_string_get_const_data (&xml);
@@ -2587,38 +2839,6 @@ bus_driver_handle_introspect (DBusConnection *connection,
return BUS_RESULT_FALSE;
}
-/*
- * Set @error and return FALSE if the message is not directed to the
- * dbus-daemon by its canonical object path. This is hardening against
- * system services with poorly-written security policy files, which
- * might allow sending dangerously broad equivalence classes of messages
- * such as "anything with this assumed-to-be-safe object path".
- *
- * dbus-daemon is unusual in that it normally ignores the object path
- * of incoming messages; we need to keep that behaviour for the "read"
- * read-only method calls like GetConnectionUnixUser for backwards
- * compatibility, but it seems safer to be more restrictive for things
- * intended to be root-only or privileged-developers-only.
- *
- * It is possible that there are other system services with the same
- * quirk as dbus-daemon.
- */
-dbus_bool_t
-bus_driver_check_message_is_for_us (DBusMessage *message,
- DBusError *error)
-{
- if (!dbus_message_has_path (message, DBUS_PATH_DBUS))
- {
- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
- "Method '%s' is only available at the canonical object path '%s'",
- dbus_message_get_member (message), DBUS_PATH_DBUS);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
BusResult
bus_driver_handle_message (DBusConnection *connection,
BusTransaction *transaction,
@@ -2629,6 +2849,7 @@ bus_driver_handle_message (DBusConnection *connection,
const InterfaceHandler *ih;
const MessageHandler *mh;
dbus_bool_t found_interface = FALSE;
+ dbus_bool_t is_canonical_path;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -2637,6 +2858,15 @@ bus_driver_handle_message (DBusConnection *connection,
BusContext *context;
DBusConnection *systemd;
+ /* This is a directed signal, not a method call, so the log message
+ * is a little weird (it talks about "calling" ActivationFailure),
+ * but it's close enough */
+ if (!bus_driver_check_caller_is_privileged (connection,
+ transaction,
+ message,
+ error))
+ return BUS_RESULT_FALSE;
+
context = bus_connection_get_context (connection);
systemd = bus_driver_get_owner_of_name (connection,
"org.freedesktop.systemd1");
@@ -2655,6 +2885,14 @@ bus_driver_handle_message (DBusConnection *connection,
return BUS_RESULT_TRUE;
}
+ if (!bus_context_get_systemd_activation (context))
+ {
+ bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
+ "Ignoring unexpected ActivationFailure message "
+ "while not using systemd activation");
+ return BUS_RESULT_FALSE;
+ }
+
return dbus_activation_systemd_failure(bus_context_get_activation(context), message) == TRUE ? BUS_RESULT_TRUE : BUS_RESULT_FALSE;
}
@@ -2677,8 +2915,13 @@ bus_driver_handle_message (DBusConnection *connection,
_dbus_assert (dbus_message_get_sender (message) != NULL ||
strcmp (name, "Hello") == 0);
+ is_canonical_path = dbus_message_has_path (message, DBUS_PATH_DBUS);
+
for (ih = interface_handlers; ih->name != NULL; ih++)
{
+ if (!(is_canonical_path || (ih->flags & INTERFACE_FLAG_ANY_PATH)))
+ continue;
+
if (interface != NULL && strcmp (interface, ih->name) != 0)
continue;
@@ -2691,6 +2934,24 @@ bus_driver_handle_message (DBusConnection *connection,
_dbus_verbose ("Found driver handler for %s\n", name);
+ if ((mh->flags & METHOD_FLAG_PRIVILEGED) &&
+ !bus_driver_check_caller_is_privileged (connection, transaction,
+ message, error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return BUS_RESULT_FALSE;
+ }
+
+ if (!(is_canonical_path || (mh->flags & METHOD_FLAG_ANY_PATH)))
+ {
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+ "Method '%s' is only available at the canonical object path '%s'",
+ dbus_message_get_member (message), DBUS_PATH_DBUS);
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return BUS_RESULT_FALSE;
+ }
+
if (!dbus_message_has_signature (message, mh->in_args))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -2741,3 +3002,298 @@ bus_driver_remove_connection (DBusConnection *connection)
* with the bus driver.
*/
}
+
+static dbus_bool_t
+features_getter (BusContext *context,
+ DBusMessageIter *variant_iter)
+{
+ DBusMessageIter arr_iter;
+
+ if (!dbus_message_iter_open_container (variant_iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &arr_iter))
+ return FALSE;
+
+ if (bus_apparmor_enabled ())
+ {
+ const char *s = "AppArmor";
+
+ if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING, &s))
+ goto abandon;
+ }
+
+ if (bus_selinux_enabled ())
+ {
+ const char *s = "SELinux";
+
+ if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING, &s))
+ goto abandon;
+ }
+
+ if (bus_context_get_systemd_activation (context))
+ {
+ const char *s = "SystemdActivation";
+
+ if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING, &s))
+ goto abandon;
+ }
+
+ return dbus_message_iter_close_container (variant_iter, &arr_iter);
+
+abandon:
+ dbus_message_iter_abandon_container (variant_iter, &arr_iter);
+ return FALSE;
+}
+
+static dbus_bool_t
+interfaces_getter (BusContext *context,
+ DBusMessageIter *variant_iter)
+{
+ DBusMessageIter arr_iter;
+ const InterfaceHandler *ih;
+
+ if (!dbus_message_iter_open_container (variant_iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &arr_iter))
+ return FALSE;
+
+ for (ih = interface_handlers; ih->name != NULL; ih++)
+ {
+ if (ih->flags & INTERFACE_FLAG_UNINTERESTING)
+ continue;
+
+ if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_STRING,
+ &ih->name))
+ goto abandon;
+ }
+
+ return dbus_message_iter_close_container (variant_iter, &arr_iter);
+
+abandon:
+ dbus_message_iter_abandon_container (variant_iter, &arr_iter);
+ return FALSE;
+}
+
+static const InterfaceHandler *
+bus_driver_find_interface (const char *name,
+ dbus_bool_t canonical_path,
+ DBusError *error)
+{
+ const InterfaceHandler *ih;
+
+ for (ih = interface_handlers; ih->name != NULL; ih++)
+ {
+ if (!(canonical_path || (ih->flags & INTERFACE_FLAG_ANY_PATH)))
+ continue;
+
+ if (strcmp (name, ih->name) == 0)
+ return ih;
+ }
+
+ dbus_set_error (error, DBUS_ERROR_UNKNOWN_INTERFACE,
+ "Interface \"%s\" not found", name);
+ return NULL;
+}
+
+static const PropertyHandler *
+interface_handler_find_property (const InterfaceHandler *ih,
+ const char *name,
+ DBusError *error)
+{
+ const PropertyHandler *ph;
+
+ for (ph = ih->property_handlers; ph != NULL && ph->name != NULL; ph++)
+ {
+ if (strcmp (name, ph->name) == 0)
+ return ph;
+ }
+
+ dbus_set_error (error, DBUS_ERROR_UNKNOWN_PROPERTY,
+ "Property \"%s.%s\" not found", ih->name, name);
+ return NULL;
+}
+
+static dbus_bool_t
+bus_driver_handle_get (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ const InterfaceHandler *ih;
+ const PropertyHandler *handler;
+ const char *iface;
+ const char *prop;
+ BusContext *context;
+ DBusMessage *reply = NULL;
+ DBusMessageIter iter;
+ DBusMessageIter var_iter;
+
+ /* The message signature has already been checked for us,
+ * so this should always succeed. */
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &prop,
+ DBUS_TYPE_INVALID))
+ return FALSE;
+
+ /* We only implement Properties on /org/freedesktop/DBus so far. */
+ ih = bus_driver_find_interface (iface, TRUE, error);
+
+ if (ih == NULL)
+ return FALSE;
+
+ handler = interface_handler_find_property (ih, prop, error);
+
+ if (handler == NULL)
+ return FALSE;
+
+ context = bus_transaction_get_context (transaction);
+
+ reply = dbus_message_new_method_return (message);
+
+ if (reply == NULL)
+ goto oom;
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT,
+ handler->type, &var_iter))
+ goto oom;
+
+ if (!handler->getter (context, &var_iter))
+ {
+ dbus_message_iter_abandon_container (&iter, &var_iter);
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &var_iter))
+ goto oom;
+
+ if (!bus_transaction_send_from_driver (transaction, connection, reply))
+ goto oom;
+
+ dbus_message_unref (reply);
+ return TRUE;
+
+oom:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ BUS_SET_OOM (error);
+ return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_all (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ const InterfaceHandler *ih;
+ const char *iface;
+ const PropertyHandler *ph;
+ DBusMessageIter reply_iter;
+ DBusMessageIter array_iter;
+ BusContext *context;
+ DBusMessage *reply = NULL;
+
+ /* The message signature has already been checked for us,
+ * so this should always succeed. */
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_INVALID))
+ return FALSE;
+
+ /* We only implement Properties on /org/freedesktop/DBus so far. */
+ ih = bus_driver_find_interface (iface, TRUE, error);
+
+ if (ih == NULL)
+ return FALSE;
+
+ context = bus_transaction_get_context (transaction);
+
+ reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter);
+
+ if (reply == NULL)
+ goto oom;
+
+ for (ph = ih->property_handlers; ph != NULL && ph->name != NULL; ph++)
+ {
+ DBusMessageIter entry_iter;
+ DBusMessageIter var_iter;
+
+ if (!_dbus_asv_open_entry (&array_iter, &entry_iter, ph->name,
+ ph->type, &var_iter))
+ goto oom_abandon_message;
+
+ if (!ph->getter (context, &var_iter))
+ {
+ _dbus_asv_abandon_entry (&array_iter, &entry_iter, &var_iter);
+ goto oom_abandon_message;
+ }
+
+ if (!_dbus_asv_close_entry (&array_iter, &entry_iter, &var_iter))
+ goto oom_abandon_message;
+ }
+
+ if (!_dbus_asv_close (&reply_iter, &array_iter))
+ goto oom;
+
+ if (!bus_transaction_send_from_driver (transaction, connection, reply))
+ goto oom;
+
+ dbus_message_unref (reply);
+ return TRUE;
+
+oom_abandon_message:
+ _dbus_asv_abandon (&reply_iter, &array_iter);
+ /* fall through */
+oom:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ BUS_SET_OOM (error);
+ return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_set (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ const InterfaceHandler *ih;
+ const char *iface;
+ const char *prop;
+ const PropertyHandler *handler;
+ DBusMessageIter iter;
+
+ /* We already checked this in bus_driver_handle_message() */
+ _dbus_assert (dbus_message_has_signature (message, "ssv"));
+
+ if (!dbus_message_iter_init (message, &iter))
+ _dbus_assert_not_reached ("Message type was already checked to be 'ssv'");
+
+ dbus_message_iter_get_basic (&iter, &iface);
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Message type was already checked to be 'ssv'");
+
+ dbus_message_iter_get_basic (&iter, &prop);
+
+ /* We only implement Properties on /org/freedesktop/DBus so far. */
+ ih = bus_driver_find_interface (iface, TRUE, error);
+
+ if (ih == NULL)
+ return FALSE;
+
+ handler = interface_handler_find_property (ih, prop, error);
+
+ if (handler == NULL)
+ return FALSE;
+
+ /* We don't implement any properties that can be set yet. */
+ dbus_set_error (error, DBUS_ERROR_PROPERTY_READ_ONLY,
+ "Property '%s.%s' cannot be set", iface, prop);
+ return FALSE;
+}
diff --git a/bus/driver.h b/bus/driver.h
index 3ff4ff15..183c28b9 100644
--- a/bus/driver.h
+++ b/bus/driver.h
@@ -27,6 +27,13 @@
#include <dbus/dbus.h>
#include "connection.h"
+typedef enum
+{
+ BUS_DRIVER_FOUND_SELF,
+ BUS_DRIVER_FOUND_PEER,
+ BUS_DRIVER_FOUND_ERROR,
+} BusDriverFound;
+
void bus_driver_remove_connection (DBusConnection *connection);
BusResult bus_driver_handle_message (DBusConnection *connection,
BusTransaction *transaction,
@@ -45,8 +52,19 @@ dbus_bool_t bus_driver_send_service_owner_changed (const char *service_name
const char *new_owner,
BusTransaction *transaction,
DBusError *error);
-dbus_bool_t bus_driver_generate_introspect_string (DBusString *xml);
-dbus_bool_t bus_driver_check_message_is_for_us (DBusMessage *message,
- DBusError *error);
+dbus_bool_t bus_driver_generate_introspect_string (DBusString *xml,
+ dbus_bool_t canonical_path,
+ DBusMessage *message);
+
+BusDriverFound bus_driver_get_conn_helper (DBusConnection *connection,
+ DBusMessage *message,
+ const char *what_we_want,
+ const char **name_p,
+ DBusConnection **peer_conn_p,
+ DBusError *error);
+dbus_bool_t bus_driver_send_ack_reply (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
#endif /* BUS_DRIVER_H */
diff --git a/bus/main.c b/bus/main.c
index 28ea39a1..d5d6510a 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -45,6 +45,9 @@
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
+#ifdef DBUS_UNIX
+#include <dbus/dbus-sysdeps-unix.h>
+#endif
static BusContext *context;
@@ -67,6 +70,10 @@ typedef enum
static void
signal_handler (int sig)
{
+ /* Signal handlers that might set errno must save and restore the errno
+ * that the interrupted function might have been relying on. */
+ int saved_errno = errno;
+
switch (sig)
{
case SIGHUP:
@@ -128,10 +135,19 @@ signal_handler (int sig)
}
}
break;
+
+ default:
+ /* can't happen unless this signal handler gets used for a wrong
+ * signal, but keep -Wswitch-default happy */
+ break;
}
+
+ errno = saved_errno;
}
#endif /* DBUS_UNIX */
+static void usage (void) _DBUS_GNUC_NORETURN;
+
static void
usage (void)
{
@@ -146,6 +162,9 @@ usage (void)
" [--introspect]"
" [--address=ADDRESS]"
" [--nopidfile]"
+ " [--nosyslog]"
+ " [--syslog]"
+ " [--syslog-only]"
" [--nofork]"
#ifdef DBUS_UNIX
" [--fork]"
@@ -155,6 +174,8 @@ usage (void)
exit (1);
}
+static void version (void) _DBUS_GNUC_NORETURN;
+
static void
version (void)
{
@@ -166,6 +187,8 @@ version (void)
exit (0);
}
+static void introspect (void) _DBUS_GNUC_NORETURN;
+
static void
introspect (void)
{
@@ -175,7 +198,7 @@ introspect (void)
if (!_dbus_string_init (&xml))
goto oom;
- if (!bus_driver_generate_introspect_string (&xml))
+ if (!bus_driver_generate_introspect_string (&xml, TRUE, NULL))
{
_dbus_string_free (&xml);
goto oom;
@@ -187,7 +210,7 @@ introspect (void)
exit (0);
oom:
- _dbus_warn ("Can not introspect - Out of memory\n");
+ _dbus_warn ("Can not introspect - Out of memory");
exit (1);
}
@@ -256,7 +279,7 @@ handle_reload_watch (DBusWatch *watch,
if ((reload_pipe[RELOAD_READ_END].fd > 0) &&
_dbus_read_socket (reload_pipe[RELOAD_READ_END], &str, 1) != 1)
{
- _dbus_warn ("Couldn't read from reload pipe.\n");
+ _dbus_warn ("Couldn't read from reload pipe.");
close_reload_pipe (&watch);
return TRUE;
}
@@ -282,7 +305,7 @@ handle_reload_watch (DBusWatch *watch,
_DBUS_ASSERT_ERROR_IS_SET (&error);
_dbus_assert (dbus_error_has_name (&error, DBUS_ERROR_FAILED) ||
dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY));
- _dbus_warn ("Unable to reload configuration: %s\n",
+ _dbus_warn ("Unable to reload configuration: %s",
error.message);
dbus_error_free (&error);
}
@@ -323,7 +346,7 @@ setup_reload_pipe (DBusLoop *loop)
if (!_dbus_socketpair (&reload_pipe[0], &reload_pipe[1],
TRUE, &error))
{
- _dbus_warn ("Unable to create reload pipe: %s\n",
+ _dbus_warn ("Unable to create reload pipe: %s",
error.message);
dbus_error_free (&error);
exit (1);
@@ -335,7 +358,7 @@ setup_reload_pipe (DBusLoop *loop)
if (watch == NULL)
{
- _dbus_warn ("Unable to create reload watch: %s\n",
+ _dbus_warn ("Unable to create reload watch: %s",
error.message);
dbus_error_free (&error);
exit (1);
@@ -343,7 +366,7 @@ setup_reload_pipe (DBusLoop *loop)
if (!_dbus_loop_add_watch (loop, watch))
{
- _dbus_warn ("Unable to add reload watch to main loop: %s\n",
+ _dbus_warn ("Unable to add reload watch to main loop: %s",
error.message);
dbus_error_free (&error);
exit (1);
@@ -382,6 +405,27 @@ main (int argc, char **argv)
dbus_bool_t print_address;
dbus_bool_t print_pid;
BusContextFlags flags;
+#ifdef DBUS_UNIX
+ const char *error_str;
+
+ /* Redirect stdin from /dev/null since we will never need it, and
+ * redirect stdout and stderr to /dev/null if not already open.
+ *
+ * We should do this as the very first thing, to ensure that when we
+ * create other file descriptors (for example for epoll, inotify or
+ * a socket), they never get assigned as fd 0, 1 or 2. If they were,
+ * which could happen if our caller had (incorrectly) closed those
+ * standard fds, they'd get closed when we daemonize - for example,
+ * closing our listening socket would stop us listening, and closing
+ * a Linux epoll socket would cause the main loop to fail. */
+ if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
+ {
+ fprintf (stderr,
+ "dbus-daemon: fatal error setting up standard fds: %s: %s\n",
+ error_str, _dbus_strerror (errno));
+ return 1;
+ }
+#endif
if (!_dbus_string_init (&config_file))
return 1;
@@ -420,6 +464,21 @@ main (int argc, char **argv)
{
introspect ();
}
+ else if (strcmp (arg, "--nosyslog") == 0)
+ {
+ flags &= ~BUS_CONTEXT_FLAG_SYSLOG_ALWAYS;
+ flags |= BUS_CONTEXT_FLAG_SYSLOG_NEVER;
+ }
+ else if (strcmp (arg, "--syslog") == 0)
+ {
+ flags &= ~BUS_CONTEXT_FLAG_SYSLOG_NEVER;
+ flags |= BUS_CONTEXT_FLAG_SYSLOG_ALWAYS;
+ }
+ else if (strcmp (arg, "--syslog-only") == 0)
+ {
+ flags &= ~BUS_CONTEXT_FLAG_SYSLOG_NEVER;
+ flags |= (BUS_CONTEXT_FLAG_SYSLOG_ALWAYS|BUS_CONTEXT_FLAG_SYSLOG_ONLY);
+ }
else if (strcmp (arg, "--nofork") == 0)
{
flags &= ~BUS_CONTEXT_FLAG_FORK_ALWAYS;
@@ -444,14 +503,14 @@ main (int argc, char **argv)
{
check_two_config_files (&config_file, "system");
- if (!_dbus_append_system_config_file (&config_file))
+ if (!_dbus_get_system_config_file (&config_file))
exit (1);
}
else if (strcmp (arg, "--session") == 0)
{
check_two_config_files (&config_file, "session");
- if (!_dbus_append_session_config_file (&config_file))
+ if (!_dbus_get_session_config_file (&config_file))
exit (1);
}
else if (strstr (arg, "--config-file=") == arg)
@@ -620,13 +679,13 @@ main (int argc, char **argv)
if (!bus_selinux_pre_init ())
{
- _dbus_warn ("SELinux pre-initialization failed\n");
+ _dbus_warn ("SELinux pre-initialization failed");
exit (1);
}
if (!bus_apparmor_pre_init ())
{
- _dbus_warn ("AppArmor pre-initialization failed: out of memory\n");
+ _dbus_warn ("AppArmor pre-initialization failed: out of memory");
exit (1);
}
@@ -636,9 +695,10 @@ main (int argc, char **argv)
_dbus_string_get_length(&address) > 0 ? &address : NULL,
&error);
_dbus_string_free (&config_file);
+ _dbus_string_free (&address);
if (context == NULL)
{
- _dbus_warn ("Failed to start message bus: %s\n",
+ _dbus_warn ("Failed to start message bus: %s",
error.message);
dbus_error_free (&error);
exit (1);
diff --git a/bus/messagebus-config.in b/bus/messagebus-config.in
deleted file mode 100644
index 39459dcb..00000000
--- a/bus/messagebus-config.in
+++ /dev/null
@@ -1,178 +0,0 @@
-#!/bin/sh
-#
-# messagebus-config, Copyright 2009 Yaakov Selkowitz
-#
-# This file is part of the Cygwin port of dbus.
-
-# ======================================================================
-# Initialization
-# ======================================================================
-PROGNAME=$(basename $0)
-_tdir=$(dirname $0)
-PROGDIR=$(cd $_tdir && pwd)
-
-CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh
-
-# Subdirectory where the new package is being installed
-PREFIX=@prefix@
-
-# Directory where the config files are stored
-SYSCONFDIR=@sysconfdir@/dbus-1
-DEVDIR=/dev
-LOGDIR=/var/log
-RUNDIR=$(dirname @DBUS_SYSTEM_PID_FILE@)
-SOCKDIR=$(dirname @DBUS_SYSTEM_SOCKET@)
-
-source ${CSIH_SCRIPT}
-
-# ======================================================================
-# Routine: install_service
-# Install messagebus as a service
-# ======================================================================
-install_service() {
-
- if csih_is_nt
- then
-
- # Check if messagebus is installed and remove on user request.
- if cygrunsrv -Q messagebus > /dev/null 2>&1
- then
- csih_warning "The messagebus service is already installed."
- echo
- if csih_request "Do you want to reinstall it with different args?"
- then
- cygrunsrv -E messagebus
- cygrunsrv -R messagebus
- fi
- fi
-
- # Install messagebus service if it is not already installed
- if ! cygrunsrv -Q messagebus > /dev/null 2>&1
- then
- echo
- csih_warning "The following function requires administrator privileges!"
- if csih_request "Do you want to install messagebus as service?"
- then
- if cygrunsrv -I messagebus -d "CYGWIN D-Bus system service" -p @EXPANDED_BINDIR@/dbus-daemon -a "--nofork --system"
- then
- echo
- csih_inform "The messagebus service has been installed under the LocalSystem"
- csih_inform "account (also known as SYSTEM). To start the service now, call"
- csih_inform "\`net start messagebus' or \`cygrunsrv -S messagebus'. Otherwise, it"
- csih_inform "will start automatically after the next reboot."
- echo
- csih_inform "Check ${SYSCONFDIR}/system.conf first, if it suits your needs."
- fi
- fi # user allowed us to install messagebus
- fi # messagebus already installed
- fi # csih_is_nt
-} # --- End of install_service --- #
-
-
-# ======================================================================
-# Main Entry Point
-# ======================================================================
-
-
-# Check how the script has been started. If
-# (1) it has been started by giving the full path and
-# that path is /etc/postinstall, OR
-# (2) Otherwise, if the environment variable
-# CONFIG_AUTO_ANSWER_NO is set
-# then set auto_answer to "no". This allows automatic
-# creation of the config files in /etc w/o overwriting
-# them if they already exist. In both cases, color
-# escape sequences are suppressed, so as to prevent
-# cluttering setup's logfiles.
-if [ "$PROGDIR" = "/etc/postinstall" ]
-then
- csih_auto_answer="no"
- csih_disable_color
-fi
-if [ -n "${CONFIG_AUTO_ANSWER_NO}" ]
-then
- csih_auto_answer="no"
- csih_disable_color
-fi
-
-
-# ======================================================================
-# Parse options
-# ======================================================================
-while :
-do
- case $# in
- 0)
- break
- ;;
- esac
-
- option=$1
- shift
-
- case "$option" in
- -d | --debug )
- set -x
- csih_trace_on
- ;;
-
- -y | --yes )
- csih_auto_answer=yes
- ;;
-
- -n | --no )
- csih_auto_answer=no
- ;;
-
- *)
- echo "usage: ${PROGNAME} [OPTION]..."
- echo
- echo "This script creates a basic messagebus configuration."
- echo
- echo "Options:"
- echo " --debug -d Enable shell's debug output."
- echo " --yes -y Answer all questions with \"yes\" automatically."
- echo " --no -n Answer all questions with \"no\" automatically."
- echo
- exit 1
- ;;
-
- esac
-done
-
-# ======================================================================
-# Action!
-# ======================================================================
-
-# Check for ${SYSCONFDIR} directory
-csih_make_dir "${SYSCONFDIR}" "Cannot create global configuration files."
-chmod 775 "${SYSCONFDIR}"
-setfacl -m u:system:rwx "${SYSCONFDIR}"
-
-# Check for ${DEVDIR} directory
-csih_make_dir "${DEVDIR}" "Syslogging using messagebus will not work."
-chmod 775 "${DEVDIR}"
-setfacl -m u:system:rwx "${DEVDIR}"
-
-# Check for ${LOGDIR} directory
-csih_make_dir "${LOGDIR}" "Syslogging using messagebus will not work."
-chmod 775 "${LOGDIR}"
-setfacl -m u:system:rwx "${LOGDIR}"
-
-# Check for ${RUNDIR} directory
-csih_make_dir "${RUNDIR}" "PID files of running processes will not be created."
-chmod 775 "${RUNDIR}"
-setfacl -m u:system:rwx "${RUNDIR}"
-
-# Check for ${SOCKDIR} directory
-csih_make_dir "${SOCKDIR}" "SOCKET files of running processes will not be created."
-chmod 775 "${SOCKDIR}"
-setfacl -m u:system:rwx "${SOCKDIR}"
-
-# maybe: csih_auto_answer=no will skip,
-# interactive user will get a chance to override
-install_service
-
-
-echo
-echo "Configuration finished. Have fun!"
diff --git a/bus/messagebus.in b/bus/messagebus.in
deleted file mode 100755
index 3e2ee07a..00000000
--- a/bus/messagebus.in
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/sh
-#
-# messagebus: The D-BUS systemwide message bus
-#
-# chkconfig: 345 22 85
-# description: This is a daemon which broadcasts notifications of system events \
-# and other messages. See http://www.freedesktop.org/software/dbus/
-#
-# processname: dbus-daemon
-# pidfile: @DBUS_SYSTEM_PID_FILE@
-#
-### BEGIN INIT INFO
-# Provides: messagebus
-# Required-Start: $syslog $local_fs
-# Required-Stop: $syslog $local_fs
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: The D-Bus systemwide message bus
-# Description: This is a daemon which broadcasts notifications of system
-# events and other messages. See http://www.freedesktop.org/software/dbus
-### END INIT INFO
-
-# Sanity checks.
-[ -x @EXPANDED_BINDIR@/dbus-daemon ] || exit 0
-
-# Source function library.
-. @EXPANDED_SYSCONFDIR@/rc.d/init.d/functions
-
-# so we can rearrange this easily
-processname=dbus-daemon
-servicename=messagebus
-
-RETVAL=0
-
-start() {
- echo -n $"Starting system message bus: "
- if [ -x @EXPANDED_BINDIR@/dbus-uuidgen ] ; then
- @EXPANDED_BINDIR@/dbus-uuidgen --ensure
- fi
-
- daemon --check $servicename $processname --system
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
-}
-
-stop() {
- echo -n $"Stopping system message bus: "
-
- ## we don't want to kill all the per-user $processname, we want
- ## to use the pid file *only*; because we use the fake nonexistent
- ## program name "$servicename" that should be safe-ish
- killproc $servicename -TERM
- RETVAL=$?
- echo
- if [ $RETVAL -eq 0 ]; then
- rm -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
- rm -f @DBUS_SYSTEM_PID_FILE@
- fi
-}
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status $servicename
- RETVAL=$?
- ;;
- restart)
- stop
- start
- ;;
- condrestart)
- if [ -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename ]; then
- stop
- start
- fi
- ;;
- reload)
- echo "Message bus can't reload its configuration, you have to restart it"
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
- ;;
-esac
-exit $RETVAL
diff --git a/bus/policy.c b/bus/policy.c
index 24c0f06d..6e642951 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -30,6 +30,7 @@
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-internals.h>
+#include <dbus/dbus-message-internal.h>
BusPolicyRule*
bus_policy_rule_new (BusPolicyRuleType type,
@@ -71,6 +72,8 @@ bus_policy_rule_new (BusPolicyRuleType type,
break;
case BUS_POLICY_RULE_OWN:
break;
+ default:
+ _dbus_assert_not_reached ("invalid rule");
}
return rule;
@@ -118,6 +121,8 @@ bus_policy_rule_unref (BusPolicyRule *rule)
break;
case BUS_POLICY_RULE_GROUP:
break;
+ default:
+ _dbus_assert_not_reached ("invalid rule");
}
dbus_free (rule->privilege);
@@ -264,6 +269,9 @@ add_list_to_client (DBusList **list,
if (!bus_client_policy_append_rule (client, rule))
return FALSE;
break;
+
+ default:
+ _dbus_assert_not_reached ("invalid rule");
}
}
@@ -836,8 +844,11 @@ bus_client_policy_optimize (BusClientPolicy *policy)
remove_preceding =
rule->d.own.service_name == NULL;
break;
+
+ /* The other rule types don't appear in this list */
case BUS_POLICY_RULE_USER:
case BUS_POLICY_RULE_GROUP:
+ default:
_dbus_assert_not_reached ("invalid rule");
break;
}
@@ -1090,7 +1101,27 @@ bus_client_policy_check_can_send (DBusConnection *sender,
continue;
}
}
-
+
+ if (rule->d.send.broadcast != BUS_POLICY_TRISTATE_ANY)
+ {
+ if (dbus_message_get_destination (message) == NULL &&
+ dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
+ {
+ /* it's a broadcast */
+ if (rule->d.send.broadcast == BUS_POLICY_TRISTATE_FALSE)
+ {
+ _dbus_verbose (" (policy) skipping rule because message is a broadcast\n");
+ continue;
+ }
+ }
+ /* else it isn't a broadcast: there is some destination */
+ else if (rule->d.send.broadcast == BUS_POLICY_TRISTATE_TRUE)
+ {
+ _dbus_verbose (" (policy) skipping rule because message is not a broadcast\n");
+ continue;
+ }
+ }
+
if (rule->d.send.destination != NULL)
{
if (!rule->d.send.destination_prefix)
@@ -1176,6 +1207,20 @@ bus_client_policy_check_can_send (DBusConnection *sender,
}
}
+ if (rule->d.send.min_fds > 0 ||
+ rule->d.send.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
+ {
+ unsigned int n_fds = _dbus_message_get_n_unix_fds (message);
+
+ if (n_fds < rule->d.send.min_fds || n_fds > rule->d.send.max_fds)
+ {
+ _dbus_verbose (" (policy) skipping rule because message has %u fds "
+ "and that is outside range [%u,%u]",
+ n_fds, rule->d.send.min_fds, rule->d.send.max_fds);
+ continue;
+ }
+ }
+
/* Use this rule */
switch (rule->access)
{
@@ -1421,7 +1466,22 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
}
}
}
-
+
+ if (rule->d.receive.min_fds > 0 ||
+ rule->d.receive.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
+ {
+ unsigned int n_fds = _dbus_message_get_n_unix_fds (message);
+
+ if (n_fds < rule->d.receive.min_fds || n_fds > rule->d.receive.max_fds)
+ {
+ _dbus_verbose (" (policy) skipping rule because message has %u fds "
+ "and that is outside range [%u,%u]",
+ n_fds, rule->d.receive.min_fds,
+ rule->d.receive.max_fds);
+ continue;
+ }
+ }
+
/* Use this rule */
switch (rule->access)
{
diff --git a/bus/policy.h b/bus/policy.h
index 951ece1f..be704e3b 100644
--- a/bus/policy.h
+++ b/bus/policy.h
@@ -47,6 +47,13 @@ typedef enum
BUS_POLICY_RULE_ACCESS_CHECK
} BusPolicyRuleAccess;
+typedef enum
+{
+ BUS_POLICY_TRISTATE_ANY = 0,
+ BUS_POLICY_TRISTATE_FALSE,
+ BUS_POLICY_TRISTATE_TRUE
+} BusPolicyTristate;
+
/** determines whether the rule affects a connection, or some global item */
#define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \
(rule)->type == BUS_POLICY_RULE_GROUP))
@@ -72,10 +79,13 @@ struct BusPolicyRule
char *member;
char *error;
char *destination;
+ unsigned int max_fds;
+ unsigned int min_fds;
unsigned int eavesdrop : 1;
unsigned int requested_reply : 1;
unsigned int log : 1;
unsigned int destination_prefix : 1;
+ unsigned int broadcast : 2; /**< really a BusPolicyTristate */
} send;
struct
@@ -88,6 +98,8 @@ struct BusPolicyRule
char *member;
char *error;
char *origin;
+ unsigned int max_fds;
+ unsigned int min_fds;
unsigned int eavesdrop : 1;
unsigned int requested_reply : 1;
} receive;
diff --git a/bus/rc.messagebus.in b/bus/rc.messagebus.in
deleted file mode 100644
index c52ca777..00000000
--- a/bus/rc.messagebus.in
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/sh
-#
-# messagebus: The D-BUS systemwide message bus
-#
-# chkconfig: 345 97 03
-# description: This is a daemon which broadcasts notifications of system events \
-# and other messages. See http://www.freedesktop.org/software/dbus/
-#
-# processname: dbus-daemon
-# pidfile: @DBUS_SYSTEM_PID_FILE@
-#
-
-# Sanity checks.
-#[ -x @EXPANDED_BINDIR@/dbus-daemon ] || exit 0
-
-# Source function library.
-#. @EXPANDED_SYSCONFDIR@/rc.d/init.d/functions
-
-# so we can rearrange this easily
-#processname=dbus-daemon
-#servicename=messagebus
-
-#RETVAL=0
-
-start() {
- echo "Starting system message bus"
- if [ -x @EXPANDED_BINDIR@/dbus-uuidgen ] ; then
- @EXPANDED_BINDIR@/dbus-uuidgen --ensure
- fi
-
- if [ -x @EXPANDED_BINDIR@/dbus-daemon ];then
- @EXPANDED_BINDIR@/dbus-daemon --system
- fi
- #daemon --check $servicename $processname --system
- #RETVAL=$?
- #echo
- #[ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
-}
-
-stop() {
- echo "Stopping system message bus"
-
- ## we don't want to kill all the per-user $processname, we want
- ## to use the pid file *only*; because we use the fake nonexistent
- ## program name "$servicename" that should be safe-ish
- killall dbus-daemon
- #RETVAL=$?
- #echo
- #if [ $RETVAL -eq 0 ]; then
- # rm -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
- # rm -f @DBUS_SYSTEM_PID_FILE@
- #fi
-}
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status $servicename
- RETVAL=$?
- ;;
- restart)
- stop
- start
- ;;
- reload)
- echo "Message bus can't reload its configuration, you have to restart it"
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|reload}"
- ;;
-esac
-exit $RETVAL
diff --git a/bus/selinux.c b/bus/selinux.c
index be66d4f0..d09afb4b 100644
--- a/bus/selinux.c
+++ b/bus/selinux.c
@@ -71,7 +71,7 @@ static security_id_t bus_sid = SECSID_WILD;
static pthread_t avc_notify_thread;
/* Prototypes for AVC callback functions. */
-static void log_callback (const char *fmt, ...);
+static void log_callback (const char *fmt, ...) _DBUS_GNUC_PRINTF (1, 2);
static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft);
static void *avc_create_thread (void (*run) (void));
static void avc_stop_thread (void *thread);
@@ -146,7 +146,9 @@ log_callback (const char *fmt, ...)
vsyslog (LOG_USER | LOG_INFO, fmt, ap);
+#ifdef HAVE_LIBAUDIT
out:
+#endif
va_end(ap);
}
@@ -203,7 +205,7 @@ avc_create_thread (void (*run) (void))
rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
if (rc != 0)
{
- _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
+ _dbus_warn ("Failed to start AVC thread: %s", _dbus_strerror (rc));
exit (1);
}
return &avc_notify_thread;
@@ -225,7 +227,7 @@ avc_alloc_lock (void)
avc_mutex = dbus_new (pthread_mutex_t, 1);
if (avc_mutex == NULL)
{
- _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
+ _dbus_warn ("Could not create mutex: %s", _dbus_strerror (errno));
exit (1);
}
pthread_mutex_init (avc_mutex, NULL);
@@ -270,6 +272,19 @@ bus_selinux_enabled (void)
#endif /* HAVE_SELINUX */
}
+BusSELinuxID*
+bus_selinux_get_self (void)
+{
+#ifdef HAVE_SELINUX
+ if(bus_selinux_enabled ())
+ return BUS_SID_FROM_SELINUX (bus_sid);
+ else
+ return NULL;
+#else
+ return NULL;
+#endif /* HAVE_SELINUX */
+}
+
/**
* Do early initialization; determine whether SELinux is enabled.
*/
@@ -284,7 +299,7 @@ bus_selinux_pre_init (void)
r = is_selinux_enabled ();
if (r < 0)
{
- _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
+ _dbus_warn ("Could not tell if SELinux is enabled: %s",
_dbus_strerror (errno));
return FALSE;
}
@@ -337,7 +352,7 @@ bus_selinux_full_init (void)
if (selinux_set_mapping (dbus_map) < 0)
{
- _dbus_warn ("Failed to set up security class mapping (selinux_set_mapping():%s).\n",
+ _dbus_warn ("Failed to set up security class mapping (selinux_set_mapping():%s).",
strerror (errno));
return FALSE;
}
@@ -345,7 +360,7 @@ bus_selinux_full_init (void)
avc_entry_ref_init (&aeref);
if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
{
- _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
+ _dbus_warn ("Failed to start Access Vector Cache (AVC).");
return FALSE;
}
else
@@ -356,7 +371,7 @@ bus_selinux_full_init (void)
if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
NULL, NULL, 0, 0) < 0)
{
- _dbus_warn ("Failed to add policy reload callback: %s\n",
+ _dbus_warn ("Failed to add policy reload callback: %s",
_dbus_strerror (errno));
avc_destroy ();
return FALSE;
@@ -387,37 +402,6 @@ bus_selinux_full_init (void)
}
/**
- * Decrement SID reference count.
- *
- * @param sid the SID to decrement
- */
-void
-bus_selinux_id_unref (BusSELinuxID *sid)
-{
-#ifdef HAVE_SELINUX
- if (!selinux_enabled)
- return;
-
- _dbus_assert (sid != NULL);
-
- sidput (SELINUX_SID_FROM_BUS (sid));
-#endif /* HAVE_SELINUX */
-}
-
-void
-bus_selinux_id_ref (BusSELinuxID *sid)
-{
-#ifdef HAVE_SELINUX
- if (!selinux_enabled)
- return;
-
- _dbus_assert (sid != NULL);
-
- sidget (SELINUX_SID_FROM_BUS (sid));
-#endif /* HAVE_SELINUX */
-}
-
-/**
* Determine if the SELinux security policy allows the given sender
* security context to go to the given recipient security context.
* This function determines if the requested permissions are to be
@@ -448,7 +432,7 @@ bus_selinux_check (BusSELinuxID *sender_sid,
if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
override_sid ?
SELINUX_SID_FROM_BUS (override_sid) :
- SELINUX_SID_FROM_BUS (bus_sid),
+ bus_sid,
target_class, requested, &aeref, auxdata) < 0)
{
switch (errno)
@@ -773,7 +757,7 @@ bus_selinux_init_connection_id (DBusConnection *connection,
"Error getting SID from context \"%s\": %s\n",
con, _dbus_strerror (errno));
- _dbus_warn ("Error getting SID from context \"%s\": %s\n",
+ _dbus_warn ("Error getting SID from context \"%s\": %s",
con, _dbus_strerror (errno));
freecon (con);
@@ -787,21 +771,6 @@ bus_selinux_init_connection_id (DBusConnection *connection,
#endif /* HAVE_SELINUX */
}
-
-/**
- * Function for freeing hash table data. These SIDs
- * should no longer be referenced.
- */
-static void
-bus_selinux_id_table_free_value (BusSELinuxID *sid)
-{
-#ifdef HAVE_SELINUX
- /* NULL sometimes due to how DBusHashTable works */
- if (sid)
- bus_selinux_id_unref (sid);
-#endif /* HAVE_SELINUX */
-}
-
/**
* Creates a new table mapping service names to security ID.
* A security ID is a "compiled" security context, a security
@@ -813,8 +782,7 @@ DBusHashTable*
bus_selinux_id_table_new (void)
{
return _dbus_hash_table_new (DBUS_HASH_STRING,
- (DBusFreeFunction) dbus_free,
- (DBusFreeFunction) bus_selinux_id_table_free_value);
+ (DBusFreeFunction) dbus_free, NULL);
}
/**
@@ -854,7 +822,7 @@ bus_selinux_id_table_insert (DBusHashTable *service_table,
return FALSE;
}
- _dbus_warn ("Error getting SID from context \"%s\": %s\n",
+ _dbus_warn ("Error getting SID from context \"%s\": %s",
(char *) service_context,
_dbus_strerror (errno));
goto out;
@@ -876,9 +844,6 @@ bus_selinux_id_table_insert (DBusHashTable *service_table,
retval = TRUE;
out:
- if (sid != SECSID_WILD)
- sidput (sid);
-
if (key)
dbus_free (key);
@@ -1013,7 +978,6 @@ bus_selinux_shutdown (void)
if (bus_sid != SECSID_WILD)
{
- sidput (bus_sid);
bus_sid = SECSID_WILD;
bus_avc_print_stats ();
diff --git a/bus/selinux.h b/bus/selinux.h
index 5252b189..a0383cdd 100644
--- a/bus/selinux.h
+++ b/bus/selinux.h
@@ -33,8 +33,7 @@ void bus_selinux_shutdown (void);
dbus_bool_t bus_selinux_enabled (void);
-void bus_selinux_id_ref (BusSELinuxID *sid);
-void bus_selinux_id_unref (BusSELinuxID *sid);
+BusSELinuxID *bus_selinux_get_self (void);
DBusHashTable* bus_selinux_id_table_new (void);
BusSELinuxID* bus_selinux_id_table_lookup (DBusHashTable *service_table,
diff --git a/bus/services.c b/bus/services.c
index 9e466d87..af0307c4 100644
--- a/bus/services.c
+++ b/bus/services.c
@@ -393,6 +393,7 @@ bus_registry_acquire_service (BusRegistry *registry,
BusActivation *activation;
BusSELinuxID *sid;
BusOwner *primary_owner;
+ int limit;
retval = BUS_RESULT_FALSE;
@@ -493,16 +494,25 @@ bus_registry_acquire_service (BusRegistry *registry,
goto out;
}
- if (bus_connection_get_n_services_owned (connection) >=
- bus_context_get_max_services_per_connection (registry->context))
+ limit = bus_context_get_max_services_per_connection (registry->context);
+
+ if (bus_connection_get_n_services_owned (connection) >= limit)
{
- dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+ DBusError tmp_error;
+
+ dbus_error_init (&tmp_error);
+ dbus_set_error (&tmp_error, DBUS_ERROR_LIMITS_EXCEEDED,
"Connection \"%s\" (%s) is not allowed to own more services "
- "(increase limits in configuration file if required)",
+ "(increase limits in configuration file if required)"
+ "max_names_per_connection=%d)",
bus_connection_is_active (connection) ?
bus_connection_get_name (connection) :
"(inactive)",
- bus_connection_get_loginfo (connection));
+ bus_connection_get_loginfo (connection),
+ limit);
+ bus_context_log (registry->context, DBUS_SYSTEM_LOG_WARNING,
+ "%s", tmp_error.message);
+ dbus_move_error (&tmp_error, error);
goto out;
}
diff --git a/bus/signals.c b/bus/signals.c
index e8def9f7..6b7a464c 100644
--- a/bus/signals.c
+++ b/bus/signals.c
@@ -871,7 +871,7 @@ bus_match_rule_parse_arg_match (BusMatchRule *rule,
else
{
dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
- "Key '%s' in match rule contains junk after argument number (%u). Only 'arg%upath' (for example) or 'arg0namespace' are valid", key, arg, arg);
+ "Key '%s' in match rule contains junk after argument number (%lu). Only 'arg%lupath' (for example) or 'arg0namespace' are valid", key, arg, arg);
goto failed;
}
}
@@ -889,7 +889,7 @@ bus_match_rule_parse_arg_match (BusMatchRule *rule,
rule->args[arg] != NULL)
{
dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
- "Argument %d matched more than once in match rule\n", key);
+ "Argument %s matched more than once in match rule\n", key);
goto failed;
}
@@ -1887,9 +1887,18 @@ match_rule_matches (BusMatchRule *rule,
return FALSE;
if (addressed_recipient == NULL)
- {
- if (strcmp (rule->destination,
- DBUS_SERVICE_DBUS) != 0)
+ {
+ /* If the message is going to be delivered to the dbus-daemon
+ * itself, its destination will be "org.freedesktop.DBus",
+ * which we again match against the rule (see bus_dispatch()
+ * in bus/dispatch.c, which checks for o.fd.DBus first).
+ *
+ * If we are monitoring and we don't know who is going to receive
+ * the message (for instance because they haven't been activated yet),
+ * assume they will own the requested destination name and no other,
+ * and match the rule's destination against that.
+ */
+ if (strcmp (rule->destination, destination) != 0)
return FALSE;
}
else
@@ -2192,7 +2201,7 @@ check_parse (dbus_bool_t should_succeed,
if (should_succeed && rule == NULL)
{
- _dbus_warn ("Failed to parse: %s: %s: \"%s\"\n",
+ _dbus_warn ("Failed to parse: %s: %s: \"%s\"",
error.name, error.message,
_dbus_string_get_const_data (&str));
exit (1);
@@ -2200,7 +2209,7 @@ check_parse (dbus_bool_t should_succeed,
if (!should_succeed && rule != NULL)
{
- _dbus_warn ("Failed to fail to parse: \"%s\"\n",
+ _dbus_warn ("Failed to fail to parse: \"%s\"",
_dbus_string_get_const_data (&str));
exit (1);
}
@@ -2540,7 +2549,7 @@ test_equality (void)
if (!match_rule_equal (first, second))
{
- _dbus_warn ("rule %s and %s should have been equal\n",
+ _dbus_warn ("rule %s and %s should have been equal",
equality_tests[i].first,
equality_tests[i].second);
exit (1);
@@ -2553,7 +2562,9 @@ test_equality (void)
_dbus_assert (second_str != NULL);
_dbus_assert (strcmp (first_str, second_str) == 0);
first_reparsed = check_parse (TRUE, first_str);
+ _dbus_assert (first_reparsed != NULL);
second_reparsed = check_parse (TRUE, second_str);
+ _dbus_assert (second_reparsed != NULL);
_dbus_assert (match_rule_equal (first, first_reparsed));
_dbus_assert (match_rule_equal (second, second_reparsed));
bus_match_rule_unref (first_reparsed);
@@ -2572,10 +2583,11 @@ test_equality (void)
if (i != j)
{
second = check_parse (TRUE, equality_tests[j].second);
+ _dbus_assert (second != NULL);
if (match_rule_equal (first, second))
{
- _dbus_warn ("rule %s and %s should not have been equal\n",
+ _dbus_warn ("rule %s and %s should not have been equal",
equality_tests[i].first,
equality_tests[j].second);
exit (1);
@@ -2685,7 +2697,7 @@ check_matches (dbus_bool_t expected_to_match,
if (matched != expected_to_match)
{
- _dbus_warn ("Expected rule %s to %s message %d, failed\n",
+ _dbus_warn ("Expected rule %s to %s message %d, failed",
rule_text, expected_to_match ?
"match" : "not match", number);
exit (1);
@@ -2814,7 +2826,7 @@ test_path_match (int type,
if (matched != should_match)
{
_dbus_warn ("Expected rule %s to %s message "
- "with first arg %s of type '%c', failed\n",
+ "with first arg %s of type '%c', failed",
rule_text,
should_match ? "match" : "not match",
path,
diff --git a/bus/stats.c b/bus/stats.c
index 5312b96a..27422352 100644
--- a/bus/stats.c
+++ b/bus/stats.c
@@ -51,9 +51,6 @@ bus_stats_handle_get_stats (DBusConnection *connection,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!bus_driver_check_message_is_for_us (message, error))
- return FALSE;
-
context = bus_transaction_get_context (transaction);
connections = bus_context_get_connections (context);
@@ -123,40 +120,37 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
DBusMessage *message,
DBusError *error)
{
- const char *bus_name = NULL;
- DBusString bus_name_str;
+ BusDriverFound found;
DBusMessage *reply = NULL;
DBusMessageIter iter, arr_iter;
static dbus_uint32_t stats_serial = 0;
dbus_uint32_t in_messages, in_bytes, in_fds, in_peak_bytes, in_peak_fds;
dbus_uint32_t out_messages, out_bytes, out_fds, out_peak_bytes, out_peak_fds;
- BusRegistry *registry;
- BusService *service;
DBusConnection *stats_connection;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!bus_driver_check_message_is_for_us (message, error))
- return FALSE;
+ found = bus_driver_get_conn_helper (caller_connection, message,
+ "statistics", NULL, &stats_connection,
+ error);
- registry = bus_connection_get_registry (caller_connection);
-
- if (! dbus_message_get_args (message, error,
- DBUS_TYPE_STRING, &bus_name,
- DBUS_TYPE_INVALID))
- return BUS_RESULT_FALSE;
-
- _dbus_string_init_const (&bus_name_str, bus_name);
- service = bus_registry_lookup (registry, &bus_name_str);
-
- if (service == NULL)
+ switch (found)
{
- dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
- "Bus name '%s' has no owner", bus_name);
- return BUS_RESULT_FALSE;
+ case BUS_DRIVER_FOUND_SELF:
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "GetConnectionStats is not meaningful for the "
+ "message bus \"%s\" itself", DBUS_SERVICE_DBUS);
+ goto failed;
+
+ case BUS_DRIVER_FOUND_PEER:
+ break;
+
+ case BUS_DRIVER_FOUND_ERROR:
+ /* fall through */
+ default:
+ goto failed;
}
- stats_connection = bus_service_get_primary_owners_connection (service);
_dbus_assert (stats_connection != NULL);
reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
@@ -218,10 +212,12 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
return BUS_RESULT_TRUE;
oom:
+ BUS_SET_OOM (error);
+ /* fall through */
+failed:
if (reply != NULL)
dbus_message_unref (reply);
- BUS_SET_OOM (error);
return BUS_RESULT_FALSE;
}
diff --git a/bus/system.conf.in b/bus/system.conf.in
index 58975dc5..f139b557 100644
--- a/bus/system.conf.in
+++ b/bus/system.conf.in
@@ -67,7 +67,8 @@
send_interface="org.freedesktop.DBus" />
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus.Introspectable"/>
-
+ <allow send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus.Properties"/>
<!-- But disallow some specific bus services -->
<deny send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus"
@@ -101,6 +102,29 @@
<!-- Include legacy configuration location -->
<include ignore_missing="yes">@SYSCONFDIR_FROM_PKGDATADIR@/dbus-1/system.conf</include>
+ <!-- The defaults for these limits are hard-coded in dbus-daemon.
+ Some clarifications:
+ Times are in milliseconds (ms); 1000ms = 1 second
+ 133169152 bytes = 127 MiB
+ 33554432 bytes = 32 MiB
+ 150000ms = 2.5 minutes -->
+ <!-- <limit name="max_incoming_bytes">133169152</limit> -->
+ <!-- <limit name="max_incoming_unix_fds">64</limit> -->
+ <!-- <limit name="max_outgoing_bytes">133169152</limit> -->
+ <!-- <limit name="max_outgoing_unix_fds">64</limit> -->
+ <!-- <limit name="max_message_size">33554432</limit> -->
+ <!-- <limit name="max_message_unix_fds">16</limit> -->
+ <!-- <limit name="service_start_timeout">25000</limit> -->
+ <!-- <limit name="auth_timeout">5000</limit> -->
+ <!-- <limit name="pending_fd_timeout">150000</limit> -->
+ <!-- <limit name="max_completed_connections">2048</limit> -->
+ <!-- <limit name="max_incomplete_connections">64</limit> -->
+ <!-- <limit name="max_connections_per_user">256</limit> -->
+ <!-- <limit name="max_pending_service_starts">512</limit> -->
+ <!-- <limit name="max_names_per_connection">512</limit> -->
+ <!-- <limit name="max_match_rules_per_connection">512</limit> -->
+ <!-- <limit name="max_replies_per_connection">128</limit> -->
+
<!-- Config files are placed here that among other things, punch
holes in the above policy for specific services. -->
<includedir>system.d</includedir>
diff --git a/bus/systemd-user/dbus.service.in b/bus/systemd-user/dbus.service.in
index 6af9c19b..103fdec9 100644
--- a/bus/systemd-user/dbus.service.in
+++ b/bus/systemd-user/dbus.service.in
@@ -5,7 +5,7 @@ DefaultDependencies=no
Requires=dbus.socket
[Service]
-ExecStart=@EXPANDED_BINDIR@/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation
+ExecStart=@EXPANDED_BINDIR@/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
ExecReload=@EXPANDED_BINDIR@/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
Capabilities=all-eip
diff --git a/bus/systemd-user/dbus.socket.in b/bus/systemd-user/dbus.socket.in
index 0028e0a7..45d938b7 100644
--- a/bus/systemd-user/dbus.socket.in
+++ b/bus/systemd-user/dbus.socket.in
@@ -4,6 +4,8 @@ DefaultDependencies=no
[Socket]
ListenStream=%t/bus
+# FIXME: check the commented line below
+#ExecStartPost=-@SYSTEMCTL@ --user set-environment DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus
[Install]
Also=dbus.service
diff --git a/bus/sysusers.d/dbus.conf.in b/bus/sysusers.d/dbus.conf.in
new file mode 100644
index 00000000..fb35702d
--- /dev/null
+++ b/bus/sysusers.d/dbus.conf.in
@@ -0,0 +1,5 @@
+# sysusers.d snippet for creating the D-Bus system user automatically
+# at boot on systemd-based systems that ship with an unpopulated
+# /etc. See sysusers.d(5) for details.
+
+u @DBUS_USER@ - "System Message Bus"
diff --git a/bus/test-launch-helper.c b/bus/test-launch-helper.c
index e9ba412a..5872ab20 100644
--- a/bus/test-launch-helper.c
+++ b/bus/test-launch-helper.c
@@ -30,7 +30,12 @@
#include <dbus/dbus-internals.h>
#include <dbus/dbus-misc.h>
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+#if !defined(DBUS_ENABLE_EMBEDDED_TESTS) || !defined(DBUS_UNIX)
+#error This file is only relevant for the embedded tests on Unix
+#endif
+
+static void die (const char *failure) _DBUS_GNUC_NORETURN;
+
static void
die (const char *failure)
{
@@ -46,7 +51,7 @@ check_memleaks (const char *name)
printf ("%s: checking for memleaks\n", name);
if (_dbus_get_malloc_blocks_outstanding () != 0)
{
- _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+ _dbus_warn ("%d dbus_malloc blocks were not freed",
_dbus_get_malloc_blocks_outstanding ());
die ("memleaks");
}
@@ -57,8 +62,6 @@ test_post_hook (const char *name)
{
check_memleaks (name);
}
-#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
-
#ifdef ACTIVATION_LAUNCHER_DO_OOM
@@ -80,7 +83,7 @@ bus_activation_helper_oom_test (void *data)
/* we failed, but a OOM is good */
if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
{
- _dbus_warn ("FAILED SELF TEST: Error: %s\n", error.message);
+ _dbus_warn ("FAILED SELF TEST: Error: %s", error.message);
retval = FALSE;
}
dbus_error_free (&error);
@@ -98,11 +101,10 @@ bus_activation_helper_oom_test (void *data)
int
main (int argc, char **argv)
{
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
const char *dir;
DBusString config_file;
- if (argc > 1)
+ if (argc > 1 && strcmp (argv[1], "--tap") != 0)
dir = argv[1];
else
dir = _dbus_getenv ("DBUS_TEST_DATA");
@@ -130,7 +132,7 @@ main (int argc, char **argv)
if (!_dbus_test_oom_handling ("dbus-daemon-launch-helper",
bus_activation_helper_oom_test,
- "org.freedesktop.DBus.TestSuiteEchoService"))
+ (char *) "org.freedesktop.DBus.TestSuiteEchoService"))
die ("OOM failed");
test_post_hook (argv[0]);
@@ -138,11 +140,4 @@ main (int argc, char **argv)
printf ("%s: Success\n", argv[0]);
return 0;
-#else /* DBUS_ENABLE_EMBEDDED_TESTS */
-
- printf ("Not compiled with test support\n");
-
- return 0;
-#endif
}
-
diff --git a/bus/test-main.c b/bus/test-main.c
index 788574fe..4d3df87a 100644
--- a/bus/test-main.c
+++ b/bus/test-main.c
@@ -31,11 +31,16 @@
#include <dbus/dbus-message-internal.h>
#include "selinux.h"
+#ifndef DBUS_ENABLE_EMBEDDED_TESTS
+#error This file is only relevant for the embedded tests
+#endif
+
#ifdef DBUS_UNIX
# include <dbus/dbus-sysdeps-unix.h>
#endif
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+static void die (const char *failure) _DBUS_GNUC_NORETURN;
+
static void
die (const char *failure)
{
@@ -51,12 +56,11 @@ check_memleaks (const char *name)
printf ("%s: checking for memleaks\n", name);
if (_dbus_get_malloc_blocks_outstanding () != 0)
{
- _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+ _dbus_warn ("%d dbus_malloc blocks were not freed",
_dbus_get_malloc_blocks_outstanding ());
die ("memleaks");
}
}
-#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
static DBusInitialFDs *initial_fds = NULL;
@@ -72,7 +76,7 @@ test_pre_hook (void)
initial_fds = _dbus_check_fdleaks_enter ();
}
-static char *progname = "";
+static const char *progname = "";
static void
test_post_hook (void)
@@ -88,14 +92,13 @@ test_post_hook (void)
int
main (int argc, char **argv)
{
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
const char *dir;
const char *only;
DBusString test_data_dir;
progname = argv[0];
- if (argc > 1)
+ if (argc > 1 && strcmp (argv[1], "--tap") != 0)
dir = argv[1];
else
dir = _dbus_getenv ("DBUS_TEST_DATA");
@@ -190,10 +193,4 @@ main (int argc, char **argv)
return 0;
-#else /* DBUS_ENABLE_EMBEDDED_TESTS */
-
- printf ("Not compiled with test support\n");
-
- return 0;
-#endif
}
diff --git a/bus/test-system.c b/bus/test-system.c
index 5f02d0ab..de1f003b 100644
--- a/bus/test-system.c
+++ b/bus/test-system.c
@@ -29,7 +29,12 @@
#include <dbus/dbus-sysdeps.h>
#include <dbus/dbus-internals.h>
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+#if !defined(DBUS_ENABLE_EMBEDDED_TESTS) || !defined(DBUS_UNIX)
+#error This file is only relevant for the embedded tests on Unix
+#endif
+
+static void die (const char *failure) _DBUS_GNUC_NORETURN;
+
static void
die (const char *failure)
{
@@ -45,19 +50,18 @@ check_memleaks (const char *name)
printf ("%s: checking for memleaks\n", name);
if (_dbus_get_malloc_blocks_outstanding () != 0)
{
- _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+ _dbus_warn ("%d dbus_malloc blocks were not freed",
_dbus_get_malloc_blocks_outstanding ());
die ("memleaks");
}
}
-#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
static void
test_pre_hook (void)
{
}
-static char *progname = "";
+static const char *progname = "";
static void
test_post_hook (void)
{
@@ -67,13 +71,12 @@ test_post_hook (void)
int
main (int argc, char **argv)
{
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
const char *dir;
DBusString test_data_dir;
progname = argv[0];
- if (argc > 1)
+ if (argc > 1 && strcmp (argv[1], "--tap") != 0)
dir = argv[1];
else
dir = _dbus_getenv ("DBUS_TEST_DATA");
@@ -98,10 +101,4 @@ main (int argc, char **argv)
printf ("%s: Success\n", argv[0]);
return 0;
-#else /* DBUS_ENABLE_EMBEDDED_TESTS */
-
- printf ("Not compiled with test support\n");
-
- return 0;
-#endif
}
diff --git a/bus/test.c b/bus/test.c
index 31ef4c8f..76960a30 100644
--- a/bus/test.c
+++ b/bus/test.c
@@ -270,14 +270,14 @@ bus_context_new_test (const DBusString *test_data_dir,
if (!_dbus_string_init (&config_file))
{
- _dbus_warn ("No memory\n");
+ _dbus_warn ("No memory");
return NULL;
}
if (!_dbus_string_copy (test_data_dir, 0,
&config_file, 0))
{
- _dbus_warn ("No memory\n");
+ _dbus_warn ("No memory");
_dbus_string_free (&config_file);
return NULL;
}
@@ -286,7 +286,7 @@ bus_context_new_test (const DBusString *test_data_dir,
if (!_dbus_concat_dir_and_file (&config_file, &relative))
{
- _dbus_warn ("No memory\n");
+ _dbus_warn ("No memory");
_dbus_string_free (&config_file);
return NULL;
}
@@ -297,7 +297,7 @@ bus_context_new_test (const DBusString *test_data_dir,
{
_DBUS_ASSERT_ERROR_IS_SET (&error);
- _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n",
+ _dbus_warn ("Failed to create debug bus context from configuration file %s: %s",
filename, error.message);
dbus_error_free (&error);
diff --git a/bus/tmpfiles.d/dbus.conf.in b/bus/tmpfiles.d/dbus.conf.in
new file mode 100644
index 00000000..0ec7de04
--- /dev/null
+++ b/bus/tmpfiles.d/dbus.conf.in
@@ -0,0 +1,9 @@
+# Fields: type; path; mode; uid; gid; age; argument (symlink target)
+
+# Make ${localstatedir}/lib/dbus (required for systemd < 237)
+# Adjust mode and ownership if it already exists.
+d @EXPANDED_LOCALSTATEDIR@/lib/dbus 0755 - - -
+
+# Make ${localstatedir}/lib/dbus/machine-id a symlink to /etc/machine-id
+# if it does not already exist
+L @EXPANDED_LOCALSTATEDIR@/lib/dbus/machine-id - - - - /etc/machine-id
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 4db9c67a..3ac71a5a 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -7,7 +7,7 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(dbus)
# we need to be up to date
-CMAKE_MINIMUM_REQUIRED(VERSION 2.4.4 FATAL_ERROR)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2 FATAL_ERROR)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
@@ -43,10 +43,11 @@ autopackage(
)
include(Macros)
-TIMESTAMP(DBUS_BUILD_TIMESTAMP)
+string(TIMESTAMP DBUS_BUILD_TIMESTAMP "%Y%m%d%H%M" UTC)
########### basic vars ###############
+include(GNUInstallDirs)
if (DBUSDIR)
set(DBUS_INSTALL_DIR "${DBUSDIR}")
@@ -61,62 +62,50 @@ else (DBUS_INSTALL_DIR)
set(DBUS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
endif (DBUS_INSTALL_DIR)
-# autotools style
-if (NOT DATAROOTDIR)
- set (DATAROOTDIR share)
-endif()
-
-if (NOT DATADIR)
- set (DATADIR ${DATAROOTDIR})
-endif()
-
-if (NOT DOCDIR)
- SET(DOCDIR ${DATAROOTDIR}/doc/dbus)
-endif()
-
-if (NOT DBUS_DATADIR)
- SET(DBUS_DATADIR ${DATADIR})
-endif()
-
set(DBUS_PREFIX ${DBUS_INSTALL_DIR})
set(prefix ${DBUS_INSTALL_DIR})
set(exec_prefix ${prefix})
-set(EXPANDED_LIBDIR ${DBUS_INSTALL_DIR}/lib)
-set(EXPANDED_INCLUDEDIR ${DBUS_INSTALL_DIR}/include)
-set(EXPANDED_BINDIR ${DBUS_INSTALL_DIR}/bin)
-set(EXPANDED_SYSCONFDIR ${DBUS_INSTALL_DIR}/etc)
-set(EXPANDED_LOCALSTATEDIR ${DBUS_INSTALL_DIR}/var)
-set(EXPANDED_DATADIR ${DBUS_INSTALL_DIR}/${DBUS_DATADIR})
-set(DBUS_MACHINE_UUID_FILE ${DBUS_INSTALL_DIR}/lib/dbus/machine-id)
-set(DBUS_BINDIR ${EXPANDED_BINDIR})
-set(DBUS_DAEMONDIR ${EXPANDED_BINDIR})
-set(DBUS_LOCALSTATEDIR ${EXPANDED_LOCALSTATEDIR})
+set(DBUS_MACHINE_UUID_FILE ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/dbus/machine-id)
+set(DBUS_BINDIR ${CMAKE_INSTALL_FULL_BINDIR})
+set(DBUS_DAEMONDIR ${CMAKE_INSTALL_FULL_BINDIR})
+set(DBUS_LOCALSTATEDIR ${CMAKE_INSTALL_FULL_LOCALSTATEDIR})
+set(DBUS_RUNSTATEDIR ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/run)
# On Windows this is relative to where we put the bus setup, in
# ${datadir}/dbus-1. For simplicity, we only do this if
# ${sysconfdir} = ${prefix}/etc and ${datadir} = ${prefix}/share.
#
# On Unix, or on Windows with weird install layouts, it's the absolute path.
-if(WIN32 AND ${EXPANDED_SYSCONFDIR} STREQUAL ${prefix}/etc AND ${EXPANDED_DATADIR} STREQUAL ${prefix}/share)
+if(WIN32 AND ${CMAKE_INSTALL_FULL_SYSCONFDIR} STREQUAL ${prefix}/etc AND ${CMAKE_INSTALL_FULL_DATADIR} STREQUAL ${prefix}/share)
set(SYSCONFDIR_FROM_PKGDATADIR ../../etc)
set(DATADIR_FROM_PKGSYSCONFDIR ../../share)
else()
-set(SYSCONFDIR_FROM_PKGDATADIR ${EXPANDED_SYSCONFDIR})
-set(DATADIR_FROM_PKGSYSCONFDIR ${EXPANDED_DATADIR})
+set(SYSCONFDIR_FROM_PKGDATADIR ${CMAKE_INSTALL_FULL_SYSCONFDIR})
+set(DATADIR_FROM_PKGSYSCONFDIR ${CMAKE_INSTALL_FULL_DATADIR})
endif()
-set(DBUS_LIBEXECDIR ${EXPANDED_LIBDIR})
-set(DBUS_DATADIR ${EXPANDED_DATADIR})
+option (DBUS_RELOCATABLE "Attempt to make metadata relocatable" ON)
+
+# For simplicity, we're not relocatable if CMAKE_INSTALL_LIBDIR
+# is something more complicated (e.g. Debian multiarch);
+# we don't want to have to compute how many ../ to add
+if(CMAKE_INSTALL_LIBDIR STREQUAL "lib" OR CMAKE_INSTALL_LIBDIR STREQUAL "lib64")
+ # We know we can use ../ to get to the prefix. Do nothing.
+elseif(DBUS_RELOCATABLE)
+ # Sorry, it's too hard to make this particular build relocatable
+ message("Unusual CMAKE_INSTALL_LIBDIR: the generated package will not be relocatable.")
+ set(DBUS_RELOCATABLE OFF)
+endif()
+
+# used in the C code
+set(DBUS_LIBEXECDIR ${CMAKE_INSTALL_FULL_LIBEXECDIR})
+set(DBUS_DATADIR ${CMAKE_INSTALL_FULL_DATADIR})
#enable building of shared library
SET(BUILD_SHARED_LIBS ON)
-if(WIN32)
- set(INSTALL_TARGETS_DEFAULT_ARGS RUNTIME DESTINATION "bin" LIBRARY DESTINATION "lib" ARCHIVE DESTINATION "lib")
-else()
- set(INSTALL_TARGETS_DEFAULT_ARGS RUNTIME DESTINATION "${EXPANDED_LIBDIR}" LIBRARY DESTINATION "${EXPANDED_LIBDIR}" ARCHIVE DESTINATION "${EXPANDED_LIBDIR}")
-endif()
+set(INSTALL_TARGETS_DEFAULT_ARGS EXPORT DBus1Targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if (CYGWIN)
set (WIN32)
@@ -132,7 +121,6 @@ if (WIN32)
endif (WIN32)
if(NOT WIN32)
- option (DBUS_ENABLE_ABSTRACT_SOCKETS "enable support for abstract sockets" ON)
set (CMAKE_THREAD_PREFER_PTHREAD ON)
include (FindThreads)
endif(NOT WIN32)
@@ -169,44 +157,67 @@ if(VCS)
set(DBUS_VERBOSE_C_S 1 CACHE STRING "verbose mode" FORCE)
endif(VCS)
-if(WIN32)
- if(MSVC)
- # controll folders in msvc projects
- include(ProjectSourceGroup)
- if(NOT GROUP_CODE)
- #set(GROUP_CODE split) #cmake default
- set(GROUP_CODE flat)
- endif(NOT GROUP_CODE)
- ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
-
-
- # Use the highest warning level
- if (WALL)
- set(WALL 1 CACHE STRING "all warnings" FORCE)
- set(CMAKE_CXX_WARNING_LEVEL 4 CACHE STRING "warning level" FORCE)
-
- if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
- STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
- endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
-
- if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
- STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
- else(CMAKE_C_FLAGS MATCHES "/W[0-4]")
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
- endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
- else (WALL)
- set(CMAKE_CXX_WARNING_LEVEL 3 CACHE STRING "warning level" FORCE)
- endif (WALL)
-
- SET(MSVC_W_ERROR " /we4028 /we4013 /we4133 /we4047 /we4031 /we4002 /we4003 /we4114")
- SET(MSVC_W_DISABLE " /wd4127 /wd4090 /wd4101 /wd4244")
-
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /FIconfig.h ${MSVC_W_ERROR} ${MSVC_W_DISABLE}")
- SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /FIconfig.h ${MSVC_W_ERROR} ${MSVC_W_DISABLE}")
- endif(MSVC)
-endif(WIN32)
+if(MSVC)
+ # controll folders in msvc projects
+ include(ProjectSourceGroup)
+ if(NOT GROUP_CODE)
+ #set(GROUP_CODE split) #cmake default
+ set(GROUP_CODE flat)
+ endif(NOT GROUP_CODE)
+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /FIconfig.h")
+ SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /FIconfig.h")
+endif()
+
+#
+# setup warnings
+#
+if(MSVC)
+ # Use the highest warning level
+ if(WALL)
+ set(WALL 1 CACHE STRING "all warnings" FORCE)
+ set(CMAKE_CXX_WARNING_LEVEL 4 CACHE STRING "warning level" FORCE)
+ if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+ string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ else()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+ endif()
+
+ if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+ string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+ else()
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
+ endif()
+ else()
+ set(CMAKE_CXX_WARNING_LEVEL 3 CACHE STRING "warning level" FORCE)
+ endif()
+
+ # see https://msdn.microsoft.com/en-us/library/z78503e6.aspx
+ # 4018 'expression' : signed/unsigned mismatch
+ set(WARNINGS "4018")
+ # 4090 'operation' : different 'modifier' qualifiers
+ # 4101 'identifier' : unreferenced local variable
+ # 4127 conditional expression is constant
+ # 4244 'argument' : conversion from 'type1' to 'type2', possible loss of data
+ set(WARNINGS_DISABLED "4090 4101 4127 4244")
+ # 4002 too many actual parameters for macro 'identifier'
+ # 4003 not enough actual parameters for macro 'identifier'
+ # 4013 'function' undefined; assuming extern returning int
+ # 4028 formal parameter 'number' different from declaration
+ # 4031 second formal parameter list longer than the first list
+ # 4047 operator' : 'identifier1' differs in levels of indirection from 'identifier2'
+ # 4114 same type qualifier used more than once
+ # 4133 'type' : incompatible types - from 'type1' to 'type2'
+ set(WARNINGS_ERRORS "4002 4003 4013 4028 4031 4047 4114 4133")
+else()
+ set(WARNINGS "sign-compare")
+ set(WARNINGS_DISABLED "")
+ set(WARNINGS_ERRORS "")
+endif()
+generate_warning_cflags(WARNINGS_CFLAGS "${WARNINGS}" "${WARNINGS_DISABLED}" "${WARNINGS_ERRORS}")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNINGS_CFLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS_CFLAGS}")
+
if (UNIX AND NOT DBUS_DISABLE_ASSERT)
# required for backtrace
@@ -221,13 +232,6 @@ if(DBUS_WITH_GLIB)
endif()
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
-if(MSVC)
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /w14018")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /w14018")
-else()
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wsign-compare")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-compare")
-endif()
#########################################################################
# Windows CE (>= 5.0.0)
@@ -359,10 +363,6 @@ if(NOT EXPAT_FOUND)
message(FATAL_ERROR "expat not found!")
endif(NOT EXPAT_FOUND)
-SET(XML_LIB "Expat")
-SET(XML_LIBRARY ${EXPAT_LIBRARIES})
-SET(XML_INCLUDE_DIR ${EXPAT_INCLUDE_DIR})
-
# all missing or hardcoded for now
# 'hidden' ones
@@ -388,9 +388,6 @@ if(CMAKE_COMPILER_IS_GNUCC AND NOT DBUS_ENABLE_ANSI)
endif(UNAME_EXECUTABLE)
endif(CMAKE_COMPILER_IS_GNUCC AND NOT DBUS_ENABLE_ANSI)
-set (DBUS_HAVE_ATOMIC_INT ${atomic_int} CACHE STRING "Some atomic integer implementation present")
-set (DBUS_USE_ATOMIC_INT_486 ${atomic_int_486} CACHE STRING "Use atomic integer implementation for 486")
-
if(X11_FOUND)
option (DBUS_BUILD_X11 "Build with X11 autolaunch support " ON)
endif(X11_FOUND)
@@ -422,33 +419,22 @@ if (MSVC_IDE)
endif (MSVC_IDE)
#### Find socket directories
- if (NOT $ENV{TMPDIR} STREQUAL "")
- set (DBUS_SESSION_SOCKET_DIR $ENV{TMPDIR})
- else (NOT $ENV{TMPDIR} STREQUAL "")
- if (NOT $ENV{TEMP} STREQUAL "")
- set (DBUS_SESSION_SOCKET_DIR $ENV{TEMP})
- else (NOT $ENV{TEMP} STREQUAL "")
- if (NOT $ENV{TMP} STREQUAL "")
- set (DBUS_SESSION_SOCKET_DIR $ENV{TMP})
- else (NOT $ENV{TMP} STREQUAL "")
- if (WIN32)
- #Should never happen, both TMP and TEMP seem always set on Windows
- message(FATAL_ERROR "Could not determine a usable temporary directory")
- else(WIN32)
- set (DBUS_SESSION_SOCKET_DIR /tmp)
- endif(WIN32)
- endif (NOT $ENV{TMP} STREQUAL "")
- endif (NOT $ENV{TEMP} STREQUAL "")
- endif (NOT $ENV{TMPDIR} STREQUAL "")
+if(UNIX)
+ if(NOT $ENV{TMPDIR} STREQUAL "")
+ set(DBUS_SESSION_SOCKET_DIR $ENV{TMPDIR})
+ elseif(NOT $ENV{TEMP} STREQUAL "")
+ set(DBUS_SESSION_SOCKET_DIR $ENV{TEMP})
+ elseif(NOT $ENV{TMP} STREQUAL "")
+ set(DBUS_SESSION_SOCKET_DIR $ENV{TMP})
+ else()
+ set(DBUS_SESSION_SOCKET_DIR /tmp)
+ endif()
+endif()
# Not used on Windows, where there is no system bus
-set (DBUS_SYSTEM_PID_FILE ${DBUS_LOCALSTATEDIR}/run/dbus/pid)
+set (DBUS_SYSTEM_PID_FILE ${DBUS_RUNSTATEDIR}/dbus/pid)
-if (WIN32)
- set (DBUS_CONSOLE_AUTH_DIR "")
-else (WIN32)
- set (DBUS_CONSOLE_AUTH_DIR "/var/run/console/")
-endif (WIN32)
+set (DBUS_CONSOLE_AUTH_DIR "" CACHE STRING "Directory to check for pam_console/pam_foreground flag files, or empty to ignore")
# This won't work on Windows. It's not meant to - the system bus is
# meaningless on Windows anyway.
@@ -458,7 +444,7 @@ endif (WIN32)
# and also to connect to. If this ever changes, it'll need to be split into
# two variables, one for the listening address and one for the connecting
# address.
-set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=${DBUS_LOCALSTATEDIR}/run/dbus/system_bus_socket" CACHE STRING "system bus default address")
+set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=${DBUS_RUNSTATEDIR}/dbus/system_bus_socket" CACHE STRING "system bus default address")
if (WIN32)
set (DBUS_SESSION_BUS_LISTEN_ADDRESS "autolaunch:" CACHE STRING "session bus default listening address")
@@ -504,12 +490,11 @@ if (DBUS_BUILD_TESTS)
# set variables used for the .in files (substituted by configure_file) in test/data:
set(DBUS_TEST_EXEC ${EXECUTABLE_OUTPUT_PATH}${IDE_BIN})
set(DBUS_TEST_DATA ${CMAKE_BINARY_DIR}/test/data)
- set(TEST_SOCKET_DIR ${DBUS_SESSION_SOCKET_DIR} )
set(TEST_LAUNCH_HELPER_BINARY ${EXECUTABLE_OUTPUT_PATH}/dbus-daemon-launch-helper-test)
- set(TEST_BUS_LAUNCH_BINARY ${EXECUTABLE_OUTPUT_PATH}/dbus-launch${EXEEXT})
if (UNIX)
- set (TEST_LISTEN "unix:tmpdir=${TEST_SOCKET_DIR}")
- endif (UNIX)
+ set(TEST_SOCKET_DIR ${DBUS_SESSION_SOCKET_DIR})
+ set(TEST_LISTEN "unix:tmpdir=${TEST_SOCKET_DIR}")
+ endif()
if (WIN32)
set (TEST_LISTEN "tcp:host=localhost")
endif (WIN32)
@@ -525,11 +510,31 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY
if (WIN32)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dbus-env.bat.cmake ${CMAKE_BINARY_DIR}/bin/dbus-env.bat )
-install_files(/bin FILES ${CMAKE_BINARY_DIR}/bin/dbus-env.bat)
+ install(FILES ${CMAKE_BINARY_DIR}/bin/dbus-env.bat DESTINATION bin)
endif()
add_definitions(-DHAVE_CONFIG_H=1)
+#
+# create cmake find_package related files
+#
+set(INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/DBus1)
+if(WIN32)
+ configure_file(DBus1Config.cmake.in "${CMAKE_BINARY_DIR}/DBus1Config.cmake" @ONLY)
+else()
+ configure_file(DBus1Config.pkgconfig.in "${CMAKE_BINARY_DIR}/DBus1Config.cmake" @ONLY)
+endif()
+configure_file(DBus1ConfigVersion.cmake.in "${CMAKE_BINARY_DIR}/DBus1ConfigVersion.cmake" @ONLY)
+install(FILES
+ "${CMAKE_BINARY_DIR}/DBus1Config.cmake"
+ "${CMAKE_BINARY_DIR}/DBus1ConfigVersion.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev
+)
+
+if(WIN32)
+ install(EXPORT DBus1Targets DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
+endif()
+
########### subdirs ###############
add_subdirectory( dbus )
@@ -554,14 +559,14 @@ GET_FILENAME_COMPONENT(C_COMPILER ${CMAKE_C_COMPILER} NAME)
GET_FILENAME_COMPONENT(CXX_COMPILER ${CMAKE_CXX_COMPILER} NAME)
message(" D-BUS ${DBUS_VERSION} ")
-message(" ============ ")
+message(" ============= ")
message(" ")
message(" install prefix: ${prefix} ")
message(" install exec_prefix: ${exec_prefix} ")
-message(" install libdir: ${EXPANDED_LIBDIR} ")
-message(" install bindir: ${EXPANDED_BINDIR} ")
-message(" install sysconfdir: ${EXPANDED_SYSCONFDIR} ")
-message(" install datadir: ${EXPANDED_DATADIR} ")
+message(" install libdir: ${CMAKE_INSTALL_FULL_LIBDIR} ")
+message(" install bindir: ${CMAKE_INSTALL_FULL_BINDIR} ")
+message(" install sysconfdir: ${CMAKE_INSTALL_FULL_SYSCONFDIR} ")
+message(" install datadir: ${CMAKE_INSTALL_FULL_DATADIR} ")
message(" source code location: ${DBUS_SOURCE_DIR} ")
message(" build dir: ${CMAKE_BINARY_DIR} ")
message(" c compiler: ${C_COMPILER} ")
@@ -592,19 +597,24 @@ message(" Building kqueue support: ${DBUS_BUS_ENABLE_KQUEUE} "
message(" Building Doxygen docs: ${DBUS_ENABLE_DOXYGEN_DOCS} ")
message(" Building XML docs: ${DBUS_ENABLE_XML_DOCS} ")
message(" Daemon executable name: ${DBUS_DAEMON_NAME}")
-if (WIN32)
-message(" System bus address: ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS} ")
+if(WIN32)
message(" Session bus listens on: ${DBUS_SESSION_BUS_LISTEN_ADDRESS} ")
message(" Session clients connect to: ${DBUS_SESSION_BUS_CONNECT_ADDRESS} ")
-else (WIN32)
-message(" System bus socket: ${DBUS_SYSTEM_SOCKET} ")
+else()
message(" System bus address: ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS} ")
+message(" System bus socket: ${DBUS_SYSTEM_SOCKET} ")
message(" System bus PID file: ${DBUS_SYSTEM_PID_FILE} ")
-message(" Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR} ")
-message(" Console auth dir: ${DBUS_CONSOLE_AUTH_DIR} ")
message(" System bus user: ${DBUS_USER} ")
+message(" Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR} ")
+
+if(DBUS_CONSOLE_AUTH_DIR)
+message(" pam_console auth dir: ${DBUS_CONSOLE_AUTH_DIR} ")
+else()
+message(" pam_console auth dir: (none) ")
+endif()
+
message(" 'make check' socket dir: ${TEST_SOCKET_DIR} ")
-endif (WIN32)
+endif()
message(" Test listen address: ${TEST_LISTEN} ")
if (MSVC)
message(" build timestamp: ${DBUS_BUILD_TIMESTAMP} ")
@@ -647,3 +657,33 @@ add_custom_target(help-options
cmake -LH
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
+
+#
+# create pkgconfig file
+#
+if(UNIX)
+ set(PLATFORM_LIBS pthread ${LIBRT})
+ include(FindPkgConfig QUIET)
+ if(PKG_CONFIG_FOUND)
+ # convert lists of link libraries into -lstdc++ -lm etc..
+ foreach(LIB ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
+ set(LIBDBUS_LIBS "${LIBDBUS_LIBS} -l${LIB}")
+ endforeach()
+ set(original_prefix "${CMAKE_INSTALL_PREFIX}")
+ if(DBUS_RELOCATABLE)
+ set(pkgconfig_prefix "\${pcfiledir}/../../")
+ else()
+ set(pkgconfig_prefix "\${original_prefix}")
+ endif()
+ set(exec_prefix "\${prefix}")
+ set(bindir "\${prefix}/${CMAKE_INSTALL_BINDIR}")
+ set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
+ set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
+ set(sysconfdir "\${prefix}/${CMAKE_INSTALL_SYSCONFDIR}")
+ set(datadir "\${prefix}/${CMAKE_INSTALL_DATADIR}")
+ set(datarootdir "\${prefix}/${CMAKE_INSTALL_DATADIR}")
+ set(dbus_daemondir "\${prefix}/${CMAKE_INSTALL_BINDIR}")
+ configure_file(../dbus-1.pc.in ${CMAKE_BINARY_DIR}/dbus-1.pc @ONLY)
+ install(FILES ${CMAKE_BINARY_DIR}/dbus-1.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+ endif()
+endif()
diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake
index 119b83e6..a9a5fc90 100644
--- a/cmake/ConfigureChecks.cmake
+++ b/cmake/ConfigureChecks.cmake
@@ -62,11 +62,13 @@ check_symbol_exists(inotify_init1 "sys/inotify.h" HAVE_INOTIFY_INIT1)
check_symbol_exists(SCM_RIGHTS "sys/types.h;sys/socket.h;sys/un.h" HAVE_UNIX_FD_PASSING)
check_symbol_exists(prctl "sys/prctl.h" HAVE_PRCTL)
check_symbol_exists(raise "signal.h" HAVE_RAISE)
+check_symbol_exists(getrlimit "sys/resource.h;sys/time.h" HAVE_GETRLIMIT)
+check_symbol_exists(prlimit "sys/resource.h;sys/time.h" HAVE_PRLIMIT)
+check_symbol_exists(setrlimit "sys/resource.h;sys/time.h" HAVE_SETRLIMIT)
check_struct_member(cmsgcred cmcred_pid "sys/types.h sys/socket.h" HAVE_CMSGCRED) # dbus-sysdeps.c
# missing:
-# HAVE_ABSTRACT_SOCKETS
# DBUS_HAVE_GCC33_GCOV
check_type_size("short" SIZEOF_SHORT)
@@ -168,19 +170,3 @@ else(DBUS_HAVE_VA_COPY)
endif(DBUS_HAVE___VA_COPY)
endif(DBUS_HAVE_VA_COPY)
endif(MSVC) # _not_ MSVC
-#### Abstract sockets
-
-if (DBUS_ENABLE_ABSTRACT_SOCKETS)
-
- try_compile(HAVE_ABSTRACT_SOCKETS
- ${CMAKE_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/modules/CheckForAbstractSockets.c)
-
-endif(DBUS_ENABLE_ABSTRACT_SOCKETS)
-
-if(HAVE_ABSTRACT_SOCKETS)
- set(DBUS_PATH_OR_ABSTRACT_VALUE abstract)
-else(HAVE_ABSTRACT_SOCKETS)
- set(DBUS_PATH_OR_ABSTRACT_VALUE path)
-endif(HAVE_ABSTRACT_SOCKETS)
-
diff --git a/cmake/DBus1Config.cmake.in b/cmake/DBus1Config.cmake.in
new file mode 100644
index 00000000..c389d5ea
--- /dev/null
+++ b/cmake/DBus1Config.cmake.in
@@ -0,0 +1,37 @@
+# - Config file for the DBus1 package
+# It defines the following variables
+# DBus1_FOUND - Flag for indicating that DBus1 package has been found
+# DBus1_DEFINITIONS - compile definitions for DBus1 [1]
+# DBus1_INCLUDE_DIRS - include directories for DBus1 [1]
+# DBus1_LIBRARIES - cmake targets to link against
+
+# [1] This variable is not required if DBus1_LIBRARIES is added
+# to a target with target_link_libraries
+
+# Compute paths
+if(@DBUS_RELOCATABLE@)
+ get_filename_component(DBus1_INSTALL_DIR "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)
+else()
+ set(DBus1_INSTALL_DIR "@DBUS_PREFIX@")
+endif()
+# Our library dependencies (contains definitions for IMPORTED targets)
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/DBus1Targets.cmake")
+ # do not additional search paths for implicit libraries
+ # see https://cmake.org/cmake/help/v3.0/policy/CMP0003.html
+ if(COMMAND cmake_policy)
+ cmake_policy(SET CMP0003 NEW)
+ endif(COMMAND cmake_policy)
+
+ if(NOT TARGET dbus-1)
+ include("${CMAKE_CURRENT_LIST_DIR}/DBus1Targets.cmake")
+ endif()
+
+ set(DBus1_INCLUDE_DIRS "${DBus1_INSTALL_DIR}/@CMAKE_INSTALL_INCLUDEDIR@/dbus-1.0" "${DBus1_INSTALL_DIR}/@CMAKE_INSTALL_LIBDIR@/dbus-1.0/include")
+ set(DBus1_DEFINITIONS)
+ set(DBus1_LIBRARIES dbus-1)
+
+ set_property(TARGET dbus-1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${DBus1_INCLUDE_DIRS})
+ set_property(TARGET dbus-1 PROPERTY INTERFACE_COMPILE_DEFINITIONS ${DBus1_DEFINITIONS})
+else()
+ message(FATAL_ERROR "Incomplete cmake support in DBus1 find_package configuration")
+endif()
diff --git a/cmake/DBus1Config.pkgconfig.in b/cmake/DBus1Config.pkgconfig.in
new file mode 100644
index 00000000..8c0a25e4
--- /dev/null
+++ b/cmake/DBus1Config.pkgconfig.in
@@ -0,0 +1,75 @@
+# - Config file for the DBus1 package
+# It defines the following variables
+# DBus1_FOUND - Flag for indicating that DBus1 package has been found
+# DBus1_DEFINITIONS - compile definitions for DBus1 [1]
+# DBus1_INCLUDE_DIRS - include directories for DBus1 [1]
+# DBus1_LIBRARIES - cmake targets to link against
+
+# [1] This variable is not required if DBus1_LIBRARIES is added
+# to a target with target_link_libraries
+
+get_filename_component(DBus1_PKGCONFIG_DIR "${CMAKE_CURRENT_LIST_DIR}/../../pkgconfig" ABSOLUTE)
+find_package(PkgConfig)
+if(DEFINED ENV{PKG_CONFIG_DIR})
+ set(_dbus_pkgconfig_dir "$ENV{PKG_CONFIG_DIR}")
+endif()
+if(DEFINED ENV{PKG_CONFIG_PATH})
+ set(_dbus_pkgconfig_path "$ENV{PKG_CONFIG_PATH}")
+endif()
+if(DEFINED ENV{PKG_CONFIG_LIBDIR})
+ set(_dbus_pkgconfig_libdir "$ENV{PKG_CONFIG_LIBDIR}")
+endif()
+set(ENV{PKG_CONFIG_DIR})
+set(ENV{PKG_CONFIG_PATH} ${DBus1_PKGCONFIG_DIR})
+set(ENV{PKG_CONFIG_LIBDIR} ${DBus1_PKGCONFIG_DIR})
+# for debugging
+#set(ENV{PKG_CONFIG_DEBUG_SPEW} 1)
+pkg_check_modules(PC_DBUS1 QUIET dbus-1)
+if(DEFINED _dbus_pkgconfig_dir)
+ set(ENV{PKG_CONFIG_DIR} "${_dbus_pkgconfig_dir}")
+else()
+ unset(ENV{PKG_CONFIG_DIR})
+endif()
+if(DEFINED _dbus_pkgconfig_path)
+ set(ENV{PKG_CONFIG_PATH} "${_dbus_pkgconfig_path}")
+else()
+ unset(ENV{PKG_CONFIG_PATH})
+endif()
+if(DEFINED _dbus_pkgconfig_libdir)
+ set(ENV{PKG_CONFIG_LIBDIR} "${_dbus_pkgconfig_libdir}")
+else()
+ unset(ENV{PKG_CONFIG_LIBDIR})
+endif()
+unset(_dbus_pkgconfig_dir)
+unset(_dbus_pkgconfig_path)
+unset(_dbus_pkgconfig_libdir)
+set(DBus1_DEFINITIONS ${PC_DBUS1_CFLAGS_OTHER})
+
+# find the real stuff and use pkgconfig variables as hints
+# because cmake provides more search options
+find_path(DBus1_INCLUDE_DIR dbus/dbus.h
+ HINTS ${PC_DBUS1_INCLUDEDIR} ${PC_DBUS1_INCLUDE_DIRS}
+ PATH_SUFFIXES dbus-1.0)
+find_path(DBus1_ARCH_INCLUDE_DIR dbus/dbus-arch-deps.h
+ HINTS ${PC_DBUS1_INCLUDE_DIRS}
+ PATH_SUFFIXES dbus-1.0)
+find_library(DBus1_LIBRARY NAMES ${PC_DBUS1_LIBRARIES}
+ HINTS ${PC_DBUS1_LIBDIR} ${PC_DBUS1_LIBRARY_DIRS})
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set DBus1_FOUND to TRUE
+# if all listed variables are TRUE
+find_package_handle_standard_args(DBus1 DEFAULT_MSG
+ DBus1_LIBRARY DBus1_INCLUDE_DIR DBus1_ARCH_INCLUDE_DIR)
+
+# make the mentioned variables only visible in cmake gui with "advanced" enabled
+mark_as_advanced(DBus1_INCLUDE_DIR DBus1_LIBRARY)
+
+set(DBus1_LIBRARIES dbus-1)
+set(DBus1_INCLUDE_DIRS "${DBus1_INCLUDE_DIR}" "${DBus1_ARCH_INCLUDE_DIR}")
+
+# setup imported target
+add_library(dbus-1 SHARED IMPORTED)
+set_property(TARGET dbus-1 APPEND PROPERTY IMPORTED_LOCATION ${DBus1_LIBRARY})
+set_property(TARGET dbus-1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${DBus1_INCLUDE_DIRS})
+set_property(TARGET dbus-1 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS ${DBus1_DEFINITIONS})
diff --git a/cmake/DBus1ConfigVersion.cmake.in b/cmake/DBus1ConfigVersion.cmake.in
new file mode 100644
index 00000000..239bf593
--- /dev/null
+++ b/cmake/DBus1ConfigVersion.cmake.in
@@ -0,0 +1,11 @@
+set(PACKAGE_VERSION @DBUS_VERSION@)
+
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif()
+endif()
diff --git a/cmake/bus/CMakeLists.txt b/cmake/bus/CMakeLists.txt
index 0dcae65a..4c5bdcf2 100644
--- a/cmake/bus/CMakeLists.txt
+++ b/cmake/bus/CMakeLists.txt
@@ -26,7 +26,6 @@ FOREACH(FILE ${FILES})
configure_file(${FILE} ${TARGET} )
ENDFOREACH(FILE)
-SET (XML_SOURCES ${BUS_DIR}/config-loader-expat.c)
if (DBUS_BUS_ENABLE_INOTIFY)
set (DIR_WATCH_SOURCE ${BUS_DIR}/dir-watch-inotify.c)
@@ -45,6 +44,7 @@ set (BUS_SOURCES
${BUS_DIR}/audit.h
${BUS_DIR}/bus.c
${BUS_DIR}/bus.h
+ ${BUS_DIR}/config-loader-expat.c
${BUS_DIR}/config-parser.c
${BUS_DIR}/config-parser.h
${BUS_DIR}/config-parser-common.c
@@ -73,7 +73,6 @@ set (BUS_SOURCES
${BUS_DIR}/test.h
${BUS_DIR}/utils.c
${BUS_DIR}/utils.h
- ${XML_SOURCES}
${DIR_WATCH_SOURCE}
)
if(DBUS_ENABLE_STATS)
@@ -86,15 +85,15 @@ endif(DBUS_ENABLE_STATS)
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/..
- ${XML_INCLUDE_DIR}
+ ${EXPAT_INCLUDE_DIR}
)
add_executable(dbus-daemon ${BUS_SOURCES} ${BUS_DIR}/main.c)
-target_link_libraries(dbus-daemon ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
+target_link_libraries(dbus-daemon ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES})
set_target_properties(dbus-daemon PROPERTIES OUTPUT_NAME ${DBUS_DAEMON_NAME})
set_target_properties(dbus-daemon PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
-install_targets(/bin dbus-daemon)
+install(TARGETS dbus-daemon ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/session.conf DESTINATION share/dbus-1)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/legacy-config/session.conf DESTINATION etc/dbus-1)
install(DIRECTORY DESTINATION share/dbus-1/session.d)
@@ -117,24 +116,47 @@ if (DBUS_SERVICE)
)
add_executable(dbus-service ${dbus_service_SOURCES} )
- target_link_libraries(dbus-service ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
+ target_link_libraries(dbus-service ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES})
set_target_properties(dbus-service PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
- install_targets(/bin dbus-service )
+ install(TARGETS dbus-service ${INSTALL_TARGETS_DEFAULT_ARGS})
endif (DBUS_SERVICE)
+set(LAUNCH_HELPER_SOURCES
+ ${BUS_DIR}/config-loader-expat.c
+ ${BUS_DIR}/config-parser-common.c
+ ${BUS_DIR}/config-parser-trivial.c
+ ${BUS_DIR}/desktop-file.c
+ ${BUS_DIR}/utils.c
+ ${BUS_DIR}/activation-helper.c
+)
+
+if(NOT WIN32)
+ add_executable(dbus-daemon-launch-helper ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/activation-helper-bin.c )
+ target_link_libraries(dbus-daemon-launch-helper ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES} )
+endif(NOT WIN32)
+
if (DBUS_ENABLE_EMBEDDED_TESTS)
set(SOURCES ${BUS_SOURCES} ${BUS_DIR}/test-main.c)
- add_test_executable(test-bus "${SOURCES}" ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
+ add_test_executable(test-bus "${SOURCES}" ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES})
set_target_properties(test-bus PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
if (NOT WIN32)
set(test_bus_system_SOURCES
- ${XML_SOURCES}
+ ${BUS_DIR}/config-loader-expat.c
${BUS_DIR}/config-parser-common.c
${BUS_DIR}/config-parser-trivial.c
${BUS_DIR}/utils.c
${BUS_DIR}/test-system.c
)
- add_test_executable(test-bus-system "${test_bus_system_SOURCES}" ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY} ${DBUS_BUS_LIBS})
+ add_test_executable(test-bus-system "${test_bus_system_SOURCES}" ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES} ${DBUS_BUS_LIBS})
+
+ add_executable(dbus-daemon-launch-helper-test ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/activation-helper-bin.c)
+ set_target_properties(dbus-daemon-launch-helper-test PROPERTIES COMPILE_FLAGS "-DACTIVATION_LAUNCHER_TEST")
+ target_link_libraries(dbus-daemon-launch-helper-test ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES} )
+
+ set (SOURCES ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/test-launch-helper.c)
+ add_test_executable(test-bus-launch-helper "${SOURCES}" ${DBUS_INTERNAL_LIBRARIES} ${EXPAT_LIBRARIES})
+ set_target_properties(test-bus-launch-helper PROPERTIES COMPILE_FLAGS "-DACTIVATION_LAUNCHER_TEST -DACTIVATION_LAUNCHER_DO_OOM")
+ install_targets(/lib dbus-daemon-launch-helper)
endif()
endif (DBUS_ENABLE_EMBEDDED_TESTS)
@@ -153,31 +175,6 @@ endif(MSVC)
##install_file(${configdir}/system.d FILE
-
-set(LAUNCH_HELPER_SOURCES ${XML_SOURCES}
- ${BUS_DIR}/config-parser-common.c
- ${BUS_DIR}/config-parser-trivial.c
- ${BUS_DIR}/desktop-file.c
- ${BUS_DIR}/utils.c
- ${BUS_DIR}/activation-helper.c
-
-)
-
-if(NOT WIN32)
-# TODO PENDING(kdab) fix build on windows (activation-helper.c)
- add_executable(dbus-daemon-launch-helper ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/activation-helper-bin.c )
- target_link_libraries(dbus-daemon-launch-helper ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY} )
-
- add_executable(dbus-daemon-launch-helper-test ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/activation-helper-bin.c)
- set_target_properties(dbus-daemon-launch-helper-test PROPERTIES COMPILE_FLAGS "-DACTIVATION_LAUNCHER_TEST")
- target_link_libraries(dbus-daemon-launch-helper-test ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY} )
-
- set (SOURCES ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/test-launch-helper.c)
- add_test_executable(test-bus-launch-helper "${SOURCES}" ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
- set_target_properties(test-bus-launch-helper PROPERTIES COMPILE_FLAGS "-DACTIVATION_LAUNCHER_TEST -DACTIVATION_LAUNCHER_DO_OOM")
- install_targets(/lib dbus-daemon-launch-helper)
-endif(NOT WIN32)
-
#### Init scripts fun
#SCRIPT_IN_FILES=messagebus.in
# rc.messagebus.in
diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake
index d2af3c96..11191821 100644
--- a/cmake/config.h.cmake
+++ b/cmake/config.h.cmake
@@ -25,15 +25,14 @@
#cmakedefine DBUS_SESSION_BUS_CONNECT_ADDRESS "@DBUS_SESSION_BUS_CONNECT_ADDRESS@"
#cmakedefine DBUS_MACHINE_UUID_FILE "@DBUS_MACHINE_UUID_FILE@"
#cmakedefine DBUS_DAEMONDIR "@DBUS_DAEMONDIR@"
+#cmakedefine DBUS_RUNSTATEDIR "@DBUS_RUNSTATEDIR@"
#cmakedefine DBUS_ENABLE_STATS
#define TEST_LISTEN "@TEST_LISTEN@"
// test binaries
-#define DBUS_TEST_EXEC "@DBUS_TEST_EXEC@"
#define DBUS_EXEEXT "@EXEEXT@"
-#cmakedefine TEST_BUS_LAUNCH_BINARY "@TEST_BUS_LAUNCH_BINARY@"
/* Some dbus features */
#cmakedefine DBUS_ENABLE_ANSI 1
@@ -50,32 +49,11 @@
/* doxygen */
#cmakedefine DBUS_GCOV_ENABLED 1
-/* abstract-sockets */
-
-#cmakedefine HAVE_ABSTRACT_SOCKETS 1
-
-#cmakedefine DBUS_PATH_OR_ABSTRACT_VALUE 1
-
-#if (defined DBUS_PATH_OR_ABSTRACT_VALUE)
-#define DBUS_PATH_OR_ABSTRACT @DBUS_PATH_OR_ABSTRACT_VALUE@
-#endif
-
-#ifdef DBUS_PATH_OR_ABSTRACT_VALUE
-#undef DBUS_PATH_OR_ABSTRACT_VALUE
-#endif
-
/* selinux */
/* kqueue */
#cmakedefine HAVE_CONSOLE_OWNER_FILE 1
#define DBUS_CONSOLE_OWNER_FILE "@DBUS_CONSOLE_OWNER_FILE@"
-#cmakedefine DBUS_HAVE_ATOMIC_INT 1
-#cmakedefine DBUS_USE_ATOMIC_INT_486 1
-#if (defined(__i386__) || defined(__x86_64__))
-# define DBUS_HAVE_ATOMIC_INT 1
-# define DBUS_USE_ATOMIC_INT_486 1
-#endif
-
#cmakedefine DBUS_BUILD_X11 1
/* For the moment, the cmake build system doesn't have an equivalent of
* the autoconf build system's --disable-x11-autolaunch */
@@ -227,6 +205,9 @@
#cmakedefine HAVE_ACCEPT4 1
#cmakedefine HAVE_DIRFD 1
#cmakedefine HAVE_INOTIFY_INIT1 1
+#cmakedefine HAVE_GETRLIMIT 1
+#cmakedefine HAVE_PRLIMIT 1
+#cmakedefine HAVE_SETRLIMIT 1
#cmakedefine HAVE_UNIX_FD_PASSING 1
// structs
diff --git a/cmake/dbus/CMakeLists.txt b/cmake/dbus/CMakeLists.txt
index 64ab279b..ec96fe94 100644
--- a/cmake/dbus/CMakeLists.txt
+++ b/cmake/dbus/CMakeLists.txt
@@ -22,7 +22,9 @@ set (dbusinclude_HEADERS
${DBUS_DIR}/dbus-syntax.h
${DBUS_DIR}/dbus-threads.h
${DBUS_DIR}/dbus-types.h
- dbus-arch-deps.h
+)
+set (dbusinclude_ARCH_HEADERS
+ ${CMAKE_CURRENT_BINARY_DIR}/dbus-arch-deps.h
)
### source code that goes in the installed client library
@@ -168,6 +170,7 @@ if (DBUS_ENABLE_EMBEDDED_TESTS)
set (DBUS_UTIL_SOURCES
${DBUS_UTIL_SOURCES}
${DBUS_DIR}/dbus-test.c
+ ${DBUS_DIR}/dbus-spawn-test.c
)
endif (DBUS_ENABLE_EMBEDDED_TESTS)
@@ -237,15 +240,12 @@ set(libdbus_HEADERS
${DBUS_LIB_HEADERS}
${DBUS_SHARED_HEADERS}
)
-if (MSVC)
- set (BUILD_FILEVERSION ${DBUS_MAJOR_VERSION},${DBUS_MINOR_VERSION},${DBUS_MICRO_VERSION},${DBUS_PATCH_VERSION})
- set (BUILD_TIMESTAMP ${DBUS_BUILD_TIMESTAMP})
-
- configure_file(${DBUS_DIR}/versioninfo.rc.in ${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc)
- file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/afxres.h "")
- list(APPEND libdbus_SOURCES versioninfo.rc)
- set_source_files_properties(versioninfo.rc COMPILE_FLAGS "-D__LINE__=1")
-endif (MSVC)
+
+set (BUILD_FILEVERSION ${DBUS_MAJOR_VERSION},${DBUS_MINOR_VERSION},${DBUS_MICRO_VERSION},${DBUS_PATCH_VERSION})
+set (BUILD_TIMESTAMP ${DBUS_BUILD_TIMESTAMP})
+
+configure_file(${DBUS_DIR}/versioninfo.rc.in ${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc)
+list(APPEND libdbus_SOURCES versioninfo.rc)
if(MSVC_IDE)
project_source_group(${GROUP_CODE} DBUS_LIB_SOURCES DBUS_LIB_HEADERS)
@@ -253,8 +253,13 @@ if(MSVC_IDE)
project_source_group(${GROUP_CODE} DBUS_UTIL_SOURCES DBUS_UTIL_SOURCES)
endif(MSVC_IDE)
-### Client library
+# for clock_getres() on e.g. GNU/Linux (but not Android)
+find_library(LIBRT rt)
+
+# for socket() on QNX
+find_library(LIBSOCKET socket)
+### Client library
add_library(dbus-1 SHARED
${libdbus_SOURCES}
${libdbus_HEADERS}
@@ -275,13 +280,19 @@ if(WIN32)
if(WINCE)
target_link_libraries(dbus-1 ws2)
else(WINCE)
- target_link_libraries(dbus-1 ws2_32 advapi32 netapi32 iphlpapi)
+ target_link_libraries(dbus-1 ws2_32 advapi32 netapi32 iphlpapi dbghelp)
endif(WINCE)
else(WIN32)
if(DEFINED DBUS_LIBRARY_REVISION)
set_target_properties(dbus-1 PROPERTIES VERSION ${DBUS_LIBRARY_MAJOR}.${DBUS_LIBRARY_AGE}.${DBUS_LIBRARY_REVISION} SOVERSION ${DBUS_LIBRARY_MAJOR})
endif()
- target_link_libraries(dbus-1 ${CMAKE_THREAD_LIBS_INIT} rt)
+ target_link_libraries(dbus-1 ${CMAKE_THREAD_LIBS_INIT})
+ if(LIBRT)
+ target_link_libraries(dbus-1 ${LIBRT})
+ endif()
+ if(LIBSOCKET)
+ target_link_libraries(dbus-1 ${LIBSOCKET})
+ endif()
endif(WIN32)
# Assume that Linux has -Wl,--version-script and other platforms do not
@@ -292,7 +303,8 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
endif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
install(TARGETS dbus-1 ${INSTALL_TARGETS_DEFAULT_ARGS})
-install_files(/include/dbus FILES ${dbusinclude_HEADERS})
+install(FILES ${dbusinclude_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dbus-1.0/dbus)
+install(FILES ${dbusinclude_ARCH_HEADERS} DESTINATION ${CMAKE_INSTALL_LIBDIR}/dbus-1.0/include/dbus)
### Internal library, used for the daemon, tools and tests, compiled statically.
@@ -308,7 +320,13 @@ if(WIN32)
target_link_libraries(dbus-internal ws2_32 advapi32 netapi32 iphlpapi)
endif(WINCE)
else(WIN32)
- target_link_libraries(dbus-internal ${CMAKE_THREAD_LIBS_INIT} rt)
+ target_link_libraries(dbus-internal ${CMAKE_THREAD_LIBS_INIT})
+ if(LIBRT)
+ target_link_libraries(dbus-internal ${LIBRT})
+ endif()
+ if(LIBSOCKET)
+ target_link_libraries(dbus-internal ${LIBSOCKET})
+ endif()
endif(WIN32)
if (DBUS_ENABLE_EMBEDDED_TESTS)
diff --git a/cmake/i686-w64-mingw32.cmake b/cmake/i686-w64-mingw32.cmake
new file mode 100644
index 00000000..1be4e78c
--- /dev/null
+++ b/cmake/i686-w64-mingw32.cmake
@@ -0,0 +1,20 @@
+# Toolchain for mingw-w64 32-bit compilers, as shipped in Debian/Ubuntu.
+
+set(GNU_HOST i686-w64-mingw32)
+set(CMAKE_SYSTEM_PROCESSOR "i686")
+
+set(COMPILER_PREFIX "${GNU_HOST}-")
+
+set(CMAKE_SYSTEM_NAME "Windows")
+set(CMAKE_CROSSCOMPILING TRUE)
+set(WIN32 TRUE)
+set(MINGW TRUE)
+
+include(CMakeForceCompiler)
+cmake_force_c_compiler(${COMPILER_PREFIX}gcc GNU)
+cmake_force_cxx_compiler(${COMPILER_PREFIX}g++ GNU)
+set(CMAKE_RC_COMPILER ${COMPILER_PREFIX}windres)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
diff --git a/cmake/modules/CPackInstallConfig.cmake b/cmake/modules/CPackInstallConfig.cmake
index 74b66898..46e8fb6d 100644
--- a/cmake/modules/CPackInstallConfig.cmake
+++ b/cmake/modules/CPackInstallConfig.cmake
@@ -1,10 +1,10 @@
if (DBUS_INSTALL_SYSTEM_LIBS)
if (MINGW)
- install_files(/bin FILES ${LIBEXPAT_LIBRARIES})
else (MINGW)
INCLUDE(InstallRequiredSystemLibraries)
endif (MINGW)
+ install(FILES ${LIBEXPAT_LIBRARIES} DESTINATION bin)
endif (DBUS_INSTALL_SYSTEM_LIBS)
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "D-BUS For Windows")
diff --git a/cmake/modules/CheckForAbstractSockets.c b/cmake/modules/CheckForAbstractSockets.c
deleted file mode 100644
index 062b846c..00000000
--- a/cmake/modules/CheckForAbstractSockets.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-
-int main() {
- int listen_fd;
- struct sockaddr_un addr;
-
- listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
-
- if (listen_fd < 0)
- {
- fprintf (stderr, "socket() failed: %s\n", strerror (errno));
- exit (1);
- }
-
- memset (&addr, '\0', sizeof (addr));
- addr.sun_family = AF_UNIX;
- strcpy (addr.sun_path, "X/tmp/dbus-fake-socket-path-used-in-configure-test");
- addr.sun_path[0] = '\0'; /* this is what makes it abstract */
-
- if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
- {
- fprintf (stderr, "Abstract socket namespace bind() failed: %s\n",
- strerror (errno));
- exit (1);
- }
- else
- exit (0);
-} \ No newline at end of file
diff --git a/cmake/modules/Macros.cmake b/cmake/modules/Macros.cmake
index fd3f62c4..63b2171b 100644
--- a/cmake/modules/Macros.cmake
+++ b/cmake/modules/Macros.cmake
@@ -5,37 +5,31 @@ if(DBUS_BUILD_TESTS AND CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_NAME STREQUAL "Win
PATHS /usr/bin /usr/local/bin
NO_CMAKE_FIND_ROOT_PATH
)
- find_file(HAVE_BINFMT_WINE_SUPPORT
+ find_file(BINFMT_WINE_SUPPORT_FILE
NAMES DOSWin wine Wine windows Windows
PATHS /proc/sys/fs/binfmt_misc
NO_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH
)
- if(WINE_EXECUTABLE AND HAVE_BINFMT_WINE_SUPPORT)
+ if(EXISTS BINFMT_WINE_SUPPORT_FILE)
+ file(READ ${BINFMT_WINE_SUPPORT_FILE} CONTENT)
+ if(${CONTENT} MATCHES "enabled")
+ set(HAVE_BINFMT_WINE_SUPPORT 1)
+ endif()
+ endif()
+ if(WINE_EXECUTABLE)
list(APPEND FOOTNOTES "NOTE: The requirements to run cross compiled applications on your host system are achieved. You may run 'make check'.")
endif()
if(NOT WINE_EXECUTABLE)
list(APPEND FOOTNOTES "NOTE: You may install the Windows emulator 'wine' to be able to run cross compiled test applications.")
endif()
if(NOT HAVE_BINFMT_WINE_SUPPORT)
- list(APPEND FOOTNOTES "NOTE: You may activate binfmt_misc support for wine to be able to run cross compiled test applications.")
+ list(APPEND FOOTNOTES "NOTE: You may activate binfmt_misc support for wine to be able to run cross compiled test applications directly.")
endif()
else()
list(APPEND FOOTNOTES "NOTE: You will not be able to run cross compiled applications on your host system.")
endif()
endif()
-MACRO(TIMESTAMP RESULT)
- if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
- EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE DATE)
- string(REGEX REPLACE "(..)[/.](..)[/.](....).*" "\\3\\2\\1" DATE ${DATE})
- EXECUTE_PROCESS(COMMAND "cmd" " /C time /T" OUTPUT_VARIABLE TIME)
- string(REGEX REPLACE "(..):(..)" "\\1\\2" TIME ${TIME})
- set (${RESULT} "${DATE}${TIME}")
- else ()
- EXECUTE_PROCESS(COMMAND "date" "+%Y%m%d%H%M" OUTPUT_VARIABLE ${RESULT})
- endif ()
-ENDMACRO()
-
macro(add_test_executable _target _source)
add_executable(${_target} ${_source})
target_link_libraries(${_target} ${ARGN})
@@ -43,16 +37,23 @@ macro(add_test_executable _target _source)
# run tests with binfmt_misc
set(PREFIX "z:")
set(_env "DBUS_TEST_DAEMON=${PREFIX}${CMAKE_BINARY_DIR}/bin/dbus-daemon${EXEEXT}")
- add_test(NAME ${_target} COMMAND $<TARGET_FILE:${_target}>)
+ if(HAVE_BINFMT_WINE_SUPPORT)
+ add_test(NAME ${_target} COMMAND $<TARGET_FILE:${_target}> --tap)
+ else()
+ add_test(NAME ${_target} COMMAND ${WINE_EXECUTABLE} ${PREFIX}$<TARGET_FILE:${_target}> --tap)
+ endif()
else()
set(PREFIX)
set(_env "DBUS_TEST_DAEMON=${CMAKE_BINARY_DIR}/bin/dbus-daemon${EXEEXT}")
- add_test(NAME ${_target} COMMAND $<TARGET_FILE:${_target}>)
+ add_test(NAME ${_target} COMMAND $<TARGET_FILE:${_target}> --tap)
endif()
list(APPEND _env "DBUS_SESSION_BUS_ADDRESS=")
list(APPEND _env "DBUS_FATAL_WARNINGS=1")
list(APPEND _env "DBUS_TEST_DATA=${PREFIX}${CMAKE_BINARY_DIR}/test/data")
+ list(APPEND _env "DBUS_TEST_DBUS_LAUNCH=${PREFIX}${CMAKE_BINARY_DIR}/bin/dbus-launch${EXEEXT}")
+ list(APPEND _env "DBUS_TEST_EXEC=${PREFIX}${DBUS_TEST_EXEC}")
list(APPEND _env "DBUS_TEST_HOMEDIR=${PREFIX}${CMAKE_BINARY_DIR}/dbus")
+ list(APPEND _env "DBUS_TEST_UNINSTALLED=1")
set_tests_properties(${_target} PROPERTIES ENVIRONMENT "${_env}")
endmacro(add_test_executable)
@@ -60,3 +61,57 @@ macro(add_helper_executable _target _source)
add_executable(${_target} ${_source})
target_link_libraries(${_target} ${ARGN})
endmacro(add_helper_executable)
+
+
+#
+# generate compiler flags from MSVC warning identifiers (e.g. '4114') or gcc warning keys (e.g. 'pointer-sign')
+#
+# @param target the variable name which will contain the warnings flags
+# @param warnings a string with space delimited warnings
+# @param disabled_warnings a string with space delimited disabled warnings
+# @param error_warnings a string with space delimited warnings which should result into compile errors
+#
+macro(generate_warning_cflags target warnings disabled_warnings error_warnings)
+ if(DEBUG_MACROS)
+ message("generate_warning_cflags got: ${warnings} - ${disabled_warnings} - ${error_warnings}")
+ endif()
+ if(MSVC)
+ # level 1 is default
+ set(enabled_prefix "/w1")
+ set(error_prefix "/we")
+ set(disabled_prefix "/wd")
+ else()
+ set(enabled_prefix "-W")
+ set(error_prefix "-Werror=")
+ set(disabled_prefix "-Wno-")
+ endif()
+
+ set(temp)
+ string(REPLACE " " ";" warnings_list "${warnings}")
+ foreach(warning ${warnings_list})
+ string(STRIP ${warning} _warning)
+ if(_warning)
+ set(temp "${temp} ${enabled_prefix}${_warning}")
+ endif()
+ endforeach()
+
+ string(REPLACE " " ";" disabled_warnings_list "${disabled_warnings}")
+ foreach(warning ${disabled_warnings_list})
+ string(STRIP ${warning} _warning)
+ if(_warning)
+ set(temp "${temp} ${disabled_prefix}${_warning}")
+ endif()
+ endforeach()
+
+ string(REPLACE " " ";" error_warnings_list "${error_warnings}")
+ foreach(warning ${error_warnings_list})
+ string(STRIP ${warning} _warning)
+ if(_warning)
+ set(temp "${temp} ${error_prefix}${_warning}")
+ endif()
+ endforeach()
+ set(${target} "${temp}")
+ if(DEBUG_MACROS)
+ message("generate_warning_cflags return: ${${target}}")
+ endif()
+endmacro()
diff --git a/cmake/modules/MacrosAutotools.cmake b/cmake/modules/MacrosAutotools.cmake
index 8bb83cdf..888d5e72 100644
--- a/cmake/modules/MacrosAutotools.cmake
+++ b/cmake/modules/MacrosAutotools.cmake
@@ -108,7 +108,7 @@ macro(autodefine name)
foreach(line ${_configure_ac})
if(line MATCHES ".*AC_DEFINE(.*${name}.*).*")
string (REGEX REPLACE ".*AC_DEFINE(.*).*" "\\1" value ${line})
- string (REGEX REPLACE ".*,(.*),.*" "\\1" value2 ${value})
+ string (REGEX REPLACE "[^[]*\\[[^]]*\\], *\\[([^]]*)\\],.*" "\\1" value2 ${value})
string (REPLACE "[" "" value3 ${value2})
string (REPLACE "]" "" value4 ${value3})
set(${name} ${value4})
diff --git a/cmake/test/CMakeLists.txt b/cmake/test/CMakeLists.txt
index eb4b1f10..19e6eb07 100644
--- a/cmake/test/CMakeLists.txt
+++ b/cmake/test/CMakeLists.txt
@@ -72,7 +72,8 @@ add_helper_executable(test-spawn ${test-spawn_SOURCES} ${DBUS_INTERNAL_LIBRARIES
add_helper_executable(test-exit ${test-exit_SOURCES} ${DBUS_INTERNAL_LIBRARIES})
add_helper_executable(test-segfault ${test-segfault_SOURCES} ${DBUS_INTERNAL_LIBRARIES})
add_helper_executable(test-sleep-forever ${test-sleep-forever_SOURCES} ${DBUS_INTERNAL_LIBRARIES})
-add_test_executable(manual-tcp ${manual-tcp_SOURCES} ${DBUS_INTERNAL_LIBRARIES})
+add_helper_executable(manual-tcp ${manual-tcp_SOURCES} ${DBUS_INTERNAL_LIBRARIES})
+add_helper_executable(manual-backtrace ${CMAKE_SOURCE_DIR}/../test/manual-backtrace.c dbus-1)
if(WIN32)
add_helper_executable(manual-paths ${manual-paths_SOURCES} ${DBUS_INTERNAL_LIBRARIES})
endif()
@@ -106,9 +107,12 @@ if(DBUS_WITH_GLIB)
add_test_executable(test-monitor ${CMAKE_SOURCE_DIR}/../test/monitor.c ${TEST_LIBRARIES})
add_test_executable(test-refs ${CMAKE_SOURCE_DIR}/../test/internals/refs.c ${TEST_LIBRARIES})
add_test_executable(test-relay ${CMAKE_SOURCE_DIR}/../test/relay.c ${TEST_LIBRARIES})
+ add_test_executable(test-server-oom ${CMAKE_SOURCE_DIR}/../test/internals/server-oom.c ${TEST_LIBRARIES})
add_test_executable(test-syntax ${CMAKE_SOURCE_DIR}/../test/syntax.c ${TEST_LIBRARIES})
add_test_executable(test-syslog ${CMAKE_SOURCE_DIR}/../test/internals/syslog.c ${TEST_LIBRARIES})
+ add_test_executable(test-uid-permissions ${CMAKE_SOURCE_DIR}/../test/uid-permissions.c ${TEST_LIBRARIES})
add_helper_executable(manual-authz ${CMAKE_SOURCE_DIR}/../test/manual-authz.c ${TEST_LIBRARIES})
+ add_helper_executable(manual-test-thread-blocking ${CMAKE_SOURCE_DIR}/../test/thread-blocking.c ${TEST_LIBRARIES})
endif()
### keep these in creation order, i.e. uppermost dirs first
@@ -119,12 +123,12 @@ set (TESTDIRS
test/data/incomplete-messages
test/data/auth
test/data/sha-1
+ test/data/systemd-activation
test/data/valid-config-files
test/data/valid-config-files/basic.d
test/data/valid-config-files/session.d
test/data/valid-config-files-system
test/data/valid-config-files-system/system.d
- test/data/valid-introspection-files
test/data/valid-messages
test/data/valid-service-files
test/data/valid-service-files-system
diff --git a/cmake/tools/CMakeLists.txt b/cmake/tools/CMakeLists.txt
index 6a2e999d..c05ced43 100644
--- a/cmake/tools/CMakeLists.txt
+++ b/cmake/tools/CMakeLists.txt
@@ -56,26 +56,35 @@ set (dbus_cleanup_sockets_SOURCES
add_executable(dbus-send ${dbus_send_SOURCES})
target_link_libraries(dbus-send ${DBUS_LIBRARIES})
-install_targets(/bin dbus-send )
+install(TARGETS dbus-send ${INSTALL_TARGETS_DEFAULT_ARGS})
add_executable(dbus-test-tool ${dbus_test_tool_SOURCES})
target_link_libraries(dbus-test-tool ${DBUS_LIBRARIES})
-install_targets(/bin dbus-test-tool )
+install(TARGETS dbus-test-tool ${INSTALL_TARGETS_DEFAULT_ARGS})
+if(WIN32 AND NOT MSVC)
+ # avoid dbus-update-activation-environment triggering UAC
+ # 1 is the resource ID, ID_MANIFEST
+ # 24 is the resource type, RT_MANIFEST
+ # constants are used because of a bug in windres
+ # see https://stackoverflow.com/questions/33000158/embed-manifest-file-to-require-administrator-execution-level-with-mingw32
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/disable-uac.rc "1 24 \"${CMAKE_SOURCE_DIR}/../tools/Win32.Manifest\"\n")
+ list(APPEND dbus_update_activation_environment_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/disable-uac.rc)
+endif()
add_executable(dbus-update-activation-environment ${dbus_update_activation_environment_SOURCES})
target_link_libraries(dbus-update-activation-environment ${DBUS_LIBRARIES})
-install_targets(/bin dbus-update-activation-environment )
+install(TARGETS dbus-update-activation-environment ${INSTALL_TARGETS_DEFAULT_ARGS})
add_executable(dbus-launch ${dbus_launch_SOURCES})
target_link_libraries(dbus-launch ${DBUS_LIBRARIES})
if (DBUS_BUILD_X11)
target_link_libraries(dbus-launch ${X11_LIBRARIES} )
endif (DBUS_BUILD_X11)
-install_targets(/bin dbus-launch )
+install(TARGETS dbus-launch ${INSTALL_TARGETS_DEFAULT_ARGS})
add_executable(dbus-monitor ${dbus_monitor_SOURCES})
target_link_libraries(dbus-monitor ${DBUS_LIBRARIES})
-install_targets(/bin dbus-monitor )
+install(TARGETS dbus-monitor ${INSTALL_TARGETS_DEFAULT_ARGS})
# create the /var/lib/dbus directory for dbus-uuidgen
install(DIRECTORY DESTINATION var/lib/dbus)
diff --git a/cmake/x86_64-w64-mingw32.cmake b/cmake/x86_64-w64-mingw32.cmake
new file mode 100644
index 00000000..069bfdde
--- /dev/null
+++ b/cmake/x86_64-w64-mingw32.cmake
@@ -0,0 +1,19 @@
+# Toolchain for mingw-w64 64-bit compilers, as shipped in Debian/Ubuntu.
+
+set(GNU_HOST x86_64-w64-mingw32)
+set(CMAKE_SYSTEM_PROCESSOR "x86_64")
+
+set(COMPILER_PREFIX "${GNU_HOST}-")
+
+set(CMAKE_SYSTEM_NAME "Windows")
+set(CMAKE_CROSSCOMPILING TRUE)
+set(WIN32 TRUE)
+set(MINGW TRUE)
+
+set(CMAKE_C_COMPILER ${COMPILER_PREFIX}gcc)
+set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}g++)
+set(CMAKE_RC_COMPILER ${COMPILER_PREFIX}windres)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
diff --git a/configure.ac b/configure.ac
index 2cc116aa..e7d8d38b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,13 +2,17 @@ dnl -*- mode: m4 -*-
AC_PREREQ([2.63])
m4_define([dbus_major_version], [1])
-m4_define([dbus_minor_version], [10])
-m4_define([dbus_micro_version], [6])
+m4_define([dbus_minor_version], [12])
+m4_define([dbus_micro_version], [16])
m4_define([dbus_version],
[dbus_major_version.dbus_minor_version.dbus_micro_version])
AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus])
+
AC_CONFIG_AUX_DIR([build-aux])
+m4_pattern_forbid([^AX_(CHECK_ENABLE_DEBUG|CODE_COVERAGE|COMPILER_FLAGS|COMPILER_FLAGS_(CFLAGS|CXXFLAGS|LDFLAGS))\b],
+ [Unexpanded AX_ macro found. Please install GNU autoconf-archive])
+
AC_CANONICAL_HOST
AC_CONFIG_HEADERS([config.h])
@@ -34,16 +38,16 @@ AC_DEFINE_UNQUOTED(DBUS_DAEMON_NAME,"dbus-daemon",[Name of executable])
#
## increment if the interface has additions, changes, removals.
-LT_CURRENT=17
+LT_CURRENT=22
## increment any time the source changes; set to
## 0 if you increment CURRENT
-LT_REVISION=6
+LT_REVISION=11
## increment if any interfaces have been added; set to 0
## if any interfaces have been changed or removed. removal has
## precedence over adding, so set to 0 if both happened.
-LT_AGE=14
+LT_AGE=19
AC_SUBST(LT_CURRENT)
AC_SUBST(LT_REVISION)
@@ -61,17 +65,45 @@ AC_SUBST(DBUS_MINOR_VERSION)
AC_SUBST(DBUS_MICRO_VERSION)
AC_SUBST(DBUS_VERSION)
+dnl
+dnl Build configuration
+dnl
+
+dnl This must come first: other options use this to set their defaults. Don't
+dnl enable developer mode on production builds.
+AC_ARG_ENABLE([developer],
+ [AS_HELP_STRING([--enable-developer],
+ [set defaults to be appropriate for a D-Bus developer instead of a distribution/end-user])],
+ [enable_developer=$enableval],
+ [enable_developer=no])
+
+dnl 'disable_developer' is the negation of 'enable_developer'. If
+dnl 'enable-developer' is set to 'no' (the default), the value of
+dnl 'disable_developer' is set to 'yes', and vice versa. It's used
+dnl for macros that require the opposite of 'enable_developer', such
+dnl as several AX_ macros.
+dnl See https://bugs.freedesktop.org/show_bug.cgi?id=97357
+AS_IF([test "x$enable_developer" = "xyes"],[
+ disable_developer=no
+ ],[
+ disable_developer=yes
+ ])
+
+# The debugging check must run before the compiler tests. Other command-line
+# options also use it to set their defaults. We disable debugging by default,
+# except for developer builds.
+AX_CHECK_ENABLE_DEBUG([$enable_developer])
+
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CXX
AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
AC_ISC_POSIX
AC_HEADER_STDC
AC_C_INLINE
AM_PROG_LIBTOOL
AC_PROG_MKDIR_P
-COMPILER_COVERAGE
-COMPILER_OPTIMISATIONS
PKG_PROG_PKG_CONFIG
# TAP test driver support
@@ -119,10 +151,8 @@ if test "$dbus_win" = yes; then
# Assume DBUS_VERSION is always three numbers
BUILD_FILEVERSION=`echo "$DBUS_VERSION" | sed -e 's/\./,/g'`,0
AC_SUBST(BUILD_FILEVERSION)
- AC_CHECK_TOOL(WINDRES, windres, no)
- if test "$WINDRES" = no; then
- AC_MSG_ERROR([*** Could not find an implementation of windres in your PATH.])
- fi
+ AS_IF([test -z "$RC"],
+ [AC_MSG_ERROR([An implementation of windres is required])])
if test "$dbus_wince" = yes; then
AC_DEFINE(DBUS_WINCE,1,[Defined if we run on a W32 CE API based system])
AC_DEFINE(_WIN32_WCE, 0x0502, [Defined to get newer W32 CE APIs])
@@ -146,13 +176,6 @@ AM_CONDITIONAL(DBUS_WINCE, test "$dbus_wince" = yes)
AM_CONDITIONAL(DBUS_UNIX, test "$dbus_unix" = yes)
AM_CONDITIONAL(DBUS_CYGWIN, test "$dbus_cygwin" = yes)
-# this must come first: other options use this to set their defaults
-AC_ARG_ENABLE([developer],
- [AS_HELP_STRING([--enable-developer],
- [set defaults to be appropriate for a D-Bus developer instead of a distribution/end-user])],
- [],
- [enable_developer=no])
-
DBUS_STATIC_BUILD_CPPFLAGS=
if test "x$enable_shared" = xno; then
# On Windows, linking against the static library requires special effort
@@ -173,7 +196,6 @@ AC_ARG_ENABLE([ducktype-docs],
AS_HELP_STRING([--enable-ducktype-docs],
[build Ducktype documentation (requires Ducktype)]),
[enable_ducktype_docs=$enableval], [enable_ducktype_docs=auto])
-AC_ARG_ENABLE(abstract-sockets, AS_HELP_STRING([--enable-abstract-sockets],[use abstract socket namespace (linux only)]),enable_abstract_sockets=$enableval,enable_abstract_sockets=auto)
AC_ARG_ENABLE(selinux, AS_HELP_STRING([--enable-selinux],[build with SELinux support]),enable_selinux=$enableval,enable_selinux=auto)
AC_ARG_ENABLE([apparmor],
[AS_HELP_STRING([--enable-apparmor], [build with AppArmor support])],
@@ -189,7 +211,6 @@ AC_ARG_ENABLE(kdbus-transport, AS_HELP_STRING([--enable-kdbus-transport],[build
AC_ARG_ENABLE(libdbuspolicy,[AS_HELP_STRING([--enable-libdbuspolicy],[enable libdbuspolicy for kdbus transport [default=no]])],,[enable_libdbuspolicy=no])
AC_ARG_ENABLE(kdbus-sync-calls,[AS_HELP_STRING([--enable-kdbus-sync-calls],[enable native sync calls support for kdbus transport [default=no]])],,[enable_kdbus_sync_calls=no])
-AC_ARG_WITH(init-scripts, AS_HELP_STRING([--with-init-scripts=[redhat]],[Style of init scripts to install]))
AC_ARG_WITH(session-socket-dir, AS_HELP_STRING([--with-session-socket-dir=[dirname]],[Where to put sockets for the per-login-session message bus]))
AC_ARG_WITH(test-socket-dir, AS_HELP_STRING([--with-test-socket-dir=[dirname]],[Where to put sockets for make check]))
AC_ARG_WITH(system-pid-file, AS_HELP_STRING([--with-system-pid-file=[pidfile]],[PID file for systemwide daemon]))
@@ -240,15 +261,22 @@ fi
# default (unless you don't have GLib), because they don't bloat the library
# or binaries.
-AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_36], [Ignore post-2.36 deprecations])
-AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_38], [Prevent post-2.38 APIs])
+dnl Don't do anything too subtle here, because the CMake build system
+dnl parses these lines with regular expressions. If necessary, adjust
+dnl cmake/modules/MacrosAutotools.cmake to compensate.
+AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_40], [Ignore post-2.40 deprecations])
+AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [G_ENCODE_VERSION(2,44)], [Prevent post-2.44 APIs])
with_glib=yes
AS_IF([test "x$enable_modular_tests" != xno],
[
- PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.36, gio-2.0 >= 2.36],
- [],
+ PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.40, gio-2.0 >= 2.40],
+ [
+ AS_IF([test "x$dbus_unix" = xyes],
+ [PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0],
+ [AC_DEFINE([HAVE_GIO_UNIX], [1], [Define if you have gio-unix-2.0])], [])])
+ ],
[if test "x$enable_modular_tests" = xyes; then
AC_MSG_NOTICE([Full test coverage (--enable-modular-tests=yes or --enable-tests=yes) requires GLib])
AC_MSG_ERROR([$GLIB_ERRORS])
@@ -298,14 +326,31 @@ if test x$enable_verbose_mode = xyes; then
AC_DEFINE(DBUS_ENABLE_VERBOSE_MODE,1,[Support a verbose mode])
fi
+dnl Intentional:
+dnl - $DISABLE_WARNINGS disables unused-label warnings if not
+dnl checking or not asserting (tested further below)
+dnl - we are not going to stop using deprecated functions on a stable
+dnl branch
+dnl - missing field initializers being 0 is a C feature, not a bug
+dnl - unused-parameter is to make writing callbacks less annoying
+dnl - cast-function-type is for the
+dnl foreach(list, (DBusForeachFunction) free, NULL) idiom which would
+dnl be too intrusive to replace in a stable branch
+DISABLE_WARNINGS="$DISABLE_WARNINGS
+ -Wno-deprecated-declarations
+ -Wno-missing-field-initializers
+ -Wno-unused-parameter
+ -Wno-cast-function-type"
+
if test x$enable_asserts = xno; then
AC_DEFINE(DBUS_DISABLE_ASSERT,1,[Disable assertion checking])
- DISABLE_UNUSED_WARNINGS="unused-label"
+ DISABLE_WARNINGS="$DISABLE_WARNINGS -Wno-unused-label"
R_DYNAMIC_LDFLAG=""
if test x$enable_embedded_tests = xyes; then
- DISABLE_UNUSED_WARNINGS="$DISABLE_UNUSED_WARNINGS \
- unused-but-set-variable unused-variable \
- unused-function"
+ DISABLE_WARNINGS="$DISABLE_WARNINGS
+ -Wno-unused-but-set-variable
+ -Wno-unused-variable
+ -Wno-unused-function"
fi
else
# -rdynamic is needed for glibc's backtrace_symbols to work.
@@ -323,7 +368,7 @@ AC_SUBST(R_DYNAMIC_LDFLAG)
if test x$enable_checks = xno; then
AC_DEFINE(DBUS_DISABLE_CHECKS,1,[Disable public API sanity checking])
AC_DEFINE(G_DISABLE_CHECKS,1,[Disable GLib public API sanity checking])
- DISABLE_UNUSED_WARNINGS="unused-label"
+ DISABLE_WARNINGS="$DISABLE_WARNINGS -Wno-unused-label"
fi
AH_BOTTOM([
@@ -335,35 +380,14 @@ AH_BOTTOM([
# define DBUS_ENABLE_CHECKS 1
#endif])
-if test x$enable_compiler_coverage = xyes; then
- ## so that config.h changes when you toggle gcov support
- AC_DEFINE_UNQUOTED(DBUS_GCOV_ENABLED, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing])
-fi
-
-# glibc21.m4 serial 3
-dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-# Test for the GNU C Library, version 2.1 or newer.
-# From Bruno Haible.
+# Test for code-coverage tools if --enable-code-coverage
+AX_CODE_COVERAGE
-AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
- ac_cv_gnu_library_2_1,
- [AC_EGREP_CPP([Lucky GNU user],
- [
-#include <features.h>
-#ifdef __GNU_LIBRARY__
- #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
- Lucky GNU user
- #endif
-#endif
- ],
- ac_cv_gnu_library_2_1=yes,
- ac_cv_gnu_library_2_1=no)
- ]
-)
+AS_IF([test x$enable_code_coverage = xyes],[
+ AC_DEFINE_UNQUOTED(
+ [DBUS_GCOV_ENABLED], [1],
+ [Defined if gcov is enabled to force a rebuild due to config.h changing])
+ ])
#### Integer sizes
@@ -383,32 +407,21 @@ $ac_cv_sizeof_int)
dbusint64=int
dbusint64_constant='(val)'
dbusuint64_constant='(val)'
- dbusint64_printf_modifier='""'
;;
$ac_cv_sizeof_long)
dbusint64=long
dbusint64_constant='(val##L)'
dbusuint64_constant='(val##UL)'
- dbusint64_printf_modifier='"l"'
;;
$ac_cv_sizeof_long_long)
dbusint64='long long'
dbusint64_constant='(val##LL)'
dbusuint64_constant='(val##ULL)'
- # Ideally we discover what the format is, but this is
- # only used in verbose mode, so eh...
- if test x"$ac_cv_gnu_library_2_1" = xyes; then
- dbusint64_printf_modifier='"ll"'
- fi
;;
$ac_cv_sizeof___int64)
dbusint64=__int64
dbusint64_constant='(val##i64)'
dbusuint64_constant='(val##ui64)'
- # See above case
- if test x"$ac_cv_gnu_library_2_1" = xyes; then
- dbusint64_printf_modifier='"ll"'
- fi
;;
esac
@@ -426,9 +439,6 @@ Please report a bug here with details of your platform and compiler:
DBUS_INT64_TYPE="$dbusint64"
DBUS_INT64_CONSTANT="$dbusint64_constant"
DBUS_UINT64_CONSTANT="$dbusuint64_constant"
- if test x"$dbusint64_printf_modifier" != x; then
- AC_DEFINE_UNQUOTED(DBUS_INT64_PRINTF_MODIFIER, [$dbusint64_printf_modifier], [Define to printf modifier for 64 bit integer type])
- fi
AC_MSG_RESULT($DBUS_INT64_TYPE)
])
@@ -500,6 +510,10 @@ case $host_os in
;;
esac
+# As a GNU extension, glibc declares environ in unistd.h, which is one of
+# the AC_INCLUDES_DEFAULT.
+AC_CHECK_DECLS([environ])
+
dnl **********************************
dnl *** va_copy checks (from GLib) ***
dnl **********************************
@@ -608,7 +622,7 @@ AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension]
AC_SEARCH_LIBS(socket,[socket network])
AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
-AC_CHECK_FUNCS([vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid setresuid getrlimit])
+AC_CHECK_FUNCS([vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid setresuid getrlimit prlimit])
AC_CHECK_HEADERS([syslog.h])
if test "x$ac_cv_header_syslog_h" = "xyes"; then
@@ -619,34 +633,6 @@ fi
AC_CHECK_HEADERS_ONCE([sys/prctl.h])
AC_CHECK_FUNCS_ONCE([prctl raise])
-#### Check for broken poll; taken from Glib's configure
-
-AC_MSG_CHECKING([for broken poll])
-AC_RUN_IFELSE([AC_LANG_SOURCE([[
- #include <stdlib.h>
- #include <fcntl.h>
- #include <poll.h>
- #ifdef HAVE_SYS_POLL_H
- #include <sys/poll.h>
- #endif
- int main(void) {
- struct pollfd fds[1];
- int fd;
- fd = open("/dev/null", 1);
- fds[0].fd = fd;
- fds[0].events = POLLIN;
- fds[0].revents = 0;
- if (poll(fds, 1, 0) < 0 || (fds[0].revents & POLLNVAL) != 0) {
- exit(1); /* Does not work for devices -- fail */
- }
- exit(0);
- }]])],
- [broken_poll=no],
- [broken_poll=yes
- AC_DEFINE(BROKEN_POLL,1,[poll doesn't work on devices])],
- [broken_poll="no (cross compiling)"])
-AC_MSG_RESULT($broken_poll)
-
AC_MSG_CHECKING(for dirfd)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
@@ -683,6 +669,7 @@ closedir(dirp);
fi
AC_CHECK_HEADERS(sys/resource.h)
+AC_CHECK_HEADERS([sys/time.h])
AC_CHECK_HEADERS(dirent.h)
@@ -701,6 +688,8 @@ AC_CHECK_HEADERS(byteswap.h)
AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_HEADERS([stdint.h])
+
AC_CHECK_HEADERS(ws2tcpip.h)
AC_CHECK_HEADERS(alloca.h)
@@ -844,99 +833,15 @@ AC_CHECK_FUNCS(getpeerucred getpeereid)
AC_CHECK_FUNCS(pipe2 accept4)
-#### Abstract sockets
+PKG_CHECK_MODULES([EXPAT], [expat])
-if test x$enable_abstract_sockets = xauto; then
-AC_LANG_PUSH(C)
-warn_on_xcompile=no
-AC_CACHE_CHECK([abstract socket namespace],
- ac_cv_have_abstract_sockets,
- [AC_RUN_IFELSE([AC_LANG_PROGRAM(
-[[
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-]],
-[[
- size_t slen;
- int listen_fd;
- struct sockaddr_un addr;
-
- listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
-
- if (listen_fd < 0)
- {
- fprintf (stderr, "socket() failed: %s\n", strerror (errno));
- exit (1);
- }
-
- memset (&addr, '\0', sizeof (addr));
- addr.sun_family = AF_UNIX;
- strcpy (addr.sun_path, "X/tmp/dbus-fake-socket-path-used-in-configure-test");
- /* SUN_LEN uses strlen() so need to calculate it before adding \0 at the
- * beginning.
- */
- slen = SUN_LEN(&addr);
- addr.sun_path[0] = '\0'; /* this is what makes it abstract */
-
- if (bind (listen_fd, (struct sockaddr*) &addr, slen) < 0)
- {
- fprintf (stderr, "Abstract socket namespace bind() failed: %s\n",
- strerror (errno));
- exit (1);
- }
- else
- exit (0);
-]])],
- [ac_cv_have_abstract_sockets=yes],
- [ac_cv_have_abstract_sockets=no],
- [
- ac_cv_have_abstract_sockets=no
- warn_on_xcompile=yes
- ]
-)])
-if test x$warn_on_xcompile = xyes ; then
- AC_MSG_WARN([Cannot check for abstract sockets when cross-compiling, please use --enable-abstract-sockets])
-fi
-AC_LANG_POP(C)
-fi
-
-if test x$enable_abstract_sockets = xyes; then
- if test x$ac_cv_have_abstract_sockets = xno; then
- AC_MSG_ERROR([Abstract sockets explicitly required, and support not detected.])
- fi
-fi
-
-if test x$enable_abstract_sockets = xno; then
- ac_cv_have_abstract_sockets=no;
-fi
-
-if test x$ac_cv_have_abstract_sockets = xyes ; then
- DBUS_PATH_OR_ABSTRACT=abstract
- AC_DEFINE(HAVE_ABSTRACT_SOCKETS,1,[Have abstract socket namespace])
-else
- DBUS_PATH_OR_ABSTRACT=path
-fi
-
-# this is used in addresses to prefer abstract, e.g.
-# unix:path=/foo or unix:abstract=/foo
-AC_SUBST(DBUS_PATH_OR_ABSTRACT)
-
-#### Sort out XML library
-
-AC_CHECK_LIB(expat, XML_ParserCreate_MM,
- [ AC_CHECK_HEADERS(expat.h, [],
- [AC_MSG_ERROR([Could not find expat.h, check config.log for failed attempts])]) ],
- [ AC_MSG_ERROR([Explicitly requested expat but expat not found]) ])
-
-XML_LIBS=-lexpat
-XML_CFLAGS=
-AC_SUBST([XML_CFLAGS])
-AC_SUBST([XML_LIBS])
+save_cflags="$CFLAGS"
+save_libs="$LIBS"
+CFLAGS="$CFLAGS $EXPAT_CFLAGS"
+LIBS="$LIBS $EXPAT_LIBS"
+AC_CHECK_FUNCS([XML_SetHashSalt])
+CFLAGS="$save_cflags"
+LIBS="$save_libs"
# Thread lib detection
AC_ARG_VAR([THREAD_LIBS])
@@ -1014,21 +919,8 @@ if test x$enable_selinux = xno ; then
have_selinux=no;
else
# See if we have SELinux library
- AC_CHECK_LIB(selinux, is_selinux_enabled,
- have_selinux=yes, have_selinux=no)
-
- # see if we have the SELinux header with the new D-Bus stuff in it
- if test x$have_selinux = xyes ; then
- AC_MSG_CHECKING([for DBUS Flask permissions in selinux/av_permissions.h])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <selinux/av_permissions.h>]],
- [[#ifdef DBUS__ACQUIRE_SVC return 0;
- #else
- #error DBUS__ACQUIRE_SVC not defined
- #endif]])],
- [have_selinux=yes],
- [have_selinux=no])
- AC_MSG_RESULT($have_selinux)
- fi
+ PKG_CHECK_MODULES([SELINUX], [libselinux >= 2.0.86],
+ [have_selinux=yes], [have_selinux=no])
if test x$enable_selinux = xauto ; then
if test x$have_selinux = xno ; then
@@ -1049,7 +941,7 @@ if test x$have_selinux = xyes ; then
AC_CHECK_FUNC(pthread_create,,[AC_CHECK_LIB(pthread,pthread_create,
[SELINUX_THREAD_LIBS="-lpthread"])])
- SELINUX_LIBS="-lselinux $SELINUX_THREAD_LIBS"
+ SELINUX_LIBS="$SELINUX_LIBS $SELINUX_THREAD_LIBS"
AC_DEFINE(HAVE_SELINUX,1,[SELinux support])
else
SELINUX_LIBS=
@@ -1061,6 +953,8 @@ AS_IF([test x$enable_apparmor = xno],
[
PKG_CHECK_MODULES([APPARMOR], [libapparmor >= 2.8.95],
[have_apparmor=yes], [have_apparmor=no])
+ PKG_CHECK_MODULES([APPARMOR_2_10], [libapparmor >= 2.10],
+ [have_apparmor_2_10=yes], [have_apparmor_2_10=no])
AS_IF([test x$enable_apparmor = xauto && test x$have_apparmor = xno],
[AC_MSG_WARN([Sufficiently new AppArmor library not found])])
@@ -1070,6 +964,9 @@ AS_IF([test x$enable_apparmor = xno],
AS_IF([test x$have_apparmor = xyes],
[AC_DEFINE([HAVE_APPARMOR], [1], [AppArmor Support])])
+AS_IF([test x$have_apparmor_2_10 = xyes],
+ [AC_DEFINE([HAVE_APPARMOR_2_10], [1],
+ [Define if libapparmor is version 2.10 or later])])
# inotify checks
if test x$enable_inotify = xno ; then
@@ -1268,7 +1165,7 @@ if test x$dbus_win = xyes ; then
if test x$dbus_wince = xyes ; then
NETWORK_libs="-lws2"
else
- NETWORK_libs="-lws2_32 -liphlpapi"
+ NETWORK_libs="-lws2_32 -liphlpapi -ldbghelp"
fi
fi
@@ -1356,82 +1253,55 @@ fi
if test "x$enable_x11_autolaunch" = xyes ; then
AC_DEFINE([DBUS_ENABLE_X11_AUTOLAUNCH], [1], [Define to enable X11 auto-launch])
fi
+AM_CONDITIONAL([DBUS_ENABLE_X11_AUTOLAUNCH],
+ [test "x$enable_x11_autolaunch" = xyes])
AC_SUBST([DBUS_X_CFLAGS])
AC_SUBST([DBUS_X_LIBS])
-#### gcc warning flags
-
-cc_supports_flag() {
- AC_MSG_CHECKING(whether $CC supports "$*")
- save_CFLAGS="$CFLAGS"
- CFLAGS="$*"
- AC_TRY_COMPILE([], [], [rc=yes], [rc=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT([$rc])
- test "x$rc" = xyes
-}
-
-TP_COMPILER_WARNINGS([WARNING_CFLAGS],
- dnl Use -Werror by default if:
- dnl - we're not on Windows (too many warnings), and
- dnl - we're in developer mode (a D-Bus developer, not a distro or end-user)
- dnl Override with --enable-Werror or --disable-Werror
- [test x$dbus_win != xyes -a x$dbus_cygwin != xyes -a x$enable_developer = xyes],
-
- dnl Enable these warnings if possible:
- [all \
- extra \
- char-subscripts \
- missing-declarations \
- missing-prototypes \
- nested-externs \
- pointer-arith \
- cast-align \
- no-address \
- float-equal \
- declaration-after-statement \
- ],
+# We're treating -fno-common like a warning: it makes the linker more
+# strict, because on some systems the linker is *always* this strict
+TEST_CFLAGS="$TEST_CFLAGS -fno-common"
- dnl Disable these warnings if possible, make them non-fatal if possible,
- dnl and don't enable -Werror unless we succeeded.
- dnl
- dnl Intentional:
- dnl - $DISABLE_UNUSED_WARNINGS disables unused-label warnings if not
- dnl checking or not asserting
- dnl - missing field initializers being 0 is a C feature, not a bug
- dnl - unused-parameter is to make writing callbacks less annoying
- dnl
- dnl To be fixed one day:
- dnl - pointer-sign is a workaround for fd.o #15522
- dnl - type-limits is probably a bug too, but having the rest of -Wextra
- dnl is better than nothing
- [$DISABLE_UNUSED_WARNINGS \
- missing-field-initializers \
- unused-parameter \
- pointer-sign \
- type-limits \
+AS_IF([test "x$enable_ansi" = "xyes"],[
+ TEST_CFLAGS="$TEST_CFLAGS -ansi -pedantic"
+ AC_DEFINE([_POSIX_C_SOURCE],[199309L],[Define to enable POSIX features])
+ AC_DEFINE([_BSD_SOURCE],[1],[Define to enable BSD features])
])
-if test "x$GCC" = "xyes"; then
- # We're treating -fno-common like a warning: it makes the linker more
- # strict, because on some systems the linker is *always* this strict
- TP_ADD_COMPILER_FLAG([WARNING_CFLAGS], [-fno-common])
-
- # http://bugs.freedesktop.org/show_bug.cgi?id=10599
- TP_ADD_COMPILER_FLAG([WARNING_CFLAGS], [-fno-strict-aliasing])
-
- if test "x$enable_ansi" = "xyes"; then
- TP_ADD_COMPILER_FLAG([WARNING_CFLAGS],
- [-ansi -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE -pedantic])
- fi
-fi
-
-dnl In principle we should put WARNING_CFLAGS in each Makefile.am like
+dnl We are only calling this for its side-effect of setting up
+dnl --enable-compile-warnings; the WARN_CFLAGS, etc. are ignored,
+dnl to work around https://github.com/peti/autoconf-archive/pull/96
+AX_COMPILER_FLAGS([], [], [$disable_developer])
+
+dnl Work around https://github.com/peti/autoconf-archive/pull/96 by using
+dnl a non-default variable name here (in particular there is no way to tell
+dnl AX_COMPILER_FLAGS to not use WARN_CXXFLAGS)
+AX_COMPILER_FLAGS_CFLAGS([EXTRA_CFLAGS],
+ [$disable_developer],
+ [$TEST_CFLAGS],
+ [-Wchar-subscripts \
+ -Wfloat-equal \
+ -Wpointer-sign \
+ $DISABLE_WARNINGS])
+dnl cc1plus: warning: command line option ‘-Wpointer-sign’ is valid for
+dnl C/ObjC but not for C++
+AX_COMPILER_FLAGS_CXXFLAGS([EXTRA_CXXFLAGS],
+ [$disable_developer],
+ [],
+ [-Wchar-subscripts \
+ -Wfloat-equal \
+ $DISABLE_WARNINGS])
+AX_COMPILER_FLAGS_LDFLAGS([EXTRA_LDFLAGS],
+ [$disable_developer])
+
+dnl TODO: In principle we should put EXTRA_CFLAGS in each Makefile.am like
dnl telepathy-glib does, since CFLAGS is meant to be reserved for the user...
dnl but prepending to CFLAGS (so the user can override it with later CFLAGS)
-dnl is the next best thing
-CFLAGS="$WARNING_CFLAGS $CFLAGS"
+dnl is the next best thing.
+CFLAGS="$EXTRA_CFLAGS $CFLAGS"
+CXXFLAGS="$EXTRA_CXXFLAGS $CXXFLAGS"
+LDFLAGS="$EXTRA_LDFLAGS $LDFLAGS"
case $host_os in
solaris*)
@@ -1544,6 +1414,11 @@ AM_CONDITIONAL(DBUS_CAN_UPLOAD_DOCS,
[test x$enable_doxygen_docs = xyes && test x$enable_xml_docs = xyes &&
test x$enable_ducktype_docs = xyes])
+# Autoconf 2.70 will support this, and many distros patch this option in,
+# but Autoconf 2.70 hasn't actually been released yet.
+AS_IF([test -z "${runstatedir}"], [runstatedir='${localstatedir}/run'])
+AC_SUBST([runstatedir])
+
#### Have to go $localstatedir->$prefix/var->/usr/local/var
#### find the actual value for $prefix that we'll end up with
@@ -1556,35 +1431,7 @@ AS_AC_EXPAND(EXPANDED_BINDIR, "$bindir")
AS_AC_EXPAND(EXPANDED_LIBDIR, "$libdir")
AS_AC_EXPAND(EXPANDED_LIBEXECDIR, "$libexecdir")
AS_AC_EXPAND(EXPANDED_DATADIR, "$datadir")
-
-#### Check our operating system
-operating_system=unknown
-if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then
- operating_system=redhat
-fi
-
-if test -f /etc/slackware-version || test -f $EXPANDED_SYSCONFDIR/slackware-version ; then
- operating_system=slackware
-fi
-
-if test -f /usr/bin/cygwin1.dll || test -f $EXPANDED_BINDIR/cygwin1.dll ; then
- operating_system=cygwin
-fi
-
-#### Sort out init scripts
-
-if test x$with_init_scripts = x; then
- case x$operating_system in
- xredhat) with_init_scripts=redhat ;;
- xslackware) with_init_scripts=slackware ;;
- xcygwin) with_init_scripts=cygwin ;;
- *) with_init_scripts=none ;;
- esac
-fi
-
-AM_CONDITIONAL(DBUS_INIT_SCRIPTS_RED_HAT, test x$with_init_scripts = xredhat)
-AM_CONDITIONAL(DBUS_INIT_SCRIPTS_SLACKWARE, test x$with_init_scripts = xslackware)
-AM_CONDITIONAL(DBUS_INIT_SCRIPTS_CYGWIN, test x$with_init_scripts = xcygwin)
+AS_AC_EXPAND(EXPANDED_RUNSTATEDIR, "$runstatedir")
##### systemd unit files
AC_ARG_WITH([systemdsystemunitdir],
@@ -1614,6 +1461,9 @@ AC_SUBST([systemduserunitdir], [$with_systemduserunitdir])
if ! test -z "$with_system_socket"; then
DBUS_SYSTEM_SOCKET=$with_system_socket
else
+ # We don't use runstatedir for this (yet?), because /var/run has been the
+ # interoperable system bus socket for 10+ years.
+ # See https://bugs.freedesktop.org/show_bug.cgi?id=101628
DBUS_SYSTEM_SOCKET=${EXPANDED_LOCALSTATEDIR}/run/dbus/system_bus_socket
fi
@@ -1642,23 +1492,17 @@ AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS, "$DBUS_SYSTEM_BUS_DEFAULT_AD
#### Set up the pid file
if ! test -z "$with_system_pid_file"; then
DBUS_SYSTEM_PID_FILE=$with_system_pid_file
-elif test x$with_init_scripts = xredhat ; then
- DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/messagebus.pid
else
- DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/dbus/pid
+ DBUS_SYSTEM_PID_FILE="${EXPANDED_RUNSTATEDIR}/dbus/pid"
fi
AC_SUBST(DBUS_SYSTEM_PID_FILE)
#### Directory to check for console ownership
-if ! test -z "$with_console_auth_dir"; then
- DBUS_CONSOLE_AUTH_DIR=$with_console_auth_dir
-else
- DBUS_CONSOLE_AUTH_DIR=/var/run/console/
-fi
-
-AC_SUBST(DBUS_CONSOLE_AUTH_DIR)
-AC_DEFINE_UNQUOTED(DBUS_CONSOLE_AUTH_DIR, "$DBUS_CONSOLE_AUTH_DIR", [Directory to check for console ownerhip])
+AS_IF([test -n "$with_console_auth_dir" && test "x$with_console_auth_dir" != xno],
+ [AC_DEFINE_UNQUOTED([DBUS_CONSOLE_AUTH_DIR], ["$with_console_auth_dir"],
+ [Directory to check for pam_console/pam_foreground flag files, or undefined])],
+ [with_console_auth_dir=])
#### File to check for console ownership
if test x$have_console_owner_file = xyes; then
@@ -1703,7 +1547,7 @@ AC_DEFINE_UNQUOTED(DBUS_DATADIR,"$DBUS_DATADIR", [Directory for installing DBUS
#### Directory to install dbus-daemon
if test -z "$with_dbus_daemondir" ; then
DBUS_DAEMONDIR=$EXPANDED_BINDIR
- dbus_daemondir='$bindir'
+ dbus_daemondir='${bindir}'
else
DBUS_DAEMONDIR=$with_dbus_daemondir
dbus_daemondir=$with_dbus_daemondir
@@ -1722,6 +1566,45 @@ DBUS_LIBEXECDIR="$EXPANDED_LIBEXECDIR"
AC_SUBST(DBUS_LIBEXECDIR)
AC_DEFINE_UNQUOTED(DBUS_LIBEXECDIR,"$DBUS_LIBEXECDIR", [Directory for installing the libexec binaries])
+AC_ARG_ENABLE([relocation],
+ [AS_HELP_STRING([--enable-relocation[=yes/no/auto]],
+ [Make pkg-config metadata relocatable [default=auto]])],
+ [], [enable_relocation=auto])
+
+can_relocate=yes
+
+AS_CASE(["${exec_prefix}"],
+ ['NONE'|'${prefix}'],
+ [:],
+ [*],
+ [can_relocate=no])
+
+AS_CASE(["${libdir}"],
+ ['${prefix}/lib'|'${prefix}/lib64'|'${exec_prefix}/lib'|'${exec_prefix}/lib64'],
+ [:],
+ [*],
+ [can_relocate=no])
+
+# If the user said --enable-relocation but we can't do it, error out
+AS_IF([test "x$can_relocate" = xno && test "x$enable_relocation" = xyes],
+ [AC_MSG_ERROR([Relocatable pkg-config metadata requires --exec-prefix='\${prefix}' and the default libdir])])
+
+# By default, on Windows we are relocatable if possible
+AS_IF([test "x$enable_relocation" = xauto && test "x$dbus_win" = xyes],
+ [enable_relocation="$can_relocate"])
+
+# By default, on non-Windows we are not relocatable because it can interfere
+# with pkg-config's ability to filter out system include directories,
+# resulting in linking an outdated system-wide library in preference to a
+# newer version installed elsewhere
+AS_IF([test "x$enable_relocation" = xauto],
+ [enable_relocation="no"])
+
+
+AS_IF([test "x$enable_relocation" = xyes],
+ [AC_SUBST([pkgconfig_prefix], ['${pcfiledir}/../../'])],
+ [AC_SUBST([pkgconfig_prefix], ['${original_prefix}'])])
+
#### Directory to source sysconfdir configuration from
# On Windows this is relative to where we put the bus setup, in
@@ -1752,14 +1635,9 @@ DBUS_TEST_DATA="$DBUS_PWD/test/data"
AC_SUBST([DBUS_TEST_DATA])
AC_SUBST([DBUS_TEST_EXEC])
-AC_DEFINE_UNQUOTED([DBUS_TEST_EXEC], ["$DBUS_TEST_EXEC"],
- [Full path to the daemon in the builddir])
AC_DEFINE_UNQUOTED([DBUS_EXEEXT], ["$EXEEXT"],
[Extension for executables, typically empty or .exe])
-AC_DEFINE_UNQUOTED(TEST_BUS_LAUNCH_BINARY, ["$DBUS_PWD/tools/dbus-launch$EXEEXT"],
- [Full path to the dbus-launch in the builddir])
-
## Export the non-setuid external helper
TEST_LAUNCH_HELPER_BINARY="$DBUS_PWD/bus/dbus-daemon-launch-helper-test$EXEEXT"
AC_SUBST(TEST_LAUNCH_HELPER_BINARY)
@@ -1915,14 +1793,13 @@ bus/legacy-config/system.conf
bus/legacy-config/session.conf
bus/example-system-enable-stats.conf
bus/example-session-disable-stats.conf
-bus/messagebus
-bus/messagebus-config
bus/org.freedesktop.dbus-session.plist
-bus/rc.messagebus
bus/dbus.service
bus/dbus.socket
bus/systemd-user/dbus.service
bus/systemd-user/dbus.socket
+bus/sysusers.d/dbus.conf
+bus/tmpfiles.d/dbus.conf
Makefile
dbus/Makefile
bus/Makefile
@@ -1960,6 +1837,8 @@ test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServ
test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service
test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service
test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service
+cmake/DBus1Config.cmake:cmake/DBus1Config.pkgconfig.in
+cmake/DBus1ConfigVersion.cmake
])
AC_OUTPUT
@@ -1975,12 +1854,14 @@ echo "
bindir: ${EXPANDED_BINDIR}
sysconfdir: ${EXPANDED_SYSCONFDIR}
localstatedir: ${EXPANDED_LOCALSTATEDIR}
+ runstatedir: ${EXPANDED_RUNSTATEDIR}
datadir: ${EXPANDED_DATADIR}
source code location: ${srcdir}
compiler: ${CC}
cflags: ${CFLAGS}
cppflags: ${CPPFLAGS}
cxxflags: ${CXXFLAGS}
+ ldflags: ${LDFLAGS}
64-bit int: ${DBUS_INT64_TYPE}
32-bit int: ${DBUS_INT32_TYPE}
16-bit int: ${DBUS_INT16_TYPE}
@@ -1991,7 +1872,7 @@ echo "
echo "
Rebuilding generated files: ${USE_MAINTAINER_MODE}
- gcc coverage profiling: ${enable_compiler_coverage}
+ gcc coverage profiling: ${enable_code_coverage}
Building embedded tests: ${enable_embedded_tests}
Building modular tests: ${enable_modular_tests}
- with GLib: ${with_glib}
@@ -2020,7 +1901,7 @@ echo "
System bus PID file: ${DBUS_SYSTEM_PID_FILE}
Session bus listens on: ${DBUS_SESSION_BUS_LISTEN_ADDRESS}
Session clients connect to: ${DBUS_SESSION_BUS_CONNECT_ADDRESS}
- Console auth dir: ${DBUS_CONSOLE_AUTH_DIR}
+ pam_console auth dir: ${with_console_auth_dir:-(none)}
Console owner file: ${have_console_owner_file}
Console owner file path: ${DBUS_CONSOLE_OWNER_FILE}
System bus user: ${DBUS_USER}
@@ -2038,9 +1919,9 @@ fi
if test x$enable_embedded_tests = xyes -a x$enable_asserts = xno; then
echo "NOTE: building with embedded tests but without assertions means tests may not properly report failures (this configuration is only useful when doing something like profiling the tests)"
fi
-if test x$enable_compiler_coverage = xyes; then
- echo "NOTE: building with coverage profiling is definitely for developers only."
-fi
+AS_IF([test x$enable_code_coverage = xyes],[
+ AC_MSG_WARN([Building with coverage profiling is definitely for developers only.])
+ ])
if test x$enable_verbose_mode = xyes; then
echo "NOTE: building with verbose mode increases library size, may slightly increase security risk, and decreases performance."
fi
diff --git a/dbus-1.pc.in b/dbus-1.pc.in
index f93d1563..3581be6e 100644
--- a/dbus-1.pc.in
+++ b/dbus-1.pc.in
@@ -1,4 +1,5 @@
-prefix=@prefix@
+original_prefix=@prefix@
+prefix=@pkgconfig_prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 885c63d8..adcf8e2d 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -2,6 +2,7 @@
dbusdatadir=$(datadir)/dbus-1
AM_CPPFLAGS = \
+ $(CODE_COVERAGE_CPPFLAGS) \
-I$(top_builddir) \
-I$(top_srcdir) \
$(DBUS_STATIC_BUILD_CPPFLAGS) \
@@ -11,9 +12,12 @@ AM_CPPFLAGS = \
-DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
-DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \
-DDBUS_SESSION_CONFIG_FILE=\""$(dbusdatadir)/session.conf"\" \
+ -DDBUS_RUNSTATEDIR=\""$(runstatedir)"\" \
$(NULL)
-AM_CFLAGS =
+AM_CFLAGS = \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(NULL)
if HAVE_VISIBILITY
if !DBUS_WIN
@@ -33,30 +37,18 @@ dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus
lib_LTLIBRARIES=libdbus-1.la
+# Initialize to empty so that we can append later
+nodist_libdbus_1_la_SOURCES =
+
#
# Deal with W32 .def and version-info.rc stuff
#
if DBUS_WIN
-SUFFIXES = rc
-
-.rc.o:
- $(WINDRES) $< -o $@
-
-dbus_res = versioninfo.o
-dbus_res_ldflag = -Wl,$(dbus_res)
-no_undefined = -no-undefined
-export_symbols =
+SUFFIXES = .rc
-EXTRA_libdbus_1_la_DEPENDENCIES = $(dbus_res)
-intllibs =
-
-else
-dbus_res =
-dbus_res_ldflag =
-no_undefined =
-
-intllibs = @LTLIBINTL@
+.rc.lo:
+ $(LIBTOOL) $(AM_V_lt) --tag=RC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(RC) $< -o $@
endif
@@ -67,7 +59,12 @@ endif
if DBUS_WIN
DBUS_LIB_arch_sources = \
dbus-server-win.c \
- dbus-server-win.h
+ dbus-server-win.h \
+ $(NULL)
+
+nodist_libdbus_1_la_SOURCES += \
+ versioninfo.rc \
+ $(NULL)
if DBUS_WINCE
wince_source = dbus-sysdeps-wince-glue.h dbus-sysdeps-wince-glue.c
@@ -284,6 +281,10 @@ DBUS_UTIL_SOURCES= \
dbus-test.c \
dbus-test.h
+if DBUS_ENABLE_EMBEDDED_TESTS
+DBUS_UTIL_SOURCES += dbus-spawn-test.c
+endif
+
libdbus_1_la_SOURCES= \
$(DBUS_LIB_SOURCES) \
$(DBUS_SHARED_SOURCES)
@@ -332,6 +333,10 @@ libdbus_internal_la_LIBADD += $(LIBDBUSPOLICY1_LIBS)
endif
if DBUS_WIN
+AM_CXXFLAGS = \
+ $(CODE_COVERAGE_CXXFLAGS) \
+ $(NULL)
+
# This must be a separate convenience library, otherwise libtool notices
# that libdbus-1 might contain C++, links it with g++ and links in libstdc++,
# even on Unix where in fact it doesn't contain any C++. For Windows, where
@@ -353,6 +358,8 @@ test_dbus_SOURCES= \
test_dbus_LDADD = libdbus-internal.la
-## mop up the gcov files
+# Add rules for code-coverage testing, as defined by AX_CODE_COVERAGE
+include $(top_srcdir)/aminclude_static.am
+
clean-local:
- /bin/rm *.bb *.bbg *.da *.gcov .libs/*.da .libs/*.bbg || true
+ $(AM_V_at)rm -fr ./.dbus-keyrings
diff --git a/dbus/dbus-address.c b/dbus/dbus-address.c
index c4cfbbe5..66b26d58 100644
--- a/dbus/dbus-address.c
+++ b/dbus/dbus-address.c
@@ -112,7 +112,7 @@ _dbus_address_append_escaped (DBusString *escaped,
ret = FALSE;
orig_len = _dbus_string_get_length (escaped);
- p = (const unsigned char *) _dbus_string_get_const_data (unescaped);
+ p = _dbus_string_get_const_udata (unescaped);
end = p + _dbus_string_get_length (unescaped);
while (p != end)
{
@@ -354,14 +354,14 @@ append_unescaped_value (DBusString *unescaped,
* in the semicolon-separated list should be tried first.
*
* @param address the address.
- * @param entry return location to an array of entries.
+ * @param entry_result return location to an array of entries.
* @param array_len return location for array length.
* @param error address where an error can be returned.
* @returns #TRUE on success, #FALSE otherwise.
*/
dbus_bool_t
dbus_parse_address (const char *address,
- DBusAddressEntry ***entry,
+ DBusAddressEntry ***entry_result,
int *array_len,
DBusError *error)
{
@@ -553,7 +553,7 @@ dbus_parse_address (const char *address,
}
_dbus_list_clear (&entries);
- *entry = entry_array;
+ *entry_result = entry_array;
return TRUE;
@@ -717,7 +717,7 @@ _dbus_address_test (void)
if (strcmp (escaped, test->escaped) != 0)
{
- _dbus_warn ("Escaped '%s' as '%s' should have been '%s'\n",
+ _dbus_warn ("Escaped '%s' as '%s' should have been '%s'",
test->unescaped, escaped, test->escaped);
exit (1);
}
@@ -726,7 +726,7 @@ _dbus_address_test (void)
unescaped = dbus_address_unescape_value (test->escaped, &error);
if (unescaped == NULL)
{
- _dbus_warn ("Failed to unescape '%s': %s\n",
+ _dbus_warn ("Failed to unescape '%s': %s",
test->escaped, error.message);
dbus_error_free (&error);
exit (1);
@@ -734,7 +734,7 @@ _dbus_address_test (void)
if (strcmp (unescaped, test->unescaped) != 0)
{
- _dbus_warn ("Unescaped '%s' as '%s' should have been '%s'\n",
+ _dbus_warn ("Unescaped '%s' as '%s' should have been '%s'",
test->escaped, unescaped, test->unescaped);
exit (1);
}
@@ -752,7 +752,7 @@ _dbus_address_test (void)
&error);
if (unescaped != NULL)
{
- _dbus_warn ("Should not have successfully unescaped '%s' to '%s'\n",
+ _dbus_warn ("Should not have successfully unescaped '%s' to '%s'",
invalid_escaped_values[i], unescaped);
dbus_free (unescaped);
exit (1);
diff --git a/dbus/dbus-address.h b/dbus/dbus-address.h
index e51ef0ae..fefb320e 100644
--- a/dbus/dbus-address.h
+++ b/dbus/dbus-address.h
@@ -42,7 +42,7 @@ typedef struct DBusAddressEntry DBusAddressEntry;
DBUS_EXPORT
dbus_bool_t dbus_parse_address (const char *address,
- DBusAddressEntry ***entry,
+ DBusAddressEntry ***entry_result,
int *array_len,
DBusError *error);
DBUS_EXPORT
@@ -59,6 +59,25 @@ DBUS_EXPORT
char* dbus_address_unescape_value (const char *value,
DBusError *error);
+/**
+ * Clear a variable or struct member that contains an array of #DBusAddressEntry.
+ * If it does not contain #NULL, the entries that were previously
+ * there are freed with dbus_address_entries_free().
+ *
+ * This is similar to dbus_clear_connection(): see that function
+ * for more details.
+ *
+ * @param pointer_to_entries A pointer to a variable or struct member.
+ * pointer_to_entries must not be #NULL, but *pointer_to_entries
+ * may be #NULL.
+ */
+static inline void
+dbus_clear_address_entries (DBusAddressEntry ***pointer_to_entries)
+{
+ _dbus_clear_pointer_impl (DBusAddressEntry *, pointer_to_entries,
+ dbus_address_entries_free);
+}
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-asv-util.c b/dbus/dbus-asv-util.c
index d3ac5e9c..fbb2e51e 100644
--- a/dbus/dbus-asv-util.c
+++ b/dbus/dbus-asv-util.c
@@ -80,7 +80,7 @@ _dbus_asv_new_method_return (DBusMessage *message,
* @param var_iter will be initialized to append (i.e. write) to the variant
* @returns #TRUE on success, or #FALSE if not enough memory
*/
-static dbus_bool_t
+dbus_bool_t
_dbus_asv_open_entry (DBusMessageIter *arr_iter,
DBusMessageIter *entry_iter,
const char *key,
@@ -118,7 +118,7 @@ _dbus_asv_open_entry (DBusMessageIter *arr_iter,
* @param var_iter the iterator appending to the variant, will be closed
* @returns #TRUE on success, or #FALSE if not enough memory
*/
-static dbus_bool_t
+dbus_bool_t
_dbus_asv_close_entry (DBusMessageIter *arr_iter,
DBusMessageIter *entry_iter,
DBusMessageIter *var_iter)
@@ -162,7 +162,7 @@ _dbus_asv_close (DBusMessageIter *iter,
* @param arr_iter the iterator appending to the array, will be closed
* @returns #TRUE on success, or #FALSE if not enough memory
*/
-static void
+void
_dbus_asv_abandon_entry (DBusMessageIter *arr_iter,
DBusMessageIter *entry_iter,
DBusMessageIter *var_iter)
diff --git a/dbus/dbus-asv-util.h b/dbus/dbus-asv-util.h
index 94968947..062c99c5 100644
--- a/dbus/dbus-asv-util.h
+++ b/dbus/dbus-asv-util.h
@@ -52,4 +52,22 @@ dbus_bool_t _dbus_asv_add_byte_array (DBusMessageIter *arr_iter,
const char *key,
const void *value,
int n_elements);
+
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_asv_open_entry (DBusMessageIter *arr_iter,
+ DBusMessageIter *entry_iter,
+ const char *key,
+ const char *type,
+ DBusMessageIter *var_iter);
+
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_asv_close_entry (DBusMessageIter *arr_iter,
+ DBusMessageIter *entry_iter,
+ DBusMessageIter *var_iter);
+
+DBUS_PRIVATE_EXPORT
+void _dbus_asv_abandon_entry (DBusMessageIter *arr_iter,
+ DBusMessageIter *entry_iter,
+ DBusMessageIter *var_iter);
+
#endif
diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c
index aaaed30d..475004b3 100644
--- a/dbus/dbus-auth-script.c
+++ b/dbus/dbus-auth-script.c
@@ -34,6 +34,8 @@
#include "dbus-credentials.h"
#include "dbus-internals.h"
+#include "test/test-utils.h"
+
/**
* @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
* @ingroup DBusInternals
@@ -75,7 +77,7 @@ append_quoted_string (DBusString *dest,
a = '\\';
else
{
- _dbus_warn ("bad backslashed byte %c\n", b);
+ _dbus_warn ("bad backslashed byte %c", b);
return FALSE;
}
@@ -146,7 +148,7 @@ auth_state_from_string (const DBusString *str)
else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED"))
return DBUS_AUTH_STATE_AUTHENTICATED;
else
- return -1;
+ return DBUS_AUTH_STATE_INVALID;
}
static const char*
@@ -164,6 +166,10 @@ auth_state_to_string (DBusAuthState state)
return "NEED_DISCONNECT";
case DBUS_AUTH_STATE_AUTHENTICATED:
return "AUTHENTICATED";
+ case DBUS_AUTH_STATE_INVALID:
+ return "INVALID";
+ default:
+ break;
}
return "unknown";
@@ -285,7 +291,7 @@ _dbus_auth_script_run (const DBusString *filename)
}
if (!_dbus_file_get_contents (&file, filename, &error)) {
- _dbus_warn ("Getting contents of %s failed: %s\n",
+ _dbus_warn ("Getting contents of %s failed: %s",
_dbus_string_get_const_data (filename), error.message);
dbus_error_free (&error);
goto out;
@@ -299,7 +305,7 @@ _dbus_auth_script_run (const DBusString *filename)
{
line_no += 1;
- /* _dbus_warn ("%s\n", _dbus_string_get_const_data (&line)); */
+ /* _dbus_warn ("%s", _dbus_string_get_const_data (&line)); */
_dbus_string_delete_leading_blanks (&line);
@@ -370,14 +376,14 @@ _dbus_auth_script_run (const DBusString *filename)
if (auth != NULL)
{
- _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
+ _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)");
goto out;
}
auth = _dbus_auth_client_new ();
if (auth == NULL)
{
- _dbus_warn ("no memory to create DBusAuth\n");
+ _dbus_warn ("no memory to create DBusAuth");
goto out;
}
@@ -388,7 +394,7 @@ _dbus_auth_script_run (const DBusString *filename)
creds = _dbus_credentials_new_from_current_process ();
if (creds == NULL)
{
- _dbus_warn ("no memory for credentials\n");
+ _dbus_warn ("no memory for credentials");
_dbus_auth_unref (auth);
auth = NULL;
goto out;
@@ -396,7 +402,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_auth_set_credentials (auth, creds))
{
- _dbus_warn ("no memory for setting credentials\n");
+ _dbus_warn ("no memory for setting credentials");
_dbus_auth_unref (auth);
auth = NULL;
_dbus_credentials_unref (creds);
@@ -412,14 +418,14 @@ _dbus_auth_script_run (const DBusString *filename)
if (auth != NULL)
{
- _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
+ _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)");
goto out;
}
auth = _dbus_auth_server_new (&guid);
if (auth == NULL)
{
- _dbus_warn ("no memory to create DBusAuth\n");
+ _dbus_warn ("no memory to create DBusAuth");
goto out;
}
@@ -430,7 +436,7 @@ _dbus_auth_script_run (const DBusString *filename)
creds = _dbus_credentials_new_from_current_process ();
if (creds == NULL)
{
- _dbus_warn ("no memory for credentials\n");
+ _dbus_warn ("no memory for credentials");
_dbus_auth_unref (auth);
auth = NULL;
goto out;
@@ -438,7 +444,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_auth_set_credentials (auth, creds))
{
- _dbus_warn ("no memory for setting credentials\n");
+ _dbus_warn ("no memory for setting credentials");
_dbus_auth_unref (auth);
auth = NULL;
_dbus_credentials_unref (creds);
@@ -451,7 +457,7 @@ _dbus_auth_script_run (const DBusString *filename)
}
else if (auth == NULL)
{
- _dbus_warn ("must specify CLIENT or SERVER\n");
+ _dbus_warn ("must specify CLIENT or SERVER");
goto out;
}
@@ -489,13 +495,13 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_init (&to_send))
{
- _dbus_warn ("no memory to allocate string\n");
+ _dbus_warn ("no memory to allocate string");
goto out;
}
if (!append_quoted_string (&to_send, &line))
{
- _dbus_warn ("failed to append quoted string line %d\n",
+ _dbus_warn ("failed to append quoted string line %d",
line_no);
_dbus_string_free (&to_send);
goto out;
@@ -505,7 +511,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_append (&to_send, "\r\n"))
{
- _dbus_warn ("failed to append \r\n from line %d\n",
+ _dbus_warn ("failed to append \\r\\n from line %d",
line_no);
_dbus_string_free (&to_send);
goto out;
@@ -514,22 +520,56 @@ _dbus_auth_script_run (const DBusString *filename)
/* Replace USERID_HEX with our username in hex */
{
int where;
-
- if (_dbus_string_find (&to_send, 0,
- "USERID_HEX", &where))
+
+ if (_dbus_string_find (&to_send, 0, "WRONG_USERID_HEX", &where))
+ {
+ /* This must be checked for before USERID_HEX, because
+ * that's a substring. */
+ DBusString uid;
+
+ if (!_dbus_string_init (&uid))
+ {
+ _dbus_warn ("no memory for uid");
+ _dbus_string_free (&to_send);
+ goto out;
+ }
+
+ if (!_dbus_test_append_different_uid (&uid))
+ {
+ _dbus_warn ("no memory for uid");
+ _dbus_string_free (&to_send);
+ _dbus_string_free (&uid);
+ goto out;
+ }
+
+ _dbus_string_delete (&to_send, where,
+ (int) strlen ("WRONG_USERID_HEX"));
+
+ if (!_dbus_string_hex_encode (&uid, 0, &to_send, where))
+ {
+ _dbus_warn ("no memory to subst WRONG_USERID_HEX");
+ _dbus_string_free (&to_send);
+ _dbus_string_free (&uid);
+ goto out;
+ }
+
+ _dbus_string_free (&uid);
+ }
+ else if (_dbus_string_find (&to_send, 0,
+ "USERID_HEX", &where))
{
DBusString username;
if (!_dbus_string_init (&username))
{
- _dbus_warn ("no memory for userid\n");
+ _dbus_warn ("no memory for userid");
_dbus_string_free (&to_send);
goto out;
}
if (!_dbus_append_user_from_current_process (&username))
{
- _dbus_warn ("no memory for userid\n");
+ _dbus_warn ("no memory for userid");
_dbus_string_free (&username);
_dbus_string_free (&to_send);
goto out;
@@ -540,13 +580,58 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_hex_encode (&username, 0,
&to_send, where))
{
- _dbus_warn ("no memory to subst USERID_HEX\n");
+ _dbus_warn ("no memory to subst USERID_HEX");
+ _dbus_string_free (&username);
+ _dbus_string_free (&to_send);
+ goto out;
+ }
+
+ _dbus_string_free (&username);
+ }
+ else if (_dbus_string_find (&to_send, 0,
+ "WRONG_USERNAME_HEX", &where))
+ {
+ /* This must be checked for before USERNAME_HEX, because
+ * that's a substring. */
+#ifdef DBUS_UNIX
+ DBusString username;
+
+ if (!_dbus_string_init (&username))
+ {
+ _dbus_warn ("no memory for username");
+ _dbus_string_free (&to_send);
+ goto out;
+ }
+
+ if (!_dbus_test_append_different_username (&username))
+ {
+ _dbus_warn ("no memory for username");
+ _dbus_string_free (&to_send);
_dbus_string_free (&username);
+ goto out;
+ }
+
+ _dbus_string_delete (&to_send, where,
+ (int) strlen ("WRONG_USERNAME_HEX"));
+
+ if (!_dbus_string_hex_encode (&username, 0,
+ &to_send, where))
+ {
+ _dbus_warn ("no memory to subst WRONG_USERNAME_HEX");
_dbus_string_free (&to_send);
+ _dbus_string_free (&username);
goto out;
}
_dbus_string_free (&username);
+#else
+ /* No authentication mechanism uses the login name on
+ * Windows, so there's no point in it appearing in an
+ * auth script that is not UNIX_ONLY. */
+ _dbus_warn ("WRONG_USERNAME_HEX cannot be used on Windows");
+ _dbus_string_free (&to_send);
+ goto out;
+#endif
}
else if (_dbus_string_find (&to_send, 0,
"USERNAME_HEX", &where))
@@ -555,14 +640,14 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_init (&username))
{
- _dbus_warn ("no memory for username\n");
+ _dbus_warn ("no memory for username");
_dbus_string_free (&to_send);
goto out;
}
if (!_dbus_append_user_from_current_process (&username))
{
- _dbus_warn ("no memory for username\n");
+ _dbus_warn ("no memory for username");
_dbus_string_free (&username);
_dbus_string_free (&to_send);
goto out;
@@ -573,7 +658,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_hex_encode (&username, 0,
&to_send, where))
{
- _dbus_warn ("no memory to subst USERNAME_HEX\n");
+ _dbus_warn ("no memory to subst USERNAME_HEX");
_dbus_string_free (&username);
_dbus_string_free (&to_send);
goto out;
@@ -590,7 +675,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_copy (&to_send, 0,
buffer, _dbus_string_get_length (buffer)))
{
- _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
+ _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state");
_dbus_string_free (&to_send);
_dbus_auth_return_buffer (auth, buffer);
goto out;
@@ -611,13 +696,13 @@ _dbus_auth_script_run (const DBusString *filename)
expected = auth_state_from_string (&line);
if (expected < 0)
{
- _dbus_warn ("bad auth state given to EXPECT_STATE\n");
+ _dbus_warn ("bad auth state given to EXPECT_STATE");
goto parse_failed;
}
if (expected != state)
{
- _dbus_warn ("expected auth state %s but got %s on line %d\n",
+ _dbus_warn ("expected auth state %s but got %s on line %d",
auth_state_to_string (expected),
auth_state_to_string (state),
line_no);
@@ -633,13 +718,13 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_init (&received))
{
- _dbus_warn ("no mem to allocate string received\n");
+ _dbus_warn ("no mem to allocate string received");
goto out;
}
if (!_dbus_string_pop_line (&from_auth, &received))
{
- _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
+ _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d",
_dbus_string_get_const_data (&line), line_no);
_dbus_string_free (&received);
goto out;
@@ -647,7 +732,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (!same_first_word (&received, &line))
{
- _dbus_warn ("line %d expected command '%s' and got '%s'\n",
+ _dbus_warn ("line %d expected command '%s' and got '%s'",
line_no,
_dbus_string_get_const_data (&line),
_dbus_string_get_const_data (&received));
@@ -667,13 +752,13 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_init (&expected))
{
- _dbus_warn ("no mem to allocate string expected\n");
+ _dbus_warn ("no mem to allocate string expected");
goto out;
}
if (!append_quoted_string (&expected, &line))
{
- _dbus_warn ("failed to append quoted string line %d\n",
+ _dbus_warn ("failed to append quoted string line %d",
line_no);
_dbus_string_free (&expected);
goto out;
@@ -688,7 +773,7 @@ _dbus_auth_script_run (const DBusString *filename)
}
else
{
- _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
+ _dbus_warn ("Expected unused bytes '%s' and have '%s'",
_dbus_string_get_const_data (&expected),
_dbus_string_get_const_data (unused));
_dbus_string_free (&expected);
@@ -703,7 +788,7 @@ _dbus_auth_script_run (const DBusString *filename)
authorized_identity = _dbus_auth_get_identity (auth);
if (!_dbus_credentials_are_anonymous (authorized_identity))
{
- _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
+ _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized");
goto out;
}
}
@@ -715,7 +800,7 @@ _dbus_auth_script_run (const DBusString *filename)
authorized_identity = _dbus_auth_get_identity (auth);
if (_dbus_credentials_are_anonymous (authorized_identity))
{
- _dbus_warn ("Expected to have some credentials, but we don't\n");
+ _dbus_warn ("Expected to have some credentials, but we don't");
goto out;
}
}
@@ -728,13 +813,13 @@ _dbus_auth_script_run (const DBusString *filename)
if (!_dbus_string_init (&expected))
{
- _dbus_warn ("no mem to allocate string expected\n");
+ _dbus_warn ("no mem to allocate string expected");
goto out;
}
if (!append_quoted_string (&expected, &line))
{
- _dbus_warn ("failed to append quoted string line %d\n",
+ _dbus_warn ("failed to append quoted string line %d",
line_no);
_dbus_string_free (&expected);
goto out;
@@ -749,7 +834,7 @@ _dbus_auth_script_run (const DBusString *filename)
}
else
{
- _dbus_warn ("Expected exact string '%s' and have '%s'\n",
+ _dbus_warn ("Expected exact string '%s' and have '%s'",
_dbus_string_get_const_data (&expected),
_dbus_string_get_const_data (&from_auth));
_dbus_string_free (&expected);
@@ -763,7 +848,7 @@ _dbus_auth_script_run (const DBusString *filename)
parse_failed:
{
- _dbus_warn ("couldn't process line %d \"%s\"\n",
+ _dbus_warn ("couldn't process line %d \"%s\"",
line_no, _dbus_string_get_const_data (&line));
goto out;
}
@@ -771,7 +856,7 @@ _dbus_auth_script_run (const DBusString *filename)
if (auth == NULL)
{
- _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER\n");
+ _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER");
goto out;
}
else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
@@ -782,15 +867,15 @@ _dbus_auth_script_run (const DBusString *filename)
if (_dbus_string_get_length (unused) > 0)
{
- _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)\n");
+ _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)");
goto out;
}
}
if (_dbus_string_get_length (&from_auth) > 0)
{
- _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth\n");
- _dbus_warn ("Leftover data: %s\n", _dbus_string_get_const_data (&from_auth));
+ _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth");
+ _dbus_warn ("Leftover data: %s", _dbus_string_get_const_data (&from_auth));
goto out;
}
diff --git a/dbus/dbus-auth-util.c b/dbus/dbus-auth-util.c
index 10cbc490..b1a5ee4a 100644
--- a/dbus/dbus-auth-util.c
+++ b/dbus/dbus-auth-util.c
@@ -51,7 +51,7 @@ process_test_subdir (const DBusString *test_base_dir,
dir = NULL;
if (!_dbus_string_init (&test_directory))
- _dbus_assert_not_reached ("didn't allocate test_directory\n");
+ _dbus_assert_not_reached ("didn't allocate test_directory");
_dbus_string_init_const (&filename, subdir);
@@ -64,12 +64,12 @@ process_test_subdir (const DBusString *test_base_dir,
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
- _dbus_assert_not_reached ("didn't allocate filename string\n");
+ _dbus_assert_not_reached ("didn't allocate filename string");
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
- _dbus_warn ("Could not open %s: %s\n",
+ _dbus_warn ("Could not open %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -113,7 +113,7 @@ process_test_subdir (const DBusString *test_base_dir,
if (dbus_error_is_set (&error))
{
- _dbus_warn ("Could not get next file in %s: %s\n",
+ _dbus_warn ("Could not get next file in %s: %s",
_dbus_string_get_const_data (&test_directory), error.message);
dbus_error_free (&error);
goto failed;
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index bd348aa6..330fb8fb 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -282,6 +282,9 @@ static const DBusAuthStateData client_state_need_send_auth = {
static const DBusAuthStateData client_state_waiting_for_data = {
"WaitingForData", handle_client_state_waiting_for_data
};
+/* The WaitingForOK state doesn't appear to be used.
+ * See https://bugs.freedesktop.org/show_bug.cgi?id=97298 */
+_DBUS_GNUC_UNUSED
static const DBusAuthStateData client_state_waiting_for_ok = {
"WaitingForOK", handle_client_state_waiting_for_ok
};
@@ -704,7 +707,9 @@ sha1_handle_first_client_response (DBusAuth *auth,
_dbus_string_free (&tmp);
_dbus_string_zero (&tmp2);
_dbus_string_free (&tmp2);
- _dbus_credentials_unref (&myself);
+
+ if (myself != NULL)
+ _dbus_credentials_unref (myself);
return retval;
}
@@ -1512,9 +1517,14 @@ send_rejected (DBusAuth *auth)
"REJECTED"))
goto nomem;
- i = 0;
- while (all_mechanisms[i].mechanism != NULL)
+ for (i = 0; all_mechanisms[i].mechanism != NULL; i++)
{
+ /* skip mechanisms that aren't allowed */
+ if (auth->allowed_mechs != NULL &&
+ !_dbus_string_array_contains ((const char**)auth->allowed_mechs,
+ all_mechanisms[i].mechanism))
+ continue;
+
if (!_dbus_string_append (&command,
" "))
goto nomem;
@@ -1522,8 +1532,6 @@ send_rejected (DBusAuth *auth)
if (!_dbus_string_append (&command,
all_mechanisms[i].mechanism))
goto nomem;
-
- ++i;
}
if (!_dbus_string_append (&command, "\r\n"))
@@ -2897,6 +2905,45 @@ _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
return auth->unix_fd_negotiated;
}
+/**
+ * Queries whether the given auth mechanism is supported.
+ *
+ * @param auth the auth mechanism to query for
+ * @returns #TRUE when auth mechanism is supported
+ */
+dbus_bool_t
+_dbus_auth_is_supported_mechanism (DBusString *name)
+{
+ _dbus_assert (name != NULL);
+
+ return find_mech (name, NULL) != NULL;
+}
+
+/**
+ * Return a human-readable string containing all supported auth mechanisms.
+ *
+ * @param string to hold the supported auth mechanisms
+ * @returns #FALSE on oom
+ */
+dbus_bool_t
+_dbus_auth_dump_supported_mechanisms (DBusString *buffer)
+{
+ unsigned int i;
+ _dbus_assert (buffer != NULL);
+
+ for (i = 0; all_mechanisms[i].mechanism != NULL; i++)
+ {
+ if (i > 0)
+ {
+ if (!_dbus_string_append (buffer, ", "))
+ return FALSE;
+ }
+ if (!_dbus_string_append (buffer, all_mechanisms[i].mechanism))
+ return FALSE;
+ }
+ return TRUE;
+}
+
/** @} */
/* tests in dbus-auth-util.c */
diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h
index d10161f1..e2d86a4b 100644
--- a/dbus/dbus-auth.h
+++ b/dbus/dbus-auth.h
@@ -38,7 +38,8 @@ typedef enum
DBUS_AUTH_STATE_WAITING_FOR_MEMORY,
DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND,
DBUS_AUTH_STATE_NEED_DISCONNECT,
- DBUS_AUTH_STATE_AUTHENTICATED
+ DBUS_AUTH_STATE_AUTHENTICATED,
+ DBUS_AUTH_STATE_INVALID = -1
} DBusAuthState;
DBUS_PRIVATE_EXPORT
@@ -93,6 +94,10 @@ const char* _dbus_auth_get_guid_from_server(DBusAuth *auth);
void _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b);
dbus_bool_t _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth);
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_auth_is_supported_mechanism(DBusString *name);
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_auth_dump_supported_mechanisms(DBusString *buffer);
DBUS_END_DECLS
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index 6c66e1c9..a7f31cd1 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -105,7 +105,7 @@ addresses_shutdown_func (void *data)
while (i < N_BUS_TYPES)
{
if (bus_connections[i] != NULL)
- _dbus_warn_check_failed ("dbus_shutdown() called but connections were still live. This probably means the application did not drop all its references to bus connections.\n");
+ _dbus_warn_check_failed ("dbus_shutdown() called but connections were still live. This probably means the application did not drop all its references to bus connections.");
dbus_free (bus_connection_addresses[i]);
bus_connection_addresses[i] = NULL;
@@ -168,9 +168,9 @@ init_session_address (void)
else if (supported && !retval)
{
if (dbus_error_is_set(&error))
- _dbus_warn ("Dynamic session lookup supported but failed: %s\n", error.message);
+ _dbus_warn ("Dynamic session lookup supported but failed: %s", error.message);
else
- _dbus_warn ("Dynamic session lookup supported but failed silently\n");
+ _dbus_warn ("Dynamic session lookup supported but failed silently");
}
_dbus_string_free (&addr);
}
@@ -940,7 +940,7 @@ dbus_bus_get_unix_user (DBusConnection *connection,
* probably the bus ID is not useful; instead, use the machine ID
* since it's accessible without necessarily connecting to the bus and
* may be persistent beyond a single bus instance (across reboots for
- * example). See dbus_get_local_machine_id().
+ * example). See dbus_try_get_local_machine_id().
*
* In addition to an ID for each bus and an ID for each machine, there is
* an ID for each address that the bus is listening on; that can
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 420dfb84..4b87da79 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -2334,10 +2334,11 @@ complete_pending_call_and_unlock (DBusConnection *connection,
{
_dbus_pending_call_set_reply_unlocked (pending, message);
_dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
+ _dbus_pending_call_start_completion_unlocked(pending);
_dbus_connection_detach_pending_call_and_unlock (connection, pending);
-
+
/* Must be called unlocked since it invokes app callback */
- _dbus_pending_call_complete (pending);
+ _dbus_pending_call_finish_completion (pending);
dbus_pending_call_unref (pending);
}
@@ -2842,8 +2843,8 @@ dbus_connection_unref (DBusConnection *connection)
{
_dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
connection->shareable ?
- "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
- "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
+ "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
+ "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
return;
}
#endif
@@ -2950,7 +2951,7 @@ dbus_connection_close (DBusConnection *connection)
{
CONNECTION_UNLOCK (connection);
- _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
+ _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
return;
}
#endif
@@ -3068,7 +3069,7 @@ dbus_connection_get_is_anonymous (DBusConnection *connection)
* dbus_bus_get_id() instead (which is just a convenience wrapper
* around the org.freedesktop.DBus.GetId method invoked on the bus).
*
- * You can also get a machine ID; see dbus_get_local_machine_id() to
+ * You can also get a machine ID; see dbus_try_get_local_machine_id() to
* get the machine you are on. There isn't a convenience wrapper, but
* you can invoke org.freedesktop.DBus.Peer.GetMachineId on any peer
* to get the machine ID on the other end.
@@ -5775,7 +5776,7 @@ dbus_connection_remove_filter (DBusConnection *connection,
#ifndef DBUS_DISABLE_CHECKS
if (filter == NULL)
{
- _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
+ _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
function, user_data);
return;
}
@@ -5894,7 +5895,7 @@ dbus_connection_register_object_path (DBusConnection *connection,
if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
- _dbus_warn ("%s\n", error.message);
+ _dbus_warn ("%s", error.message);
dbus_error_free (&error);
return FALSE;
}
@@ -5966,7 +5967,7 @@ dbus_connection_register_fallback (DBusConnection *connection,
if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
- _dbus_warn ("%s\n", error.message);
+ _dbus_warn ("%s", error.message);
dbus_error_free (&error);
return FALSE;
}
diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h
index fe4d04ef..bed54242 100644
--- a/dbus/dbus-connection.h
+++ b/dbus/dbus-connection.h
@@ -28,6 +28,7 @@
#define DBUS_CONNECTION_H
#include <dbus/dbus-errors.h>
+#include <dbus/dbus-macros.h>
#include <dbus/dbus-memory.h>
#include <dbus/dbus-message.h>
#include <dbus/dbus-shared.h>
@@ -438,6 +439,35 @@ DBUS_EXPORT
dbus_bool_t dbus_connection_get_socket (DBusConnection *connection,
int *fd);
+/**
+ * Clear a variable or struct member that contains a #DBusConnection.
+ * If it does not contain #NULL, the connection that was previously
+ * there is unreferenced with dbus_connection_unref().
+ *
+ * For example, this function and the similar functions for
+ * other reference-counted types can be used in code like this:
+ *
+ * @code
+ * DBusConnection *conn = NULL;
+ * struct { ...; DBusMessage *m; ... } *larger_structure = ...;
+ *
+ * ... code that might set conn or m to be non-NULL ...
+ *
+ * dbus_clear_connection (&conn);
+ * dbus_clear_message (&larger_structure->m);
+ * @endcode
+ *
+ * @param pointer_to_connection A pointer to a variable or struct member.
+ * pointer_to_connection must not be #NULL, but *pointer_to_connection
+ * may be #NULL.
+ */
+static inline void
+dbus_clear_connection (DBusConnection **pointer_to_connection)
+{
+ _dbus_clear_pointer_impl (DBusConnection, pointer_to_connection,
+ dbus_connection_unref);
+}
+
/** @} */
diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c
index 151bb00f..5fa754c2 100644
--- a/dbus/dbus-credentials.c
+++ b/dbus/dbus-credentials.c
@@ -267,10 +267,10 @@ _dbus_credentials_include (DBusCredentials *credentials,
return credentials->linux_security_label != NULL;
case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID:
return credentials->adt_audit_data != NULL;
+ default:
+ _dbus_assert_not_reached ("Unknown credential enum value");
+ return FALSE;
}
-
- _dbus_assert_not_reached ("Unknown credential enum value");
- return FALSE;
}
/**
diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c
index e37c9dd5..a4b3bfc0 100644
--- a/dbus/dbus-dataslot.c
+++ b/dbus/dbus-dataslot.c
@@ -394,7 +394,7 @@ _dbus_data_slot_test (void)
_dbus_data_slot_allocator_alloc (&allocator, &tmp);
if (tmp != i)
- _dbus_assert_not_reached ("did not allocate slots in numeric order\n");
+ _dbus_assert_not_reached ("did not allocate slots in numeric order");
++i;
}
diff --git a/dbus/dbus-errors.h b/dbus/dbus-errors.h
index e63139a0..3804085b 100644
--- a/dbus/dbus-errors.h
+++ b/dbus/dbus-errors.h
@@ -69,7 +69,7 @@ DBUS_EXPORT
void dbus_set_error (DBusError *error,
const char *name,
const char *message,
- ...);
+ ...) _DBUS_GNUC_PRINTF (3, 4);
DBUS_EXPORT
void dbus_set_error_const (DBusError *error,
const char *name,
diff --git a/dbus/dbus-file-win.c b/dbus/dbus-file-win.c
index 0dbe11ec..bdd0dcf8 100644
--- a/dbus/dbus-file-win.c
+++ b/dbus/dbus-file-win.c
@@ -73,7 +73,7 @@ _dbus_file_read (HANDLE hnd,
{
char *emsg = _dbus_win_error_string (GetLastError ());
dbus_set_error (error, _dbus_win_error_from_last_error (),
- "Failed to read from 0x%x: %s", hnd, emsg);
+ "Failed to read from %p: %s", hnd, emsg);
_dbus_win_free_error_string (emsg);
return -1;
}
diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c
index 1a667056..ba5e7ca4 100644
--- a/dbus/dbus-hash.c
+++ b/dbus/dbus-hash.c
@@ -724,8 +724,9 @@ _dbus_hash_iter_get_string_key (DBusHashIter *iter)
* because create_if_not_found was #FALSE and the entry
* did not exist.
*
- * If create_if_not_found is #TRUE and the entry is created, the hash
- * table takes ownership of the key that's passed in.
+ * If create_if_not_found is #TRUE, the hash
+ * table takes ownership of the key that's passed in (either using it to create
+ * the entry, or freeing it immediately).
*
* For a hash table of type #DBUS_HASH_INT, cast the int
* key to the key parameter using #_DBUS_INT_TO_POINTER().
@@ -754,7 +755,15 @@ _dbus_hash_iter_lookup (DBusHashTable *table,
if (entry == NULL)
return FALSE;
-
+
+ if (create_if_not_found)
+ {
+ if (table->free_key_function && entry->key != key)
+ (* table->free_key_function) (entry->key);
+
+ entry->key = key;
+ }
+
real->table = table;
real->bucket = bucket;
real->entry = entry;
@@ -1400,6 +1409,135 @@ _dbus_hash_table_get_n_entries (DBusHashTable *table)
return table->n_entries;
}
+/**
+ * Imports a string array into a hash table
+ * The hash table needs to be initialized with string keys,
+ * and dbus_free() as both key and value free-function.
+ *
+ * @param table the hash table
+ * @param array the string array to import
+ * @param delimiter the delimiter to separate key and value
+ * @return #TRUE on success.
+ * @return #FALSE if not enough memory.
+ */
+
+dbus_bool_t
+_dbus_hash_table_from_array (DBusHashTable *table, char **array, char delimiter)
+{
+ DBusString key;
+ DBusString value;
+ int i;
+ dbus_bool_t retval = FALSE;
+
+ _dbus_assert (table != NULL);
+ _dbus_assert (array != NULL);
+
+ if (!_dbus_string_init (&key))
+ {
+ return FALSE;
+ }
+
+ if (!_dbus_string_init (&value))
+ {
+ _dbus_string_free (&key);
+ return FALSE;
+ }
+
+ for (i = 0; array[i] != NULL; i++)
+ {
+ if (!_dbus_string_append (&key, array[i]))
+ break;
+
+ if (_dbus_string_split_on_byte (&key, delimiter, &value))
+ {
+ char *hash_key, *hash_value;
+
+ if (!_dbus_string_steal_data (&key, &hash_key))
+ break;
+
+ if (!_dbus_string_steal_data (&value, &hash_value))
+ break;
+
+ if (!_dbus_hash_table_insert_string (table,
+ hash_key, hash_value))
+ break;
+ }
+ _dbus_string_set_length (&key, 0);
+ _dbus_string_set_length (&value, 0);
+ }
+
+ if (array[i] != NULL)
+ goto out;
+
+ retval = TRUE;
+out:
+
+ _dbus_string_free (&key);
+ _dbus_string_free (&value);
+
+ return retval;
+}
+
+/**
+ * Creates a string array from a hash table
+ *
+ * @param table the hash table
+ * @param delimiter the delimiter to join key and value
+ * @return pointer to created string array (free with dbus_free_string_array)
+ * @return #FALSE if not enough memory.
+ */
+char **
+_dbus_hash_table_to_array (DBusHashTable *table, char delimiter)
+{
+ int i, length;
+ DBusString entry;
+ DBusHashIter iter;
+ char **array;
+
+ _dbus_assert (table != NULL);
+
+ length = _dbus_hash_table_get_n_entries (table);
+
+ array = dbus_new0 (char *, length + 1);
+
+ if (array == NULL)
+ return NULL;
+
+ i = 0;
+ _dbus_hash_iter_init (table, &iter);
+
+ if (!_dbus_string_init (&entry))
+ {
+ dbus_free_string_array (array);
+ return NULL;
+ }
+
+ while (_dbus_hash_iter_next (&iter))
+ {
+ const char *key, *value;
+
+ key = (const char *) _dbus_hash_iter_get_string_key (&iter);
+ value = (const char *) _dbus_hash_iter_get_value (&iter);
+
+ if (!_dbus_string_append_printf (&entry, "%s%c%s", key, delimiter, value))
+ break;
+
+ if (!_dbus_string_steal_data (&entry, array + i))
+ break;
+ i++;
+ }
+
+ _dbus_string_free (&entry);
+
+ if (i != length)
+ {
+ dbus_free_string_array (array);
+ array = NULL;
+ }
+
+ return array;
+}
+
/** @} */
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
@@ -1426,6 +1564,19 @@ count_entries (DBusHashTable *table)
return count;
}
+static inline void *
+steal (void *ptr)
+{
+ /* @ptr is passed in as void* to avoid casting in the call */
+ void **_ptr = (void **) ptr;
+ void *val;
+
+ val = *_ptr;
+ *_ptr = NULL;
+
+ return val;
+}
+
/**
* @ingroup DBusHashTableInternals
* Unit test for DBusHashTable
@@ -1442,6 +1593,8 @@ _dbus_hash_test (void)
#define N_HASH_KEYS 5000
char **keys;
dbus_bool_t ret = FALSE;
+ char *str_key = NULL;
+ char *str_value = NULL;
keys = dbus_new (char *, N_HASH_KEYS);
if (keys == NULL)
@@ -1488,51 +1641,51 @@ _dbus_hash_test (void)
i = 0;
while (i < 3000)
{
- void *value;
- char *key;
+ const void *out_value;
- key = _dbus_strdup (keys[i]);
- if (key == NULL)
+ str_key = _dbus_strdup (keys[i]);
+ if (str_key == NULL)
goto out;
- value = _dbus_strdup ("Value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Value!");
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_table_insert_string (table1,
- key, value))
+ steal (&str_key),
+ steal (&str_value)))
goto out;
- value = _dbus_strdup (keys[i]);
- if (value == NULL)
+ str_value = _dbus_strdup (keys[i]);
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_table_insert_int (table2,
- i, value))
+ i, steal (&str_value)))
goto out;
- value = _dbus_strdup (keys[i]);
- if (value == NULL)
+ str_value = _dbus_strdup (keys[i]);
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_table_insert_uintptr (table3,
- i, value))
+ i, steal (&str_value)))
goto out;
_dbus_assert (count_entries (table1) == i + 1);
_dbus_assert (count_entries (table2) == i + 1);
_dbus_assert (count_entries (table3) == i + 1);
- value = _dbus_hash_table_lookup_string (table1, keys[i]);
- _dbus_assert (value != NULL);
- _dbus_assert (strcmp (value, "Value!") == 0);
+ out_value = _dbus_hash_table_lookup_string (table1, keys[i]);
+ _dbus_assert (out_value != NULL);
+ _dbus_assert (strcmp (out_value, "Value!") == 0);
- value = _dbus_hash_table_lookup_int (table2, i);
- _dbus_assert (value != NULL);
- _dbus_assert (strcmp (value, keys[i]) == 0);
+ out_value = _dbus_hash_table_lookup_int (table2, i);
+ _dbus_assert (out_value != NULL);
+ _dbus_assert (strcmp (out_value, keys[i]) == 0);
- value = _dbus_hash_table_lookup_uintptr (table3, i);
- _dbus_assert (value != NULL);
- _dbus_assert (strcmp (value, keys[i]) == 0);
+ out_value = _dbus_hash_table_lookup_uintptr (table3, i);
+ _dbus_assert (out_value != NULL);
+ _dbus_assert (strcmp (out_value, keys[i]) == 0);
++i;
}
@@ -1573,40 +1726,38 @@ _dbus_hash_test (void)
dbus_free, dbus_free);
if (table1 == NULL)
goto out;
-
+
table2 = _dbus_hash_table_new (DBUS_HASH_INT,
NULL, dbus_free);
if (table2 == NULL)
goto out;
-
+
i = 0;
while (i < 5000)
{
- char *key;
- void *value;
-
- key = _dbus_strdup (keys[i]);
- if (key == NULL)
+ str_key = _dbus_strdup (keys[i]);
+ if (str_key == NULL)
goto out;
- value = _dbus_strdup ("Value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Value!");
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_table_insert_string (table1,
- key, value))
+ steal (&str_key),
+ steal (&str_value)))
goto out;
- value = _dbus_strdup (keys[i]);
- if (value == NULL)
+ str_value = _dbus_strdup (keys[i]);
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_table_insert_int (table2,
- i, value))
+ i, steal (&str_value)))
goto out;
-
+
_dbus_assert (count_entries (table1) == i + 1);
_dbus_assert (count_entries (table2) == i + 1);
-
+
++i;
}
@@ -1614,22 +1765,22 @@ _dbus_hash_test (void)
while (_dbus_hash_iter_next (&iter))
{
const char *key;
- void *value;
+ const void *value;
key = _dbus_hash_iter_get_string_key (&iter);
value = _dbus_hash_iter_get_value (&iter);
_dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
- value = _dbus_strdup ("Different value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Different value!");
+ if (str_value == NULL)
goto out;
-
- _dbus_hash_iter_set_value (&iter, value);
+ value = str_value;
+ _dbus_hash_iter_set_value (&iter, steal (&str_value));
_dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
}
-
+
_dbus_hash_iter_init (table1, &iter);
while (_dbus_hash_iter_next (&iter))
{
@@ -1642,19 +1793,19 @@ _dbus_hash_test (void)
while (_dbus_hash_iter_next (&iter))
{
int key;
- void *value;
+ const void *value;
key = _dbus_hash_iter_get_int_key (&iter);
value = _dbus_hash_iter_get_value (&iter);
_dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
- value = _dbus_strdup ("Different value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Different value!");
+ if (str_value == NULL)
goto out;
-
- _dbus_hash_iter_set_value (&iter, value);
+ value = str_value;
+ _dbus_hash_iter_set_value (&iter, steal (&str_value));
_dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
}
@@ -1673,42 +1824,38 @@ _dbus_hash_test (void)
i = 0;
while (i < 1000)
{
- char *key;
- void *value;
-
- key = _dbus_strdup (keys[i]);
- if (key == NULL)
+ str_key = _dbus_strdup (keys[i]);
+ if (str_key == NULL)
goto out;
- value = _dbus_strdup ("Value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Value!");
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_table_insert_string (table1,
- key, value))
+ steal (&str_key),
+ steal (&str_value)))
goto out;
-
+
++i;
}
--i;
while (i >= 0)
{
- char *key;
- void *value;
-
- key = _dbus_strdup (keys[i]);
- if (key == NULL)
+ str_key = _dbus_strdup (keys[i]);
+ if (str_key == NULL)
goto out;
- value = _dbus_strdup ("Value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Value!");
+ if (str_value == NULL)
goto out;
if (!_dbus_hash_table_remove_string (table1, keys[i]))
goto out;
-
+
if (!_dbus_hash_table_insert_string (table1,
- key, value))
+ steal (&str_key),
+ steal (&str_value)))
goto out;
if (!_dbus_hash_table_remove_string (table1, keys[i]))
@@ -1731,63 +1878,62 @@ _dbus_hash_test (void)
dbus_free, dbus_free);
if (table1 == NULL)
goto out;
-
+
table2 = _dbus_hash_table_new (DBUS_HASH_INT,
NULL, dbus_free);
if (table2 == NULL)
goto out;
-
+
i = 0;
while (i < 3000)
{
- void *value;
- char *key;
+ const void *out_value;
- key = _dbus_strdup (keys[i]);
- if (key == NULL)
+ str_key = _dbus_strdup (keys[i]);
+ if (str_key == NULL)
goto out;
- value = _dbus_strdup ("Value!");
- if (value == NULL)
+ str_value = _dbus_strdup ("Value!");
+ if (str_value == NULL)
goto out;
-
+
if (!_dbus_hash_iter_lookup (table1,
- key, TRUE, &iter))
+ steal (&str_key), TRUE, &iter))
goto out;
_dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
- _dbus_hash_iter_set_value (&iter, value);
+ _dbus_hash_iter_set_value (&iter, steal (&str_value));
- value = _dbus_strdup (keys[i]);
- if (value == NULL)
+ str_value = _dbus_strdup (keys[i]);
+ if (str_value == NULL)
goto out;
if (!_dbus_hash_iter_lookup (table2,
_DBUS_INT_TO_POINTER (i), TRUE, &iter))
goto out;
_dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
- _dbus_hash_iter_set_value (&iter, value);
-
+ _dbus_hash_iter_set_value (&iter, steal (&str_value));
+
_dbus_assert (count_entries (table1) == i + 1);
_dbus_assert (count_entries (table2) == i + 1);
if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
goto out;
-
- value = _dbus_hash_iter_get_value (&iter);
- _dbus_assert (value != NULL);
- _dbus_assert (strcmp (value, "Value!") == 0);
+
+ out_value = _dbus_hash_iter_get_value (&iter);
+ _dbus_assert (out_value != NULL);
+ _dbus_assert (strcmp (out_value, "Value!") == 0);
/* Iterate just to be sure it works, though
* it's a stupid thing to do
*/
while (_dbus_hash_iter_next (&iter))
;
-
+
if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
goto out;
- value = _dbus_hash_iter_get_value (&iter);
- _dbus_assert (value != NULL);
- _dbus_assert (strcmp (value, keys[i]) == 0);
+ out_value = _dbus_hash_iter_get_value (&iter);
+ _dbus_assert (out_value != NULL);
+ _dbus_assert (strcmp (out_value, keys[i]) == 0);
/* Iterate just to be sure it works, though
* it's a stupid thing to do
@@ -1825,6 +1971,9 @@ _dbus_hash_test (void)
dbus_free (keys[i]);
dbus_free (keys);
+
+ dbus_free (str_key);
+ dbus_free (str_value);
return ret;
}
diff --git a/dbus/dbus-hash.h b/dbus/dbus-hash.h
index 2898f51c..fadab91f 100644
--- a/dbus/dbus-hash.h
+++ b/dbus/dbus-hash.h
@@ -133,6 +133,14 @@ dbus_bool_t _dbus_hash_table_insert_uintptr (DBusHashTable *table,
DBUS_PRIVATE_EXPORT
int _dbus_hash_table_get_n_entries (DBusHashTable *table);
+DBUS_PRIVATE_EXPORT
+char ** _dbus_hash_table_to_array (DBusHashTable *table,
+ char delimiter);
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_hash_table_from_array (DBusHashTable *table,
+ char **array,
+ char delimiter);
+
/* Preallocation */
/** A preallocated hash entry */
@@ -202,6 +210,12 @@ _dbus_hash_table_insert_pollable (DBusHashTable *table,
#endif
}
+static inline void
+_dbus_clear_hash_table (DBusHashTable **table_p)
+{
+ _dbus_clear_pointer_impl (DBusHashTable, table_p, _dbus_hash_table_unref);
+}
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index 3f10c0c3..267aef97 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -230,13 +230,17 @@ void
_dbus_warn (const char *format,
...)
{
+ DBusSystemLogSeverity severity = DBUS_SYSTEM_LOG_WARNING;
va_list args;
if (!warn_initted)
init_warnings ();
-
+
+ if (fatal_warnings)
+ severity = DBUS_SYSTEM_LOG_ERROR;
+
va_start (args, format);
- vfprintf (stderr, format, args);
+ _dbus_logv (severity, format, args);
va_end (args);
if (fatal_warnings)
@@ -248,7 +252,7 @@ _dbus_warn (const char *format,
/**
* Prints a "critical" warning to stderr when an assertion fails;
- * differs from _dbus_warn primarily in that it prefixes the pid and
+ * differs from _dbus_warn primarily in that it
* defaults to fatal. This should be used only when a programming
* error has been detected. (NOT for unavoidable errors that an app
* might handle - those should be returned as DBusError.) Calling this
@@ -258,15 +262,17 @@ void
_dbus_warn_check_failed(const char *format,
...)
{
+ DBusSystemLogSeverity severity = DBUS_SYSTEM_LOG_WARNING;
va_list args;
if (!warn_initted)
init_warnings ();
- fprintf (stderr, "process %lu: ", _dbus_pid_for_log ());
-
+ if (fatal_warnings_on_check_failed)
+ severity = DBUS_SYSTEM_LOG_ERROR;
+
va_start (args, format);
- vfprintf (stderr, format, args);
+ _dbus_logv (severity, format, args);
va_end (args);
if (fatal_warnings_on_check_failed)
@@ -388,6 +394,7 @@ _dbus_verbose_real (
va_list args;
static dbus_bool_t need_pid = TRUE;
int len;
+ long sec, usec;
/* things are written a bit oddly here so that
* in the non-verbose case we just have the one
@@ -402,6 +409,8 @@ _dbus_verbose_real (
{
_dbus_print_thread ();
}
+ _dbus_get_real_time (&sec, &usec);
+ fprintf (stderr, "%ld.%06ld ", sec, usec);
#endif
/* Only print pid again if the next line is a new line */
@@ -632,6 +641,21 @@ _dbus_string_array_contains (const char **array,
}
/**
+ * Returns the size of a string array
+ *
+ * @param array array to search.
+ * @returns size of array
+ */
+size_t
+_dbus_string_array_length (const char **array)
+{
+ size_t i;
+ for (i = 0; array[i]; i++) {}
+ return i;
+}
+
+
+/**
* Generates a new UUID. If you change how this is done,
* there's some text about it in the spec that should also change.
*
@@ -884,25 +908,8 @@ _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str,
if (machine_uuid_initialized_generation != _dbus_current_generation)
{
- DBusError local_error = DBUS_ERROR_INIT;
-
- if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
- &local_error))
- {
-#ifndef DBUS_ENABLE_EMBEDDED_TESTS
- /* For the test suite, we may not be installed so just continue silently
- * here. But in a production build, we want to be nice and loud about
- * this.
- */
- _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
- "See the manual page for dbus-uuidgen to correct this issue.\n",
- local_error.message);
-#endif
-
- dbus_error_free (&local_error);
-
- ok = _dbus_generate_uuid (&machine_uuid, error);
- }
+ if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE, error))
+ ok = FALSE;
}
if (ok)
@@ -920,10 +927,17 @@ _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str,
}
#ifndef DBUS_DISABLE_CHECKS
-/** String used in _dbus_return_if_fail macro */
-const char *_dbus_return_if_fail_warning_format =
-"arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
-"This is normally a bug in some application using the D-Bus library.\n";
+void
+_dbus_warn_return_if_fail (const char *function,
+ const char *assertion,
+ const char *file,
+ int line)
+{
+ _dbus_warn_check_failed (
+ "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
+ "This is normally a bug in some application using the D-Bus library.\n",
+ function, assertion, file, line);
+}
#endif
#ifndef DBUS_DISABLE_ASSERT
@@ -948,8 +962,8 @@ _dbus_real_assert (dbus_bool_t condition,
{
if (_DBUS_UNLIKELY (!condition))
{
- _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
- _dbus_pid_for_log (), condition_text, file, line, func);
+ _dbus_warn ("assertion failed \"%s\" file \"%s\" line %d function %s",
+ condition_text, file, line, func);
_dbus_abort ();
}
}
@@ -969,8 +983,8 @@ _dbus_real_assert_not_reached (const char *explanation,
const char *file,
int line)
{
- _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
- file, line, _dbus_pid_for_log (), explanation);
+ _dbus_warn ("File \"%s\" line %d should not have been reached: %s",
+ file, line, explanation);
_dbus_abort ();
}
#endif /* DBUS_DISABLE_ASSERT */
@@ -1056,6 +1070,12 @@ _dbus_test_oom_handling (const char *description,
max_failures_to_try = 4;
}
+ if (max_failures_to_try < 1)
+ {
+ _dbus_verbose ("not testing OOM handling\n");
+ return TRUE;
+ }
+
i = setting ? max_failures_to_try - 1 : 1;
while (i < max_failures_to_try)
{
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index 3eb8749f..e7649e1d 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -42,7 +42,11 @@ void _dbus_warn (const char *format,
DBUS_PRIVATE_EXPORT
void _dbus_warn_check_failed (const char *format,
...) _DBUS_GNUC_PRINTF (1, 2);
-
+DBUS_PRIVATE_EXPORT
+void _dbus_warn_return_if_fail (const char *function,
+ const char *assertion,
+ const char *file,
+ int line);
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define _DBUS_FUNCTION_NAME __func__
@@ -124,6 +128,7 @@ static void _dbus_verbose(const char * x,...) {;}
# define _dbus_is_verbose() FALSE
#endif /* !DBUS_ENABLE_VERBOSE_MODE */
+DBUS_PRIVATE_EXPORT
void _dbus_trace_ref (const char *obj_name,
void *obj,
int old_refcount,
@@ -164,22 +169,17 @@ void _dbus_real_assert_not_reached (const char *explanation,
#define _dbus_return_val_if_fail(condition, val)
#else
-DBUS_PRIVATE_EXPORT
-extern const char *_dbus_return_if_fail_warning_format;
-
#define _dbus_return_if_fail(condition) do { \
_dbus_assert ((*(const char*)_DBUS_FUNCTION_NAME) != '_'); \
if (!(condition)) { \
- _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, \
- _DBUS_FUNCTION_NAME, #condition, __FILE__, __LINE__); \
+ _dbus_warn_return_if_fail (_DBUS_FUNCTION_NAME, #condition, __FILE__, __LINE__); \
return; \
} } while (0)
#define _dbus_return_val_if_fail(condition, val) do { \
_dbus_assert ((*(const char*)_DBUS_FUNCTION_NAME) != '_'); \
if (!(condition)) { \
- _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, \
- _DBUS_FUNCTION_NAME, #condition, __FILE__, __LINE__); \
+ _dbus_warn_return_if_fail (_DBUS_FUNCTION_NAME, #condition, __FILE__, __LINE__); \
return (val); \
} } while (0)
@@ -195,6 +195,9 @@ extern const char *_dbus_return_if_fail_warning_format;
#define _DBUS_STRUCT_OFFSET(struct_type, member) \
((intptr_t) ((unsigned char*) &((struct_type*) 0)->member))
+#define _DBUS_ALIGNOF(type) \
+ (_DBUS_STRUCT_OFFSET (struct { char _1; type _2; }, _2))
+
#ifdef DBUS_DISABLE_CHECKS
/* this is an assert and not an error, but in the typical --disable-checks case (you're trying
* to really minimize code size), disabling these assertions makes sense.
@@ -246,6 +249,8 @@ void* _dbus_memdup (const void *mem,
DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_string_array_contains (const char **array,
const char *str);
+DBUS_PRIVATE_EXPORT
+size_t _dbus_string_array_length (const char **array);
char** _dbus_dup_string_array (const char **array);
#define _DBUS_INT16_MIN ((dbus_int16_t) 0x8000)
@@ -296,6 +301,8 @@ void _dbus_set_error_valist (DBusError *error,
const char *format,
va_list args) _DBUS_GNUC_PRINTF (3, 0);
+typedef dbus_bool_t (* DBusTestMemoryFunction) (void *data);
+
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
/* Memory debugging */
void _dbus_set_fail_alloc_counter (int until_next_fail);
@@ -307,7 +314,6 @@ dbus_bool_t _dbus_disable_mem_pools (void);
DBUS_PRIVATE_EXPORT
int _dbus_get_malloc_blocks_outstanding (void);
-typedef dbus_bool_t (* DBusTestMemoryFunction) (void *data);
DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_test_oom_handling (const char *description,
DBusTestMemoryFunction func,
@@ -321,7 +327,9 @@ dbus_bool_t _dbus_test_oom_handling (const char *description,
*/
#define _dbus_decrement_fail_alloc_counter() (FALSE)
#define _dbus_disable_mem_pools() (FALSE)
-#define _dbus_get_malloc_blocks_outstanding (0)
+#define _dbus_get_malloc_blocks_outstanding() (0)
+
+#define _dbus_test_oom_handling(description, func, data) ((*func) (data))
#endif /* !DBUS_ENABLE_EMBEDDED_TESTS */
typedef void (* DBusShutdownFunction) (void *data);
@@ -404,6 +412,7 @@ dbus_bool_t _dbus_write_uuid_file (const DBusString *filename,
const DBusGUID *uuid,
DBusError *error);
+DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str,
DBusError *error);
diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c
index bb7e4f8d..d9adaa6a 100644
--- a/dbus/dbus-keyring.c
+++ b/dbus/dbus-keyring.c
@@ -250,7 +250,7 @@ _dbus_keyring_unlock (DBusKeyring *keyring)
if (!_dbus_delete_file (&keyring->filename_lock, &error))
{
- _dbus_warn ("Failed to delete lock file: %s\n",
+ _dbus_warn ("Failed to delete lock file: %s",
error.message);
dbus_error_free (&error);
}
@@ -452,7 +452,7 @@ _dbus_keyring_reload (DBusKeyring *keyring,
if (!_dbus_string_validate_ascii (&contents, 0,
_dbus_string_get_length (&contents)))
{
- _dbus_warn ("Secret keyring file contains non-ASCII! Ignoring existing contents\n");
+ _dbus_warn ("Secret keyring file contains non-ASCII! Ignoring existing contents");
_dbus_string_set_length (&contents, 0);
}
@@ -621,7 +621,7 @@ _dbus_keyring_reload (DBusKeyring *keyring,
{
if (error && error->name)
_dbus_verbose ("error is %s: %s\n", error->name, error->message);
- _dbus_warn ("returning %d but error pointer %p name %s\n",
+ _dbus_warn ("returning %d but error pointer %p name %s",
retval, error, error->name ? error->name : "(none)");
_dbus_assert_not_reached ("didn't handle errors properly");
}
@@ -807,7 +807,7 @@ _dbus_keyring_new_for_credentials (DBusCredentials *credentials,
* unless someone else manages to create it
*/
dbus_error_init (&tmp_error);
- if (!_dbus_create_directory (&keyring->directory,
+ if (!_dbus_ensure_directory (&keyring->directory,
&tmp_error))
{
_dbus_verbose ("Creating keyring directory: %s\n",
diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
index f84918b1..32ea871f 100644
--- a/dbus/dbus-list.c
+++ b/dbus/dbus-list.c
@@ -1020,8 +1020,10 @@ _dbus_list_test (void)
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
}
@@ -1063,8 +1065,10 @@ _dbus_list_test (void)
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
}
@@ -1073,8 +1077,6 @@ _dbus_list_test (void)
{
DBusList *got_link1;
DBusList *got_link2;
-
- DBusList *link2;
void *data1_indirect;
void *data1;
@@ -1111,12 +1113,14 @@ _dbus_list_test (void)
_dbus_assert (list2 == NULL);
/* Test iteration */
-
+
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
verify_list (&list1);
@@ -1173,8 +1177,10 @@ _dbus_list_test (void)
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
}
@@ -1205,8 +1211,10 @@ _dbus_list_test (void)
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
}
@@ -1245,8 +1253,10 @@ _dbus_list_test (void)
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
}
@@ -1294,8 +1304,10 @@ _dbus_list_test (void)
i = 0;
while (i < 10)
{
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
- _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+ _dbus_assert_not_reached ("could not allocate for prepend");
++i;
}
@@ -1362,9 +1374,12 @@ _dbus_list_test (void)
_dbus_list_clear (&list1);
/* using remove_last */
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2));
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1));
- _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3));
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1)))
+ _dbus_assert_not_reached ("could not allocate for append");
+ if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3)))
+ _dbus_assert_not_reached ("could not allocate for append");
_dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2));
diff --git a/dbus/dbus-macros.h b/dbus/dbus-macros.h
index a82d911e..2c8956e3 100644
--- a/dbus/dbus-macros.h
+++ b/dbus/dbus-macros.h
@@ -64,7 +64,8 @@
# define _DBUS_GNUC_EXTENSION
#endif
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)) || \
+ defined(__clang__)
#define _DBUS_GNUC_PRINTF( format_idx, arg_idx ) \
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
#define _DBUS_GNUC_NORETURN \
@@ -214,6 +215,26 @@
# define DBUS_PRIVATE_EXPORT /* no decoration */
#endif
+/* Implementation for dbus_clear_message() etc. This is not API,
+ * do not use it directly.
+ *
+ * We're using a specific type (T ** and T *) instead of void ** and
+ * void * partly for type-safety, partly to be strict-aliasing-compliant,
+ * and partly to keep C++ compilers happy. This code is inlined into
+ * users of libdbus, so we can't rely on it having dbus' own compiler
+ * settings. */
+#define _dbus_clear_pointer_impl(T, pointer_to_pointer, destroy) \
+ do { \
+ T **_pp = (pointer_to_pointer); \
+ T *_value = *_pp; \
+ \
+ *_pp = NULL; \
+ \
+ if (_value != NULL) \
+ destroy (_value); \
+ } while (0)
+/* Not (destroy) (_value) in case destroy() is a function-like macro */
+
/** @} */
#endif /* DBUS_MACROS_H */
diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c
index 24d0b50a..1f8ae0f7 100644
--- a/dbus/dbus-mainloop.c
+++ b/dbus/dbus-mainloop.c
@@ -200,7 +200,7 @@ cull_watches_for_invalid_fd (DBusLoop *loop,
DBusList *link;
DBusList **watches;
- _dbus_warn ("invalid request, socket fd %" DBUS_POLLABLE_FORMAT " not open\n",
+ _dbus_warn ("invalid request, socket fd %" DBUS_POLLABLE_FORMAT " not open",
_dbus_pollable_printable (fd));
watches = _dbus_hash_table_lookup_pollable (loop->watches, fd);
@@ -364,7 +364,7 @@ _dbus_loop_remove_watch (DBusLoop *loop,
}
}
- _dbus_warn ("could not find watch %p to remove\n", watch);
+ _dbus_warn ("could not find watch %p to remove", watch);
}
dbus_bool_t
@@ -416,7 +416,7 @@ _dbus_loop_remove_timeout (DBusLoop *loop,
link = next;
}
- _dbus_warn ("could not find timeout %p to remove\n", timeout);
+ _dbus_warn ("could not find timeout %p to remove", timeout);
}
/* Convolutions from GLib, there really must be a better way
@@ -629,9 +629,6 @@ _dbus_loop_iterate (DBusLoop *loop,
#endif
_dbus_assert (timeout >= 0);
-
- if (timeout == 0)
- break; /* it's not going to get shorter... */
}
#if MAINLOOP_SPEW
else
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
index 74fe3f91..4352e52a 100644
--- a/dbus/dbus-marshal-basic.c
+++ b/dbus/dbus-marshal-basic.c
@@ -29,6 +29,10 @@
#include <string.h>
+#if !defined(PRIx64) && defined(DBUS_WIN)
+#define PRIx64 "I64x"
+#endif
+
#if defined(__GNUC__) && (__GNUC__ >= 4)
# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
_DBUS_STATIC_ASSERT (__extension__ __alignof__ (type) op val)
@@ -204,7 +208,7 @@ set_2_octets (DBusString *str,
data = _dbus_string_get_data_len (str, offset, 2);
- pack_2_octets (value, byte_order, data);
+ pack_2_octets (value, byte_order, (unsigned char *) data);
}
static void
@@ -220,7 +224,7 @@ set_4_octets (DBusString *str,
data = _dbus_string_get_data_len (str, offset, 4);
- pack_4_octets (value, byte_order, data);
+ pack_4_octets (value, byte_order, (unsigned char *) data);
}
static void
@@ -236,7 +240,7 @@ set_8_octets (DBusString *str,
data = _dbus_string_get_data_len (str, offset, 8);
- pack_8_octets (value, byte_order, data);
+ pack_8_octets (value, byte_order, (unsigned char *) data);
}
/**
@@ -292,7 +296,7 @@ set_string (DBusString *str,
_dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
old_len = _dbus_unpack_uint32 (byte_order,
- _dbus_string_get_const_data_len (str, pos, 4));
+ _dbus_string_get_const_udata_len (str, pos, 4));
new_len = _dbus_string_get_length (&dstr);
@@ -464,7 +468,7 @@ _dbus_marshal_read_uint32 (const DBusString *str,
_dbus_assert (pos + 4 <= _dbus_string_get_length (str));
return _dbus_unpack_uint32 (byte_order,
- _dbus_string_get_const_data (str) + pos);
+ _dbus_string_get_const_udata (str) + pos);
}
/**
@@ -579,7 +583,7 @@ _dbus_marshal_read_basic (const DBusString *str,
}
break;
default:
- _dbus_warn_check_failed ("type %s %d not a basic type\n",
+ _dbus_warn_check_failed ("type %s %d not a basic type",
_dbus_type_to_string (type), type);
_dbus_assert_not_reached ("not a basic type");
break;
@@ -694,7 +698,7 @@ marshal_len_followed_by_bytes (int marshal_as,
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
if (insert_at > _dbus_string_get_length (str))
- _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
+ _dbus_warn ("insert_at = %d string len = %d data_len = %d",
insert_at, _dbus_string_get_length (str), data_len);
if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
@@ -702,7 +706,7 @@ marshal_len_followed_by_bytes (int marshal_as,
else
value_len = data_len + 1; /* value has a nul */
- _dbus_string_init_const_len (&value_str, value, value_len);
+ _dbus_string_init_const_len (&value_str, (const char *) value, value_len);
pos = insert_at;
@@ -756,7 +760,7 @@ marshal_string (DBusString *str,
int *pos_after)
{
return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
- str, insert_at, value,
+ str, insert_at, (const unsigned char *) value,
strlen (value),
byte_order, pos_after);
}
@@ -768,7 +772,7 @@ marshal_signature (DBusString *str,
int *pos_after)
{
return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
- str, insert_at, value,
+ str, insert_at, (const unsigned char *) value,
strlen (value),
DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
pos_after);
@@ -861,7 +865,7 @@ marshal_1_octets_array (DBusString *str,
int pos;
DBusString value_str;
- _dbus_string_init_const_len (&value_str, value, n_elements);
+ _dbus_string_init_const_len (&value_str, (const char *) value, n_elements);
pos = insert_at;
@@ -978,7 +982,7 @@ marshal_fixed_multi (DBusString *str,
goto error;
_dbus_string_init_const_len (&t,
- (const unsigned char*) value,
+ (const char *) value,
len_in_bytes);
if (!_dbus_string_copy (&t, 0,
@@ -1125,7 +1129,7 @@ _dbus_marshal_skip_basic (const DBusString *str,
}
break;
default:
- _dbus_warn ("type %s not a basic type\n",
+ _dbus_warn ("type %s not a basic type",
_dbus_type_to_string (type));
_dbus_assert_not_reached ("not a basic type");
break;
@@ -1334,10 +1338,8 @@ _dbus_verbose_bytes (const unsigned char *data,
if (i > 7 &&
_DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
{
-#ifdef DBUS_INT64_PRINTF_MODIFIER
- _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
+ _dbus_verbose (" u64: 0x%" PRIx64,
*(dbus_uint64_t*)&data[i-8]);
-#endif
_dbus_verbose (" dbl: %g",
*(double*)&data[i-8]);
}
@@ -1384,7 +1386,7 @@ _dbus_verbose_bytes_of_string (const DBusString *str,
d = _dbus_string_get_const_data_len (str, start, len);
- _dbus_verbose_bytes (d, len, start);
+ _dbus_verbose_bytes ((const unsigned char *) d, len, start);
}
static int
@@ -1546,7 +1548,7 @@ swap_test_array (void *array,
{ \
_dbus_verbose_bytes_of_string (&str, dump_pos, \
_dbus_string_get_length (&str) - dump_pos); \
- _dbus_warn ("literal '%s'\nvalue '%s'\n", literal, v_##typename); \
+ _dbus_warn ("literal '%s'\nvalue '%s'", literal, v_##typename); \
_dbus_assert_not_reached ("demarshaled wrong value"); \
} \
} while (0)
@@ -1586,9 +1588,9 @@ swap_test_array (void *array,
_dbus_verbose_bytes_of_string (&str, dump_pos, \
_dbus_string_get_length (&str) - dump_pos); \
_dbus_verbose ("LITERAL DATA\n"); \
- _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0); \
+ _dbus_verbose_bytes ((const unsigned char *) literal, sizeof (literal), 0); \
_dbus_verbose ("READ DATA\n"); \
- _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0); \
+ _dbus_verbose_bytes ((const unsigned char *) v_ARRAY_##typename, sizeof (literal), 0); \
_dbus_assert_not_reached ("demarshaled wrong fixed array value"); \
} \
} while (0)
@@ -1608,7 +1610,9 @@ _dbus_marshal_test (void)
int pos, dump_pos;
unsigned char array1[5] = { 3, 4, 0, 1, 9 };
dbus_int16_t array2[3] = { 124, 457, 780 };
+ dbus_uint16_t array2u[3] = { 124, 457, 780 };
dbus_int32_t array4[3] = { 123, 456, 789 };
+ dbus_uint32_t array4u[3] = { 123, 456, 789 };
dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
DBUS_INT64_CONSTANT (0x456ffffffff),
DBUS_INT64_CONSTANT (0x789ffffffff) };
@@ -1705,13 +1709,13 @@ _dbus_marshal_test (void)
/* Arrays */
MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
- MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
- MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
+ MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2u);
+ MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2u);
MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
- MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
- MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
+ MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4u);
+ MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4u);
MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
index 68ff348b..0c4e4117 100644
--- a/dbus/dbus-marshal-basic.h
+++ b/dbus/dbus-marshal-basic.h
@@ -214,7 +214,6 @@ dbus_uint32_t _dbus_marshal_read_uint32 (const DBusString *str,
int byte_order,
int *new_pos);
int _dbus_type_get_alignment (int typecode);
-int _dbus_type_get_alignment (int typecode);
DBUS_PRIVATE_EXPORT
const char* _dbus_type_to_string (int typecode);
diff --git a/dbus/dbus-marshal-byteswap-util.c b/dbus/dbus-marshal-byteswap-util.c
index 57874859..80fc013b 100644
--- a/dbus/dbus-marshal-byteswap-util.c
+++ b/dbus/dbus-marshal-byteswap-util.c
@@ -75,7 +75,7 @@ do_byteswap_test (int byte_order)
_dbus_verbose_bytes_of_string (&copy, 0,
_dbus_string_get_length (&copy));
- _dbus_warn ("Byte-swapped data did not have same values as original data\n");
+ _dbus_warn ("Byte-swapped data did not have same values as original data");
_dbus_assert_not_reached ("test failed");
}
diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c
index e6711be6..27695aaf 100644
--- a/dbus/dbus-marshal-byteswap.c
+++ b/dbus/dbus-marshal-byteswap.c
@@ -161,7 +161,7 @@ byteswap_body_helper (DBusTypeReader *reader,
sig_len = *p;
++p;
- _dbus_string_init_const_len (&sig, p, sig_len);
+ _dbus_string_init_const_len (&sig, (const char *) p, sig_len);
p += (sig_len + 1); /* 1 for nul */
@@ -239,7 +239,7 @@ _dbus_marshal_byteswap (const DBusString *signature,
byteswap_body_helper (&reader, TRUE,
old_byte_order, new_byte_order,
- _dbus_string_get_data_len (value_str, value_pos, 0),
+ _dbus_string_get_udata_len (value_str, value_pos, 0),
NULL);
}
diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c
index ab85d69c..053ab737 100644
--- a/dbus/dbus-marshal-header.c
+++ b/dbus/dbus-marshal-header.c
@@ -1564,7 +1564,7 @@ _dbus_header_toggle_flag (DBusHeader *header,
{
unsigned char *flags_p;
- flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
+ flags_p = _dbus_string_get_udata_len (&header->data, FLAGS_OFFSET, 1);
if (value)
*flags_p |= flag;
@@ -1585,7 +1585,7 @@ _dbus_header_get_flag (DBusHeader *header,
{
const unsigned char *flags_p;
- flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
+ flags_p = _dbus_string_get_const_udata_len (&header->data, FLAGS_OFFSET, 1);
return (*flags_p & flag) != 0;
}
diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c
index 3bc26a8c..b30f5883 100644
--- a/dbus/dbus-marshal-recursive-util.c
+++ b/dbus/dbus-marshal-recursive-util.c
@@ -31,6 +31,13 @@
#include "dbus-internals.h"
#include <string.h>
+#if !defined(PRIx64) && defined(DBUS_WIN)
+#define PRIx64 "I64x"
+#endif
+
+/** turn this on to get deluged in TypeWriter verbose spam */
+#define RECURSIVE_MARSHAL_WRITE_TRACE 0
+
static void
basic_value_zero (DBusBasicValue *value)
{
@@ -300,7 +307,7 @@ real_check_expected_type (DBusTypeReader *reader,
if (t != expected)
{
- _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
+ _dbus_warn ("Read type %s while expecting %s at %s line %d",
_dbus_type_to_string (t),
_dbus_type_to_string (expected),
funcname, line);
@@ -313,7 +320,7 @@ real_check_expected_type (DBusTypeReader *reader,
#define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \
{ \
- _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \
+ _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d", \
_DBUS_FUNCTION_NAME, __LINE__); \
_dbus_assert_not_reached ("test failed"); \
} \
@@ -321,7 +328,7 @@ real_check_expected_type (DBusTypeReader *reader,
#define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \
{ \
- _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \
+ _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d", \
_DBUS_FUNCTION_NAME, __LINE__); \
_dbus_assert_not_reached ("test failed"); \
} \
@@ -1316,7 +1323,7 @@ run_test_delete_values (NodeIterationData *nid)
while (elem > 0)
{
if (!_dbus_type_reader_next (&array))
- _dbus_assert_not_reached ("should have had another element\n");
+ _dbus_assert_not_reached ("should have had another element");
--elem;
}
@@ -1391,7 +1398,7 @@ run_test_nodes_iteration (void *data)
if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
&nid->block->signature, nid->type_offset))
{
- _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
+ _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d",
_dbus_string_get_const_data (nid->signature),
_dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
nid->type_offset);
@@ -1697,14 +1704,14 @@ make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
}
static void
-start_next_test (const char *format,
+start_next_test (const char *description,
int expected)
{
n_iterations_completed_this_test = 0;
n_iterations_expected_this_test = expected;
- fprintf (stderr, ">>> >>> ");
- fprintf (stderr, format,
+ fprintf (stderr, ">>> >>> %s %d iterations\n",
+ description,
n_iterations_expected_this_test);
}
@@ -1745,7 +1752,7 @@ make_and_run_test_nodes (void)
/* FIXME test just an empty body, no types at all */
- start_next_test ("Each value by itself %d iterations\n", N_VALUES);
+ start_next_test ("Each value by itself", N_VALUES);
{
TestTypeNode *node;
i = 0;
@@ -1757,7 +1764,7 @@ make_and_run_test_nodes (void)
}
}
- start_next_test ("Each value by itself with arrays as blocks %d iterations\n", N_VALUES);
+ start_next_test ("Each value by itself with arrays as blocks", N_VALUES);
arrays_write_fixed_in_blocks = TRUE;
{
TestTypeNode *node;
@@ -1771,7 +1778,7 @@ make_and_run_test_nodes (void)
}
arrays_write_fixed_in_blocks = FALSE;
- start_next_test ("All values in one big toplevel %d iteration\n", 1);
+ start_next_test ("All values in one big toplevel", 1);
{
TestTypeNode *nodes[N_VALUES];
TestTypeNode *node;
@@ -1788,7 +1795,7 @@ make_and_run_test_nodes (void)
node_destroy (nodes[i]);
}
- start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n",
+ start_next_test ("Each value,value pair combination as toplevel, in both orders",
N_VALUES * N_VALUES);
{
TestTypeNode *nodes[2];
@@ -1808,7 +1815,7 @@ make_and_run_test_nodes (void)
}
}
- start_next_test ("Each container containing each value %d iterations\n",
+ start_next_test ("Each container containing each value",
N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
{
@@ -1817,7 +1824,7 @@ make_and_run_test_nodes (void)
make_and_run_values_inside_container (container_klass, 1);
}
- start_next_test ("Each container containing each value with arrays as blocks %d iterations\n",
+ start_next_test ("Each container containing each value with arrays as blocks",
N_CONTAINERS * N_VALUES);
arrays_write_fixed_in_blocks = TRUE;
for (i = 0; i < N_CONTAINERS; i++)
@@ -1828,7 +1835,7 @@ make_and_run_test_nodes (void)
}
arrays_write_fixed_in_blocks = FALSE;
- start_next_test ("Each container of same container of each value %d iterations\n",
+ start_next_test ("Each container of same container of each value",
N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
{
@@ -1837,7 +1844,7 @@ make_and_run_test_nodes (void)
make_and_run_values_inside_container (container_klass, 2);
}
- start_next_test ("Each container of same container of same container of each value %d iterations\n",
+ start_next_test ("Each container of same container of same container of each value",
N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
{
@@ -1846,7 +1853,7 @@ make_and_run_test_nodes (void)
make_and_run_values_inside_container (container_klass, 3);
}
- start_next_test ("Each value,value pair inside a struct %d iterations\n",
+ start_next_test ("Each value,value pair inside a struct",
N_VALUES * N_VALUES);
{
TestTypeNode *val1, *val2;
@@ -1875,8 +1882,7 @@ make_and_run_test_nodes (void)
node_destroy (node);
}
- start_next_test ("All values in one big struct %d iteration\n",
- 1);
+ start_next_test ("All values in one big struct", 1);
{
TestTypeNode *node;
TestTypeNode *child;
@@ -1892,8 +1898,7 @@ make_and_run_test_nodes (void)
node_destroy (node);
}
- start_next_test ("Each value in a large array %d iterations\n",
- N_VALUES);
+ start_next_test ("Each value in a large array", N_VALUES);
{
TestTypeNode *val;
TestTypeNode *node;
@@ -1924,7 +1929,7 @@ make_and_run_test_nodes (void)
goto out;
}
- start_next_test ("Each container of each container of each value %d iterations\n",
+ start_next_test ("Each container of each container of each value",
N_CONTAINERS * N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
{
@@ -1955,7 +1960,7 @@ make_and_run_test_nodes (void)
node_destroy (outer_container);
}
- start_next_test ("Each container of each container of each container of each value %d iterations\n",
+ start_next_test ("Each container of each container of each container of each value",
N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
{
@@ -2005,7 +2010,7 @@ make_and_run_test_nodes (void)
goto out;
}
- start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
+ start_next_test ("Each value,value,value triplet combination as toplevel, in all orders",
N_VALUES * N_VALUES * N_VALUES);
{
TestTypeNode *nodes[3];
@@ -2065,27 +2070,15 @@ int16_from_seed (int seed)
* just use seed itself, but that would only ever touch one byte of
* the int so would miss some kinds of bug.
*/
- dbus_int16_t v;
+ static const dbus_int16_t v_of_seed[5] = {
+ SAMPLE_INT16,
+ SAMPLE_INT16_ALTERNATE,
+ -1,
+ _DBUS_INT16_MAX,
+ 1
+ };
- v = 42; /* just to quiet compiler afaik */
- switch (seed % 5)
- {
- case 0:
- v = SAMPLE_INT16;
- break;
- case 1:
- v = SAMPLE_INT16_ALTERNATE;
- break;
- case 2:
- v = -1;
- break;
- case 3:
- v = _DBUS_INT16_MAX;
- break;
- case 4:
- v = 1;
- break;
- }
+ dbus_int16_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
if (seed > 1)
v *= seed; /* wraps around eventually, which is fine */
@@ -2181,7 +2174,7 @@ int16_read_multi (TestTypeNode *node,
&n_elements);
if (n_elements != count)
- _dbus_warn ("got %d elements expected %d\n", n_elements, count);
+ _dbus_warn ("got %d elements expected %d", n_elements, count);
_dbus_assert (n_elements == count);
for (i = 0; i < count; i++)
@@ -2202,27 +2195,15 @@ int32_from_seed (int seed)
* just use seed itself, but that would only ever touch one byte of
* the int so would miss some kinds of bug.
*/
- dbus_int32_t v;
+ static const dbus_int32_t v_of_seed[5] = {
+ SAMPLE_INT32,
+ SAMPLE_INT32_ALTERNATE,
+ -1,
+ _DBUS_INT_MAX,
+ 1
+ };
- v = 42; /* just to quiet compiler afaik */
- switch (seed % 5)
- {
- case 0:
- v = SAMPLE_INT32;
- break;
- case 1:
- v = SAMPLE_INT32_ALTERNATE;
- break;
- case 2:
- v = -1;
- break;
- case 3:
- v = _DBUS_INT_MAX;
- break;
- case 4:
- v = 1;
- break;
- }
+ dbus_int32_t v = v_of_seed[seed % _DBUS_N_ELEMENTS(v_of_seed)];
if (seed > 1)
v *= seed; /* wraps around eventually, which is fine */
@@ -2318,7 +2299,7 @@ int32_read_multi (TestTypeNode *node,
&n_elements);
if (n_elements != count)
- _dbus_warn ("got %d elements expected %d\n", n_elements, count);
+ _dbus_warn ("got %d elements expected %d", n_elements, count);
_dbus_assert (n_elements == count);
for (i = 0; i < count; i++)
@@ -2409,6 +2390,9 @@ string_from_seed (char *buf,
*/
switch (seed % 3)
{
+ default:
+ /* don't alter it */
+ break;
case 1:
len += 2;
break;
@@ -2473,7 +2457,7 @@ string_read_value (TestTypeNode *node,
if (strcmp (buf, v) != 0)
{
- _dbus_warn ("read string '%s' expected '%s'\n",
+ _dbus_warn ("read string '%s' expected '%s'",
v, buf);
_dbus_assert_not_reached ("test failed");
}
@@ -2644,12 +2628,10 @@ double_read_value (TestTypeNode *node,
if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
{
-#ifdef DBUS_INT64_PRINTF_MODIFIER
- _dbus_warn ("Expected double %g got %g\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x vs.\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x)\n",
+ _dbus_warn ("Expected double %g got %g\n bits = 0x%" PRIx64 " vs.\n bits = 0x%" PRIx64,
expected, v,
*(dbus_uint64_t*)(char*)&expected,
*(dbus_uint64_t*)(char*)&v);
-#endif
_dbus_assert_not_reached ("test failed");
}
@@ -2743,7 +2725,7 @@ object_path_read_value (TestTypeNode *node,
if (strcmp (buf, v) != 0)
{
- _dbus_warn ("read object path '%s' expected '%s'\n",
+ _dbus_warn ("read object path '%s' expected '%s'",
v, buf);
_dbus_assert_not_reached ("test failed");
}
@@ -2818,7 +2800,7 @@ signature_read_value (TestTypeNode *node,
if (strcmp (buf, v) != 0)
{
- _dbus_warn ("read signature value '%s' expected '%s'\n",
+ _dbus_warn ("read signature value '%s' expected '%s'",
v, buf);
_dbus_assert_not_reached ("test failed");
}
@@ -3068,10 +3050,10 @@ array_write_value (TestTypeNode *node,
link = _dbus_list_get_first_link (&container->children);
while (link != NULL)
{
- TestTypeNode *child = link->data;
+ TestTypeNode *child2 = link->data;
DBusList *next = _dbus_list_get_next_link (&container->children, link);
- if (!node_write_value (child, block, &sub, seed + i))
+ if (!node_write_value (child2, block, &sub, seed + i))
goto oom;
link = next;
@@ -3132,20 +3114,20 @@ array_read_or_set_value (TestTypeNode *node,
link = _dbus_list_get_first_link (&container->children);
while (link != NULL)
{
- TestTypeNode *child = link->data;
+ TestTypeNode *child2 = link->data;
DBusList *next = _dbus_list_get_next_link (&container->children, link);
- _dbus_assert (child->klass->typecode ==
+ _dbus_assert (child2->klass->typecode ==
_dbus_type_reader_get_element_type (reader));
if (realign_root == NULL)
{
- if (!node_read_value (child, &sub, seed + i))
+ if (!node_read_value (child2, &sub, seed + i))
return FALSE;
}
else
{
- if (!node_set_value (child, &sub, realign_root, seed + i))
+ if (!node_set_value (child2, &sub, realign_root, seed + i))
return FALSE;
}
diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c
index bd77bfad..c9cb4b7e 100644
--- a/dbus/dbus-marshal-recursive.c
+++ b/dbus/dbus-marshal-recursive.c
@@ -259,7 +259,7 @@ array_reader_get_array_len (const DBusTypeReader *reader)
_dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (unsigned) len_pos);
array_len = _dbus_unpack_uint32 (reader->byte_order,
- _dbus_string_get_const_data_len (reader->value_str, len_pos, 4));
+ _dbus_string_get_const_udata_len (reader->value_str, len_pos, 4));
#if RECURSIVE_MARSHAL_READ_TRACE
_dbus_verbose (" reader %p len_pos %d array len %u len_offset %d\n",
@@ -425,7 +425,7 @@ _dbus_type_signature_next (const char *type_str,
_dbus_assert (type_str != NULL);
_dbus_assert (type_pos != NULL);
- start = type_str;
+ start = (const unsigned char *)type_str;
p = start + *type_pos;
_dbus_assert (*p != DBUS_STRUCT_END_CHAR);
@@ -1017,9 +1017,9 @@ _dbus_type_reader_read_raw (const DBusTypeReader *reader,
{
_dbus_assert (!reader->klass->types_only);
- *value_location = _dbus_string_get_const_data_len (reader->value_str,
- reader->value_pos,
- 0);
+ *value_location = _dbus_string_get_const_udata_len (reader->value_str,
+ reader->value_pos,
+ 0);
}
/**
@@ -1152,8 +1152,8 @@ void
_dbus_type_reader_recurse (DBusTypeReader *reader,
DBusTypeReader *sub)
{
- const DBusTypeReaderClass *klass = NULL;
int t;
+ const DBusTypeReaderClass *klass = NULL;
t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos);
@@ -1187,12 +1187,13 @@ _dbus_type_reader_recurse (DBusTypeReader *reader,
_dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
#ifndef DBUS_DISABLE_CHECKS
if (t == DBUS_TYPE_INVALID)
- _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body\n");
+ _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body");
#endif /* DBUS_DISABLE_CHECKS */
_dbus_assert_not_reached ("don't yet handle recursing into this type");
}
+ _dbus_assert (klass != NULL);
_dbus_assert (klass == all_reader_classes[klass->id]);
(* klass->recurse) (sub, reader);
@@ -1880,13 +1881,13 @@ writer_recurse_init_and_check (DBusTypeWriter *writer,
{
if (expected != DBUS_TYPE_INVALID)
_dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n"
- "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.",
_dbus_type_to_string (sub->container_type),
_dbus_type_to_string (expected),
_dbus_string_get_const_data (writer->type_str), writer->type_pos);
else
_dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n"
- "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.",
_dbus_type_to_string (sub->container_type),
_dbus_string_get_const_data (writer->type_str), writer->type_pos);
@@ -1946,12 +1947,12 @@ write_or_verify_typecode (DBusTypeWriter *writer,
{
if (expected != DBUS_TYPE_INVALID)
_dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n"
- "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.",
_dbus_type_to_string (expected), _dbus_type_to_string (typecode),
_dbus_string_get_const_data (writer->type_str), writer->type_pos);
else
_dbus_warn_check_failed ("Array or variant type wasn't expecting any more values to be written into it, but a value %s was written.\n"
- "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+ "The overall signature expected here was '%s' and we are on byte %d of that signature.",
_dbus_type_to_string (typecode),
_dbus_string_get_const_data (writer->type_str), writer->type_pos);
_dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
@@ -2061,7 +2062,7 @@ writer_recurse_array (DBusTypeWriter *writer,
writer->type_str,
writer->u.array.element_type_pos + 1))
{
- _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
+ _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array",
_dbus_string_get_const_data_len (contained_type,
contained_type_start,
contained_type_len));
@@ -2187,7 +2188,7 @@ writer_recurse_array (DBusTypeWriter *writer,
_dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
(unsigned) sub->u.array.len_pos);
len = _dbus_unpack_uint32 (sub->byte_order,
- _dbus_string_get_const_data_len (sub->value_str,
+ _dbus_string_get_const_udata_len (sub->value_str,
sub->u.array.len_pos,
4));
@@ -2884,7 +2885,7 @@ writer_write_reader_helper (DBusTypeWriter *writer,
(unsigned) fixup.len_pos_in_reader);
old_len = _dbus_unpack_uint32 (reader->byte_order,
- _dbus_string_get_const_data_len (reader->value_str,
+ _dbus_string_get_const_udata_len (reader->value_str,
fixup.len_pos_in_reader, 4));
if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
diff --git a/dbus/dbus-marshal-validate-util.c b/dbus/dbus-marshal-validate-util.c
index 2880a4d9..9e75a7e7 100644
--- a/dbus/dbus-marshal-validate-util.c
+++ b/dbus/dbus-marshal-validate-util.c
@@ -57,18 +57,18 @@ run_validity_tests (const ValidityTest *tests,
if (v != tests[i].expected)
{
- _dbus_warn ("Improper validation result %d for '%s'\n",
+ _dbus_warn ("Improper validation result %d for '%s'",
v, tests[i].data);
_dbus_assert_not_reached ("test failed");
}
-
- ++i;
}
}
static const ValidityTest signature_tests[] = {
{ "", DBUS_VALID },
+ { "sss", DBUS_VALID },
{ "i", DBUS_VALID },
+ { "b", DBUS_VALID },
{ "ai", DBUS_VALID },
{ "(i)", DBUS_VALID },
{ "w", DBUS_INVALID_UNKNOWN_TYPECODE },
@@ -83,7 +83,7 @@ static const ValidityTest signature_tests[] = {
DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION },
{ ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
{ "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
- { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
+ { "a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
{ "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
{ "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
{ "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
@@ -97,9 +97,15 @@ static const ValidityTest signature_tests[] = {
{ "a{ia}", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
{ "a{}", DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS },
{ "a{aii}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
- /* { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD }, */
- /* { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY }, */
- /* { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS }, */
+ { " ", DBUS_INVALID_UNKNOWN_TYPECODE },
+ { "not a valid signature", DBUS_INVALID_UNKNOWN_TYPECODE },
+ { "123", DBUS_INVALID_UNKNOWN_TYPECODE },
+ { ".", DBUS_INVALID_UNKNOWN_TYPECODE },
+ /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
+ { "a{(ii)i}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
+ { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD },
+ { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY },
+ { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS },
};
dbus_bool_t
@@ -215,22 +221,6 @@ _dbus_marshal_validate_test (void)
"foo bar"
};
- const char *valid_signatures[] = {
- "",
- "sss",
- "i",
- "b"
- };
-
- const char *invalid_signatures[] = {
- " ",
- "not a valid signature",
- "123",
- ".",
- "(",
- "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
- };
-
/* Signature with reason */
run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
@@ -245,7 +235,7 @@ _dbus_marshal_validate_test (void)
if (!_dbus_validate_path (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
+ _dbus_warn ("Path \"%s\" should have been valid", valid_paths[i]);
_dbus_assert_not_reached ("invalid path");
}
@@ -260,7 +250,7 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_path (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
+ _dbus_warn ("Path \"%s\" should have been invalid", invalid_paths[i]);
_dbus_assert_not_reached ("valid path");
}
@@ -276,7 +266,7 @@ _dbus_marshal_validate_test (void)
if (!_dbus_validate_interface (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
+ _dbus_warn ("Interface \"%s\" should have been valid", valid_interfaces[i]);
_dbus_assert_not_reached ("invalid interface");
}
@@ -291,7 +281,7 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_interface (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
+ _dbus_warn ("Interface \"%s\" should have been invalid", invalid_interfaces[i]);
_dbus_assert_not_reached ("valid interface");
}
@@ -309,7 +299,7 @@ _dbus_marshal_validate_test (void)
if (!_dbus_validate_bus_name (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]);
+ _dbus_warn ("Bus name \"%s\" should have been valid", valid_interfaces[i]);
_dbus_assert_not_reached ("invalid bus name");
}
@@ -326,7 +316,7 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_bus_name (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]);
+ _dbus_warn ("Bus name \"%s\" should have been invalid", invalid_interfaces[i]);
_dbus_assert_not_reached ("valid bus name");
}
}
@@ -343,7 +333,7 @@ _dbus_marshal_validate_test (void)
if (!_dbus_validate_bus_name (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]);
+ _dbus_warn ("Bus name \"%s\" should have been valid", valid_unique_names[i]);
_dbus_assert_not_reached ("invalid unique name");
}
@@ -358,7 +348,7 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_bus_name (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]);
+ _dbus_warn ("Bus name \"%s\" should have been invalid", invalid_unique_names[i]);
_dbus_assert_not_reached ("valid unique name");
}
@@ -376,7 +366,7 @@ _dbus_marshal_validate_test (void)
if (!_dbus_validate_error_name (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
+ _dbus_warn ("Error name \"%s\" should have been valid", valid_interfaces[i]);
_dbus_assert_not_reached ("invalid error name");
}
@@ -393,7 +383,7 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_error_name (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
+ _dbus_warn ("Error name \"%s\" should have been invalid", invalid_interfaces[i]);
_dbus_assert_not_reached ("valid error name");
}
}
@@ -410,7 +400,7 @@ _dbus_marshal_validate_test (void)
if (!_dbus_validate_member (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
+ _dbus_warn ("Member \"%s\" should have been valid", valid_members[i]);
_dbus_assert_not_reached ("invalid member");
}
@@ -425,44 +415,13 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_member (&str, 0,
_dbus_string_get_length (&str)))
{
- _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
+ _dbus_warn ("Member \"%s\" should have been invalid", invalid_members[i]);
_dbus_assert_not_reached ("valid member");
}
++i;
}
- /* Signature validation */
- i = 0;
- while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
- {
- _dbus_string_init_const (&str, valid_signatures[i]);
-
- if (!_dbus_validate_signature (&str, 0,
- _dbus_string_get_length (&str)))
- {
- _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
- _dbus_assert_not_reached ("invalid signature");
- }
-
- ++i;
- }
-
- i = 0;
- while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
- {
- _dbus_string_init_const (&str, invalid_signatures[i]);
-
- if (_dbus_validate_signature (&str, 0,
- _dbus_string_get_length (&str)))
- {
- _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
- _dbus_assert_not_reached ("valid signature");
- }
-
- ++i;
- }
-
/* Validate claimed length longer than real length */
_dbus_string_init_const (&str, "abc.efg");
if (_dbus_validate_bus_name (&str, 0, 8))
@@ -476,10 +435,6 @@ _dbus_marshal_validate_test (void)
if (_dbus_validate_member (&str, 0, 4))
_dbus_assert_not_reached ("validated too-long string");
- _dbus_string_init_const (&str, "sss");
- if (_dbus_validate_signature (&str, 0, 4))
- _dbus_assert_not_reached ("validated too-long signature");
-
/* Validate string exceeding max name length */
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("no memory");
@@ -539,7 +494,7 @@ _dbus_marshal_validate_test (void)
_dbus_string_get_length (&body));
if (validity != DBUS_VALID)
{
- _dbus_warn ("invalid code %d expected valid on sequence %d little endian\n",
+ _dbus_warn ("invalid code %d expected valid on sequence %d little endian",
validity, sequence);
_dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
_dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
@@ -564,7 +519,7 @@ _dbus_marshal_validate_test (void)
_dbus_string_get_length (&body));
if (validity != DBUS_VALID)
{
- _dbus_warn ("invalid code %d expected valid on sequence %d big endian\n",
+ _dbus_warn ("invalid code %d expected valid on sequence %d big endian",
validity, sequence);
_dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
_dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c
index 9187a3e9..4d492f3f 100644
--- a/dbus/dbus-marshal-validate.c
+++ b/dbus/dbus-marshal-validate.c
@@ -83,9 +83,9 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
goto out;
}
- p = _dbus_string_get_const_data_len (type_str, type_pos, 0);
+ p = _dbus_string_get_const_udata_len (type_str, type_pos, 0);
- end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
+ end = _dbus_string_get_const_udata_len (type_str, type_pos + len, 0);
struct_depth = 0;
array_depth = 0;
dict_entry_depth = 0;
@@ -233,7 +233,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
{
if (*p == DBUS_TYPE_ARRAY && p != end)
{
- const char *p1;
+ const unsigned char *p1;
p1 = p + 1;
if (*p1 == DBUS_STRUCT_END_CHAR ||
*p1 == DBUS_DICT_ENTRY_END_CHAR)
@@ -358,8 +358,13 @@ validate_body_helper (DBusTypeReader *reader,
if (current_type == DBUS_TYPE_BOOLEAN)
{
- dbus_uint32_t v = _dbus_unpack_uint32 (byte_order,
- p);
+ dbus_uint32_t v;
+
+ if (p + 4 > end)
+ return DBUS_INVALID_NOT_ENOUGH_DATA;
+
+ v = _dbus_unpack_uint32 (byte_order, p);
+
if (!(v == 0 || v == 1))
return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
}
@@ -420,7 +425,7 @@ validate_body_helper (DBusTypeReader *reader,
if (current_type == DBUS_TYPE_OBJECT_PATH)
{
DBusString str;
- _dbus_string_init_const_len (&str, p, claimed_len);
+ _dbus_string_init_const_len (&str, (const char *) p, claimed_len);
if (!_dbus_validate_path (&str, 0,
_dbus_string_get_length (&str)))
return DBUS_INVALID_BAD_PATH;
@@ -430,7 +435,7 @@ validate_body_helper (DBusTypeReader *reader,
else if (current_type == DBUS_TYPE_STRING)
{
DBusString str;
- _dbus_string_init_const_len (&str, p, claimed_len);
+ _dbus_string_init_const_len (&str, (const char *) p, claimed_len);
if (!_dbus_string_validate_utf8 (&str, 0,
_dbus_string_get_length (&str)))
return DBUS_INVALID_BAD_UTF8_IN_STRING;
@@ -529,7 +534,7 @@ validate_body_helper (DBusTypeReader *reader,
if (claimed_len + 1 > (unsigned long) (end - p))
return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
- _dbus_string_init_const_len (&str, p, claimed_len);
+ _dbus_string_init_const_len (&str, (const char *) p, claimed_len);
validity =
_dbus_validate_signature_with_reason (&str, 0,
_dbus_string_get_length (&str));
@@ -573,7 +578,7 @@ validate_body_helper (DBusTypeReader *reader,
if (claimed_len + 1 > (unsigned long) (end - p))
return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
- _dbus_string_init_const_len (&sig, p, claimed_len);
+ _dbus_string_init_const_len (&sig, (const char *) p, claimed_len);
reason = _dbus_validate_signature_with_reason (&sig, 0,
_dbus_string_get_length (&sig));
if (!(reason == DBUS_VALID))
@@ -725,7 +730,7 @@ _dbus_validate_body_with_reason (const DBusString *expected_signature,
_dbus_type_reader_init_types_only (&reader,
expected_signature, expected_signature_start);
- p = _dbus_string_get_const_data_len (value_str, value_pos, len);
+ p = _dbus_string_get_const_udata_len (value_str, value_pos, len);
end = p + len;
validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p);
@@ -800,7 +805,7 @@ _dbus_validate_path (const DBusString *str,
if (len == 0)
return FALSE;
- s = _dbus_string_get_const_data (str) + start;
+ s = _dbus_string_get_const_udata (str) + start;
end = s + len;
if (*s != '/')
@@ -898,7 +903,9 @@ _dbus_validity_to_error_message (DBusValidity validity)
case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS: return "Dict entry has too many fields";
case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY: return "Dict entry not inside array";
case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE: return "Dict key must be basic type";
+ case DBUS_INVALID_MISSING_UNIX_FDS: return "Unix file descriptor missing";
case DBUS_INVALID_NESTED_TOO_DEEPLY: return "Variants cannot be used to create a hugely recursive tree of values";
+ case DBUS_VALIDITY_LAST:
default:
return "Invalid";
}
@@ -941,7 +948,7 @@ _dbus_validate_interface (const DBusString *str,
return FALSE;
last_dot = NULL;
- iface = _dbus_string_get_const_data (str) + start;
+ iface = _dbus_string_get_const_udata (str) + start;
end = iface + len;
s = iface;
@@ -1015,7 +1022,7 @@ _dbus_validate_member (const DBusString *str,
if (len == 0)
return FALSE;
- member = _dbus_string_get_const_data (str) + start;
+ member = _dbus_string_get_const_udata (str) + start;
end = member + len;
s = member;
@@ -1107,7 +1114,7 @@ _dbus_validate_bus_name_full (const DBusString *str,
return FALSE;
last_dot = NULL;
- iface = _dbus_string_get_const_data (str) + start;
+ iface = _dbus_string_get_const_udata (str) + start;
end = iface + len;
s = iface;
@@ -1212,33 +1219,6 @@ _dbus_validate_bus_namespace (const DBusString *str,
return _dbus_validate_bus_name_full (str, start, len, TRUE);
}
-/**
- * Checks that the given range of the string is a valid message type
- * signature in the D-Bus protocol.
- *
- * @todo this is inconsistent with most of DBusString in that
- * it allows a start,len range that extends past the string end.
- *
- * @param str the string
- * @param start first byte index to check
- * @param len number of bytes to check
- * @returns #TRUE if the byte range exists and is a valid signature
- */
-dbus_bool_t
-_dbus_validate_signature (const DBusString *str,
- int start,
- int len)
-{
- _dbus_assert (start >= 0);
- _dbus_assert (start <= _dbus_string_get_length (str));
- _dbus_assert (len >= 0);
-
- if (len > _dbus_string_get_length (str) - start)
- return FALSE;
-
- return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
-}
-
/** define _dbus_check_is_valid_path() */
DEFINE_DBUS_NAME_CHECK(path)
/** define _dbus_check_is_valid_interface() */
@@ -1249,8 +1229,6 @@ DEFINE_DBUS_NAME_CHECK(member)
DEFINE_DBUS_NAME_CHECK(error_name)
/** define _dbus_check_is_valid_bus_name() */
DEFINE_DBUS_NAME_CHECK(bus_name)
-/** define _dbus_check_is_valid_signature() */
-DEFINE_DBUS_NAME_CHECK(signature)
/** define _dbus_check_is_valid_utf8() */
DEFINE_DBUS_NAME_CHECK(utf8)
diff --git a/dbus/dbus-marshal-validate.h b/dbus/dbus-marshal-validate.h
index 8ab024fe..df8e5672 100644
--- a/dbus/dbus-marshal-validate.h
+++ b/dbus/dbus-marshal-validate.h
@@ -155,10 +155,6 @@ DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_validate_bus_namespace (const DBusString *str,
int start,
int len);
-DBUS_PRIVATE_EXPORT
-dbus_bool_t _dbus_validate_signature (const DBusString *str,
- int start,
- int len);
/* just to have a name consistent with the above: */
#define _dbus_validate_utf8(s,b,e) _dbus_string_validate_utf8 (s, b, e)
@@ -205,8 +201,6 @@ DECLARE_DBUS_NAME_CHECK(member);
DECLARE_DBUS_NAME_CHECK(error_name);
/** defines _dbus_check_is_valid_bus_name() */
DECLARE_DBUS_NAME_CHECK(bus_name);
-/** defines _dbus_check_is_valid_signature() */
-DECLARE_DBUS_NAME_CHECK(signature);
/** defines _dbus_check_is_valid_utf8() */
DECLARE_DBUS_NAME_CHECK(utf8);
diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
index 67d5cb05..a9c2f7a4 100644
--- a/dbus/dbus-memory.c
+++ b/dbus/dbus-memory.c
@@ -334,9 +334,10 @@ source_string (BlockSource source)
return "malloc0";
case SOURCE_REALLOC_NULL:
return "realloc(NULL)";
+ default:
+ _dbus_assert_not_reached ("Invalid malloc block source ID");
+ return "invalid!";
}
- _dbus_assert_not_reached ("Invalid malloc block source ID");
- return "invalid!";
}
static void
@@ -364,7 +365,7 @@ check_guards (void *free_block,
dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
if (value != GUARD_VALUE)
{
- _dbus_warn ("Block of %lu bytes from %s had start guard value 0x%ux at %d expected 0x%x\n",
+ _dbus_warn ("Block of %lu bytes from %s had start guard value 0x%ux at %d expected 0x%x",
(long) requested_bytes, source_string (source),
value, i, GUARD_VALUE);
failed = TRUE;
@@ -379,7 +380,7 @@ check_guards (void *free_block,
dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
if (value != GUARD_VALUE)
{
- _dbus_warn ("Block of %lu bytes from %s had end guard value 0x%ux at %d expected 0x%x\n",
+ _dbus_warn ("Block of %lu bytes from %s had end guard value 0x%ux at %d expected 0x%x",
(long) requested_bytes, source_string (source),
value, i, GUARD_VALUE);
failed = TRUE;
@@ -486,7 +487,7 @@ dbus_malloc (size_t bytes)
}
else if (malloc_cannot_fail)
{
- _dbus_warn ("out of memory: malloc (%ld + %ld)\n",
+ _dbus_warn ("out of memory: malloc (%ld + %ld)",
(long) bytes, (long) GUARD_EXTRA_SIZE);
_dbus_abort ();
}
@@ -506,7 +507,7 @@ dbus_malloc (size_t bytes)
}
else if (malloc_cannot_fail)
{
- _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes);
+ _dbus_warn ("out of memory: malloc (%ld)", (long) bytes);
_dbus_abort ();
}
#endif
@@ -558,7 +559,7 @@ dbus_malloc0 (size_t bytes)
}
else if (malloc_cannot_fail)
{
- _dbus_warn ("out of memory: calloc (%ld + %ld, 1)\n",
+ _dbus_warn ("out of memory: calloc (%ld + %ld, 1)",
(long) bytes, (long) GUARD_EXTRA_SIZE);
_dbus_abort ();
}
@@ -578,7 +579,7 @@ dbus_malloc0 (size_t bytes)
}
else if (malloc_cannot_fail)
{
- _dbus_warn ("out of memory: calloc (%ld)\n", (long) bytes);
+ _dbus_warn ("out of memory: calloc (%ld)", (long) bytes);
_dbus_abort ();
}
#endif
@@ -636,7 +637,7 @@ dbus_realloc (void *memory,
{
if (malloc_cannot_fail)
{
- _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n",
+ _dbus_warn ("out of memory: realloc (%p, %ld + %ld)",
memory, (long) bytes, (long) GUARD_EXTRA_SIZE);
_dbus_abort ();
}
@@ -663,7 +664,7 @@ dbus_realloc (void *memory,
}
else if (malloc_cannot_fail)
{
- _dbus_warn ("out of memory: malloc (%ld + %ld)\n",
+ _dbus_warn ("out of memory: malloc (%ld + %ld)",
(long) bytes, (long) GUARD_EXTRA_SIZE);
_dbus_abort ();
}
@@ -680,7 +681,7 @@ dbus_realloc (void *memory,
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
if (mem == NULL && malloc_cannot_fail)
{
- _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes);
+ _dbus_warn ("out of memory: malloc (%ld)", (long) bytes);
_dbus_abort ();
}
diff --git a/dbus/dbus-memory.h b/dbus/dbus-memory.h
index 4fd56bd6..c575b46f 100644
--- a/dbus/dbus-memory.h
+++ b/dbus/dbus-memory.h
@@ -48,7 +48,6 @@ DBUS_ALLOC_SIZE(1)
void* dbus_malloc0 (size_t bytes);
DBUS_EXPORT
-DBUS_MALLOC
DBUS_ALLOC_SIZE(2)
void* dbus_realloc (void *memory,
size_t bytes);
diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c
index b742e4c1..23e13d8e 100644
--- a/dbus/dbus-message-factory.c
+++ b/dbus/dbus-message-factory.c
@@ -139,11 +139,11 @@ generate_trivial_inner (DBusMessageDataIter *iter,
_dbus_assert_not_reached ("oom");
{
- DBusMessageIter iter;
+ DBusMessageIter iter2;
const char *v_STRING = "This is an error";
- dbus_message_iter_init_append (message, &iter);
- if (!dbus_message_iter_append_basic (&iter,
+ dbus_message_iter_init_append (message, &iter2);
+ if (!dbus_message_iter_append_basic (&iter2,
DBUS_TYPE_STRING,
&v_STRING))
_dbus_assert_not_reached ("oom");
@@ -362,19 +362,24 @@ message_with_nesting_levels (int levels)
dbus_message_iter_init_append (message, &parents[i]);
while (i < levels)
{
- dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT,
- i == (levels - 1) ?
- DBUS_TYPE_INT32_AS_STRING :
- DBUS_TYPE_VARIANT_AS_STRING,
- &children[i]);
+ if (!dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT,
+ i == (levels - 1) ?
+ DBUS_TYPE_INT32_AS_STRING :
+ DBUS_TYPE_VARIANT_AS_STRING,
+ &children[i]))
+ _dbus_assert_not_reached ("oom");
++i;
parents[i] = children[i-1];
}
--i;
- dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32);
+
+ if (!dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32))
+ _dbus_assert_not_reached ("oom");
+
while (i >= 0)
{
- dbus_message_iter_close_container (&parents[i], &children[i]);
+ if (!dbus_message_iter_close_container (&parents[i], &children[i]))
+ _dbus_assert_not_reached ("oom");
--i;
}
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index 2db5d85a..2d8bf006 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -57,6 +57,7 @@ void _dbus_message_get_unix_fds (DBusMessage *message,
const int **fds,
unsigned *n_fds);
+unsigned int _dbus_message_get_n_unix_fds (DBusMessage *message);
void _dbus_message_lock (DBusMessage *message);
void _dbus_message_unlock (DBusMessage *message);
dbus_bool_t _dbus_message_add_counter (DBusMessage *message,
@@ -75,19 +76,25 @@ void _dbus_message_loader_unref (DBusMessageLoader
DBUS_PRIVATE_EXPORT
void _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
- DBusString **buffer);
+ DBusString **buffer,
+ int *max_to_read,
+ dbus_bool_t *may_read_unix_fds);
DBUS_PRIVATE_EXPORT
void _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
DBusString *buffer);
+
+#ifdef HAVE_UNIX_FD_PASSING
DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_message_loader_get_unix_fds (DBusMessageLoader *loader,
int **fds,
unsigned *max_n_fds);
+
DBUS_PRIVATE_EXPORT
void _dbus_message_loader_return_unix_fds (DBusMessageLoader *loader,
int *fds,
unsigned n_fds);
+#endif
DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_message_loader_queue_messages (DBusMessageLoader *loader);
@@ -118,6 +125,27 @@ void _dbus_message_loader_set_unique_sender_id (DBusMessageLoader
uint64_t id);
uint64_t _dbus_message_loader_get_unique_sender_id (DBusMessageLoader *loader);
+typedef struct DBusVariant DBusVariant;
+DBUS_PRIVATE_EXPORT
+DBusVariant *_dbus_variant_read (DBusMessageIter *reader);
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_variant_write (DBusVariant *self,
+ DBusMessageIter *writer);
+DBUS_PRIVATE_EXPORT
+void _dbus_variant_free (DBusVariant *self);
+DBUS_PRIVATE_EXPORT
+int _dbus_variant_get_length (DBusVariant *self);
+DBUS_PRIVATE_EXPORT
+const DBusString *_dbus_variant_peek (DBusVariant *self);
+DBUS_PRIVATE_EXPORT
+const char *_dbus_variant_get_signature (DBusVariant *self);
+
+static inline void
+_dbus_clear_variant (DBusVariant **variant_p)
+{
+ _dbus_clear_pointer_impl (DBusVariant, variant_p, _dbus_variant_free);
+}
+
typedef struct DBusInitialFDs DBusInitialFDs;
DBusInitialFDs *_dbus_check_fdleaks_enter (void);
void _dbus_check_fdleaks_leave (DBusInitialFDs *fds);
@@ -130,8 +158,8 @@ DBusMessage * _dbus_decode_kmsg (DBusString *da
unsigned n_fds);
DBusMessage * _dbus_generate_local_error_message (dbus_uint32_t serial,
- char *error_name,
- char *error_msg);
+ const char *error_name,
+ const char *error_msg);
dbus_bool_t _dbus_message_assure_dbus1 (DBusMessage **message);
dbus_bool_t _dbus_message_assure_gvariant (DBusMessage **message);
diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c
index 5acd541e..ebf00e27 100644
--- a/dbus/dbus-message-util.c
+++ b/dbus/dbus-message-util.c
@@ -45,6 +45,22 @@
* @{
*/
+/**
+ * Gets the number of unix fds attached to this message.
+ *
+ * @param message the message
+ * @returns the number of file descriptors
+ */
+unsigned int
+_dbus_message_get_n_unix_fds (DBusMessage *message)
+{
+#ifdef HAVE_UNIX_FD_PASSING
+ return message->n_unix_fds;
+#else
+ return 0;
+#endif
+}
+
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
/**
* Reads arguments from a message iterator given a variable argument
@@ -132,7 +148,7 @@ check_memleaks (void)
if (_dbus_get_malloc_blocks_outstanding () != 0)
{
- _dbus_warn ("%d dbus_malloc blocks were not freed in %s\n",
+ _dbus_warn ("%d dbus_malloc blocks were not freed in %s",
_dbus_get_malloc_blocks_outstanding (), __FILE__);
_dbus_assert_not_reached ("memleaks");
}
@@ -182,6 +198,13 @@ _dbus_check_fdleaks_enter (void)
if (fd == dirfd (d))
continue;
+ if (fd >= FD_SETSIZE)
+ {
+ _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
+ "it is leaked\n", fd);
+ continue;
+ }
+
FD_SET (fd, &fds->set);
}
@@ -227,10 +250,17 @@ _dbus_check_fdleaks_leave (DBusInitialFDs *fds)
if (fd == dirfd (d))
continue;
+ if (fd >= FD_SETSIZE)
+ {
+ _dbus_verbose ("FD %d unexpectedly large; cannot track whether "
+ "it is leaked\n", fd);
+ continue;
+ }
+
if (FD_ISSET (fd, &fds->set))
continue;
- _dbus_warn ("file descriptor %i leaked in %s.\n", fd, __FILE__);
+ _dbus_warn ("file descriptor %i leaked in %s.", fd, __FILE__);
_dbus_assert_not_reached ("fdleaks");
}
@@ -254,7 +284,7 @@ check_have_valid_message (DBusMessageLoader *loader)
if (_dbus_message_loader_get_is_corrupted (loader))
{
- _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d\n",
+ _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d",
loader->corruption_reason);
goto failed;
}
@@ -262,13 +292,13 @@ check_have_valid_message (DBusMessageLoader *loader)
message = _dbus_message_loader_pop_message (loader);
if (message == NULL)
{
- _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
+ _dbus_warn ("didn't load message that was expected to be valid (message not popped)");
goto failed;
}
if (_dbus_string_get_length (&loader->data) > 0)
{
- _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
+ _dbus_warn ("had leftover bytes from expected-to-be-valid single message");
goto failed;
}
@@ -303,7 +333,7 @@ check_invalid_message (DBusMessageLoader *loader,
if (!_dbus_message_loader_get_is_corrupted (loader))
{
- _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
+ _dbus_warn ("loader not corrupted on message that was expected to be invalid");
goto failed;
}
@@ -312,7 +342,7 @@ check_invalid_message (DBusMessageLoader *loader,
if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
loader->corruption_reason != expected_validity)
{
- _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead\n",
+ _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead",
expected_validity, loader->corruption_reason);
goto failed;
}
@@ -334,7 +364,7 @@ check_incomplete_message (DBusMessageLoader *loader)
if (_dbus_message_loader_get_is_corrupted (loader))
{
- _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d\n",
+ _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d",
loader->corruption_reason);
goto failed;
}
@@ -342,7 +372,7 @@ check_incomplete_message (DBusMessageLoader *loader)
message = _dbus_message_loader_pop_message (loader);
if (message != NULL)
{
- _dbus_warn ("loaded message that was expected to be incomplete\n");
+ _dbus_warn ("loaded message that was expected to be incomplete");
goto failed;
}
@@ -400,7 +430,7 @@ dbus_internal_do_not_use_load_message_file (const DBusString *filename,
_dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
if (!_dbus_file_get_contents (data, filename, &error))
{
- _dbus_warn ("Could not load message file %s: %s\n",
+ _dbus_warn ("Could not load message file %s: %s",
_dbus_string_get_const_data (filename),
error.message);
dbus_error_free (&error);
@@ -432,7 +462,7 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
retval = FALSE;
if (!_dbus_string_init (&data))
- _dbus_assert_not_reached ("could not allocate string\n");
+ _dbus_assert_not_reached ("could not allocate string");
if (!dbus_internal_do_not_use_load_message_file (filename, &data))
goto failed;
@@ -447,7 +477,7 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
_dbus_verbose_bytes_of_string (&data, 0,
_dbus_string_get_length (&data));
- _dbus_warn ("Failed message loader test on %s\n",
+ _dbus_warn ("Failed message loader test on %s",
_dbus_string_get_const_data (filename));
}
@@ -479,20 +509,22 @@ dbus_internal_do_not_use_try_message_data (const DBusString *data,
/* Write the data one byte at a time */
loader = _dbus_message_loader_new ();
+ if (loader == NULL)
+ goto failed;
/* check some trivial loader functions */
_dbus_message_loader_ref (loader);
_dbus_message_loader_unref (loader);
- _dbus_message_loader_get_max_message_size (loader);
len = _dbus_string_get_length (data);
for (i = 0; i < len; i++)
{
DBusString *buffer;
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_append_byte (buffer,
- _dbus_string_get_byte (data, i));
+ _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
+ if (!_dbus_string_append_byte (buffer,
+ _dbus_string_get_byte (data, i)))
+ goto failed;
_dbus_message_loader_return_buffer (loader, buffer);
}
@@ -505,13 +537,16 @@ dbus_internal_do_not_use_try_message_data (const DBusString *data,
/* Write the data all at once */
loader = _dbus_message_loader_new ();
+ if (loader == NULL)
+ goto failed;
{
DBusString *buffer;
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_copy (data, 0, buffer,
- _dbus_string_get_length (buffer));
+ _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
+ if (!_dbus_string_copy (data, 0, buffer,
+ _dbus_string_get_length (buffer)))
+ goto failed;
_dbus_message_loader_return_buffer (loader, buffer);
}
@@ -524,18 +559,26 @@ dbus_internal_do_not_use_try_message_data (const DBusString *data,
/* Write the data 2 bytes at a time */
loader = _dbus_message_loader_new ();
+ if (loader == NULL)
+ goto failed;
len = _dbus_string_get_length (data);
for (i = 0; i < len; i += 2)
{
DBusString *buffer;
- _dbus_message_loader_get_buffer (loader, &buffer);
- _dbus_string_append_byte (buffer,
- _dbus_string_get_byte (data, i));
+ _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
+ if (!_dbus_string_append_byte (buffer,
+ _dbus_string_get_byte (data, i)))
+ goto failed;
+
if ((i+1) < len)
- _dbus_string_append_byte (buffer,
- _dbus_string_get_byte (data, i+1));
+ {
+ if (!_dbus_string_append_byte (buffer,
+ _dbus_string_get_byte (data, i+1)))
+ goto failed;
+ }
+
_dbus_message_loader_return_buffer (loader, buffer);
}
@@ -572,7 +615,7 @@ process_test_subdir (const DBusString *test_base_dir,
dir = NULL;
if (!_dbus_string_init (&test_directory))
- _dbus_assert_not_reached ("didn't allocate test_directory\n");
+ _dbus_assert_not_reached ("didn't allocate test_directory");
_dbus_string_init_const (&filename, subdir);
@@ -585,12 +628,12 @@ process_test_subdir (const DBusString *test_base_dir,
_dbus_string_free (&filename);
if (!_dbus_string_init (&filename))
- _dbus_assert_not_reached ("didn't allocate filename string\n");
+ _dbus_assert_not_reached ("didn't allocate filename string");
dir = _dbus_directory_open (&test_directory, &error);
if (dir == NULL)
{
- _dbus_warn ("Could not open %s: %s\n",
+ _dbus_warn ("Could not open %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -644,7 +687,7 @@ process_test_subdir (const DBusString *test_base_dir,
if (dbus_error_is_set (&error))
{
- _dbus_warn ("Could not get next file in %s: %s\n",
+ _dbus_warn ("Could not get next file in %s: %s",
_dbus_string_get_const_data (&test_directory),
error.message);
dbus_error_free (&error);
@@ -875,7 +918,7 @@ verify_test_message (DBusMessage *message)
&our_string_array, &our_string_array_len,
0))
{
- _dbus_warn ("error: %s - %s\n", error.name,
+ _dbus_warn ("error: %s - %s", error.name,
(error.message != NULL) ? error.message : "no message");
_dbus_assert_not_reached ("Could not get arguments");
}
@@ -1006,7 +1049,7 @@ verify_test_message_args_ignored (DBusMessage *message)
if (!dbus_message_iter_get_args (&iter, &error,
DBUS_TYPE_INVALID))
{
- _dbus_warn ("error: %s - %s\n", error.name,
+ _dbus_warn ("error: %s - %s", error.name,
(error.message != NULL) ? error.message : "no message");
}
else
@@ -1021,7 +1064,7 @@ verify_test_message_args_ignored (DBusMessage *message)
DBUS_TYPE_UINT32, &our_uint,
DBUS_TYPE_INVALID))
{
- _dbus_warn ("error: %s - %s\n", error.name,
+ _dbus_warn ("error: %s - %s", error.name,
(error.message != NULL) ? error.message : "no message");
}
else
@@ -1077,7 +1120,7 @@ verify_test_message_memleak (DBusMessage *message)
}
else
{
- _dbus_warn ("error: parse with wrong signature: 'uashuu'.\n");
+ _dbus_warn ("error: parse with wrong signature: 'uashuu'.");
}
/* parse with wrong signature: "uashuashu" */
@@ -1111,7 +1154,7 @@ verify_test_message_memleak (DBusMessage *message)
}
else
{
- _dbus_warn ("error: parse with wrong signature: 'uashuashu'.\n");
+ _dbus_warn ("error: parse with wrong signature: 'uashuashu'.");
}
/* parse with correct signature: "uashuash" */
@@ -1132,7 +1175,7 @@ verify_test_message_memleak (DBusMessage *message)
#endif
DBUS_TYPE_INVALID))
{
- _dbus_warn ("error: %s - %s\n", error.name,
+ _dbus_warn ("error: %s - %s", error.name,
(error.message != NULL) ? error.message : "no message");
_dbus_assert_not_reached ("Could not get arguments");
}
@@ -1498,7 +1541,7 @@ _dbus_message_test (const char *test_data_dir)
{
DBusString *buffer;
- _dbus_message_loader_get_buffer (loader, &buffer);
+ _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
_dbus_string_append_byte (buffer, data[i]);
_dbus_message_loader_return_buffer (loader, buffer);
}
@@ -1509,7 +1552,7 @@ _dbus_message_test (const char *test_data_dir)
{
DBusString *buffer;
- _dbus_message_loader_get_buffer (loader, &buffer);
+ _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
_dbus_string_append_byte (buffer, data[i]);
_dbus_message_loader_return_buffer (loader, buffer);
}
@@ -1749,7 +1792,7 @@ _dbus_message_test (const char *test_data_dir)
if (!dbus_internal_do_not_use_try_message_data (&mdata.data,
mdata.expected_validity))
{
- _dbus_warn ("expected validity %d and did not get it\n",
+ _dbus_warn ("expected validity %d and did not get it",
mdata.expected_validity);
_dbus_assert_not_reached ("message data failed");
}
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 99d314c1..09e5a877 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -169,6 +169,29 @@ _dbus_message_toggle_gvariant (DBusMessage *message, dbus_bool_t gvariant)
message->header.protocol_version = gvariant ? DBUS_PROTOCOL_VERSION_GVARIANT : DBUS_MAJOR_PROTOCOL_VERSION;
}
+/**
+ * Layout of a DBusMessageIter on the stack in dbus 1.10.0. This is no
+ * longer used, but for ABI compatibility we need to assert that the
+ * new layout is the same size.
+ */
+typedef struct
+{
+ void *dummy1;
+ void *dummy2;
+ dbus_uint32_t dummy3;
+ int dummy4;
+ int dummy5;
+ int dummy6;
+ int dummy7;
+ int dummy8;
+ int dummy9;
+ int dummy10;
+ int dummy11;
+ int pad1;
+ int pad2;
+ void *pad3;
+} DBusMessageIter_1_10_0;
+
static void
get_const_signature (DBusMessage *message,
const DBusString **type_str_p,
@@ -499,50 +522,6 @@ set_or_delete_string_field (DBusMessage *message,
&value);
}
-#if 0
-/* Probably we don't need to use this */
-/**
- * Sets the signature of the message, i.e. the arguments in the
- * message payload. The signature includes only "in" arguments for
- * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
- * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
- * what you might expect (it does not include the signature of the
- * entire C++-style method).
- *
- * The signature is a string made up of type codes such as
- * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
- * the value of #DBUS_TYPE_INVALID). The macros such as
- * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you
- * may find it useful to use the string forms, such as
- * #DBUS_TYPE_INT32_AS_STRING.
- *
- * An "unset" or #NULL signature is considered the same as an empty
- * signature. In fact dbus_message_get_signature() will never return
- * #NULL.
- *
- * @param message the message
- * @param signature the type signature or #NULL to unset
- * @returns #FALSE if no memory
- */
-static dbus_bool_t
-_dbus_message_set_signature (DBusMessage *message,
- const char *signature)
-{
- _dbus_return_val_if_fail (message != NULL, FALSE);
- _dbus_return_val_if_fail (!message->locked, FALSE);
- _dbus_return_val_if_fail (signature == NULL ||
- _dbus_check_is_valid_signature (signature));
- /* can't delete the signature if you have a message body */
- _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
- signature != NULL);
-
- return set_or_delete_string_field (message,
- DBUS_HEADER_FIELD_SIGNATURE,
- DBUS_TYPE_SIGNATURE,
- signature);
-}
-#endif
-
/* Message Cache
*
* We cache some DBusMessage to reduce the overhead of allocating
@@ -701,7 +680,7 @@ close_unix_fds(int *fds, unsigned *n_fds)
{
if (!_dbus_close(fds[i], &e))
{
- _dbus_warn("Failed to close file descriptor: %s\n", e.message);
+ _dbus_warn("Failed to close file descriptor: %s", e.message);
dbus_error_free(&e);
}
}
@@ -832,6 +811,38 @@ dbus_message_cache_or_finalize (DBusMessage *message)
dbus_message_finalize (message);
}
+/*
+ * Arrange for iter to be something that _dbus_message_iter_check() would
+ * reject as not a valid iterator.
+ */
+static void
+_dbus_message_real_iter_zero (DBusMessageRealIter *iter)
+{
+ _dbus_assert (iter != NULL);
+ _DBUS_ZERO (*iter);
+ /* NULL is not, strictly speaking, guaranteed to be all-bits-zero */
+ iter->message = NULL;
+}
+
+/**
+ * Initialize iter as if with #DBUS_MESSAGE_ITER_INIT_CLOSED. The only valid
+ * operation for such an iterator is
+ * dbus_message_iter_abandon_container_if_open(), which does nothing.
+ */
+void
+dbus_message_iter_init_closed (DBusMessageIter *iter)
+{
+ _dbus_return_if_fail (iter != NULL);
+ _dbus_message_real_iter_zero ((DBusMessageRealIter *) iter);
+}
+
+static dbus_bool_t
+_dbus_message_real_iter_is_zeroed (DBusMessageRealIter *iter)
+{
+ return (iter != NULL && iter->message == NULL && iter->changed_stamp == 0 &&
+ iter->iter_type == 0 && iter->sig_refcount == 0);
+}
+
#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
static dbus_bool_t
_dbus_message_iter_check (DBusMessageRealIter *iter)
@@ -840,7 +851,14 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)
if (iter == NULL)
{
- _dbus_warn_check_failed ("dbus message iterator is NULL\n");
+ _dbus_warn_check_failed ("dbus message iterator is NULL");
+ return FALSE;
+ }
+
+ if (iter->message == NULL || iter->iter_type == 0)
+ {
+ _dbus_warn_check_failed ("dbus message iterator has already been "
+ "closed, or is uninitialized or corrupt");
return FALSE;
}
@@ -850,7 +868,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)
{
if (iter->u.reader.byte_order != byte_order)
{
- _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
+ _dbus_warn_check_failed ("dbus message changed byte order since iterator was created");
return FALSE;
}
/* because we swap the message into compiler order when you init an iter */
@@ -860,7 +878,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)
{
if (iter->u.writer.byte_order != byte_order)
{
- _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
+ _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created");
return FALSE;
}
/* because we swap the message into compiler order when you init an iter */
@@ -868,13 +886,13 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)
}
else
{
- _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
+ _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted");
return FALSE;
}
if (iter->changed_stamp != iter->message->changed_stamp)
{
- _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
+ _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)");
return FALSE;
}
@@ -1074,7 +1092,7 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
#ifndef DBUS_DISABLE_CHECKS
else
{
- _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
+ _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now",
_DBUS_FUNCTION_NAME);
goto out;
}
@@ -1083,7 +1101,7 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
#ifndef DBUS_DISABLE_CHECKS
else
{
- _dbus_warn ("you can only read arrays and basic types with %s for now\n",
+ _dbus_warn ("you can only read arrays and basic types with %s for now",
_DBUS_FUNCTION_NAME);
goto out;
}
@@ -2036,7 +2054,7 @@ dbus_message_append_args_valist (DBusMessage *message,
}
else
{
- _dbus_warn ("arrays of %s can't be appended with %s for now\n",
+ _dbus_warn ("arrays of %s can't be appended with %s for now",
_dbus_type_to_string (element_type),
_DBUS_FUNCTION_NAME);
dbus_message_iter_abandon_container (&iter, &array);
@@ -2049,7 +2067,7 @@ dbus_message_append_args_valist (DBusMessage *message,
#ifndef DBUS_DISABLE_CHECKS
else
{
- _dbus_warn ("type %s isn't supported yet in %s\n",
+ _dbus_warn ("type %s isn't supported yet in %s",
_dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
goto failed;
}
@@ -2157,7 +2175,21 @@ _dbus_message_iter_init_common (DBusMessage *message,
DBusMessageRealIter *real,
int iter_type)
{
+ /* If these static assertions fail on your platform, report it as a bug. */
_DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
+ _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
+ _DBUS_ALIGNOF (DBusMessageIter));
+ /* A failure of these two assertions would indicate that we've broken
+ * ABI on this platform since 1.10.0. */
+ _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
+ sizeof (DBusMessageIter));
+ _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
+ _DBUS_ALIGNOF (DBusMessageIter));
+ /* If this static assertion fails, it means the DBusMessageIter struct
+ * is not "packed", which might result in "iter = other_iter" not copying
+ * every byte. */
+ _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
+ 4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
/* Since the iterator will read or write who-knows-what from the
* message, we need to get in the right byte order
@@ -2691,6 +2723,9 @@ _dbus_message_iter_open_signature (DBusMessageRealIter *real)
real->sig_refcount = 1;
+ /* If this assertion failed, then str would be neither stored in u.writer
+ * nor freed by this function, resulting in a memory leak. */
+ _dbus_assert (real->u.writer.type_str == NULL);
_dbus_type_writer_add_types (&real->u.writer,
str, _dbus_string_get_length (str));
return TRUE;
@@ -2778,7 +2813,7 @@ _dbus_message_iter_append_check (DBusMessageRealIter *iter)
if (iter->message->locked)
{
- _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
+ _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
return FALSE;
}
@@ -2855,6 +2890,8 @@ dbus_message_iter_append_basic (DBusMessageIter *iter,
#ifndef DBUS_DISABLE_CHECKS
switch (type)
{
+ DBusString str;
+ DBusValidity signature_validity;
const char * const *string_p;
const dbus_bool_t *bool_p;
@@ -2870,7 +2907,15 @@ dbus_message_iter_append_basic (DBusMessageIter *iter,
case DBUS_TYPE_SIGNATURE:
string_p = value;
- _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
+ _dbus_string_init_const (&str, *string_p);
+ signature_validity = _dbus_validate_signature_with_reason (&str,
+ 0,
+ _dbus_string_get_length (&str));
+
+ if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
+ return FALSE;
+
+ _dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
break;
case DBUS_TYPE_BOOLEAN:
@@ -3018,8 +3063,8 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
}
/**
- * Appends a container-typed value to the message; you are required to
- * append the contents of the container using the returned
+ * Appends a container-typed value to the message. On success, you are
+ * required to append the contents of the container using the returned
* sub-iterator, and then call
* dbus_message_iter_close_container(). Container types are for
* example struct, variant, and array. For variants, the
@@ -3032,6 +3077,12 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
* @todo If this fails due to lack of memory, the message is hosed and
* you have to start over building the whole message.
*
+ * If this function fails, the sub-iterator remains invalid, and must
+ * not be closed with dbus_message_iter_close_container() or abandoned
+ * with dbus_message_iter_abandon_container(). However, after this
+ * function has either succeeded or failed, it is valid to call
+ * dbus_message_iter_abandon_container_if_open().
+ *
* @param iter the append iterator
* @param type the type of the value
* @param contained_signature the type of container contents
@@ -3047,12 +3098,17 @@ dbus_message_iter_open_container (DBusMessageIter *iter,
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
DBusString contained_str;
+ DBusValidity contained_signature_validity;
dbus_bool_t ret;
+ _dbus_return_val_if_fail (sub != NULL, FALSE);
+ /* Do our best to make sure the sub-iterator doesn't contain something
+ * valid-looking on failure */
+ _dbus_message_real_iter_zero (real_sub);
+
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
_dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
- _dbus_return_val_if_fail (sub != NULL, FALSE);
_dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
contained_signature == NULL) ||
(type == DBUS_TYPE_DICT_ENTRY &&
@@ -3066,9 +3122,25 @@ dbus_message_iter_open_container (DBusMessageIter *iter,
* dict entries are invalid signatures standalone (they must be in
* an array)
*/
+ if (contained_signature != NULL)
+ {
+ _dbus_string_init_const (&contained_str, contained_signature);
+ contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
+ 0,
+ _dbus_string_get_length (&contained_str));
+
+ if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
+ return FALSE;
+ }
+ else
+ {
+ /* just some placeholder value */
+ contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
+ }
+
_dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
- (contained_signature == NULL ||
- _dbus_check_is_valid_signature (contained_signature)),
+ contained_signature == NULL ||
+ contained_signature_validity == DBUS_VALID,
FALSE);
if (!_dbus_message_iter_open_signature (real))
@@ -3082,16 +3154,16 @@ dbus_message_iter_open_container (DBusMessageIter *iter,
_dbus_string_init_const (&contained_str, contained_signature);
ret = _dbus_type_writer_recurse (&real->u.writer,
- type,
- &contained_str, 0,
- &real_sub->u.writer);
+ type,
+ &contained_str, 0,
+ &real_sub->u.writer);
}
else
{
ret = _dbus_type_writer_recurse (&real->u.writer,
- type,
- NULL, 0,
- &real_sub->u.writer);
+ type,
+ NULL, 0,
+ &real_sub->u.writer);
}
if (!ret)
@@ -3107,6 +3179,12 @@ dbus_message_iter_open_container (DBusMessageIter *iter,
* container is written, and may free resources created by
* dbus_message_iter_open_container().
*
+ * Even if this function fails due to lack of memory, the sub-iterator sub
+ * has been closed and invalidated. It must not be closed again with this
+ * function, or abandoned with dbus_message_iter_abandon_container().
+ * However, it remains valid to call
+ * dbus_message_iter_abandon_container_if_open().
+ *
* @todo If this fails due to lack of memory, the message is hosed and
* you have to start over building the whole message.
*
@@ -3129,6 +3207,7 @@ dbus_message_iter_close_container (DBusMessageIter *iter,
ret = _dbus_type_writer_unrecurse (&real->u.writer,
&real_sub->u.writer);
+ _dbus_message_real_iter_zero (real_sub);
if (!_dbus_message_iter_close_signature (real))
ret = FALSE;
@@ -3152,16 +3231,107 @@ dbus_message_iter_abandon_container (DBusMessageIter *iter,
DBusMessageIter *sub)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
+
#ifndef DBUS_DISABLE_CHECKS
+ _dbus_return_if_fail (_dbus_message_iter_append_check (real));
+ _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+ _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
+ _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+#endif
+
+ _dbus_message_iter_abandon_signature (real);
+ _dbus_message_real_iter_zero (real_sub);
+}
+
+/**
+ * Abandons creation of a contained-typed value and frees resources created
+ * by dbus_message_iter_open_container(). Once this returns, the message
+ * is hosed and you have to start over building the whole message.
+ *
+ * Unlike dbus_message_iter_abandon_container(), it is valid to call this
+ * function on an iterator that was initialized with
+ * #DBUS_MESSAGE_ITER_INIT_CLOSED, or an iterator that was already closed
+ * or abandoned. However, it is not valid to call this function on
+ * uninitialized memory. This is intended to be used in error cleanup
+ * code paths, similar to this pattern:
+ *
+ * DBusMessageIter outer = DBUS_MESSAGE_ITER_INIT_CLOSED;
+ * DBusMessageIter inner = DBUS_MESSAGE_ITER_INIT_CLOSED;
+ * dbus_bool_t result = FALSE;
+ *
+ * if (!dbus_message_iter_open_container (iter, ..., &outer))
+ * goto out;
+ *
+ * if (!dbus_message_iter_open_container (&outer, ..., &inner))
+ * goto out;
+ *
+ * if (!dbus_message_iter_append_basic (&inner, ...))
+ * goto out;
+ *
+ * if (!dbus_message_iter_close_container (&outer, ..., &inner))
+ * goto out;
+ *
+ * if (!dbus_message_iter_close_container (iter, ..., &outer))
+ * goto out;
+ *
+ * result = TRUE;
+ *
+ * out:
+ * dbus_message_iter_abandon_container_if_open (&outer, &inner);
+ * dbus_message_iter_abandon_container_if_open (iter, &outer);
+ * return result;
+ *
+ * @param iter the append iterator
+ * @param sub sub-iterator to close
+ */
+void
+dbus_message_iter_abandon_container_if_open (DBusMessageIter *iter,
+ DBusMessageIter *sub)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
+ /* If both the parent and the child are zeroed out, then either we didn't
+ * even get as far as successfully recursing into the parent, or we already
+ * closed both the child and the parent. For example, in the code sample
+ * in the doc-comment above, this happens for
+ * abandon_container_if_open (&outer, &inner) if the first open_container
+ * call failed, or if we reached result = TRUE and fell through. */
+ if (_dbus_message_real_iter_is_zeroed (real) &&
+ _dbus_message_real_iter_is_zeroed (real_sub))
+ return;
+
+#ifndef DBUS_DISABLE_CHECKS
+ /* If the child is not zeroed out, but the parent is, then something has
+ * gone horribly wrong (in practice that would probably mean both are
+ * uninitialized or corrupt, and the parent happens to have ended up
+ * all-bytes-zero). */
_dbus_return_if_fail (_dbus_message_iter_append_check (real));
_dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+#endif
+
+ /* If the parent is not zeroed out, but the child is, then either we did
+ * not successfully open the child, or we already closed the child. This
+ * means we do not own a reference to the parent's signature, so it would
+ * be wrong to release it; so we must not call abandon_signature() here.
+ * In the code sample in the doc-comment above, this happens for
+ * abandon_container_if_open (&outer, &inner) if the second open_container
+ * call failed, or if the second close_container call failed. */
+ if (_dbus_message_real_iter_is_zeroed (real_sub))
+ return;
+
+#ifndef DBUS_DISABLE_CHECKS
_dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
_dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
#endif
+ /* If neither the parent nor the child is zeroed out, then we genuinely
+ * have an open container; close it. In the code sample in the doc-comment,
+ * this happens for abandon_container_if_open (&outer, &inner) if the
+ * append_basic call failed. */
_dbus_message_iter_abandon_signature (real);
+ _dbus_message_real_iter_zero (real_sub);
}
/**
@@ -4163,13 +4333,101 @@ _dbus_message_loader_unref (DBusMessageLoader *loader)
*/
void
_dbus_message_loader_get_buffer (DBusMessageLoader *loader,
- DBusString **buffer)
+ DBusString **buffer,
+ int *max_to_read,
+ dbus_bool_t *may_read_fds)
{
_dbus_assert (!loader->buffer_outstanding);
*buffer = &loader->data;
loader->buffer_outstanding = TRUE;
+
+ if (max_to_read != NULL)
+ {
+#ifdef HAVE_UNIX_FD_PASSING
+ int offset = 0;
+ int remain;
+ int byte_order;
+ int fields_array_len;
+ int header_len;
+ int body_len;
+#endif
+
+ *max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
+ *may_read_fds = TRUE;
+
+#ifdef HAVE_UNIX_FD_PASSING
+ /* If we aren't holding onto any fds, we can read as much as we want
+ * (fast path). */
+ if (loader->n_unix_fds == 0)
+ return;
+
+ /* Slow path: we have a message with some fds in it. We don't want
+ * to start on the next message until this one is out of the way;
+ * otherwise a legitimate sender can keep us processing messages
+ * containing fds, until we disconnect it for having had fds pending
+ * for too long, a limit that is in place to stop malicious senders
+ * from setting up recursive fd-passing that takes up our quota and
+ * will never go away. */
+
+ remain = _dbus_string_get_length (&loader->data);
+
+ while (remain > 0)
+ {
+ DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
+ int needed;
+ dbus_bool_t is_gvariant;
+
+ /* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
+ * least the first byte of a message, but we don't know how
+ * much more to read. Only read the rest of the
+ * DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
+ if (remain < DBUS_MINIMUM_HEADER_SIZE)
+ {
+ *max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
+ *may_read_fds = FALSE;
+ return;
+ }
+
+ if (!_dbus_header_have_message_untrusted (loader->max_message_size,
+ &validity,
+ &byte_order,
+ &fields_array_len,
+ &header_len,
+ &body_len,
+ &loader->data,
+ offset,
+ remain,
+ &is_gvariant))
+ {
+ /* If a message in the buffer is invalid, we're going to
+ * disconnect the sender anyway, so reading an arbitrary amount
+ * is fine. */
+ if (validity != DBUS_VALID)
+ return;
+
+ /* We have a partial message, with the
+ * DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
+ * lets us work out how much more we need), but no more. Read
+ * the rest of the message. */
+ needed = header_len + body_len;
+ _dbus_assert (needed > remain);
+ *max_to_read = needed - remain;
+ *may_read_fds = FALSE;
+ return;
+ }
+
+ /* Skip over entire messages until we have less than a message
+ * remaining. */
+ needed = header_len + body_len;
+ _dbus_assert (needed > DBUS_MINIMUM_HEADER_SIZE);
+ _dbus_assert (remain >= needed);
+ remain -= needed;
+ offset += needed;
+ }
+#endif
+ }
}
/**
@@ -4191,6 +4449,7 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
loader->buffer_outstanding = FALSE;
}
+#ifdef HAVE_UNIX_FD_PASSING
/**
* Gets the buffer to use for reading unix fds from the network.
*
@@ -4206,7 +4465,6 @@ _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
int **fds,
unsigned *max_n_fds)
{
-#ifdef HAVE_UNIX_FD_PASSING
_dbus_assert (!loader->unix_fds_outstanding);
/* Allocate space where we can put the fds we read. We allocate
@@ -4234,10 +4492,6 @@ _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
loader->unix_fds_outstanding = TRUE;
return TRUE;
-#else
- _dbus_assert_not_reached("Platform doesn't support unix fd passing");
- return FALSE;
-#endif
}
/**
@@ -4255,7 +4509,6 @@ _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
int *fds,
unsigned n_fds)
{
-#ifdef HAVE_UNIX_FD_PASSING
_dbus_assert(loader->unix_fds_outstanding);
_dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
_dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
@@ -4265,10 +4518,8 @@ _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
if (n_fds && loader->unix_fds_change)
loader->unix_fds_change (loader->unix_fds_change_data);
-#else
- _dbus_assert_not_reached("Platform doesn't support unix fd passing");
-#endif
}
+#endif
/*
* FIXME when we move the header out of the buffer, that memmoves all
@@ -5228,7 +5479,7 @@ dbus_message_demarshal (const char *str,
if (loader == NULL)
return NULL;
- _dbus_message_loader_get_buffer (loader, &buffer);
+ _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
if (!_dbus_string_append_len (buffer, str, len))
goto fail_oom;
@@ -5543,8 +5794,8 @@ dbus_set_default_protocol_strategy (const char *strategy_name)
DBusMessage *
_dbus_generate_local_error_message (dbus_uint32_t serial,
- char *error_name,
- char *error_msg)
+ const char *error_name,
+ const char *error_msg)
{
DBusMessage *message;
message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
@@ -5609,6 +5860,248 @@ _dbus_message_assure_gvariant (DBusMessage **message)
return FALSE;
}
+/**
+ * An opaque data structure containing the serialized form of any single
+ * D-Bus message item, whose signature is a single complete type.
+ *
+ * (Implementation detail: It's serialized as a single variant.)
+ */
+struct DBusVariant
+{
+ DBusString data;
+};
+
+/**
+ * Copy a single D-Bus message item from reader into a
+ * newly-allocated #DBusVariant.
+ *
+ * For example, if a message contains three string arguments, and reader points
+ * to the second string, the resulting DBusVariant will have signature
+ * #DBUS_TYPE_STRING_AS_STRING and contain only that second string.
+ *
+ * @param reader An iterator over message items, pointing to one item to copy
+ * @returns The variant, or #NULL if out of memory
+ */
+DBusVariant *
+_dbus_variant_read (DBusMessageIter *reader)
+{
+ DBusVariant *self = NULL;
+ /* Points to the single item we will read from the reader */
+ DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
+ /* The position in self at which we will write a single variant
+ * (it is position 0) */
+ DBusTypeWriter items_writer;
+ /* The position in self at which we will write a copy of reader
+ * (it is inside the variant) */
+ DBusTypeWriter variant_writer;
+ /* 'v' */
+ DBusString variant_signature;
+ /* Whatever is the signature of the item we will copy from the reader */
+ DBusString contained_signature;
+ /* TRUE if self->data needs to be freed */
+ dbus_bool_t data_inited = FALSE;
+ /* The type of the item we will read from the reader */
+ int type;
+ /* The string, start position within that string, and length of the signature
+ * of the single complete type of the item reader points to */
+ const DBusString *sig;
+ int start, len;
+
+ _dbus_assert (_dbus_message_iter_check (real_reader));
+ _dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
+ _dbus_string_init_const (&variant_signature, DBUS_TYPE_VARIANT_AS_STRING);
+ type = dbus_message_iter_get_arg_type (reader);
+ _dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
+
+ if (!_dbus_string_init (&contained_signature))
+ return NULL;
+
+ if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
+ goto oom;
+
+ self = dbus_new0 (DBusVariant, 1);
+
+ if (self == NULL)
+ goto oom;
+
+ if (!_dbus_string_init (&self->data))
+ goto oom;
+
+ data_inited = TRUE;
+
+ _dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
+ &variant_signature, 0, &self->data, 0);
+
+ if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
+ &contained_signature, 0, &variant_writer))
+ goto oom;
+
+ if (type == DBUS_TYPE_ARRAY)
+ {
+ /* Points to each item in turn inside the array we are copying */
+ DBusMessageIter array_reader;
+ /* Same as array_reader */
+ DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
+ /* The position inside the copied array at which we will write
+ * the copy of array_reader */
+ DBusTypeWriter array_writer;
+
+ dbus_message_iter_recurse (reader, &array_reader);
+
+ if (!_dbus_type_writer_recurse (&variant_writer, type,
+ &contained_signature, 1, &array_writer))
+ goto oom;
+
+ if (!_dbus_type_writer_write_reader (&array_writer,
+ &real_array_reader->u.reader))
+ goto oom;
+
+ if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
+ goto oom;
+ }
+ else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
+ type == DBUS_TYPE_STRUCT)
+ {
+ /* Points to each item in turn inside the container we are copying */
+ DBusMessageIter inner_reader;
+ /* Same as inner_reader */
+ DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
+ /* The position inside the copied container at which we will write the
+ * copy of inner_reader */
+ DBusTypeWriter inner_writer;
+
+ dbus_message_iter_recurse (reader, &inner_reader);
+
+ if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
+ &inner_writer))
+ goto oom;
+
+ if (!_dbus_type_writer_write_reader (&inner_writer,
+ &real_inner_reader->u.reader))
+ goto oom;
+
+ if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
+ goto oom;
+ }
+ else
+ {
+ DBusBasicValue value;
+
+ /* We eliminated all the container types above */
+ _dbus_assert (dbus_type_is_basic (type));
+
+ dbus_message_iter_get_basic (reader, &value);
+
+ if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
+ goto oom;
+ }
+
+ _dbus_string_free (&contained_signature);
+ return self;
+
+oom:
+ if (self != NULL)
+ {
+ if (data_inited)
+ _dbus_string_free (&self->data);
+
+ dbus_free (self);
+ }
+
+ _dbus_string_free (&contained_signature);
+ return NULL;
+}
+
+/**
+ * Return the signature of the item stored in self. It is a single complete
+ * type.
+ *
+ * @param self the variant
+ */
+const char *
+_dbus_variant_get_signature (DBusVariant *self)
+{
+ unsigned char len;
+ const char *ret;
+
+ _dbus_assert (self != NULL);
+
+ /* Here we make use of the fact that the serialization of a variant starts
+ * with the 1-byte length, then that many bytes of signature, then \0. */
+ len = _dbus_string_get_byte (&self->data, 0);
+ ret = _dbus_string_get_const_data_len (&self->data, 1, len);
+ _dbus_assert (strlen (ret) == len);
+ return ret;
+}
+
+/**
+ * Copy the single D-Bus message item from self into writer.
+ *
+ * For example, if writer points into the body of an empty message and self has
+ * signature #DBUS_TYPE_STRING_AS_STRING, then the message will
+ * have signature #DBUS_TYPE_STRING_AS_STRING after this function returns
+ *
+ * @param self the variant
+ * @param writer the place to write the contents of the variant
+ * @returns #TRUE on success, #FALSE if out of memory
+ */
+dbus_bool_t
+_dbus_variant_write (DBusVariant *self,
+ DBusMessageIter *writer)
+{
+ /* 'v' */
+ DBusString variant_signature;
+ /* Points to the single item in self */
+ DBusTypeReader variant_reader;
+ /* Points to the single item (of whatever type) inside the variant */
+ DBusTypeReader reader;
+ /* The position at which we will copy reader */
+ DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
+ dbus_bool_t ret;
+
+ _dbus_assert (self != NULL);
+ _dbus_assert (_dbus_message_iter_append_check (real_writer));
+ _dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+
+ _dbus_string_init_const (&variant_signature, DBUS_TYPE_VARIANT_AS_STRING);
+ _dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
+ &variant_signature, 0, &self->data, 0);
+ _dbus_type_reader_recurse (&reader, &variant_reader);
+
+ if (!_dbus_message_iter_open_signature (real_writer))
+ return FALSE;
+
+ ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
+ &variant_reader);
+
+ if (!_dbus_message_iter_close_signature (real_writer))
+ return FALSE;
+
+ return ret;
+}
+
+int
+_dbus_variant_get_length (DBusVariant *self)
+{
+ _dbus_assert (self != NULL);
+ return _dbus_string_get_length (&self->data);
+}
+
+const DBusString *
+_dbus_variant_peek (DBusVariant *self)
+{
+ _dbus_assert (self != NULL);
+ return &self->data;
+}
+
+void
+_dbus_variant_free (DBusVariant *self)
+{
+ _dbus_assert (self != NULL);
+ _dbus_string_free (&self->data);
+ dbus_free (self);
+}
+
/** @} */
/* tests in dbus-message-util.c */
diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
index 1c8f9dd6..db66c581 100644
--- a/dbus/dbus-message.h
+++ b/dbus/dbus-message.h
@@ -43,7 +43,17 @@ DBUS_BEGIN_DECLS
*/
typedef struct DBusMessage DBusMessage;
-/** Opaque type representing a message iterator. Can be copied by value, and contains no allocated memory so never needs to be freed and can be allocated on the stack. */
+/**
+ * Opaque type representing a message iterator. Can be copied by value and
+ * allocated on the stack.
+ *
+ * A DBusMessageIter usually contains no allocated memory. However, there
+ * is one special case: after a successful call to
+ * dbus_message_iter_open_container(), the caller is responsible for calling
+ * either dbus_message_iter_close_container() or
+ * dbus_message_iter_abandon_container() exactly once, with the same pair
+ * of iterators.
+ */
typedef struct DBusMessageIter DBusMessageIter;
/**
@@ -122,6 +132,30 @@ struct DBusMessageIter
} u;
};
+/**
+ * A message iterator for which dbus_message_iter_abandon_container_if_open()
+ * is the only valid operation.
+ */
+#define DBUS_MESSAGE_ITER_INIT_CLOSED \
+{ \
+ NULL, /* dummy1 */ \
+ 0, 0, 0, /* dummy3a, dummy3b, dummy3c */ \
+ { .s2 = {0, 0, 0, 0, 0, 0, 0, /* dummy1a-1g */ \
+ NULL, /* dummy2 */ \
+ 0, /* dummy3 */ \
+ NULL, /* dummy4 */ \
+ 0, /* dummy5 */ \
+ 0, /* dummy6 */ \
+ 0, /* dummy7 */ \
+ 0, /* dummy8 */ \
+ 0, /* dummy9 */ \
+ {{ .dummy10 = 0, /* dummy10 */ \
+ .dummy11 = 0, /* dummy11 */ \
+ .dummy12 = 0, /* dummy12 */ \
+ }} \
+ }} \
+}
+
DBUS_EXPORT
DBusMessage* dbus_message_new (int message_type);
DBUS_EXPORT
@@ -143,7 +177,7 @@ DBUS_EXPORT
DBusMessage* dbus_message_new_error_printf (DBusMessage *reply_to,
const char *error_name,
const char *error_format,
- ...);
+ ...) _DBUS_GNUC_PRINTF (3, 4);
DBUS_EXPORT
DBusMessage* dbus_message_copy (const DBusMessage *message);
@@ -264,6 +298,8 @@ DBUS_EXPORT
dbus_bool_t dbus_message_contains_unix_fds (DBusMessage *message);
DBUS_EXPORT
+void dbus_message_iter_init_closed (DBusMessageIter *iter);
+DBUS_EXPORT
dbus_bool_t dbus_message_iter_init (DBusMessage *message,
DBusMessageIter *iter);
DBUS_EXPORT
@@ -323,6 +359,10 @@ void dbus_message_iter_abandon_container (DBusMessageIter *iter,
DBusMessageIter *sub);
DBUS_EXPORT
+void dbus_message_iter_abandon_container_if_open (DBusMessageIter *iter,
+ DBusMessageIter *sub);
+
+DBUS_EXPORT
void dbus_message_lock (DBusMessage *message);
DBUS_EXPORT
@@ -373,6 +413,24 @@ DBUS_EXPORT
void dbus_set_protocol_version (unsigned char version);
DBUS_EXPORT
void dbus_set_default_protocol_strategy (const char *strategy_name);
+/**
+ * Clear a variable or struct member that contains a #DBusMessage.
+ * If it does not contain #NULL, the message that was previously
+ * there is unreferenced with dbus_message_unref().
+ *
+ * This is very similar to dbus_clear_connection(): see that function
+ * for more details.
+ *
+ * @param pointer_to_message A pointer to a variable or struct member.
+ * pointer_to_message must not be #NULL, but *pointer_to_message
+ * may be #NULL.
+ */
+static inline void
+dbus_clear_message (DBusMessage **pointer_to_message)
+{
+ _dbus_clear_pointer_impl (DBusMessage, pointer_to_message,
+ dbus_message_unref);
+}
/** @} */
diff --git a/dbus/dbus-misc.c b/dbus/dbus-misc.c
index a2da562a..2be58a25 100644
--- a/dbus/dbus-misc.c
+++ b/dbus/dbus-misc.c
@@ -67,10 +67,10 @@
* The UUID is not a UUID in the sense of RFC4122; the details
* are explained in the D-Bus specification.
*
- * @returns a 32-byte-long hex-encoded UUID string, or #NULL if insufficient memory
+ * @returns a 32-byte-long hex-encoded UUID string, or #NULL on failure
*/
-char*
-dbus_get_local_machine_id (void)
+char *
+dbus_try_get_local_machine_id (DBusError *error)
{
DBusString uuid;
char *s;
@@ -78,18 +78,23 @@ dbus_get_local_machine_id (void)
s = NULL;
if (!_dbus_string_init (&uuid))
- return NULL;
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ return NULL;
+ }
- /* The documentation says dbus_get_local_machine_id() only fails on OOM;
- * this can actually also fail if the D-Bus installation is faulty
- * (no UUID) *and* reading a new random UUID fails, but we have no way
- * to report that */
- if (!_dbus_get_local_machine_uuid_encoded (&uuid, NULL) ||
- !_dbus_string_steal_data (&uuid, &s))
+ if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
{
_dbus_string_free (&uuid);
return NULL;
}
+
+ if (!_dbus_string_steal_data (&uuid, &s))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ _dbus_string_free (&uuid);
+ return NULL;
+ }
else
{
_dbus_string_free (&uuid);
@@ -99,6 +104,46 @@ dbus_get_local_machine_id (void)
}
/**
+ * Obtains the machine UUID of the machine this process is running on.
+ *
+ * The returned string must be freed with dbus_free().
+ *
+ * This function returns #NULL if there was not enough memory to read
+ * the UUID, or if the UUID could not be read because the D-Bus
+ * library was installed incorrectly. In the latter case, a warning
+ * is logged.
+ *
+ * Other than its deficient error reporting, this function is the same as
+ * dbus_try_get_local_machine_id().
+ *
+ * @returns a 32-byte-long hex-encoded UUID string, or #NULL on failure
+ */
+char *
+dbus_get_local_machine_id (void)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ char *s;
+
+ s = dbus_try_get_local_machine_id (&error);
+
+ /* The documentation says dbus_get_local_machine_id() only fails on OOM;
+ * this can actually also fail if the D-Bus installation is faulty
+ * (no UUID), but we have no good way to report that. Historically,
+ * _dbus_get_local_machine_uuid_encoded was responsible for issuing the
+ * warning; now we do that here. */
+ if (s == NULL)
+ {
+ if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ _dbus_warn_check_failed ("%s", error.message);
+
+ dbus_error_free (&error);
+ return NULL;
+ }
+
+ return s;
+}
+
+/**
* @def DBUS_MAJOR_VERSION
*
* The COMPILE TIME major version of libdbus, that is, the "X" in "X.Y.Z",
diff --git a/dbus/dbus-misc.h b/dbus/dbus-misc.h
index 6e72d9ed..d78d7993 100644
--- a/dbus/dbus-misc.h
+++ b/dbus/dbus-misc.h
@@ -48,6 +48,9 @@ DBUS_EXPORT
dbus_bool_t dbus_setenv (const char *variable,
const char *value);
+DBUS_EXPORT
+char *dbus_try_get_local_machine_id (DBusError *error);
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-nonce.c b/dbus/dbus-nonce.c
index 3c0f6f37..00255d39 100644
--- a/dbus/dbus-nonce.c
+++ b/dbus/dbus-nonce.c
@@ -43,6 +43,20 @@ do_check_nonce (DBusSocket fd, const DBusString *nonce, DBusError *error)
nleft = 16;
+ /* This is a trick to make it safe to call _dbus_string_free on these
+ * strings during error unwinding, even if allocating memory for them
+ * fails. A constant DBusString is considered to be valid to "free",
+ * even though there is nothing to free (of course the free operation
+ * is trivial, because it does not own its own buffer); but
+ * unlike a mutable DBusString, initializing a constant DBusString
+ * cannot fail.
+ *
+ * We must successfully re-initialize the strings to be mutable before
+ * writing to them, of course.
+ */
+ _dbus_string_init_const (&buffer, "");
+ _dbus_string_init_const (&p, "");
+
if ( !_dbus_string_init (&buffer)
|| !_dbus_string_init (&p) ) {
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
@@ -64,7 +78,7 @@ do_check_nonce (DBusSocket fd, const DBusString *nonce, DBusError *error)
_dbus_sleep_milliseconds (100);
else if (n==-1)
{
- dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
+ dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%" DBUS_SOCKET_FORMAT ")", _dbus_socket_printable (fd));
_dbus_string_free (&p);
_dbus_string_free (&buffer);
return FALSE;
@@ -73,7 +87,7 @@ do_check_nonce (DBusSocket fd, const DBusString *nonce, DBusError *error)
{
_dbus_string_free (&p);
_dbus_string_free (&buffer);
- dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
+ dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%" DBUS_SOCKET_FORMAT ")", _dbus_socket_printable (fd));
return FALSE;
}
else
@@ -91,7 +105,7 @@ do_check_nonce (DBusSocket fd, const DBusString *nonce, DBusError *error)
result = _dbus_string_equal_len (&buffer, nonce, 16);
if (!result)
- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%d)", fd );
+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%" DBUS_SOCKET_FORMAT ")", _dbus_socket_printable (fd));
_dbus_string_free (&p);
_dbus_string_free (&buffer);
@@ -151,24 +165,36 @@ _dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error)
DBusSocket
_dbus_accept_with_noncefile (DBusSocket listen_fd, const DBusNonceFile *noncefile)
{
- DBusSocket fd;
+ DBusSocket fd = _dbus_socket_get_invalid ();
DBusString nonce;
_dbus_assert (noncefile != NULL);
+
+ /* Make it valid to "free" this even if _dbus_string_init() runs
+ * out of memory: see comment in do_check_nonce() */
+ _dbus_string_init_const (&nonce, "");
+
if (!_dbus_string_init (&nonce))
- return _dbus_socket_get_invalid ();
+ goto out;
+
//PENDING(kdab): set better errors
if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
- return _dbus_socket_get_invalid ();
+ goto out;
+
fd = _dbus_accept (listen_fd);
+
if (!_dbus_socket_is_valid (fd))
- return fd;
+ goto out;
+
if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
_dbus_verbose ("nonce check failed. Closing socket.\n");
_dbus_close_socket(fd, NULL);
- return _dbus_socket_get_invalid ();
+ _dbus_socket_invalidate (&fd);
+ goto out;
}
+out:
+ _dbus_string_free (&nonce);
return fd;
}
@@ -245,8 +271,9 @@ _dbus_send_nonce (DBusSocket fd,
{
dbus_set_error (error,
_dbus_error_from_system_errno (),
- "Failed to send nonce (fd=%d): %s",
- fd, _dbus_strerror_from_errno ());
+ "Failed to send nonce (fd=%" DBUS_SOCKET_FORMAT "): %s",
+ _dbus_socket_printable (fd),
+ _dbus_strerror_from_errno ());
return FALSE;
}
@@ -265,6 +292,12 @@ do_noncefile_create (DBusNonceFile *noncefile,
_dbus_assert (noncefile);
+ /* Make it valid to "free" these even if _dbus_string_init() runs
+ * out of memory: see comment in do_check_nonce() */
+ _dbus_string_init_const (&randomStr, "");
+ _dbus_string_init_const (&noncefile->dir, "");
+ _dbus_string_init_const (&noncefile->path, "");
+
if (!_dbus_string_init (&randomStr))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
@@ -334,7 +367,7 @@ do_noncefile_create (DBusNonceFile *noncefile,
return TRUE;
on_error:
- if (use_subdir)
+ if (use_subdir && _dbus_string_get_length (&noncefile->dir) != 0)
_dbus_delete_directory (&noncefile->dir, NULL);
_dbus_string_free (&noncefile->dir);
_dbus_string_free (&noncefile->path);
diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c
index e2a3b737..ab5df39b 100644
--- a/dbus/dbus-object-tree.c
+++ b/dbus/dbus-object-tree.c
@@ -647,7 +647,7 @@ _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree,
#ifndef DBUS_DISABLE_CHECKS
if (found_subtree == FALSE)
{
- _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n",
+ _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered",
path[0] ? path[0] : "null",
(path[0] && path[1]) ? path[1] : "null");
goto unlock;
@@ -1592,14 +1592,6 @@ do_test_dispatch (DBusObjectTree *tree,
return FALSE;
}
-static size_t
-string_array_length (const char **array)
-{
- size_t i;
- for (i = 0; array[i]; i++) ;
- return i;
-}
-
typedef struct
{
const char *path;
@@ -1617,6 +1609,8 @@ static DecomposePathTest decompose_tests[] = {
{ "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } }
};
+/* Return TRUE on success, FALSE on OOM, die with an assertion failure
+ * on failure. */
static dbus_bool_t
run_decompose_tests (void)
{
@@ -1634,15 +1628,15 @@ run_decompose_tests (void)
&result, &result_len))
return FALSE;
- expected_len = string_array_length (decompose_tests[i].result);
+ expected_len = _dbus_string_array_length (decompose_tests[i].result);
- if (result_len != (int) string_array_length ((const char**)result) ||
+ if (result_len != (int) _dbus_string_array_length ((const char**)result) ||
expected_len != result_len ||
path_contains (decompose_tests[i].result,
(const char**) result) != STR_EQUAL)
{
- int real_len = string_array_length ((const char**)result);
- _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d\n",
+ int real_len = _dbus_string_array_length ((const char**)result);
+ _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d",
decompose_tests[i].path, expected_len, result_len,
real_len);
_dbus_warn ("Decompose resulted in elements: { ");
@@ -1653,8 +1647,8 @@ run_decompose_tests (void)
(i + 1) == real_len ? "" : ", ");
++i;
}
- _dbus_warn ("}\n");
- _dbus_assert_not_reached ("path decompose failed\n");
+ _dbus_warn ("}");
+ _dbus_assert_not_reached ("path decompose failed");
}
dbus_free_string_array (result);
@@ -1676,6 +1670,8 @@ find_subtree_registered_or_unregistered (DBusObjectTree *tree,
return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL);
}
+/* Returns TRUE if the right thing happens, but the right thing might
+ * be OOM. */
static dbus_bool_t
object_tree_test_iteration (void *data)
{
@@ -1701,7 +1697,7 @@ object_tree_test_iteration (void *data)
dbus_bool_t exact_match;
if (!run_decompose_tests ())
- return FALSE;
+ return TRUE; /* OOM is OK */
tree = NULL;
@@ -1875,7 +1871,7 @@ object_tree_test_iteration (void *data)
_dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries);
if (child_entries != NULL)
{
- nb = string_array_length ((const char**)child_entries);
+ nb = _dbus_string_array_length ((const char**)child_entries);
_dbus_assert (nb == 1);
dbus_free_string_array (child_entries);
}
@@ -1883,7 +1879,7 @@ object_tree_test_iteration (void *data)
_dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries);
if (child_entries != NULL)
{
- nb = string_array_length ((const char**)child_entries);
+ nb = _dbus_string_array_length ((const char**)child_entries);
_dbus_assert (nb == 2);
dbus_free_string_array (child_entries);
}
@@ -1891,7 +1887,7 @@ object_tree_test_iteration (void *data)
_dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries);
if (child_entries != NULL)
{
- nb = string_array_length ((const char**)child_entries);
+ nb = _dbus_string_array_length ((const char**)child_entries);
_dbus_assert (nb == 0);
dbus_free_string_array (child_entries);
}
@@ -1899,7 +1895,7 @@ object_tree_test_iteration (void *data)
_dbus_object_tree_list_registered_unlocked (tree, root, &child_entries);
if (child_entries != NULL)
{
- nb = string_array_length ((const char**)child_entries);
+ nb = _dbus_string_array_length ((const char**)child_entries);
_dbus_assert (nb == 3);
dbus_free_string_array (child_entries);
}
@@ -2323,11 +2319,9 @@ object_tree_test_iteration (void *data)
dbus_bool_t
_dbus_object_tree_test (void)
{
- _dbus_test_oom_handling ("object tree",
- object_tree_test_iteration,
- NULL);
-
- return TRUE;
+ return _dbus_test_oom_handling ("object tree",
+ object_tree_test_iteration,
+ NULL);
}
#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/dbus/dbus-pending-call-internal.h b/dbus/dbus-pending-call-internal.h
index 393e6608..4f379b4f 100644
--- a/dbus/dbus-pending-call-internal.h
+++ b/dbus/dbus-pending-call-internal.h
@@ -41,13 +41,14 @@ void _dbus_pending_call_set_reply_serial_unlocked (DBusPendingCal
DBusConnection * _dbus_pending_call_get_connection_and_lock (DBusPendingCall *pending);
DBusConnection * _dbus_pending_call_get_connection_unlocked (DBusPendingCall *pending);
dbus_bool_t _dbus_pending_call_get_completed_unlocked (DBusPendingCall *pending);
-void _dbus_pending_call_complete (DBusPendingCall *pending);
+
+void _dbus_pending_call_start_completion_unlocked (DBusPendingCall *pending);
+void _dbus_pending_call_finish_completion (DBusPendingCall *pending);
+
void _dbus_pending_call_set_reply_unlocked (DBusPendingCall *pending,
DBusMessage *message);
void _dbus_pending_call_queue_timeout_error_unlocked (DBusPendingCall *pending,
DBusConnection *connection);
-void _dbus_pending_call_set_reply_serial_unlocked (DBusPendingCall *pending,
- dbus_uint32_t serial);
dbus_bool_t _dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending,
DBusMessage *message,
dbus_uint32_t serial);
diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c
index ed96242e..7e664abd 100644
--- a/dbus/dbus-pending-call.c
+++ b/dbus/dbus-pending-call.c
@@ -75,8 +75,16 @@ struct DBusPendingCall
dbus_uint32_t reply_serial; /**< Expected serial of reply */
- unsigned int completed : 1; /**< TRUE if completed */
- unsigned int timeout_added : 1; /**< Have added the timeout */
+ /**
+ * TRUE if some thread has taken responsibility for completing this
+ * pending call: either the pending call has completed, or it is about
+ * to be completed. Protected by the connection lock.
+ */
+ unsigned int completed : 1;
+ /**
+ * TRUE if we have added the timeout. Protected by the connection lock.
+ */
+ unsigned int timeout_added : 1;
};
static void
@@ -194,18 +202,36 @@ _dbus_pending_call_set_reply_unlocked (DBusPendingCall *pending,
}
/**
- * Calls notifier function for the pending call
- * and sets the call to completed.
+ * Sets the pending call to completed
+ *
+ * This method is called with the connection lock held, to protect
+ * pending->completed. It must be paired with a call to
+ * _dbus_pending_call_finish_completion() after the connection lock has
+ * been released.
*
* @param pending the pending call
- *
*/
void
-_dbus_pending_call_complete (DBusPendingCall *pending)
+_dbus_pending_call_start_completion_unlocked (DBusPendingCall *pending)
{
_dbus_assert (!pending->completed);
pending->completed = TRUE;
+}
+
+/**
+ * Call the notifier function for the pending call.
+ *
+ * This method must be called after the connection lock has been
+ * released, and must be paired with a call to
+ * _dbus_pending_call_start_completion_unlocked().
+ *
+ * @param pending the pending call
+ */
+void
+_dbus_pending_call_finish_completion (DBusPendingCall *pending)
+{
+ _dbus_assert (pending->completed);
if (pending->function)
{
diff --git a/dbus/dbus-pending-call.h b/dbus/dbus-pending-call.h
index 8a37ec0a..5593397a 100644
--- a/dbus/dbus-pending-call.h
+++ b/dbus/dbus-pending-call.h
@@ -72,6 +72,25 @@ DBUS_EXPORT
void* dbus_pending_call_get_data (DBusPendingCall *pending,
dbus_int32_t slot);
+/**
+ * Clear a variable or struct member that contains a #DBusPendingCall.
+ * If it does not contain #NULL, the pending call that was previously
+ * there is unreferenced with dbus_pending_call_unref().
+ *
+ * This is very similar to dbus_clear_connection(): see that function
+ * for more details.
+ *
+ * @param pointer_to_pending_call A pointer to a variable or struct member.
+ * pointer_to_pending_call must not be #NULL, but *pointer_to_pending_call
+ * may be #NULL.
+ */
+static inline void
+dbus_clear_pending_call (DBusPendingCall **pointer_to_pending_call)
+{
+ _dbus_clear_pointer_impl (DBusPendingCall, pointer_to_pending_call,
+ dbus_pending_call_unref);
+}
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h
index f613bf34..5664b2b4 100644
--- a/dbus/dbus-server-protected.h
+++ b/dbus/dbus-server-protected.h
@@ -96,6 +96,7 @@ dbus_bool_t _dbus_server_init_base (DBusServer *server,
const DBusString *address,
DBusError *error);
void _dbus_server_finalize_base (DBusServer *server);
+void _dbus_server_disconnect_unlocked (DBusServer *server);
dbus_bool_t _dbus_server_add_watch (DBusServer *server,
DBusWatch *watch);
void _dbus_server_remove_watch (DBusServer *server,
diff --git a/dbus/dbus-server-socket.c b/dbus/dbus-server-socket.c
index d716f500..6a93091a 100644
--- a/dbus/dbus-server-socket.c
+++ b/dbus/dbus-server-socket.c
@@ -243,8 +243,11 @@ socket_disconnect (DBusServer *server)
socket_server->watch[i] = NULL;
}
- _dbus_close_socket (socket_server->fds[i], NULL);
- _dbus_socket_invalidate (&socket_server->fds[i]);
+ if (_dbus_socket_is_valid (socket_server->fds[i]))
+ {
+ _dbus_close_socket (socket_server->fds[i], NULL);
+ _dbus_socket_invalidate (&socket_server->fds[i]);
+ }
}
if (socket_server->socket_name != NULL)
@@ -338,10 +341,24 @@ _dbus_server_new_for_socket (DBusSocket *fds,
socket_server->watch[i]))
{
int j;
- for (j = 0 ; j < i ; j++)
- _dbus_server_remove_watch (server,
- socket_server->watch[j]);
+ /* The caller is still responsible for closing the fds until
+ * we return successfully, so don't let socket_disconnect()
+ * close them */
+ for (j = 0; j < n_fds; j++)
+ _dbus_socket_invalidate (&socket_server->fds[j]);
+
+ /* socket_disconnect() will try to remove all the watches;
+ * make sure it doesn't see the ones that weren't even added
+ * yet */
+ for (j = i; j < n_fds; j++)
+ {
+ _dbus_watch_invalidate (socket_server->watch[j]);
+ _dbus_watch_unref (socket_server->watch[j]);
+ socket_server->watch[j] = NULL;
+ }
+
+ _dbus_server_disconnect_unlocked (server);
SERVER_UNLOCK (server);
_dbus_server_finalize_base (&socket_server->base);
goto failed_2;
@@ -358,6 +375,7 @@ _dbus_server_new_for_socket (DBusSocket *fds,
{
if (socket_server->watch[i] != NULL)
{
+ _dbus_watch_invalidate (socket_server->watch[i]);
_dbus_watch_unref (socket_server->watch[i]);
socket_server->watch[i] = NULL;
}
diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c
index 92664a8d..c7ace2bc 100644
--- a/dbus/dbus-server-unix.c
+++ b/dbus/dbus-server-unix.c
@@ -64,18 +64,19 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
if (strcmp (method, "unix") == 0)
{
const char *path = dbus_address_entry_get_value (entry, "path");
+ const char *dir = dbus_address_entry_get_value (entry, "dir");
const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
const char *abstract = dbus_address_entry_get_value (entry, "abstract");
const char *runtime = dbus_address_entry_get_value (entry, "runtime");
int mutually_exclusive_modes = 0;
mutually_exclusive_modes = (path != NULL) + (tmpdir != NULL) +
- (abstract != NULL) + (runtime != NULL);
+ (abstract != NULL) + (runtime != NULL) + (dir != NULL);
if (mutually_exclusive_modes < 1)
{
_dbus_set_bad_address(error, "unix",
- "path or tmpdir or abstract or runtime",
+ "path or tmpdir or abstract or runtime or dir",
NULL);
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
}
@@ -83,7 +84,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
if (mutually_exclusive_modes > 1)
{
_dbus_set_bad_address(error, NULL, NULL,
- "cannot specify two of \"path\", \"tmpdir\", \"abstract\" and \"runtime\" at the same time");
+ "cannot specify two of \"path\", \"tmpdir\", \"abstract\", \"runtime\" and \"dir\" at the same time");
return DBUS_SERVER_LISTEN_BAD_ADDRESS;
}
@@ -134,10 +135,23 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
_dbus_string_free (&full_path);
}
- else if (tmpdir != NULL)
+ else if (tmpdir != NULL || dir != NULL)
{
DBusString full_path;
DBusString filename;
+ dbus_bool_t use_abstract = FALSE;
+
+ if (tmpdir != NULL)
+ {
+ dir = tmpdir;
+
+#ifdef __linux__
+ /* Use abstract sockets for tmpdir if supported, so that it
+ * never needs to be cleaned up. Use dir instead if you want a
+ * path-based socket. */
+ use_abstract = TRUE;
+#endif
+ }
if (!_dbus_string_init (&full_path))
{
@@ -167,7 +181,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
}
- if (!_dbus_string_append (&full_path, tmpdir) ||
+ if (!_dbus_string_append (&full_path, dir) ||
!_dbus_concat_dir_and_file (&full_path, &filename))
{
_dbus_string_free (&full_path);
@@ -176,15 +190,9 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
}
- /* Always use abstract namespace if possible with tmpdir */
-
*server_p =
_dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
-#ifdef HAVE_ABSTRACT_SOCKETS
- TRUE,
-#else
- FALSE,
-#endif
+ use_abstract,
error);
_dbus_string_free (&full_path);
@@ -241,6 +249,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
goto systemd_err;
dbus_free (fds);
+ _dbus_string_free (&address);
return DBUS_SERVER_LISTEN_OK;
diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
index 9af906fa..7a1243b8 100644
--- a/dbus/dbus-server.c
+++ b/dbus/dbus-server.c
@@ -680,6 +680,7 @@ dbus_server_listen (const char *address,
}
else
{
+ dbus_error_free (&first_connect_error);
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
return server;
}
@@ -704,9 +705,8 @@ dbus_server_ref (DBusServer *server)
if (_DBUS_UNLIKELY (old_refcount <= 0))
{
_dbus_atomic_dec (&server->refcount);
- _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
- _DBUS_FUNCTION_NAME, "old_refcount > 0",
- __FILE__, __LINE__);
+ _dbus_warn_return_if_fail (_DBUS_FUNCTION_NAME, "old_refcount > 0",
+ __FILE__, __LINE__);
return NULL;
}
#endif
@@ -746,9 +746,8 @@ dbus_server_unref (DBusServer *server)
* Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68303
*/
_dbus_atomic_inc (&server->refcount);
- _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
- _DBUS_FUNCTION_NAME, "old_refcount > 0",
- __FILE__, __LINE__);
+ _dbus_warn_return_if_fail (_DBUS_FUNCTION_NAME, "old_refcount > 0",
+ __FILE__, __LINE__);
return;
}
#endif
@@ -766,6 +765,20 @@ dbus_server_unref (DBusServer *server)
}
}
+void
+_dbus_server_disconnect_unlocked (DBusServer *server)
+{
+ _dbus_assert (server->vtable->disconnect != NULL);
+
+ if (!server->disconnected)
+ {
+ /* this has to be first so recursive calls to disconnect don't happen */
+ server->disconnected = TRUE;
+
+ (* server->vtable->disconnect) (server);
+ }
+}
+
/**
* Releases the server's address and stops listening for
* new clients. If called more than once, only the first
@@ -782,15 +795,7 @@ dbus_server_disconnect (DBusServer *server)
dbus_server_ref (server);
SERVER_LOCK (server);
- _dbus_assert (server->vtable->disconnect != NULL);
-
- if (!server->disconnected)
- {
- /* this has to be first so recursive calls to disconnect don't happen */
- server->disconnected = TRUE;
-
- (* server->vtable->disconnect) (server);
- }
+ _dbus_server_disconnect_unlocked (server);
SERVER_UNLOCK (server);
dbus_server_unref (server);
@@ -962,7 +967,7 @@ dbus_server_set_watch_functions (DBusServer *server,
}
else
{
- _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
+ _dbus_warn_check_failed ("Re-entrant call to %s", _DBUS_FUNCTION_NAME);
result = FALSE;
}
server->watches = watches;
@@ -1015,7 +1020,7 @@ dbus_server_set_timeout_functions (DBusServer *server,
}
else
{
- _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
+ _dbus_warn_check_failed ("Re-entrant call to %s", _DBUS_FUNCTION_NAME);
result = FALSE;
}
server->timeouts = timeouts;
@@ -1213,7 +1218,7 @@ _dbus_server_test (void)
server = dbus_server_listen (valid_addresses[i], &error);
if (server == NULL)
{
- _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
+ _dbus_warn ("server listen error: %s: %s", error.name, error.message);
dbus_error_free (&error);
_dbus_assert_not_reached ("Failed to listen for valid address.");
}
@@ -1225,7 +1230,7 @@ _dbus_server_test (void)
if (strstr (address, id) == NULL)
{
- _dbus_warn ("server id '%s' is not in the server address '%s'\n",
+ _dbus_warn ("server id '%s' is not in the server address '%s'",
id, address);
_dbus_assert_not_reached ("bad server id or address");
}
diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h
index bdbefa0f..7d8f04e4 100644
--- a/dbus/dbus-server.h
+++ b/dbus/dbus-server.h
@@ -28,6 +28,7 @@
#define DBUS_SERVER_H
#include <dbus/dbus-errors.h>
+#include <dbus/dbus-macros.h>
#include <dbus/dbus-message.h>
#include <dbus/dbus-connection.h>
#include <dbus/dbus-protocol.h>
@@ -99,6 +100,24 @@ DBUS_EXPORT
void* dbus_server_get_data (DBusServer *server,
int slot);
+/**
+ * Clear a variable or struct member that contains a #DBusServer.
+ * If it does not contain #NULL, the server that was previously
+ * there is unreferenced with dbus_server_unref().
+ *
+ * This is very similar to dbus_clear_connection(): see that function
+ * for more details.
+ *
+ * @param pointer_to_server A pointer to a variable or struct member.
+ * pointer_to_server must not be #NULL, but *pointer_to_server
+ * may be #NULL.
+ */
+static inline void
+dbus_clear_server (DBusServer **pointer_to_server)
+{
+ _dbus_clear_pointer_impl (DBusServer, pointer_to_server, dbus_server_unref);
+}
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-sha.c b/dbus/dbus-sha.c
index febfba20..52c74f54 100644
--- a/dbus/dbus-sha.c
+++ b/dbus/dbus-sha.c
@@ -460,7 +460,7 @@ _dbus_sha_final (DBusSHAContext *context,
sha_finish (context, digest);
- if (!_dbus_string_append_len (results, digest, 20))
+ if (!_dbus_string_append_len (results, (const char *) digest, 20))
return FALSE;
/* some kind of security paranoia, though it seems pointless
@@ -524,7 +524,7 @@ check_sha_binary (const unsigned char *input,
DBusString expected_str;
DBusString results;
- _dbus_string_init_const_len (&input_str, input, input_len);
+ _dbus_string_init_const_len (&input_str, (const char *) input, input_len);
_dbus_string_init_const (&expected_str, expected);
if (!_dbus_string_init (&results))
@@ -535,7 +535,7 @@ check_sha_binary (const unsigned char *input,
if (!_dbus_string_equal (&expected_str, &results))
{
- _dbus_warn ("Expected hash %s got %s for SHA-1 sum\n",
+ _dbus_warn ("Expected hash %s got %s for SHA-1 sum",
expected,
_dbus_string_get_const_data (&results));
_dbus_string_free (&results);
@@ -550,7 +550,7 @@ static dbus_bool_t
check_sha_str (const char *input,
const char *expected)
{
- return check_sha_binary (input, strlen (input), expected);
+ return check_sha_binary ((unsigned char *) input, strlen (input), expected);
}
static dbus_bool_t
@@ -693,7 +693,9 @@ get_next_expected_result (DBusString *results,
i = 0;
while (i < _dbus_string_get_length (result))
{
- switch (_dbus_string_get_byte (result, i))
+ unsigned char c = _dbus_string_get_byte (result, i);
+
+ switch (c)
{
case 'A':
_dbus_string_set_byte (result, i, 'a');
@@ -718,6 +720,9 @@ get_next_expected_result (DBusString *results,
_dbus_string_delete (result, i, 1);
--i; /* to offset ++i below */
break;
+ default:
+ if ((c < '0' || c > '9') && (c < 'a' || c > 'f'))
+ _dbus_assert_not_reached ("invalid SHA-1 test script");
}
++i;
diff --git a/dbus/dbus-shell.c b/dbus/dbus-shell.c
index 2384961c..44cbbcf3 100644
--- a/dbus/dbus-shell.c
+++ b/dbus/dbus-shell.c
@@ -419,15 +419,15 @@ tokenize_command_line (const char *command_line, DBusError *error)
{
case '\n':
if (!delimit_token (&current_token, &retval, error))
- goto error;
+ goto error;
- _dbus_string_free (&current_token);
+ _dbus_string_free (&current_token);
- if (!_dbus_string_init (&current_token))
- {
- _DBUS_SET_OOM (error);
- goto init_error;
- }
+ if (!_dbus_string_init (&current_token))
+ {
+ _DBUS_SET_OOM (error);
+ goto init_error;
+ }
break;
diff --git a/dbus/dbus-signature.c b/dbus/dbus-signature.c
index 6f1521b1..ef9eca91 100644
--- a/dbus/dbus-signature.c
+++ b/dbus/dbus-signature.c
@@ -244,7 +244,8 @@ dbus_signature_validate (const char *signature,
return TRUE;
else
{
- dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, _dbus_validity_to_error_message (reason));
+ dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "%s",
+ _dbus_validity_to_error_message (reason));
return FALSE;
}
}
diff --git a/dbus/dbus-socket-set-epoll.c b/dbus/dbus-socket-set-epoll.c
index aedc26df..4692cbe4 100644
--- a/dbus/dbus-socket-set-epoll.c
+++ b/dbus/dbus-socket-set-epoll.c
@@ -144,6 +144,7 @@ socket_set_epoll_add (DBusSocketSet *set,
struct epoll_event event;
int err;
+ _DBUS_ZERO (event);
event.data.fd = fd;
if (enabled)
@@ -171,15 +172,15 @@ socket_set_epoll_add (DBusSocketSet *set,
break;
case EBADF:
- _dbus_warn ("Bad fd %d\n", fd);
+ _dbus_warn ("Bad fd %d", fd);
break;
case EEXIST:
- _dbus_warn ("fd %d added and then added again\n", fd);
+ _dbus_warn ("fd %d added and then added again", fd);
break;
default:
- _dbus_warn ("Misc error when trying to watch fd %d: %s\n", fd,
+ _dbus_warn ("Misc error when trying to watch fd %d: %s", fd,
strerror (err));
break;
}
@@ -196,6 +197,7 @@ socket_set_epoll_enable (DBusSocketSet *set,
struct epoll_event event;
int err;
+ _DBUS_ZERO (event);
event.data.fd = fd;
event.events = watch_flags_to_epoll_events (flags);
@@ -209,19 +211,19 @@ socket_set_epoll_enable (DBusSocketSet *set,
switch (err)
{
case EBADF:
- _dbus_warn ("Bad fd %d\n", fd);
+ _dbus_warn ("Bad fd %d", fd);
break;
case ENOENT:
- _dbus_warn ("fd %d enabled before it was added\n", fd);
+ _dbus_warn ("fd %d enabled before it was added", fd);
break;
case ENOMEM:
- _dbus_warn ("Insufficient memory to change watch for fd %d\n", fd);
+ _dbus_warn ("Insufficient memory to change watch for fd %d", fd);
break;
default:
- _dbus_warn ("Misc error when trying to watch fd %d: %s\n", fd,
+ _dbus_warn ("Misc error when trying to watch fd %d: %s", fd,
strerror (err));
break;
}
@@ -251,6 +253,7 @@ socket_set_epoll_disable (DBusSocketSet *set,
* work on 2.6.32). Compile this file with -DTEST_BEHAVIOUR_OF_EPOLLET for
* test code.
*/
+ _DBUS_ZERO (event);
event.data.fd = fd;
event.events = EPOLLET;
@@ -258,7 +261,7 @@ socket_set_epoll_disable (DBusSocketSet *set,
return;
err = errno;
- _dbus_warn ("Error when trying to watch fd %d: %s\n", fd,
+ _dbus_warn ("Error when trying to watch fd %d: %s", fd,
strerror (err));
}
@@ -270,13 +273,14 @@ socket_set_epoll_remove (DBusSocketSet *set,
int err;
/* Kernels < 2.6.9 require a non-NULL struct pointer, even though its
* contents are ignored */
- struct epoll_event dummy = { 0 };
+ struct epoll_event dummy;
+ _DBUS_ZERO (dummy);
if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, &dummy) == 0)
return;
err = errno;
- _dbus_warn ("Error when trying to remove fd %d: %s\n", fd, strerror (err));
+ _dbus_warn ("Error when trying to remove fd %d: %s", fd, strerror (err));
}
/* Optimally, this should be the same as in DBusLoop: we use it to translate
@@ -346,6 +350,8 @@ main (void)
int fd = 0; /* stdin */
int ret;
+ _DBUS_ZERO (input);
+
input.events = EPOLLHUP | EPOLLET;
ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &input);
printf ("ctl ADD: %d\n", ret);
diff --git a/dbus/dbus-spawn-test.c b/dbus/dbus-spawn-test.c
new file mode 100644
index 00000000..2d9b6ec7
--- /dev/null
+++ b/dbus/dbus-spawn-test.c
@@ -0,0 +1,288 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-spawn-test.c
+ *
+ * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include <config.h>
+
+
+#include "dbus-spawn.h"
+#include "dbus-sysdeps.h"
+#include "dbus-test.h"
+
+static char *
+get_test_exec (const char *exe,
+ DBusString *scratch_space)
+{
+ const char *dbus_test_exec;
+
+ dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
+
+ if (dbus_test_exec == NULL)
+ return NULL;
+
+ if (!_dbus_string_init (scratch_space))
+ return NULL;
+
+ if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
+ dbus_test_exec, exe, DBUS_EXEEXT))
+ {
+ _dbus_string_free (scratch_space);
+ return NULL;
+ }
+
+ return _dbus_string_get_data (scratch_space);
+}
+
+static dbus_bool_t
+check_spawn_nonexistent (void *data)
+{
+ static const char arg_does_not_exist[] = "/this/does/not/exist/32542sdgafgafdg";
+
+ const char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+
+ /*** Test launching nonexistent binary */
+
+ argv[0] = arg_does_not_exist;
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent",
+ (char * const *) argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_block_for_child_exit (sitter);
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error launching nonexistent executable");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
+ {
+ _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_segfault (void *data)
+{
+ char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusString argv0;
+
+ /*** Test launching segfault binary */
+
+ argv[0] = get_test_exec ("test-segfault", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
+ return TRUE;
+ }
+
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_block_for_child_exit (sitter);
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ _dbus_string_free (&argv0);
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error launching segfaulting binary");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+#ifdef DBUS_WIN
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+#else
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
+#endif
+ {
+ _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_exit (void *data)
+{
+ char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusString argv0;
+
+ /*** Test launching exit failure binary */
+
+ argv[0] = get_test_exec ("test-exit", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
+ return TRUE;
+ }
+
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_block_for_child_exit (sitter);
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ _dbus_string_free (&argv0);
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error launching binary that exited with failure code");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+ {
+ _dbus_warn ("Not expecting error when launching exiting executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_and_kill (void *data)
+{
+ char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusString argv0;
+
+ /*** Test launching sleeping binary then killing it */
+
+ argv[0] = get_test_exec ("test-sleep-forever", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
+ return TRUE;
+ }
+
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_kill_child (sitter);
+
+ _dbus_babysitter_block_for_child_exit (sitter);
+
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ _dbus_string_free (&argv0);
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error after killing spawned binary");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+#ifdef DBUS_WIN
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+#else
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
+#endif
+ {
+ _dbus_warn ("Not expecting error when killing executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+dbus_bool_t
+_dbus_spawn_test (const char *test_data_dir)
+{
+ if (!_dbus_test_oom_handling ("spawn_nonexistent",
+ check_spawn_nonexistent,
+ NULL))
+ return FALSE;
+
+ if (!_dbus_test_oom_handling ("spawn_segfault",
+ check_spawn_segfault,
+ NULL))
+ return FALSE;
+
+ if (!_dbus_test_oom_handling ("spawn_exit",
+ check_spawn_exit,
+ NULL))
+ return FALSE;
+
+ if (!_dbus_test_oom_handling ("spawn_and_kill",
+ check_spawn_and_kill,
+ NULL))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/dbus/dbus-spawn-win.c b/dbus/dbus-spawn-win.c
index c58bf3cd..cc5bfc3b 100644
--- a/dbus/dbus-spawn-win.c
+++ b/dbus/dbus-spawn-win.c
@@ -60,22 +60,17 @@
*/
struct DBusBabysitter
{
- int refcount;
+ DBusAtomic refcount;
HANDLE start_sync_event;
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
-
- HANDLE end_sync_event;
-#endif
char *log_name;
- DBusSpawnChildSetupFunc child_setup;
- void *user_data;
int argc;
char **argv;
char **envp;
+ HANDLE thread_handle;
HANDLE child_handle;
DBusSocket socket_to_babysitter; /* Connection to the babysitter thread */
DBusSocket socket_to_main;
@@ -91,16 +86,33 @@ struct DBusBabysitter
int child_status;
};
+static void
+_dbus_babysitter_trace_ref (DBusBabysitter *sitter,
+ int old_refcount,
+ int new_refcount,
+ const char *why)
+{
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+ static int enabled = -1;
+
+ _dbus_trace_ref ("DBusBabysitter", sitter, old_refcount, new_refcount, why,
+ "DBUS_BABYSITTER_TRACE", &enabled);
+#endif
+}
+
static DBusBabysitter*
_dbus_babysitter_new (void)
{
DBusBabysitter *sitter;
+ dbus_int32_t old_refcount;
sitter = dbus_new0 (DBusBabysitter, 1);
if (sitter == NULL)
return NULL;
- sitter->refcount = 1;
+ old_refcount = _dbus_atomic_inc (&sitter->refcount);
+
+ _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
if (sitter->start_sync_event == NULL)
@@ -109,15 +121,6 @@ _dbus_babysitter_new (void)
return NULL;
}
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
- sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
- if (sitter->end_sync_event == NULL)
- {
- _dbus_babysitter_unref (sitter);
- return NULL;
- }
-#endif
-
sitter->child_handle = NULL;
sitter->socket_to_babysitter = sitter->socket_to_main = _dbus_socket_get_invalid ();
@@ -148,11 +151,13 @@ _dbus_babysitter_new (void)
DBusBabysitter *
_dbus_babysitter_ref (DBusBabysitter *sitter)
{
+ dbus_int32_t old_refcount;
PING();
_dbus_assert (sitter != NULL);
- _dbus_assert (sitter->refcount > 0);
- sitter->refcount += 1;
+ old_refcount = _dbus_atomic_inc (&sitter->refcount);
+ _dbus_assert (old_refcount > 0);
+ _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
return sitter;
}
@@ -187,14 +192,16 @@ void
_dbus_babysitter_unref (DBusBabysitter *sitter)
{
int i;
+ dbus_int32_t old_refcount;
PING();
_dbus_assert (sitter != NULL);
- _dbus_assert (sitter->refcount > 0);
- sitter->refcount -= 1;
+ old_refcount = _dbus_atomic_dec (&sitter->refcount);
+ _dbus_assert (old_refcount > 0);
+ _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, __FUNCTION__);
- if (sitter->refcount == 0)
+ if (old_refcount == 1)
{
close_socket_to_babysitter (sitter);
@@ -250,13 +257,11 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
sitter->start_sync_event = NULL;
}
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
- if (sitter->end_sync_event != NULL)
+ if (sitter->thread_handle)
{
- CloseHandle (sitter->end_sync_event);
- sitter->end_sync_event = NULL;
+ CloseHandle (sitter->thread_handle);
+ sitter->thread_handle = NULL;
}
-#endif
dbus_free (sitter->log_name);
@@ -407,8 +412,8 @@ handle_watch (DBusWatch *watch,
/* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
static int
-protect_argv (char **argv,
- char ***new_argv)
+protect_argv (char * const *argv,
+ char ***new_argv)
{
int i;
int argc = 0;
@@ -435,7 +440,7 @@ protect_argv (char **argv,
*/
for (i = 0; i < argc; i++)
{
- char *p = argv[i];
+ const char *p = argv[i];
char *q;
int len = 0;
int need_dblquotes = FALSE;
@@ -447,7 +452,7 @@ protect_argv (char **argv,
len++;
else if (*p == '\\')
{
- char *pp = p;
+ const char *pp = p;
while (*pp && *pp == '\\')
pp++;
if (*pp == '"')
@@ -474,7 +479,7 @@ protect_argv (char **argv,
*q++ = '\\';
else if (*p == '\\')
{
- char *pp = p;
+ const char *pp = p;
while (*pp && *pp == '\\')
pp++;
if (*pp == '"')
@@ -584,24 +589,20 @@ babysitter (void *parameter)
{
int ret = 0;
DBusBabysitter *sitter = (DBusBabysitter *) parameter;
+ HANDLE handle;
PING();
- _dbus_babysitter_ref (sitter);
-
- if (sitter->child_setup)
- {
- PING();
- (*sitter->child_setup) (sitter->user_data);
- }
-
_dbus_verbose ("babysitter: spawning %s\n", sitter->log_name);
PING();
- sitter->child_handle = spawn_program (sitter->log_name,
- sitter->argv, sitter->envp);
+ handle = spawn_program (sitter->log_name, sitter->argv, sitter->envp);
PING();
- if (sitter->child_handle == (HANDLE) -1)
+ if (handle != INVALID_HANDLE_VALUE)
+ {
+ sitter->child_handle = handle;
+ }
+ else
{
sitter->child_handle = NULL;
sitter->have_spawn_errno = TRUE;
@@ -631,10 +632,6 @@ babysitter (void *parameter)
sitter->child_handle = NULL;
}
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
- SetEvent (sitter->end_sync_event);
-#endif
-
PING();
send (sitter->socket_to_main.sock, " ", 1, 0);
@@ -646,20 +643,21 @@ babysitter (void *parameter)
dbus_bool_t
_dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
const char *log_name,
- char **argv,
+ char * const *argv,
char **envp,
- DBusSpawnChildSetupFunc child_setup,
- void *user_data,
+ DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
+ DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
+ void *user_data _DBUS_GNUC_UNUSED,
DBusError *error)
{
DBusBabysitter *sitter;
- HANDLE sitter_thread;
DWORD sitter_thread_id;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_assert (argv[0] != NULL);
- *sitter_p = NULL;
+ if (sitter_p != NULL)
+ *sitter_p = NULL;
PING();
sitter = _dbus_babysitter_new ();
@@ -669,9 +667,6 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
return FALSE;
}
- sitter->child_setup = child_setup;
- sitter->user_data = user_data;
-
sitter->log_name = _dbus_strdup (log_name);
if (sitter->log_name == NULL && log_name != NULL)
{
@@ -726,17 +721,16 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
sitter->envp = envp;
PING();
- sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
- sitter, 0, &sitter_thread_id);
+ sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
+ _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
- if (sitter_thread == 0)
+ if (sitter->thread_handle == NULL)
{
PING();
dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
"Failed to create new thread");
goto out0;
}
- CloseHandle (sitter_thread);
PING();
WaitForSingleObject (sitter->start_sync_event, INFINITE);
@@ -767,283 +761,13 @@ _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
sitter->finished_data = user_data;
}
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
-
-static char *
-get_test_exec (const char *exe,
- DBusString *scratch_space)
-{
- const char *dbus_test_exec;
-
- dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
-
- if (dbus_test_exec == NULL)
- dbus_test_exec = DBUS_TEST_EXEC;
-
- if (!_dbus_string_init (scratch_space))
- return NULL;
-
- if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
- dbus_test_exec, exe, DBUS_EXEEXT))
- {
- _dbus_string_free (scratch_space);
- return NULL;
- }
-
- return _dbus_string_get_data (scratch_space);
-}
-
#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
-static void
+void
_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
{
- if (sitter->child_handle == NULL)
- return;
-
- WaitForSingleObject (sitter->end_sync_event, INFINITE);
-}
-
-static dbus_bool_t
-check_spawn_nonexistent (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter;
- DBusError error;
-
- sitter = NULL;
-
- dbus_error_init (&error);
-
- /*** Test launching nonexistent binary */
-
- argv[0] = "/this/does/not/exist/32542sdgafgafdg";
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv, NULL,
- NULL, NULL,
- &error))
- {
- _dbus_babysitter_block_for_child_exit (sitter);
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error launching nonexistent executable\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
- {
- _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
+ /* The thread terminates after the child does. We want to wait for the thread,
+ * not just the child, to avoid data races and ensure that it has freed all
+ * its memory. */
+ WaitForSingleObject (sitter->thread_handle, INFINITE);
}
-
-static dbus_bool_t
-check_spawn_segfault (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter;
- DBusError error;
- DBusString argv0;
-
- sitter = NULL;
-
- dbus_error_init (&error);
-
- /*** Test launching segfault binary */
-
- argv[0] = get_test_exec ("test-segfault", &argv0);
-
- if (argv[0] == NULL)
- {
- /* OOM was simulated, never mind */
- return TRUE;
- }
-
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv, NULL,
- NULL, NULL,
- &error))
- {
- _dbus_babysitter_block_for_child_exit (sitter);
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- _dbus_string_free (&argv0);
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error launching segfaulting binary\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
- {
- _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_spawn_exit (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter;
- DBusError error;
- DBusString argv0;
-
- sitter = NULL;
-
- dbus_error_init (&error);
-
- /*** Test launching exit failure binary */
-
- argv[0] = get_test_exec ("test-exit", &argv0);
-
- if (argv[0] == NULL)
- {
- /* OOM was simulated, never mind */
- return TRUE;
- }
-
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv, NULL,
- NULL, NULL,
- &error))
- {
- _dbus_babysitter_block_for_child_exit (sitter);
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- _dbus_string_free (&argv0);
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
- {
- _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_spawn_and_kill (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter;
- DBusError error;
- DBusString argv0;
-
- sitter = NULL;
-
- dbus_error_init (&error);
-
- /*** Test launching sleeping binary then killing it */
-
- argv[0] = get_test_exec ("test-sleep-forever", &argv0);
-
- if (argv[0] == NULL)
- {
- /* OOM was simulated, never mind */
- return TRUE;
- }
-
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv, NULL,
- NULL, NULL,
- &error))
- {
- _dbus_babysitter_kill_child (sitter);
-
- _dbus_babysitter_block_for_child_exit (sitter);
-
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- _dbus_string_free (&argv0);
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error after killing spawned binary\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
- {
- _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-dbus_bool_t
-_dbus_spawn_test (const char *test_data_dir)
-{
- if (!_dbus_test_oom_handling ("spawn_nonexistent",
- check_spawn_nonexistent,
- NULL))
- return FALSE;
-
- /* Don't run the obnoxious segfault test by default,
- * it's a pain to have to click all those error boxes.
- */
- if (getenv ("DO_SEGFAULT_TEST"))
- if (!_dbus_test_oom_handling ("spawn_segfault",
- check_spawn_segfault,
- NULL))
- return FALSE;
-
- if (!_dbus_test_oom_handling ("spawn_exit",
- check_spawn_exit,
- NULL))
- return FALSE;
-
- if (!_dbus_test_oom_handling ("spawn_and_kill",
- check_spawn_and_kill,
- NULL))
- return FALSE;
-
- return TRUE;
-}
-#endif
diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c
index d58d7981..8ab529a4 100644
--- a/dbus/dbus-spawn.c
+++ b/dbus/dbus-spawn.c
@@ -45,7 +45,12 @@
#include <systemd/sd-journal.h>
#endif
+#if defined(__APPLE__)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron ())
+#elif !HAVE_DECL_ENVIRON
extern char **environ;
+#endif
/**
* @addtogroup DBusInternalsUtils
@@ -369,9 +374,9 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
if (ret < 0)
{
if (errno == ECHILD)
- _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
+ _dbus_warn ("Babysitter process not available to be reaped; should not happen");
else
- _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
+ _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s",
errno, _dbus_strerror (errno));
}
else
@@ -415,7 +420,7 @@ read_data (DBusBabysitter *sitter,
switch (r)
{
case READ_STATUS_ERROR:
- _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
+ _dbus_warn ("Failed to read data from fd %d: %s", fd, error.message);
dbus_error_free (&error);
return r;
@@ -424,6 +429,10 @@ read_data (DBusBabysitter *sitter,
case READ_STATUS_OK:
break;
+
+ default:
+ _dbus_assert_not_reached ("invalid ReadStatus");
+ break;
}
if (got == 1)
@@ -441,13 +450,16 @@ read_data (DBusBabysitter *sitter,
switch (r)
{
case READ_STATUS_ERROR:
- _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
+ _dbus_warn ("Failed to read arg from fd %d: %s", fd, error.message);
dbus_error_free (&error);
return r;
case READ_STATUS_EOF:
return r;
case READ_STATUS_OK:
break;
+ default:
+ _dbus_assert_not_reached ("invalid ReadStatus");
+ break;
}
if (got == 1)
@@ -501,13 +513,16 @@ read_data (DBusBabysitter *sitter,
switch (r)
{
case READ_STATUS_ERROR:
- _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
+ _dbus_warn ("Failed to read PID from fd %d: %s", fd, error.message);
dbus_error_free (&error);
return r;
case READ_STATUS_EOF:
return r;
case READ_STATUS_OK:
break;
+ default:
+ _dbus_assert_not_reached ("invalid ReadStatus");
+ break;
}
sitter->grandchild_pid = pid;
@@ -516,7 +531,7 @@ read_data (DBusBabysitter *sitter,
}
break;
default:
- _dbus_warn ("Unknown message received from babysitter process\n");
+ _dbus_warn ("Unknown message received from babysitter process");
break;
}
}
@@ -960,7 +975,7 @@ do_write (int fd, const void *buf, size_t count)
goto again;
else
{
- _dbus_warn ("Failed to write data to pipe!\n");
+ _dbus_warn ("Failed to write data to pipe!");
exit (1); /* give up, we suck */
}
}
@@ -971,6 +986,8 @@ do_write (int fd, const void *buf, size_t count)
goto again;
}
+static void write_err_and_exit (int fd, int msg) _DBUS_GNUC_NORETURN;
+
static void
write_err_and_exit (int fd, int msg)
{
@@ -991,6 +1008,8 @@ write_pid (int fd, pid_t pid)
do_write (fd, &pid, sizeof (pid));
}
+static void write_status_and_exit (int fd, int status) _DBUS_GNUC_NORETURN;
+
static void
write_status_and_exit (int fd, int status)
{
@@ -1002,10 +1021,16 @@ write_status_and_exit (int fd, int status)
exit (0);
}
+static void do_exec (int child_err_report_fd,
+ char * const *argv,
+ char * const *envp,
+ DBusSpawnChildSetupFunc child_setup,
+ void *user_data) _DBUS_GNUC_NORETURN;
+
static void
do_exec (int child_err_report_fd,
- char **argv,
- char **envp,
+ char * const *argv,
+ char * const *envp,
DBusSpawnChildSetupFunc child_setup,
void *user_data)
{
@@ -1033,7 +1058,7 @@ do_exec (int child_err_report_fd,
retval = fcntl (i, F_GETFD);
if (retval != -1 && !(retval & FD_CLOEXEC))
- _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
+ _dbus_warn ("Fd %d did not have the close-on-exec flag set!", i);
}
#endif
@@ -1077,7 +1102,7 @@ check_babysit_events (pid_t grandchild_pid,
else if (ret < 0)
{
/* This isn't supposed to happen. */
- _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
+ _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s",
_dbus_strerror (errno));
exit (1);
}
@@ -1090,7 +1115,7 @@ check_babysit_events (pid_t grandchild_pid,
}
else
{
- _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
+ _dbus_warn ("waitpid() reaped pid %d that we've never heard of",
(int) ret);
exit (1);
}
@@ -1113,13 +1138,22 @@ static int babysit_sigchld_pipe = -1;
static void
babysit_signal_handler (int signo)
{
+ /* Signal handlers that might set errno must save and restore the errno
+ * that the interrupted function might have been relying on. */
+ int saved_errno = errno;
char b = '\0';
+
again:
if (write (babysit_sigchld_pipe, &b, 1) <= 0)
if (errno == EINTR)
goto again;
+
+ errno = saved_errno;
}
+static void babysit (pid_t grandchild_pid,
+ int parent_pipe) _DBUS_GNUC_NORETURN;
+
static void
babysit (pid_t grandchild_pid,
int parent_pipe)
@@ -1138,7 +1172,7 @@ babysit (pid_t grandchild_pid,
*/
if (pipe (sigchld_pipe) < 0)
{
- _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
+ _dbus_warn ("Not enough file descriptors to create pipe in babysitter process");
exit (1);
}
@@ -1164,7 +1198,7 @@ babysit (pid_t grandchild_pid,
if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
{
- _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
+ _dbus_warn ("_dbus_poll() error: %s", strerror (errno));
exit (1);
}
@@ -1188,9 +1222,14 @@ babysit (pid_t grandchild_pid,
}
/**
- * Spawns a new process. The child_setup
- * function is passed the given user_data and is run in the child
- * just before calling exec().
+ * Spawns a new process.
+ *
+ * On Unix platforms, the child_setup function is passed the given
+ * user_data and is run in the child after fork() but before calling exec().
+ * This can be used to change uid, resource limits and so on.
+ * On Windows, this functionality does not fit the multi-processing model
+ * (Windows does the equivalent of fork() and exec() in a single API call),
+ * and the child_setup function and its user_data are ignored.
*
* Also creates a "babysitter" which tracks the status of the
* child process, advising the parent if the child exits.
@@ -1209,8 +1248,9 @@ babysit (pid_t grandchild_pid,
dbus_bool_t
_dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
const char *log_name,
- char **argv,
+ char * const *argv,
char **env,
+ DBusSpawnFlags flags,
DBusSpawnChildSetupFunc child_setup,
void *user_data,
DBusError *error)
@@ -1311,12 +1351,15 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
#ifdef HAVE_SYSTEMD
- /* This may fail, but it's not critical.
- * In particular, if we were compiled with journald support but are now
- * running on a non-systemd system, this is going to fail, so we
- * have to cope gracefully. */
- fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
- fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
+ if (flags & DBUS_SPAWN_REDIRECT_OUTPUT)
+ {
+ /* This may fail, but it's not critical.
+ * In particular, if we were compiled with journald support but are now
+ * running on a non-systemd system, this is going to fail, so we
+ * have to cope gracefully. */
+ fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
+ fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
+ }
#endif
pid = fork ();
@@ -1353,17 +1396,27 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
_dbus_assert_not_reached ("Got to code after write_err_and_exit()");
}
else if (grandchild_pid == 0)
- {
- #ifdef __linux__
- int fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
-
- if (fd >= 0)
- {
- write (fd, "0", sizeof (char));
- _dbus_close (fd, NULL);
- }
- #endif
+ {
+#ifdef __linux__
+ int fd = -1;
+
+#ifdef O_CLOEXEC
+ fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
+#endif
+
+ if (fd < 0)
+ {
+ fd = open ("/proc/self/oom_score_adj", O_WRONLY);
+ _dbus_fd_set_close_on_exec (fd);
+ }
+ if (fd >= 0)
+ {
+ if (write (fd, "0", sizeof (char)) < 0)
+ _dbus_warn ("writing oom_score_adj error: %s", strerror (errno));
+ _dbus_close (fd, NULL);
+ }
+#endif
/* Go back to ignoring SIGPIPE, since it's evil
*/
signal (SIGPIPE, SIG_IGN);
@@ -1455,259 +1508,9 @@ _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
/** @} */
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
-
-static char *
-get_test_exec (const char *exe,
- DBusString *scratch_space)
-{
- const char *dbus_test_exec;
-
- dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
-
- if (dbus_test_exec == NULL)
- dbus_test_exec = DBUS_TEST_EXEC;
-
- if (!_dbus_string_init (scratch_space))
- return NULL;
-
- if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
- dbus_test_exec, exe, DBUS_EXEEXT))
- {
- _dbus_string_free (scratch_space);
- return NULL;
- }
-
- return _dbus_string_get_data (scratch_space);
-}
-
-static void
+void
_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
{
while (LIVE_CHILDREN (sitter))
babysitter_iteration (sitter, TRUE);
}
-
-static dbus_bool_t
-check_spawn_nonexistent (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter = NULL;
- DBusError error = DBUS_ERROR_INIT;
-
- /*** Test launching nonexistent binary */
-
- argv[0] = "/this/does/not/exist/32542sdgafgafdg";
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv,
- NULL, NULL, NULL,
- &error))
- {
- _dbus_babysitter_block_for_child_exit (sitter);
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error launching nonexistent executable\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
- {
- _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_spawn_segfault (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter = NULL;
- DBusError error = DBUS_ERROR_INIT;
- DBusString argv0;
-
- /*** Test launching segfault binary */
-
- argv[0] = get_test_exec ("test-segfault", &argv0);
-
- if (argv[0] == NULL)
- {
- /* OOM was simulated, never mind */
- return TRUE;
- }
-
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
- NULL, NULL, NULL,
- &error))
- {
- _dbus_babysitter_block_for_child_exit (sitter);
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- _dbus_string_free (&argv0);
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error launching segfaulting binary\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
- {
- _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_spawn_exit (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter = NULL;
- DBusError error = DBUS_ERROR_INIT;
- DBusString argv0;
-
- /*** Test launching exit failure binary */
-
- argv[0] = get_test_exec ("test-exit", &argv0);
-
- if (argv[0] == NULL)
- {
- /* OOM was simulated, never mind */
- return TRUE;
- }
-
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
- NULL, NULL, NULL,
- &error))
- {
- _dbus_babysitter_block_for_child_exit (sitter);
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- _dbus_string_free (&argv0);
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
- {
- _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-static dbus_bool_t
-check_spawn_and_kill (void *data)
-{
- char *argv[4] = { NULL, NULL, NULL, NULL };
- DBusBabysitter *sitter = NULL;
- DBusError error = DBUS_ERROR_INIT;
- DBusString argv0;
-
- /*** Test launching sleeping binary then killing it */
-
- argv[0] = get_test_exec ("test-sleep-forever", &argv0);
-
- if (argv[0] == NULL)
- {
- /* OOM was simulated, never mind */
- return TRUE;
- }
-
- if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
- NULL, NULL, NULL,
- &error))
- {
- _dbus_babysitter_kill_child (sitter);
-
- _dbus_babysitter_block_for_child_exit (sitter);
-
- _dbus_babysitter_set_child_exit_error (sitter, &error);
- }
-
- _dbus_string_free (&argv0);
-
- if (sitter)
- _dbus_babysitter_unref (sitter);
-
- if (!dbus_error_is_set (&error))
- {
- _dbus_warn ("Did not get an error after killing spawned binary\n");
- return FALSE;
- }
-
- if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
- dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
- {
- _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
- error.name, error.message);
- dbus_error_free (&error);
- return FALSE;
- }
-
- dbus_error_free (&error);
-
- return TRUE;
-}
-
-dbus_bool_t
-_dbus_spawn_test (const char *test_data_dir)
-{
- if (!_dbus_test_oom_handling ("spawn_nonexistent",
- check_spawn_nonexistent,
- NULL))
- return FALSE;
-
- if (!_dbus_test_oom_handling ("spawn_segfault",
- check_spawn_segfault,
- NULL))
- return FALSE;
-
- if (!_dbus_test_oom_handling ("spawn_exit",
- check_spawn_exit,
- NULL))
- return FALSE;
-
- if (!_dbus_test_oom_handling ("spawn_and_kill",
- check_spawn_and_kill,
- NULL))
- return FALSE;
-
- return TRUE;
-}
-#endif
diff --git a/dbus/dbus-spawn.h b/dbus/dbus-spawn.h
index e6baae97..b34324de 100644
--- a/dbus/dbus-spawn.h
+++ b/dbus/dbus-spawn.h
@@ -38,10 +38,16 @@ typedef struct DBusBabysitter DBusBabysitter;
typedef void (* DBusBabysitterFinishedFunc) (DBusBabysitter *sitter,
void *user_data);
+typedef enum {
+ DBUS_SPAWN_REDIRECT_OUTPUT = (1 << 0),
+ DBUS_SPAWN_NONE = 0
+} DBusSpawnFlags;
+
dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
const char *log_name,
- char **argv,
+ char * const *argv,
char **env,
+ DBusSpawnFlags flags,
DBusSpawnChildSetupFunc child_setup,
void *user_data,
DBusError *error);
@@ -62,6 +68,7 @@ dbus_bool_t _dbus_babysitter_set_watch_functions (DBusBabysitter *si
DBusWatchToggledFunction toggled_function,
void *data,
DBusFreeFunction free_data_function);
+void _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter);
DBUS_END_DECLS
diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c
index 3babc053..85bc5705 100644
--- a/dbus/dbus-string-util.c
+++ b/dbus/dbus-string-util.c
@@ -120,8 +120,8 @@ _dbus_string_find_byte_backward (const DBusString *str,
#include <stdio.h>
static void
-test_hex_roundtrip (const unsigned char *data,
- int len)
+test_hex_roundtrip (const char *data,
+ int len)
{
DBusString orig;
DBusString encoded;
@@ -170,8 +170,8 @@ test_hex_roundtrip (const unsigned char *data,
_dbus_string_free (&decoded);
}
-typedef void (* TestRoundtripFunc) (const unsigned char *data,
- int len);
+typedef void (* TestRoundtripFunc) (const char *data,
+ int len);
static void
test_roundtrips (TestRoundtripFunc func)
{
@@ -200,13 +200,13 @@ test_roundtrips (TestRoundtripFunc func)
i = 0;
while (i < _DBUS_N_ELEMENTS (buf))
{
- buf[i] = i;
+ buf[i] = (i & 0xff);
++i;
}
i = 0;
while (i < _DBUS_N_ELEMENTS (buf))
{
- (* func) (buf, i);
+ (* func) ((const char *) buf, i);
++i;
}
}
@@ -312,12 +312,12 @@ _dbus_string_test (void)
while (i < 10)
{
if (!_dbus_string_append (&str, "a"))
- _dbus_assert_not_reached ("failed to append string to string\n");
+ _dbus_assert_not_reached ("failed to append string to string");
_dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
if (!_dbus_string_append_byte (&str, 'b'))
- _dbus_assert_not_reached ("failed to append byte to string\n");
+ _dbus_assert_not_reached ("failed to append byte to string");
_dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
index 388e762d..a6b74286 100644
--- a/dbus/dbus-string.h
+++ b/dbus/dbus-string.h
@@ -203,7 +203,7 @@ dbus_bool_t _dbus_string_append_printf (DBusString *str,
DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_string_append_printf_valist (DBusString *str,
const char *format,
- va_list args);
+ va_list args) _DBUS_GNUC_PRINTF (2, 0);
dbus_bool_t _dbus_string_insert_2_aligned (DBusString *str,
int insert_at,
const unsigned char octets[2]);
@@ -365,6 +365,29 @@ dbus_bool_t _dbus_string_validate_nul (const DBusString *str,
int len);
void _dbus_string_zero (DBusString *str);
+static inline unsigned char *
+_dbus_string_get_udata (DBusString *str)
+{
+ return (unsigned char *) _dbus_string_get_data (str);
+}
+
+static inline unsigned char *
+_dbus_string_get_udata_len (DBusString *str, int start, int len)
+{
+ return (unsigned char *) _dbus_string_get_data_len (str, start, len);
+}
+
+static inline const unsigned char *
+_dbus_string_get_const_udata (const DBusString *str)
+{
+ return (const unsigned char *) _dbus_string_get_const_data (str);
+}
+
+static inline const unsigned char *
+_dbus_string_get_const_udata_len (const DBusString *str, int start, int len)
+{
+ return (const unsigned char *) _dbus_string_get_const_data_len (str, start, len);
+}
/**
* We allocate 1 byte for nul termination, plus 7 bytes for possible
diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c
index bc0b2c35..e1c14f99 100644
--- a/dbus/dbus-sysdeps-pthread.c
+++ b/dbus/dbus-sysdeps-pthread.c
@@ -73,7 +73,7 @@ struct DBusCondVar {
#define PTHREAD_CHECK(func_name, result_or_call) do { \
int tmp = (result_or_call); \
if (tmp != 0) { \
- _dbus_warn_check_failed ("pthread function %s failed with %d %s in %s\n", \
+ _dbus_warn_check_failed ("pthread function %s failed with %d %s in %s", \
func_name, tmp, strerror(tmp), _DBUS_FUNCTION_NAME); \
} \
} while (0)
diff --git a/dbus/dbus-sysdeps-thread-win.c b/dbus/dbus-sysdeps-thread-win.c
index d006cb8b..b5c098cf 100644
--- a/dbus/dbus-sysdeps-thread-win.c
+++ b/dbus/dbus-sysdeps-thread-win.c
@@ -28,6 +28,8 @@
#include "dbus-threads.h"
#include "dbus-list.h"
+#include <stdio.h>
+
#include <windows.h>
static dbus_bool_t global_init_done = FALSE;
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 50ca60a2..e8cd5b33 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -62,6 +62,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
#ifdef HAVE_WRITEV
#include <sys/uio.h>
#endif
@@ -134,6 +137,81 @@
#endif /* Solaris */
+/**
+ * Ensure that the standard file descriptors stdin, stdout and stderr
+ * are open, by opening /dev/null if necessary.
+ *
+ * This function does not use DBusError, to avoid calling malloc(), so
+ * that it can be used in contexts where an async-signal-safe function
+ * is required (for example after fork()). Instead, on failure it sets
+ * errno and returns something like "Failed to open /dev/null" in
+ * *error_str_p. Callers are expected to combine *error_str_p
+ * with _dbus_strerror (errno) to get a full error report.
+ *
+ * This function can only be called while single-threaded: either during
+ * startup of an executable, or after fork().
+ */
+dbus_bool_t
+_dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
+ const char **error_str_p)
+{
+ static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
+ DBUS_FORCE_STDOUT_NULL,
+ DBUS_FORCE_STDERR_NULL };
+ /* Should always get replaced with the real error before use */
+ const char *error_str = "Failed mysteriously";
+ int devnull = -1;
+ int saved_errno;
+ /* This function relies on the standard fds having their POSIX values. */
+ _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
+ _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
+ _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
+ int i;
+
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
+ {
+ /* Because we rely on being single-threaded, and we want the
+ * standard fds to not be close-on-exec, we don't set it
+ * close-on-exec. */
+ if (devnull < i)
+ devnull = open ("/dev/null", O_RDWR);
+
+ if (devnull < 0)
+ {
+ error_str = "Failed to open /dev/null";
+ goto out;
+ }
+
+ /* We already opened all fds < i, so the only way this assertion
+ * could fail is if another thread closed one, and we document
+ * this function as not safe for multi-threading. */
+ _dbus_assert (devnull >= i);
+
+ if (devnull != i && (flags & relevant_flag[i]) != 0)
+ {
+ if (dup2 (devnull, i) < 0)
+ {
+ error_str = "Failed to dup2 /dev/null onto a standard fd";
+ goto out;
+ }
+ }
+ }
+
+ error_str = NULL;
+
+out:
+ saved_errno = errno;
+
+ if (devnull > STDERR_FILENO)
+ close (devnull);
+
+ if (error_str_p != NULL)
+ *error_str_p = error_str;
+
+ errno = saved_errno;
+ return (error_str == NULL);
+}
+
static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
DBusError *error);
@@ -281,7 +359,7 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd,
DBusString *buffer,
int count,
int *fds,
- int *n_fds) {
+ unsigned int *n_fds) {
#ifndef HAVE_UNIX_FD_PASSING
int r;
@@ -298,7 +376,7 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd,
struct iovec iov;
_dbus_assert (count >= 0);
- _dbus_assert (*n_fds >= 0);
+ _dbus_assert (*n_fds <= DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
start = _dbus_string_get_length (buffer);
@@ -378,10 +456,9 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd,
size_t payload_len_fds = payload_len_bytes / sizeof (int);
size_t fds_to_use;
- /* Every non-negative int fits in a size_t without truncation,
- * and we already know that *n_fds is non-negative, so
+ /* Every unsigned int fits in a size_t without truncation, so
* casting (size_t) *n_fds is OK */
- _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
+ _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
{
@@ -407,9 +484,10 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd,
memcpy (fds, payload, fds_to_use * sizeof (int));
found = TRUE;
- /* This cannot overflow because we have chosen fds_to_use
+ /* This narrowing cast from size_t to unsigned int cannot
+ * overflow because we have chosen fds_to_use
* to be <= *n_fds */
- *n_fds = (int) fds_to_use;
+ *n_fds = (unsigned int) fds_to_use;
/* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
worked, hence we need to go through this list and set
@@ -835,6 +913,7 @@ _dbus_connect_unix_socket (const char *path,
int fd;
size_t path_len;
struct sockaddr_un addr;
+ _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -855,7 +934,7 @@ _dbus_connect_unix_socket (const char *path,
if (abstract)
{
-#ifdef HAVE_ABSTRACT_SOCKETS
+#ifdef __linux__
addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
path_len++; /* Account for the extra nul byte added to the start of sun_path */
@@ -867,14 +946,14 @@ _dbus_connect_unix_socket (const char *path,
return -1;
}
- strncpy (&addr.sun_path[1], path, path_len);
+ strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
/* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
-#else /* HAVE_ABSTRACT_SOCKETS */
+#else /* !__linux__ */
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
"Operating system does not support abstract socket namespace\n");
_dbus_close (fd, NULL);
return -1;
-#endif /* ! HAVE_ABSTRACT_SOCKETS */
+#endif /* !__linux__ */
}
else
{
@@ -886,7 +965,7 @@ _dbus_connect_unix_socket (const char *path,
return -1;
}
- strncpy (addr.sun_path, path, path_len);
+ strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
}
if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
@@ -991,7 +1070,7 @@ _dbus_connect_exec (const char *path,
_dbus_close_all ();
- execvp (path, argv);
+ execvp (path, (char * const *) argv);
fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
@@ -1037,6 +1116,7 @@ _dbus_listen_unix_socket (const char *path,
int listen_fd;
struct sockaddr_un addr;
size_t path_len;
+ _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1056,7 +1136,7 @@ _dbus_listen_unix_socket (const char *path,
if (abstract)
{
-#ifdef HAVE_ABSTRACT_SOCKETS
+#ifdef __linux__
/* remember that abstract names aren't nul-terminated so we rely
* on sun_path being filled in with zeroes above.
*/
@@ -1071,14 +1151,14 @@ _dbus_listen_unix_socket (const char *path,
return -1;
}
- strncpy (&addr.sun_path[1], path, path_len);
+ strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
/* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
-#else /* HAVE_ABSTRACT_SOCKETS */
+#else /* !__linux__ */
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
"Operating system does not support abstract socket namespace\n");
_dbus_close (listen_fd, NULL);
return -1;
-#endif /* ! HAVE_ABSTRACT_SOCKETS */
+#endif /* !__linux__ */
}
else
{
@@ -1108,7 +1188,7 @@ _dbus_listen_unix_socket (const char *path,
return -1;
}
- strncpy (addr.sun_path, path, path_len);
+ strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
}
if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
@@ -1120,7 +1200,7 @@ _dbus_listen_unix_socket (const char *path,
return -1;
}
- if (listen (listen_fd, 30 /* backlog */) < 0)
+ if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to listen on socket \"%s\": %s",
@@ -1140,8 +1220,7 @@ _dbus_listen_unix_socket (const char *path,
* and continue, maybe it will be good enough.
*/
if (!abstract && chmod (path, 0777) < 0)
- _dbus_warn ("Could not set mode 0777 on socket %s\n",
- path);
+ _dbus_warn ("Could not set mode 0777 on socket %s", path);
return listen_fd;
}
@@ -1243,6 +1322,56 @@ _dbus_listen_systemd_sockets (DBusSocket **fds,
#endif
}
+/* Convert an error code from getaddrinfo() or getnameinfo() into
+ * a D-Bus error name. */
+static const char *
+_dbus_error_from_gai (int gai_res,
+ int saved_errno)
+{
+ switch (gai_res)
+ {
+#ifdef EAI_FAMILY
+ case EAI_FAMILY:
+ /* ai_family not supported (at all) */
+ return DBUS_ERROR_NOT_SUPPORTED;
+#endif
+
+#ifdef EAI_SOCKTYPE
+ case EAI_SOCKTYPE:
+ /* ai_socktype not supported (at all) */
+ return DBUS_ERROR_NOT_SUPPORTED;
+#endif
+
+#ifdef EAI_MEMORY
+ case EAI_MEMORY:
+ /* Out of memory */
+ return DBUS_ERROR_NO_MEMORY;
+#endif
+
+#ifdef EAI_SYSTEM
+ case EAI_SYSTEM:
+ /* Unspecified system error, details in errno */
+ return _dbus_error_from_errno (saved_errno);
+#endif
+
+ case 0:
+ /* It succeeded, but we didn't get any addresses? */
+ return DBUS_ERROR_FAILED;
+
+ /* EAI_AGAIN: Transient failure */
+ /* EAI_BADFLAGS: invalid ai_flags (programming error) */
+ /* EAI_FAIL: Non-recoverable failure */
+ /* EAI_NODATA: host exists but has no addresses */
+ /* EAI_NONAME: host does not exist */
+ /* EAI_OVERFLOW: argument buffer overflow */
+ /* EAI_SERVICE: service not available for specified socket
+ * type (we should never see this because we use numeric
+ * ports) */
+ default:
+ return DBUS_ERROR_FAILED;
+ }
+}
+
/**
* Creates a socket and connects to a socket at the given host
* and port. The connection fd is returned, and is set up as
@@ -1302,7 +1431,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
{
dbus_set_error (error,
- _dbus_error_from_errno (errno),
+ _dbus_error_from_gai (res, errno),
"Failed to lookup host/port: \"%s:%s\": %s (%d)",
host, port, gai_strerror(res), res);
return _dbus_socket_get_invalid ();
@@ -1424,7 +1553,7 @@ _dbus_listen_tcp_socket (const char *host,
if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
{
dbus_set_error (error,
- _dbus_error_from_errno (errno),
+ _dbus_error_from_gai (res, errno),
"Failed to lookup host/port: \"%s:%s\": %s (%d)",
host ? host : "*", port, gai_strerror(res), res);
goto failed;
@@ -1499,11 +1628,9 @@ _dbus_listen_tcp_socket (const char *host,
newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
if (!newlisten_fd)
{
- saved_errno = errno;
_dbus_close (fd, NULL);
- dbus_set_error (error, _dbus_error_from_errno (saved_errno),
- "Failed to allocate file handle array: %s",
- _dbus_strerror (saved_errno));
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "Failed to allocate file handle array");
goto failed;
}
listen_fd = newlisten_fd;
@@ -1526,16 +1653,26 @@ _dbus_listen_tcp_socket (const char *host,
addrlen = sizeof(addr);
result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
- if (result == -1 ||
- (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
+ if (result == -1)
+ {
+ saved_errno = errno;
+ dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+ "Failed to retrieve socket name for \"%s:%s\": %s",
+ host ? host : "*", port, _dbus_strerror (saved_errno));
+ goto failed;
+ }
+
+ if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
portbuf, sizeof(portbuf),
NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
{
- dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to resolve port \"%s:%s\": %s (%s)",
+ saved_errno = errno;
+ dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
+ "Failed to resolve port \"%s:%s\": %s (%d)",
host ? host : "*", port, gai_strerror(res), res);
goto failed;
}
+
if (!_dbus_string_append(retport, portbuf))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
@@ -1905,7 +2042,7 @@ _dbus_read_credentials_socket (DBusSocket client_fd,
#else
struct ucred cr;
#endif
- int cr_len = sizeof (cr);
+ socklen_t cr_len = sizeof (cr);
if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
{
@@ -1977,13 +2114,13 @@ _dbus_read_credentials_socket (DBusSocket client_fd,
ucred_t * ucred = NULL;
if (getpeerucred (client_fd.fd, &ucred) == 0)
{
+#ifdef HAVE_ADT
+ adt_session_data_t *adth = NULL;
+#endif
pid_read = ucred_getpid (ucred);
uid_read = ucred_geteuid (ucred);
#ifdef HAVE_ADT
/* generate audit session data based on socket ucred */
- adt_session_data_t *adth = NULL;
- adt_export_data_t *data = NULL;
- size_t size = 0;
if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
{
_dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
@@ -1996,7 +2133,8 @@ _dbus_read_credentials_socket (DBusSocket client_fd,
}
else
{
- size = adt_export_session_data (adth, &data);
+ adt_export_data_t *data = NULL;
+ size_t size = adt_export_session_data (adth, &data);
if (size <= 0)
{
_dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
@@ -2878,7 +3016,7 @@ _dbus_get_real_time (long *tv_sec,
* @returns #TRUE on success
*/
dbus_bool_t
-_dbus_create_directory (const DBusString *filename,
+_dbus_ensure_directory (const DBusString *filename,
DBusError *error)
{
const char *filename_c;
@@ -2902,6 +3040,35 @@ _dbus_create_directory (const DBusString *filename,
}
/**
+ * Creates a directory. Unlike _dbus_ensure_directory(), this only succeeds
+ * if the directory is genuinely newly-created.
+ *
+ * @param filename directory filename
+ * @param error initialized error object
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_create_directory (const DBusString *filename,
+ DBusError *error)
+{
+ const char *filename_c;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ filename_c = _dbus_string_get_const_data (filename);
+
+ if (mkdir (filename_c, 0700) < 0)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to create directory %s: %s\n",
+ filename_c, _dbus_strerror (errno));
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+/**
* Appends the given filename to the given directory.
*
* @todo it might be cute to collapse multiple '/' such as "foo//"
@@ -3322,7 +3489,7 @@ _dbus_socketpair (DBusSocket *fd1,
return TRUE;
#else
- _dbus_warn ("_dbus_socketpair() not implemented on this OS\n");
+ _dbus_warn ("_dbus_socketpair() not implemented on this OS");
dbus_set_error (error, DBUS_ERROR_FAILED,
"_dbus_socketpair() not implemented on this OS");
return FALSE;
@@ -3468,7 +3635,7 @@ _dbus_get_tmpdir(void)
static dbus_bool_t
_read_subprocess_line_argv (const char *progpath,
dbus_bool_t path_fallback,
- char * const *argv,
+ const char * const *argv,
DBusString *result,
DBusError *error)
{
@@ -3530,21 +3697,35 @@ _read_subprocess_line_argv (const char *progpath,
if (pid == 0)
{
/* child process */
- int fd;
+ const char *error_str;
- fd = open ("/dev/null", O_RDWR);
- if (fd == -1)
- /* huh?! can't open /dev/null? */
- _exit (1);
+ if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
+ {
+ int saved_errno = errno;
+
+ /* Try to write details into the pipe, but don't bother
+ * trying too hard (no retry loop). */
+
+ if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
+ write (errors_pipe[WRITE_END], ": ", 2) < 0)
+ {
+ /* ignore, not much we can do */
+ }
- _dbus_verbose ("/dev/null fd %d opened\n", fd);
+ error_str = _dbus_strerror (saved_errno);
+
+ if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
+ {
+ /* ignore, not much we can do */
+ }
+
+ _exit (1);
+ }
/* set-up stdXXX */
close (result_pipe[READ_END]);
close (errors_pipe[READ_END]);
- if (dup2 (fd, 0) == -1) /* setup stdin */
- _exit (1);
if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
_exit (1);
if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
@@ -3557,7 +3738,7 @@ _read_subprocess_line_argv (const char *progpath,
/* If it looks fully-qualified, try execv first */
if (progpath[0] == '/')
{
- execv (progpath, argv);
+ execv (progpath, (char * const *) argv);
/* Ok, that failed. Now if path_fallback is given, let's
* try unqualified. This is mostly a hack to work
* around systems which ship dbus-launch in /usr/bin
@@ -3566,10 +3747,10 @@ _read_subprocess_line_argv (const char *progpath,
*/
if (path_fallback)
/* We must have a slash, because we checked above */
- execvp (strrchr (progpath, '/')+1, argv);
+ execvp (strrchr (progpath, '/')+1, (char * const *) argv);
}
else
- execvp (progpath, argv);
+ execvp (progpath, (char * const *) argv);
/* still nothing, we failed */
_exit (1);
@@ -3667,12 +3848,17 @@ _dbus_get_autolaunch_address (const char *scope,
DBusError *error)
{
#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
+ static const char arg_dbus_launch[] = "dbus-launch";
+ static const char arg_autolaunch[] = "--autolaunch";
+ static const char arg_binary_syntax[] = "--binary-syntax";
+ static const char arg_close_stderr[] = "--close-stderr";
+
/* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
* but that's done elsewhere, and if it worked, this function wouldn't
* be called.) */
const char *display;
- char *progpath;
- char *argv[6];
+ const char *progpath;
+ const char *argv[6];
int i;
DBusString uuid;
dbus_bool_t retval;
@@ -3716,9 +3902,9 @@ _dbus_get_autolaunch_address (const char *scope,
}
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
- if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL)
- progpath = TEST_BUS_LAUNCH_BINARY;
- else
+ progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
+
+ if (progpath == NULL)
#endif
progpath = DBUS_BINDIR "/dbus-launch";
/*
@@ -3727,15 +3913,15 @@ _dbus_get_autolaunch_address (const char *scope,
* see fd.o#69716
*/
i = 0;
- argv[i] = "dbus-launch";
+ argv[i] = arg_dbus_launch;
++i;
- argv[i] = "--autolaunch";
+ argv[i] = arg_autolaunch;
++i;
argv[i] = _dbus_string_get_data (&uuid);
++i;
- argv[i] = "--binary-syntax";
+ argv[i] = arg_binary_syntax;
++i;
- argv[i] = "--close-stderr";
+ argv[i] = arg_close_stderr;
++i;
argv[i] = NULL;
++i;
@@ -3780,36 +3966,51 @@ _dbus_read_local_machine_uuid (DBusGUID *machine_id,
dbus_bool_t create_if_not_found,
DBusError *error)
{
+ DBusError our_error = DBUS_ERROR_INIT;
+ DBusError etc_error = DBUS_ERROR_INIT;
DBusString filename;
dbus_bool_t b;
_dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
- b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
+ b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
if (b)
return TRUE;
- dbus_error_free (error);
-
/* Fallback to the system machine ID */
_dbus_string_init_const (&filename, "/etc/machine-id");
- b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
+ b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
if (b)
{
- /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
- * complain if that isn't possible for whatever reason */
- _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
- _dbus_write_uuid_file (&filename, machine_id, NULL);
+ if (create_if_not_found)
+ {
+ /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
+ * complain if that isn't possible for whatever reason */
+ _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
+ _dbus_write_uuid_file (&filename, machine_id, NULL);
+ }
+ dbus_error_free (&our_error);
return TRUE;
}
if (!create_if_not_found)
- return FALSE;
+ {
+ dbus_set_error (error, etc_error.name,
+ "D-Bus library appears to be incorrectly set up: "
+ "see the manual page for dbus-uuidgen to correct "
+ "this issue. (%s; %s)",
+ our_error.message, etc_error.message);
+ dbus_error_free (&our_error);
+ dbus_error_free (&etc_error);
+ return FALSE;
+ }
+
+ dbus_error_free (&our_error);
+ dbus_error_free (&etc_error);
/* if none found, try to make a new one */
- dbus_error_free (error);
_dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
if (!_dbus_generate_uuid (machine_id, error))
@@ -4113,7 +4314,8 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory,
static dbus_bool_t already_warned = FALSE;
if (!already_warned)
{
- _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
+ _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
+ _dbus_string_get_const_data (&homedir));
already_warned = TRUE;
}
}
@@ -4162,7 +4364,15 @@ _dbus_daemon_unpublish_session_bus_address (void)
dbus_bool_t
_dbus_get_is_errno_eagain_or_ewouldblock (int e)
{
+ /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
+ * EWOULDBLOCK are numerically equal, which is permitted as described by
+ * errno(3).
+ */
+#if EAGAIN == EWOULDBLOCK
+ return e == EAGAIN;
+#else
return e == EAGAIN || e == EWOULDBLOCK;
+#endif
}
/**
@@ -4245,13 +4455,13 @@ _dbus_close_all (void)
{
for (;;)
{
- struct dirent buf, *de;
- int k, fd;
+ struct dirent *de;
+ int fd;
long l;
char *e = NULL;
- k = readdir_r (d, &buf, &de);
- if (k != 0 || !de)
+ de = readdir (d);
+ if (!de)
break;
if (de->d_name[0] == '.')
@@ -4365,7 +4575,7 @@ _dbus_append_address_from_socket (DBusSocket fd,
struct sockaddr_in6 ipv6;
} socket;
char hostip[INET6_ADDRSTRLEN];
- int size = sizeof (socket);
+ socklen_t size = sizeof (socket);
DBusString path_str;
if (getsockname (fd.fd, &socket.sa, &size))
@@ -4431,4 +4641,94 @@ _dbus_restore_socket_errno (int saved_errno)
errno = saved_errno;
}
+static const char *syslog_tag = "dbus";
+#ifdef HAVE_SYSLOG_H
+static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
+#endif
+
+/**
+ * Initialize the system log.
+ *
+ * The "tag" is not copied, and must remain valid for the entire lifetime of
+ * the process or until _dbus_init_system_log() is called again. In practice
+ * it will normally be a constant.
+ *
+ * On platforms that do not support a system log, the
+ * #DBUS_LOG_FLAGS_SYSTEM_LOG flag is treated as equivalent to
+ * #DBUS_LOG_FLAGS_STDERR.
+ *
+ * @param tag the name of the executable (syslog tag)
+ * @param mode whether to log to stderr, the system log or both
+ */
+void
+_dbus_init_system_log (const char *tag,
+ DBusLogFlags flags)
+{
+ /* We never want to turn off logging completely */
+ _dbus_assert (
+ (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
+
+ syslog_tag = tag;
+
+#ifdef HAVE_SYSLOG_H
+ log_flags = flags;
+
+ if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
+ openlog (tag, LOG_PID, LOG_DAEMON);
+#endif
+}
+
+/**
+ * Log a message to the system log file (e.g. syslog on Unix) and/or stderr.
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ */
+void
+_dbus_logv (DBusSystemLogSeverity severity,
+ const char *msg,
+ va_list args)
+{
+ va_list tmp;
+#ifdef HAVE_SYSLOG_H
+ if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
+ {
+ int flags;
+ switch (severity)
+ {
+ case DBUS_SYSTEM_LOG_INFO:
+ flags = LOG_DAEMON | LOG_INFO;
+ break;
+ case DBUS_SYSTEM_LOG_WARNING:
+ flags = LOG_DAEMON | LOG_WARNING;
+ break;
+ case DBUS_SYSTEM_LOG_SECURITY:
+ flags = LOG_AUTH | LOG_NOTICE;
+ break;
+ case DBUS_SYSTEM_LOG_ERROR:
+ flags = LOG_DAEMON|LOG_CRIT;
+ break;
+ default:
+ _dbus_assert_not_reached ("invalid log severity");
+ }
+
+ DBUS_VA_COPY (tmp, args);
+ vsyslog (flags, msg, tmp);
+ va_end (tmp);
+ }
+
+ /* If we don't have syslog.h, we always behave as though stderr was in
+ * the flags */
+ if (log_flags & DBUS_LOG_FLAGS_STDERR)
+#endif
+ {
+ DBUS_VA_COPY (tmp, args);
+ fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
+ vfprintf (stderr, msg, tmp);
+ fputc ('\n', stderr);
+ va_end (tmp);
+ }
+}
+
/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index 72f3ecf5..8d3df2d6 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -154,6 +154,23 @@ dbus_bool_t _dbus_append_address_from_socket (DBusSocket fd,
DBUS_PRIVATE_EXPORT
void _dbus_fd_set_close_on_exec (int fd);
+typedef enum
+{
+ DBUS_FORCE_STDIN_NULL = (1 << 0),
+ DBUS_FORCE_STDOUT_NULL = (1 << 1),
+ DBUS_FORCE_STDERR_NULL = (1 << 2)
+} DBusEnsureStandardFdsFlags;
+
+DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
+ const char **error_str_p);
+
+/** A UNIX signal handler */
+typedef void (* DBusSignalHandler) (int sig);
+
+void _dbus_set_signal_handler (int sig,
+ DBusSignalHandler handler);
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index 9b724cc9..26fcb5bc 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -26,6 +26,7 @@
#include "dbus-sysdeps.h"
#include "dbus-sysdeps-unix.h"
#include "dbus-internals.h"
+#include "dbus-list.h"
#include "dbus-pipe.h"
#include "dbus-protocol.h"
#include "dbus-string.h"
@@ -50,10 +51,6 @@
#include <dirent.h>
#include <sys/un.h>
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-
#ifdef HAVE_SYS_SYSLIMITS_H
#include <sys/syslimits.h>
#endif
@@ -89,7 +86,7 @@ _dbus_become_daemon (const DBusString *pidfile,
{
const char *s;
pid_t child_pid;
- int dev_null_fd;
+ DBusEnsureStandardFdsFlags flags;
_dbus_verbose ("Becoming a daemon...\n");
@@ -114,23 +111,18 @@ _dbus_become_daemon (const DBusString *pidfile,
case 0:
_dbus_verbose ("in child, closing std file descriptors\n");
- /* silently ignore failures here, if someone
- * doesn't have /dev/null we may as well try
- * to continue anyhow
- */
-
- dev_null_fd = open ("/dev/null", O_RDWR);
- if (dev_null_fd >= 0)
+ flags = DBUS_FORCE_STDIN_NULL | DBUS_FORCE_STDOUT_NULL;
+ s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
+
+ if (s == NULL || *s == '\0')
+ flags |= DBUS_FORCE_STDERR_NULL;
+ else
+ _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
+
+ if (!_dbus_ensure_standard_fds (flags, &s))
{
- dup2 (dev_null_fd, 0);
- dup2 (dev_null_fd, 1);
-
- s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
- if (s == NULL || *s == '\0')
- dup2 (dev_null_fd, 2);
- else
- _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
- close (dev_null_fd);
+ _dbus_warn ("%s: %s", s, _dbus_strerror (errno));
+ _exit (1);
}
if (!keep_umask)
@@ -354,7 +346,7 @@ _dbus_change_to_daemon_user (const char *user,
* is going to work then setgroups() should also work.
*/
if (setgroups (0, NULL) < 0)
- _dbus_warn ("Failed to drop supplementary groups: %s\n",
+ _dbus_warn ("Failed to drop supplementary groups: %s",
_dbus_strerror (errno));
/* Set GID first, or the setuid may remove our permission
@@ -414,23 +406,15 @@ _dbus_rlimit_save_fd_limit (DBusError *error)
return self;
}
+/* Enough fds that we shouldn't run out, even if several uids work
+ * together to carry out a denial-of-service attack. This happens to be
+ * the same number that systemd < 234 would normally use. */
+#define ENOUGH_FDS 65536
+
dbus_bool_t
-_dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
- DBusError *error)
+_dbus_rlimit_raise_fd_limit (DBusError *error)
{
- struct rlimit lim;
-
- /* No point to doing this practically speaking
- * if we're not uid 0. We expect the system
- * bus to use this before we change UID, and
- * the session bus takes the Linux default,
- * currently 1024 for cur and 4096 for max.
- */
- if (getuid () != 0)
- {
- /* not an error, we're probably the session bus */
- return TRUE;
- }
+ struct rlimit old, lim;
if (getrlimit (RLIMIT_NOFILE, &lim) < 0)
{
@@ -439,22 +423,43 @@ _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
return FALSE;
}
- if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= desired)
+ old = lim;
+
+ if (getuid () == 0)
{
- /* not an error, everything is fine */
- return TRUE;
+ /* We are privileged, so raise the soft limit to at least
+ * ENOUGH_FDS, and the hard limit to at least the desired soft
+ * limit. This assumes we can exercise CAP_SYS_RESOURCE on Linux,
+ * or other OSs' equivalents. */
+ if (lim.rlim_cur != RLIM_INFINITY &&
+ lim.rlim_cur < ENOUGH_FDS)
+ lim.rlim_cur = ENOUGH_FDS;
+
+ if (lim.rlim_max != RLIM_INFINITY &&
+ lim.rlim_max < lim.rlim_cur)
+ lim.rlim_max = lim.rlim_cur;
}
- /* Ignore "maximum limit", assume we have the "superuser"
- * privileges. On Linux this is CAP_SYS_RESOURCE.
- */
- lim.rlim_cur = lim.rlim_max = desired;
+ /* Raise the soft limit to match the hard limit, which we can do even
+ * if we are unprivileged. In particular, systemd >= 240 will normally
+ * set rlim_cur to 1024 and rlim_max to 512*1024, recent Debian
+ * versions end up setting rlim_cur to 1024 and rlim_max to 1024*1024,
+ * and older and non-systemd Linux systems would typically set rlim_cur
+ * to 1024 and rlim_max to 4096. */
+ if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
+ lim.rlim_cur = lim.rlim_max;
+
+ /* Early-return if there is nothing to do. */
+ if (lim.rlim_max == old.rlim_max &&
+ lim.rlim_cur == old.rlim_cur)
+ return TRUE;
if (setrlimit (RLIMIT_NOFILE, &lim) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
- "Failed to set fd limit to %u: %s",
- desired, _dbus_strerror (errno));
+ "Failed to set fd limit to %lu: %s",
+ (unsigned long) lim.rlim_cur,
+ _dbus_strerror (errno));
return FALSE;
}
@@ -493,8 +498,7 @@ _dbus_rlimit_save_fd_limit (DBusError *error)
}
dbus_bool_t
-_dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
- DBusError *error)
+_dbus_rlimit_raise_fd_limit (DBusError *error)
{
fd_limit_not_supported (error);
return FALSE;
@@ -516,95 +520,6 @@ _dbus_rlimit_free (DBusRLimit *lim)
dbus_free (lim);
}
-void
-_dbus_init_system_log (dbus_bool_t is_daemon)
-{
-#ifdef HAVE_SYSLOG_H
- int logopts = LOG_PID;
-
-#if HAVE_DECL_LOG_PERROR
-#ifdef HAVE_SYSTEMD
- if (!is_daemon || sd_booted () <= 0)
-#endif
- logopts |= LOG_PERROR;
-#endif
-
- openlog ("dbus", logopts, LOG_DAEMON);
-#endif
-}
-
-/**
- * Log a message to the system log file (e.g. syslog on Unix).
- *
- * @param severity a severity value
- * @param msg a printf-style format string
- */
-void
-_dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
-{
- va_list args;
-
- va_start (args, msg);
-
- _dbus_system_logv (severity, msg, args);
-
- va_end (args);
-}
-
-/**
- * Log a message to the system log file (e.g. syslog on Unix).
- *
- * @param severity a severity value
- * @param msg a printf-style format string
- * @param args arguments for the format string
- *
- * If the FATAL severity is given, this function will terminate the program
- * with an error code.
- */
-void
-_dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
-{
- va_list tmp;
-#ifdef HAVE_SYSLOG_H
- int flags;
- switch (severity)
- {
- case DBUS_SYSTEM_LOG_INFO:
- flags = LOG_DAEMON | LOG_NOTICE;
- break;
- case DBUS_SYSTEM_LOG_WARNING:
- flags = LOG_DAEMON | LOG_WARNING;
- break;
- case DBUS_SYSTEM_LOG_SECURITY:
- flags = LOG_AUTH | LOG_NOTICE;
- break;
- case DBUS_SYSTEM_LOG_FATAL:
- flags = LOG_DAEMON|LOG_CRIT;
- break;
- default:
- return;
- }
-
- DBUS_VA_COPY (tmp, args);
- vsyslog (flags, msg, tmp);
- va_end (tmp);
-#endif
-
-#if !defined(HAVE_SYSLOG_H) || !HAVE_DECL_LOG_PERROR
- {
- /* vsyslog() won't write to stderr, so we'd better do it */
- DBUS_VA_COPY (tmp, args);
- fprintf (stderr, "dbus[" DBUS_PID_FORMAT "]: ", _dbus_getpid ());
- vfprintf (stderr, msg, tmp);
- fputc ('\n', stderr);
- va_end (tmp);
- }
-#endif
-
- if (severity == DBUS_SYSTEM_LOG_FATAL)
- exit (1);
-}
-
/** Installs a UNIX signal handler
*
* @param sig the signal to handle
@@ -645,7 +560,7 @@ dbus_bool_t
_dbus_user_at_console (const char *username,
DBusError *error)
{
-
+#ifdef DBUS_CONSOLE_AUTH_DIR
DBusString u, f;
dbus_bool_t result;
@@ -676,6 +591,9 @@ _dbus_user_at_console (const char *username,
_dbus_string_free (&f);
return result;
+#else
+ return FALSE;
+#endif
}
@@ -1177,7 +1095,7 @@ string_squash_nonprintable (DBusString *str)
unsigned char *buf;
int i, len;
- buf = _dbus_string_get_data (str);
+ buf = _dbus_string_get_udata (str);
len = _dbus_string_get_length (str);
for (i = 0; i < len; i++)
@@ -1272,23 +1190,177 @@ fail:
return FALSE;
}
-/*
- * replaces the term DBUS_PREFIX in configure_time_path by the
- * current dbus installation directory. On unix this function is a noop
+/**
+ * Replace the DBUS_PREFIX in the given path, in-place, by the
+ * current D-Bus installation directory. On Unix this function
+ * does nothing, successfully.
*
- * @param configure_time_path
- * @return real path
+ * @param path path to edit
+ * @return #FALSE on OOM
*/
-const char *
-_dbus_replace_install_prefix (const char *configure_time_path)
+dbus_bool_t
+_dbus_replace_install_prefix (DBusString *path)
+{
+ return TRUE;
+}
+
+static dbus_bool_t
+ensure_owned_directory (const char *label,
+ const DBusString *string,
+ dbus_bool_t create,
+ DBusError *error)
{
- return configure_time_path;
+ const char *dir = _dbus_string_get_const_data (string);
+ struct stat buf;
+
+ if (create && !_dbus_ensure_directory (string, error))
+ return FALSE;
+
+ /*
+ * The stat()-based checks in this function are to protect against
+ * mistakes, not malice. We are working in a directory that is meant
+ * to be trusted; but if a user has used `su` or similar to escalate
+ * their privileges without correctly clearing the environment, the
+ * XDG_RUNTIME_DIR in the environment might still be the user's
+ * and not root's. We don't want to write root-owned files into that
+ * directory, so just warn and don't provide support for transient
+ * services in that case.
+ *
+ * In particular, we use stat() and not lstat() so that if we later
+ * decide to use a different directory name for transient services,
+ * we can drop in a compatibility symlink without breaking older
+ * libdbus.
+ */
+
+ if (stat (dir, &buf) != 0)
+ {
+ int saved_errno = errno;
+
+ dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+ "%s \"%s\" not available: %s", label, dir,
+ _dbus_strerror (saved_errno));
+ return FALSE;
+ }
+
+ if (!S_ISDIR (buf.st_mode))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED, "%s \"%s\" is not a directory",
+ label, dir);
+ return FALSE;
+ }
+
+ if (buf.st_uid != geteuid ())
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "%s \"%s\" is owned by uid %ld, not our uid %ld",
+ label, dir, (long) buf.st_uid, (long) geteuid ());
+ return FALSE;
+ }
+
+ /* This is just because we have the stat() results already, so we might
+ * as well check opportunistically. */
+ if ((S_IWOTH | S_IWGRP) & buf.st_mode)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "%s \"%s\" can be written by others (mode 0%o)",
+ label, dir, buf.st_mode);
+ return FALSE;
+ }
+
+ return TRUE;
}
#define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
#define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
/**
+ * Returns the standard directories for a session bus to look for
+ * transient service activation files.
+ *
+ * @param dirs the directory list we are returning
+ * @returns #FALSE on error
+ */
+dbus_bool_t
+_dbus_set_up_transient_session_servicedirs (DBusList **dirs,
+ DBusError *error)
+{
+ const char *xdg_runtime_dir;
+ DBusString services;
+ DBusString dbus1;
+ DBusString xrd;
+ dbus_bool_t ret = FALSE;
+ char *data = NULL;
+
+ if (!_dbus_string_init (&dbus1))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!_dbus_string_init (&services))
+ {
+ _dbus_string_free (&dbus1);
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!_dbus_string_init (&xrd))
+ {
+ _dbus_string_free (&dbus1);
+ _dbus_string_free (&services);
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ xdg_runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
+
+ /* Not an error, we just can't have transient session services */
+ if (xdg_runtime_dir == NULL)
+ {
+ _dbus_verbose ("XDG_RUNTIME_DIR is unset: transient session services "
+ "not available here\n");
+ ret = TRUE;
+ goto out;
+ }
+
+ if (!_dbus_string_append (&xrd, xdg_runtime_dir) ||
+ !_dbus_string_append_printf (&dbus1, "%s/dbus-1",
+ xdg_runtime_dir) ||
+ !_dbus_string_append_printf (&services, "%s/dbus-1/services",
+ xdg_runtime_dir))
+ {
+ _DBUS_SET_OOM (error);
+ goto out;
+ }
+
+ if (!ensure_owned_directory ("XDG_RUNTIME_DIR", &xrd, FALSE, error) ||
+ !ensure_owned_directory ("XDG_RUNTIME_DIR subdirectory", &dbus1, TRUE,
+ error) ||
+ !ensure_owned_directory ("XDG_RUNTIME_DIR subdirectory", &services,
+ TRUE, error))
+ goto out;
+
+ if (!_dbus_string_steal_data (&services, &data) ||
+ !_dbus_list_append (dirs, data))
+ {
+ _DBUS_SET_OOM (error);
+ goto out;
+ }
+
+ _dbus_verbose ("Transient service directory is %s\n", data);
+ /* Ownership was transferred to @dirs */
+ data = NULL;
+ ret = TRUE;
+
+out:
+ _dbus_string_free (&dbus1);
+ _dbus_string_free (&services);
+ _dbus_string_free (&xrd);
+ dbus_free (data);
+ return ret;
+}
+
+/**
* Returns the standard directories for a session bus to look for service
* activation files
*
@@ -1424,27 +1496,71 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs)
}
/**
- * Append the absolute path of the system.conf file
+ * Get the absolute path of the system.conf file
* (there is no system bus on Windows so this can just
* return FALSE and print a warning or something)
*
- * @param str the string to append to
+ * @param str the string to append to, which must be empty on entry
* @returns #FALSE if no memory
*/
dbus_bool_t
-_dbus_append_system_config_file (DBusString *str)
+_dbus_get_system_config_file (DBusString *str)
{
+ _dbus_assert (_dbus_string_get_length (str) == 0);
+
return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
}
/**
- * Append the absolute path of the session.conf file.
+ * Get the absolute path of the session.conf file.
*
- * @param str the string to append to
+ * @param str the string to append to, which must be empty on entry
* @returns #FALSE if no memory
*/
dbus_bool_t
-_dbus_append_session_config_file (DBusString *str)
+_dbus_get_session_config_file (DBusString *str)
{
+ _dbus_assert (_dbus_string_get_length (str) == 0);
+
return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
}
+
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+
+/*
+ * Set uid to a machine-readable authentication identity (numeric Unix
+ * uid or ConvertSidToStringSid-style Windows SID) that is likely to exist,
+ * and differs from the identity of the current process.
+ *
+ * @param uid Populated with a machine-readable authentication identity
+ * on success
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_test_append_different_uid (DBusString *uid)
+{
+ if (geteuid () == 0)
+ return _dbus_string_append (uid, "65534");
+ else
+ return _dbus_string_append (uid, "0");
+}
+
+/*
+ * Set uid to a human-readable authentication identity (login name)
+ * that is likely to exist, and differs from the identity of the current
+ * process. This function currently only exists on Unix platforms.
+ *
+ * @param uid Populated with a machine-readable authentication identity
+ * on success
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_test_append_different_username (DBusString *username)
+{
+ if (geteuid () == 0)
+ return _dbus_string_append (username, "nobody");
+ else
+ return _dbus_string_append (username, "root");
+}
+
+#endif
diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c
index 3b754dbf..8c8fbed8 100644
--- a/dbus/dbus-sysdeps-util-win.c
+++ b/dbus/dbus-sysdeps-util-win.c
@@ -273,8 +273,7 @@ _dbus_rlimit_save_fd_limit (DBusError *error)
}
dbus_bool_t
-_dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
- DBusError *error)
+_dbus_rlimit_raise_fd_limit (DBusError *error)
{
fd_limit_not_supported (error);
return FALSE;
@@ -296,75 +295,6 @@ _dbus_rlimit_free (DBusRLimit *lim)
_dbus_assert (lim == NULL);
}
-void
-_dbus_init_system_log (dbus_bool_t is_daemon)
-{
- /* OutputDebugStringA doesn't need any special initialization, do nothing */
-}
-
-/**
- * Log a message to the system log file (e.g. syslog on Unix).
- *
- * @param severity a severity value
- * @param msg a printf-style format string
- */
-void
-_dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
-{
- va_list args;
-
- va_start (args, msg);
-
- _dbus_system_logv (severity, msg, args);
-
- va_end (args);
-}
-
-/**
- * Log a message to the system log file (e.g. syslog on Unix).
- *
- * @param severity a severity value
- * @param msg a printf-style format string
- * @param args arguments for the format string
- *
- * If the FATAL severity is given, this function will terminate the program
- * with an error code.
- */
-void
-_dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
-{
- char *s = "";
- char buf[1024];
- char format[1024];
-
- switch(severity)
- {
- case DBUS_SYSTEM_LOG_INFO: s = "info"; break;
- case DBUS_SYSTEM_LOG_WARNING: s = "warning"; break;
- case DBUS_SYSTEM_LOG_SECURITY: s = "security"; break;
- case DBUS_SYSTEM_LOG_FATAL: s = "fatal"; break;
- }
-
- snprintf(format, sizeof(format), "%s%s", s ,msg);
- vsnprintf(buf, sizeof(buf), format, args);
- OutputDebugStringA(buf);
-
- if (severity == DBUS_SYSTEM_LOG_FATAL)
- exit (1);
-}
-
-/** Installs a signal handler
- *
- * @param sig the signal to handle
- * @param handler the handler
- */
-void
-_dbus_set_signal_handler (int sig,
- DBusSignalHandler handler)
-{
- _dbus_verbose ("_dbus_set_signal_handler() has to be implemented\n");
-}
-
/**
* stat() wrapper.
*
@@ -1437,12 +1367,14 @@ _dbus_lm_strerror(int error_number)
return "The password does not meet the requirements of the password filter DLLs.";
#endif
- }
- msg = strerror (error_number);
- if (msg == NULL)
- msg = "unknown";
+ default:
+ msg = strerror (error_number);
- return msg;
+ if (msg == NULL)
+ msg = "unknown";
+
+ return msg;
+ }
#endif //DBUS_WINCE
}
@@ -1470,76 +1402,87 @@ _dbus_command_for_pid (unsigned long pid,
return FALSE;
}
-/*
- * replaces the term DBUS_PREFIX in configure_time_path by the
- * current dbus installation directory. On unix this function is a noop
+/**
+ * Replace the DBUS_PREFIX in the given path, in-place, by the
+ * current D-Bus installation directory. On Unix this function
+ * does nothing, successfully.
*
- * @param configure_time_path
- * @return real path
+ * @param path path to edit
+ * @return #FALSE on OOM
*/
-const char *
-_dbus_replace_install_prefix (const char *configure_time_path)
+dbus_bool_t
+_dbus_replace_install_prefix (DBusString *path)
{
#ifndef DBUS_PREFIX
- return configure_time_path;
+ /* leave path unchanged */
+ return TRUE;
#else
- static char retval[1000];
- static char runtime_prefix[1000];
- int len = 1000;
+ DBusString runtime_prefix;
int i;
- if (!configure_time_path)
- return NULL;
-
- if ((!_dbus_get_install_root(runtime_prefix, len) ||
- strncmp (configure_time_path, DBUS_PREFIX "/",
- strlen (DBUS_PREFIX) + 1))) {
- strncpy (retval, configure_time_path, sizeof (retval) - 1);
- /* strncpy does not guarantee to 0-terminate the string */
- retval[sizeof (retval) - 1] = '\0';
- } else {
- size_t remaining;
-
- strncpy (retval, runtime_prefix, sizeof (retval) - 1);
- retval[sizeof (retval) - 1] = '\0';
- remaining = sizeof (retval) - 1 - strlen (retval);
- strncat (retval,
- configure_time_path + strlen (DBUS_PREFIX) + 1,
- remaining);
- }
+ if (!_dbus_string_init (&runtime_prefix))
+ return FALSE;
+
+ if (!_dbus_get_install_root (&runtime_prefix))
+ {
+ _dbus_string_free (&runtime_prefix);
+ return FALSE;
+ }
+
+ if (_dbus_string_get_length (&runtime_prefix) == 0)
+ {
+ /* cannot determine install root, leave path unchanged */
+ _dbus_string_free (&runtime_prefix);
+ return TRUE;
+ }
+
+ if (_dbus_string_starts_with_c_str (path, DBUS_PREFIX "/"))
+ {
+ /* Replace DBUS_PREFIX "/" with runtime_prefix.
+ * Note unusual calling convention: source is first, then dest */
+ if (!_dbus_string_replace_len (
+ &runtime_prefix, 0, _dbus_string_get_length (&runtime_prefix),
+ path, 0, strlen (DBUS_PREFIX) + 1))
+ {
+ _dbus_string_free (&runtime_prefix);
+ return FALSE;
+ }
+ }
/* Somehow, in some situations, backslashes get collapsed in the string.
* Since windows C library accepts both forward and backslashes as
* path separators, convert all backslashes to forward slashes.
*/
- for(i = 0; retval[i] != '\0'; i++) {
- if(retval[i] == '\\')
- retval[i] = '/';
- }
- return retval;
+ for (i = 0; i < _dbus_string_get_length (path); i++)
+ {
+ if (_dbus_string_get_byte (path, i) == '\\')
+ _dbus_string_set_byte (path, i, '/');
+ }
+
+ _dbus_string_free (&runtime_prefix);
+ return TRUE;
#endif
}
+#define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
+#define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
+
/**
- * return the relocated DATADIR
+ * Returns the standard directories for a session bus to look for
+ * transient service activation files. On Windows, there are none.
*
- * @returns relocated DATADIR static string
+ * @param dirs the directory list we are returning
+ * @returns #TRUE
*/
-
-static const char *
-_dbus_windows_get_datadir (void)
+dbus_bool_t
+_dbus_set_up_transient_session_servicedirs (DBusList **dirs,
+ DBusError *error)
{
- return _dbus_replace_install_prefix(DBUS_DATADIR);
+ /* Not an error, we just don't have transient session services on Windows */
+ return TRUE;
}
-#undef DBUS_DATADIR
-#define DBUS_DATADIR _dbus_windows_get_datadir ()
-
-
-#define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
-#define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
-
/**
* Returns the standard directories for a session bus to look for service
* activation files
@@ -1580,27 +1523,30 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs)
}
}
#else
-/*
- the code for accessing services requires absolute base pathes
- in case DBUS_DATADIR is relative make it absolute
-*/
-#ifdef DBUS_WIN
{
DBusString p;
- _dbus_string_init_const (&p, DBUS_DATADIR);
+ if (!_dbus_string_init (&p))
+ goto oom;
+
+ /* DBUS_DATADIR is assumed to be absolute; the build systems should
+ * ensure that. */
+ if (!_dbus_string_append (&p, DBUS_DATADIR) ||
+ !_dbus_replace_install_prefix (&p))
+ {
+ _dbus_string_free (&p);
+ goto oom;
+ }
- if (!_dbus_path_is_absolute (&p))
+ if (!_dbus_string_append (&servicedir_path,
+ _dbus_string_get_const_data (&p)))
{
- char install_root[1000];
- if (_dbus_get_install_root (install_root, sizeof(install_root)))
- if (!_dbus_string_append (&servicedir_path, install_root))
- goto oom;
+ _dbus_string_free (&p);
+ goto oom;
}
+
+ _dbus_string_free (&p);
}
-#endif
- if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
- goto oom;
if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
goto oom;
@@ -1661,7 +1607,8 @@ _dbus_get_config_file_name (DBusString *str,
{
DBusString tmp;
- if (!_dbus_string_append (str, _dbus_windows_get_datadir ()))
+ if (!_dbus_string_append (str, DBUS_DATADIR) ||
+ !_dbus_replace_install_prefix (str))
return FALSE;
_dbus_string_init_const (&tmp, "dbus-1");
@@ -1678,27 +1625,56 @@ _dbus_get_config_file_name (DBusString *str,
}
/**
- * Append the absolute path of the system.conf file
+ * Get the absolute path of the system.conf file
* (there is no system bus on Windows so this can just
* return FALSE and print a warning or something)
*
- * @param str the string to append to
+ * @param str the string to append to, which must be empty on entry
* @returns #FALSE if no memory
*/
dbus_bool_t
-_dbus_append_system_config_file (DBusString *str)
+_dbus_get_system_config_file (DBusString *str)
{
+ _dbus_assert (_dbus_string_get_length (str) == 0);
+
return _dbus_get_config_file_name(str, "system.conf");
}
/**
- * Append the absolute path of the session.conf file.
+ * Get the absolute path of the session.conf file.
*
- * @param str the string to append to
+ * @param str the string to append to, which must be empty on entry
* @returns #FALSE if no memory
*/
dbus_bool_t
-_dbus_append_session_config_file (DBusString *str)
+_dbus_get_session_config_file (DBusString *str)
{
+ _dbus_assert (_dbus_string_get_length (str) == 0);
+
return _dbus_get_config_file_name(str, "session.conf");
}
+
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+
+#define ANONYMOUS_SID "S-1-5-7"
+#define LOCAL_SYSTEM_SID "S-1-5-18"
+
+dbus_bool_t
+_dbus_test_append_different_uid (DBusString *uid)
+{
+ char *sid = NULL;
+ dbus_bool_t ret;
+
+ if (!_dbus_getsid (&sid, _dbus_getpid ()))
+ return FALSE;
+
+ if (strcmp (sid, ANONYMOUS_SID) == 0)
+ ret = _dbus_string_append (uid, LOCAL_SYSTEM_SID);
+ else
+ ret = _dbus_string_append (uid, ANONYMOUS_SID);
+
+ LocalFree (sid);
+ return ret;
+}
+
+#endif
diff --git a/dbus/dbus-sysdeps-util.c b/dbus/dbus-sysdeps-util.c
index 6b361ef0..44cc6a23 100644
--- a/dbus/dbus-sysdeps-util.c
+++ b/dbus/dbus-sysdeps-util.c
@@ -35,6 +35,8 @@
#elif (defined __APPLE__)
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
+#elif HAVE_DECL_ENVIRON && defined(HAVE_UNISTD_H)
+# include <unistd.h>
#else
extern char **environ;
#endif
@@ -97,7 +99,7 @@ check_dirname (const char *filename,
if (!_dbus_string_equal_c_str (&d, dirname))
{
- _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
+ _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"",
filename,
_dbus_string_get_const_data (&d),
dirname);
@@ -117,7 +119,7 @@ check_path_absolute (const char *path,
if (_dbus_path_is_absolute (&p) != expected)
{
- _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
+ _dbus_warn ("For path \"%s\" expected absolute = %d got %d",
path, expected, _dbus_path_is_absolute (&p));
exit (1);
}
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index f535d9a1..0deedeaf 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -99,7 +99,7 @@ _dbus_win_set_errno (int err)
#endif
}
-static BOOL is_winxp_sp3_or_lower();
+static BOOL is_winxp_sp3_or_lower (void);
/*
* _MIB_TCPROW_EX and friends are not available in system headers
@@ -323,9 +323,10 @@ _dbus_win_error_from_last_error (void)
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return DBUS_ERROR_FILE_NOT_FOUND;
+
+ default:
+ return DBUS_ERROR_FAILED;
}
-
- return DBUS_ERROR_FAILED;
}
@@ -507,7 +508,7 @@ _dbus_close_socket (DBusSocket fd,
fd.sock, _dbus_strerror_from_errno ());
return FALSE;
}
- _dbus_verbose ("_dbus_close_socket: socket=%Iu, \n", fd.sock);
+ _dbus_verbose ("socket=%Iu, \n", fd.sock);
return TRUE;
}
@@ -631,12 +632,12 @@ _dbus_write_socket_two (DBusSocket fd,
{
DBUS_SOCKET_SET_ERRNO ();
_dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ());
- bytes_written = -1;
+ bytes_written = (DWORD) -1;
}
else
_dbus_verbose ("WSASend: = %ld\n", bytes_written);
- if (bytes_written < 0 && errno == EINTR)
+ if (bytes_written == (DWORD) -1 && errno == EINTR)
goto again;
return bytes_written;
@@ -941,7 +942,8 @@ _dbus_pid_for_log (void)
#ifndef DBUS_WINCE
-static BOOL is_winxp_sp3_or_lower()
+static BOOL
+is_winxp_sp3_or_lower (void)
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
@@ -1315,9 +1317,11 @@ _dbus_poll (DBusPollFD *fds,
#else /* USE_CHRIS_IMPL */
+#ifdef DBUS_ENABLE_VERBOSE_MODE
#define DBUS_POLL_CHAR_BUFFER_SIZE 2000
char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
char *msgp;
+#endif
fd_set read_set, write_set, err_set;
SOCKET max_fd = 0;
@@ -2224,6 +2228,35 @@ _dbus_disable_sigpipe (void)
}
/**
+ * Creates a directory. Unlike _dbus_ensure_directory(), this only succeeds
+ * if the directory is genuinely newly-created.
+ *
+ * @param filename directory filename
+ * @param error initialized error object
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_create_directory (const DBusString *filename,
+ DBusError *error)
+{
+ const char *filename_c;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ filename_c = _dbus_string_get_const_data (filename);
+
+ if (!CreateDirectoryA (filename_c, NULL))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to create directory %s: %s\n",
+ filename_c, _dbus_strerror_from_errno ());
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+/**
* Creates a directory; succeeds if the directory
* is created or already existed.
*
@@ -2232,7 +2265,7 @@ _dbus_disable_sigpipe (void)
* @returns #TRUE on success
*/
dbus_bool_t
-_dbus_create_directory (const DBusString *filename,
+_dbus_ensure_directory (const DBusString *filename,
DBusError *error)
{
const char *filename_c;
@@ -2271,7 +2304,7 @@ _dbus_generate_random_bytes (DBusString *str,
DBusError *error)
{
int old_len;
- char *p;
+ unsigned char *p;
HCRYPTPROV hprov;
old_len = _dbus_string_get_length (str);
@@ -2282,7 +2315,7 @@ _dbus_generate_random_bytes (DBusString *str,
return FALSE;
}
- p = _dbus_string_get_data_len (str, old_len, n_bytes);
+ p = _dbus_string_get_udata_len (str, old_len, n_bytes);
if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
@@ -2320,20 +2353,21 @@ _dbus_get_tmpdir(void)
if (tmpdir == NULL)
{
- char *last_slash;
+ unsigned char *last_slash;
+ unsigned char *p = (unsigned char *)buf;
if (!GetTempPathA (sizeof (buf), buf))
{
- _dbus_warn ("GetTempPath failed\n");
+ _dbus_warn ("GetTempPath failed");
_dbus_abort ();
}
/* Drop terminating backslash or slash */
- last_slash = _mbsrchr (buf, '\\');
- if (last_slash > buf && last_slash[1] == '\0')
+ last_slash = _mbsrchr (p, '\\');
+ if (last_slash > p && last_slash[1] == '\0')
last_slash[0] = '\0';
- last_slash = _mbsrchr (buf, '/');
- if (last_slash > buf && last_slash[1] == '\0')
+ last_slash = _mbsrchr (p, '/');
+ if (last_slash > p && last_slash[1] == '\0')
last_slash[0] = '\0';
tmpdir = buf;
@@ -2420,192 +2454,56 @@ _dbus_delete_file (const DBusString *filename,
#define __i386__
#endif
-//#define MAKE_FUNCPTR(f) static typeof(f) * p##f
-
-//MAKE_FUNCPTR(StackWalk);
-//MAKE_FUNCPTR(SymGetModuleBase);
-//MAKE_FUNCPTR(SymFunctionTableAccess);
-//MAKE_FUNCPTR(SymInitialize);
-//MAKE_FUNCPTR(SymGetSymFromAddr);
-//MAKE_FUNCPTR(SymGetModuleInfo);
-static BOOL (WINAPI *pStackWalk)(
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME StackFrame,
- PVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
-);
-#ifdef _WIN64
-static DWORD64 (WINAPI *pSymGetModuleBase)(
- HANDLE hProcess,
- DWORD64 dwAddr
-);
-static PVOID (WINAPI *pSymFunctionTableAccess)(
- HANDLE hProcess,
- DWORD64 AddrBase
-);
-#else
-static DWORD (WINAPI *pSymGetModuleBase)(
- HANDLE hProcess,
- DWORD dwAddr
-);
-static PVOID (WINAPI *pSymFunctionTableAccess)(
- HANDLE hProcess,
- DWORD AddrBase
-);
-#endif
-static BOOL (WINAPI *pSymInitialize)(
- HANDLE hProcess,
- PSTR UserSearchPath,
- BOOL fInvadeProcess
-);
-static BOOL (WINAPI *pSymGetSymFromAddr)(
- HANDLE hProcess,
- DWORD Address,
- PDWORD Displacement,
- PIMAGEHLP_SYMBOL Symbol
-);
-static BOOL (WINAPI *pSymGetModuleInfo)(
- HANDLE hProcess,
- DWORD dwAddr,
- PIMAGEHLP_MODULE ModuleInfo
-);
-static DWORD (WINAPI *pSymSetOptions)(
- DWORD SymOptions
-);
-
-
-static BOOL init_backtrace()
-{
- HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
-/*
- #define GETFUNC(x) \
- p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
- if (!p##x) \
- { \
- return FALSE; \
- }
- */
-
-
-// GETFUNC(StackWalk);
-// GETFUNC(SymGetModuleBase);
-// GETFUNC(SymFunctionTableAccess);
-// GETFUNC(SymInitialize);
-// GETFUNC(SymGetSymFromAddr);
-// GETFUNC(SymGetModuleInfo);
-
-#define FUNC(x) #x
-
- pStackWalk = (BOOL (WINAPI *)(
-DWORD MachineType,
-HANDLE hProcess,
-HANDLE hThread,
-LPSTACKFRAME StackFrame,
-PVOID ContextRecord,
-PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
-PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
-PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
-PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
-))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
-#ifdef _WIN64
- pSymGetModuleBase=(DWORD64 (WINAPI *)(
- HANDLE hProcess,
- DWORD64 dwAddr
-))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
- pSymFunctionTableAccess=(PVOID (WINAPI *)(
- HANDLE hProcess,
- DWORD64 AddrBase
-))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
-#else
- pSymGetModuleBase=(DWORD (WINAPI *)(
- HANDLE hProcess,
- DWORD dwAddr
-))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
- pSymFunctionTableAccess=(PVOID (WINAPI *)(
- HANDLE hProcess,
- DWORD AddrBase
-))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
-#endif
- pSymInitialize = (BOOL (WINAPI *)(
- HANDLE hProcess,
- PSTR UserSearchPath,
- BOOL fInvadeProcess
-))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
- pSymGetSymFromAddr = (BOOL (WINAPI *)(
- HANDLE hProcess,
- DWORD Address,
- PDWORD Displacement,
- PIMAGEHLP_SYMBOL Symbol
-))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
- pSymGetModuleInfo = (BOOL (WINAPI *)(
- HANDLE hProcess,
- DWORD dwAddr,
- PIMAGEHLP_MODULE ModuleInfo
-))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
-pSymSetOptions = (DWORD (WINAPI *)(
-DWORD SymOptions
-))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
-
-
- pSymSetOptions(SYMOPT_UNDNAME);
-
- pSymInitialize(GetCurrentProcess(), NULL, TRUE);
-
- return TRUE;
-}
-
-static void dump_backtrace_for_thread(HANDLE hThread)
+static void dump_backtrace_for_thread (HANDLE hThread)
{
- STACKFRAME sf;
- CONTEXT context;
- DWORD dwImageType;
+ ADDRESS old_address;
+ STACKFRAME sf;
+ CONTEXT context;
+ DWORD dwImageType;
+ int i = 0;
+
+ SymSetOptions (SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
+ SymInitialize (GetCurrentProcess (), NULL, TRUE);
- if (!pStackWalk)
- if (!init_backtrace())
- return;
- /* can't use this function for current thread as GetThreadContext
- * doesn't support getting context from current thread */
- if (hThread == GetCurrentThread())
- return;
+ /* can't use this function for current thread as GetThreadContext
+ * doesn't support getting context from current thread */
+ if (hThread == GetCurrentThread())
+ return;
- DPRINTF("Backtrace:\n");
+ DPRINTF ("Backtrace:\n");
- _DBUS_ZERO(context);
- context.ContextFlags = CONTEXT_FULL;
+ _DBUS_ZERO (old_address);
+ _DBUS_ZERO (context);
+ context.ContextFlags = CONTEXT_FULL;
- SuspendThread(hThread);
+ SuspendThread (hThread);
- if (!GetThreadContext(hThread, &context))
+ if (!GetThreadContext (hThread, &context))
{
- DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
- ResumeThread(hThread);
- return;
+ DPRINTF ("Couldn't get thread context (error %ld)\n", GetLastError ());
+ ResumeThread (hThread);
+ return;
}
- _DBUS_ZERO(sf);
+ _DBUS_ZERO (sf);
#ifdef __i386__
- sf.AddrFrame.Offset = context.Ebp;
- sf.AddrFrame.Mode = AddrModeFlat;
- sf.AddrPC.Offset = context.Eip;
- sf.AddrPC.Mode = AddrModeFlat;
- dwImageType = IMAGE_FILE_MACHINE_I386;
-#elif _M_X64
- dwImageType = IMAGE_FILE_MACHINE_AMD64;
+ dwImageType = IMAGE_FILE_MACHINE_I386;
+ sf.AddrFrame.Offset = context.Ebp;
+ sf.AddrFrame.Mode = AddrModeFlat;
+ sf.AddrPC.Offset = context.Eip;
+ sf.AddrPC.Mode = AddrModeFlat;
+#elif defined(_M_X64)
+ dwImageType = IMAGE_FILE_MACHINE_AMD64;
sf.AddrPC.Offset = context.Rip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Offset = context.Rsp;
sf.AddrFrame.Mode = AddrModeFlat;
sf.AddrStack.Offset = context.Rsp;
sf.AddrStack.Mode = AddrModeFlat;
-#elif _M_IA64
- dwImageType = IMAGE_FILE_MACHINE_IA64;
+#elif defined(_M_IA64)
+ dwImageType = IMAGE_FILE_MACHINE_IA64;
sf.AddrPC.Offset = context.StIIP;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Offset = context.IntSp;
@@ -2618,71 +2516,98 @@ static void dump_backtrace_for_thread(HANDLE hThread)
# error You need to fill in the STACKFRAME structure for your architecture
#endif
- while (pStackWalk(dwImageType, GetCurrentProcess(),
- hThread, &sf, &context, NULL, pSymFunctionTableAccess,
- pSymGetModuleBase, NULL))
+ /*
+ backtrace format
+ <level> <address> <symbol>[+offset] [ '[' <file> ':' <line> ']' ] [ 'in' <module> ]
+ example:
+ 6 0xf75ade6b wine_switch_to_stack+0x2a [/usr/src/debug/wine-snapshot/libs/wine/port.c:59] in libwine.so.1
+ */
+ while (StackWalk (dwImageType, GetCurrentProcess (),
+ hThread, &sf, &context, NULL, SymFunctionTableAccess,
+ SymGetModuleBase, NULL))
{
- BYTE buffer[256];
- IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
- DWORD dwDisplacement;
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(char)];
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
+ DWORD64 displacement;
+ IMAGEHLP_LINE line;
+ DWORD dwDisplacement;
+ IMAGEHLP_MODULE moduleInfo;
- pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
- pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
+ /*
+ on Wine64 version 1.7.54, we get an infinite number of stack entries
+ pointing to the same stack frame (_start+0x29 in <wine-loader>)
+ see bug https://bugs.winehq.org/show_bug.cgi?id=39606
+ */
+#ifndef __i386__
+ if (old_address.Offset == sf.AddrPC.Offset)
+ {
+ break;
+ }
+#endif
- if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
- &dwDisplacement, pSymbol))
+ pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ pSymbol->MaxNameLen = MAX_SYM_NAME;
+
+ if (SymFromAddr (GetCurrentProcess (), sf.AddrPC.Offset, &displacement, pSymbol))
{
- IMAGEHLP_MODULE ModuleInfo;
- ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
-
- if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
- &ModuleInfo))
- DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
- else
- DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
- sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
+ if (displacement)
+ DPRINTF ("%3d %s+0x%I64x", i++, pSymbol->Name, displacement);
+ else
+ DPRINTF ("%3d %s", i++, pSymbol->Name);
+ }
+ else
+ DPRINTF ("%3d 0x%Ix", i++, sf.AddrPC.Offset);
+
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
+ if (SymGetLineFromAddr (GetCurrentProcess (), sf.AddrPC.Offset, &dwDisplacement, &line))
+ {
+ DPRINTF (" [%s:%ld]", line.FileName, line.LineNumber);
}
- else if (dwDisplacement)
- DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
- else
- DPRINTF("4\t%s\n", pSymbol->Name);
- }
- ResumeThread(hThread);
+ moduleInfo.SizeOfStruct = sizeof(moduleInfo);
+ if (SymGetModuleInfo (GetCurrentProcess (), sf.AddrPC.Offset, &moduleInfo))
+ {
+ DPRINTF (" in %s", moduleInfo.ModuleName);
+ }
+ DPRINTF ("\n");
+ old_address = sf.AddrPC;
+ }
+ ResumeThread (hThread);
}
-static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
+static DWORD WINAPI dump_thread_proc (LPVOID lpParameter)
{
- dump_backtrace_for_thread((HANDLE)lpParameter);
- return 0;
+ dump_backtrace_for_thread ((HANDLE) lpParameter);
+ return 0;
}
/* cannot get valid context from current thread, so we have to execute
* backtrace from another thread */
-static void dump_backtrace()
-{
- HANDLE hCurrentThread;
- HANDLE hThread;
- DWORD dwThreadId;
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
- GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
- hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
- 0, &dwThreadId);
- WaitForSingleObject(hThread, INFINITE);
- CloseHandle(hThread);
- CloseHandle(hCurrentThread);
+static void
+dump_backtrace (void)
+{
+ HANDLE hCurrentThread;
+ HANDLE hThread;
+ DWORD dwThreadId;
+ DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+ GetCurrentProcess (), &hCurrentThread,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+ hThread = CreateThread (NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
+ 0, &dwThreadId);
+ WaitForSingleObject (hThread, INFINITE);
+ CloseHandle (hThread);
+ CloseHandle (hCurrentThread);
}
#endif
#endif /* asserts or tests enabled */
#ifdef BACKTRACES
-void _dbus_print_backtrace(void)
+void _dbus_print_backtrace (void)
{
- init_backtrace();
- dump_backtrace();
+ dump_backtrace ();
}
#else
-void _dbus_print_backtrace(void)
+void _dbus_print_backtrace (void)
{
_dbus_verbose (" D-Bus not compiled with backtrace support\n");
}
@@ -2792,9 +2717,9 @@ HANDLE _dbus_global_lock (const char *mutexname)
case WAIT_FAILED:
case WAIT_TIMEOUT:
return 0;
+ default:
+ return mutex;
}
-
- return mutex;
}
static
@@ -2821,15 +2746,12 @@ _dbus_get_install_root_as_hash(DBusString *out)
{
DBusString install_path;
- char path[MAX_PATH*2];
- int path_size = sizeof(path);
+ _dbus_string_init(&install_path);
- if (!_dbus_get_install_root(path,path_size))
+ if (!_dbus_get_install_root (&install_path) ||
+ _dbus_string_get_length (&install_path) == 0)
return FALSE;
- _dbus_string_init(&install_path);
- _dbus_string_append(&install_path,path);
-
_dbus_string_init(out);
_dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path));
@@ -3299,45 +3221,87 @@ _dbus_get_is_errno_eagain_or_ewouldblock (int e)
}
/**
- * return the absolute path of the dbus installation
+ * Fill str with the absolute path of the D-Bus installation, or truncate str
+ * to zero length if we cannot determine it.
*
- * @param prefix buffer for installation path
- * @param len length of buffer
- * @returns #FALSE on failure
+ * @param str buffer for installation path
+ * @returns #FALSE on OOM, #TRUE if not OOM
*/
dbus_bool_t
-_dbus_get_install_root(char *prefix, int len)
-{
- //To find the prefix, we cut the filename and also \bin\ if present
- DWORD pathLength;
- char *lastSlash;
- SetLastError( 0 );
- pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len);
- if ( pathLength == 0 || GetLastError() != 0 ) {
- *prefix = '\0';
- return FALSE;
- }
- lastSlash = _mbsrchr(prefix, '\\');
+_dbus_get_install_root (DBusString *str)
+{
+ /* this is just an initial guess */
+ DWORD pathLength = MAX_PATH;
+ unsigned char *lastSlash;
+ unsigned char *prefix;
+
+ do
+ {
+ /* allocate enough space for our best guess at the length */
+ if (!_dbus_string_set_length (str, pathLength))
+ {
+ _dbus_string_set_length (str, 0);
+ return FALSE;
+ }
+
+ SetLastError (0);
+ pathLength = GetModuleFileNameA (_dbus_win_get_dll_hmodule (),
+ _dbus_string_get_data (str), _dbus_string_get_length (str));
+
+ if (pathLength == 0 || GetLastError () != 0)
+ {
+ /* failed, but not OOM */
+ _dbus_string_set_length (str, 0);
+ return TRUE;
+ }
+
+ /* if the return is strictly less than the buffer size, it has
+ * not been truncated, so we can continue */
+ if (pathLength < (DWORD) _dbus_string_get_length (str))
+ {
+ /* reduce the length to match what Windows filled in */
+ if (!_dbus_string_set_length (str, pathLength))
+ {
+ _dbus_string_set_length (str, 0);
+ return FALSE;
+ }
+
+ break;
+ }
+
+ /* else it may have been truncated; try with a larger buffer */
+ pathLength *= 2;
+ }
+ while (TRUE);
+
+ /* the rest of this function works by direct byte manipulation of the
+ * underlying buffer */
+ prefix = _dbus_string_get_udata (str);
+
+ lastSlash = _mbsrchr (prefix, '\\');
if (lastSlash == NULL) {
- *prefix = '\0';
- return FALSE;
+ /* failed, but not OOM */
+ _dbus_string_set_length (str, 0);
+ return TRUE;
}
//cut off binary name
lastSlash[1] = 0;
//cut possible "\\bin"
-
//this fails if we are in a double-byte system codepage and the
//folder's name happens to end with the *bytes*
//"\\bin"... (I.e. the second byte of some Han character and then
//the Latin "bin", but that is not likely I think...
- if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0)
+ if (lastSlash - prefix >= 4 && _mbsnicmp (lastSlash - 4, (const unsigned char *)"\\bin", 4) == 0)
lastSlash[-3] = 0;
- else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0)
+ else if (lastSlash - prefix >= 10 && _mbsnicmp (lastSlash - 10, (const unsigned char *)"\\bin\\debug", 10) == 0)
lastSlash[-9] = 0;
- else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0)
+ else if (lastSlash - prefix >= 12 && _mbsnicmp (lastSlash - 12, (const unsigned char *)"\\bin\\release", 12) == 0)
lastSlash[-11] = 0;
+ /* fix up the length to match the byte-manipulation */
+ _dbus_string_set_length (str, strlen ((char *) prefix));
+
return TRUE;
}
@@ -3413,7 +3377,7 @@ _dbus_append_keyring_directory_for_credentials (DBusString *directory,
static dbus_bool_t already_warned = FALSE;
if (!already_warned)
{
- _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
+ _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid");
already_warned = TRUE;
}
}
@@ -3590,12 +3554,15 @@ _dbus_strerror (int error_number)
case WSASYSCALLFAILURE:
return "System call failure";
- }
- msg = strerror (error_number);
- if (msg == NULL)
- msg = "unknown";
- return msg;
+ default:
+ msg = strerror (error_number);
+
+ if (msg == NULL)
+ msg = "unknown";
+
+ return msg;
+ }
#endif //DBUS_WINCE
}
@@ -3635,7 +3602,7 @@ _dbus_win_warn_win_error (const char *message,
dbus_error_init (&error);
_dbus_win_set_error_from_win_error (&error, code);
- _dbus_warn ("%s: %s\n", message, error.message);
+ _dbus_warn ("%s: %s", message, error.message);
dbus_error_free (&error);
}
@@ -3704,5 +3671,76 @@ _dbus_restore_socket_errno (int saved_errno)
_dbus_win_set_errno (saved_errno);
}
+static const char *log_tag = "dbus";
+static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
+
+/**
+ * Initialize the system log.
+ *
+ * The "tag" is not copied, and must remain valid for the entire lifetime of
+ * the process or until _dbus_init_system_log() is called again. In practice
+ * it will normally be a constant.
+ *
+ * @param tag the name of the executable (syslog tag)
+ * @param mode whether to log to stderr, the system log or both
+ */
+void
+_dbus_init_system_log (const char *tag,
+ DBusLogFlags flags)
+{
+ /* We never want to turn off logging completely */
+ _dbus_assert (
+ (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
+
+ log_tag = tag;
+ log_flags = flags;
+}
+
+/**
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ */
+void
+_dbus_logv (DBusSystemLogSeverity severity,
+ const char *msg,
+ va_list args)
+{
+ const char *s = "";
+ va_list tmp;
+
+ switch(severity)
+ {
+ case DBUS_SYSTEM_LOG_INFO: s = "info"; break;
+ case DBUS_SYSTEM_LOG_WARNING: s = "warning"; break;
+ case DBUS_SYSTEM_LOG_SECURITY: s = "security"; break;
+ case DBUS_SYSTEM_LOG_ERROR: s = "error"; break;
+ default: _dbus_assert_not_reached ("invalid log severity");
+ }
+
+ if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
+ {
+ char buf[1024];
+ char format[1024];
+
+ DBUS_VA_COPY (tmp, args);
+ snprintf (format, sizeof (format), "%s: %s", s, msg);
+ vsnprintf(buf, sizeof(buf), format, tmp);
+ OutputDebugStringA(buf);
+ va_end (tmp);
+ }
+
+ if (log_flags & DBUS_LOG_FLAGS_STDERR)
+ {
+ DBUS_VA_COPY (tmp, args);
+ fprintf (stderr, "%s[%lu]: %s: ", log_tag, _dbus_pid_for_log (), s);
+ vfprintf (stderr, msg, tmp);
+ fprintf (stderr, "\n");
+ va_end (tmp);
+ }
+}
+
/** @} end of sysdeps-win */
/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus-sysdeps-win.h b/dbus/dbus-sysdeps-win.h
index e9b30d7a..b8861a1f 100644
--- a/dbus/dbus-sysdeps-win.h
+++ b/dbus/dbus-sysdeps-win.h
@@ -82,10 +82,8 @@ _dbus_win_sid_to_name_and_domain (dbus_uid_t uid,
wchar_t **wdomain,
DBusError *error);
-dbus_bool_t _dbus_file_exists (const char *filename);
-
DBUS_PRIVATE_EXPORT
-dbus_bool_t _dbus_get_install_root(char *prefix, int len);
+dbus_bool_t _dbus_get_install_root (DBusString *str);
void _dbus_threads_windows_init_global (void);
void _dbus_threads_windows_ensure_ctor_linked (void);
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 8b986d58..20bb8944 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -52,6 +52,8 @@
#elif (defined __APPLE__)
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
+#elif HAVE_DECL_ENVIRON && defined(HAVE_UNISTD_H)
+# include <unistd.h>
#else
extern char **environ;
#endif
@@ -668,9 +670,9 @@ _dbus_error_from_errno (int error_number)
case ENOENT:
return DBUS_ERROR_FILE_NOT_FOUND;
#endif
+ default:
+ return DBUS_ERROR_FAILED;
}
-
- return DBUS_ERROR_FAILED;
}
/**
@@ -751,6 +753,26 @@ _dbus_strerror_from_errno (void)
return _dbus_strerror (errno);
}
+/**
+ * Log a message to the system log file (e.g. syslog on Unix) and/or stderr.
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ */
+void
+_dbus_log (DBusSystemLogSeverity severity,
+ const char *msg,
+ ...)
+{
+ va_list args;
+
+ va_start (args, msg);
+
+ _dbus_logv (severity, msg, args);
+
+ va_end (args);
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index fc3818f9..24fbec6a 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -48,6 +48,32 @@
#include <string.h>
#include <stdarg.h>
+#if !defined(BROKEN_POLL) && (defined(__APPLE__) || defined(__INTERIX))
+ /* Following libcurl's example, we blacklist poll() on Darwin
+ * (macOS, iOS, etc.) and Interix due to a history of implementation
+ * issues.
+ * https://github.com/curl/curl/blob/master/m4/curl-functions.m4
+ *
+ * On unspecified older macOS versions, poll() failed if given a
+ * device node to poll.
+ *
+ * On macOS < 10.9, poll() with nfds=0 failed instead of waiting for
+ * the timeout and then succeeding.
+ *
+ * On macOS >= 10.12, poll() with nfds=0 succeeded immediately
+ * instead of waiting for the timeout, resulting in busy-looping.
+ *
+ * On Interix, poll() apparently only works for files in /proc.
+ *
+ * The "legacy" build flavour in our CI machinery defines BROKEN_POLL
+ * on whatever platform is in use (normally Linux) to force use of the
+ * same select()-based poll() emulation that we use for macOS, Interix,
+ * and any platform that lacks a real poll(), so that we can test it
+ * more regularly.
+ */
+# define BROKEN_POLL
+#endif
+
/* AIX sys/poll.h does #define events reqevents, and other
* wonderousness, so must include sys/poll before declaring
* DBusPollFD
@@ -92,6 +118,7 @@ typedef struct DBusPipe DBusPipe;
* @{
*/
+DBUS_PRIVATE_EXPORT
void _dbus_abort (void) _DBUS_GNUC_NORETURN;
dbus_bool_t _dbus_check_setuid (void);
@@ -198,7 +225,7 @@ int _dbus_read_socket_with_unix_fds (DBusSocket fd,
DBusString *buffer,
int count,
int *fds,
- int *n_fds);
+ unsigned int *n_fds);
DBUS_PRIVATE_EXPORT
int _dbus_write_socket_with_unix_fds (DBusSocket fd,
const DBusString *buffer,
@@ -285,18 +312,11 @@ struct DBusAtomic
#endif
};
-/* The value we get from autofoo is in the form of a cpp expression;
- * convert that to a conventional defined/undef switch. (We can't get
- * the conventional defined/undef because of multiarch builds only running
- * ./configure once, on Darwin.) */
-#if DBUS_HAVE_ATOMIC_INT_COND
-# define DBUS_HAVE_ATOMIC_INT 1
-#else
-# undef DBUS_HAVE_ATOMIC_INT
-#endif
-
+DBUS_PRIVATE_EXPORT
dbus_int32_t _dbus_atomic_inc (DBusAtomic *atomic);
+DBUS_PRIVATE_EXPORT
dbus_int32_t _dbus_atomic_dec (DBusAtomic *atomic);
+DBUS_PRIVATE_EXPORT
dbus_int32_t _dbus_atomic_get (DBusAtomic *atomic);
#ifdef DBUS_WIN
@@ -418,6 +438,9 @@ DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_create_directory (const DBusString *filename,
DBusError *error);
DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_ensure_directory (const DBusString *filename,
+ DBusError *error);
+DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_delete_directory (const DBusString *filename,
DBusError *error);
@@ -431,9 +454,11 @@ dbus_bool_t _dbus_path_is_absolute (const DBusString *filename);
dbus_bool_t _dbus_get_standard_session_servicedirs (DBusList **dirs);
dbus_bool_t _dbus_get_standard_system_servicedirs (DBusList **dirs);
+dbus_bool_t _dbus_set_up_transient_session_servicedirs (DBusList **dirs,
+ DBusError *error);
-dbus_bool_t _dbus_append_system_config_file (DBusString *str);
-dbus_bool_t _dbus_append_session_config_file (DBusString *str);
+dbus_bool_t _dbus_get_system_config_file (DBusString *str);
+dbus_bool_t _dbus_get_session_config_file (DBusString *str);
/** Opaque type for reading a directory listing */
typedef struct DBusDirIter DBusDirIter;
@@ -489,7 +514,7 @@ void _dbus_exit (int code) _DBUS_GNUC_NORETURN;
DBUS_PRIVATE_EXPORT
int _dbus_printf_string_upper_bound (const char *format,
- va_list args);
+ va_list args) _DBUS_GNUC_PRINTF (1, 0);
#ifdef DBUS_ENABLE_VERBOSE_MODE
DBUS_PRIVATE_EXPORT
@@ -520,6 +545,7 @@ dbus_bool_t _dbus_socketpair (DBusSocket *fd1,
dbus_bool_t blocking,
DBusError *error);
+DBUS_PRIVATE_EXPORT
void _dbus_print_backtrace (void);
dbus_bool_t _dbus_become_daemon (const DBusString *pidfile,
@@ -541,26 +567,33 @@ dbus_bool_t _dbus_command_for_pid (unsigned long pid,
int max_len,
DBusError *error);
-/** A UNIX signal handler */
-typedef void (* DBusSignalHandler) (int sig);
-
-void _dbus_set_signal_handler (int sig,
- DBusSignalHandler handler);
-
dbus_bool_t _dbus_user_at_console (const char *username,
DBusError *error);
-void _dbus_init_system_log (dbus_bool_t is_daemon);
+typedef enum {
+ DBUS_LOG_FLAGS_STDERR = (1 << 0),
+ DBUS_LOG_FLAGS_SYSTEM_LOG = (1 << 1)
+} DBusLogFlags;
+
+DBUS_PRIVATE_EXPORT
+void _dbus_init_system_log (const char *tag,
+ DBusLogFlags flags);
typedef enum {
DBUS_SYSTEM_LOG_INFO,
DBUS_SYSTEM_LOG_WARNING,
DBUS_SYSTEM_LOG_SECURITY,
- DBUS_SYSTEM_LOG_FATAL
+ DBUS_SYSTEM_LOG_ERROR
} DBusSystemLogSeverity;
-void _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) _DBUS_GNUC_PRINTF (2, 3);
-void _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args);
+DBUS_PRIVATE_EXPORT
+void _dbus_log (DBusSystemLogSeverity severity,
+ const char *msg,
+ ...) _DBUS_GNUC_PRINTF (2, 3);
+DBUS_PRIVATE_EXPORT
+void _dbus_logv (DBusSystemLogSeverity severity,
+ const char *msg,
+ va_list args) _DBUS_GNUC_PRINTF (2, 0);
/* Define DBUS_VA_COPY() to do the right thing for copying va_list variables.
* config.h may have already defined DBUS_VA_COPY as va_copy or __va_copy.
@@ -610,6 +643,7 @@ dbus_bool_t _dbus_lookup_session_address (dbus_bool_t *supported,
*/
typedef union DBusGUID DBusGUID;
+DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id,
dbus_bool_t create_if_not_found,
DBusError *error);
@@ -648,21 +682,10 @@ dbus_pid_t _dbus_getpid (void);
DBUS_PRIVATE_EXPORT
dbus_uid_t _dbus_getuid (void);
-dbus_bool_t _dbus_change_to_daemon_user (const char *user,
- DBusError *error);
-
DBUS_PRIVATE_EXPORT
void _dbus_flush_caches (void);
-/*
- * replaces the term DBUS_PREFIX in configure_time_path by the
- * current dbus installation directory. On unix this function is a noop
- *
- * @param configure_time_path
- * @return real path
- */
-const char *
-_dbus_replace_install_prefix (const char *configure_time_path);
+dbus_bool_t _dbus_replace_install_prefix (DBusString *path);
/* Do not set this too high: it is a denial-of-service risk.
* See <https://bugs.freedesktop.org/show_bug.cgi?id=82820>
@@ -675,12 +698,21 @@ _dbus_replace_install_prefix (const char *configure_time_path);
typedef struct DBusRLimit DBusRLimit;
DBusRLimit *_dbus_rlimit_save_fd_limit (DBusError *error);
-dbus_bool_t _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
- DBusError *error);
+dbus_bool_t _dbus_rlimit_raise_fd_limit (DBusError *error);
dbus_bool_t _dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
DBusError *error);
void _dbus_rlimit_free (DBusRLimit *lim);
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+_DBUS_GNUC_WARN_UNUSED_RESULT
+dbus_bool_t _dbus_test_append_different_uid (DBusString *uid);
+
+#ifdef DBUS_UNIX
+_DBUS_GNUC_WARN_UNUSED_RESULT
+dbus_bool_t _dbus_test_append_different_username (DBusString *username);
+#endif
+#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-test-main.c b/dbus/dbus-test-main.c
index 9a80f853..f8088f82 100644
--- a/dbus/dbus-test-main.c
+++ b/dbus/dbus-test-main.c
@@ -27,6 +27,7 @@
#include "dbus-test.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#if HAVE_LOCALE_H
#include <locale.h>
#endif
@@ -51,7 +52,7 @@ main (int argc,
setlocale(LC_ALL, "");
#endif
- if (argc > 1)
+ if (argc > 1 && strcmp (argv[1], "--tap") != 0)
test_data_dir = argv[1];
else
test_data_dir = NULL;
diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c
index 5990d6ec..6c0d71f6 100644
--- a/dbus/dbus-test.c
+++ b/dbus/dbus-test.c
@@ -29,6 +29,8 @@
#include <stdlib.h>
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+static void die (const char *failure) _DBUS_GNUC_NORETURN;
+
static void
die (const char *failure)
{
@@ -44,7 +46,7 @@ check_memleaks (void)
printf ("%s: checking for memleaks\n", "test-dbus");
if (_dbus_get_malloc_blocks_outstanding () != 0)
{
- _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+ _dbus_warn ("%d dbus_malloc blocks were not freed",
_dbus_get_malloc_blocks_outstanding ());
die ("memleaks");
}
diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c
index f2401179..23ca6e44 100644
--- a/dbus/dbus-timeout.c
+++ b/dbus/dbus-timeout.c
@@ -266,12 +266,12 @@ _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list,
link2 = _dbus_list_get_first_link (&timeout_list->timeouts);
while (link2 != link)
{
- DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
- link2);
+ DBusList *next2 = _dbus_list_get_next_link (&timeout_list->timeouts,
+ link2);
(* remove_function) (link2->data, data);
- link2 = next;
+ link2 = next2;
}
return FALSE;
diff --git a/dbus/dbus-transport-kdbus.c b/dbus/dbus-transport-kdbus.c
index d549f5a1..2eb532c4 100755
--- a/dbus/dbus-transport-kdbus.c
+++ b/dbus/dbus-transport-kdbus.c
@@ -3822,7 +3822,7 @@ do_reading (DBusTransport *transport)
oom = TRUE;
goto out;
}
- _dbus_message_loader_get_buffer (transport->loader, &buffer);
+ _dbus_message_loader_get_buffer (transport->loader, &buffer, NULL, NULL);
bytes_read = kdbus_read_message (kdbus_transport, buffer, fds, &n_fds);
diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c
index 35c3cbfc..73896501 100644
--- a/dbus/dbus-transport-socket.c
+++ b/dbus/dbus-transport-socket.c
@@ -476,6 +476,11 @@ do_authentication (DBusTransport *transport,
_dbus_verbose (" %s auth state: authenticated\n",
TRANSPORT_SIDE (transport));
break;
+
+ case DBUS_AUTH_STATE_INVALID:
+ /* fall through */
+ default:
+ _dbus_assert_not_reached ("invalid auth state");
}
}
@@ -794,7 +799,9 @@ do_reading (DBusTransport *transport)
if (bytes_read > 0)
{
_dbus_message_loader_get_buffer (transport->loader,
- &buffer);
+ &buffer,
+ NULL,
+ NULL);
if (!_dbus_auth_decode_data (transport->auth,
&socket_transport->encoded_incoming,
@@ -817,13 +824,22 @@ do_reading (DBusTransport *transport)
}
else
{
+ int max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
+ dbus_bool_t may_read_unix_fds = TRUE;
+
_dbus_message_loader_get_buffer (transport->loader,
- &buffer);
+ &buffer,
+ &max_to_read,
+ &may_read_unix_fds);
+
+ if (max_to_read > socket_transport->max_bytes_read_per_iteration)
+ max_to_read = socket_transport->max_bytes_read_per_iteration;
#ifdef HAVE_UNIX_FD_PASSING
- if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
+ if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport) && may_read_unix_fds)
{
- int *fds, n_fds;
+ int *fds;
+ unsigned int n_fds;
if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
{
@@ -835,7 +851,7 @@ do_reading (DBusTransport *transport)
bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
buffer,
- socket_transport->max_bytes_read_per_iteration,
+ max_to_read,
fds, &n_fds);
saved_errno = _dbus_save_socket_errno ();
@@ -848,7 +864,7 @@ do_reading (DBusTransport *transport)
#endif
{
bytes_read = _dbus_read_socket (socket_transport->fd,
- buffer, socket_transport->max_bytes_read_per_iteration);
+ buffer, max_to_read);
saved_errno = _dbus_save_socket_errno ();
}
@@ -1010,7 +1026,7 @@ socket_handle_watch (DBusTransport *transport,
flags);
else
_dbus_verbose ("asked to handle watch %p on fd %" DBUS_SOCKET_FORMAT " that we don't recognize\n",
- watch, dbus_watch_get_socket (watch));
+ watch, _dbus_socket_printable (_dbus_watch_get_socket (watch)));
}
#endif /* DBUS_ENABLE_VERBOSE_MODE */
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index db9b037d..5771279a 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -393,13 +393,16 @@ check_address (const char *address, DBusError *error)
int len, i;
_dbus_assert (address != NULL);
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
if (!dbus_parse_address (address, &entries, &len, error))
return NULL; /* not a valid address */
for (i = 0; i < len; i++)
{
+ dbus_error_free (error);
transport = _dbus_transport_open (entries[i], error);
+
if (transport != NULL)
break;
}
@@ -552,6 +555,9 @@ _dbus_transport_open (DBusAddressEntry *entry,
_DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
goto out;
break;
+ default:
+ _dbus_assert_not_reached ("invalid transport open result");
+ break;
}
}
@@ -889,8 +895,17 @@ _dbus_transport_try_to_authenticate (DBusTransport *transport)
case DBUS_AUTH_STATE_AUTHENTICATED:
/* leave as maybe_authenticated */
break;
- default:
+
+ case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
+ case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
+ case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
+ case DBUS_AUTH_STATE_NEED_DISCONNECT:
maybe_authenticated = FALSE;
+ break;
+
+ case DBUS_AUTH_STATE_INVALID:
+ default:
+ _dbus_assert_not_reached ("invalid authentication state");
}
}
@@ -1057,7 +1072,7 @@ _dbus_transport_handle_watch (DBusTransport *transport,
if (dbus_watch_get_socket (watch) < 0)
{
- _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
+ _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed");
return TRUE;
}
@@ -1187,7 +1202,9 @@ recover_unused_bytes (DBusTransport *transport)
}
_dbus_message_loader_get_buffer (transport->loader,
- &buffer);
+ &buffer,
+ NULL,
+ NULL);
orig_len = _dbus_string_get_length (buffer);
@@ -1213,19 +1230,25 @@ recover_unused_bytes (DBusTransport *transport)
{
const DBusString *bytes;
DBusString *buffer;
+#ifdef DBUS_ENABLE_VERBOSE_MODE
int orig_len;
+#endif
dbus_bool_t succeeded;
_dbus_message_loader_get_buffer (transport->loader,
- &buffer);
-
+ &buffer,
+ NULL,
+ NULL);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
orig_len = _dbus_string_get_length (buffer);
-
+#endif
+
_dbus_auth_get_unused_bytes (transport->auth,
&bytes);
succeeded = TRUE;
- if (!_dbus_string_copy (bytes, 0, buffer, orig_len))
+ if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
succeeded = FALSE;
_dbus_verbose (" %d unused bytes sent to message loader\n",
@@ -1300,9 +1323,9 @@ _dbus_transport_queue_messages (DBusTransport *transport)
DBusDispatchStatus status;
#if 0
- _dbus_verbose ("_dbus_transport_queue_messages()\n");
+ _dbus_verbose ("enter\n");
#endif
-
+
/* Queue any messages */
while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
{
diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c
index 888a23e9..44a1a78c 100644
--- a/dbus/dbus-userdb-util.c
+++ b/dbus/dbus-userdb-util.c
@@ -29,7 +29,7 @@
#include "dbus-protocol.h"
#include <string.h>
-#if HAVE_SYSTEMD
+#ifdef HAVE_SYSTEMD
#include <systemd/sd-login.h>
#endif
diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c
index 52f927a3..4c42b7dd 100644
--- a/dbus/dbus-userdb.c
+++ b/dbus/dbus-userdb.c
@@ -260,7 +260,7 @@ init_system_db (void)
else
{
/* This really should not happen. */
- _dbus_warn ("Could not get password database information for UID of current process: %s\n",
+ _dbus_warn ("Could not get password database information for UID of current process: %s",
error.message);
dbus_error_free (&error);
return FALSE;
@@ -464,6 +464,16 @@ _dbus_homedir_from_uid (dbus_uid_t uid,
DBusUserDatabase *db;
const DBusUserInfo *info;
+ if (uid == _dbus_getuid () && uid == _dbus_geteuid ())
+ {
+ const char *from_environment;
+
+ from_environment = _dbus_getenv ("HOME");
+
+ if (from_environment != NULL)
+ return _dbus_string_append (homedir, from_environment);
+ }
+
/* FIXME: this can't distinguish ENOMEM from other errors */
if (!_dbus_user_database_lock_system ())
return FALSE;
diff --git a/dbus/dbus-uuidgen.h b/dbus/dbus-uuidgen.h
index 5e4a948c..7003f163 100644
--- a/dbus/dbus-uuidgen.h
+++ b/dbus/dbus-uuidgen.h
@@ -37,9 +37,6 @@ dbus_bool_t dbus_internal_do_not_use_get_uuid (const char *filename,
char **uuid_p,
dbus_bool_t create_if_not_found,
DBusError *error);
-dbus_bool_t dbus_internal_do_not_use_ensure_uuid (const char *filename,
- char **uuid_p,
- DBusError *error);
DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_create_uuid (char **uuid_p,
DBusError *error);
diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c
index 093f1937..98422968 100644
--- a/dbus/dbus-watch.c
+++ b/dbus/dbus-watch.c
@@ -326,8 +326,8 @@ _dbus_watch_list_set_functions (DBusWatchList *watch_list,
link2 = _dbus_list_get_first_link (&watch_list->watches);
while (link2 != link)
{
- DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
- link2);
+ DBusList *next2 = _dbus_list_get_next_link (&watch_list->watches,
+ link2);
#ifdef DBUS_ENABLE_VERBOSE_MODE
DBusWatch *watch2 = link2->data;
@@ -337,7 +337,7 @@ _dbus_watch_list_set_functions (DBusWatchList *watch_list,
(* remove_function) (link2->data, data);
- link2 = next;
+ link2 = next2;
}
return FALSE;
@@ -739,7 +739,7 @@ dbus_watch_handle (DBusWatch *watch,
#ifndef DBUS_DISABLE_CHECKS
if (!_dbus_pollable_is_valid (watch->fd) || watch->flags == 0)
{
- _dbus_warn_check_failed ("Watch is invalid, it should have been removed\n");
+ _dbus_warn_check_failed ("Watch is invalid, it should have been removed");
return TRUE;
}
#endif
diff --git a/dbus/dbus.h b/dbus/dbus.h
index 932ceab3..31aa4d1f 100644
--- a/dbus/dbus.h
+++ b/dbus/dbus.h
@@ -91,8 +91,8 @@
* This manual also contains docs for @ref DBusInternals "D-Bus internals",
* so you can use it to get oriented to the D-Bus source code if you're
* interested in patching the code. You should also read the
- * file HACKING which comes with the source code if you plan to contribute to
- * D-Bus.
+ * file CONTRIBUTING.md which comes with the source code if you plan to
+ * contribute to D-Bus.
*
* As you read the code, you can identify internal D-Bus functions
* because they start with an underscore ('_') character. Also, any
diff --git a/dbus/versioninfo.rc.in b/dbus/versioninfo.rc.in
index b745b39a..4af2beee 100644
--- a/dbus/versioninfo.rc.in
+++ b/dbus/versioninfo.rc.in
@@ -12,41 +12,43 @@
/* This file is processed by configure to create versioninfo.rc */
-#line __LINE__ "versioninfo.rc.in"
-
-#include <afxres.h>
-
+#include <windows.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION @BUILD_FILEVERSION@
PRODUCTVERSION @BUILD_FILEVERSION@
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
- FILEFLAGS 0x21L
+ FILEFLAGS VS_FF_DEBUG
#else
- FILEFLAGS 0x20L
+ FILEFLAGS 0x0L
#endif
- FILEOS 0x40004L
- FILETYPE 0x1L
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
- BLOCK "040904b0"
+ /* string need to match concated hex values in 'VarFileInfo' block */
+ BLOCK "040904e4"
BEGIN
- VALUE "Comments", "Provided under the terms of the GNU Lesser General Public License.\0"
- VALUE "CompanyName", "FreeDesktop.org\0"
+ VALUE "Comments", "Provided under the terms of the GNU Lesser General Public License >= 2.0 or Academic Free License version 2.1\0"
+ VALUE "CompanyName", "freedesktop.org\0"
VALUE "FileDescription", "dbus - FreeDesktop message bus system\0"
VALUE "FileVersion", "@DBUS_VERSION@\0"
- VALUE "InternalName", "dbus\0"
- VALUE "LegalCopyright", "Copyright 2009 FreeDesktop.org\0"
+ VALUE "InternalName", "libdbus-1-3\0"
+ VALUE "LegalCopyright", "Copyright 1994-2017 dbus contributors, see dbus source code for details\0"
VALUE "LegalTrademarks", "\0"
- VALUE "OriginalFilename", "dbus-1.dll\0"
- VALUE "PrivateBuild", "\0"
+ VALUE "OriginalFilename", "libdbus-1-3.dll\0"
VALUE "ProductName", "dbus\0"
VALUE "ProductVersion", "@DBUS_VERSION@\0"
VALUE "SpecialBuild", "@BUILD_TIMESTAMP@\0"
END
END
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* supports English language (0x409) in the Windows ANSI codepage (1252). */
+ VALUE "Translation", 0x409, 1252
+ END
END
diff --git a/doc/.gitignore b/doc/.gitignore
index e1ccbc8d..6bc82863 100644
--- a/doc/.gitignore
+++ b/doc/.gitignore
@@ -10,6 +10,7 @@ Makefile.in
*.o
api
dbus.devhelp
+/dbus.devhelp2
dbus-specification.html
dbus-test-plan.html
dbus-tutorial.html
@@ -19,6 +20,7 @@ dbus-docs.tar.gz
doxygen.stamp
dbus-api-design.page
dbus-api-design.html
+/highlight.pack.js
jquery.js
jquery.syntax.brush.html.js
jquery.syntax.core.js
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 8bc85c53..97dfa9a6 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -20,7 +20,8 @@ endif
MAN_HTML_FILES = $(patsubst %.1,%.1.html,$(man_pages))
-DTDS = \
+dtddir = $(datadir)/xml/dbus-1
+dist_dtd_DATA = \
busconfig.dtd \
introspect.dtd
@@ -34,8 +35,7 @@ STATIC_DOCS = \
dbus-tutorial.xml \
dbus-api-design.duck \
dcop-howto.txt \
- introspect.xsl \
- $(DTDS)
+ introspect.xsl
EXTRA_DIST = \
file-boilerplate.c \
@@ -57,6 +57,7 @@ STATIC_HTML = \
YELP_STATIC_HTML = \
yelp.js \
C.css \
+ highlight.pack.js \
jquery.js \
jquery.syntax.js \
jquery.syntax.brush.html.js \
@@ -97,14 +98,14 @@ doxygen.stamp: $(wildcard $(top_srcdir)/dbus/*.[ch])
@touch $@
if DBUS_HAVE_XSLTPROC
-html_DATA += dbus.devhelp
+html_DATA += dbus.devhelp2
-dbus.devhelp: $(srcdir)/doxygen_to_devhelp.xsl doxygen.stamp
+dbus.devhelp2: $(srcdir)/doxygen_to_devhelp.xsl doxygen.stamp
$(XSLTPROC) -o $@ $< api/xml/index.xml
endif
if DBUS_DUCKTYPE_DOCS_ENABLED
-html_DATA += $(YELP_HTML) $(YELP_STATIC_HTML)
+html_DATA += $(YELP_HTML)
%.page: %.duck
$(DUCKTYPE) -o $@ $<
@@ -118,12 +119,21 @@ endif
install-data-local:: doxygen.stamp
$(MKDIR_P) $(DESTDIR)$(apidir)
$(INSTALL_DATA) api/html/* $(DESTDIR)$(apidir)
+if DBUS_DUCKTYPE_DOCS_ENABLED
+ $(AM_V_at)for x in $(YELP_STATIC_HTML); do \
+ if test -e "$$x"; then \
+ $(INSTALL_DATA) "$$x" $(DESTDIR)$(htmldir); \
+ fi; \
+ done
+endif
uninstall-local::
rm -f $(DESTDIR)$(apidir)/*.html
rm -f $(DESTDIR)$(apidir)/*.png
rm -f $(DESTDIR)$(apidir)/*.css
rm -f $(DESTDIR)$(apidir)/*.js
+ rm -f $(DESTDIR)$(htmldir)/*.css
+ rm -f $(DESTDIR)$(htmldir)/*.js
rm -f $(DESTDIR)$(htmldir)/*.html
rm -f $(DESTDIR)$(docdir)/*.txt
rm -f $(DESTDIR)$(htmldir)/*.png
@@ -135,21 +145,26 @@ endif
if DBUS_CAN_UPLOAD_DOCS
BONUS_FILES = \
$(top_srcdir)/README \
- $(top_srcdir)/HACKING \
+ $(top_srcdir)/CONTRIBUTING.md \
$(top_srcdir)/AUTHORS \
$(top_srcdir)/NEWS \
$(top_srcdir)/COPYING \
$(top_srcdir)/ChangeLog
-dbus-docs: $(STATIC_DOCS) $(MAN_XML_FILES) $(dist_doc_DATA) $(dist_html_DATA) $(MAN_HTML_FILES) $(BONUS_FILES) doxygen.stamp $(XMLTO_HTML) $(YELP_HTML) $(YELP_STATIC_HTML)
+dbus-docs: $(STATIC_DOCS) $(dist_dtd_DATA) $(MAN_XML_FILES) $(dist_doc_DATA) $(dist_html_DATA) $(MAN_HTML_FILES) $(BONUS_FILES) doxygen.stamp $(XMLTO_HTML) $(YELP_HTML)
$(AM_V_at)rm -rf $@ $@.tmp
$(AM_V_GEN)$(MKDIR_P) $@.tmp/api
$(AM_V_at)cd $(srcdir) && cp $(STATIC_DOCS) @abs_builddir@/$@.tmp
+ $(AM_V_at)cd $(srcdir) && cp $(dist_dtd_DATA) @abs_builddir@/$@.tmp
$(AM_V_at)cd $(srcdir) && cp $(dist_doc_DATA) @abs_builddir@/$@.tmp
$(AM_V_at)cd $(srcdir) && cp $(STATIC_HTML) @abs_builddir@/$@.tmp
$(AM_V_at)cp $(XMLTO_HTML) @abs_builddir@/$@.tmp
$(AM_V_at)cp $(YELP_HTML) @abs_builddir@/$@.tmp
- $(AM_V_at)cp $(YELP_STATIC_HTML) @abs_builddir@/$@.tmp
+ $(AM_V_at)for x in $(YELP_STATIC_HTML); do \
+ if test -e "$$x"; then \
+ cp "$$x" @abs_builddir@/$@.tmp; \
+ fi; \
+ done
$(AM_V_at)cp $(MAN_HTML_FILES) @abs_builddir@/$@.tmp
$(AM_V_at)cp $(MAN_XML_FILES) @abs_builddir@/$@.tmp
$(AM_V_at)cp $(BONUS_FILES) @abs_builddir@/$@.tmp
@@ -169,12 +184,11 @@ maintainer-upload-docs: dbus-docs.tar.gz dbus-docs
scp dbus-docs.tar.gz $(DOC_SERVER):$(DOC_WWW_DIR)/
rsync -rpvzP --chmod=Dg+s,ug+rwX,o=rX \
dbus-docs/ $(DOC_SERVER):$(DOC_WWW_DIR)/doc/
- cd $(srcdir) && scp -p $(DTDS) $(SPECIFICATION_SERVER):$(SPECIFICATION_PATH)/
+ cd $(srcdir) && scp -p $(dist_dtd_DATA) $(SPECIFICATION_SERVER):$(SPECIFICATION_PATH)/
else
maintainer-upload-docs:
@echo "Can't upload documentation! Re-run configure with"
@echo " --enable-doxygen-docs --enable-xml-docs --enable-ducktype-docs"
- @echo "and ensure that man2html is installed."
@false
endif
diff --git a/doc/dbus-api-design.duck b/doc/dbus-api-design.duck
index be3ea9fd..82a36877 100644
--- a/doc/dbus-api-design.duck
+++ b/doc/dbus-api-design.duck
@@ -60,12 +60,12 @@ $link[>>http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-fo
specification), and is supported by tools such as $cmd(gdbus-codegen).
Interface files for public API should be installed to
-$code($var($$(datadir$))/dbus-1/interfaces) so that other services can load
+$code($var($$(datadir))/dbus-1/interfaces) so that other services can load
them. Private APIs should not be installed. There should be one file installed
per D-Bus interface, named after the interface, containing a single top-level
$code(<node>) element with a single $code(<interface>) beneath it. For example,
interface $code(com.example.MyService1.Manager) would be described by file
-$file($var($$(datadir$))/dbus-1/interfaces/com.example.MyService1.Manager.xml):
+$file($var($$(datadir))/dbus-1/interfaces/com.example.MyService1.Manager.xml):
[listing]
[title]
@@ -189,16 +189,16 @@ convenience APIs and designing APIs which operate on large data sets in a single
call, rather than requiring as many calls as elements in the data set.
Consider an address book API, $code(com.example.MyService1.AddressBook). It
-might have an $code(AddContact(ss$) → (u$)) method to add a contact (taking name
+might have an $code(AddContact(ss) → (u)) method to add a contact (taking name
and e-mail address parameters and returning a unique contact ID), and a
-$code(RemoveContact(u$)) method to remove one by ID. In the normal case of
+$code(RemoveContact(u)) method to remove one by ID. In the normal case of
operating on single contacts in the address book, these calls are optimal.
However, if the user wants to import a list of contacts, or delete multiple
contacts simultaneously, one call has to be made per contact — this could take
a long time for large contact lists.
Instead of the $code(AddContact) and $code(RemoveContact) methods, the interface
-could have an $code(UpdateContacts(a(ss$)au$) → (au$)) method, which takes an array
+could have an $code(UpdateContacts(a(ss)au) → (au)) method, which takes an array
of structs containing the new contacts’ details, and an array of IDs of the
contacts to delete, and returns an array of IDs for the new contacts. This
reduces the number of round trips needed to one.
@@ -479,18 +479,18 @@ $code(Get$var(PropertyName)) and $code(Set$var(PropertyName)) methods.
For example, consider an object implementing an interface
$code(com.example.MyService1.SomeInterface) with methods:
[list]
- * $code(GetName($) → (s$))
- * $code(SetName(s$) → ($))
- * $code(GetStatus($) → (u$))
- * $code(RunOperation(ss$) → (u$))
+ * $code(GetName() → (s))
+ * $code(SetName(s) → ())
+ * $code(GetStatus() → (u))
+ * $code(RunOperation(ss) → (u))
and signals:
[list]
- * $code(NameChanged(u$))
- * $code(StatusChanged(u$))
+ * $code(NameChanged(u))
+ * $code(StatusChanged(u))
The interface could be cut down to a single method:
[list]
- * $code(RunOperation(ss$) → (u$))
+ * $code(RunOperation(ss) → (u))
The object could then implement the $code(org.freedesktop.DBus.Properties)
interface and define properties:
[list]
@@ -522,11 +522,11 @@ not expose the entire file system hierarchy using $code(ObjectManager).
For example, consider an object implementing an interface
$code(com.example.MyService1.AddressBookManager) with methods:
[list]
- * $code(GetAddressBooks($) → (ao$))
+ * $code(GetAddressBooks() → (ao))
and signals:
[list]
- * $code(AddressBookAdded(o$))
- * $code(AddressBookRemoved(o$))
+ * $code(AddressBookAdded(o))
+ * $code(AddressBookRemoved(o))
If the manager object is at path
$code(/com/example/MyService1/AddressBookManager), each address book is a
@@ -802,8 +802,8 @@ specification)).
Service files must be named after the service’s well-known name, for example
file $file(com.example.MyService1.service) for well-known name
$code(com.example.MyService1). Files must be installed in
-$file($var($$(datadir$))/dbus-1/services) for the session bus and
-$file($var($$(datadir$))/dbus-1/system-services) for the system bus. Note, however,
+$file($var($$(datadir))/dbus-1/services) for the session bus and
+$file($var($$(datadir))/dbus-1/system-services) for the system bus. Note, however,
that services on the system bus almost always need a
$link[>#security-policies](security policy) as well.
@@ -826,8 +826,10 @@ however there are some steps which you can take when designing an API to ease
security policy implementation.
D-Bus security policies are written as XML files in
-$file($var($$(sysconfdir$)/dbus-1/system.d)) and
-$file($var($$(sysconfdir$)/dbus-1/session.d)) and use an allow/deny model, where
+$file($var($$(datadir)/dbus-1/system.d)),
+$file($var($$(datadir)/dbus-1/session.d)),
+$file($var($$(sysconfdir)/dbus-1/system.d)) and
+$file($var($$(sysconfdir)/dbus-1/session.d)) and use an allow/deny model, where
each message (method call, signal emission, etc.) can be allowed or denied
according to the sum of all policy rules which match it. Each $code(<allow>) or
$code(<deny>) rule in the policy should have the $code(own),
@@ -836,7 +838,10 @@ $code(send_destination) or $code(receive_sender) attribute set.
When designing an API, bear in mind the need to write and install such a
security policy, and consider splitting up methods or providing more restricted
versions which accept constrained parameters, so that they can be exposed with
-less restrictive security policies if needed by less trusted clients.
+less restrictive security policies if needed by less trusted clients. Since
+dbus-daemon 1.10, security policies should be installed to
+$file($var($$(datadir))) rather than $(file($var($$(sysconfdir))); the latter
+is intended for system administators.
Secondly, the default D-Bus security policy for the system bus is restrictive
enough to allow sensitive data, such as passwords, to be safely sent over the
diff --git a/doc/dbus-daemon.1.xml.in b/doc/dbus-daemon.1.xml.in
index df67a907..960da080 100644
--- a/doc/dbus-daemon.1.xml.in
+++ b/doc/dbus-daemon.1.xml.in
@@ -29,6 +29,9 @@
<arg choice='opt'><arg choice='plain'>--print-address </arg><arg choice='opt'><replaceable>=DESCRIPTOR</replaceable></arg></arg>
<arg choice='opt'><arg choice='plain'>--print-pid </arg><arg choice='opt'><replaceable>=DESCRIPTOR</replaceable></arg></arg>
<arg choice='opt'>--fork </arg>
+ <arg choice='opt'>--nosyslog </arg>
+ <arg choice='opt'>--syslog </arg>
+ <arg choice='opt'>--syslog-only </arg>
<sbr/>
</cmdsynopsis>
</refsynopsisdiv>
@@ -145,8 +148,10 @@ bus.</para>
<varlistentry>
<term><option>--address[=ADDRESS]</option></term>
<listitem>
-<para>Set the address to listen on. This option overrides the address
-configured in the configuration file.</para>
+ <para>Set the address to listen on. This option overrides the address
+ configured in the configuration file via the
+ <literal>&lt;listen&gt;</literal> directive.
+ See the documentation of that directive for more details.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -164,6 +169,36 @@ files.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><option>--syslog</option></term>
+ <listitem>
+ <para>Force the message bus to use the system log for messages,
+ in addition to writing to standard error, even if the configuration
+ file does not specify that it should. On Unix, this uses
+ the syslog; on Windows, this uses OutputDebugString().</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--syslog-only</option></term>
+ <listitem>
+ <para>Force the message bus to use the system log for messages,
+ and <emphasis>not</emphasis> duplicate them to standard error.
+ On Unix, this uses the syslog; on Windows, this uses
+ OutputDebugString().</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--nosyslog</option></term>
+ <listitem>
+ <para>Force the message bus to use only standard error for messages,
+ even if the configuration file specifies that it should use
+ the system log.</para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
@@ -325,7 +360,9 @@ This may be useful to avoid affecting the behavior of child processes.</para>
</itemizedlist>
-<para>If present, the bus daemon will log to syslog.</para>
+<para>If present, the bus daemon will log to syslog. The
+ --syslog, --syslog-only and --nosyslog command-line options take precedence
+ over this setting.</para>
<itemizedlist remap='TP'>
@@ -349,6 +386,13 @@ mechanism will be authorized to connect. This option has no practical
effect unless the ANONYMOUS mechanism has also been enabled using the
<emphasis remap='I'>&lt;auth&gt;</emphasis> element, described below.</para>
+<para>Using this directive in the configuration of the well-known
+ system bus or the well-known session bus will make that bus insecure
+ and should never be done. Similarly, on custom bus types, using this
+ directive will usually make the custom bus insecure, unless its
+ configuration has been specifically designed to prevent anonymous
+ users from causing damage or escalating privileges.</para>
+
<itemizedlist remap='TP'>
<listitem><para><emphasis remap='I'>&lt;listen&gt;</emphasis></para></listitem>
@@ -360,6 +404,47 @@ effect unless the ANONYMOUS mechanism has also been enabled using the
address is in the standard D-Bus format that contains
a transport name plus possible parameters/options.</para>
+<para>On platforms other than Windows, <literal>unix</literal>-based
+ transports (<literal>unix</literal>, <literal>systemd</literal>,
+ <literal>launchd</literal>) are the default for both the well-known
+ system bus and the well-known session bus, and are strongly
+ recommended.</para>
+
+<para>
+ On Windows, <literal>unix</literal>-based transports are not available,
+ so TCP-based transports must be used.
+ Similar to remote X11, the <literal>tcp</literal> and
+ <literal>nonce-tcp</literal> transports have no integrity or
+ confidentiality protection, so they should normally only be
+ used across the local loopback interface, for example using an
+ address like <literal>tcp:host=127.0.0.1</literal> or
+ <literal>nonce-tcp:host=localhost</literal>. In particular,
+ configuring the well-known system bus or the well-known session
+ bus to listen on a non-loopback TCP address is insecure.
+</para>
+<para>
+ Developers are sometimes tempted to use remote TCP as a debugging
+ tool. However, if this functionality is left enabled in finished
+ products, the result will be dangerously insecure. Instead of
+ using remote TCP, developers should <ulink
+ url="https://lists.freedesktop.org/archives/dbus/2018-April/017447.html"
+ >relay connections via Secure Shell or a similar protocol</ulink>.
+ <!-- TODO: Ideally someone would write a more formal guide to
+ remote D-Bus debugging, and we could link to that instead -->
+</para>
+<para>
+ Remote TCP connections were historically sometimes used to share
+ a single session bus between login sessions of the same user on
+ different machines within a trusted local area network, in
+ conjunction with unencrypted remote X11, a NFS-shared home
+ directory and NIS (YP) authentication. This is insecure against
+ an attacker on the same LAN and should be considered strongly
+ deprecated; more specifically, it is insecure in the same ways
+ and for the same reasons as unencrypted remote X11 and NFSv2/NFSv3.
+ The D-Bus maintainers
+ recommend using a separate session bus per (user, machine) pair,
+ only accessible from within that machine.
+</para>
<para>Example: &lt;listen&gt;unix:path=/tmp/foo&lt;/listen&gt;</para>
@@ -419,6 +504,10 @@ exist, then all known mechanisms are allowed. If there are multiple
&lt;auth&gt; elements, all the listed mechanisms are allowed. The order in
which mechanisms are listed is not meaningful.</para>
+<para>On non-Windows operating systems, allowing only the
+ <literal>EXTERNAL</literal> authentication
+ mechanism is strongly recommended. This is the default for the
+ well-known system bus and for the well-known session bus.</para>
<para>Example: &lt;auth&gt;EXTERNAL&lt;/auth&gt;</para>
@@ -432,15 +521,22 @@ which mechanisms are listed is not meaningful.</para>
</itemizedlist>
-<para>Adds a directory to scan for .service files. Directories are
-scanned starting with the first to appear in the config file
-(the first .service file found that provides a particular
-service will be used).</para>
-
-
-<para>Service files tell the bus how to automatically start a program.
-They are primarily used with the per-user-session bus,
-not the systemwide bus.</para>
+<para>
+ Adds a directory to search for .service files, which tell the
+ dbus-daemon how to start a program to provide a particular well-known
+ bus name. See the D-Bus Specification for more details about the
+ contents of .service files.
+</para>
+
+<para>
+ If a particular service is found in more than one &lt;servicedir&gt;,
+ the first directory listed in the configuration file takes precedence.
+ If two service files providing the same well-known bus name are found
+ in the same directory, it is arbitrary which one will be chosen
+ (this can only happen if at least one of the service files does not
+ have the recommended name, which is its well-known bus name followed
+ by ".service").
+</para>
<itemizedlist remap='TP'>
@@ -449,17 +545,128 @@ not the systemwide bus.</para>
</itemizedlist>
-<para>&lt;standard_session_servicedirs/&gt; is equivalent to specifying a series
-of &lt;servicedir/&gt; elements for each of the data directories in the "XDG
-Base Directory Specification" with the subdirectory "dbus-1/services",
-so for example "/usr/share/dbus-1/services" would be among the
-directories searched.</para>
-
+<para>
+ &lt;standard_session_servicedirs/&gt; requests a standard set of
+ session service directories. Its effect is similar to specifying a series
+ of &lt;servicedir/&gt; elements for each of the data directories,
+ in the order given here.
+ It is not exactly equivalent, because there is currently no way
+ to disable directory monitoring or enforce strict service file naming
+ for a &lt;servicedir/&gt;.
+</para>
+
+<para>
+ As with &lt;servicedir/&gt; elements, if a particular service is found
+ in more than one service directory, the first directory takes precedence.
+ If two service files providing the same well-known bus name are found
+ in the same directory, it is arbitrary which one will be chosen
+ (this can only happen if at least one of the service files does not
+ have the recommended name, which is its well-known bus name followed
+ by ".service").
+</para>
+
+<para>
+ On Unix, the standard session service directories are:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>$XDG_RUNTIME_DIR</emphasis>/dbus-1/services,
+ if XDG_RUNTIME_DIR is set (see the XDG Base Directory
+ Specification for details of XDG_RUNTIME_DIR):
+ this location is suitable for transient services created at runtime
+ by systemd generators (see
+ <citerefentry>
+ <refentrytitle>systemd.generator</refentrytitle>
+ <manvolnum>7</manvolnum>
+ </citerefentry>),
+ session managers or other session infrastructure.
+ It is an extension provided by the reference implementation
+ of dbus-daemon, and is not standardized in the D-Bus Specification.
+ </para>
+ <para>
+ Unlike the other standard session service directories, this directory
+ enforces strict naming for the service files: the filename must be
+ exactly the well-known bus name of the service, followed by
+ ".service".
+ </para>
+ <para>
+ Also unlike the other standard session service directories, this
+ directory is never monitored with
+ <citerefentry>
+ <refentrytitle>inotify</refentrytitle>
+ <manvolnum>7</manvolnum>
+ </citerefentry>
+ or similar APIs. Programs that create service files in this directory
+ while a dbus-daemon is running are expected to call the dbus-daemon's
+ ReloadConfig() method after they have made changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>$XDG_DATA_HOME</emphasis>/dbus-1/services,
+ where XDG_DATA_HOME defaults to ~/.local/share
+ (see the XDG Base Directory Specification): this location is
+ specified by the D-Bus Specification, and is suitable for per-user,
+ locally-installed software.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>directory</emphasis>/dbus-1/services for each
+ directory in XDG_DATA_DIRS, where XDG_DATA_DIRS defaults to
+ /usr/local/share:/usr/share
+ (see the XDG Base Directory Specification): these locations are
+ specified by the D-Bus Specification. The defaults are suitable
+ for software installed locally by a system administrator
+ (/usr/local/share) or for software installed from operating system
+ packages (/usr/share). Per-user or system-wide configuration that
+ sets the XDG_DATA_DIRS environment variable can extend this search
+ path to cover installations in other locations, for example
+ ~/.local/share/flatpak/exports/share/ and
+ /var/lib/flatpak/exports/share/ when
+ <citerefentry>
+ <refentrytitle>flatpak</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ is used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>${datadir}</emphasis>/dbus-1/services
+ for the <emphasis>${datadir}</emphasis> that was specified when
+ dbus was compiled, typically /usr/share: this location is an
+ extension provided by the reference dbus-daemon implementation,
+ and is suitable for software stacks installed alongside dbus-daemon.
+ </para>
+ </listitem>
+ </itemizedlist>
+</para>
<para>The "XDG Base Directory Specification" can be found at
<ulink url='http://freedesktop.org/wiki/Standards/basedir-spec'>http://freedesktop.org/wiki/Standards/basedir-spec</ulink> if it hasn't moved,
otherwise try your favorite search engine.</para>
+<para>
+ On Windows, the standard session service directories are:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>%CommonProgramFiles%</emphasis>/dbus-1/services
+ if %CommonProgramFiles% is set: this location is suitable for
+ system-wide installed software packages
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A share/dbus-1/services directory found in the same
+ directory hierarchy (prefix) as the dbus-daemon: this location
+ is suitable for software stacks installed alongside dbus-daemon
+ </para>
+ </listitem>
+ </itemizedlist>
+</para>
+
<para>The &lt;standard_session_servicedirs/&gt; option is only relevant to the
per-user-session bus daemon defined in
@@ -474,9 +681,53 @@ configuration file would probably be nonsense.</para>
</itemizedlist>
<para>&lt;standard_system_servicedirs/&gt; specifies the standard system-wide
-activation directories that should be searched for service files.
-This option defaults to @EXPANDED_DATADIR@/dbus-1/system-services.</para>
-
+ activation directories that should be searched for service files.
+ As with session services, the first directory listed has highest
+ precedence.</para>
+
+<para>
+ On Unix, the standard session service directories are:
+ <itemizedlist>
+ <listitem>
+ <para>
+ /usr/local/share/dbus-1/system-services: this location is
+ specified by the D-Bus Specification, and is suitable for
+ software installed locally by the system administrator
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ /usr/share/dbus-1/system-services: this location is
+ specified by the D-Bus Specification, and is suitable for
+ software installed by operating system packages
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>${datadir}</emphasis>/dbus-1/system-services
+ for the <emphasis>${datadir}</emphasis> that was specified when
+ dbus was compiled, typically /usr/share: this location is an
+ extension provided by the reference dbus-daemon implementation,
+ and is suitable for software stacks installed alongside dbus-daemon
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ /lib/dbus-1/system-services: this location is
+ specified by the D-Bus Specification, and was intended for
+ software installed by operating system packages and used during
+ early boot (but it should be considered deprecated, because
+ the reference dbus-daemon is not designed to be available during
+ early boot)
+ </para>
+ </listitem>
+ </itemizedlist>
+</para>
+
+<para>
+ On Windows, there is no standard system bus, so there are no standard
+ system bus directories either.
+</para>
<para>The &lt;standard_system_servicedirs/&gt; option is only relevant to the
per-system bus daemon defined in
@@ -582,9 +833,13 @@ they are analogous to a firewall in that they allow expected traffic
and prevent unexpected traffic.</para>
-<para>Currently, the system bus has a default-deny policy for sending method calls
-and owning bus names. Everything else, in particular reply messages, receive
-checks, and signals has a default allow policy.</para>
+<para>
+ Currently, the system bus has a default-deny policy for sending method calls
+ and owning bus names, and a default-allow policy for receiving messages,
+ sending signals, and sending a single success or error reply for each
+ method call that does not have the <literal>NO_REPLY</literal> flag.
+ Sending more than the expected number of replies is not allowed.
+</para>
<para>In general, it is best to keep system services as small, targeted programs which
@@ -638,29 +893,30 @@ statements, and works just like &lt;deny&gt; but with the inverse meaning.</para
<para>The possible attributes of these elements are:</para>
<literallayout remap='.nf'>
- send_interface="interface_name"
- send_member="method_or_signal_name"
- send_error="error_name"
- send_destination="name"
- send_type="method_call" | "method_return" | "signal" | "error"
- send_path="/path/name"
-
- receive_interface="interface_name"
- receive_member="method_or_signal_name"
- receive_error="error_name"
- receive_sender="name"
- receive_type="method_call" | "method_return" | "signal" | "error"
- receive_path="/path/name"
+ send_interface="interface_name" | "*"
+ send_member="method_or_signal_name" | "*"
+ send_error="error_name" | "*"
+ send_broadcast="true" | "false"
+ send_destination="name" | "*"
+ send_type="method_call" | "method_return" | "signal" | "error" | "*"
+ send_path="/path/name" | "*"
+
+ receive_interface="interface_name" | "*"
+ receive_member="method_or_signal_name" | "*"
+ receive_error="error_name" | "*"
+ receive_sender="name" | "*"
+ receive_type="method_call" | "method_return" | "signal" | "error" | "*"
+ receive_path="/path/name" | "*"
send_requested_reply="true" | "false"
receive_requested_reply="true" | "false"
eavesdrop="true" | "false"
- own="name"
+ own="name" | "*"
own_prefix="name"
- user="username"
- group="groupname"
+ user="username" | "*"
+ group="groupname" | "*"
</literallayout> <!-- .fi -->
@@ -678,14 +934,68 @@ statements, and works just like &lt;deny&gt; but with the inverse meaning.</para
particular action. If it matches, the action is denied (unless later
rules in the config file allow it).</para>
+<para>
+ Rules with one or more of the <literal>send_</literal>* family of attributes
+ are checked in order when a connection attempts to send a message. The last
+ rule that matches the message determines whether it may be sent.
+ The well-known session bus normally allows sending any message.
+ The well-known system bus normally allows sending any signal, selected
+ method calls to the <command>dbus-daemon</command>, and exactly one
+ reply to each previously-sent method call (either success or an error).
+ Either of these can be overridden by configuration; on the system bus,
+ services that will receive method calls must install configuration that
+ allows them to do so, usually via rules of the form
+ <literal>&lt;policy context="default"&gt;&lt;allow send_destination="&hellip;"/&gt;&lt;policy&gt;</literal>.
+</para>
+
+<para>
+ Rules with one or more of the <literal>receive_</literal>* family of
+ attributes, or with the <literal>eavesdrop</literal> attribute and no others,
+ are checked for each recipient of a message (there might be more than one
+ recipient if the message is a broadcast or a connection is eavesdropping).
+ The last rule that matches the message determines whether it may be received.
+ The well-known session bus normally allows receiving any message, including
+ eavesdropping. The well-known system bus normally allows receiving any
+ message that was not eavesdropped (any unicast message addressed to the
+ recipient, and any broadcast message).
+</para>
+
+<para>
+ The <literal>eavesdrop</literal>, <literal>min_fds</literal> and
+ <literal>max_fds</literal> attributes are modifiers that can be applied
+ to either <literal>send_</literal>* or <literal>receive_</literal>*
+ rules, and are documented below.
+</para>
+
<para>send_destination and receive_sender rules mean that messages may not be
sent to or received from the *owner* of the given name, not that
they may not be sent *to that name*. That is, if a connection
owns services A, B, C, and sending to A is denied, sending to B or C
-will not work either.</para>
-
-<para>The other send_* and receive_* attributes are purely textual/by-value
-matches against the given field in the message header.</para>
+will not work either. As a special case,
+<literal>send_destination="*"</literal> matches any message
+(whether it has a destination specified or not), and
+<literal>receive_sender="*"</literal> similarly matches any message.</para>
+
+<para>
+ Rules with <literal>send_broadcast="true"</literal> match signal messages
+ with no destination (broadcasts). Rules with
+ <literal>send_broadcast="false"</literal> are the inverse: they match any
+ unicast destination (unicast signals, together with all method calls, replies
+ and errors) but do not match messages with no destination (broadcasts). This
+ is not the same as <literal>send_destination="*"</literal>, which matches any
+ sent message, regardless of whether it has a destination or not.
+</para>
+
+<para>
+ The other <literal>send_</literal>* and <literal>receive_</literal>*
+ attributes are purely textual/by-value matches against the given field in
+ the message header, except that for the attributes where it is allowed,
+ <literal>*</literal> matches any message (whether it has the relevant
+ header field or not). For example, <literal>send_interface="*"</literal>
+ matches any sent message, even if it does not contain an interface header
+ field. More complex glob matching such as <literal>foo.bar.*</literal> is
+ not allowed.
+</para>
<para>"Eavesdropping" occurs when an application receives a message that
was explicitly addressed to a name the application does not own, or
@@ -720,16 +1030,44 @@ the rule matches only when the reply was not
requested. [send|receive]_requested_reply="true" indicates that the rule applies
always, regardless of pending reply state.</para>
-
-<para>user and group denials mean that the given user or group may
-not connect to the message bus.</para>
-
-
-<para>For "name", "username", "groupname", etc.
-the character "*" can be substituted, meaning "any." Complex globs
-like "foo.bar.*" aren't allowed for now because they'd be work to
-implement and maybe encourage sloppy security anyway.</para>
-
+<para>
+ The <literal>min_fds</literal> and <literal>max_fds</literal> attributes
+ modify either <literal>send_</literal>* or <literal>receive_</literal>*
+ rules. A rule with the <literal>min_fds</literal> attribute only matches
+ messages if they have at least that many Unix file descriptors attached.
+ Conversely, a rule with the <literal>max_fds</literal> attribute only
+ matches messages if they have no more than that many file descriptors
+ attached. In practice, rules with these attributes will most commonly
+ take the form
+ <literal>&lt;allow send_destination="&hellip;" max_fds="0"/&gt;</literal>,
+ <literal>&lt;deny send_destination="&hellip;" min_fds="1"/&gt;</literal> or
+ <literal>&lt;deny receive_sender="*" min_fds="1"/&gt;</literal>.
+</para>
+
+<para>
+ Rules with the <literal>user</literal> or <literal>group</literal>
+ attribute are checked when a new connection to the message bus is
+ established, and control whether the connection can continue.
+ Each of these attributes cannot be combined with any other
+ attribute. As a special case, both <literal>user="*"</literal> and
+ <literal>group="*"</literal> match any connection. If there are
+ no rules of this form, the default is to allow connections from the same
+ user ID that owns the <command>dbus-daemon</command> process. The well-known
+ session bus normally uses that default behaviour, while the well-known
+ system bus normally allows any connection.
+</para>
+
+<para>
+ Rules with the <literal>own</literal> or <literal>own_prefix</literal>
+ attribute are checked when a connection attempts to own a well-known bus
+ names. As a special case, <literal>own="*"</literal> matches any well-known
+ bus name. The well-known session bus normally allows any connection to
+ own any name, while the well-known system bus normally does not allow any
+ connection to own any name, except where allowed by further configuration.
+ System services that will own a name must install configuration that allows
+ them to do so, usually via rules of the form
+ <literal>&lt;policy user="some-system-user"&gt;&lt;allow own="&hellip;"/&gt;&lt;/policy&gt;</literal>.
+</para>
<para>&lt;allow own_prefix="a.b"/&gt; allows you to own the name "a.b" or any
name whose first dot-separated elements are "a.b": in particular,
diff --git a/doc/dbus-launch.1.xml.in b/doc/dbus-launch.1.xml.in
index 5135d9ca..2fcea03f 100644
--- a/doc/dbus-launch.1.xml.in
+++ b/doc/dbus-launch.1.xml.in
@@ -29,6 +29,7 @@
<arg choice='opt'>--binary-syntax </arg>
<arg choice='opt'>--close-stderr </arg>
<arg choice='opt'>--exit-with-session </arg>
+ <arg choice='opt'>--exit-with-x11 </arg>
<arg choice='opt'>--autolaunch=<replaceable>MACHINEID</replaceable></arg>
<arg choice='opt'>--config-file=<replaceable>FILENAME</replaceable></arg>
<arg choice='opt'><replaceable>PROGRAM</replaceable></arg>
@@ -216,16 +217,35 @@ the --session argument. See the man page for dbus-daemon</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><option>--exit-with-session</option></term>
- <listitem>
-<para>If this option is provided, a persistent "babysitter" process will be
-created that watches stdin for HUP and tries to connect to the X
-server. If this process gets a HUP on stdin or loses its X connection,
-it kills the message bus daemon.</para>
+ <term><option>--exit-with-x11</option></term>
+ <listitem>
+ <para>If this option is provided, a persistent "babysitter" process
+ will be created, and will connect to the X server. If it cannot
+ do so, launching fails. If the "babysitter" process loses its
+ X connection, it kills the message bus daemon, disconnecting
+ all of its clients (which should exit in response). This avoids
+ having leftover daemon processes from a user X session, after
+ the X session has ended.</para>
+ </listitem>
+ </varlistentry>
- </listitem>
+ <varlistentry>
+ <term><option>--exit-with-session</option></term>
+ <listitem>
+ <para>
+ If this option is provided, a persistent "babysitter" process will
+ be created, as if for --exit-with-x11. If it cannot connect to
+ the X server, it will monitor the terminal from which dbus-launch
+ was started instead, and if it gets a HUP on stdin, the message
+ bus daemon will be killed. This option is not recommended, since
+ it will consume input from the terminal where it was started;
+ it is mainly provided for backwards compatibility.
+ </para>
+ </listitem>
</varlistentry>
+
<varlistentry>
<term><option>--autolaunch=MACHINEID</option></term>
<listitem>
diff --git a/doc/dbus-send.1.xml.in b/doc/dbus-send.1.xml.in
index 67b6dfd2..271435ca 100644
--- a/doc/dbus-send.1.xml.in
+++ b/doc/dbus-send.1.xml.in
@@ -65,7 +65,7 @@ may include containers (arrays, dicts, and variants) as described below.</para>
&lt;array&gt; ::= array:&lt;type&gt;:&lt;value&gt;[,&lt;value&gt;...]
&lt;dict&gt; ::= dict:&lt;type&gt;:&lt;type&gt;:&lt;key&gt;,&lt;value&gt;[,&lt;key&gt;,&lt;value&gt;...]
&lt;variant&gt; ::= variant:&lt;type&gt;:&lt;value&gt;
-&lt;type&gt; ::= string | int16 | uint 16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
+&lt;type&gt; ::= string | int16 | uint16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
</literallayout> <!-- .fi -->
<para>D-Bus supports more types than these, but <command>dbus-send</command> currently
diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml
index cdef44db..f6319a88 100644
--- a/doc/dbus-specification.xml
+++ b/doc/dbus-specification.xml
@@ -6,8 +6,8 @@
<article id="index">
<articleinfo>
<title>D-Bus Specification</title>
- <releaseinfo>Version 0.26</releaseinfo>
- <date>2015-02-19</date>
+ <releaseinfo>Version 0.32</releaseinfo>
+ <date>(not yet released)</date>
<authorgroup>
<author>
<firstname>Havoc</firstname>
@@ -55,7 +55,7 @@
<affiliation>
<orgname>Collabora Ltd.</orgname>
<address>
- <email>simon.mcvittie@collabora.co.uk</email>
+ <email>smcv@collabora.com</email>
</address>
</affiliation>
</author>
@@ -71,6 +71,78 @@
</authorgroup>
<revhistory>
<revision>
+ <revnumber>latest</revnumber>
+ <date>(not yet released)</date>
+ <authorinitials>n/a</authorinitials>
+ <revremark>
+ See <ulink url='http://cgit.freedesktop.org/dbus/dbus/log/doc/dbus-specification.xml'>commit log</ulink>
+ </revremark>
+ </revision>
+ <revision>
+ <revnumber>0.31</revnumber>
+ <date>2017-06-29</date>
+ <authorinitials>smcv, TG</authorinitials>
+ <revdescription>
+ <itemizedlist>
+ <listitem><simpara>Don't require implementation-specific search
+ paths to be lowest priority</simpara></listitem>
+ <listitem><simpara>Correct regex syntax for optionally-escaped
+ bytes in addresses so it includes hyphen-minus, forward slash
+ and underscore as intended</simpara></listitem>
+ <listitem><simpara>Describe all message bus methods in the same
+ section</simpara></listitem>
+ <listitem><simpara>Clarify the correct object path for method calls
+ to the message bus</simpara></listitem>
+ <listitem><simpara>Document that the message bus implements
+ Introspectable, Peer and Properties</simpara></listitem>
+ <listitem><simpara>Add new Features and Interfaces properties for
+ message bus feature-discovery</simpara></listitem>
+ <listitem><simpara>Add unix:dir=..., which resembles
+ unix:tmpdir=... but never uses abstract
+ sockets</simpara></listitem>
+ <listitem><simpara>Don't require eavesdrop='true' to be accepted
+ from connections not sufficiently privileged to use it
+ successfully</simpara></listitem>
+ <listitem><simpara>Formally deprecate eavesdropping in favour of
+ BecomeMonitor</simpara></listitem>
+ </itemizedlist>
+ </revdescription>
+ </revision>
+ <revision>
+ <revnumber>0.30</revnumber>
+ <date>2016-11-28</date>
+ <authorinitials>smcv, PW</authorinitials>
+ <revremark>
+ Define the jargon terms service activation and auto-starting more
+ clearly. Document the SystemdService key in service files.
+ Document how AppArmor interacts with service activation, and the
+ new AssumedAppArmorLabel key in service files (dbus-daemon 1.11.8).
+ Clarify intended behaviour of Properties.GetAll.
+ Use versioned interface and bus names in most examples.
+ </revremark>
+ </revision>
+ <revision>
+ <revnumber>0.29</revnumber>
+ <date>2016-10-10</date>
+ <authorinitials>PW</authorinitials>
+ <revremark>
+ Introspection arguments may contain annotations; recommend against
+ using the object path '/'
+ </revremark>
+ </revision>
+ <revision>
+ <revnumber>0.28</revnumber>
+ <date>2016-08-15</date>
+ <authorinitials>PW</authorinitials>
+ <revremark>Clarify serialization</revremark>
+ </revision>
+ <revision>
+ <revnumber>0.27</revnumber>
+ <date>2015-12-02</date>
+ <authorinitials>LU</authorinitials>
+ <revremark>Services should not send unwanted replies</revremark>
+ </revision>
+ <revision>
<revnumber>0.26</revnumber>
<date>2015-02-19</date>
<authorinitials>smcv, rh</authorinitials>
@@ -269,13 +341,13 @@
</listitem>
<listitem>
<para>
- A "session bus" used to implement desktop environments such as
+ A "session bus" used to implement desktop environments such as
GNOME and KDE.
</para>
</listitem>
</itemizedlist>
- D-Bus is not intended to be a generic IPC system for any possible
- application, and intentionally omits many features found in other
+ D-Bus is not intended to be a generic IPC system for any possible
+ application, and intentionally omits many features found in other
IPC systems for this reason.
</para>
@@ -283,7 +355,7 @@
At the same time, the bus daemons offer a number of features not found in
other IPC systems, such as single-owner "bus names" (similar to X
selections), on-demand startup of services, and security policies.
- In many ways, these features are the primary motivation for developing
+ In many ways, these features are the primary motivation for developing
D-Bus; other systems would have sufficed if IPC were the only goal.
</para>
@@ -314,17 +386,17 @@
reference implementation's behavior.
</para>
<para>
- Until this work is complete, any attempt to reimplement D-Bus will
+ Until this work is complete, any attempt to reimplement D-Bus will
probably require looking at the reference implementation and/or asking
- questions on the D-Bus mailing list about intended behavior.
+ questions on the D-Bus mailing list about intended behavior.
Questions on the list are very welcome.
</para>
<para>
- Nonetheless, this document should be a useful starting point and is
+ Nonetheless, this document should be a useful starting point and is
to our knowledge accurate, though incomplete.
</para>
</sect2>
-
+
</sect1>
<sect1 id="type-system">
@@ -405,7 +477,7 @@
<para>
As a simple example, the type code for 32-bit integer (<literal>INT32</literal>) is
- the ASCII character 'i'. So the signature for a block of values
+ the ASCII character 'i'. So the signature for a block of values
containing a single <literal>INT32</literal> would be:
<programlisting>
"i"
@@ -413,7 +485,7 @@
A block of values containing two <literal>INT32</literal> would have this signature:
<programlisting>
"ii"
- </programlisting>
+ </programlisting>
</para>
<para>
@@ -575,6 +647,15 @@
</para>
<para>
+ Using an object path of <literal>/</literal> is allowed, but
+ recommended against, as it makes versioning of interfaces hard. Any
+ signals emitted from a D-Bus object have the service’s unique bus name
+ associated with them, rather than its well-known name. This means that
+ receipients of the signals must rely entirely on the signal name and
+ object path to work out which interface the signal originated from.
+ </para>
+
+ <para>
For instance, if the owner of <literal>example.com</literal> is
developing a D-Bus API for a music player, they might use the
hierarchy of object paths that start with
@@ -678,21 +759,21 @@
<title>Container types</title>
<para>
- In addition to basic types, there are four <firstterm>container</firstterm>
- types: <literal>STRUCT</literal>, <literal>ARRAY</literal>, <literal>VARIANT</literal>,
+ In addition to basic types, there are four <firstterm>container</firstterm>
+ types: <literal>STRUCT</literal>, <literal>ARRAY</literal>, <literal>VARIANT</literal>,
and <literal>DICT_ENTRY</literal>.
</para>
<para>
- <literal>STRUCT</literal> has a type code, ASCII character 'r', but this type
+ <literal>STRUCT</literal> has a type code, ASCII character 'r', but this type
code does not appear in signatures. Instead, ASCII characters
'(' and ')' are used to mark the beginning and end of the struct.
- So for example, a struct containing two integers would have this
+ So for example, a struct containing two integers would have this
signature:
<programlisting>
"(ii)"
</programlisting>
- Structs can be nested, so for example a struct containing
+ Structs can be nested, so for example a struct containing
an integer and another struct:
<programlisting>
"(i(ii))"
@@ -704,7 +785,7 @@
<para>
The <literal>STRUCT</literal> type code 'r' is not currently used in the D-Bus protocol,
- but is useful in code that implements the protocol. This type code
+ but is useful in code that implements the protocol. This type code
is specified to allow such code to interoperate in non-protocol contexts.
</para>
@@ -721,7 +802,7 @@
<programlisting>
"ai"
</programlisting>
- which is an array of 32-bit integers. But an array can be of any type,
+ which is an array of 32-bit integers. But an array can be of any type,
such as this array-of-struct-with-two-int32-fields:
<programlisting>
"a(ii)"
@@ -758,7 +839,7 @@
fields, and must not accept dict entries with non-basic-typed keys. A
dict entry is always a key-value pair.
</para>
-
+
<para>
The first field in the <literal>DICT_ENTRY</literal> is always the key.
A message is considered corrupt if the same key occurs twice in the same
@@ -767,7 +848,7 @@
</para>
<para>
- In most languages, an array of dict entry would be represented as a
+ In most languages, an array of dict entry would be represented as a
map, hash table, or dict object.
</para>
</sect2>
@@ -962,8 +1043,10 @@
<para>
Each value in a block of bytes is aligned "naturally," for example
4-byte values are aligned to a 4-byte boundary, and 8-byte values to an
- 8-byte boundary. To properly align a value, <firstterm>alignment
- padding</firstterm> may be necessary. The alignment padding must always
+ 8-byte boundary. Boundaries are calculated globally, with respect to
+ the first byte in the message. To properly align a value,
+ <firstterm>alignment padding</firstterm> may be necessary before the
+ value. The alignment padding must always
be the minimum required padding to properly align the following value;
and it must always be made up of nul bytes. The alignment padding must
not be left uninitialized (it can't contain garbage), and more padding
@@ -990,21 +1073,50 @@
</para>
<para>
- The string-like types are all marshalled as a
+ The string-like types (STRING, OBJECT_PATH and SIGNATURE) are all
+ marshalled as a
fixed-length unsigned integer <varname>n</varname> giving the
length of the variable part, followed by <varname>n</varname>
nonzero bytes of UTF-8 text, followed by a single zero (nul) byte
which is not considered to be part of the text. The alignment
of the string-like type is the same as the alignment of
- <varname>n</varname>.
+ <varname>n</varname>: any padding required for <varname>n</varname>
+ appears immediately before <varname>n</varname> itself. There is never
+ any alignment padding between <varname>n</varname> and the string text,
+ or between the string text and the trailing nul. The alignment padding
+ for the next value in the message (if there is one) starts after the
+ trailing nul.
</para>
<para>
For the STRING and OBJECT_PATH types, <varname>n</varname> is
- encoded in 4 bytes, leading to 4-byte alignment.
- For the SIGNATURE type, <varname>n</varname> is encoded as a single
- byte. As a result, alignment padding is never required before a
- SIGNATURE.
+ encoded in 4 bytes (a <literal>UINT32</literal>), leading to 4-byte
+ alignment. For the SIGNATURE type, <varname>n</varname> is encoded as a
+ single byte (a <literal>UINT8</literal>). As a result, alignment
+ padding is never required before a SIGNATURE.
+ </para>
+
+ <para>
+ For example, if the current position is a multiple of 8 bytes from the
+ beginning of a little-endian message, strings ‘foo’, ‘+’ and ‘bar’
+ would be serialized in sequence as follows:
+
+ <screen>
+ <lineannotation>no padding required, we are already at a multiple of 4</lineannotation>
+0x03 0x00 0x00 0x00 <lineannotation>length of ‘foo’ = 3</lineannotation>
+ 0x66 0x6f 0x6f <lineannotation>‘foo’</lineannotation>
+ 0x00 <lineannotation>trailing nul</lineannotation>
+
+ <lineannotation>no padding required, we are already at a multiple of 4</lineannotation>
+0x01 0x00 0x00 0x00 <lineannotation>length of ‘+’ = 1</lineannotation>
+ 0x2b <lineannotation>‘+’</lineannotation>
+ 0x00 <lineannotation>trailing nul</lineannotation>
+
+ 0x00 0x00 <lineannotation>2 bytes of padding to reach next multiple of 4</lineannotation>
+0x03 0x00 0x00 0x00 <lineannotation>length of ‘bar’ = 1</lineannotation>
+ 0x62 0x61 0x72 <lineannotation>‘bar’</lineannotation>
+ 0x00 <lineannotation>trailing nul</lineannotation>
+ </screen>
</para>
</sect2>
@@ -1018,7 +1130,8 @@
element type, followed by the <varname>n</varname> bytes of the
array elements marshalled in sequence. <varname>n</varname> does not
include the padding after the length, or any padding after the
- last element.
+ last element. i.e. <varname>n</varname> should be divisible by the
+ number of elements in the array.
</para>
<para>
@@ -1027,7 +1140,7 @@
the 64-bit integer 5 would be marshalled as:
<screen>
-00 00 00 08 <lineannotation>8 bytes of data</lineannotation>
+00 00 00 08 <lineannotation><varname>n</varname> = 8 bytes of data</lineannotation>
00 00 00 00 <lineannotation>padding to 8-byte boundary</lineannotation>
00 00 00 00 00 00 00 05 <lineannotation>first element = 5</lineannotation>
</screen>
@@ -1051,8 +1164,10 @@
marshalled value with the type given by that signature. The
variant has the same 1-byte alignment as the signature, which means
that alignment padding before a variant is never needed.
- Use of variants may not cause a total message depth to be larger
+ Use of variants must not cause a total message depth to be larger
than 64, including other container types such as structures.
+ (See <link linkend="message-protocol-marshaling-signature">Valid
+ Signatures</link>.)
</para>
</sect2>
@@ -1113,9 +1228,9 @@
<entry>8</entry>
</row><row>
<entry><literal>STRING</literal></entry>
- <entry>A <literal>UINT32</literal> indicating the string's
- length in bytes excluding its terminating nul, followed by
- non-nul string data of the given length, followed by a terminating nul
+ <entry>A <literal>UINT32</literal> indicating the string's
+ length in bytes excluding its terminating nul, followed by
+ non-nul string data of the given length, followed by a terminating nul
byte.
</entry>
<entry>
@@ -1123,7 +1238,7 @@
</entry>
</row><row>
<entry><literal>OBJECT_PATH</literal></entry>
- <entry>Exactly the same as <literal>STRING</literal> except the
+ <entry>Exactly the same as <literal>STRING</literal> except the
content must be a valid object path (see above).
</entry>
<entry>
@@ -1131,7 +1246,7 @@
</entry>
</row><row>
<entry><literal>SIGNATURE</literal></entry>
- <entry>The same as <literal>STRING</literal> except the length is a single
+ <entry>The same as <literal>STRING</literal> except the length is a single
byte (thus signatures have a maximum length of 255)
and the content must be a valid signature (see above).
</entry>
@@ -1141,7 +1256,7 @@
</row><row>
<entry><literal>ARRAY</literal></entry>
<entry>
- A <literal>UINT32</literal> giving the length of the array data in bytes, followed by
+ A <literal>UINT32</literal> giving the length of the array data in bytes, followed by
alignment padding to the alignment boundary of the array element type,
followed by each array element.
</entry>
@@ -1207,7 +1322,7 @@
information to figure out where to send the message and how to interpret
it; the recipient interprets the body of the message.
</para>
-
+
<para>
The body of the message is made up of zero or more
<firstterm>arguments</firstterm>, which are typed values, such as an
@@ -1231,7 +1346,7 @@
<para>
The length of the header must be a multiple of 8, allowing the body to
begin on an 8-byte boundary when storing the entire message in a single
- buffer. If the header does not naturally end on an 8-byte boundary
+ buffer. If the header does not naturally end on an 8-byte boundary
up to 7 bytes of nul-initialized alignment padding must be added.
</para>
@@ -1240,11 +1355,11 @@
</para>
<para>
- The maximum length of a message, including header, header alignment padding,
+ The maximum length of a message, including header, header alignment padding,
and body is 2 to the 27th power or 134217728 (128 MiB).
Implementations must not send or accept messages exceeding this size.
</para>
-
+
<para>
The signature of the header is:
<programlisting>
@@ -1269,13 +1384,13 @@
<tbody>
<row>
<entry>1st <literal>BYTE</literal></entry>
- <entry>Endianness flag; ASCII 'l' for little-endian
- or ASCII 'B' for big-endian. Both header and body are
+ <entry>Endianness flag; ASCII 'l' for little-endian
+ or ASCII 'B' for big-endian. Both header and body are
in this endianness.</entry>
</row>
<row>
<entry>2nd <literal>BYTE</literal></entry>
- <entry><firstterm>Message type</firstterm>. Unknown types must be ignored.
+ <entry><firstterm>Message type</firstterm>. Unknown types must be ignored.
Currently-defined types are described below.
</entry>
</row>
@@ -1296,23 +1411,23 @@
</row>
<row>
<entry>1st <literal>UINT32</literal></entry>
- <entry>Length in bytes of the message body, starting
- from the end of the header. The header ends after
+ <entry>Length in bytes of the message body, starting
+ from the end of the header. The header ends after
its alignment padding to an 8-boundary.
</entry>
</row>
<row>
<entry>2nd <literal>UINT32</literal></entry>
- <entry>The serial of this message, used as a cookie
+ <entry>The serial of this message, used as a cookie
by the sender to identify the reply corresponding
to this request. This must not be zero.
</entry>
- </row>
+ </row>
<row>
<entry><literal>ARRAY</literal> of <literal>STRUCT</literal> of (<literal>BYTE</literal>,<literal>VARIANT</literal>)</entry>
<entry>An array of zero or more <firstterm>header
fields</firstterm> where the byte is the field code, and the
- variant is the field value. The message type determines
+ variant is the field value. The message type determines
which fields are required.
</entry>
</row>
@@ -1383,12 +1498,7 @@
<para>
This message does not expect method return replies or
error replies, even if it is of a type that can
- have a reply; the reply can be omitted as an
- optimization. It is compliant with this specification
- to return the reply despite this flag, although doing
- so on a bus with a non-trivial security policy
- (such as the well-known system bus) may result in
- access denial messages being logged for the reply.
+ have a reply; the reply should be omitted.
</para>
<para>
Note that METHOD_CALL is the only message type currently
@@ -1490,8 +1600,8 @@
<para>
Again, if an implementation sees a header field code that it does not
expect, it must ignore that field, as it will be part of a new
- (but compatible) version of this specification. This also applies
- to known header fields appearing in unexpected messages, for
+ (but compatible) version of this specification. This also applies
+ to known header fields appearing in unexpected messages, for
example: if a signal has a reply serial it must be ignored
even though it has no meaning as of this version of the spec.
</para>
@@ -1544,8 +1654,8 @@
<entry><literal>STRING</literal></entry>
<entry><literal>SIGNAL</literal></entry>
<entry>
- The interface to invoke a method call on, or
- that a signal is emitted from. Optional for
+ The interface to invoke a method call on, or
+ that a signal is emitted from. Optional for
method calls, required for signals.
The special interface
<literal>org.freedesktop.DBus.Local</literal> is reserved;
@@ -1583,7 +1693,7 @@
<entry><literal>STRING</literal></entry>
<entry>optional</entry>
<entry>The name of the connection this message is intended for.
- Only used in combination with the message bus, see
+ Only used in combination with the message bus, see
<xref linkend="message-bus"/>.</entry>
</row>
<row>
@@ -1601,7 +1711,7 @@
<entry><literal>SIGNATURE</literal></entry>
<entry>optional</entry>
<entry>The signature of the message body.
- If omitted, it is assumed to be the
+ If omitted, it is assumed to be the
empty signature "" (i.e. the body must be 0-length).</entry>
</row>
<row>
@@ -1633,23 +1743,23 @@
The various names in D-Bus messages have some restrictions.
</para>
<para>
- There is a <firstterm>maximum name length</firstterm>
- of 255 which applies to bus names, interfaces, and members.
+ There is a <firstterm>maximum name length</firstterm>
+ of 255 which applies to bus names, interfaces, and members.
</para>
<sect3 id="message-protocol-names-interface">
<title>Interface names</title>
<para>
- Interfaces have names with type <literal>STRING</literal>, meaning that
- they must be valid UTF-8. However, there are also some
- additional restrictions that apply to interface names
+ Interfaces have names with type <literal>STRING</literal>, meaning that
+ they must be valid UTF-8. However, there are also some
+ additional restrictions that apply to interface names
specifically:
<itemizedlist>
<listitem><para>Interface names are composed of 1 or more elements separated by
- a period ('.') character. All elements must contain at least
+ a period ('.') character. All elements must contain at least
one character.
</para>
</listitem>
- <listitem><para>Each element must only contain the ASCII characters
+ <listitem><para>Each element must only contain the ASCII characters
"[A-Z][a-z][0-9]_" and must not begin with a digit.
</para>
</listitem>
@@ -1698,7 +1808,7 @@
with the connection for its entire lifetime.
A bus name is of type <literal>STRING</literal>,
meaning that it must be valid UTF-8. However, there are also
- some additional restrictions that apply to bus names
+ some additional restrictions that apply to bus names
specifically:
<itemizedlist>
<listitem><para>Bus names that start with a colon (':')
@@ -1707,11 +1817,11 @@
</para>
</listitem>
<listitem><para>Bus names are composed of 1 or more elements separated by
- a period ('.') character. All elements must contain at least
+ a period ('.') character. All elements must contain at least
one character.
</para>
</listitem>
- <listitem><para>Each element must only contain the ASCII characters
+ <listitem><para>Each element must only contain the ASCII characters
"[A-Z][a-z][0-9]_-". Only elements that are part of a unique
connection name may begin with a digit, elements in
other bus names must not begin with a digit.
@@ -1788,8 +1898,8 @@
Error names have the same naming conventions as interface
names, and often contain <literal>.Error.</literal>; for instance,
the owner of <literal>example.com</literal> might define the
- errors <literal>com.example.MusicPlayer.Error.FileNotFound</literal>
- and <literal>com.example.MusicPlayer.Error.OutOfMemory</literal>.
+ errors <literal>com.example.MusicPlayer1.Error.FileNotFound</literal>
+ and <literal>com.example.MusicPlayer1.Error.OutOfMemory</literal>.
The errors defined by D-Bus itself, such as
<literal>org.freedesktop.DBus.Error.Failed</literal>, follow a
similar pattern.
@@ -1848,33 +1958,32 @@
reply can have one of two types; either <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>.
</para>
<para>
- If the reply has type <literal>METHOD_RETURN</literal>, the arguments to the reply message
- are the return value(s) or "out parameters" of the method call.
- If the reply has type <literal>ERROR</literal>, then an "exception" has been thrown,
- and the call fails; no return value will be provided. It makes
+ If the reply has type <literal>METHOD_RETURN</literal>, the arguments to the reply message
+ are the return value(s) or "out parameters" of the method call.
+ If the reply has type <literal>ERROR</literal>, then an "exception" has been thrown,
+ and the call fails; no return value will be provided. It makes
no sense to send multiple replies to the same method call.
</para>
<para>
- Even if a method call has no return values, a <literal>METHOD_RETURN</literal>
- reply is required, so the caller will know the method
+ Even if a method call has no return values, a <literal>METHOD_RETURN</literal>
+ reply is required, so the caller will know the method
was successfully processed.
</para>
<para>
- The <literal>METHOD_RETURN</literal> or <literal>ERROR</literal> reply message must have the <literal>REPLY_SERIAL</literal>
+ The <literal>METHOD_RETURN</literal> or <literal>ERROR</literal> reply message must have the <literal>REPLY_SERIAL</literal>
header field.
</para>
<para>
- If a <literal>METHOD_CALL</literal> message has the flag <literal>NO_REPLY_EXPECTED</literal>,
- then as an optimization the application receiving the method
- call may choose to omit the reply message (regardless of
- whether the reply would have been <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>).
- However, it is also acceptable to ignore the <literal>NO_REPLY_EXPECTED</literal>
- flag and reply anyway.
+ If a <literal>METHOD_CALL</literal> message has the flag <literal>NO_REPLY_EXPECTED</literal>,
+ then the application receiving the method should not send the reply message (regardless of
+ whether the reply would have been <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>).
</para>
<para>
Unless a message has the flag <literal>NO_AUTO_START</literal>, if the
destination name does not exist then a program to own the destination
- name will be started before the message is delivered. The message
+ name will be started (activated) before the message is delivered. See
+ <xref linkend="message-bus-starting-services"/>.
+ The message
will be held until the new program is successfully started or has
failed to start; in case of failure, an error will be returned. This
flag is only relevant in the context of a message bus, it is ignored
@@ -1904,8 +2013,8 @@
in order. "out" arguments are not represented in the caller's message.
</para>
<para>
- The recipient constructs a reply by appending first the return value
- if any, then each "out" or "inout" argument, in order.
+ The recipient constructs a reply by appending first the return value
+ if any, then each "out" or "inout" argument, in order.
"in" arguments are not represented in the reply message.
</para>
<para>
@@ -1913,19 +2022,19 @@
exceptions.
</para>
<para>
- In converting from native APIs to D-Bus, it is perhaps nice to
- map D-Bus naming conventions ("FooBar") to native conventions
- such as "fooBar" or "foo_bar" automatically. This is OK
- as long as you can say that the native API is one that
+ In converting from native APIs to D-Bus, it is perhaps nice to
+ map D-Bus naming conventions ("FooBar") to native conventions
+ such as "fooBar" or "foo_bar" automatically. This is OK
+ as long as you can say that the native API is one that
was specifically written for D-Bus. It makes the most sense
- when writing object implementations that will be exported
- over the bus. Object proxies used to invoke remote D-Bus
+ when writing object implementations that will be exported
+ over the bus. Object proxies used to invoke remote D-Bus
objects probably need the ability to call any D-Bus method,
and thus a magic name mapping like this could be a problem.
</para>
<para>
This specification doesn't require anything of native API bindings;
- the preceding is only a suggested convention for consistency
+ the preceding is only a suggested convention for consistency
among bindings.
</para>
</sect4>
@@ -1934,9 +2043,9 @@
<sect3 id="message-protocol-types-signal">
<title>Signal Emission</title>
<para>
- Unlike method calls, signal emissions have no replies.
+ Unlike method calls, signal emissions have no replies.
A signal emission is simply a single message of type <literal>SIGNAL</literal>.
- It must have three header fields: <literal>PATH</literal> giving the object
+ It must have three header fields: <literal>PATH</literal> giving the object
the signal was emitted from, plus <literal>INTERFACE</literal> and <literal>MEMBER</literal> giving
the fully-qualified name of the signal. The <literal>INTERFACE</literal> header is required
for signals, though it is optional for method calls.
@@ -1946,14 +2055,14 @@
<sect3 id="message-protocol-types-errors">
<title>Errors</title>
<para>
- Messages of type <literal>ERROR</literal> are most commonly replies
- to a <literal>METHOD_CALL</literal>, but may be returned in reply
+ Messages of type <literal>ERROR</literal> are most commonly replies
+ to a <literal>METHOD_CALL</literal>, but may be returned in reply
to any kind of message. The message bus for example
- will return an <literal>ERROR</literal> in reply to a signal emission if
+ will return an <literal>ERROR</literal> in reply to a signal emission if
the bus does not have enough memory to send the signal.
</para>
<para>
- An <literal>ERROR</literal> may have any arguments, but if the first
+ An <literal>ERROR</literal> may have any arguments, but if the first
argument is a <literal>STRING</literal>, it must be an error message.
The error message may be logged or shown to the user
in some way.
@@ -1963,13 +2072,13 @@
<sect3 id="message-protocol-types-notation">
<title>Notation in this document</title>
<para>
- This document uses a simple pseudo-IDL to describe particular method
+ This document uses a simple pseudo-IDL to describe particular method
calls and signals. Here is an example of a method call:
<programlisting>
org.freedesktop.DBus.StartServiceByName (in STRING name, in UINT32 flags,
out UINT32 resultcode)
</programlisting>
- This means <literal>INTERFACE</literal> = org.freedesktop.DBus, <literal>MEMBER</literal> = StartServiceByName,
+ This means <literal>INTERFACE</literal> = org.freedesktop.DBus, <literal>MEMBER</literal> = StartServiceByName,
<literal>METHOD_CALL</literal> arguments are <literal>STRING</literal> and <literal>UINT32</literal>, <literal>METHOD_RETURN</literal> argument
is <literal>UINT32</literal>. Remember that the <literal>MEMBER</literal> field can't contain any '.' (period)
characters so it's known that the last part of the name in
@@ -1983,12 +2092,12 @@
</programlisting>
or equally valid, the return value could be done as an argument:
<programlisting>
- void org::freedesktop::DBus::StartServiceByName (const char *name,
+ void org::freedesktop::DBus::StartServiceByName (const char *name,
unsigned int flags,
unsigned int *resultcode);
</programlisting>
- It's really up to the API designer how they want to make
- this look. You could design an API where the namespace wasn't used
+ It's really up to the API designer how they want to make
+ this look. You could design an API where the namespace wasn't used
in C++, using STL or Qt, using varargs, or whatever you wanted.
</para>
<para>
@@ -1996,7 +2105,7 @@
<programlisting>
org.freedesktop.DBus.NameLost (STRING name)
</programlisting>
- Signals don't specify "in" vs. "out" because only
+ Signals don't specify "in" vs. "out" because only
a single direction is possible.
</para>
<para>
@@ -2009,7 +2118,7 @@
<sect2 id="message-protocol-handling-invalid">
<title>Invalid Protocol and Spec Extensions</title>
-
+
<para>
For security reasons, the D-Bus protocol should be strictly parsed and
validated, with the exception of defined extension points. Any invalid
@@ -2023,8 +2132,8 @@
</para>
<para>
- Generally speaking violations of the "must" requirements in this spec
- should be considered possible attempts to exploit security, and violations
+ Generally speaking violations of the "must" requirements in this spec
+ should be considered possible attempts to exploit security, and violations
of the "should" suggestions should be considered legitimate (though perhaps
they should generate an error in some cases).
</para>
@@ -2040,9 +2149,9 @@
<itemizedlist>
<listitem>
<para>
- In the authentication protocol (see <xref linkend="auth-protocol"/>) unknown
- commands result in an ERROR rather than a disconnect. This enables
- future extensions to the protocol. Commands starting with EXTENSION_ are
+ In the authentication protocol (see <xref linkend="auth-protocol"/>) unknown
+ commands result in an ERROR rather than a disconnect. This enables
+ future extensions to the protocol. Commands starting with EXTENSION_ are
reserved for third parties.
</para>
</listitem>
@@ -2061,15 +2170,15 @@
<para>
Messages with an unknown type (something other than
<literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>,
- <literal>ERROR</literal>, <literal>SIGNAL</literal>) are ignored.
- Unknown-type messages must still be well-formed in the same way
- as the known messages, however. They still have the normal
+ <literal>ERROR</literal>, <literal>SIGNAL</literal>) are ignored.
+ Unknown-type messages must still be well-formed in the same way
+ as the known messages, however. They still have the normal
header and body.
</para>
</listitem>
<listitem>
<para>
- Header fields with an unknown or unexpected field code must be ignored,
+ Header fields with an unknown or unexpected field code must be ignored,
though again they must still be well-formed.
</para>
</listitem>
@@ -2129,7 +2238,7 @@
</itemizedlist>
</para>
<para>
- Unofficial extensions to the command set must begin with the letters
+ Unofficial extensions to the command set must begin with the letters
"EXTENSION_", to avoid conflicts with future official commands.
For example, "EXTENSION_COM_MYDOMAIN_DO_STUFF".
</para>
@@ -2145,15 +2254,15 @@
socket, and even on operating systems that do not require a byte to be
sent in order to transmit credentials. The text protocol described in
this document begins after the single nul byte. If the first byte
- received from the client is not a nul byte, the server may disconnect
+ received from the client is not a nul byte, the server may disconnect
that client.
</para>
<para>
- A nul byte in any context other than the initial byte is an error;
+ A nul byte in any context other than the initial byte is an error;
the protocol is ASCII-only.
</para>
<para>
- The credentials sent along with the nul byte may be used with the
+ The credentials sent along with the nul byte may be used with the
SASL mechanism EXTERNAL.
</para>
</sect2>
@@ -2183,7 +2292,7 @@
REJECTED.
</para>
<para>
- If authentication succeeds after exchanging DATA commands,
+ If authentication succeeds after exchanging DATA commands,
an OK command must be sent to the client.
</para>
<para>
@@ -2210,21 +2319,21 @@
<sect2 id="auth-command-data">
<title>DATA Command</title>
<para>
- The DATA command may come from either client or server, and simply
- contains a hex-encoded block of data to be interpreted
+ The DATA command may come from either client or server, and simply
+ contains a hex-encoded block of data to be interpreted
according to the SASL mechanism in use.
</para>
<para>
- Some SASL mechanisms support sending an "empty string";
+ Some SASL mechanisms support sending an "empty string";
FIXME we need some way to do this.
</para>
</sect2>
<sect2 id="auth-command-begin">
<title>BEGIN Command</title>
<para>
- The BEGIN command acknowledges that the client has received an
+ The BEGIN command acknowledges that the client has received an
OK command from the server, and that the stream of messages
- is about to begin.
+ is about to begin.
</para>
<para>
The first octet received by the server after the \r\n of the BEGIN
@@ -2242,8 +2351,8 @@
</para><para>
Optionally, the REJECTED command has a space-separated list of
available auth mechanisms as arguments. If a server ever provides
- a list of supported mechanisms, it must provide the same list
- each time it sends a REJECTED message. Clients are free to
+ a list of supported mechanisms, it must provide the same list
+ each time it sends a REJECTED message. Clients are free to
ignore all lists received after the first.
</para>
</sect2>
@@ -2288,8 +2397,8 @@
<para>
If an ERROR is sent, the server or client that sent the
error must continue as if the command causing the ERROR had never been
- received. However, the the server or client receiving the error
- should try something other than whatever caused the error;
+ received. However, the the server or client receiving the error
+ should try something other than whatever caused the error;
if only canceling/rejecting the authentication.
</para>
<para>
@@ -2353,7 +2462,7 @@
</sect2>
<sect2 id="auth-examples">
<title>Authentication examples</title>
-
+
<para>
<figure>
<title>Example of successful magic cookie authentication</title>
@@ -2459,16 +2568,16 @@
</sect2>
<sect2 id="auth-states">
<title>Authentication state diagrams</title>
-
+
<para>
- This section documents the auth protocol in terms of
- a state machine for the client and the server. This is
+ This section documents the auth protocol in terms of
+ a state machine for the client and the server. This is
probably the most robust way to implement the protocol.
</para>
<sect3 id="auth-states-client">
<title>Client states</title>
-
+
<para>
To more precisely describe the interaction between the
protocol state machine and the authentication mechanisms the
@@ -2499,10 +2608,10 @@
</para>
</listitem>
</itemizedlist>
-
+
Both RESP and CHALL may be empty.
</para>
-
+
<para>
The Client starts by getting an initial response from the
default mechanism and sends AUTH MECH RESP, or AUTH MECH if
@@ -2512,7 +2621,7 @@
returns OK the client starts in state
<emphasis>WaitingForOK</emphasis>.
</para>
-
+
<para>
The client should keep track of available mechanisms and
which it mechanisms it has already attempted. This list is
@@ -2648,7 +2757,7 @@
<sect3 id="auth-states-server">
<title>Server states</title>
-
+
<para>
For the server MECH(RESP) means that the client response
RESP was fed to the the mechanism MECH, which returns one of
@@ -2750,7 +2859,7 @@
</para>
</formalpara>
-
+
<formalpara>
<title><emphasis>WaitingForData</emphasis></title>
<para>
@@ -2846,7 +2955,7 @@
</formalpara>
</sect3>
-
+
</sect2>
<sect2 id="auth-mechanisms">
<title>Authentication mechanisms</title>
@@ -2860,8 +2969,8 @@
The DBUS_COOKIE_SHA1 mechanism is designed to establish that a client
has the ability to read a private file owned by the user being
authenticated. If the client can prove that it has access to a secret
- cookie stored in this file, then the client is authenticated.
- Thus the security of DBUS_COOKIE_SHA1 depends on a secure home
+ cookie stored in this file, then the client is authenticated.
+ Thus the security of DBUS_COOKIE_SHA1 depends on a secure home
directory.
</para>
<para>
@@ -2874,7 +2983,7 @@
<itemizedlist>
<listitem>
<para>
- The client sends the username it would like to authenticate
+ The client sends the username it would like to authenticate
as, hex-encoded.
</para>
</listitem>
@@ -2920,13 +3029,13 @@
</para>
<para>
Cookies are stored in a user's home directory, in the directory
- <filename>~/.dbus-keyrings/</filename>. This directory must
- not be readable or writable by other users. If it is,
- clients and servers must ignore it. The directory
+ <filename>~/.dbus-keyrings/</filename>. This directory must
+ not be readable or writable by other users. If it is,
+ clients and servers must ignore it. The directory
contains cookie files named after the cookie context.
</para>
<para>
- A cookie file contains one cookie per line. Each line
+ A cookie file contains one cookie per line. Each line
has three space-separated fields:
<itemizedlist>
<listitem>
@@ -2944,7 +3053,7 @@
<listitem>
<para>
The cookie itself, a hex-encoded random block of bytes. The cookie
- may be of any length, though obviously security increases
+ may be of any length, though obviously security increases
as the length increases.
</para>
</listitem>
@@ -2973,16 +3082,16 @@
Once the lockfile has been created, the server loads the cookie
file. It should then delete any cookies that are old (the
timeout can be fairly short), or more than a reasonable
- time in the future (so that cookies never accidentally
- become permanent, if the clock was set far into the future
- at some point). If no recent keys remain, the
+ time in the future (so that cookies never accidentally
+ become permanent, if the clock was set far into the future
+ at some point). If no recent keys remain, the
server may generate a new key.
</para>
</listitem>
<listitem>
<para>
- The pruned and possibly added-to cookie file
- must be resaved atomically (using a temporary
+ The pruned and possibly added-to cookie file
+ must be resaved atomically (using a temporary
file which is rename()'d).
</para>
</listitem>
@@ -2994,8 +3103,8 @@
</itemizedlist>
</para>
<para>
- Clients need not lock the file in order to load it,
- because servers are required to save the file atomically.
+ Clients need not lock the file in order to load it,
+ because servers are required to save the file atomically.
</para>
</sect3>
</sect2>
@@ -3008,7 +3117,7 @@
Each value is escaped.
</para>
<para>
- For example:
+ For example:
<programlisting>unix:path=/tmp/dbus-test</programlisting>
Which is the address to a unix socket with the path /tmp/dbus-test.
</para>
@@ -3018,7 +3127,7 @@
<listitem>
<para>
The set of optionally-escaped bytes is:
- <literal>[0-9A-Za-z_-/.\]</literal>. To escape, each
+ <literal>[-0-9A-Za-z_/.\]</literal>. To escape, each
<emphasis>byte</emphasis> (note, not character) which is not in the
set of optionally-escaped bytes must be replaced with an ASCII
percent (<literal>%</literal>) and the value of the byte in hex.
@@ -3036,7 +3145,7 @@
</para>
</listitem>
</itemizedlist>
- The set of optionally-escaped bytes is intended to preserve address
+ The set of optionally-escaped bytes is intended to preserve address
readability and convenience.
</para>
@@ -3051,7 +3160,7 @@
those two connections are equivalent post-connection but should have
distinct UUIDs to distinguish the kinds of connection.
</para>
-
+
<para>
The intent of the address UUID feature is to allow a client to avoid
opening multiple identical connections to the same server, by allowing the
@@ -3063,12 +3172,12 @@
</para>
<para>
- Note that the address key is <literal>guid</literal> even though the
+ Note that the address key is <literal>guid</literal> even though the
rest of the API and documentation says "UUID," for historical reasons.
</para>
<para>
- [FIXME clarify if attempting to connect to each is a requirement
+ [FIXME clarify if attempting to connect to each is a requirement
or just a suggestion]
When connecting to a server, multiple server addresses can be
separated by a semi-colon. The library will then try to connect
@@ -3110,28 +3219,28 @@
<literal>unix:path=/run/user/1234/bus</literal>.
</para>
</sect1>
-
+
<sect1 id="transports">
<title>Transports</title>
<para>
[FIXME we need to specify in detail each transport and its possible arguments]
-
- Current transports include: unix domain sockets (including
+
+ Current transports include: unix domain sockets (including
abstract namespace on linux), launchd, systemd, TCP/IP, an executed subprocess and a debug/testing transport
using in-process pipes. Future possible transports include one that
tunnels over X11 protocol.
</para>
-
+
<sect2 id="transports-unix-domain-sockets">
<title>Unix Domain Sockets</title>
<para>
- Unix domain sockets can be either paths in the file system or on Linux
+ Unix domain sockets can be either paths in the file system or on Linux
kernels, they can be abstract which are similar to paths but
do not show up in the file system.
</para>
<para>
- When a socket is opened by the D-Bus library it truncates the path
+ When a socket is opened by the D-Bus library it truncates the path
name right before the first trailing Nul byte. This is true for both
normal paths and abstract paths. Note that this is a departure from
previous versions of D-Bus that would create sockets with a fixed
@@ -3144,7 +3253,8 @@
<para>
Unix addresses that specify <literal>path</literal> or
<literal>abstract</literal> are both listenable and connectable.
- Unix addresses that specify <literal>tmpdir</literal> are only
+ Unix addresses that specify <literal>tmpdir</literal>
+ or <literal>dir</literal> are only
listenable: the corresponding connectable address will specify
either <literal>path</literal> or <literal>abstract</literal>.
Similarly, Unix addresses that specify <literal>runtime</literal>
@@ -3153,8 +3263,8 @@
</para>
<sect3 id="transports-unix-domain-sockets-addresses">
<title>Server Address Format</title>
- <para>
- Unix domain socket addresses are identified by the "unix:" prefix
+ <para>
+ Unix domain socket addresses are identified by the "unix:" prefix
and support the following key/value pairs:
</para>
<informaltable>
@@ -3170,17 +3280,42 @@
<row>
<entry>path</entry>
<entry>(path)</entry>
- <entry>path of the unix domain socket. If set, the "tmpdir" and "abstract" key must not be set.</entry>
+ <entry>
+ Path of the unix domain socket.
+ </entry>
+ </row>
+ <row>
+ <entry>dir</entry>
+ <entry>(path)</entry>
+ <entry>
+ Directory in which a socket file with a random file name
+ starting with 'dbus-' will be created by the server. This key
+ can only be used in server addresses, not in client addresses;
+ the resulting client address will have the "path" key instead.
+ be set.
+ </entry>
</row>
<row>
<entry>tmpdir</entry>
<entry>(path)</entry>
- <entry>temporary directory in which a socket file with a random file name starting with 'dbus-' will be created by the server. This key can only be used in server addresses, not in client addresses. If set, the "path" and "abstract" key must not be set.</entry>
+ <entry>
+ The same as "dir", except that on platforms with
+ abstract sockets, the server may attempt to create an
+ abstract socket whose name starts with this directory instead
+ of a path-based socket. This key can only be used in server
+ addresses, not in client addresses; the resulting client address
+ will have the "abstract" or "path" key instead.
+ </entry>
</row>
<row>
<entry>abstract</entry>
<entry>(string)</entry>
- <entry>unique string (path) in the abstract namespace. If set, the "path" or "tmpdir" key must not be set. This key is only supported on platforms with "abstract Unix sockets", of which Linux is the only known example.</entry>
+ <entry>
+ Unique string in the abstract namespace, often syntactically
+ resembling a path but unconnected to the filesystem namespace.
+ This key is only supported on platforms with abstract Unix
+ sockets, of which Linux is the only known example.
+ </entry>
</row>
<row>
<entry>runtime</entry>
@@ -3192,8 +3327,8 @@
</informaltable>
<para>
Exactly one of the keys <literal>path</literal>,
- <literal>abstract</literal>, <literal>runtime</literal> or
- <literal>tmpdir</literal> must be provided.
+ <literal>abstract</literal>, <literal>runtime</literal>,
+ <literal>dir</literal> or <literal>tmpdir</literal> must be provided.
</para>
</sect3>
</sect2>
@@ -3280,13 +3415,13 @@
<title>TCP Sockets</title>
<para>
The tcp transport provides TCP/IP based connections between clients
- located on the same or different hosts.
+ located on the same or different hosts.
</para>
<para>
- Using tcp transport without any additional secure authentification mechanismus
- over a network is unsecure.
+ Using tcp transport without any additional secure authentification mechanismus
+ over a network is unsecure.
</para>
- <para>
+ <para>
On Windows and most Unix platforms, the TCP stack is unable to transfer
credentials over a TCP connection, so the EXTERNAL authentication
mechanism does not work for this transport.
@@ -3300,8 +3435,8 @@
</para>
<sect3 id="transports-tcp-sockets-addresses">
<title>Server Address Format</title>
- <para>
- TCP/IP socket addresses are identified by the "tcp:" prefix
+ <para>
+ TCP/IP socket addresses are identified by the "tcp:" prefix
and support the following key/value pairs:
</para>
<informaltable>
@@ -3333,9 +3468,9 @@
<row>
<entry>port</entry>
<entry>(number)</entry>
- <entry>The tcp port the server will open. A zero value let the server
- choose a free port provided from the underlaying operating system.
- libdbus is able to retrieve the real used port from the server.
+ <entry>The tcp port the server will open. A zero value let the server
+ choose a free port provided from the underlaying operating system.
+ libdbus is able to retrieve the real used port from the server.
</entry>
</row>
<row>
@@ -3387,8 +3522,8 @@
</para>
<sect3 id="transports-nonce-tcp-sockets-addresses">
<title>Server Address Format</title>
- <para>
- Nonce TCP/IP socket addresses uses the "nonce-tcp:" prefix
+ <para>
+ Nonce TCP/IP socket addresses uses the "nonce-tcp:" prefix
and support the following key/value pairs:
</para>
<informaltable>
@@ -3415,9 +3550,9 @@
<row>
<entry>port</entry>
<entry>(number)</entry>
- <entry>The tcp port the server will open. A zero value let the server
- choose a free port provided from the underlaying operating system.
- libdbus is able to retrieve the real used port from the server.
+ <entry>The tcp port the server will open. A zero value let the server
+ choose a free port provided from the underlaying operating system.
+ libdbus is able to retrieve the real used port from the server.
</entry>
</row>
<row>
@@ -3606,7 +3741,7 @@
<title>UUIDs</title>
<para>
A working D-Bus implementation uses universally-unique IDs in two places.
- First, each server address has a UUID identifying the address,
+ First, each server address has a UUID identifying the address,
as described in <xref linkend="addresses"/>. Second, each operating
system kernel instance running a D-Bus client or server has a UUID
identifying that kernel, retrieved by invoking the method
@@ -3638,18 +3773,18 @@
of the UUID.
</para>
</sect1>
-
+
<sect1 id="standard-interfaces">
<title>Standard Interfaces</title>
<para>
- See <xref linkend="message-protocol-types-notation"/> for details on
+ See <xref linkend="message-protocol-types-notation"/> for details on
the notation used in this section. There are some standard interfaces
that may be useful across various D-Bus applications.
</para>
<sect2 id="standard-interfaces-peer">
<title><literal>org.freedesktop.DBus.Peer</literal></title>
<para>
- The <literal>org.freedesktop.DBus.Peer</literal> interface
+ The <literal>org.freedesktop.DBus.Peer</literal> interface
has two methods:
<programlisting>
org.freedesktop.DBus.Peer.Ping ()
@@ -3665,12 +3800,12 @@
</para>
<para>
On receipt of the <literal>METHOD_CALL</literal> message
- <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should
- reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded
+ <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should
+ reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded
UUID representing the identity of the machine the process is running on.
This UUID must be the same for all processes on a single system at least
- until that system next reboots. It should be the same across reboots
- if possible, but this is not always possible to implement and is not
+ until that system next reboots. It should be the same across reboots
+ if possible, but this is not always possible to implement and is not
guaranteed.
It does not matter which object path a GetMachineId is sent to. The
reference implementation handles this method automatically.
@@ -3679,11 +3814,11 @@
The UUID is intended to be per-instance-of-the-operating-system, so may represent
a virtual machine running on a hypervisor, rather than a physical machine.
Basically if two processes see the same UUID, they should also see the same
- shared memory, UNIX domain sockets, process IDs, and other features that require
+ shared memory, UNIX domain sockets, process IDs, and other features that require
a running OS kernel in common between the processes.
</para>
<para>
- The UUID is often used where other programs might use a hostname. Hostnames
+ The UUID is often used where other programs might use a hostname. Hostnames
can change without rebooting, however, or just be "localhost" - so the UUID
is more robust.
</para>
@@ -3713,8 +3848,8 @@
<sect2 id="standard-interfaces-properties">
<title><literal>org.freedesktop.DBus.Properties</literal></title>
<para>
- Many native APIs will have a concept of object <firstterm>properties</firstterm>
- or <firstterm>attributes</firstterm>. These can be exposed via the
+ Many native APIs will have a concept of object <firstterm>properties</firstterm>
+ or <firstterm>attributes</firstterm>. These can be exposed via the
<literal>org.freedesktop.DBus.Properties</literal> interface.
</para>
<para>
@@ -3751,13 +3886,24 @@
see <xref linkend="standard-interfaces-introspectable"/>.
</para>
<para>
- An empty string may be provided for the interface name; in this case,
- if there are multiple properties on an object with the same name,
- the results are undefined (picking one by according to an arbitrary
- deterministic rule, or returning an error, are the reasonable
+ An empty string may be provided for the interface name; in this case,
+ if there are multiple properties on an object with the same name,
+ the results are undefined (picking one by according to an arbitrary
+ deterministic rule, or returning an error, are the reasonable
possibilities).
</para>
<para>
+ If <literal>org.freedesktop.DBus.Properties.GetAll</literal> is called
+ with a valid interface name which contains no properties, an empty array
+ should be returned. If it is called with a valid interface name for
+ which some properties are not accessible to the caller (for example, due
+ to per-property access control implemented in the service), those
+ properties should be silently omitted from the result array.
+ If <literal>org.freedesktop.DBus.Properties.Get</literal> is called for
+ any such properties, an appropriate access control error should be
+ returned.
+ </para>
+ <para>
If one or more properties change on an object, the
<literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
signal may be emitted (this signal was added in 0.14):
@@ -3873,7 +4019,7 @@
<para>
<programlisting>
org.freedesktop.DBus.AddMatch (bus_proxy,
- "type='signal',name='org.example.App',path_namespace='/org/example/App'");
+ "type='signal',name='org.example.App2',path_namespace='/org/example/App2'");
objects = org.freedesktop.DBus.ObjectManager.GetManagedObjects (app_proxy);
</programlisting>
</para>
@@ -3904,10 +4050,10 @@
<sect1 id="introspection-format">
<title>Introspection Data Format</title>
<para>
- As described in <xref linkend="standard-interfaces-introspectable"/>,
- objects may be introspected at runtime, returning an XML string
- that describes the object. The same XML format may be used in
- other contexts as well, for example as an "IDL" for generating
+ As described in <xref linkend="standard-interfaces-introspectable"/>,
+ objects may be introspected at runtime, returning an XML string
+ that describes the object. The same XML format may be used in
+ other contexts as well, for example as an "IDL" for generating
static language bindings.
</para>
<para>
@@ -3915,8 +4061,8 @@
<programlisting>
&lt;!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"&gt;
- &lt;node name="/com/example/sample_object"&gt;
- &lt;interface name="com.example.SampleInterface"&gt;
+ &lt;node name="/com/example/sample_object0"&gt;
+ &lt;interface name="com.example.SampleInterface0"&gt;
&lt;method name="Frobate"&gt;
&lt;arg name="foo" type="i" direction="in"/&gt;
&lt;arg name="bar" type="s" direction="out"/&gt;
@@ -3954,39 +4100,39 @@
</listitem>
<listitem>
<para>
- If a child &lt;node&gt; has any sub-elements, then they
+ If a child &lt;node&gt; has any sub-elements, then they
must represent a complete introspection of the child.
- If a child &lt;node&gt; is empty, then it may or may
+ If a child &lt;node&gt; is empty, then it may or may
not have sub-elements; the child must be introspected
- in order to find out. The intent is that if an object
+ in order to find out. The intent is that if an object
knows that its children are "fast" to introspect
- it can go ahead and return their information, but
+ it can go ahead and return their information, but
otherwise it can omit it.
</para>
</listitem>
<listitem>
<para>
- The direction element on &lt;arg&gt; may be omitted,
- in which case it defaults to "in" for method calls
- and "out" for signals. Signals only allow "out"
+ The direction element on &lt;arg&gt; may be omitted,
+ in which case it defaults to "in" for method calls
+ and "out" for signals. Signals only allow "out"
so while direction may be specified, it's pointless.
</para>
</listitem>
<listitem>
<para>
- The possible directions are "in" and "out",
+ The possible directions are "in" and "out",
unlike CORBA there is no "inout"
</para>
</listitem>
<listitem>
<para>
- The possible property access flags are
+ The possible property access flags are
"readwrite", "read", and "write"
</para>
</listitem>
<listitem>
<para>
- Multiple interfaces can of course be listed for
+ Multiple interfaces can of course be listed for
one &lt;node&gt;.
</para>
</listitem>
@@ -3998,7 +4144,7 @@
</itemizedlist>
</para>
<para>
- Method, interface, property, and signal elements may have
+ Method, interface, property, signal, and argument elements may have
"annotations", which are generic key/value pairs of metadata.
They are similar conceptually to Java's annotations and C# attributes.
Well-known annotations:
@@ -4083,8 +4229,8 @@
<sect2 id="message-bus-overview">
<title>Message Bus Overview</title>
<para>
- The message bus accepts connections from one or more applications.
- Once connected, applications can exchange messages with other
+ The message bus accepts connections from one or more applications.
+ Once connected, applications can exchange messages with other
applications that are also connected to the bus.
</para>
<para>
@@ -4093,7 +4239,7 @@
unique-for-the-lifetime-of-the-bus name automatically assigned.
Applications may request additional names for a connection. Additional
names are usually "well-known names" such as
- "com.example.TextEditor". When a name is bound to a connection,
+ "com.example.TextEditor1". When a name is bound to a connection,
that connection is said to <firstterm>own</firstterm> the name.
</para>
<para>
@@ -4108,15 +4254,15 @@
<para>
Each name may have <firstterm>queued owners</firstterm>. When an
application requests a name for a connection and the name is already in
- use, the bus will optionally add the connection to a queue waiting for
+ use, the bus will optionally add the connection to a queue waiting for
the name. If the current owner of the name disconnects or releases
the name, the next connection in the queue will become the new owner.
</para>
<para>
This feature causes the right thing to happen if you start two text
- editors for example; the first one may request "com.example.TextEditor",
- and the second will be queued as a possible owner of that name. When
+ editors for example; the first one may request "com.example.TextEditor1",
+ and the second will be queued as a possible owner of that name. When
the first exits, the second will take over.
</para>
@@ -4139,9 +4285,9 @@
connections to the same bus.
</para>
<para>
- Ownership of a unique name is a prerequisite for interaction with
- the message bus. It logically follows that the unique name is always
- the first name that an application comes to own, and the last
+ Ownership of a unique name is a prerequisite for interaction with
+ the message bus. It logically follows that the unique name is always
+ the first name that an application comes to own, and the last
one that it loses ownership of.
</para>
<para>
@@ -4163,397 +4309,6 @@
name. These names can be released again using the
<literal>org.freedesktop.DBus.ReleaseName</literal> message.
</para>
-
- <sect3 id="bus-messages-request-name">
- <title><literal>org.freedesktop.DBus.RequestName</literal></title>
- <para>
- As a method:
- <programlisting>
- UINT32 RequestName (in STRING name, in UINT32 flags)
- </programlisting>
- Message arguments:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Argument</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>0</entry>
- <entry>STRING</entry>
- <entry>Name to request</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>UINT32</entry>
- <entry>Flags</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- Reply arguments:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Argument</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>0</entry>
- <entry>UINT32</entry>
- <entry>Return value</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- <para>
- This method call should be sent to
- <literal>org.freedesktop.DBus</literal> and asks the message bus to
- assign the given name to the method caller. Each name maintains a
- queue of possible owners, where the head of the queue is the primary
- or current owner of the name. Each potential owner in the queue
- maintains the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and
- DBUS_NAME_FLAG_DO_NOT_QUEUE settings from its latest RequestName
- call. When RequestName is invoked the following occurs:
- <itemizedlist>
- <listitem>
- <para>
- If the method caller is currently the primary owner of the name,
- the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and DBUS_NAME_FLAG_DO_NOT_QUEUE
- values are updated with the values from the new RequestName call,
- and nothing further happens.
- </para>
- </listitem>
-
- <listitem>
- <para>
- If the current primary owner (head of the queue) has
- DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, and the RequestName
- invocation has the DBUS_NAME_FLAG_REPLACE_EXISTING flag, then
- the caller of RequestName replaces the current primary owner at
- the head of the queue and the current primary owner moves to the
- second position in the queue. If the caller of RequestName was
- in the queue previously its flags are updated with the values from
- the new RequestName in addition to moving it to the head of the queue.
- </para>
- </listitem>
-
- <listitem>
- <para>
- If replacement is not possible, and the method caller is
- currently in the queue but not the primary owner, its flags are
- updated with the values from the new RequestName call.
- </para>
- </listitem>
-
- <listitem>
- <para>
- If replacement is not possible, and the method caller is
- currently not in the queue, the method caller is appended to the
- queue.
- </para>
- </listitem>
-
- <listitem>
- <para>
- If any connection in the queue has DBUS_NAME_FLAG_DO_NOT_QUEUE
- set and is not the primary owner, it is removed from the
- queue. This can apply to the previous primary owner (if it
- was replaced) or the method caller (if it updated the
- DBUS_NAME_FLAG_DO_NOT_QUEUE flag while still stuck in the
- queue, or if it was just added to the queue with that flag set).
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Note that DBUS_NAME_FLAG_REPLACE_EXISTING results in "jumping the
- queue," even if another application already in the queue had specified
- DBUS_NAME_FLAG_REPLACE_EXISTING. This comes up if a primary owner
- that does not allow replacement goes away, and the next primary owner
- does allow replacement. In this case, queued items that specified
- DBUS_NAME_FLAG_REPLACE_EXISTING <emphasis>do not</emphasis>
- automatically replace the new primary owner. In other words,
- DBUS_NAME_FLAG_REPLACE_EXISTING is not saved, it is only used at the
- time RequestName is called. This is deliberate to avoid an infinite loop
- anytime two applications are both DBUS_NAME_FLAG_ALLOW_REPLACEMENT
- and DBUS_NAME_FLAG_REPLACE_EXISTING.
- </para>
- <para>
- The flags argument contains any of the following values logically ORed
- together:
-
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Conventional Name</entry>
- <entry>Value</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>DBUS_NAME_FLAG_ALLOW_REPLACEMENT</entry>
- <entry>0x1</entry>
- <entry>
-
- If an application A specifies this flag and succeeds in
- becoming the owner of the name, and another application B
- later calls RequestName with the
- DBUS_NAME_FLAG_REPLACE_EXISTING flag, then application A
- will lose ownership and receive a
- <literal>org.freedesktop.DBus.NameLost</literal> signal, and
- application B will become the new owner. If DBUS_NAME_FLAG_ALLOW_REPLACEMENT
- is not specified by application A, or DBUS_NAME_FLAG_REPLACE_EXISTING
- is not specified by application B, then application B will not replace
- application A as the owner.
-
- </entry>
- </row>
- <row>
- <entry>DBUS_NAME_FLAG_REPLACE_EXISTING</entry>
- <entry>0x2</entry>
- <entry>
-
- Try to replace the current owner if there is one. If this
- flag is not set the application will only become the owner of
- the name if there is no current owner. If this flag is set,
- the application will replace the current owner if
- the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT.
-
- </entry>
- </row>
- <row>
- <entry>DBUS_NAME_FLAG_DO_NOT_QUEUE</entry>
- <entry>0x4</entry>
- <entry>
-
- Without this flag, if an application requests a name that is
- already owned, the application will be placed in a queue to
- own the name when the current owner gives it up. If this
- flag is given, the application will not be placed in the
- queue, the request for the name will simply fail. This flag
- also affects behavior when an application is replaced as
- name owner; by default the application moves back into the
- waiting queue, unless this flag was provided when the application
- became the name owner.
-
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- The return code can be one of the following values:
-
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Conventional Name</entry>
- <entry>Value</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER</entry>
- <entry>1</entry> <entry>The caller is now the primary owner of
- the name, replacing any previous owner. Either the name had no
- owner before, or the caller specified
- DBUS_NAME_FLAG_REPLACE_EXISTING and the current owner specified
- DBUS_NAME_FLAG_ALLOW_REPLACEMENT.</entry>
- </row>
- <row>
- <entry>DBUS_REQUEST_NAME_REPLY_IN_QUEUE</entry>
- <entry>2</entry>
-
- <entry>The name already had an owner,
- DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified, and either
- the current owner did not specify
- DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the requesting
- application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING.
- </entry>
- </row>
- <row>
- <entry>DBUS_REQUEST_NAME_REPLY_EXISTS</entry> <entry>3</entry>
- <entry>The name already has an owner,
- DBUS_NAME_FLAG_DO_NOT_QUEUE was specified, and either
- DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the
- current owner, or DBUS_NAME_FLAG_REPLACE_EXISTING was not
- specified by the requesting application.</entry>
- </row>
- <row>
- <entry>DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER</entry>
- <entry>4</entry>
- <entry>The application trying to request ownership of a name is already the owner of it.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </sect3>
-
- <sect3 id="bus-messages-release-name">
- <title><literal>org.freedesktop.DBus.ReleaseName</literal></title>
- <para>
- As a method:
- <programlisting>
- UINT32 ReleaseName (in STRING name)
- </programlisting>
- Message arguments:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Argument</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>0</entry>
- <entry>STRING</entry>
- <entry>Name to release</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- Reply arguments:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Argument</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>0</entry>
- <entry>UINT32</entry>
- <entry>Return value</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- <para>
- This method call should be sent to
- <literal>org.freedesktop.DBus</literal> and asks the message bus to
- release the method caller's claim to the given name. If the caller is
- the primary owner, a new primary owner will be selected from the
- queue if any other owners are waiting. If the caller is waiting in
- the queue for the name, the caller will removed from the queue and
- will not be made an owner of the name if it later becomes available.
- If there are no other owners in the queue for the name, it will be
- removed from the bus entirely.
-
- The return code can be one of the following values:
-
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Conventional Name</entry>
- <entry>Value</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>DBUS_RELEASE_NAME_REPLY_RELEASED</entry>
- <entry>1</entry> <entry>The caller has released his claim on
- the given name. Either the caller was the primary owner of
- the name, and the name is now unused or taken by somebody
- waiting in the queue for the name, or the caller was waiting
- in the queue for the name and has now been removed from the
- queue.</entry>
- </row>
- <row>
- <entry>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</entry>
- <entry>2</entry>
- <entry>The given name does not exist on this bus.</entry>
- </row>
- <row>
- <entry>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</entry>
- <entry>3</entry>
- <entry>The caller was not the primary owner of this name,
- and was also not waiting in the queue to own this name.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </sect3>
-
- <sect3 id="bus-messages-list-queued-owners">
- <title><literal>org.freedesktop.DBus.ListQueuedOwners</literal></title>
- <para>
- As a method:
- <programlisting>
- ARRAY of STRING ListQueuedOwners (in STRING name)
- </programlisting>
- Message arguments:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Argument</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>0</entry>
- <entry>STRING</entry>
- <entry>The well-known bus name to query, such as
- <literal>com.example.cappuccino</literal></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- Reply arguments:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Argument</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>0</entry>
- <entry>ARRAY of STRING</entry>
- <entry>The unique bus names of connections currently queued
- for the name</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- <para>
- This method call should be sent to
- <literal>org.freedesktop.DBus</literal> and lists the connections
- currently queued for a bus name (see
- <xref linkend="term-queued-owner"/>).
- </para>
- </sect3>
</sect2>
<sect2 id="message-bus-routing">
@@ -4636,6 +4391,14 @@
</para>
<para>
+ Eavesdropping interacts poorly with buses with non-trivial
+ access control restrictions, and is deprecated. The
+ <literal>BecomeMonitor</literal> method (see
+ <xref linkend="bus-messages-become-monitor"/>) provides
+ a preferable way to monitor buses.
+ </para>
+
+ <para>
Eavesdropping is mainly useful for debugging tools, such as
the <literal>dbus-monitor</literal> tool in the reference
implementation of D-Bus. Tools which eavesdrop on the message bus
@@ -4646,21 +4409,12 @@
<para>
Clients may attempt to eavesdrop by adding match rules
(see <xref linkend="message-bus-routing-match-rules"/>) containing
- the <literal>eavesdrop='true'</literal> match. If the message bus'
- security policy does not allow eavesdropping, the match rule can
- still be added, but will not have any practical effect. For
+ the <literal>eavesdrop='true'</literal> match. For
compatibility with older message bus implementations, if adding such
a match rule results in an error reply, the client may fall back to
adding the same rule with the <literal>eavesdrop</literal> match
omitted.
</para>
-
- <para>
- Eavesdropping interacts poorly with buses with non-trivial
- access control restrictions. The
- <xref linkend="bus-messages-become-monitor"/> method provides
- an alternative way to monitor buses.
- </para>
</sect3>
<sect3 id="message-bus-routing-match-rules">
@@ -4682,16 +4436,18 @@
<para>
Match rules can also be used for eavesdropping
(see <xref linkend="message-bus-routing-eavesdropping"/>),
- if the security policy of the message bus allows it.
+ if the security policy of the message bus allows it, but this
+ usage is deprecated in favour of the <literal>BecomeMonitor</literal>
+ method (see <xref linkend="bus-messages-become-monitor"/>).
</para>
<para>
- Match rules are added using the AddMatch bus method
+ Match rules are added using the AddMatch bus method
(see <xref linkend="bus-messages-add-match"/>). Rules are
- specified as a string of comma separated key/value pairs.
- Excluding a key from the rule indicates a wildcard match.
- For instance excluding the the member from a match rule but
+ specified as a string of comma separated key/value pairs.
+ Excluding a key from the rule indicates a wildcard match.
+ For instance excluding the the member from a match rule but
adding a sender would let all messages from that sender through.
- An example of a complete rule would be
+ An example of a complete rule would be
"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',path='/bar/foo',destination=':452345.34',arg2='bar'"
</para>
<para>
@@ -4721,7 +4477,7 @@
</footnote>.
</para>
<para>
- The following table describes the keys that can be used to create
+ The following table describes the keys that can be used to create
a match rule.
<informaltable>
<tgroup cols="3">
@@ -4751,7 +4507,7 @@
<entry>An interface name (see <xref linkend="message-protocol-names-interface"/>)</entry>
<entry>Match messages sent over or to a particular interface. An example of an
interface match is interface='org.freedesktop.Hal.Manager'.
- If a message omits the interface header, it must not match any rule
+ If a message omits the interface header, it must not match any rule
that specifies this key.</entry>
</row>
<row>
@@ -4812,10 +4568,10 @@
<row>
<entry><literal>arg[0, 1, 2, 3, ...]</literal></entry>
<entry>Any string</entry>
- <entry>Arg matches are special and are used for further restricting the
+ <entry>Arg matches are special and are used for further restricting the
match based on the arguments in the body of a message. Only arguments of type
- STRING can be matched in this way. An example of an argument match
- would be arg3='Foo'. Only argument indexes from 0 to 63 should be
+ STRING can be matched in this way. An example of an argument match
+ would be arg3='Foo'. Only argument indexes from 0 to 63 should be
accepted.</entry>
</row>
<row>
@@ -4869,11 +4625,11 @@
first argument is an interface name.</para>
<para>For example, the match rule
- <literal>member='NameOwnerChanged',arg0namespace='com.example.backend'</literal>
+ <literal>member='NameOwnerChanged',arg0namespace='com.example.backend1'</literal>
matches name owner changes for bus names such as
- <literal>com.example.backend.foo</literal>,
- <literal>com.example.backend.foo.bar</literal>, and
- <literal>com.example.backend</literal> itself.</para>
+ <literal>com.example.backend1.foo</literal>,
+ <literal>com.example.backend1.foo.bar</literal>, and
+ <literal>com.example.backend1</literal> itself.</para>
<para>See also <xref linkend='bus-messages-name-owner-changed'/>.</para>
<para>
@@ -4888,23 +4644,44 @@
<row>
<entry><literal>eavesdrop</literal></entry>
<entry><literal>'true'</literal>, <literal>'false'</literal></entry>
- <entry>Since D-Bus 1.5.6, match rules do not
- match messages which have a <literal>DESTINATION</literal>
- field unless the match rule specifically
- requests this
- (see <xref linkend="message-bus-routing-eavesdropping"/>)
- by specifying <literal>eavesdrop='true'</literal>
- in the match rule. <literal>eavesdrop='false'</literal>
- restores the default behaviour. Messages are
- delivered to their <literal>DESTINATION</literal>
- regardless of match rules, so this match does not
- affect normal delivery of unicast messages.
- If the message bus has a security policy which forbids
- eavesdropping, this match may still be used without error,
- but will not have any practical effect.
- In older versions of D-Bus, this match was not allowed
- in match rules, and all match rules behaved as if
- <literal>eavesdrop='true'</literal> had been used.
+ <entry>
+ <para>
+ Since D-Bus 1.5.6, match rules do not
+ match messages which have a <literal>DESTINATION</literal>
+ field unless the match rule specifically
+ requests this
+ (see <xref linkend="message-bus-routing-eavesdropping"/>)
+ by specifying <literal>eavesdrop='true'</literal>
+ in the match rule. <literal>eavesdrop='false'</literal>
+ restores the default behaviour. Messages are
+ delivered to their <literal>DESTINATION</literal>
+ regardless of match rules, so this match does not
+ affect normal delivery of unicast messages.
+ In older versions of D-Bus, this match was not allowed
+ in match rules, and all match rules behaved as if
+ <literal>eavesdrop='true'</literal> had been used.
+ </para>
+ <para>
+ Use of <literal>eavesdrop='true'</literal> is
+ deprecated. Monitors should prefer to use the
+ <literal>BecomeMonitor</literal> method (see
+ <xref linkend="bus-messages-become-monitor"/>),
+ which was introduced in version 0.26 of the D-Bus
+ specification and version 1.9.10 of the reference
+ dbus-daemon.
+ </para>
+ <para>
+ Message bus implementations may restrict match rules
+ with <literal>eavesdrop='true'</literal> so that they
+ can only be added by privileged connections.
+ </para>
+ <para>
+ <emphasis>
+ This match key was added in version 0.18 of the
+ D-Bus specification and implemented by the bus
+ daemon in dbus 1.5.6 and later.
+ </emphasis>
+ </para>
</entry>
</row>
</tbody>
@@ -4914,22 +4691,48 @@
</sect3>
</sect2>
<sect2 id="message-bus-starting-services">
- <title>Message Bus Starting Services</title>
+ <title>Message Bus Starting Services (Activation)</title>
<para>
The message bus can start applications on behalf of other applications.
- In CORBA terms, this would be called <firstterm>activation</firstterm>.
+ This is referred to as <firstterm>service activation</firstterm> or
+ <firstterm>activation</firstterm>.
An application that can be started in this way is called a
- <firstterm>service</firstterm>.
+ <firstterm>service</firstterm> or an
+ <firstterm>activatable service</firstterm>.
+ </para>
+
+ <para>
+ <firstterm>Starting a service</firstterm> should be read as synonymous
+ with service activation.
+ </para>
+
+ <para>
+ In D-Bus, service activation is normally done by
+ <firstterm>auto-starting</firstterm>.
+ In auto-starting, applications send a
+ message to a particular well-known name, such as
+ <literal>com.example.TextEditor1</literal>, without specifying the
+ <literal>NO_AUTO_START</literal> flag in the message header.
+ If no application on the bus owns the requested name, but the bus
+ daemon does know how to start an activatable service for that name,
+ then the bus daemon will start that service, wait for it to request
+ that name, and deliver the message to it.
</para>
+
<para>
- With D-Bus, starting a service is normally done by name. That is,
- applications ask the message bus to start some program that will own a
- well-known name, such as <literal>com.example.TextEditor</literal>.
- This implies a contract documented along with the name
- <literal>com.example.TextEditor</literal> for which object
- the owner of that name will provide, and what interfaces those
+ It is also possible for applications to send an explicit request to
+ start a service: this is another form of activation, distinct from
+ auto-starting. See
+ <xref linkend="bus-messages-start-service-by-name"/> for details.
+ </para>
+
+ <para>
+ In either case, this implies a contract documented along with the name
+ <literal>com.example.TextEditor1</literal> for which object
+ the owner of that name will provide, and what interfaces those
objects will have.
</para>
+
<para>
To find an executable corresponding to a particular name, the bus daemon
looks for <firstterm>service description files</firstterm>. Service
@@ -4953,7 +4756,7 @@
On the well-known system bus, the name of a service description file
must be its well-known name plus <literal>.service</literal>,
for instance
- <literal>com.example.ConfigurationDatabase.service</literal>.
+ <literal>com.example.ConfigurationDatabase1.service</literal>.
</para>
<para>
@@ -4983,7 +4786,7 @@
<programlisting>
# Sample service description file
[D-BUS Service]
- Name=com.example.ConfigurationDatabase
+ Name=com.example.ConfigurationDatabase1
Exec=/usr/bin/sample-configd
</programlisting>
</figure>
@@ -5067,18 +4870,128 @@
only by name.
</para>
<para>
- Contrast this with a per-display scope. To achieve that, we would
+ Contrast this with a per-display scope. To achieve that, we would
want a single bus spanning all sessions using a given display.
- So we might set a <literal>_DBUS_DISPLAY_BUS_ADDRESS</literal>
+ So we might set a <literal>_DBUS_DISPLAY_BUS_ADDRESS</literal>
property on screen 0 of the display, pointing to this bus.
</para>
</sect3>
+
+ <sect3 id="message-bus-starting-services-systemd">
+ <title>systemd Activation</title>
+
+ <para>
+ Service description files may contain a
+ <literal>SystemdService</literal> key. Its value is the name of a
+ <ulink
+ url="https://www.freedesktop.org/wiki/Software/systemd/">systemd</ulink>
+ service, for example
+ <literal>dbus-com.example.MyDaemon.service</literal>.
+ </para>
+
+ <para>
+ If this key is present, the bus daemon may carry out activation for
+ this D-Bus service by sending a request to systemd asking it to
+ start the systemd service whose name is the value of
+ <literal>SystemdService</literal>. For example, the reference
+ <literal>dbus-daemon</literal> has a
+ <literal>--systemd-activation</literal> option that enables this
+ feature, and that option is given when it is started by systemd.
+ </para>
+
+ <para>
+ On the well-known system bus, it is a common practice to set
+ <literal>SystemdService</literal> to <literal>dbus-</literal>,
+ followed by the well-known bus name, followed by
+ <literal>.service</literal>, then register that name as an alias
+ for the real systemd service. This allows D-Bus activation of a
+ service to be enabled or disabled independently of whether the
+ service is started by systemd during boot.
+ </para>
+ </sect3>
+
+ <sect3 id="message-bus-starting-services-apparmor">
+ <title>Mediating Activation with AppArmor</title>
+
+ <para>
+ Please refer to
+ <ulink url="http://wiki.apparmor.net/index.php/Documentation">AppArmor documentation</ulink>
+ for general information on AppArmor, and how it mediates D-Bus
+ messages when used in conjunction with a kernel and
+ <literal>dbus-daemon</literal> that support this.
+ </para>
+
+ <para>
+ In recent versions of the reference <literal>dbus-daemon</literal>,
+ AppArmor policy rules of type <literal>dbus send</literal>
+ are also used to control auto-starting: if a message is sent to
+ the well-known name of an activatable service, the
+ <literal>dbus-daemon</literal> will attempt to determine whether
+ it would deliver the message to that service
+ <emphasis>before</emphasis>auto-starting it, by making some
+ assumptions about the resulting process's credentials.
+ </para>
+
+ <para>
+ If it does proceed with auto-starting, when the service appears, the
+ <literal>dbus-daemon</literal> repeats the policy check (with
+ the service's true credentials, which might not be identical)
+ before delivering the message. In practice, this second check will
+ usually be more strict than the first; the first check would only
+ be more strict if there are "blacklist"-style rules like
+ <literal>deny dbus send peer=(label=/usr/bin/protected)</literal>
+ that match on the peer's specific credentials, but AppArmor is
+ normally used in a "whitelist" style where this does not apply.
+ </para>
+
+ <para>
+ To support this process, service description files may contain a
+ <literal>AssumedAppArmorLabel</literal> key. Its value is the name
+ of an AppArmor label, for example
+ <literal>/usr/sbin/mydaemon</literal>.
+ If present, AppArmor mediation of messages that auto-start a
+ service will decide whether to allow auto-starting to occur based
+ on the assumption that the activated service will be confined
+ under the specified label; in particular, rules of the form
+ <literal>dbus send peer=(label=/usr/sbin/mydaemon)</literal> or
+ <literal>deny dbus send peer=(label=/usr/sbin/mydaemon)</literal>
+ will match it, allowing or denying as appropriate
+ (even if there is in fact no profile of that name loaded).
+ </para>
+
+ <para>
+ Otherwise, AppArmor mediation of messages that auto-start a
+ service will decide whether to allow auto-starting to occur
+ without specifying any particular label. In particular, any rule of
+ the form <literal>dbus send peer=(label=X)</literal> or
+ <literal>deny dbus send peer=(label=X)</literal>
+ (for any value of X, including the special label
+ <literal>unconfined</literal>) will not influence whether the
+ auto-start is allowed.
+ </para>
+
+ <para>
+ Rules of type <literal>dbus receive</literal> are not checked
+ when deciding whether to allow auto-starting; they are only checked
+ against the service's profile after the service has started, when
+ deciding whether to deliver the message that caused the auto-starting
+ operation.
+ </para>
+
+ <para>
+ Explicit activation via
+ <xref linkend="bus-messages-start-service-by-name"/> is not currently
+ affected by this mediation: if a confined process is to be prevented
+ from starting arbitrary services, then it must not be allowed to call
+ that method.
+ </para>
+ </sect3>
</sect2>
<sect2 id="message-bus-types">
<title>Well-known Message Bus Instances</title>
<para>
- Two standard message bus instances are defined here, along with how
+ Two standard message bus instances are defined here, along with how
to locate them and where their service files live.
</para>
<sect3 id="message-bus-types-login">
@@ -5089,13 +5002,13 @@
session may interact with one another using this message bus.
</para>
<para>
- The address of the login session message bus is given
- in the <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment
- variable. If that variable is not set, applications may
- also try to read the address from the X Window System root
+ The address of the login session message bus is given
+ in the <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment
+ variable. If that variable is not set, applications may
+ also try to read the address from the X Window System root
window property <literal>_DBUS_SESSION_BUS_ADDRESS</literal>.
The root window property must have type <literal>STRING</literal>.
- The environment variable should have precedence over the
+ The environment variable should have precedence over the
root window property.
</para>
<para>The address of the login session message bus is given in the
@@ -5306,18 +5219,14 @@
</para>
</sect4>
<sect4>
- <title></title>
+ <title>Finding session services</title>
<para>
On Unix systems, the session bus should search for .service files
in <literal>$XDG_DATA_DIRS/dbus-1/services</literal> as defined
by the
<ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG Base Directory Specification</ulink>.
- Implementations may also search additional locations, which
- should be searched with lower priority than anything in
- XDG_DATA_HOME, XDG_DATA_DIRS or their respective defaults;
- for example, the reference implementation also
- looks in <literal>${datadir}/dbus-1/services</literal> as
- set at compile time.
+ Implementations may also search additional locations,
+ with a higher or lower priority than the XDG directories.
</para>
<para>
As described in the XDG Base Directory Specification, software
@@ -5335,19 +5244,19 @@
<para>
A computer may have a <firstterm>system message bus</firstterm>,
accessible to all applications on the system. This message bus may be
- used to broadcast system events, such as adding new hardware devices,
+ used to broadcast system events, such as adding new hardware devices,
changes in the printer queue, and so forth.
</para>
<para>
- The address of the system message bus is given
- in the <literal>DBUS_SYSTEM_BUS_ADDRESS</literal> environment
- variable. If that variable is not set, applications should try
+ The address of the system message bus is given
+ in the <literal>DBUS_SYSTEM_BUS_ADDRESS</literal> environment
+ variable. If that variable is not set, applications should try
to connect to the well-known address
<literal>unix:path=/var/run/dbus/system_bus_socket</literal>.
<footnote>
<para>
- The D-Bus reference implementation actually honors the
- <literal>$(localstatedir)</literal> configure option
+ The D-Bus reference implementation actually honors the
+ <literal>$(localstatedir)</literal> configure option
for this address, on both client and server side.
</para>
</footnote>
@@ -5387,7 +5296,33 @@
<title>Message Bus Messages</title>
<para>
The special message bus name <literal>org.freedesktop.DBus</literal>
- responds to a number of additional messages.
+ responds to a number of additional messages at the object path
+ <literal>/org/freedesktop/DBus</literal>.
+ That object path is also used when emitting the
+ <xref linkend='bus-messages-name-owner-changed'/> signal.
+ </para>
+
+ <para>
+ For historical reasons, some of the methods in the
+ <literal>org.freedesktop.DBus</literal> interface are available
+ on multiple object paths. Message bus implementations should
+ accept method calls that were added before specification version
+ 0.26 on any object path. Message bus implementations should
+ not accept newer method calls on unexpected object paths,
+ and as a security hardening measure, older method calls
+ that are security-sensitive may be rejected with the error
+ <literal>org.freedesktop.DBus.Error.AccessDenied</literal> when
+ called on an unexpected object path. Client software should send
+ all method calls to <literal>/org/freedesktop/DBus</literal>
+ instead of relying on this.
+ </para>
+
+ <para>
+ In addition to the method calls listed below, the message bus
+ should implement the standard Introspectable, Properties and Peer
+ interfaces (see <xref linkend="standard-interfaces"/>).
+ Support for the Properties and Peer interfaces was added in version
+ 1.11.x of the reference implementation of the message bus.
</para>
<sect3 id="bus-messages-hello">
@@ -5428,10 +5363,396 @@
</para>
<para>
There is no corresponding "disconnect" request; if a client wishes to
- disconnect from the bus, it simply closes the socket (or other
+ disconnect from the bus, it simply closes the socket (or other
communication channel).
</para>
</sect3>
+
+ <sect3 id="bus-messages-request-name">
+ <title><literal>org.freedesktop.DBus.RequestName</literal></title>
+ <para>
+ As a method:
+ <programlisting>
+ UINT32 RequestName (in STRING name, in UINT32 flags)
+ </programlisting>
+ Message arguments:
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Argument</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>STRING</entry>
+ <entry>Name to request</entry>
+ </row>
+ <row>
+ <entry>1</entry>
+ <entry>UINT32</entry>
+ <entry>Flags</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ Reply arguments:
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Argument</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>UINT32</entry>
+ <entry>Return value</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ <para>
+ Ask the message bus to assign the given name to the method caller. Each
+ name maintains a queue of possible owners, where the head of the queue is
+ the primary or current owner of the name. Each potential owner in the
+ queue maintains the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and
+ DBUS_NAME_FLAG_DO_NOT_QUEUE settings from its latest RequestName call.
+ When RequestName is invoked the following occurs:
+ <itemizedlist>
+ <listitem>
+ <para>
+ If the method caller is currently the primary owner of the name,
+ the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and DBUS_NAME_FLAG_DO_NOT_QUEUE
+ values are updated with the values from the new RequestName call,
+ and nothing further happens.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ If the current primary owner (head of the queue) has
+ DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, and the RequestName
+ invocation has the DBUS_NAME_FLAG_REPLACE_EXISTING flag, then
+ the caller of RequestName replaces the current primary owner at
+ the head of the queue and the current primary owner moves to the
+ second position in the queue. If the caller of RequestName was
+ in the queue previously its flags are updated with the values from
+ the new RequestName in addition to moving it to the head of the queue.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ If replacement is not possible, and the method caller is
+ currently in the queue but not the primary owner, its flags are
+ updated with the values from the new RequestName call.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ If replacement is not possible, and the method caller is
+ currently not in the queue, the method caller is appended to the
+ queue.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ If any connection in the queue has DBUS_NAME_FLAG_DO_NOT_QUEUE
+ set and is not the primary owner, it is removed from the
+ queue. This can apply to the previous primary owner (if it
+ was replaced) or the method caller (if it updated the
+ DBUS_NAME_FLAG_DO_NOT_QUEUE flag while still stuck in the
+ queue, or if it was just added to the queue with that flag set).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Note that DBUS_NAME_FLAG_REPLACE_EXISTING results in "jumping the
+ queue," even if another application already in the queue had specified
+ DBUS_NAME_FLAG_REPLACE_EXISTING. This comes up if a primary owner
+ that does not allow replacement goes away, and the next primary owner
+ does allow replacement. In this case, queued items that specified
+ DBUS_NAME_FLAG_REPLACE_EXISTING <emphasis>do not</emphasis>
+ automatically replace the new primary owner. In other words,
+ DBUS_NAME_FLAG_REPLACE_EXISTING is not saved, it is only used at the
+ time RequestName is called. This is deliberate to avoid an infinite loop
+ anytime two applications are both DBUS_NAME_FLAG_ALLOW_REPLACEMENT
+ and DBUS_NAME_FLAG_REPLACE_EXISTING.
+ </para>
+ <para>
+ The flags argument contains any of the following values logically ORed
+ together:
+
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Conventional Name</entry>
+ <entry>Value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>DBUS_NAME_FLAG_ALLOW_REPLACEMENT</entry>
+ <entry>0x1</entry>
+ <entry>
+
+ If an application A specifies this flag and succeeds in
+ becoming the owner of the name, and another application B
+ later calls RequestName with the
+ DBUS_NAME_FLAG_REPLACE_EXISTING flag, then application A
+ will lose ownership and receive a
+ <literal>org.freedesktop.DBus.NameLost</literal> signal, and
+ application B will become the new owner. If DBUS_NAME_FLAG_ALLOW_REPLACEMENT
+ is not specified by application A, or DBUS_NAME_FLAG_REPLACE_EXISTING
+ is not specified by application B, then application B will not replace
+ application A as the owner.
+
+ </entry>
+ </row>
+ <row>
+ <entry>DBUS_NAME_FLAG_REPLACE_EXISTING</entry>
+ <entry>0x2</entry>
+ <entry>
+
+ Try to replace the current owner if there is one. If this
+ flag is not set the application will only become the owner of
+ the name if there is no current owner. If this flag is set,
+ the application will replace the current owner if
+ the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT.
+
+ </entry>
+ </row>
+ <row>
+ <entry>DBUS_NAME_FLAG_DO_NOT_QUEUE</entry>
+ <entry>0x4</entry>
+ <entry>
+
+ Without this flag, if an application requests a name that is
+ already owned, the application will be placed in a queue to
+ own the name when the current owner gives it up. If this
+ flag is given, the application will not be placed in the
+ queue, the request for the name will simply fail. This flag
+ also affects behavior when an application is replaced as
+ name owner; by default the application moves back into the
+ waiting queue, unless this flag was provided when the application
+ became the name owner.
+
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ The return code can be one of the following values:
+
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Conventional Name</entry>
+ <entry>Value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER</entry>
+ <entry>1</entry> <entry>The caller is now the primary owner of
+ the name, replacing any previous owner. Either the name had no
+ owner before, or the caller specified
+ DBUS_NAME_FLAG_REPLACE_EXISTING and the current owner specified
+ DBUS_NAME_FLAG_ALLOW_REPLACEMENT.</entry>
+ </row>
+ <row>
+ <entry>DBUS_REQUEST_NAME_REPLY_IN_QUEUE</entry>
+ <entry>2</entry>
+
+ <entry>The name already had an owner,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified, and either
+ the current owner did not specify
+ DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the requesting
+ application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING.
+ </entry>
+ </row>
+ <row>
+ <entry>DBUS_REQUEST_NAME_REPLY_EXISTS</entry> <entry>3</entry>
+ <entry>The name already has an owner,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE was specified, and either
+ DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the
+ current owner, or DBUS_NAME_FLAG_REPLACE_EXISTING was not
+ specified by the requesting application.</entry>
+ </row>
+ <row>
+ <entry>DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER</entry>
+ <entry>4</entry>
+ <entry>The application trying to request ownership of a name is already the owner of it.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect3>
+
+ <sect3 id="bus-messages-release-name">
+ <title><literal>org.freedesktop.DBus.ReleaseName</literal></title>
+ <para>
+ As a method:
+ <programlisting>
+ UINT32 ReleaseName (in STRING name)
+ </programlisting>
+ Message arguments:
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Argument</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>STRING</entry>
+ <entry>Name to release</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ Reply arguments:
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Argument</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>UINT32</entry>
+ <entry>Return value</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ <para>
+ Ask the message bus to release the method caller's claim to the given
+ name. If the caller is the primary owner, a new primary owner will be
+ selected from the queue if any other owners are waiting. If the
+ caller is waiting in the queue for the name, the caller will removed
+ from the queue and will not be made an owner of the name if it later
+ becomes available. If there are no other owners in the queue for the
+ name, it will be removed from the bus entirely.
+
+ The return code can be one of the following values:
+
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Conventional Name</entry>
+ <entry>Value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>DBUS_RELEASE_NAME_REPLY_RELEASED</entry>
+ <entry>1</entry> <entry>The caller has released his claim on
+ the given name. Either the caller was the primary owner of
+ the name, and the name is now unused or taken by somebody
+ waiting in the queue for the name, or the caller was waiting
+ in the queue for the name and has now been removed from the
+ queue.</entry>
+ </row>
+ <row>
+ <entry>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</entry>
+ <entry>2</entry>
+ <entry>The given name does not exist on this bus.</entry>
+ </row>
+ <row>
+ <entry>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</entry>
+ <entry>3</entry>
+ <entry>The caller was not the primary owner of this name,
+ and was also not waiting in the queue to own this name.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect3>
+
+ <sect3 id="bus-messages-list-queued-owners">
+ <title><literal>org.freedesktop.DBus.ListQueuedOwners</literal></title>
+ <para>
+ As a method:
+ <programlisting>
+ ARRAY of STRING ListQueuedOwners (in STRING name)
+ </programlisting>
+ Message arguments:
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Argument</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>STRING</entry>
+ <entry>The well-known bus name to query, such as
+ <literal>com.example.cappuccino</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ Reply arguments:
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Argument</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>ARRAY of STRING</entry>
+ <entry>The unique bus names of connections currently queued
+ for the name</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ <para>
+ List the connections currently queued for a bus name (see
+ <xref linkend="term-queued-owner"/>).
+ </para>
+ </sect3>
+
<sect3 id="bus-messages-list-names">
<title><literal>org.freedesktop.DBus.ListNames</literal></title>
<para>
@@ -5584,7 +5905,7 @@
</para>
<para>
This signal indicates that the owner of a name has changed.
- It's also the signal to use to detect the appearance of
+ It's also the signal to use to detect the appearance of
new names on the bus.
</para>
</sect3>
@@ -5704,8 +6025,27 @@
</tbody>
</tgroup>
</informaltable>
- Tries to launch the executable associated with a name. For more information, see <xref linkend="message-bus-starting-services"/>.
-
+ Tries to launch the executable associated with a name (service
+ activation), as an explicit request. This is an alternative to
+ relying on auto-starting. For more information on how services
+ are activated and the difference between auto-starting and explicit
+ activation, see
+ <xref linkend="message-bus-starting-services"/>.
+ </para>
+ <para>
+ It is often preferable to carry out auto-starting
+ instead of calling this method. This is because calling this method
+ is subject to a
+ <ulink url="https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use">time-of-check/time-of-use</ulink>
+ issue: if a caller asks the message bus to start a service so that
+ the same caller can make follow-up method calls to that service,
+ the fact that the message bus was able to start the required
+ service is no guarantee that it will not have crashed or otherwise
+ exited by the time the caller makes those follow-up method calls.
+ As a result, calling this method does not remove the need for
+ the caller to handle errors from method calls. Given that fact,
+ it is usually simpler to rely on auto-starting, in which the
+ required service starts as a side-effect of the first method call.
</para>
<para>
The return value can be one of the following values:
@@ -6233,7 +6573,7 @@
</tbody>
</tgroup>
</informaltable>
- Adds a match rule to match messages going through the message bus (see <xref linkend='message-bus-routing-match-rules'/>).
+ Adds a match rule to match messages going through the message bus (see <xref linkend='message-bus-routing-match-rules'/>).
If the bus does not have enough resources the <literal>org.freedesktop.DBus.Error.OOM</literal>
error is returned.
</para>
@@ -6264,7 +6604,7 @@
</tbody>
</tgroup>
</informaltable>
- Removes the first rule that matches (see <xref linkend='message-bus-routing-match-rules'/>).
+ Removes the first rule that matches (see <xref linkend='message-bus-routing-match-rules'/>).
If the rule is not found the <literal>org.freedesktop.DBus.Error.MatchRuleNotFound</literal>
error is returned.
</para>
@@ -6296,9 +6636,9 @@
</tbody>
</tgroup>
</informaltable>
- Gets the unique ID of the bus. The unique ID here is shared among all addresses the
- bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in
- <xref linkend="uuids"/>. Each address the bus is listening on also has its own unique
+ Gets the unique ID of the bus. The unique ID here is shared among all addresses the
+ bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in
+ <xref linkend="uuids"/>. Each address the bus is listening on also has its own unique
ID, as described in <xref linkend="addresses"/>. The per-bus and per-address IDs are not related.
There is also a per-machine ID, described in <xref linkend="standard-interfaces-peer"/> and returned
by org.freedesktop.DBus.Peer.GetMachineId().
@@ -6398,6 +6738,122 @@
</sect2>
+ <sect2 id="message-bus-properties">
+ <title>Message Bus Properties</title>
+ <para>
+ The special message bus name <literal>org.freedesktop.DBus</literal>
+ exports several properties (see
+ <xref linkend="standard-interfaces-properties"/>) on the object path
+ <literal>/org/freedesktop/DBus</literal>.
+ </para>
+
+ <sect3 id="message-bus-properties-features">
+ <title><literal>org.freedesktop.DBus.Features</literal></title>
+ <para>
+ As a property:
+ <programlisting>
+ Read-only constant ARRAY of STRING Features
+ </programlisting>
+ This property lists abstract “features” provided by the message
+ bus, and can be used by clients to detect the capabilities
+ of the message bus with which they are communicating.
+ This property was added in version 1.11.x of the reference
+ implementation of the message bus.
+ </para>
+
+ <para>
+ Items in the returned array not containing “.” are defined
+ by this specification. Bus daemon implementors wishing to advertise
+ features not mentioned in this document should either contribute
+ patches to this specification, or use keys containing “.” and
+ starting with their own reversed domain name, for example
+ <literal>com.example.MyBus.SubliminalMessages</literal>.
+ </para>
+
+ <para>
+ The features currently defined in this specification are as follows:
+ <variablelist>
+
+ <varlistentry>
+ <term><literal>AppArmor</literal></term>
+ <listitem>
+ <para>
+ This message bus filters messages via the
+ <ulink url="http://wiki.apparmor.net/">AppArmor</ulink>
+ security framework. This feature should only be
+ advertised if AppArmor mediation is enabled and
+ active at runtime; merely compiling in support
+ for AppArmor should not result in this feature being
+ advertised on message bus instances where it is disabled by
+ message bus or operating system configuration.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>SELinux</literal></term>
+ <listitem>
+ <para>
+ This message bus filters messages via the
+ <ulink url="https://selinuxproject.org/">SELinux</ulink>
+ security framework. Similar to <literal>apparmor</literal>,
+ this feature should only be advertised if SELinux mediation
+ is enabled and active at runtime (if SELinux is placed in
+ permissive mode, that is still considered to be active).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>SystemdActivation</literal></term>
+ <listitem>
+ <para>
+ When asked to activate a service that has the
+ <literal>SystemdService</literal> field in its
+ <filename>.service</filename> file, this message bus will
+ carry out systemd activation (for details see
+ <xref linkend="message-bus-starting-services-systemd"/>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </sect3>
+
+ <sect3 id="message-bus-properties-interfaces">
+ <title><literal>org.freedesktop.DBus.Interfaces</literal></title>
+ <para>
+ As a property:
+ <programlisting>
+ Read-only constant ARRAY of STRING Interfaces
+ </programlisting>
+ This property lists interfaces provided by the
+ <literal>/org/freedesktop/DBus</literal> object,
+ and can be used by clients to detect the capabilities
+ of the message bus with which they are communicating.
+ Unlike the standard Introspectable interface, querying this
+ property does not require parsing XML.
+ This property was added in version 1.11.x of the reference
+ implementation of the message bus.
+ </para>
+
+ <para>
+ The standard <literal>org.freedesktop.DBus</literal> and
+ <literal>org.freedesktop.DBus.Properties</literal> interfaces
+ are not included in the value of this property, because their
+ presence can be inferred from the fact that a method call on
+ <literal>org.freedesktop.DBus.Properties</literal> asking for
+ properties of <literal>org.freedesktop.DBus</literal> was
+ successful. The standard <literal>org.freedesktop.DBus.Peer</literal>
+ and <literal>org.freedesktop.DBus.Introspectable</literal>
+ interfaces are not included in the value of this property either,
+ because they do not indicate features of the message bus
+ implementation.
+ </para>
+ </sect3>
+ </sect2>
+
</sect1>
<!--
<appendix id="implementation-notes">
@@ -6427,9 +6883,9 @@
name if the message bus has associated the application's connection
with the name. Names may also have <firstterm>queued
owners</firstterm> (see <xref linkend="term-queued-owner"/>).
- The bus assigns a unique name to each connection,
- see <xref linkend="term-unique-name"/>. Other names
- can be thought of as "well-known names" and are
+ The bus assigns a unique name to each connection,
+ see <xref linkend="term-unique-name"/>. Other names
+ can be thought of as "well-known names" and are
used to find applications that offer specific functionality.
</para>
@@ -6439,7 +6895,7 @@
</para>
</glossdef>
</glossentry>
-
+
<glossentry id="term-message"><glossterm>Message</glossterm>
<glossdef>
<para>
@@ -6454,9 +6910,9 @@
<glossentry id="term-message-bus"><glossterm>Message Bus</glossterm>
<glossdef>
<para>
- The message bus is a special application that forwards
+ The message bus is a special application that forwards
or routes messages between a group of applications
- connected to the message bus. It also manages
+ connected to the message bus. It also manages
<firstterm>names</firstterm> used for routing
messages.
</para>
@@ -6466,7 +6922,7 @@
<glossentry id="term-name"><glossterm>Name</glossterm>
<glossdef>
<para>
- See <xref linkend="term-bus-name"/>. "Name" may
+ See <xref linkend="term-bus-name"/>. "Name" may
also be used to refer to some of the other names
in D-Bus, such as interface names.
</para>
@@ -6539,9 +6995,9 @@
A service is an executable that can be launched by the bus daemon.
Services normally guarantee some particular features, for example they
may guarantee that they will request a specific name such as
- "com.example.Screensaver", have a singleton object
- "/com/example/Application", and that object will implement the
- interface "com.example.Screensaver.Control".
+ "com.example.Screensaver1", have a singleton object
+ "/com/example/Screensaver1", and that object will implement the
+ interface "com.example.Screensaver1.Control".
</para>
</glossdef>
</glossentry>
diff --git a/doc/dbus-test-tool.1.xml.in b/doc/dbus-test-tool.1.xml.in
index 091dee14..5b7c43ed 100644
--- a/doc/dbus-test-tool.1.xml.in
+++ b/doc/dbus-test-tool.1.xml.in
@@ -45,7 +45,7 @@
<arg choice="plain">--system</arg>
</group>
<arg choice="opt">--name=<replaceable>NAME</replaceable></arg>
- <arg choice="opt">--sleep=<replaceable>MS</replaceable></arg>
+ <arg choice="opt">--sleep-ms=<replaceable>MS</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
@@ -161,7 +161,7 @@
</varlistentry>
<varlistentry>
- <term><option>--sleep=</option><replaceable>MS</replaceable></term>
+ <term><option>--sleep-ms=</option><replaceable>MS</replaceable></term>
<listitem>
<para>Block for <replaceable>MS</replaceable> milliseconds
before replying to a method call.</para>
diff --git a/doc/doxygen_to_devhelp.xsl b/doc/doxygen_to_devhelp.xsl
index 72098f9f..fd33bcee 100644
--- a/doc/doxygen_to_devhelp.xsl
+++ b/doc/doxygen_to_devhelp.xsl
@@ -10,7 +10,13 @@
<xsl:template match="/">
<book title="D-Bus: A system for interprocess communication"
name="dbus"
- link="dbus-tutorial.html">
+ link="{$prefix}/api/index.html"
+ xmlns="http://www.devhelp.net/book"
+ version="2"
+ online="https://dbus.freedesktop.org/doc/"
+ author="D-Bus contributors"
+ language="c"
+ >
<chapters>
<sub name="Tutorial" link="{$prefix}dbus-tutorial.html"/>
<sub name="FAQ" link="{$prefix}dbus-faq.html"/>
@@ -32,7 +38,7 @@
<xsl:param name="link"><xsl:value-of select="$before"/>.html#<xsl:value-of select="$after"/></xsl:param>
<xsl:if test="starts-with($name,'dbus') or starts-with($name, 'DBus')">
<xsl:if test="starts-with($refid,'group__') and contains($refid, '_1')">
- <function name="{$name}" link="{$prefix}api/{$link}"/>
+ <keyword xmlns="http://www.devhelp.net/book" type="function" name="{$name}" link="{$prefix}api/{$link}"/>
</xsl:if>
</xsl:if>
</xsl:template>
diff --git a/doc/introspect.dtd b/doc/introspect.dtd
index ba263d32..4d396f98 100644
--- a/doc/introspect.dtd
+++ b/doc/introspect.dtd
@@ -16,7 +16,7 @@
<!ELEMENT signal (arg|annotation)*>
<!ATTLIST signal name CDATA #REQUIRED>
-<!ELEMENT arg EMPTY>
+<!ELEMENT arg (annotation)*>
<!ATTLIST arg name CDATA #IMPLIED>
<!ATTLIST arg type CDATA #REQUIRED>
<!-- Method arguments SHOULD include "direction",
diff --git a/doc/introspect.xsl b/doc/introspect.xsl
index 2a344741..89b68441 100644
--- a/doc/introspect.xsl
+++ b/doc/introspect.xsl
@@ -80,6 +80,12 @@
<span class="type"><xsl:value-of select="@type"/></span><xsl:text> </xsl:text>
<span class="symbol"><xsl:value-of select="@name"/></span><xsl:text> </xsl:text>
+
+ <xsl:if test="annotation">
+ <ul>
+ <xsl:apply-templates select="annotation"/>
+ </ul>
+ </xsl:if>
</li>
</xsl:for-each>
</ul>
@@ -97,7 +103,7 @@
<xsl:template match="annotation">
<li>
- <span class="keyword">annotation</span>
+ <span class="keyword">annotation</span><xsl:text> </xsl:text>
<code><xsl:value-of select="@name"/></code><xsl:text> = </xsl:text>
<code><xsl:value-of select="@value"/></code>
</li>
diff --git a/doc/system-activation.txt b/doc/system-activation.txt
index dd195f75..dde648e8 100644
--- a/doc/system-activation.txt
+++ b/doc/system-activation.txt
@@ -46,7 +46,8 @@ Exec=/usr/sbin/dbus-test-server.py
User=ftp
This gives the user to switch to, and also the path of the executable.
-The service name must match that specified in the /etc/dbus-1/system.d conf file.
+The service name must match that specified in the /etc/dbus-1/system.d or
+/usr/share/dbus-1/system.d conf file.
Precautions taken:
diff --git a/m4/ax_ac_append_to_file.m4 b/m4/ax_ac_append_to_file.m4
new file mode 100644
index 00000000..242b3d52
--- /dev/null
+++ b/m4/ax_ac_append_to_file.m4
@@ -0,0 +1,32 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_ac_append_to_file.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_AC_APPEND_TO_FILE([FILE],[DATA])
+#
+# DESCRIPTION
+#
+# Appends the specified data to the specified Autoconf is run. If you want
+# to append to a file when configure is run use AX_APPEND_TO_FILE instead.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 10
+
+AC_DEFUN([AX_AC_APPEND_TO_FILE],[
+AC_REQUIRE([AX_FILE_ESCAPES])
+m4_esyscmd(
+AX_FILE_ESCAPES
+[
+printf "%s" "$2" >> "$1"
+])
+])
diff --git a/m4/ax_ac_print_to_file.m4 b/m4/ax_ac_print_to_file.m4
new file mode 100644
index 00000000..642dfc15
--- /dev/null
+++ b/m4/ax_ac_print_to_file.m4
@@ -0,0 +1,32 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_ac_print_to_file.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_AC_PRINT_TO_FILE([FILE],[DATA])
+#
+# DESCRIPTION
+#
+# Writes the specified data to the specified file when Autoconf is run. If
+# you want to print to a file when configure is run use AX_PRINT_TO_FILE
+# instead.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 10
+
+AC_DEFUN([AX_AC_PRINT_TO_FILE],[
+m4_esyscmd(
+AC_REQUIRE([AX_FILE_ESCAPES])
+[
+printf "%s" "$2" > "$1"
+])
+])
diff --git a/m4/ax_add_am_macro_static.m4 b/m4/ax_add_am_macro_static.m4
new file mode 100644
index 00000000..6442d24b
--- /dev/null
+++ b/m4/ax_add_am_macro_static.m4
@@ -0,0 +1,28 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_add_am_macro_static.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_ADD_AM_MACRO_STATIC([RULE])
+#
+# DESCRIPTION
+#
+# Adds the specified rule to $AMINCLUDE.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Tom Howard <tomhoward@users.sf.net>
+# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 8
+
+AC_DEFUN([AX_ADD_AM_MACRO_STATIC],[
+ AC_REQUIRE([AX_AM_MACROS_STATIC])
+ AX_AC_APPEND_TO_FILE(AMINCLUDE_STATIC,[$1])
+])
diff --git a/m4/ax_am_macros_static.m4 b/m4/ax_am_macros_static.m4
new file mode 100644
index 00000000..f4cee8c8
--- /dev/null
+++ b/m4/ax_am_macros_static.m4
@@ -0,0 +1,38 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_am_macros_static.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_AM_MACROS_STATIC
+#
+# DESCRIPTION
+#
+# Adds support for macros that create Automake rules. You must manually
+# add the following line
+#
+# include $(top_srcdir)/aminclude_static.am
+#
+# to your Makefile.am files.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Tom Howard <tomhoward@users.sf.net>
+# Copyright (c) 2009 Allan Caffee <allan.caffee@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 11
+
+AC_DEFUN([AMINCLUDE_STATIC],[aminclude_static.am])
+
+AC_DEFUN([AX_AM_MACROS_STATIC],
+[
+AX_AC_PRINT_TO_FILE(AMINCLUDE_STATIC,[
+# ]AMINCLUDE_STATIC[ generated automatically by Autoconf
+# from AX_AM_MACROS_STATIC on ]m4_esyscmd([LC_ALL=C date])[
+])
+])
diff --git a/m4/ax_code_coverage.m4 b/m4/ax_code_coverage.m4
new file mode 100644
index 00000000..3d36924b
--- /dev/null
+++ b/m4/ax_code_coverage.m4
@@ -0,0 +1,272 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CODE_COVERAGE()
+#
+# DESCRIPTION
+#
+# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS,
+# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included
+# in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every
+# build target (program or library) which should be built with code
+# coverage support. Also add rules using AX_ADD_AM_MACRO_STATIC; and
+# $enable_code_coverage which can be used in subsequent configure output.
+# CODE_COVERAGE_ENABLED is defined and substituted, and corresponds to the
+# value of the --enable-code-coverage option, which defaults to being
+# disabled.
+#
+# Test also for gcov program and create GCOV variable that could be
+# substituted.
+#
+# Note that all optimization flags in CFLAGS must be disabled when code
+# coverage is enabled.
+#
+# Usage example:
+#
+# configure.ac:
+#
+# AX_CODE_COVERAGE
+#
+# Makefile.am:
+#
+# include $(top_srcdir)/aminclude_static.am
+#
+# my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ...
+# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ...
+# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ...
+# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ...
+#
+# clean-local: code-coverage-clean
+# distclean-local: code-coverage-dist-clean
+#
+# This results in a "check-code-coverage" rule being added to any
+# Makefile.am which do "include $(top_srcdir)/aminclude_static.am"
+# (assuming the module has been configured with --enable-code-coverage).
+# Running `make check-code-coverage` in that directory will run the
+# module's test suite (`make check`) and build a code coverage report
+# detailing the code which was touched, then print the URI for the report.
+#
+# This code was derived from Makefile.decl in GLib, originally licensed
+# under LGPLv2.1+.
+#
+# LICENSE
+#
+# Copyright (c) 2012, 2016 Philip Withnall
+# Copyright (c) 2012 Xan Lopez
+# Copyright (c) 2012 Christian Persch
+# Copyright (c) 2012 Paolo Borelli
+# Copyright (c) 2012 Dan Winship
+# Copyright (c) 2015,2018 Bastien ROUCARIES
+#
+# This library is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or (at
+# your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+#serial 32
+
+m4_define(_AX_CODE_COVERAGE_RULES,[
+AX_ADD_AM_MACRO_STATIC([
+# Code coverage
+#
+# Optional:
+# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
+# Multiple directories may be specified, separated by whitespace.
+# (Default: \$(top_builddir))
+# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
+# by lcov for code coverage. (Default:
+# \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info)
+# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
+# reports to be created. (Default:
+# \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage)
+# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
+# set to 0 to disable it and leave empty to stay with the default.
+# (Default: empty)
+# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
+# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
+# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
+# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
+# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
+# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
+# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
+# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
+# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
+# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
+# lcov instance. (Default: empty)
+# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
+# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
+# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
+# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
+# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
+# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
+# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
+#
+# The generated report will be titled using the \$(PACKAGE_NAME) and
+# \$(PACKAGE_VERSION). In order to add the current git hash to the title,
+# use the git-version-gen script, available online.
+# Optional variables
+# run only on top dir
+if CODE_COVERAGE_ENABLED
+ ifeq (\$(abs_builddir), \$(abs_top_builddir))
+CODE_COVERAGE_DIRECTORY ?= \$(top_builddir)
+CODE_COVERAGE_OUTPUT_FILE ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage.info
+CODE_COVERAGE_OUTPUT_DIRECTORY ?= \$(PACKAGE_NAME)-\$(PACKAGE_VERSION)-coverage
+
+CODE_COVERAGE_BRANCH_COVERAGE ?=
+CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= \$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\
+--rc lcov_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE))
+CODE_COVERAGE_LCOV_SHOPTS ?= \$(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
+CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool \"\$(GCOV)\"
+CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= \$(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
+CODE_COVERAGE_LCOV_OPTIONS ?= \$(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
+CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
+CODE_COVERAGE_LCOV_RMOPTS ?= \$(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
+CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\
+\$(if \$(CODE_COVERAGE_BRANCH_COVERAGE),\
+--rc genhtml_branch_coverage=\$(CODE_COVERAGE_BRANCH_COVERAGE))
+CODE_COVERAGE_GENHTML_OPTIONS ?= \$(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
+CODE_COVERAGE_IGNORE_PATTERN ?=
+
+GITIGNOREFILES = \$(GITIGNOREFILES) \$(CODE_COVERAGE_OUTPUT_FILE) \$(CODE_COVERAGE_OUTPUT_DIRECTORY)
+code_coverage_v_lcov_cap = \$(code_coverage_v_lcov_cap_\$(V))
+code_coverage_v_lcov_cap_ = \$(code_coverage_v_lcov_cap_\$(AM_DEFAULT_VERBOSITY))
+code_coverage_v_lcov_cap_0 = @echo \" LCOV --capture\" \$(CODE_COVERAGE_OUTPUT_FILE);
+code_coverage_v_lcov_ign = \$(code_coverage_v_lcov_ign_\$(V))
+code_coverage_v_lcov_ign_ = \$(code_coverage_v_lcov_ign_\$(AM_DEFAULT_VERBOSITY))
+code_coverage_v_lcov_ign_0 = @echo \" LCOV --remove /tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN);
+code_coverage_v_genhtml = \$(code_coverage_v_genhtml_\$(V))
+code_coverage_v_genhtml_ = \$(code_coverage_v_genhtml_\$(AM_DEFAULT_VERBOSITY))
+code_coverage_v_genhtml_0 = @echo \" GEN \" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\";
+code_coverage_quiet = \$(code_coverage_quiet_\$(V))
+code_coverage_quiet_ = \$(code_coverage_quiet_\$(AM_DEFAULT_VERBOSITY))
+code_coverage_quiet_0 = --quiet
+
+# sanitizes the test-name: replaces with underscores: dashes and dots
+code_coverage_sanitize = \$(subst -,_,\$(subst .,_,\$(1)))
+
+# Use recursive makes in order to ignore errors during check
+check-code-coverage:
+ -\$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) -k check
+ \$(AM_V_at)\$(MAKE) \$(AM_MAKEFLAGS) code-coverage-capture
+
+# Capture code coverage data
+code-coverage-capture: code-coverage-capture-hook
+ \$(code_coverage_v_lcov_cap)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --capture --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" --test-name \"\$(call code_coverage_sanitize,\$(PACKAGE_NAME)-\$(PACKAGE_VERSION))\" --no-checksum --compat-libtool \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_OPTIONS)
+ \$(code_coverage_v_lcov_ign)\$(LCOV) \$(code_coverage_quiet) \$(addprefix --directory ,\$(CODE_COVERAGE_DIRECTORY)) --remove \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"/tmp/*\" \$(CODE_COVERAGE_IGNORE_PATTERN) --output-file \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_LCOV_SHOPTS) \$(CODE_COVERAGE_LCOV_RMOPTS)
+ -@rm -f \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\"
+ \$(code_coverage_v_genhtml)LANG=C \$(GENHTML) \$(code_coverage_quiet) \$(addprefix --prefix ,\$(CODE_COVERAGE_DIRECTORY)) --output-directory \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\" --title \"\$(PACKAGE_NAME)-\$(PACKAGE_VERSION) Code Coverage\" --legend --show-details \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \$(CODE_COVERAGE_GENHTML_OPTIONS)
+ @echo \"file://\$(abs_builddir)/\$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html\"
+
+code-coverage-clean:
+ -\$(LCOV) --directory \$(top_builddir) -z
+ -rm -rf \"\$(CODE_COVERAGE_OUTPUT_FILE)\" \"\$(CODE_COVERAGE_OUTPUT_FILE).tmp\" \"\$(CODE_COVERAGE_OUTPUT_DIRECTORY)\"
+ -find . \\( -name \"*.gcda\" -o -name \"*.gcno\" -o -name \"*.gcov\" \\) -delete
+
+code-coverage-dist-clean:
+
+A][M_DISTCHECK_CONFIGURE_FLAGS = \$(A][M_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage
+ else # ifneq (\$(abs_builddir), \$(abs_top_builddir))
+check-code-coverage:
+
+code-coverage-capture: code-coverage-capture-hook
+
+code-coverage-clean:
+
+code-coverage-dist-clean:
+ endif # ifeq (\$(abs_builddir), \$(abs_top_builddir))
+else #! CODE_COVERAGE_ENABLED
+# Use recursive makes in order to ignore errors during check
+check-code-coverage:
+ @echo \"Need to reconfigure with --enable-code-coverage\"
+# Capture code coverage data
+code-coverage-capture: code-coverage-capture-hook
+ @echo \"Need to reconfigure with --enable-code-coverage\"
+
+code-coverage-clean:
+
+code-coverage-dist-clean:
+
+endif #CODE_COVERAGE_ENABLED
+# Hook rule executed before code-coverage-capture, overridable by the user
+code-coverage-capture-hook:
+
+.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook
+])
+])
+
+AC_DEFUN([_AX_CODE_COVERAGE_ENABLED],[
+ AX_CHECK_GNU_MAKE([],[AC_MSG_ERROR([not using GNU make that is needed for coverage])])
+ AC_REQUIRE([AX_ADD_AM_MACRO_STATIC])
+ # check for gcov
+ AC_CHECK_TOOL([GCOV],
+ [$_AX_CODE_COVERAGE_GCOV_PROG_WITH],
+ [:])
+ AS_IF([test "X$GCOV" = "X:"],
+ [AC_MSG_ERROR([gcov is needed to do coverage])])
+ AC_SUBST([GCOV])
+
+ dnl Check if gcc is being used
+ AS_IF([ test "$GCC" = "no" ], [
+ AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
+ ])
+
+ AC_CHECK_PROG([LCOV], [lcov], [lcov])
+ AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
+
+ AS_IF([ test x"$LCOV" = x ], [
+ AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed])
+ ])
+
+ AS_IF([ test x"$GENHTML" = x ], [
+ AC_MSG_ERROR([Could not find genhtml from the lcov package])
+ ])
+
+ dnl Build the code coverage flags
+ dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility
+ CODE_COVERAGE_CPPFLAGS="-DNDEBUG"
+ CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
+ CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
+ CODE_COVERAGE_LIBS="-lgcov"
+
+ AC_SUBST([CODE_COVERAGE_CPPFLAGS])
+ AC_SUBST([CODE_COVERAGE_CFLAGS])
+ AC_SUBST([CODE_COVERAGE_CXXFLAGS])
+ AC_SUBST([CODE_COVERAGE_LIBS])
+])
+
+AC_DEFUN([AX_CODE_COVERAGE],[
+ dnl Check for --enable-code-coverage
+
+ # allow to override gcov location
+ AC_ARG_WITH([gcov],
+ [AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])],
+ [_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov],
+ [_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov])
+
+ AC_MSG_CHECKING([whether to build with code coverage support])
+ AC_ARG_ENABLE([code-coverage],
+ AS_HELP_STRING([--enable-code-coverage],
+ [Whether to enable code coverage support]),,
+ enable_code_coverage=no)
+
+ AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test "x$enable_code_coverage" = xyes])
+ AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
+ AC_MSG_RESULT($enable_code_coverage)
+
+ AS_IF([ test "x$enable_code_coverage" = xyes ], [
+ _AX_CODE_COVERAGE_ENABLED
+ ])
+
+ _AX_CODE_COVERAGE_RULES
+])
diff --git a/m4/ax_file_escapes.m4 b/m4/ax_file_escapes.m4
new file mode 100644
index 00000000..a86fdc32
--- /dev/null
+++ b/m4/ax_file_escapes.m4
@@ -0,0 +1,30 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_file_escapes.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_FILE_ESCAPES
+#
+# DESCRIPTION
+#
+# Writes the specified data to the specified file.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Tom Howard <tomhoward@users.sf.net>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 8
+
+AC_DEFUN([AX_FILE_ESCAPES],[
+AX_DOLLAR="\$"
+AX_SRB="\\135"
+AX_SLB="\\133"
+AX_BS="\\\\"
+AX_DQ="\""
+])
diff --git a/m4/compiler.m4 b/m4/compiler.m4
deleted file mode 100644
index 5a197ada..00000000
--- a/m4/compiler.m4
+++ /dev/null
@@ -1,67 +0,0 @@
-# compiler.m4 - autoconf macros for compiler settings
-#
-# Copyright © 2005 Scott James Remnant <scott@netsplit.com>.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
-# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-# COMPILER_WARNINGS
-# ----------------------
-# Add configure option to enable additional compiler warnings and treat
-# them as errors.
-AC_DEFUN([COMPILER_WARNINGS],
-[AC_ARG_ENABLE(compiler-warnings,
- AS_HELP_STRING([--enable-compiler-warnings],
- [Enable additional compiler warnings]),
-[if test "x$enable_compiler_warnings" = "xyes"; then
- if test "x$GCC" = "xyes"; then
- CFLAGS="-Wall -Werror $CFLAGS"
- fi
- if test "x$GXX" = "xyes"; then
- CXXFLAGS="-Wall -Werror $CXXFLAGS"
- fi
-fi])dnl
-])# COMPILER_WARNINGS
-
-# COMPILER_OPTIMISATIONS
-# ---------------------------
-# Add configure option to disable optimisations.
-AC_DEFUN([COMPILER_OPTIMISATIONS],
-[AC_ARG_ENABLE(compiler-optimisations,
- AS_HELP_STRING([--disable-compiler-optimisations],
- [Disable compiler optimisations]),
-[if test "x$enable_compiler_optimisations" = "xno"; then
- [CFLAGS=`echo "$CFLAGS" | sed -e "s/ -O[1-9]*\b/ -O0/g"`]
-fi])dnl
-])# COMPILER_OPTIMISATIONS
-
-# COMPILER_COVERAGE
-# ----------------------
-# Add configure option to enable coverage data.
-AC_DEFUN([COMPILER_COVERAGE],
-[AC_ARG_ENABLE(compiler-coverage,
- AS_HELP_STRING([--enable-compiler-coverage],
- [Enable generation of coverage data]),
-[if test "x$enable_compiler_coverage" = "xyes"; then
- if test "x$GCC" = "xyes"; then
- CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
- fi
-fi],[enable_compiler_coverage=no])dnl
-])# COMPILER_COVERAGE
diff --git a/m4/tp-compiler-flag.m4 b/m4/tp-compiler-flag.m4
deleted file mode 100644
index 06deaba0..00000000
--- a/m4/tp-compiler-flag.m4
+++ /dev/null
@@ -1,43 +0,0 @@
-dnl A version of AS_COMPILER_FLAG that supports both C and C++.
-dnl Based on:
-
-dnl as-compiler-flag.m4 0.1.0
-dnl autostars m4 macro for detection of compiler flags
-dnl David Schleef <ds@schleef.org>
-dnl $Id: as-compiler-flag.m4,v 1.1 2005/06/18 18:02:46 burgerman Exp $
-
-dnl TP_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
-dnl Tries to compile with the given CFLAGS and CXXFLAGS.
-dnl
-dnl Runs ACTION-IF-ACCEPTED if the compiler for the currently selected
-dnl AC_LANG can compile with the flags, and ACTION-IF-NOT-ACCEPTED otherwise.
-
-AC_DEFUN([TP_COMPILER_FLAG],
-[
- AC_MSG_CHECKING([to see if compiler understands $1])
-
- save_CFLAGS="$CFLAGS"
- save_CXXFLAGS="$CXXFLAGS"
- CFLAGS="$CFLAGS $1"
- CXXFLAGS="$CXXFLAGS $1"
-
- AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
- CFLAGS="$save_CFLAGS"
- CXXFLAGS="$save_CXXFLAGS"
-
- if test "X$flag_ok" = Xyes ; then
- $2
- true
- else
- $3
- true
- fi
- AC_MSG_RESULT([$flag_ok])
-])
-
-dnl TP_ADD_COMPILER_FLAG(VARIABLE, CFLAGS)
-dnl Append CFLAGS to VARIABLE if the compiler supports them.
-AC_DEFUN([TP_ADD_COMPILER_FLAG],
-[
- TP_COMPILER_FLAG([$2], [$1="[$]$1 $2"])
-])
diff --git a/m4/tp-compiler-warnings.m4 b/m4/tp-compiler-warnings.m4
deleted file mode 100644
index ee4af310..00000000
--- a/m4/tp-compiler-warnings.m4
+++ /dev/null
@@ -1,49 +0,0 @@
-dnl TP_COMPILER_WARNINGS(VARIABLE, WERROR_BY_DEFAULT, DESIRABLE, UNDESIRABLE)
-dnl $1 (VARIABLE): the variable to put flags into
-dnl $2 (WERROR_BY_DEFAULT): a command returning true if -Werror should be the
-dnl default
-dnl $3 (DESIRABLE): warning flags we want (e.g. all extra shadow)
-dnl $4 (UNDESIRABLE): warning flags we don't want (e.g.
-dnl missing-field-initializers unused-parameter)
-AC_DEFUN([TP_COMPILER_WARNINGS],
-[
- AC_REQUIRE([AC_ARG_ENABLE])dnl
- AC_REQUIRE([AC_HELP_STRING])dnl
- AC_REQUIRE([TP_COMPILER_FLAG])dnl
-
- tp_warnings=""
- for tp_flag in $3; do
- TP_COMPILER_FLAG([-W$tp_flag], [tp_warnings="$tp_warnings -W$tp_flag"])
- done
-
- tp_error_flags="-Werror"
- TP_COMPILER_FLAG([-Werror], [tp_werror=yes], [tp_werror=no])
-
- for tp_flag in $4; do
- TP_COMPILER_FLAG([-Wno-$tp_flag],
- [tp_warnings="$tp_warnings -Wno-$tp_flag"])
-dnl Yes, we do need to use both -Wno-foo and -Wno-error=foo. Simon says:
-dnl some warnings we explicitly don't want, like unused-parameter, but
-dnl they're in -Wall. when a distro using cdbs compiles us, we have:
-dnl -Werror -Wno-unused-parameter -Wall
-dnl ^ from us ^ from cdbs
-dnl which turns -Wunused-parameter back on, in effect
- TP_COMPILER_FLAG([-Wno-error=$tp_flag],
- [tp_error_flags="$tp_error_flags -Wno-error=$tp_flag"], [tp_werror=no])
- done
-
- AC_ARG_ENABLE([Werror],
- AC_HELP_STRING([--disable-Werror],
- [compile without -Werror (normally enabled in development builds)]),
- tp_werror=$enableval, :)
-
- if test "x$tp_werror" = xyes && $2; then
-dnl We put -Wno-error=foo before -Wno-foo because clang interprets -Wall
-dnl -Werror -Wno-foo -Wno-error=foo as “make foo a non-fatal warning”, but does
-dnl what we want if you reverse them.
- $1="$tp_error_flags $tp_warnings"
- else
- $1="$tp_warnings"
- fi
-
-])
diff --git a/packaging/coverage.txt b/packaging/coverage.txt
index b3674cb2..438bcd73 100644
--- a/packaging/coverage.txt
+++ b/packaging/coverage.txt
@@ -1,5 +1,5 @@
How to analyze coverage:
-1. read HACKING file.
+1. read CONTRIBUTING.md file.
2. gbs build adding --define '_with_coverage 1'
3. take *.o and *.gcno files from compilation (<gbs-build-root>/home/abuild/rpmbuild/BUILD/dbus-1.10.6/dbus/.libs) into a /safe/place
you may also use generated rpm package dbus-coverage-objects.
diff --git a/packaging/dbus.spec b/packaging/dbus.spec
index 4f97865b..a7057999 100644
--- a/packaging/dbus.spec
+++ b/packaging/dbus.spec
@@ -13,6 +13,7 @@ Group: Base/IPC
%define with_systemd 1
+BuildRequires: autoconf-archive
BuildRequires: libzio
BuildRequires: libtool
BuildRequires: pkg-config
@@ -26,7 +27,7 @@ BuildRequires: pkgconfig(cynara-client)
BuildRequires: pkgconfig(cynara-session)
BuildRequires: pkgconfig(cynara-client-async)
BuildRequires: pkgconfig(libdbuspolicy1)
-Version: 1.10.6
+Version: 1.12.16
Release: 3
Source0: http://dbus.freedesktop.org/releases/dbus/dbus-%{version}.tar.gz
Source3: dbus_at_console.ck
@@ -130,7 +131,6 @@ export V=1
--with-dbus-user=dbus \
--libexecdir=%{_libdir}/%{name} \
--libdir=%{_libdir} \
- --with-init-scripts=suse \
--enable-inotify \
--disable-doxygen-docs \
--disable-xml-docs \
@@ -167,7 +167,6 @@ popd
--with-dbus-user=dbus \
--libexecdir=%{_libdir}/%{name} \
--libdir=%{_libdir} \
- --with-init-scripts=suse \
--enable-inotify \
--disable-doxygen-docs \
--disable-xml-docs \
@@ -199,7 +198,6 @@ find dbus -name '*.gcno' -exec cp '{}' coverage-objects ';'
--with-dbus-user=dbus \
--libexecdir=%{_libdir}/%{name} \
--libdir=%{_libdir} \
- --with-init-scripts=suse \
--enable-inotify \
--disable-doxygen-docs \
--disable-xml-docs \
@@ -232,7 +230,7 @@ mkdir -p %{buildroot}/lib/dbus-1/system-services
mkdir -p %{buildroot}/%{_datadir}/dbus-1/system-services
mkdir -p %{buildroot}/%{_datadir}/dbus-1/interfaces
#
-chmod a-x AUTHORS COPYING HACKING NEWS README doc/*.txt doc/file-boilerplate.c doc/TODO
+chmod a-x AUTHORS COPYING CONTRIBUTING.md NEWS README doc/*.txt doc/file-boilerplate.c doc/TODO
#
install -d %{buildroot}%{_sysconfdir}/ConsoleKit/run-session.d
install -m 755 %{SOURCE3} %{buildroot}%{_sysconfdir}/ConsoleKit/run-session.d
@@ -333,8 +331,6 @@ popd
%{_unitdir}/dbus.service
%dir %{_unitdir}/sockets.target.wants
%{_unitdir}/sockets.target.wants/dbus.socket
-%dir %{_unitdir}/dbus.target.wants
-%{_unitdir}/dbus.target.wants/dbus.socket
%dir %{_unitdir_user}
%{_unitdir_user}/dbus.socket
%{_unitdir_user}/dbus.service
@@ -348,6 +344,8 @@ popd
%dir %{_datadir}/dbus-1/services
%dir %{_datadir}/dbus-1/system-services
%{_sysconfdir}/profile.d/dbus.sh
+%{_libdir}/sysusers.d/dbus.conf
+%{_libdir}/tmpfiles.d/dbus.conf
%files libs
%manifest %{name}.manifest
@@ -365,6 +363,10 @@ popd
%{_libdir}/dbus-1.0/include
%{_libdir}/pkgconfig/dbus-1.pc
%dir %{_libdir}/dbus-1.0
+%{_libdir}/cmake/DBus1/DBus1Config.cmake
+%{_libdir}/cmake/DBus1/DBus1ConfigVersion.cmake
+%{_datadir}/xml/dbus-1/busconfig.dtd
+%{_datadir}/xml/dbus-1/introspect.dtd
%files tests
%manifest %{name}.manifest
diff --git a/test/Makefile.am b/test/Makefile.am
index cd4d1e75..e6f50e1f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,22 +1,29 @@
-## the "name-test" subdir in fact contains a bunch of tests now that need a temporary bus
+## the "name-test" subdir in fact contains a bunch of tests now that need a temporary bus
## to be running to do stuff with. The directory should be renamed.
## We want to build the current directory first to pick up the testutils lib
-SUBDIRS= . name-test
+SUBDIRS= . name-test
DIST_SUBDIRS=name-test
CLEANFILES =
EXTRA_DIST =
AM_CPPFLAGS = \
+ $(CODE_COVERAGE_CPPFLAGS) \
-I$(top_srcdir) \
$(DBUS_STATIC_BUILD_CPPFLAGS) \
-DDBUS_COMPILATION \
+ $(APPARMOR_CFLAGS) \
$(GLIB_CFLAGS) \
+ $(GIO_UNIX_CFLAGS) \
$(NULL)
# improve backtraces from test stuff
AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+AM_CFLAGS = \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(NULL)
+
noinst_LTLIBRARIES = libdbus-testutils.la
libdbus_testutils_la_SOURCES = \
@@ -32,6 +39,7 @@ libdbus_testutils_la_SOURCES += \
endif
libdbus_testutils_la_LIBADD = \
+ $(CODE_COVERAGE_LIBS) \
$(top_builddir)/dbus/libdbus-1.la \
$(top_builddir)/dbus/libdbus-internal.la \
$(NULL)
@@ -107,9 +115,18 @@ test_printf_LDADD = $(top_builddir)/dbus/libdbus-internal.la
test_refs_SOURCES = internals/refs.c
test_refs_LDADD = libdbus-testutils.la $(GLIB_LIBS)
+test_server_oom_SOURCES = internals/server-oom.c
+test_server_oom_LDADD = libdbus-testutils.la $(GLIB_LIBS)
+
test_syslog_SOURCES = internals/syslog.c
test_syslog_LDADD = libdbus-testutils.la $(GLIB_LIBS)
+test_variant_SOURCES = internals/variant.c
+test_variant_LDADD = libdbus-testutils.la $(GLIB_LIBS)
+
+manual_backtrace_SOURCES = manual-backtrace.c
+manual_backtrace_LDADD = $(top_builddir)/dbus/libdbus-1.la
+
manual_dir_iter_SOURCES = manual-dir-iter.c
manual_dir_iter_LDADD = $(top_builddir)/dbus/libdbus-internal.la
@@ -124,17 +141,25 @@ EXTRA_DIST += dbus-test-runner
testexecdir = $(libexecdir)/installed-tests/dbus
testmetadir = $(datadir)/installed-tests/dbus
-testexec_PROGRAMS =
-testmeta_DATA =
+nobase_dist_testexec_SCRIPTS =
+nobase_testexec_PROGRAMS =
+nobase_testmeta_DATA =
+installable_helpers = \
+ $(NULL)
installable_tests = \
test-shell \
test-printf \
$(NULL)
installable_manual_tests = \
+ manual-backtrace \
manual-dir-iter \
- manual-tcp \
- $(NULL)
+ manual-tcp \
+ $(NULL)
+dist_installable_test_scripts = \
+ $(NULL)
+dist_installed_test_scripts = \
+ $(NULL)
if DBUS_WIN
installable_manual_tests += manual-paths
@@ -146,44 +171,109 @@ installable_tests += \
test-dbus-daemon \
test-dbus-daemon-eavesdrop \
test-fdpass \
+ test-message \
test-monitor \
test-loopback \
test-marshal \
test-refs \
test-relay \
+ test-server-oom \
test-syntax \
test-syslog \
test-uid-permissions \
+ test-variant \
$(NULL)
if DBUS_UNIX
+# These binaries are used in tests but are not themselves tests
+installable_helpers += \
+ test-apparmor-activation \
+ $(NULL)
+
installable_tests += \
test-sd-activation \
$(NULL)
+
+dist_installable_test_scripts += \
+ test-dbus-daemon-fork.sh \
+ $(NULL)
+
+# Only runnable when installed, not from the source tree
+dist_installed_test_scripts += \
+ integration/transient-services.sh \
+ test-apparmor-activation.sh \
+ $(NULL)
+
+# Testing dbus-launch relies on special code in that binary.
+if DBUS_ENABLE_EMBEDDED_TESTS
+dist_installable_test_scripts += \
+ test-dbus-launch-eval.sh \
+ $(NULL)
+
+if DBUS_ENABLE_X11_AUTOLAUNCH
+dist_installable_test_scripts += \
+ test-dbus-launch-x11.sh \
+ $(NULL)
+endif DBUS_ENABLE_X11_AUTOLAUNCH
+endif DBUS_ENABLE_EMBEDDED_TESTS
+
endif DBUS_UNIX
installable_manual_tests += \
manual-authz \
+ manual-test-thread-blocking \
$(NULL)
endif DBUS_WITH_GLIB
-installable_test_meta = $(installable_tests:=.test)
-installable_test_meta_with_config = $(installable_tests:=_with_config.test)
+installable_test_meta = \
+ $(dist_installable_test_scripts:=.test) \
+ $(dist_installed_test_scripts:=.test) \
+ $(installable_tests:=.test) \
+ $(NULL)
+installable_test_meta_with_config = \
+ $(dist_installable_test_scripts:=_with_config.test) \
+ $(dist_installed_test_scripts:=_with_config.test) \
+ $(installable_tests:=_with_config.test) \
+ $(NULL)
installcheck_tests =
installcheck_environment = \
+ export XDG_DATA_HOME=@abs_top_builddir@/test/XDG_DATA_HOME; \
+ export XDG_DATA_DIRS=@abs_top_builddir@/test/XDG_DATA_DIRS:$(DESTDIR)$(datadir); \
export XDG_RUNTIME_DIR=@abs_top_builddir@/test/XDG_RUNTIME_DIR; \
+ export DBUS_SESSION_BUS_ADDRESS=do-not-use-real-session:; \
export DBUS_TEST_DAEMON=$(DESTDIR)$(DBUS_DAEMONDIR)/dbus-daemon$(EXEEXT); \
+ export DBUS_TEST_DBUS_LAUNCH=$(DESTDIR)$(bindir)/dbus-launch$(EXEEXT); \
+ export DBUS_TEST_DBUS_MONITOR=$(DESTDIR)$(bindir)/dbus-monitor$(EXEEXT); \
+ export DBUS_TEST_DBUS_SEND=$(DESTDIR)$(bindir)/dbus-send$(EXEEXT); \
+ export DBUS_TEST_DBUS_UUIDGEN=$(DESTDIR)$(bindir)/dbus-uuidgen$(EXEEXT); \
+ export DBUS_TEST_EXEC=@abs_top_builddir@/test; \
export DBUS_TEST_HOMEDIR=@abs_top_builddir@/dbus; \
export DBUS_TEST_DATADIR=$(DESTDIR)$(datadir); \
+ export DBUS_TEST_UNINSTALLED=1; \
+ export HOME=@abs_top_builddir@/dbus; \
${NULL}
+# Tests in bus/config-parser.c rely on these specific values for XDG_* and
+# DBUS_TEST_BUILDDIR.
AM_TESTS_ENVIRONMENT = \
+ export XDG_DATA_HOME=@abs_top_builddir@/test/XDG_DATA_HOME; \
+ export XDG_DATA_DIRS=@abs_top_builddir@/test/XDG_DATA_DIRS:@abs_top_builddir@/test/XDG_DATA_DIRS2; \
export XDG_RUNTIME_DIR=@abs_top_builddir@/test/XDG_RUNTIME_DIR; \
export DBUS_FATAL_WARNINGS=1; \
+ export DBUS_SESSION_BUS_ADDRESS=do-not-use-real-session:; \
+ export DBUS_TEST_BUILDDIR=@abs_builddir@; \
+ export DBUS_TEST_SRCDIR=@abs_srcdir@; \
export DBUS_TEST_DAEMON=@abs_top_builddir@/bus/dbus-daemon$(EXEEXT); \
+ export DBUS_TEST_DBUS_LAUNCH=@abs_top_builddir@/tools/dbus-launch$(EXEEXT); \
+ export DBUS_TEST_DBUS_MONITOR=@abs_top_builddir@/tools/dbus-monitor$(EXEEXT); \
+ export DBUS_TEST_DBUS_SEND=@abs_top_builddir@/tools/dbus-send$(EXEEXT); \
+ export DBUS_TEST_DBUS_UUIDGEN=@abs_top_builddir@/tools/dbus-uuidgen$(EXEEXT); \
export DBUS_TEST_DATA=@abs_top_builddir@/test/data; \
+ export DBUS_TEST_EXEC=@abs_top_builddir@/test; \
export DBUS_TEST_HOMEDIR=@abs_top_builddir@/dbus; \
+ export DBUS_TEST_UNINSTALLED=1; \
+ export HOME=@abs_top_builddir@/dbus; \
$(NULL)
manual_authz_SOURCES = manual-authz.c
@@ -192,6 +282,21 @@ manual_authz_LDADD = \
$(GLIB_LIBS) \
$(NULL)
+if DBUS_UNIX
+test_apparmor_activation_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -DDBUS_TEST_APPARMOR_ACTIVATION \
+ $(NULL)
+test_apparmor_activation_SOURCES = \
+ sd-activation.c \
+ $(NULL)
+test_apparmor_activation_LDADD = \
+ libdbus-testutils.la \
+ $(APPARMOR_LIBS) \
+ $(GLIB_LIBS) \
+ $(NULL)
+endif
+
test_corrupt_SOURCES = corrupt.c
test_corrupt_LDADD = \
libdbus-testutils.la \
@@ -214,6 +319,7 @@ test_dbus_daemon_SOURCES = dbus-daemon.c
test_dbus_daemon_LDADD = \
libdbus-testutils.la \
$(GLIB_LIBS) \
+ $(GIO_UNIX_LIBS) \
$(NULL)
test_dbus_daemon_eavesdrop_SOURCES = dbus-daemon-eavesdrop.c
@@ -238,6 +344,15 @@ test_marshal_LDADD = \
$(GLIB_LIBS) \
$(NULL)
+test_message_SOURCES = \
+ message.c \
+ $(NULL)
+test_message_LDADD = \
+ libdbus-testutils.la \
+ $(top_builddir)/dbus/libdbus-internal.la \
+ $(GLIB_LIBS) \
+ $(NULL)
+
test_monitor_SOURCES = \
monitor.c \
$(NULL)
@@ -252,6 +367,12 @@ test_syntax_LDADD = \
$(GLIB_LIBS) \
$(NULL)
+manual_test_thread_blocking_SOURCES = thread-blocking.c
+manual_test_thread_blocking_LDADD = \
+ libdbus-testutils.la \
+ $(GLIB_LIBS) \
+ $(NULL)
+
test_uid_permissions_SOURCES = \
uid-permissions.c \
$(NULL)
@@ -268,15 +389,22 @@ test_fdpass_LDADD = \
$(GLIB_LIBS) \
$(NULL)
+TESTS += $(dist_installable_test_scripts)
+installcheck_tests += $(dist_installable_test_scripts)
+
if DBUS_ENABLE_MODULAR_TESTS
TESTS += $(installable_tests)
installcheck_tests += $(installable_tests)
if DBUS_ENABLE_INSTALLED_TESTS
- testexec_PROGRAMS += $(installable_tests) $(installable_manual_tests)
-
- testmeta_DATA += $(installable_test_meta)
- testmeta_DATA += $(installable_test_meta_with_config)
+ nobase_testexec_PROGRAMS += $(installable_helpers)
+ nobase_testexec_PROGRAMS += $(installable_manual_tests)
+ nobase_testexec_PROGRAMS += $(installable_tests)
+ nobase_dist_testexec_SCRIPTS += $(dist_installed_test_scripts)
+ nobase_dist_testexec_SCRIPTS += $(dist_installable_test_scripts)
+
+ nobase_testmeta_DATA += $(installable_test_meta)
+ nobase_testmeta_DATA += $(installable_test_meta_with_config)
else !DBUS_ENABLE_INSTALLED_TESTS
noinst_PROGRAMS += $(installable_tests) $(installable_manual_tests)
endif !DBUS_ENABLE_INSTALLED_TESTS
@@ -294,19 +422,32 @@ if DBUS_ENABLE_INSTALLED_TESTS
$(installcheck_environment) \
$(srcdir)/dbus-test-runner \
$(testexecdir) \
- $(testexec_PROGRAMS) }
+ $(installable_tests); }
endif DBUS_ENABLE_INSTALLED_TESTS
in_data = \
+ data/dbus-installed-tests.aaprofile.in \
+ data/systemd-activation/com.example.ReceiveDeniedByAppArmorLabel.service.in \
+ data/systemd-activation/com.example.SendDeniedByAppArmorLabel.service.in \
+ data/systemd-activation/com.example.SendDeniedByNonexistentAppArmorLabel.service.in \
+ data/systemd-activation/com.example.SystemdActivatable3.service.in \
data/valid-config-files-system/debug-allow-all-fail.conf.in \
data/valid-config-files-system/debug-allow-all-pass.conf.in \
+ data/valid-config-files/as-another-user.conf.in \
+ data/valid-config-files/count-fds.conf.in \
data/valid-config-files/debug-allow-all-sha1.conf.in \
data/valid-config-files/debug-allow-all.conf.in \
data/valid-config-files/finite-timeout.conf.in \
data/valid-config-files/forbidding.conf.in \
data/valid-config-files/debug-check-some.conf.in \
data/valid-config-files/incoming-limit.conf.in \
+ data/valid-config-files/max-completed-connections.conf.in \
+ data/valid-config-files/max-connections-per-user.conf.in \
+ data/valid-config-files/max-match-rules-per-connection.conf.in \
+ data/valid-config-files/max-names-per-connection.conf.in \
+ data/valid-config-files/max-replies-per-connection.conf.in \
data/valid-config-files/multi-user.conf.in \
+ data/valid-config-files/pending-fd-timeout.conf.in \
data/valid-config-files/systemd-activation.conf.in \
data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \
data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in \
@@ -331,6 +472,8 @@ static_data = \
data/auth/anonymous-server-successful.auth-script \
data/auth/cancel.auth-script \
data/auth/client-out-of-mechanisms.auth-script \
+ data/auth/cookie-sha1-username.auth-script \
+ data/auth/cookie-sha1.auth-script \
data/auth/external-failed.auth-script \
data/auth/external-root.auth-script \
data/auth/external-silly.auth-script \
@@ -354,8 +497,10 @@ static_data = \
data/invalid-config-files/circular-1.conf \
data/invalid-config-files/circular-2.conf \
data/invalid-config-files/circular-3.conf \
+ data/invalid-config-files/impossible-send.conf \
data/invalid-config-files/not-well-formed.conf \
data/invalid-config-files/truncated-file.conf \
+ data/invalid-config-files/send-and-receive.conf \
data/invalid-messages/array-of-nil.message \
data/invalid-messages/array-with-mixed-types.message \
data/invalid-messages/bad-boolean-array.message \
@@ -378,15 +523,18 @@ static_data = \
data/sha-1/byte-messages.sha1 \
data/systemd-activation/com.example.ReceiveDenied.service \
data/systemd-activation/com.example.SendDenied.service \
+ data/systemd-activation/com.example.SendDeniedByAppArmorName.service \
data/systemd-activation/com.example.SystemdActivatable1.service \
data/systemd-activation/com.example.SystemdActivatable2.service \
- data/systemd-activation/com.example.SystemdActivatable3.service \
data/systemd-activation/org.freedesktop.systemd1.service \
data/valid-config-files/basic.conf \
data/valid-config-files/basic.d/basic.conf \
+ data/valid-config-files/check-own-rules.conf \
data/valid-config-files/entities.conf \
data/valid-config-files/listen-unix-runtime.conf \
data/valid-config-files/many-rules.conf \
+ data/valid-config-files/standard-session-dirs.conf \
+ data/valid-config-files-system/many-rules.conf \
data/valid-config-files-system/system.d/test.conf \
data/valid-messages/array-of-array-of-uint32.message \
data/valid-messages/dict-simple.message \
@@ -409,8 +557,11 @@ EXTRA_DIST += $(static_data)
## copy tests to builddir so that generated tests and static tests
## are all in one place.
+## Note that we can't create the XDG_RUNTIME_DIR with permissions 0700
+## on MSYS2, which rejects attempts to change permissions, hence "|| true".
all-local: copy-config-local uninstalled-config-local
- @:
+ $(AM_V_at)$(MKDIR_P) XDG_RUNTIME_DIR
+ $(AM_V_at)chmod 0700 XDG_RUNTIME_DIR || true
copy-config-local:
$(AM_V_at)$(MKDIR_P) data/valid-config-files/session.d
@@ -432,6 +583,7 @@ uninstalled-config-local:
sed \
-e 's,[@]DBUS_TEST_DATA[@],@abs_builddir@/data,' \
-e 's,[@]DBUS_TEST_EXEC[@],@abs_builddir@,' \
+ -e 's,[@]DBUS_USER[@],$(DBUS_USER),' \
-e 's,[@]EXEEXT[@],$(EXEEXT),' \
-e 's,[@]TEST_LAUNCH_HELPER_BINARY[@],@abs_top_builddir@/bus/dbus-daemon-launch-helper-test$(EXEEXT),' \
-e 's,[@]TEST_LISTEN[@],$(TEST_LISTEN),' \
@@ -446,6 +598,7 @@ if DBUS_ENABLE_INSTALLED_TESTS
sed \
-e 's,[@]DBUS_TEST_DATA[@],$(testexecdir)/data,' \
-e 's,[@]DBUS_TEST_EXEC[@],$(testexecdir),' \
+ -e 's,[@]DBUS_USER[@],$(DBUS_USER),' \
-e 's,[@]EXEEXT[@],$(EXEEXT),' \
-e 's,[@]TEST_LAUNCH_HELPER_BINARY[@],/bin/false,' \
-e 's,[@]TEST_LISTEN[@],$(TEST_LISTEN),' \
@@ -486,6 +639,7 @@ clean-local:
rm -f "$${F%.in}"; \
done; \
fi
+ rm -fr ./XDG_RUNTIME_DIR ./installable
imported_data = \
data/valid-config-files/session.conf \
@@ -495,8 +649,6 @@ imported_data = \
noinst_DATA = $(imported_data)
CLEANFILES += \
$(noinst_DATA) \
- XDG_RUNTIME_DIR \
- installable \
$(NULL)
data/valid-config-files/session.conf: $(top_builddir)/bus/session.conf
@@ -508,6 +660,7 @@ data/valid-config-files-system/system.conf: $(top_builddir)/bus/system.conf
$(AM_V_GEN)cp $< $@
$(installable_test_meta): %.test: %$(EXEEXT) Makefile
+ $(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GEN) ( \
echo '[Test]'; \
echo 'Type=session'; \
@@ -516,9 +669,13 @@ $(installable_test_meta): %.test: %$(EXEEXT) Makefile
) > $@.tmp && mv $@.tmp $@
$(installable_test_meta_with_config): %_with_config.test: %$(EXEEXT) Makefile
+ $(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GEN) ( \
echo '[Test]'; \
echo 'Type=session'; \
echo 'Output=TAP'; \
- echo 'Exec=env DBUS_TEST_DATA=$(testexecdir)/data $(testexecdir)/$* --tap'; \
+ echo 'Exec=env DBUS_TEST_EXEC=$(testexecdir) DBUS_TEST_DATA=$(testexecdir)/data $(testexecdir)/$* --tap'; \
) > $@.tmp && mv $@.tmp $@
+
+# Add rules for code-coverage testing, as defined by AX_CODE_COVERAGE
+include $(top_srcdir)/aminclude_static.am
diff --git a/test/break-loader.c b/test/break-loader.c
deleted file mode 100644
index 1e406fc3..00000000
--- a/test/break-loader.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/* dbus-break-loader.c Program to find byte streams that break the message loader
- *
- * Copyright (C) 2003 Red Hat Inc.
- *
- * Licensed under the Academic Free License version 2.1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <config.h>
-#include <dbus/dbus.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include <string.h>
-
-#include <dbus/dbus-string.h>
-#include <dbus/dbus-internals.h>
-#include <dbus/dbus-test.h>
-#include <dbus/dbus-marshal-basic.h>
-
-static DBusString failure_dir;
-static int total_attempts;
-static int failures_this_iteration;
-
-static int
-random_int_in_range (int start,
- int end)
-{
- /* such elegant math */
- double gap;
- double v_double;
- int v;
-
- if (start == end)
- return start;
-
- _dbus_assert (end > start);
-
- gap = end - start - 1; /* -1 to not include "end" */
- v_double = ((double)start) + (((double)rand ())/RAND_MAX) * gap;
- if (v_double < 0.0)
- v = (v_double - 0.5);
- else
- v = (v_double + 0.5);
-
- if (v < start)
- {
- fprintf (stderr, "random_int_in_range() generated %d for range [%d,%d)\n",
- v, start, end);
- v = start;
- }
- else if (v >= end)
- {
- fprintf (stderr, "random_int_in_range() generated %d for range [%d,%d)\n",
- v, start, end);
- v = end - 1;
- }
-
- /* printf (" %d of [%d,%d)\n", v, start, end); */
-
- return v;
-}
-
-static dbus_bool_t
-try_mutated_data (const DBusString *data)
-{
- int pid;
-
- total_attempts += 1;
- /* printf (" attempt %d\n", total_attempts); */
-
- pid = fork ();
-
- if (pid < 0)
- {
- fprintf (stderr, "fork() failed: %s\n",
- strerror (errno));
- exit (1);
- return FALSE;
- }
-
- if (pid == 0)
- {
- /* Child, try loading the data */
- if (!dbus_internal_do_not_use_try_message_data (data, _DBUS_MESSAGE_UNKNOWN))
- exit (1);
- else
- exit (0);
- }
- else
- {
- /* Parent, wait for child */
- int status;
- DBusString filename;
- dbus_bool_t failed;
-
- if (waitpid (pid, &status, 0) < 0)
- {
- fprintf (stderr, "waitpid() failed: %s\n", strerror (errno));
- exit (1);
- return FALSE;
- }
-
- failed = FALSE;
-
- if (!_dbus_string_init (&filename) ||
- !_dbus_string_copy (&failure_dir, 0,
- &filename, 0) ||
- !_dbus_string_append_byte (&filename, '/'))
- {
- fprintf (stderr, "out of memory\n");
- exit (1);
- }
-
- _dbus_string_append_int (&filename, total_attempts);
-
- if (WIFEXITED (status))
- {
- if (WEXITSTATUS (status) != 0)
- {
- _dbus_string_append (&filename, "-exited-");
- _dbus_string_append_int (&filename, WEXITSTATUS (status));
- failed = TRUE;
- }
- }
- else if (WIFSIGNALED (status))
- {
- _dbus_string_append (&filename, "signaled-");
- _dbus_string_append_int (&filename, WTERMSIG (status));
- failed = TRUE;
- }
-
- if (failed)
- {
- DBusError error;
-
- _dbus_string_append (&filename, ".message-raw");
-
- printf ("Child failed, writing %s\n", _dbus_string_get_const_data (&filename));
-
- dbus_error_init (&error);
- if (!_dbus_string_save_to_file (data, &filename, FALSE, &error))
- {
- fprintf (stderr, "Failed to save failed message data: %s\n",
- error.message);
- dbus_error_free (&error);
- exit (1); /* so we can see the seed that was printed out */
- }
-
- failures_this_iteration += 1;
-
- _dbus_string_free (&filename);
-
- return FALSE;
- }
- else
- {
- _dbus_string_free (&filename);
- return TRUE;
- }
- }
-
- _dbus_assert_not_reached ("should not be reached");
- return TRUE;
-}
-
-static void
-randomly_shorten_or_lengthen (const DBusString *orig_data,
- DBusString *mutated)
-{
- int delta;
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- if (_dbus_string_get_length (mutated) == 0)
- delta = random_int_in_range (0, 10);
- else
- delta = random_int_in_range (- _dbus_string_get_length (mutated),
- _dbus_string_get_length (mutated) * 3);
-
- if (delta < 0)
- _dbus_string_shorten (mutated, - delta);
- else if (delta > 0)
- {
- int i = 0;
-
- i = _dbus_string_get_length (mutated);
- if (!_dbus_string_lengthen (mutated, delta))
- _dbus_assert_not_reached ("couldn't lengthen string");
-
- while (i < _dbus_string_get_length (mutated))
- {
- _dbus_string_set_byte (mutated,
- i,
- random_int_in_range (0, 256));
- ++i;
- }
- }
-}
-
-static void
-randomly_change_one_byte (const DBusString *orig_data,
- DBusString *mutated)
-{
- int i;
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- if (_dbus_string_get_length (mutated) == 0)
- return;
-
- i = random_int_in_range (0, _dbus_string_get_length (mutated));
-
- _dbus_string_set_byte (mutated, i,
- random_int_in_range (0, 256));
-}
-
-static void
-randomly_remove_one_byte (const DBusString *orig_data,
- DBusString *mutated)
-{
- int i;
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- if (_dbus_string_get_length (mutated) == 0)
- return;
-
- i = random_int_in_range (0, _dbus_string_get_length (mutated));
-
- _dbus_string_delete (mutated, i, 1);
-}
-
-
-static void
-randomly_add_one_byte (const DBusString *orig_data,
- DBusString *mutated)
-{
- int i;
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- i = random_int_in_range (0, _dbus_string_get_length (mutated));
-
- _dbus_string_insert_bytes (mutated, i, 1,
- random_int_in_range (0, 256));
-}
-
-static void
-randomly_modify_length (const DBusString *orig_data,
- DBusString *mutated)
-{
- int i;
- int byte_order;
- const char *d;
- dbus_uint32_t orig;
- int delta;
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- if (_dbus_string_get_length (mutated) < 12)
- return;
-
- d = _dbus_string_get_const_data (mutated);
-
- if (!(*d == DBUS_LITTLE_ENDIAN ||
- *d == DBUS_BIG_ENDIAN))
- return;
-
- byte_order = *d;
-
- i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
- i = _DBUS_ALIGN_VALUE (i, 4);
-
- orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);
-
- delta = random_int_in_range (-10, 10);
-
- _dbus_marshal_set_uint32 (mutated, byte_order, i,
- (unsigned) (orig + delta));
-}
-
-static void
-randomly_set_extreme_ints (const DBusString *orig_data,
- DBusString *mutated)
-{
- int i;
- int byte_order;
- const char *d;
- dbus_uint32_t orig;
- static int which = 0;
- unsigned int extreme_ints[] = {
- _DBUS_INT_MAX,
- _DBUS_UINT_MAX,
- _DBUS_INT_MAX - 1,
- _DBUS_UINT_MAX - 1,
- _DBUS_INT_MAX - 2,
- _DBUS_UINT_MAX - 2,
- _DBUS_INT_MAX - 17,
- _DBUS_UINT_MAX - 17,
- _DBUS_INT_MAX / 2,
- _DBUS_INT_MAX / 3,
- _DBUS_UINT_MAX / 2,
- _DBUS_UINT_MAX / 3,
- 0, 1, 2, 3,
- (unsigned int) -1,
- (unsigned int) -2,
- (unsigned int) -3
- };
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- if (_dbus_string_get_length (mutated) < 12)
- return;
-
- d = _dbus_string_get_const_data (mutated);
-
- if (!(*d == DBUS_LITTLE_ENDIAN ||
- *d == DBUS_BIG_ENDIAN))
- return;
-
- byte_order = *d;
-
- i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
- i = _DBUS_ALIGN_VALUE (i, 4);
-
- orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);
-
- which = random_int_in_range (0, _DBUS_N_ELEMENTS (extreme_ints));
-
- _dbus_assert (which >= 0);
- _dbus_assert (which < _DBUS_N_ELEMENTS (extreme_ints));
-
- _dbus_marshal_set_uint32 (mutated, byte_order, i,
- extreme_ints[which]);
-}
-
-static int
-random_type (void)
-{
- const char types[] = {
- DBUS_TYPE_INVALID,
- DBUS_TYPE_NIL,
- DBUS_TYPE_BYTE,
- DBUS_TYPE_BOOLEAN,
- DBUS_TYPE_INT32,
- DBUS_TYPE_UINT32,
- DBUS_TYPE_INT64,
- DBUS_TYPE_UINT64,
- DBUS_TYPE_DOUBLE,
- DBUS_TYPE_STRING,
- DBUS_TYPE_CUSTOM,
- DBUS_TYPE_ARRAY,
- DBUS_TYPE_DICT,
- DBUS_TYPE_OBJECT_PATH
- };
-
- _dbus_assert (_DBUS_N_ELEMENTS (types) == DBUS_NUMBER_OF_TYPES + 1);
-
- return types[ random_int_in_range (0, _DBUS_N_ELEMENTS (types)) ];
-}
-
-static void
-randomly_change_one_type (const DBusString *orig_data,
- DBusString *mutated)
-{
- int i;
- int len;
-
- if (orig_data != mutated)
- {
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
- }
-
- if (_dbus_string_get_length (mutated) == 0)
- return;
-
- len = _dbus_string_get_length (mutated);
- i = random_int_in_range (0, len);
-
- /* Look for a type starting at a random location,
- * and replace with a different type
- */
- while (i < len)
- {
- int b;
- b = _dbus_string_get_byte (mutated, i);
- if (dbus_type_is_valid (b))
- {
- _dbus_string_set_byte (mutated, i, random_type ());
- return;
- }
- ++i;
- }
-}
-
-static int times_we_did_each_thing[7] = { 0, };
-
-static void
-randomly_do_n_things (const DBusString *orig_data,
- DBusString *mutated,
- int n)
-{
- int i;
- void (* functions[]) (const DBusString *orig_data,
- DBusString *mutated) =
- {
- randomly_shorten_or_lengthen,
- randomly_change_one_byte,
- randomly_add_one_byte,
- randomly_remove_one_byte,
- randomly_modify_length,
- randomly_set_extreme_ints,
- randomly_change_one_type
- };
-
- _dbus_string_set_length (mutated, 0);
-
- if (!_dbus_string_copy (orig_data, 0, mutated, 0))
- _dbus_assert_not_reached ("out of mem");
-
- i = 0;
- while (i < n)
- {
- int which;
-
- which = random_int_in_range (0, _DBUS_N_ELEMENTS (functions));
-
- (* functions[which]) (mutated, mutated);
- times_we_did_each_thing[which] += 1;
-
- ++i;
- }
-}
-
-static dbus_bool_t
-find_breaks_based_on (const DBusString *filename,
- dbus_bool_t is_raw,
- DBusMessageValidity expected_validity,
- void *data)
-{
- DBusString orig_data;
- DBusString mutated;
- const char *filename_c;
- dbus_bool_t retval;
- int i;
-
- filename_c = _dbus_string_get_const_data (filename);
-
- retval = FALSE;
-
- if (!_dbus_string_init (&orig_data))
- _dbus_assert_not_reached ("could not allocate string\n");
-
- if (!_dbus_string_init (&mutated))
- _dbus_assert_not_reached ("could not allocate string\n");
-
- if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
- &orig_data))
- {
- fprintf (stderr, "could not load file %s\n", filename_c);
- goto failed;
- }
-
- printf (" changing one random byte 100 times\n");
- i = 0;
- while (i < 100)
- {
- randomly_change_one_byte (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" changing length 50 times\n");
- i = 0;
- while (i < 50)
- {
- randomly_modify_length (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" removing one byte 50 times\n");
- i = 0;
- while (i < 50)
- {
- randomly_remove_one_byte (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" adding one byte 50 times\n");
- i = 0;
- while (i < 50)
- {
- randomly_add_one_byte (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" changing ints to boundary values 50 times\n");
- i = 0;
- while (i < 50)
- {
- randomly_set_extreme_ints (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" changing typecodes 50 times\n");
- i = 0;
- while (i < 50)
- {
- randomly_change_one_type (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" changing message length 15 times\n");
- i = 0;
- while (i < 15)
- {
- randomly_shorten_or_lengthen (&orig_data, &mutated);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" randomly making 2 of above modifications 42 times\n");
- i = 0;
- while (i < 42)
- {
- randomly_do_n_things (&orig_data, &mutated, 2);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" randomly making 3 of above modifications 42 times\n");
- i = 0;
- while (i < 42)
- {
- randomly_do_n_things (&orig_data, &mutated, 3);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- printf (" randomly making 4 of above modifications 42 times\n");
- i = 0;
- while (i < 42)
- {
- randomly_do_n_things (&orig_data, &mutated, 4);
- try_mutated_data (&mutated);
-
- ++i;
- }
-
- retval = TRUE;
-
- failed:
-
- _dbus_string_free (&orig_data);
- _dbus_string_free (&mutated);
-
- /* FALSE means end the whole process */
- return retval;
-}
-
-static unsigned int
-get_random_seed (void)
-{
- DBusString bytes;
- unsigned int seed;
- int fd;
- const char *s;
-
- seed = 0;
-
- if (!_dbus_string_init (&bytes))
- exit (1);
-
- fd = open ("/dev/urandom", O_RDONLY);
- if (fd < 0)
- goto use_fallback;
-
- if (_dbus_read (fd, &bytes, 4) != 4)
- goto use_fallback;
-
- close (fd);
-
- s = _dbus_string_get_const_data (&bytes);
-
- seed = * (unsigned int*) s;
- goto out;
-
- use_fallback:
- {
- long tv_usec;
-
- fprintf (stderr, "could not open/read /dev/urandom, using current time for seed\n");
-
- _dbus_get_monotonic_time (NULL, &tv_usec);
-
- seed = tv_usec;
- }
-
- out:
- _dbus_string_free (&bytes);
-
- return seed;
-}
-
-int
-main (int argc,
- char **argv)
-{
- const char *test_data_dir;
- const char *failure_dir_c;
- int total_failures_found;
-
- if (argc > 1)
- test_data_dir = argv[1];
- else
- {
- fprintf (stderr, "Must specify a top_srcdir/test/data directory\n");
- return 1;
- }
-
- total_failures_found = 0;
- total_attempts = 0;
-
- if (!_dbus_string_init (&failure_dir))
- return 1;
-
- /* so you can leave it overnight safely */
-#define MAX_FAILURES 1000
-
- while (total_failures_found < MAX_FAILURES)
- {
- unsigned int seed;
-
- failures_this_iteration = 0;
-
- seed = get_random_seed ();
-
- _dbus_string_set_length (&failure_dir, 0);
-
- if (!_dbus_string_append (&failure_dir, "failures-"))
- return 1;
-
- if (!_dbus_string_append_uint (&failure_dir, seed))
- return 1;
-
- failure_dir_c = _dbus_string_get_const_data (&failure_dir);
-
- if (mkdir (failure_dir_c, 0700) < 0)
- {
- if (errno != EEXIST)
- fprintf (stderr, "didn't mkdir %s: %s\n",
- failure_dir_c, strerror (errno));
- }
-
- printf ("next seed = %u \ttotal failures %d of %d attempts\n",
- seed, total_failures_found, total_attempts);
-
- srand (seed);
-
- if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
- find_breaks_based_on,
- NULL))
- {
- fprintf (stderr, "fatal error iterating over message files\n");
- rmdir (failure_dir_c);
- return 1;
- }
-
- printf (" did %d random mutations: %d %d %d %d %d %d %d\n",
- _DBUS_N_ELEMENTS (times_we_did_each_thing),
- times_we_did_each_thing[0],
- times_we_did_each_thing[1],
- times_we_did_each_thing[2],
- times_we_did_each_thing[3],
- times_we_did_each_thing[4],
- times_we_did_each_thing[5],
- times_we_did_each_thing[6]);
-
- printf ("Found %d failures with seed %u stored in %s\n",
- failures_this_iteration, seed, failure_dir_c);
-
- total_failures_found += failures_this_iteration;
-
- rmdir (failure_dir_c); /* does nothing if non-empty */
- }
-
- return 0;
-}
diff --git a/test/corrupt.c b/test/corrupt.c
index d106fcc5..a6a912f4 100644
--- a/test/corrupt.c
+++ b/test/corrupt.c
@@ -36,6 +36,7 @@
typedef struct {
DBusError e;
TestMainContext *ctx;
+ gboolean skip;
DBusServer *server;
DBusConnection *server_conn;
@@ -85,6 +86,14 @@ setup (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->client_messages);
+ if ((g_str_has_prefix (addr, "tcp:") ||
+ g_str_has_prefix (addr, "nonce-tcp:")) &&
+ !test_check_tcp_works ())
+ {
+ f->skip = TRUE;
+ return;
+ }
+
f->server = dbus_server_listen (addr, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
@@ -99,14 +108,19 @@ test_connect (Fixture *f,
gconstpointer addr G_GNUC_UNUSED)
{
dbus_bool_t have_mem;
+ char *address = NULL;
+
+ if (f->skip)
+ return;
g_assert (f->server_conn == NULL);
- f->client_conn = dbus_connection_open_private (
- dbus_server_get_address (f->server), &f->e);
+ address = dbus_server_get_address (f->server);
+ f->client_conn = dbus_connection_open_private (address, &f->e);
assert_no_error (&f->e);
g_assert (f->client_conn != NULL);
test_connection_setup (f->ctx, f->client_conn);
+ dbus_free (address);
while (f->server_conn == NULL)
{
@@ -127,6 +141,9 @@ test_message (Fixture *f,
dbus_uint32_t serial;
DBusMessage *outgoing, *incoming;
+ if (f->skip)
+ return;
+
test_connect (f, addr);
outgoing = dbus_message_new_signal ("/com/example/Hello",
@@ -211,6 +228,9 @@ test_corrupt (Fixture *f,
int fd;
DBusMessage *incoming;
+ if (f->skip)
+ return;
+
test_message (f, addr);
dbus_connection_flush (f->server_conn);
@@ -271,11 +291,13 @@ test_byte_order (Fixture *f,
int fd;
char *blob;
const gchar *arg = not_a_dbus_message;
- const gchar * const *args = &arg;
int blob_len;
DBusMessage *message;
dbus_bool_t mem;
+ if (f->skip)
+ return;
+
test_message (f, addr);
message = dbus_message_new_signal ("/", "a.b", "c");
@@ -283,7 +305,7 @@ test_byte_order (Fixture *f,
/* Append 0xFF bytes, so that the length of the body when byte-swapped
* is 0xFF000000, which is invalid */
mem = dbus_message_append_args (message,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &args, 0xFF,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &arg, 0xFF,
DBUS_TYPE_INVALID);
g_assert (mem);
mem = dbus_message_marshal (message, &blob, &blob_len);
@@ -353,6 +375,7 @@ teardown (Fixture *f,
{
if (f->client_conn != NULL)
{
+ test_connection_shutdown (f->ctx, f->client_conn);
dbus_connection_close (f->client_conn);
dbus_connection_unref (f->client_conn);
f->client_conn = NULL;
@@ -360,6 +383,7 @@ teardown (Fixture *f,
if (f->server_conn != NULL)
{
+ test_connection_shutdown (f->ctx, f->server_conn);
dbus_connection_close (f->server_conn);
dbus_connection_unref (f->server_conn);
f->server_conn = NULL;
@@ -392,5 +416,10 @@ main (int argc,
g_test_add ("/corrupt/byte-order/tcp", Fixture, "tcp:host=127.0.0.1", setup,
test_byte_order, teardown);
+#ifdef DBUS_UNIX
+ g_test_add ("/corrupt/byte-order/unix", Fixture, "unix:tmpdir=/tmp", setup,
+ test_byte_order, teardown);
+#endif
+
return g_test_run ();
}
diff --git a/test/data/auth/cookie-sha1-username.auth-script b/test/data/auth/cookie-sha1-username.auth-script
new file mode 100644
index 00000000..45668294
--- /dev/null
+++ b/test/data/auth/cookie-sha1-username.auth-script
@@ -0,0 +1,12 @@
+UNIX_ONLY
+SERVER
+SEND 'AUTH DBUS_COOKIE_SHA1 WRONG_USERNAME_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+EXPECT_HAVE_NO_CREDENTIALS
+SEND 'AUTH DBUS_COOKIE_SHA1 USERNAME_HEX'
+EXPECT_COMMAND DATA
+EXPECT_STATE WAITING_FOR_INPUT
+EXPECT_HAVE_NO_CREDENTIALS
+# We don't actually complete DBUS_COOKIE_SHA1 authentication, because
+# it's non-trivial.
diff --git a/test/data/auth/cookie-sha1.auth-script b/test/data/auth/cookie-sha1.auth-script
new file mode 100644
index 00000000..f0dd33d7
--- /dev/null
+++ b/test/data/auth/cookie-sha1.auth-script
@@ -0,0 +1,11 @@
+SERVER
+SEND 'AUTH DBUS_COOKIE_SHA1 WRONG_USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+EXPECT_HAVE_NO_CREDENTIALS
+SEND 'AUTH DBUS_COOKIE_SHA1 USERID_HEX'
+EXPECT_COMMAND DATA
+EXPECT_STATE WAITING_FOR_INPUT
+EXPECT_HAVE_NO_CREDENTIALS
+# We don't actually complete DBUS_COOKIE_SHA1 authentication, because
+# it's non-trivial.
diff --git a/test/data/dbus-installed-tests.aaprofile.in b/test/data/dbus-installed-tests.aaprofile.in
new file mode 100644
index 00000000..7a65282a
--- /dev/null
+++ b/test/data/dbus-installed-tests.aaprofile.in
@@ -0,0 +1,98 @@
+# Copyright © 2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+#include <tunables/global>
+#include <tunables/sys>
+
+@DBUS_TEST_EXEC@/test-apparmor-activation {
+ #include <abstractions/apparmor_api/change_profile>
+ #include <abstractions/apparmor_api/find_mountpoint>
+ #include <abstractions/apparmor_api/is_enabled>
+ #include <abstractions/base>
+
+ # We aren't really confining this process seriously; allow most things.
+ /** mrix,
+ /tmp/dbus-daemon-test.*/{,**} w,
+ @{sys}/kernel/security/apparmor/** w,
+ dbus (send, receive, bind),
+ network,
+ signal,
+
+ # "Hat" subprofile used for the part of the process that imitates a client
+ # trying to cause service activation via auto-starting.
+ ^caller {
+ #include <abstractions/apparmor_api/change_profile>
+ #include <abstractions/base>
+
+ /** mrix,
+ @{sys}/kernel/security/apparmor/** w,
+ dbus (send, receive, bind),
+ network,
+ signal,
+
+ deny dbus send peer=(label=@DBUS_TEST_EXEC@/test-apparmor-activation//com.example.SendDeniedByAppArmorLabel),
+ deny dbus send peer=(name=com.example.SendDeniedByAppArmorName),
+
+ # There is no profile of this name. That's deliberate.
+ deny dbus send peer=(label=@DBUS_TEST_EXEC@/test-apparmor-activation-com.example.SendDeniedByNonexistentAppArmorLabel),
+ }
+
+ # Used when we check that XML-based policy still works.
+ ^com.example.ReceiveDenied {
+ #include <abstractions/apparmor_api/change_profile>
+ #include <abstractions/base>
+
+ /** mrix,
+ @{sys}/kernel/security/apparmor/** w,
+ dbus,
+ network,
+ signal,
+ }
+
+ # This one is never actually used, but needs to exist so ^caller can
+ # refer to it
+ ^com.example.SendDeniedByAppArmorLabel {
+ #include <abstractions/apparmor_api/change_profile>
+ #include <abstractions/base>
+
+ /** mrix,
+ @{sys}/kernel/security/apparmor/** w,
+ dbus (send, receive, bind),
+ network,
+ signal,
+ }
+
+ # "Hat" subprofile used for the part of the process that imitates a service
+ # that is not allowed to receive from the caller.
+ ^com.example.ReceiveDeniedByAppArmorLabel {
+ #include <abstractions/apparmor_api/change_profile>
+ #include <abstractions/base>
+
+ /** mrix,
+ @{sys}/kernel/security/apparmor/** w,
+ dbus (send, receive, bind),
+ network,
+ signal,
+
+ deny dbus receive peer=(label=@DBUS_TEST_EXEC@/test-apparmor-activation//caller),
+ }
+}
diff --git a/test/data/invalid-config-files/impossible-send.conf b/test/data/invalid-config-files/impossible-send.conf
new file mode 100644
index 00000000..136d7474
--- /dev/null
+++ b/test/data/invalid-config-files/impossible-send.conf
@@ -0,0 +1,6 @@
+<busconfig>
+ <listen>unix:path=/foo</listen>
+ <policy context="default">
+ <allow send_broadcast="true" send_destination="com.example.Bees"/>
+ </policy>
+</busconfig>
diff --git a/test/data/invalid-config-files/send-and-receive.conf b/test/data/invalid-config-files/send-and-receive.conf
new file mode 100644
index 00000000..f5b1a313
--- /dev/null
+++ b/test/data/invalid-config-files/send-and-receive.conf
@@ -0,0 +1,6 @@
+<busconfig>
+ <listen>unix:path=/foo</listen>
+ <policy context="default">
+ <allow receive_type="signal" send_destination="com.example.Bees"/>
+ </policy>
+</busconfig>
diff --git a/test/data/systemd-activation/com.example.ReceiveDeniedByAppArmorLabel.service.in b/test/data/systemd-activation/com.example.ReceiveDeniedByAppArmorLabel.service.in
new file mode 100644
index 00000000..295253ec
--- /dev/null
+++ b/test/data/systemd-activation/com.example.ReceiveDeniedByAppArmorLabel.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=com.example.ReceiveDeniedByAppArmorLabel
+Exec=/bin/false ReceiveDeniedByAppArmorLabel
+SystemdService=dbus-com.example.ReceiveDeniedByAppArmorLabel.service
+AssumedAppArmorLabel=@DBUS_TEST_EXEC@/test-apparmor-activation//com.example.ReceiveDeniedByAppArmorLabel
diff --git a/test/data/systemd-activation/com.example.SendDeniedByAppArmorLabel.service.in b/test/data/systemd-activation/com.example.SendDeniedByAppArmorLabel.service.in
new file mode 100644
index 00000000..882531b1
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SendDeniedByAppArmorLabel.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=com.example.SendDeniedByAppArmorLabel
+Exec=/bin/false SendDeniedByAppArmorLabel
+SystemdService=dbus-com.example.SendDeniedByAppArmorLabel.service
+AssumedAppArmorLabel=@DBUS_TEST_EXEC@/test-apparmor-activation//com.example.SendDeniedByAppArmorLabel
diff --git a/test/data/systemd-activation/com.example.SendDeniedByAppArmorName.service b/test/data/systemd-activation/com.example.SendDeniedByAppArmorName.service
new file mode 100644
index 00000000..f47674a0
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SendDeniedByAppArmorName.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SendDeniedByAppArmorName
+Exec=/bin/false SendDeniedByAppArmorName
+SystemdService=dbus-com.example.SendDeniedByAppArmorName.service
diff --git a/test/data/systemd-activation/com.example.SendDeniedByNonexistentAppArmorLabel.service.in b/test/data/systemd-activation/com.example.SendDeniedByNonexistentAppArmorLabel.service.in
new file mode 100644
index 00000000..bf843b13
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SendDeniedByNonexistentAppArmorLabel.service.in
@@ -0,0 +1,6 @@
+[D-BUS Service]
+Name=com.example.SendDeniedByNonexistentAppArmorLabel
+Exec=/bin/false SendDeniedByNonexistentAppArmorLabel
+SystemdService=dbus-com.example.SendDeniedByNonexistentAppArmorLabel.service
+# This label is not defined in any AppArmor profile
+AssumedAppArmorLabel=@DBUS_TEST_EXEC@/test-apparmor-activation-com.example.SendDeniedByNonexistentAppArmorLabel
diff --git a/test/data/systemd-activation/com.example.SystemdActivatable3.service b/test/data/systemd-activation/com.example.SystemdActivatable3.service
deleted file mode 100644
index f6f0559c..00000000
--- a/test/data/systemd-activation/com.example.SystemdActivatable3.service
+++ /dev/null
@@ -1,4 +0,0 @@
-[D-BUS Service]
-Name=com.example.SystemdActivatable3
-Exec=/bin/false 3
-SystemdService=dbus-com.example.SystemdActivatable3.service
diff --git a/test/data/systemd-activation/com.example.SystemdActivatable3.service.in b/test/data/systemd-activation/com.example.SystemdActivatable3.service.in
new file mode 100644
index 00000000..05180647
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SystemdActivatable3.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=com.example.SystemdActivatable3
+Exec=/bin/false 3
+SystemdService=dbus-com.example.SystemdActivatable3.service
+# This AppArmor label doesn't actually exist, but that's OK - nothing
+# prevents us from sending messages to it.
+AssumedAppArmorLabel=@DBUS_TEST_EXEC@/test-apparmor-activation-com.example.SystemdActivatable3
diff --git a/test/data/valid-config-files/as-another-user.conf.in b/test/data/valid-config-files/as-another-user.conf.in
new file mode 100644
index 00000000..89d00c8c
--- /dev/null
+++ b/test/data/valid-config-files/as-another-user.conf.in
@@ -0,0 +1,28 @@
+<!--
+Configuration similar to the system bus, to be used when testing rlimit
+handling.
+-->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <type>system</type>
+ <user>@DBUS_USER@</user>
+ <auth>EXTERNAL</auth>
+
+ <!-- This is not the same as the real system bus: we don't want to collide -->
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <allow user="*"/>
+ <deny own="*"/>
+ <deny send_type="method_call"/>
+ <allow send_type="signal"/>
+ <allow send_requested_reply="true" send_type="method_return"/>
+ <allow send_requested_reply="true" send_type="error"/>
+ <allow receive_type="method_call"/>
+ <allow receive_type="method_return"/>
+ <allow receive_type="error"/>
+ <allow receive_type="signal"/>
+ </policy>
+</busconfig>
diff --git a/test/data/valid-config-files/count-fds.conf.in b/test/data/valid-config-files/count-fds.conf.in
new file mode 100644
index 00000000..f9ae3edc
--- /dev/null
+++ b/test/data/valid-config-files/count-fds.conf.in
@@ -0,0 +1,22 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ <!-- Exercise rules that match on numbers of fds -->
+ <deny send_path="/test/DenySendMax2" max_fds="2"/>
+ <deny receive_path="/test/DenyReceiveMax3" max_fds="3"/>
+ <deny send_path="/test/DenySendMin4" min_fds="4"/>
+ <deny receive_path="/test/DenyReceiveMin5" min_fds="5"/>
+ </policy>
+
+</busconfig>
diff --git a/test/data/valid-config-files/forbidding.conf.in b/test/data/valid-config-files/forbidding.conf.in
index 6a674f88..d145613c 100644
--- a/test/data/valid-config-files/forbidding.conf.in
+++ b/test/data/valid-config-files/forbidding.conf.in
@@ -13,6 +13,16 @@
<!-- Exception: some messages are forbidden -->
<deny send_interface="com.example.CannotSend"/>
+
+ <deny send_interface="com.example.CannotBroadcast" send_broadcast="true"/>
+ <deny send_interface="com.example.CannotUnicast" send_broadcast="false"/>
+
+ <!-- A more long-winded way to spell the same things. -->
+ <deny send_interface="com.example.CannotBroadcast2"/>
+ <allow send_interface="com.example.CannotBroadcast2" send_broadcast="false"/>
+ <deny send_interface="com.example.CannotUnicast2"/>
+ <allow send_interface="com.example.CannotUnicast2" send_broadcast="true"/>
+
<deny receive_interface="com.example.CannotReceive"/>
</policy>
</busconfig>
diff --git a/test/data/valid-config-files/incoming-limit.conf.in b/test/data/valid-config-files/incoming-limit.conf.in
index 40ff2244..cd813442 100644
--- a/test/data/valid-config-files/incoming-limit.conf.in
+++ b/test/data/valid-config-files/incoming-limit.conf.in
@@ -15,4 +15,7 @@
</policy>
<limit name="max_incoming_bytes">1</limit>
+
+ <!-- Avoid reaching this limit -->
+ <limit name="max_replies_per_connection">1000000</limit>
</busconfig>
diff --git a/test/data/valid-config-files/max-completed-connections.conf.in b/test/data/valid-config-files/max-completed-connections.conf.in
new file mode 100644
index 00000000..a403e1fd
--- /dev/null
+++ b/test/data/valid-config-files/max-completed-connections.conf.in
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <limit name="max_completed_connections">3</limit>
+</busconfig>
diff --git a/test/data/valid-config-files/max-connections-per-user.conf.in b/test/data/valid-config-files/max-connections-per-user.conf.in
new file mode 100644
index 00000000..5394557b
--- /dev/null
+++ b/test/data/valid-config-files/max-connections-per-user.conf.in
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <limit name="max_connections_per_user">3</limit>
+</busconfig>
diff --git a/test/data/valid-config-files/max-match-rules-per-connection.conf.in b/test/data/valid-config-files/max-match-rules-per-connection.conf.in
new file mode 100644
index 00000000..27d27b63
--- /dev/null
+++ b/test/data/valid-config-files/max-match-rules-per-connection.conf.in
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <limit name="max_match_rules_per_connection">3</limit>
+</busconfig>
diff --git a/test/data/valid-config-files/max-names-per-connection.conf.in b/test/data/valid-config-files/max-names-per-connection.conf.in
new file mode 100644
index 00000000..186ed7b7
--- /dev/null
+++ b/test/data/valid-config-files/max-names-per-connection.conf.in
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <limit name="max_names_per_connection">4</limit>
+</busconfig>
diff --git a/test/data/valid-config-files/max-replies-per-connection.conf.in b/test/data/valid-config-files/max-replies-per-connection.conf.in
new file mode 100644
index 00000000..d4615ed8
--- /dev/null
+++ b/test/data/valid-config-files/max-replies-per-connection.conf.in
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <limit name="max_replies_per_connection">3</limit>
+</busconfig>
diff --git a/test/data/valid-config-files/pending-fd-timeout.conf.in b/test/data/valid-config-files/pending-fd-timeout.conf.in
new file mode 100644
index 00000000..849d8852
--- /dev/null
+++ b/test/data/valid-config-files/pending-fd-timeout.conf.in
@@ -0,0 +1,20 @@
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <!-- 500ms -->
+ <limit name="pending_fd_timeout">500</limit>
+</busconfig>
diff --git a/test/data/valid-config-files/standard-session-dirs.conf b/test/data/valid-config-files/standard-session-dirs.conf
new file mode 100644
index 00000000..f62dc87f
--- /dev/null
+++ b/test/data/valid-config-files/standard-session-dirs.conf
@@ -0,0 +1,8 @@
+<!-- Simplified version of session.conf -->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <listen>unix:path=/foo</listen>
+ <type>session</type>
+ <standard_session_servicedirs />
+</busconfig>
diff --git a/test/data/valid-config-files/systemd-activation.conf.in b/test/data/valid-config-files/systemd-activation.conf.in
index a3a59f05..2c3d2c21 100644
--- a/test/data/valid-config-files/systemd-activation.conf.in
+++ b/test/data/valid-config-files/systemd-activation.conf.in
@@ -2,7 +2,9 @@
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<listen>@TEST_LISTEN@</listen>
+
<servicedir>@DBUS_TEST_DATA@/systemd-activation</servicedir>
+ <standard_session_servicedirs />
<policy context="default">
<allow send_destination="*"/>
diff --git a/test/data/valid-introspection-files/lots-of-types.xml b/test/data/valid-introspection-files/lots-of-types.xml
deleted file mode 100644
index 8e0e6053..00000000
--- a/test/data/valid-introspection-files/lots-of-types.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Introspection 0.1//EN"
- "http://www.freedesktop.org/software/dbus/introspection.dtd">
-<node>
-
- <interface name="org.freedesktop.LotsOfTypesInterface">
-
- <method name="SetInt32Value">
- <arg name="theInt32" type="int32"/>
- </method>
- <method name="GetInt32Value">
- <arg name="theInt32" type="int32" direction="out"/>
- </method>
- <signal name="Int32ValueChanged">
- <arg name="newInt32Value" type="int32"/>
- </signal>
-
- <method name="SetUint32Value">
- <arg name="theUint32" type="uint32"/>
- </method>
- <method name="GetUint32Value">
- <arg name="theUint32" type="uint32" direction="out"/>
- </method>
- <signal name="Uint32ValueChanged">
- <arg name="newUint32Value" type="uint32"/>
- </signal>
-
- <method name="SetInt64Value">
- <arg name="theInt64" type="int64"/>
- </method>
- <method name="GetInt64Value">
- <arg name="theInt64" type="int64" direction="out"/>
- </method>
- <signal name="Int64ValueChanged">
- <arg name="newInt64Value" type="int64"/>
- </signal>
-
- <method name="SetUint64Value">
- <arg name="theUint64" type="uint64"/>
- </method>
- <method name="GetUint64Value">
- <arg name="theUint64" type="uint64" direction="out"/>
- </method>
- <signal name="Uint64ValueChanged">
- <arg name="newUint64Value" type="uint64"/>
- </signal>
-
- <method name="SetBooleanValue">
- <arg name="theBoolean" type="boolean"/>
- </method>
- <method name="GetBooleanValue">
- <arg name="theBoolean" type="boolean" direction="out"/>
- </method>
- <signal name="BooleanValueChanged">
- <arg name="newBooleanValue" type="boolean"/>
- </signal>
-
- <method name="SetStringValue">
- <arg name="theString" type="string"/>
- </method>
- <method name="GetStringValue">
- <arg name="theString" type="string" direction="out"/>
- </method>
- <signal name="StringValueChanged">
- <arg name="newStringValue" type="string"/>
- </signal>
-
- <method name="SetDoubleValue">
- <arg name="theDouble" type="double"/>
- </method>
- <method name="GetDoubleValue">
- <arg name="theDouble" type="double" direction="out"/>
- </method>
- <signal name="DoubleValueChanged">
- <arg name="newDoubleValue" type="double"/>
- </signal>
-
- </interface>
-
- <interface name="org.freedesktop.ASecondInterface">
- <method name="RandomFrobate">
- <arg type="boolean" direction="in"/>
- <arg type="string" direction="out"/>
- <arg type="string" direction="out"/>
- <arg type="int64"/> <!-- direction defaults to "in" -->
- <arg type="string" direction="out"/>
- <arg type="string" direction="out"/>
- <arg type="int32" direction="in"/>
- </method>
- </interface>
-
-</node>
-
diff --git a/test/dbus-daemon-eavesdrop.c b/test/dbus-daemon-eavesdrop.c
index 41985787..d2c0872d 100644
--- a/test/dbus-daemon-eavesdrop.c
+++ b/test/dbus-daemon-eavesdrop.c
@@ -88,11 +88,12 @@ sender_send_unicast_to_sender (Fixture *f)
signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE,
SENDER_SIGNAL_NAME);
- dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->sender));
-
if (signal == NULL)
g_error ("OOM");
+ if (!dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->sender)))
+ g_error ("OOM");
+
if (!dbus_connection_send (f->sender, signal, NULL))
g_error ("OOM");
@@ -109,11 +110,12 @@ sender_send_unicast_to_receiver (Fixture *f)
DBusMessage *signal;
signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_SIGNAL_NAME);
- dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->receiver));
-
if (signal == NULL)
g_error ("OOM");
+ if (!dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->receiver)))
+ g_error ("OOM");
+
if (!dbus_connection_send (f->sender, signal, NULL))
g_error ("OOM");
@@ -128,11 +130,12 @@ sender_send_broadcast (Fixture *f)
DBusMessage *signal;
signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_SIGNAL_NAME);
- dbus_message_set_destination (signal, NULL);
-
if (signal == NULL)
g_error ("OOM");
+ if (!dbus_message_set_destination (signal, NULL))
+ g_error ("OOM");
+
if (!dbus_connection_send (f->sender, signal, NULL))
g_error ("OOM");
@@ -152,11 +155,12 @@ sender_send_stopper (Fixture *f)
DBusMessage *signal;
signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_STOPPER_NAME);
- dbus_message_set_destination (signal, NULL);
-
if (signal == NULL)
g_error ("OOM");
+ if (!dbus_message_set_destination (signal, NULL))
+ g_error ("OOM");
+
if (!dbus_connection_send (f->sender, signal, NULL))
g_error ("OOM");
@@ -283,7 +287,7 @@ setup (Fixture *f,
f->ge = NULL;
dbus_error_init (&f->e);
- address = test_get_dbus_daemon (NULL, TEST_USER_ME, &f->daemon_pid);
+ address = test_get_dbus_daemon (NULL, TEST_USER_ME, NULL, &f->daemon_pid);
f->sender = test_connect_to_bus (f->ctx, address);
dbus_bus_request_name (f->sender, SENDER_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE,
@@ -403,8 +407,12 @@ teardown (Fixture *f,
f->eavesdropper = NULL;
}
- test_kill_pid (f->daemon_pid);
- g_spawn_close_pid (f->daemon_pid);
+ if (f->daemon_pid != 0)
+ {
+ test_kill_pid (f->daemon_pid);
+ g_spawn_close_pid (f->daemon_pid);
+ f->daemon_pid = 0;
+ }
test_main_context_unref (f->ctx);
}
diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c
index 72bcd08c..7d3bb4b2 100644
--- a/test/dbus-daemon.c
+++ b/test/dbus-daemon.c
@@ -34,14 +34,30 @@
#include <glib.h>
#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include "bus/stats.h"
#include "test-utils-glib.h"
#include <string.h>
#ifdef DBUS_UNIX
+# include <pwd.h>
# include <unistd.h>
# include <sys/types.h>
+
+# ifdef HAVE_GIO_UNIX
+ /* The CMake build system doesn't know how to check for this yet */
+# include <gio/gunixfdmessage.h>
+# endif
+
+# ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+# endif
+
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
#endif
/* Platforms where we know that credentials-passing passes both the
@@ -78,11 +94,14 @@ typedef struct {
GError *ge;
GPid daemon_pid;
+ gchar *address;
DBusConnection *left_conn;
DBusConnection *right_conn;
+ GQueue held_messages;
gboolean right_conn_echo;
+ gboolean right_conn_hold;
gboolean wait_forever_called;
gchar *tmp_runtime_dir;
@@ -115,7 +134,22 @@ echo_filter (DBusConnection *connection,
if (!dbus_connection_send (connection, reply, NULL))
g_error ("OOM");
- dbus_message_unref (reply);
+ dbus_clear_message (&reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+hold_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ Fixture *f = user_data;
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ g_queue_push_tail (&f->held_messages, dbus_message_ref (message));
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -124,6 +158,7 @@ typedef struct {
const char *bug_ref;
guint min_messages;
const char *config_file;
+ TestUser user;
enum { SPECIFY_ADDRESS = 0, RELY_ON_DEFAULT } connect_mode;
} Config;
@@ -132,7 +167,9 @@ setup (Fixture *f,
gconstpointer context)
{
const Config *config = context;
- gchar *address;
+
+ /* Some tests are fairly slow, so make the test timeout per-test */
+ test_timeout_reset (1);
f->ctx = test_main_context_get ();
f->ge = NULL;
@@ -147,19 +184,20 @@ setup (Fixture *f,
/* we're relying on being single-threaded for this to be safe */
f->saved_runtime_dir = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
g_setenv ("XDG_RUNTIME_DIR", f->tmp_runtime_dir, TRUE);
+ g_unsetenv ("DBUS_SESSION_BUS_ADDRESS");
}
- address = test_get_dbus_daemon (config ? config->config_file : NULL,
- TEST_USER_ME,
- &f->daemon_pid);
+ f->address = test_get_dbus_daemon (config ? config->config_file : NULL,
+ config ? config->user : TEST_USER_ME,
+ NULL, &f->daemon_pid);
- if (address == NULL)
+ if (f->address == NULL)
{
f->skip = TRUE;
return;
}
- f->left_conn = test_connect_to_bus (f->ctx, address);
+ f->left_conn = test_connect_to_bus (f->ctx, f->address);
if (config != NULL && config->connect_mode == RELY_ON_DEFAULT)
{
@@ -173,10 +211,8 @@ setup (Fixture *f,
}
else
{
- f->right_conn = test_connect_to_bus (f->ctx, address);
+ f->right_conn = test_connect_to_bus (f->ctx, f->address);
}
-
- g_free (address);
}
static void
@@ -189,6 +225,15 @@ add_echo_filter (Fixture *f)
}
static void
+add_hold_filter (Fixture *f)
+{
+ if (!dbus_connection_add_filter (f->right_conn, hold_filter, f, NULL))
+ g_error ("OOM");
+
+ f->right_conn_hold = TRUE;
+}
+
+static void
pc_count (DBusPendingCall *pc,
void *data)
{
@@ -198,6 +243,17 @@ pc_count (DBusPendingCall *pc,
}
static void
+pc_enqueue (DBusPendingCall *pc,
+ void *data)
+{
+ GQueue *q = data;
+ DBusMessage *m = dbus_pending_call_steal_reply (pc);
+
+ g_test_message ("message of type %d", dbus_message_get_type (m));
+ g_queue_push_tail (q, m);
+}
+
+static void
test_echo (Fixture *f,
gconstpointer context)
{
@@ -244,8 +300,8 @@ test_echo (Fixture *f,
NULL))
g_error ("OOM");
- dbus_pending_call_unref (pc);
- dbus_message_unref (m);
+ dbus_clear_pending_call (&pc);
+ dbus_clear_message (&m);
}
while (received < count)
@@ -298,8 +354,8 @@ test_no_reply (Fixture *f,
&reply, NULL))
g_error ("OOM");
- dbus_pending_call_unref (pc);
- dbus_message_unref (m);
+ dbus_clear_pending_call (&pc);
+ dbus_clear_message (&m);
if (mode == DISCONNECT)
{
@@ -308,8 +364,7 @@ test_no_reply (Fixture *f,
dbus_connection_remove_filter (f->right_conn, echo_filter, f);
dbus_connection_close (f->right_conn);
- dbus_connection_unref (f->right_conn);
- f->right_conn = NULL;
+ dbus_clear_connection (&f->right_conn);
}
while (reply == NULL)
@@ -329,6 +384,8 @@ test_no_reply (Fixture *f,
else
g_assert_cmpstr (f->e.message, ==,
"Message did not receive a reply (timeout by message bus)");
+
+ dbus_clear_message (&reply);
}
static void
@@ -363,8 +420,7 @@ test_creds (Fixture *f,
pc == NULL)
g_error ("OOM");
- dbus_message_unref (m);
- m = NULL;
+ dbus_clear_message (&m);
if (dbus_pending_call_get_completed (pc))
test_pending_call_store_reply (pc, &m);
@@ -488,6 +544,9 @@ test_creds (Fixture *f,
#ifdef G_OS_WIN32
g_assert (seen & SEEN_WINDOWS_SID);
#endif
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
}
static void
@@ -514,8 +573,7 @@ test_processid (Fixture *f,
pc == NULL)
g_error ("OOM");
- dbus_message_unref (m);
- m = NULL;
+ dbus_clear_message (&m);
if (dbus_pending_call_get_completed (pc))
test_pending_call_store_reply (pc, &m);
@@ -526,7 +584,18 @@ test_processid (Fixture *f,
while (m == NULL)
test_main_context_iterate (f->ctx, TRUE);
- if (dbus_message_get_args (m, &error,
+ if (dbus_set_error_from_message (&error, m))
+ {
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN);
+
+#ifdef PID_SHOULD_WORK
+ g_error ("Expected pid to be passed, but got %s: %s",
+ error.name, error.message);
+#endif
+
+ dbus_error_free (&error);
+ }
+ else if (dbus_message_get_args (m, &error,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID))
{
@@ -545,15 +614,11 @@ test_processid (Fixture *f,
}
else
{
- g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN);
-
-#ifdef PID_SHOULD_WORK
- g_error ("Expected pid to be passed, but got %s: %s",
- error.name, error.message);
-#endif
-
- dbus_error_free (&error);
+ g_error ("Unexpected error: %s: %s", error.name, error.message);
}
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
}
static void
@@ -582,8 +647,7 @@ test_canonical_path_uae (Fixture *f,
pc == NULL)
g_error ("OOM");
- dbus_message_unref (m);
- m = NULL;
+ dbus_clear_message (&m);
if (dbus_pending_call_get_completed (pc))
test_pending_call_store_reply (pc, &m);
@@ -598,7 +662,8 @@ test_canonical_path_uae (Fixture *f,
g_assert_cmpint (dbus_message_get_type (m), ==,
DBUS_MESSAGE_TYPE_METHOD_RETURN);
- dbus_message_unref (m);
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
/* Now try with the wrong object path */
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
@@ -620,8 +685,7 @@ test_canonical_path_uae (Fixture *f,
pc == NULL)
g_error ("OOM");
- dbus_message_unref (m);
- m = NULL;
+ dbus_clear_message (&m);
if (dbus_pending_call_get_completed (pc))
test_pending_call_store_reply (pc, &m);
@@ -638,10 +702,1401 @@ test_canonical_path_uae (Fixture *f,
DBUS_ERROR_ACCESS_DENIED);
g_assert_cmpstr (dbus_message_get_signature (m), ==, "s");
- dbus_message_unref (m);
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_max_connections (Fixture *f,
+ gconstpointer context)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ DBusConnection *third_conn;
+ DBusConnection *failing_conn;
+
+ if (f->skip)
+ return;
+
+ /* We have two connections already */
+ g_assert (f->left_conn != NULL);
+ g_assert (f->right_conn != NULL);
+
+ /* Our configuration file sets the limit to 3 connections, either globally
+ * or per uid, so this one is the last that will work */
+ third_conn = test_connect_to_bus (f->ctx, f->address);
+
+ /* This one is going to fail. We don't guarantee whether it will fail
+ * now, or while registering (implementation detail: it's the latter). */
+ failing_conn = dbus_connection_open_private (f->address, &error);
+
+ if (failing_conn != NULL)
+ {
+ gboolean ok = dbus_bus_register (failing_conn, &error);
+
+ g_assert (!ok);
+ }
+
+ g_assert (dbus_error_is_set (&error));
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
+
+ if (failing_conn != NULL)
+ dbus_connection_close (failing_conn);
+
+ dbus_clear_connection (&failing_conn);
+ dbus_connection_close (third_conn);
+ dbus_clear_connection (&third_conn);
+}
+
+static void
+test_max_replies_per_connection (Fixture *f,
+ gconstpointer context)
+{
+ GQueue received = G_QUEUE_INIT;
+ GQueue errors = G_QUEUE_INIT;
+ DBusMessage *m;
+ DBusPendingCall *pc;
+ guint i;
+ DBusError error = DBUS_ERROR_INIT;
+
+ if (f->skip)
+ return;
+
+ add_hold_filter (f);
+
+ /* The configured limit is 3 replies per connection. */
+ for (i = 0; i < 3; i++)
+ {
+ m = dbus_message_new_method_call (
+ dbus_bus_get_unique_name (f->right_conn), "/",
+ "com.example", "Spam");
+
+ if (m == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_INFINITE) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ if (dbus_pending_call_get_completed (pc))
+ pc_enqueue (pc, &received);
+ else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &received,
+ NULL))
+ g_error ("OOM");
+
+ dbus_pending_call_unref (pc);
+ dbus_message_unref (m);
+ }
+
+ while (g_queue_get_length (&f->held_messages) < 3)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ g_assert_cmpuint (g_queue_get_length (&received), ==, 0);
+ g_assert_cmpuint (g_queue_get_length (&errors), ==, 0);
+
+ /* Go a couple of messages over the limit. */
+ for (i = 0; i < 2; i++)
+ {
+ m = dbus_message_new_method_call (
+ dbus_bus_get_unique_name (f->right_conn), "/",
+ "com.example", "Spam");
+
+ if (m == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_INFINITE) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ if (dbus_pending_call_get_completed (pc))
+ pc_enqueue (pc, &errors);
+ else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &errors,
+ NULL))
+ g_error ("OOM");
+
+ dbus_pending_call_unref (pc);
+ dbus_message_unref (m);
+ }
+
+ /* Reply to the held messages. */
+ for (m = g_queue_pop_head (&f->held_messages);
+ m != NULL;
+ m = g_queue_pop_head (&f->held_messages))
+ {
+ DBusMessage *reply = dbus_message_new_method_return (m);
+
+ if (reply == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send (f->right_conn, reply, NULL))
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+ dbus_clear_message (&reply);
+ }
+
+ /* Wait for all 5 replies to come in. */
+ while (g_queue_get_length (&received) + g_queue_get_length (&errors) < 5)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ /* The first three succeeded. */
+ for (i = 0; i < 3; i++)
+ {
+ m = g_queue_pop_head (&received);
+ g_assert (m != NULL);
+
+ if (dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected error: %s: %s", error.name, error.message);
+
+ dbus_clear_message (&m);
+ }
+
+ /* The last two failed. */
+ for (i = 0; i < 2; i++)
+ {
+ m = g_queue_pop_head (&errors);
+ g_assert (m != NULL);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
+ dbus_error_free (&error);
+ dbus_clear_message (&m);
+ }
+
+ g_assert_cmpuint (g_queue_get_length (&received), ==, 0);
+ g_assert_cmpuint (g_queue_get_length (&errors), ==, 0);
+ g_queue_clear (&received);
+ g_queue_clear (&errors);
+}
+
+static void
+test_max_match_rules_per_connection (Fixture *f,
+ gconstpointer context)
+{
+ DBusError error = DBUS_ERROR_INIT;
+
+ if (f->skip)
+ return;
+
+ dbus_bus_add_match (f->left_conn, "sender='com.example.C1'", &error);
+ test_assert_no_error (&error);
+ dbus_bus_add_match (f->left_conn, "sender='com.example.C2'", &error);
+ test_assert_no_error (&error);
+ dbus_bus_add_match (f->left_conn, "sender='com.example.C3'", &error);
+ test_assert_no_error (&error);
+
+ dbus_bus_add_match (f->left_conn, "sender='com.example.C4'", &error);
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
+ dbus_error_free (&error);
+
+ dbus_bus_remove_match (f->left_conn, "sender='com.example.C3'", &error);
+ test_assert_no_error (&error);
+
+ dbus_bus_add_match (f->left_conn, "sender='com.example.C4'", &error);
+ test_assert_no_error (&error);
+}
+
+static void
+test_max_names_per_connection (Fixture *f,
+ gconstpointer context)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ int ret;
+
+ if (f->skip)
+ return;
+
+ /* The limit in the configuration file is set to 4, but we only own 3
+ * names here - remember that the unique name is a name too. */
+
+ ret = dbus_bus_request_name (f->left_conn, "com.example.C1", 0, &error);
+ test_assert_no_error (&error);
+ g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+ ret = dbus_bus_request_name (f->left_conn, "com.example.C2", 0, &error);
+ test_assert_no_error (&error);
+ g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+ ret = dbus_bus_request_name (f->left_conn, "com.example.C3", 0, &error);
+ test_assert_no_error (&error);
+ g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+ ret = dbus_bus_request_name (f->left_conn, "com.example.C4", 0, &error);
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
+ dbus_error_free (&error);
+ g_assert_cmpint (ret, ==, -1);
+
+ ret = dbus_bus_release_name (f->left_conn, "com.example.C3", &error);
+ test_assert_no_error (&error);
+ g_assert_cmpint (ret, ==, DBUS_RELEASE_NAME_REPLY_RELEASED);
+
+ ret = dbus_bus_request_name (f->left_conn, "com.example.C4", 0, &error);
+ test_assert_no_error (&error);
+ g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+}
+
+#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
+
+static DBusHandlerResult
+wait_for_disconnected_cb (DBusConnection *client_conn,
+ DBusMessage *message,
+ void *data)
+{
+ gboolean *disconnected = data;
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
+ {
+ *disconnected = TRUE;
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static const guchar partial_message[] =
+{
+ DBUS_LITTLE_ENDIAN,
+ DBUS_MESSAGE_TYPE_METHOD_CALL,
+ 0, /* flags */
+ 1, /* version */
+ 0xff, 0xff, 0, 0, /* length of body = 65535 bytes */
+ 1, 2, 3, 4, /* cookie */
+ 0xff, 0xff, 0, 0, /* length of header fields array = 65535 bytes */
+ 42 /* pretending to be the beginning of the header fields array */
+};
+
+static void
+send_all_with_fd (GSocket *socket,
+ const guchar *local_partial_message,
+ gsize len,
+ int fd)
+{
+ GSocketControlMessage *fdm = g_unix_fd_message_new ();
+ GError *error = NULL;
+ gssize sent;
+ GOutputVector vector = { local_partial_message, len };
+
+ g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (fdm), fd, &error);
+ g_assert_no_error (error);
+
+ sent = g_socket_send_message (socket, NULL, &vector, 1, &fdm, 1,
+ G_SOCKET_MSG_NONE, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (sent, >=, 1);
+ g_assert_cmpint (sent, <=, vector.size);
+
+ while (((gsize) sent) < vector.size)
+ {
+ vector.size -= sent;
+ vector.buffer = ((const guchar *) vector.buffer) + sent;
+ sent = g_socket_send_message (socket, NULL, &vector, 1, NULL, 0,
+ G_SOCKET_MSG_NONE, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (sent, >=, 1);
+ g_assert_cmpint (sent, <=, vector.size);
+ }
+
+ g_object_unref (fdm);
+}
+
+static void
+test_pending_fd_timeout (Fixture *f,
+ gconstpointer context)
+{
+ GError *error = NULL;
+ gint64 start;
+ int fd;
+ GSocket *socket;
+ gboolean have_mem;
+ gboolean disconnected = FALSE;
+
+ if (f->skip)
+ return;
+
+ if (getuid () == 0)
+ {
+ g_test_skip ("Cannot test, uid 0 is immune to this limit");
+ return;
+ }
+
+ have_mem = dbus_connection_add_filter (f->left_conn, wait_for_disconnected_cb,
+ &disconnected, NULL);
+ g_assert (have_mem);
+
+ /* This is not API. Never do this. */
+
+ if (!dbus_connection_get_socket (f->left_conn, &fd))
+ g_error ("failed to steal fd from left connection");
+
+ socket = g_socket_new_from_fd (fd, &error);
+ g_assert_no_error (error);
+ g_assert (socket != NULL);
+
+ /* We send part of a message that contains a fd, then stop. */
+ start = g_get_monotonic_time ();
+ send_all_with_fd (socket, partial_message, G_N_ELEMENTS (partial_message),
+ fd);
+
+ while (!disconnected)
+ {
+ test_progress ('.');
+ test_main_context_iterate (f->ctx, TRUE);
+
+ /* It should take 0.5s to get disconnected, as configured in
+ * valid-config-files/pending-fd-timeout.conf; but this test
+ * might get starved by other processes running in parallel
+ * (particularly on shared CI systems), so we have to be a lot
+ * more generous. Allow up to 10 seconds. */
+ g_assert_cmpint (g_get_monotonic_time (), <=,
+ start + (10 * G_USEC_PER_SEC));
+ }
+
+ g_object_unref (socket);
+}
+
+typedef struct
+{
+ const gchar *path;
+ guint n_fds;
+ gboolean should_work;
+} CountFdsVector;
+
+static const CountFdsVector count_fds_vectors[] =
+{
+ /* Deny sending if number of fds <= 2 */
+ { "/test/DenySendMax2", 1, FALSE },
+ { "/test/DenySendMax2", 2, FALSE },
+ { "/test/DenySendMax2", 3, TRUE },
+ { "/test/DenySendMax2", 4, TRUE },
+
+ /* Deny receiving if number of fds <= 3 */
+ { "/test/DenyReceiveMax3", 2, FALSE },
+ { "/test/DenyReceiveMax3", 3, FALSE },
+ { "/test/DenyReceiveMax3", 4, TRUE },
+ { "/test/DenyReceiveMax3", 5, TRUE },
+
+ /* Deny sending if number of fds >= 4 */
+ { "/test/DenySendMin4", 2, TRUE },
+ { "/test/DenySendMin4", 3, TRUE },
+ { "/test/DenySendMin4", 4, FALSE },
+ { "/test/DenySendMin4", 5, FALSE },
+
+ /* Deny receiving if number of fds >= 5 */
+ { "/test/DenyReceiveMin5", 3, TRUE },
+ { "/test/DenyReceiveMin5", 4, TRUE },
+ { "/test/DenyReceiveMin5", 5, FALSE },
+ { "/test/DenyReceiveMin5", 6, FALSE },
+};
+
+static void
+test_count_fds (Fixture *f,
+ gconstpointer context)
+{
+ GQueue received = G_QUEUE_INIT;
+ DBusMessage *m;
+ DBusPendingCall *pc;
+ guint i;
+ DBusError error = DBUS_ERROR_INIT;
+ const int stdin_fd = 0;
+
+ if (f->skip)
+ return;
+
+ add_hold_filter (f);
+
+ for (i = 0; i < G_N_ELEMENTS (count_fds_vectors); i++)
+ {
+ const CountFdsVector *vector = &count_fds_vectors[i];
+ guint j;
+
+ m = dbus_message_new_method_call (
+ dbus_bus_get_unique_name (f->right_conn), vector->path,
+ "com.example", "Spam");
+
+ if (m == NULL)
+ g_error ("OOM");
+
+ for (j = 0; j < vector->n_fds; j++)
+ {
+ if (!dbus_message_append_args (m,
+ DBUS_TYPE_UNIX_FD, &stdin_fd,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+ }
+
+ if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_INFINITE) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ if (dbus_pending_call_get_completed (pc))
+ pc_enqueue (pc, &received);
+ else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &received,
+ NULL))
+ g_error ("OOM");
+
+ dbus_pending_call_unref (pc);
+ dbus_message_unref (m);
+
+ if (vector->should_work)
+ {
+ DBusMessage *reply;
+
+ while (g_queue_get_length (&f->held_messages) < 1)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ g_assert_cmpint (g_queue_get_length (&f->held_messages), ==, 1);
+
+ m = g_queue_pop_head (&f->held_messages);
+
+ g_assert_cmpint (g_queue_get_length (&f->held_messages), ==, 0);
+
+ reply = dbus_message_new_method_return (m);
+
+ if (reply == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send (f->right_conn, reply, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (reply);
+ dbus_message_unref (m);
+ }
+
+ while (g_queue_get_length (&received) < 1)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ g_assert_cmpint (g_queue_get_length (&received), ==, 1);
+ m = g_queue_pop_head (&received);
+ g_assert (m != NULL);
+ g_assert_cmpint (g_queue_get_length (&received), ==, 0);
+
+ if (vector->should_work)
+ {
+ if (dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected error: %s: %s", error.name, error.message);
+
+ g_test_message ("Sending %u fds to %s was not denied, as expected",
+ vector->n_fds, vector->path);
+ }
+ else if (!dbus_set_error_from_message (&error, m))
+ {
+ g_error ("Unexpected success");
+ }
+ else
+ {
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_ACCESS_DENIED);
+ dbus_error_free (&error);
+ g_test_message ("Sending %u fds to %s was denied, as expected",
+ vector->n_fds, vector->path);
+ }
+
+ dbus_message_unref (m);
+ }
+}
+
+#endif
+
+static void
+test_peer_get_machine_id (Fixture *f,
+ gconstpointer context)
+{
+ char *what_i_think;
+ const char *what_daemon_thinks;
+ DBusMessage *m = NULL;
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+
+ if (f->skip)
+ return;
+
+ what_i_think = dbus_try_get_local_machine_id (&error);
+
+ if (what_i_think == NULL)
+ {
+ if (g_getenv ("DBUS_TEST_UNINSTALLED") != NULL)
+ {
+ /* When running unit tests during make check or make installcheck,
+ * tolerate this */
+ g_test_skip ("Machine UUID not available");
+ return;
+ }
+ else
+ {
+ /* When running integration tests, don't tolerate it */
+ g_error ("%s", error.message);
+ }
+ }
+
+ /* Check that the dbus-daemon agrees with us. */
+ m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_PEER,
+ "GetMachineId");
+
+ if (m == NULL ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_message_get_args (m, &error,
+ DBUS_TYPE_STRING, &what_daemon_thinks,
+ DBUS_TYPE_INVALID))
+ g_error ("%s: %s", error.name, error.message);
+
+ g_assert_cmpstr (what_i_think, ==, what_daemon_thinks);
+ g_assert_nonnull (what_daemon_thinks);
+ g_assert_cmpuint (strlen (what_daemon_thinks), ==, 32);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+ dbus_free (what_i_think);
}
static void
+test_peer_ping (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PEER, "Ping");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+
+ if (f->skip)
+ return;
+
+ m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PEER, "Ping");
+
+ if (m == NULL ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_message_get_args (m, &error, DBUS_TYPE_INVALID))
+ g_error ("%s: %s", error.name, error.message);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_get_invalid_path (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ "/", DBUS_INTERFACE_PROPERTIES, "Get");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *property = "Interfaces";
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ /* That object path does not have that interface */
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_get_invalid_iface (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = "com.example.Nope";
+ const char *property = "Whatever";
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_get_invalid (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *property = "Whatever";
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_PROPERTY);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_get_all_invalid_iface (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "GetAll");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = "com.example.Nope";
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_get_all_invalid_path (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ "/", DBUS_INTERFACE_PROPERTIES, "GetAll");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = DBUS_INTERFACE_DBUS;
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ /* That object path does not have that interface */
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_set_invalid_iface (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = "com.example.Nope";
+ const char *property = "Whatever";
+ DBusMessageIter args_iter;
+ DBusMessageIter var_iter;
+ dbus_bool_t b = FALSE;
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (m, &args_iter);
+
+ if (!dbus_message_iter_open_container (&args_iter,
+ DBUS_TYPE_VARIANT, "b", &var_iter) ||
+ !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
+ !dbus_message_iter_close_container (&args_iter, &var_iter) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_set_invalid_path (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ "/", DBUS_INTERFACE_PROPERTIES, "Set");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *property = "Interfaces";
+ DBusMessageIter args_iter;
+ DBusMessageIter var_iter;
+ dbus_bool_t b = FALSE;
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (m, &args_iter);
+
+ if (!dbus_message_iter_open_container (&args_iter,
+ DBUS_TYPE_VARIANT, "b", &var_iter) ||
+ !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
+ !dbus_message_iter_close_container (&args_iter, &var_iter) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_set_invalid (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *property = "Whatever";
+ DBusMessageIter args_iter;
+ DBusMessageIter var_iter;
+ dbus_bool_t b = FALSE;
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (m, &args_iter);
+
+ if (!dbus_message_iter_open_container (&args_iter,
+ DBUS_TYPE_VARIANT, "b", &var_iter) ||
+ !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
+ !dbus_message_iter_close_container (&args_iter, &var_iter) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_PROPERTY);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_set (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
+ DBusPendingCall *pc = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *property = "Features";
+ DBusMessageIter args_iter;
+ DBusMessageIter var_iter;
+ dbus_bool_t b = FALSE;
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (m, &args_iter);
+
+ if (!dbus_message_iter_open_container (&args_iter,
+ DBUS_TYPE_VARIANT, "b", &var_iter) ||
+ !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
+ !dbus_message_iter_close_container (&args_iter, &var_iter) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_set_error_from_message (&error, m))
+ g_error ("Unexpected success");
+
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_PROPERTY_READ_ONLY);
+ dbus_error_free (&error);
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+check_features (DBusMessageIter *var_iter)
+{
+ DBusMessageIter arr_iter;
+ gboolean have_systemd_activation = FALSE;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (var_iter), ==,
+ DBUS_TYPE_ARRAY);
+ g_assert_cmpint (dbus_message_iter_get_element_type (var_iter), ==,
+ DBUS_TYPE_STRING);
+ dbus_message_iter_recurse (var_iter, &arr_iter);
+
+ while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
+ {
+ const char *feature;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
+ DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic (&arr_iter, &feature);
+
+ g_test_message ("Feature: %s", feature);
+
+ if (g_strcmp0 (feature, "SystemdActivation") == 0)
+ have_systemd_activation = TRUE;
+
+ dbus_message_iter_next (&arr_iter);
+ }
+
+ /* We pass --systemd-activation to the daemon for this unit test on Unix
+ * (it can only work in practice on Linux, but there's nothing
+ * inherently Linux-specific about the protocol). */
+#ifdef DBUS_UNIX
+ g_assert_true (have_systemd_activation);
+#else
+ g_assert_false (have_systemd_activation);
+#endif
+}
+
+static void
+test_features (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
+ DBusPendingCall *pc = NULL;
+ DBusMessageIter args_iter;
+ DBusMessageIter var_iter;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *features = "Features";
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &features,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_message_iter_init (m, &args_iter))
+ g_error ("Reply has no arguments");
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&args_iter), ==,
+ DBUS_TYPE_VARIANT);
+
+ dbus_message_iter_recurse (&args_iter, &var_iter);
+ check_features (&var_iter);
+
+ if (dbus_message_iter_next (&args_iter))
+ g_error ("Reply has too many arguments");
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+check_interfaces (DBusMessageIter *var_iter)
+{
+ DBusMessageIter arr_iter;
+ gboolean have_monitoring = FALSE;
+ gboolean have_stats = FALSE;
+ gboolean have_verbose = FALSE;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (var_iter), ==,
+ DBUS_TYPE_ARRAY);
+ g_assert_cmpint (dbus_message_iter_get_element_type (var_iter), ==,
+ DBUS_TYPE_STRING);
+ dbus_message_iter_recurse (var_iter, &arr_iter);
+
+ while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
+ {
+ const char *iface;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
+ DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic (&arr_iter, &iface);
+ g_test_message ("Interface: %s", iface);
+
+ g_assert_cmpstr (iface, !=, DBUS_INTERFACE_DBUS);
+ g_assert_cmpstr (iface, !=, DBUS_INTERFACE_PROPERTIES);
+ g_assert_cmpstr (iface, !=, DBUS_INTERFACE_INTROSPECTABLE);
+ g_assert_cmpstr (iface, !=, DBUS_INTERFACE_PEER);
+
+ if (g_strcmp0 (iface, DBUS_INTERFACE_MONITORING) == 0)
+ have_monitoring = TRUE;
+ else if (g_strcmp0 (iface, BUS_INTERFACE_STATS) == 0)
+ have_stats = TRUE;
+ else if (g_strcmp0 (iface, DBUS_INTERFACE_VERBOSE) == 0)
+ have_verbose = TRUE;
+
+ dbus_message_iter_next (&arr_iter);
+ }
+
+ g_assert_true (have_monitoring);
+
+#ifdef DBUS_ENABLE_STATS
+ g_assert_true (have_stats);
+#else
+ g_assert_false (have_stats);
+#endif
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+ g_assert_true (have_verbose);
+#else
+ g_assert_false (have_verbose);
+#endif
+}
+
+static void
+test_interfaces (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
+ DBusPendingCall *pc = NULL;
+ DBusMessageIter args_iter;
+ DBusMessageIter var_iter;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ const char *ifaces = "Interfaces";
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_STRING, &ifaces,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ if (!dbus_message_iter_init (m, &args_iter))
+ g_error ("Reply has no arguments");
+
+ if (dbus_message_iter_get_arg_type (&args_iter) != DBUS_TYPE_VARIANT)
+ g_error ("Reply does not have a variant argument");
+
+ dbus_message_iter_recurse (&args_iter, &var_iter);
+ check_interfaces (&var_iter);
+
+ if (dbus_message_iter_next (&args_iter))
+ g_error ("Reply has too many arguments");
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+static void
+test_get_all (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "GetAll");
+ DBusPendingCall *pc = NULL;
+ DBusMessageIter args_iter;
+ DBusMessageIter arr_iter;
+ DBusMessageIter pair_iter;
+ DBusMessageIter var_iter;
+ const char *iface = DBUS_INTERFACE_DBUS;
+ gboolean have_features = FALSE;
+ gboolean have_interfaces = FALSE;
+
+ if (f->skip)
+ return;
+
+ if (m == NULL ||
+ !dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_INVALID) ||
+ !dbus_connection_send_with_reply (f->left_conn, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_clear_message (&m);
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ dbus_message_iter_init (m, &args_iter);
+ g_assert_cmpuint (dbus_message_iter_get_arg_type (&args_iter), ==,
+ DBUS_TYPE_ARRAY);
+ g_assert_cmpuint (dbus_message_iter_get_element_type (&args_iter), ==,
+ DBUS_TYPE_DICT_ENTRY);
+ dbus_message_iter_recurse (&args_iter, &arr_iter);
+
+ while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
+ {
+ const char *name;
+
+ dbus_message_iter_recurse (&arr_iter, &pair_iter);
+ g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
+ DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic (&pair_iter, &name);
+ dbus_message_iter_next (&pair_iter);
+ g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
+ DBUS_TYPE_VARIANT);
+ dbus_message_iter_recurse (&pair_iter, &var_iter);
+
+ if (g_strcmp0 (name, "Features") == 0)
+ {
+ check_features (&var_iter);
+ have_features = TRUE;
+ }
+ else if (g_strcmp0 (name, "Interfaces") == 0)
+ {
+ check_interfaces (&var_iter);
+ have_interfaces = TRUE;
+ }
+
+ dbus_message_iter_next (&arr_iter);
+ }
+
+ g_assert_true (have_features);
+ g_assert_true (have_interfaces);
+
+ if (dbus_message_iter_next (&args_iter))
+ g_error ("Reply has too many arguments");
+
+ dbus_clear_message (&m);
+ dbus_clear_pending_call (&pc);
+}
+
+#define DESIRED_RLIMIT 65536
+
+#ifdef DBUS_UNIX
+static void
+test_fd_limit (Fixture *f,
+ gconstpointer context)
+{
+#ifdef HAVE_PRLIMIT
+ struct rlimit lim;
+ const struct passwd *pwd = NULL;
+#endif
+
+ if (f->skip)
+ return;
+
+#ifdef HAVE_PRLIMIT
+
+ if (getuid () != 0)
+ {
+ g_test_skip ("Cannot test, only uid 0 is expected to raise fd limit");
+ return;
+ }
+
+ pwd = getpwnam (DBUS_USER);
+
+ if (pwd == NULL)
+ {
+ gchar *message = g_strdup_printf ("user '%s' does not exist",
+ DBUS_USER);
+
+ g_test_skip (message);
+ g_free (message);
+ return;
+ }
+
+ if (prlimit (getpid (), RLIMIT_NOFILE, NULL, &lim) < 0)
+ g_error ("prlimit(): %s", g_strerror (errno));
+
+ g_test_message ("our RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
+ (long) lim.rlim_cur, (long) lim.rlim_max);
+
+ if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= DESIRED_RLIMIT)
+ {
+ /* The dbus-daemon will have inherited our large rlimit */
+ g_test_skip ("Cannot test, our own fd limit was already large");
+ return;
+ }
+
+ if (prlimit (f->daemon_pid, RLIMIT_NOFILE, NULL, &lim) < 0)
+ g_error ("prlimit(): %s", g_strerror (errno));
+
+ g_test_message ("dbus-daemon's RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
+ (long) lim.rlim_cur, (long) lim.rlim_max);
+
+ if (lim.rlim_cur != RLIM_INFINITY)
+ g_assert_cmpint (lim.rlim_cur, >=, DESIRED_RLIMIT);
+
+#else /* !HAVE_PRLIMIT */
+
+ g_test_skip ("prlimit() not supported on this platform");
+
+#endif /* !HAVE_PRLIMIT */
+}
+#endif
+
+static void
teardown (Fixture *f,
gconstpointer context G_GNUC_UNUSED)
{
@@ -649,11 +2104,7 @@ teardown (Fixture *f,
g_clear_error (&f->ge);
if (f->left_conn != NULL)
- {
- dbus_connection_close (f->left_conn);
- dbus_connection_unref (f->left_conn);
- f->left_conn = NULL;
- }
+ dbus_connection_close (f->left_conn);
if (f->right_conn != NULL)
{
@@ -663,11 +2114,21 @@ teardown (Fixture *f,
f->right_conn_echo = FALSE;
}
+ if (f->right_conn_hold)
+ {
+ dbus_connection_remove_filter (f->right_conn, hold_filter, f);
+ f->right_conn_hold = FALSE;
+ }
+
+ g_queue_foreach (&f->held_messages, (GFunc) dbus_message_unref, NULL);
+ g_queue_clear (&f->held_messages);
+
dbus_connection_close (f->right_conn);
- dbus_connection_unref (f->right_conn);
- f->right_conn = NULL;
}
+ dbus_clear_connection (&f->left_conn);
+ dbus_clear_connection (&f->right_conn);
+
if (f->daemon_pid != 0)
{
test_kill_pid (f->daemon_pid);
@@ -681,10 +2142,11 @@ teardown (Fixture *f,
/* the socket may exist */
path = g_strdup_printf ("%s/bus", f->tmp_runtime_dir);
- g_assert (g_remove (path) == 0 || errno == ENOENT);
+
+ test_remove_if_exists (path);
g_free (path);
/* there shouldn't be anything else in there */
- g_assert_cmpint (g_rmdir (f->tmp_runtime_dir), ==, 0);
+ test_rmdir_must_exist (f->tmp_runtime_dir);
/* we're relying on being single-threaded for this to be safe */
if (f->saved_runtime_dir != NULL)
@@ -696,22 +2158,69 @@ teardown (Fixture *f,
}
test_main_context_unref (f->ctx);
+ g_free (f->address);
}
static Config limited_config = {
"34393", 10000, "valid-config-files/incoming-limit.conf",
- SPECIFY_ADDRESS
+ TEST_USER_ME, SPECIFY_ADDRESS
};
static Config finite_timeout_config = {
NULL, 1, "valid-config-files/finite-timeout.conf",
- SPECIFY_ADDRESS
+ TEST_USER_ME, SPECIFY_ADDRESS
};
#ifdef DBUS_UNIX
static Config listen_unix_runtime_config = {
"61303", 1, "valid-config-files/listen-unix-runtime.conf",
- RELY_ON_DEFAULT
+ TEST_USER_ME, RELY_ON_DEFAULT
+};
+#endif
+
+static Config max_completed_connections_config = {
+ NULL, 1, "valid-config-files/max-completed-connections.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
+static Config max_connections_per_user_config = {
+ NULL, 1, "valid-config-files/max-connections-per-user.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
+static Config max_replies_per_connection_config = {
+ NULL, 1, "valid-config-files/max-replies-per-connection.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
+static Config max_match_rules_per_connection_config = {
+ NULL, 1, "valid-config-files/max-match-rules-per-connection.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
+static Config max_names_per_connection_config = {
+ NULL, 1, "valid-config-files/max-names-per-connection.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
+#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
+static Config pending_fd_timeout_config = {
+ NULL, 1, "valid-config-files/pending-fd-timeout.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
+static Config count_fds_config = {
+ NULL, 1, "valid-config-files/count-fds.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+#endif
+
+#if defined(DBUS_UNIX)
+static Config as_another_user_config = {
+ NULL, 1, "valid-config-files/as-another-user.conf",
+ /* We start the dbus-daemon as root and drop privileges, like the
+ * real system bus does */
+ TEST_USER_ROOT, SPECIFY_ADDRESS
};
#endif
@@ -732,12 +2241,68 @@ main (int argc,
g_test_add ("/processid", Fixture, NULL, setup, test_processid, teardown);
g_test_add ("/canonical-path/uae", Fixture, NULL,
setup, test_canonical_path_uae, teardown);
+ g_test_add ("/limits/max-completed-connections", Fixture,
+ &max_completed_connections_config,
+ setup, test_max_connections, teardown);
+ g_test_add ("/limits/max-connections-per-user", Fixture,
+ &max_connections_per_user_config,
+ setup, test_max_connections, teardown);
+ g_test_add ("/limits/max-replies-per-connection", Fixture,
+ &max_replies_per_connection_config,
+ setup, test_max_replies_per_connection, teardown);
+ g_test_add ("/limits/max-match-rules-per-connection", Fixture,
+ &max_match_rules_per_connection_config,
+ setup, test_max_match_rules_per_connection, teardown);
+ g_test_add ("/limits/max-names-per-connection", Fixture,
+ &max_names_per_connection_config,
+ setup, test_max_names_per_connection, teardown);
+ g_test_add ("/peer/ping", Fixture, NULL, setup, test_peer_ping, teardown);
+ g_test_add ("/peer/get-machine-id", Fixture, NULL,
+ setup, test_peer_get_machine_id, teardown);
+ g_test_add ("/properties/get-invalid-iface", Fixture, NULL,
+ setup, test_get_invalid_iface, teardown);
+ g_test_add ("/properties/get-invalid-path", Fixture, NULL,
+ setup, test_get_invalid_path, teardown);
+ g_test_add ("/properties/get-invalid", Fixture, NULL,
+ setup, test_get_invalid, teardown);
+ g_test_add ("/properties/get-all-invalid-iface", Fixture, NULL, setup,
+ test_get_all_invalid_iface, teardown);
+ g_test_add ("/properties/get-all-invalid-path", Fixture, NULL, setup,
+ test_get_all_invalid_path, teardown);
+ g_test_add ("/properties/set-invalid-iface", Fixture, NULL,
+ setup, test_set_invalid_iface, teardown);
+ g_test_add ("/properties/set-invalid-path", Fixture, NULL,
+ setup, test_set_invalid_path, teardown);
+ g_test_add ("/properties/set-invalid", Fixture, NULL,
+ setup, test_set_invalid, teardown);
+ g_test_add ("/properties/set", Fixture, NULL,
+ setup, test_set, teardown);
+ g_test_add ("/properties/features", Fixture, NULL,
+ setup, test_features, teardown);
+ g_test_add ("/properties/interfaces", Fixture, NULL, setup,
+ test_interfaces, teardown);
+ g_test_add ("/properties/get-all", Fixture, NULL, setup,
+ test_get_all, teardown);
+
+#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
+ g_test_add ("/limits/pending-fd-timeout", Fixture,
+ &pending_fd_timeout_config,
+ setup, test_pending_fd_timeout, teardown);
+ g_test_add ("/policy/count-fds", Fixture, &count_fds_config,
+ setup, test_count_fds, teardown);
+#endif
+
#ifdef DBUS_UNIX
/* We can't test this in loopback.c with the rest of unix:runtime=yes,
* because dbus_bus_get[_private] is the only way to use the default,
* and that blocks on a round-trip to the dbus-daemon */
g_test_add ("/unix-runtime-is-default", Fixture, &listen_unix_runtime_config,
setup, test_echo, teardown);
+
+ g_test_add ("/fd-limit/session", Fixture, NULL,
+ setup, test_fd_limit, teardown);
+ g_test_add ("/fd-limit/system", Fixture, &as_another_user_config,
+ setup, test_fd_limit, teardown);
#endif
return g_test_run ();
diff --git a/test/fdpass.c b/test/fdpass.c
index 665b4a12..4a3edc4e 100644
--- a/test/fdpass.c
+++ b/test/fdpass.c
@@ -79,6 +79,7 @@ _DBUS_STATIC_ASSERT (MAX_MESSAGE_UNIX_FDS < TOO_MANY_FDS);
typedef struct {
TestMainContext *ctx;
DBusError e;
+ gboolean skip;
DBusServer *server;
@@ -172,6 +173,9 @@ test_connect (Fixture *f,
{
char *address;
+ if (f->skip)
+ return;
+
g_assert (f->left_server_conn == NULL);
g_assert (f->right_server_conn == NULL);
@@ -251,6 +255,14 @@ setup_common (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->messages);
+ if ((g_str_has_prefix (address, "tcp:") ||
+ g_str_has_prefix (address, "nonce-tcp:")) &&
+ !test_check_tcp_works ())
+ {
+ f->skip = TRUE;
+ return;
+ }
+
f->server = dbus_server_listen (address, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
@@ -289,6 +301,9 @@ static void
test_unsupported (Fixture *f,
gconstpointer data)
{
+ if (f->skip)
+ return;
+
test_connect (f, FALSE);
if (dbus_connection_can_send_type (f->left_client_conn,
@@ -321,6 +336,9 @@ test_relay (Fixture *f,
struct stat stat_before;
struct stat stat_after;
+ if (f->skip)
+ return;
+
test_connect (f, TRUE);
outgoing = dbus_message_new_signal ("/com/example/Hello",
@@ -359,7 +377,9 @@ test_relay (Fixture *f,
g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello");
g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial);
- if (!dbus_message_get_args (incoming,
+ if (dbus_set_error_from_message (&f->e, incoming))
+ g_error ("%s: %s", f->e.name, f->e.message);
+ else if (!dbus_message_get_args (incoming,
&f->e,
DBUS_TYPE_UNIX_FD, &fd_after,
DBUS_TYPE_INVALID))
@@ -401,6 +421,9 @@ test_limit (Fixture *f,
DBusMessage *outgoing, *incoming;
int i;
+ if (f->skip)
+ return;
+
test_connect (f, TRUE);
outgoing = dbus_message_new_signal ("/com/example/Hello",
@@ -459,6 +482,9 @@ test_too_many (Fixture *f,
DBusMessage *outgoing;
unsigned int i;
+ if (f->skip)
+ return;
+
test_connect (f, TRUE);
outgoing = dbus_message_new_signal ("/com/example/Hello",
@@ -511,6 +537,12 @@ test_too_many_split (Fixture *f,
DBusString buffer;
int fds[TOO_MANY_FDS];
int done;
+#ifdef HAVE_GETRLIMIT
+ struct rlimit lim;
+#endif
+
+ if (f->skip)
+ return;
/* This test deliberately pushes up against OS limits, so skip it
* if we don't have enough fds. 4 times the maximum per message
@@ -518,8 +550,6 @@ test_too_many_split (Fixture *f,
* we actually send, the copy that we potentially receive, and some
* spare capacity for everything else. */
#ifdef HAVE_GETRLIMIT
- struct rlimit lim;
-
if (getrlimit (RLIMIT_NOFILE, &lim) == 0)
{
if (lim.rlim_cur != RLIM_INFINITY &&
@@ -641,6 +671,9 @@ test_flood (Fixture *f,
DBusMessage *outgoing[SOME_MESSAGES];
dbus_uint32_t serial;
+ if (f->skip)
+ return;
+
test_connect (f, TRUE);
for (j = 0; j < SOME_MESSAGES; j++)
@@ -713,6 +746,9 @@ test_odd_limit (Fixture *f,
DBusMessage *outgoing;
int i;
+ if (f->skip)
+ return;
+
test_connect (f, TRUE);
dbus_connection_set_max_message_unix_fds (f->left_server_conn, 7);
dbus_connection_set_max_message_unix_fds (f->right_server_conn, 7);
diff --git a/test/integration/transient-services.sh b/test/integration/transient-services.sh
new file mode 100644
index 00000000..2d946d9e
--- /dev/null
+++ b/test/integration/transient-services.sh
@@ -0,0 +1,191 @@
+#!/bin/sh
+
+# Copyright © 2017 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -e
+
+if test -z "$XDG_RUNTIME_DIR"; then
+ echo "1..0 # SKIP - $XDG_RUNTIME_DIR is empty or unset"
+ exit 0
+fi
+
+# test -O is non-POSIX, but bash and dash have it. If it doesn't work,
+# we're probably not on Linux and so would likely be skipping this test
+# anyway.
+if ! test -O "$XDG_RUNTIME_DIR"; then
+ echo "1..0 # SKIP - $XDG_RUNTIME_DIR is not ours or test -O does not work"
+ exit 0
+fi
+
+if ! test -S "$XDG_RUNTIME_DIR/bus"; then
+ echo "1..0 # SKIP - $XDG_RUNTIME_DIR/bus is not a socket"
+ exit 0
+fi
+
+if ! test -O "$XDG_RUNTIME_DIR/bus"; then
+ echo "1..0 # SKIP - $XDG_RUNTIME_DIR/bus is not ours"
+ exit 0
+fi
+
+if test -n "$DBUS_SESSION_BUS_ADDRESS" && \
+ ! test "unix:path=$XDG_RUNTIME_DIR/bus" = "$DBUS_SESSION_BUS_ADDRESS"; then
+ echo "1..0 # SKIP - DBUS_SESSION_BUS_ADDRESS does not point to $XDG_RUNTIME_DIR/bus"
+ exit 0
+fi
+
+# Any unique token that won't collide would do here. It must start with
+# a letter or underscore.
+unique="t$(dbus-uuidgen)"
+
+if ! workdir="$(mktemp -d)"; then
+ echo "1..0 # SKIP - mktemp -d doesn't work"
+ exit 0
+fi
+
+cleanup () {
+ rm -fr "$workdir"
+ rm -f "$XDG_RUNTIME_DIR/dbus-1/services/com.example.DBusTests.$unique.tmp"
+ rm -f "$XDG_RUNTIME_DIR/dbus-1/services/com.example.DBusTests.$unique.service"
+ rm -f "$XDG_RUNTIME_DIR/dbus-1/services/com.example.DBusTests.Systemd.$unique.tmp"
+ rm -f "$XDG_RUNTIME_DIR/dbus-1/services/com.example.DBusTests.Systemd.$unique.service"
+ rm -f "$XDG_RUNTIME_DIR/systemd/user/dbus-com.example.DBusTests.Systemd.$unique.service"
+}
+trap cleanup EXIT
+
+echo "1..2"
+
+# This is an integration test, so we expect the dbus-daemon to already be
+# running
+if ! test -d "$XDG_RUNTIME_DIR/dbus-1/services"; then
+ echo "Bail out! $XDG_RUNTIME_DIR/dbus-1/services is not a directory"
+ exit 1
+fi
+
+cd "$XDG_RUNTIME_DIR/dbus-1/services"
+
+sed -e 's/^ *//' > "com.example.DBusTests.$unique.tmp" <<EOF
+ [D-BUS Service]
+ Name=com.example.DBusTests.$unique
+ Exec=/bin/sh -c 'touch "\$1"; exit 1' sh '$workdir/ran-$unique'
+EOF
+mv "com.example.DBusTests.$unique.tmp" "com.example.DBusTests.$unique.service"
+
+(
+dbus-send --session --dest="org.freedesktop.DBus" \
+ --type=method_call --print-reply /org/freedesktop/DBus \
+ org.freedesktop.DBus.ReloadConfig || touch "$workdir/failed" \
+) 2>&1 | sed -e 's/^/# /'
+
+if [ -e "$workdir/failed" ]; then
+ echo "Bail out! Unable to tell dbus-daemon to reload"
+ exit 1
+fi
+
+# Because the service never actually takes a bus name, we expect this to fail;
+# but its exit status is ignored because it's in a pipeline.
+dbus-send --session --dest="com.example.DBusTests.$unique" \
+ --type=method_call --print-reply / com.example.DBusTests.ThisWillFail \
+ 2>&1 | sed -e 's/^/# /'
+
+if [ -e "$workdir/ran-$unique" ]; then
+ echo "ok 1 - attempted to run transient service directly"
+else
+ echo "not ok 1 - no sign of having run transient service"
+fi
+
+# See whether systemd is on the session bus.
+(
+dbus-send --session --dest="org.freedesktop.systemd1" \
+ --type=method_call --print-reply /org/freedesktop/systemd1/Manager \
+ org.freedesktop.DBus.Peer.Ping || touch "$workdir/no-systemd" \
+) 2>&1 | sed -e 's/^/# /'
+
+if [ -d "$XDG_RUNTIME_DIR/systemd" ] && ! [ -e "$workdir/no-systemd" ]; then
+
+ # systemd is Linux-specific, so we can assume GNU mkdir.
+ mkdir -p -m700 "$XDG_RUNTIME_DIR/systemd/user"
+ cd "$XDG_RUNTIME_DIR/systemd/user"
+
+ sed -e 's/^ *//' > "dbus-com.example.DBusTests.Systemd.$unique.tmp" <<EOF
+ [Unit]
+ Description=Non-functional service in the dbus integration tests
+ [Service]
+ ExecStart=/bin/sh -c 'touch "\$1"; exit 1' sh '$workdir/ran-$unique-via-systemd'
+ Type=forking
+EOF
+ mv "dbus-com.example.DBusTests.Systemd.$unique.tmp" \
+ "dbus-com.example.DBusTests.Systemd.$unique.service"
+
+ if ! systemctl --user daemon-reload; then
+ echo "Bail out! Unable to tell systemd to reload"
+ exit 1
+ fi
+
+ cd "$XDG_RUNTIME_DIR/dbus-1/services"
+
+ sed -e 's/^ *//' > "com.example.DBusTests.Systemd.$unique.tmp" <<EOF
+ [D-BUS Service]
+ Name=com.example.DBusTests.Systemd.$unique
+ SystemdService=dbus-com.example.DBusTests.Systemd.$unique.service
+ Exec=/bin/sh -c 'touch "\$1"; exit 1' sh '$workdir/ran-$unique-wrong'
+EOF
+ mv "com.example.DBusTests.Systemd.$unique.tmp" \
+ "com.example.DBusTests.Systemd.$unique.service"
+
+ (
+ dbus-send --session --dest="org.freedesktop.DBus" \
+ --type=method_call --print-reply /org/freedesktop/DBus \
+ org.freedesktop.DBus.ReloadConfig || touch "$workdir/failed" \
+ ) 2>&1 | sed -e 's/^/# /'
+
+ if [ -e "$workdir/failed" ]; then
+ echo "Bail out! Unable to tell dbus-daemon to reload"
+ exit 1
+ fi
+
+ # Because the service never actually takes a bus name, we expect this to fail;
+ # but its exit status is ignored because it's in a pipeline.
+ #
+ # systemd never sends back an ActivationFailure message for a service
+ # if it starts the job but the service subsequently doesn't behave as
+ # intended, so use a relatively short timeout (3000ms).
+ dbus-send --session --dest="com.example.DBusTests.Systemd.$unique" \
+ --reply-timeout=3000 --type=method_call --print-reply \
+ / com.example.DBusTests.ThisWillFail \
+ 2>&1 | sed -e 's/^/# /'
+
+ if [ -e "$workdir/ran-$unique-via-systemd" ]; then
+ echo "ok 2 - attempted to run transient service via systemd"
+ elif [ -e "$workdir/ran-$unique-wrong" ]; then
+ echo "not ok 2 - ran transient service incorrectly"
+ else
+ echo "not ok 2 - no sign of having run transient service"
+ fi
+else
+ echo "ok 2 # SKIP session bus does not appear to be managed by systemd"
+fi
+
+echo "# Done."
+cleanup
+trap '' EXIT
+exit 0
diff --git a/test/internals/printf.c b/test/internals/printf.c
index 2006f321..fb8f3552 100644
--- a/test/internals/printf.c
+++ b/test/internals/printf.c
@@ -34,6 +34,10 @@
#include <stdio.h>
#include <stdlib.h>
+static void do_test (int minimum,
+ const char *format,
+ ...) _DBUS_GNUC_PRINTF (2, 3);
+
static void
do_test (int minimum,
const char *format,
diff --git a/test/internals/refs.c b/test/internals/refs.c
index a4656622..72ff8741 100644
--- a/test/internals/refs.c
+++ b/test/internals/refs.c
@@ -80,11 +80,6 @@ typedef struct {
VoidFunc unlock;
} Thread;
-/* provide backwards compatibility shim when building with a glib <= 2.30.x */
-#if !GLIB_CHECK_VERSION(2,31,0)
-#define g_thread_new(name,func,data) g_thread_create(func,data,TRUE,NULL)
-#endif
-
static gpointer
ref_thread (gpointer data)
{
@@ -206,6 +201,9 @@ setup (Fixture *f,
if (!dbus_threads_init_default ())
g_error ("OOM");
+ /* This can be fairly slow, so make the test timeout per-test */
+ test_timeout_reset (1);
+
f->n_threads = N_THREADS;
f->n_refs = N_REFS;
@@ -225,7 +223,12 @@ setup (Fixture *f,
dbus_error_init (&f->e);
+#ifdef DBUS_UNIX
+ f->server = dbus_server_listen ("unix:tmpdir=/tmp", &f->e);
+#else
f->server = dbus_server_listen ("tcp:host=127.0.0.1", &f->e);
+#endif
+
assert_no_error (&f->e);
g_assert (f->server != NULL);
diff --git a/test/internals/server-oom.c b/test/internals/server-oom.c
new file mode 100644
index 00000000..4c3ab058
--- /dev/null
+++ b/test/internals/server-oom.c
@@ -0,0 +1,140 @@
+/* Targeted unit tests for OOM paths in DBusServer
+ *
+ * Copyright © 2017 Collabora Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include "dbus/dbus-internals.h"
+#include "dbus/dbus-pipe.h"
+#include "dbus/dbus-server-socket.h"
+#include "test-utils-glib.h"
+
+/* Return TRUE if the right thing happens, but the right thing might include
+ * OOM. */
+static dbus_bool_t
+test_new_server (void *user_data)
+{
+ const char *listen_address = user_data;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusServer *server = NULL;
+ dbus_bool_t result = FALSE;
+
+ server = dbus_server_listen (listen_address, &error);
+
+ if (server == NULL)
+ goto out;
+
+ result = TRUE;
+
+out:
+ if (result)
+ {
+ test_assert_no_error (&error);
+ }
+ else
+ {
+ g_assert_cmpstr (error.name, ==, DBUS_ERROR_NO_MEMORY);
+ result = TRUE;
+ }
+
+ if (server != NULL)
+ dbus_server_disconnect (server);
+
+ dbus_clear_server (&server);
+ dbus_error_free (&error);
+
+ return result;
+}
+
+typedef struct
+{
+ const gchar *name;
+ DBusTestMemoryFunction function;
+ const void *data;
+} OOMTestCase;
+
+static void
+test_oom_wrapper (gconstpointer data)
+{
+ const OOMTestCase *test = data;
+
+ if ((g_str_has_prefix (test->data, "tcp:") ||
+ g_str_has_prefix (test->data, "nonce-tcp:")) &&
+ !test_check_tcp_works ())
+ return;
+
+ if (!_dbus_test_oom_handling (test->name, test->function,
+ (void *) test->data))
+ {
+ g_test_message ("OOM test failed");
+ g_test_fail ();
+ }
+}
+
+static GQueue *test_cases_to_free = NULL;
+
+static void
+add_oom_test (const gchar *name,
+ DBusTestMemoryFunction function,
+ const void *data)
+{
+ /* By using GLib memory allocation here, we avoid being affected by
+ * dbus_shutdown() or contributing to
+ * _dbus_get_malloc_blocks_outstanding() */
+ OOMTestCase *test_case = g_new0 (OOMTestCase, 1);
+
+ test_case->name = name;
+ test_case->function = function;
+ test_case->data = data;
+ g_test_add_data_func (name, test_case, test_oom_wrapper);
+ g_queue_push_tail (test_cases_to_free, test_case);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ int ret;
+
+ test_init (&argc, &argv);
+
+ test_cases_to_free = g_queue_new ();
+ add_oom_test ("/server/new-tcp", test_new_server, "tcp:host=127.0.0.1,bind=127.0.0.1");
+ add_oom_test ("/server/new-nonce-tcp", test_new_server, "nonce-tcp:host=127.0.0.1,bind=127.0.0.1");
+ add_oom_test ("/server/new-tcp-star", test_new_server, "tcp:host=127.0.0.1,bind=*");
+ add_oom_test ("/server/new-tcp-v4", test_new_server, "tcp:host=127.0.0.1,bind=127.0.0.1,family=ipv4");
+#ifdef DBUS_UNIX
+ add_oom_test ("/server/unix", test_new_server, "unix:tmpdir=/tmp");
+#endif
+
+ ret = g_test_run ();
+
+ g_queue_free_full (test_cases_to_free, g_free);
+ return ret;
+}
diff --git a/test/internals/syslog.c b/test/internals/syslog.c
index 805c5784..e69c14a1 100644
--- a/test/internals/syslog.c
+++ b/test/internals/syslog.c
@@ -47,42 +47,49 @@ setup (Fixture *f,
/* hopefully clear enough that people don't think these messages in syslog
* are a bug */
-#define MESSAGE "regression test for _dbus_system_log(): "
+#define MESSAGE "regression test for _dbus_log(): "
static void
-test_syslog (Fixture *f,
+test_syslog_normal (Fixture *f,
gconstpointer data)
{
-#ifndef G_OS_WIN32
- if (g_test_trap_fork (0, 0))
+ if (g_test_subprocess ())
{
- _dbus_init_system_log (FALSE);
- _dbus_system_log (DBUS_SYSTEM_LOG_FATAL, MESSAGE "%d", 23);
- /* should not be reached: exit 0 so the assertion in the main process
- * will fail */
- exit (0);
- }
+ _dbus_init_system_log ("test-syslog",
+ DBUS_LOG_FLAGS_SYSTEM_LOG | DBUS_LOG_FLAGS_STDERR);
+ _dbus_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
+ _dbus_log (DBUS_SYSTEM_LOG_WARNING, MESSAGE "%d", 45);
+ _dbus_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);
+ _dbus_log (DBUS_SYSTEM_LOG_ERROR, MESSAGE "%d", 23);
+
+ _dbus_init_system_log ("test-syslog-stderr", DBUS_LOG_FLAGS_STDERR);
+ _dbus_log (DBUS_SYSTEM_LOG_INFO,
+ MESSAGE "this should not appear in the syslog");
+ _dbus_init_system_log ("test-syslog-both",
+ DBUS_LOG_FLAGS_SYSTEM_LOG | DBUS_LOG_FLAGS_STDERR);
+ _dbus_log (DBUS_SYSTEM_LOG_INFO,
+ MESSAGE "this should appear in the syslog and on stderr");
+ _dbus_init_system_log ("test-syslog-only", DBUS_LOG_FLAGS_SYSTEM_LOG);
+ _dbus_log (DBUS_SYSTEM_LOG_INFO,
+ MESSAGE "this should appear in the syslog only");
- g_test_trap_assert_failed ();
- g_test_trap_assert_stderr ("*" MESSAGE "23\n*");
-
- if (g_test_trap_fork (0, 0))
- {
- _dbus_init_system_log (FALSE);
- _dbus_system_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
- _dbus_system_log (DBUS_SYSTEM_LOG_WARNING, MESSAGE "%d", 45);
- _dbus_system_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);
exit (0);
}
+ g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_passed ();
- g_test_trap_assert_stderr ("*" MESSAGE "42\n*" MESSAGE "45\n*" MESSAGE "666\n*");
-#endif
- /* manual test (this is the best we can do on Windows) */
- _dbus_init_system_log (FALSE);
- _dbus_system_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
- _dbus_system_log (DBUS_SYSTEM_LOG_WARNING, MESSAGE "%d", 45);
- _dbus_system_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);
+ g_test_trap_assert_stderr ("*" MESSAGE "42\n"
+ "*" MESSAGE "45\n"
+ "*" MESSAGE "666\n"
+ "*" MESSAGE "23\n"
+ "*test-syslog-stderr*" MESSAGE
+ "this should not appear in the syslog\n"
+ "*test-syslog-both*" MESSAGE
+ "this should appear in the syslog and "
+ "on stderr\n");
+ g_test_trap_assert_stderr_unmatched ("*this should appear in the syslog "
+ "only*");
+ g_test_trap_assert_stderr_unmatched ("*test-syslog-only*");
}
static void
@@ -97,7 +104,8 @@ main (int argc,
{
test_init (&argc, &argv);
- g_test_add ("/syslog", Fixture, NULL, setup, test_syslog, teardown);
+ g_test_add ("/syslog/normal", Fixture, NULL, setup, test_syslog_normal,
+ teardown);
return g_test_run ();
}
diff --git a/test/internals/variant.c b/test/internals/variant.c
new file mode 100644
index 00000000..67b633b9
--- /dev/null
+++ b/test/internals/variant.c
@@ -0,0 +1,572 @@
+/* Regression test for DBusVariant
+ *
+ * Copyright © 2017 Collabora Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-message-internal.h>
+#include "test-utils-glib.h"
+
+typedef struct
+{
+ DBusMessage *original;
+ DBusMessage *copy;
+} Fixture;
+
+/* Return TRUE on success, FALSE on OOM, abort on failure. */
+static gboolean
+setup (Fixture *f)
+{
+ dbus_int32_t fortytwo = 42;
+ dbus_int64_t twentythree = 23;
+ const char *s = "Hello, world!";
+ DBusMessageIter iter;
+ DBusMessageIter arr_iter;
+ DBusMessageIter struct_iter;
+ DBusMessageIter pair_iter;
+
+ f->original = dbus_message_new_signal ("/", "a.b", "c");
+
+ if (f->original == NULL)
+ return FALSE;
+
+ /* It ends up as:
+ * (
+ * int32 42,
+ * "Hello, world!",
+ * int64 23,
+ * [int32 42, int32 42],
+ * (int32 42, "Hello, world!", int64 23),
+ * {int32 42: int64 23},
+ * )
+ */
+
+ if (!dbus_message_append_args (f->original,
+ DBUS_TYPE_INT32, &fortytwo,
+ DBUS_TYPE_STRING, &s,
+ DBUS_TYPE_INT64, &twentythree,
+ DBUS_TYPE_INVALID))
+ return FALSE;
+
+ dbus_message_iter_init_append (f->original, &iter);
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_INT32_AS_STRING, &arr_iter))
+ return FALSE;
+
+ {
+ if (!dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_INT32, &fortytwo) ||
+ !dbus_message_iter_append_basic (&arr_iter, DBUS_TYPE_INT32, &fortytwo))
+ {
+ dbus_message_iter_abandon_container (&iter, &arr_iter);
+ return FALSE;
+ }
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &arr_iter))
+ return FALSE;
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
+ &struct_iter))
+ return FALSE;
+
+ {
+ if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_INT32,
+ &fortytwo) ||
+ !dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &s) ||
+ !dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_INT64,
+ &twentythree))
+ {
+ dbus_message_iter_abandon_container (&iter, &struct_iter);
+ return FALSE;
+ }
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &struct_iter))
+ return FALSE;
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ix}",
+ &arr_iter))
+ return FALSE;
+
+ {
+ if (!dbus_message_iter_open_container (&arr_iter, DBUS_TYPE_DICT_ENTRY,
+ NULL, &pair_iter))
+ {
+ dbus_message_iter_abandon_container (&iter, &arr_iter);
+ return FALSE;
+ }
+
+ {
+ if (!dbus_message_iter_append_basic (&pair_iter, DBUS_TYPE_INT32,
+ &fortytwo) ||
+ !dbus_message_iter_append_basic (&pair_iter, DBUS_TYPE_INT64,
+ &twentythree))
+ {
+ dbus_message_iter_abandon_container (&arr_iter, &pair_iter);
+ dbus_message_iter_abandon_container (&iter, &arr_iter);
+ return FALSE;
+ }
+ }
+
+ if (!dbus_message_iter_close_container (&arr_iter, &pair_iter))
+ {
+ dbus_message_iter_abandon_container (&iter, &arr_iter);
+ return FALSE;
+ }
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &arr_iter))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Assert that item_iter points to an int32 equal to expected_value.
+ * Copy it into a DBusVariant and assert that the copy is done correctly.
+ * Return TRUE on success, FALSE if libdbus pretends to run out of memory,
+ * or abort on failure. */
+static gboolean
+assert_int32 (DBusMessageIter *item_iter,
+ dbus_int32_t expected_value)
+{
+ DBusVariant *v;
+ const DBusString *s;
+ const void *value_p;
+ dbus_int32_t value;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (item_iter), ==,
+ DBUS_TYPE_INT32);
+ dbus_message_iter_get_basic (item_iter, &value);
+ g_assert_cmpint (value, ==, expected_value);
+
+ v = _dbus_variant_read (item_iter);
+
+ if (v == NULL)
+ return FALSE;
+
+ s = _dbus_variant_peek (v);
+ g_assert (s != NULL);
+ g_assert_cmpstr (_dbus_variant_get_signature (v), ==,
+ DBUS_TYPE_INT32_AS_STRING);
+
+ /* Variant serialization of <int32 something> at offset 0:
+ * 01 'i' 00 signature
+ * 00 padding
+ * vv vv vv vv bytes of value
+ */
+ g_assert_cmpint (_dbus_variant_get_length (v), ==, 8);
+ g_assert_cmpint (_dbus_string_get_length (s), ==, 8);
+ g_assert_cmpint (_dbus_string_get_byte (s, 0), ==, 1);
+ g_assert_cmpint (_dbus_string_get_byte (s, 1), ==, DBUS_TYPE_INT32);
+ g_assert_cmpint (_dbus_string_get_byte (s, 2), ==, '\0');
+ g_assert_cmpint (_dbus_string_get_byte (s, 3), ==, 0); /* padding */
+ value_p = _dbus_string_get_const_data_len (s, 4, 4);
+ memcpy (&value, value_p, 4);
+ g_assert_cmpint (value, ==, expected_value);
+
+ _dbus_variant_free (v);
+ return TRUE;
+}
+
+/* Assert that item_iter points to an int64 equal to expected_value.
+ * Copy it into a DBusVariant and assert that the copy is done correctly.
+ * Return TRUE on success, FALSE if libdbus pretends to run out of memory,
+ * or abort on failure. */
+static gboolean
+assert_int64 (DBusMessageIter *item_iter,
+ dbus_int64_t expected_value)
+{
+ DBusVariant *v;
+ const DBusString *s;
+ const void *value_p;
+ dbus_int64_t value;
+ int i;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (item_iter), ==,
+ DBUS_TYPE_INT64);
+ dbus_message_iter_get_basic (item_iter, &value);
+ g_assert_cmpint (value, ==, expected_value);
+
+ v = _dbus_variant_read (item_iter);
+
+ if (v == NULL)
+ return FALSE;
+
+ s = _dbus_variant_peek (v);
+ g_assert (s != NULL);
+ g_assert_cmpstr (_dbus_variant_get_signature (v), ==,
+ DBUS_TYPE_INT64_AS_STRING);
+
+ /* Variant serialization of <int64 something> at offset 0:
+ * 01 'i' 00 signature
+ * 00 00 00 00 00 padding
+ * vv vv vv vv vv vv vv vv bytes of value
+ */
+ g_assert_cmpint (_dbus_variant_get_length (v), ==, 16);
+ g_assert_cmpint (_dbus_string_get_length (s), ==, 16);
+ g_assert_cmpint (_dbus_string_get_byte (s, 0), ==, 1);
+ g_assert_cmpint (_dbus_string_get_byte (s, 1), ==, DBUS_TYPE_INT64);
+ g_assert_cmpint (_dbus_string_get_byte (s, 2), ==, '\0');
+
+ for (i = 3; i < 8; i++)
+ g_assert_cmpint (_dbus_string_get_byte (s, i), ==, 0); /* padding */
+
+ value_p = _dbus_string_get_const_data_len (s, 8, 8);
+ memcpy (&value, value_p, 8);
+ g_assert_cmpint (value, ==, expected_value);
+
+ _dbus_variant_free (v);
+ return TRUE;
+}
+
+/* Assert that item_iter points to a string equal to expected_value.
+ * Copy it into a DBusVariant and assert that the copy is done correctly.
+ * Return TRUE on success, FALSE if libdbus pretends to run out of memory,
+ * or abort on failure. */
+static gboolean
+assert_string (DBusMessageIter *item_iter,
+ const char *expected_value)
+{
+ DBusVariant *v;
+ const DBusString *s;
+ const char *value;
+ dbus_int32_t length;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (item_iter), ==,
+ DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic (item_iter, &value);
+ g_assert_cmpstr (value, ==, expected_value);
+
+ v = _dbus_variant_read (item_iter);
+
+ if (v == NULL)
+ return FALSE;
+
+ s = _dbus_variant_peek (v);
+ g_assert (s != NULL);
+ g_assert_cmpstr (_dbus_variant_get_signature (v), ==,
+ DBUS_TYPE_STRING_AS_STRING);
+
+ /* Variant serialization of <"something"> at offset 0:
+ * 01 's' 00 signature
+ * 00 padding
+ * ll ll ll ll bytes of length excluding \0
+ * vv vv vv ... 00 bytes of value
+ */
+ g_assert_cmpint (_dbus_variant_get_length (v), ==,
+ (int) strlen (expected_value) + 9);
+ g_assert_cmpint (_dbus_string_get_length (s), ==,
+ _dbus_variant_get_length (v));
+ g_assert_cmpint (_dbus_string_get_byte (s, 0), ==, 1);
+ g_assert_cmpint (_dbus_string_get_byte (s, 1), ==, DBUS_TYPE_STRING);
+ g_assert_cmpint (_dbus_string_get_byte (s, 2), ==, '\0');
+ g_assert_cmpint (_dbus_string_get_byte (s, 3), ==, 0); /* padding */
+
+ value = _dbus_string_get_const_data_len (s, 4, 4);
+ memcpy (&length, value, 4);
+ g_assert_cmpuint (length, ==, (int) strlen (expected_value));
+ value = _dbus_string_get_const_data_len (s, 8, length + 1);
+ g_assert_cmpstr (value, ==, expected_value);
+
+ _dbus_variant_free (v);
+ return TRUE;
+}
+
+/* Assert that item_iter points to an array of n_values repetitions of the
+ * int32 expected_value. Copy it into a DBusVariant and assert that the
+ * copy is done correctly.
+ * Return TRUE on success, FALSE if libdbus pretends to run out of memory,
+ * or abort on failure. */
+static gboolean
+assert_array_of_int32 (DBusMessageIter *item_iter,
+ int n_values,
+ dbus_int32_t expected_value)
+{
+ DBusMessageIter arr_iter;
+ DBusVariant *v;
+ const DBusString *s;
+ const void *value_p;
+ dbus_int32_t value;
+ int i;
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (item_iter), ==,
+ DBUS_TYPE_ARRAY);
+
+ dbus_message_iter_recurse (item_iter, &arr_iter);
+
+ for (i = 0; i < n_values; i++)
+ {
+ assert_int32 (&arr_iter, expected_value);
+
+ if (i == n_values - 1)
+ g_assert_false (dbus_message_iter_next (&arr_iter));
+ else
+ g_assert_true (dbus_message_iter_next (&arr_iter));
+ }
+
+ v = _dbus_variant_read (item_iter);
+
+ if (v == NULL)
+ return FALSE;
+
+ s = _dbus_variant_peek (v);
+ g_assert (s != NULL);
+ g_assert_cmpstr (_dbus_variant_get_signature (v), ==,
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
+
+ /* Variant serialization of <[int32 something, ...]> at offset 0:
+ * 02 'a' 'i' 00 signature
+ * ll ll ll ll total number of bytes in values
+ * vv vv vv vv ... bytes of values
+ */
+ g_assert_cmpint (_dbus_variant_get_length (v), ==, 8 + (4 * n_values));
+ g_assert_cmpint (_dbus_string_get_length (s), ==, 8 + (4 * n_values));
+ g_assert_cmpint (_dbus_string_get_byte (s, 0), ==, 2);
+ g_assert_cmpint (_dbus_string_get_byte (s, 1), ==, DBUS_TYPE_ARRAY);
+ g_assert_cmpint (_dbus_string_get_byte (s, 2), ==, DBUS_TYPE_INT32);
+ g_assert_cmpint (_dbus_string_get_byte (s, 3), ==, '\0');
+ value_p = _dbus_string_get_const_data_len (s, 4, 4);
+ memcpy (&value, value_p, 4);
+ g_assert_cmpint (value, ==, n_values * 4);
+
+ for (i = 0; i < n_values; i++)
+ {
+ value_p = _dbus_string_get_const_data_len (s, 8 + (4 * (n_values - 1)),
+ 4);
+ memcpy (&value, value_p, 4);
+ g_assert_cmpint (value, ==, expected_value);
+ }
+
+ _dbus_variant_free (v);
+ return TRUE;
+}
+
+/* Assert that m is (in GVariant notation):
+ * (
+ * int32 42,
+ * "Hello, world!",
+ * int64 23,
+ * [int32 42, int32 42],
+ * (int32 42, "Hello, world!", int64 23),
+ * {int32 42: int64 23},
+ * )
+ *
+ * Serialize some of those values into DBusVariants and assert that it is
+ * done correctly.
+ *
+ * Return TRUE on success, FALSE if libdbus pretends to run out of memory,
+ * or abort on failure. */
+static gboolean
+assert_message_as_expected (DBusMessage *m)
+{
+ DBusMessageIter item_iter;
+ DBusMessageIter arr_iter;
+ DBusMessageIter struct_iter;
+ DBusMessageIter pair_iter;
+
+ g_assert_cmpstr (dbus_message_get_signature (m), ==, "isxai(isx)a{ix}");
+ dbus_message_iter_init (m, &item_iter);
+
+ {
+ if (!assert_int32 (&item_iter, 42))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&item_iter));
+
+ if (!assert_string (&item_iter, "Hello, world!"))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&item_iter));
+
+ if (!assert_int64 (&item_iter, 23))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&item_iter));
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&item_iter), ==,
+ DBUS_TYPE_ARRAY);
+ if (!assert_array_of_int32 (&item_iter, 2, 42))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&item_iter));
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&item_iter), ==,
+ DBUS_TYPE_STRUCT);
+ dbus_message_iter_recurse (&item_iter, &struct_iter);
+
+ {
+ if (!assert_int32 (&struct_iter, 42))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&struct_iter));
+
+ if (!assert_string (&struct_iter, "Hello, world!"))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&struct_iter));
+
+ if (!assert_int64 (&struct_iter, 23))
+ return FALSE;
+
+ g_assert_false (dbus_message_iter_next (&struct_iter));
+ }
+
+ g_assert_true (dbus_message_iter_next (&item_iter));
+
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&item_iter), ==,
+ DBUS_TYPE_ARRAY);
+ dbus_message_iter_recurse (&item_iter, &arr_iter);
+
+ {
+ g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
+ DBUS_TYPE_DICT_ENTRY);
+ dbus_message_iter_recurse (&arr_iter, &pair_iter);
+
+ {
+ if (!assert_int32 (&pair_iter, 42))
+ return FALSE;
+
+ g_assert_true (dbus_message_iter_next (&pair_iter));
+
+ if (!assert_int64 (&pair_iter, 23))
+ return FALSE;
+
+ g_assert_false (dbus_message_iter_next (&pair_iter));
+ }
+
+ g_assert_false (dbus_message_iter_next (&arr_iter));
+ }
+ }
+
+ g_assert_false (dbus_message_iter_next (&item_iter));
+ return TRUE;
+}
+
+/* Return TRUE on success or OOM, as per DBusTestMemoryFunction signature */
+static dbus_bool_t
+test_once (void *data)
+{
+ gboolean *really_succeeded = data;
+ Fixture fixture = { NULL, NULL };
+ Fixture *f = &fixture;
+ DBusMessageIter item_iter;
+ DBusMessageIter appender;
+ int i;
+
+ if (really_succeeded != NULL)
+ *really_succeeded = FALSE;
+
+ if (!setup (f))
+ goto out;
+
+ if (!assert_message_as_expected (f->original))
+ goto out;
+
+ dbus_message_iter_init (f->original, &item_iter);
+
+ f->copy = dbus_message_new_signal ("/", "a.b", "c");
+
+ if (f->copy == NULL)
+ goto out;
+
+ dbus_message_iter_init_append (f->copy, &appender);
+
+ for (i = 0; i < 6; i++)
+ {
+ DBusVariant *var = _dbus_variant_read (&item_iter);
+
+ if (var == NULL)
+ goto out;
+
+ if (!_dbus_variant_write (var, &appender))
+ {
+ _dbus_variant_free (var);
+ goto out;
+ }
+
+ _dbus_variant_free (var);
+
+ if (i == 5)
+ g_assert_false (dbus_message_iter_next (&item_iter));
+ else
+ g_assert_true (dbus_message_iter_next (&item_iter));
+ }
+
+ if (!assert_message_as_expected (f->copy))
+ goto out;
+
+ if (really_succeeded != NULL)
+ *really_succeeded = TRUE;
+out:
+ if (f->original)
+ dbus_message_unref (f->original);
+
+ if (f->copy)
+ dbus_message_unref (f->copy);
+
+ dbus_shutdown ();
+ g_assert_cmpint (_dbus_get_malloc_blocks_outstanding (), ==, 0);
+
+ return !g_test_failed ();
+}
+
+static void
+test_simple (void)
+{
+ gboolean really_succeeded = FALSE;
+
+ if (!test_once (&really_succeeded))
+ g_error ("Test failed");
+
+ if (!really_succeeded)
+ g_error ("Out of memory");
+}
+
+static void
+test_oom (void)
+{
+ if (!_dbus_test_oom_handling ("DBusVariant", test_once, NULL))
+ g_error ("Test failed");
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ test_init (&argc, &argv);
+
+ g_test_add_func ("/variant/simple", test_simple);
+ g_test_add_func ("/variant/oom", test_oom);
+
+ return g_test_run ();
+}
diff --git a/test/loopback.c b/test/loopback.c
index bf0542aa..b8725b7e 100644
--- a/test/loopback.c
+++ b/test/loopback.c
@@ -40,6 +40,7 @@
typedef struct {
TestMainContext *ctx;
DBusError e;
+ gboolean skip;
DBusServer *server;
DBusConnection *server_conn;
@@ -97,6 +98,14 @@ setup (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->server_messages);
+ if ((g_str_has_prefix (addr, "tcp:") ||
+ g_str_has_prefix (addr, "nonce-tcp:")) &&
+ !test_check_tcp_works ())
+ {
+ f->skip = TRUE;
+ return;
+ }
+
f->server = dbus_server_listen (addr, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
@@ -124,6 +133,9 @@ setup_runtime (Fixture *f,
setup (f, addr);
+ if (f->skip)
+ return;
+
listening_at = dbus_server_get_address (f->server);
g_test_message ("listening at %s", listening_at);
g_assert (g_str_has_prefix (listening_at, "unix:path="));
@@ -146,6 +158,9 @@ setup_no_runtime (Fixture *f,
setup (f, addr);
+ if (f->skip)
+ return;
+
listening_at = dbus_server_get_address (f->server);
g_test_message ("listening at %s", listening_at);
/* we have fallen back to something in /tmp, either abstract or not */
@@ -158,12 +173,99 @@ setup_no_runtime (Fixture *f,
static void
test_connect (Fixture *f,
- gconstpointer addr G_GNUC_UNUSED)
+ gconstpointer addr)
{
+ const char *listening_address = addr;
+ char *address;
+ DBusAddressEntry **entries;
+ int n_entries;
+ dbus_bool_t ok;
+
+ if (f->skip)
+ return;
+
g_assert (f->server_conn == NULL);
- f->client_conn = dbus_connection_open_private (
- dbus_server_get_address (f->server), &f->e);
+ address = dbus_server_get_address (f->server);
+ g_test_message ("listening at %s", address);
+
+ ok = dbus_parse_address (address, &entries, &n_entries, &f->e);
+ assert_no_error (&f->e);
+ g_assert_true (ok);
+ g_assert_cmpint (n_entries, ==, 1);
+
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "guid"), !=,
+ NULL);
+
+ if (g_strcmp0 (listening_address, "tcp:host=127.0.0.1") == 0)
+ {
+ g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "tcp");
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "host"), ==,
+ "127.0.0.1");
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "port"), !=,
+ NULL);
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "noncefile"),
+ ==, NULL);
+ }
+ else if (g_strcmp0 (listening_address, "nonce-tcp:host=127.0.0.1") == 0)
+ {
+ g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==,
+ "nonce-tcp");
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "host"), ==,
+ "127.0.0.1");
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "port"), !=,
+ NULL);
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "noncefile"),
+ !=, NULL);
+ }
+#ifdef DBUS_UNIX
+ else if (g_strcmp0 (listening_address, "unix:tmpdir=/tmp") == 0)
+ {
+ g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "unix");
+
+ if (dbus_address_entry_get_value (entries[0], "abstract") != NULL)
+ {
+ const char *abstract = dbus_address_entry_get_value (entries[0],
+ "abstract");
+
+ g_assert_true (g_str_has_prefix (abstract, "/tmp/dbus-"));
+ g_assert_cmpstr (dbus_address_entry_get_value (entries[0], "path"),
+ ==, NULL);
+ }
+ else
+ {
+ const char *path = dbus_address_entry_get_value (entries[0],
+ "path");
+
+ g_assert_nonnull (path);
+ g_assert_true (g_str_has_prefix (path, "/tmp/dbus-"));
+ }
+ }
+ else if (g_strcmp0 (listening_address, "unix:dir=/tmp") == 0)
+ {
+ const char *path = dbus_address_entry_get_value (entries[0],
+ "path");
+
+ g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "unix");
+ g_assert_nonnull (path);
+ g_assert_true (g_str_has_prefix (path, "/tmp/dbus-"));
+ }
+ else if (g_strcmp0 (listening_address,
+ "unix:runtime=yes;unix:tmpdir=/tmp") == 0)
+ {
+ g_assert_cmpstr (dbus_address_entry_get_method (entries[0]), ==, "unix");
+ /* No particular statement about the path here: for that see
+ * setup_runtime() and setup_no_runtime() */
+ }
+#endif
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ dbus_address_entries_free (entries);
+
+ f->client_conn = dbus_connection_open_private (address, &f->e);
assert_no_error (&f->e);
g_assert (f->client_conn != NULL);
test_connection_setup (f->ctx, f->client_conn);
@@ -173,6 +275,8 @@ test_connect (Fixture *f,
test_progress ('.');
test_main_context_iterate (f->ctx, TRUE);
}
+
+ dbus_free (address);
}
static void
@@ -180,13 +284,17 @@ test_bad_guid (Fixture *f,
gconstpointer addr G_GNUC_UNUSED)
{
DBusMessage *incoming;
- gchar *address = g_strdup (dbus_server_get_address (f->server));
+ char *address;
gchar *guid;
+ if (f->skip)
+ return;
+
g_test_bug ("39720");
g_assert (f->server_conn == NULL);
+ address = dbus_server_get_address (f->server);
g_assert (strstr (address, "guid=") != NULL);
guid = strstr (address, "guid=");
g_assert_cmpuint (strlen (guid), >=, 5 + 32);
@@ -230,9 +338,8 @@ test_bad_guid (Fixture *f,
g_assert_cmpstr (dbus_message_get_signature (incoming), ==, "");
g_assert_cmpstr (dbus_message_get_path (incoming), ==, DBUS_PATH_LOCAL);
- dbus_message_unref (incoming);
-
- g_free (address);
+ dbus_clear_message (&incoming);
+ dbus_free (address);
}
static void
@@ -243,6 +350,9 @@ test_message (Fixture *f,
dbus_uint32_t serial;
DBusMessage *outgoing, *incoming;
+ if (f->skip)
+ return;
+
test_connect (f, addr);
outgoing = dbus_message_new_signal ("/com/example/Hello",
@@ -274,9 +384,8 @@ test_message (Fixture *f,
g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello");
g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial);
- dbus_message_unref (incoming);
-
- dbus_message_unref (outgoing);
+ dbus_clear_message (&incoming);
+ dbus_clear_message (&outgoing);
}
static void
@@ -284,26 +393,18 @@ teardown (Fixture *f,
gconstpointer addr G_GNUC_UNUSED)
{
if (f->client_conn != NULL)
- {
- dbus_connection_close (f->client_conn);
- dbus_connection_unref (f->client_conn);
- f->client_conn = NULL;
- }
+ dbus_connection_close (f->client_conn);
if (f->server_conn != NULL)
- {
- dbus_connection_close (f->server_conn);
- dbus_connection_unref (f->server_conn);
- f->server_conn = NULL;
- }
+ dbus_connection_close (f->server_conn);
+
+ dbus_clear_connection (&f->client_conn);
+ dbus_clear_connection (&f->server_conn);
if (f->server != NULL)
- {
- dbus_server_disconnect (f->server);
- dbus_server_unref (f->server);
- f->server = NULL;
- }
+ dbus_server_disconnect (f->server);
+ dbus_clear_server (&f->server);
test_main_context_unref (f->ctx);
}
@@ -332,10 +433,10 @@ teardown_runtime (Fixture *f,
/* the socket may exist */
path = g_strdup_printf ("%s/bus", f->tmp_runtime_dir);
- g_assert (g_remove (path) == 0 || errno == ENOENT);
+ test_remove_if_exists (path);
g_free (path);
/* there shouldn't be anything else in there */
- g_assert_cmpint (g_rmdir (f->tmp_runtime_dir), ==, 0);
+ test_rmdir_must_exist (f->tmp_runtime_dir);
/* we're relying on being single-threaded for this to be safe */
if (f->saved_runtime_dir != NULL)
@@ -363,10 +464,17 @@ main (int argc,
g_test_add ("/message/nonce-tcp", Fixture, "nonce-tcp:host=127.0.0.1", setup,
test_message, teardown);
+ g_test_add ("/message/bad-guid/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+ test_bad_guid, teardown);
+
#ifdef DBUS_UNIX
- g_test_add ("/connect/unix", Fixture, "unix:tmpdir=/tmp", setup,
+ g_test_add ("/connect/unix/tmpdir", Fixture, "unix:tmpdir=/tmp", setup,
+ test_connect, teardown);
+ g_test_add ("/message/unix/tmpdir", Fixture, "unix:tmpdir=/tmp", setup,
+ test_message, teardown);
+ g_test_add ("/connect/unix/dir", Fixture, "unix:dir=/tmp", setup,
test_connect, teardown);
- g_test_add ("/message/unix", Fixture, "unix:tmpdir=/tmp", setup,
+ g_test_add ("/message/unix/dir", Fixture, "unix:dir=/tmp", setup,
test_message, teardown);
g_test_add ("/connect/unix/runtime", Fixture,
@@ -375,10 +483,10 @@ main (int argc,
g_test_add ("/connect/unix/no-runtime", Fixture,
"unix:runtime=yes;unix:tmpdir=/tmp", setup_no_runtime, test_connect,
teardown_no_runtime);
-#endif
- g_test_add ("/message/bad-guid", Fixture, "tcp:host=127.0.0.1", setup,
+ g_test_add ("/message/bad-guid/unix", Fixture, "unix:tmpdir=/tmp", setup,
test_bad_guid, teardown);
+#endif
return g_test_run ();
}
diff --git a/test/manual-backtrace.c b/test/manual-backtrace.c
new file mode 100644
index 00000000..0cc1499d
--- /dev/null
+++ b/test/manual-backtrace.c
@@ -0,0 +1,62 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* test-backtrace.c backtrace test app
+ *
+ * Copyright (C) 2015 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-sysdeps.h>
+
+#include <stdio.h>
+
+static void
+test2 (void)
+{
+ _dbus_print_backtrace();
+}
+
+static void
+test1 (void)
+{
+ test2();
+}
+
+static void
+test (void)
+{
+ test1();
+}
+
+int
+main (int argc, char **argv)
+{
+ if (argc == 2)
+ {
+ fprintf(stderr, "dbus_abort test\n");
+ _dbus_abort ();
+ }
+ else
+ {
+ test();
+ }
+ return 0;
+}
diff --git a/test/manual-dir-iter.c b/test/manual-dir-iter.c
index 21ac0e95..85081748 100644
--- a/test/manual-dir-iter.c
+++ b/test/manual-dir-iter.c
@@ -47,7 +47,9 @@ main (int argc,
if (!_dbus_string_init (&dirname))
oom ("init dirname");
- _dbus_string_append (&dirname, argv[1]);
+ if (!_dbus_string_append (&dirname, argv[1]))
+ oom ("append argv[1]");
+
dir = _dbus_directory_open (&dirname, &tmp_error);
if (dir == NULL)
diff --git a/test/manual-paths.c b/test/manual-paths.c
index e392c5c3..82fc669d 100644
--- a/test/manual-paths.c
+++ b/test/manual-paths.c
@@ -12,20 +12,39 @@
#include <stdio.h>
-static dbus_bool_t print_install_root()
+static dbus_bool_t
+print_install_root (void)
{
- char runtime_prefix[1000];
+ DBusString runtime_prefix;
- if (!_dbus_get_install_root(runtime_prefix, sizeof(runtime_prefix)))
+ if (!_dbus_string_init (&runtime_prefix))
{
- fprintf(stderr, "dbus_get_install_root() failed\n");
+ _dbus_assert_not_reached ("out of memory");
return FALSE;
}
- fprintf(stdout, "dbus_get_install_root() returned '%s'\n", runtime_prefix);
+
+ if (!_dbus_get_install_root (&runtime_prefix))
+ {
+ _dbus_assert_not_reached ("out of memory");
+ _dbus_string_free (&runtime_prefix);
+ return FALSE;
+ }
+
+ if (_dbus_string_get_length (&runtime_prefix) == 0)
+ {
+ fprintf (stderr, "_dbus_get_install_root() failed\n");
+ _dbus_string_free (&runtime_prefix);
+ return FALSE;
+ }
+
+ fprintf (stdout, "_dbus_get_install_root() returned '%s'\n",
+ _dbus_string_get_const_data (&runtime_prefix));
+ _dbus_string_free (&runtime_prefix);
return TRUE;
}
-static dbus_bool_t print_service_dirs()
+static dbus_bool_t
+print_service_dirs (void)
{
DBusList *dirs;
DBusList *link;
@@ -46,11 +65,25 @@ static dbus_bool_t print_service_dirs()
static dbus_bool_t print_replace_install_prefix(const char *s)
{
- const char *s2 = _dbus_replace_install_prefix(s);
- if (!s2)
- return FALSE;
+ DBusString str;
+
+ if (!_dbus_string_init (&str))
+ {
+ _dbus_assert_not_reached ("out of memory");
+ return FALSE;
+ }
+
+ if (!_dbus_string_append (&str, s) ||
+ !_dbus_replace_install_prefix (&str))
+ {
+ _dbus_assert_not_reached ("out of memory");
+ _dbus_string_free (&str);
+ return FALSE;
+ }
- fprintf(stdout, "replaced '%s' by '%s'\n", s, s2);
+ fprintf(stdout, "replaced '%s' by '%s'\n", s,
+ _dbus_string_get_const_data (&str));
+ _dbus_string_free (&str);
return TRUE;
}
diff --git a/test/message.c b/test/message.c
new file mode 100644
index 00000000..75c441e5
--- /dev/null
+++ b/test/message.c
@@ -0,0 +1,311 @@
+/* Targeted unit tests for OOM paths in DBusMessage
+ *
+ * Copyright © 2017 Collabora Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include "dbus/dbus-internals.h"
+#include "dbus/dbus-pipe.h"
+#include "test-utils-glib.h"
+
+/* Return TRUE if the right thing happens, but the right thing might include
+ * OOM. */
+static dbus_bool_t
+test_array (void *contained_signature)
+{
+ DBusMessage *m;
+ DBusMessageIter iter;
+ DBusMessageIter arr_iter;
+ dbus_bool_t arr_iter_open = FALSE;
+ DBusMessageIter inner_iter;
+ dbus_bool_t inner_iter_open = FALSE;
+
+ m = dbus_message_new_signal ("/", "a.b", "c");
+
+ if (m == NULL)
+ goto out;
+
+ dbus_message_iter_init_append (m, &iter);
+
+ /* open_container only opens the container if it succeeds */
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+ contained_signature,
+ &arr_iter))
+ goto out;
+
+ arr_iter_open = TRUE;
+
+ if (g_strcmp0 (contained_signature, "ai") == 0)
+ {
+ /* open_container only opens the container if it succeeds */
+ if (!dbus_message_iter_open_container (&arr_iter, DBUS_TYPE_ARRAY, "i",
+ &inner_iter))
+ goto out;
+
+ /* We do not set inner_iter_open to TRUE here because we would
+ * immediately set it to FALSE again */
+
+ /* close_container closes the container, even when it fails */
+ if (!dbus_message_iter_close_container (&arr_iter, &inner_iter))
+ goto out;
+ }
+ else if (g_strcmp0 (contained_signature, "{ss}") == 0)
+ {
+ const char *s = "hello";
+
+ /* open_container only opens the container if it succeeds */
+ if (!dbus_message_iter_open_container (&arr_iter, DBUS_TYPE_DICT_ENTRY,
+ NULL, &inner_iter))
+ goto out;
+
+ inner_iter_open = TRUE;
+
+ if (!dbus_message_iter_append_basic (&inner_iter, DBUS_TYPE_STRING, &s))
+ goto out;
+
+ if (!dbus_message_iter_append_basic (&inner_iter, DBUS_TYPE_STRING, &s))
+ goto out;
+
+ /* close_container closes the container, even when it fails */
+ inner_iter_open = FALSE;
+
+ if (!dbus_message_iter_close_container (&arr_iter, &inner_iter))
+ goto out;
+ }
+ else if (g_strcmp0 (contained_signature, "v") == 0)
+ {
+ dbus_bool_t yes = TRUE;
+
+ /* open_container only opens the container if it succeeds */
+ if (!dbus_message_iter_open_container (&arr_iter, DBUS_TYPE_VARIANT,
+ "b", &inner_iter))
+ goto out;
+
+ inner_iter_open = TRUE;
+
+ if (!dbus_message_iter_append_basic (&inner_iter, DBUS_TYPE_BOOLEAN,
+ &yes))
+ goto out;
+
+ /* close_container closes the container, even when it fails */
+ inner_iter_open = FALSE;
+
+ if (!dbus_message_iter_close_container (&arr_iter, &inner_iter))
+ goto out;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ /* close_container closes the container, even when it fails */
+ arr_iter_open = FALSE;
+
+ if (!dbus_message_iter_close_container (&iter, &arr_iter))
+ goto out;
+
+out:
+ if (inner_iter_open)
+ dbus_message_iter_abandon_container (&arr_iter, &inner_iter);
+
+ if (arr_iter_open)
+ dbus_message_iter_abandon_container (&iter, &arr_iter);
+
+ if (m != NULL)
+ dbus_message_unref (m);
+
+ dbus_shutdown ();
+ g_assert_cmpint (_dbus_get_malloc_blocks_outstanding (), ==, 0);
+
+ return !g_test_failed ();
+}
+
+/* Return TRUE if the right thing happens, but the right thing might include
+ * OOM or inability to pass fds. */
+static dbus_bool_t
+test_fd (void *ignored)
+{
+ DBusMessage *m = NULL;
+ DBusPipe pipe;
+
+ _dbus_pipe_init_stdout (&pipe);
+
+ m = dbus_message_new_signal ("/", "a.b", "c");
+
+ if (m == NULL)
+ goto out;
+
+ if (!dbus_message_append_args (m,
+ DBUS_TYPE_UNIX_FD, &pipe.fd,
+ DBUS_TYPE_INVALID))
+ goto out;
+
+out:
+ if (m != NULL)
+ dbus_message_unref (m);
+
+ dbus_shutdown ();
+ g_assert_cmpint (_dbus_get_malloc_blocks_outstanding (), ==, 0);
+
+ return !g_test_failed ();
+}
+
+/* Similar to test_array(), but making use of
+ * dbus_message_iter_abandon_container_if_open().
+ *
+ * Return TRUE if the right thing happens, but the right thing might include
+ * OOM. */
+static dbus_bool_t
+test_zero_iter (void *ignored)
+{
+ DBusMessage *m;
+ DBusMessageIter iter = DBUS_MESSAGE_ITER_INIT_CLOSED;
+ DBusMessageIter arr_iter = DBUS_MESSAGE_ITER_INIT_CLOSED;
+ DBusMessageIter inner_iter;
+ dbus_int32_t fortytwo = 42;
+ dbus_bool_t message_should_be_complete = FALSE;
+
+ /* This one was left uninitialized, just so we could exercise this
+ * function */
+ dbus_message_iter_init_closed (&inner_iter);
+
+ m = dbus_message_new_signal ("/", "a.b", "c");
+
+ if (m == NULL)
+ goto out;
+
+ dbus_message_iter_init_append (m, &iter);
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+ "ai", &arr_iter))
+ goto out;
+
+ if (!dbus_message_iter_open_container (&arr_iter, DBUS_TYPE_ARRAY, "i",
+ &inner_iter))
+ goto out;
+
+ if (!dbus_message_iter_append_basic (&inner_iter, DBUS_TYPE_INT32, &fortytwo))
+ goto out;
+
+ if (!dbus_message_iter_close_container (&arr_iter, &inner_iter))
+ goto out;
+
+ if (!dbus_message_iter_close_container (&iter, &arr_iter))
+ goto out;
+
+ message_should_be_complete = TRUE;
+
+out:
+ dbus_message_iter_abandon_container_if_open (&arr_iter, &inner_iter);
+ dbus_message_iter_abandon_container_if_open (&iter, &arr_iter);
+ /* Redundant calls are OK */
+ dbus_message_iter_abandon_container_if_open (&iter, &arr_iter);
+
+ /* dbus_message_iter_abandon_container_if_open does not leave the message
+ * in what seems to be consistently documented as a "hosed" state */
+ if (message_should_be_complete)
+ {
+ DBusBasicValue read_back;
+
+ _DBUS_ZERO (read_back);
+ dbus_message_iter_init (m, &iter);
+ dbus_message_iter_recurse (&iter, &arr_iter);
+ dbus_message_iter_recurse (&arr_iter, &inner_iter);
+ dbus_message_iter_get_basic (&inner_iter, &read_back);
+ g_assert_cmpint (read_back.i32, ==, 42);
+ }
+
+ if (m != NULL)
+ dbus_message_unref (m);
+
+ dbus_shutdown ();
+ g_assert_cmpint (_dbus_get_malloc_blocks_outstanding (), ==, 0);
+
+ return !g_test_failed ();
+}
+
+typedef struct
+{
+ const gchar *name;
+ DBusTestMemoryFunction function;
+ const void *data;
+} OOMTestCase;
+
+static void
+test_oom_wrapper (gconstpointer data)
+{
+ const OOMTestCase *test = data;
+
+ if (!_dbus_test_oom_handling (test->name, test->function,
+ (void *) test->data))
+ {
+ g_test_message ("OOM test failed");
+ g_test_fail ();
+ }
+}
+
+static GQueue *test_cases_to_free = NULL;
+
+static void
+add_oom_test (const gchar *name,
+ DBusTestMemoryFunction function,
+ const void *data)
+{
+ /* By using GLib memory allocation here, we avoid being affected by
+ * dbus_shutdown() or contributing to
+ * _dbus_get_malloc_blocks_outstanding() */
+ OOMTestCase *test_case = g_new0 (OOMTestCase, 1);
+
+ test_case->name = name;
+ test_case->function = function;
+ test_case->data = data;
+ g_test_add_data_func (name, test_case, test_oom_wrapper);
+ g_queue_push_tail (test_cases_to_free, test_case);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ int ret;
+
+ test_init (&argc, &argv);
+
+ test_cases_to_free = g_queue_new ();
+ add_oom_test ("/message/array/array", test_array, "ai");
+ add_oom_test ("/message/array/dict", test_array, "{ss}");
+ add_oom_test ("/message/array/variant", test_array, "v");
+ add_oom_test ("/message/fd", test_fd, NULL);
+ add_oom_test ("/message/zero-iter", test_zero_iter, NULL);
+
+ ret = g_test_run ();
+
+ g_queue_free_full (test_cases_to_free, g_free);
+ return ret;
+}
diff --git a/test/monitor.c b/test/monitor.c
index ad4b1954..df5a7180 100644
--- a/test/monitor.c
+++ b/test/monitor.c
@@ -48,8 +48,10 @@ typedef struct {
DBusConnection *monitor;
DBusConnection *sender;
DBusConnection *recipient;
+ gboolean recipient_enqueue_filter_added;
GQueue monitored;
+ GQueue received;
const char *monitor_name;
const char *sender_name;
@@ -92,6 +94,11 @@ static const char * const selective_match_rules[] = {
FALSE
};
+static const char * const well_known_destination_match_rules[] = {
+ "destination='com.example.Recipient'",
+ NULL
+};
+
static Config forbidding_config = {
"valid-config-files/forbidding.conf",
NULL,
@@ -110,6 +117,12 @@ static Config selective_config = {
FALSE
};
+static Config well_known_destination_config = {
+ NULL,
+ well_known_destination_match_rules,
+ FALSE
+};
+
static Config no_rules_config = {
NULL,
no_match_rules,
@@ -360,7 +373,7 @@ monitor_filter (DBusConnection *connection,
}
static DBusHandlerResult
-recipient_filter (DBusConnection *connection,
+recipient_check_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
@@ -373,6 +386,27 @@ recipient_filter (DBusConnection *connection,
}
static DBusHandlerResult
+recipient_enqueue_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ Fixture *f = user_data;
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameAcquired") ||
+ dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameLost") ||
+ dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged"))
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ g_queue_push_tail (&f->received, dbus_message_ref (message));
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
systemd_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -415,6 +449,19 @@ activated_filter (DBusConnection *connection,
}
static void
+take_well_known_name (Fixture *f,
+ DBusConnection *connection,
+ const char *name)
+{
+ int ret;
+
+ ret = dbus_bus_request_name (connection, name,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e);
+ test_assert_no_error (&f->e);
+ g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+}
+
+static void
setup (Fixture *f,
gconstpointer context)
{
@@ -426,7 +473,7 @@ setup (Fixture *f,
dbus_error_init (&f->e);
f->address = test_get_dbus_daemon (f->config ? f->config->config_file : NULL,
- TEST_USER_ME, &f->daemon_pid);
+ TEST_USER_ME, NULL, &f->daemon_pid);
if (f->address == NULL)
return;
@@ -441,12 +488,14 @@ setup (Fixture *f,
if (!dbus_connection_add_filter (f->monitor, monitor_filter, f, NULL))
g_error ("OOM");
- if (!dbus_connection_add_filter (f->recipient, recipient_filter, f, NULL))
+ if (!dbus_connection_add_filter (f->recipient, recipient_check_filter,
+ f, NULL))
g_error ("OOM");
}
static void
-become_monitor (Fixture *f)
+become_monitor (Fixture *f,
+ const Config *config)
{
DBusMessage *m;
DBusPendingCall *pc;
@@ -458,8 +507,11 @@ become_monitor (Fixture *f)
dbus_connection_set_route_peer_messages (f->monitor, TRUE);
- if (f->config != NULL && f->config->match_rules != NULL)
- match_rules = f->config->match_rules;
+ if (config == NULL)
+ config = f->config;
+
+ if (config != NULL && config->match_rules != NULL)
+ match_rules = config->match_rules;
else
match_rules = wildcard_match_rules;
@@ -573,6 +625,49 @@ test_invalid (Fixture *f,
g_assert_cmpstr (dbus_message_get_error_name (m), ==,
DBUS_ERROR_INVALID_ARGS);
+ /* Try to become a monitor but use the wrong object path - not allowed
+ * (security hardening against inappropriate XML policy rules) */
+
+ dbus_pending_call_unref (pc);
+ dbus_message_unref (m);
+
+ m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ "/", DBUS_INTERFACE_MONITORING, "BecomeMonitor");
+
+ if (m == NULL)
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (m, &appender);
+
+ if (!dbus_message_iter_open_container (&appender, DBUS_TYPE_ARRAY, "s",
+ &array_appender))
+ g_error ("OOM");
+
+ if (!dbus_message_iter_close_container (&appender, &array_appender) ||
+ !dbus_message_iter_append_basic (&appender, DBUS_TYPE_UINT32, &zero))
+ g_error ("OOM");
+
+ if (!dbus_connection_send_with_reply (f->monitor, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) ||
+ pc == NULL)
+ g_error ("OOM");
+
+ dbus_message_unref (m);
+ m = NULL;
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ g_assert_cmpint (dbus_message_get_type (m), ==, DBUS_MESSAGE_TYPE_ERROR);
+ g_assert_cmpstr (dbus_message_get_error_name (m), ==,
+ DBUS_ERROR_UNKNOWN_INTERFACE);
+
/* Try to become a monitor but specify a bad match rule -
* also not allowed */
@@ -650,6 +745,9 @@ test_invalid (Fixture *f,
while (m == NULL)
test_main_context_iterate (f->ctx, TRUE);
+ if (dbus_set_error_from_message (&f->e, m))
+ g_error ("%s: %s", f->e.name, f->e.message);
+
ok = dbus_message_get_args (m, &f->e,
DBUS_TYPE_STRING, &s,
DBUS_TYPE_INVALID);
@@ -746,7 +844,7 @@ test_become_monitor (Fixture *f,
}
}
- become_monitor (f);
+ become_monitor (f, NULL);
while (!lost_unique || !lost_a || !lost_b || !lost_c)
{
@@ -848,7 +946,7 @@ test_broadcast (Fixture *f,
dbus_bus_add_match (f->recipient, "type='signal'", &f->e);
test_assert_no_error (&f->e);
- become_monitor (f);
+ become_monitor (f, NULL);
m = dbus_message_new_signal ("/foo", "com.example.bar", "BroadcastSignal1");
dbus_connection_send (f->sender, m, NULL);
@@ -896,7 +994,12 @@ test_forbidden_broadcast (Fixture *f,
dbus_bus_add_match (f->recipient, "type='signal'", &f->e);
test_assert_no_error (&f->e);
- become_monitor (f);
+ if (!dbus_connection_add_filter (f->recipient, recipient_enqueue_filter,
+ f, NULL))
+ g_error ("OOM");
+ f->recipient_enqueue_filter_added = TRUE;
+
+ become_monitor (f, NULL);
m = dbus_message_new_signal ("/foo", "com.example.CannotSend",
"BroadcastSignal1");
@@ -913,7 +1016,28 @@ test_forbidden_broadcast (Fixture *f,
dbus_connection_send (f->sender, m, NULL);
dbus_message_unref (m);
- while (g_queue_get_length (&f->monitored) < 6)
+ m = dbus_message_new_signal ("/foo", "com.example.CannotBroadcast",
+ "CannotBroadcast");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ m = dbus_message_new_signal ("/foo", "com.example.CannotBroadcast2",
+ "CannotBroadcast2");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ /* these two will go through: we use them as an indirect way to assert that
+ * the recipient has not received anything earlier */
+ m = dbus_message_new_signal ("/foo", "com.example.CannotUnicast",
+ "CannotUnicast");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+ m = dbus_message_new_signal ("/foo", "com.example.CannotUnicast2",
+ "CannotUnicast2");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ while (g_queue_get_length (&f->monitored) < 12)
test_main_context_iterate (f->ctx, TRUE);
m = g_queue_pop_head (&f->monitored);
@@ -947,6 +1071,55 @@ test_forbidden_broadcast (Fixture *f,
dbus_message_unref (m);
m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotBroadcast",
+ "CannotBroadcast", "", NULL);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name,
+ DBUS_ERROR_ACCESS_DENIED);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotBroadcast2",
+ "CannotBroadcast2", "", NULL);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name,
+ DBUS_ERROR_ACCESS_DENIED);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotUnicast",
+ "CannotUnicast", "", NULL);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotUnicast2",
+ "CannotUnicast2", "", NULL);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ g_assert (m == NULL);
+
+ /* the intended recipient only received the ones that were on the interface
+ * where broadcasts are allowed */
+
+ while (g_queue_get_length (&f->received) < 2)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = g_queue_pop_head (&f->received);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotUnicast",
+ "CannotUnicast", "", NULL);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->received);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotUnicast2",
+ "CannotUnicast2", "", NULL);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->received);
g_assert (m == NULL);
}
@@ -959,7 +1132,7 @@ test_unicast_signal (Fixture *f,
if (f->address == NULL)
return;
- become_monitor (f);
+ become_monitor (f, NULL);
m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal1");
if (!dbus_message_set_destination (m, f->recipient_name))
@@ -1010,7 +1183,12 @@ test_forbidden (Fixture *f,
if (f->address == NULL)
return;
- become_monitor (f);
+ if (!dbus_connection_add_filter (f->recipient, recipient_enqueue_filter,
+ f, NULL))
+ g_error ("OOM");
+ f->recipient_enqueue_filter_added = TRUE;
+
+ become_monitor (f, NULL);
m = dbus_message_new_signal ("/foo", "com.example.CannotSend",
"UnicastSignal1");
@@ -1033,7 +1211,36 @@ test_forbidden (Fixture *f,
dbus_connection_send (f->sender, m, NULL);
dbus_message_unref (m);
- while (g_queue_get_length (&f->monitored) < 6)
+ m = dbus_message_new_signal ("/foo", "com.example.CannotUnicast",
+ "CannotUnicast");
+ if (!dbus_message_set_destination (m, f->recipient_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ m = dbus_message_new_signal ("/foo", "com.example.CannotUnicast2",
+ "CannotUnicast2");
+ if (!dbus_message_set_destination (m, f->recipient_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ /* these two will go through: we use them as an indirect way to assert that
+ * the recipient has not received anything earlier */
+ m = dbus_message_new_signal ("/foo", "com.example.CannotBroadcast",
+ "CannotBroadcast");
+ if (!dbus_message_set_destination (m, f->recipient_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+ m = dbus_message_new_signal ("/foo", "com.example.CannotBroadcast2",
+ "CannotBroadcast2");
+ if (!dbus_message_set_destination (m, f->recipient_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ while (g_queue_get_length (&f->monitored) < 12)
test_main_context_iterate (f->ctx, TRUE);
m = g_queue_pop_head (&f->monitored);
@@ -1067,6 +1274,55 @@ test_forbidden (Fixture *f,
dbus_message_unref (m);
m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotUnicast",
+ "CannotUnicast", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name,
+ DBUS_ERROR_ACCESS_DENIED);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotUnicast2",
+ "CannotUnicast2", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_error_reply (m, DBUS_SERVICE_DBUS, f->sender_name,
+ DBUS_ERROR_ACCESS_DENIED);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotBroadcast",
+ "CannotBroadcast", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotBroadcast2",
+ "CannotBroadcast2", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ g_assert (m == NULL);
+
+ /* the intended recipient only received the ones that were on the interface
+ * where unicasts are allowed */
+
+ while (g_queue_get_length (&f->received) < 2)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = g_queue_pop_head (&f->received);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotBroadcast",
+ "CannotBroadcast", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->received);
+ assert_signal (m, f->sender_name, "/foo", "com.example.CannotBroadcast2",
+ "CannotBroadcast2", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->received);
g_assert (m == NULL);
}
@@ -1079,7 +1335,7 @@ test_method_call (Fixture *f,
if (f->address == NULL)
return;
- become_monitor (f);
+ become_monitor (f, NULL);
/* regression test for
* https://bugs.freedesktop.org/show_bug.cgi?id=90952 */
@@ -1134,7 +1390,7 @@ test_forbidden_method_call (Fixture *f,
if (f->address == NULL)
return;
- become_monitor (f);
+ become_monitor (f, NULL);
m = dbus_message_new_method_call (f->recipient_name, "/foo",
"com.example.CannotSend", "Call1");
@@ -1189,7 +1445,7 @@ test_dbus_daemon (Fixture *f,
if (f->address == NULL)
return;
- become_monitor (f);
+ become_monitor (f, NULL);
res = dbus_bus_request_name (f->sender, "com.example.Sender",
DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e);
@@ -1266,7 +1522,7 @@ test_selective (Fixture *f,
"eavesdrop='true',interface='com.example.Tedious'", &f->e);
test_assert_no_error (&f->e);
- become_monitor (f);
+ become_monitor (f, NULL);
m = dbus_message_new_signal ("/foo", "com.example.Interesting",
"UnicastSignal1");
@@ -1309,6 +1565,129 @@ test_selective (Fixture *f,
g_assert (m == NULL);
}
+static void
+test_well_known_destination (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m;
+
+ if (f->address == NULL)
+ return;
+
+ take_well_known_name (f, f->recipient, "com.example.Recipient");
+ /* we don't expect_take_well_known_name here because the
+ * monitor isn't up yet */
+
+ become_monitor (f, NULL);
+
+ /* The sender sends a message to itself. It will not be observed. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "Unobserved");
+ if (!dbus_message_set_destination (m, f->sender_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ /* The sender sends a message to the recipient by well-known name.
+ * It will be observed. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "Observed1");
+ if (!dbus_message_set_destination (m, "com.example.Recipient"))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ /* The sender sends a message to the recipient by unique name.
+ * It will still be observed. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "Observed2");
+ if (!dbus_message_set_destination (m, f->recipient_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ while (g_queue_get_length (&f->monitored) < 2)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.bar",
+ "Observed1", "", "com.example.Recipient");
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.bar",
+ "Observed2", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ g_assert (m == NULL);
+}
+
+static void
+test_unique_destination (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m;
+ Config config = {
+ NULL,
+ NULL, /* match rules */
+ FALSE
+ };
+ const gchar *match_rules[2] = { NULL, NULL };
+ gchar *rule;
+
+ if (f->address == NULL)
+ return;
+
+ take_well_known_name (f, f->recipient, "com.example.Recipient");
+ /* we don't expect_take_well_known_name here because the
+ * monitor isn't up yet */
+
+ rule = g_strdup_printf ("destination='%s'", f->recipient_name);
+ /* free it later */
+ g_test_queue_free (rule);
+ match_rules[0] = rule;
+ config.match_rules = match_rules;
+
+ become_monitor (f, &config);
+
+ /* The sender sends a message to itself. It will not be observed. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "Unobserved");
+ if (!dbus_message_set_destination (m, f->sender_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ /* The sender sends a message to the recipient by well-known name.
+ * It will be observed. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "Observed1");
+ if (!dbus_message_set_destination (m, "com.example.Recipient"))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ /* The sender sends a message to the recipient by unique name.
+ * It will still be observed. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "Observed2");
+ if (!dbus_message_set_destination (m, f->recipient_name))
+ g_error ("OOM");
+ dbus_connection_send (f->sender, m, NULL);
+ dbus_message_unref (m);
+
+ while (g_queue_get_length (&f->monitored) < 2)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.bar",
+ "Observed1", "", "com.example.Recipient");
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ assert_signal (m, f->sender_name, "/foo", "com.example.bar",
+ "Observed2", "", f->recipient_name);
+ dbus_message_unref (m);
+
+ m = g_queue_pop_head (&f->monitored);
+ g_assert (m == NULL);
+}
+
#ifdef DBUS_UNIX
/* currently only used for the systemd activation test */
static void
@@ -1339,20 +1718,6 @@ expect_new_connection (Fixture *f)
/* currently only used for the systemd activation test */
static void
-take_well_known_name (Fixture *f,
- DBusConnection *connection,
- const char *name)
-{
- int ret;
-
- ret = dbus_bus_request_name (connection, name,
- DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e);
- test_assert_no_error (&f->e);
- g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
-}
-
-/* currently only used for the systemd activation test */
-static void
expect_take_well_known_name (Fixture *f,
DBusConnection *connection,
const char *name)
@@ -1392,7 +1757,7 @@ test_activation (Fixture *f,
if (f->address == NULL)
return;
- become_monitor (f);
+ become_monitor (f, NULL);
/* The sender sends a message to an activatable service. */
m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal1");
@@ -1607,7 +1972,10 @@ teardown (Fixture *f,
if (f->recipient != NULL)
{
- dbus_connection_remove_filter (f->recipient, recipient_filter, f);
+ dbus_connection_remove_filter (f->recipient, recipient_check_filter, f);
+ if (f->recipient_enqueue_filter_added)
+ dbus_connection_remove_filter (f->recipient, recipient_enqueue_filter,
+ f);
dbus_connection_close (f->recipient);
dbus_connection_unref (f->recipient);
f->recipient = NULL;
@@ -1629,14 +1997,21 @@ teardown (Fixture *f,
f->activated = NULL;
}
- test_kill_pid (f->daemon_pid);
- g_spawn_close_pid (f->daemon_pid);
+ if (f->daemon_pid != 0)
+ {
+ test_kill_pid (f->daemon_pid);
+ g_spawn_close_pid (f->daemon_pid);
+ f->daemon_pid = 0;
+ }
test_main_context_unref (f->ctx);
g_queue_foreach (&f->monitored, (GFunc) dbus_message_unref, NULL);
g_queue_clear (&f->monitored);
+ g_queue_foreach (&f->received, (GFunc) dbus_message_unref, NULL);
+ g_queue_clear (&f->received);
+
g_free (f->address);
}
@@ -1666,6 +2041,12 @@ main (int argc,
setup, test_dbus_daemon, teardown);
g_test_add ("/monitor/selective", Fixture, &selective_config,
setup, test_selective, teardown);
+ g_test_add ("/monitor/well-known-destination",
+ Fixture, &well_known_destination_config,
+ setup, test_well_known_destination, teardown);
+ g_test_add ("/monitor/unique-destination",
+ Fixture, NULL,
+ setup, test_unique_destination, teardown);
g_test_add ("/monitor/wildcard", Fixture, &wildcard_config,
setup, test_unicast_signal, teardown);
g_test_add ("/monitor/no-rule", Fixture, &no_rules_config,
diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am
index 9982e454..40096350 100644
--- a/test/name-test/Makefile.am
+++ b/test/name-test/Makefile.am
@@ -4,12 +4,24 @@ AM_CPPFLAGS = \
-DDBUS_COMPILATION \
$(NULL)
+AM_CFLAGS = \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(NULL)
+
# if assertions are enabled, improve backtraces
AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
TEST_EXTENSIONS = .sh
-SH_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh
+LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh
+SH_LOG_DRIVER = $(LOG_DRIVER)
+
+LOG_COMPILER = \
+ @abs_top_builddir@/tools/dbus-run-session$(EXEEXT) \
+ --config-file=@abs_builddir@/uninstalled-session.conf \
+ --dbus-daemon=@abs_top_builddir@/bus/dbus-daemon$(EXEEXT) \
+ -- \
+ $(NULL)
SH_LOG_COMPILER = $(SHELL)
## note that TESTS has special meaning (stuff to use in make check)
@@ -20,18 +32,38 @@ TESTS =
if DBUS_ENABLE_EMBEDDED_TESTS
if DBUS_UNIX
AM_TESTS_ENVIRONMENT = \
+ export DBUS_SESSION_BUS_ADDRESS=do-not-use-real-session:; \
export DBUS_TOP_BUILDDIR=@abs_top_builddir@; \
export DBUS_TOP_SRCDIR=@abs_top_srcdir@; \
+ export PATH="@abs_top_builddir@/bus:$$PATH"; \
export PYTHON=@PYTHON@; \
export DBUS_TEST_DATA=@abs_top_builddir@/test/data; \
export DBUS_TEST_DAEMON=@abs_top_builddir@/bus/dbus-daemon$(EXEEXT); \
+ export DBUS_TEST_DBUS_LAUNCH=@abs_top_builddir@/tools/dbus-launch$(EXEEXT); \
export XDG_RUNTIME_DIR=@abs_top_builddir@/test/XDG_RUNTIME_DIR; \
+ unset DBUS_SESSION_BUS_ADDRESS; \
+ unset DBUS_SESSION_BUS_PID; \
$(NULL)
+uninstalled-session.conf: $(top_builddir)/bus/session.conf Makefile
+ $(SED) -e 's|<standard_session_servicedirs.*$$|<servicedir>@abs_top_builddir@/test/data/valid-service-files</servicedir>|g' \
+ -e 's|<include.*$$||g' \
+ < $< > $@
+
+check_DATA = \
+ uninstalled-session.conf \
+ $(NULL)
+
TESTS += \
run-test.sh \
run-test-systemserver.sh \
+ test-ids \
+ test-pending-call-dispatch \
+ test-pending-call-timeout \
test-pending-call-disconnected \
+ test-privserver-client \
+ test-shutdown \
+ test-threads-init \
$(NULL)
endif
endif
diff --git a/test/name-test/run-test.sh b/test/name-test/run-test.sh
index 1e257a16..092ec69f 100755
--- a/test/name-test/run-test.sh
+++ b/test/name-test/run-test.sh
@@ -48,10 +48,8 @@ c_test () {
shift
e=0
echo "# running test $t"
- if ! "${DBUS_TOP_BUILDDIR}/libtool" --mode=execute $DEBUG "$DBUS_TOP_BUILDDIR/test/name-test/$t" "$@" >&2; then
- e=$?
- echo "# exit status $e"
- fi
+ "${DBUS_TOP_BUILDDIR}/libtool" --mode=execute $DEBUG "$DBUS_TOP_BUILDDIR/test/name-test/$t" "$@" >&2 || e=$?
+ echo "# exit status $e"
interpret_result "$e" "$t" "$@"
}
@@ -69,14 +67,8 @@ py_test () {
}
test_num=1
-# TAP test plan: we will run 8 tests
-echo "1..8"
+# TAP test plan: we will run 2 tests
+echo "1..2"
-c_test test-ids
-c_test test-pending-call-dispatch
-c_test test-pending-call-timeout
-c_test test-threads-init
-c_test test-privserver-client
-c_test test-shutdown
py_test test-activation-forking.py
c_test test-autolaunch
diff --git a/test/name-test/test-activation-forking.py b/test/name-test/test-activation-forking.py
index f98537eb..44bc1a6e 100644
--- a/test/name-test/test-activation-forking.py
+++ b/test/name-test/test-activation-forking.py
@@ -7,7 +7,7 @@ try:
import dbus
import dbus.mainloop.glib
except:
- print "Failed import, aborting test"
+ print("Failed import, aborting test")
sys.exit(0)
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -23,7 +23,7 @@ i = dbus.Interface(o, 'org.freedesktop.TestSuite')
# Start it up
reply = i.Echo("hello world")
-print "TestSuiteForkingEchoService initial reply OK"
+print("TestSuiteForkingEchoService initial reply OK")
def ignore(*args, **kwargs):
pass
@@ -36,7 +36,7 @@ def on_forking_echo_owner_changed(name, old, new):
global o
global i
if counter > 10:
- print "Activated 10 times OK, TestSuiteForkingEchoService pass"
+ print("Activated 10 times OK, TestSuiteForkingEchoService pass")
loop.quit()
return
counter += 1
@@ -52,7 +52,7 @@ i.Exit(reply_handler=ignore, error_handler=ignore)
def check_counter():
if counter == 0:
- print "Failed to get NameOwnerChanged for TestSuiteForkingEchoService"
+ print("Failed to get NameOwnerChanged for TestSuiteForkingEchoService")
sys.exit(1)
GObject.timeout_add(15000, check_counter)
diff --git a/test/name-test/test-autolaunch.c b/test/name-test/test-autolaunch.c
index 8b5206a6..61760555 100644
--- a/test/name-test/test-autolaunch.c
+++ b/test/name-test/test-autolaunch.c
@@ -8,6 +8,7 @@
#endif
#include <dbus/dbus.h>
+#include "dbus/dbus-internals.h"
#include "dbus/dbus-sysdeps.h"
int
@@ -15,11 +16,20 @@ main (int argc, char *argv[])
{
DBusConnection *conn = NULL;
DBusError error;
+ DBusGUID uuid;
dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", NULL);
dbus_error_init (&error);
+ if (!_dbus_read_local_machine_uuid (&uuid, FALSE, &error))
+ {
+ /* We can't expect autolaunching to work in this situation */
+ fprintf (stderr, "*** %s\n", error.message);
+ dbus_error_free (&error);
+ return 0;
+ }
+
conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
diff --git a/test/name-test/test-ids.c b/test/name-test/test-ids.c
index 8f63d044..73b71f15 100644
--- a/test/name-test/test-ids.c
+++ b/test/name-test/test-ids.c
@@ -8,13 +8,18 @@
#include <unistd.h>
#endif
+static void die (const char *message) _DBUS_GNUC_NORETURN;
+
static void
die (const char *message)
{
- fprintf (stderr, "*** test-ids: %s", message);
+ printf ("Bail out! test-ids: %s\n", message);
exit (1);
}
+static int test_num = 0;
+
+/* This test outputs TAP syntax: http://testanything.org/ */
int
main (int argc,
char **argv)
@@ -23,7 +28,7 @@ main (int argc,
DBusConnection *connection;
char *id;
char *server_id;
-
+
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
if (connection == NULL)
@@ -33,24 +38,35 @@ main (int argc,
dbus_error_free (&error);
return 1;
}
+ printf ("ok %d - connected to session bus\n", ++test_num);
server_id = dbus_connection_get_server_id (connection);
+
if (server_id == NULL)
die ("No bus server ID retrieved\n");
- /* printf("'%s'\n", server_id); */
+
+ printf ("ok %d - session bus server ID is %s\n", ++test_num, server_id);
+
if (strlen (server_id) != 32)
die ("Bus server id should have length 32\n");
+
+ printf ("ok %d - session bus server ID length is 32\n", ++test_num);
+
dbus_free (server_id);
id = dbus_bus_get_id (connection, NULL);
if (id == NULL)
die ("No bus ID retrieved\n");
- /* printf("'%s'\n", id); */
+
+ printf ("ok %d - session bus ID is %s\n", ++test_num, id);
+
if (strlen (id) != 32)
die ("Bus ID should have length 32\n");
+
+ printf ("ok %d - session bus ID length is 32\n", ++test_num);
+
dbus_free (id);
-
- _dbus_verbose ("*** Test IDs exiting\n");
-
+
+ printf ("1..%d\n", test_num);
return 0;
}
diff --git a/test/name-test/test-pending-call-dispatch.c b/test/name-test/test-pending-call-dispatch.c
index c8b5a467..af80868a 100644
--- a/test/name-test/test-pending-call-dispatch.c
+++ b/test/name-test/test-pending-call-dispatch.c
@@ -1,3 +1,26 @@
+/*
+ * Copyright © 2006 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
/**
* Test to make sure we don't get stuck polling a dbus connection
* which has no data on the socket. This was an issue where
@@ -20,7 +43,7 @@ _run_iteration (DBusConnection *conn)
DBusPendingCall *dbus_pending;
DBusMessage *method;
DBusMessage *reply;
- char *echo = "echo";
+ const char *echo = "echo";
/* send the first message */
method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
@@ -28,7 +51,12 @@ _run_iteration (DBusConnection *conn)
"org.freedesktop.TestSuite",
"Echo");
- dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
+ if (!dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL))
+ {
+ fprintf (stderr, "Bail out! Failed to append arguments: OOM\n");
+ exit (1);
+ }
+
dbus_connection_send_with_reply (conn, method, &echo_pending, -1);
dbus_message_unref (method);
@@ -56,13 +84,13 @@ _run_iteration (DBusConnection *conn)
if (reply == NULL)
{
- printf ("Failed: Reply is NULL ***\n");
+ printf ("Bail out! Reply is NULL ***\n");
exit (1);
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
{
- printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
+ printf ("Bail out! Reply is error: %s ***\n", dbus_message_get_error_name (reply));
exit (1);
}
@@ -72,6 +100,7 @@ _run_iteration (DBusConnection *conn)
}
+/* This test outputs TAP syntax: http://testanything.org/ */
int
main (int argc, char *argv[])
{
@@ -87,7 +116,7 @@ main (int argc, char *argv[])
but if it does and we are stuck in a poll call then we know the
stuck in poll bug has come back to haunt us */
- printf ("*** Testing stuck in poll\n");
+ printf ("# Testing stuck in poll\n");
dbus_error_init (&error);
@@ -104,10 +133,10 @@ main (int argc, char *argv[])
/* we just care about seconds */
delta = end_tv_sec - start_tv_sec;
- printf ("Iter %i: %lis\n", i, delta);
+ printf ("ok %d - %lis\n", i + 1, delta);
if (delta >= 5)
{
- printf ("Failed: looks like we might have been be stuck in poll ***\n");
+ printf ("Bail out! Looks like we might have been be stuck in poll ***\n");
exit (1);
}
}
@@ -119,6 +148,6 @@ main (int argc, char *argv[])
dbus_connection_send (conn, method, NULL);
dbus_message_unref (method);
- printf ("Success ***\n");
+ printf ("# Testing completed\n1..%d\n", i);
exit (0);
}
diff --git a/test/name-test/test-pending-call-timeout.c b/test/name-test/test-pending-call-timeout.c
index d051faba..a204db01 100644
--- a/test/name-test/test-pending-call-timeout.c
+++ b/test/name-test/test-pending-call-timeout.c
@@ -17,7 +17,7 @@ _method_call (DBusConnection *conn,
DBusPendingCall *pending;
DBusMessage *method;
DBusMessage *reply;
- char *echo = "echo";
+ const char *echo = "echo";
/* send the message */
method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
@@ -25,8 +25,13 @@ _method_call (DBusConnection *conn,
"org.freedesktop.TestSuite",
"DelayEcho");
- dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
- dbus_connection_send_with_reply (conn, method, &pending, timeout_milliseconds);
+ if (method == NULL ||
+ !dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL) ||
+ !dbus_connection_send_with_reply (conn, method, &pending, timeout_milliseconds))
+ {
+ printf ("Bail out! OOM when building and sending message ***\n");
+ exit (1);
+ }
dbus_message_unref (method);
/* block on the message */
@@ -39,13 +44,13 @@ _method_call (DBusConnection *conn,
if (reply == NULL)
{
- printf ("Failed: Reply is NULL ***\n");
+ printf ("Bail out! Reply is NULL ***\n");
exit (1);
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
{
- printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
+ printf ("Bail out! Reply is error: %s ***\n", dbus_message_get_error_name (reply));
exit (1);
}
@@ -61,6 +66,7 @@ _run_iteration (DBusConnection *conn)
_method_call (conn, INT_MAX);
}
+/* This test outputs TAP syntax: http://testanything.org/ */
int
main (int argc, char *argv[])
{
@@ -71,7 +77,7 @@ main (int argc, char *argv[])
DBusConnection *conn;
DBusError error;
- printf ("*** Testing pending call timeouts\n");
+ printf ("# Testing pending call timeouts\n");
dbus_error_init (&error);
@@ -88,7 +94,7 @@ main (int argc, char *argv[])
/* we just care about seconds */
delta = end_tv_sec - start_tv_sec;
- printf ("Iter %i: %lis\n", i, delta);
+ printf ("ok %d - %lis\n", i + 1, delta);
}
method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
@@ -98,6 +104,6 @@ main (int argc, char *argv[])
dbus_connection_send (conn, method, NULL);
dbus_message_unref (method);
- printf ("Success ***\n");
+ printf ("# Testing completed\n1..%d\n", i);
exit (0);
}
diff --git a/test/name-test/test-privserver-client.c b/test/name-test/test-privserver-client.c
index e7f48960..7a293f4e 100644
--- a/test/name-test/test-privserver-client.c
+++ b/test/name-test/test-privserver-client.c
@@ -1,6 +1,9 @@
#include <config.h>
#include "../test-utils.h"
+static void die (const char *message,
+ ...) _DBUS_GNUC_NORETURN _DBUS_GNUC_PRINTF (1, 2);
+
static void
die (const char *message, ...)
{
@@ -100,9 +103,13 @@ open_shutdown_private_connection (dbus_bool_t use_guid)
if (!(reply = dbus_connection_send_with_reply_and_block (session, msg, -1, &error)))
die ("couldn't send message: %s\n", error.message);
dbus_message_unref (msg);
+
+ if (dbus_set_error_from_message (&error, reply))
+ die ("%s: %s", error.name, error.message);
+
if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID))
die ("couldn't parse message replym\n");
- printf ("got private temp address %s\n", addr);
+ printf ("# got private temp address %s\n", addr);
addr = strdup (addr);
if (!use_guid)
{
@@ -145,24 +152,32 @@ open_shutdown_private_connection (dbus_bool_t use_guid)
_dbus_loop_unref (loop);
}
+/* This test outputs TAP syntax: http://testanything.org/ */
int
main (int argc, char *argv[])
{
+ int test_num = 0;
+
open_shutdown_private_connection (TRUE);
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
open_shutdown_private_connection (TRUE);
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
open_shutdown_private_connection (FALSE);
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
open_shutdown_private_connection (FALSE);
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
+ printf ("1..%d\n", test_num);
return 0;
}
diff --git a/test/name-test/test-privserver.c b/test/name-test/test-privserver.c
index 39a98b7f..c6de7348 100644
--- a/test/name-test/test-privserver.c
+++ b/test/name-test/test-privserver.c
@@ -1,6 +1,9 @@
#include <config.h>
#include "../test-utils.h"
+static void die (const char *message,
+ ...) _DBUS_GNUC_NORETURN _DBUS_GNUC_PRINTF (1, 2);
+
static void
die (const char *message, ...)
{
@@ -42,11 +45,20 @@ filter_session_message (DBusConnection *connection,
"GetPrivateAddress"))
{
DBusMessage *reply;
+
reply = dbus_message_new_method_return (message);
- dbus_message_append_args (reply, DBUS_TYPE_STRING,
- &(testdata->private_addr), DBUS_TYPE_INVALID);
- dbus_connection_send (connection, reply, NULL);
+ if (reply == NULL)
+ die ("OOM");
+ if (!dbus_message_append_args (reply, DBUS_TYPE_STRING,
+ &(testdata->private_addr),
+ DBUS_TYPE_INVALID))
+ die ("OOM");
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ die ("Error sending message");
+
dbus_message_unref (reply);
+
return DBUS_HANDLER_RESULT_HANDLED;
}
else if (dbus_message_is_method_call (message,
@@ -95,9 +107,9 @@ main (int argc, char *argv[])
server = dbus_server_listen ("unix:tmpdir=/tmp", &error);
#endif
if (!server)
- die (error.message);
+ die ("%s", error.message);
testdata->private_addr = dbus_server_get_address (server);
- printf ("test server listening on %s\n", testdata->private_addr);
+ fprintf (stderr, "test server listening on %s\n", testdata->private_addr);
dbus_server_set_new_connection_function (server, new_connection_callback,
testdata, NULL);
diff --git a/test/name-test/test-shutdown.c b/test/name-test/test-shutdown.c
index 526c1cbc..e70bfd39 100644
--- a/test/name-test/test-shutdown.c
+++ b/test/name-test/test-shutdown.c
@@ -4,10 +4,12 @@
static DBusLoop *loop;
+static void die (const char *message) _DBUS_GNUC_NORETURN;
+
static void
die (const char *message)
{
- fprintf (stderr, "*** test-shutdown: %s", message);
+ printf ("Bail out! test-shutdown: %s", message);
exit (1);
}
@@ -46,23 +48,28 @@ open_destroy_shared_session_bus_connection (void)
dbus_connection_unref (connection);
}
+/* This test outputs TAP syntax: http://testanything.org/ */
int
main (int argc,
char **argv)
{
+ int test_num = 0;
+
open_destroy_shared_session_bus_connection ();
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
open_destroy_shared_session_bus_connection ();
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
open_destroy_shared_session_bus_connection ();
dbus_shutdown ();
+ printf ("ok %d\n", ++test_num);
- _dbus_verbose ("*** Test shutdown exiting\n");
-
+ printf ("1..%d\n", test_num);
return 0;
}
diff --git a/test/name-test/test-threads-init.c b/test/name-test/test-threads-init.c
index a517e2a2..a19b9627 100644
--- a/test/name-test/test-threads-init.c
+++ b/test/name-test/test-threads-init.c
@@ -18,7 +18,7 @@ _run_iteration (DBusConnection *conn)
DBusPendingCall *dbus_pending;
DBusMessage *method;
DBusMessage *reply;
- char *echo = "echo";
+ const char *echo = "echo";
/* send the first message */
method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
@@ -26,7 +26,12 @@ _run_iteration (DBusConnection *conn)
"org.freedesktop.TestSuite",
"Echo");
- dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
+ if (!dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL))
+ {
+ fprintf (stderr, "Bail out! Failed to append arguments: OOM\n");
+ exit (1);
+ }
+
dbus_connection_send_with_reply (conn, method, &echo_pending, -1);
dbus_message_unref (method);
@@ -54,13 +59,13 @@ _run_iteration (DBusConnection *conn)
if (reply == NULL)
{
- printf ("Failed: Reply is NULL ***\n");
+ printf ("Bail out! Reply is NULL ***\n");
exit (1);
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
{
- printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
+ printf ("Bail out! Reply is error: %s ***\n", dbus_message_get_error_name (reply));
exit (1);
}
@@ -105,7 +110,7 @@ check_condvar_lock (DBusCondVar *condvar1,
}
}
-
+/* This test outputs TAP syntax: http://testanything.org/ */
int
main (int argc, char *argv[])
{
@@ -116,14 +121,23 @@ main (int argc, char *argv[])
DBusCondVar *dispatch_cond1, *io_path_cond1;
DBusMutex *mutex2, *dispatch_mutex2, *io_path_mutex2;
DBusCondVar *dispatch_cond2, *io_path_cond2;
+ int test_num = 0;
- printf ("*** Testing late thread init\n");
+ printf ("# Testing late thread init\n");
dbus_error_init (&error);
conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
- _dbus_connection_test_get_locks (conn, &mutex1,
+ if (conn == NULL)
+ {
+ fprintf (stderr, "Bail out! Failed to open connection to session bus: %s\n",
+ error.message);
+ dbus_error_free (&error);
+ return 1;
+ }
+
+ _dbus_connection_test_get_locks (conn, &mutex1,
&dispatch_mutex1,
&io_path_mutex1,
&dispatch_cond1,
@@ -140,8 +154,13 @@ main (int argc, char *argv[])
check_mutex_lock (io_path_mutex1, io_path_mutex2, TRUE);
check_condvar_lock (dispatch_cond1, dispatch_cond2, TRUE);
check_condvar_lock (io_path_cond1, io_path_cond2, TRUE);
+ printf ("ok %d\n", ++test_num);
- dbus_threads_init_default ();
+ if (!dbus_threads_init_default ())
+ {
+ fprintf (stderr, "Bail out! Failed to initialise threads: OOM\n");
+ return 1;
+ }
_dbus_connection_test_get_locks (conn, &mutex1,
&dispatch_mutex1,
@@ -161,6 +180,7 @@ main (int argc, char *argv[])
check_mutex_lock (io_path_mutex1, io_path_mutex2, TRUE);
check_condvar_lock (dispatch_cond1, dispatch_cond2, TRUE);
check_condvar_lock (io_path_cond1, io_path_cond2, TRUE);
+ printf ("ok %d\n", ++test_num);
method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
"/org/freedesktop/TestSuite",
@@ -169,6 +189,6 @@ main (int argc, char *argv[])
dbus_connection_send (conn, method, NULL);
dbus_message_unref (method);
- printf ("Success ***\n");
+ printf ("# Testing completed\n1..%d\n", test_num);
exit (0);
}
diff --git a/test/name-test/test-wait-for-echo.py b/test/name-test/test-wait-for-echo.py
index 49ecbb46..d1b9e0c4 100755
--- a/test/name-test/test-wait-for-echo.py
+++ b/test/name-test/test-wait-for-echo.py
@@ -7,7 +7,7 @@ try:
import dbus.mainloop.glib
from gi.repository import GObject
except:
- print "Failed import, aborting test"
+ print("Failed import, aborting test")
sys.exit(0)
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -16,7 +16,7 @@ loop = GObject.MainLoop()
exitcode = 0
def handle_noreceipt():
- print "Failed to get signal"
+ print("Failed to get signal")
global exitcode
exitcode = 1
loop.quit()
@@ -26,7 +26,7 @@ GObject.timeout_add(7000, handle_noreceipt)
bus = dbus.SessionBus()
def sighandler(*args, **kwargs):
- print "got signal"
+ print("got signal")
loop.quit()
bus.add_signal_receiver(sighandler, dbus_interface='org.freedesktop.TestSuite', signal_name='Foo')
diff --git a/test/name-test/tmp-session-like-system.conf b/test/name-test/tmp-session-like-system.conf
index 29ab115f..b3d9caea 100644
--- a/test/name-test/tmp-session-like-system.conf
+++ b/test/name-test/tmp-session-like-system.conf
@@ -12,8 +12,6 @@
the behavior of child processes. -->
<keep_umask/>
- <syslog/>
-
<listen>unix:tmpdir=/tmp</listen>
<standard_session_servicedirs />
diff --git a/test/relay.c b/test/relay.c
index e275c167..2b3efb96 100644
--- a/test/relay.c
+++ b/test/relay.c
@@ -46,6 +46,7 @@
typedef struct {
TestMainContext *ctx;
DBusError e;
+ gboolean skip;
DBusServer *server;
@@ -120,13 +121,23 @@ new_conn_cb (DBusServer *server,
static void
setup (Fixture *f,
- gconstpointer data G_GNUC_UNUSED)
+ gconstpointer address)
{
+ test_timeout_reset (1);
+
f->ctx = test_main_context_get ();
dbus_error_init (&f->e);
g_queue_init (&f->messages);
- f->server = dbus_server_listen ("tcp:host=127.0.0.1", &f->e);
+ if ((g_str_has_prefix (address, "tcp:") ||
+ g_str_has_prefix (address, "nonce-tcp:")) &&
+ !test_check_tcp_works ())
+ {
+ f->skip = TRUE;
+ return;
+ }
+
+ f->server = dbus_server_listen (address, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
@@ -142,6 +153,9 @@ test_connect (Fixture *f,
dbus_bool_t have_mem;
char *address;
+ if (f->skip)
+ return;
+
g_assert (f->left_server_conn == NULL);
g_assert (f->right_server_conn == NULL);
@@ -203,6 +217,9 @@ test_relay (Fixture *f,
{
DBusMessage *incoming;
+ if (f->skip)
+ return;
+
test_connect (f, data);
send_one (f, "First");
@@ -235,6 +252,9 @@ test_limit (Fixture *f,
DBusMessage *incoming;
guint i;
+ if (f->skip)
+ return;
+
test_connect (f, data);
/* This was an attempt to reproduce fd.o #34393. It didn't work. */
@@ -319,12 +339,21 @@ main (int argc,
{
test_init (&argc, &argv);
- g_test_add ("/connect", Fixture, NULL, setup,
+ g_test_add ("/connect/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+ test_connect, teardown);
+ g_test_add ("/relay/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+ test_relay, teardown);
+ g_test_add ("/limit/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+ test_limit, teardown);
+
+#ifdef DBUS_UNIX
+ g_test_add ("/connect/unix", Fixture, "unix:tmpdir=/tmp", setup,
test_connect, teardown);
- g_test_add ("/relay", Fixture, NULL, setup,
+ g_test_add ("/relay/unix", Fixture, "unix:tmpdir=/tmp", setup,
test_relay, teardown);
- g_test_add ("/limit", Fixture, NULL, setup,
+ g_test_add ("/limit/unix", Fixture, "unix:tmpdir=/tmp", setup,
test_limit, teardown);
+#endif
return g_test_run ();
}
diff --git a/test/sd-activation.c b/test/sd-activation.c
index 9b2a5bb5..8e0b2af6 100644
--- a/test/sd-activation.c
+++ b/test/sd-activation.c
@@ -1,4 +1,7 @@
-/* Unit tests for systemd activation.
+/* Unit tests for systemd activation, with or without AppArmor.
+ *
+ * We compile this source file twice: once with AppArmor support (if available)
+ * and once without.
*
* Copyright © 2010-2011 Nokia Corporation
* Copyright © 2015 Collabora Ltd.
@@ -26,7 +29,16 @@
#include <config.h>
+#include <errno.h>
+#include <unistd.h>
#include <string.h>
+#include <sys/types.h>
+
+#include <glib/gstdio.h>
+
+#if defined(HAVE_APPARMOR_2_10) && defined(DBUS_TEST_APPARMOR_ACTIVATION)
+#include <sys/apparmor.h>
+#endif
#include "test-utils-glib.h"
@@ -52,8 +64,23 @@ typedef struct {
const char *activated_name;
DBusMessage *activated_message;
dbus_bool_t activated_filter_added;
+
+ gchar *transient_service_file;
+ gchar *tmp_runtime_dir;
} Fixture;
+typedef enum
+{
+ FLAG_EARLY_TRANSIENT_SERVICE = (1 << 0),
+ FLAG_NONE = 0
+} Flags;
+
+typedef struct
+{
+ const gchar *bus_name;
+ Flags flags;
+} Config;
+
/* this is a macro so it gets the right line number */
#define assert_signal(m, \
sender, path, iface, member, signature, \
@@ -168,6 +195,10 @@ activated_filter (DBusConnection *connection,
g_assert (f->activated_message == NULL);
f->activated_message = dbus_message_ref (message);
+ /* Test code is expected to reply to method calls itself */
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
+ return DBUS_HANDLER_RESULT_HANDLED;
+
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -193,23 +224,123 @@ caller_filter (DBusConnection *connection,
}
static void
+fixture_create_transient_service (Fixture *f,
+ const gchar *name)
+{
+ gchar *service;
+ gchar *content;
+ gboolean ok;
+
+ service = g_strdup_printf ("%s.service", name);
+ f->transient_service_file = g_build_filename (f->tmp_runtime_dir, "dbus-1",
+ "services", service, NULL);
+ g_free (service);
+
+ content = g_strdup_printf (
+ "[D-BUS Service]\n"
+ "Name=%s\n"
+ "Exec=/bin/false %s\n"
+ "SystemdService=dbus-%s.service\n", name, name, name);
+ ok = g_file_set_contents (f->transient_service_file, content, -1, &f->ge);
+ g_assert_no_error (f->ge);
+ g_assert (ok);
+ g_free (content);
+}
+
+static void
setup (Fixture *f,
- gconstpointer context G_GNUC_UNUSED)
+ gconstpointer context)
{
- f->ctx = test_main_context_get ();
+ const Config *config = context;
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION) && defined(HAVE_APPARMOR_2_10)
+ aa_features *features;
+#endif
f->ge = NULL;
dbus_error_init (&f->e);
+ f->tmp_runtime_dir = g_dir_make_tmp ("dbus-daemon-test.XXXXXX", &f->ge);
+ g_assert_no_error (f->ge);
+
+ if (config != NULL && (config->flags & FLAG_EARLY_TRANSIENT_SERVICE) != 0)
+ {
+ gchar *dbus1 = g_build_filename (f->tmp_runtime_dir, "dbus-1", NULL);
+ gchar *services = g_build_filename (dbus1, "services", NULL);
+
+ /* We just created it so the directories shouldn't exist yet */
+ test_mkdir (dbus1, 0700);
+ test_mkdir (services, 0700);
+ fixture_create_transient_service (f, config->bus_name);
+ g_free (dbus1);
+ g_free (services);
+ }
+
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION) && !defined(HAVE_APPARMOR_2_10)
+
+ g_test_skip ("AppArmor support not compiled or AppArmor 2.10 unavailable");
+ return;
+
+#else
+
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION)
+ if (!aa_is_enabled ())
+ {
+ g_test_message ("aa_is_enabled() -> %s", g_strerror (errno));
+ g_test_skip ("AppArmor not enabled");
+ return;
+ }
+
+ if (aa_features_new_from_kernel (&features) != 0)
+ {
+ g_test_skip ("Unable to check AppArmor features");
+ return;
+ }
+
+ if (!aa_features_supports (features, "dbus/mask/send") ||
+ !aa_features_supports (features, "dbus/mask/receive"))
+ {
+ g_test_skip ("D-Bus send/receive mediation unavailable");
+ aa_features_unref (features);
+ return;
+ }
+
+ aa_features_unref (features);
+#endif
+
+ f->ctx = test_main_context_get ();
+
f->address = test_get_dbus_daemon (
"valid-config-files/systemd-activation.conf",
- TEST_USER_ME, &f->daemon_pid);
+ TEST_USER_ME, f->tmp_runtime_dir, &f->daemon_pid);
if (f->address == NULL)
return;
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION)
+ /*
+ * Make use of the fact that the LSM security label (and other process
+ * properties) that are used for access-control are whatever was current
+ * at the time the connection was opened.
+ *
+ * 42 is arbitrary. In a real use of AppArmor it would be a securely-random
+ * value, to prevent less-privileged code (that does not know the magic
+ * value) from changing back.
+ */
+ if (aa_change_hat ("caller", 42) != 0)
+ g_error ("Unable to change profile to ...//^caller: %s",
+ g_strerror (errno));
+#endif
+
f->caller = test_connect_to_bus (f->ctx, f->address);
f->caller_name = dbus_bus_get_unique_name (f->caller);
+
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION)
+ if (aa_change_hat (NULL, 42) != 0)
+ g_error ("Unable to change back to initial profile: %s",
+ g_strerror (errno));
+#endif
+
+#endif
}
static void
@@ -557,6 +688,10 @@ test_deny_send (Fixture *f,
gconstpointer context)
{
DBusMessage *m;
+ const Config *config = context;
+
+ g_assert (config != NULL);
+ g_assert (config->bus_name != NULL);
if (f->address == NULL)
return;
@@ -567,7 +702,7 @@ test_deny_send (Fixture *f,
f->caller_filter_added = TRUE;
/* The sender sends a message to an activatable service. */
- m = dbus_message_new_method_call ("com.example.SendDenied", "/foo",
+ m = dbus_message_new_method_call (config->bus_name, "/foo",
"com.example.bar", "Call");
if (m == NULL)
g_error ("OOM");
@@ -575,8 +710,20 @@ test_deny_send (Fixture *f,
dbus_connection_send (f->caller, m, NULL);
dbus_message_unref (m);
- /* Even before the fake systemd connects to the bus, we get an error
- * back: activation is not allowed. */
+ /*
+ * Even before the fake systemd connects to the bus, we get an error
+ * back: activation is not allowed.
+ *
+ * In the normal case, this is because the XML policy does not allow
+ * anyone to send messages to the bus name com.example.SendDenied.
+ *
+ * In the AppArmor case, this is because the AppArmor policy does not allow
+ * this process to send messages to the bus name
+ * com.example.SendDeniedByAppArmorName, or to the label
+ * @DBUS_TEST_EXEC@/com.example.SendDeniedByAppArmorLabel that we assume the
+ * service com.example.SendDeniedByAppArmorLabel will receive after systemd
+ * runs it.
+ */
while (f->caller_message == NULL)
test_main_context_iterate (f->ctx, TRUE);
@@ -593,6 +740,10 @@ test_deny_receive (Fixture *f,
gconstpointer context)
{
DBusMessage *m;
+ const Config *config = context;
+
+ g_assert (config != NULL);
+ g_assert (config->bus_name != NULL);
if (f->address == NULL)
return;
@@ -602,9 +753,11 @@ test_deny_receive (Fixture *f,
f->caller_filter_added = TRUE;
- /* The sender sends a message to an activatable service. */
- m = dbus_message_new_method_call ("com.example.ReceiveDenied", "/foo",
- "com.example.ReceiveDenied", "Call");
+ /* The sender sends a message to an activatable service.
+ * We set the interface name equal to the bus name to make it
+ * easier to write the necessary policy rules. */
+ m = dbus_message_new_method_call (config->bus_name, "/foo",
+ config->bus_name, "Call");
if (m == NULL)
g_error ("OOM");
@@ -631,16 +784,44 @@ test_deny_receive (Fixture *f,
dbus_message_unref (m);
/* systemd starts the activatable service. */
+
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION) && defined(HAVE_APPARMOR_2_10)
+ /* The use of 42 here is arbitrary, see setup(). */
+ if (aa_change_hat (config->bus_name, 42) != 0)
+ g_error ("Unable to change profile to ...//^%s: %s",
+ config->bus_name, g_strerror (errno));
+#endif
+
f->activated = test_connect_to_bus (f->ctx, f->address);
if (!dbus_connection_add_filter (f->activated, activated_filter,
f, NULL))
g_error ("OOM");
f->activated_filter_added = TRUE;
f->activated_name = dbus_bus_get_unique_name (f->activated);
- take_well_known_name (f, f->activated, "com.example.ReceiveDenied");
-
- /* We re-do the message matching, and now the message is
- * forbidden by the receive policy. */
+ take_well_known_name (f, f->activated, config->bus_name);
+
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION) && defined(HAVE_APPARMOR_2_10)
+ if (aa_change_hat (NULL, 42) != 0)
+ g_error ("Unable to change back to initial profile: %s",
+ g_strerror (errno));
+#endif
+
+ /*
+ * We re-do the message matching, and now the message is
+ * forbidden by the receive policy.
+ *
+ * In the normal case, this is because the XML policy does not allow
+ * receiving any message with interface com.example.ReceiveDenied.
+ * We can't use the recipient's bus name here because the XML policy
+ * has no syntax for preventing the owner of a name from receiving
+ * messages - that would be pointless, because the sender could just
+ * open another connection and not own the same name on that connection.
+ *
+ * In the AppArmor case, this is because the AppArmor policy does not allow
+ * receiving messages with interface com.example.ReceiveDeniedByAppArmor
+ * from a peer with the same label we have. Again, we can't use the
+ * recipient's bus name because there is no syntax for this.
+ */
while (f->caller_message == NULL)
test_main_context_iterate (f->ctx, TRUE);
@@ -654,6 +835,172 @@ test_deny_receive (Fixture *f,
g_assert (f->activated_message == NULL);
}
+/*
+ * Test that we can set up transient services.
+ *
+ * If (flags & FLAG_EARLY_TRANSIENT_SERVICE), we assert that a service that
+ * was deployed before starting systemd (in setup()) is available.
+ *
+ * Otherwise, we assert that a service that is deployed while dbus-daemon
+ * is already running becomes available after reloading the dbus-daemon
+ * configuration.
+ */
+static void
+test_transient_services (Fixture *f,
+ gconstpointer context)
+{
+ const Config *config = context;
+ DBusMessage *m = NULL;
+ DBusMessage *send_reply = NULL;
+ DBusMessage *reply = NULL;
+ DBusPendingCall *pc;
+
+ g_assert (config != NULL);
+ g_assert (config->bus_name != NULL);
+
+ if (f->address == NULL)
+ return;
+
+ /* Connect the fake systemd to the bus. */
+ f->systemd = test_connect_to_bus (f->ctx, f->address);
+ if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL))
+ g_error ("OOM");
+ f->systemd_filter_added = TRUE;
+ f->systemd_name = dbus_bus_get_unique_name (f->systemd);
+ take_well_known_name (f, f->systemd, "org.freedesktop.systemd1");
+
+ if ((config->flags & FLAG_EARLY_TRANSIENT_SERVICE) == 0)
+ {
+ /* Try to activate a service that isn't there. */
+ m = dbus_message_new_method_call (config->bus_name,
+ "/foo", "com.example.bar", "Activate");
+
+ if (m == NULL ||
+ !dbus_connection_send_with_reply (f->caller, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) || pc == NULL)
+ g_error ("OOM");
+
+ dbus_message_unref (m);
+ m = NULL;
+
+ /* It fails. */
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ assert_error_reply (m, DBUS_SERVICE_DBUS, f->caller_name,
+ DBUS_ERROR_SERVICE_UNKNOWN);
+
+ dbus_message_unref (m);
+ m = NULL;
+
+ /* Now generate a transient D-Bus service file for it. The directory
+ * should have been created during dbus-daemon startup, so we don't have to
+ * recreate it. */
+ fixture_create_transient_service (f, config->bus_name);
+
+ /* To guarantee that the transient service has been picked up, we have
+ * to reload. */
+ m = dbus_message_new_method_call (DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS, "ReloadConfig");
+
+ if (m == NULL ||
+ !dbus_connection_send_with_reply (f->caller, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) || pc == NULL)
+ g_error ("OOM");
+
+ dbus_message_unref (m);
+ m = NULL;
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &m);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &m, NULL))
+ g_error ("OOM");
+
+ while (m == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ assert_method_reply (m, DBUS_SERVICE_DBUS, f->caller_name, "");
+ dbus_message_unref (m);
+ m = NULL;
+ }
+
+ /* The service is present now. */
+ m = dbus_message_new_method_call (config->bus_name,
+ "/foo", "com.example.bar", "Activate");
+
+ if (m == NULL ||
+ !dbus_connection_send_with_reply (f->caller, m, &pc,
+ DBUS_TIMEOUT_USE_DEFAULT) || pc == NULL)
+ g_error ("OOM");
+
+ dbus_message_unref (m);
+ m = NULL;
+
+ if (dbus_pending_call_get_completed (pc))
+ test_pending_call_store_reply (pc, &reply);
+ else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
+ &reply, NULL))
+ g_error ("OOM");
+
+ /* The mock systemd is told to start the service. */
+ while (f->systemd_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->systemd_message;
+ f->systemd_message = NULL;
+ assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ "org.freedesktop.systemd1.Activator", "ActivationRequest", "s",
+ "org.freedesktop.systemd1");
+ dbus_message_unref (m);
+ m = NULL;
+
+ /* The activatable service connects and gets its name. */
+ f->activated = test_connect_to_bus (f->ctx, f->address);
+ if (!dbus_connection_add_filter (f->activated, activated_filter,
+ f, NULL))
+ g_error ("OOM");
+ f->activated_filter_added = TRUE;
+ f->activated_name = dbus_bus_get_unique_name (f->activated);
+ take_well_known_name (f, f->activated, config->bus_name);
+
+ /* The message is delivered to the activatable service. */
+ while (f->activated_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->activated_message;
+ f->activated_message = NULL;
+ assert_method_call (m, f->caller_name, config->bus_name, "/foo",
+ "com.example.bar", "Activate", "");
+
+ /* The activatable service sends back a reply. */
+ send_reply = dbus_message_new_method_return (m);
+
+ if (send_reply == NULL ||
+ !dbus_connection_send (f->activated, send_reply, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (send_reply);
+ send_reply = NULL;
+ dbus_message_unref (m);
+ m = NULL;
+
+ /* The caller receives the reply. */
+ while (reply == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ assert_method_reply (reply, f->activated_name, f->caller_name, "");
+ dbus_message_unref (reply);
+ reply = NULL;
+}
+
static void
teardown (Fixture *f,
gconstpointer context G_GNUC_UNUSED)
@@ -691,26 +1038,105 @@ teardown (Fixture *f,
f->activated = NULL;
}
- test_kill_pid (f->daemon_pid);
- g_spawn_close_pid (f->daemon_pid);
- test_main_context_unref (f->ctx);
+ if (f->daemon_pid != 0)
+ {
+ test_kill_pid (f->daemon_pid);
+ g_spawn_close_pid (f->daemon_pid);
+ }
+
+ if (f->ctx != NULL)
+ test_main_context_unref (f->ctx);
+
g_free (f->address);
+
+ if (f->transient_service_file != NULL)
+ {
+ test_remove_if_exists (f->transient_service_file);
+ g_free (f->transient_service_file);
+ }
+
+ if (f->tmp_runtime_dir != NULL)
+ {
+ gchar *dbus1 = g_build_filename (f->tmp_runtime_dir, "dbus-1", NULL);
+ gchar *services = g_build_filename (dbus1, "services", NULL);
+
+ test_rmdir_if_exists (services);
+ test_rmdir_if_exists (dbus1);
+ test_rmdir_if_exists (f->tmp_runtime_dir);
+
+ g_free (f->tmp_runtime_dir);
+ g_free (dbus1);
+ g_free (services);
+ }
}
+static const Config deny_send_tests[] =
+{
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION)
+ { "com.example.SendDeniedByAppArmorLabel" },
+ { "com.example.SendDeniedByNonexistentAppArmorLabel" },
+ { "com.example.SendDeniedByAppArmorName" },
+#endif
+ { "com.example.SendDenied" }
+};
+
+static const Config deny_receive_tests[] =
+{
+#if defined(DBUS_TEST_APPARMOR_ACTIVATION)
+ { "com.example.ReceiveDeniedByAppArmorLabel" },
+#endif
+ { "com.example.ReceiveDenied" }
+};
+
+static const Config transient_service_later =
+{
+ "com.example.TransientActivatable1",
+ FLAG_NONE
+};
+
+static const Config transient_service_in_advance =
+{
+ "com.example.TransientActivatable1",
+ FLAG_EARLY_TRANSIENT_SERVICE
+};
+
int
main (int argc,
char **argv)
{
+ gsize i;
+
test_init (&argc, &argv);
g_test_add ("/sd-activation/activation", Fixture, NULL,
setup, test_activation, teardown);
g_test_add ("/sd-activation/uae", Fixture, NULL,
setup, test_uae, teardown);
- g_test_add ("/sd-activation/deny-send", Fixture, NULL,
- setup, test_deny_send, teardown);
- g_test_add ("/sd-activation/deny-receive", Fixture, NULL,
- setup, test_deny_receive, teardown);
+
+ for (i = 0; i < G_N_ELEMENTS (deny_send_tests); i++)
+ {
+ gchar *name = g_strdup_printf ("/sd-activation/deny-send/%s",
+ deny_send_tests[i].bus_name);
+
+ g_test_add (name, Fixture, &deny_send_tests[i],
+ setup, test_deny_send, teardown);
+ g_free (name);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (deny_receive_tests); i++)
+ {
+ gchar *name = g_strdup_printf ("/sd-activation/deny-receive/%s",
+ deny_receive_tests[i].bus_name);
+
+ g_test_add (name, Fixture, &deny_receive_tests[i],
+ setup, test_deny_receive, teardown);
+ g_free (name);
+ }
+
+ g_test_add ("/sd-activation/transient-services/later", Fixture,
+ &transient_service_later, setup, test_transient_services, teardown);
+ g_test_add ("/sd-activation/transient-services/in-advance", Fixture,
+ &transient_service_in_advance, setup, test_transient_services, teardown);
return g_test_run ();
}
diff --git a/test/shell-test.c b/test/shell-test.c
index 61280d68..794757f3 100644
--- a/test/shell-test.c
+++ b/test/shell-test.c
@@ -25,25 +25,42 @@ test_command_line_internal (dbus_bool_t should_work,
DBusList *list = NULL, *node;
DBusError error;
- _dbus_list_append (&list, (char *)arg1);
+ if (!_dbus_list_append (&list, (char *)arg1))
+ return FALSE;
+
do
{
tmp = va_arg (var_args, char *);
if (!tmp)
break;
- _dbus_list_append (&list, tmp);
+ if (!_dbus_list_append (&list, tmp))
+ {
+ _dbus_list_clear (&list);
+ return FALSE;
+ }
} while (tmp);
original_argc = _dbus_list_get_length (&list);
original_argv = dbus_new (char *, original_argc);
- _dbus_string_init (&str);
+ if (!_dbus_string_init (&str))
+ {
+ _dbus_list_clear (&list);
+ dbus_free (original_argv);
+ return FALSE;
+ }
+
for (i = 0, node = _dbus_list_get_first_link (&list); i < original_argc && node;
i++, node = _dbus_list_get_next_link (&list, node))
{
original_argv[i] = node->data;
- if (i > 0)
- _dbus_string_append_byte (&str, ' ');
- _dbus_string_append (&str, original_argv[i]);
+ if ((i > 0 && !_dbus_string_append_byte (&str, ' ')) ||
+ !_dbus_string_append (&str, original_argv[i]))
+ {
+ _dbus_list_clear (&list);
+ dbus_free (original_argv);
+ _dbus_string_free (&str);
+ return FALSE;
+ }
}
_dbus_list_clear (&list);
@@ -57,6 +74,7 @@ test_command_line_internal (dbus_bool_t should_work,
should_work ? "" : " (as expected)",
error.message ? error.message : "");
dbus_free (original_argv);
+ _dbus_string_free (&str);
return !should_work;
}
else
@@ -154,7 +172,7 @@ main (int argc, char **argv)
test_command_line ("/opt/gnome/bin/service-start", NULL);
test_command_line ("grep", "-l", "-r", "-i", "'whatever'", "files*.c", NULL);
test_command_line ("/home/boston/johnp/devel-local/dbus/test/test-segfault", NULL);
- test_command_line ("ls", "-l", "-a", "--colors", _dbus_get_tmpdir(), NULL);
+ test_command_line ("ls", "-l", "-a", "--colors", NULL);
test_command_line ("rsync-to-server", NULL);
test_command_line ("test-segfault", "--no-segfault", NULL);
test_command_line ("evolution", "mailto:pepe@cuco.com", NULL);
diff --git a/test/spawn-test.c b/test/spawn-test.c
index 723a4889..a12c869f 100644
--- a/test/spawn-test.c
+++ b/test/spawn-test.c
@@ -16,7 +16,7 @@ main (int argc, char **argv)
{
char **argv_copy;
int i;
- DBusError error;
+ DBusError error = DBUS_ERROR_INIT;
if (argc < 2)
{
@@ -30,7 +30,9 @@ main (int argc, char **argv)
argv_copy [i] = argv[i + 1];
argv_copy[argc - 1] = NULL;
- if (!_dbus_spawn_async_with_babysitter (NULL, argv_copy[0], argv_copy, NULL, setup_func, NULL, &error))
+ if (!_dbus_spawn_async_with_babysitter (NULL, argv_copy[0], argv_copy, NULL,
+ DBUS_SPAWN_NONE, setup_func, NULL,
+ &error))
{
fprintf (stderr, "Could not launch application: \"%s\"\n",
error.message);
diff --git a/test/test-apparmor-activation.sh b/test/test-apparmor-activation.sh
new file mode 100644
index 00000000..ffc12534
--- /dev/null
+++ b/test/test-apparmor-activation.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+# Copyright © 2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -e
+
+if [ "x$(id -u)" != "x0" ]; then
+ echo "1..0 # SKIP - this test can only be run as root"
+ exit 0
+fi
+
+if [ -z "$DBUS_TEST_EXEC" ]; then
+ DBUS_TEST_EXEC="$(dirname "$0")"
+ if ! [ -x "$DBUS_TEST_EXEC/test-apparmor-activation" ]; then
+ echo "1..0 # SKIP - executable not found and DBUS_TEST_EXEC not set"
+ exit 0
+ fi
+fi
+
+if [ -z "$DBUS_TEST_DATA" ]; then
+ DBUS_TEST_DATA="$DBUS_TEST_EXEC/data"
+ if ! [ -e "$DBUS_TEST_DATA/dbus-installed-tests.aaprofile" ]; then
+ echo "1..0 # SKIP - required data not found and DBUS_TEST_DATA not set"
+ exit 0
+ fi
+fi
+
+echo "# Attempting to load AppArmor profiles"
+if ! apparmor_parser --skip-cache --replace \
+ "$DBUS_TEST_DATA/dbus-installed-tests.aaprofile"; then
+ echo "1..0 # SKIP - unable to load AppArmor profiles"
+ exit 0
+fi
+
+exec "$DBUS_TEST_EXEC/test-apparmor-activation" --tap "$@"
+
+# vim:set sts=4 sw=4 et:
diff --git a/test/test-dbus-daemon-fork.sh b/test/test-dbus-daemon-fork.sh
new file mode 100755
index 00000000..1a7175de
--- /dev/null
+++ b/test/test-dbus-daemon-fork.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+# Copyright © 2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -e
+
+export DBUS_DEBUG_OUTPUT=1
+echo "# dbus-daemon binary: ${DBUS_TEST_DAEMON:=dbus-daemon}"
+echo "# dbus-send binary: ${DBUS_TEST_DBUS_SEND:=dbus-send}"
+
+if test -n "$DBUS_TEST_DATA"; then
+ echo "# test data: $DBUS_TEST_DATA"
+ config="--config-file=$DBUS_TEST_DATA/valid-config-files/session.conf"
+elif test -n "$DBUS_TEST_DATADIR"; then
+ echo "# datadir: $DBUS_TEST_DATADIR"
+ config="--config-file=$DBUS_TEST_DATADIR/dbus-1/session.conf"
+else
+ echo "# using standard session bus configuration"
+ config="--session"
+fi
+
+if ! workdir="$(mktemp -d)"; then
+ echo "1..0 # SKIP - mktemp -d doesn't work"
+ exit 0
+fi
+
+echo "1..3"
+
+unset DBUS_SESSION_BUS_ADDRESS
+unset DBUS_SESSION_BUS_PID
+rm -f "$workdir"/address "$workdir"/pid
+
+${DBUS_TEST_DAEMON} --fork --print-address=8 --print-pid=9 "$config" \
+ 8>"$workdir/address" 9>"$workdir/pid"
+
+export DBUS_SESSION_BUS_ADDRESS="$(cat "$workdir"/address)"
+test -n "$DBUS_SESSION_BUS_ADDRESS"
+DBUS_SESSION_BUS_PID="$(cat "$workdir"/pid)"
+kill -0 "$DBUS_SESSION_BUS_PID"
+
+${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+kill "$DBUS_SESSION_BUS_PID"
+
+echo "ok 1 - normal dbus-daemon"
+
+unset DBUS_SESSION_BUS_ADDRESS
+unset DBUS_SESSION_BUS_PID
+rm -f "$workdir"/address "$workdir"/pid
+
+${DBUS_TEST_DAEMON} --fork --print-address=8 --print-pid=9 "$config" \
+ 8>"$workdir/address" 9>"$workdir/pid" <&-
+
+export DBUS_SESSION_BUS_ADDRESS="$(cat "$workdir"/address)"
+test -n "$DBUS_SESSION_BUS_ADDRESS"
+DBUS_SESSION_BUS_PID="$(cat "$workdir"/pid)"
+kill -0 "$DBUS_SESSION_BUS_PID"
+
+${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+kill "$DBUS_SESSION_BUS_PID"
+
+echo "ok 2 - dbus-daemon with stdin closed"
+
+unset DBUS_SESSION_BUS_ADDRESS
+unset DBUS_SESSION_BUS_PID
+rm -f "$workdir"/address "$workdir"/pid
+
+${DBUS_TEST_DAEMON} --fork --print-address=8 --print-pid=9 "$config" \
+ 8>"$workdir/address" 9>"$workdir/pid" <&- >&- 2>&-
+
+export DBUS_SESSION_BUS_ADDRESS="$(cat "$workdir"/address)"
+test -n "$DBUS_SESSION_BUS_ADDRESS"
+DBUS_SESSION_BUS_PID="$(cat "$workdir"/pid)"
+kill -0 "$DBUS_SESSION_BUS_PID"
+
+${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+kill "$DBUS_SESSION_BUS_PID"
+
+echo "ok 3 - dbus-daemon with stdin, stdout, stderr closed"
+
+rm -r "$workdir"
diff --git a/test/test-dbus-launch-eval.sh b/test/test-dbus-launch-eval.sh
new file mode 100755
index 00000000..cd960650
--- /dev/null
+++ b/test/test-dbus-launch-eval.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+# Copyright © 2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -e
+
+export DBUS_DEBUG_OUTPUT=1
+echo "# dbus-daemon binary: ${DBUS_TEST_DAEMON:=dbus-daemon}"
+echo "# dbus-launch binary: ${DBUS_TEST_DBUS_LAUNCH:=dbus-launch}"
+echo "# dbus-send binary: ${DBUS_TEST_DBUS_SEND:=dbus-send}"
+echo "# dbus-uuidgen binary: ${DBUS_TEST_DBUS_UUIDGEN:=dbus-uuidgen}"
+
+if test -n "$DBUS_TEST_DATA"; then
+ echo "# test data: $DBUS_TEST_DATA"
+ config="--config-file=$DBUS_TEST_DATA/valid-config-files/session.conf"
+elif test -n "$DBUS_TEST_DATADIR"; then
+ echo "# datadir: $DBUS_TEST_DATADIR"
+ config="--config-file=$DBUS_TEST_DATADIR/dbus-1/session.conf"
+else
+ echo "# using standard session bus configuration"
+ # add a harmless command-line argument
+ config="--sh-syntax"
+fi
+
+if ! "${DBUS_TEST_DBUS_UUIDGEN}" --get >/dev/null; then
+ if test -n "$DBUS_TEST_UNINSTALLED"; then
+ echo "1..0 # SKIP - Unable to test dbus-launch without a machine ID"
+ exit 0
+ else
+ echo "Bail out! dbus not correctly installed: no machine ID"
+ exit 1
+ fi
+fi
+
+echo "1..1"
+
+unset DBUS_SESSION_BUS_ADDRESS
+unset DBUS_SESSION_BUS_PID
+
+eval "$(${DBUS_TEST_DBUS_LAUNCH} --sh-syntax "$config")"
+
+test -n "$DBUS_SESSION_BUS_ADDRESS"
+env | grep '^DBUS_SESSION_BUS_ADDRESS='
+
+test -n "$DBUS_SESSION_BUS_PID"
+test "x$(env | grep '^DBUS_SESSION_BUS_PID=')" = "x"
+kill -0 "$DBUS_SESSION_BUS_PID"
+
+${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+kill "$DBUS_SESSION_BUS_PID"
+
+echo "ok 1 - normal dbus-launch"
diff --git a/test/test-dbus-launch-x11.sh b/test/test-dbus-launch-x11.sh
new file mode 100755
index 00000000..48c2718c
--- /dev/null
+++ b/test/test-dbus-launch-x11.sh
@@ -0,0 +1,267 @@
+#!/bin/sh
+
+# Copyright © 2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -e
+set -x
+
+export DBUS_DEBUG_OUTPUT=1
+echo "# dbus-daemon binary: ${DBUS_TEST_DAEMON:=dbus-daemon}"
+echo "# dbus-launch binary: ${DBUS_TEST_DBUS_LAUNCH:=dbus-launch}"
+echo "# dbus-monitor binary: ${DBUS_TEST_DBUS_LAUNCH:=dbus-monitor}"
+echo "# dbus-send binary: ${DBUS_TEST_DBUS_SEND:=dbus-send}"
+echo "# dbus-uuidgen binary: ${DBUS_TEST_DBUS_UUIDGEN:=dbus-uuidgen}"
+
+if test -n "$DBUS_TEST_DATA"; then
+ echo "# test data: $DBUS_TEST_DATA"
+ bus_config="--config-file=$DBUS_TEST_DATA/valid-config-files/session.conf"
+ launch_config="$bus_config"
+elif test -n "$DBUS_TEST_DATADIR"; then
+ echo "# datadir: $DBUS_TEST_DATADIR"
+ bus_config="--config-file=$DBUS_TEST_DATADIR/dbus-1/session.conf"
+ launch_config="$bus_config"
+else
+ echo "# using standard session bus configuration"
+ bus_config="--session"
+ # dbus-launch doesn't accept --session so add a harmless command-line
+ # argument
+ launch_config="--sh-syntax"
+fi
+
+if ! "${DBUS_TEST_DBUS_UUIDGEN}" --get >/dev/null; then
+ if test -n "$DBUS_TEST_UNINSTALLED"; then
+ echo "1..0 # SKIP - Unable to test dbus-launch without a machine ID"
+ exit 0
+ else
+ echo "Bail out! dbus not correctly installed: no machine ID"
+ exit 1
+ fi
+fi
+
+if ! workdir="$(mktemp -d)"; then
+ echo "1..0 # SKIP - mktemp -d doesn't work"
+ exit 0
+fi
+
+if ! xvfb-run --auto-servernum true; then
+ echo "1..0 # SKIP - xvfb-run doesn't work"
+ exit 0
+fi
+
+test_num=0
+x_session_pid=
+unset DISPLAY
+unset XAUTHORITY
+
+start_xvfb () {
+ rm -f "$workdir/display"
+ rm -f "$workdir/ready"
+ rm -f "$workdir/x-session-pid"
+ rm -f "$workdir/xauthority"
+ rm -f "$workdir/xvfb-done"
+
+ # Run an X session in the background for up to 5 minutes.
+ (
+ set +e
+ xvfb-run --auto-servernum \
+ sh -c 'echo "$$" > "$1/x-session-pid"; echo "$XAUTHORITY" > "$1/xauthority"; echo "$DISPLAY" > "$1/display"; touch "$1/ready"; exec sleep 300' \
+ sh "$workdir"
+ touch "$workdir/xvfb-done"
+ ) &
+
+ tries=0
+ while ! [ -e "$workdir/ready" ]; do
+ if [ $tries -ge 10 ]; then
+ echo "# Failed to start xvfb-run within $tries seconds"
+ exit 1
+ fi
+ tries=$(($tries + 1))
+ sleep 1
+ done
+
+ x_session_pid="$(cat "$workdir/x-session-pid")"
+ export DISPLAY="$(cat "$workdir/display")"
+ export XAUTHORITY="$(cat "$workdir/xauthority")"
+ kill -0 "$x_session_pid"
+}
+
+test_disconnection () {
+ rm -f "$workdir/disconnected"
+ (
+ set +e
+ ${DBUS_TEST_DBUS_MONITOR} > "$workdir/dbus-monitor.log" 2>&1
+ touch "$workdir/disconnected"
+ ) &
+
+ kill "$x_session_pid"
+
+ tries=0
+ while ! [ -e "$workdir/disconnected" ]; do
+ if [ $tries -ge 10 ]; then
+ echo "# dbus-monitor was not disconnected within $tries seconds" >&2
+ exit 1
+ fi
+ tries=$(($tries + 1))
+ sleep 1
+ done
+
+ tries=0
+ while ! [ -e "$workdir/xvfb-done" ]; do
+ if [ $tries -ge 10 ]; then
+ echo "# xvfb-run did not exit within $tries seconds" >&2
+ exit 1
+ fi
+ tries=$(($tries + 1))
+ sleep 1
+ done
+}
+
+test_exit_with_x11 () {
+ arg="$1"
+ unset DBUS_SESSION_BUS_ADDRESS
+ unset DBUS_SESSION_BUS_PID
+ unset DBUS_SESSION_BUS_WINDOWID
+
+ start_xvfb
+ eval "$($DBUS_TEST_DBUS_LAUNCH --sh-syntax "$arg" "$launch_config" </dev/null)"
+
+ test -n "$DBUS_SESSION_BUS_ADDRESS"
+ env | grep '^DBUS_SESSION_BUS_ADDRESS='
+
+ test -n "$DBUS_SESSION_BUS_PID"
+ test "x$(env | grep '^DBUS_SESSION_BUS_PID=')" = "x"
+ kill -0 "$DBUS_SESSION_BUS_PID"
+
+ test -n "$DBUS_SESSION_BUS_WINDOWID"
+ test "x$(env | grep '^DBUS_SESSION_BUS_WINDOWID=')" = "x"
+
+ ${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+ test_disconnection
+
+ test_num=$(($test_num + 1))
+ echo "ok ${test_num} - dbus-launch $arg"
+}
+
+test_autolaunch () {
+ unset DBUS_SESSION_BUS_ADDRESS
+ unset DBUS_SESSION_BUS_PID
+ unset DBUS_SESSION_BUS_WINDOWID
+ unset XDG_RUNTIME_DIR
+ fake_uuid="ffffffffffffffffffffffffffffffff"
+
+ start_xvfb
+ eval "$($DBUS_TEST_DBUS_LAUNCH --sh-syntax --autolaunch=${fake_uuid} "$launch_config" </dev/null)"
+
+ test -n "$DBUS_SESSION_BUS_ADDRESS"
+ env | grep '^DBUS_SESSION_BUS_ADDRESS='
+
+ test -n "$DBUS_SESSION_BUS_PID"
+ test "x$(env | grep '^DBUS_SESSION_BUS_PID=')" = "x"
+ kill -0 "$DBUS_SESSION_BUS_PID"
+
+ test -n "$DBUS_SESSION_BUS_WINDOWID"
+ test "x$(env | grep '^DBUS_SESSION_BUS_WINDOWID=')" = "x"
+
+ # It is idempotent
+ old_address="$DBUS_SESSION_BUS_ADDRESS"
+ old_pid="$DBUS_SESSION_BUS_PID"
+ old_window="$DBUS_SESSION_BUS_WINDOWID"
+ eval "$($DBUS_TEST_DBUS_LAUNCH --sh-syntax --autolaunch=${fake_uuid} "$launch_config" </dev/null)"
+ test "$DBUS_SESSION_BUS_ADDRESS" = "$old_address"
+ test "$DBUS_SESSION_BUS_PID" = "$old_pid"
+ test "$DBUS_SESSION_BUS_WINDOWID" = "$old_window"
+
+ ${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+ test_disconnection
+
+ test_num=$(($test_num + 1))
+ echo "ok ${test_num} - dbus-launch --autolaunch"
+}
+
+test_xdg_runtime_dir () {
+ unset DBUS_SESSION_BUS_ADDRESS
+ unset DBUS_SESSION_BUS_PID
+ unset DBUS_SESSION_BUS_WINDOWID
+ export XDG_RUNTIME_DIR="$workdir"
+ fake_uuid="ffffffffffffffffffffffffffffffff"
+
+ if echo "$workdir" | grep '[^-0-9A-Za-z_/.]'; then
+ test_num=$(($test_num + 1))
+ echo "ok ${test_num} # SKIP - $workdir would need escaping"
+ return
+ fi
+
+ ${DBUS_TEST_DAEMON} "$bus_config" --address="unix:path=$XDG_RUNTIME_DIR/bus" --print-pid=9 --fork 9>"$workdir/bus-pid"
+ bus_pid="$(cat "$workdir/bus-pid")"
+ kill -0 "$bus_pid"
+
+ start_xvfb
+ eval "$($DBUS_TEST_DBUS_LAUNCH --sh-syntax --autolaunch=${fake_uuid} "$launch_config" </dev/null)"
+
+ env | grep '^DBUS_SESSION_BUS_ADDRESS='
+ test "$DBUS_SESSION_BUS_ADDRESS" = "unix:path=$XDG_RUNTIME_DIR/bus"
+
+ # When dbus-launch picks up the address from XDG_RUNTIME_DIR/bus, it
+ # doesn't know the pid
+ test -z "$DBUS_SESSION_BUS_PID"
+
+ # It still knows which window it stashed the information in
+ test -n "$DBUS_SESSION_BUS_WINDOWID"
+ test "x$(env | grep '^DBUS_SESSION_BUS_WINDOWID=')" = "x"
+
+ ${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+ kill "$x_session_pid"
+
+ tries=0
+ while ! [ -e "$workdir/xvfb-done" ]; do
+ if [ $tries -ge 10 ]; then
+ echo "# xvfb-run did not exit within $tries seconds" >&2
+ exit 1
+ fi
+ tries=$(($tries + 1))
+ sleep 1
+ done
+
+ # dbus-launch has gone but the dbus-daemon is still alive
+ ${DBUS_TEST_DBUS_SEND} --session --dest=org.freedesktop.DBus \
+ --type=method_call --print-reply / org.freedesktop.DBus.ListNames >&2
+
+ kill "$bus_pid"
+
+ test_num=$(($test_num + 1))
+ echo "ok ${test_num} - dbus-launch --autolaunch with XDG_RUNTIME_DIR"
+}
+
+echo "1..4"
+test_exit_with_x11 --exit-with-session
+test_exit_with_x11 --exit-with-x11
+test_autolaunch
+test_xdg_runtime_dir
+
+# vim:set sw=4 sts=4 et:
diff --git a/test/test-names.c b/test/test-names.c
index 27366350..95e42865 100644
--- a/test/test-names.c
+++ b/test/test-names.c
@@ -3,6 +3,8 @@
static DBusLoop *loop;
+static void die (const char *message) _DBUS_GNUC_NORETURN;
+
static void
die (const char *message)
{
diff --git a/test/test-segfault.c b/test/test-segfault.c
index c062ce1c..8517dd6c 100644
--- a/test/test-segfault.c
+++ b/test/test-segfault.c
@@ -13,12 +13,39 @@
#include <sys/prctl.h>
#endif
+#ifdef DBUS_WIN
+#include <stdio.h>
+#include <windows.h>
+
+#include <dbus/dbus-macros.h>
+
+int exception_handler (LPEXCEPTION_POINTERS p) _DBUS_GNUC_NORETURN;
+
+/* Explicit Windows exception handlers needed to supress OS popups */
+int
+exception_handler(LPEXCEPTION_POINTERS p)
+{
+ fprintf(stderr, "test-segfault: raised fatal exception as intended\n");
+ ExitProcess(0xc0000005);
+}
+#endif
+
int
main (int argc, char **argv)
{
char *p;
-#if HAVE_SETRLIMIT
+#ifdef DBUS_WIN
+ /* Disable Windows popup dialog when an app crashes so that app quits
+ * immediately with error code instead of waiting for user to dismiss
+ * the dialog. */
+ DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
+ SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
+ /* Disable "just in time" debugger */
+ SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&exception_handler);
+#endif
+
+#ifdef HAVE_SETRLIMIT
/* No core dumps please, we know we crashed. */
struct rlimit r = { 0, };
diff --git a/test/test-service.c b/test/test-service.c
index c0bd2c60..b500af31 100644
--- a/test/test-service.c
+++ b/test/test-service.c
@@ -19,6 +19,8 @@ quit (void)
}
}
+static void die (const char *message) _DBUS_GNUC_NORETURN;
+
static void
die (const char *message)
{
@@ -90,9 +92,8 @@ check_hello_from_self_reply (DBusPendingCall *pcall,
dbus_message_unref (echo_reply);
}
- else if (type == DBUS_MESSAGE_TYPE_ERROR)
+ else if (dbus_set_error_from_message (&error, reply))
{
- dbus_set_error_from_message (&error, reply);
printf ("Error type in reply: %s\n", error.message);
if (strcmp (error.name, DBUS_ERROR_NO_MEMORY) != 0)
@@ -112,7 +113,7 @@ check_hello_from_self_reply (DBusPendingCall *pcall,
dbus_error_free (&error);
}
else
- _dbus_assert_not_reached ("Unexpected message received\n");
+ _dbus_assert_not_reached ("Unexpected message received");
hello_from_self_reply_received = TRUE;
diff --git a/test/test-shell-service.c b/test/test-shell-service.c
index 32a88329..2eaccc1d 100644
--- a/test/test-shell-service.c
+++ b/test/test-shell-service.c
@@ -22,6 +22,8 @@ quit (void)
}
}
+static void die (const char *message) _DBUS_GNUC_NORETURN;
+
static void
die (const char *message)
{
diff --git a/test/test-utils-glib.c b/test/test-utils-glib.c
index e0849771..28a36848 100644
--- a/test/test-utils-glib.c
+++ b/test/test-utils-glib.c
@@ -27,15 +27,17 @@
#include <config.h>
#include "test-utils-glib.h"
+#include <errno.h>
#include <string.h>
#ifdef DBUS_WIN
# include <io.h>
# include <windows.h>
#else
-# include <errno.h>
+# include <netdb.h>
# include <signal.h>
# include <unistd.h>
+# include <sys/socket.h>
# include <sys/types.h>
# include <pwd.h>
#endif
@@ -95,12 +97,14 @@ spawn_dbus_daemon (const gchar *binary,
const gchar *configuration,
const gchar *listen_address,
TestUser user,
+ const gchar *runtime_dir,
GPid *daemon_pid)
{
GError *error = NULL;
GString *address;
gint address_fd;
GPtrArray *argv;
+ gchar **envp;
#ifdef DBUS_UNIX
const struct passwd *pwd = NULL;
#endif
@@ -149,6 +153,8 @@ spawn_dbus_daemon (const gchar *binary,
break;
+ case TEST_USER_ME:
+ /* cannot get here, fall through */
default:
g_assert_not_reached ();
}
@@ -158,6 +164,11 @@ spawn_dbus_daemon (const gchar *binary,
#endif
}
+ envp = g_get_environ ();
+
+ if (runtime_dir != NULL)
+ envp = g_environ_setenv (envp, "XDG_RUNTIME_DIR", runtime_dir, TRUE);
+
argv = g_ptr_array_new_with_free_func (g_free);
g_ptr_array_add (argv, g_strdup (binary));
g_ptr_array_add (argv, g_strdup (configuration));
@@ -175,7 +186,7 @@ spawn_dbus_daemon (const gchar *binary,
g_spawn_async_with_pipes (NULL, /* working directory */
(gchar **) argv->pdata,
- NULL, /* envp */
+ envp,
G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
#ifdef DBUS_UNIX
child_setup, (gpointer) pwd,
@@ -190,6 +201,7 @@ spawn_dbus_daemon (const gchar *binary,
g_assert_no_error (error);
g_ptr_array_free (argv, TRUE);
+ g_strfreev (envp);
address = g_string_new (NULL);
@@ -228,6 +240,7 @@ spawn_dbus_daemon (const gchar *binary,
gchar *
test_get_dbus_daemon (const gchar *config_file,
TestUser user,
+ const gchar *runtime_dir,
GPid *daemon_pid)
{
gchar *dbus_daemon;
@@ -296,7 +309,7 @@ test_get_dbus_daemon (const gchar *config_file,
else
{
address = spawn_dbus_daemon (dbus_daemon, arg,
- listen_address, user, daemon_pid);
+ listen_address, user, runtime_dir, daemon_pid);
}
g_free (dbus_daemon);
@@ -321,7 +334,9 @@ test_connect_to_bus (TestMainContext *ctx,
g_assert (ok);
g_assert (dbus_bus_get_unique_name (conn) != NULL);
- test_connection_setup (ctx, conn);
+ if (ctx != NULL)
+ test_connection_setup (ctx, conn);
+
return conn;
}
@@ -400,18 +415,39 @@ test_connect_to_bus_as_user (TestMainContext *ctx,
case TEST_USER_ME:
return test_connect_to_bus (ctx, address);
- default:
+ case TEST_USER_ROOT:
+ case TEST_USER_MESSAGEBUS:
+ case TEST_USER_OTHER:
g_test_skip ("setresuid() not available, or unsure about "
"credentials-passing semantics on this platform");
return NULL;
+
+ default:
+ g_return_val_if_reached (NULL);
}
#endif
}
+static void
+pid_died (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ gboolean *result = user_data;
+
+ g_assert (result != NULL);
+ g_assert (!*result);
+ *result = TRUE;
+}
+
void
test_kill_pid (GPid pid)
{
+ gint died = FALSE;
+
+ g_child_watch_add (pid, pid_died, &died);
+
#ifdef DBUS_WIN
if (pid != NULL)
TerminateProcess (pid, 1);
@@ -419,41 +455,60 @@ test_kill_pid (GPid pid)
if (pid > 0)
kill (pid, SIGTERM);
#endif
+
+ while (!died)
+ g_main_context_iteration (NULL, TRUE);
}
static gboolean
time_out (gpointer data)
{
- g_error ("timed out");
+ puts ("Bail out! Test timed out (GLib main loop timeout callback reached)");
+ fflush (stdout);
+ abort ();
return FALSE;
}
#ifdef G_OS_UNIX
+static void wrap_abort (int signal) _DBUS_GNUC_NORETURN;
+
static void
wrap_abort (int signal)
{
+ /* We might be halfway through writing out something else, so force this
+ * onto its own line */
+ const char message [] = "\nBail out! Test timed out (SIGALRM received)\n";
+
+ if (write (STDOUT_FILENO, message, sizeof (message) - 1) <
+ (ssize_t) sizeof (message) - 1)
+ {
+ /* ignore short write - what would we do about it? */
+ }
+
abort ();
}
#endif
-void
-test_init (int *argcp, char ***argvp)
+static void
+set_timeout (guint factor)
{
- g_test_init (argcp, argvp, NULL);
- g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+ static guint timeout = 0;
/* Prevent tests from hanging forever. This is intended to be long enough
* that any reasonable regression test on any reasonable hardware would
* have finished. */
#define TIMEOUT 60
- g_timeout_add_seconds (TIMEOUT, time_out, NULL);
+ if (timeout != 0)
+ g_source_remove (timeout);
+
+ timeout = g_timeout_add_seconds (TIMEOUT * factor, time_out, NULL);
#ifdef G_OS_UNIX
/* The GLib main loop might not be running (we don't use it in every
* test). Die with SIGALRM shortly after if necessary. */
- alarm (TIMEOUT + 10);
+ alarm ((TIMEOUT * factor) + 10);
- /* Get a core dump from the SIGALRM. */
+ /* Get a log message and a core dump from the SIGALRM. */
{
struct sigaction act = { };
@@ -465,8 +520,185 @@ test_init (int *argcp, char ***argvp)
}
void
+test_init (int *argcp, char ***argvp)
+{
+ g_test_init (argcp, argvp, NULL);
+ g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+ set_timeout (1);
+}
+
+static void
+report_and_destroy (gpointer p)
+{
+ GTimer *timer = p;
+
+ g_test_message ("Time since timeout reset %p: %.3f seconds",
+ timer, g_timer_elapsed (timer, NULL));
+ g_timer_destroy (timer);
+}
+
+void
+test_timeout_reset (guint factor)
+{
+ GTimer *timer = g_timer_new ();
+
+ g_test_message ("Resetting test timeout (reference: %p; factor: %u)",
+ timer, factor);
+ set_timeout (factor);
+
+ g_test_queue_destroy (report_and_destroy, timer);
+}
+
+void
test_progress (char symbol)
{
if (g_test_verbose () && isatty (1))
g_print ("%c", symbol);
}
+
+/*
+ * Delete @path, with a retry loop if the system call is interrupted by
+ * an async signal. If @path does not exist, ignore; otherwise, it is
+ * required to be a non-directory.
+ */
+void
+test_remove_if_exists (const gchar *path)
+{
+ while (g_remove (path) != 0)
+ {
+ int saved_errno = errno;
+
+ if (saved_errno == ENOENT)
+ return;
+
+#ifdef G_OS_UNIX
+ if (saved_errno == EINTR)
+ continue;
+#endif
+
+ g_error ("Unable to remove file \"%s\": %s", path,
+ g_strerror (saved_errno));
+ }
+}
+
+/*
+ * Delete empty directory @path, with a retry loop if the system call is
+ * interrupted by an async signal. @path is required to exist.
+ */
+void
+test_rmdir_must_exist (const gchar *path)
+{
+ while (g_remove (path) != 0)
+ {
+ int saved_errno = errno;
+
+#ifdef G_OS_UNIX
+ if (saved_errno == EINTR)
+ continue;
+#endif
+
+ g_error ("Unable to remove directory \"%s\": %s", path,
+ g_strerror (saved_errno));
+ }
+}
+
+/*
+ * Delete empty directory @path, with a retry loop if the system call is
+ * interrupted by an async signal. If @path does not exist, ignore.
+ */
+void
+test_rmdir_if_exists (const gchar *path)
+{
+ while (g_remove (path) != 0)
+ {
+ int saved_errno = errno;
+
+ if (saved_errno == ENOENT)
+ return;
+
+#ifdef G_OS_UNIX
+ if (saved_errno == EINTR)
+ continue;
+#endif
+
+ g_error ("Unable to remove directory \"%s\": %s", path,
+ g_strerror (saved_errno));
+ }
+}
+
+/*
+ * Create directory @path, with a retry loop if the system call is
+ * interrupted by an async signal.
+ */
+void
+test_mkdir (const gchar *path,
+ gint mode)
+{
+ while (g_mkdir (path, mode) != 0)
+ {
+ int saved_errno = errno;
+
+#ifdef G_OS_UNIX
+ if (saved_errno == EINTR)
+ continue;
+#endif
+
+ g_error ("Unable to create directory \"%s\": %s", path,
+ g_strerror (saved_errno));
+ }
+}
+
+gboolean
+test_check_tcp_works (void)
+{
+#ifdef DBUS_UNIX
+ /* In pathological container environments, we might not have a
+ * working 127.0.0.1 */
+ int res;
+ struct addrinfo *addrs = NULL;
+ struct addrinfo hints;
+ int saved_errno;
+
+ _DBUS_ZERO (hints);
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+ hints.ai_flags = AI_ADDRCONFIG;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ res = getaddrinfo ("127.0.0.1", "0", &hints, &addrs);
+ saved_errno = errno;
+
+ if (res != 0)
+ {
+ const gchar *system_message;
+ gchar *skip_message;
+
+#ifdef EAI_SYSTEM
+ if (res == EAI_SYSTEM)
+ system_message = g_strerror (saved_errno);
+ else
+#endif
+ system_message = gai_strerror (res);
+
+ skip_message = g_strdup_printf ("Name resolution does not work here: "
+ "getaddrinfo(\"127.0.0.1\", \"0\", "
+ "{flags=ADDRCONFIG, family=INET,"
+ "socktype=STREAM, protocol=TCP}): "
+ "%s",
+ system_message);
+ g_test_skip (skip_message);
+ free (skip_message);
+ }
+
+ if (addrs != NULL)
+ freeaddrinfo (addrs);
+
+ return (res == 0);
+#else
+ /* Assume that on Windows, TCP always works */
+ return TRUE;
+#endif
+}
diff --git a/test/test-utils-glib.h b/test/test-utils-glib.h
index acacee0a..e62121cb 100644
--- a/test/test-utils-glib.h
+++ b/test/test-utils-glib.h
@@ -69,6 +69,7 @@ void _test_assert_no_error (const DBusError *e,
gchar *test_get_dbus_daemon (const gchar *config_file,
TestUser user,
+ const gchar *runtime_dir,
GPid *daemon_pid);
DBusConnection *test_connect_to_bus (TestMainContext *ctx,
@@ -83,12 +84,28 @@ void test_init (int *argcp, char ***argvp);
void test_progress (char symbol);
-#if !GLIB_CHECK_VERSION (2, 38, 0)
-#define g_test_skip(s) my_test_skip (s)
-static inline void my_test_skip (const gchar *s)
+void test_remove_if_exists (const gchar *path);
+void test_rmdir_must_exist (const gchar *path);
+void test_rmdir_if_exists (const gchar *path);
+void test_mkdir (const gchar *path, gint mode);
+
+void test_timeout_reset (guint factor);
+
+#if !GLIB_CHECK_VERSION(2, 44, 0)
+#define g_steal_pointer(x) backported_g_steal_pointer (x)
+/* A simplified version of g_steal_pointer without type-safety. */
+static inline gpointer
+backported_g_steal_pointer (gpointer pointer_to_pointer)
{
- g_test_message ("SKIP: %s", s);
+ gpointer *pp = pointer_to_pointer;
+ gpointer ret;
+
+ ret = *pp;
+ *pp = NULL;
+ return ret;
}
#endif
+gboolean test_check_tcp_works (void);
+
#endif
diff --git a/test/test-utils.c b/test/test-utils.c
index cb6cf1fb..3f4d1959 100644
--- a/test/test-utils.c
+++ b/test/test-utils.c
@@ -151,6 +151,8 @@ test_connection_setup (TestMainContext *ctx,
return FALSE;
}
+static void die (const char *message) _DBUS_GNUC_NORETURN;
+
static void
die (const char *message)
{
diff --git a/test/thread-blocking.c b/test/thread-blocking.c
new file mode 100644
index 00000000..e814dec3
--- /dev/null
+++ b/test/thread-blocking.c
@@ -0,0 +1,299 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Regression test for fd.o #102839: blocking on pending calls in threads
+ *
+ * Copyright © 2018 KPIT Technologies Ltd.
+ * Copyright © 2018 Manish Narang <manrock007@gmail.com>
+ * Copyright © 2018 Collabora Ltd.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <config.h>
+
+#include <dbus/dbus.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "test-utils-glib.h"
+
+typedef struct
+{
+ DBusError e;
+ GError *ge;
+ GPid daemon_pid;
+ gchar *address;
+
+ DBusConnection *service_conn;
+ GThread *service_thread;
+ const gchar *service_name;
+
+ GThread *client_dispatcher_thread;
+ GThread **client_caller_threads;
+ DBusConnection *client_conn;
+ GMutex callers_remaining_mutex;
+ GCond callers_remaining_cond;
+ gsize callers_remaining;
+
+ gsize n_caller_threads;
+ gsize calls_per_thread;
+} Fixture;
+
+static DBusHandlerResult
+echo_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ DBusMessage *reply;
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ reply = dbus_message_new_method_return (message);
+
+ if (reply == NULL ||
+ !dbus_connection_send (connection, reply, NULL))
+ g_error ("OOM");
+
+ dbus_clear_message (&reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/*
+ * Thread function to dispatch the service connection. This function runs
+ * in its own thread, dispatching the service connection and replying to
+ * method calls from the callers, until the service connection is
+ * disconnected by the main thread.
+ */
+static gpointer
+service_thread_cb (gpointer user_data)
+{
+ Fixture *f = user_data;
+
+ /* In principle we should be able to wait indefinitely (-1) but that
+ * seems to prevent closing the connection from the main thread from
+ * having its desired effect */
+ while (dbus_connection_read_write_dispatch (f->service_conn, 1000))
+ {
+ /* Disconnected message not received; keep processing */
+ }
+
+ return NULL;
+}
+
+/*
+ * Much like service_thread_cb, but for the client connection. In a real
+ * program this would often be the main thread, running an event loop
+ * like the one provided by GLib.
+ */
+static gpointer
+client_dispatcher_thread_cb (gpointer user_data)
+{
+ Fixture *f = user_data;
+
+ /* This thread needs to yield occasionally, otherwise the caller
+ * threads won't ever get a chance to send their messages.
+ * This is not a recommended I/O pattern, but in principle it was
+ * always meant to work... */
+ while (dbus_connection_read_write_dispatch (f->client_conn, 10))
+ {
+ /* Disconnected message not received; keep processing */
+ }
+
+ return NULL;
+}
+
+/*
+ * Worker thread representing some background task. Some programs
+ * dispatch a DBusConnection in one thread (in this test that's the
+ * "client dispatcher thread"), and expect to be able to block on
+ * pending calls in other threads. This represents one of those other
+ * threads.
+ */
+static gpointer
+client_caller_thread_cb (gpointer user_data)
+{
+ Fixture *f = user_data;
+ gsize i;
+
+ for (i = 0; i < f->calls_per_thread; i++)
+ {
+ DBusMessage *call, *reply;
+ DBusError error = DBUS_ERROR_INIT;
+ gint64 time_before, time_after;
+
+ /* This deliberately isn't g_test_message() to avoid buffering
+ * issues: stderr is line-buffered */
+ if (i % 100 == 0)
+ g_printerr ("# thread %p: %" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT "\n",
+ g_thread_self (), i, f->calls_per_thread);
+
+ call = dbus_message_new_method_call (f->service_name, "/",
+ "com.example.Echo", "Echo");
+ g_assert_nonnull (call);
+
+ time_before = g_get_monotonic_time ();
+ reply = dbus_connection_send_with_reply_and_block (f->client_conn, call,
+ 30000, &error);
+ time_after = g_get_monotonic_time ();
+ test_assert_no_error (&error);
+ g_assert_nonnull (reply);
+ /* We don't expect it to have taken long - a few seconds max, even
+ * with all the other threads contending with us. If we were
+ * anywhere near the 30 second timeout then that's a failure. */
+ g_assert_cmpint (time_after - time_before, <=, 10 * G_USEC_PER_SEC);
+ dbus_clear_message (&reply);
+ dbus_clear_message (&call);
+ }
+
+ g_printerr ("# thread %p: finishing\n", g_thread_self ());
+ g_mutex_lock (&f->callers_remaining_mutex);
+ f->callers_remaining--;
+ g_cond_signal (&f->callers_remaining_cond);
+ g_mutex_unlock (&f->callers_remaining_mutex);
+
+ return NULL;
+}
+
+static void
+setup (Fixture *f,
+ gconstpointer context)
+{
+ f->ge = NULL;
+ dbus_error_init (&f->e);
+
+ f->address = test_get_dbus_daemon (NULL, TEST_USER_ME, NULL, &f->daemon_pid);
+ g_assert_nonnull (f->address);
+
+ f->service_conn = test_connect_to_bus (NULL, f->address);
+ f->service_name = dbus_bus_get_unique_name (f->service_conn);
+ f->client_conn = test_connect_to_bus (NULL, f->address);
+
+ if (!dbus_connection_add_filter (f->service_conn, echo_filter, f, NULL))
+ g_error ("OOM");
+
+ f->service_thread = g_thread_new ("service", service_thread_cb, f);
+ f->client_dispatcher_thread = g_thread_new ("client dispatcher",
+ client_dispatcher_thread_cb, f);
+}
+
+/*
+ * Assert that in the following situation:
+ *
+ * - one thread dispatches the server connection (in real life this would
+ * normally be a separate process, of course)
+ * - one thread dispatches the client connection
+ * - many threads make blocking method calls on the same client connection
+ *
+ * the caller threads are regularly dispatched, and never get blocked
+ * until their method call timeout.
+ */
+static void
+test_threads (Fixture *f,
+ gconstpointer context)
+{
+ gsize i;
+
+ g_test_bug ("102839");
+
+ if (g_test_slow ())
+ {
+ test_timeout_reset (10);
+ f->n_caller_threads = 20;
+ f->calls_per_thread = 10000;
+ }
+ else
+ {
+ test_timeout_reset (1);
+ f->n_caller_threads = 4;
+ f->calls_per_thread = 1000;
+ }
+
+ f->client_caller_threads = g_new0 (GThread *, f->n_caller_threads);
+ f->callers_remaining = f->n_caller_threads;
+
+ /* Start the caller threads off */
+
+ for (i = 0; i < f->n_caller_threads; i++)
+ {
+ gchar *name = g_strdup_printf ("client %" G_GSIZE_FORMAT, i);
+
+ f->client_caller_threads[i] = g_thread_new (name,
+ client_caller_thread_cb,
+ f);
+ }
+
+ /* Wait for all caller threads to exit */
+
+ g_mutex_lock (&f->callers_remaining_mutex);
+
+ while (f->callers_remaining > 0)
+ g_cond_wait (&f->callers_remaining_cond, &f->callers_remaining_mutex);
+
+ g_mutex_unlock (&f->callers_remaining_mutex);
+
+ for (i = 0; i < f->n_caller_threads; i++)
+ g_thread_join (g_steal_pointer (&f->client_caller_threads[i]));
+
+ /* If we haven't crashed out yet, then we're good! */
+}
+
+static void
+teardown (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ dbus_error_free (&f->e);
+ g_clear_error (&f->ge);
+
+ if (f->client_conn != NULL)
+ dbus_connection_close (f->client_conn);
+
+ if (f->service_conn != NULL)
+ {
+ dbus_connection_remove_filter (f->service_conn, echo_filter, f);
+ dbus_connection_close (f->service_conn);
+ }
+
+ /* Now that the connections have been closed, the threads will exit */
+ if (f->service_thread != NULL)
+ g_thread_join (g_steal_pointer (&f->service_thread));
+
+ if (f->client_dispatcher_thread != NULL)
+ g_thread_join (g_steal_pointer (&f->client_dispatcher_thread));
+
+ dbus_clear_connection (&f->service_conn);
+ dbus_clear_connection (&f->client_conn);
+
+ if (f->daemon_pid != 0)
+ {
+ test_kill_pid (f->daemon_pid);
+ g_spawn_close_pid (f->daemon_pid);
+ f->daemon_pid = 0;
+ }
+
+ g_free (f->address);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ test_init (&argc, &argv);
+
+ g_test_add ("/thread-blocking", Fixture, NULL, setup, test_threads,
+ teardown);
+
+ return g_test_run ();
+}
diff --git a/test/uid-permissions.c b/test/uid-permissions.c
index 57f7ec96..19a9aa46 100644
--- a/test/uid-permissions.c
+++ b/test/uid-permissions.c
@@ -60,7 +60,7 @@ setup (Fixture *f,
dbus_error_init (&f->e);
address = test_get_dbus_daemon (config ? config->config_file : NULL,
- TEST_USER_MESSAGEBUS,
+ TEST_USER_MESSAGEBUS, NULL,
&f->daemon_pid);
if (address == NULL)
diff --git a/test/unused-code-gc.py b/test/unused-code-gc.py
deleted file mode 100755
index a58597f7..00000000
--- a/test/unused-code-gc.py
+++ /dev/null
@@ -1,242 +0,0 @@
-#! /usr/bin/python
-
-import os
-import sys
-import string
-import re
-
-## hash from symbol name to list of symbols with that name,
-## where the list of symbols contains a list representing each symbol
-symbols = {}
-roots = {}
-
-def createBacklinks(name, syms):
- for s in syms:
- refs = s[2]
- for r in refs:
- ## for each ref, add ourselves as a referencer
- if symbols.has_key(r):
- targets = symbols[r]
- for t in targets:
- if name not in t[5]:
- t[5].append(name)
-
-def markSymbol(frm, name):
- if not symbols.has_key(name):
- print "%s referenced but was not in the objdump"
- syms = symbols[name]
- ## print ambiguous references unless they are internal noise like ".L129"
- if len(syms) > 1 and name[0] != '.':
- print "Reference to symbol '%s' from '%s' is ambiguous, marking all '%s'" % (name, frm, name)
- print syms
- for s in syms:
- if s[4]:
- pass ## already marked
- else:
- s[4] = 1
- refs = s[2]
- for r in refs:
- markSymbol(s[0], r)
-
-def cmpFilename(a, b):
- v = cmp(a[1], b[1])
- if v == 0:
- v = cmp(a[0], b[0])
- return v
-
-def sizeAsString(bytes):
- if bytes < 1024:
- return "%d bytes" % bytes
- elif bytes < 1024*1024:
- return "%.2gK" % (bytes / 1024.0)
- else:
- return "%.2gM" % (bytes / 1024.0 / 1024.0)
-
-def printLost():
- list = []
- filename = None
- for (name, syms) in symbols.items():
- s = syms[0] ## we always mark all or none for now
- if not s[4] and name[0] != '.': ## skip .L129 type symbols
- filename = s[3]
- if not filename:
- filename = "unknown file"
- list.append ((name, filename, s[5], s[7]))
-
- file_summaries = []
- total_unused = 0
- total_this_file = 0
- filename = None
- list.sort(cmpFilename)
- for l in list:
- next_filename = l[1]
- if next_filename != filename:
- if total_this_file > 0:
- file_summaries.append (" %s may be unused in %s" % (sizeAsString(total_this_file), filename))
- print "%s has these symbols not reachable from exported symbols:" % next_filename
- filename = next_filename
- total_this_file = 0
- print " %s %s" % (l[0], sizeAsString(l[3]))
- total_unused = total_unused + l[3]
- total_this_file = total_this_file + l[3]
- for trace in l[2]:
- print " referenced from %s" % trace
-
- for fs in file_summaries:
- print fs
- print "%s total may be unused" % sizeAsString(total_unused)
-
-def main():
-
- ## 0001aa44 <_dbus_message_get_network_data>:
- sym_re = re.compile ('([0-9a-f]+) <([^>]+)>:')
- ## 1aa49: e8 00 00 00 00 call 1aa4e <_dbus_message_get_network_data+0xa>
- ref_re = re.compile (' <([^>]+)> *$')
- ## /home/hp/dbus-cvs/dbus/dbus/dbus-message.c:139
- file_re = re.compile ('^(\/[^:].*):[0-9]+$')
- ## _dbus_message_get_network_data+0xa
- funcname_re = re.compile ('([^+]+)\+[0-9a-fx]+')
- ## 00005410 T dbus_address_entries_free
- dynsym_re = re.compile ('T ([^ \n]+)$')
-
- filename = sys.argv[1]
-
- command = """
- objdump -D --demangle -l %s
- """ % filename
-
- command = string.strip (command)
-
- print "Running: %s" % command
-
- f = os.popen(command)
-
- ## first we find which functions reference which other functions
- current_sym = None
- lines = f.readlines()
- for l in lines:
- addr = None
- name = None
- target = None
- file = None
-
- match = sym_re.match(l)
- if match:
- addr = match.group(1)
- name = match.group(2)
- else:
- match = ref_re.search(l)
- if match:
- target = match.group(1)
- else:
- match = file_re.match(l)
- if match:
- file = match.group(1)
-
- if name:
- ## 0 symname, 1 address, 2 references, 3 filename, 4 reached, 5 referenced-by 6 backlinked 7 approx size
- item = [name, addr, [], None, 0, [], 0, 0]
- if symbols.has_key(name):
- symbols[name].append(item)
- else:
- symbols[name] = [item]
-
- if current_sym:
- prev_addr = long(current_sym[1], 16)
- our_addr = long(item[1], 16)
- item[7] = our_addr - prev_addr
- if item[7] < 0:
- print "Computed negative size %d for %s" % (item[7], item[0])
- item[7] = 0
-
- current_sym = item
-
- elif target and current_sym:
- match = funcname_re.match(target)
- if match:
- ## dump the "+address"
- target = match.group(1)
- if target == current_sym[0]:
- pass ## skip self-references
- else:
- current_sym[2].append (target)
-
- elif file and current_sym:
- if file.startswith('/usr/include'):
- ## inlined libc thingy
- pass
- elif current_sym[0].startswith('.debug'):
- ## debug info
- pass
- elif current_sym[3] and current_sym[3] != file:
- raise Exception ("%s in both %s and %s" % (current_sym[0], current_sym[3], file))
- else:
- current_sym[3] = file
-
- ## now we need to find the roots (exported symbols)
- command = "nm -D %s" % filename
- print "Running: %s" % command
- f = os.popen(command)
- lines = f.readlines ()
- for l in lines:
- match = dynsym_re.search(l)
- if match:
- name = match.group(1)
- if roots.has_key(name):
- raise Exception("symbol %s exported twice?" % name)
- else:
- roots[name] = 1
-
- print "%d symbols exported from this object" % len(roots)
-
- ## these functions are used only indirectly, so we don't
- ## notice they are used. Manually add them as roots...
- vtable_roots = ['unix_finalize',
- 'unix_handle_watch',
- 'unix_disconnect',
- 'unix_connection_set',
- 'unix_do_iteration',
- 'unix_live_messages_changed',
- 'unix_get_unix_fd',
- 'handle_client_data_cookie_sha1_mech',
- 'handle_client_data_external_mech',
- 'handle_server_data_cookie_sha1_mech',
- 'handle_server_data_external_mech',
- 'handle_client_initial_response_cookie_sha1_mech',
- 'handle_client_initial_response_external_mech',
- 'handle_client_shutdown_cookie_sha1_mech',
- 'handle_client_shutdown_external_mech',
- 'handle_server_shutdown_cookie_sha1_mech',
- 'handle_server_shutdown_external_mech'
- ]
-
- for vr in vtable_roots:
- if roots.has_key(vr):
- raise Exception("%s is already a root" % vr)
- roots[vr] = 1
-
- for k in roots.keys():
- markSymbol("root", k)
-
- for (k, v) in symbols.items():
- createBacklinks(k, v)
-
- print """
-
-The symbols mentioned below don't appear to be reachable starting from
-the dynamic exports of the library. However, this program is pretty
-dumb; a limitation that creates false positives is that it can only
-trace 'reachable' through hardcoded function calls, if a function is
-called only through a vtable, it won't be marked reachable (and
-neither will its children in the call graph).
-
-Also, the sizes mentioned are more or less completely bogus.
-
-"""
-
- print "The following are hardcoded in as vtable roots: %s" % vtable_roots
-
- printLost()
-
-if __name__ == "__main__":
- main()
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 56a0b7fc..cfce4348 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -6,6 +6,10 @@ AM_CPPFLAGS = \
-DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
$(NULL)
+AM_CFLAGS = \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(NULL)
+
# if assertions are enabled, improve backtraces
AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
@@ -110,9 +114,22 @@ dbus_update_activation_environment_SOURCES = \
$(NULL)
dbus_update_activation_environment_LDADD = $(top_builddir)/dbus/libdbus-1.la
-EXTRA_DIST = run-with-tmp-session-bus.sh strtoll.c strtoull.c
+if DBUS_WIN
+SUFFIXES = .rc
+
+.rc.o:
+ $(RC) $< -o $@
+
+nodist_dbus_update_activation_environment_SOURCES = disable-uac.rc
+
+disable-uac.rc: Win32.Manifest
+ echo '1 24 "$<"' > $@
+endif
+
+EXTRA_DIST = run-with-tmp-session-bus.sh strtoll.c strtoull.c Win32.Manifest
CLEANFILES = \
- run-with-tmp-session-bus.conf
+ run-with-tmp-session-bus.conf \
+ $(nodist_dbus_update_activation_environment_SOURCES)
# create the /var/lib/dbus directory for dbus-uuidgen
install-data-local:
diff --git a/tools/Win32.Manifest b/tools/Win32.Manifest
new file mode 100644
index 00000000..b926d066
--- /dev/null
+++ b/tools/Win32.Manifest
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+</assembly>
diff --git a/tools/ci-Dockerfile.in b/tools/ci-Dockerfile.in
new file mode 100644
index 00000000..e198b0d9
--- /dev/null
+++ b/tools/ci-Dockerfile.in
@@ -0,0 +1,10 @@
+FROM @ci_docker@
+ENV container docker
+
+ADD tools/ci-install.sh /ci-install.sh
+RUN ci_suite="@ci_suite@" ci_distro="@ci_distro@" ci_in_docker=yes /ci-install.sh
+
+ADD . /home/user/ci
+RUN chown -R user:user /home/user/ci
+WORKDIR /home/user/ci
+USER user
diff --git a/tools/ci-build.sh b/tools/ci-build.sh
new file mode 100755
index 00000000..cb19f4a7
--- /dev/null
+++ b/tools/ci-build.sh
@@ -0,0 +1,315 @@
+#!/bin/bash
+
+# Copyright © 2015-2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -euo pipefail
+set -x
+
+NULL=
+
+# ci_buildsys:
+# Build system under test: autotools or cmake
+: "${ci_buildsys:=autotools}"
+
+# ci_distro:
+# OS distribution in which we are testing
+# Typical values: ubuntu, debian; maybe fedora in future
+: "${ci_distro:=ubuntu}"
+
+# ci_docker:
+# If non-empty, this is the name of a Docker image. ci-install.sh will
+# fetch it with "docker pull" and use it as a base for a new Docker image
+# named "ci-image" in which we will do our testing.
+#
+# If empty, we test on "bare metal".
+# Typical values: ubuntu:xenial, debian:jessie-slim
+: "${ci_docker:=}"
+
+# ci_host:
+# See ci-install.sh
+: "${ci_host:=native}"
+
+# ci_parallel:
+# A number of parallel jobs, passed to make -j
+: "${ci_parallel:=1}"
+
+# ci_sudo:
+# If yes, assume we can get root using sudo; if no, only use current user
+: "${ci_sudo:=no}"
+
+# ci_suite:
+# OS suite (release, branch) in which we are testing.
+# Typical values for ci_distro=debian: sid, jessie
+# Typical values for ci_distro=fedora might be 25, rawhide
+: "${ci_suite:=xenial}"
+
+# ci_test:
+# If yes, run tests; if no, just build
+: "${ci_test:=yes}"
+
+# ci_test_fatal:
+# If yes, test failures break the build; if no, they are reported but ignored
+: "${ci_test_fatal:=yes}"
+
+# ci_variant:
+# One of debug, reduced, legacy, production
+: "${ci_variant:=production}"
+
+if [ -n "$ci_docker" ]; then
+ exec docker run \
+ --env=ci_buildsys="${ci_buildsys}" \
+ --env=ci_docker="" \
+ --env=ci_host="${ci_host}" \
+ --env=ci_parallel="${ci_parallel}" \
+ --env=ci_sudo=yes \
+ --env=ci_test="${ci_test}" \
+ --env=ci_test_fatal="${ci_test_fatal}" \
+ --env=ci_variant="${ci_variant}" \
+ --privileged \
+ ci-image \
+ tools/ci-build.sh
+fi
+
+maybe_fail_tests () {
+ if [ "$ci_test_fatal" = yes ]; then
+ exit 1
+ fi
+}
+
+NOCONFIGURE=1 ./autogen.sh
+
+srcdir="$(pwd)"
+mkdir ci-build-${ci_variant}-${ci_host}
+cd ci-build-${ci_variant}-${ci_host}
+
+make="make -j${ci_parallel} V=1 VERBOSE=1"
+
+case "$ci_host" in
+ (*-w64-mingw32)
+ mirror=http://repo.msys2.org/mingw/${ci_host%%-*}
+ if [ "${ci_host%%-*}" = i686 ]; then
+ mingw="$(pwd)/mingw32"
+ else
+ mingw="$(pwd)/mingw64"
+ fi
+ install -d "${mingw}"
+ export PKG_CONFIG_LIBDIR="${mingw}/lib/pkgconfig"
+ export PKG_CONFIG_PATH=
+ export PKG_CONFIG="pkg-config --define-variable=prefix=${mingw}"
+ unset CC
+ unset CXX
+ for pkg in \
+ expat-2.1.0-6 \
+ gcc-libs-5.2.0-4 \
+ gettext-0.19.6-1 \
+ glib2-2.46.1-1 \
+ libffi-3.2.1-3 \
+ zlib-1.2.8-9 \
+ ; do
+ wget ${mirror}/mingw-w64-${ci_host%%-*}-${pkg}-any.pkg.tar.xz
+ tar -xvf mingw-w64-${ci_host%%-*}-${pkg}-any.pkg.tar.xz
+ done
+ export TMPDIR=/tmp
+ ;;
+esac
+
+case "$ci_buildsys" in
+ (autotools)
+ case "$ci_variant" in
+ (debug)
+ # Full developer/debug build.
+ set _ "$@"
+ set "$@" --enable-developer --enable-tests
+ # Enable optional features that are off by default
+ case "$ci_host" in
+ *-w64-mingw32)
+ ;;
+ *)
+ set "$@" --enable-user-session
+ ;;
+ esac
+ shift
+ # The test coverage for OOM-safety is too
+ # verbose to be useful on travis-ci.
+ export DBUS_TEST_MALLOC_FAILURES=0
+ ;;
+
+ (reduced)
+ # A smaller configuration than normal, with
+ # various features disabled; this emulates
+ # an older system or one that does not have
+ # all the optional libraries.
+ set _ "$@"
+ # No LSMs (the production build has both)
+ set "$@" --disable-selinux --disable-apparmor
+ # No inotify (we will use dnotify)
+ set "$@" --disable-inotify
+ # No epoll or kqueue (we will use poll)
+ set "$@" --disable-epoll --disable-kqueue
+ # No special init system support
+ set "$@" --disable-launchd --disable-systemd
+ # No libaudit or valgrind
+ set "$@" --disable-libaudit --without-valgrind
+ # Disable optional features, some of which are on by
+ # default
+ set "$@" --disable-stats
+ set "$@" --disable-user-session
+ shift
+ ;;
+
+ (legacy)
+ # An unrealistically cut-down configuration,
+ # to check that it compiles and works.
+ set _ "$@"
+ # Disable native atomic operations on Unix
+ # (armv4, as used as the baseline for Debian
+ # armel, is one architecture that really
+ # doesn't have them)
+ set "$@" dbus_cv_sync_sub_and_fetch=no
+ # No epoll, kqueue or poll (we will fall back
+ # to select, even on Unix where we would
+ # usually at least have poll)
+ set "$@" --disable-epoll --disable-kqueue
+ set "$@" CPPFLAGS=-DBROKEN_POLL=1
+ # Enable SELinux and AppArmor but not
+ # libaudit - that configuration has sometimes
+ # failed
+ set "$@" --enable-selinux --enable-apparmor
+ set "$@" --disable-libaudit --without-valgrind
+ # No directory monitoring at all
+ set "$@" --disable-inotify --disable-dnotify
+ # No special init system support
+ set "$@" --disable-launchd --disable-systemd
+ # No X11 autolaunching
+ set "$@" --disable-x11-autolaunch
+ # Re-enable the deprecated pam_console support to make
+ # sure it still builds
+ set "$@" --with-console-auth-dir=/var/run/console
+ # Leave stats, user-session, etc. at default settings
+ # to check that the defaults can compile on an old OS
+ shift
+ ;;
+
+ (*)
+ ;;
+ esac
+
+ case "$ci_host" in
+ (*-w64-mingw32)
+ set _ "$@"
+ set "$@" --build="$(build-aux/config.guess)"
+ set "$@" --host="${ci_host}"
+ set "$@" CFLAGS=-static-libgcc
+ set "$@" CXXFLAGS=-static-libgcc
+ # don't run tests yet, Wine needs Xvfb and
+ # more msys2 libraries
+ ci_test=no
+ # don't "make install" system-wide
+ ci_sudo=no
+ shift
+ ;;
+ esac
+
+ ../configure \
+ --enable-installed-tests \
+ --enable-maintainer-mode \
+ --enable-modular-tests \
+ "$@"
+
+ ${make}
+ [ "$ci_test" = no ] || ${make} check || maybe_fail_tests
+ cat test/test-suite.log || :
+ [ "$ci_test" = no ] || ${make} distcheck || maybe_fail_tests
+
+ ${make} install DESTDIR=$(pwd)/DESTDIR
+ ( cd DESTDIR && find . -ls )
+
+ case "$ci_suite" in
+ (jessie|xenial|stretch)
+ # these are too old for maintainer-upload-docs
+ ;;
+
+ (*)
+ # assume Ubuntu 18.04 'bionic', Debian 10 'buster' or newer
+ ${make} -C doc dbus-docs.tar.xz
+ tar -C $(pwd)/DESTDIR -xf doc/dbus-docs.tar.xz
+ ( cd DESTDIR/dbus-docs && find . -ls )
+ ;;
+ esac
+
+ if [ "$ci_sudo" = yes ] && [ "$ci_test" = yes ]; then
+ sudo ${make} install
+ sudo env LD_LIBRARY_PATH=/usr/local/lib \
+ /usr/local/bin/dbus-uuidgen --ensure
+ LD_LIBRARY_PATH=/usr/local/lib ${make} installcheck || \
+ maybe_fail_tests
+ cat test/test-suite.log || :
+
+ # re-run them with gnome-desktop-testing
+ env LD_LIBRARY_PATH=/usr/local/lib \
+ gnome-desktop-testing-runner -d /usr/local/share dbus/ || \
+ maybe_fail_tests
+
+ # these tests benefit from being re-run as root, and one
+ # test needs a finite fd limit to be useful
+ sudo env LD_LIBRARY_PATH=/usr/local/lib \
+ bash -c 'ulimit -S -n 1024; ulimit -H -n 4096; exec "$@"' bash \
+ gnome-desktop-testing-runner -d /usr/local/share \
+ dbus/test-dbus-daemon_with_config.test \
+ dbus/test-uid-permissions_with_config.test || \
+ maybe_fail_tests
+ fi
+ ;;
+
+ (cmake)
+ case "$ci_host" in
+ (*-w64-mingw32)
+ set _ "$@"
+ set "$@" -D CMAKE_TOOLCHAIN_FILE="${srcdir}/cmake/${ci_host}.cmake"
+ set "$@" -D CMAKE_PREFIX_PATH="${mingw}"
+ set "$@" -D CMAKE_INCLUDE_PATH="${mingw}/include"
+ set "$@" -D CMAKE_LIBRARY_PATH="${mingw}/lib"
+ set "$@" -D EXPAT_LIBRARY="${mingw}/lib/libexpat.dll.a"
+ set "$@" -D GLIB2_LIBRARIES="${mingw}/lib/libglib-2.0.dll.a"
+ set "$@" -D GOBJECT_LIBRARIES="${mingw}/lib/libgobject-2.0.dll.a"
+ set "$@" -D GIO_LIBRARIES="${mingw}/lib/libgio-2.0.dll.a"
+ shift
+ # don't run tests yet, Wine needs Xvfb and more
+ # msys2 libraries
+ ci_test=no
+ ;;
+ esac
+
+ cmake "$@" ../cmake
+
+ ${make}
+ # The test coverage for OOM-safety is too verbose to be useful on
+ # travis-ci.
+ export DBUS_TEST_MALLOC_FAILURES=0
+ [ "$ci_test" = no ] || ctest -VV || maybe_fail_tests
+ ${make} install DESTDIR=$(pwd)/DESTDIR
+ ( cd DESTDIR && find . -ls)
+ ;;
+esac
+
+# vim:set sw=4 sts=4 et:
diff --git a/tools/ci-install.sh b/tools/ci-install.sh
new file mode 100755
index 00000000..1c2e3b64
--- /dev/null
+++ b/tools/ci-install.sh
@@ -0,0 +1,188 @@
+#!/bin/bash
+
+# Copyright © 2015-2016 Collabora Ltd.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+set -euo pipefail
+set -x
+
+NULL=
+
+# ci_distro:
+# OS distribution in which we are testing
+# Typical values: ubuntu, debian; maybe fedora in future
+: "${ci_distro:=ubuntu}"
+
+# ci_docker:
+# If non-empty, this is the name of a Docker image. ci-install.sh will
+# fetch it with "docker pull" and use it as a base for a new Docker image
+# named "ci-image" in which we will do our testing.
+: "${ci_docker:=}"
+
+# ci_host:
+# Either "native", or an Autoconf --host argument to cross-compile
+# the package
+: "${ci_host:=native}"
+
+# ci_in_docker:
+# Used internally by ci-install.sh. If yes, we are inside the Docker image
+# (ci_docker is empty in this case).
+: "${ci_in_docker:=no}"
+
+# ci_suite:
+# OS suite (release, branch) in which we are testing.
+# Typical values for ci_distro=debian: sid, jessie
+# Typical values for ci_distro=fedora might be 25, rawhide
+: "${ci_suite:=xenial}"
+
+if [ $(id -u) = 0 ]; then
+ sudo=
+else
+ sudo=sudo
+fi
+
+if [ -n "$ci_docker" ]; then
+ sed \
+ -e "s/@ci_distro@/${ci_distro}/" \
+ -e "s/@ci_docker@/${ci_docker}/" \
+ -e "s/@ci_suite@/${ci_suite}/" \
+ < tools/ci-Dockerfile.in > Dockerfile
+ exec docker build -t ci-image .
+fi
+
+case "$ci_distro" in
+ (debian|ubuntu)
+ # Don't ask questions, just do it
+ sudo="$sudo env DEBIAN_FRONTEND=noninteractive"
+
+ # Debian Docker images use httpredir.debian.org but it seems to be
+ # unreliable; use a CDN instead
+ $sudo sed -i -e 's/httpredir\.debian\.org/deb.debian.org/g' \
+ /etc/apt/sources.list
+
+ case "$ci_suite" in
+ (xenial)
+ # Ubuntu 16.04 didn't have the wine32, wine64 packages
+ wine32=wine:i386
+ wine64=wine:amd64
+ ;;
+ (*)
+ wine32=wine32
+ wine64=wine64
+ ;;
+ esac
+
+ case "$ci_host" in
+ (i686-w64-mingw32)
+ $sudo dpkg --add-architecture i386
+ ;;
+ (x86_64-w64-mingw32)
+ # assume the host or container is x86_64 already
+ ;;
+ esac
+
+ $sudo apt-get -qq -y update
+
+ case "$ci_host" in
+ (i686-w64-mingw32)
+ $sudo apt-get -qq -y install \
+ binutils-mingw-w64-i686 \
+ g++-mingw-w64-i686 \
+ $wine32 \
+ ${NULL}
+ ;;
+ (x86_64-w64-mingw32)
+ $sudo apt-get -qq -y install \
+ binutils-mingw-w64-x86-64\
+ g++-mingw-w64-x86-64 \
+ $wine64 \
+ ${NULL}
+ ;;
+ esac
+
+ $sudo apt-get -qq -y install \
+ autoconf-archive \
+ automake \
+ autotools-dev \
+ ccache \
+ cmake \
+ debhelper \
+ dh-autoreconf \
+ dh-exec \
+ doxygen \
+ dpkg-dev \
+ gnome-desktop-testing \
+ libapparmor-dev \
+ libaudit-dev \
+ libcap-ng-dev \
+ libexpat-dev \
+ libglib2.0-dev \
+ libselinux1-dev \
+ libsystemd-dev \
+ libx11-dev \
+ python \
+ python-dbus \
+ python-gi \
+ valgrind \
+ wget \
+ xauth \
+ xmlto \
+ xsltproc \
+ xvfb \
+ ${NULL}
+
+ if [ "$ci_in_docker" = yes ]; then
+ # Add the user that we will use to do the build inside the
+ # Docker container, and let them use sudo
+ adduser --disabled-password user </dev/null
+ apt-get -y install sudo
+ echo "user ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/nopasswd
+ chmod 0440 /etc/sudoers.d/nopasswd
+ fi
+
+ case "$ci_suite" in
+ (jessie|xenial)
+ # autoconf-archive in Debian 8 and Ubuntu 16.04 is too old,
+ # use the one from Debian 9 instead
+ wget http://deb.debian.org/debian/pool/main/a/autoconf-archive/autoconf-archive_20160916-1_all.deb
+ $sudo dpkg -i autoconf-archive_*_all.deb
+ rm autoconf-archive_*_all.deb
+ ;;
+
+ (stretch)
+ # Debian 9 'stretch' didn't have the ducktype package
+ ;;
+
+ (*)
+ # assume Ubuntu 18.04 'bionic', Debian 10 'buster' or newer
+ $sudo apt-get -qq -y install ducktype
+ ;;
+ esac
+ ;;
+
+ (*)
+ echo "Don't know how to set up ${ci_distro}" >&2
+ exit 1
+ ;;
+esac
+
+# vim:set sw=4 sts=4 et:
diff --git a/tools/dbus-cleanup-sockets.c b/tools/dbus-cleanup-sockets.c
index 1b6709af..994e57ed 100644
--- a/tools/dbus-cleanup-sockets.c
+++ b/tools/dbus-cleanup-sockets.c
@@ -328,6 +328,7 @@ handle_sockets (SocketEntry **entries,
break;
case SOCKET_UNLINKED:
+ default:
fprintf (stderr, "Bad status from open_socket(), should not happen\n");
exit (1);
break;
diff --git a/tools/dbus-echo.c b/tools/dbus-echo.c
index 0e7de1bd..917d983c 100644
--- a/tools/dbus-echo.c
+++ b/tools/dbus-echo.c
@@ -40,6 +40,8 @@ static int sleep_ms = -1;
static dbus_bool_t noreply = FALSE;
static dbus_bool_t noread = FALSE;
+static void usage_echo (int exit_with) _DBUS_GNUC_NORETURN;
+
static void
usage_echo (int exit_with)
{
@@ -52,7 +54,7 @@ usage_echo (int exit_with)
"\n"
" --name=NAME claim this well-known name first\n"
"\n"
- " --sleep=N sleep N milliseconds before sending each reply\n"
+ " --sleep-ms=N sleep N milliseconds before sending each reply\n"
"\n"
" --session use the session bus (default)\n"
" --system use the system bus\n"
@@ -60,6 +62,8 @@ usage_echo (int exit_with)
exit (exit_with);
}
+static void usage_black_hole (int exit_with) _DBUS_GNUC_NORETURN;
+
static void
usage_black_hole (int exit_with)
{
diff --git a/tools/dbus-launch-win.c b/tools/dbus-launch-win.c
index 1dfd0954..34837c12 100644
--- a/tools/dbus-launch-win.c
+++ b/tools/dbus-launch-win.c
@@ -38,7 +38,7 @@
#define wcscpy_s my_wcscpy_s
static errno_t
-wcscat_s (wchar_t *dest, size_t size, wchar_t *src)
+wcscat_s (wchar_t *dest, size_t size, const wchar_t *src)
{
assert (sizeof (wchar_t) * (wcslen (dest) + wcslen (src) + 1) <= size);
wcscat (dest, src);
@@ -47,7 +47,7 @@ wcscat_s (wchar_t *dest, size_t size, wchar_t *src)
static errno_t
-wcscpy_s (wchar_t *dest, size_t size, wchar_t *src)
+wcscpy_s (wchar_t *dest, size_t size, const wchar_t *src)
{
assert (sizeof (wchar_t) * (wcslen (src) + 1) <= size);
wcscpy (dest, src);
@@ -87,7 +87,7 @@ main (int argc, char **argv)
wchar_t dbusDaemonPath[MAX_PATH * 2 + 1];
wchar_t command[MAX_PATH * 2 + 1];
wchar_t *p;
- wchar_t *daemon_name;
+ const wchar_t *daemon_name;
int result;
#ifdef DBUS_WINCE
diff --git a/tools/dbus-launch-x11.c b/tools/dbus-launch-x11.c
index c7e33309..c4b97904 100644
--- a/tools/dbus-launch-x11.c
+++ b/tools/dbus-launch-x11.c
@@ -43,7 +43,7 @@ static Atom address_atom;
static Atom pid_atom;
static int
-x_io_error_handler (Display *xdisplay)
+x_io_error_handler (Display *local_xdisplay)
{
verbose ("X IO error\n");
kill_bus_and_exit (0);
@@ -52,7 +52,7 @@ x_io_error_handler (Display *xdisplay)
static void
remove_prefix (char *s,
- char *prefix)
+ const char *prefix)
{
int plen;
@@ -367,7 +367,8 @@ set_address_in_x11(char *address, pid_t pid)
wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
0, CopyFromParent, InputOnly, CopyFromParent,
0, NULL);
- verbose ("Created window %d\n", wid);
+ /* The type of a Window varies, so cast it to something reasonable */
+ verbose ("Created window %lu\n", (unsigned long) wid);
/* Save the property in the window */
XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
@@ -414,7 +415,7 @@ set_address_in_file (char *address, pid_t pid, Window wid)
"# If the DBUS_SESSION_BUS_ADDRESS environment variable is set, it will\n"
"# be used rather than this file.\n"
"# See \"man dbus-launch\" for more details.\n"
- "DBUS_SESSION_BUS_ADDRESS=%s\n"
+ "DBUS_SESSION_BUS_ADDRESS='%s'\n"
"DBUS_SESSION_BUS_PID=%ld\n"
"DBUS_SESSION_BUS_WINDOWID=%ld\n",
get_machine_uuid (),
diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c
index 0f1e6ede..f5287548 100644
--- a/tools/dbus-launch.c
+++ b/tools/dbus-launch.c
@@ -117,12 +117,12 @@ save_machine_uuid (const char *uuid_arg)
/* Read the machine uuid from file if needed. Returns TRUE if machine_uuid is
* set after this function */
static int
-read_machine_uuid_if_needed (void)
+read_machine_uuid_if_needed (DBusError *error)
{
if (machine_uuid != NULL)
return TRUE;
- machine_uuid = dbus_get_local_machine_id ();
+ machine_uuid = dbus_try_get_local_machine_id (error);
if (machine_uuid == NULL)
return FALSE;
@@ -164,16 +164,20 @@ verbose (const char *format,
#endif /* DBUS_ENABLE_VERBOSE_MODE */
}
+static void usage (int ecode) _DBUS_GNUC_NORETURN;
+
static void
usage (int ecode)
{
fprintf (stderr, "dbus-launch [--version] [--help] [--sh-syntax]"
" [--csh-syntax] [--auto-syntax] [--binary-syntax] [--close-stderr]"
- " [--exit-with-session] [--autolaunch=MACHINEID]"
+ " [--exit-with-session|--exit-with-x11] [--autolaunch=MACHINEID]"
" [--config-file=FILENAME] [PROGRAM] [ARGS...]\n");
exit (ecode);
}
+static void version (void) _DBUS_GNUC_NORETURN;
+
static void
version (void)
{
@@ -205,6 +209,7 @@ xstrdup (const char *str)
return copy;
}
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
static char *
concat2 (const char *a,
const char *b)
@@ -224,6 +229,7 @@ concat2 (const char *a,
memcpy (ret + la, b, lb + 1);
return ret;
}
+#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
typedef enum
{
@@ -453,21 +459,16 @@ print_variables (const char *bus_address, pid_t bus_pid, long bus_wid,
}
}
-static int got_sighup = FALSE;
+static int got_fatal_signal = 0;
static void
signal_handler (int sig)
{
- switch (sig)
- {
- case SIGHUP:
- case SIGINT:
- case SIGTERM:
- got_sighup = TRUE;
- break;
- }
+ got_fatal_signal = sig;
}
+static void kill_bus_when_session_ends (void) _DBUS_GNUC_NORETURN;
+
static void
kill_bus_when_session_ends (void)
{
@@ -479,7 +480,7 @@ kill_bus_when_session_ends (void)
sigset_t empty_mask;
/* install SIGHUP handler */
- got_sighup = FALSE;
+ got_fatal_signal = 0;
sigemptyset (&empty_mask);
act.sa_handler = signal_handler;
act.sa_mask = empty_mask;
@@ -556,9 +557,10 @@ kill_bus_when_session_ends (void)
select (MAX (tty_fd, x_fd) + 1,
&read_set, NULL, &err_set, NULL);
- if (got_sighup)
+ if (got_fatal_signal)
{
- verbose ("Got SIGHUP, exiting\n");
+ verbose ("Got fatal signal %d, killing dbus-daemon\n",
+ got_fatal_signal);
kill_bus_and_exit (0);
}
@@ -605,15 +607,16 @@ kill_bus_when_session_ends (void)
}
}
}
+ /* not reached */
}
-static void
+_DBUS_GNUC_NORETURN static void
babysit (int exit_with_session,
pid_t child_pid,
int read_bus_pid_fd) /* read pid from here */
{
+ DBusEnsureStandardFdsFlags flags;
int ret;
- int dev_null_fd;
const char *s;
verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n",
@@ -633,28 +636,26 @@ babysit (int exit_with_session,
exit (1);
}
+ flags = DBUS_FORCE_STDOUT_NULL;
+
+ if (!exit_with_session)
+ flags |= DBUS_FORCE_STDIN_NULL;
+
+ s = getenv ("DBUS_DEBUG_OUTPUT");
+
+ if (s == NULL || *s == '\0')
+ flags |= DBUS_FORCE_STDERR_NULL;
+
/* Close stdout/stderr so we don't block an "eval" or otherwise
* lock up. stdout is still chaining through to dbus-launch
* and in turn to the parent shell.
*/
- dev_null_fd = open ("/dev/null", O_RDWR);
- if (dev_null_fd >= 0)
- {
- if (!exit_with_session)
- dup2 (dev_null_fd, 0);
- dup2 (dev_null_fd, 1);
- s = getenv ("DBUS_DEBUG_OUTPUT");
- if (s == NULL || *s == '\0')
- dup2 (dev_null_fd, 2);
- close (dev_null_fd);
- }
- else
+ if (!_dbus_ensure_standard_fds (flags, &s))
{
- fprintf (stderr, "Failed to open /dev/null: %s\n",
- strerror (errno));
- /* continue, why not */
+ fprintf (stderr, "%s: %s\n", s, strerror (errno));
+ exit (1);
}
-
+
ret = fork ();
if (ret < 0)
@@ -702,6 +703,8 @@ babysit (int exit_with_session,
strerror (errno));
exit (1);
break;
+ default:
+ _dbus_assert_not_reached ("Invalid read result");
}
verbose ("Got PID %ld from daemon\n",
@@ -725,29 +728,23 @@ babysit (int exit_with_session,
static void
do_close_stderr (void)
{
- int fd;
+ const char *err;
fflush (stderr);
- /* dbus-launch is a Unix-only program, so we can rely on /dev/null being there.
- * We're including unistd.h and we're dealing with sh/csh launch sequences...
- */
- fd = open ("/dev/null", O_RDWR);
- if (fd == -1)
- {
- fprintf (stderr, "Internal error: cannot open /dev/null: %s", strerror (errno));
- exit (1);
- }
-
- close (2);
- if (dup2 (fd, 2) == -1)
+ if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDERR_NULL, &err))
{
- /* error; we can't report an error anymore... */
+ fprintf (stderr, "%s: %s\n", err, strerror (errno));
exit (1);
}
- close (fd);
}
+static void pass_info (const char *runprog, const char *bus_address,
+ pid_t bus_pid, long bus_wid, int c_shell_syntax,
+ int bourne_shell_syntax, int binary_syntax,
+ int argc, char **argv,
+ int remaining_args) _DBUS_GNUC_NORETURN;
+
static void
pass_info (const char *runprog, const char *bus_address, pid_t bus_pid,
long bus_wid, int c_shell_syntax, int bourne_shell_syntax,
@@ -827,6 +824,7 @@ main (int argc, char **argv)
const char *runprog = NULL;
int remaining_args = 0;
int exit_with_session;
+ int exit_with_x11 = FALSE;
int binary_syntax = FALSE;
int c_shell_syntax = FALSE;
int bourne_shell_syntax = FALSE;
@@ -842,10 +840,26 @@ main (int argc, char **argv)
char *config_file;
dbus_bool_t user_bus_supported = FALSE;
DBusString user_bus;
-
+ const char *error_str;
+ DBusError error = DBUS_ERROR_INIT;
+
exit_with_session = FALSE;
config_file = NULL;
-
+
+ /* Ensure that the first three fds are open, to ensure that when we
+ * create other file descriptors (for example for epoll, inotify or
+ * a socket), they never get assigned as fd 0, 1 or 2. If they were,
+ * which could happen if our caller had (incorrectly) closed those
+ * standard fds, then we'd start dbus-daemon with those fds closed,
+ * which is unexpected and could cause it to misbehave. */
+ if (!_dbus_ensure_standard_fds (0, &error_str))
+ {
+ fprintf (stderr,
+ "dbus-launch: fatal error setting up standard fds: %s: %s\n",
+ error_str, _dbus_strerror (errno));
+ return 1;
+ }
+
prev_arg = NULL;
i = 1;
while (i < argc)
@@ -870,6 +884,8 @@ main (int argc, char **argv)
version ();
else if (strcmp (arg, "--exit-with-session") == 0)
exit_with_session = TRUE;
+ else if (strcmp (arg, "--exit-with-x11") == 0)
+ exit_with_x11 = TRUE;
else if (strcmp (arg, "--close-stderr") == 0)
close_stderr = TRUE;
else if (strstr (arg, "--autolaunch=") == arg)
@@ -981,6 +997,9 @@ main (int argc, char **argv)
if (exit_with_session)
verbose ("--exit-with-session enabled\n");
+ if (exit_with_x11)
+ verbose ("--exit-with-x11 enabled\n");
+
if (autolaunch)
{
#ifndef DBUS_BUILD_X11
@@ -995,7 +1014,6 @@ main (int argc, char **argv)
char *address;
pid_t pid;
long wid;
- DBusError error = DBUS_ERROR_INIT;
if (get_machine_uuid () == NULL)
{
@@ -1035,10 +1053,10 @@ main (int argc, char **argv)
}
verbose ("Autolaunch enabled (using X11).\n");
- if (!exit_with_session)
+ if (!exit_with_x11)
{
- verbose ("--exit-with-session automatically enabled\n");
- exit_with_session = TRUE;
+ verbose ("--exit-with-x11 automatically enabled\n");
+ exit_with_x11 = TRUE;
}
if (!x11_init ())
@@ -1061,12 +1079,40 @@ main (int argc, char **argv)
exit (0);
}
#endif /* DBUS_ENABLE_X11_AUTOLAUNCH */
+#endif /* DBUS_BUILD_X11 */
}
- else if (read_machine_uuid_if_needed())
+ else if (exit_with_x11)
{
- x11_init();
+#ifndef DBUS_BUILD_X11
+ fprintf (stderr, "Session lifetime based on X11 requested, but X11 support not compiled in.\n");
+ exit (1);
+#else /* DBUS_BUILD_X11 */
+ if (!read_machine_uuid_if_needed (&error))
+ {
+ fprintf (stderr, "Session lifetime based on X11 requested, but machine UUID unavailable: %s.\n", error.message);
+ dbus_error_free (&error);
+ exit (1);
+ }
+
+ if (!x11_init ())
+ {
+ fprintf (stderr, "Session lifetime based on X11 requested, but X11 initialization failed.\n");
+ exit (1);
+ }
#endif /* DBUS_BUILD_X11 */
}
+#ifdef DBUS_BUILD_X11
+ else if (read_machine_uuid_if_needed (&error))
+ {
+ x11_init();
+ }
+ else
+ {
+ /* Survive this misconfiguration, but complain about it. */
+ fprintf (stderr, "%s\n", error.message);
+ dbus_error_free (&error);
+ }
+#endif /* DBUS_BUILD_X11 */
if (pipe (bus_pid_to_launcher_pipe) < 0 ||
@@ -1128,7 +1174,7 @@ main (int argc, char **argv)
* and will also reap the pre-forked bus
* daemon
*/
- babysit (exit_with_session, ret,
+ babysit (exit_with_session || exit_with_x11, ret,
bus_pid_to_babysitter_pipe[READ_END]);
exit (0);
}
@@ -1169,10 +1215,10 @@ main (int argc, char **argv)
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
{
- const char *test_daemon;
/* exec from testdir */
- if (getenv ("DBUS_USE_TEST_BINARY") != NULL &&
- (test_daemon = getenv ("DBUS_TEST_DAEMON")) != NULL)
+ const char *test_daemon = getenv ("DBUS_TEST_DAEMON");
+
+ if (test_daemon != NULL)
{
if (config_file == NULL && getenv ("DBUS_TEST_DATA") != NULL)
{
@@ -1188,6 +1234,7 @@ main (int argc, char **argv)
execl (test_daemon,
test_daemon,
+ close_stderr ? "--syslog-only" : "--syslog",
"--fork",
"--print-pid", write_pid_fd_as_string,
"--print-address", write_address_fd_as_string,
@@ -1205,6 +1252,7 @@ main (int argc, char **argv)
execl (DBUS_DAEMONDIR"/dbus-daemon",
DBUS_DAEMONDIR"/dbus-daemon",
+ close_stderr ? "--syslog-only" : "--syslog",
"--fork",
"--print-pid", write_pid_fd_as_string,
"--print-address", write_address_fd_as_string,
@@ -1224,6 +1272,7 @@ main (int argc, char **argv)
*/
execlp ("dbus-daemon",
"dbus-daemon",
+ close_stderr ? "--syslog-only" : "--syslog",
"--fork",
"--print-pid", write_pid_fd_as_string,
"--print-address", write_address_fd_as_string,
@@ -1282,6 +1331,8 @@ main (int argc, char **argv)
strerror (errno));
exit (1);
break;
+ default:
+ _dbus_assert_not_reached ("Invalid read result");
}
close (bus_address_to_launcher_pipe[READ_END]);
@@ -1301,6 +1352,8 @@ main (int argc, char **argv)
strerror (errno));
exit (1);
break;
+ default:
+ _dbus_assert_not_reached ("Invalid read result");
}
end = NULL;
diff --git a/tools/dbus-launch.h b/tools/dbus-launch.h
index d0ede6ba..56596d26 100644
--- a/tools/dbus-launch.h
+++ b/tools/dbus-launch.h
@@ -42,9 +42,9 @@
#define MAX_ADDR_LEN 512
/* defined in dbus-launch.c */
-void verbose (const char *format, ...);
+void verbose (const char *format, ...) _DBUS_GNUC_PRINTF (1, 2);
char *xstrdup (const char *str);
-void kill_bus_and_exit (int exitcode);
+void kill_bus_and_exit (int exitcode) _DBUS_GNUC_NORETURN;
const char* get_machine_uuid (void);
diff --git a/tools/dbus-monitor.c b/tools/dbus-monitor.c
index 483d42ee..c6f36d59 100644
--- a/tools/dbus-monitor.c
+++ b/tools/dbus-monitor.c
@@ -21,7 +21,7 @@
#include <config.h>
-#include "dbus/dbus-internals.h" /* just for the macros */
+#include "dbus/dbus-internals.h"
#include <stdio.h>
#include <stdlib.h>
@@ -240,6 +240,10 @@ binary_filter_func (DBusConnection *connection,
}
break;
+ case BINARY_MODE_NOT:
+ _dbus_assert_not_reached ("wrong filter function");
+ break;
+
case BINARY_MODE_RAW:
default:
/* nothing special, just the raw message stream */
@@ -262,6 +266,8 @@ binary_filter_func (DBusConnection *connection,
return DBUS_HANDLER_RESULT_HANDLED;
}
+static void usage (char *name, int ecode) _DBUS_GNUC_NORETURN;
+
static void
usage (char *name, int ecode)
{
@@ -472,8 +478,10 @@ main (int argc, char *argv[])
case DBUS_BUS_SESSION:
where = "session bus";
break;
+ case DBUS_BUS_STARTER:
default:
- where = "";
+ /* We don't set type to anything else */
+ _dbus_assert_not_reached ("impossible bus type");
}
}
fprintf (stderr, "Failed to open connection to %s: %s\n",
@@ -547,6 +555,8 @@ main (int argc, char *argv[])
{
case BINARY_MODE_NOT:
case BINARY_MODE_RAW:
+ default:
+ /* no special header needed */
break;
case BINARY_MODE_PCAP:
diff --git a/tools/dbus-print-message.c b/tools/dbus-print-message.c
index 80c96986..547f72f8 100644
--- a/tools/dbus-print-message.c
+++ b/tools/dbus-print-message.c
@@ -39,6 +39,23 @@
#include "tool-common.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#if defined(DBUS_WIN)
+#if !defined(PRId64)
+#define PRId64 "I64d"
+#endif
+#if !defined(PRIu64)
+#define PRIu64 "I64u"
+#endif
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+#define socklen_t int
+#endif
+
static const char*
type_to_name (int message_type)
{
@@ -169,8 +186,8 @@ print_fd (int fd, int depth)
struct sockaddr_in6 ipv6;
} addr, peer;
char hostip[INET6_ADDRSTRLEN];
- int addrlen = sizeof (addr);
- int peerlen = sizeof (peer);
+ socklen_t addrlen = sizeof (addr);
+ socklen_t peerlen = sizeof (peer);
int has_peer;
/* Don't print the fd number: it is different in every process and since
@@ -384,11 +401,7 @@ print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
{
dbus_int64_t val;
dbus_message_iter_get_basic (iter, &val);
-#ifdef DBUS_INT64_PRINTF_MODIFIER
- printf ("int64 %" DBUS_INT64_PRINTF_MODIFIER "d\n", val);
-#else
- printf ("int64 (omitted)\n");
-#endif
+ printf ("int64 %" PRId64 "\n", val);
break;
}
@@ -396,11 +409,7 @@ print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
{
dbus_uint64_t val;
dbus_message_iter_get_basic (iter, &val);
-#ifdef DBUS_INT64_PRINTF_MODIFIER
- printf ("uint64 %" DBUS_INT64_PRINTF_MODIFIER "u\n", val);
-#else
- printf ("uint64 (omitted)\n");
-#endif
+ printf ("uint64 %" PRIu64 "\n", val);
break;
}
diff --git a/tools/dbus-run-session.c b/tools/dbus-run-session.c
index 105ab3b4..0adb5ad1 100644
--- a/tools/dbus-run-session.c
+++ b/tools/dbus-run-session.c
@@ -37,6 +37,7 @@
#include <signal.h>
#include "dbus/dbus.h"
+#include "dbus/dbus-internals.h"
#define MAX_ADDR_LEN 512
#define PIPE_READ_END 0
@@ -65,6 +66,8 @@
static const char me[] = "dbus-run-session";
+static void usage (int ecode) _DBUS_GNUC_NORETURN;
+
static void
usage (int ecode)
{
@@ -81,6 +84,8 @@ usage (int ecode)
exit (ecode);
}
+static void version (void) _DBUS_GNUC_NORETURN;
+
static void
version (void)
{
@@ -95,6 +100,8 @@ version (void)
exit (0);
}
+static void oom (void) _DBUS_GNUC_NORETURN;
+
static void
oom (void)
{
@@ -191,6 +198,8 @@ exec_dbus_daemon (const char *dbus_daemon,
me, dbus_daemon, strerror (errno));
}
+static void exec_app (int prog_arg, char **argv) _DBUS_GNUC_NORETURN;
+
static void
exec_app (int prog_arg, char **argv)
{
@@ -378,6 +387,9 @@ main (int argc, char **argv)
me, strerror (errno));
return 127;
break;
+
+ default:
+ _dbus_assert_not_reached ("invalid read result");
}
close (bus_address_pipe[PIPE_READ_END]);
diff --git a/tools/dbus-send.c b/tools/dbus-send.c
index 0dc1f5b3..efeb76e0 100644
--- a/tools/dbus-send.c
+++ b/tools/dbus-send.c
@@ -49,6 +49,8 @@
static const char *appname;
+static void usage (int ecode) _DBUS_GNUC_NORETURN;
+
static void
usage (int ecode)
{
@@ -56,6 +58,17 @@ usage (int ecode)
exit (ecode);
}
+/* Abort on any allocation failure; there is nothing else we can do. */
+static void
+handle_oom (dbus_bool_t success)
+{
+ if (!success)
+ {
+ fprintf (stderr, "%s: Ran out of memory\n", appname);
+ exit (1);
+ }
+}
+
static void
append_arg (DBusMessageIter *iter, int type, const char *value)
{
@@ -68,68 +81,68 @@ append_arg (DBusMessageIter *iter, int type, const char *value)
double d;
unsigned char byte;
dbus_bool_t v_BOOLEAN;
-
- /* FIXME - we are ignoring OOM returns on all these functions */
+ dbus_bool_t ret;
+
switch (type)
{
case DBUS_TYPE_BYTE:
byte = strtoul (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &byte);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &byte);
break;
case DBUS_TYPE_DOUBLE:
d = strtod (value, NULL);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &d);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &d);
break;
case DBUS_TYPE_INT16:
int16 = strtol (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &int16);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &int16);
break;
case DBUS_TYPE_UINT16:
uint16 = strtoul (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &uint16);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &uint16);
break;
case DBUS_TYPE_INT32:
int32 = strtol (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &int32);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &int32);
break;
case DBUS_TYPE_UINT32:
uint32 = strtoul (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &uint32);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &uint32);
break;
case DBUS_TYPE_INT64:
int64 = strtoll (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &int64);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &int64);
break;
case DBUS_TYPE_UINT64:
uint64 = strtoull (value, NULL, 0);
- dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &uint64);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &uint64);
break;
case DBUS_TYPE_STRING:
- dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
break;
case DBUS_TYPE_OBJECT_PATH:
- dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &value);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &value);
break;
case DBUS_TYPE_BOOLEAN:
if (strcmp (value, "true") == 0)
{
v_BOOLEAN = TRUE;
- dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
}
else if (strcmp (value, "false") == 0)
{
v_BOOLEAN = FALSE;
- dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
+ ret = dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
}
else
{
@@ -142,6 +155,8 @@ append_arg (DBusMessageIter *iter, int type, const char *value)
fprintf (stderr, "%s: Unsupported data type %c\n", appname, (char) type);
exit (1);
}
+
+ handle_oom (ret);
}
static void
@@ -150,6 +165,8 @@ append_array (DBusMessageIter *iter, int type, const char *value)
const char *val;
char *dupval = strdup (value);
+ handle_oom (dupval != NULL);
+
val = strtok (dupval, ",");
while (val != NULL)
{
@@ -165,15 +182,17 @@ append_dict (DBusMessageIter *iter, int keytype, int valtype, const char *value)
const char *val;
char *dupval = strdup (value);
+ handle_oom (dupval != NULL);
+
val = strtok (dupval, ",");
while (val != NULL)
{
DBusMessageIter subiter;
- dbus_message_iter_open_container (iter,
- DBUS_TYPE_DICT_ENTRY,
- NULL,
- &subiter);
+ handle_oom (dbus_message_iter_open_container (iter,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &subiter));
append_arg (&subiter, keytype, val);
val = strtok (NULL, ",");
@@ -184,7 +203,7 @@ append_dict (DBusMessageIter *iter, int keytype, int valtype, const char *value)
}
append_arg (&subiter, valtype, val);
- dbus_message_iter_close_container (iter, &subiter);
+ handle_oom (dbus_message_iter_close_container (iter, &subiter));
val = strtok (NULL, ",");
}
free (dupval);
@@ -270,13 +289,16 @@ main (int argc, char *argv[])
}
else if ((strstr (arg, "--bus=") == arg) || (strstr (arg, "--peer=") == arg) || (strstr (arg, "--address=") == arg))
{
- if (arg[2] == 'b') /* bus */
+ /* Check for peer first, to avoid the GCC -Wduplicated-branches
+ * warning.
+ */
+ if (arg[2] == 'p') /* peer */
{
- is_bus = TRUE;
+ is_bus = FALSE;
}
- else if (arg[2] == 'p') /* peer */
+ else if (arg[2] == 'b') /* bus */
{
- is_bus = FALSE;
+ is_bus = TRUE;
}
else /* address; keeping backwards compatibility */
{
@@ -416,6 +438,7 @@ main (int argc, char *argv[])
path,
name,
last_dot + 1);
+ handle_oom (message != NULL);
dbus_message_set_auto_start (message, TRUE);
}
else if (message_type == DBUS_MESSAGE_TYPE_SIGNAL)
@@ -432,6 +455,7 @@ main (int argc, char *argv[])
*last_dot = '\0';
message = dbus_message_new_signal (path, name, last_dot + 1);
+ handle_oom (message != NULL);
}
else
{
@@ -457,13 +481,14 @@ main (int argc, char *argv[])
{
char *arg;
char *c;
- int type;
+ int type2;
int secondary_type;
int container_type;
DBusMessageIter *target_iter;
DBusMessageIter container_iter;
- type = DBUS_TYPE_INVALID;
+ type2 = DBUS_TYPE_INVALID;
+ secondary_type = DBUS_TYPE_INVALID;
arg = argv[i++];
c = strchr (arg, ':');
@@ -497,9 +522,9 @@ main (int argc, char *argv[])
}
if (arg[0] == 0)
- type = DBUS_TYPE_STRING;
+ type2 = DBUS_TYPE_STRING;
else
- type = type_from_name (arg);
+ type2 = type_from_name (arg);
if (container_type == DBUS_TYPE_DICT_ENTRY)
{
@@ -514,25 +539,25 @@ main (int argc, char *argv[])
*(c++) = 0;
secondary_type = type_from_name (arg);
sig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR;
- sig[1] = type;
+ sig[1] = type2;
sig[2] = secondary_type;
sig[3] = DBUS_DICT_ENTRY_END_CHAR;
sig[4] = '\0';
- dbus_message_iter_open_container (&iter,
- DBUS_TYPE_ARRAY,
- sig,
- &container_iter);
+ handle_oom (dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ sig,
+ &container_iter));
target_iter = &container_iter;
}
else if (container_type != DBUS_TYPE_INVALID)
{
char sig[2];
- sig[0] = type;
+ sig[0] = type2;
sig[1] = '\0';
- dbus_message_iter_open_container (&iter,
- container_type,
- sig,
- &container_iter);
+ handle_oom (dbus_message_iter_open_container (&iter,
+ container_type,
+ sig,
+ &container_iter));
target_iter = &container_iter;
}
else
@@ -540,19 +565,20 @@ main (int argc, char *argv[])
if (container_type == DBUS_TYPE_ARRAY)
{
- append_array (target_iter, type, c);
+ append_array (target_iter, type2, c);
}
else if (container_type == DBUS_TYPE_DICT_ENTRY)
{
- append_dict (target_iter, type, secondary_type, c);
+ _dbus_assert (secondary_type != DBUS_TYPE_INVALID);
+ append_dict (target_iter, type2, secondary_type, c);
}
else
- append_arg (target_iter, type, c);
+ append_arg (target_iter, type2, c);
if (container_type != DBUS_TYPE_INVALID)
{
- dbus_message_iter_close_container (&iter,
- &container_iter);
+ handle_oom (dbus_message_iter_close_container (&iter,
+ &container_iter));
}
}
diff --git a/tools/dbus-spam.c b/tools/dbus-spam.c
index c78d8ea6..192911cb 100644
--- a/tools/dbus-spam.c
+++ b/tools/dbus-spam.c
@@ -35,6 +35,8 @@
static dbus_bool_t ignore_errors = FALSE;
+static void usage (int ecode) _DBUS_GNUC_NORETURN;
+
static void
usage (int ecode)
{
@@ -177,6 +179,17 @@ dbus_test_tool_spam (int argc, char **argv)
{
const char *arg = argv[i];
+ if (payload != NULL &&
+ (strstr (arg, "--payload=") == arg ||
+ strcmp (arg, "--stdin") == 0 ||
+ strcmp (arg, "--message-stdin") == 0 ||
+ strcmp (arg, "--random-size") == 0))
+ {
+ fprintf (stderr, "At most one of --payload, --stdin, --message-stdin "
+ "and --random-size may be specified\n\n");
+ usage (2);
+ }
+
if (strcmp (arg, "--system") == 0)
{
type = DBUS_BUS_SYSTEM;
@@ -245,7 +258,7 @@ dbus_test_tool_spam (int argc, char **argv)
n_random_sizes++;
}
- random_sizes = dbus_new0 (int, n_random_sizes);
+ random_sizes = dbus_new0 (unsigned int, n_random_sizes);
if (random_sizes == NULL)
tool_oom ("allocating array of message lengths");
diff --git a/tools/dbus-update-activation-environment.c b/tools/dbus-update-activation-environment.c
index 6c53d8e2..452e5053 100644
--- a/tools/dbus-update-activation-environment.c
+++ b/tools/dbus-update-activation-environment.c
@@ -62,9 +62,12 @@
#ifdef DBUS_WIN
/* The Windows C runtime uses a different name */
#define environ _environ
+#elif defined(__APPLE__)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron ())
+#elif HAVE_DECL_ENVIRON && defined(HAVE_UNISTD_H)
+# include <unistd.h>
#else
-/* apparently this is the portable way to get the entire environment...
- * GNU platforms also put it in unistd.h but that's not portable */
extern char **environ;
#endif
@@ -378,7 +381,8 @@ next:
exit (EX_UNAVAILABLE);
}
- if (!dbus_message_get_args (msg, &error, DBUS_TYPE_INVALID))
+ if (dbus_set_error_from_message (&error, msg) ||
+ !dbus_message_get_args (msg, &error, DBUS_TYPE_INVALID))
{
fprintf (stderr,
"%s: error from dbus-daemon: %s: %s\n",
@@ -402,7 +406,8 @@ next:
"%s: warning: error sending to systemd: %s: %s\n",
PROGNAME, error.name, error.message);
}
- else if (!dbus_message_get_args (msg, &error, DBUS_TYPE_INVALID))
+ else if (dbus_set_error_from_message (&error, msg) ||
+ !dbus_message_get_args (msg, &error, DBUS_TYPE_INVALID))
{
fprintf (stderr,
"%s: warning: error from systemd: %s: %s\n",
diff --git a/tools/dbus-uuidgen.c b/tools/dbus-uuidgen.c
index 03ce5536..337bdd0b 100644
--- a/tools/dbus-uuidgen.c
+++ b/tools/dbus-uuidgen.c
@@ -27,8 +27,11 @@
#include <dbus/dbus-uuidgen.h>
#include <dbus/dbus.h>
+static void usage (const char *name, int ecode) _DBUS_GNUC_NORETURN;
+
static void
-usage (char *name, int ecode)
+usage (const char *name,
+ int ecode)
{
if (name == NULL)
name = "dbus-uuidgen";
@@ -37,6 +40,8 @@ usage (char *name, int ecode)
exit (ecode);
}
+static void version (void) _DBUS_GNUC_NORETURN;
+
static void
version (void)
{
diff --git a/tools/lcov.am b/tools/lcov.am
deleted file mode 100644
index ac348671..00000000
--- a/tools/lcov.am
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright © 2008-2011 Collabora Ltd.
-# Copyright © 2008-2011 Nokia Corporation
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-lcov-reset:
- lcov --directory @abs_top_builddir@ --zerocounters
-
-lcov-report:
- lcov --directory @abs_top_builddir@ --capture \
- --output-file @abs_top_builddir@/lcov.info
- $(mkdir_p) @abs_top_builddir@/lcov.html
- git_commit=`GIT_DIR=@abs_top_srcdir@/.git git log -1 --pretty=format:%h 2>/dev/null`;\
- genhtml --title "@PACKAGE_STRING@ $$git_commit" \
- --output-directory @abs_top_builddir@/lcov.html lcov.info
- @echo
- @echo 'lcov report can be found in:'
- @echo 'file://@abs_top_builddir@/lcov.html/index.html'
- @echo
-
-lcov-check:
- $(MAKE) lcov-reset
- $(MAKE) check $(LCOV_CHECK_ARGS)
- $(MAKE) lcov-report
-
-## vim:set ft=automake:
diff --git a/tools/run-with-tmp-session-bus.sh b/tools/run-with-tmp-session-bus.sh
index 94ae8fc8..688f9e48 100755
--- a/tools/run-with-tmp-session-bus.sh
+++ b/tools/run-with-tmp-session-bus.sh
@@ -45,11 +45,6 @@ export LD_LIBRARY_PATH
unset DBUS_SESSION_BUS_ADDRESS
unset DBUS_SESSION_BUS_PID
-# this does not actually affect dbus-run-session any more, but could be
-# significant for dbus-launch as used by the autolaunch test
-DBUS_USE_TEST_BINARY=1
-export DBUS_USE_TEST_BINARY
-
$DBUS_TOP_BUILDDIR/tools/dbus-run-session \
--config-file="$CONFIG_FILE" \
--dbus-daemon="$DBUS_TOP_BUILDDIR/bus/dbus-daemon" \