#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-internal.h"
-#include "bus-util.h"
+#include "bus-polkit.h"
#include "dbus-automount.h"
#include "dbus-cgroup.h"
#include "dbus-device.h"
#include "fd-util.h"
#include "fs-util.h"
#include "log.h"
-#include "missing.h"
#include "mkdir.h"
#include "process-util.h"
#include "selinux-access.h"
+#include "serialize.h"
#include "service.h"
#include "special.h"
#include "string-util.h"
static void destroy_bus(Manager *m, sd_bus **bus);
-int bus_send_queued_message(Manager *m) {
+int bus_send_pending_reload_message(Manager *m) {
int r;
assert(m);
- if (!m->queued_message)
+ if (!m->pending_reload_message)
return 0;
- /* If we cannot get rid of this message we won't dispatch any
- * D-Bus messages, so that we won't end up wanting to queue
- * another message. */
+ /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
+ * to queue another message. */
- r = sd_bus_send(NULL, m->queued_message, NULL);
+ r = sd_bus_send(NULL, m->pending_reload_message, NULL);
if (r < 0)
- log_warning_errno(r, "Failed to send queued message: %m");
+ log_warning_errno(r, "Failed to send queued message, ignoring: %m");
- m->queued_message = sd_bus_message_unref(m->queued_message);
+ m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
return 0;
}
goto failed;
}
- r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, NULL);
+ r = manager_add_job(m, JOB_START, u, JOB_REPLACE, NULL, &error, NULL);
if (r < 0)
goto failed;
}
static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
_cleanup_close_ int nfd = -1;
Manager *m = userdata;
sd_id128_t id;
nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (nfd < 0) {
+ if (ERRNO_IS_ACCEPT_AGAIN(errno))
+ return 0;
+
log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
return 0;
}
return 0;
}
-static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) {
- _cleanup_strv_free_ char **names = NULL;
- Manager *m = userdata;
- const char *name;
- Iterator i;
- Unit *u;
- int r;
-
- assert(es);
- assert(m);
- assert(m->sync_bus_names_event_source == es);
-
- /* First things first, destroy the defer event so that we aren't triggered again */
- m->sync_bus_names_event_source = sd_event_source_unref(m->sync_bus_names_event_source);
-
- /* Let's see if there's anything to do still? */
- if (!m->api_bus)
- return 0;
- if (hashmap_isempty(m->watch_bus))
- return 0;
-
- /* OK, let's sync up the names. Let's see which names are currently on the bus. */
- r = sd_bus_list_names(m->api_bus, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to get initial list of names: %m");
-
- /* We have to synchronize the current bus names with the
- * list of active services. To do this, walk the list of
- * all units with bus names. */
- HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
- Service *s = SERVICE(u);
-
- assert(s);
-
- if (!streq_ptr(s->bus_name, name)) {
- log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name);
- continue;
- }
-
- /* Check if a service's bus name is in the list of currently
- * active names */
- if (strv_contains(names, name)) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- const char *unique;
-
- /* If it is, determine its current owner */
- r = sd_bus_get_name_creds(m->api_bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds);
- if (r < 0) {
- log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name);
- continue;
- }
-
- r = sd_bus_creds_get_unique_name(creds, &unique);
- if (r < 0) {
- log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name);
- continue;
- }
-
- /* Now, let's compare that to the previous bus owner, and
- * if it's still the same, all is fine, so just don't
- * bother the service. Otherwise, the name has apparently
- * changed, so synthesize a name owner changed signal. */
-
- if (!streq_ptr(unique, s->bus_name_owner))
- UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique);
- } else {
- /* So, the name we're watching is not on the bus.
- * This either means it simply hasn't appeared yet,
- * or it was lost during the daemon reload.
- * Check if the service has a stored name owner,
- * and synthesize a name loss signal in this case. */
-
- if (s->bus_name_owner)
- UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL);
- }
- }
-
- return 0;
-}
-
-int manager_enqueue_sync_bus_names(Manager *m) {
- int r;
-
- assert(m);
-
- /* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't
- * want us to invoke ->bus_name_owner_change() unit calls from their stack frames as this might result in event
- * dispatching on its own creating loops, hence we simply create a defer event for the event loop and exit. */
-
- if (m->sync_bus_names_event_source)
- return 0;
-
- r = sd_event_add_defer(m->event, &m->sync_bus_names_event_source, manager_dispatch_sync_bus_names, m);
- if (r < 0)
- return log_error_errno(r, "Failed to create bus name synchronization event: %m");
-
- r = sd_event_source_set_priority(m->sync_bus_names_event_source, SD_EVENT_PRIORITY_IDLE);
- if (r < 0)
- return log_error_errno(r, "Failed to set event priority: %m");
-
- r = sd_event_source_set_enabled(m->sync_bus_names_event_source, SD_EVENT_ONESHOT);
- if (r < 0)
- return log_error_errno(r, "Failed to set even to oneshot: %m");
-
- (void) sd_event_source_set_description(m->sync_bus_names_event_source, "manager-sync-bus-names");
- return 0;
-}
-
static int bus_setup_api(Manager *m, sd_bus *bus) {
Iterator i;
char *name;
}
int bus_init_api(Manager *m) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
if (m->api_bus)
m->api_bus = TAKE_PTR(bus);
- r = manager_enqueue_sync_bus_names(m);
- if (r < 0)
- return r;
-
return 0;
}
}
int bus_init_system(Manager *m) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
if (m->system_bus)
int bus_init_private(Manager *m) {
_cleanup_close_ int fd = -1;
- union sockaddr_union sa = {
- .un.sun_family = AF_UNIX
- };
+ union sockaddr_union sa = {};
sd_event_source *s;
- socklen_t salen;
- int r;
+ int r, salen;
assert(m);
if (getpid_cached() != 1)
return 0;
- strcpy(sa.un.sun_path, "/run/systemd/private");
- salen = SOCKADDR_UN_LEN(sa.un);
+ salen = sockaddr_un_set_path(&sa.un, "/run/systemd/private");
} else {
- size_t left = sizeof(sa.un.sun_path);
- char *p = sa.un.sun_path;
- const char *e;
+ const char *e, *joined;
e = secure_getenv("XDG_RUNTIME_DIR");
- if (!e) {
- log_error("XDG_RUNTIME_DIR is not set, refusing.");
- return -EHOSTDOWN;
- }
+ if (!e)
+ return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
+ "XDG_RUNTIME_DIR is not set, refusing.");
- left = strpcpy(&p, left, e);
- left = strpcpy(&p, left, "/systemd/private");
-
- salen = sizeof(sa.un) - left;
+ joined = strjoina(e, "/systemd/private");
+ salen = sockaddr_un_set_path(&sa.un, joined);
}
+ if (salen < 0)
+ return log_error_errno(salen, "Can't set path for AF_UNIX socket to bind to: %m");
(void) mkdir_parents_label(sa.un.sun_path, 0755);
(void) sockaddr_un_unlink(&sa.un);
/* Make sure all bus slots watching names are released. */
HASHMAP_FOREACH(u, m->watch_bus, i) {
- if (!u->match_bus_slot)
- continue;
-
- if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus)
- continue;
-
- u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
+ if (u->match_bus_slot && sd_bus_slot_get_bus(u->match_bus_slot) == *bus)
+ u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
+ if (u->get_name_owner_slot && sd_bus_slot_get_bus(u->get_name_owner_slot) == *bus)
+ u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
}
/* Get rid of tracked clients on this bus */
u->bus_track = sd_bus_track_unref(u->bus_track);
/* Get rid of queued message on this bus */
- if (m->queued_message && sd_bus_message_get_bus(m->queued_message) == *bus)
- m->queued_message = sd_bus_message_unref(m->queued_message);
+ if (m->pending_reload_message && sd_bus_message_get_bus(m->pending_reload_message) == *bus)
+ m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
/* Possibly flush unwritten data, but only if we are
* unprivileged, since we don't want to sync here */
sd_bus_flush(*bus);
/* And destroy the object */
- sd_bus_close(*bus);
- *bus = sd_bus_unref(*bus);
+ *bus = sd_bus_close_unref(*bus);
}
void bus_done_api(Manager *m) {
int c, j;
c = sd_bus_track_count_name(t, n);
-
- for (j = 0; j < c; j++) {
- fputs(prefix, f);
- fputc('=', f);
- fputs(n, f);
- fputc('\n', f);
- }
+ for (j = 0; j < c; j++)
+ (void) serialize_item(f, prefix, n);
}
}
sd_bus *b;
int r;
- /* Returns the total number of messages queued for writing on all our direct and API busses. */
+ /* Returns the total number of messages queued for writing on all our direct and API buses. */
SET_FOREACH(b, m->private_buses, i) {
uint64_t k;