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;
218 sender = sd_bus_message_get_sender(call);
222 r = sd_bus_call_method(
224 "org.freedesktop.PolicyKit1",
225 "/org/freedesktop/PolicyKit1/Authority",
226 "org.freedesktop.PolicyKit1.Authority",
227 "CheckAuthorization",
231 "system-bus-name", 1, "name", "s", sender,
238 /* Treat no PK available as access denied */
239 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
240 sd_bus_error_free(e);
247 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
251 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
259 *_challenge = challenge;
270 typedef struct AsyncPolkitQuery {
271 sd_bus_message *request, *reply;
272 sd_bus_message_handler_t callback;
278 static void async_polkit_query_free(AsyncPolkitQuery *q) {
283 sd_bus_slot_unref(q->slot);
285 if (q->registry && q->request)
286 hashmap_remove(q->registry, q->request);
288 sd_bus_message_unref(q->request);
289 sd_bus_message_unref(q->reply);
294 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
295 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
296 AsyncPolkitQuery *q = userdata;
303 q->slot = sd_bus_slot_unref(q->slot);
304 q->reply = sd_bus_message_ref(reply);
306 r = sd_bus_message_rewind(q->request, true);
308 r = sd_bus_reply_method_errno(q->request, r, NULL);
312 r = q->callback(bus, q->request, q->userdata, &error_buffer);
313 r = bus_maybe_reply_error(q->request, r, &error_buffer);
316 async_polkit_query_free(q);
323 int bus_verify_polkit_async(
324 sd_bus_message *call,
329 sd_bus_error *error) {
332 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
335 sd_bus_message_handler_t callback;
345 q = hashmap_get(*registry, call);
347 int authorized, challenge;
349 /* This is the second invocation of this function, and
350 * there's already a response from polkit, let's
354 if (sd_bus_message_is_method_error(q->reply, NULL)) {
355 const sd_bus_error *e;
357 /* Copy error from polkit reply */
358 e = sd_bus_message_get_error(q->reply);
359 sd_bus_error_copy(error, e);
361 /* Treat no PK available as access denied */
362 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
365 return -sd_bus_error_get_errno(e);
368 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
370 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
382 r = sd_bus_query_sender_privilege(call, capability);
389 if (sd_bus_get_current_message(call->bus) != call)
392 callback = sd_bus_get_current_handler(call->bus);
396 userdata = sd_bus_get_current_userdata(call->bus);
398 sender = sd_bus_message_get_sender(call);
402 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
406 r = sd_bus_message_new_method_call(
409 "org.freedesktop.PolicyKit1",
410 "/org/freedesktop/PolicyKit1/Authority",
411 "org.freedesktop.PolicyKit1.Authority",
412 "CheckAuthorization");
416 r = sd_bus_message_append(
419 "system-bus-name", 1, "name", "s", sender,
427 q = new0(AsyncPolkitQuery, 1);
431 q->request = sd_bus_message_ref(call);
432 q->callback = callback;
433 q->userdata = userdata;
435 r = hashmap_put(*registry, call, q);
437 async_polkit_query_free(q);
441 q->registry = *registry;
443 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
445 async_polkit_query_free(q);
455 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
459 while ((q = hashmap_steal_first(registry)))
460 async_polkit_query_free(q);
462 hashmap_free(registry);
466 int bus_check_peercred(sd_bus *c) {
473 fd = sd_bus_get_fd(c);
477 l = sizeof(struct ucred);
478 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
481 if (l != sizeof(struct ucred))
484 if (ucred.uid != 0 && ucred.uid != geteuid())
490 int bus_open_system_systemd(sd_bus **_bus) {
491 _cleanup_bus_unref_ sd_bus *bus = NULL;
497 return sd_bus_open_system(_bus);
499 /* If we are root and kdbus is not available, then let's talk
500 * directly to the system instance, instead of going via the
504 r = sd_bus_new(&bus);
508 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
512 bus->bus_client = true;
514 r = sd_bus_start(bus);
521 bus = sd_bus_unref(bus);
524 r = sd_bus_new(&bus);
528 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
532 r = sd_bus_start(bus);
534 return sd_bus_open_system(_bus);
536 r = bus_check_peercred(bus);
546 int bus_open_user_systemd(sd_bus **_bus) {
547 _cleanup_bus_unref_ sd_bus *bus = NULL;
548 _cleanup_free_ char *ee = NULL;
552 /* Try via kdbus first, and then directly */
557 r = sd_bus_new(&bus);
561 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, getuid()) < 0)
564 bus->bus_client = true;
566 r = sd_bus_start(bus);
573 bus = sd_bus_unref(bus);
576 e = secure_getenv("XDG_RUNTIME_DIR");
578 return sd_bus_open_user(_bus);
580 ee = bus_address_escape(e);
584 r = sd_bus_new(&bus);
588 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
592 r = sd_bus_start(bus);
594 return sd_bus_open_user(_bus);
596 r = bus_check_peercred(bus);
606 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
608 const char *contents;
614 r = sd_bus_message_peek_type(property, &type, &contents);
620 case SD_BUS_TYPE_STRING: {
623 r = sd_bus_message_read_basic(property, type, &s);
627 if (all || !isempty(s))
628 printf("%s=%s\n", name, s);
633 case SD_BUS_TYPE_BOOLEAN: {
636 r = sd_bus_message_read_basic(property, type, &b);
640 printf("%s=%s\n", name, yes_no(b));
645 case SD_BUS_TYPE_UINT64: {
648 r = sd_bus_message_read_basic(property, type, &u);
652 /* Yes, heuristics! But we can change this check
653 * should it turn out to not be sufficient */
655 if (endswith(name, "Timestamp")) {
656 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
658 t = format_timestamp(timestamp, sizeof(timestamp), u);
660 printf("%s=%s\n", name, strempty(t));
662 } else if (strstr(name, "USec")) {
663 char timespan[FORMAT_TIMESPAN_MAX];
665 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
667 printf("%s=%llu\n", name, (unsigned long long) u);
672 case SD_BUS_TYPE_UINT32: {
675 r = sd_bus_message_read_basic(property, type, &u);
679 if (strstr(name, "UMask") || strstr(name, "Mode"))
680 printf("%s=%04o\n", name, u);
682 printf("%s=%u\n", name, (unsigned) u);
687 case SD_BUS_TYPE_INT32: {
690 r = sd_bus_message_read_basic(property, type, &i);
694 printf("%s=%i\n", name, (int) i);
698 case SD_BUS_TYPE_DOUBLE: {
701 r = sd_bus_message_read_basic(property, type, &d);
705 printf("%s=%g\n", name, d);
709 case SD_BUS_TYPE_ARRAY:
710 if (streq(contents, "s")) {
714 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
718 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
722 printf("%s%s", first ? "" : " ", str);
734 r = sd_bus_message_exit_container(property);
740 } else if (streq(contents, "y")) {
744 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
753 for (i = 0; i < n; i++)
754 printf("%02x", u[i]);
761 } else if (streq(contents, "u")) {
765 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
774 for (i = 0; i < n; i++)
775 printf("%08x", u[i]);
789 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
790 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
791 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
797 r = sd_bus_call_method(bus,
800 "org.freedesktop.DBus.Properties",
808 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
812 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
814 const char *contents;
816 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
820 if (!filter || strv_find(filter, name)) {
821 r = sd_bus_message_peek_type(reply, NULL, &contents);
825 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
829 r = bus_print_property(name, reply, all);
834 printf("%s=[unprintable]\n", name);
835 /* skip what we didn't read */
836 r = sd_bus_message_skip(reply, contents);
841 r = sd_bus_message_exit_container(reply);
845 r = sd_bus_message_skip(reply, "v");
850 r = sd_bus_message_exit_container(reply);
857 r = sd_bus_message_exit_container(reply);
864 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
865 sd_id128_t *p = userdata;
870 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
877 memcpy((*p).bytes, v, n);
884 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
888 r = sd_bus_message_peek_type(m, &type, NULL);
893 case SD_BUS_TYPE_STRING: {
898 r = sd_bus_message_read_basic(m, type, &s);
916 case SD_BUS_TYPE_ARRAY: {
917 _cleanup_strv_free_ char **l = NULL;
918 char ***p = userdata;
920 r = bus_message_read_strv_extend(m, &l);
931 case SD_BUS_TYPE_BOOLEAN: {
935 r = sd_bus_message_read_basic(m, type, &b);
944 case SD_BUS_TYPE_UINT32: {
946 uint32_t *p = userdata;
948 r = sd_bus_message_read_basic(m, type, &u);
957 case SD_BUS_TYPE_UINT64: {
959 uint64_t *p = userdata;
961 r = sd_bus_message_read_basic(m, type, &t);
977 int bus_message_map_all_properties(sd_bus *bus,
979 const struct bus_properties_map *map,
981 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
988 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
992 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
993 const struct bus_properties_map *prop;
995 const char *contents;
999 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1003 for (i = 0, prop = NULL; map[i].member; i++)
1004 if (streq(map[i].member, member)) {
1010 r = sd_bus_message_peek_type(m, NULL, &contents);
1014 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1018 v = (uint8_t *)userdata + prop->offset;
1020 r = prop->set(bus, member, m, &error, v);
1022 r = map_basic(bus, member, m, &error, v);
1026 r = sd_bus_message_exit_container(m);
1030 r = sd_bus_message_skip(m, "v");
1035 r = sd_bus_message_exit_container(m);
1040 return sd_bus_message_exit_container(m);
1043 int bus_message_map_properties_changed(sd_bus *bus,
1045 const struct bus_properties_map *map,
1048 int r, invalidated, i;
1054 /* skip interface, but allow callers to do that themselves */
1055 sd_bus_message_skip(m, "s");
1057 r = bus_message_map_all_properties(bus, m, map, userdata);
1061 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1066 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1067 for (i = 0; map[i].member; i++)
1068 if (streq(map[i].member, member)) {
1073 r = sd_bus_message_exit_container(m);
1080 int bus_map_all_properties(sd_bus *bus,
1081 const char *destination,
1083 const struct bus_properties_map *map,
1085 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1086 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1090 assert(destination);
1094 r = sd_bus_call_method(
1098 "org.freedesktop.DBus.Properties",
1106 return bus_message_map_all_properties(bus, m, map, userdata);
1109 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1112 assert(transport >= 0);
1113 assert(transport < _BUS_TRANSPORT_MAX);
1116 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1117 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1119 switch (transport) {
1121 case BUS_TRANSPORT_LOCAL:
1123 r = sd_bus_default_user(bus);
1125 r = sd_bus_default_system(bus);
1129 case BUS_TRANSPORT_REMOTE:
1130 r = sd_bus_open_system_remote(bus, host);
1133 case BUS_TRANSPORT_CONTAINER:
1134 r = sd_bus_open_system_container(bus, host);
1138 assert_not_reached("Hmm, unknown transport type.");
1144 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1147 assert(transport >= 0);
1148 assert(transport < _BUS_TRANSPORT_MAX);
1151 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1152 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1154 switch (transport) {
1156 case BUS_TRANSPORT_LOCAL:
1158 r = bus_open_user_systemd(bus);
1160 r = bus_open_system_systemd(bus);
1164 case BUS_TRANSPORT_REMOTE:
1165 r = sd_bus_open_system_remote(bus, host);
1168 case BUS_TRANSPORT_CONTAINER:
1169 r = sd_bus_open_system_container(bus, host);
1173 assert_not_reached("Hmm, unknown transport type.");
1179 int bus_property_get_bool(
1182 const char *interface,
1183 const char *property,
1184 sd_bus_message *reply,
1186 sd_bus_error *error) {
1188 int b = *(bool*) userdata;
1190 return sd_bus_message_append_basic(reply, 'b', &b);
1193 #if __SIZEOF_SIZE_T__ != 8
1194 int bus_property_get_size(
1197 const char *interface,
1198 const char *property,
1199 sd_bus_message *reply,
1201 sd_bus_error *error) {
1203 uint64_t sz = *(size_t*) userdata;
1205 return sd_bus_message_append_basic(reply, 't', &sz);
1209 #if __SIZEOF_LONG__ != 8
1210 int bus_property_get_long(
1213 const char *interface,
1214 const char *property,
1215 sd_bus_message *reply,
1217 sd_bus_error *error) {
1219 int64_t l = *(long*) userdata;
1221 return sd_bus_message_append_basic(reply, 'x', &l);
1224 int bus_property_get_ulong(
1227 const char *interface,
1228 const char *property,
1229 sd_bus_message *reply,
1231 sd_bus_error *error) {
1233 uint64_t ul = *(unsigned long*) userdata;
1235 return sd_bus_message_append_basic(reply, 't', &ul);
1239 int bus_log_parse_error(int r) {
1240 log_error("Failed to parse bus message: %s", strerror(-r));
1244 int bus_log_create_error(int r) {
1245 log_error("Failed to create bus message: %s", strerror(-r));
1249 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1255 return sd_bus_message_read(
1270 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1274 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1275 sd_bus_reply_method_errno(m, r, error);
1277 } else if (sd_bus_error_is_set(error)) {
1278 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1279 sd_bus_reply_method_error(m, error);
1283 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1284 bus_message_type_to_string(m->header->type),
1287 strna(m->interface),
1289 strna(m->root_container.signature),
1290 bus_error_message(error, r));
1295 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1296 const char *eq, *field;
1302 eq = strchr(assignment, '=');
1304 log_error("Not an assignment: %s", assignment);
1308 field = strndupa(assignment, eq - assignment);
1311 if (streq(field, "CPUQuota")) {
1315 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1317 return bus_log_create_error(r);
1319 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1321 } else if (endswith(eq, "%")) {
1324 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1325 log_error("CPU quota '%s' invalid.", eq);
1329 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1331 return bus_log_create_error(r);
1333 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1335 log_error("CPU quota needs to be in percent.");
1340 return bus_log_create_error(r);
1345 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1347 return bus_log_create_error(r);
1349 if (STR_IN_SET(field,
1350 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1351 "SendSIGHUP", "SendSIGKILL")) {
1353 r = parse_boolean(eq);
1355 log_error("Failed to parse boolean assignment %s.", assignment);
1359 r = sd_bus_message_append(m, "v", "b", r);
1361 } else if (streq(field, "MemoryLimit")) {
1364 r = parse_size(eq, 1024, &bytes);
1366 log_error("Failed to parse bytes specification %s", assignment);
1370 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1372 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1375 r = safe_atou64(eq, &u);
1377 log_error("Failed to parse %s value %s.", field, eq);
1381 r = sd_bus_message_append(m, "v", "t", u);
1383 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1384 r = sd_bus_message_append(m, "v", "s", eq);
1386 else if (streq(field, "DeviceAllow")) {
1389 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1391 const char *path, *rwm, *e;
1393 e = strchr(eq, ' ');
1395 path = strndupa(eq, e - eq);
1402 if (!path_startswith(path, "/dev")) {
1403 log_error("%s is not a device file in /dev.", path);
1407 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1410 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1413 r = sd_bus_message_append(m, "v", "a(st)", 0);
1415 const char *path, *bandwidth, *e;
1418 e = strchr(eq, ' ');
1420 path = strndupa(eq, e - eq);
1423 log_error("Failed to parse %s value %s.", field, eq);
1427 if (!path_startswith(path, "/dev")) {
1428 log_error("%s is not a device file in /dev.", path);
1432 r = parse_size(bandwidth, 1000, &bytes);
1434 log_error("Failed to parse byte value %s.", bandwidth);
1438 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1441 } else if (streq(field, "BlockIODeviceWeight")) {
1444 r = sd_bus_message_append(m, "v", "a(st)", 0);
1446 const char *path, *weight, *e;
1449 e = strchr(eq, ' ');
1451 path = strndupa(eq, e - eq);
1454 log_error("Failed to parse %s value %s.", field, eq);
1458 if (!path_startswith(path, "/dev")) {
1459 log_error("%s is not a device file in /dev.", path);
1463 r = safe_atou64(weight, &u);
1465 log_error("Failed to parse %s value %s.", field, weight);
1468 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1471 } else if (rlimit_from_string(field) >= 0) {
1474 if (streq(eq, "infinity"))
1477 r = safe_atou64(eq, &rl);
1479 log_error("Invalid resource limit: %s", eq);
1484 r = sd_bus_message_append(m, "v", "t", rl);
1486 } else if (streq(field, "Nice")) {
1489 r = safe_atoi32(eq, &i);
1491 log_error("Failed to parse %s value %s.", field, eq);
1495 r = sd_bus_message_append(m, "v", "i", i);
1497 } else if (streq(field, "Environment")) {
1499 r = sd_bus_message_append(m, "v", "as", 1, eq);
1501 } else if (streq(field, "KillSignal")) {
1504 sig = signal_from_string_try_harder(eq);
1506 log_error("Failed to parse %s value %s.", field, eq);
1510 r = sd_bus_message_append(m, "v", "i", sig);
1513 log_error("Unknown assignment %s.", assignment);
1518 return bus_log_create_error(r);