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;
214 int bus_verify_polkit(
215 sd_bus_message *call,
228 r = check_good_user(call, good_user);
232 r = sd_bus_query_sender_privilege(call, capability);
239 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
240 int authorized = false, challenge = false, c;
243 sender = sd_bus_message_get_sender(call);
247 c = sd_bus_message_get_allow_interactive_authorization(call);
253 r = sd_bus_call_method(
255 "org.freedesktop.PolicyKit1",
256 "/org/freedesktop/PolicyKit1/Authority",
257 "org.freedesktop.PolicyKit1.Authority",
258 "CheckAuthorization",
262 "system-bus-name", 1, "name", "s", sender,
269 /* Treat no PK available as access denied */
270 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
271 sd_bus_error_free(e);
278 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
282 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
290 *_challenge = challenge;
301 typedef struct AsyncPolkitQuery {
302 sd_bus_message *request, *reply;
303 sd_bus_message_handler_t callback;
309 static void async_polkit_query_free(AsyncPolkitQuery *q) {
314 sd_bus_slot_unref(q->slot);
316 if (q->registry && q->request)
317 hashmap_remove(q->registry, q->request);
319 sd_bus_message_unref(q->request);
320 sd_bus_message_unref(q->reply);
325 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
326 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
327 AsyncPolkitQuery *q = userdata;
334 q->slot = sd_bus_slot_unref(q->slot);
335 q->reply = sd_bus_message_ref(reply);
337 r = sd_bus_message_rewind(q->request, true);
339 r = sd_bus_reply_method_errno(q->request, r, NULL);
343 r = q->callback(bus, q->request, q->userdata, &error_buffer);
344 r = bus_maybe_reply_error(q->request, r, &error_buffer);
347 async_polkit_query_free(q);
354 int bus_verify_polkit_async(
355 sd_bus_message *call,
361 sd_bus_error *error) {
364 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
367 sd_bus_message_handler_t callback;
377 r = check_good_user(call, good_user);
382 q = hashmap_get(*registry, call);
384 int authorized, challenge;
386 /* This is the second invocation of this function, and
387 * there's already a response from polkit, let's
391 if (sd_bus_message_is_method_error(q->reply, NULL)) {
392 const sd_bus_error *e;
394 /* Copy error from polkit reply */
395 e = sd_bus_message_get_error(q->reply);
396 sd_bus_error_copy(error, e);
398 /* Treat no PK available as access denied */
399 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
402 return -sd_bus_error_get_errno(e);
405 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
407 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
416 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
422 r = sd_bus_query_sender_privilege(call, capability);
429 if (sd_bus_get_current_message(call->bus) != call)
432 callback = sd_bus_get_current_handler(call->bus);
436 userdata = sd_bus_get_current_userdata(call->bus);
438 sender = sd_bus_message_get_sender(call);
442 c = sd_bus_message_get_allow_interactive_authorization(call);
448 r = hashmap_ensure_allocated(registry, NULL);
452 r = sd_bus_message_new_method_call(
455 "org.freedesktop.PolicyKit1",
456 "/org/freedesktop/PolicyKit1/Authority",
457 "org.freedesktop.PolicyKit1.Authority",
458 "CheckAuthorization");
462 r = sd_bus_message_append(
465 "system-bus-name", 1, "name", "s", sender,
473 q = new0(AsyncPolkitQuery, 1);
477 q->request = sd_bus_message_ref(call);
478 q->callback = callback;
479 q->userdata = userdata;
481 r = hashmap_put(*registry, call, q);
483 async_polkit_query_free(q);
487 q->registry = *registry;
489 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
491 async_polkit_query_free(q);
501 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
505 while ((q = hashmap_steal_first(registry)))
506 async_polkit_query_free(q);
508 hashmap_free(registry);
512 int bus_check_peercred(sd_bus *c) {
519 fd = sd_bus_get_fd(c);
523 l = sizeof(struct ucred);
524 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
527 if (l != sizeof(struct ucred))
530 if (ucred.uid != 0 && ucred.uid != geteuid())
536 int bus_open_system_systemd(sd_bus **_bus) {
537 _cleanup_bus_unref_ sd_bus *bus = NULL;
543 return sd_bus_open_system(_bus);
545 /* If we are root and kdbus is not available, then let's talk
546 * directly to the system instance, instead of going via the
550 r = sd_bus_new(&bus);
554 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
558 bus->bus_client = true;
560 r = sd_bus_start(bus);
567 bus = sd_bus_unref(bus);
570 r = sd_bus_new(&bus);
574 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
578 r = sd_bus_start(bus);
580 return sd_bus_open_system(_bus);
582 r = bus_check_peercred(bus);
592 int bus_open_user_systemd(sd_bus **_bus) {
593 _cleanup_bus_unref_ sd_bus *bus = NULL;
594 _cleanup_free_ char *ee = NULL;
598 /* Try via kdbus first, and then directly */
603 r = sd_bus_new(&bus);
607 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
610 bus->bus_client = true;
612 r = sd_bus_start(bus);
619 bus = sd_bus_unref(bus);
622 e = secure_getenv("XDG_RUNTIME_DIR");
624 return sd_bus_open_user(_bus);
626 ee = bus_address_escape(e);
630 r = sd_bus_new(&bus);
634 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
638 r = sd_bus_start(bus);
640 return sd_bus_open_user(_bus);
642 r = bus_check_peercred(bus);
652 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
654 const char *contents;
660 r = sd_bus_message_peek_type(property, &type, &contents);
666 case SD_BUS_TYPE_STRING: {
669 r = sd_bus_message_read_basic(property, type, &s);
673 if (all || !isempty(s)) {
674 _cleanup_free_ char *escaped = NULL;
676 escaped = xescape(s, "\n");
680 printf("%s=%s\n", name, escaped);
686 case SD_BUS_TYPE_BOOLEAN: {
689 r = sd_bus_message_read_basic(property, type, &b);
693 printf("%s=%s\n", name, yes_no(b));
698 case SD_BUS_TYPE_UINT64: {
701 r = sd_bus_message_read_basic(property, type, &u);
705 /* Yes, heuristics! But we can change this check
706 * should it turn out to not be sufficient */
708 if (endswith(name, "Timestamp")) {
709 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
711 t = format_timestamp(timestamp, sizeof(timestamp), u);
713 printf("%s=%s\n", name, strempty(t));
715 } else if (strstr(name, "USec")) {
716 char timespan[FORMAT_TIMESPAN_MAX];
718 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
720 printf("%s=%llu\n", name, (unsigned long long) u);
725 case SD_BUS_TYPE_INT64: {
728 r = sd_bus_message_read_basic(property, type, &i);
732 printf("%s=%lld\n", name, (long long) i);
737 case SD_BUS_TYPE_UINT32: {
740 r = sd_bus_message_read_basic(property, type, &u);
744 if (strstr(name, "UMask") || strstr(name, "Mode"))
745 printf("%s=%04o\n", name, u);
747 printf("%s=%u\n", name, (unsigned) u);
752 case SD_BUS_TYPE_INT32: {
755 r = sd_bus_message_read_basic(property, type, &i);
759 printf("%s=%i\n", name, (int) i);
763 case SD_BUS_TYPE_DOUBLE: {
766 r = sd_bus_message_read_basic(property, type, &d);
770 printf("%s=%g\n", name, d);
774 case SD_BUS_TYPE_ARRAY:
775 if (streq(contents, "s")) {
779 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
783 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
784 _cleanup_free_ char *escaped = NULL;
789 escaped = xescape(str, "\n ");
793 printf("%s%s", first ? "" : " ", escaped);
805 r = sd_bus_message_exit_container(property);
811 } else if (streq(contents, "y")) {
815 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
824 for (i = 0; i < n; i++)
825 printf("%02x", u[i]);
832 } else if (streq(contents, "u")) {
836 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
845 for (i = 0; i < n; i++)
846 printf("%08x", u[i]);
860 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
861 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
862 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
868 r = sd_bus_call_method(bus,
871 "org.freedesktop.DBus.Properties",
879 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
883 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
885 const char *contents;
887 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
891 if (!filter || strv_find(filter, name)) {
892 r = sd_bus_message_peek_type(reply, NULL, &contents);
896 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
900 r = bus_print_property(name, reply, all);
905 printf("%s=[unprintable]\n", name);
906 /* skip what we didn't read */
907 r = sd_bus_message_skip(reply, contents);
912 r = sd_bus_message_exit_container(reply);
916 r = sd_bus_message_skip(reply, "v");
921 r = sd_bus_message_exit_container(reply);
928 r = sd_bus_message_exit_container(reply);
935 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
936 sd_id128_t *p = userdata;
941 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
948 memcpy((*p).bytes, v, n);
955 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
959 r = sd_bus_message_peek_type(m, &type, NULL);
964 case SD_BUS_TYPE_STRING: {
969 r = sd_bus_message_read_basic(m, type, &s);
987 case SD_BUS_TYPE_ARRAY: {
988 _cleanup_strv_free_ char **l = NULL;
989 char ***p = userdata;
991 r = bus_message_read_strv_extend(m, &l);
1002 case SD_BUS_TYPE_BOOLEAN: {
1006 r = sd_bus_message_read_basic(m, type, &b);
1015 case SD_BUS_TYPE_UINT32: {
1017 uint32_t *p = userdata;
1019 r = sd_bus_message_read_basic(m, type, &u);
1028 case SD_BUS_TYPE_UINT64: {
1030 uint64_t *p = userdata;
1032 r = sd_bus_message_read_basic(m, type, &t);
1048 int bus_message_map_all_properties(sd_bus *bus,
1050 const struct bus_properties_map *map,
1052 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1059 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1063 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1064 const struct bus_properties_map *prop;
1066 const char *contents;
1070 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1074 for (i = 0, prop = NULL; map[i].member; i++)
1075 if (streq(map[i].member, member)) {
1081 r = sd_bus_message_peek_type(m, NULL, &contents);
1085 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1089 v = (uint8_t *)userdata + prop->offset;
1091 r = prop->set(bus, member, m, &error, v);
1093 r = map_basic(bus, member, m, &error, v);
1097 r = sd_bus_message_exit_container(m);
1101 r = sd_bus_message_skip(m, "v");
1106 r = sd_bus_message_exit_container(m);
1111 return sd_bus_message_exit_container(m);
1114 int bus_message_map_properties_changed(sd_bus *bus,
1116 const struct bus_properties_map *map,
1119 int r, invalidated, i;
1125 r = bus_message_map_all_properties(bus, m, map, userdata);
1129 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1134 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1135 for (i = 0; map[i].member; i++)
1136 if (streq(map[i].member, member)) {
1141 r = sd_bus_message_exit_container(m);
1148 int bus_map_all_properties(sd_bus *bus,
1149 const char *destination,
1151 const struct bus_properties_map *map,
1153 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1154 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1158 assert(destination);
1162 r = sd_bus_call_method(
1166 "org.freedesktop.DBus.Properties",
1174 return bus_message_map_all_properties(bus, m, map, userdata);
1177 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1180 assert(transport >= 0);
1181 assert(transport < _BUS_TRANSPORT_MAX);
1184 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1185 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1187 switch (transport) {
1189 case BUS_TRANSPORT_LOCAL:
1191 r = sd_bus_default_user(bus);
1193 r = sd_bus_default_system(bus);
1197 case BUS_TRANSPORT_REMOTE:
1198 r = sd_bus_open_system_remote(bus, host);
1201 case BUS_TRANSPORT_MACHINE:
1202 r = sd_bus_open_system_machine(bus, host);
1206 assert_not_reached("Hmm, unknown transport type.");
1212 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1215 assert(transport >= 0);
1216 assert(transport < _BUS_TRANSPORT_MAX);
1219 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1220 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1222 switch (transport) {
1224 case BUS_TRANSPORT_LOCAL:
1226 r = bus_open_user_systemd(bus);
1228 r = bus_open_system_systemd(bus);
1232 case BUS_TRANSPORT_REMOTE:
1233 r = sd_bus_open_system_remote(bus, host);
1236 case BUS_TRANSPORT_MACHINE:
1237 r = sd_bus_open_system_machine(bus, host);
1241 assert_not_reached("Hmm, unknown transport type.");
1247 int bus_property_get_bool(
1250 const char *interface,
1251 const char *property,
1252 sd_bus_message *reply,
1254 sd_bus_error *error) {
1256 int b = *(bool*) userdata;
1258 return sd_bus_message_append_basic(reply, 'b', &b);
1261 #if __SIZEOF_SIZE_T__ != 8
1262 int bus_property_get_size(
1265 const char *interface,
1266 const char *property,
1267 sd_bus_message *reply,
1269 sd_bus_error *error) {
1271 uint64_t sz = *(size_t*) userdata;
1273 return sd_bus_message_append_basic(reply, 't', &sz);
1277 #if __SIZEOF_LONG__ != 8
1278 int bus_property_get_long(
1281 const char *interface,
1282 const char *property,
1283 sd_bus_message *reply,
1285 sd_bus_error *error) {
1287 int64_t l = *(long*) userdata;
1289 return sd_bus_message_append_basic(reply, 'x', &l);
1292 int bus_property_get_ulong(
1295 const char *interface,
1296 const char *property,
1297 sd_bus_message *reply,
1299 sd_bus_error *error) {
1301 uint64_t ul = *(unsigned long*) userdata;
1303 return sd_bus_message_append_basic(reply, 't', &ul);
1307 int bus_log_parse_error(int r) {
1308 return log_error_errno(r, "Failed to parse bus message: %m");
1311 int bus_log_create_error(int r) {
1312 return log_error_errno(r, "Failed to create bus message: %m");
1315 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1321 return sd_bus_message_read(
1336 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1340 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1341 sd_bus_reply_method_errno(m, r, error);
1343 } else if (sd_bus_error_is_set(error)) {
1344 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1345 sd_bus_reply_method_error(m, error);
1349 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1350 bus_message_type_to_string(m->header->type),
1353 strna(m->interface),
1355 strna(m->root_container.signature),
1356 bus_error_message(error, r));
1361 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1362 const char *eq, *field;
1368 eq = strchr(assignment, '=');
1370 log_error("Not an assignment: %s", assignment);
1374 field = strndupa(assignment, eq - assignment);
1377 if (streq(field, "CPUQuota")) {
1381 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1383 return bus_log_create_error(r);
1385 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1387 } else if (endswith(eq, "%")) {
1390 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1391 log_error("CPU quota '%s' invalid.", eq);
1395 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1397 return bus_log_create_error(r);
1399 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1401 log_error("CPU quota needs to be in percent.");
1406 return bus_log_create_error(r);
1411 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1413 return bus_log_create_error(r);
1415 if (STR_IN_SET(field,
1416 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1417 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
1419 r = parse_boolean(eq);
1421 log_error("Failed to parse boolean assignment %s.", assignment);
1425 r = sd_bus_message_append(m, "v", "b", r);
1427 } else if (streq(field, "MemoryLimit")) {
1430 r = parse_size(eq, 1024, &bytes);
1432 log_error("Failed to parse bytes specification %s", assignment);
1436 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1438 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1441 r = safe_atou64(eq, &u);
1443 log_error("Failed to parse %s value %s.", field, eq);
1447 r = sd_bus_message_append(m, "v", "t", u);
1449 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1450 r = sd_bus_message_append(m, "v", "s", eq);
1452 else if (streq(field, "DeviceAllow")) {
1455 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1457 const char *path, *rwm, *e;
1459 e = strchr(eq, ' ');
1461 path = strndupa(eq, e - eq);
1468 if (!path_startswith(path, "/dev")) {
1469 log_error("%s is not a device file in /dev.", path);
1473 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1476 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1479 r = sd_bus_message_append(m, "v", "a(st)", 0);
1481 const char *path, *bandwidth, *e;
1484 e = strchr(eq, ' ');
1486 path = strndupa(eq, e - eq);
1489 log_error("Failed to parse %s value %s.", field, eq);
1493 if (!path_startswith(path, "/dev")) {
1494 log_error("%s is not a device file in /dev.", path);
1498 r = parse_size(bandwidth, 1000, &bytes);
1500 log_error("Failed to parse byte value %s.", bandwidth);
1504 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1507 } else if (streq(field, "BlockIODeviceWeight")) {
1510 r = sd_bus_message_append(m, "v", "a(st)", 0);
1512 const char *path, *weight, *e;
1515 e = strchr(eq, ' ');
1517 path = strndupa(eq, e - eq);
1520 log_error("Failed to parse %s value %s.", field, eq);
1524 if (!path_startswith(path, "/dev")) {
1525 log_error("%s is not a device file in /dev.", path);
1529 r = safe_atou64(weight, &u);
1531 log_error("Failed to parse %s value %s.", field, weight);
1534 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1537 } else if (rlimit_from_string(field) >= 0) {
1540 if (streq(eq, "infinity"))
1543 r = safe_atou64(eq, &rl);
1545 log_error("Invalid resource limit: %s", eq);
1550 r = sd_bus_message_append(m, "v", "t", rl);
1552 } else if (streq(field, "Nice")) {
1555 r = safe_atoi32(eq, &i);
1557 log_error("Failed to parse %s value %s.", field, eq);
1561 r = sd_bus_message_append(m, "v", "i", i);
1563 } else if (streq(field, "Environment")) {
1565 r = sd_bus_message_append(m, "v", "as", 1, eq);
1567 } else if (streq(field, "KillSignal")) {
1570 sig = signal_from_string_try_harder(eq);
1572 log_error("Failed to parse %s value %s.", field, eq);
1576 r = sd_bus_message_append(m, "v", "i", sig);
1578 } else if (streq(field, "AccuracySec")) {
1581 r = parse_sec(eq, &u);
1583 log_error("Failed to parse %s value %s", field, eq);
1587 r = sd_bus_message_append(m, "v", "t", u);
1590 log_error("Unknown assignment %s.", assignment);
1595 return bus_log_create_error(r);
1600 typedef struct BusWaitForJobs {
1607 sd_bus_slot *slot_job_removed;
1608 sd_bus_slot *slot_disconnected;
1611 static int match_disconnected(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1615 log_error("Warning! D-Bus connection terminated.");
1621 static int match_job_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1622 const char *path, *unit, *result;
1623 BusWaitForJobs *d = userdata;
1632 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1634 bus_log_parse_error(r);
1638 found = set_remove(d->jobs, (char*) path);
1644 if (!isempty(result))
1645 d->result = strdup(result);
1648 d->name = strdup(unit);
1653 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1657 set_free_free(d->jobs);
1659 sd_bus_slot_unref(d->slot_disconnected);
1660 sd_bus_slot_unref(d->slot_job_removed);
1662 sd_bus_unref(d->bus);
1670 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1671 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1677 d = new0(BusWaitForJobs, 1);
1681 d->bus = sd_bus_ref(bus);
1683 /* When we are a bus client we match by sender. Direct
1684 * connections OTOH have no initialized sender field, and
1685 * hence we ignore the sender then */
1686 r = sd_bus_add_match(
1688 &d->slot_job_removed,
1691 "sender='org.freedesktop.systemd1',"
1692 "interface='org.freedesktop.systemd1.Manager',"
1693 "member='JobRemoved',"
1694 "path='/org/freedesktop/systemd1'" :
1696 "interface='org.freedesktop.systemd1.Manager',"
1697 "member='JobRemoved',"
1698 "path='/org/freedesktop/systemd1'",
1699 match_job_removed, d);
1703 r = sd_bus_add_match(
1705 &d->slot_disconnected,
1707 "sender='org.freedesktop.DBus.Local',"
1708 "interface='org.freedesktop.DBus.Local',"
1709 "member='Disconnected'",
1710 match_disconnected, d);
1720 static int bus_process_wait(sd_bus *bus) {
1724 r = sd_bus_process(bus, NULL);
1730 r = sd_bus_wait(bus, (uint64_t) -1);
1736 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1742 if (streq(d->result, "canceled"))
1743 log_error("Job for %s canceled.", strna(d->name));
1744 else if (streq(d->result, "timeout"))
1745 log_error("Job for %s timed out.", strna(d->name));
1746 else if (streq(d->result, "dependency"))
1747 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1748 else if (streq(d->result, "invalid"))
1749 log_error("Job for %s invalid.", strna(d->name));
1750 else if (streq(d->result, "assert"))
1751 log_error("Assertion failed on job for %s.", strna(d->name));
1752 else if (streq(d->result, "unsupported"))
1753 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1754 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1758 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
1760 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
1762 quotes ? "'" : "", d->name, quotes ? "'" : "");
1764 log_error("Job failed. See \"journalctl -xe\" for details.");
1768 if (streq(d->result, "canceled"))
1770 else if (streq(d->result, "timeout"))
1772 else if (streq(d->result, "dependency"))
1774 else if (streq(d->result, "invalid"))
1776 else if (streq(d->result, "assert"))
1778 else if (streq(d->result, "unsupported"))
1780 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1786 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1791 while (!set_isempty(d->jobs)) {
1794 q = bus_process_wait(d->bus);
1796 return log_error_errno(q, "Failed to wait for response: %m");
1799 q = check_wait_response(d, quiet);
1800 /* Return the first error as it is most likely to be
1802 if (q < 0 && r == 0)
1805 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1818 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1823 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1827 return set_put_strdup(d->jobs, path);
1830 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
1831 const char *type, *path, *source;
1834 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1836 return bus_log_parse_error(r);
1838 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1840 if (streq(type, "symlink"))
1841 log_info("Created symlink from %s to %s.", path, source);
1843 log_info("Removed symlink %s.", path);
1847 return bus_log_parse_error(r);
1849 r = sd_bus_message_exit_container(m);
1851 return bus_log_parse_error(r);