diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c index 7b32fcb7b7..441fb0075c 100644 --- a/src/analyze/analyze-security.c +++ b/src/analyze/analyze-security.c @@ -4,6 +4,7 @@ #include "analyze-security.h" #include "bus-error.h" +#include "bus-map-properties.h" #include "bus-unit-util.h" #include "bus-util.h" #include "env-util.h" diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 8911d95c07..e42f7ff935 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -18,6 +18,7 @@ #include "build.h" #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "bus-unit-util.h" #include "calendarspec.h" #include "conf-files.h" diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index e08ab15acd..348d2b0429 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -12,7 +12,7 @@ #include "alloc-util.h" #include "architecture.h" #include "bus-error.h" -#include "bus-util.h" +#include "bus-map-properties.h" #include "hostname-util.h" #include "main-func.h" #include "pretty-print.h" diff --git a/src/locale/localectl.c b/src/locale/localectl.c index f00f15f3fe..251901c391 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -9,6 +9,7 @@ #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "fd-util.h" #include "fileio.h" #include "kbd-util.h" diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 85b6e162f1..6302589a48 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -10,6 +10,7 @@ #include "alloc-util.h" #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "bus-unit-procs.h" #include "cgroup-show.h" #include "cgroup-util.h" diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index bdb384fe58..6d124b418c 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -17,6 +17,7 @@ #include "bus-common-errors.h" #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "bus-unit-procs.h" #include "bus-unit-util.h" #include "bus-wait-for-jobs.h" diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 838da9aae9..b40f159c76 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -12,6 +12,7 @@ #include "bus-common-errors.h" #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "dns-domain.h" #include "escape.h" #include "format-table.h" diff --git a/src/run/run.c b/src/run/run.c index 80ddd0f521..6b996015e3 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -12,6 +12,7 @@ #include "alloc-util.h" #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "bus-unit-util.h" #include "bus-wait-for-jobs.h" #include "calendarspec.h" diff --git a/src/shared/bus-map-properties.c b/src/shared/bus-map-properties.c new file mode 100644 index 0000000000..ab393c3952 --- /dev/null +++ b/src/shared/bus-map-properties.c @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#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; +} + +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; +} diff --git a/src/shared/bus-map-properties.h b/src/shared/bus-map-properties.h new file mode 100644 index 0000000000..11b899227b --- /dev/null +++ b/src/shared/bus-map-properties.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); + +struct bus_properties_map { + const char *member; + const char *signature; + bus_property_set_t set; + size_t offset; +}; + +enum { + BUS_MAP_STRDUP = 1 << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */ + BUS_MAP_BOOLEAN_AS_BOOL = 1 << 1, /* If set, each "b" message is written to a bool pointer. If not set, "b" is written to a int pointer. */ +}; + +int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); + +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 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); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index b018a9e527..fc5ac7a057 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -701,229 +701,6 @@ int bus_print_all_properties( return bus_message_print_all_properties(reply, func, filter, value, all, found_properties); } -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; -} - -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; -} - int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) { _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; int r; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index db245a791e..8f700c3cfd 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -22,26 +22,6 @@ typedef enum BusTransport { _BUS_TRANSPORT_INVALID = -1 } BusTransport; -typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); - -struct bus_properties_map { - const char *member; - const char *signature; - bus_property_set_t set; - size_t offset; -}; - -enum { - BUS_MAP_STRDUP = 1 << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */ - BUS_MAP_BOOLEAN_AS_BOOL = 1 << 1, /* If set, each "b" message is written to a bool pointer. If not set, "b" is written to a int pointer. */ -}; - -int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); - -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 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); - int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); typedef bool (*check_idle_t)(void *userdata); diff --git a/src/shared/bus-wait-for-units.c b/src/shared/bus-wait-for-units.c index 3ee3c0ccba..7592dcf18d 100644 --- a/src/shared/bus-wait-for-units.c +++ b/src/shared/bus-wait-for-units.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -#include "bus-util.h" +#include "bus-map-properties.h" #include "bus-wait-for-units.h" #include "hashmap.h" #include "string-util.h" diff --git a/src/shared/meson.build b/src/shared/meson.build index 30ece1f193..881e30835e 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -31,6 +31,8 @@ shared_sources = files(''' bus-locator.h bus-log-control-api.c bus-log-control-api.h + bus-map-properties.c + bus-map-properties.h bus-object.c bus-object.h bus-polkit.c diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index c937b1e298..3bc32065a5 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -21,6 +21,7 @@ #include "bus-common-errors.h" #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "bus-message.h" #include "bus-unit-procs.h" #include "bus-unit-util.h" diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 97768808b7..9ee995802c 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -10,6 +10,7 @@ #include "bus-error.h" #include "bus-locator.h" +#include "bus-map-properties.h" #include "format-table.h" #include "in-addr-util.h" #include "main-func.h" diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 8ecd9d5dd3..d7d9305711 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -14,6 +14,7 @@ #include "bus-error.h" #include "bus-locator.h" #include "bus-log-control-api.h" +#include "bus-map-properties.h" #include "bus-polkit.h" #include "clock-util.h" #include "conf-files.h"