From: Yu Watanabe Date: Sat, 19 May 2018 16:55:39 +0000 (+0900) Subject: timesync,shared: move logic requesting bus name to shared X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=3681bac889ef9c938544a43ebef302a58fc8c00a;p=elogind.git timesync,shared: move logic requesting bus name to shared Preparation for setting DynamicUser= to other services which request bus names. --- diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 4cfe40433..a191c3a4a 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1744,3 +1744,124 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri return 0; } + +struct request_name_data { + const char *name; + uint64_t flags; + void *userdata; +}; + +static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + _cleanup_free_ struct request_name_data *data = userdata; + const sd_bus_error *e; + int r; + + assert(m); + assert(data); + assert(data->name); + + e = sd_bus_message_get_error(m); + if (e) { + log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message); + return 1; + } + + /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */ + r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, data->name, data->flags, NULL, data->userdata); + if (r < 0) + log_error_errno(r, "Failed to request name: %m"); + + return 1; +} + +static int request_name_handler_may_reload_dbus(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + _cleanup_free_ struct request_name_data *data = userdata; + uint32_t ret; + int r; + + assert(m); + assert(userdata); + + if (sd_bus_message_is_method_error(m, NULL)) { + const sd_bus_error *e = sd_bus_message_get_error(m); + + if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) { + log_debug_errno(sd_bus_error_get_errno(e), + "Unable to request name, failing connection: %s", + e->message); + + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug_errno(sd_bus_error_get_errno(e), + "Unable to request name, retry after reloading DBus configuration: %s", + e->message); + + /* If systemd-timesyncd.service enables DynamicUser= and dbus.service + * started before the dynamic user is realized, then the DBus policy + * about timesyncd has not been enabled yet. So, let's try to reload + * DBus configuration, and after that request name again. Note that it + * seems that no privileges are necessary to call the following method. */ + + r = sd_bus_call_method_async( + sd_bus_message_get_bus(m), + NULL, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ReloadConfig", + reload_dbus_handler, + userdata, NULL); + if (r < 0) { + log_error_errno(r, "Failed to reload DBus configuration: %m"); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + data = NULL; /* Avoid free() */ + return 1; + } + + r = sd_bus_message_read(m, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_ALREADY_OWNER: + log_debug("Already owner of requested service name, ignoring."); + return 1; + + case BUS_NAME_IN_QUEUE: + log_debug("In queue for requested service name."); + return 1; + + case BUS_NAME_PRIMARY_OWNER: + log_debug("Successfully acquired requested service name."); + return 1; + + case BUS_NAME_EXISTS: + log_debug("Requested service name already owned, failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug("Unexpected response from RequestName(), failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; +} + +int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata) { + struct request_name_data *data; + + data = new0(struct request_name_data, 1); + if (!data) + return -ENOMEM; + + data->name = name; + data->flags = flags; + data->userdata = userdata; + + return sd_bus_request_name_async(bus, ret_slot, name, flags, request_name_handler_may_reload_dbus, data); +} diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index db1ce4280..4c3846969 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -202,3 +202,5 @@ int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *descri static inline int bus_open_system_watch_bind(sd_bus **ret) { return bus_open_system_watch_bind_with_description(ret, NULL); } + +int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata);