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_UINT32: {
728 r = sd_bus_message_read_basic(property, type, &u);
732 if (strstr(name, "UMask") || strstr(name, "Mode"))
733 printf("%s=%04o\n", name, u);
735 printf("%s=%u\n", name, (unsigned) u);
740 case SD_BUS_TYPE_INT32: {
743 r = sd_bus_message_read_basic(property, type, &i);
747 printf("%s=%i\n", name, (int) i);
751 case SD_BUS_TYPE_DOUBLE: {
754 r = sd_bus_message_read_basic(property, type, &d);
758 printf("%s=%g\n", name, d);
762 case SD_BUS_TYPE_ARRAY:
763 if (streq(contents, "s")) {
767 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
771 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
772 _cleanup_free_ char *escaped = NULL;
777 escaped = xescape(str, "\n ");
781 printf("%s%s", first ? "" : " ", escaped);
793 r = sd_bus_message_exit_container(property);
799 } else if (streq(contents, "y")) {
803 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
812 for (i = 0; i < n; i++)
813 printf("%02x", u[i]);
820 } else if (streq(contents, "u")) {
824 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
833 for (i = 0; i < n; i++)
834 printf("%08x", u[i]);
848 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
849 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
850 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
856 r = sd_bus_call_method(bus,
859 "org.freedesktop.DBus.Properties",
867 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
871 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
873 const char *contents;
875 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
879 if (!filter || strv_find(filter, name)) {
880 r = sd_bus_message_peek_type(reply, NULL, &contents);
884 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
888 r = bus_print_property(name, reply, all);
893 printf("%s=[unprintable]\n", name);
894 /* skip what we didn't read */
895 r = sd_bus_message_skip(reply, contents);
900 r = sd_bus_message_exit_container(reply);
904 r = sd_bus_message_skip(reply, "v");
909 r = sd_bus_message_exit_container(reply);
916 r = sd_bus_message_exit_container(reply);
923 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
924 sd_id128_t *p = userdata;
929 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
936 memcpy((*p).bytes, v, n);
943 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
947 r = sd_bus_message_peek_type(m, &type, NULL);
952 case SD_BUS_TYPE_STRING: {
957 r = sd_bus_message_read_basic(m, type, &s);
975 case SD_BUS_TYPE_ARRAY: {
976 _cleanup_strv_free_ char **l = NULL;
977 char ***p = userdata;
979 r = bus_message_read_strv_extend(m, &l);
990 case SD_BUS_TYPE_BOOLEAN: {
994 r = sd_bus_message_read_basic(m, type, &b);
1003 case SD_BUS_TYPE_UINT32: {
1005 uint32_t *p = userdata;
1007 r = sd_bus_message_read_basic(m, type, &u);
1016 case SD_BUS_TYPE_UINT64: {
1018 uint64_t *p = userdata;
1020 r = sd_bus_message_read_basic(m, type, &t);
1036 int bus_message_map_all_properties(sd_bus *bus,
1038 const struct bus_properties_map *map,
1040 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1047 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1051 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1052 const struct bus_properties_map *prop;
1054 const char *contents;
1058 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1062 for (i = 0, prop = NULL; map[i].member; i++)
1063 if (streq(map[i].member, member)) {
1069 r = sd_bus_message_peek_type(m, NULL, &contents);
1073 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1077 v = (uint8_t *)userdata + prop->offset;
1079 r = prop->set(bus, member, m, &error, v);
1081 r = map_basic(bus, member, m, &error, v);
1085 r = sd_bus_message_exit_container(m);
1089 r = sd_bus_message_skip(m, "v");
1094 r = sd_bus_message_exit_container(m);
1099 return sd_bus_message_exit_container(m);
1102 int bus_message_map_properties_changed(sd_bus *bus,
1104 const struct bus_properties_map *map,
1107 int r, invalidated, i;
1113 r = bus_message_map_all_properties(bus, m, map, userdata);
1117 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1122 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1123 for (i = 0; map[i].member; i++)
1124 if (streq(map[i].member, member)) {
1129 r = sd_bus_message_exit_container(m);
1136 int bus_map_all_properties(sd_bus *bus,
1137 const char *destination,
1139 const struct bus_properties_map *map,
1141 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1142 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1146 assert(destination);
1150 r = sd_bus_call_method(
1154 "org.freedesktop.DBus.Properties",
1162 return bus_message_map_all_properties(bus, m, map, userdata);
1165 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1168 assert(transport >= 0);
1169 assert(transport < _BUS_TRANSPORT_MAX);
1172 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1173 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1175 switch (transport) {
1177 case BUS_TRANSPORT_LOCAL:
1179 r = sd_bus_default_user(bus);
1181 r = sd_bus_default_system(bus);
1185 case BUS_TRANSPORT_REMOTE:
1186 r = sd_bus_open_system_remote(bus, host);
1189 case BUS_TRANSPORT_MACHINE:
1190 r = sd_bus_open_system_machine(bus, host);
1194 assert_not_reached("Hmm, unknown transport type.");
1200 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1203 assert(transport >= 0);
1204 assert(transport < _BUS_TRANSPORT_MAX);
1207 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1208 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1210 switch (transport) {
1212 case BUS_TRANSPORT_LOCAL:
1214 r = bus_open_user_systemd(bus);
1216 r = bus_open_system_systemd(bus);
1220 case BUS_TRANSPORT_REMOTE:
1221 r = sd_bus_open_system_remote(bus, host);
1224 case BUS_TRANSPORT_MACHINE:
1225 r = sd_bus_open_system_machine(bus, host);
1229 assert_not_reached("Hmm, unknown transport type.");
1235 int bus_property_get_bool(
1238 const char *interface,
1239 const char *property,
1240 sd_bus_message *reply,
1242 sd_bus_error *error) {
1244 int b = *(bool*) userdata;
1246 return sd_bus_message_append_basic(reply, 'b', &b);
1249 #if __SIZEOF_SIZE_T__ != 8
1250 int bus_property_get_size(
1253 const char *interface,
1254 const char *property,
1255 sd_bus_message *reply,
1257 sd_bus_error *error) {
1259 uint64_t sz = *(size_t*) userdata;
1261 return sd_bus_message_append_basic(reply, 't', &sz);
1265 #if __SIZEOF_LONG__ != 8
1266 int bus_property_get_long(
1269 const char *interface,
1270 const char *property,
1271 sd_bus_message *reply,
1273 sd_bus_error *error) {
1275 int64_t l = *(long*) userdata;
1277 return sd_bus_message_append_basic(reply, 'x', &l);
1280 int bus_property_get_ulong(
1283 const char *interface,
1284 const char *property,
1285 sd_bus_message *reply,
1287 sd_bus_error *error) {
1289 uint64_t ul = *(unsigned long*) userdata;
1291 return sd_bus_message_append_basic(reply, 't', &ul);
1295 int bus_log_parse_error(int r) {
1296 return log_error_errno(r, "Failed to parse bus message: %m");
1299 int bus_log_create_error(int r) {
1300 return log_error_errno(r, "Failed to create bus message: %m");
1303 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1309 return sd_bus_message_read(
1324 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1328 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1329 sd_bus_reply_method_errno(m, r, error);
1331 } else if (sd_bus_error_is_set(error)) {
1332 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1333 sd_bus_reply_method_error(m, error);
1337 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1338 bus_message_type_to_string(m->header->type),
1341 strna(m->interface),
1343 strna(m->root_container.signature),
1344 bus_error_message(error, r));
1349 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1350 const char *eq, *field;
1356 eq = strchr(assignment, '=');
1358 log_error("Not an assignment: %s", assignment);
1362 field = strndupa(assignment, eq - assignment);
1365 if (streq(field, "CPUQuota")) {
1369 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1371 return bus_log_create_error(r);
1373 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1375 } else if (endswith(eq, "%")) {
1378 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1379 log_error("CPU quota '%s' invalid.", eq);
1383 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1385 return bus_log_create_error(r);
1387 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1389 log_error("CPU quota needs to be in percent.");
1394 return bus_log_create_error(r);
1399 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1401 return bus_log_create_error(r);
1403 if (STR_IN_SET(field,
1404 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1405 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
1407 r = parse_boolean(eq);
1409 log_error("Failed to parse boolean assignment %s.", assignment);
1413 r = sd_bus_message_append(m, "v", "b", r);
1415 } else if (streq(field, "MemoryLimit")) {
1418 r = parse_size(eq, 1024, &bytes);
1420 log_error("Failed to parse bytes specification %s", assignment);
1424 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1426 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1429 r = safe_atou64(eq, &u);
1431 log_error("Failed to parse %s value %s.", field, eq);
1435 r = sd_bus_message_append(m, "v", "t", u);
1437 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1438 r = sd_bus_message_append(m, "v", "s", eq);
1440 else if (streq(field, "DeviceAllow")) {
1443 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1445 const char *path, *rwm, *e;
1447 e = strchr(eq, ' ');
1449 path = strndupa(eq, e - eq);
1456 if (!path_startswith(path, "/dev")) {
1457 log_error("%s is not a device file in /dev.", path);
1461 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1464 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1467 r = sd_bus_message_append(m, "v", "a(st)", 0);
1469 const char *path, *bandwidth, *e;
1472 e = strchr(eq, ' ');
1474 path = strndupa(eq, e - eq);
1477 log_error("Failed to parse %s value %s.", field, eq);
1481 if (!path_startswith(path, "/dev")) {
1482 log_error("%s is not a device file in /dev.", path);
1486 r = parse_size(bandwidth, 1000, &bytes);
1488 log_error("Failed to parse byte value %s.", bandwidth);
1492 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1495 } else if (streq(field, "BlockIODeviceWeight")) {
1498 r = sd_bus_message_append(m, "v", "a(st)", 0);
1500 const char *path, *weight, *e;
1503 e = strchr(eq, ' ');
1505 path = strndupa(eq, e - eq);
1508 log_error("Failed to parse %s value %s.", field, eq);
1512 if (!path_startswith(path, "/dev")) {
1513 log_error("%s is not a device file in /dev.", path);
1517 r = safe_atou64(weight, &u);
1519 log_error("Failed to parse %s value %s.", field, weight);
1522 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1525 } else if (rlimit_from_string(field) >= 0) {
1528 if (streq(eq, "infinity"))
1531 r = safe_atou64(eq, &rl);
1533 log_error("Invalid resource limit: %s", eq);
1538 r = sd_bus_message_append(m, "v", "t", rl);
1540 } else if (streq(field, "Nice")) {
1543 r = safe_atoi32(eq, &i);
1545 log_error("Failed to parse %s value %s.", field, eq);
1549 r = sd_bus_message_append(m, "v", "i", i);
1551 } else if (streq(field, "Environment")) {
1553 r = sd_bus_message_append(m, "v", "as", 1, eq);
1555 } else if (streq(field, "KillSignal")) {
1558 sig = signal_from_string_try_harder(eq);
1560 log_error("Failed to parse %s value %s.", field, eq);
1564 r = sd_bus_message_append(m, "v", "i", sig);
1566 } else if (streq(field, "AccuracySec")) {
1569 r = parse_sec(eq, &u);
1571 log_error("Failed to parse %s value %s", field, eq);
1575 r = sd_bus_message_append(m, "v", "t", u);
1578 log_error("Unknown assignment %s.", assignment);
1583 return bus_log_create_error(r);
1588 typedef struct BusWaitForJobs {
1595 sd_bus_slot *slot_job_removed;
1596 sd_bus_slot *slot_disconnected;
1599 static int match_disconnected(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1603 log_error("Warning! D-Bus connection terminated.");
1609 static int match_job_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1610 const char *path, *unit, *result;
1611 BusWaitForJobs *d = userdata;
1620 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1622 bus_log_parse_error(r);
1626 found = set_remove(d->jobs, (char*) path);
1632 if (!isempty(result))
1633 d->result = strdup(result);
1636 d->name = strdup(unit);
1641 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1645 set_free_free(d->jobs);
1647 sd_bus_slot_unref(d->slot_disconnected);
1648 sd_bus_slot_unref(d->slot_job_removed);
1650 sd_bus_unref(d->bus);
1658 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1659 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1665 d = new0(BusWaitForJobs, 1);
1669 d->bus = sd_bus_ref(bus);
1671 /* When we are a bus client we match by sender. Direct
1672 * connections OTOH have no initialized sender field, and
1673 * hence we ignore the sender then */
1674 r = sd_bus_add_match(
1676 &d->slot_job_removed,
1679 "sender='org.freedesktop.systemd1',"
1680 "interface='org.freedesktop.systemd1.Manager',"
1681 "member='JobRemoved',"
1682 "path='/org/freedesktop/systemd1'" :
1684 "interface='org.freedesktop.systemd1.Manager',"
1685 "member='JobRemoved',"
1686 "path='/org/freedesktop/systemd1'",
1687 match_job_removed, d);
1691 r = sd_bus_add_match(
1693 &d->slot_disconnected,
1695 "sender='org.freedesktop.DBus.Local',"
1696 "interface='org.freedesktop.DBus.Local',"
1697 "member='Disconnected'",
1698 match_disconnected, d);
1708 static int bus_process_wait(sd_bus *bus) {
1712 r = sd_bus_process(bus, NULL);
1718 r = sd_bus_wait(bus, (uint64_t) -1);
1724 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1730 if (streq(d->result, "canceled"))
1731 log_error("Job for %s canceled.", strna(d->name));
1732 else if (streq(d->result, "timeout"))
1733 log_error("Job for %s timed out.", strna(d->name));
1734 else if (streq(d->result, "dependency"))
1735 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1736 else if (streq(d->result, "invalid"))
1737 log_error("Job for %s invalid.", strna(d->name));
1738 else if (streq(d->result, "assert"))
1739 log_error("Assertion failed on job for %s.", strna(d->name));
1740 else if (streq(d->result, "unsupported"))
1741 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1742 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1746 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
1748 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
1750 quotes ? "'" : "", d->name, quotes ? "'" : "");
1752 log_error("Job failed. See \"journalctl -xe\" for details.");
1756 if (streq(d->result, "canceled"))
1758 else if (streq(d->result, "timeout"))
1760 else if (streq(d->result, "dependency"))
1762 else if (streq(d->result, "invalid"))
1764 else if (streq(d->result, "assert"))
1766 else if (streq(d->result, "unsupported"))
1768 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1774 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1779 while (!set_isempty(d->jobs)) {
1782 q = bus_process_wait(d->bus);
1784 return log_error_errno(q, "Failed to wait for response: %m");
1787 q = check_wait_response(d, quiet);
1788 /* Return the first error as it is most likely to be
1790 if (q < 0 && r == 0)
1793 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1806 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1811 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1815 return set_put_strdup(d->jobs, path);
1818 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
1819 const char *type, *path, *source;
1822 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1824 return bus_log_parse_error(r);
1826 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1828 if (streq(type, "symlink"))
1829 log_info("Created symlink from %s to %s.", path, source);
1831 log_info("Removed symlink %s.", path);
1835 return bus_log_parse_error(r);
1837 r = sd_bus_message_exit_container(m);
1839 return bus_log_parse_error(r);