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);
386 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
392 r = sd_bus_query_sender_privilege(call, capability);
399 if (sd_bus_get_current_message(call->bus) != call)
402 callback = sd_bus_get_current_handler(call->bus);
406 userdata = sd_bus_get_current_userdata(call->bus);
408 sender = sd_bus_message_get_sender(call);
412 c = sd_bus_message_get_allow_interactive_authorization(call);
418 r = hashmap_ensure_allocated(registry, NULL);
422 r = sd_bus_message_new_method_call(
425 "org.freedesktop.PolicyKit1",
426 "/org/freedesktop/PolicyKit1/Authority",
427 "org.freedesktop.PolicyKit1.Authority",
428 "CheckAuthorization");
432 r = sd_bus_message_append(
435 "system-bus-name", 1, "name", "s", sender,
443 q = new0(AsyncPolkitQuery, 1);
447 q->request = sd_bus_message_ref(call);
448 q->callback = callback;
449 q->userdata = userdata;
451 r = hashmap_put(*registry, call, q);
453 async_polkit_query_free(q);
457 q->registry = *registry;
459 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
461 async_polkit_query_free(q);
471 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
475 while ((q = hashmap_steal_first(registry)))
476 async_polkit_query_free(q);
478 hashmap_free(registry);
482 int bus_check_peercred(sd_bus *c) {
489 fd = sd_bus_get_fd(c);
493 l = sizeof(struct ucred);
494 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
497 if (l != sizeof(struct ucred))
500 if (ucred.uid != 0 && ucred.uid != geteuid())
506 int bus_open_system_systemd(sd_bus **_bus) {
507 _cleanup_bus_unref_ sd_bus *bus = NULL;
513 return sd_bus_open_system(_bus);
515 /* If we are root and kdbus is not available, then let's talk
516 * directly to the system instance, instead of going via the
520 r = sd_bus_new(&bus);
524 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
528 bus->bus_client = true;
530 r = sd_bus_start(bus);
537 bus = sd_bus_unref(bus);
540 r = sd_bus_new(&bus);
544 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
548 r = sd_bus_start(bus);
550 return sd_bus_open_system(_bus);
552 r = bus_check_peercred(bus);
562 int bus_open_user_systemd(sd_bus **_bus) {
563 _cleanup_bus_unref_ sd_bus *bus = NULL;
564 _cleanup_free_ char *ee = NULL;
568 /* Try via kdbus first, and then directly */
573 r = sd_bus_new(&bus);
577 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, getuid()) < 0)
580 bus->bus_client = true;
582 r = sd_bus_start(bus);
589 bus = sd_bus_unref(bus);
592 e = secure_getenv("XDG_RUNTIME_DIR");
594 return sd_bus_open_user(_bus);
596 ee = bus_address_escape(e);
600 r = sd_bus_new(&bus);
604 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
608 r = sd_bus_start(bus);
610 return sd_bus_open_user(_bus);
612 r = bus_check_peercred(bus);
622 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
624 const char *contents;
630 r = sd_bus_message_peek_type(property, &type, &contents);
636 case SD_BUS_TYPE_STRING: {
639 r = sd_bus_message_read_basic(property, type, &s);
643 if (all || !isempty(s))
644 printf("%s=%s\n", name, s);
649 case SD_BUS_TYPE_BOOLEAN: {
652 r = sd_bus_message_read_basic(property, type, &b);
656 printf("%s=%s\n", name, yes_no(b));
661 case SD_BUS_TYPE_UINT64: {
664 r = sd_bus_message_read_basic(property, type, &u);
668 /* Yes, heuristics! But we can change this check
669 * should it turn out to not be sufficient */
671 if (endswith(name, "Timestamp")) {
672 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
674 t = format_timestamp(timestamp, sizeof(timestamp), u);
676 printf("%s=%s\n", name, strempty(t));
678 } else if (strstr(name, "USec")) {
679 char timespan[FORMAT_TIMESPAN_MAX];
681 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
683 printf("%s=%llu\n", name, (unsigned long long) u);
688 case SD_BUS_TYPE_UINT32: {
691 r = sd_bus_message_read_basic(property, type, &u);
695 if (strstr(name, "UMask") || strstr(name, "Mode"))
696 printf("%s=%04o\n", name, u);
698 printf("%s=%u\n", name, (unsigned) u);
703 case SD_BUS_TYPE_INT32: {
706 r = sd_bus_message_read_basic(property, type, &i);
710 printf("%s=%i\n", name, (int) i);
714 case SD_BUS_TYPE_DOUBLE: {
717 r = sd_bus_message_read_basic(property, type, &d);
721 printf("%s=%g\n", name, d);
725 case SD_BUS_TYPE_ARRAY:
726 if (streq(contents, "s")) {
730 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
734 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
738 printf("%s%s", first ? "" : " ", str);
750 r = sd_bus_message_exit_container(property);
756 } else if (streq(contents, "y")) {
760 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
769 for (i = 0; i < n; i++)
770 printf("%02x", u[i]);
777 } else if (streq(contents, "u")) {
781 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
790 for (i = 0; i < n; i++)
791 printf("%08x", u[i]);
805 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
806 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
807 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
813 r = sd_bus_call_method(bus,
816 "org.freedesktop.DBus.Properties",
824 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
828 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
830 const char *contents;
832 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
836 if (!filter || strv_find(filter, name)) {
837 r = sd_bus_message_peek_type(reply, NULL, &contents);
841 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
845 r = bus_print_property(name, reply, all);
850 printf("%s=[unprintable]\n", name);
851 /* skip what we didn't read */
852 r = sd_bus_message_skip(reply, contents);
857 r = sd_bus_message_exit_container(reply);
861 r = sd_bus_message_skip(reply, "v");
866 r = sd_bus_message_exit_container(reply);
873 r = sd_bus_message_exit_container(reply);
880 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
881 sd_id128_t *p = userdata;
886 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
893 memcpy((*p).bytes, v, n);
900 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
904 r = sd_bus_message_peek_type(m, &type, NULL);
909 case SD_BUS_TYPE_STRING: {
914 r = sd_bus_message_read_basic(m, type, &s);
932 case SD_BUS_TYPE_ARRAY: {
933 _cleanup_strv_free_ char **l = NULL;
934 char ***p = userdata;
936 r = bus_message_read_strv_extend(m, &l);
947 case SD_BUS_TYPE_BOOLEAN: {
951 r = sd_bus_message_read_basic(m, type, &b);
960 case SD_BUS_TYPE_UINT32: {
962 uint32_t *p = userdata;
964 r = sd_bus_message_read_basic(m, type, &u);
973 case SD_BUS_TYPE_UINT64: {
975 uint64_t *p = userdata;
977 r = sd_bus_message_read_basic(m, type, &t);
993 int bus_message_map_all_properties(sd_bus *bus,
995 const struct bus_properties_map *map,
997 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1004 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1008 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1009 const struct bus_properties_map *prop;
1011 const char *contents;
1015 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1019 for (i = 0, prop = NULL; map[i].member; i++)
1020 if (streq(map[i].member, member)) {
1026 r = sd_bus_message_peek_type(m, NULL, &contents);
1030 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1034 v = (uint8_t *)userdata + prop->offset;
1036 r = prop->set(bus, member, m, &error, v);
1038 r = map_basic(bus, member, m, &error, v);
1042 r = sd_bus_message_exit_container(m);
1046 r = sd_bus_message_skip(m, "v");
1051 r = sd_bus_message_exit_container(m);
1056 return sd_bus_message_exit_container(m);
1059 int bus_message_map_properties_changed(sd_bus *bus,
1061 const struct bus_properties_map *map,
1064 int r, invalidated, i;
1070 r = bus_message_map_all_properties(bus, m, map, userdata);
1074 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1079 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1080 for (i = 0; map[i].member; i++)
1081 if (streq(map[i].member, member)) {
1086 r = sd_bus_message_exit_container(m);
1093 int bus_map_all_properties(sd_bus *bus,
1094 const char *destination,
1096 const struct bus_properties_map *map,
1098 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1099 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1103 assert(destination);
1107 r = sd_bus_call_method(
1111 "org.freedesktop.DBus.Properties",
1119 return bus_message_map_all_properties(bus, m, map, userdata);
1122 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1125 assert(transport >= 0);
1126 assert(transport < _BUS_TRANSPORT_MAX);
1129 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1130 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1132 switch (transport) {
1134 case BUS_TRANSPORT_LOCAL:
1136 r = sd_bus_default_user(bus);
1138 r = sd_bus_default_system(bus);
1142 case BUS_TRANSPORT_REMOTE:
1143 r = sd_bus_open_system_remote(bus, host);
1146 case BUS_TRANSPORT_CONTAINER:
1147 r = sd_bus_open_system_container(bus, host);
1151 assert_not_reached("Hmm, unknown transport type.");
1157 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1160 assert(transport >= 0);
1161 assert(transport < _BUS_TRANSPORT_MAX);
1164 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1165 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1167 switch (transport) {
1169 case BUS_TRANSPORT_LOCAL:
1171 r = bus_open_user_systemd(bus);
1173 r = bus_open_system_systemd(bus);
1177 case BUS_TRANSPORT_REMOTE:
1178 r = sd_bus_open_system_remote(bus, host);
1181 case BUS_TRANSPORT_CONTAINER:
1182 r = sd_bus_open_system_container(bus, host);
1186 assert_not_reached("Hmm, unknown transport type.");
1192 int bus_property_get_bool(
1195 const char *interface,
1196 const char *property,
1197 sd_bus_message *reply,
1199 sd_bus_error *error) {
1201 int b = *(bool*) userdata;
1203 return sd_bus_message_append_basic(reply, 'b', &b);
1206 #if __SIZEOF_SIZE_T__ != 8
1207 int bus_property_get_size(
1210 const char *interface,
1211 const char *property,
1212 sd_bus_message *reply,
1214 sd_bus_error *error) {
1216 uint64_t sz = *(size_t*) userdata;
1218 return sd_bus_message_append_basic(reply, 't', &sz);
1222 #if __SIZEOF_LONG__ != 8
1223 int bus_property_get_long(
1226 const char *interface,
1227 const char *property,
1228 sd_bus_message *reply,
1230 sd_bus_error *error) {
1232 int64_t l = *(long*) userdata;
1234 return sd_bus_message_append_basic(reply, 'x', &l);
1237 int bus_property_get_ulong(
1240 const char *interface,
1241 const char *property,
1242 sd_bus_message *reply,
1244 sd_bus_error *error) {
1246 uint64_t ul = *(unsigned long*) userdata;
1248 return sd_bus_message_append_basic(reply, 't', &ul);
1252 int bus_log_parse_error(int r) {
1253 log_error("Failed to parse bus message: %s", strerror(-r));
1257 int bus_log_create_error(int r) {
1258 log_error("Failed to create bus message: %s", strerror(-r));
1262 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1268 return sd_bus_message_read(
1283 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1287 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1288 sd_bus_reply_method_errno(m, r, error);
1290 } else if (sd_bus_error_is_set(error)) {
1291 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1292 sd_bus_reply_method_error(m, error);
1296 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1297 bus_message_type_to_string(m->header->type),
1300 strna(m->interface),
1302 strna(m->root_container.signature),
1303 bus_error_message(error, r));
1308 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1309 const char *eq, *field;
1315 eq = strchr(assignment, '=');
1317 log_error("Not an assignment: %s", assignment);
1321 field = strndupa(assignment, eq - assignment);
1324 if (streq(field, "CPUQuota")) {
1328 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1330 return bus_log_create_error(r);
1332 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1334 } else if (endswith(eq, "%")) {
1337 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1338 log_error("CPU quota '%s' invalid.", eq);
1342 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1344 return bus_log_create_error(r);
1346 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1348 log_error("CPU quota needs to be in percent.");
1353 return bus_log_create_error(r);
1358 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1360 return bus_log_create_error(r);
1362 if (STR_IN_SET(field,
1363 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1364 "SendSIGHUP", "SendSIGKILL")) {
1366 r = parse_boolean(eq);
1368 log_error("Failed to parse boolean assignment %s.", assignment);
1372 r = sd_bus_message_append(m, "v", "b", r);
1374 } else if (streq(field, "MemoryLimit")) {
1377 r = parse_size(eq, 1024, &bytes);
1379 log_error("Failed to parse bytes specification %s", assignment);
1383 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1385 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1388 r = safe_atou64(eq, &u);
1390 log_error("Failed to parse %s value %s.", field, eq);
1394 r = sd_bus_message_append(m, "v", "t", u);
1396 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1397 r = sd_bus_message_append(m, "v", "s", eq);
1399 else if (streq(field, "DeviceAllow")) {
1402 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1404 const char *path, *rwm, *e;
1406 e = strchr(eq, ' ');
1408 path = strndupa(eq, e - eq);
1415 if (!path_startswith(path, "/dev")) {
1416 log_error("%s is not a device file in /dev.", path);
1420 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1423 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1426 r = sd_bus_message_append(m, "v", "a(st)", 0);
1428 const char *path, *bandwidth, *e;
1431 e = strchr(eq, ' ');
1433 path = strndupa(eq, e - eq);
1436 log_error("Failed to parse %s value %s.", field, eq);
1440 if (!path_startswith(path, "/dev")) {
1441 log_error("%s is not a device file in /dev.", path);
1445 r = parse_size(bandwidth, 1000, &bytes);
1447 log_error("Failed to parse byte value %s.", bandwidth);
1451 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1454 } else if (streq(field, "BlockIODeviceWeight")) {
1457 r = sd_bus_message_append(m, "v", "a(st)", 0);
1459 const char *path, *weight, *e;
1462 e = strchr(eq, ' ');
1464 path = strndupa(eq, e - eq);
1467 log_error("Failed to parse %s value %s.", field, eq);
1471 if (!path_startswith(path, "/dev")) {
1472 log_error("%s is not a device file in /dev.", path);
1476 r = safe_atou64(weight, &u);
1478 log_error("Failed to parse %s value %s.", field, weight);
1481 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1484 } else if (rlimit_from_string(field) >= 0) {
1487 if (streq(eq, "infinity"))
1490 r = safe_atou64(eq, &rl);
1492 log_error("Invalid resource limit: %s", eq);
1497 r = sd_bus_message_append(m, "v", "t", rl);
1499 } else if (streq(field, "Nice")) {
1502 r = safe_atoi32(eq, &i);
1504 log_error("Failed to parse %s value %s.", field, eq);
1508 r = sd_bus_message_append(m, "v", "i", i);
1510 } else if (streq(field, "Environment")) {
1512 r = sd_bus_message_append(m, "v", "as", 1, eq);
1514 } else if (streq(field, "KillSignal")) {
1517 sig = signal_from_string_try_harder(eq);
1519 log_error("Failed to parse %s value %s.", field, eq);
1523 r = sd_bus_message_append(m, "v", "i", sig);
1526 log_error("Unknown assignment %s.", assignment);
1531 return bus_log_create_error(r);