From cf6cc86cd2177f3dfaccb4cccf5ea487051e9f45 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Tue, 15 Sep 2020 14:22:57 +0200 Subject: [PATCH] drop libdbus from libvirt Signed-off-by: Pavel Hrdina Reviewed-by: Michal Privoznik --- libvirt.spec.in | 3 - meson.build | 27 +- meson_options.txt | 1 - po/POTFILES.in | 1 - src/libvirt_private.syms | 17 - src/libvirt_probes.d | 6 - src/meson.build | 1 - src/remote/remote_daemon_dispatch.c | 1 - src/util/meson.build | 2 - src/util/virdbus.c | 1871 --------------------------- src/util/virdbus.h | 76 -- src/util/virdbuspriv.h | 56 - tests/meson.build | 13 - tests/virdbusmock.c | 62 - tests/virdbustest.c | 728 ----------- 15 files changed, 3 insertions(+), 2862 deletions(-) delete mode 100644 src/util/virdbus.c delete mode 100644 src/util/virdbus.h delete mode 100644 src/util/virdbuspriv.h delete mode 100644 tests/virdbusmock.c delete mode 100644 tests/virdbustest.c diff --git a/libvirt.spec.in b/libvirt.spec.in index d9bfed0bef..c4a7c30737 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -374,9 +374,6 @@ BuildRequires: util-linux # For showmount in FS driver (netfs discovery) BuildRequires: nfs-utils -# Communication with the firewall and polkit daemons use DBus -BuildRequires: dbus-devel - # Fedora build root suckage BuildRequires: gawk diff --git a/meson.build b/meson.build index b5b1223227..24535a403c 100644 --- a/meson.build +++ b/meson.build @@ -1019,22 +1019,6 @@ if curl_dep.found() conf.set('WITH_CURL', 1) endif -dbus_version = '1.0.0' -dbus_dep = dependency('dbus-1', version: '>=' + dbus_version, required: get_option('dbus')) -if dbus_dep.found() - conf.set('WITH_DBUS', 1) - - function = 'dbus_watch_get_unix_fd' - if cc.has_function(function, dependencies: dbus_dep) - conf.set('WITH_@0@'.format(function.to_upper()), 1) - endif - - type = 'DBusBasicValue' - if cc.has_type(type, dependencies: dbus_dep, prefix: '#include ') - conf.set('WITH_@0@'.format(type.to_upper()), 1) - endif -endif - devmapper_version = '1.0.0' devmapper_dep = dependency('devmapper', version: '>=' + devmapper_version, required: false) if not devmapper_dep.found() @@ -1536,10 +1520,8 @@ if bash_completion_dep.found() endif if host_machine.system() != 'freebsd' - if not get_option('firewalld').disabled() and dbus_dep.found() + if not get_option('firewalld').disabled() conf.set('WITH_FIREWALLD', 1) - elif get_option('firewalld').enabled() - error('You must have dbus enabled for firewalld support') endif endif @@ -1553,10 +1535,8 @@ if conf.has('WITH_MACVTAP') and not conf.has('WITH_LIBNL') error('libnl3-devel is required for macvtap support') endif -if (pkcheck_prog.found() or get_option('polkit').enabled()) and dbus_dep.found() +if (pkcheck_prog.found() or get_option('polkit').enabled()) conf.set('WITH_POLKIT', 1) -elif get_option('polkit').enabled() - error('You must install dbus to compile libvirt with polkit-1') endif if udev_dep.found() and not pciaccess_dep.found() @@ -2203,7 +2183,7 @@ endif if not get_option('pm_utils').disabled() use_pm_utils = true - if dbus_dep.found() and init_script == 'systemd' + if init_script == 'systemd' use_pm_utils = false endif @@ -2423,7 +2403,6 @@ libs_summary = { 'blkid': blkid_dep.found(), 'capng': capng_dep.found(), 'curl': curl_dep.found(), - 'dbus': dbus_dep.found(), 'dlopen': dlopen_dep.found(), 'firewalld': conf.has('WITH_FIREWALLD'), 'firewalld-zone': conf.has('WITH_FIREWALLD_ZONE'), diff --git a/meson_options.txt b/meson_options.txt index c8886e1430..f92c80553c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -18,7 +18,6 @@ option('bash_completion_dir', type: 'string', value: '', description: 'directory option('blkid', type: 'feature', value: 'auto', description: 'blkid support') option('capng', type: 'feature', value: 'auto', description: 'cap-ng support') option('curl', type: 'feature', value: 'auto', description: 'curl support') -option('dbus', type: 'feature', value: 'auto', description: 'dbus-1 support') option('firewalld', type: 'feature', value: 'auto', description: 'firewalld support') option('firewalld_zone', type: 'feature', value: 'auto', description: 'whether to install firewalld libvirt zone') option('fuse', type: 'feature', value: 'auto', description: 'fuse support') diff --git a/po/POTFILES.in b/po/POTFILES.in index d87425a64c..54f78e7861 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -243,7 +243,6 @@ @SRCDIR@src/util/virconf.c @SRCDIR@src/util/vircrypto.c @SRCDIR@src/util/virdaemon.c -@SRCDIR@src/util/virdbus.c @SRCDIR@src/util/virdevmapper.c @SRCDIR@src/util/virdnsmasq.c @SRCDIR@src/util/virerror.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fea5a49e55..bdbe3431b8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1948,23 +1948,6 @@ virDaemonSetupLogging; virDaemonUnixSocketPaths; -# util/virdbus.h -virDBusCallMethod; -virDBusCloseSystemBus; -virDBusCreateMethod; -virDBusCreateMethodV; -virDBusCreateReply; -virDBusCreateReplyV; -virDBusErrorIsUnknownMethod; -virDBusGetSessionBus; -virDBusGetSystemBus; -virDBusHasSystemBus; -virDBusMessageDecode; -virDBusMessageEncode; -virDBusMessageUnref; -virDBusSetSharedBus; - - # util/virdevmapper.h virDevMapperGetTargets; virIsDevMapperDevice; diff --git a/src/libvirt_probes.d b/src/libvirt_probes.d index 5e4faa2f5b..6fac10a2bf 100644 --- a/src/libvirt_probes.d +++ b/src/libvirt_probes.d @@ -13,12 +13,6 @@ provider libvirt { probe event_glib_remove_timeout_idle(int timer, void *ff, void *opaque); probe event_glib_dispatch_timeout(int timer, void *cb, void *opaque); - # file: src/util/virdbus.c - # prefix: dbus - probe dbus_method_call(const char *interface, const char *member, const char *object, const char *destination); - probe dbus_method_error(const char *interface, const char *member, const char *object, const char *destination, const char *name, const char *message); - probe dbus_method_reply(const char *interface, const char *member, const char *object, const char *destination); - # file: src/util/virobject.c # prefix: object probe object_new(void *obj, const char *klassname); diff --git a/src/meson.build b/src/meson.build index 897b5ecbca..29c8210ab2 100644 --- a/src/meson.build +++ b/src/meson.build @@ -614,7 +614,6 @@ foreach daemon : virt_daemons dependencies: [ admin_dep, access_dep, - dbus_dep, gnutls_dep, libnl_dep, rpc_dep, diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 53d17a8f4a..c187932a3c 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -35,7 +35,6 @@ #include "virnetserver.h" #include "virfile.h" #include "virtypedparam.h" -#include "virdbus.h" #include "virprocess.h" #include "remote_protocol.h" #include "qemu_protocol.h" diff --git a/src/util/meson.build b/src/util/meson.build index 8a9dcac053..4d63173cbd 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -18,7 +18,6 @@ util_sources = [ 'virconf.c', 'vircrypto.c', 'virdaemon.c', - 'virdbus.c', 'virdevmapper.c', 'virdnsmasq.c', 'virebtables.c', @@ -185,7 +184,6 @@ virt_util_lib = static_library( acl_dep, audit_dep, capng_dep, - dbus_dep, devmapper_dep, gnutls_dep, intl_dep, diff --git a/src/util/virdbus.c b/src/util/virdbus.c deleted file mode 100644 index 459b57abc6..0000000000 --- a/src/util/virdbus.c +++ /dev/null @@ -1,1871 +0,0 @@ -/* - * virdbus.c: helper for using DBus - * - * Copyright (C) 2012-2014 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, see - * . - * - */ - -#include - -#define LIBVIRT_VIRDBUSPRIV_H_ALLOW -#include "virdbuspriv.h" -#include "viralloc.h" -#include "virerror.h" -#include "virlog.h" -#include "virthread.h" -#include "virstring.h" -#include "virprobe.h" - -#define VIR_FROM_THIS VIR_FROM_DBUS - -VIR_LOG_INIT("util.dbus"); - -#ifdef WITH_DBUS - -static bool sharedBus = true; -static DBusConnection *systembus; -static DBusConnection *sessionbus; -static virOnceControl systemonce = VIR_ONCE_CONTROL_INITIALIZER; -static virOnceControl sessiononce = VIR_ONCE_CONTROL_INITIALIZER; -static DBusError systemdbuserr; -static DBusError sessiondbuserr; - -static dbus_bool_t virDBusAddWatch(DBusWatch *watch, void *data); -static void virDBusRemoveWatch(DBusWatch *watch, void *data); -static void virDBusToggleWatch(DBusWatch *watch, void *data); - -void virDBusSetSharedBus(bool shared) -{ - sharedBus = shared; -} - -static DBusConnection *virDBusBusInit(DBusBusType type, DBusError *dbuserr) -{ - DBusConnection *bus; - - /* Allocate and initialize a new HAL context */ - dbus_connection_set_change_sigpipe(FALSE); - dbus_threads_init_default(); - - dbus_error_init(dbuserr); - bus = sharedBus ? - dbus_bus_get(type, dbuserr) : - dbus_bus_get_private(type, dbuserr); - if (!bus) - return NULL; - - dbus_connection_set_exit_on_disconnect(bus, FALSE); - - /* Register dbus watch callbacks */ - if (!dbus_connection_set_watch_functions(bus, - virDBusAddWatch, - virDBusRemoveWatch, - virDBusToggleWatch, - bus, NULL)) { - return NULL; - } - return bus; -} - -static void virDBusSystemBusInit(void) -{ - systembus = virDBusBusInit(DBUS_BUS_SYSTEM, &systemdbuserr); -} - -static DBusConnection * -virDBusGetSystemBusInternal(void) -{ - if (virOnce(&systemonce, virDBusSystemBusInit) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to run one time DBus initializer")); - return NULL; - } - - return systembus; -} - - -DBusConnection * -virDBusGetSystemBus(void) -{ - DBusConnection *bus; - - if (!(bus = virDBusGetSystemBusInternal())) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get DBus system bus connection: %s"), - systemdbuserr.message ? systemdbuserr.message : "watch setup failed"); - return NULL; - } - - return bus; -} - - -/** - * virDBusHasSystemBus: - * - * Check if dbus system bus is running. This does not - * imply that we have a connection. DBus might be running - * and refusing connections due to its client limit. The - * latter must be treated as a fatal error. - * - * Return false if dbus is not available, true if probably available. - */ -bool -virDBusHasSystemBus(void) -{ - if (virDBusGetSystemBusInternal()) - return true; - - if (systemdbuserr.name && - (STREQ(systemdbuserr.name, "org.freedesktop.DBus.Error.FileNotFound") || - STREQ(systemdbuserr.name, "org.freedesktop.DBus.Error.NoServer"))) { - VIR_DEBUG("System DBus not available: %s", NULLSTR(systemdbuserr.message)); - return false; - } - return true; -} - - -void virDBusCloseSystemBus(void) -{ - if (systembus && !sharedBus) { - dbus_connection_close(systembus); - dbus_connection_unref(systembus); - systembus = NULL; - } -} - -static void virDBusSessionBusInit(void) -{ - sessionbus = virDBusBusInit(DBUS_BUS_SESSION, &sessiondbuserr); -} - -DBusConnection *virDBusGetSessionBus(void) -{ - if (virOnce(&sessiononce, virDBusSessionBusInit) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to run one time DBus initializer")); - return NULL; - } - - if (!sessionbus) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get DBus session bus connection: %s"), - sessiondbuserr.message ? sessiondbuserr.message : "watch setup failed"); - return NULL; - } - - return sessionbus; -} - -struct virDBusWatch -{ - int watch; - DBusConnection *bus; -}; - -static void virDBusWatchCallback(int fdatch G_GNUC_UNUSED, - int fd G_GNUC_UNUSED, - int events, void *opaque) -{ - DBusWatch *watch = opaque; - struct virDBusWatch *info; - int dbus_flags = 0; - - info = dbus_watch_get_data(watch); - - 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; - - if (dbus_watch_handle(watch, dbus_flags) == FALSE) - VIR_DEBUG("dbus_watch_handle() returned FALSE"); - - dbus_connection_ref(info->bus); - while (dbus_connection_dispatch(info->bus) == DBUS_DISPATCH_DATA_REMAINS) - /* keep dispatching while data remains */; - dbus_connection_unref(info->bus); -} - - -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; -} - - -static void virDBusWatchFree(void *data) -{ - struct virDBusWatch *info = data; - VIR_FREE(info); -} - -static dbus_bool_t virDBusAddWatch(DBusWatch *watch, - void *data) -{ - int flags = 0; - int fd; - struct virDBusWatch *info; - - if (VIR_ALLOC(info) < 0) - return FALSE; - - if (dbus_watch_get_enabled(watch)) - flags = virDBusTranslateWatchFlags(dbus_watch_get_flags(watch)); - -# if WITH_DBUS_WATCH_GET_UNIX_FD - fd = dbus_watch_get_unix_fd(watch); -# else - fd = dbus_watch_get_fd(watch); -# endif - dbus_watch_set_data(watch, info, virDBusWatchFree); - info->bus = (DBusConnection *)data; - info->watch = virEventAddHandle(fd, flags, - virDBusWatchCallback, - watch, NULL); - if (info->watch < 0) { - dbus_watch_set_data(watch, NULL, NULL); - return FALSE; - } - - return TRUE; -} - - -static void virDBusRemoveWatch(DBusWatch *watch, - void *data G_GNUC_UNUSED) -{ - struct virDBusWatch *info; - - info = dbus_watch_get_data(watch); - - (void)virEventRemoveHandle(info->watch); -} - - -static void virDBusToggleWatch(DBusWatch *watch, - void *data G_GNUC_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); -} - -# define VIR_DBUS_TYPE_STACK_MAX_DEPTH 32 - -static const char virDBusBasicTypes[] = { - DBUS_TYPE_BYTE, - DBUS_TYPE_BOOLEAN, - DBUS_TYPE_INT16, - DBUS_TYPE_UINT16, - DBUS_TYPE_INT32, - DBUS_TYPE_UINT32, - DBUS_TYPE_INT64, - DBUS_TYPE_UINT64, - DBUS_TYPE_DOUBLE, - DBUS_TYPE_STRING, - DBUS_TYPE_OBJECT_PATH, - DBUS_TYPE_SIGNATURE, -}; - -static bool virDBusIsBasicType(char c) -{ - return !!memchr(virDBusBasicTypes, c, G_N_ELEMENTS(virDBusBasicTypes)); -} - -/* - * All code related to virDBusMessageIterEncode and - * virDBusMessageIterDecode is derived from systemd - * bus_message_append_ap()/message_read_ap() in - * bus-message.c under the terms of the LGPLv2+ - */ -static int -virDBusSignatureLengthInternal(const char *s, - bool allowDict, - unsigned arrayDepth, - unsigned structDepth, - size_t *skiplen, - size_t *siglen) -{ - if (virDBusIsBasicType(*s) || *s == DBUS_TYPE_VARIANT) { - *skiplen = *siglen = 1; - return 0; - } - - if (*s == DBUS_TYPE_ARRAY) { - size_t skiplencont; - size_t siglencont; - bool arrayref = false; - - if (arrayDepth >= VIR_DBUS_TYPE_STACK_MAX_DEPTH) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Signature '%s' too deeply nested"), - s); - return -1; - } - - if (*(s + 1) == '&') { - arrayref = true; - s++; - } - - if (virDBusSignatureLengthInternal(s + 1, - true, - arrayDepth + 1, - structDepth, - &skiplencont, - &siglencont) < 0) - return -1; - - *skiplen = skiplencont + 1; - *siglen = siglencont + 1; - if (arrayref) - (*skiplen)++; - return 0; - } - - if (*s == DBUS_STRUCT_BEGIN_CHAR) { - const char *p = s + 1; - - if (structDepth >= VIR_DBUS_TYPE_STACK_MAX_DEPTH) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Signature '%s' too deeply nested"), - s); - return -1; - } - - *skiplen = *siglen = 2; - - while (*p != DBUS_STRUCT_END_CHAR) { - size_t skiplencont; - size_t siglencont; - - if (virDBusSignatureLengthInternal(p, - false, - arrayDepth, - structDepth + 1, - &skiplencont, - &siglencont) < 0) - return -1; - - p += skiplencont; - *skiplen += skiplencont; - *siglen += siglencont; - } - - return 0; - } - - if (*s == DBUS_DICT_ENTRY_BEGIN_CHAR && allowDict) { - const char *p = s + 1; - unsigned n = 0; - if (structDepth >= VIR_DBUS_TYPE_STACK_MAX_DEPTH) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Signature '%s' too deeply nested"), - s); - return -1; - } - - *skiplen = *siglen = 2; - - while (*p != DBUS_DICT_ENTRY_END_CHAR) { - size_t skiplencont; - size_t siglencont; - - if (n == 0 && !virDBusIsBasicType(*p)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Dict entry in signature '%s' must be a basic type"), - s); - return -1; - } - - if (virDBusSignatureLengthInternal(p, - false, - arrayDepth, - structDepth + 1, - &skiplencont, - &siglencont) < 0) - return -1; - - p += skiplencont; - *skiplen += skiplencont; - *siglen += siglencont; - n++; - } - - if (n != 2) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Dict entry in signature '%s' is wrong size"), - s); - return -1; - } - - return 0; - } - - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unexpected signature '%s'"), s); - return -1; -} - - -static int virDBusSignatureLength(const char *s, size_t *skiplen, size_t *siglen) -{ - return virDBusSignatureLengthInternal(s, true, 0, 0, skiplen, siglen); -} - - -static char *virDBusCopyContainerSignature(const char *sig, - size_t *skiplen, - size_t *siglen) -{ - size_t i, j; - char *contsig; - bool isGroup; - - isGroup = (sig[0] == DBUS_STRUCT_BEGIN_CHAR || - sig[0] == DBUS_DICT_ENTRY_BEGIN_CHAR); - - if (virDBusSignatureLength(isGroup ? sig : sig + 1, skiplen, siglen) < 0) - return NULL; - - if (VIR_ALLOC_N(contsig, *siglen + 1) < 0) - return NULL; - - for (i = 0, j = 0; i < *skiplen && j < *siglen; i++) { - if (sig[i + 1] == '&') - continue; - contsig[j] = sig[i + 1]; - j++; - } - contsig[*siglen] = '\0'; - VIR_DEBUG("Extracted '%s' from '%s'", contsig, sig); - return contsig; -} - - -/* Ideally, we'd just call ourselves recursively on every - * complex type. However, the state of a va_list that is - * passed to a function is undefined after that function - * returns. This means we need to decode the va_list linearly - * in a single stackframe. We hence implement our own - * home-grown stack in an array. */ - -typedef struct _virDBusTypeStack virDBusTypeStack; -struct _virDBusTypeStack { - const char *types; - size_t nstruct; - size_t narray; - DBusMessageIter *iter; -}; - -static int virDBusTypeStackPush(virDBusTypeStack **stack, - size_t *nstack, - DBusMessageIter *iter, - const char *types, - size_t nstruct, - size_t narray) -{ - if (*nstack >= VIR_DBUS_TYPE_STACK_MAX_DEPTH) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("DBus type too deeply nested")); - return -1; - } - - if (VIR_EXPAND_N(*stack, *nstack, 1) < 0) - return -1; - - (*stack)[(*nstack) - 1].iter = iter; - (*stack)[(*nstack) - 1].types = types; - (*stack)[(*nstack) - 1].nstruct = nstruct; - (*stack)[(*nstack) - 1].narray = narray; - VIR_DEBUG("Pushed types='%s' nstruct=%zu narray=%zd", - types, nstruct, (ssize_t)narray); - return 0; -} - - -static int virDBusTypeStackPop(virDBusTypeStack **stack, - size_t *nstack, - DBusMessageIter **iter, - const char **types, - size_t *nstruct, - size_t *narray) -{ - if (*nstack == 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("DBus type stack is empty")); - return -1; - } - - *iter = (*stack)[(*nstack) - 1].iter; - *types = (*stack)[(*nstack) - 1].types; - *nstruct = (*stack)[(*nstack) - 1].nstruct; - *narray = (*stack)[(*nstack) - 1].narray; - VIR_DEBUG("Popped types='%s' nstruct=%zu narray=%zd", - *types, *nstruct, (ssize_t)*narray); - VIR_SHRINK_N(*stack, *nstack, 1); - - return 0; -} - - -static void virDBusTypeStackFree(virDBusTypeStack **stack, - size_t *nstack) -{ - size_t i; - - if (!*stack) - return; - - /* The iter in the first level of the stack is the - * root iter which must not be freed - */ - for (i = 1; i < *nstack; i++) - VIR_FREE((*stack)[i].iter); - VIR_FREE(*stack); -} - - -static bool -virDBusIsAllowedRefType(const char *sig) -{ - if (*sig == '{') { - if (strlen(sig) != 4) - return false; - if (!virDBusIsBasicType(sig[1]) || - !virDBusIsBasicType(sig[2]) || - sig[1] != sig[2]) - return false; - if (sig[3] != '}') - return false; - } else { - if (strlen(sig) != 1) - return false; - if (!virDBusIsBasicType(sig[0])) - return false; - } - return true; -} - - -# define SET_NEXT_VAL(dbustype, vargtype, arrtype, sigtype, fmt) \ - do { \ - dbustype x; \ - if (arrayref) { \ - arrtype valarray = arrayptr; \ - x = (dbustype)*valarray; \ - valarray++; \ - arrayptr = valarray; \ - } else { \ - x = (dbustype)va_arg(args, vargtype); \ - } \ - if (!dbus_message_iter_append_basic(iter, sigtype, &x)) { \ - virReportError(VIR_ERR_INTERNAL_ERROR, \ - _("Cannot append basic type %s"), #vargtype);\ - goto cleanup; \ - } \ - VIR_DEBUG("Appended basic type '" #dbustype "' varg '" #vargtype\ - "' sig '%c' val '" fmt "'", sigtype, (vargtype)x); \ - } while (0) - - -static int -virDBusMessageIterEncode(DBusMessageIter *rootiter, - const char *types, - va_list args) -{ - int ret = -1; - size_t narray; - size_t nstruct; - bool arrayref = false; - void *arrayptr = NULL; - virDBusTypeStack *stack = NULL; - size_t nstack = 0; - size_t siglen; - size_t skiplen; - char *contsig = NULL; - const char *vsig; - DBusMessageIter *newiter = NULL; - DBusMessageIter *iter = rootiter; - - VIR_DEBUG("rootiter=%p types=%s", rootiter, types); - - if (!types) - return 0; - - narray = (size_t)-1; - nstruct = strlen(types); - - for (;;) { - const char *t; - - VIR_DEBUG("Loop nstack=%zu narray=%zd nstruct=%zu types='%s'", - nstack, (ssize_t)narray, nstruct, types); - if (narray == 0 || - (narray == (size_t)-1 && - nstruct == 0)) { - DBusMessageIter *thisiter = iter; - if (*types != '}') { - VIR_DEBUG("Reset array ref"); - arrayref = false; - arrayptr = NULL; - } - VIR_DEBUG("Popping iter=%p", iter); - if (nstack == 0) - break; - if (virDBusTypeStackPop(&stack, &nstack, &iter, - &types, &nstruct, &narray) < 0) - goto cleanup; - VIR_DEBUG("Popped iter=%p", iter); - - if (!dbus_message_iter_close_container(iter, thisiter)) { - if (thisiter != rootiter) - VIR_FREE(thisiter); - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot close container iterator")); - goto cleanup; - } - if (thisiter != rootiter) - VIR_FREE(thisiter); - continue; - } - - t = types; - if (narray != (size_t)-1) { - narray--; - } else { - types++; - nstruct--; - } - - switch (*t) { - case DBUS_TYPE_BYTE: - SET_NEXT_VAL(unsigned char, int, unsigned char *, *t, "%d"); - break; - - case DBUS_TYPE_BOOLEAN: - SET_NEXT_VAL(dbus_bool_t, int, bool *, *t, "%d"); - break; - - case DBUS_TYPE_INT16: - SET_NEXT_VAL(dbus_int16_t, int, short *, *t, "%d"); - break; - - case DBUS_TYPE_UINT16: - SET_NEXT_VAL(dbus_uint16_t, unsigned int, unsigned short *, - *t, "%d"); - break; - - case DBUS_TYPE_INT32: - SET_NEXT_VAL(dbus_int32_t, int, int *, *t, "%d"); - break; - - case DBUS_TYPE_UINT32: - SET_NEXT_VAL(dbus_uint32_t, unsigned int, unsigned int *, - *t, "%u"); - break; - - case DBUS_TYPE_INT64: - SET_NEXT_VAL(dbus_int64_t, long long, long long *, *t, "%lld"); - break; - - case DBUS_TYPE_UINT64: - SET_NEXT_VAL(dbus_uint64_t, unsigned long long, - unsigned long long *, *t, "%llu"); - break; - - case DBUS_TYPE_DOUBLE: - SET_NEXT_VAL(double, double, double *, *t, "%lf"); - break; - - case DBUS_TYPE_STRING: - case DBUS_TYPE_OBJECT_PATH: - case DBUS_TYPE_SIGNATURE: - SET_NEXT_VAL(char *, char *, char **, *t, "%s"); - break; - - case DBUS_TYPE_ARRAY: - arrayptr = NULL; - if (t[1] == '&') { - VIR_DEBUG("Got array ref"); - t++; - types++; - nstruct--; - arrayref = true; - } else { - VIR_DEBUG("Got array non-ref"); - arrayref = false; - } - - if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen))) - goto cleanup; - - if (arrayref && !virDBusIsAllowedRefType(contsig)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Got array ref but '%s' is not a single basic type " - "or dict with matching key+value type"), - contsig); - goto cleanup; - } - - if (narray == (size_t)-1) { - types += skiplen; - nstruct -= skiplen; - } - - if (VIR_ALLOC(newiter) < 0) - goto cleanup; - VIR_DEBUG("Contsig '%s' skip='%zu' len='%zu'", contsig, skiplen, siglen); - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, - contsig, newiter)) - goto cleanup; - if (virDBusTypeStackPush(&stack, &nstack, - iter, types, - nstruct, narray) < 0) { - VIR_FREE(newiter); - goto cleanup; - } - VIR_FREE(contsig); - iter = g_steal_pointer(&newiter); - types = t + 1; - nstruct = skiplen; - narray = (size_t)va_arg(args, int); - if (arrayref) - arrayptr = va_arg(args, void *); - break; - - case DBUS_TYPE_VARIANT: - vsig = va_arg(args, const char *); - if (!vsig) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Missing variant type signature")); - goto cleanup; - } - if (VIR_ALLOC(newiter) < 0) - goto cleanup; - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, - vsig, newiter)) - goto cleanup; - if (virDBusTypeStackPush(&stack, &nstack, - iter, types, - nstruct, narray) < 0) { - VIR_FREE(newiter); - goto cleanup; - } - iter = g_steal_pointer(&newiter); - types = vsig; - nstruct = strlen(types); - narray = (size_t)-1; - break; - - case DBUS_STRUCT_BEGIN_CHAR: - case DBUS_DICT_ENTRY_BEGIN_CHAR: - if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen))) - goto cleanup; - - if (VIR_ALLOC(newiter) < 0) - goto cleanup; - VIR_DEBUG("Contsig '%s' skip='%zu' len='%zu'", contsig, skiplen, siglen); - if (!dbus_message_iter_open_container(iter, - *t == DBUS_STRUCT_BEGIN_CHAR ? - DBUS_TYPE_STRUCT : DBUS_TYPE_DICT_ENTRY, - NULL, newiter)) - goto cleanup; - if (narray == (size_t)-1) { - types += skiplen - 1; - nstruct -= skiplen - 1; - } - - if (virDBusTypeStackPush(&stack, &nstack, - iter, types, - nstruct, narray) < 0) { - VIR_FREE(newiter); - goto cleanup; - } - VIR_FREE(contsig); - iter = g_steal_pointer(&newiter); - types = t + 1; - nstruct = skiplen - 2; - narray = (size_t)-1; - - break; - - default: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown type '%x' in signature '%s'"), - (int)*t, types); - goto cleanup; - } - } - - ret = 0; - - cleanup: - while (nstack > 0) { - DBusMessageIter *thisiter = iter; - VIR_DEBUG("Popping iter=%p", iter); - ignore_value(virDBusTypeStackPop(&stack, &nstack, &iter, - &types, &nstruct, &narray)); - VIR_DEBUG("Popped iter=%p", iter); - - if (thisiter != rootiter) - VIR_FREE(thisiter); - } - - virDBusTypeStackFree(&stack, &nstack); - VIR_FREE(contsig); - VIR_FREE(newiter); - return ret; -} -# undef SET_NEXT_VAL - - -# define GET_NEXT_VAL(dbustype, member, vargtype, fmt) \ - do { \ - DBusBasicValue v; \ - dbustype *x = (dbustype *)&v.member; \ - vargtype *y; \ - if (arrayref) { \ - vargtype **xptrptr = arrayptr; \ - VIR_DEBUG("Use arrayref"); \ - if (VIR_EXPAND_N(*xptrptr, *narrayptr, 1) < 0) \ - goto cleanup; \ - y = (*xptrptr + (*narrayptr - 1)); \ - VIR_DEBUG("Expanded to %zu", *narrayptr); \ - } else { \ - y = va_arg(args, vargtype *); \ - } \ - dbus_message_iter_get_basic(iter, x); \ - *y = *x; \ - VIR_DEBUG("Read basic type '" #dbustype "' varg '" #vargtype \ - "' val '" fmt "'", (vargtype)*y); \ - } while (0) - - -static int -virDBusMessageIterDecode(DBusMessageIter *rootiter, - const char *types, - va_list args) -{ - int ret = -1; - size_t narray; - size_t nstruct; - bool arrayref = false; - void *arrayptr = NULL; - size_t *narrayptr = 0; - virDBusTypeStack *stack = NULL; - size_t nstack = 0; - size_t skiplen; - size_t siglen; - char *contsig = NULL; - const char *vsig; - DBusMessageIter *newiter = NULL; - DBusMessageIter *iter = rootiter; - - VIR_DEBUG("rootiter=%p types=%s", rootiter, types); - - if (!types) - return 0; - - narray = (size_t)-1; - nstruct = strlen(types); - - for (;;) { - const char *t; - bool advanceiter = true; - - VIR_DEBUG("Loop nstack=%zu narray=%zd nstruct=%zu type='%s'", - nstack, (ssize_t)narray, nstruct, types); - if (narray == 0 || - (narray == (size_t)-1 && - nstruct == 0)) { - DBusMessageIter *thisiter = iter; - VIR_DEBUG("Popping iter=%p", iter); - if (nstack == 0) - break; - if (virDBusTypeStackPop(&stack, &nstack, &iter, - &types, &nstruct, &narray) < 0) - goto cleanup; - VIR_DEBUG("Popped iter=%p types=%s", iter, types); - if (strchr(types, '}') == NULL) { - arrayref = false; - arrayptr = NULL; - VIR_DEBUG("Clear array ref flag"); - } - if (thisiter != rootiter) - VIR_FREE(thisiter); - if (arrayref) { - if (!dbus_message_iter_has_next(iter)) - narray = 0; - else - narray = 1; - VIR_DEBUG("Pop set narray=%zd", (ssize_t)narray); - } - if (!(narray == 0 || - (narray == (size_t)-1 && - nstruct == 0)) && - !dbus_message_iter_next(iter)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Not enough fields in message for signature")); - goto cleanup; - } - continue; - } - - t = types; - if (narray != (size_t)-1) { - if (!arrayref) - narray--; - } else { - types++; - nstruct--; - } - - switch (*t) { - case DBUS_TYPE_BYTE: - GET_NEXT_VAL(unsigned char, byt, unsigned char, "%d"); - break; - - case DBUS_TYPE_BOOLEAN: - GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d"); - break; - - case DBUS_TYPE_INT16: - GET_NEXT_VAL(dbus_int16_t, i16, short, "%d"); - break; - - case DBUS_TYPE_UINT16: - GET_NEXT_VAL(dbus_uint16_t, u16, unsigned short, "%d"); - break; - - case DBUS_TYPE_INT32: - GET_NEXT_VAL(dbus_uint32_t, i32, int, "%d"); - break; - - case DBUS_TYPE_UINT32: - GET_NEXT_VAL(dbus_uint32_t, u32, unsigned int, "%u"); - break; - - case DBUS_TYPE_INT64: - GET_NEXT_VAL(dbus_uint64_t, i64, long long, "%lld"); - break; - - case DBUS_TYPE_UINT64: - GET_NEXT_VAL(dbus_uint64_t, u64, unsigned long long, "%llu"); - break; - - case DBUS_TYPE_DOUBLE: - GET_NEXT_VAL(double, dbl, double, "%lf"); - break; - - case DBUS_TYPE_STRING: - case DBUS_TYPE_OBJECT_PATH: - case DBUS_TYPE_SIGNATURE: - do { - char **x; - char *s; - if (arrayref) { - char ***xptrptr = arrayptr; - if (VIR_EXPAND_N(*xptrptr, *narrayptr, 1) < 0) - goto cleanup; - x = (char **)(*xptrptr + (*narrayptr - 1)); - VIR_DEBUG("Expanded to %zu", *narrayptr); - } else { - x = (char **)va_arg(args, char **); - } - dbus_message_iter_get_basic(iter, &s); - *x = g_strdup(s); - VIR_DEBUG("Read basic type 'char *' varg 'char **'" - "' val '%s'", *x); - } while (0); - break; - - case DBUS_TYPE_ARRAY: - arrayptr = NULL; - if (t[1] == '&') { - VIR_DEBUG("Got array ref"); - t++; - types++; - nstruct--; - arrayref = true; - } else { - VIR_DEBUG("Got array non-ref"); - arrayref = false; - } - - advanceiter = false; - if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen))) - goto cleanup; - - if (arrayref && !virDBusIsAllowedRefType(contsig)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Got array ref but '%s' is not a single basic type / dict"), - contsig); - goto cleanup; - } - - if (narray == (size_t)-1) { - types += skiplen; - nstruct -= skiplen; - } - - if (VIR_ALLOC(newiter) < 0) - goto cleanup; - VIR_DEBUG("Array contsig='%s' skip=%'zu' len='%zu' types='%s'", - contsig, skiplen, siglen, types); - dbus_message_iter_recurse(iter, newiter); - if (virDBusTypeStackPush(&stack, &nstack, - iter, types, - nstruct, narray) < 0) - goto cleanup; - VIR_FREE(contsig); - iter = g_steal_pointer(&newiter); - types = t + 1; - nstruct = skiplen; - if (arrayref) { - narrayptr = va_arg(args, size_t *); - arrayptr = va_arg(args, void *); - *narrayptr = 0; - *(char **)arrayptr = NULL; - } else { - narray = va_arg(args, int); - } - break; - - case DBUS_TYPE_VARIANT: - advanceiter = false; - vsig = va_arg(args, const char *); - if (!vsig) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Missing variant type signature")); - goto cleanup; - } - if (VIR_ALLOC(newiter) < 0) - goto cleanup; - dbus_message_iter_recurse(iter, newiter); - if (virDBusTypeStackPush(&stack, &nstack, - iter, types, - nstruct, narray) < 0) { - VIR_DEBUG("Push failed"); - goto cleanup; - } - iter = g_steal_pointer(&newiter); - types = vsig; - nstruct = strlen(types); - narray = (size_t)-1; - break; - - case DBUS_STRUCT_BEGIN_CHAR: - case DBUS_DICT_ENTRY_BEGIN_CHAR: - advanceiter = false; - if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen))) - goto cleanup; - - if (VIR_ALLOC(newiter) < 0) - goto cleanup; - VIR_DEBUG("Dict/struct contsig='%s' skip='%zu' len='%zu' types='%s'", - contsig, skiplen, siglen, types); - dbus_message_iter_recurse(iter, newiter); - if (narray == (size_t)-1) { - types += skiplen - 1; - nstruct -= skiplen - 1; - } - - if (virDBusTypeStackPush(&stack, &nstack, - iter, types, - nstruct, narray) < 0) - goto cleanup; - VIR_FREE(contsig); - iter = g_steal_pointer(&newiter); - types = t + 1; - nstruct = skiplen - 2; - narray = (size_t)-1; - - break; - - default: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown type '%c' in signature '%s'"), - *t, types); - goto cleanup; - } - - VIR_DEBUG("After nstack=%zu narray=%zd nstruct=%zu types='%s'", - nstack, (ssize_t)narray, nstruct, types); - - if (arrayref) { - if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID) { - narray = 0; - } else { - if (advanceiter) - dbus_message_iter_next(iter); - if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID) { - narray = 0; - } else { - narray = 1; - } - } - VIR_DEBUG("Set narray=%zd", (ssize_t)narray); - } else { - if (advanceiter && - !(narray == 0 || - (narray == (size_t)-1 && - nstruct == 0)) && - !dbus_message_iter_next(iter)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Not enough fields in message for signature")); - goto cleanup; - } - } - } - - if (dbus_message_iter_has_next(iter)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Too many fields in message for signature")); - goto cleanup; - } - - ret = 0; - - cleanup: - virDBusTypeStackFree(&stack, &nstack); - VIR_FREE(contsig); - VIR_FREE(newiter); - return ret; -} -# undef GET_NEXT_VAL - -int -virDBusMessageEncodeArgs(DBusMessage* msg, - const char *types, - va_list args) -{ - DBusMessageIter iter; - - memset(&iter, 0, sizeof(iter)); - - dbus_message_iter_init_append(msg, &iter); - - return virDBusMessageIterEncode(&iter, types, args); -} - - -int virDBusMessageDecodeArgs(DBusMessage* msg, - const char *types, - va_list args) -{ - DBusMessageIter iter; - - if (!dbus_message_iter_init(msg, &iter)) { - if (*types != '\0') { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("No args present for signature %s"), - types); - } else { - return 0; - } - return -1; - } - - return virDBusMessageIterDecode(&iter, types, args); -} - - -int virDBusMessageEncode(DBusMessage* msg, - const char *types, - ...) -{ - int ret; - va_list args; - va_start(args, types); - ret = virDBusMessageEncodeArgs(msg, types, args); - va_end(args); - return ret; -} - - -/** - * virDBusMessageDecode: - * @msg: the reply to decode - * @types: type signature for following return values - * @...: pointers in which to store return values - * - * The @types type signature is the same format as - * that used for the virDBusCallMethod. The difference - * is that each variadic parameter must be a pointer to - * be filled with the values. eg instead of passing an - * 'int', pass an 'int *'. - * - */ -int -virDBusMessageDecode(DBusMessage* msg, - const char *types, - ...) -{ - int ret; - va_list args; - va_start(args, types); - ret = virDBusMessageDecodeArgs(msg, types, args); - va_end(args); - return ret; -} - -# define VIR_DBUS_METHOD_CALL_TIMEOUT_MILLIS 30 * 1000 - -/** - * virDBusCreateMethodV: - * @call: pointer to be filled with a method call message - * @destination: bus identifier of the target service - * @path: object path of the target service - * @iface: the interface of the object - * @member: the name of the method in the interface - * @types: type signature for following method arguments - * @args: method arguments - * - * This creates a DBus method call message and saves a - * pointer to it in @call. The @destination, @path, @iface - * and @member parameters identify the object method to - * be invoked. The optional @replyout parameter will be - * filled with any reply to the method call. The method - * can be later invoked using virDBusCall. - * - * The @types parameter is a DBus signature describing - * the method call parameters which will be provided - * as variadic args. Each character in @types must - * correspond to one of the following DBus codes for - * basic types: - * - * 'y' - 8-bit byte, promoted to an 'int' - * 'b' - bool value, promoted to an 'int' - * 'n' - 16-bit signed integer, promoted to an 'int' - * 'q' - 16-bit unsigned integer, promoted to an 'int' - * 'i' - 32-bit signed integer, passed as an 'int' - * 'u' - 32-bit unsigned integer, passed as an 'int' - * 'x' - 64-bit signed integer, passed as a 'long long' - * 't' - 64-bit unsigned integer, passed as an 'unsigned long long' - * 'd' - 8-byte floating point, passed as a 'double' - * 's' - NUL-terminated string, in UTF-8 - * 'o' - NUL-terminated string, representing a valid object path - * 'g' - NUL-terminated string, representing a valid type signature - * - * or use one of the compound types - * - * 'a' - array of values - * 'v' - a variadic type. - * '(' - start of a struct - * ')' - end of a struct - * '{' - start of a dictionary entry (pair of types) - * '}' - start of a dictionary entry (pair of types) - * - * At this time, there is no support for Unix fd's ('h'), which only - * newer DBus supports. - * - * Passing values in variadic args for basic types is - * simple, the value is just passed directly using the - * corresponding C type listed against the type code - * above. Note how any integer value smaller than an - * 'int' is promoted to an 'int' by the C rules for - * variadic args. - * - * Passing values in variadic args for compound types - * requires a little further explanation. - * - * - Variant: the first arg is a string containing - * the type signature for the values to be stored - * inside the variant. This is then followed by - * the values corresponding to the type signature - * in the normal manner. - * - * - Array: when 'a' appears in a type signature, it - * must be followed by a single type describing the - * array element type. For example 'as' is an array - * of strings. 'a(is)' is an array of structs, each - * struct containing an int and a string. - * - * The first variadic arg for an array, is an 'int' - * specifying the number of elements in the array. - * This is then followed by additional variadic args, - * one for each element of the array. - * - * - Array reference: when 'a' appears in a type signature, - * followed by '&', this signifies an array passed by - * reference. - * - * Array references may only be used when the - * element values are basic types, or a dict - * entry where both keys and values are using - * the same basic type. - * - * The first variadic arg for an array, is an 'int' - * specifying the number of elements in the array. - * When the element is a basic type, the second - * variadic arg is a pointer to an array containing - * the element values. When the element is a dict - * entry, the second variadic arg is a pointer to - * an array containing the dict keys, and the - * third variadic arg is a pointer to an array - * containing the dict values. - * - * - Struct: when a '(' appears in a type signature, - * it must be followed by one or more types describing - * the elements in the array, terminated by a ')'. - * - * - Dict entry: when a '{' appears in a type signature it - * must be followed by exactly two types, one describing - * the type of the hash key, the other describing the - * type of the hash entry. The hash key type must be - * a basic type, not a compound type. - * - * Example signatures, with their corresponding variadic - * args: - * - * - "biiss" - some basic types - * - * (true, 7, 42, "hello", "world") - * - * - "as" - an array with a basic type element - * - * (3, "one", "two", "three") - * - * - "a(is)" - an array with a struct element - * - * (3, 1, "one", 2, "two", 3, "three") - * - * - "svs" - some basic types with a variant as an int - * - * ("hello", "i", 3, "world") - * - * - "svs" - some basic types with a variant as an array of ints - * - * ("hello", "ai", 4, 1, 2, 3, 4, "world") - * - * - "a{ss}" - a hash table (aka array + dict entry) - * - * (3, "title", "Mr", "forename", "Joe", "surname", "Bloggs") - * - * - "a{sv}" - a hash table (aka array + dict entry) - * - * (3, "email", "s", "joe@blogs.com", "age", "i", 35, - * "address", "as", 3, "Some house", "Some road", "some city") - */ -int virDBusCreateMethodV(DBusMessage **call, - const char *destination, - const char *path, - const char *iface, - const char *member, - const char *types, - va_list args) -{ - if (!(*call = dbus_message_new_method_call(destination, - path, - iface, - member))) { - virReportOOMError(); - return -1; - } - - if (virDBusMessageEncodeArgs(*call, types, args) < 0) { - virDBusMessageUnref(*call); - *call = NULL; - return -1; - } - - return 0; -} - - -/** - * virDBusCreateMethod: - * @call: pointer to be filled with a method call message - * @destination: bus identifier of the target service - * @path: object path of the target service - * @iface: the interface of the object - * @member: the name of the method in the interface - * @types: type signature for following method arguments - * @...: method arguments - * - * See virDBusCreateMethodV for a description of the - * behaviour of this method. - */ -int virDBusCreateMethod(DBusMessage **call, - const char *destination, - const char *path, - const char *iface, - const char *member, - const char *types, ...) -{ - va_list args; - int ret; - - va_start(args, types); - ret = virDBusCreateMethodV(call, destination, path, - iface, member, types, args); - va_end(args); - - return ret; -} - - -/** - * virDBusCreateReplyV: - * @reply: pointer to be filled with a method reply message - * @types: type signature for following method arguments - * @args: method arguments - * - * This creates a DBus method reply message and saves a - * pointer to it in @reply. - * - * The @types parameter is a DBus signature describing - * the method call parameters which will be provided - * as variadic args. See virDBusCreateMethodV for a - * description of this parameter. - */ -int virDBusCreateReplyV(DBusMessage **reply, - const char *types, - va_list args) -{ - if (!(*reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN))) { - virReportOOMError(); - return -1; - } - - if (virDBusMessageEncodeArgs(*reply, types, args) < 0) { - virDBusMessageUnref(*reply); - *reply = NULL; - return -1; - } - - return 0; -} - - -/** - * virDBusCreateReply: - * @reply: pointer to be filled with a method reply message - * @types: type signature for following method arguments - * @...: method arguments - * - * See virDBusCreateReplyV for a description of the - * behaviour of this method. - */ -int virDBusCreateReply(DBusMessage **reply, - const char *types, ...) -{ - va_list args; - int ret; - - va_start(args, types); - ret = virDBusCreateReplyV(reply, types, args); - va_end(args); - - return ret; -} - - -/** - * virDBusCall: - * @conn: a DBus connection - * @call: pointer to a message to send - * @replyout: pointer to receive reply message, or NULL - * @error: pointer to receive error message - * - * This invokes a method encoded in @call on a remote - * service on the DBus bus @conn. The optional @replyout - * parameter will be filled with any reply to the method - * call. The virDBusMethodReply method can be used to - * decode the return values. - * - * If @error is NULL then a libvirt error will be raised - * when a DBus error is received and the return value will - * be -1. If @error is non-NULL then any DBus error will - * be saved into that object and the return value will - * be 0. - * - * Returns 0 on success, or -1 upon error - */ -static int -virDBusCall(DBusConnection *conn, - DBusMessage *call, - DBusMessage **replyout, - virErrorPtr error) - -{ - DBusMessage *reply = NULL; - DBusError localerror; - int ret = -1; - const char *iface, *member, *path, *dest; - - dbus_error_init(&localerror); - if (error) - memset(error, 0, sizeof(*error)); - - iface = dbus_message_get_interface(call); - member = dbus_message_get_member(call); - path = dbus_message_get_path(call); - dest = dbus_message_get_destination(call); - - PROBE(DBUS_METHOD_CALL, - "'%s.%s' on '%s' at '%s'", - iface, member, path, dest); - - if (!(reply = dbus_connection_send_with_reply_and_block(conn, - call, - VIR_DBUS_METHOD_CALL_TIMEOUT_MILLIS, - &localerror))) { - PROBE(DBUS_METHOD_ERROR, - "'%s.%s' on '%s' at '%s' error %s: %s", - iface, member, path, dest, - localerror.name, - localerror.message); - if (error) { - error->level = VIR_ERR_ERROR; - error->code = VIR_ERR_DBUS_SERVICE; - error->domain = VIR_FROM_DBUS; - error->message = g_strdup(localerror.message); - error->str1 = g_strdup(localerror.name); - ret = 0; - } else { - virReportError(VIR_ERR_DBUS_SERVICE, _("%s: %s"), member, - localerror.message ? : _("unknown error")); - } - goto cleanup; - } - - PROBE(DBUS_METHOD_REPLY, - "'%s.%s' on '%s' at '%s'", - iface, member, path, dest); - - ret = 0; - - cleanup: - if (ret < 0 && error) - virResetError(error); - dbus_error_free(&localerror); - if (reply) { - if (ret == 0 && replyout) - *replyout = reply; - else - virDBusMessageUnref(reply); - } - return ret; -} - - -/** - * virDBusCallMethod: - * @conn: a DBus connection - * @replyout: pointer to receive reply message, or NULL - * @destination: bus identifier of the target service - * @path: object path of the target service - * @iface: the interface of the object - * @member: the name of the method in the interface - * @types: type signature for following method arguments - * @...: method arguments - * - * This invokes a method on a remote service on the - * DBus bus @conn. The @destination, @path, @iface - * and @member parameters identify the object method to - * be invoked. The optional @replyout parameter will be - * filled with any reply to the method call. The - * virDBusMethodReply method can be used to decode the - * return values. - * - * The @types parameter is a DBus signature describing - * the method call parameters which will be provided - * as variadic args. See virDBusCreateMethodV for a - * description of this parameter. - * - * - * If @error is NULL then a libvirt error will be raised - * when a DBus error is received and the return value will - * be -1. If @error is non-NULL then any DBus error will - * be saved into that object and the return value will - * be 0. If an error occurs while encoding method args - * the return value will always be -1 regardless of whether - * @error is set. - * - * Returns 0 on success, or -1 upon error - */ -int virDBusCallMethod(DBusConnection *conn, - DBusMessage **replyout, - virErrorPtr error, - const char *destination, - const char *path, - const char *iface, - const char *member, - const char *types, ...) -{ - DBusMessage *call = NULL; - int ret = -1; - va_list args; - - va_start(args, types); - ret = virDBusCreateMethodV(&call, destination, path, - iface, member, types, args); - va_end(args); - if (ret < 0) - goto cleanup; - - ret = virDBusCall(conn, call, replyout, error); - - cleanup: - virDBusMessageUnref(call); - return ret; -} - - -static int virDBusIsServiceInList(const char *listMethod, const char *name) -{ - DBusConnection *conn; - DBusMessage *reply = NULL; - DBusMessageIter iter, sub; - int ret = -1; - - if (!virDBusHasSystemBus()) - return -2; - - if (!(conn = virDBusGetSystemBus())) - return -1; - - if (virDBusCallMethod(conn, - &reply, - NULL, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - listMethod, - NULL) < 0) - return ret; - - if (!dbus_message_iter_init(reply, &iter) || - dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Reply message incorrect")); - goto cleanup; - } - - ret = -2; - dbus_message_iter_recurse(&iter, &sub); - while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) { - const char *service = NULL; - - dbus_message_iter_get_basic(&sub, &service); - dbus_message_iter_next(&sub); - - if (STREQ(service, name)) { - ret = 0; - break; - } - } - - cleanup: - virDBusMessageUnref(reply); - return ret; -} - -/** - * virDBusIsServiceEnabled: - * @name: service name - * - * Returns 0 if service is available, -1 on fatal error, or -2 if service is not available - */ -int virDBusIsServiceEnabled(const char *name) -{ - int ret = virDBusIsServiceInList("ListActivatableNames", name); - - VIR_DEBUG("Service %s is %s", name, ret ? "unavailable" : "available"); - - return ret; -} - -/** - * virDBusIsServiceRegistered - * @name: service name - * - * Returns 0 if service is registered, -1 on fatal error, or -2 if service is not registered - */ -int virDBusIsServiceRegistered(const char *name) -{ - int ret = virDBusIsServiceInList("ListNames", name); - - VIR_DEBUG("Service %s is %s", name, ret ? "not registered" : "registered"); - - return ret; -} - -void virDBusMessageUnref(DBusMessage *msg) -{ - if (msg) - dbus_message_unref(msg); -} - -#else /* ! WITH_DBUS */ -void virDBusSetSharedBus(bool shared G_GNUC_UNUSED) -{ - /* nothing */ -} - -DBusConnection *virDBusGetSystemBus(void) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return NULL; -} - - -bool -virDBusHasSystemBus(void) -{ - VIR_DEBUG("DBus support not compiled into this binary"); - return false; -} - -void virDBusCloseSystemBus(void) -{ - /* nothing */ -} - -DBusConnection *virDBusGetSessionBus(void) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return NULL; -} - -int virDBusCreateMethod(DBusMessage **call G_GNUC_UNUSED, - const char *destination G_GNUC_UNUSED, - const char *path G_GNUC_UNUSED, - const char *iface G_GNUC_UNUSED, - const char *member G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, ...) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - -int virDBusCreateMethodV(DBusMessage **call G_GNUC_UNUSED, - const char *destination G_GNUC_UNUSED, - const char *path G_GNUC_UNUSED, - const char *iface G_GNUC_UNUSED, - const char *member G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, - va_list args G_GNUC_UNUSED) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - -int virDBusCreateReplyV(DBusMessage **reply G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, - va_list args G_GNUC_UNUSED) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - -int virDBusCreateReply(DBusMessage **reply G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, ...) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - -int virDBusCallMethod(DBusConnection *conn G_GNUC_UNUSED, - DBusMessage **reply G_GNUC_UNUSED, - virErrorPtr error G_GNUC_UNUSED, - const char *destination G_GNUC_UNUSED, - const char *path G_GNUC_UNUSED, - const char *iface G_GNUC_UNUSED, - const char *member G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, ...) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - - -int virDBusMessageEncode(DBusMessage* msg G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, - ...) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - -int virDBusMessageDecode(DBusMessage* msg G_GNUC_UNUSED, - const char *types G_GNUC_UNUSED, - ...) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("DBus support not compiled into this binary")); - return -1; -} - -int virDBusIsServiceEnabled(const char *name G_GNUC_UNUSED) -{ - VIR_DEBUG("DBus support not compiled into this binary"); - return -2; -} - -int virDBusIsServiceRegistered(const char *name G_GNUC_UNUSED) -{ - VIR_DEBUG("DBus support not compiled into this binary"); - return -2; -} - -void virDBusMessageUnref(DBusMessage *msg G_GNUC_UNUSED) -{ - /* nothing */ -} -#endif /* ! WITH_DBUS */ - -bool virDBusErrorIsUnknownMethod(virErrorPtr err) -{ - return err->domain == VIR_FROM_DBUS && - err->code == VIR_ERR_DBUS_SERVICE && - err->level == VIR_ERR_ERROR && - STREQ_NULLABLE("org.freedesktop.DBus.Error.UnknownMethod", - err->str1); -} diff --git a/src/util/virdbus.h b/src/util/virdbus.h deleted file mode 100644 index 083c074d59..0000000000 --- a/src/util/virdbus.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * virdbus.h: helper for using DBus - * - * Copyright (C) 2012-2013 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, see - * . - * - */ - -#pragma once - -#ifdef WITH_DBUS -# undef interface /* Work around namespace pollution in mingw's rpc.h */ -# include -#else -# define DBusConnection void -# define DBusMessage void -#endif -#include "internal.h" - -#include - -void virDBusSetSharedBus(bool shared); - -DBusConnection *virDBusGetSystemBus(void); -bool virDBusHasSystemBus(void); -void virDBusCloseSystemBus(void); -DBusConnection *virDBusGetSessionBus(void); - -int virDBusCreateMethod(DBusMessage **call, - const char *destination, - const char *path, - const char *iface, - const char *member, - const char *types, ...); -int virDBusCreateMethodV(DBusMessage **call, - const char *destination, - const char *path, - const char *iface, - const char *member, - const char *types, - va_list args); -int virDBusCreateReply(DBusMessage **reply, - const char *types, ...); -int virDBusCreateReplyV(DBusMessage **reply, - const char *types, - va_list args); - -int virDBusCallMethod(DBusConnection *conn, - DBusMessage **reply, - virErrorPtr error, - const char *destination, - const char *path, - const char *iface, - const char *member, - const char *types, ...); -int virDBusMessageDecode(DBusMessage *msg, - const char *types, ...); -void virDBusMessageUnref(DBusMessage *msg); - -int virDBusIsServiceEnabled(const char *name); -int virDBusIsServiceRegistered(const char *name); - -bool virDBusErrorIsUnknownMethod(virErrorPtr err); diff --git a/src/util/virdbuspriv.h b/src/util/virdbuspriv.h deleted file mode 100644 index 5b4fe217f9..0000000000 --- a/src/util/virdbuspriv.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * virdbuspriv.h: internal APIs for testing DBus code - * - * Copyright (C) 2012-2014 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, see - * . - * - */ - -#ifndef LIBVIRT_VIRDBUSPRIV_H_ALLOW -# error "virdbuspriv.h may only be included by virdbus.c or test suites" -#endif /* LIBVIRT_VIRDBUSPRIV_H_ALLOW */ - -#pragma once - -#include "virdbus.h" - -#if defined(WITH_DBUS) && !WITH_DBUSBASICVALUE -/* Copied (and simplified) from dbus 1.6.12, for use with older dbus headers */ -typedef union -{ - dbus_int16_t i16; /**< as int16 */ - dbus_uint16_t u16; /**< as int16 */ - dbus_int32_t i32; /**< as int32 */ - dbus_uint32_t u32; /**< as int32 */ - dbus_bool_t bool_val; /**< as boolean */ - dbus_int64_t i64; /**< as int64 */ - dbus_uint64_t u64; /**< as int64 */ - double dbl; /**< as double */ - unsigned char byt; /**< as byte */ -} DBusBasicValue; -#endif - -int virDBusMessageEncodeArgs(DBusMessage* msg, - const char *types, - va_list args); - -int virDBusMessageDecodeArgs(DBusMessage* msg, - const char *types, - va_list args); - -int virDBusMessageEncode(DBusMessage* msg, - const char *types, - ...); diff --git a/tests/meson.build b/tests/meson.build index 356286839a..f4fbb25e66 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -86,12 +86,6 @@ if conf.has('WITH_BHYVE') ] endif -if conf.has('WITH_DBUS') - mock_libs += [ - { 'name': 'virdbusmock', 'deps': [ dbus_dep ] }, - ] -endif - if conf.has('WITH_LIBXL') mock_libs += [ { 'name': 'xlmock', 'sources': [ 'libxlmock.c' ], 'deps': [ libxl_dep ] }, @@ -360,13 +354,6 @@ if conf.has('WITH_BHYVE') ] endif -if conf.has('WITH_DBUS') - tests += [ - { 'name': 'virdbustest', 'deps': [ dbus_dep ] }, - ] - -endif - if conf.has('WITH_ESX') tests += [ { 'name': 'esxutilstest', 'include': [ esx_inc_dir ] }, diff --git a/tests/virdbusmock.c b/tests/virdbusmock.c deleted file mode 100644 index 0673f7292a..0000000000 --- a/tests/virdbusmock.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * virdbusmock.c: mocking of dbus message send/reply - * - * Copyright (C) 2013-2014 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, see - * . - */ - -#include - -#if defined(WITH_DBUS) && !defined(WIN32) -# include "virmock.h" -# include - -VIR_MOCK_STUB_VOID_ARGS(dbus_connection_set_change_sigpipe, - dbus_bool_t, will_modify_sigpipe) - - -VIR_MOCK_STUB_RET_ARGS(dbus_bus_get, - DBusConnection *, (DBusConnection *)0x1, - DBusBusType, type, - DBusError *, error) - -VIR_MOCK_STUB_VOID_ARGS(dbus_connection_set_exit_on_disconnect, - DBusConnection *, connection, - dbus_bool_t, exit_on_disconnect) - -VIR_MOCK_STUB_RET_ARGS(dbus_connection_set_watch_functions, - dbus_bool_t, 1, - DBusConnection *, connection, - DBusAddWatchFunction, add_function, - DBusRemoveWatchFunction, remove_function, - DBusWatchToggledFunction, toggled_function, - void *, data, - DBusFreeFunction, free_data_function) - -VIR_MOCK_STUB_RET_ARGS(dbus_message_set_reply_serial, - dbus_bool_t, 1, - DBusMessage *, message, - dbus_uint32_t, serial) - - -VIR_MOCK_LINK_RET_ARGS(dbus_connection_send_with_reply_and_block, - DBusMessage *, - DBusConnection *, connection, - DBusMessage *, message, - int, timeout_milliseconds, - DBusError *, error) - -#endif /* WITH_DBUS && !WIN32 */ diff --git a/tests/virdbustest.c b/tests/virdbustest.c deleted file mode 100644 index f9c2fb9587..0000000000 --- a/tests/virdbustest.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (C) 2013, 2014 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, see - * . - */ - -#include - -#define LIBVIRT_VIRDBUSPRIV_H_ALLOW -#include "virdbuspriv.h" -#include "virlog.h" -#include "testutils.h" - -VIR_LOG_INIT("tests.dbustest"); - -#define VERIFY(typname, valorig, valnew, fmt) \ - do { \ - VIR_DEBUG("Compare " typname " '" fmt "' to '" \ - fmt "'", valorig, valnew); \ - if (valorig != valnew) { \ - fprintf(stderr, "Failed to round-trip " typname " '" \ - fmt "' to '" fmt "'\n", valorig, valnew); \ - goto cleanup; \ - } \ - } while (0) - -#define VERIFY_STR(typname, valorig, valnew, fmt) \ - do { \ - VIR_DEBUG("Compare " typname " '" fmt "' to '" \ - fmt "'", valorig, valnew); \ - if (STRNEQ(valorig, valnew)) { \ - fprintf(stderr, "Failed to round-trip " typname " '" \ - fmt "' to '" fmt "'\n", valorig, valnew); \ - goto cleanup; \ - } \ - } while (0) - -static int testMessageSimple(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - unsigned char in_byte = 200, out_byte = 0; - bool in_bool = true, out_bool = false; - short in_int16 = 0xfefe, out_int16 = 0; - unsigned short in_uint16 = 32000, out_uint16 = 0; - int in_int32 = 100000000, out_int32 = 0; - unsigned int in_uint32 = 200000000, out_uint32 = 0; - long long in_int64 = 1000000000000LL, out_int64 = 0; - unsigned long long in_uint64 = 2000000000000LL, out_uint64 = 0; - double in_double = 3.14159265359, out_double = 0; - const char *in_string = "Hello World"; - char *out_string = NULL; - const char *in_objectpath = "/org/libvirt/test"; - char *out_objectpath = NULL; - const char *in_signature = "ybnqiuxtdsog"; - char *out_signature = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "ybnqiuxtdsog", - in_byte, in_bool, - in_int16, in_uint16, - in_int32, in_uint32, - in_int64, in_uint64, - in_double, in_string, - in_objectpath, in_signature) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "ybnqiuxtdsog", - &out_byte, &out_bool, - &out_int16, &out_uint16, - &out_int32, &out_uint32, - &out_int64, &out_uint64, - &out_double, &out_string, - &out_objectpath, &out_signature) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - VERIFY("byte", in_byte, out_byte, "%d"); - VERIFY("bool", in_bool, out_bool, "%d"); - VERIFY("int16", in_int16, out_int16, "%d"); - VERIFY("uint16", in_int16, out_int16, "%d"); - VERIFY("int32", in_int32, out_int32, "%d"); - VERIFY("uint32", in_int32, out_int32, "%d"); - VERIFY("int64", in_int64, out_int64, "%lld"); - VERIFY("uint64", in_int64, out_int64, "%lld"); - VERIFY("double", in_double, out_double, "%lf"); - VERIFY_STR("string", in_string, out_string, "%s"); - VERIFY_STR("objectpath", in_objectpath, out_objectpath, "%s"); - VERIFY_STR("signature", in_signature, out_signature, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_string); - VIR_FREE(out_signature); - VIR_FREE(out_objectpath); - virDBusMessageUnref(msg); - return ret; -} - - -static int testMessageVariant(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_str1 = "Hello"; - int in_int32 = 100000000, out_int32 = 0; - const char *in_str2 = "World"; - char *out_str1 = NULL, *out_str2 = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "svs", - in_str1, - "i", in_int32, - in_str2) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "svs", - &out_str1, - "i", &out_int32, - &out_str2) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - - VERIFY_STR("str1", in_str1, out_str1, "%s"); - VERIFY("int32", in_int32, out_int32, "%d"); - VERIFY_STR("str2", in_str2, out_str2, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_str1); - VIR_FREE(out_str2); - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageArray(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_str1 = "Hello"; - int in_int32a = 1000000000, out_int32a = 0; - int in_int32b = 2000000000, out_int32b = 0; - int in_int32c = -2000000000, out_int32c = 0; - bool in_bool[] = { true, false, true }, out_bool[] = { false, true, false}; - const char *in_str2 = "World"; - char *out_str1 = NULL, *out_str2 = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "saiabs", - in_str1, - 3, in_int32a, in_int32b, in_int32c, - 3, in_bool[0], in_bool[1], in_bool[2], - in_str2) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "saiabs", - &out_str1, - 3, &out_int32a, &out_int32b, &out_int32c, - 3, &out_bool[0], &out_bool[1], &out_bool[2], - &out_str2) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - - VERIFY_STR("str1", in_str1, out_str1, "%s"); - VERIFY("int32a", in_int32a, out_int32a, "%d"); - VERIFY("int32b", in_int32b, out_int32b, "%d"); - VERIFY("int32c", in_int32c, out_int32c, "%d"); - VERIFY("bool[0]", in_bool[0], out_bool[0], "%d"); - VERIFY("bool[1]", in_bool[1], out_bool[1], "%d"); - VERIFY("bool[2]", in_bool[2], out_bool[2], "%d"); - VERIFY_STR("str2", in_str2, out_str2, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_str1); - VIR_FREE(out_str2); - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageEmptyArrayRef(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_strv1[] = {}; - size_t out_nstrv1; - char **out_strv1 = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "a&s", - 0, in_strv1) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "a&s", - &out_nstrv1, &out_strv1) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - - if (out_nstrv1 != 0) { - fprintf(stderr, "Expected 0 string, but got %zu\n", - out_nstrv1); - goto cleanup; - } - - ret = 0; - - cleanup: - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageSingleArrayRef(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_strv1[] = { - "Fishfood", - }; - char **out_strv1 = NULL; - size_t out_nstrv1 = 0; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "a&s", - 1, in_strv1) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "a&s", - &out_nstrv1, &out_strv1) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - - if (out_nstrv1 != 1) { - fprintf(stderr, "Expected 1 string, but got %zu\n", - out_nstrv1); - goto cleanup; - } - VERIFY_STR("strv1[0]", in_strv1[0], out_strv1[0], "%s"); - - ret = 0; - - cleanup: - if (out_strv1) - VIR_FREE(out_strv1[0]); - VIR_FREE(out_strv1); - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageArrayRef(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_str1 = "Hello"; - int in_int32[] = { - 100000000, 2000000000, -2000000000 - }; - bool in_bool[] = { true, false, true }; - const char *in_strv1[] = { - "Fishfood", - }; - const char *in_strv2[] = { - "Hello", "World", - }; - int *out_int32 = NULL; - size_t out_nint32 = 0; - bool *out_bool = NULL; - size_t out_nbool = 0; - char **out_strv1 = NULL; - char **out_strv2 = NULL; - size_t out_nstrv1 = 0; - size_t out_nstrv2 = 0; - const char *in_str2 = "World"; - char *out_str1 = NULL, *out_str2 = NULL; - size_t i; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "sa&sa&ia&ba&ss", - in_str1, - 1, in_strv1, - 3, in_int32, - 3, in_bool, - 2, in_strv2, - in_str2) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "sa&sa&ia&ba&ss", - &out_str1, - &out_nstrv1, &out_strv1, - &out_nint32, &out_int32, - &out_nbool, &out_bool, - &out_nstrv2, &out_strv2, - &out_str2) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - - VERIFY_STR("str1", in_str1, out_str1, "%s"); - if (out_nstrv1 != 1) { - fprintf(stderr, "Expected 1 string, but got %zu\n", - out_nstrv1); - goto cleanup; - } - VERIFY_STR("strv1[0]", in_strv1[0], out_strv1[0], "%s"); - - if (out_nint32 != 3) { - fprintf(stderr, "Expected 3 integers, but got %zu\n", - out_nint32); - goto cleanup; - } - VERIFY("int32a", in_int32[0], out_int32[0], "%d"); - VERIFY("int32b", in_int32[1], out_int32[1], "%d"); - VERIFY("int32c", in_int32[2], out_int32[2], "%d"); - - if (out_nbool != 3) { - fprintf(stderr, "Expected 3 bools, but got %zu\n", - out_nbool); - goto cleanup; - } - VERIFY("bool[0]", in_bool[0], out_bool[0], "%d"); - VERIFY("bool[1]", in_bool[1], out_bool[1], "%d"); - VERIFY("bool[2]", in_bool[2], out_bool[2], "%d"); - - if (out_nstrv2 != 2) { - fprintf(stderr, "Expected 2 strings, but got %zu\n", - out_nstrv2); - goto cleanup; - } - VERIFY_STR("strv2[0]", in_strv2[0], out_strv2[0], "%s"); - VERIFY_STR("strv2[1]", in_strv2[1], out_strv2[1], "%s"); - - VERIFY_STR("str2", in_str2, out_str2, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_int32); - VIR_FREE(out_bool); - VIR_FREE(out_str1); - VIR_FREE(out_str2); - for (i = 0; i < out_nstrv1; i++) - VIR_FREE(out_strv1[i]); - VIR_FREE(out_strv1); - for (i = 0; i < out_nstrv2; i++) - VIR_FREE(out_strv2[i]); - VIR_FREE(out_strv2); - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageStruct(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - unsigned char in_byte = 200, out_byte = 0; - bool in_bool = true, out_bool = false; - short in_int16 = 12000, out_int16 = 0; - unsigned short in_uint16 = 32000, out_uint16 = 0; - int in_int32 = 100000000, out_int32 = 0; - unsigned int in_uint32 = 200000000, out_uint32 = 0; - long long in_int64 = -1000000000000LL, out_int64 = 0; - unsigned long long in_uint64 = 2000000000000LL, out_uint64 = 0; - double in_double = 3.14159265359, out_double = 0; - const char *in_string = "Hello World"; - char *out_string = NULL; - const char *in_objectpath = "/org/libvirt/test"; - char *out_objectpath = NULL; - const char *in_signature = "ybnqiuxtdsog"; - char *out_signature = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "ybn(qiuxtds)og", - in_byte, in_bool, - in_int16, in_uint16, - in_int32, in_uint32, - in_int64, in_uint64, - in_double, in_string, - in_objectpath, in_signature) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "ybn(qiuxtds)og", - &out_byte, &out_bool, - &out_int16, &out_uint16, - &out_int32, &out_uint32, - &out_int64, &out_uint64, - &out_double, &out_string, - &out_objectpath, &out_signature) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - VERIFY("byte", in_byte, out_byte, "%d"); - VERIFY("bool", in_bool, out_bool, "%d"); - VERIFY("int16", in_int16, out_int16, "%d"); - VERIFY("uint16", in_int16, out_int16, "%d"); - VERIFY("int32", in_int32, out_int32, "%d"); - VERIFY("uint32", in_int32, out_int32, "%d"); - VERIFY("int64", in_int64, out_int64, "%lld"); - VERIFY("uint64", in_int64, out_int64, "%lld"); - VERIFY("double", in_double, out_double, "%lf"); - VERIFY_STR("string", in_string, out_string, "%s"); - VERIFY_STR("objectpath", in_objectpath, out_objectpath, "%s"); - VERIFY_STR("signature", in_signature, out_signature, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_string); - VIR_FREE(out_signature); - VIR_FREE(out_objectpath); - virDBusMessageUnref(msg); - return ret; -} - - -static int testMessageDict(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_str1 = "Hello"; - int in_int32a = 100000000, out_int32a = 0; - const char *in_key1 = "turnover"; - int in_int32b = 200000000, out_int32b = 0; - const char *in_key2 = "revenue"; - int in_int32c = 300000000, out_int32c = 0; - const char *in_key3 = "debt"; - const char *in_str2 = "World"; - char *out_str1 = NULL, *out_str2 = NULL; - char *out_key1 = NULL, *out_key2 = NULL, *out_key3 = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "(sa{si}s)", - in_str1, - 3, - in_key1, in_int32a, - in_key2, in_int32b, - in_key3, in_int32c, - in_str2) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "(sa{si}s)", - &out_str1, - 3, - &out_key1, &out_int32a, - &out_key2, &out_int32b, - &out_key3, &out_int32c, - &out_str2) < 0) { - VIR_DEBUG("Failed to decode arguments"); - goto cleanup; - } - - - VERIFY_STR("str1", in_str1, out_str1, "%s"); - VERIFY("int32a", in_int32a, out_int32a, "%d"); - VERIFY("int32b", in_int32b, out_int32b, "%d"); - VERIFY("int32c", in_int32c, out_int32c, "%d"); - VERIFY_STR("key1", in_key1, out_key1, "%s"); - VERIFY_STR("key1", in_key2, out_key2, "%s"); - VERIFY_STR("key1", in_key3, out_key3, "%s"); - VERIFY_STR("str2", in_str2, out_str2, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_str1); - VIR_FREE(out_str2); - VIR_FREE(out_key1); - VIR_FREE(out_key2); - VIR_FREE(out_key3); - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageDictRef(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_str1 = "Hello"; - const char *in_strv1[] = { - "Fruit1", "Apple", - "Fruit2", "Orange", - "Fruit3", "Kiwi", - }; - const char *in_str2 = "World"; - char *out_str1 = NULL; - size_t out_nint32 = 0; - char **out_strv1 = NULL; - char *out_str2 = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "(sa&{ss}s)", - in_str1, - 3, in_strv1, - in_str2) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "(sa&{ss}s)", - &out_str1, - &out_nint32, - &out_strv1, - &out_str2) < 0) { - VIR_DEBUG("Failed to decode arguments: '%s'", virGetLastErrorMessage()); - goto cleanup; - } - - - VERIFY_STR("str1", in_str1, out_str1, "%s"); - VERIFY_STR("strv1[0]", in_strv1[0], out_strv1[0], "%s"); - VERIFY_STR("strv1[1]", in_strv1[1], out_strv1[1], "%s"); - VERIFY_STR("strv1[2]", in_strv1[2], out_strv1[2], "%s"); - VERIFY_STR("strv1[3]", in_strv1[3], out_strv1[3], "%s"); - VERIFY_STR("strv1[4]", in_strv1[4], out_strv1[4], "%s"); - VERIFY_STR("strv1[5]", in_strv1[5], out_strv1[5], "%s"); - VERIFY_STR("str2", in_str2, out_str2, "%s"); - - ret = 0; - - cleanup: - VIR_FREE(out_str1); - VIR_FREE(out_str2); - if (out_strv1) { - VIR_FREE(out_strv1[0]); - VIR_FREE(out_strv1[1]); - VIR_FREE(out_strv1[2]); - VIR_FREE(out_strv1[3]); - VIR_FREE(out_strv1[4]); - VIR_FREE(out_strv1[5]); - } - VIR_FREE(out_strv1); - virDBusMessageUnref(msg); - return ret; -} - -static int testMessageEmptyDictRef(const void *args G_GNUC_UNUSED) -{ - DBusMessage *msg = NULL; - int ret = -1; - const char *in_strv1[] = {}; - size_t out_nint32 = 0; - char **out_strv1 = NULL; - - if (!(msg = dbus_message_new_method_call("org.libvirt.test", - "/org/libvirt/test", - "org.libvirt.test.astrochicken", - "cluck"))) { - VIR_DEBUG("Failed to allocate method call"); - goto cleanup; - } - - if (virDBusMessageEncode(msg, - "a&{ss}", - 0, in_strv1) < 0) { - VIR_DEBUG("Failed to encode arguments"); - goto cleanup; - } - - if (virDBusMessageDecode(msg, - "a&{ss}", - &out_nint32, - &out_strv1) < 0) { - VIR_DEBUG("Failed to decode arguments: '%s'", virGetLastErrorMessage()); - goto cleanup; - } - - if (out_nint32 != 0) { - fprintf(stderr, "Unexpected dict entries\n"); - goto cleanup; - } - - ret = 0; - - cleanup: - virDBusMessageUnref(msg); - return ret; -} - -static int -mymain(void) -{ - int ret = 0; - - if (virTestRun("Test message simple ", testMessageSimple, NULL) < 0) - ret = -1; - if (virTestRun("Test message variant ", testMessageVariant, NULL) < 0) - ret = -1; - if (virTestRun("Test message array ", testMessageArray, NULL) < 0) - ret = -1; - if (virTestRun("Test message array empty ref ", testMessageEmptyArrayRef, NULL) < 0) - ret = -1; - if (virTestRun("Test message array single ref ", testMessageSingleArrayRef, NULL) < 0) - ret = -1; - if (virTestRun("Test message array ref ", testMessageArrayRef, NULL) < 0) - ret = -1; - if (virTestRun("Test message struct ", testMessageStruct, NULL) < 0) - ret = -1; - if (virTestRun("Test message dict ", testMessageDict, NULL) < 0) - ret = -1; - if (virTestRun("Test message dict empty ref ", testMessageEmptyDictRef, NULL) < 0) - ret = -1; - if (virTestRun("Test message dict ref ", testMessageDictRef, NULL) < 0) - ret = -1; - return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -} - -VIR_TEST_MAIN(mymain)