2012-04-19 14:34:35 +00:00
|
|
|
/*
|
|
|
|
* virdbus.c: helper for using DBus
|
|
|
|
*
|
2014-03-18 08:14:35 +00:00
|
|
|
* Copyright (C) 2012-2014 Red Hat, Inc.
|
2012-04-19 14:34:35 +00:00
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2012-04-19 14:34:35 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2018-12-13 14:53:50 +00:00
|
|
|
#define LIBVIRT_VIRDBUSPRIV_H_ALLOW
|
2013-07-12 10:13:04 +00:00
|
|
|
#include "virdbuspriv.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2013-07-12 10:13:04 +00:00
|
|
|
#include "virstring.h"
|
2014-11-11 18:39:19 +00:00
|
|
|
#include "virprobe.h"
|
2012-04-19 14:34:35 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_DBUS
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.dbus");
|
|
|
|
|
2012-09-20 14:05:39 +00:00
|
|
|
#ifdef WITH_DBUS
|
2012-04-19 14:34:35 +00:00
|
|
|
|
2013-10-11 14:28:39 +00:00
|
|
|
static bool sharedBus = true;
|
2014-10-28 18:38:04 +00:00
|
|
|
static DBusConnection *systembus;
|
|
|
|
static DBusConnection *sessionbus;
|
2012-10-31 19:03:49 +00:00
|
|
|
static virOnceControl systemonce = VIR_ONCE_CONTROL_INITIALIZER;
|
|
|
|
static virOnceControl sessiononce = VIR_ONCE_CONTROL_INITIALIZER;
|
|
|
|
static DBusError systemdbuserr;
|
|
|
|
static DBusError sessiondbuserr;
|
2012-04-19 14:34:35 +00:00
|
|
|
|
|
|
|
static dbus_bool_t virDBusAddWatch(DBusWatch *watch, void *data);
|
|
|
|
static void virDBusRemoveWatch(DBusWatch *watch, void *data);
|
|
|
|
static void virDBusToggleWatch(DBusWatch *watch, void *data);
|
|
|
|
|
2013-10-11 14:28:39 +00:00
|
|
|
void virDBusSetSharedBus(bool shared)
|
|
|
|
{
|
|
|
|
sharedBus = shared;
|
|
|
|
}
|
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
static DBusConnection *virDBusBusInit(DBusBusType type, DBusError *dbuserr)
|
2012-04-19 14:34:35 +00:00
|
|
|
{
|
2012-10-31 19:03:49 +00:00
|
|
|
DBusConnection *bus;
|
|
|
|
|
2012-04-19 14:34:35 +00:00
|
|
|
/* Allocate and initialize a new HAL context */
|
|
|
|
dbus_connection_set_change_sigpipe(FALSE);
|
|
|
|
dbus_threads_init_default();
|
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
dbus_error_init(dbuserr);
|
2013-10-11 14:28:39 +00:00
|
|
|
bus = sharedBus ?
|
|
|
|
dbus_bus_get(type, dbuserr) :
|
|
|
|
dbus_bus_get_private(type, dbuserr);
|
|
|
|
if (!bus)
|
2012-10-31 19:03:49 +00:00
|
|
|
return NULL;
|
2012-04-19 14:34:35 +00:00
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
2012-04-19 14:34:35 +00:00
|
|
|
|
|
|
|
/* Register dbus watch callbacks */
|
2012-10-31 19:03:49 +00:00
|
|
|
if (!dbus_connection_set_watch_functions(bus,
|
2012-04-19 14:34:35 +00:00
|
|
|
virDBusAddWatch,
|
|
|
|
virDBusRemoveWatch,
|
|
|
|
virDBusToggleWatch,
|
2012-10-31 19:03:49 +00:00
|
|
|
bus, NULL)) {
|
|
|
|
return NULL;
|
2012-04-19 14:34:35 +00:00
|
|
|
}
|
2012-10-31 19:03:49 +00:00
|
|
|
return bus;
|
2012-04-19 14:34:35 +00:00
|
|
|
}
|
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
static void virDBusSystemBusInit(void)
|
|
|
|
{
|
|
|
|
systembus = virDBusBusInit(DBUS_BUS_SYSTEM, &systemdbuserr);
|
|
|
|
}
|
2012-04-19 14:34:35 +00:00
|
|
|
|
2013-08-19 09:24:04 +00:00
|
|
|
static DBusConnection *
|
|
|
|
virDBusGetSystemBusInternal(void)
|
2012-04-19 14:34:35 +00:00
|
|
|
{
|
2012-10-31 19:03:49 +00:00
|
|
|
if (virOnce(&systemonce, virDBusSystemBusInit) < 0) {
|
2012-07-18 10:26:24 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to run one time DBus initializer"));
|
2012-04-19 14:34:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-08-19 09:24:04 +00:00
|
|
|
return systembus;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DBusConnection *
|
|
|
|
virDBusGetSystemBus(void)
|
|
|
|
{
|
|
|
|
DBusConnection *bus;
|
|
|
|
|
|
|
|
if (!(bus = virDBusGetSystemBusInternal())) {
|
2012-07-18 10:26:24 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to get DBus system bus connection: %s"),
|
2012-10-31 19:03:49 +00:00
|
|
|
systemdbuserr.message ? systemdbuserr.message : "watch setup failed");
|
2012-04-19 14:34:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-08-19 09:24:04 +00:00
|
|
|
return bus;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-11 16:50:43 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-08-19 09:24:04 +00:00
|
|
|
bool
|
|
|
|
virDBusHasSystemBus(void)
|
|
|
|
{
|
|
|
|
if (virDBusGetSystemBusInternal())
|
|
|
|
return true;
|
|
|
|
|
2013-10-11 16:50:43 +00:00
|
|
|
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;
|
2012-04-19 14:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-11 14:57:05 +00:00
|
|
|
void virDBusCloseSystemBus(void)
|
|
|
|
{
|
|
|
|
if (systembus && !sharedBus) {
|
|
|
|
dbus_connection_close(systembus);
|
2018-09-21 13:02:02 +00:00
|
|
|
dbus_connection_unref(systembus);
|
2013-10-11 14:57:05 +00:00
|
|
|
systembus = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2012-04-19 14:34:35 +00:00
|
|
|
static void virDBusWatchCallback(int fdatch ATTRIBUTE_UNUSED,
|
|
|
|
int fd ATTRIBUTE_UNUSED,
|
|
|
|
int events, void *opaque)
|
|
|
|
{
|
|
|
|
DBusWatch *watch = opaque;
|
2012-10-31 19:03:49 +00:00
|
|
|
struct virDBusWatch *info;
|
2012-04-19 14:34:35 +00:00
|
|
|
int dbus_flags = 0;
|
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
info = dbus_watch_get_data(watch);
|
|
|
|
|
2012-04-19 14:34:35 +00:00
|
|
|
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;
|
|
|
|
|
2018-09-21 13:02:03 +00:00
|
|
|
if (dbus_watch_handle(watch, dbus_flags) == FALSE)
|
|
|
|
VIR_DEBUG("dbus_watch_handle() returned FALSE");
|
2012-04-19 14:34:35 +00:00
|
|
|
|
2018-09-21 13:02:01 +00:00
|
|
|
dbus_connection_ref(info->bus);
|
2012-10-31 19:03:49 +00:00
|
|
|
while (dbus_connection_dispatch(info->bus) == DBUS_DISPATCH_DATA_REMAINS)
|
2012-04-19 14:34:35 +00:00
|
|
|
/* keep dispatching while data remains */;
|
2018-09-21 13:02:01 +00:00
|
|
|
dbus_connection_unref(info->bus);
|
2012-04-19 14:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-18 08:14:35 +00:00
|
|
|
static void virDBusWatchFree(void *data)
|
|
|
|
{
|
2012-04-19 14:34:35 +00:00
|
|
|
struct virDBusWatch *info = data;
|
|
|
|
VIR_FREE(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static dbus_bool_t virDBusAddWatch(DBusWatch *watch,
|
2012-10-31 19:03:49 +00:00
|
|
|
void *data)
|
2012-04-19 14:34:35 +00:00
|
|
|
{
|
|
|
|
int flags = 0;
|
|
|
|
int fd;
|
|
|
|
struct virDBusWatch *info;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(info) < 0)
|
2018-09-21 13:02:04 +00:00
|
|
|
return FALSE;
|
2012-04-19 14:34:35 +00:00
|
|
|
|
|
|
|
if (dbus_watch_get_enabled(watch))
|
|
|
|
flags = virDBusTranslateWatchFlags(dbus_watch_get_flags(watch));
|
|
|
|
|
|
|
|
# if HAVE_DBUS_WATCH_GET_UNIX_FD
|
|
|
|
fd = dbus_watch_get_unix_fd(watch);
|
|
|
|
# else
|
|
|
|
fd = dbus_watch_get_fd(watch);
|
|
|
|
# endif
|
2013-12-18 12:19:46 +00:00
|
|
|
dbus_watch_set_data(watch, info, virDBusWatchFree);
|
2012-10-31 19:03:49 +00:00
|
|
|
info->bus = (DBusConnection *)data;
|
2012-04-19 14:34:35 +00:00
|
|
|
info->watch = virEventAddHandle(fd, flags,
|
|
|
|
virDBusWatchCallback,
|
|
|
|
watch, NULL);
|
|
|
|
if (info->watch < 0) {
|
2013-12-18 12:19:46 +00:00
|
|
|
dbus_watch_set_data(watch, NULL, NULL);
|
2018-09-21 13:02:04 +00:00
|
|
|
return FALSE;
|
2012-04-19 14:34:35 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 13:02:04 +00:00
|
|
|
return TRUE;
|
2012-04-19 14:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void virDBusRemoveWatch(DBusWatch *watch,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
struct virDBusWatch *info;
|
|
|
|
|
|
|
|
info = dbus_watch_get_data(watch);
|
|
|
|
|
|
|
|
(void)virEventRemoveHandle(info->watch);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void virDBusToggleWatch(DBusWatch *watch,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
int flags = 0;
|
|
|
|
struct virDBusWatch *info;
|
|
|
|
|
|
|
|
if (dbus_watch_get_enabled(watch))
|
|
|
|
flags = virDBusTranslateWatchFlags(dbus_watch_get_flags(watch));
|
|
|
|
|
|
|
|
info = dbus_watch_get_data(watch);
|
|
|
|
|
|
|
|
(void)virEventUpdateHandle(info->watch, flags);
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
# 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,
|
|
|
|
};
|
|
|
|
|
2014-03-18 08:14:35 +00:00
|
|
|
static bool virDBusIsBasicType(char c)
|
|
|
|
{
|
2013-07-12 10:13:04 +00:00
|
|
|
return !!memchr(virDBusBasicTypes, c, ARRAY_CARDINALITY(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,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
size_t *skiplen,
|
|
|
|
size_t *siglen)
|
2013-07-12 10:13:04 +00:00
|
|
|
{
|
|
|
|
if (virDBusIsBasicType(*s) || *s == DBUS_TYPE_VARIANT) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
*skiplen = *siglen = 1;
|
2013-07-12 10:13:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*s == DBUS_TYPE_ARRAY) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
size_t skiplencont;
|
|
|
|
size_t siglencont;
|
|
|
|
bool arrayref = false;
|
2013-07-12 10:13:04 +00:00
|
|
|
|
|
|
|
if (arrayDepth >= VIR_DBUS_TYPE_STACK_MAX_DEPTH) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Signature '%s' too deeply nested"),
|
|
|
|
s);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (*(s + 1) == '&') {
|
|
|
|
arrayref = true;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
if (virDBusSignatureLengthInternal(s + 1,
|
|
|
|
true,
|
|
|
|
arrayDepth + 1,
|
|
|
|
structDepth,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
&skiplencont,
|
|
|
|
&siglencont) < 0)
|
2013-07-12 10:13:04 +00:00
|
|
|
return -1;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
*skiplen = skiplencont + 1;
|
|
|
|
*siglen = siglencont + 1;
|
|
|
|
if (arrayref)
|
|
|
|
(*skiplen)++;
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
*skiplen = *siglen = 2;
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
while (*p != DBUS_STRUCT_END_CHAR) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
size_t skiplencont;
|
|
|
|
size_t siglencont;
|
2013-07-12 10:13:04 +00:00
|
|
|
|
|
|
|
if (virDBusSignatureLengthInternal(p,
|
|
|
|
false,
|
|
|
|
arrayDepth,
|
|
|
|
structDepth + 1,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
&skiplencont,
|
|
|
|
&siglencont) < 0)
|
2013-07-12 10:13:04 +00:00
|
|
|
return -1;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
p += skiplencont;
|
|
|
|
*skiplen += skiplencont;
|
|
|
|
*siglen += siglencont;
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
*skiplen = *siglen = 2;
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
while (*p != DBUS_DICT_ENTRY_END_CHAR) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
size_t skiplencont;
|
|
|
|
size_t siglencont;
|
2013-07-12 10:13:04 +00:00
|
|
|
|
|
|
|
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,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
&skiplencont,
|
|
|
|
&siglencont) < 0)
|
2013-07-12 10:13:04 +00:00
|
|
|
return -1;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
p += skiplencont;
|
|
|
|
*skiplen += skiplencont;
|
|
|
|
*siglen += siglencont;
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
static int virDBusSignatureLength(const char *s, size_t *skiplen, size_t *siglen)
|
2013-07-12 10:13:04 +00:00
|
|
|
{
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
return virDBusSignatureLengthInternal(s, true, 0, 0, skiplen, siglen);
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
|
|
|
|
/* 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;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Pushed types='%s' nstruct=%zu narray=%zd",
|
|
|
|
types, nstruct, (ssize_t)narray);
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Popped types='%s' nstruct=%zu narray=%zd",
|
|
|
|
*types, *nstruct, (ssize_t)*narray);
|
2013-07-12 10:13:04 +00:00
|
|
|
VIR_SHRINK_N(*stack, *nstack, 1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void virDBusTypeStackFree(virDBusTypeStack **stack,
|
|
|
|
size_t *nstack)
|
|
|
|
{
|
|
|
|
size_t i;
|
2015-09-01 11:02:30 +00:00
|
|
|
|
|
|
|
if (!*stack)
|
|
|
|
return;
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
/* The iter in the first level of the stack is the
|
|
|
|
* root iter which must not be freed
|
|
|
|
*/
|
2014-11-13 14:28:18 +00:00
|
|
|
for (i = 1; i < *nstack; i++)
|
2013-07-12 10:13:04 +00:00
|
|
|
VIR_FREE((*stack)[i].iter);
|
|
|
|
VIR_FREE(*stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
# 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, \
|
2014-03-13 15:38:18 +00:00
|
|
|
_("Cannot append basic type %s"), #vargtype);\
|
2017-11-03 12:09:47 +00:00
|
|
|
goto cleanup; \
|
|
|
|
} \
|
2014-03-13 15:38:18 +00:00
|
|
|
VIR_DEBUG("Appended basic type '" #dbustype "' varg '" #vargtype\
|
2017-11-03 12:09:47 +00:00
|
|
|
"' sig '%c' val '" fmt "'", sigtype, (vargtype)x); \
|
2013-07-12 10:13:04 +00:00
|
|
|
} while (0)
|
|
|
|
|
2014-03-13 15:38:18 +00:00
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
static int
|
|
|
|
virDBusMessageIterEncode(DBusMessageIter *rootiter,
|
|
|
|
const char *types,
|
|
|
|
va_list args)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
size_t narray;
|
|
|
|
size_t nstruct;
|
2014-03-13 15:38:18 +00:00
|
|
|
bool arrayref = false;
|
|
|
|
void *arrayptr = NULL;
|
2013-07-12 10:13:04 +00:00
|
|
|
virDBusTypeStack *stack = NULL;
|
|
|
|
size_t nstack = 0;
|
|
|
|
size_t siglen;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
size_t skiplen;
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Loop nstack=%zu narray=%zd nstruct=%zu types='%s'",
|
|
|
|
nstack, (ssize_t)narray, nstruct, types);
|
2013-07-12 10:13:04 +00:00
|
|
|
if (narray == 0 ||
|
|
|
|
(narray == (size_t)-1 &&
|
|
|
|
nstruct == 0)) {
|
|
|
|
DBusMessageIter *thisiter = iter;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (*types != '}') {
|
|
|
|
VIR_DEBUG("Reset array ref");
|
|
|
|
arrayref = false;
|
|
|
|
arrayptr = NULL;
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
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:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(unsigned char, int, unsigned char *, *t, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_BOOLEAN:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_bool_t, int, bool *, *t, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_INT16:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_int16_t, int, short *, *t, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_UINT16:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_uint16_t, unsigned int, unsigned short *,
|
|
|
|
*t, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_INT32:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_int32_t, int, int *, *t, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_UINT32:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_uint32_t, unsigned int, unsigned int *,
|
|
|
|
*t, "%u");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_INT64:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_int64_t, long long, long long *, *t, "%lld");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_UINT64:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(dbus_uint64_t, unsigned long long,
|
|
|
|
unsigned long long *, *t, "%llu");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_DOUBLE:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(double, double, double *, *t, "%lf");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_STRING:
|
|
|
|
case DBUS_TYPE_OBJECT_PATH:
|
|
|
|
case DBUS_TYPE_SIGNATURE:
|
dbus: fix arrays of bools
Commit 2aa167ca tried to fix the DBus interaction code to allow
callers to use native types instead of 4-byte bools. But in
fixing the issue, I missed the case of an arrayref; Conrad Meyer
shows the following valid complaint issued by clang:
CC util/libvirt_util_la-virdbus.lo
util/virdbus.c:956:13: error: cast from 'bool *' to 'dbus_bool_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
util/virdbus.c:858:17: note: expanded from macro 'GET_NEXT_VAL'
x = (dbustype *)(*xptrptr + (*narrayptr - 1)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
But fixing that points out that we have NEVER supported arrayrefs
of sub-int types (byte, i16, u16, and now bool). Again, while raw
types promote, arrays do not; so the macros HAVE to deal with both
size possibilities rather than assuming that an arrayref uses the
same sizing as the promoted raw type.
Obviously, our testsuite wasn't covering as much as it should have.
* src/util/virdbus.c (GET_NEXT_VAL): Also fix array cases.
(SET_NEXT_VAL): Fix uses of sub-int arrays.
* tests/virdbustest.c (testMessageArray, testMessageArrayRef):
Test it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-22 00:03:34 +00:00
|
|
|
SET_NEXT_VAL(char *, char *, char **, *t, "%s");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_ARRAY:
|
2014-03-13 15:38:18 +00:00
|
|
|
arrayptr = NULL;
|
|
|
|
if (t[1] == '&') {
|
|
|
|
VIR_DEBUG("Got array ref");
|
|
|
|
t++;
|
|
|
|
types++;
|
|
|
|
nstruct--;
|
|
|
|
arrayref = true;
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Got array non-ref");
|
|
|
|
arrayref = false;
|
|
|
|
}
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen)))
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (arrayref && !virDBusIsAllowedRefType(contsig)) {
|
2014-03-13 15:38:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
_("Got array ref but '%s' is not a single basic type "
|
|
|
|
"or dict with matching key+value type"),
|
2014-03-13 15:38:18 +00:00
|
|
|
contsig);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
if (narray == (size_t)-1) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
types += skiplen;
|
|
|
|
nstruct -= skiplen;
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(newiter) < 0)
|
|
|
|
goto cleanup;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Contsig '%s' skip='%zu' len='%zu'", contsig, skiplen, siglen);
|
2013-07-12 10:13:04 +00:00
|
|
|
if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
|
|
|
|
contsig, newiter))
|
|
|
|
goto cleanup;
|
|
|
|
if (virDBusTypeStackPush(&stack, &nstack,
|
|
|
|
iter, types,
|
2013-09-25 14:15:45 +00:00
|
|
|
nstruct, narray) < 0) {
|
|
|
|
VIR_FREE(newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
2013-09-25 14:15:45 +00:00
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
VIR_FREE(contsig);
|
2019-01-28 13:41:37 +00:00
|
|
|
VIR_STEAL_PTR(iter, newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
types = t + 1;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
nstruct = skiplen;
|
2014-03-13 15:38:18 +00:00
|
|
|
narray = (size_t)va_arg(args, int);
|
|
|
|
if (arrayref)
|
|
|
|
arrayptr = va_arg(args, void *);
|
2013-07-12 10:13:04 +00:00
|
|
|
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,
|
2013-09-25 14:15:45 +00:00
|
|
|
nstruct, narray) < 0) {
|
|
|
|
VIR_FREE(newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
2013-09-25 14:15:45 +00:00
|
|
|
}
|
2019-01-28 13:41:37 +00:00
|
|
|
VIR_STEAL_PTR(iter, newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
types = vsig;
|
|
|
|
nstruct = strlen(types);
|
|
|
|
narray = (size_t)-1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_STRUCT_BEGIN_CHAR:
|
|
|
|
case DBUS_DICT_ENTRY_BEGIN_CHAR:
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen)))
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(newiter) < 0)
|
|
|
|
goto cleanup;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Contsig '%s' skip='%zu' len='%zu'", contsig, skiplen, siglen);
|
2013-07-12 10:13:04 +00:00
|
|
|
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) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
types += skiplen - 1;
|
|
|
|
nstruct -= skiplen - 1;
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virDBusTypeStackPush(&stack, &nstack,
|
|
|
|
iter, types,
|
2013-09-25 14:15:45 +00:00
|
|
|
nstruct, narray) < 0) {
|
|
|
|
VIR_FREE(newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
2013-09-25 14:15:45 +00:00
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
VIR_FREE(contsig);
|
2019-01-28 13:41:37 +00:00
|
|
|
VIR_STEAL_PTR(iter, newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
types = t + 1;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
nstruct = skiplen - 2;
|
2013-07-12 10:13:04 +00:00
|
|
|
narray = (size_t)-1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
_("Unknown type '%x' in signature '%s'"),
|
|
|
|
(int)*t, types);
|
2014-03-13 15:38:18 +00:00
|
|
|
goto cleanup;
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-09-25 14:15:45 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
virDBusTypeStackFree(&stack, &nstack);
|
|
|
|
VIR_FREE(contsig);
|
|
|
|
VIR_FREE(newiter);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
# undef SET_NEXT_VAL
|
|
|
|
|
|
|
|
|
2017-11-03 12:09:47 +00:00
|
|
|
# define GET_NEXT_VAL(dbustype, member, vargtype, fmt) \
|
|
|
|
do { \
|
|
|
|
DBusBasicValue v; \
|
|
|
|
dbustype *x = (dbustype *)&v.member; \
|
|
|
|
vargtype *y; \
|
|
|
|
if (arrayref) { \
|
|
|
|
VIR_DEBUG("Use arrayref"); \
|
|
|
|
vargtype **xptrptr = arrayptr; \
|
|
|
|
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); \
|
2013-07-12 10:13:04 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virDBusMessageIterDecode(DBusMessageIter *rootiter,
|
|
|
|
const char *types,
|
|
|
|
va_list args)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
size_t narray;
|
|
|
|
size_t nstruct;
|
2014-03-13 15:38:18 +00:00
|
|
|
bool arrayref = false;
|
|
|
|
void *arrayptr = NULL;
|
|
|
|
size_t *narrayptr = 0;
|
2013-07-12 10:13:04 +00:00
|
|
|
virDBusTypeStack *stack = NULL;
|
|
|
|
size_t nstack = 0;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
size_t skiplen;
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Loop nstack=%zu narray=%zd nstruct=%zu type='%s'",
|
|
|
|
nstack, (ssize_t)narray, nstruct, types);
|
2013-07-12 10:13:04 +00:00
|
|
|
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);
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (strchr(types, '}') == NULL) {
|
|
|
|
arrayref = false;
|
|
|
|
arrayptr = NULL;
|
|
|
|
VIR_DEBUG("Clear array ref flag");
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
if (thisiter != rootiter)
|
|
|
|
VIR_FREE(thisiter);
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (arrayref) {
|
|
|
|
if (!dbus_message_iter_has_next(iter))
|
|
|
|
narray = 0;
|
|
|
|
else
|
|
|
|
narray = 1;
|
|
|
|
VIR_DEBUG("Pop set narray=%zd", (ssize_t)narray);
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
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) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (!arrayref)
|
|
|
|
narray--;
|
2013-07-12 10:13:04 +00:00
|
|
|
} else {
|
|
|
|
types++;
|
|
|
|
nstruct--;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (*t) {
|
|
|
|
case DBUS_TYPE_BYTE:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(unsigned char, byt, unsigned char, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_BOOLEAN:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_bool_t, bool_val, bool, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_INT16:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_int16_t, i16, short, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_UINT16:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_uint16_t, u16, unsigned short, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_INT32:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_uint32_t, i32, int, "%d");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_UINT32:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_uint32_t, u32, unsigned int, "%u");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_INT64:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_uint64_t, i64, long long, "%lld");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_UINT64:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(dbus_uint64_t, u64, unsigned long long, "%llu");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_DOUBLE:
|
2014-11-18 00:18:58 +00:00
|
|
|
GET_NEXT_VAL(double, dbl, double, "%lf");
|
2013-07-12 10:13:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_STRING:
|
|
|
|
case DBUS_TYPE_OBJECT_PATH:
|
|
|
|
case DBUS_TYPE_SIGNATURE:
|
|
|
|
do {
|
2014-03-13 15:38:18 +00:00
|
|
|
char **x;
|
|
|
|
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 **);
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
char *s;
|
|
|
|
dbus_message_iter_get_basic(iter, &s);
|
|
|
|
if (VIR_STRDUP(*x, s) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
VIR_DEBUG("Read basic type 'char *' varg 'char **'"
|
|
|
|
"' val '%s'", *x);
|
|
|
|
} while (0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_TYPE_ARRAY:
|
2014-03-13 15:38:18 +00:00
|
|
|
arrayptr = NULL;
|
|
|
|
if (t[1] == '&') {
|
|
|
|
VIR_DEBUG("Got array ref");
|
|
|
|
t++;
|
|
|
|
types++;
|
|
|
|
nstruct--;
|
|
|
|
arrayref = true;
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Got array non-ref");
|
|
|
|
arrayref = false;
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
advanceiter = false;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen)))
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (arrayref && !virDBusIsAllowedRefType(contsig)) {
|
2014-03-13 15:38:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
_("Got array ref but '%s' is not a single basic type / dict"),
|
2014-03-13 15:38:18 +00:00
|
|
|
contsig);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
if (narray == (size_t)-1) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
types += skiplen;
|
|
|
|
nstruct -= skiplen;
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(newiter) < 0)
|
|
|
|
goto cleanup;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Array contsig='%s' skip=%'zu' len='%zu' types='%s'",
|
|
|
|
contsig, skiplen, siglen, types);
|
2013-07-12 10:13:04 +00:00
|
|
|
dbus_message_iter_recurse(iter, newiter);
|
|
|
|
if (virDBusTypeStackPush(&stack, &nstack,
|
|
|
|
iter, types,
|
|
|
|
nstruct, narray) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
VIR_FREE(contsig);
|
2019-01-28 13:41:37 +00:00
|
|
|
VIR_STEAL_PTR(iter, newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
types = t + 1;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
nstruct = skiplen;
|
2014-03-13 15:38:18 +00:00
|
|
|
if (arrayref) {
|
|
|
|
narrayptr = va_arg(args, size_t *);
|
|
|
|
arrayptr = va_arg(args, void *);
|
|
|
|
*narrayptr = 0;
|
|
|
|
*(char **)arrayptr = NULL;
|
|
|
|
} else {
|
|
|
|
narray = va_arg(args, int);
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
|
|
|
}
|
2019-01-28 13:41:37 +00:00
|
|
|
VIR_STEAL_PTR(iter, newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
types = vsig;
|
|
|
|
nstruct = strlen(types);
|
|
|
|
narray = (size_t)-1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DBUS_STRUCT_BEGIN_CHAR:
|
|
|
|
case DBUS_DICT_ENTRY_BEGIN_CHAR:
|
|
|
|
advanceiter = false;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (!(contsig = virDBusCopyContainerSignature(t, &skiplen, &siglen)))
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(newiter) < 0)
|
|
|
|
goto cleanup;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("Dict/struct contsig='%s' skip='%zu' len='%zu' types='%s'",
|
|
|
|
contsig, skiplen, siglen, types);
|
2013-07-12 10:13:04 +00:00
|
|
|
dbus_message_iter_recurse(iter, newiter);
|
|
|
|
if (narray == (size_t)-1) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
types += skiplen - 1;
|
|
|
|
nstruct -= skiplen - 1;
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virDBusTypeStackPush(&stack, &nstack,
|
|
|
|
iter, types,
|
|
|
|
nstruct, narray) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
VIR_FREE(contsig);
|
2019-01-28 13:41:37 +00:00
|
|
|
VIR_STEAL_PTR(iter, newiter);
|
2013-07-12 10:13:04 +00:00
|
|
|
types = t + 1;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
nstruct = skiplen - 2;
|
2013-07-12 10:13:04 +00:00
|
|
|
narray = (size_t)-1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2014-03-13 15:38:18 +00:00
|
|
|
_("Unknown type '%c' in signature '%s'"),
|
|
|
|
*t, types);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
VIR_DEBUG("After nstack=%zu narray=%zd nstruct=%zu types='%s'",
|
|
|
|
nstack, (ssize_t)narray, nstruct, types);
|
|
|
|
|
2014-03-13 15:38:18 +00:00
|
|
|
if (arrayref) {
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID) {
|
2014-03-13 15:38:18 +00:00
|
|
|
narray = 0;
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
} 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;
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dbus_message_iter_has_next(iter)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Too many fields in message for signature"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-07-12 10:13:04 +00:00
|
|
|
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;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
memset(&iter, 0, sizeof(iter));
|
|
|
|
|
|
|
|
dbus_message_iter_init_append(msg, &iter);
|
|
|
|
|
|
|
|
ret = virDBusMessageIterEncode(&iter, types, args);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int virDBusMessageDecodeArgs(DBusMessage* msg,
|
|
|
|
const char *types,
|
|
|
|
va_list args)
|
|
|
|
{
|
|
|
|
DBusMessageIter iter;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!dbus_message_iter_init(msg, &iter)) {
|
|
|
|
if (*types != '\0') {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No args present for signature %s"),
|
|
|
|
types);
|
|
|
|
} else {
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virDBusMessageIterDecode(&iter, types, args);
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-07-12 10:13:04 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-12 16:58:01 +00:00
|
|
|
/**
|
|
|
|
* 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,
|
|
|
|
...)
|
2013-07-12 10:13:04 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
|
/**
|
2014-03-13 15:47:46 +00:00
|
|
|
* virDBusCreateMethodV:
|
|
|
|
* @call: pointer to be filled with a method call message
|
2013-07-12 10:13:04 +00:00
|
|
|
* @destination: bus identifier of the target service
|
|
|
|
* @path: object path of the target service
|
2013-07-29 13:54:10 +00:00
|
|
|
* @iface: the interface of the object
|
2013-07-12 10:13:04 +00:00
|
|
|
* @member: the name of the method in the interface
|
|
|
|
* @types: type signature for following method arguments
|
2014-03-13 15:47:46 +00:00
|
|
|
* @args: method arguments
|
2013-07-12 10:13:04 +00:00
|
|
|
*
|
2014-03-13 15:47:46 +00:00
|
|
|
* This creates a DBus method call message and saves a
|
|
|
|
* pointer to it in @call. The @destination, @path, @iface
|
2013-07-12 10:13:04 +00:00
|
|
|
* and @member parameters identify the object method to
|
|
|
|
* be invoked. The optional @replyout parameter will be
|
2014-03-13 15:47:46 +00:00
|
|
|
* filled with any reply to the method call. The method
|
|
|
|
* can be later invoked using virDBusCall.
|
2013-07-12 10:13:04 +00:00
|
|
|
*
|
|
|
|
* 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)
|
|
|
|
*
|
2013-07-23 23:06:26 +00:00
|
|
|
* At this time, there is no support for Unix fd's ('h'), which only
|
|
|
|
* newer DBus supports.
|
|
|
|
*
|
2013-07-12 10:13:04 +00:00
|
|
|
* 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.
|
Support passing dict by reference for dbus messages
Currently DBus dict values must be passed inline
virDBusMessageEncode("a{ss}",
3,
"key1", "val1",
"key2", "val2",
"key3", "val3");
virDBusMessageDecode("a{ss}",
3,
&key1, &val1,
&key2, &val2,
&key3, &val3);
This allows them to be passed by reference
const char **dictin = {
"key1", "val1",
"key2", "val2",
"key3", "val3"
};
char **dictout;
size_t ndictout;
virDBusMessageEncode("a&{ss}",
ARRAY_CARDINALITY(dict) / 2,
dictin);
virDBusMessageDecode("a&{ss}",
&ndictout,
&dictout);
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2014-09-09 14:19:58 +00:00
|
|
|
* 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.
|
2013-07-12 10:13:04 +00:00
|
|
|
*
|
|
|
|
* - 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")
|
|
|
|
*/
|
2014-03-13 15:47:46 +00:00
|
|
|
int virDBusCreateMethodV(DBusMessage **call,
|
|
|
|
const char *destination,
|
|
|
|
const char *path,
|
|
|
|
const char *iface,
|
|
|
|
const char *member,
|
|
|
|
const char *types,
|
|
|
|
va_list args)
|
2013-07-12 10:13:04 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
if (!(*call = dbus_message_new_method_call(destination,
|
|
|
|
path,
|
|
|
|
iface,
|
|
|
|
member))) {
|
2013-07-12 10:13:04 +00:00
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
if (virDBusMessageEncodeArgs(*call, types, args) < 0) {
|
2016-02-11 10:14:11 +00:00
|
|
|
virDBusMessageUnref(*call);
|
2014-03-13 15:47:46 +00:00
|
|
|
*call = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
va_start(args, types);
|
2014-03-13 15:47:46 +00:00
|
|
|
ret = virDBusCreateMethodV(call, destination, path,
|
|
|
|
iface, member, types, args);
|
2013-07-12 10:13:04 +00:00
|
|
|
va_end(args);
|
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-19 10:58:42 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(*reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDBusMessageEncodeArgs(*reply, types, args) < 0) {
|
2016-02-11 10:14:11 +00:00
|
|
|
virDBusMessageUnref(*reply);
|
2014-03-19 10:58:42 +00:00
|
|
|
*reply = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
/**
|
|
|
|
* virDBusCall:
|
|
|
|
* @conn: a DBus connection
|
|
|
|
* @call: pointer to a message to send
|
|
|
|
* @replyout: pointer to receive reply message, or NULL
|
2014-03-17 17:56:48 +00:00
|
|
|
* @error: pointer to receive error message
|
2014-03-13 15:47:46 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2014-03-17 17:56:48 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2014-03-13 15:47:46 +00:00
|
|
|
* Returns 0 on success, or -1 upon error
|
|
|
|
*/
|
2014-05-03 19:28:08 +00:00
|
|
|
static int
|
|
|
|
virDBusCall(DBusConnection *conn,
|
|
|
|
DBusMessage *call,
|
|
|
|
DBusMessage **replyout,
|
2015-01-19 12:30:24 +00:00
|
|
|
virErrorPtr error)
|
2014-11-11 18:39:19 +00:00
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
{
|
|
|
|
DBusMessage *reply = NULL;
|
2014-03-17 17:56:48 +00:00
|
|
|
DBusError localerror;
|
2014-03-13 15:47:46 +00:00
|
|
|
int ret = -1;
|
2014-11-11 18:39:19 +00:00
|
|
|
const char *iface, *member, *path, *dest;
|
2014-03-13 15:47:46 +00:00
|
|
|
|
2015-01-19 12:30:24 +00:00
|
|
|
dbus_error_init(&localerror);
|
|
|
|
if (error)
|
|
|
|
memset(error, 0, sizeof(*error));
|
2013-07-12 10:13:04 +00:00
|
|
|
|
2014-11-11 18:39:19 +00:00
|
|
|
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);
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
if (!(reply = dbus_connection_send_with_reply_and_block(conn,
|
|
|
|
call,
|
|
|
|
VIR_DBUS_METHOD_CALL_TIMEOUT_MILLIS,
|
2015-01-19 12:30:24 +00:00
|
|
|
&localerror))) {
|
2014-11-11 18:39:19 +00:00
|
|
|
PROBE(DBUS_METHOD_ERROR,
|
|
|
|
"'%s.%s' on '%s' at '%s' error %s: %s",
|
|
|
|
iface, member, path, dest,
|
2015-01-19 12:30:24 +00:00
|
|
|
localerror.name,
|
|
|
|
localerror.message);
|
2014-09-03 19:39:21 +00:00
|
|
|
if (error) {
|
2015-01-19 12:30:24 +00:00
|
|
|
error->level = VIR_ERR_ERROR;
|
|
|
|
error->code = VIR_ERR_DBUS_SERVICE;
|
|
|
|
error->domain = VIR_FROM_DBUS;
|
|
|
|
if (VIR_STRDUP(error->message, localerror.message) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (VIR_STRDUP(error->str1, localerror.name) < 0)
|
|
|
|
goto cleanup;
|
2014-03-17 17:56:48 +00:00
|
|
|
ret = 0;
|
2014-09-03 19:39:21 +00:00
|
|
|
} else {
|
2014-05-03 19:53:03 +00:00
|
|
|
virReportError(VIR_ERR_DBUS_SERVICE, _("%s: %s"), member,
|
2018-09-19 08:38:14 +00:00
|
|
|
localerror.message ? : _("unknown error"));
|
2014-05-03 19:46:52 +00:00
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-11-11 18:39:19 +00:00
|
|
|
PROBE(DBUS_METHOD_REPLY,
|
|
|
|
"'%s.%s' on '%s' at '%s'",
|
|
|
|
iface, member, path, dest);
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
cleanup:
|
2015-01-19 12:30:24 +00:00
|
|
|
if (ret < 0 && error)
|
|
|
|
virResetError(error);
|
|
|
|
dbus_error_free(&localerror);
|
2013-07-12 10:13:04 +00:00
|
|
|
if (reply) {
|
|
|
|
if (ret == 0 && replyout)
|
|
|
|
*replyout = reply;
|
|
|
|
else
|
2016-02-11 10:14:11 +00:00
|
|
|
virDBusMessageUnref(reply);
|
2013-07-12 10:13:04 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
2014-03-17 17:56:48 +00:00
|
|
|
*
|
|
|
|
* 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
|
2014-03-13 15:47:46 +00:00
|
|
|
*/
|
|
|
|
int virDBusCallMethod(DBusConnection *conn,
|
|
|
|
DBusMessage **replyout,
|
2015-01-19 12:30:24 +00:00
|
|
|
virErrorPtr error,
|
2014-03-13 15:47:46 +00:00
|
|
|
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;
|
|
|
|
|
2014-11-11 18:39:19 +00:00
|
|
|
ret = virDBusCall(conn, call, replyout, error);
|
2014-03-13 15:47:46 +00:00
|
|
|
|
|
|
|
cleanup:
|
2016-02-11 10:14:11 +00:00
|
|
|
virDBusMessageUnref(call);
|
2014-03-13 15:47:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-03 15:16:08 +00:00
|
|
|
static int virDBusIsServiceInList(const char *listMethod, const char *name)
|
2013-09-11 03:15:02 +00:00
|
|
|
{
|
|
|
|
DBusConnection *conn;
|
|
|
|
DBusMessage *reply = NULL;
|
|
|
|
DBusMessageIter iter, sub;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!virDBusHasSystemBus())
|
|
|
|
return -2;
|
|
|
|
|
2013-10-11 16:50:43 +00:00
|
|
|
if (!(conn = virDBusGetSystemBus()))
|
|
|
|
return -1;
|
2013-09-11 03:15:02 +00:00
|
|
|
|
|
|
|
if (virDBusCallMethod(conn,
|
|
|
|
&reply,
|
2014-03-17 17:56:48 +00:00
|
|
|
NULL,
|
2013-09-11 03:15:02 +00:00
|
|
|
"org.freedesktop.DBus",
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus",
|
2014-03-03 15:16:08 +00:00
|
|
|
listMethod,
|
2014-02-12 10:36:06 +00:00
|
|
|
NULL) < 0)
|
2013-09-11 03:15:02 +00:00
|
|
|
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:
|
2016-02-11 10:14:11 +00:00
|
|
|
virDBusMessageUnref(reply);
|
2013-09-11 03:15:02 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-03 15:16:08 +00:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
|
2014-02-27 20:21:57 +00:00
|
|
|
/**
|
|
|
|
* virDBusIsServiceRegistered
|
|
|
|
* @name: service name
|
|
|
|
*
|
2016-11-15 14:00:08 +00:00
|
|
|
* Returns 0 if service is registered, -1 on fatal error, or -2 if service is not registered
|
2014-02-27 20:21:57 +00:00
|
|
|
*/
|
|
|
|
int virDBusIsServiceRegistered(const char *name)
|
|
|
|
{
|
|
|
|
int ret = virDBusIsServiceInList("ListNames", name);
|
|
|
|
|
|
|
|
VIR_DEBUG("Service %s is %s", name, ret ? "not registered" : "registered");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-04-14 17:45:47 +00:00
|
|
|
void virDBusMessageUnref(DBusMessage *msg)
|
|
|
|
{
|
2016-02-11 10:14:11 +00:00
|
|
|
if (msg)
|
|
|
|
dbus_message_unref(msg);
|
2014-04-14 17:45:47 +00:00
|
|
|
}
|
|
|
|
|
2012-09-20 14:05:39 +00:00
|
|
|
#else /* ! WITH_DBUS */
|
2013-10-11 14:28:39 +00:00
|
|
|
void virDBusSetSharedBus(bool shared ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* nothing */
|
|
|
|
}
|
|
|
|
|
2012-04-19 14:34:35 +00:00
|
|
|
DBusConnection *virDBusGetSystemBus(void)
|
|
|
|
{
|
2012-07-18 10:26:24 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
2012-04-19 14:34:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-08-19 09:24:04 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
virDBusHasSystemBus(void)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("DBus support not compiled into this binary");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-10-11 14:57:05 +00:00
|
|
|
void virDBusCloseSystemBus(void)
|
|
|
|
{
|
|
|
|
/* nothing */
|
|
|
|
}
|
2013-08-19 09:24:04 +00:00
|
|
|
|
2012-10-31 19:03:49 +00:00
|
|
|
DBusConnection *virDBusGetSessionBus(void)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-07-12 10:13:04 +00:00
|
|
|
|
2014-03-13 15:47:46 +00:00
|
|
|
int virDBusCreateMethod(DBusMessage **call ATTRIBUTE_UNUSED,
|
|
|
|
const char *destination ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
const char *iface ATTRIBUTE_UNUSED,
|
|
|
|
const char *member ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED, ...)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int virDBusCreateMethodV(DBusMessage **call ATTRIBUTE_UNUSED,
|
|
|
|
const char *destination ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
const char *iface ATTRIBUTE_UNUSED,
|
|
|
|
const char *member ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED,
|
|
|
|
va_list args ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-03-21 13:27:34 +00:00
|
|
|
int virDBusCreateReplyV(DBusMessage **reply ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED,
|
|
|
|
va_list args ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int virDBusCreateReply(DBusMessage **reply ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED, ...)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-12 10:13:04 +00:00
|
|
|
int virDBusCallMethod(DBusConnection *conn ATTRIBUTE_UNUSED,
|
|
|
|
DBusMessage **reply ATTRIBUTE_UNUSED,
|
2015-01-19 12:30:24 +00:00
|
|
|
virErrorPtr error ATTRIBUTE_UNUSED,
|
2013-07-12 10:13:04 +00:00
|
|
|
const char *destination ATTRIBUTE_UNUSED,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
2013-07-29 13:54:10 +00:00
|
|
|
const char *iface ATTRIBUTE_UNUSED,
|
2013-07-12 10:13:04 +00:00
|
|
|
const char *member ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED, ...)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-22 18:32:49 +00:00
|
|
|
int virDBusMessageEncode(DBusMessage* msg ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int virDBusMessageDecode(DBusMessage* msg ATTRIBUTE_UNUSED,
|
|
|
|
const char *types ATTRIBUTE_UNUSED,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("DBus support not compiled into this binary"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-11 03:15:02 +00:00
|
|
|
int virDBusIsServiceEnabled(const char *name ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("DBus support not compiled into this binary");
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2014-02-27 20:21:57 +00:00
|
|
|
int virDBusIsServiceRegistered(const char *name ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("DBus support not compiled into this binary");
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2014-04-14 17:45:47 +00:00
|
|
|
void virDBusMessageUnref(DBusMessage *msg ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* nothing */
|
|
|
|
}
|
2012-09-20 14:05:39 +00:00
|
|
|
#endif /* ! WITH_DBUS */
|
2015-01-22 16:50:33 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|