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, NULL);
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 r = bus_message_map_all_properties(bus, m, map, userdata);
1058 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1063 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1064 for (i = 0; map[i].member; i++)
1065 if (streq(map[i].member, member)) {
1070 r = sd_bus_message_exit_container(m);
1077 int bus_map_all_properties(sd_bus *bus,
1078 const char *destination,
1080 const struct bus_properties_map *map,
1082 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1083 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1087 assert(destination);
1091 r = sd_bus_call_method(
1095 "org.freedesktop.DBus.Properties",
1103 return bus_message_map_all_properties(bus, m, map, userdata);
1106 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1109 assert(transport >= 0);
1110 assert(transport < _BUS_TRANSPORT_MAX);
1113 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1114 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1116 switch (transport) {
1118 case BUS_TRANSPORT_LOCAL:
1120 r = sd_bus_default_user(bus);
1122 r = sd_bus_default_system(bus);
1126 case BUS_TRANSPORT_REMOTE:
1127 r = sd_bus_open_system_remote(bus, host);
1130 case BUS_TRANSPORT_CONTAINER:
1131 r = sd_bus_open_system_container(bus, host);
1135 assert_not_reached("Hmm, unknown transport type.");
1141 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1144 assert(transport >= 0);
1145 assert(transport < _BUS_TRANSPORT_MAX);
1148 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1149 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1151 switch (transport) {
1153 case BUS_TRANSPORT_LOCAL:
1155 r = bus_open_user_systemd(bus);
1157 r = bus_open_system_systemd(bus);
1161 case BUS_TRANSPORT_REMOTE:
1162 r = sd_bus_open_system_remote(bus, host);
1165 case BUS_TRANSPORT_CONTAINER:
1166 r = sd_bus_open_system_container(bus, host);
1170 assert_not_reached("Hmm, unknown transport type.");
1176 int bus_property_get_bool(
1179 const char *interface,
1180 const char *property,
1181 sd_bus_message *reply,
1183 sd_bus_error *error) {
1185 int b = *(bool*) userdata;
1187 return sd_bus_message_append_basic(reply, 'b', &b);
1190 #if __SIZEOF_SIZE_T__ != 8
1191 int bus_property_get_size(
1194 const char *interface,
1195 const char *property,
1196 sd_bus_message *reply,
1198 sd_bus_error *error) {
1200 uint64_t sz = *(size_t*) userdata;
1202 return sd_bus_message_append_basic(reply, 't', &sz);
1206 #if __SIZEOF_LONG__ != 8
1207 int bus_property_get_long(
1210 const char *interface,
1211 const char *property,
1212 sd_bus_message *reply,
1214 sd_bus_error *error) {
1216 int64_t l = *(long*) userdata;
1218 return sd_bus_message_append_basic(reply, 'x', &l);
1221 int bus_property_get_ulong(
1224 const char *interface,
1225 const char *property,
1226 sd_bus_message *reply,
1228 sd_bus_error *error) {
1230 uint64_t ul = *(unsigned long*) userdata;
1232 return sd_bus_message_append_basic(reply, 't', &ul);
1236 int bus_log_parse_error(int r) {
1237 log_error("Failed to parse bus message: %s", strerror(-r));
1241 int bus_log_create_error(int r) {
1242 log_error("Failed to create bus message: %s", strerror(-r));
1246 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1252 return sd_bus_message_read(
1267 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1271 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1272 sd_bus_reply_method_errno(m, r, error);
1274 } else if (sd_bus_error_is_set(error)) {
1275 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1276 sd_bus_reply_method_error(m, error);
1280 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1281 bus_message_type_to_string(m->header->type),
1284 strna(m->interface),
1286 strna(m->root_container.signature),
1287 bus_error_message(error, r));
1292 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1293 const char *eq, *field;
1299 eq = strchr(assignment, '=');
1301 log_error("Not an assignment: %s", assignment);
1305 field = strndupa(assignment, eq - assignment);
1308 if (streq(field, "CPUQuota")) {
1312 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1314 return bus_log_create_error(r);
1316 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1318 } else if (endswith(eq, "%")) {
1321 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1322 log_error("CPU quota '%s' invalid.", eq);
1326 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1328 return bus_log_create_error(r);
1330 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1332 log_error("CPU quota needs to be in percent.");
1337 return bus_log_create_error(r);
1342 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1344 return bus_log_create_error(r);
1346 if (STR_IN_SET(field,
1347 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1348 "SendSIGHUP", "SendSIGKILL")) {
1350 r = parse_boolean(eq);
1352 log_error("Failed to parse boolean assignment %s.", assignment);
1356 r = sd_bus_message_append(m, "v", "b", r);
1358 } else if (streq(field, "MemoryLimit")) {
1361 r = parse_size(eq, 1024, &bytes);
1363 log_error("Failed to parse bytes specification %s", assignment);
1367 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1369 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1372 r = safe_atou64(eq, &u);
1374 log_error("Failed to parse %s value %s.", field, eq);
1378 r = sd_bus_message_append(m, "v", "t", u);
1380 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1381 r = sd_bus_message_append(m, "v", "s", eq);
1383 else if (streq(field, "DeviceAllow")) {
1386 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1388 const char *path, *rwm, *e;
1390 e = strchr(eq, ' ');
1392 path = strndupa(eq, e - eq);
1399 if (!path_startswith(path, "/dev")) {
1400 log_error("%s is not a device file in /dev.", path);
1404 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1407 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1410 r = sd_bus_message_append(m, "v", "a(st)", 0);
1412 const char *path, *bandwidth, *e;
1415 e = strchr(eq, ' ');
1417 path = strndupa(eq, e - eq);
1420 log_error("Failed to parse %s value %s.", field, eq);
1424 if (!path_startswith(path, "/dev")) {
1425 log_error("%s is not a device file in /dev.", path);
1429 r = parse_size(bandwidth, 1000, &bytes);
1431 log_error("Failed to parse byte value %s.", bandwidth);
1435 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1438 } else if (streq(field, "BlockIODeviceWeight")) {
1441 r = sd_bus_message_append(m, "v", "a(st)", 0);
1443 const char *path, *weight, *e;
1446 e = strchr(eq, ' ');
1448 path = strndupa(eq, e - eq);
1451 log_error("Failed to parse %s value %s.", field, eq);
1455 if (!path_startswith(path, "/dev")) {
1456 log_error("%s is not a device file in /dev.", path);
1460 r = safe_atou64(weight, &u);
1462 log_error("Failed to parse %s value %s.", field, weight);
1465 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1468 } else if (rlimit_from_string(field) >= 0) {
1471 if (streq(eq, "infinity"))
1474 r = safe_atou64(eq, &rl);
1476 log_error("Invalid resource limit: %s", eq);
1481 r = sd_bus_message_append(m, "v", "t", rl);
1483 } else if (streq(field, "Nice")) {
1486 r = safe_atoi32(eq, &i);
1488 log_error("Failed to parse %s value %s.", field, eq);
1492 r = sd_bus_message_append(m, "v", "i", i);
1494 } else if (streq(field, "Environment")) {
1496 r = sd_bus_message_append(m, "v", "as", 1, eq);
1498 } else if (streq(field, "KillSignal")) {
1501 sig = signal_from_string_try_harder(eq);
1503 log_error("Failed to parse %s value %s.", field, eq);
1507 r = sd_bus_message_append(m, "v", "i", sig);
1510 log_error("Unknown assignment %s.", assignment);
1515 return bus_log_create_error(r);