/* SPDX-License-Identifier: LGPL-2.1-or-later */ #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; } 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 = sd_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; } 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 = sd_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; }