From: "Daniel P. Berrange" <berrange(a)redhat.com>
The policy kit and HAL node device drivers both require a
DBus connection. The HAL device code further requires that
the DBus connection is integrated with the event loop and
provides such glue logic itself.
The forthcoming FirewallD integration also requires a
dbus connection with event loop integration. Thus we need
to pull the current event loop glue out of the HAL driver.
Thus we create src/util/virdbus.{c,h} files. This contains
just one method virDBusGetSystemBus() which obtains a handle
to the single shared system bus instance, with event glue
automagically setup.
---
.gitignore | 6 +-
configure.ac | 37 ++++++-
daemon/Makefile.am | 3 +-
daemon/libvirtd.c | 4 -
daemon/remote.c | 8 +-
include/libvirt/virterror.h | 1 +
src/Makefile.am | 13 +--
src/libvirt_dbus.syms | 2 -
src/node_device/node_device_hal.c | 143 ++------------------------
src/rpc/virnetserver.c | 40 --------
src/rpc/virnetserver.h | 8 --
src/util/virdbus.c | 201 +++++++++++++++++++++++++++++++++++++
src/util/virdbus.h | 34 ++++++
src/util/virterror.c | 3 +
14 files changed, 296 insertions(+), 207 deletions(-)
delete mode 100644 src/libvirt_dbus.syms
create mode 100644 src/util/virdbus.c
create mode 100644 src/util/virdbus.h
diff --git a/.gitignore b/.gitignore
index 5aa9c9b..14a21d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,12 +48,12 @@
/daemon/*_dispatch.h
/daemon/libvirt_qemud
/daemon/libvirtd
-/daemon/libvirtd.init
-/daemon/libvirtd.service
/daemon/libvirtd*.logrotate
/daemon/libvirtd.8
/daemon/libvirtd.8.in
+/daemon/libvirtd.init
/daemon/libvirtd.pod
+/daemon/libvirtd.service
/docs/devhelp/libvirt.devhelp
/docs/hvsupport.html.in
/docs/libvirt-api.xml
@@ -118,6 +118,7 @@
/tests/eventtest
/tests/hashtest
/tests/jsontest
+/tests/libvirtdconftest
/tests/networkxml2argvtest
/tests/nodeinfotest
/tests/nwfilterxml2xmltest
@@ -150,7 +151,6 @@
/tests/vmx2xmltest
/tests/xencapstest
/tests/xmconfigtest
-/tests/libvirtdconftest
/tools/*.[18]
/tools/libvirt-guests.init
/tools/virsh
diff --git a/configure.ac b/configure.ac
index 3f5b3ff..f49b620 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,6 +74,7 @@ LIBPCAP_REQUIRED="1.0.0"
LIBNL_REQUIRED="1.1"
LIBSSH2_REQUIRED="1.0"
LIBBLKID_REQUIRED="2.17"
+DBUS_REQUIRED="1.0.0"
dnl Checks for C compiler.
AC_PROG_CC
@@ -1099,6 +1100,36 @@ AC_SUBST([SANLOCK_CFLAGS])
AC_SUBST([SANLOCK_LIBS])
+dnl DBus library
+DBUS_CFLAGS=
+DBUS_LIBS=
+AC_ARG_WITH([dbus],
+ AC_HELP_STRING([--with-dbus], [enable communication with DBus
@<:@default=check@:>@]),
+ [],
+ [with_dbus=check])
+if test "$with_dbus" = "yes" || test "$with_dbus" =
"check" ; then
+ PKG_CHECK_MODULES(DBUS, dbus-1 >= $DBUS_REQUIRED,
+ [with_dbus=yes], [
+ if test "$with_dbus" = "check" ; then
+ with_dbus=no
+ else
+ AC_MSG_ERROR([You must install DBus >= $DBUS_REQUIRED to compile libvirt])
+ fi])
+fi
+
+if test "$with_dbus" = "yes" ; then
+ AC_DEFINE_UNQUOTED([HAVE_DBUS], 1, [enable communication with DBus])
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$LIBS $DBUS_LIBS"
+ CFLAGS="$CFLAGS $DBUS_CFLAGS"
+ AC_CHECK_FUNCS([dbus_watch_get_unix_fd])
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+
dnl PolicyKit library
POLKIT_CFLAGS=
POLKIT_LIBS=
@@ -1109,7 +1140,6 @@ AC_ARG_WITH([polkit],
[with_polkit=check])
with_polkit0=no
-with_dbus=no
with_polkit1=no
if test "x$with_polkit" = "xyes" || test "x$with_polkit" =
"xcheck"; then
dnl Check for new polkit first - just a binary
@@ -1138,8 +1168,6 @@ if test "x$with_polkit" = "xyes" || test
"x$with_polkit" = "xcheck"; then
[use PolicyKit for UNIX socket access checks])
AC_DEFINE_UNQUOTED([HAVE_POLKIT0], 1,
[use PolicyKit for UNIX socket access checks])
- AC_DEFINE_UNQUOTED([HAVE_DBUS], 1,
- [use DBus for PolicyKit])
old_CFLAGS=$CFLAGS
old_LIBS=$LIBS
@@ -1154,13 +1182,11 @@ if test "x$with_polkit" = "xyes" || test
"x$with_polkit" = "xcheck"; then
AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of
polkit-auth program])
fi
with_polkit0="yes"
- with_dbus="yes"
fi
fi
fi
AM_CONDITIONAL([HAVE_POLKIT], [test "x$with_polkit" = "xyes"])
AM_CONDITIONAL([HAVE_POLKIT0], [test "x$with_polkit0" = "xyes"])
-AM_CONDITIONAL([HAVE_DBUS], [test "x$with_dbus" = "xyes"])
AM_CONDITIONAL([HAVE_POLKIT1], [test "x$with_polkit1" = "xyes"])
AC_SUBST([POLKIT_CFLAGS])
AC_SUBST([POLKIT_LIBS])
@@ -2413,7 +2439,6 @@ if test "x$with_hal" = "xyes" || test
"x$with_hal" = "xcheck"; then
CFLAGS="$CFLAGS $HAL_CFLAGS"
LIBS="$LIBS $HAL_LIBS"
AC_CHECK_FUNCS([libhal_get_all_devices],,[with_hal=no])
- AC_CHECK_FUNCS([dbus_watch_get_unix_fd])
CFLAGS="$old_CFLAGS"
LIBS="$old_LIBS"
fi
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 5d9f5d7..24cce8f 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -94,7 +94,7 @@ libvirtd_SOURCES = $(DAEMON_SOURCES)
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
libvirtd_CFLAGS = \
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
- $(XDR_CFLAGS) $(POLKIT_CFLAGS) \
+ $(XDR_CFLAGS) $(POLKIT_CFLAGS) $(DBUS_CFLAGS) \
$(WARN_CFLAGS) \
$(COVERAGE_CFLAGS) \
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
@@ -108,6 +108,7 @@ libvirtd_LDADD = \
$(LIBXML_LIBS) \
$(GNUTLS_LIBS) \
$(SASL_LIBS) \
+ $(DBUS_LIBS) \
$(POLKIT_LIBS)
if WITH_DTRACE_PROBES
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index ce931d4..b098f6a 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -812,7 +812,6 @@ int main(int argc, char **argv) {
struct daemonConfig *config;
bool privileged = geteuid() == 0 ? true : false;
bool implicit_conf = false;
- bool use_polkit_dbus;
char *run_dir = NULL;
mode_t old_umask;
@@ -1008,8 +1007,6 @@ int main(int argc, char **argv) {
goto cleanup;
}
- use_polkit_dbus = config->auth_unix_rw == REMOTE_AUTH_POLKIT ||
- config->auth_unix_ro == REMOTE_AUTH_POLKIT;
if (!(srv = virNetServerNew(config->min_workers,
config->max_workers,
config->prio_workers,
@@ -1018,7 +1015,6 @@ int main(int argc, char **argv) {
config->keepalive_count,
!!config->keepalive_required,
config->mdns_adv ? config->mdns_name : NULL,
- use_polkit_dbus,
remoteClientInitHook))) {
ret = VIR_DAEMON_ERR_INIT;
goto cleanup;
diff --git a/daemon/remote.c b/daemon/remote.c
index b71ffa2..16a8a05 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -45,7 +45,7 @@
#include "virnetserver.h"
#include "virfile.h"
#include "virtypedparam.h"
-
+#include "virdbus.h"
#include "remote_protocol.h"
#include "qemu_protocol.h"
@@ -2672,6 +2672,7 @@ remoteDispatchAuthPolkit(virNetServerPtr server,
char *ident = NULL;
struct daemonClientPrivate *priv =
virNetServerClientGetPrivateData(client);
+ DBusConnection *sysbus;
virMutexLock(&priv->lock);
@@ -2697,10 +2698,13 @@ remoteDispatchAuthPolkit(virNetServerPtr server,
goto authfail;
}
+ if (!(sysbus = virDBusGetSystemBus()))
+ goto authfail;
+
VIR_INFO("Checking PID %lld running as %d",
(long long) callerPid, callerUid);
dbus_error_init(&err);
- if (!(pkcaller = polkit_caller_new_from_pid(virNetServerGetDBusConn(server),
+ if (!(pkcaller = polkit_caller_new_from_pid(sysbus,
callerPid, &err))) {
VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
dbus_error_free(&err);
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index e04d29e..cda15ff 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -87,6 +87,7 @@ typedef enum {
VIR_FROM_CAPABILITIES = 44, /* Error from capabilities */
VIR_FROM_URI = 45, /* Error from URI handling */
VIR_FROM_AUTH = 46, /* Error from auth handling */
+ VIR_FROM_DBUS = 47, /* Error from DBus */
} virErrorDomain;
diff --git a/src/Makefile.am b/src/Makefile.am
index a2aae9d..b8a19b4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -88,6 +88,7 @@ UTIL_SOURCES = \
util/virtypedparam.c util/virtypedparam.h \
util/xml.c util/xml.h \
util/virterror.c util/virterror_internal.h \
+ util/virdbus.c util/virdbus.h \
util/virhash.c util/virhash.h \
util/virhashcode.c util/virhashcode.h \
util/virkeycode.c util/virkeycode.h \
@@ -574,10 +575,11 @@ libvirt_la_BUILT_LIBADD = libvirt_util.la
libvirt_util_la_SOURCES = \
$(UTIL_SOURCES)
libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS) $(YAJL_CFLAGS) $(LIBNL_CFLAGS) \
- $(AM_CFLAGS) $(AUDIT_CFLAGS) $(DEVMAPPER_CFLAGS)
+ $(AM_CFLAGS) $(AUDIT_CFLAGS) $(DEVMAPPER_CFLAGS) \
+ $(DBUS_CFLAGS)
libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
$(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \
- $(RT_LIBS)
+ $(RT_LIBS) $(DBUS_LIBS)
noinst_LTLIBRARIES += libvirt_conf.la
@@ -1198,10 +1200,6 @@ if WITH_LINUX
USED_SYM_FILES += libvirt_linux.syms
endif
-if HAVE_DBUS
-USED_SYM_FILES += libvirt_dbus.syms
-endif
-
if WITH_LIBVIRTD
USED_SYM_FILES += libvirt_daemon.syms
endif
@@ -1525,7 +1523,7 @@ libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
libvirt_lxc_LDADD = $(CAPNG_LIBS) $(YAJL_LIBS) \
$(LIBXML_LIBS) $(NUMACTL_LIBS) $(THREAD_LIBS) \
$(LIBNL_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \
- $(RT_LIBS) \
+ $(RT_LIBS) $(DBUS_LIBS) \
../gnulib/lib/libgnu.la
if WITH_DTRACE_PROBES
libvirt_lxc_LDADD += probes.o
@@ -1542,6 +1540,7 @@ libvirt_lxc_CFLAGS = \
$(CAPNG_CFLAGS) \
$(YAJL_CFLAGS) \
$(AUDIT_CFLAGS) \
+ $(DBUS_CFLAGS) \
-I$(top_srcdir)/src/conf \
$(AM_CFLAGS)
if HAVE_LIBBLKID
diff --git a/src/libvirt_dbus.syms b/src/libvirt_dbus.syms
deleted file mode 100644
index a460ec5..0000000
--- a/src/libvirt_dbus.syms
+++ /dev/null
@@ -1,2 +0,0 @@
-# virnetserver.h
-virNetServerGetDBusConn;
diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_device_hal.c
index a028886..dd14271 100644
--- a/src/node_device/node_device_hal.c
+++ b/src/node_device/node_device_hal.c
@@ -39,6 +39,7 @@
#include "logging.h"
#include "node_device_driver.h"
#include "ignore-value.h"
+#include "virdbus.h"
#define VIR_FROM_THIS VIR_FROM_NODEDEV
@@ -586,124 +587,15 @@ static void device_prop_modified(LibHalContext *ctx
ATTRIBUTE_UNUSED,
}
-static void dbus_watch_callback(int fdatch ATTRIBUTE_UNUSED,
- int fd ATTRIBUTE_UNUSED,
- int events, void *opaque)
-{
- DBusWatch *watch = opaque;
- LibHalContext *hal_ctx;
- DBusConnection *dbus_conn;
- int dbus_flags = 0;
-
- if (events & VIR_EVENT_HANDLE_READABLE)
- dbus_flags |= DBUS_WATCH_READABLE;
- if (events & VIR_EVENT_HANDLE_WRITABLE)
- dbus_flags |= DBUS_WATCH_WRITABLE;
- if (events & VIR_EVENT_HANDLE_ERROR)
- dbus_flags |= DBUS_WATCH_ERROR;
- if (events & VIR_EVENT_HANDLE_HANGUP)
- dbus_flags |= DBUS_WATCH_HANGUP;
-
- (void)dbus_watch_handle(watch, dbus_flags);
-
- nodeDeviceLock(driverState);
- hal_ctx = DRV_STATE_HAL_CTX(driverState);
- dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
- nodeDeviceUnlock(driverState);
- while (dbus_connection_dispatch(dbus_conn) == DBUS_DISPATCH_DATA_REMAINS)
- /* keep dispatching while data remains */;
-}
-
-
-static int xlate_dbus_watch_flags(int dbus_flags)
-{
- unsigned int flags = 0;
- if (dbus_flags & DBUS_WATCH_READABLE)
- flags |= VIR_EVENT_HANDLE_READABLE;
- if (dbus_flags & DBUS_WATCH_WRITABLE)
- flags |= VIR_EVENT_HANDLE_WRITABLE;
- if (dbus_flags & DBUS_WATCH_ERROR)
- flags |= VIR_EVENT_HANDLE_ERROR;
- if (dbus_flags & DBUS_WATCH_HANGUP)
- flags |= VIR_EVENT_HANDLE_HANGUP;
- return flags;
-}
-
-
-struct nodeDeviceWatchInfo
-{
- int watch;
-};
-
-static void nodeDeviceWatchFree(void *data) {
- struct nodeDeviceWatchInfo *info = data;
- VIR_FREE(info);
-}
-
-static dbus_bool_t add_dbus_watch(DBusWatch *watch,
- void *data ATTRIBUTE_UNUSED)
-{
- int flags = 0;
- int fd;
- struct nodeDeviceWatchInfo *info;
-
- if (VIR_ALLOC(info) < 0)
- return 0;
-
- if (dbus_watch_get_enabled(watch))
- flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch));
-
-#if HAVE_DBUS_WATCH_GET_UNIX_FD
- fd = dbus_watch_get_unix_fd(watch);
-#else
- fd = dbus_watch_get_fd(watch);
-#endif
- info->watch = virEventAddHandle(fd, flags, dbus_watch_callback,
- watch, NULL);
- if (info->watch < 0) {
- VIR_FREE(info);
- return 0;
- }
- dbus_watch_set_data(watch, info, nodeDeviceWatchFree);
-
- return 1;
-}
-
-
-static void remove_dbus_watch(DBusWatch *watch,
- void *data ATTRIBUTE_UNUSED)
-{
- struct nodeDeviceWatchInfo *info;
-
- info = dbus_watch_get_data(watch);
-
- (void)virEventRemoveHandle(info->watch);
-}
-
-
-static void toggle_dbus_watch(DBusWatch *watch,
- void *data ATTRIBUTE_UNUSED)
-{
- int flags = 0;
- struct nodeDeviceWatchInfo *info;
-
- if (dbus_watch_get_enabled(watch))
- flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch));
-
- info = dbus_watch_get_data(watch);
-
- (void)virEventUpdateHandle(info->watch, flags);
-}
static int halDeviceMonitorStartup(int privileged ATTRIBUTE_UNUSED)
{
LibHalContext *hal_ctx = NULL;
- DBusConnection *dbus_conn = NULL;
- DBusError err;
char **udi = NULL;
int num_devs, i;
int ret = -1;
+ DBusConnection *sysbus;
/* Ensure caps_tbl is sorted by capability name */
qsort(caps_tbl, ARRAY_CARDINALITY(caps_tbl), sizeof(caps_tbl[0]),
@@ -718,26 +610,19 @@ static int halDeviceMonitorStartup(int privileged ATTRIBUTE_UNUSED)
}
nodeDeviceLock(driverState);
- /* Allocate and initialize a new HAL context */
- dbus_connection_set_change_sigpipe(FALSE);
- dbus_threads_init_default();
+ if (!(sysbus == virDBusGetSystemBus())) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("DBus not available, disabling HAL driver: %s",
+ err->message));
+ ret = 0;
+ goto failure;
+ }
- dbus_error_init(&err);
hal_ctx = libhal_ctx_new();
if (hal_ctx == NULL) {
VIR_ERROR(_("libhal_ctx_new returned NULL"));
goto failure;
}
- dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (dbus_conn == NULL) {
- VIR_ERROR(_("dbus_bus_get failed"));
- /* We don't want to show a fatal error here,
- otherwise entire libvirtd shuts down when
- D-Bus isn't running */
- ret = 0;
- goto failure;
- }
- dbus_connection_set_exit_on_disconnect(dbus_conn, FALSE);
if (!libhal_ctx_set_dbus_connection(hal_ctx, dbus_conn)) {
VIR_ERROR(_("libhal_ctx_set_dbus_connection failed"));
@@ -752,16 +637,6 @@ static int halDeviceMonitorStartup(int privileged ATTRIBUTE_UNUSED)
goto failure;
}
- /* Register dbus watch callbacks */
- if (!dbus_connection_set_watch_functions(dbus_conn,
- add_dbus_watch,
- remove_dbus_watch,
- toggle_dbus_watch,
- NULL, NULL)) {
- VIR_ERROR(_("dbus_connection_set_watch_functions failed"));
- goto failure;
- }
-
/* Populate with known devices */
driverState->privateData = hal_ctx;
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index f761e6b..3965fc2 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -39,9 +39,6 @@
#if HAVE_AVAHI
# include "virnetservermdns.h"
#endif
-#if HAVE_DBUS
-# include <dbus/dbus.h>
-#endif
#define VIR_FROM_THIS VIR_FROM_RPC
#define virNetError(code, ...) \
@@ -88,10 +85,6 @@ struct _virNetServer {
virNetServerMDNSGroupPtr mdnsGroup;
#endif
-#if HAVE_DBUS
- DBusConnection *sysbus;
-#endif
-
size_t nservices;
virNetServerServicePtr *services;
@@ -311,7 +304,6 @@ virNetServerPtr virNetServerNew(size_t min_workers,
unsigned int keepaliveCount,
bool keepaliveRequired,
const char *mdnsGroupName,
- bool connectDBus ATTRIBUTE_UNUSED,
virNetServerClientInitHook clientInitHook)
{
virNetServerPtr srv;
@@ -353,25 +345,6 @@ virNetServerPtr virNetServerNew(size_t min_workers,
}
#endif
-#if HAVE_DBUS
- if (connectDBus) {
- DBusError derr;
-
- dbus_connection_set_change_sigpipe(FALSE);
- dbus_threads_init_default();
-
- dbus_error_init(&derr);
- srv->sysbus = dbus_bus_get(DBUS_BUS_SYSTEM, &derr);
- if (!(srv->sysbus)) {
- VIR_ERROR(_("Failed to connect to system bus for PolicyKit auth:
%s"),
- derr.message);
- dbus_error_free(&derr);
- goto error;
- }
- dbus_connection_set_exit_on_disconnect(srv->sysbus, FALSE);
- }
-#endif
-
if (virMutexInit(&srv->lock) < 0) {
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot initialize mutex"));
@@ -429,14 +402,6 @@ bool virNetServerIsPrivileged(virNetServerPtr srv)
}
-#if HAVE_DBUS
-DBusConnection* virNetServerGetDBusConn(virNetServerPtr srv)
-{
- return srv->sysbus;
-}
-#endif
-
-
void virNetServerAutoShutdown(virNetServerPtr srv,
unsigned int timeout,
virNetServerAutoShutdownFunc func,
@@ -828,11 +793,6 @@ void virNetServerFree(virNetServerPtr srv)
virNetServerMDNSFree(srv->mdns);
#endif
-#if HAVE_DBUS
- if (srv->sysbus)
- dbus_connection_unref(srv->sysbus);
-#endif
-
virNetServerUnlock(srv);
virMutexDestroy(&srv->lock);
VIR_FREE(srv);
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index a04ffdd..0ebe00e 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -25,9 +25,6 @@
# define __VIR_NET_SERVER_H__
# include <signal.h>
-# if HAVE_DBUS
-# include <dbus/dbus.h>
-# endif
# include "virnettlscontext.h"
# include "virnetserverprogram.h"
@@ -45,7 +42,6 @@ virNetServerPtr virNetServerNew(size_t min_workers,
unsigned int keepaliveCount,
bool keepaliveRequired,
const char *mdnsGroupName,
- bool connectDBus,
virNetServerClientInitHook clientInitHook);
typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void *opaque);
@@ -54,10 +50,6 @@ void virNetServerRef(virNetServerPtr srv);
bool virNetServerIsPrivileged(virNetServerPtr srv);
-# if HAVE_DBUS
-DBusConnection* virNetServerGetDBusConn(virNetServerPtr srv);
-# endif
-
void virNetServerAutoShutdown(virNetServerPtr srv,
unsigned int timeout,
virNetServerAutoShutdownFunc func,
diff --git a/src/util/virdbus.c b/src/util/virdbus.c
new file mode 100644
index 0000000..badfe8c
--- /dev/null
+++ b/src/util/virdbus.c
@@ -0,0 +1,201 @@
+/*
+ * virdbus.c: helper for using DBus
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#include "virdbus.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "logging.h"
+#include "threads.h"
+
+#define VIR_FROM_THIS VIR_FROM_DBUS
+
+#define virDBusReportError(code, ...) \
+ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+#ifdef HAVE_DBUS
+
+static DBusConnection *systembus = NULL;
+static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER;
+static DBusError dbuserr;
+
+static dbus_bool_t virDBusAddWatch(DBusWatch *watch, void *data);
+static void virDBusRemoveWatch(DBusWatch *watch, void *data);
+static void virDBusToggleWatch(DBusWatch *watch, void *data);
+
+static void virDBusSystemBusInit(void)
+{
+ /* Allocate and initialize a new HAL context */
+ dbus_connection_set_change_sigpipe(FALSE);
+ dbus_threads_init_default();
+
+ dbus_error_init(&dbuserr);
+ if (!(systembus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbuserr)))
+ return;
+
+ dbus_connection_set_exit_on_disconnect(systembus, FALSE);
+
+ /* Register dbus watch callbacks */
+ if (!dbus_connection_set_watch_functions(systembus,
+ virDBusAddWatch,
+ virDBusRemoveWatch,
+ virDBusToggleWatch,
+ NULL, NULL)) {
+ systembus = NULL;
+ return;
+ }
+}
+
+
+DBusConnection *virDBusGetSystemBus(void)
+{
+ if (virOnce(&once, virDBusSystemBusInit) < 0) {
+ virDBusReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to run one time DBus initializer"));
+ return NULL;
+ }
+
+ if (!systembus) {
+ virDBusReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to get DBus system bus connection: %s"),
+ dbuserr.message ? dbuserr.message : "watch setup
failed");
+ return NULL;
+ }
+
+ return systembus;
+}
+
+
+static void virDBusWatchCallback(int fdatch ATTRIBUTE_UNUSED,
+ int fd ATTRIBUTE_UNUSED,
+ int events, void *opaque)
+{
+ DBusWatch *watch = opaque;
+ int dbus_flags = 0;
+
+ if (events & VIR_EVENT_HANDLE_READABLE)
+ dbus_flags |= DBUS_WATCH_READABLE;
+ if (events & VIR_EVENT_HANDLE_WRITABLE)
+ dbus_flags |= DBUS_WATCH_WRITABLE;
+ if (events & VIR_EVENT_HANDLE_ERROR)
+ dbus_flags |= DBUS_WATCH_ERROR;
+ if (events & VIR_EVENT_HANDLE_HANGUP)
+ dbus_flags |= DBUS_WATCH_HANGUP;
+
+ (void)dbus_watch_handle(watch, dbus_flags);
+
+ while (dbus_connection_dispatch(systembus) == DBUS_DISPATCH_DATA_REMAINS)
+ /* keep dispatching while data remains */;
+}
+
+
+static int virDBusTranslateWatchFlags(int dbus_flags)
+{
+ unsigned int flags = 0;
+ if (dbus_flags & DBUS_WATCH_READABLE)
+ flags |= VIR_EVENT_HANDLE_READABLE;
+ if (dbus_flags & DBUS_WATCH_WRITABLE)
+ flags |= VIR_EVENT_HANDLE_WRITABLE;
+ if (dbus_flags & DBUS_WATCH_ERROR)
+ flags |= VIR_EVENT_HANDLE_ERROR;
+ if (dbus_flags & DBUS_WATCH_HANGUP)
+ flags |= VIR_EVENT_HANDLE_HANGUP;
+ return flags;
+}
+
+
+struct virDBusWatch
+{
+ int watch;
+};
+
+static void virDBusWatchFree(void *data) {
+ struct virDBusWatch *info = data;
+ VIR_FREE(info);
+}
+
+static dbus_bool_t virDBusAddWatch(DBusWatch *watch,
+ void *data ATTRIBUTE_UNUSED)
+{
+ int flags = 0;
+ int fd;
+ struct virDBusWatch *info;
+
+ if (VIR_ALLOC(info) < 0)
+ return 0;
+
+ if (dbus_watch_get_enabled(watch))
+ flags = virDBusTranslateWatchFlags(dbus_watch_get_flags(watch));
+
+# if HAVE_DBUS_WATCH_GET_UNIX_FD
+ fd = dbus_watch_get_unix_fd(watch);
+# else
+ fd = dbus_watch_get_fd(watch);
+# endif
+ info->watch = virEventAddHandle(fd, flags,
+ virDBusWatchCallback,
+ watch, NULL);
+ if (info->watch < 0) {
+ VIR_FREE(info);
+ return 0;
+ }
+ dbus_watch_set_data(watch, info, virDBusWatchFree);
+
+ return 1;
+}
+
+
+static void virDBusRemoveWatch(DBusWatch *watch,
+ void *data ATTRIBUTE_UNUSED)
+{
+ struct virDBusWatch *info;
+
+ info = dbus_watch_get_data(watch);
+
+ (void)virEventRemoveHandle(info->watch);
+}
+
+
+static void virDBusToggleWatch(DBusWatch *watch,
+ void *data ATTRIBUTE_UNUSED)
+{
+ int flags = 0;
+ struct virDBusWatch *info;
+
+ if (dbus_watch_get_enabled(watch))
+ flags = virDBusTranslateWatchFlags(dbus_watch_get_flags(watch));
+
+ info = dbus_watch_get_data(watch);
+
+ (void)virEventUpdateHandle(info->watch, flags);
+}
+
+#else /* ! HAVE_DBUS */
+DBusConnection *virDBusGetSystemBus(void)
+{
+ virDBusReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("DBus support not compiled into this
binary"));
+ return NULL;
+}
+
+#endif /* ! HAVE_DBUS */
diff --git a/src/util/virdbus.h b/src/util/virdbus.h
new file mode 100644
index 0000000..7d9ec8f
--- /dev/null
+++ b/src/util/virdbus.h
@@ -0,0 +1,34 @@
+/*
+ * virdbus.h: helper for using DBus
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __VIR_DBUS_H__
+# define __VIR_DBUS_H__
+
+# ifdef HAVE_DBUS
+# include <dbus/dbus.h>
+# else
+# define DBusConnection void
+# endif
+# include "internal.h"
+
+DBusConnection *virDBusGetSystemBus(void);
+
+#endif /* __VIR_DBUS_H__ */
diff --git a/src/util/virterror.c b/src/util/virterror.c
index ff9a36f..de45bb0 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -184,6 +184,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_AUTH:
dom = "Auth ";
break;
+ case VIR_FROM_DBUS:
+ dom = "DBus ";
+ break;
}
return dom;
}
--
1.7.7.6