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_ADDRESS
);
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_ADDRESS_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 _cleanup_free_
char *escaped
= NULL
;
646 escaped
= xescape(s
, "\n");
650 printf("%s=%s\n", name
, escaped
);
656 case SD_BUS_TYPE_BOOLEAN
: {
659 r
= sd_bus_message_read_basic(property
, type
, &b
);
663 printf("%s=%s\n", name
, yes_no(b
));
668 case SD_BUS_TYPE_UINT64
: {
671 r
= sd_bus_message_read_basic(property
, type
, &u
);
675 /* Yes, heuristics! But we can change this check
676 * should it turn out to not be sufficient */
678 if (endswith(name
, "Timestamp")) {
679 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
681 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
683 printf("%s=%s\n", name
, strempty(t
));
685 } else if (strstr(name
, "USec")) {
686 char timespan
[FORMAT_TIMESPAN_MAX
];
688 printf("%s=%s\n", name
, format_timespan(timespan
, sizeof(timespan
), u
, 0));
690 printf("%s=%llu\n", name
, (unsigned long long) u
);
695 case SD_BUS_TYPE_UINT32
: {
698 r
= sd_bus_message_read_basic(property
, type
, &u
);
702 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
703 printf("%s=%04o\n", name
, u
);
705 printf("%s=%u\n", name
, (unsigned) u
);
710 case SD_BUS_TYPE_INT32
: {
713 r
= sd_bus_message_read_basic(property
, type
, &i
);
717 printf("%s=%i\n", name
, (int) i
);
721 case SD_BUS_TYPE_DOUBLE
: {
724 r
= sd_bus_message_read_basic(property
, type
, &d
);
728 printf("%s=%g\n", name
, d
);
732 case SD_BUS_TYPE_ARRAY
:
733 if (streq(contents
, "s")) {
737 r
= sd_bus_message_enter_container(property
, SD_BUS_TYPE_ARRAY
, contents
);
741 while((r
= sd_bus_message_read_basic(property
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
742 _cleanup_free_
char *escaped
= NULL
;
747 escaped
= xescape(str
, "\n ");
751 printf("%s%s", first
? "" : " ", escaped
);
763 r
= sd_bus_message_exit_container(property
);
769 } else if (streq(contents
, "y")) {
773 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
782 for (i
= 0; i
< n
; i
++)
783 printf("%02x", u
[i
]);
790 } else if (streq(contents
, "u")) {
794 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
803 for (i
= 0; i
< n
; i
++)
804 printf("%08x", u
[i
]);
818 int bus_print_all_properties(sd_bus
*bus
, const char *dest
, const char *path
, char **filter
, bool all
) {
819 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
820 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
826 r
= sd_bus_call_method(bus
,
829 "org.freedesktop.DBus.Properties",
837 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
841 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
843 const char *contents
;
845 r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &name
);
849 if (!filter
|| strv_find(filter
, name
)) {
850 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
854 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
858 r
= bus_print_property(name
, reply
, all
);
863 printf("%s=[unprintable]\n", name
);
864 /* skip what we didn't read */
865 r
= sd_bus_message_skip(reply
, contents
);
870 r
= sd_bus_message_exit_container(reply
);
874 r
= sd_bus_message_skip(reply
, "v");
879 r
= sd_bus_message_exit_container(reply
);
886 r
= sd_bus_message_exit_container(reply
);
893 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
894 sd_id128_t
*p
= userdata
;
899 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
906 memcpy((*p
).bytes
, v
, n
);
913 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
917 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
922 case SD_BUS_TYPE_STRING
: {
927 r
= sd_bus_message_read_basic(m
, type
, &s
);
945 case SD_BUS_TYPE_ARRAY
: {
946 _cleanup_strv_free_
char **l
= NULL
;
947 char ***p
= userdata
;
949 r
= bus_message_read_strv_extend(m
, &l
);
960 case SD_BUS_TYPE_BOOLEAN
: {
964 r
= sd_bus_message_read_basic(m
, type
, &b
);
973 case SD_BUS_TYPE_UINT32
: {
975 uint32_t *p
= userdata
;
977 r
= sd_bus_message_read_basic(m
, type
, &u
);
986 case SD_BUS_TYPE_UINT64
: {
988 uint64_t *p
= userdata
;
990 r
= sd_bus_message_read_basic(m
, type
, &t
);
1006 int bus_message_map_all_properties(sd_bus
*bus
,
1008 const struct bus_properties_map
*map
,
1010 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1017 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1021 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1022 const struct bus_properties_map
*prop
;
1024 const char *contents
;
1028 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1032 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1033 if (streq(map
[i
].member
, member
)) {
1039 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1043 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1047 v
= (uint8_t *)userdata
+ prop
->offset
;
1049 r
= prop
->set(bus
, member
, m
, &error
, v
);
1051 r
= map_basic(bus
, member
, m
, &error
, v
);
1055 r
= sd_bus_message_exit_container(m
);
1059 r
= sd_bus_message_skip(m
, "v");
1064 r
= sd_bus_message_exit_container(m
);
1069 return sd_bus_message_exit_container(m
);
1072 int bus_message_map_properties_changed(sd_bus
*bus
,
1074 const struct bus_properties_map
*map
,
1077 int r
, invalidated
, i
;
1083 r
= bus_message_map_all_properties(bus
, m
, map
, userdata
);
1087 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1092 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1093 for (i
= 0; map
[i
].member
; i
++)
1094 if (streq(map
[i
].member
, member
)) {
1099 r
= sd_bus_message_exit_container(m
);
1106 int bus_map_all_properties(sd_bus
*bus
,
1107 const char *destination
,
1109 const struct bus_properties_map
*map
,
1111 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
1112 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1116 assert(destination
);
1120 r
= sd_bus_call_method(
1124 "org.freedesktop.DBus.Properties",
1132 return bus_message_map_all_properties(bus
, m
, map
, userdata
);
1135 int bus_open_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1138 assert(transport
>= 0);
1139 assert(transport
< _BUS_TRANSPORT_MAX
);
1142 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1143 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -ENOTSUP
);
1145 switch (transport
) {
1147 case BUS_TRANSPORT_LOCAL
:
1149 r
= sd_bus_default_user(bus
);
1151 r
= sd_bus_default_system(bus
);
1155 case BUS_TRANSPORT_REMOTE
:
1156 r
= sd_bus_open_system_remote(bus
, host
);
1159 case BUS_TRANSPORT_CONTAINER
:
1160 r
= sd_bus_open_system_container(bus
, host
);
1164 assert_not_reached("Hmm, unknown transport type.");
1170 int bus_open_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1173 assert(transport
>= 0);
1174 assert(transport
< _BUS_TRANSPORT_MAX
);
1177 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1178 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -ENOTSUP
);
1180 switch (transport
) {
1182 case BUS_TRANSPORT_LOCAL
:
1184 r
= bus_open_user_systemd(bus
);
1186 r
= bus_open_system_systemd(bus
);
1190 case BUS_TRANSPORT_REMOTE
:
1191 r
= sd_bus_open_system_remote(bus
, host
);
1194 case BUS_TRANSPORT_CONTAINER
:
1195 r
= sd_bus_open_system_container(bus
, host
);
1199 assert_not_reached("Hmm, unknown transport type.");
1205 int bus_property_get_bool(
1208 const char *interface
,
1209 const char *property
,
1210 sd_bus_message
*reply
,
1212 sd_bus_error
*error
) {
1214 int b
= *(bool*) userdata
;
1216 return sd_bus_message_append_basic(reply
, 'b', &b
);
1219 #if __SIZEOF_SIZE_T__ != 8
1220 int bus_property_get_size(
1223 const char *interface
,
1224 const char *property
,
1225 sd_bus_message
*reply
,
1227 sd_bus_error
*error
) {
1229 uint64_t sz
= *(size_t*) userdata
;
1231 return sd_bus_message_append_basic(reply
, 't', &sz
);
1235 #if __SIZEOF_LONG__ != 8
1236 int bus_property_get_long(
1239 const char *interface
,
1240 const char *property
,
1241 sd_bus_message
*reply
,
1243 sd_bus_error
*error
) {
1245 int64_t l
= *(long*) userdata
;
1247 return sd_bus_message_append_basic(reply
, 'x', &l
);
1250 int bus_property_get_ulong(
1253 const char *interface
,
1254 const char *property
,
1255 sd_bus_message
*reply
,
1257 sd_bus_error
*error
) {
1259 uint64_t ul
= *(unsigned long*) userdata
;
1261 return sd_bus_message_append_basic(reply
, 't', &ul
);
1265 int bus_log_parse_error(int r
) {
1266 return log_error_errno(r
, "Failed to parse bus message: %m");
1269 int bus_log_create_error(int r
) {
1270 return log_error_errno(r
, "Failed to create bus message: %m");
1273 int bus_parse_unit_info(sd_bus_message
*message
, UnitInfo
*u
) {
1279 return sd_bus_message_read(
1294 int bus_maybe_reply_error(sd_bus_message
*m
, int r
, sd_bus_error
*error
) {
1298 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1299 sd_bus_reply_method_errno(m
, r
, error
);
1301 } else if (sd_bus_error_is_set(error
)) {
1302 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1303 sd_bus_reply_method_error(m
, error
);
1307 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1308 bus_message_type_to_string(m
->header
->type
),
1311 strna(m
->interface
),
1313 strna(m
->root_container
.signature
),
1314 bus_error_message(error
, r
));
1319 int bus_append_unit_property_assignment(sd_bus_message
*m
, const char *assignment
) {
1320 const char *eq
, *field
;
1326 eq
= strchr(assignment
, '=');
1328 log_error("Not an assignment: %s", assignment
);
1332 field
= strndupa(assignment
, eq
- assignment
);
1335 if (streq(field
, "CPUQuota")) {
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_INFINITY
);
1345 } else if (endswith(eq
, "%")) {
1348 if (sscanf(eq
, "%lf%%", &percent
) != 1 || percent
<= 0) {
1349 log_error("CPU quota '%s' invalid.", eq
);
1353 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "CPUQuotaPerSecUSec");
1355 return bus_log_create_error(r
);
1357 r
= sd_bus_message_append(m
, "v", "t", (usec_t
) percent
* USEC_PER_SEC
/ 100);
1359 log_error("CPU quota needs to be in percent.");
1364 return bus_log_create_error(r
);
1369 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, field
);
1371 return bus_log_create_error(r
);
1373 if (STR_IN_SET(field
,
1374 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1375 "SendSIGHUP", "SendSIGKILL",
1378 r
= parse_boolean(eq
);
1380 log_error("Failed to parse boolean assignment %s.", assignment
);
1384 r
= sd_bus_message_append(m
, "v", "b", r
);
1386 } else if (streq(field
, "MemoryLimit")) {
1389 r
= parse_size(eq
, 1024, &bytes
);
1391 log_error("Failed to parse bytes specification %s", assignment
);
1395 r
= sd_bus_message_append(m
, "v", "t", (uint64_t) bytes
);
1397 } else if (STR_IN_SET(field
, "CPUShares", "BlockIOWeight")) {
1400 r
= safe_atou64(eq
, &u
);
1402 log_error("Failed to parse %s value %s.", field
, eq
);
1406 r
= sd_bus_message_append(m
, "v", "t", u
);
1408 } else if (STR_IN_SET(field
, "User", "Group", "DevicePolicy", "KillMode"))
1409 r
= sd_bus_message_append(m
, "v", "s", eq
);
1411 else if (streq(field
, "DeviceAllow")) {
1414 r
= sd_bus_message_append(m
, "v", "a(ss)", 0);
1416 const char *path
, *rwm
, *e
;
1418 e
= strchr(eq
, ' ');
1420 path
= strndupa(eq
, e
- eq
);
1427 if (!path_startswith(path
, "/dev")) {
1428 log_error("%s is not a device file in /dev.", path
);
1432 r
= sd_bus_message_append(m
, "v", "a(ss)", 1, path
, rwm
);
1435 } else if (STR_IN_SET(field
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1438 r
= sd_bus_message_append(m
, "v", "a(st)", 0);
1440 const char *path
, *bandwidth
, *e
;
1443 e
= strchr(eq
, ' ');
1445 path
= strndupa(eq
, e
- eq
);
1448 log_error("Failed to parse %s value %s.", field
, eq
);
1452 if (!path_startswith(path
, "/dev")) {
1453 log_error("%s is not a device file in /dev.", path
);
1457 r
= parse_size(bandwidth
, 1000, &bytes
);
1459 log_error("Failed to parse byte value %s.", bandwidth
);
1463 r
= sd_bus_message_append(m
, "v", "a(st)", 1, path
, (uint64_t) bytes
);
1466 } else if (streq(field
, "BlockIODeviceWeight")) {
1469 r
= sd_bus_message_append(m
, "v", "a(st)", 0);
1471 const char *path
, *weight
, *e
;
1474 e
= strchr(eq
, ' ');
1476 path
= strndupa(eq
, e
- eq
);
1479 log_error("Failed to parse %s value %s.", field
, eq
);
1483 if (!path_startswith(path
, "/dev")) {
1484 log_error("%s is not a device file in /dev.", path
);
1488 r
= safe_atou64(weight
, &u
);
1490 log_error("Failed to parse %s value %s.", field
, weight
);
1493 r
= sd_bus_message_append(m
, "v", "a(st)", path
, u
);
1496 } else if (rlimit_from_string(field
) >= 0) {
1499 if (streq(eq
, "infinity"))
1502 r
= safe_atou64(eq
, &rl
);
1504 log_error("Invalid resource limit: %s", eq
);
1509 r
= sd_bus_message_append(m
, "v", "t", rl
);
1511 } else if (streq(field
, "Nice")) {
1514 r
= safe_atoi32(eq
, &i
);
1516 log_error("Failed to parse %s value %s.", field
, eq
);
1520 r
= sd_bus_message_append(m
, "v", "i", i
);
1522 } else if (streq(field
, "Environment")) {
1524 r
= sd_bus_message_append(m
, "v", "as", 1, eq
);
1526 } else if (streq(field
, "KillSignal")) {
1529 sig
= signal_from_string_try_harder(eq
);
1531 log_error("Failed to parse %s value %s.", field
, eq
);
1535 r
= sd_bus_message_append(m
, "v", "i", sig
);
1537 } else if (streq(field
, "AccuracySec")) {
1540 r
= parse_sec(eq
, &u
);
1542 log_error("Failed to parse %s value %s", field
, eq
);
1546 r
= sd_bus_message_append(m
, "v", "t", u
);
1549 log_error("Unknown assignment %s.", assignment
);
1554 return bus_log_create_error(r
);