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>
29 #include "path-util.h"
34 #include "bus-error.h"
35 #include "bus-message.h"
37 #include "bus-internal.h"
39 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
40 sd_event *e = userdata;
50 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
51 _cleanup_free_ char *match = NULL;
59 /* We unregister the name here and then wait for the
60 * NameOwnerChanged signal for this event to arrive before we
61 * quit. We do this in order to make sure that any queued
62 * requests are still processed before we really exit. */
64 r = sd_bus_get_unique_name(bus, &unique);
69 "sender='org.freedesktop.DBus',"
71 "interface='org.freedesktop.DBus',"
72 "member='NameOwnerChanged',"
73 "path='/org/freedesktop/DBus',"
76 "arg2=''", name, unique);
80 r = sd_bus_add_match(bus, match, name_owner_change_callback, e);
84 r = sd_bus_release_name(bus, name);
91 int bus_event_loop_with_idle(
96 check_idle_t check_idle,
108 r = sd_event_get_state(e);
111 if (r == SD_EVENT_FINISHED)
115 idle = check_idle(userdata);
119 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
123 if (r == 0 && !exiting) {
124 r = bus_async_unregister_and_exit(e, bus, name);
132 r = sd_event_get_exit_code(e, &code);
139 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
140 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
141 int r, has_owner = 0;
146 r = sd_bus_call_method(c,
147 "org.freedesktop.DBus",
148 "/org/freedesktop/dbus",
149 "org.freedesktop.DBus",
158 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
160 return sd_bus_error_set_errno(error, r);
165 int bus_verify_polkit(
173 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
181 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
185 r = sd_bus_creds_get_uid(creds, &uid);
194 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
195 int authorized = false, challenge = false;
198 sender = sd_bus_message_get_sender(m);
202 r = sd_bus_call_method(
204 "org.freedesktop.PolicyKit1",
205 "/org/freedesktop/PolicyKit1/Authority",
206 "org.freedesktop.PolicyKit1.Authority",
207 "CheckAuthorization",
211 "system-bus-name", 1, "name", "s", sender,
218 /* Treat no PK available as access denied */
219 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
220 sd_bus_error_free(e);
227 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
231 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
239 *_challenge = challenge;
250 typedef struct AsyncPolkitQuery {
251 sd_bus_message *request, *reply;
252 sd_bus_message_handler_t callback;
258 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
263 if (q->serial > 0 && b)
264 sd_bus_call_async_cancel(b, q->serial);
266 if (q->registry && q->request)
267 hashmap_remove(q->registry, q->request);
269 sd_bus_message_unref(q->request);
270 sd_bus_message_unref(q->reply);
275 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
276 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
277 AsyncPolkitQuery *q = userdata;
284 q->reply = sd_bus_message_ref(reply);
287 r = sd_bus_message_rewind(q->request, true);
289 r = sd_bus_reply_method_errno(q->request, r, NULL);
293 r = q->callback(bus, q->request, q->userdata, &error_buffer);
294 r = bus_maybe_reply_error(q->request, r, &error_buffer);
297 async_polkit_query_free(bus, q);
303 int bus_verify_polkit_async(
310 sd_bus_message_handler_t callback,
314 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
318 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
328 q = hashmap_get(*registry, m);
330 int authorized, challenge;
332 /* This is the second invocation of this function, and
333 * there's already a response from polkit, let's
337 if (sd_bus_message_is_method_error(q->reply, NULL)) {
338 const sd_bus_error *e;
340 /* Copy error from polkit reply */
341 e = sd_bus_message_get_error(q->reply);
342 sd_bus_error_copy(error, e);
344 /* Treat no PK available as access denied */
345 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
348 return -sd_bus_error_get_errno(e);
351 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
353 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
365 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
369 r = sd_bus_creds_get_uid(creds, &uid);
377 sender = sd_bus_message_get_sender(m);
381 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
385 r = sd_bus_message_new_method_call(
388 "org.freedesktop.PolicyKit1",
389 "/org/freedesktop/PolicyKit1/Authority",
390 "org.freedesktop.PolicyKit1.Authority",
391 "CheckAuthorization");
395 r = sd_bus_message_append(
398 "system-bus-name", 1, "name", "s", sender,
406 q = new0(AsyncPolkitQuery, 1);
410 q->request = sd_bus_message_ref(m);
411 q->callback = callback;
412 q->userdata = userdata;
414 r = hashmap_put(*registry, m, q);
416 async_polkit_query_free(bus, q);
420 q->registry = *registry;
422 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
424 async_polkit_query_free(bus, q);
434 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
438 while ((q = hashmap_steal_first(registry)))
439 async_polkit_query_free(bus, q);
441 hashmap_free(registry);
445 int bus_check_peercred(sd_bus *c) {
452 fd = sd_bus_get_fd(c);
456 l = sizeof(struct ucred);
457 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
460 if (l != sizeof(struct ucred))
463 if (ucred.uid != 0 && ucred.uid != geteuid())
469 int bus_open_system_systemd(sd_bus **_bus) {
470 _cleanup_bus_unref_ sd_bus *bus = NULL;
476 return sd_bus_open_system(_bus);
478 /* If we are root and kdbus is not available, then let's talk
479 * directly to the system instance, instead of going via the
483 r = sd_bus_new(&bus);
487 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
491 bus->bus_client = true;
493 r = sd_bus_start(bus);
500 bus = sd_bus_unref(bus);
503 r = sd_bus_new(&bus);
507 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
511 r = sd_bus_start(bus);
513 return sd_bus_open_system(_bus);
515 r = bus_check_peercred(bus);
525 int bus_open_user_systemd(sd_bus **_bus) {
526 _cleanup_bus_unref_ sd_bus *bus = NULL;
527 _cleanup_free_ char *ee = NULL;
531 /* Try via kdbus first, and then directly */
536 r = sd_bus_new(&bus);
540 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid()) < 0)
543 bus->bus_client = true;
545 r = sd_bus_start(bus);
552 bus = sd_bus_unref(bus);
555 e = secure_getenv("XDG_RUNTIME_DIR");
557 return sd_bus_open_user(_bus);
559 ee = bus_address_escape(e);
563 r = sd_bus_new(&bus);
567 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
571 r = sd_bus_start(bus);
573 return sd_bus_open_user(_bus);
575 r = bus_check_peercred(bus);
585 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
587 const char *contents;
593 r = sd_bus_message_peek_type(property, &type, &contents);
599 case SD_BUS_TYPE_STRING: {
602 r = sd_bus_message_read_basic(property, type, &s);
606 if (all || !isempty(s))
607 printf("%s=%s\n", name, s);
612 case SD_BUS_TYPE_BOOLEAN: {
615 r = sd_bus_message_read_basic(property, type, &b);
619 printf("%s=%s\n", name, yes_no(b));
624 case SD_BUS_TYPE_UINT64: {
627 r = sd_bus_message_read_basic(property, type, &u);
631 /* Yes, heuristics! But we can change this check
632 * should it turn out to not be sufficient */
634 if (endswith(name, "Timestamp")) {
635 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
637 t = format_timestamp(timestamp, sizeof(timestamp), u);
639 printf("%s=%s\n", name, strempty(t));
641 } else if (strstr(name, "USec")) {
642 char timespan[FORMAT_TIMESPAN_MAX];
644 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
646 printf("%s=%llu\n", name, (unsigned long long) u);
651 case SD_BUS_TYPE_UINT32: {
654 r = sd_bus_message_read_basic(property, type, &u);
658 if (strstr(name, "UMask") || strstr(name, "Mode"))
659 printf("%s=%04o\n", name, u);
661 printf("%s=%u\n", name, (unsigned) u);
666 case SD_BUS_TYPE_INT32: {
669 r = sd_bus_message_read_basic(property, type, &i);
673 printf("%s=%i\n", name, (int) i);
677 case SD_BUS_TYPE_DOUBLE: {
680 r = sd_bus_message_read_basic(property, type, &d);
684 printf("%s=%g\n", name, d);
688 case SD_BUS_TYPE_ARRAY:
689 if (streq(contents, "s")) {
693 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
697 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
701 printf("%s%s", first ? "" : " ", str);
713 r = sd_bus_message_exit_container(property);
719 } else if (streq(contents, "y")) {
723 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
732 for (i = 0; i < n; i++)
733 printf("%02x", u[i]);
740 } else if (streq(contents, "u")) {
744 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
753 for (i = 0; i < n; i++)
754 printf("%08x", u[i]);
768 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
769 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
770 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
776 r = sd_bus_call_method(bus,
779 "org.freedesktop.DBus.Properties",
787 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
791 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
793 const char *contents;
795 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
799 if (!filter || strv_find(filter, name)) {
800 r = sd_bus_message_peek_type(reply, NULL, &contents);
804 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
808 r = bus_print_property(name, reply, all);
813 printf("%s=[unprintable]\n", name);
814 /* skip what we didn't read */
815 r = sd_bus_message_skip(reply, contents);
820 r = sd_bus_message_exit_container(reply);
824 r = sd_bus_message_skip(reply, "v");
829 r = sd_bus_message_exit_container(reply);
836 r = sd_bus_message_exit_container(reply);
843 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
844 sd_id128_t *p = userdata;
849 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
856 memcpy((*p).bytes, v, n);
863 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
867 r = sd_bus_message_peek_type(m, &type, NULL);
872 case SD_BUS_TYPE_STRING: {
877 r = sd_bus_message_read_basic(m, type, &s);
895 case SD_BUS_TYPE_ARRAY: {
896 _cleanup_strv_free_ char **l = NULL;
897 char ***p = userdata;
899 r = bus_message_read_strv_extend(m, &l);
910 case SD_BUS_TYPE_BOOLEAN: {
914 r = sd_bus_message_read_basic(m, type, &b);
923 case SD_BUS_TYPE_UINT32: {
925 uint32_t *p = userdata;
927 r = sd_bus_message_read_basic(m, type, &u);
936 case SD_BUS_TYPE_UINT64: {
938 uint64_t *p = userdata;
940 r = sd_bus_message_read_basic(m, type, &t);
956 int bus_map_all_properties(sd_bus *bus,
957 const char *destination,
959 const struct bus_properties_map *map,
961 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
962 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
970 r = sd_bus_call_method(
974 "org.freedesktop.DBus.Properties",
982 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
986 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
987 const struct bus_properties_map *prop;
989 const char *contents;
993 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
997 for (i = 0, prop = NULL; map[i].member; i++)
998 if (streq(map[i].member, member)) {
1004 r = sd_bus_message_peek_type(m, NULL, &contents);
1008 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1012 v = (uint8_t *)userdata + prop->offset;
1014 r = prop->set(bus, member, m, &error, v);
1016 r = map_basic(bus, member, m, &error, v);
1020 r = sd_bus_message_exit_container(m);
1024 r = sd_bus_message_skip(m, "v");
1029 r = sd_bus_message_exit_container(m);
1037 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1040 assert(transport >= 0);
1041 assert(transport < _BUS_TRANSPORT_MAX);
1044 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1045 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1047 switch (transport) {
1049 case BUS_TRANSPORT_LOCAL:
1051 r = sd_bus_default_user(bus);
1053 r = sd_bus_default_system(bus);
1057 case BUS_TRANSPORT_REMOTE:
1058 r = sd_bus_open_system_remote(bus, host);
1061 case BUS_TRANSPORT_CONTAINER:
1062 r = sd_bus_open_system_container(bus, host);
1066 assert_not_reached("Hmm, unknown transport type.");
1072 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1075 assert(transport >= 0);
1076 assert(transport < _BUS_TRANSPORT_MAX);
1079 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1080 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1082 switch (transport) {
1084 case BUS_TRANSPORT_LOCAL:
1086 r = bus_open_user_systemd(bus);
1088 r = bus_open_system_systemd(bus);
1092 case BUS_TRANSPORT_REMOTE:
1093 r = sd_bus_open_system_remote(bus, host);
1096 case BUS_TRANSPORT_CONTAINER:
1097 r = sd_bus_open_system_container(bus, host);
1101 assert_not_reached("Hmm, unknown transport type.");
1107 int bus_property_get_tristate(
1110 const char *interface,
1111 const char *property,
1112 sd_bus_message *reply,
1114 sd_bus_error *error) {
1116 int *tristate = userdata;
1118 return sd_bus_message_append(reply, "b", *tristate > 0);
1121 int bus_property_get_bool(
1124 const char *interface,
1125 const char *property,
1126 sd_bus_message *reply,
1128 sd_bus_error *error) {
1130 int b = *(bool*) userdata;
1132 return sd_bus_message_append_basic(reply, 'b', &b);
1135 #if __SIZEOF_SIZE_T__ != 8
1136 int bus_property_get_size(
1139 const char *interface,
1140 const char *property,
1141 sd_bus_message *reply,
1143 sd_bus_error *error) {
1145 uint64_t sz = *(size_t*) userdata;
1147 return sd_bus_message_append_basic(reply, 't', &sz);
1151 #if __SIZEOF_LONG__ != 8
1152 int bus_property_get_long(
1155 const char *interface,
1156 const char *property,
1157 sd_bus_message *reply,
1159 sd_bus_error *error) {
1161 int64_t l = *(long*) userdata;
1163 return sd_bus_message_append_basic(reply, 'x', &l);
1166 int bus_property_get_ulong(
1169 const char *interface,
1170 const char *property,
1171 sd_bus_message *reply,
1173 sd_bus_error *error) {
1175 uint64_t ul = *(unsigned long*) userdata;
1177 return sd_bus_message_append_basic(reply, 't', &ul);
1181 int bus_log_parse_error(int r) {
1182 log_error("Failed to parse message: %s", strerror(-r));
1186 int bus_log_create_error(int r) {
1187 log_error("Failed to create message: %s", strerror(-r));
1191 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1197 return sd_bus_message_read(
1212 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1216 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1217 sd_bus_reply_method_errno(m, r, error);
1219 } else if (sd_bus_error_is_set(error)) {
1220 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1221 sd_bus_reply_method_error(m, error);
1225 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1226 bus_message_type_to_string(m->header->type),
1229 strna(m->interface),
1231 strna(m->root_container.signature),
1232 bus_error_message(error, r));
1237 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1238 const char *eq, *field;
1244 eq = strchr(assignment, '=');
1246 log_error("Not an assignment: %s", assignment);
1250 field = strndupa(assignment, eq - assignment);
1253 if (streq(field, "CPUQuota")) {
1257 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1259 return bus_log_create_error(r);
1261 r = sd_bus_message_append(m, "v", "t", (usec_t) -1);
1263 } else if (endswith(eq, "%")) {
1266 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1267 log_error("CPU quota '%s' invalid.", eq);
1271 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1273 return bus_log_create_error(r);
1275 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1279 r = parse_sec(eq, &us);
1281 log_error("CPU quota '%s' invalid.", eq);
1285 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaUSec");
1287 return bus_log_create_error(r);
1289 r = sd_bus_message_append(m, "v", "t", us);
1293 return bus_log_create_error(r);
1297 } else if (streq(field, "CPUQuotaPeriodSec")) {
1300 r = parse_sec(eq, &us);
1302 log_error("CPU period '%s' invalid.", eq);
1306 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPeriodUSec");
1308 return bus_log_create_error(r);
1310 r = sd_bus_message_append(m, "v", "t", us);
1312 return bus_log_create_error(r);
1317 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1319 return bus_log_create_error(r);
1321 if (STR_IN_SET(field,
1322 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1323 "SendSIGHUP", "SendSIGKILL")) {
1325 r = parse_boolean(eq);
1327 log_error("Failed to parse boolean assignment %s.", assignment);
1331 r = sd_bus_message_append(m, "v", "b", r);
1333 } else if (streq(field, "MemoryLimit")) {
1336 r = parse_size(eq, 1024, &bytes);
1338 log_error("Failed to parse bytes specification %s", assignment);
1342 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1344 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1347 r = safe_atou64(eq, &u);
1349 log_error("Failed to parse %s value %s.", field, eq);
1353 r = sd_bus_message_append(m, "v", "t", u);
1355 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1356 r = sd_bus_message_append(m, "v", "s", eq);
1358 else if (streq(field, "DeviceAllow")) {
1361 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1363 const char *path, *rwm, *e;
1365 e = strchr(eq, ' ');
1367 path = strndupa(eq, e - eq);
1374 if (!path_startswith(path, "/dev")) {
1375 log_error("%s is not a device file in /dev.", path);
1379 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1382 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1385 r = sd_bus_message_append(m, "v", "a(st)", 0);
1387 const char *path, *bandwidth, *e;
1390 e = strchr(eq, ' ');
1392 path = strndupa(eq, e - eq);
1395 log_error("Failed to parse %s value %s.", field, eq);
1399 if (!path_startswith(path, "/dev")) {
1400 log_error("%s is not a device file in /dev.", path);
1404 r = parse_size(bandwidth, 1000, &bytes);
1406 log_error("Failed to parse byte value %s.", bandwidth);
1410 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1413 } else if (streq(field, "BlockIODeviceWeight")) {
1416 r = sd_bus_message_append(m, "v", "a(st)", 0);
1418 const char *path, *weight, *e;
1421 e = strchr(eq, ' ');
1423 path = strndupa(eq, e - eq);
1426 log_error("Failed to parse %s value %s.", field, eq);
1430 if (!path_startswith(path, "/dev")) {
1431 log_error("%s is not a device file in /dev.", path);
1435 r = safe_atou64(weight, &u);
1437 log_error("Failed to parse %s value %s.", field, weight);
1440 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1443 } else if (rlimit_from_string(field) >= 0) {
1446 if (streq(eq, "infinity"))
1449 r = safe_atou64(eq, &rl);
1451 log_error("Invalid resource limit: %s", eq);
1456 r = sd_bus_message_append(m, "v", "t", rl);
1458 } else if (streq(field, "Nice")) {
1461 r = safe_atoi32(eq, &i);
1463 log_error("Failed to parse %s value %s.", field, eq);
1467 r = sd_bus_message_append(m, "v", "i", i);
1469 } else if (streq(field, "Environment")) {
1471 r = sd_bus_message_append(m, "v", "as", 1, eq);
1473 } else if (streq(field, "KillSignal")) {
1476 sig = signal_from_string_try_harder(eq);
1478 log_error("Failed to parse %s value %s.", field, eq);
1482 r = sd_bus_message_append(m, "v", "i", sig);
1485 log_error("Unknown assignment %s.", assignment);
1490 return bus_log_create_error(r);