2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2020-06-28 16:08:37 +02:00
|
|
|
|
|
|
|
#include "bus-map-properties.h"
|
|
|
|
#include "alloc-util.h"
|
|
|
|
#include "strv.h"
|
|
|
|
#include "bus-message.h"
|
|
|
|
|
|
|
|
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
|
|
|
|
sd_id128_t *p = userdata;
|
|
|
|
const void *v;
|
|
|
|
size_t n;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
*p = SD_ID128_NULL;
|
|
|
|
else if (n == 16)
|
|
|
|
memcpy((*p).bytes, v, n);
|
|
|
|
else
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-11 12:19:46 +02:00
|
|
|
int bus_map_strv_sort(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
|
|
|
|
_cleanup_strv_free_ char **l = NULL;
|
|
|
|
char ***p = userdata;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = bus_message_read_strv_extend(m, &l);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = strv_extend_strv(p, l, false);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
strv_sort(*p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-06-28 16:08:37 +02:00
|
|
|
static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
|
|
|
|
char type;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = sd_bus_message_peek_type(m, &type, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_STRING:
|
|
|
|
case SD_BUS_TYPE_OBJECT_PATH: {
|
|
|
|
const char **p = userdata;
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, type, &s);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (isempty(s))
|
|
|
|
s = NULL;
|
|
|
|
|
|
|
|
if (flags & BUS_MAP_STRDUP)
|
|
|
|
return free_and_strdup((char **) userdata, s);
|
|
|
|
|
|
|
|
*p = s;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_ARRAY: {
|
|
|
|
_cleanup_strv_free_ char **l = NULL;
|
|
|
|
char ***p = userdata;
|
|
|
|
|
|
|
|
r = bus_message_read_strv_extend(m, &l);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return strv_extend_strv(p, l, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_BOOLEAN: {
|
|
|
|
int b;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, type, &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
|
|
|
|
*(bool*) userdata = b;
|
|
|
|
else
|
|
|
|
*(int*) userdata = b;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_INT32:
|
|
|
|
case SD_BUS_TYPE_UINT32: {
|
|
|
|
uint32_t u, *p = userdata;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, type, &u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
*p = u;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_INT64:
|
|
|
|
case SD_BUS_TYPE_UINT64: {
|
|
|
|
uint64_t t, *p = userdata;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, type, &t);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
*p = t;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SD_BUS_TYPE_DOUBLE: {
|
|
|
|
double d, *p = userdata;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, type, &d);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
*p = d;
|
|
|
|
return 0;
|
|
|
|
}}
|
|
|
|
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bus_message_map_all_properties(
|
|
|
|
sd_bus_message *m,
|
|
|
|
const struct bus_properties_map *map,
|
|
|
|
unsigned flags,
|
|
|
|
sd_bus_error *error,
|
|
|
|
void *userdata) {
|
|
|
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(m);
|
|
|
|
assert(map);
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
|
|
|
|
const struct bus_properties_map *prop;
|
|
|
|
const char *member;
|
|
|
|
const char *contents;
|
|
|
|
void *v;
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
for (i = 0, prop = NULL; map[i].member; i++)
|
|
|
|
if (streq(map[i].member, member)) {
|
|
|
|
prop = &map[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop) {
|
|
|
|
r = sd_bus_message_peek_type(m, NULL, &contents);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
v = (uint8_t *)userdata + prop->offset;
|
|
|
|
if (map[i].set)
|
|
|
|
r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
|
|
|
|
else
|
|
|
|
r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
} else {
|
|
|
|
r = sd_bus_message_skip(m, "v");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return sd_bus_message_exit_container(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
int bus_map_all_properties(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *destination,
|
|
|
|
const char *path,
|
|
|
|
const struct bus_properties_map *map,
|
|
|
|
unsigned flags,
|
|
|
|
sd_bus_error *error,
|
|
|
|
sd_bus_message **reply,
|
|
|
|
void *userdata) {
|
|
|
|
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(destination);
|
|
|
|
assert(path);
|
|
|
|
assert(map);
|
|
|
|
assert(reply || (flags & BUS_MAP_STRDUP));
|
|
|
|
|
|
|
|
r = sd_bus_call_method(
|
|
|
|
bus,
|
|
|
|
destination,
|
|
|
|
path,
|
|
|
|
"org.freedesktop.DBus.Properties",
|
|
|
|
"GetAll",
|
|
|
|
error,
|
|
|
|
&m,
|
|
|
|
"s", "");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = bus_message_map_all_properties(m, map, flags, error, userdata);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (reply)
|
|
|
|
*reply = sd_bus_message_ref(m);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|