1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/socket.h>
24 #include "sd-daemon.h"
30 #include "path-util.h"
35 #include "bus-error.h"
36 #include "bus-message.h"
38 #include "bus-internal.h"
40 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
41 sd_event *e = userdata;
53 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
54 _cleanup_free_ char *match = NULL;
62 /* We unregister the name here and then wait for the
63 * NameOwnerChanged signal for this event to arrive before we
64 * quit. We do this in order to make sure that any queued
65 * requests are still processed before we really exit. */
67 r = sd_bus_get_unique_name(bus, &unique);
72 "sender='org.freedesktop.DBus',"
74 "interface='org.freedesktop.DBus',"
75 "member='NameOwnerChanged',"
76 "path='/org/freedesktop/DBus',"
79 "arg2=''", name, unique);
83 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
87 r = sd_bus_release_name(bus, name);
94 int bus_event_loop_with_idle(
99 check_idle_t check_idle,
101 bool exiting = false;
111 r = sd_event_get_state(e);
114 if (r == SD_EVENT_FINISHED)
118 idle = check_idle(userdata);
122 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
126 if (r == 0 && !exiting && idle) {
128 r = sd_bus_try_close(bus);
132 /* Fallback for dbus1 connections: we
133 * unregister the name and wait for the
134 * response to come through for it */
135 if (r == -EOPNOTSUPP) {
137 /* Inform the service manager that we
138 * are going down, so that it will
139 * queue all further start requests,
140 * instead of assuming we are already
142 sd_notify(false, "STOPPING=1");
144 r = bus_async_unregister_and_exit(e, bus, name);
160 r = sd_event_get_exit_code(e, &code);
167 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
168 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
169 int r, has_owner = 0;
174 r = sd_bus_call_method(c,
175 "org.freedesktop.DBus",
176 "/org/freedesktop/dbus",
177 "org.freedesktop.DBus",
186 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
188 return sd_bus_error_set_errno(error, r);
193 static int check_good_user(sd_bus_message *m, uid_t good_user) {
194 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
200 if (good_user == UID_INVALID)
203 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
207 r = sd_bus_creds_get_euid(creds, &sender_uid);
211 return sender_uid == good_user;
215 sd_bus_message *call,
227 /* Tests non-interactively! */
229 r = check_good_user(call, good_user);
233 r = sd_bus_query_sender_privilege(call, capability);
240 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
241 int authorized = false, challenge = false;
244 sender = sd_bus_message_get_sender(call);
248 r = sd_bus_call_method(
250 "org.freedesktop.PolicyKit1",
251 "/org/freedesktop/PolicyKit1/Authority",
252 "org.freedesktop.PolicyKit1.Authority",
253 "CheckAuthorization",
257 "system-bus-name", 1, "name", "s", sender,
264 /* Treat no PK available as access denied */
265 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
266 sd_bus_error_free(e);
273 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
277 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
285 *_challenge = challenge;
296 typedef struct AsyncPolkitQuery {
297 sd_bus_message *request, *reply;
298 sd_bus_message_handler_t callback;
304 static void async_polkit_query_free(AsyncPolkitQuery *q) {
309 sd_bus_slot_unref(q->slot);
311 if (q->registry && q->request)
312 hashmap_remove(q->registry, q->request);
314 sd_bus_message_unref(q->request);
315 sd_bus_message_unref(q->reply);
320 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
321 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
322 AsyncPolkitQuery *q = userdata;
329 q->slot = sd_bus_slot_unref(q->slot);
330 q->reply = sd_bus_message_ref(reply);
332 r = sd_bus_message_rewind(q->request, true);
334 r = sd_bus_reply_method_errno(q->request, r, NULL);
338 r = q->callback(bus, q->request, q->userdata, &error_buffer);
339 r = bus_maybe_reply_error(q->request, r, &error_buffer);
342 async_polkit_query_free(q);
349 int bus_verify_polkit_async(
350 sd_bus_message *call,
356 sd_bus_error *error) {
359 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
362 sd_bus_message_handler_t callback;
372 r = check_good_user(call, good_user);
377 q = hashmap_get(*registry, call);
379 int authorized, challenge;
381 /* This is the second invocation of this function, and
382 * there's already a response from polkit, let's
386 if (sd_bus_message_is_method_error(q->reply, NULL)) {
387 const sd_bus_error *e;
389 /* Copy error from polkit reply */
390 e = sd_bus_message_get_error(q->reply);
391 sd_bus_error_copy(error, e);
393 /* Treat no PK available as access denied */
394 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
397 return -sd_bus_error_get_errno(e);
400 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
402 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
411 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
417 r = sd_bus_query_sender_privilege(call, capability);
424 if (sd_bus_get_current_message(call->bus) != call)
427 callback = sd_bus_get_current_handler(call->bus);
431 userdata = sd_bus_get_current_userdata(call->bus);
433 sender = sd_bus_message_get_sender(call);
437 c = sd_bus_message_get_allow_interactive_authorization(call);
443 r = hashmap_ensure_allocated(registry, NULL);
447 r = sd_bus_message_new_method_call(
450 "org.freedesktop.PolicyKit1",
451 "/org/freedesktop/PolicyKit1/Authority",
452 "org.freedesktop.PolicyKit1.Authority",
453 "CheckAuthorization");
457 r = sd_bus_message_append(
460 "system-bus-name", 1, "name", "s", sender,
468 q = new0(AsyncPolkitQuery, 1);
472 q->request = sd_bus_message_ref(call);
473 q->callback = callback;
474 q->userdata = userdata;
476 r = hashmap_put(*registry, call, q);
478 async_polkit_query_free(q);
482 q->registry = *registry;
484 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
486 async_polkit_query_free(q);
496 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
500 while ((q = hashmap_steal_first(registry)))
501 async_polkit_query_free(q);
503 hashmap_free(registry);
507 int bus_check_peercred(sd_bus *c) {
514 fd = sd_bus_get_fd(c);
518 l = sizeof(struct ucred);
519 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
522 if (l != sizeof(struct ucred))
525 if (ucred.uid != 0 && ucred.uid != geteuid())
531 int bus_open_system_systemd(sd_bus **_bus) {
532 _cleanup_bus_unref_ sd_bus *bus = NULL;
538 return sd_bus_open_system(_bus);
540 /* If we are root and kdbus is not available, then let's talk
541 * directly to the system instance, instead of going via the
545 r = sd_bus_new(&bus);
549 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
553 bus->bus_client = true;
555 r = sd_bus_start(bus);
562 bus = sd_bus_unref(bus);
565 r = sd_bus_new(&bus);
569 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
573 r = sd_bus_start(bus);
575 return sd_bus_open_system(_bus);
577 r = bus_check_peercred(bus);
587 int bus_open_user_systemd(sd_bus **_bus) {
588 _cleanup_bus_unref_ sd_bus *bus = NULL;
589 _cleanup_free_ char *ee = NULL;
593 /* Try via kdbus first, and then directly */
598 r = sd_bus_new(&bus);
602 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
605 bus->bus_client = true;
607 r = sd_bus_start(bus);
614 bus = sd_bus_unref(bus);
617 e = secure_getenv("XDG_RUNTIME_DIR");
619 return sd_bus_open_user(_bus);
621 ee = bus_address_escape(e);
625 r = sd_bus_new(&bus);
629 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
633 r = sd_bus_start(bus);
635 return sd_bus_open_user(_bus);
637 r = bus_check_peercred(bus);
647 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
649 const char *contents;
655 r = sd_bus_message_peek_type(property, &type, &contents);
661 case SD_BUS_TYPE_STRING: {
664 r = sd_bus_message_read_basic(property, type, &s);
668 if (all || !isempty(s)) {
669 _cleanup_free_ char *escaped = NULL;
671 escaped = xescape(s, "\n");
675 printf("%s=%s\n", name, escaped);
681 case SD_BUS_TYPE_BOOLEAN: {
684 r = sd_bus_message_read_basic(property, type, &b);
688 printf("%s=%s\n", name, yes_no(b));
693 case SD_BUS_TYPE_UINT64: {
696 r = sd_bus_message_read_basic(property, type, &u);
700 /* Yes, heuristics! But we can change this check
701 * should it turn out to not be sufficient */
703 if (endswith(name, "Timestamp")) {
704 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
706 t = format_timestamp(timestamp, sizeof(timestamp), u);
708 printf("%s=%s\n", name, strempty(t));
710 } else if (strstr(name, "USec")) {
711 char timespan[FORMAT_TIMESPAN_MAX];
713 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
715 printf("%s=%llu\n", name, (unsigned long long) u);
720 case SD_BUS_TYPE_INT64: {
723 r = sd_bus_message_read_basic(property, type, &i);
727 printf("%s=%lld\n", name, (long long) i);
732 case SD_BUS_TYPE_UINT32: {
735 r = sd_bus_message_read_basic(property, type, &u);
739 if (strstr(name, "UMask") || strstr(name, "Mode"))
740 printf("%s=%04o\n", name, u);
742 printf("%s=%u\n", name, (unsigned) u);
747 case SD_BUS_TYPE_INT32: {
750 r = sd_bus_message_read_basic(property, type, &i);
754 printf("%s=%i\n", name, (int) i);
758 case SD_BUS_TYPE_DOUBLE: {
761 r = sd_bus_message_read_basic(property, type, &d);
765 printf("%s=%g\n", name, d);
769 case SD_BUS_TYPE_ARRAY:
770 if (streq(contents, "s")) {
774 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
778 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
779 _cleanup_free_ char *escaped = NULL;
784 escaped = xescape(str, "\n ");
788 printf("%s%s", first ? "" : " ", escaped);
800 r = sd_bus_message_exit_container(property);
806 } else if (streq(contents, "y")) {
810 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
819 for (i = 0; i < n; i++)
820 printf("%02x", u[i]);
827 } else if (streq(contents, "u")) {
831 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
840 for (i = 0; i < n; i++)
841 printf("%08x", u[i]);
855 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
856 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
857 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
863 r = sd_bus_call_method(bus,
866 "org.freedesktop.DBus.Properties",
874 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
878 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
880 const char *contents;
882 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
886 if (!filter || strv_find(filter, name)) {
887 r = sd_bus_message_peek_type(reply, NULL, &contents);
891 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
895 r = bus_print_property(name, reply, all);
900 printf("%s=[unprintable]\n", name);
901 /* skip what we didn't read */
902 r = sd_bus_message_skip(reply, contents);
907 r = sd_bus_message_exit_container(reply);
911 r = sd_bus_message_skip(reply, "v");
916 r = sd_bus_message_exit_container(reply);
923 r = sd_bus_message_exit_container(reply);
930 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
931 sd_id128_t *p = userdata;
936 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
943 memcpy((*p).bytes, v, n);
950 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
954 r = sd_bus_message_peek_type(m, &type, NULL);
959 case SD_BUS_TYPE_STRING: {
963 r = sd_bus_message_read_basic(m, type, &s);
970 r = free_and_strdup(p, s);
974 case SD_BUS_TYPE_ARRAY: {
975 _cleanup_strv_free_ char **l = NULL;
976 char ***p = userdata;
978 r = bus_message_read_strv_extend(m, &l);
989 case SD_BUS_TYPE_BOOLEAN: {
993 r = sd_bus_message_read_basic(m, type, &b);
1002 case SD_BUS_TYPE_UINT32: {
1004 uint32_t *p = userdata;
1006 r = sd_bus_message_read_basic(m, type, &u);
1015 case SD_BUS_TYPE_UINT64: {
1017 uint64_t *p = userdata;
1019 r = sd_bus_message_read_basic(m, type, &t);
1035 int bus_message_map_all_properties(sd_bus *bus,
1037 const struct bus_properties_map *map,
1039 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1046 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1050 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1051 const struct bus_properties_map *prop;
1053 const char *contents;
1057 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1061 for (i = 0, prop = NULL; map[i].member; i++)
1062 if (streq(map[i].member, member)) {
1068 r = sd_bus_message_peek_type(m, NULL, &contents);
1072 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1076 v = (uint8_t *)userdata + prop->offset;
1078 r = prop->set(bus, member, m, &error, v);
1080 r = map_basic(bus, member, m, &error, v);
1084 r = sd_bus_message_exit_container(m);
1088 r = sd_bus_message_skip(m, "v");
1093 r = sd_bus_message_exit_container(m);
1098 return sd_bus_message_exit_container(m);
1101 int bus_message_map_properties_changed(sd_bus *bus,
1103 const struct bus_properties_map *map,
1106 int r, invalidated, i;
1112 r = bus_message_map_all_properties(bus, m, map, userdata);
1116 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1121 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1122 for (i = 0; map[i].member; i++)
1123 if (streq(map[i].member, member)) {
1128 r = sd_bus_message_exit_container(m);
1135 int bus_map_all_properties(sd_bus *bus,
1136 const char *destination,
1138 const struct bus_properties_map *map,
1140 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1141 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1145 assert(destination);
1149 r = sd_bus_call_method(
1153 "org.freedesktop.DBus.Properties",
1161 return bus_message_map_all_properties(bus, m, map, userdata);
1164 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1167 assert(transport >= 0);
1168 assert(transport < _BUS_TRANSPORT_MAX);
1171 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1172 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1174 switch (transport) {
1176 case BUS_TRANSPORT_LOCAL:
1178 r = sd_bus_default_user(bus);
1180 r = sd_bus_default_system(bus);
1184 case BUS_TRANSPORT_REMOTE:
1185 r = sd_bus_open_system_remote(bus, host);
1188 case BUS_TRANSPORT_MACHINE:
1189 r = sd_bus_open_system_machine(bus, host);
1193 assert_not_reached("Hmm, unknown transport type.");
1199 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1202 assert(transport >= 0);
1203 assert(transport < _BUS_TRANSPORT_MAX);
1206 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1207 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1209 switch (transport) {
1211 case BUS_TRANSPORT_LOCAL:
1213 r = bus_open_user_systemd(bus);
1215 r = bus_open_system_systemd(bus);
1219 case BUS_TRANSPORT_REMOTE:
1220 r = sd_bus_open_system_remote(bus, host);
1223 case BUS_TRANSPORT_MACHINE:
1224 r = sd_bus_open_system_machine(bus, host);
1228 assert_not_reached("Hmm, unknown transport type.");
1234 int bus_property_get_bool(
1237 const char *interface,
1238 const char *property,
1239 sd_bus_message *reply,
1241 sd_bus_error *error) {
1243 int b = *(bool*) userdata;
1245 return sd_bus_message_append_basic(reply, 'b', &b);
1248 #if __SIZEOF_SIZE_T__ != 8
1249 int bus_property_get_size(
1252 const char *interface,
1253 const char *property,
1254 sd_bus_message *reply,
1256 sd_bus_error *error) {
1258 uint64_t sz = *(size_t*) userdata;
1260 return sd_bus_message_append_basic(reply, 't', &sz);
1264 #if __SIZEOF_LONG__ != 8
1265 int bus_property_get_long(
1268 const char *interface,
1269 const char *property,
1270 sd_bus_message *reply,
1272 sd_bus_error *error) {
1274 int64_t l = *(long*) userdata;
1276 return sd_bus_message_append_basic(reply, 'x', &l);
1279 int bus_property_get_ulong(
1282 const char *interface,
1283 const char *property,
1284 sd_bus_message *reply,
1286 sd_bus_error *error) {
1288 uint64_t ul = *(unsigned long*) userdata;
1290 return sd_bus_message_append_basic(reply, 't', &ul);
1294 int bus_log_parse_error(int r) {
1295 return log_error_errno(r, "Failed to parse bus message: %m");
1298 int bus_log_create_error(int r) {
1299 return log_error_errno(r, "Failed to create bus message: %m");
1302 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1308 return sd_bus_message_read(
1323 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1327 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1328 sd_bus_reply_method_errno(m, r, error);
1330 } else if (sd_bus_error_is_set(error)) {
1331 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1332 sd_bus_reply_method_error(m, error);
1336 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1337 bus_message_type_to_string(m->header->type),
1340 strna(m->interface),
1342 strna(m->root_container.signature),
1343 bus_error_message(error, r));
1348 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1349 const char *eq, *field;
1355 eq = strchr(assignment, '=');
1357 log_error("Not an assignment: %s", assignment);
1361 field = strndupa(assignment, eq - assignment);
1364 if (streq(field, "CPUQuota")) {
1368 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1370 return bus_log_create_error(r);
1372 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1374 } else if (endswith(eq, "%")) {
1377 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1378 log_error("CPU quota '%s' invalid.", eq);
1382 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1384 return bus_log_create_error(r);
1386 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1388 log_error("CPU quota needs to be in percent.");
1393 return bus_log_create_error(r);
1398 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1400 return bus_log_create_error(r);
1402 if (STR_IN_SET(field,
1403 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1404 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
1406 r = parse_boolean(eq);
1408 log_error("Failed to parse boolean assignment %s.", assignment);
1412 r = sd_bus_message_append(m, "v", "b", r);
1414 } else if (streq(field, "MemoryLimit")) {
1417 r = parse_size(eq, 1024, &bytes);
1419 log_error("Failed to parse bytes specification %s", assignment);
1423 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1425 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1428 r = safe_atou64(eq, &u);
1430 log_error("Failed to parse %s value %s.", field, eq);
1434 r = sd_bus_message_append(m, "v", "t", u);
1436 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1437 r = sd_bus_message_append(m, "v", "s", eq);
1439 else if (streq(field, "DeviceAllow")) {
1442 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1444 const char *path, *rwm, *e;
1446 e = strchr(eq, ' ');
1448 path = strndupa(eq, e - eq);
1455 if (!path_startswith(path, "/dev")) {
1456 log_error("%s is not a device file in /dev.", path);
1460 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1463 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1466 r = sd_bus_message_append(m, "v", "a(st)", 0);
1468 const char *path, *bandwidth, *e;
1471 e = strchr(eq, ' ');
1473 path = strndupa(eq, e - eq);
1476 log_error("Failed to parse %s value %s.", field, eq);
1480 if (!path_startswith(path, "/dev")) {
1481 log_error("%s is not a device file in /dev.", path);
1485 r = parse_size(bandwidth, 1000, &bytes);
1487 log_error("Failed to parse byte value %s.", bandwidth);
1491 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1494 } else if (streq(field, "BlockIODeviceWeight")) {
1497 r = sd_bus_message_append(m, "v", "a(st)", 0);
1499 const char *path, *weight, *e;
1502 e = strchr(eq, ' ');
1504 path = strndupa(eq, e - eq);
1507 log_error("Failed to parse %s value %s.", field, eq);
1511 if (!path_startswith(path, "/dev")) {
1512 log_error("%s is not a device file in /dev.", path);
1516 r = safe_atou64(weight, &u);
1518 log_error("Failed to parse %s value %s.", field, weight);
1521 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1524 } else if (rlimit_from_string(field) >= 0) {
1527 if (streq(eq, "infinity"))
1530 r = safe_atou64(eq, &rl);
1532 log_error("Invalid resource limit: %s", eq);
1537 r = sd_bus_message_append(m, "v", "t", rl);
1539 } else if (streq(field, "Nice")) {
1542 r = safe_atoi32(eq, &i);
1544 log_error("Failed to parse %s value %s.", field, eq);
1548 r = sd_bus_message_append(m, "v", "i", i);
1550 } else if (streq(field, "Environment")) {
1552 r = sd_bus_message_append(m, "v", "as", 1, eq);
1554 } else if (streq(field, "KillSignal")) {
1557 sig = signal_from_string_try_harder(eq);
1559 log_error("Failed to parse %s value %s.", field, eq);
1563 r = sd_bus_message_append(m, "v", "i", sig);
1565 } else if (streq(field, "AccuracySec")) {
1568 r = parse_sec(eq, &u);
1570 log_error("Failed to parse %s value %s", field, eq);
1574 r = sd_bus_message_append(m, "v", "t", u);
1577 log_error("Unknown assignment %s.", assignment);
1582 return bus_log_create_error(r);
1587 typedef struct BusWaitForJobs {
1594 sd_bus_slot *slot_job_removed;
1595 sd_bus_slot *slot_disconnected;
1598 static int match_disconnected(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1602 log_error("Warning! D-Bus connection terminated.");
1608 static int match_job_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1609 const char *path, *unit, *result;
1610 BusWaitForJobs *d = userdata;
1619 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1621 bus_log_parse_error(r);
1625 found = set_remove(d->jobs, (char*) path);
1631 if (!isempty(result))
1632 d->result = strdup(result);
1635 d->name = strdup(unit);
1640 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1644 set_free_free(d->jobs);
1646 sd_bus_slot_unref(d->slot_disconnected);
1647 sd_bus_slot_unref(d->slot_job_removed);
1649 sd_bus_unref(d->bus);
1657 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1658 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1664 d = new0(BusWaitForJobs, 1);
1668 d->bus = sd_bus_ref(bus);
1670 /* When we are a bus client we match by sender. Direct
1671 * connections OTOH have no initialized sender field, and
1672 * hence we ignore the sender then */
1673 r = sd_bus_add_match(
1675 &d->slot_job_removed,
1678 "sender='org.freedesktop.systemd1',"
1679 "interface='org.freedesktop.systemd1.Manager',"
1680 "member='JobRemoved',"
1681 "path='/org/freedesktop/systemd1'" :
1683 "interface='org.freedesktop.systemd1.Manager',"
1684 "member='JobRemoved',"
1685 "path='/org/freedesktop/systemd1'",
1686 match_job_removed, d);
1690 r = sd_bus_add_match(
1692 &d->slot_disconnected,
1694 "sender='org.freedesktop.DBus.Local',"
1695 "interface='org.freedesktop.DBus.Local',"
1696 "member='Disconnected'",
1697 match_disconnected, d);
1707 static int bus_process_wait(sd_bus *bus) {
1711 r = sd_bus_process(bus, NULL);
1717 r = sd_bus_wait(bus, (uint64_t) -1);
1723 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1729 if (streq(d->result, "canceled"))
1730 log_error("Job for %s canceled.", strna(d->name));
1731 else if (streq(d->result, "timeout"))
1732 log_error("Job for %s timed out.", strna(d->name));
1733 else if (streq(d->result, "dependency"))
1734 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1735 else if (streq(d->result, "invalid"))
1736 log_error("Job for %s invalid.", strna(d->name));
1737 else if (streq(d->result, "assert"))
1738 log_error("Assertion failed on job for %s.", strna(d->name));
1739 else if (streq(d->result, "unsupported"))
1740 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1741 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1742 _cleanup_free_ char *quoted = NULL;
1745 quoted = shell_maybe_quote(d->name);
1748 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xe' for details.", d->name, quoted);
1750 log_error("Job failed. See 'journalctl -xe' for details.");
1754 if (streq(d->result, "canceled"))
1756 else if (streq(d->result, "timeout"))
1758 else if (streq(d->result, "dependency"))
1760 else if (streq(d->result, "invalid"))
1762 else if (streq(d->result, "assert"))
1764 else if (streq(d->result, "unsupported"))
1766 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1772 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1777 while (!set_isempty(d->jobs)) {
1780 q = bus_process_wait(d->bus);
1782 return log_error_errno(q, "Failed to wait for response: %m");
1785 q = check_wait_response(d, quiet);
1786 /* Return the first error as it is most likely to be
1788 if (q < 0 && r == 0)
1791 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1804 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1809 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1813 return set_put_strdup(d->jobs, path);
1816 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
1817 const char *type, *path, *source;
1820 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1822 return bus_log_parse_error(r);
1824 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1826 if (streq(type, "symlink"))
1827 log_info("Created symlink from %s to %s.", path, source);
1829 log_info("Removed symlink %s.", path);
1833 return bus_log_parse_error(r);
1835 r = sd_bus_message_exit_container(m);
1837 return bus_log_parse_error(r);