From: Yu Watanabe Date: Wed, 28 Mar 2018 11:37:27 +0000 (+0900) Subject: bus-util: add flags for bus_map_all_properties() (#8546) X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=b4031e810423eb6474ca9c8eb41cf04d9884c71a;p=elogind.git bus-util: add flags for bus_map_all_properties() (#8546) This adds flags BUS_MAP_STRDUP and BUS_MAP_BOOLEAN_AS_BOOL. If BUS_MAP_STRDUP is set, then each "s" message is duplicated. If BUS_MAP_BOOLEAN_AS_BOOL is set, then each "b" message is written to a bool pointer. Follow-up for #8488. See https://github.com/systemd/systemd/pull/8488#discussion_r175816270. --- diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 8135f8011..96c49947f 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -127,7 +127,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) { assert(bus); assert(argv); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); r = sd_bus_call_method( bus, @@ -202,7 +202,7 @@ static int list_users(int argc, char *argv[], void *userdata) { assert(bus); assert(argv); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); r = sd_bus_call_method( bus, @@ -247,7 +247,7 @@ static int list_seats(int argc, char *argv[], void *userdata) { assert(bus); assert(argv); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); r = sd_bus_call_method( bus, @@ -325,77 +325,52 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit #endif // 0 typedef struct SessionStatusInfo { - char *id; + const char *id; uid_t uid; - char *name; + const char *name; struct dual_timestamp timestamp; unsigned int vtnr; - char *seat; - char *tty; - char *display; - int remote; - char *remote_host; - char *remote_user; - char *service; + const char *seat; + const char *tty; + const char *display; + bool remote; + const char *remote_host; + const char *remote_user; + const char *service; pid_t leader; - char *type; - char *class; - char *state; - char *scope; - char *desktop; + const char *type; + const char *class; + const char *state; + const char *scope; + const char *desktop; } SessionStatusInfo; typedef struct UserStatusInfo { uid_t uid; - int linger; - char *name; + bool linger; + const char *name; struct dual_timestamp timestamp; - char *state; + const char *state; char **sessions; - char *display; - char *slice; + const char *display; + const char *slice; } UserStatusInfo; typedef struct SeatStatusInfo { - char *id; - char *active_session; + const char *id; + const char *active_session; char **sessions; } SeatStatusInfo; -static void session_status_info_clear(SessionStatusInfo *info) { - if (info) { - free(info->id); - free(info->name); - free(info->seat); - free(info->tty); - free(info->display); - free(info->remote_host); - free(info->remote_user); - free(info->service); - free(info->type); - free(info->class); - free(info->state); - free(info->scope); - free(info->desktop); - zero(*info); - } -} - static void user_status_info_clear(UserStatusInfo *info) { if (info) { - free(info->name); - free(info->state); strv_free(info->sessions); - free(info->display); - free(info->slice); zero(*info); } } static void seat_status_info_clear(SeatStatusInfo *info) { if (info) { - free(info->id); - free(info->active_session); strv_free(info->sessions); zero(*info); } @@ -413,22 +388,9 @@ static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_mess if (r < 0) return r; - if (IN_SET(contents[0], 's', 'o')) { - const char *s; - char **p = (char **) userdata; - - r = sd_bus_message_read_basic(m, contents[0], &s); - if (r < 0) - return r; - - r = free_and_strdup(p, s); - if (r < 0) - return r; - } else { - r = sd_bus_message_read_basic(m, contents[0], userdata); - if (r < 0) - return r; - } + r = sd_bus_message_read_basic(m, contents[0], userdata); + if (r < 0) + return r; r = sd_bus_message_skip(m, contents+1); if (r < 0) @@ -489,12 +451,13 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; - _cleanup_(session_status_info_clear) SessionStatusInfo i = {}; + SessionStatusInfo i = {}; int r; - r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i); + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i); if (r < 0) return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); @@ -621,12 +584,13 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1; char since2[FORMAT_TIMESTAMP_MAX], *s2; _cleanup_(user_status_info_clear) UserStatusInfo i = {}; int r; - r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i); + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i); if (r < 0) return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); @@ -698,10 +662,11 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) }; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(seat_status_info_clear) SeatStatusInfo i = {}; int r; - r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, &error, &i); + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i); if (r < 0) return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); @@ -745,40 +710,41 @@ static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) #define property(name, fmt, ...) \ do { \ - if (arg_value) \ + if (value) \ printf(fmt "\n", __VA_ARGS__); \ else \ printf("%s=" fmt "\n", name, __VA_ARGS__); \ } while (0) -static int print_property(const char *name, sd_bus_message *m, const char *contents) { +static int print_property(const char *name, sd_bus_message *m, bool value, bool all) { + char type; + const char *contents; int r; assert(name); assert(m); - assert(contents); - if (arg_property && !strv_find(arg_property, name)) - /* skip what we didn't read */ - return sd_bus_message_skip(m, contents); + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; - switch (contents[0]) { + switch (type) { - case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_STRUCT: - if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) { + if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) { const char *s; r = sd_bus_message_read(m, "(so)", &s, NULL); if (r < 0) return bus_log_parse_error(r); - if (arg_all || !isempty(s)) + if (all || !isempty(s)) property(name, "%s", s); - return 0; + return 1; - } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) { + } else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) { uint32_t uid; r = sd_bus_message_read(m, "(uo)", &uid, NULL); @@ -791,14 +757,13 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte } property(name, UID_FMT, uid); - return 0; + return 1; } - break; case SD_BUS_TYPE_ARRAY: - if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) { + if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) { const char *s; bool space = false; @@ -806,7 +771,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte if (r < 0) return bus_log_parse_error(r); - if (!arg_value) + if (!value) printf("%s=", name); while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) { @@ -814,7 +779,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte space = true; } - if (space || !arg_value) + if (space || !value) printf("\n"); if (r < 0) @@ -824,25 +789,11 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte if (r < 0) return bus_log_parse_error(r); - return 0; + return 1; } - break; } - r = bus_print_property(name, m, arg_value, arg_all); - if (r < 0) - return bus_log_parse_error(r); - - if (r == 0) { - r = sd_bus_message_skip(m, contents); - if (r < 0) - return bus_log_parse_error(r); - - if (arg_all) - printf("%s=[unprintable]\n", name); - } - return 0; } @@ -855,58 +806,12 @@ static int show_properties(sd_bus *bus, const char *path, bool *new_line) { assert(path); assert(new_line); - r = sd_bus_call_method( - bus, - "org.freedesktop.login1", - path, - "org.freedesktop.DBus.Properties", - "GetAll", - &error, - &reply, - "s", ""); - if (r < 0) - return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); - - r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); - if (r < 0) - return bus_log_parse_error(r); - if (*new_line) printf("\n"); *new_line = true; - while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { - const char *name, *contents; - - r = sd_bus_message_read(reply, "s", &name); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_peek_type(reply, NULL, &contents); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); - if (r < 0) - return bus_log_parse_error(r); - - r = print_property(name, reply, contents); - if (r < 0) - return r; - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - } - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_exit_container(reply); + r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL); if (r < 0) return bus_log_parse_error(r); @@ -925,7 +830,7 @@ static int show_session(int argc, char *argv[], void *userdata) { properties = !strstr(argv[0], "status"); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); if (argc <= 1) { const char *session, *p = "/org/freedesktop/login1/session/self"; @@ -977,7 +882,7 @@ static int show_user(int argc, char *argv[], void *userdata) { properties = !strstr(argv[0], "status"); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); if (argc <= 1) { /* If not argument is specified inspect the manager @@ -1037,7 +942,7 @@ static int show_seat(int argc, char *argv[], void *userdata) { properties = !strstr(argv[0], "status"); - pager_open(arg_no_pager, false); + (void) pager_open(arg_no_pager, false); if (argc <= 1) { /* If not argument is specified inspect the manager diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index f0549f8d4..870ffbb26 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1061,7 +1061,7 @@ int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_err return 0; } -static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata, bool copy_string) { +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; @@ -1082,7 +1082,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ if (isempty(s)) s = NULL; - if (copy_string) + if (flags & BUS_MAP_STRDUP) return free_and_strdup((char **) userdata, s); *p = s; @@ -1103,14 +1103,17 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ } case SD_BUS_TYPE_BOOLEAN: { - unsigned b; - bool *p = userdata; + int b; r = sd_bus_message_read_basic(m, type, &b); if (r < 0) return r; - *p = !!b; + if (flags & BUS_MAP_BOOLEAN_AS_BOOL) + * (bool*) userdata = !!b; + else + * (int*) userdata = b; + return 0; } @@ -1155,7 +1158,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ int bus_message_map_all_properties( sd_bus_message *m, const struct bus_properties_map *map, - bool copy_string, + unsigned flags, sd_bus_error *error, void *userdata) { @@ -1198,7 +1201,7 @@ int bus_message_map_all_properties( 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, error, v, copy_string); + r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v); if (r < 0) return r; @@ -1225,7 +1228,7 @@ int bus_message_map_all_properties( int bus_message_map_properties_changed( sd_bus_message *m, const struct bus_properties_map *map, - bool copy_string, + unsigned flags, sd_bus_error *error, void *userdata) { @@ -1235,7 +1238,7 @@ int bus_message_map_properties_changed( assert(m); assert(map); - r = bus_message_map_all_properties(m, map, copy_string, error, userdata); + r = bus_message_map_all_properties(m, map, flags, error, userdata); if (r < 0) return r; @@ -1266,6 +1269,7 @@ int bus_map_all_properties( const char *destination, const char *path, const struct bus_properties_map *map, + unsigned flags, sd_bus_error *error, sd_bus_message **reply, void *userdata) { @@ -1277,6 +1281,7 @@ int bus_map_all_properties( assert(destination); assert(path); assert(map); + assert(reply || (flags & BUS_MAP_STRDUP)); r = sd_bus_call_method( bus, @@ -1290,7 +1295,7 @@ int bus_map_all_properties( if (r < 0) return r; - r = bus_message_map_all_properties(m, map, !reply, error, userdata); + r = bus_message_map_all_properties(m, map, flags, error, userdata); if (r < 0) return r; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index 608345130..c4b07673b 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -49,13 +49,19 @@ struct bus_properties_map { size_t offset; }; +enum { + BUS_MAP_STRDUP = 1U << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */ + BUS_MAP_BOOLEAN_AS_BOOL = 1U << 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, sd_bus_error *error, void *userdata); #if 0 /// UNNEEDED by elogind -int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); #endif // 0 -int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, 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_message_map_properties_changed(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); #if 0 /// UNNEEDED by elogind int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); @@ -88,8 +94,11 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s #endif // 0 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); +typedef int (*bus_message_print_t) (const char *name, sd_bus_message *m, bool value, bool all); + int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all); -int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all); +int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties); +int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties); int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error); @@ -166,8 +175,7 @@ int bus_log_create_error(int r); return r; \ \ return 1; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ + } #define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \ SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \