[libvirt] [dbus PATCH 7/8] switch from sd-bus to GDBus implementation

Pavel Hrdina phrdina at redhat.com
Mon Mar 19 09:30:51 UTC 2018


This removes all the sd-bus code and uses GDBus instead.

Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
---
 README                       |   1 -
 configure.ac                 |   3 -
 data/Makefile.am             |   4 +-
 data/org.libvirt.Connect.xml |  56 ++++
 data/org.libvirt.Domain.xml  |  51 +++
 libvirt-dbus.spec.in         |   4 +-
 src/Makefile.am              |   3 -
 src/connect.c                | 316 ++++++++-----------
 src/connect.h                |  35 +--
 src/domain.c                 | 729 +++++++++++++++++++------------------------
 src/domain.h                 |   7 +-
 src/events.c                 | 177 +++++------
 src/main.c                   | 299 +++++++-----------
 src/util.c                   | 170 +++++-----
 src/util.h                   |  53 ++--
 test/travis-run              |   2 +-
 16 files changed, 855 insertions(+), 1055 deletions(-)
 create mode 100644 data/org.libvirt.Connect.xml
 create mode 100644 data/org.libvirt.Domain.xml

diff --git a/README b/README
index a85114e..b95b09b 100644
--- a/README
+++ b/README
@@ -56,7 +56,6 @@ raised in future releases based on this distro build target policy.
 
 The packages required to build libvirt-dbus are
 
- - systemd-211
  - libvirt
  - glib2
 
diff --git a/configure.ac b/configure.ac
index d6ed0ef..6db5a59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,11 +13,9 @@ AM_SILENT_RULES([yes])
 
 GLIB2_REQUIRED=2.50.0
 LIBVIRT_REQUIRED=AC_PACKAGE_VERSION
-SYSTEMD_REQUIRED=211
 LIBVIRT_GLIB_REQUIRED=1.0.0
 AC_SUBST([GLIB2_REQUIRED]) dnl used in the .spec file
 AC_SUBST([LIBVIRT_REQUIRED]) dnl used in the .spec file
-AC_SUBST([SYSTEMD_REQUIRED]) dnl used in the .spec file
 AC_SUBST([LIBVIRT_GLIB_REQUIRED]) dnl used in the .spec file
 
 LIBVIRT_DBUS_MAJOR_VERSION=`echo $VERSION | awk -F. '{print $1}'`
@@ -41,7 +39,6 @@ AC_PROG_CC_STDC
 PKG_CHECK_MODULES(GIO2, gio-unix-2.0 >= GLIB2_REQUIRED)
 PKG_CHECK_MODULES(GLIB2, glib-2.0 >= GLIB2_REQUIRED)
 PKG_CHECK_MODULES(LIBVIRT, libvirt >= $LIBVIRT_REQUIRED)
-PKG_CHECK_MODULES(SYSTEMD, libsystemd >= $SYSTEMD_REQUIRED)
 PKG_CHECK_MODULES(LIBVIRT_GLIB, libvirt-glib-1.0 >= LIBVIRT_GLIB_REQUIRED)
 
 LIBVIRT_COMPILE_WARNINGS
diff --git a/data/Makefile.am b/data/Makefile.am
index a886687..dd60713 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -18,7 +18,9 @@ polkit_files = \
 polkitdir = $(sysconfdir)/polkit-1/rules.d
 polkit_DATA = $(polkit_files:.rules.in=.rules)
 
-interfaces_files =
+interfaces_files = \
+	org.libvirt.Connect.xml \
+	org.libvirt.Domain.xml
 interfacesdir = $(DBUS_INTERFACES_DIR)
 interfaces_DATA = $(interfaces_files)
 
diff --git a/data/org.libvirt.Connect.xml b/data/org.libvirt.Connect.xml
new file mode 100644
index 0000000..a40ce1d
--- /dev/null
+++ b/data/org.libvirt.Connect.xml
@@ -0,0 +1,56 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node name="/org/libvirt/connect">
+  <interface name="org.libvirt.Connect">
+    <method name="CreateXML">
+      <arg name="xml" type="s" direction="in"/>
+      <arg name="flags" type="u" direction="in"/>
+      <arg name="domain" type="o" direction="out"/>
+    </method>
+    <method name="DefineXML">
+      <arg name="xml" type="s" direction="in"/>
+      <arg name="domain" type="o" direction="out"/>
+    </method>
+    <method name="ListDomains">
+      <arg name="flags" type="u" direction="in"/>
+      <arg name="domains" type="ao" direction="out"/>
+    </method>
+    <signal name="DomainCrashed">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainDefined">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainPMSuspended">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainResumed">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainShutdown">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainStarted">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainStopped">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainSuspended">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+    <signal name="DomainUndefined">
+      <arg name="reason" type="s"/>
+      <arg name="domain" type="o"/>
+    </signal>
+  </interface>
+</node>
diff --git a/data/org.libvirt.Domain.xml b/data/org.libvirt.Domain.xml
new file mode 100644
index 0000000..48bf40f
--- /dev/null
+++ b/data/org.libvirt.Domain.xml
@@ -0,0 +1,51 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node name="/org/libvirt/domain">
+  <interface name="org.libvirt.Domain">
+    <property name="Name" type="s" access="read"/>
+    <property name="UUID" type="s" access="read"/>
+    <property name="Id" type="u" access="read"/>
+    <property name="Vcpus" type="u" access="read"/>
+    <property name="OSType" type="s" access="read"/>
+    <property name="Active" type="b" access="read"/>
+    <property name="Persistent" type="b" access="read"/>
+    <property name="State" type="s" access="read"/>
+    <property name="Autostart" type="b" access="read"/>
+    <method name="GetXMLDesc">
+      <arg name="flags" type="u" direction="in"/>
+      <arg name="xml" type="s" direction="out"/>
+    </method>
+    <method name="GetStats">
+      <arg name="stats" type="u" direction="in"/>
+      <arg name="flags" type="u" direction="in"/>
+      <arg name="records" type="a{sv}" direction="out"/>
+    </method>
+    <method name="Shutdown"/>
+    <method name="Destroy"/>
+    <method name="Reboot">
+      <arg name="flags" type="u" direction="in"/>
+    </method>
+    <method name="Reset">
+      <arg name="flags" type="u" direction="in"/>
+    </method>
+    <method name="Create"/>
+    <method name="Undefine"/>
+    <signal name="DeviceAdded">
+      <arg name="device" type="s"/>
+    </signal>
+    <signal name="DeviceRemoved">
+      <arg name="device" type="s"/>
+    </signal>
+    <signal name="DiskChange">
+      <arg name="oldSrcPath" type="s"/>
+      <arg name="newSrcPath" type="s"/>
+      <arg name="device" type="s"/>
+      <arg name="reason" type="s"/>
+    </signal>
+    <signal name="TrayChange">
+      <arg name="device" type="s"/>
+      <arg name="reason" type="s"/>
+    </signal>
+  </interface>
+</node>
diff --git a/libvirt-dbus.spec.in b/libvirt-dbus.spec.in
index 662ece1..eb531bb 100644
--- a/libvirt-dbus.spec.in
+++ b/libvirt-dbus.spec.in
@@ -2,7 +2,6 @@
 
 %define glib2_version @GLIB2_REQUIRED@
 %define libvirt_version @LIBVIRT_REQUIRED@
-%define systemd_version @SYSTEMD_REQUIRED@
 %define libvirt_glib_version @LIBVIRT_GLIB_REQUIRED@
 %define system_user @SYSTEM_USER@
 
@@ -19,12 +18,10 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: gcc
 BuildRequires: glib2-devel >= %{glib2_version}
 BuildRequires: libvirt-devel >= %{libvirt_version}
-BuildRequires: systemd-devel >= %{systemd_version}
 BuildRequires: libvirt-glib-devel >= %{libvirt_glib_version}
 
 Requires: glib2 >= %{glib2_version}
 Requires: libvirt-libs >= %{libvirt_version}
-Requires: systemd-libs >= %{systemd_version}
 Requires: libvirt-glib >= %{libvirt_glib_version}
 
 Requires(pre): shadow-utils
@@ -61,5 +58,6 @@ exit 0
 %{_datadir}/dbus-1/services/org.libvirt.service
 %{_datadir}/dbus-1/system-services/org.libvirt.service
 %{_datadir}/dbus-1/system.d/org.libvirt.conf
+%{_datadir}/dbus-1/interfaces/org.libvirt.*.xml
 
 %changelog
diff --git a/src/Makefile.am b/src/Makefile.am
index e7bba9d..7248561 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,7 +19,6 @@ bin_PROGRAMS = libvirt-dbus
 libvirt_dbus_SOURCES = $(DAEMON_SOURCES)
 
 libvirt_dbus_CFLAGS = \
-	$(SYSTEMD_CFLAGS) \
 	$(GIO2_CFLAGS) \
 	$(GLIB2_CFLAGS) \
 	$(LIBVIRT_CFLAGS) \
@@ -29,7 +28,6 @@ libvirt_dbus_CFLAGS = \
 	$(NULL)
 
 libvirt_dbus_LDFLAGS = \
-	$(SYSTEMD_LDFLAGS) \
 	$(GIO2_LDFLAGS) \
 	$(GLIB2_LDFLAGS) \
 	$(LIBVIRT_LDFLAGS) \
@@ -39,7 +37,6 @@ libvirt_dbus_LDFLAGS = \
 	$(NULL)
 
 libvirt_dbus_LDADD = \
-	$(SYSTEMD_LIBS) \
 	$(GIO2_LIBS) \
 	$(GLIB2_LIBS) \
 	$(LIBVIRT_LIBS) \
diff --git a/src/connect.c b/src/connect.c
index 695fc0d..a3b1cf2 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -1,12 +1,11 @@
+#include "connect.h"
 #include "domain.h"
 #include "events.h"
-#include "connect.h"
 #include "util.h"
 
-#include <stdbool.h>
-#include <stdlib.h>
+#include <glib/gprintf.h>
 
-static int virtDBusConnectCredType[] = {
+static gint virtDBusConnectCredType[] = {
     VIR_CRED_AUTHNAME,
     VIR_CRED_ECHOPROMPT,
     VIR_CRED_REALM,
@@ -15,31 +14,31 @@ static int virtDBusConnectCredType[] = {
     VIR_CRED_EXTERNAL,
 };
 
-static int
-virtDBusConnectAuthCallback(virConnectCredentialPtr cred VIRT_ATTR_UNUSED,
-                            unsigned int ncred VIRT_ATTR_UNUSED,
-                            void *cbdata)
+static gint
+virtDBusConnectAuthCallback(virConnectCredentialPtr cred G_GNUC_UNUSED,
+                            guint ncred G_GNUC_UNUSED,
+                            gpointer cbdata)
 {
-    sd_bus_error *error = cbdata;
-
-    return virtDBusUtilSetError(error,
-                                "Interactive authentication is not supported. "
-                                "Use client configuration file for libvirt.");
+    GError **error = cbdata;
+    g_set_error(error, VIRT_DBUS_ERROR, VIRT_DBUS_ERROR_LIBVIRT,
+                "Interactive authentication is not supported. "
+                "Use client configuration file for libvirt.");
+    return -1;
 }
 
 static virConnectAuth virtDBusConnectAuth = {
     virtDBusConnectCredType,
-    VIRT_N_ELEMENTS(virtDBusConnectCredType),
+    G_N_ELEMENTS(virtDBusConnectCredType),
     virtDBusConnectAuthCallback,
     NULL,
 };
 
 static void
 virtDBusConnectClose(virtDBusConnect *connect,
-                     bool deregisterEvents)
+                     gboolean deregisterEvents)
 {
 
-    for (int i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i += 1) {
+    for (gint i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i += 1) {
         if (connect->callback_ids[i] >= 0) {
             if (deregisterEvents) {
                 virConnectDomainEventDeregisterAny(connect->connection,
@@ -53,130 +52,91 @@ virtDBusConnectClose(virtDBusConnect *connect,
     connect->connection = NULL;
 }
 
-int
+gboolean
 virtDBusConnectOpen(virtDBusConnect *connect,
-                    sd_bus_error *error)
+                    GError **error)
 {
     if (connect->connection) {
         if (virConnectIsAlive(connect->connection))
-            return 0;
+            return TRUE;
         else
-            virtDBusConnectClose(connect, false);
+            virtDBusConnectClose(connect, FALSE);
     }
 
     virtDBusConnectAuth.cbdata = error;
 
     connect->connection = virConnectOpenAuth(connect->uri,
                                              &virtDBusConnectAuth, 0);
-    if (!connect->connection)
-        return virtDBusUtilSetLastVirtError(error);
+    if (!connect->connection) {
+        if (!*error)
+            virtDBusUtilSetLastVirtError(error);
+        return FALSE;
+    }
 
     virtDBusEventsRegister(connect);
 
-    return 0;
+    return TRUE;
 }
 
-static int
-virtDBusConnectEnumarateDomains(sd_bus *bus VIRT_ATTR_UNUSED,
-                                const char *path VIRT_ATTR_UNUSED,
-                                void *userdata,
-                                char ***nodes,
-                                sd_bus_error *error)
+static void
+virtDBusConnectListDomains(GVariant *inArgs,
+                           GUnixFDList *inFDs G_GNUC_UNUSED,
+                           const gchar *objectPath G_GNUC_UNUSED,
+                           gpointer userData,
+                           GVariant **outArgs,
+                           GUnixFDList **outFDs G_GNUC_UNUSED,
+                           GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainListFreep) virDomainPtr *domains = NULL;
-    _cleanup_(virtDBusUtilStrvFreep) char **paths = NULL;
-    int n_domains;
-    int r;
-
-    r = virtDBusConnectOpen(connect, error);
-    if (r < 0)
-        return r;
-
-    n_domains = virConnectListAllDomains(connect->connection, &domains, 0);
-    if (n_domains < 0)
-        return virtDBusUtilSetLastVirtError(error);
-
-    paths = calloc(n_domains + 1, sizeof(char *));
-
-    for (int i = 0; i < n_domains; i += 1)
-        paths[i] = virtDBusUtilBusPathForVirDomain(domains[i],
-                                                   connect->domainPath);
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomainPtr) domains = NULL;
+    guint flags;
+    GVariantBuilder builder;
+    GVariant *gdomains;
 
-    *nodes = paths;
-    paths = NULL;
+    g_variant_get(inArgs, "(u)", &flags);
 
-    return 0;
-}
+    if (!virtDBusConnectOpen(connect, error))
+        return;
 
-static int
-virtDBusConnectListDomains(sd_bus_message *message,
-                           void *userdata,
-                           sd_bus_error *error)
-{
-    virtDBusConnect *connect = userdata;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-    _cleanup_(virtDBusUtilVirDomainListFreep) virDomainPtr *domains = NULL;
-    uint32_t flags;
-    int r;
-
-    r = sd_bus_message_read(message, "u", &flags);
-    if (r < 0)
-        return r;
-
-    r = virtDBusConnectOpen(connect, error);
-    if (r < 0)
-        return r;
-
-    r = virConnectListAllDomains(connect->connection, &domains, flags);
-    if (r < 0)
+    if (virConnectListAllDomains(connect->connection, &domains, flags) < 0)
         return virtDBusUtilSetLastVirtError(error);
 
-    r = sd_bus_message_new_method_return(message, &reply);
-    if (r < 0)
-        return r;
-
-    r = sd_bus_message_open_container(reply, 'a', "o");
-    if (r < 0)
-        return r;
+    if (!*domains)
+        return;
 
-    for (int i = 0; domains[i] != NULL; i += 1) {
-        _cleanup_(virtDBusUtilFreep) char *path = NULL;
+    g_variant_builder_init(&builder, G_VARIANT_TYPE("ao"));
 
+    for (gint i = 0; domains[i]; i++) {
+        g_autofree gchar *path = NULL;
         path = virtDBusUtilBusPathForVirDomain(domains[i],
                                                connect->domainPath);
 
-        r = sd_bus_message_append(reply, "o", path);
-        if (r < 0)
-            return r;
+        g_variant_builder_add(&builder, "o", path);
     }
 
-    r = sd_bus_message_close_container(reply);
-    if (r < 0)
-        return r;
-
-    return sd_bus_send(NULL, reply, NULL);
+    gdomains = g_variant_builder_end(&builder);
+    *outArgs = g_variant_new_tuple(&gdomains, 1);
 }
 
-static int
-virtDBusConnectCreateXML(sd_bus_message *message,
-                         void *userdata,
-                         sd_bus_error *error)
+static void
+virtDBusConnectCreateXML(GVariant *inArgs,
+                         GUnixFDList *inFDs G_GNUC_UNUSED,
+                         const gchar *objectPath G_GNUC_UNUSED,
+                         gpointer userData,
+                         GVariant **outArgs,
+                         GUnixFDList **outFDs G_GNUC_UNUSED,
+                         GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    const char *xml;
-    uint32_t flags;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    int r;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    g_autofree gchar *path = NULL;
+    gchar *xml;
+    guint flags;
 
-    r = sd_bus_message_read(message, "su", &xml, &flags);
-    if (r < 0)
-        return r;
+    g_variant_get(inArgs, "(&su)", &xml, &flags);
 
-    r = virtDBusConnectOpen(connect, error);
-    if (r < 0)
-        return r;
+    if (!virtDBusConnectOpen(connect, error))
+        return;
 
     domain = virDomainCreateXML(connect->connection, xml, flags);
     if (!domain)
@@ -184,27 +144,27 @@ virtDBusConnectCreateXML(sd_bus_message *message,
 
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    return sd_bus_reply_method_return(message, "o", path);
+    *outArgs = g_variant_new("(o)", path);
 }
 
-static int
-virtDBusConnectDefineXML(sd_bus_message *message,
-                         void *userdata,
-                         sd_bus_error *error)
+static void
+virtDBusConnectDefineXML(GVariant *inArgs,
+                         GUnixFDList *inFDs G_GNUC_UNUSED,
+                         const gchar *objectPath G_GNUC_UNUSED,
+                         gpointer userData,
+                         GVariant **outArgs,
+                         GUnixFDList **outFDs G_GNUC_UNUSED,
+                         GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    const char *xml;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    int r;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    g_autofree gchar *path = NULL;
+    gchar *xml;
 
-    r = sd_bus_message_read(message, "s", &xml);
-    if (r < 0)
-        return r;
+    g_variant_get(inArgs, "(&s)", &xml);
 
-    r = virtDBusConnectOpen(connect, error);
-    if (r < 0)
-        return r;
+    if (!virtDBusConnectOpen(connect, error))
+        return;
 
     domain = virDomainDefineXML(connect->connection, xml);
     if (!domain)
@@ -212,97 +172,73 @@ virtDBusConnectDefineXML(sd_bus_message *message,
 
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    return sd_bus_reply_method_return(message, "o", path);
+    *outArgs = g_variant_new("(o)", path);
 }
 
-static const sd_bus_vtable virt_connect_vtable[] = {
-    SD_BUS_VTABLE_START(0),
+static virtDBusGDBusMethodTable virtDBusConnectMethodTable[] = {
+    { "ListDomains", virtDBusConnectListDomains },
+    { "CreateXML", virtDBusConnectCreateXML },
+    { "DefineXML", virtDBusConnectDefineXML },
+    { NULL, NULL }
+};
 
-    SD_BUS_METHOD("ListDomains", "u", "ao", virtDBusConnectListDomains, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("CreateXML", "su", "o", virtDBusConnectCreateXML, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("DefineXML", "s", "o", virtDBusConnectDefineXML, SD_BUS_VTABLE_UNPRIVILEGED),
+static GDBusInterfaceInfo *interfaceInfo = NULL;
 
-    SD_BUS_SIGNAL("DomainDefined", "so", 0),
-    SD_BUS_SIGNAL("DomainUndefined", "so", 0),
-    SD_BUS_SIGNAL("DomainStarted", "so", 0),
-    SD_BUS_SIGNAL("DomainSuspended", "so", 0),
-    SD_BUS_SIGNAL("DomainResumed", "so", 0),
-    SD_BUS_SIGNAL("DomainStopped", "so", 0),
-    SD_BUS_SIGNAL("DomainShutdown", "so", 0),
-    SD_BUS_SIGNAL("DomainPMSuspended", "so", 0),
-    SD_BUS_SIGNAL("DomainCrashed", "so", 0),
+static void
+virtDBusConnectFree(virtDBusConnect *connect)
+{
+    if (connect->connection)
+        virtDBusConnectClose(connect, TRUE);
 
-    SD_BUS_VTABLE_END
-};
+    g_free(connect->domainPath);
+    g_free(connect);
+}
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virtDBusConnect, virtDBusConnectFree);
 
-int
+void
 virtDBusConnectNew(virtDBusConnect **connectp,
-                   sd_bus *bus,
-                   const char *uri,
-                   const char *connectPath)
+                   GDBusConnection *bus,
+                   const gchar *uri,
+                   const gchar *connectPath)
 {
-    _cleanup_(virtDBusConnectFreep) virtDBusConnect *connect = NULL;
-    int r;
+    g_autoptr(virtDBusConnect) connect = NULL;
+
+    if (!interfaceInfo) {
+        interfaceInfo = virtDBusGDBusLoadIntrospectData(VIRT_DBUS_CONNECT_INTERFACE);
+        g_assert(interfaceInfo != NULL);
+    }
 
-    connect = calloc(1, sizeof(virtDBusConnect));
-    for (int i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i += 1)
+    connect = g_new0(virtDBusConnect, 1);
+    g_assert(connect != NULL);
+
+    for (gint i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i += 1)
         connect->callback_ids[i] = -1;
 
-    connect->bus = sd_bus_ref(bus);
+    connect->bus = bus;
     connect->uri = uri;
     connect->connectPath = connectPath;
 
-    connect->enumerateDomains = virtDBusConnectEnumarateDomains;
-
-    r = sd_bus_add_object_vtable(connect->bus,
-                                 NULL,
-                                 connect->connectPath,
-                                 VIRT_DBUS_CONNECT_INTERFACE,
-                                 virt_connect_vtable,
-                                 connect);
-    if (r < 0)
-        return r;
+    virtDBusGDBusRegisterObject(bus,
+                                connect->connectPath,
+                                interfaceInfo,
+                                virtDBusConnectMethodTable,
+                                NULL,
+                                connect);
 
-    if ((r = virtDBusDomainRegister(connect, bus) < 0))
-        return r;
+    virtDBusDomainRegister(connect);
 
     *connectp = connect;
     connect = NULL;
-
-    return 0;
-}
-
-virtDBusConnect *
-virtDBusConnectFree(virtDBusConnect *connect)
-{
-    if (connect->bus)
-        sd_bus_unref(connect->bus);
-
-    if (connect->connection)
-        virtDBusConnectClose(connect, true);
-
-    free(connect->domainPath);
-
-    free(connect);
-
-    return NULL;
-}
-
-void
-virtDBusConnectFreep(virtDBusConnect **connectp)
-{
-    if (*connectp)
-        virtDBusConnectFree(*connectp);
 }
 
 void
-virtDBusConnectListFree(virtDBusConnect ***connectList)
+virtDBusConnectListFree(virtDBusConnect **connectList)
 {
-    if (!*connectList)
+    if (!connectList)
         return;
 
-    for (int i = 0; (*connectList)[i]; i += 1)
-        virtDBusConnectFree((*connectList)[i]);
+    for (gint i = 0; connectList[i]; i += 1)
+        virtDBusConnectFree(connectList[i]);
 
-    free(*connectList);
+    g_free(connectList);
 }
diff --git a/src/connect.h b/src/connect.h
index 9e5f533..f8b1d06 100644
--- a/src/connect.h
+++ b/src/connect.h
@@ -2,39 +2,32 @@
 
 #define VIR_ENUM_SENTINELS
 
+#include "util.h"
+
 #include <libvirt/libvirt.h>
-#include <systemd/sd-bus.h>
 
 #define VIRT_DBUS_CONNECT_INTERFACE "org.libvirt.Connect"
 
 struct virtDBusConnect {
-    sd_bus *bus;
-    const char *uri;
-    const char *connectPath;
-    char *domainPath;
+    GDBusConnection *bus;
+    const gchar *uri;
+    const gchar *connectPath;
+    gchar *domainPath;
     virConnectPtr connection;
 
-    sd_bus_node_enumerator_t enumerateDomains;
-
-    int callback_ids[VIR_DOMAIN_EVENT_ID_LAST];
+    gint callback_ids[VIR_DOMAIN_EVENT_ID_LAST];
 };
 typedef struct virtDBusConnect virtDBusConnect;
 
-int
+void
 virtDBusConnectNew(virtDBusConnect **connectp,
-                   sd_bus *bus,
-                   const char *uri,
-                   const char *connectPath);
+                   GDBusConnection *bus,
+                   const gchar *uri,
+                   const gchar *connectPath);
 
-int
+gboolean
 virtDBusConnectOpen(virtDBusConnect *connect,
-                    sd_bus_error *error);
-
-virtDBusConnect *
-virtDBusConnectFree(virtDBusConnect *connect);
-
-void
-virtDBusConnectFreep(virtDBusConnect **connectp);
+                    GError **error);
 
 void
-virtDBusConnectListFree(virtDBusConnect ***connectList);
+virtDBusConnectListFree(virtDBusConnect **connectList);
diff --git a/src/domain.c b/src/domain.c
index f68a3a0..8403ea6 100644
--- a/src/domain.c
+++ b/src/domain.c
@@ -1,208 +1,192 @@
-#define _GNU_SOURCE
-
 #include "domain.h"
 #include "util.h"
 
 #include <libvirt/libvirt.h>
-#include <stdio.h>
 
 static virDomainPtr
 virtDBusDomainGetVirDomain(virtDBusConnect *connect,
-                           const char *path,
-                           sd_bus_error *error)
+                           const gchar *objectPath,
+                           GError **error)
 {
     virDomainPtr domain;
 
     if (virtDBusConnectOpen(connect, error) < 0)
         return NULL;
 
-    domain = virtDBusUtilVirDomainFromBusPath(connect->connection, path,
+    domain = virtDBusUtilVirDomainFromBusPath(connect->connection,
+                                              objectPath,
                                               connect->domainPath);
-    if (domain == NULL) {
-        sd_bus_error_setf(error,
-                          SD_BUS_ERROR_UNKNOWN_OBJECT,
-                          "Unknown object '%s'.", path);
+    if (!domain) {
+        virtDBusUtilSetLastVirtError(error);
         return NULL;
     }
 
     return domain;
 }
 
-static int
-virtDBusDomainGetName(sd_bus *bus VIRT_ATTR_UNUSED,
-                      const char *path,
-                      const char *interface VIRT_ATTR_UNUSED,
-                      const char *property VIRT_ATTR_UNUSED,
-                      sd_bus_message *reply,
-                      void *userdata,
-                      sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetName(const gchar *objectPath,
+                      gpointer userData,
+                      GVariant **value,
+                      GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    const char *name = "";
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    const gchar *name;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
     name = virDomainGetName(domain);
-    if (name == NULL)
-        return sd_bus_message_append(reply, "s", "");
+    if (!name)
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "s", name);
+    *value = g_variant_new("s", name);
 }
 
-static int
-virtDBusDomainGetUUID(sd_bus *bus VIRT_ATTR_UNUSED,
-                      const char *path,
-                      const char *interface VIRT_ATTR_UNUSED,
-                      const char *property VIRT_ATTR_UNUSED,
-                      sd_bus_message *reply,
-                      void *userdata,
-                      sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetUUID(const gchar *objectPath,
+                      gpointer userData,
+                      GVariant **value,
+                      GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    char uuid[VIR_UUID_STRING_BUFLEN] = "";
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    gchar uuid[VIR_UUID_STRING_BUFLEN] = "";
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    virDomainGetUUIDString(domain, uuid);
+    if (virDomainGetUUIDString(domain, uuid) < 0)
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "s", uuid);
+    *value = g_variant_new("s", uuid);
 }
 
-static int
-virtDBusDomainGetId(sd_bus *bus VIRT_ATTR_UNUSED,
-                    const char *path,
-                    const char *interface VIRT_ATTR_UNUSED,
-                    const char *property VIRT_ATTR_UNUSED,
-                    sd_bus_message *reply,
-                    void *userdata,
-                    sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetId(const gchar *objectPath,
+                    gpointer userData,
+                    GVariant **value,
+                    GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    guint id;
+
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    id = virDomainGetID(domain);
+    if (id == (guint)-1)
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "u", virDomainGetID(domain));
+    *value = g_variant_new("u", id);
 }
 
-static int
-virtDBusDomainGetVcpus(sd_bus *bus VIRT_ATTR_UNUSED,
-                       const char *path,
-                       const char *interface VIRT_ATTR_UNUSED,
-                       const char *property VIRT_ATTR_UNUSED,
-                       sd_bus_message *reply,
-                       void *userdata,
-                       sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetVcpus(const gchar *objectPath,
+                       gpointer userData,
+                       GVariant **value,
+                       GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    gint vcpus;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
+
+    vcpus = virDomainGetVcpusFlags(domain, VIR_DOMAIN_VCPU_CURRENT);
+    if (vcpus < 0)
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "u", virDomainGetVcpusFlags(domain, VIR_DOMAIN_VCPU_CURRENT));
+    *value = g_variant_new("u", vcpus);
 }
 
-static int
-virtDBusDomainGetOsType(sd_bus *bus VIRT_ATTR_UNUSED,
-                        const char *path,
-                        const char *interface VIRT_ATTR_UNUSED,
-                        const char *property VIRT_ATTR_UNUSED,
-                        sd_bus_message *reply,
-                        void *userdata,
-                        sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetOsType(const gchar *objectPath,
+                        gpointer userData,
+                        GVariant **value,
+                        GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    _cleanup_(virtDBusUtilFreep) char *os_type = NULL;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    g_autofree gchar *osType = NULL;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    os_type = virDomainGetOSType(domain);
-    if (os_type == NULL)
-        return sd_bus_message_append(reply, "s", "");
+    osType = virDomainGetOSType(domain);
+    if (!osType)
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "s", os_type);
+    *value = g_variant_new("s", osType);
 }
 
-static int
-virtDBusDomainGetActive(sd_bus *bus VIRT_ATTR_UNUSED,
-                        const char *path,
-                        const char *interface VIRT_ATTR_UNUSED,
-                        const char *property VIRT_ATTR_UNUSED,
-                        sd_bus_message *reply,
-                        void *userdata,
-                        sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetActive(const gchar *objectPath,
+                        gpointer userData,
+                        GVariant **value,
+                        GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int active;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    gint active;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
     active = virDomainIsActive(domain);
     if (active < 0)
-        return sd_bus_message_append(reply, "b", 0);
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "b", active);
+    *value = g_variant_new("b", !!active);
 }
 
-static int
-virtDBusDomainGetPersistent(sd_bus *bus VIRT_ATTR_UNUSED,
-                            const char *path,
-                            const char *interface VIRT_ATTR_UNUSED,
-                            const char *property VIRT_ATTR_UNUSED,
-                            sd_bus_message *reply,
-                            void *userdata,
-                            sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetPersistent(const gchar *objectPath,
+                            gpointer userData,
+                            GVariant **value,
+                            GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int persistent;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    gint persistent;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
     persistent = virDomainIsPersistent(domain);
     if (persistent < 0)
-        return sd_bus_message_append(reply, "b", 0);
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "b", persistent);
+    *value = g_variant_new("b", !!persistent);
 }
 
-static int
-virtDBusDomainGetState(sd_bus *bus VIRT_ATTR_UNUSED,
-                       const char *path,
-                       const char *interface VIRT_ATTR_UNUSED,
-                       const char *property VIRT_ATTR_UNUSED,
-                       sd_bus_message *reply,
-                       void *userdata,
-                       sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetState(const gchar *objectPath,
+                       gpointer userData,
+                       GVariant **value,
+                       GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int state = 0;
-    const char *string;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    gint state = 0;
+    const gchar *string;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    virDomainGetState(domain, &state, NULL, 0);
+    if (virDomainGetState(domain, &state, NULL, 0) < 0)
+        return virtDBusUtilSetLastVirtError(error);
 
     switch (state) {
     case VIR_DOMAIN_NOSTATE:
@@ -232,88 +216,80 @@ virtDBusDomainGetState(sd_bus *bus VIRT_ATTR_UNUSED,
         break;
     }
 
-    return sd_bus_message_append(reply, "s", string);
+    *value = g_variant_new("s", string);
 }
 
-static int
-virtDBusDomainGetAutostart(sd_bus *bus VIRT_ATTR_UNUSED,
-                           const char *path,
-                           const char *interface VIRT_ATTR_UNUSED,
-                           const char *property VIRT_ATTR_UNUSED,
-                           sd_bus_message *reply,
-                           void *userdata,
-                           sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainGetAutostart(const gchar *objectPath,
+                           gpointer userData,
+                           GVariant **value,
+                           GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int autostart = 0;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    gint autostart = 0;
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    virDomainGetAutostart(domain, &autostart);
+    if (virDomainGetAutostart(domain, &autostart) < 0)
+        return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_message_append(reply, "b", autostart);
+    *value = g_variant_new("b", !!autostart);
 }
 
-static int
-virtDBusDomainGetXMLDesc(sd_bus_message *message,
-                         void *userdata,
-                         sd_bus_error *error)
+static void
+virtDBusDomainGetXMLDesc(GVariant *inArgs,
+                         GUnixFDList *inFDs G_GNUC_UNUSED,
+                         const gchar *objectPath,
+                         gpointer userData,
+                         GVariant **outArgs,
+                         GUnixFDList **outFDs G_GNUC_UNUSED,
+                         GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    _cleanup_(virtDBusUtilFreep) char *description = NULL;
-    uint32_t flags;
-    int r;
-
-    r = sd_bus_message_read(message, "u", &flags);
-    if (r < 0)
-        return r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    description = virDomainGetXMLDesc(domain, flags);
-    if (!description)
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    g_autofree gchar *xml = NULL;
+    guint flags;
+
+    g_variant_get(inArgs, "(u)", &flags);
+
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
+
+    xml = virDomainGetXMLDesc(domain, flags);
+    if (!xml)
         return virtDBusUtilSetLastVirtError(error);
 
-    return sd_bus_reply_method_return(message, "s", description);
+    *outArgs = g_variant_new("(s)", xml);
 }
 
-static void
-virtDBusDomainStatsRecordListFreep(virDomainStatsRecordPtr **statsp)
-{
-    if (*statsp)
-        virDomainStatsRecordListFree(*statsp);
-}
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainStatsRecordPtr, virDomainStatsRecordListFree);
 
-static int
-virtDBusDomainGetStats(sd_bus_message *message,
-                       void *userdata,
-                       sd_bus_error *error)
+static void
+virtDBusDomainGetStats(GVariant *inArgs,
+                       GUnixFDList *inFDs G_GNUC_UNUSED,
+                       const gchar *objectPath G_GNUC_UNUSED,
+                       gpointer userData,
+                       GVariant **outArgs,
+                       GUnixFDList **outFDs G_GNUC_UNUSED,
+                       GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
     virDomainPtr domains[2];
-    _cleanup_(virtDBusDomainStatsRecordListFreep) virDomainStatsRecordPtr *records = NULL;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-    uint32_t flags, stats;
-    int r;
+    g_autoptr(virDomainStatsRecordPtr) records = NULL;
+    guint stats;
+    guint flags;
+    GVariant *grecords;
 
-    r = sd_bus_message_read(message, "uu", &stats, &flags);
-    if (r < 0)
-        return r;
+    g_variant_get(inArgs, "(uu)", &stats, &flags);
 
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
     domains[0] = domain;
     domains[1] = NULL;
@@ -321,243 +297,182 @@ virtDBusDomainGetStats(sd_bus_message *message,
     if (virDomainListGetStats(domains, stats, &records, flags) != 1)
         return virtDBusUtilSetLastVirtError(error);
 
-    r = sd_bus_message_new_method_return(message, &reply);
-    if (r < 0)
-        return r;
-
-    r = virtDBusUtilMessageAppendTypedParameters(reply, records[0]->params, records[0]->nparams);
-    if (r < 0)
-        return r;
+    grecords = virtDBusUtilTypedParamsToGVariant(records[0]->params,
+                                                 records[0]->nparams);
 
-    return sd_bus_send(NULL, reply, NULL);
+    *outArgs = g_variant_new_tuple(&grecords, 1);
 }
 
-static int
-virtDBusDomainShutdown(sd_bus_message *message,
-                       void *userdata,
-                       sd_bus_error *error)
+static void
+virtDBusDomainShutdown(GVariant *inArgs G_GNUC_UNUSED,
+                       GUnixFDList *inFDs G_GNUC_UNUSED,
+                       const gchar *objectPath G_GNUC_UNUSED,
+                       gpointer userData,
+                       GVariant **outArgs G_GNUC_UNUSED,
+                       GUnixFDList **outFDs G_GNUC_UNUSED,
+                       GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    r = virDomainShutdown(domain);
-    if (r < 0)
-        return virtDBusUtilSetLastVirtError(error);
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    return sd_bus_reply_method_return(message, "");
+    if (virDomainShutdown(domain) < 0)
+        virtDBusUtilSetLastVirtError(error);
 }
 
-static int
-virtDBusDomainDestroy(sd_bus_message *message,
-                      void *userdata,
-                      sd_bus_error *error)
+static void
+virtDBusDomainDestroy(GVariant *inArgs G_GNUC_UNUSED,
+                      GUnixFDList *inFDs G_GNUC_UNUSED,
+                      const gchar *objectPath G_GNUC_UNUSED,
+                      gpointer userData,
+                      GVariant **outArgs G_GNUC_UNUSED,
+                      GUnixFDList **outFDs G_GNUC_UNUSED,
+                      GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    r = virDomainDestroy(domain);
-    if (r < 0)
-        return virtDBusUtilSetLastVirtError(error);
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    return sd_bus_reply_method_return(message, "");
+    if (virDomainDestroy(domain) < 0)
+        virtDBusUtilSetLastVirtError(error);
 }
 
-static int
-virtDBusDomainReboot(sd_bus_message *message,
-                     void *userdata,
-                     sd_bus_error *error)
+static void
+virtDBusDomainReboot(GVariant *inArgs,
+                     GUnixFDList *inFDs G_GNUC_UNUSED,
+                     const gchar *objectPath G_GNUC_UNUSED,
+                     gpointer userData,
+                     GVariant **outArgs G_GNUC_UNUSED,
+                     GUnixFDList **outFDs G_GNUC_UNUSED,
+                     GError **error)
+
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    uint32_t flags;
-    int r;
-
-    r = sd_bus_message_read(message, "u", &flags);
-    if (r < 0)
-        return r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    r = virDomainReboot(domain, flags);
-    if (r < 0)
-        return virtDBusUtilSetLastVirtError(error);
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    guint flags;
 
-    return sd_bus_reply_method_return(message, "");
-}
+    g_variant_get(inArgs, "(u)", &flags);
 
-static int
-virtDBusDomainReset(sd_bus_message *message,
-                    void *userdata,
-                    sd_bus_error *error)
-{
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    uint32_t flags;
-    int r;
-
-    r = sd_bus_message_read(message, "u", &flags);
-    if (r < 0)
-        return r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    r = virDomainReset(domain, flags);
-    if (r < 0)
-        return virtDBusUtilSetLastVirtError(error);
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    return sd_bus_reply_method_return(message, "");
+    if (virDomainReboot(domain, flags) < 0)
+        virtDBusUtilSetLastVirtError(error);
 }
 
-static int
-virtDBusDomainCreate(sd_bus_message *message,
-                     void *userdata,
-                     sd_bus_error *error)
+static void
+virtDBusDomainReset(GVariant *inArgs,
+                    GUnixFDList *inFDs G_GNUC_UNUSED,
+                    const gchar *objectPath G_GNUC_UNUSED,
+                    gpointer userData,
+                    GVariant **outArgs G_GNUC_UNUSED,
+                    GUnixFDList **outFDs G_GNUC_UNUSED,
+                    GError **error)
+
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    r = virDomainCreate(domain);
-    if (r < 0)
-        return virtDBusUtilSetLastVirtError(error);
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
+    guint flags;
 
-    return sd_bus_reply_method_return(message, "");
+    g_variant_get(inArgs, "(u)", &flags);
+
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
+
+    if (virDomainReset(domain, flags) < 0)
+        virtDBusUtilSetLastVirtError(error);
 }
 
-static int
-virtDBusDomainUndefine(sd_bus_message *message,
-                       void *userdata,
-                       sd_bus_error *error)
+static void
+virtDBusDomainCreate(GVariant *inArgs G_GNUC_UNUSED,
+                     GUnixFDList *inFDs G_GNUC_UNUSED,
+                     const gchar *objectPath G_GNUC_UNUSED,
+                     gpointer userData,
+                     GVariant **outArgs G_GNUC_UNUSED,
+                     GUnixFDList **outFDs G_GNUC_UNUSED,
+                     GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int r;
-
-    domain = virtDBusDomainGetVirDomain(connect,
-                                        sd_bus_message_get_path(message),
-                                        error);
-    if (domain == NULL)
-        return -1;
-
-    r = virDomainUndefine(domain);
-    if (r < 0)
-        return virtDBusUtilSetLastVirtError(error);
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
 
-    return sd_bus_reply_method_return(message, "");
-}
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-static const sd_bus_vtable virt_domain_vtable[] = {
-    SD_BUS_VTABLE_START(0),
-
-    SD_BUS_PROPERTY("Name", "s", virtDBusDomainGetName, 0, 0),
-    SD_BUS_PROPERTY("UUID", "s", virtDBusDomainGetUUID, 0, 0),
-    SD_BUS_PROPERTY("Id", "u", virtDBusDomainGetId, 0, 0),
-    SD_BUS_PROPERTY("Vcpus", "u", virtDBusDomainGetVcpus, 0, 0),
-    SD_BUS_PROPERTY("OSType", "s", virtDBusDomainGetOsType, 0, 0),
-    SD_BUS_PROPERTY("Active", "b", virtDBusDomainGetActive, 0, 0),
-    SD_BUS_PROPERTY("Persistent", "b", virtDBusDomainGetPersistent, 0, 0),
-    SD_BUS_PROPERTY("State", "s", virtDBusDomainGetState, 0, 0),
-    SD_BUS_PROPERTY("Autostart", "b", virtDBusDomainGetAutostart, 0, 0),
-
-    SD_BUS_METHOD("GetXMLDesc", "u", "s", virtDBusDomainGetXMLDesc, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("GetStats", "uu", "a{sv}", virtDBusDomainGetStats, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("Shutdown", "", "", virtDBusDomainShutdown, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("Destroy", "", "", virtDBusDomainDestroy, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("Reboot", "u", "", virtDBusDomainReboot, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("Reset", "u", "", virtDBusDomainReset, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("Create", "", "", virtDBusDomainCreate, SD_BUS_VTABLE_UNPRIVILEGED),
-    SD_BUS_METHOD("Undefine", "", "", virtDBusDomainUndefine, SD_BUS_VTABLE_UNPRIVILEGED),
-
-    SD_BUS_SIGNAL("DeviceAdded", "s", 0),
-    SD_BUS_SIGNAL("DeviceRemoved", "s", 0),
-    SD_BUS_SIGNAL("DiskChange", "ssss", 0),
-    SD_BUS_SIGNAL("TrayChange", "ss", 0),
-
-    SD_BUS_VTABLE_END
-};
+    if (virDomainCreate(domain) < 0)
+        virtDBusUtilSetLastVirtError(error);
+}
 
-static int
-virtDBusDomainLookup(sd_bus *bus VIRT_ATTR_UNUSED,
-                     const char *path,
-                     const char *interface VIRT_ATTR_UNUSED,
-                     void *userdata,
-                     void **found,
-                     sd_bus_error *error VIRT_ATTR_UNUSED)
+static void
+virtDBusDomainUndefine(GVariant *inArgs G_GNUC_UNUSED,
+                       GUnixFDList *inFDs G_GNUC_UNUSED,
+                       const gchar *objectPath G_GNUC_UNUSED,
+                       gpointer userData,
+                       GVariant **outArgs G_GNUC_UNUSED,
+                       GUnixFDList **outFDs G_GNUC_UNUSED,
+                       GError **error)
 {
-    virtDBusConnect *connect = userdata;
-    _cleanup_(virtDBusUtilFreep) char *name = NULL;
-    _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain = NULL;
-    int r;
+    virtDBusConnect *connect = userData;
+    g_autoptr(virDomain) domain = NULL;
 
-    r = sd_bus_path_decode(path, connect->domainPath, &name);
-    if (r < 0)
-        return r;
+    domain = virtDBusDomainGetVirDomain(connect, objectPath, error);
+    if (!domain)
+        return;
 
-    if (*name == '\0')
-        return 0;
+    if (virDomainUndefine(domain) < 0)
+        virtDBusUtilSetLastVirtError(error);
+}
 
-    domain = virtDBusDomainGetVirDomain(connect, path, error);
-    if (!domain)
-        return 0;
+static virtDBusGDBusPropertyTable virtDBusDomainPropertyTable[] = {
+    { "Name", virtDBusDomainGetName, NULL },
+    { "UUID", virtDBusDomainGetUUID, NULL },
+    { "Id", virtDBusDomainGetId, NULL },
+    { "Vcpus", virtDBusDomainGetVcpus, NULL },
+    { "OSType", virtDBusDomainGetOsType, NULL },
+    { "Active", virtDBusDomainGetActive, NULL },
+    { "Persistent", virtDBusDomainGetPersistent, NULL },
+    { "State", virtDBusDomainGetState, NULL },
+    { "Autostart", virtDBusDomainGetAutostart, NULL },
+    { NULL, NULL, NULL }
+};
 
-    /*
-     * There's no way to unref the pointer we're returning here. So,
-     * return the connect object and look up the domain again in the
-     * domain_* callbacks.
-     */
-    *found = connect;
+static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] = {
+    { "GetXMLDesc", virtDBusDomainGetXMLDesc },
+    { "GetStats", virtDBusDomainGetStats },
+    { "Shutdown", virtDBusDomainShutdown },
+    { "Destroy", virtDBusDomainDestroy },
+    { "Reboot", virtDBusDomainReboot },
+    { "Reset", virtDBusDomainReset },
+    { "Create", virtDBusDomainCreate },
+    { "Undefine", virtDBusDomainUndefine },
+    { NULL, NULL }
+};
 
-    return 1;
-}
+static GDBusInterfaceInfo *interfaceInfo = NULL;
 
-int
-virtDBusDomainRegister(virtDBusConnect *connect,
-                       sd_bus *bus)
+void
+virtDBusDomainRegister(virtDBusConnect *connect)
 {
-    int r;
-
-    r = asprintf(&connect->domainPath, "%s/domain", connect->connectPath);
-    if (r < 0)
-        return r;
-
-    r = sd_bus_add_node_enumerator(bus, NULL, connect->domainPath,
-                                   connect->enumerateDomains, connect);
-    if (r < 0)
-        return r;
-
-    return sd_bus_add_fallback_vtable(bus,
-                                      NULL,
-                                      connect->domainPath,
-                                      VIRT_DBUS_DOMAIN_INTERFACE,
-                                      virt_domain_vtable,
-                                      virtDBusDomainLookup,
-                                      connect);
+    connect->domainPath = g_strdup_printf("%s/domain", connect->connectPath);
+    g_assert(connect->domainPath);
+
+    if (!interfaceInfo) {
+        interfaceInfo = virtDBusGDBusLoadIntrospectData(VIRT_DBUS_DOMAIN_INTERFACE);
+        g_assert(interfaceInfo != NULL);
+    }
+
+    virtDBusGDBusRegisterSubtree(connect->bus,
+                                 connect->domainPath,
+                                 interfaceInfo,
+                                 virtDBusDomainMethodTable,
+                                 virtDBusDomainPropertyTable,
+                                 connect);
 }
diff --git a/src/domain.h b/src/domain.h
index 03a29ed..d56d703 100644
--- a/src/domain.h
+++ b/src/domain.h
@@ -2,10 +2,7 @@
 
 #include "connect.h"
 
-#include <systemd/sd-bus.h>
-
 #define VIRT_DBUS_DOMAIN_INTERFACE "org.libvirt.Domain"
 
-int
-virtDBusDomainRegister(virtDBusConnect *connect,
-                       sd_bus *bus);
+void
+virtDBusDomainRegister(virtDBusConnect *connect);
diff --git a/src/events.c b/src/events.c
index c45acd7..dada55f 100644
--- a/src/events.c
+++ b/src/events.c
@@ -2,23 +2,19 @@
 #include "events.h"
 #include "util.h"
 
-#include <assert.h>
 #include <libvirt/libvirt.h>
-#include <systemd/sd-bus.h>
 
-static int
-virtDBusEventsDomainLifecycle(virConnectPtr connection VIRT_ATTR_UNUSED,
+static gint
+virtDBusEventsDomainLifecycle(virConnectPtr connection G_GNUC_UNUSED,
                               virDomainPtr domain,
-                              int event,
-                              int detail VIRT_ATTR_UNUSED,
-                              void *opaque)
+                              gint event,
+                              gint detail G_GNUC_UNUSED,
+                              gpointer opaque)
 {
     virtDBusConnect *connect = opaque;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
-    const char *signal = NULL;
-    const char *name;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    int r;
+    const gchar *signal = NULL;
+    const gchar *name;
+    g_autofree gchar *path = NULL;
 
     switch (event) {
     case VIR_DOMAIN_EVENT_DEFINED:
@@ -52,103 +48,77 @@ virtDBusEventsDomainLifecycle(virConnectPtr connection VIRT_ATTR_UNUSED,
         return 0;
     }
 
-    r = sd_bus_message_new_signal(connect->bus,
-                                  &message,
-                                  connect->connectPath,
-                                  VIRT_DBUS_CONNECT_INTERFACE,
-                                  signal);
-    if (r < 0)
-        return r;
-
     name = virDomainGetName(domain);
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    r = sd_bus_message_append(message, "so", name ? : "", path);
-    if (r < 0)
-        return r;
+    g_dbus_connection_emit_signal(connect->bus,
+                                  NULL,
+                                  connect->connectPath,
+                                  VIRT_DBUS_CONNECT_INTERFACE,
+                                  signal,
+                                  g_variant_new("(so)", name, path),
+                                  NULL);
 
-    return sd_bus_send(connect->bus, message, NULL);
+    return 0;
 }
 
-static int
-virtDBusEventsDomainDeviceAdded(virConnectPtr connection VIRT_ATTR_UNUSED,
+static gint
+virtDBusEventsDomainDeviceAdded(virConnectPtr connection G_GNUC_UNUSED,
                                 virDomainPtr domain,
-                                const char *device,
-                                void *opaque)
+                                const gchar *device,
+                                gpointer opaque)
 {
     virtDBusConnect *connect = opaque;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    int r;
+    g_autofree gchar *path = NULL;
 
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    r = sd_bus_message_new_signal(connect->bus,
-                                  &message,
+    g_dbus_connection_emit_signal(connect->bus,
+                                  NULL,
                                   path,
                                   VIRT_DBUS_DOMAIN_INTERFACE,
-                                  "DeviceAdded");
-    if (r < 0)
-        return r;
+                                  "DeviceAdded",
+                                  g_variant_new("(s)", device),
+                                  NULL);
 
-    r = sd_bus_message_append(message, "s", device);
-    if (r < 0)
-        return r;
-
-    return sd_bus_send(connect->bus, message, NULL);
+    return 0;
 }
 
-static int
-virtDBusEventsDomainDeviceRemoved(virConnectPtr connection VIRT_ATTR_UNUSED,
+static gint
+virtDBusEventsDomainDeviceRemoved(virConnectPtr connection G_GNUC_UNUSED,
                                   virDomainPtr domain,
-                                  const char *device,
-                                  void *opaque)
+                                  const gchar *device,
+                                  gpointer opaque)
 {
     virtDBusConnect *connect = opaque;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    int r;
+    g_autofree gchar *path = NULL;
 
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    r = sd_bus_message_new_signal(connect->bus,
-                                  &message,
+    g_dbus_connection_emit_signal(connect->bus,
+                                  NULL,
                                   path,
                                   VIRT_DBUS_DOMAIN_INTERFACE,
-                                  "DeviceRemoved");
-    if (r < 0)
-        return r;
-
-    r = sd_bus_message_append(message, "s", device);
-    if (r < 0)
-        return r;
+                                  "DeviceRemoved",
+                                  g_variant_new("(s)", device),
+                                  NULL);
 
-    return sd_bus_send(connect->bus, message, NULL);
+    return 0;
 }
 
-static int
-virtDBusEventsDomainTrayChange(virConnectPtr connection VIRT_ATTR_UNUSED,
+static gint
+virtDBusEventsDomainTrayChange(virConnectPtr connection G_GNUC_UNUSED,
                                virDomainPtr domain,
-                               const char *device,
-                               int reason,
-                               void *opaque)
+                               const gchar *device,
+                               gint reason,
+                               gpointer opaque)
 {
     virtDBusConnect *connect = opaque;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    const char *reasonstr;
-    int r;
+    g_autofree gchar *path = NULL;
+    const gchar *reasonstr;
 
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    r = sd_bus_message_new_signal(connect->bus,
-                                  &message,
-                                  path,
-                                  VIRT_DBUS_DOMAIN_INTERFACE,
-                                  "TrayChange");
-    if (r < 0)
-        return r;
-
     switch (reason) {
     case VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN:
         reasonstr = "open";
@@ -161,38 +131,32 @@ virtDBusEventsDomainTrayChange(virConnectPtr connection VIRT_ATTR_UNUSED,
         break;
     }
 
-    r = sd_bus_message_append(message, "ss", device, reasonstr);
-    if (r < 0)
-        return r;
+    g_dbus_connection_emit_signal(connect->bus,
+                                  NULL,
+                                  path,
+                                  VIRT_DBUS_DOMAIN_INTERFACE,
+                                  "TrayChange",
+                                  g_variant_new("(ss)", device, reasonstr),
+                                  NULL);
 
-    return sd_bus_send(connect->bus, message, NULL);
+    return 0;
 }
 
-static int
-virtDBusEventsDomainDiskChange(virConnectPtr connection VIRT_ATTR_UNUSED,
+static gint
+virtDBusEventsDomainDiskChange(virConnectPtr connection G_GNUC_UNUSED,
                                virDomainPtr domain,
-                               const char *old_src_path,
-                               const char *new_src_path,
-                               const char *device,
-                               int reason,
-                               void *opaque)
+                               const gchar *old_src_path,
+                               const gchar *new_src_path,
+                               const gchar *device,
+                               gint reason,
+                               gpointer opaque)
 {
     virtDBusConnect *connect = opaque;
-    _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
-    _cleanup_(virtDBusUtilFreep) char *path = NULL;
-    const char *reasonstr;
-    int r;
+    g_autofree gchar *path = NULL;
+    const gchar *reasonstr;
 
     path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath);
 
-    r = sd_bus_message_new_signal(connect->bus,
-                                  &message,
-                                  path,
-                                  VIRT_DBUS_DOMAIN_INTERFACE,
-                                  "DiskChange");
-    if (r < 0)
-        return r;
-
     switch (reason) {
     case VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START:
         reasonstr = "missing-on-start";
@@ -205,19 +169,24 @@ virtDBusEventsDomainDiskChange(virConnectPtr connection VIRT_ATTR_UNUSED,
         break;
     }
 
-    r = sd_bus_message_append(message, "ssss", old_src_path, new_src_path, device, reasonstr);
-    if (r < 0)
-        return r;
+    g_dbus_connection_emit_signal(connect->bus,
+                                  NULL,
+                                  path,
+                                  VIRT_DBUS_DOMAIN_INTERFACE,
+                                  "DiskChange",
+                                  g_variant_new("(ssss)", old_src_path,
+                                                new_src_path, device, reasonstr),
+                                  NULL);
 
-    return sd_bus_send(connect->bus, message, NULL);
+    return 0;
 }
 
 static void
 virtDBusEventsRegisterEvent(virtDBusConnect *connect,
-                            int id,
+                            gint id,
                             virConnectDomainEventGenericCallback callback)
 {
-    assert(connect->callback_ids[id] == -1);
+    g_assert(connect->callback_ids[id] == -1);
 
     connect->callback_ids[id] = virConnectDomainEventRegisterAny(connect->connection,
                                                                  NULL,
diff --git a/src/main.c b/src/main.c
index 6f11aab..2991075 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,92 +1,23 @@
-#include "config.h"
-
 #include "connect.h"
 #include "util.h"
 
-#include <errno.h>
-#include <getopt.h>
-#include <poll.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/signalfd.h>
-#include <systemd/sd-bus.h>
-#include <unistd.h>
-
-static int loop_status;
-
-static int
-virtDBusGetLibvirtEvents(sd_bus *bus)
-{
-    int events;
-    int virt_events = 0;
-
-    events = sd_bus_get_events(bus);
-
-    if (events & POLLIN)
-        virt_events |= VIR_EVENT_HANDLE_READABLE;
-
-    if (events & POLLOUT)
-        virt_events |= VIR_EVENT_HANDLE_WRITABLE;
-
-    return virt_events;
-}
-
-static int
-virtDBusProcessEvents(sd_bus *bus)
-{
-    for (;;) {
-            int r;
-
-            r = sd_bus_process(bus, NULL);
-            if (r < 0)
-                    return r;
-
-            if (r == 0)
-                    break;
-    }
-
-    return 0;
-}
-
-static void
-virtDBusVirEventRemoveHandlep(int *watchp)
-{
-    if (*watchp >= 0)
-        virEventRemoveHandle(*watchp);
-}
-
-static void
-virtDBusHandleSignal(int watch VIRT_ATTR_UNUSED,
-                     int fd VIRT_ATTR_UNUSED,
-                     int events VIRT_ATTR_UNUSED,
-                     void *opaque VIRT_ATTR_UNUSED)
-{
-    loop_status = -ECANCELED;
-}
-
-static void
-virtDBusHandleBusEvent(int watch,
-                       int fd VIRT_ATTR_UNUSED,
-                       int events VIRT_ATTR_UNUSED,
-                       void *opaque)
-{
-    sd_bus *bus = opaque;
-
-    loop_status = virtDBusProcessEvents(bus);
+#include <glib-unix.h>
+#include <libvirt-glib/libvirt-glib.h>
 
-    if (loop_status < 0)
-        return;
-
-    virEventUpdateHandle(watch, virtDBusGetLibvirtEvents(bus));
-}
+struct _virtDBusDriver {
+    const gchar *uri;
+    const gchar *object;
+};
+typedef struct _virtDBusDriver virtDBusDriver;
 
-struct virtDBusDriver {
-    const char *uri;
-    const char *object;
+struct _virtDBusRegisterData {
+    virtDBusConnect **connectList;
+    const virtDBusDriver *drivers;
+    gsize ndrivers;
 };
+typedef struct _virtDBusRegisterData virtDBusRegisterData;
 
-static const struct virtDBusDriver sessionDrivers[] = {
+static const virtDBusDriver sessionDrivers[] = {
     { "qemu:///session",            "/org/libvirt/QEMU" },
     { "test:///default",            "/org/libvirt/Test" },
     { "uml:///session",             "/org/libvirt/UML" },
@@ -96,7 +27,7 @@ static const struct virtDBusDriver sessionDrivers[] = {
     { "vmwarews:///session",        "/org/libvirt/VMwareWS" },
 };
 
-static const struct virtDBusDriver systemDrivers[] = {
+static const virtDBusDriver systemDrivers[] = {
     { "bhyve:///system",        "/org/libvirt/BHyve" },
     { "lxc:///",                "/org/libvirt/LXC" },
     { "openvz:///system",       "/org/libvirt/OpenVZ" },
@@ -108,131 +39,127 @@ static const struct virtDBusDriver systemDrivers[] = {
     { "xen:///",                "/org/libvirt/Xen" },
 };
 
-int
-main(int argc, char *argv[])
+static gboolean
+virtDBusHandleSignal(gpointer data)
 {
-    enum {
-        ARG_SYSTEM = 255,
-        ARG_SESSION
-    };
+    g_main_loop_quit(data);
+    return TRUE;
+}
 
-    static const struct option options[] = {
-        { "help",    no_argument,       NULL, 'h' },
-        { "system",  no_argument,       NULL, ARG_SYSTEM },
-        { "session", no_argument,       NULL, ARG_SESSION },
-        {}
-    };
+static void
+virtDBusAcquired(GDBusConnection *connection,
+                 const gchar *name G_GNUC_UNUSED,
+                 gpointer opaque)
+{
+    virtDBusRegisterData *data = opaque;
 
-    bool system_bus;
-    const struct virtDBusDriver *drivers = NULL;
-    int ndrivers = 0;
-
-    _cleanup_(virtDBusConnectListFree) virtDBusConnect **connect = NULL;
-    _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
-    _cleanup_(virtDBusUtilClosep) int signal_fd = -1;
-    _cleanup_(virtDBusVirEventRemoveHandlep) int bus_watch = -1;
-    _cleanup_(virtDBusVirEventRemoveHandlep) int signal_watch = -1;
-    sigset_t mask;
-    int c;
-    int r;
-
-    if (geteuid() == 0) {
-        system_bus = true;
-    } else {
-        system_bus = false;
+    for (gsize i = 0; i < data->ndrivers; i += 1) {
+        virtDBusConnectNew(&data->connectList[i], connection,
+                           data->drivers[i].uri, data->drivers[i].object);
     }
 
-    while ((c = getopt_long(argc, argv, "hc:", options, NULL)) >= 0) {
-        switch (c) {
-            case 'h':
-                printf("Usage: %s [OPTIONS]\n", program_invocation_short_name);
-                printf("\n");
-                printf("Provide a D-Bus interface to a libvirtd.\n");
-                printf("\n");
-                printf("  -h, --help        Display this help text and exit\n");
-                printf("  --session         Connect to the session bus\n");
-                printf("  --system          Connect to the system bus\n");
-                return 0;
-
-            case ARG_SYSTEM:
-                system_bus = true;
-                break;
-
-            case ARG_SESSION:
-                system_bus = false;
-                break;
-
-            default:
-                return EXIT_FAILURE;
-        }
-    }
+}
 
-    sigemptyset(&mask);
-    sigaddset(&mask, SIGTERM);
-    sigaddset(&mask, SIGINT);
-    sigprocmask(SIG_BLOCK, &mask, NULL);
+static void
+virtDBusNameAcquired(GDBusConnection *connection G_GNUC_UNUSED,
+                     const gchar *name G_GNUC_UNUSED,
+                     gpointer data G_GNUC_UNUSED)
+{
+}
 
-    virEventRegisterDefaultImpl();
+static void
+virtDBusNameLost(GDBusConnection *connection G_GNUC_UNUSED,
+                 const gchar *name G_GNUC_UNUSED,
+                 gpointer data G_GNUC_UNUSED)
+{
+    g_printerr("Disconnected from D-Bus.\n");
+    exit(EXIT_FAILURE);
+}
 
-    r = system_bus ? sd_bus_open_system(&bus) : sd_bus_open_user(&bus);
-    if (r < 0) {
-        fprintf(stderr, "Failed to connect to session bus: %s\n", strerror(-r));
-        return EXIT_FAILURE;
+static void
+virtDBusRegisterDataFree(virtDBusRegisterData *data)
+{
+    virtDBusConnectListFree(data->connectList);
+}
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virtDBusRegisterData, virtDBusRegisterDataFree);
+
+int
+main(gint argc, gchar *argv[])
+{
+    static gboolean systemOpt = FALSE;
+    static gboolean sessionOpt = FALSE;
+    GBusType busType;
+    g_auto(virtDBusGDBusSource) sigintSource = 0;
+    g_auto(virtDBusGDBusSource) sigtermSource = 0;
+    g_auto(virtDBusGDBusOwner) busOwner = 0;
+    g_autoptr(GOptionContext) context = NULL;
+    g_autoptr(GError) error = NULL;
+    g_autoptr(GMainLoop) loop = NULL;
+    g_auto(virtDBusRegisterData) data = { 0 };
+
+    static GOptionEntry options[] = {
+        { "system", 0, 0, G_OPTION_ARG_NONE, &systemOpt,
+            "Connect to the system bus", NULL },
+        { "session", 0, 0, G_OPTION_ARG_NONE, &sessionOpt,
+            "Connect to the session bus", NULL },
+        { NULL }
+    };
+
+    context = g_option_context_new("Provide a D-Bus interface to a libvirtd.");
+    g_option_context_add_main_entries(context, options, NULL);
+
+    if (!g_option_context_parse(context, &argc, &argv, &error)) {
+        g_printerr("%s\n", error->message);
+        exit(EXIT_FAILURE);
     }
 
-    r = sd_bus_request_name(bus, "org.libvirt", 0);
-    if (r < 0) {
-        fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
-        return EXIT_FAILURE;
+    if (sessionOpt && systemOpt) {
+        g_printerr("Only one of --session or --system can be used.\n");
+        exit(EXIT_FAILURE);
     }
 
-    if (system_bus) {
-        drivers = systemDrivers;
-        ndrivers = VIRT_N_ELEMENTS(systemDrivers);
+    if (sessionOpt) {
+        busType = G_BUS_TYPE_SESSION;
+    } else if (systemOpt) {
+        busType = G_BUS_TYPE_SYSTEM;
     } else {
-        drivers = sessionDrivers;
-        ndrivers = VIRT_N_ELEMENTS(sessionDrivers);
+        if (geteuid() == 0) {
+            busType = G_BUS_TYPE_SYSTEM;
+        } else {
+            busType = G_BUS_TYPE_SESSION;
+        }
     }
 
-    connect = calloc(ndrivers + 1, sizeof(virtDBusConnect *));
-
-    for (int i = 0; i < ndrivers; i += 1) {
-        r = virtDBusConnectNew(&connect[i], bus,
-                               drivers[i].uri, drivers[i].object);
-        if (r < 0) {
-            fprintf(stderr, "Failed to register libvirt connection.\n");
-            return EXIT_FAILURE;
-        }
+    if (busType == G_BUS_TYPE_SYSTEM) {
+        data.drivers = systemDrivers;
+        data.ndrivers = G_N_ELEMENTS(systemDrivers);
+    } else {
+        data.drivers = sessionDrivers;
+        data.ndrivers = G_N_ELEMENTS(sessionDrivers);
     }
+    data.connectList = g_new0(virtDBusConnect *, data.ndrivers + 1);
+    g_assert(data.connectList);
 
-    r = virtDBusProcessEvents(bus);
-    if (r < 0)
-        return EXIT_FAILURE;
+    loop = g_main_loop_new(NULL, FALSE);
 
-    bus_watch = virEventAddHandle(sd_bus_get_fd(bus),
-                                  virtDBusGetLibvirtEvents(bus),
-                                  virtDBusHandleBusEvent,
-                                  bus,
-                                  NULL);
+    sigtermSource = g_unix_signal_add(SIGTERM,
+                                      virtDBusHandleSignal,
+                                      loop);
 
-    signal_fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
-    signal_watch = virEventAddHandle(signal_fd,
-                                     VIR_EVENT_HANDLE_READABLE,
+    sigintSource = g_unix_signal_add(SIGINT,
                                      virtDBusHandleSignal,
-                                     NULL,
-                                     NULL);
-    if (signal_watch < 0) {
-        fprintf(stderr, "Failed to register signal handler.\n");
-        return EXIT_FAILURE;
-    }
+                                     loop);
 
-    while (loop_status >= 0)
-        virEventRunDefaultImpl();
+    gvir_event_register();
 
-    if (loop_status < 0 && loop_status != -ECANCELED) {
-        fprintf(stderr, "Error: %s\n", strerror(-loop_status));
-        return EXIT_FAILURE;
-    }
+    busOwner = g_bus_own_name(busType, "org.libvirt",
+                              G_BUS_NAME_OWNER_FLAGS_NONE,
+                              virtDBusAcquired,
+                              virtDBusNameAcquired,
+                              virtDBusNameLost,
+                              &data, NULL);
+
+    g_main_loop_run(loop);
 
     return EXIT_SUCCESS;
 }
diff --git a/src/util.c b/src/util.c
index 9042a0f..c0b5bbe 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,155 +1,129 @@
 #include "util.h"
 
 #include <libvirt/virterror.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
 
-int
-virtDBusUtilMessageAppendTypedParameters(sd_bus_message *message,
-                                         virTypedParameterPtr parameters,
-                                         int n_parameters)
+static const GDBusErrorEntry virtDBusUtilErrorEntries[] = {
+    { VIRT_DBUS_ERROR_LIBVIRT, "org.libvirt.Error" },
+};
+
+G_STATIC_ASSERT(G_N_ELEMENTS(virtDBusUtilErrorEntries) == VIRT_DBUS_N_ERRORS);
+
+GQuark
+virtDBusErrorQuark(void)
 {
-    int r;
+    static volatile gsize quarkVolatile = 0;
+    g_dbus_error_register_error_domain("virt-dbus-error-quark",
+                                       &quarkVolatile,
+                                       virtDBusUtilErrorEntries,
+                                       G_N_ELEMENTS(virtDBusUtilErrorEntries));
+    return (GQuark) quarkVolatile;
+}
 
-    r = sd_bus_message_open_container(message, 'a', "{sv}");
-    if (r < 0)
-        return r;
+GVariant *
+virtDBusUtilTypedParamsToGVariant(virTypedParameterPtr params,
+                                  gint nparams)
+{
+    GVariantBuilder builder;
 
-    for (int i = 0; i < n_parameters; i += 1) {
-        r = sd_bus_message_open_container(message, SD_BUS_TYPE_DICT_ENTRY, "sv");
-        if (r < 0)
-            return r;
+    g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
 
-        r = sd_bus_message_append(message, "s", parameters[i].field);
-        if (r < 0)
-            return r;
+    for (gint i = 0; i < nparams; i++) {
+        GVariant *value = NULL;
 
-        switch (parameters[i].type) {
+        switch (params[i].type) {
         case VIR_TYPED_PARAM_INT:
-            r = sd_bus_message_append(message, "v", "i", parameters[i].value.i);
+            value = g_variant_new("i", params[i].value.i);
             break;
         case VIR_TYPED_PARAM_UINT:
-            r = sd_bus_message_append(message, "v", "u", parameters[i].value.ui);
+            value = g_variant_new("u", params[i].value.ui);
             break;
         case VIR_TYPED_PARAM_LLONG:
-            r = sd_bus_message_append(message, "v", "x", parameters[i].value.l);
+            value = g_variant_new("x", params[i].value.l);
             break;
         case VIR_TYPED_PARAM_ULLONG:
-            r = sd_bus_message_append(message, "v", "t", parameters[i].value.ul);
+            value = g_variant_new("t", params[i].value.ul);
             break;
         case VIR_TYPED_PARAM_DOUBLE:
-            r = sd_bus_message_append(message, "v", "d", parameters[i].value.d);
+            value = g_variant_new("d", params[i].value.d);
             break;
         case VIR_TYPED_PARAM_BOOLEAN:
-            r = sd_bus_message_append(message, "v", "b", parameters[i].value.b);
+            value = g_variant_new("b", params[i].value.b);
             break;
         case VIR_TYPED_PARAM_STRING:
-            r = sd_bus_message_append(message, "v", "s", parameters[i].value.s);
+            value = g_variant_new("s", params[i].value.s);
             break;
         }
 
-        if (r < 0)
-            return r;
-
-        r = sd_bus_message_close_container(message);
-        if (r < 0)
-            return r;
+        g_variant_builder_add(&builder, "{sv}",
+                              params[i].field,
+                              g_variant_new_variant(value));
     }
 
-    return sd_bus_message_close_container(message);
+    return g_variant_builder_end(&builder);
 }
 
-int
-virtDBusUtilSetLastVirtError(sd_bus_error *error)
+void
+virtDBusUtilSetLastVirtError(GError **error)
 {
     virErrorPtr vir_error;
 
     vir_error = virGetLastError();
-    if (!vir_error)
-        return 0;
+    if (!vir_error) {
+        g_set_error(error, VIRT_DBUS_ERROR, VIRT_DBUS_ERROR_LIBVIRT,
+                    "unknown error");
+    } else {
+        g_set_error_literal(error, VIRT_DBUS_ERROR, VIRT_DBUS_ERROR_LIBVIRT,
+                            vir_error->message);
+    }
+}
 
-    return sd_bus_error_set(error, VIRT_DBUS_ERROR_INTERFACE, vir_error->message);
+static gchar *
+virtDBusUtilEncodeUUID(const gchar *uuid)
+{
+    gchar *ret = g_strdup_printf("_%s", uuid);
+    g_assert(ret);
+    return g_strdelimit(ret, "-", '_');
 }
 
-int
-virtDBusUtilSetError(sd_bus_error *error,
-                     const char *message)
+static gchar *
+virtDBusUtilDecodeUUID(const gchar *uuid)
 {
-    return sd_bus_error_set(error, VIRT_DBUS_ERROR_INTERFACE, message);
+    gchar *ret = g_strdup(uuid+1);
+    g_assert(ret);
+    return g_strdelimit(ret, "_", '-');
 }
 
-char *
+gchar *
 virtDBusUtilBusPathForVirDomain(virDomainPtr domain,
-                                const char *domainPath)
+                                const gchar *domainPath)
 {
-    char *path = NULL;
-    char uuid[VIR_UUID_STRING_BUFLEN] = "";
-
+    gchar uuid[VIR_UUID_STRING_BUFLEN] = "";
+    g_autofree gchar *newUuid = NULL;
     virDomainGetUUIDString(domain, uuid);
-    sd_bus_path_encode(domainPath, uuid, &path);
-
-    return path;
+    newUuid = virtDBusUtilEncodeUUID(uuid);
+    return g_strdup_printf("%s/%s", domainPath, newUuid);
 }
 
 virDomainPtr
 virtDBusUtilVirDomainFromBusPath(virConnectPtr connection,
-                                 const char *path,
-                                 const char *domainPath)
+                                 const gchar *path,
+                                 const gchar *domainPath)
 {
-    _cleanup_(virtDBusUtilFreep) char *name = NULL;
-    int r;
+    g_autofree gchar *name = NULL;
+    gsize prefixLen = strlen(domainPath) + 1;
 
-    r = sd_bus_path_decode(path, domainPath, &name);
-    if (r < 0)
-        return NULL;
+    name = virtDBusUtilDecodeUUID(path+prefixLen);
+    g_assert(name);
 
     return virDomainLookupByUUIDString(connection, name);
 }
 
 void
-virtDBusUtilFreep(void *p)
-{
-    free(*(void **)p);
-}
-
-void
-virtDBusUtilClosep(int *fdp)
-{
-    if (*fdp >= 0)
-        close(*fdp);
-}
-
-void
-virtDBusUtilStrvFreep(void *p)
-{
-    char **strv = *(char ***)p;
-
-    if (strv == NULL)
-        return;
-
-    for (unsigned i = 0; strv[i] != NULL; i++)
-        free(strv[i]);
-
-    free(strv);
-}
-
-void
-virtDBusUtilVirDomainFreep(virDomainPtr *domainp)
-{
-    if (*domainp)
-        virDomainFree(*domainp);
-}
-
-void
-virtDBusUtilVirDomainListFreep(virDomainPtr **domainsp)
+virtDBusUtilVirDomainListFree(virDomainPtr *domains)
 {
-    virDomainPtr *domains = *domainsp;
-
-    if (!domains)
-        return;
-
-    for (int i = 0; domains[i] != NULL; i += 1)
+    for (gint i = 0; domains[i] != NULL; i += 1)
         virDomainFree(domains[i]);
 
-    free(domains);
+    g_free(domains);
 }
diff --git a/src/util.h b/src/util.h
index 2a6f7e2..8cafafa 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,49 +1,38 @@
 #pragma once
 
-#include <libvirt/libvirt.h>
-#include <systemd/sd-bus.h>
-
-#define VIRT_DBUS_ERROR_INTERFACE "org.libvirt.Error"
-
-#define _cleanup_(_x) __attribute__((__cleanup__(_x)))
+#include "gdbus.h"
 
-#define VIRT_ATTR_UNUSED __attribute__((__unused__))
+#include <libvirt/libvirt.h>
 
-#define VIRT_N_ELEMENTS(array) (sizeof(array) / sizeof(*(array)))
+#define VIRT_DBUS_ERROR virtDBusErrorQuark()
 
+typedef enum {
+    VIRT_DBUS_ERROR_LIBVIRT,
+    VIRT_DBUS_N_ERRORS /*< skip >*/
+} VirtDBusError;
 
-int
-virtDBusUtilMessageAppendTypedParameters(sd_bus_message *message,
-                                         virTypedParameterPtr parameters,
-                                         int n_parameters);
+GQuark
+virtDBusErrorQuark(void);
 
-int
-virtDBusUtilSetLastVirtError(sd_bus_error *error);
+GVariant *
+virtDBusUtilTypedParamsToGVariant(virTypedParameterPtr params,
+                                  gint nparams);
 
-int
-virtDBusUtilSetError(sd_bus_error *error,
-                     const char *message);
+void
+virtDBusUtilSetLastVirtError(GError **error);
 
-char *
+gchar *
 virtDBusUtilBusPathForVirDomain(virDomainPtr domain,
-                                const char *domainPath);
+                                const gchar *domainPath);
 
 virDomainPtr
 virtDBusUtilVirDomainFromBusPath(virConnectPtr connection,
-                                 const char *path,
-                                 const char *domainPath);
+                                 const gchar *path,
+                                 const gchar *domainPath);
 
 void
-virtDBusUtilFreep(void *p);
+virtDBusUtilVirDomainListFree(virDomainPtr *domains);
 
-void
-virtDBusUtilClosep(int *fdp);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomain, virDomainFree);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainPtr, virtDBusUtilVirDomainListFree);
 
-void
-virtDBusUtilStrvFreep(void *p);
-
-void
-virtDBusUtilVirDomainFreep(virDomainPtr *domainp);
-
-void
-virtDBusUtilVirDomainListFreep(virDomainPtr **domainsp);
diff --git a/test/travis-run b/test/travis-run
index 28260f4..7577253 100755
--- a/test/travis-run
+++ b/test/travis-run
@@ -22,7 +22,7 @@ sudo chroot "$CHROOT" << EOF
 set -ex
 # install build deps
 apt-get update
-apt-get install -y dh-autoreconf pkg-config libvirt-dev libsystemd-dev libglib2.0-dev libtool python3-gi python3-dbus dbus
+apt-get install -y dh-autoreconf pkg-config libvirt-dev libglib2.0-dev libtool python3-gi python3-dbus dbus
 
 # run build and tests as user
 chown -R buildd:buildd /build
-- 
2.14.3




More information about the libvir-list mailing list