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>
23 #include <sys/capability.h>
25 #include "systemd/sd-daemon.h"
31 #include "path-util.h"
36 #include "bus-error.h"
37 #include "bus-message.h"
39 #include "bus-internal.h"
41 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
42 sd_event *e = userdata;
54 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
55 _cleanup_free_ char *match = NULL;
63 /* We unregister the name here and then wait for the
64 * NameOwnerChanged signal for this event to arrive before we
65 * quit. We do this in order to make sure that any queued
66 * requests are still processed before we really exit. */
68 r = sd_bus_get_unique_name(bus, &unique);
73 "sender='org.freedesktop.DBus',"
75 "interface='org.freedesktop.DBus',"
76 "member='NameOwnerChanged',"
77 "path='/org/freedesktop/DBus',"
80 "arg2=''", name, unique);
84 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
88 r = sd_bus_release_name(bus, name);
95 int bus_event_loop_with_idle(
100 check_idle_t check_idle,
102 bool exiting = false;
112 r = sd_event_get_state(e);
115 if (r == SD_EVENT_FINISHED)
119 idle = check_idle(userdata);
123 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
127 if (r == 0 && !exiting) {
129 r = sd_bus_try_close(bus);
133 /* Fallback for dbus1 connections: we
134 * unregister the name and wait for the
135 * response to come through for it */
138 /* Inform the service manager that we
139 * are going down, so that it will
140 * queue all further start requests,
141 * instead of assuming we are already
143 sd_notify(false, "STOPPING=1");
145 r = bus_async_unregister_and_exit(e, bus, name);
161 r = sd_event_get_exit_code(e, &code);
168 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
169 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
170 int r, has_owner = 0;
175 r = sd_bus_call_method(c,
176 "org.freedesktop.DBus",
177 "/org/freedesktop/dbus",
178 "org.freedesktop.DBus",
187 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
189 return sd_bus_error_set_errno(error, r);
194 int bus_verify_polkit(
195 sd_bus_message *call,
207 r = sd_bus_query_sender_privilege(call, capability);
214 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
215 int authorized = false, challenge = false, c;
218 sender = sd_bus_message_get_sender(call);
222 c = sd_bus_message_get_allow_interactive_authorization(call);
228 r = sd_bus_call_method(
230 "org.freedesktop.PolicyKit1",
231 "/org/freedesktop/PolicyKit1/Authority",
232 "org.freedesktop.PolicyKit1.Authority",
233 "CheckAuthorization",
237 "system-bus-name", 1, "name", "s", sender,
244 /* Treat no PK available as access denied */
245 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
246 sd_bus_error_free(e);
253 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
257 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
265 *_challenge = challenge;
276 typedef struct AsyncPolkitQuery {
277 sd_bus_message *request, *reply;
278 sd_bus_message_handler_t callback;
284 static void async_polkit_query_free(AsyncPolkitQuery *q) {
289 sd_bus_slot_unref(q->slot);
291 if (q->registry && q->request)
292 hashmap_remove(q->registry, q->request);
294 sd_bus_message_unref(q->request);
295 sd_bus_message_unref(q->reply);
300 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
301 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
302 AsyncPolkitQuery *q = userdata;
309 q->slot = sd_bus_slot_unref(q->slot);
310 q->reply = sd_bus_message_ref(reply);
312 r = sd_bus_message_rewind(q->request, true);
314 r = sd_bus_reply_method_errno(q->request, r, NULL);
318 r = q->callback(bus, q->request, q->userdata, &error_buffer);
319 r = bus_maybe_reply_error(q->request, r, &error_buffer);
322 async_polkit_query_free(q);
329 int bus_verify_polkit_async(
330 sd_bus_message *call,
335 sd_bus_error *error) {
338 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
341 sd_bus_message_handler_t callback;
352 q = hashmap_get(*registry, call);
354 int authorized, challenge;
356 /* This is the second invocation of this function, and
357 * there's already a response from polkit, let's
361 if (sd_bus_message_is_method_error(q->reply, NULL)) {
362 const sd_bus_error *e;
364 /* Copy error from polkit reply */
365 e = sd_bus_message_get_error(q->reply);
366 sd_bus_error_copy(error, e);
368 /* Treat no PK available as access denied */
369 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
372 return -sd_bus_error_get_errno(e);
375 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
377 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
389 r = sd_bus_query_sender_privilege(call, capability);
396 if (sd_bus_get_current_message(call->bus) != call)
399 callback = sd_bus_get_current_handler(call->bus);
403 userdata = sd_bus_get_current_userdata(call->bus);
405 sender = sd_bus_message_get_sender(call);
409 c = sd_bus_message_get_allow_interactive_authorization(call);
415 r = hashmap_ensure_allocated(registry, NULL);
419 r = sd_bus_message_new_method_call(
422 "org.freedesktop.PolicyKit1",
423 "/org/freedesktop/PolicyKit1/Authority",
424 "org.freedesktop.PolicyKit1.Authority",
425 "CheckAuthorization");
429 r = sd_bus_message_append(
432 "system-bus-name", 1, "name", "s", sender,
440 q = new0(AsyncPolkitQuery, 1);
444 q->request = sd_bus_message_ref(call);
445 q->callback = callback;
446 q->userdata = userdata;
448 r = hashmap_put(*registry, call, q);
450 async_polkit_query_free(q);
454 q->registry = *registry;
456 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
458 async_polkit_query_free(q);
468 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
472 while ((q = hashmap_steal_first(registry)))
473 async_polkit_query_free(q);
475 hashmap_free(registry);
479 int bus_check_peercred(sd_bus *c) {
486 fd = sd_bus_get_fd(c);
490 l = sizeof(struct ucred);
491 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
494 if (l != sizeof(struct ucred))
497 if (ucred.uid != 0 && ucred.uid != geteuid())
503 int bus_open_system_systemd(sd_bus **_bus) {
504 _cleanup_bus_unref_ sd_bus *bus = NULL;
510 return sd_bus_open_system(_bus);
512 /* If we are root and kdbus is not available, then let's talk
513 * directly to the system instance, instead of going via the
517 r = sd_bus_new(&bus);
521 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
525 bus->bus_client = true;
527 r = sd_bus_start(bus);
534 bus = sd_bus_unref(bus);
537 r = sd_bus_new(&bus);
541 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
545 r = sd_bus_start(bus);
547 return sd_bus_open_system(_bus);
549 r = bus_check_peercred(bus);
559 int bus_open_user_systemd(sd_bus **_bus) {
560 _cleanup_bus_unref_ sd_bus *bus = NULL;
561 _cleanup_free_ char *ee = NULL;
565 /* Try via kdbus first, and then directly */
570 r = sd_bus_new(&bus);
574 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, getuid()) < 0)
577 bus->bus_client = true;
579 r = sd_bus_start(bus);
586 bus = sd_bus_unref(bus);
589 e = secure_getenv("XDG_RUNTIME_DIR");
591 return sd_bus_open_user(_bus);
593 ee = bus_address_escape(e);
597 r = sd_bus_new(&bus);
601 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
605 r = sd_bus_start(bus);
607 return sd_bus_open_user(_bus);
609 r = bus_check_peercred(bus);
619 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
621 const char *contents;
627 r = sd_bus_message_peek_type(property, &type, &contents);
633 case SD_BUS_TYPE_STRING: {
636 r = sd_bus_message_read_basic(property, type, &s);
640 if (all || !isempty(s))
641 printf("%s=%s\n", name, s);
646 case SD_BUS_TYPE_BOOLEAN: {
649 r = sd_bus_message_read_basic(property, type, &b);
653 printf("%s=%s\n", name, yes_no(b));
658 case SD_BUS_TYPE_UINT64: {
661 r = sd_bus_message_read_basic(property, type, &u);
665 /* Yes, heuristics! But we can change this check
666 * should it turn out to not be sufficient */
668 if (endswith(name, "Timestamp")) {
669 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
671 t = format_timestamp(timestamp, sizeof(timestamp), u);
673 printf("%s=%s\n", name, strempty(t));
675 } else if (strstr(name, "USec")) {
676 char timespan[FORMAT_TIMESPAN_MAX];
678 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
680 printf("%s=%llu\n", name, (unsigned long long) u);
685 case SD_BUS_TYPE_UINT32: {
688 r = sd_bus_message_read_basic(property, type, &u);
692 if (strstr(name, "UMask") || strstr(name, "Mode"))
693 printf("%s=%04o\n", name, u);
695 printf("%s=%u\n", name, (unsigned) u);
700 case SD_BUS_TYPE_INT32: {
703 r = sd_bus_message_read_basic(property, type, &i);
707 printf("%s=%i\n", name, (int) i);
711 case SD_BUS_TYPE_DOUBLE: {
714 r = sd_bus_message_read_basic(property, type, &d);
718 printf("%s=%g\n", name, d);
722 case SD_BUS_TYPE_ARRAY:
723 if (streq(contents, "s")) {
727 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
731 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
735 printf("%s%s", first ? "" : " ", str);
747 r = sd_bus_message_exit_container(property);
753 } else if (streq(contents, "y")) {
757 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
766 for (i = 0; i < n; i++)
767 printf("%02x", u[i]);
774 } else if (streq(contents, "u")) {
778 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
787 for (i = 0; i < n; i++)
788 printf("%08x", u[i]);
802 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
803 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
804 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
810 r = sd_bus_call_method(bus,
813 "org.freedesktop.DBus.Properties",
821 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
825 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
827 const char *contents;
829 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
833 if (!filter || strv_find(filter, name)) {
834 r = sd_bus_message_peek_type(reply, NULL, &contents);
838 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
842 r = bus_print_property(name, reply, all);
847 printf("%s=[unprintable]\n", name);
848 /* skip what we didn't read */
849 r = sd_bus_message_skip(reply, contents);
854 r = sd_bus_message_exit_container(reply);
858 r = sd_bus_message_skip(reply, "v");
863 r = sd_bus_message_exit_container(reply);
870 r = sd_bus_message_exit_container(reply);
877 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
878 sd_id128_t *p = userdata;
883 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
890 memcpy((*p).bytes, v, n);
897 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
901 r = sd_bus_message_peek_type(m, &type, NULL);
906 case SD_BUS_TYPE_STRING: {
911 r = sd_bus_message_read_basic(m, type, &s);
929 case SD_BUS_TYPE_ARRAY: {
930 _cleanup_strv_free_ char **l = NULL;
931 char ***p = userdata;
933 r = bus_message_read_strv_extend(m, &l);
944 case SD_BUS_TYPE_BOOLEAN: {
948 r = sd_bus_message_read_basic(m, type, &b);
957 case SD_BUS_TYPE_UINT32: {
959 uint32_t *p = userdata;
961 r = sd_bus_message_read_basic(m, type, &u);
970 case SD_BUS_TYPE_UINT64: {
972 uint64_t *p = userdata;
974 r = sd_bus_message_read_basic(m, type, &t);
990 int bus_message_map_all_properties(sd_bus *bus,
992 const struct bus_properties_map *map,
994 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1001 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1005 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1006 const struct bus_properties_map *prop;
1008 const char *contents;
1012 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1016 for (i = 0, prop = NULL; map[i].member; i++)
1017 if (streq(map[i].member, member)) {
1023 r = sd_bus_message_peek_type(m, NULL, &contents);
1027 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1031 v = (uint8_t *)userdata + prop->offset;
1033 r = prop->set(bus, member, m, &error, v);
1035 r = map_basic(bus, member, m, &error, v);
1039 r = sd_bus_message_exit_container(m);
1043 r = sd_bus_message_skip(m, "v");
1048 r = sd_bus_message_exit_container(m);
1053 return sd_bus_message_exit_container(m);
1056 int bus_message_map_properties_changed(sd_bus *bus,
1058 const struct bus_properties_map *map,
1061 int r, invalidated, i;
1067 r = bus_message_map_all_properties(bus, m, map, userdata);
1071 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1076 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1077 for (i = 0; map[i].member; i++)
1078 if (streq(map[i].member, member)) {
1083 r = sd_bus_message_exit_container(m);
1090 int bus_map_all_properties(sd_bus *bus,
1091 const char *destination,
1093 const struct bus_properties_map *map,
1095 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1096 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1100 assert(destination);
1104 r = sd_bus_call_method(
1108 "org.freedesktop.DBus.Properties",
1116 return bus_message_map_all_properties(bus, m, map, userdata);
1119 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1122 assert(transport >= 0);
1123 assert(transport < _BUS_TRANSPORT_MAX);
1126 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1127 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1129 switch (transport) {
1131 case BUS_TRANSPORT_LOCAL:
1133 r = sd_bus_default_user(bus);
1135 r = sd_bus_default_system(bus);
1139 case BUS_TRANSPORT_REMOTE:
1140 r = sd_bus_open_system_remote(bus, host);
1143 case BUS_TRANSPORT_CONTAINER:
1144 r = sd_bus_open_system_container(bus, host);
1148 assert_not_reached("Hmm, unknown transport type.");
1154 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1157 assert(transport >= 0);
1158 assert(transport < _BUS_TRANSPORT_MAX);
1161 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1162 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1164 switch (transport) {
1166 case BUS_TRANSPORT_LOCAL:
1168 r = bus_open_user_systemd(bus);
1170 r = bus_open_system_systemd(bus);
1174 case BUS_TRANSPORT_REMOTE:
1175 r = sd_bus_open_system_remote(bus, host);
1178 case BUS_TRANSPORT_CONTAINER:
1179 r = sd_bus_open_system_container(bus, host);
1183 assert_not_reached("Hmm, unknown transport type.");
1189 int bus_property_get_bool(
1192 const char *interface,
1193 const char *property,
1194 sd_bus_message *reply,
1196 sd_bus_error *error) {
1198 int b = *(bool*) userdata;
1200 return sd_bus_message_append_basic(reply, 'b', &b);
1203 #if __SIZEOF_SIZE_T__ != 8
1204 int bus_property_get_size(
1207 const char *interface,
1208 const char *property,
1209 sd_bus_message *reply,
1211 sd_bus_error *error) {
1213 uint64_t sz = *(size_t*) userdata;
1215 return sd_bus_message_append_basic(reply, 't', &sz);
1219 #if __SIZEOF_LONG__ != 8
1220 int bus_property_get_long(
1223 const char *interface,
1224 const char *property,
1225 sd_bus_message *reply,
1227 sd_bus_error *error) {
1229 int64_t l = *(long*) userdata;
1231 return sd_bus_message_append_basic(reply, 'x', &l);
1234 int bus_property_get_ulong(
1237 const char *interface,
1238 const char *property,
1239 sd_bus_message *reply,
1241 sd_bus_error *error) {
1243 uint64_t ul = *(unsigned long*) userdata;
1245 return sd_bus_message_append_basic(reply, 't', &ul);
1249 int bus_log_parse_error(int r) {
1250 log_error("Failed to parse bus message: %s", strerror(-r));
1254 int bus_log_create_error(int r) {
1255 log_error("Failed to create bus message: %s", strerror(-r));
1259 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1265 return sd_bus_message_read(
1280 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1284 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1285 sd_bus_reply_method_errno(m, r, error);
1287 } else if (sd_bus_error_is_set(error)) {
1288 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1289 sd_bus_reply_method_error(m, error);
1293 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1294 bus_message_type_to_string(m->header->type),
1297 strna(m->interface),
1299 strna(m->root_container.signature),
1300 bus_error_message(error, r));
1305 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1306 const char *eq, *field;
1312 eq = strchr(assignment, '=');
1314 log_error("Not an assignment: %s", assignment);
1318 field = strndupa(assignment, eq - assignment);
1321 if (streq(field, "CPUQuota")) {
1325 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1327 return bus_log_create_error(r);
1329 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1331 } else if (endswith(eq, "%")) {
1334 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1335 log_error("CPU quota '%s' invalid.", eq);
1339 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1341 return bus_log_create_error(r);
1343 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1345 log_error("CPU quota needs to be in percent.");
1350 return bus_log_create_error(r);
1355 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1357 return bus_log_create_error(r);
1359 if (STR_IN_SET(field,
1360 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1361 "SendSIGHUP", "SendSIGKILL")) {
1363 r = parse_boolean(eq);
1365 log_error("Failed to parse boolean assignment %s.", assignment);
1369 r = sd_bus_message_append(m, "v", "b", r);
1371 } else if (streq(field, "MemoryLimit")) {
1374 r = parse_size(eq, 1024, &bytes);
1376 log_error("Failed to parse bytes specification %s", assignment);
1380 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1382 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1385 r = safe_atou64(eq, &u);
1387 log_error("Failed to parse %s value %s.", field, eq);
1391 r = sd_bus_message_append(m, "v", "t", u);
1393 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1394 r = sd_bus_message_append(m, "v", "s", eq);
1396 else if (streq(field, "DeviceAllow")) {
1399 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1401 const char *path, *rwm, *e;
1403 e = strchr(eq, ' ');
1405 path = strndupa(eq, e - eq);
1412 if (!path_startswith(path, "/dev")) {
1413 log_error("%s is not a device file in /dev.", path);
1417 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1420 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1423 r = sd_bus_message_append(m, "v", "a(st)", 0);
1425 const char *path, *bandwidth, *e;
1428 e = strchr(eq, ' ');
1430 path = strndupa(eq, e - eq);
1433 log_error("Failed to parse %s value %s.", field, eq);
1437 if (!path_startswith(path, "/dev")) {
1438 log_error("%s is not a device file in /dev.", path);
1442 r = parse_size(bandwidth, 1000, &bytes);
1444 log_error("Failed to parse byte value %s.", bandwidth);
1448 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1451 } else if (streq(field, "BlockIODeviceWeight")) {
1454 r = sd_bus_message_append(m, "v", "a(st)", 0);
1456 const char *path, *weight, *e;
1459 e = strchr(eq, ' ');
1461 path = strndupa(eq, e - eq);
1464 log_error("Failed to parse %s value %s.", field, eq);
1468 if (!path_startswith(path, "/dev")) {
1469 log_error("%s is not a device file in /dev.", path);
1473 r = safe_atou64(weight, &u);
1475 log_error("Failed to parse %s value %s.", field, weight);
1478 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1481 } else if (rlimit_from_string(field) >= 0) {
1484 if (streq(eq, "infinity"))
1487 r = safe_atou64(eq, &rl);
1489 log_error("Invalid resource limit: %s", eq);
1494 r = sd_bus_message_append(m, "v", "t", rl);
1496 } else if (streq(field, "Nice")) {
1499 r = safe_atoi32(eq, &i);
1501 log_error("Failed to parse %s value %s.", field, eq);
1505 r = sd_bus_message_append(m, "v", "i", i);
1507 } else if (streq(field, "Environment")) {
1509 r = sd_bus_message_append(m, "v", "as", 1, eq);
1511 } else if (streq(field, "KillSignal")) {
1514 sig = signal_from_string_try_harder(eq);
1516 log_error("Failed to parse %s value %s.", field, eq);
1520 r = sd_bus_message_append(m, "v", "i", sig);
1523 log_error("Unknown assignment %s.", assignment);
1528 return bus_log_create_error(r);