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>
25 #include "sd-daemon.h"
28 #include "bus-error.h"
29 #include "bus-internal.h"
30 #include "bus-label.h"
31 #include "bus-message.h"
33 #include "cgroup-util.h"
40 #include "parse-util.h"
41 #include "path-util.h"
43 #include "signal-util.h"
44 #include "string-util.h"
46 #include "unit-name.h"
50 static int name_owner_change_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
51 sd_event
*e
= userdata
;
56 sd_bus_close(sd_bus_message_get_bus(m
));
62 int bus_async_unregister_and_exit(sd_event
*e
, sd_bus
*bus
, const char *name
) {
63 _cleanup_free_
char *match
= NULL
;
71 /* We unregister the name here and then wait for the
72 * NameOwnerChanged signal for this event to arrive before we
73 * quit. We do this in order to make sure that any queued
74 * requests are still processed before we really exit. */
76 r
= sd_bus_get_unique_name(bus
, &unique
);
81 "sender='org.freedesktop.DBus',"
83 "interface='org.freedesktop.DBus',"
84 "member='NameOwnerChanged',"
85 "path='/org/freedesktop/DBus',"
88 "arg2=''", name
, unique
);
92 r
= sd_bus_add_match(bus
, NULL
, match
, name_owner_change_callback
, e
);
96 r
= sd_bus_release_name(bus
, name
);
103 int bus_event_loop_with_idle(
108 check_idle_t check_idle
,
110 bool exiting
= false;
120 r
= sd_event_get_state(e
);
123 if (r
== SD_EVENT_FINISHED
)
127 idle
= check_idle(userdata
);
131 r
= sd_event_run(e
, exiting
|| !idle
? (uint64_t) -1 : timeout
);
135 if (r
== 0 && !exiting
&& idle
) {
137 r
= sd_bus_try_close(bus
);
141 /* Fallback for dbus1 connections: we
142 * unregister the name and wait for the
143 * response to come through for it */
144 if (r
== -EOPNOTSUPP
) {
146 /* Inform the service manager that we
147 * are going down, so that it will
148 * queue all further start requests,
149 * instead of assuming we are already
151 sd_notify(false, "STOPPING=1");
153 r
= bus_async_unregister_and_exit(e
, bus
, name
);
169 r
= sd_event_get_exit_code(e
, &code
);
176 int bus_name_has_owner(sd_bus
*c
, const char *name
, sd_bus_error
*error
) {
177 _cleanup_bus_message_unref_ sd_bus_message
*rep
= NULL
;
178 int r
, has_owner
= 0;
183 r
= sd_bus_call_method(c
,
184 "org.freedesktop.DBus",
185 "/org/freedesktop/dbus",
186 "org.freedesktop.DBus",
195 r
= sd_bus_message_read_basic(rep
, 'b', &has_owner
);
197 return sd_bus_error_set_errno(error
, r
);
202 static int check_good_user(sd_bus_message
*m
, uid_t good_user
) {
203 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
209 if (good_user
== UID_INVALID
)
212 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_EUID
, &creds
);
216 /* Don't trust augmented credentials for authorization */
217 assert_return((sd_bus_creds_get_augmented_mask(creds
) & SD_BUS_CREDS_EUID
) == 0, -EPERM
);
219 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
223 return sender_uid
== good_user
;
227 sd_bus_message
*call
,
230 const char **details
,
240 /* Tests non-interactively! */
242 r
= check_good_user(call
, good_user
);
246 r
= sd_bus_query_sender_privilege(call
, capability
);
253 _cleanup_bus_message_unref_ sd_bus_message
*request
= NULL
;
254 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
255 int authorized
= false, challenge
= false;
256 const char *sender
, **k
, **v
;
258 sender
= sd_bus_message_get_sender(call
);
262 r
= sd_bus_message_new_method_call(
265 "org.freedesktop.PolicyKit1",
266 "/org/freedesktop/PolicyKit1/Authority",
267 "org.freedesktop.PolicyKit1.Authority",
268 "CheckAuthorization");
272 r
= sd_bus_message_append(
275 "system-bus-name", 1, "name", "s", sender
,
280 r
= sd_bus_message_open_container(request
, 'a', "{ss}");
284 STRV_FOREACH_PAIR(k
, v
, details
) {
285 r
= sd_bus_message_append(request
, "{ss}", *k
, *v
);
290 r
= sd_bus_message_close_container(request
);
294 r
= sd_bus_message_append(request
, "us", 0, NULL
);
298 r
= sd_bus_call(call
->bus
, request
, 0, e
, &reply
);
300 /* Treat no PK available as access denied */
301 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
)) {
302 sd_bus_error_free(e
);
309 r
= sd_bus_message_enter_container(reply
, 'r', "bba{ss}");
313 r
= sd_bus_message_read(reply
, "bb", &authorized
, &challenge
);
321 *_challenge
= challenge
;
332 typedef struct AsyncPolkitQuery
{
333 sd_bus_message
*request
, *reply
;
334 sd_bus_message_handler_t callback
;
340 static void async_polkit_query_free(AsyncPolkitQuery
*q
) {
345 sd_bus_slot_unref(q
->slot
);
347 if (q
->registry
&& q
->request
)
348 hashmap_remove(q
->registry
, q
->request
);
350 sd_bus_message_unref(q
->request
);
351 sd_bus_message_unref(q
->reply
);
356 static int async_polkit_callback(sd_bus_message
*reply
, void *userdata
, sd_bus_error
*error
) {
357 _cleanup_bus_error_free_ sd_bus_error error_buffer
= SD_BUS_ERROR_NULL
;
358 AsyncPolkitQuery
*q
= userdata
;
364 q
->slot
= sd_bus_slot_unref(q
->slot
);
365 q
->reply
= sd_bus_message_ref(reply
);
367 r
= sd_bus_message_rewind(q
->request
, true);
369 r
= sd_bus_reply_method_errno(q
->request
, r
, NULL
);
373 r
= q
->callback(q
->request
, q
->userdata
, &error_buffer
);
374 r
= bus_maybe_reply_error(q
->request
, r
, &error_buffer
);
377 async_polkit_query_free(q
);
384 int bus_verify_polkit_async(
385 sd_bus_message
*call
,
388 const char **details
,
392 sd_bus_error
*error
) {
395 _cleanup_bus_message_unref_ sd_bus_message
*pk
= NULL
;
397 const char *sender
, **k
, **v
;
398 sd_bus_message_handler_t callback
;
408 r
= check_good_user(call
, good_user
);
413 q
= hashmap_get(*registry
, call
);
415 int authorized
, challenge
;
417 /* This is the second invocation of this function, and
418 * there's already a response from polkit, let's
422 if (sd_bus_message_is_method_error(q
->reply
, NULL
)) {
423 const sd_bus_error
*e
;
425 /* Copy error from polkit reply */
426 e
= sd_bus_message_get_error(q
->reply
);
427 sd_bus_error_copy(error
, e
);
429 /* Treat no PK available as access denied */
430 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
))
433 return -sd_bus_error_get_errno(e
);
436 r
= sd_bus_message_enter_container(q
->reply
, 'r', "bba{ss}");
438 r
= sd_bus_message_read(q
->reply
, "bb", &authorized
, &challenge
);
447 return sd_bus_error_set(error
, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED
, "Interactive authentication required.");
453 r
= sd_bus_query_sender_privilege(call
, capability
);
460 if (sd_bus_get_current_message(call
->bus
) != call
)
463 callback
= sd_bus_get_current_handler(call
->bus
);
467 userdata
= sd_bus_get_current_userdata(call
->bus
);
469 sender
= sd_bus_message_get_sender(call
);
473 c
= sd_bus_message_get_allow_interactive_authorization(call
);
479 r
= hashmap_ensure_allocated(registry
, NULL
);
483 r
= sd_bus_message_new_method_call(
486 "org.freedesktop.PolicyKit1",
487 "/org/freedesktop/PolicyKit1/Authority",
488 "org.freedesktop.PolicyKit1.Authority",
489 "CheckAuthorization");
493 r
= sd_bus_message_append(
496 "system-bus-name", 1, "name", "s", sender
,
501 r
= sd_bus_message_open_container(pk
, 'a', "{ss}");
505 STRV_FOREACH_PAIR(k
, v
, details
) {
506 r
= sd_bus_message_append(pk
, "{ss}", *k
, *v
);
511 r
= sd_bus_message_close_container(pk
);
515 r
= sd_bus_message_append(pk
, "us", !!interactive
, NULL
);
519 q
= new0(AsyncPolkitQuery
, 1);
523 q
->request
= sd_bus_message_ref(call
);
524 q
->callback
= callback
;
525 q
->userdata
= userdata
;
527 r
= hashmap_put(*registry
, call
, q
);
529 async_polkit_query_free(q
);
533 q
->registry
= *registry
;
535 r
= sd_bus_call_async(call
->bus
, &q
->slot
, pk
, async_polkit_callback
, q
, 0);
537 async_polkit_query_free(q
);
547 void bus_verify_polkit_async_registry_free(Hashmap
*registry
) {
551 while ((q
= hashmap_steal_first(registry
)))
552 async_polkit_query_free(q
);
554 hashmap_free(registry
);
558 int bus_check_peercred(sd_bus
*c
) {
565 fd
= sd_bus_get_fd(c
);
569 l
= sizeof(struct ucred
);
570 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &ucred
, &l
) < 0)
573 if (l
!= sizeof(struct ucred
))
576 if (ucred
.uid
!= 0 && ucred
.uid
!= geteuid())
582 int bus_connect_system_systemd(sd_bus
**_bus
) {
583 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
589 return sd_bus_default_system(_bus
);
591 /* If we are root and kdbus is not available, then let's talk
592 * directly to the system instance, instead of going via the
595 r
= sd_bus_new(&bus
);
599 r
= sd_bus_set_address(bus
, KERNEL_SYSTEM_BUS_ADDRESS
);
603 bus
->bus_client
= true;
605 r
= sd_bus_start(bus
);
612 bus
= sd_bus_unref(bus
);
614 r
= sd_bus_new(&bus
);
618 r
= sd_bus_set_address(bus
, "unix:path=/run/systemd/private");
622 r
= sd_bus_start(bus
);
624 return sd_bus_default_system(_bus
);
626 r
= bus_check_peercred(bus
);
636 int bus_connect_user_systemd(sd_bus
**_bus
) {
637 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
638 _cleanup_free_
char *ee
= NULL
;
642 /* Try via kdbus first, and then directly */
646 r
= sd_bus_new(&bus
);
650 if (asprintf(&bus
->address
, KERNEL_USER_BUS_ADDRESS_FMT
, getuid()) < 0)
653 bus
->bus_client
= true;
655 r
= sd_bus_start(bus
);
662 bus
= sd_bus_unref(bus
);
664 e
= secure_getenv("XDG_RUNTIME_DIR");
666 return sd_bus_default_user(_bus
);
668 ee
= bus_address_escape(e
);
672 r
= sd_bus_new(&bus
);
676 bus
->address
= strjoin("unix:path=", ee
, "/systemd/private", NULL
);
680 r
= sd_bus_start(bus
);
682 return sd_bus_default_user(_bus
);
684 r
= bus_check_peercred(bus
);
694 int bus_print_property(const char *name
, sd_bus_message
*property
, bool all
) {
696 const char *contents
;
702 r
= sd_bus_message_peek_type(property
, &type
, &contents
);
708 case SD_BUS_TYPE_STRING
: {
711 r
= sd_bus_message_read_basic(property
, type
, &s
);
715 if (all
|| !isempty(s
)) {
716 _cleanup_free_
char *escaped
= NULL
;
718 escaped
= xescape(s
, "\n");
722 printf("%s=%s\n", name
, escaped
);
728 case SD_BUS_TYPE_BOOLEAN
: {
731 r
= sd_bus_message_read_basic(property
, type
, &b
);
735 printf("%s=%s\n", name
, yes_no(b
));
740 case SD_BUS_TYPE_UINT64
: {
743 r
= sd_bus_message_read_basic(property
, type
, &u
);
747 /* Yes, heuristics! But we can change this check
748 * should it turn out to not be sufficient */
750 if (endswith(name
, "Timestamp")) {
751 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
753 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
755 printf("%s=%s\n", name
, strempty(t
));
757 } else if (strstr(name
, "USec")) {
758 char timespan
[FORMAT_TIMESPAN_MAX
];
760 printf("%s=%s\n", name
, format_timespan(timespan
, sizeof(timespan
), u
, 0));
762 printf("%s=%llu\n", name
, (unsigned long long) u
);
767 case SD_BUS_TYPE_INT64
: {
770 r
= sd_bus_message_read_basic(property
, type
, &i
);
774 printf("%s=%lld\n", name
, (long long) i
);
779 case SD_BUS_TYPE_UINT32
: {
782 r
= sd_bus_message_read_basic(property
, type
, &u
);
786 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
787 printf("%s=%04o\n", name
, u
);
789 printf("%s=%u\n", name
, (unsigned) u
);
794 case SD_BUS_TYPE_INT32
: {
797 r
= sd_bus_message_read_basic(property
, type
, &i
);
801 printf("%s=%i\n", name
, (int) i
);
805 case SD_BUS_TYPE_DOUBLE
: {
808 r
= sd_bus_message_read_basic(property
, type
, &d
);
812 printf("%s=%g\n", name
, d
);
816 case SD_BUS_TYPE_ARRAY
:
817 if (streq(contents
, "s")) {
821 r
= sd_bus_message_enter_container(property
, SD_BUS_TYPE_ARRAY
, contents
);
825 while((r
= sd_bus_message_read_basic(property
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
826 _cleanup_free_
char *escaped
= NULL
;
831 escaped
= xescape(str
, "\n ");
835 printf("%s%s", first
? "" : " ", escaped
);
847 r
= sd_bus_message_exit_container(property
);
853 } else if (streq(contents
, "y")) {
857 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
866 for (i
= 0; i
< n
; i
++)
867 printf("%02x", u
[i
]);
874 } else if (streq(contents
, "u")) {
878 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
887 for (i
= 0; i
< n
; i
++)
888 printf("%08x", u
[i
]);
902 int bus_print_all_properties(sd_bus
*bus
, const char *dest
, const char *path
, char **filter
, bool all
) {
903 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
904 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
910 r
= sd_bus_call_method(bus
,
913 "org.freedesktop.DBus.Properties",
921 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
925 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
927 const char *contents
;
929 r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &name
);
933 if (!filter
|| strv_find(filter
, name
)) {
934 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
938 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
942 r
= bus_print_property(name
, reply
, all
);
947 printf("%s=[unprintable]\n", name
);
948 /* skip what we didn't read */
949 r
= sd_bus_message_skip(reply
, contents
);
954 r
= sd_bus_message_exit_container(reply
);
958 r
= sd_bus_message_skip(reply
, "v");
963 r
= sd_bus_message_exit_container(reply
);
970 r
= sd_bus_message_exit_container(reply
);
977 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
978 sd_id128_t
*p
= userdata
;
983 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
990 memcpy((*p
).bytes
, v
, n
);
997 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1001 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
1006 case SD_BUS_TYPE_STRING
: {
1008 char **p
= userdata
;
1010 r
= sd_bus_message_read_basic(m
, type
, &s
);
1017 r
= free_and_strdup(p
, s
);
1021 case SD_BUS_TYPE_ARRAY
: {
1022 _cleanup_strv_free_
char **l
= NULL
;
1023 char ***p
= userdata
;
1025 r
= bus_message_read_strv_extend(m
, &l
);
1036 case SD_BUS_TYPE_BOOLEAN
: {
1040 r
= sd_bus_message_read_basic(m
, type
, &b
);
1049 case SD_BUS_TYPE_UINT32
: {
1051 uint32_t *p
= userdata
;
1053 r
= sd_bus_message_read_basic(m
, type
, &u
);
1062 case SD_BUS_TYPE_UINT64
: {
1064 uint64_t *p
= userdata
;
1066 r
= sd_bus_message_read_basic(m
, type
, &t
);
1082 int bus_message_map_all_properties(
1084 const struct bus_properties_map
*map
,
1087 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1093 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1097 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1098 const struct bus_properties_map
*prop
;
1100 const char *contents
;
1104 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1108 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1109 if (streq(map
[i
].member
, member
)) {
1115 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1119 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1123 v
= (uint8_t *)userdata
+ prop
->offset
;
1125 r
= prop
->set(sd_bus_message_get_bus(m
), member
, m
, &error
, v
);
1127 r
= map_basic(sd_bus_message_get_bus(m
), member
, m
, &error
, v
);
1131 r
= sd_bus_message_exit_container(m
);
1135 r
= sd_bus_message_skip(m
, "v");
1140 r
= sd_bus_message_exit_container(m
);
1147 return sd_bus_message_exit_container(m
);
1150 int bus_message_map_properties_changed(
1152 const struct bus_properties_map
*map
,
1156 int r
, invalidated
, i
;
1161 r
= bus_message_map_all_properties(m
, map
, userdata
);
1165 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1170 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1171 for (i
= 0; map
[i
].member
; i
++)
1172 if (streq(map
[i
].member
, member
)) {
1179 r
= sd_bus_message_exit_container(m
);
1186 int bus_map_all_properties(
1188 const char *destination
,
1190 const struct bus_properties_map
*map
,
1193 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
1194 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1198 assert(destination
);
1202 r
= sd_bus_call_method(
1206 "org.freedesktop.DBus.Properties",
1214 return bus_message_map_all_properties(m
, map
, userdata
);
1217 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1220 assert(transport
>= 0);
1221 assert(transport
< _BUS_TRANSPORT_MAX
);
1224 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1225 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1227 switch (transport
) {
1229 case BUS_TRANSPORT_LOCAL
:
1231 r
= sd_bus_default_user(bus
);
1233 r
= sd_bus_default_system(bus
);
1237 case BUS_TRANSPORT_REMOTE
:
1238 r
= sd_bus_open_system_remote(bus
, host
);
1241 case BUS_TRANSPORT_MACHINE
:
1242 r
= sd_bus_open_system_machine(bus
, host
);
1246 assert_not_reached("Hmm, unknown transport type.");
1252 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1255 assert(transport
>= 0);
1256 assert(transport
< _BUS_TRANSPORT_MAX
);
1259 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1260 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1262 switch (transport
) {
1264 case BUS_TRANSPORT_LOCAL
:
1266 r
= bus_connect_user_systemd(bus
);
1268 r
= bus_connect_system_systemd(bus
);
1272 case BUS_TRANSPORT_REMOTE
:
1273 r
= sd_bus_open_system_remote(bus
, host
);
1276 case BUS_TRANSPORT_MACHINE
:
1277 r
= sd_bus_open_system_machine(bus
, host
);
1281 assert_not_reached("Hmm, unknown transport type.");
1287 int bus_property_get_bool(
1290 const char *interface
,
1291 const char *property
,
1292 sd_bus_message
*reply
,
1294 sd_bus_error
*error
) {
1296 int b
= *(bool*) userdata
;
1298 return sd_bus_message_append_basic(reply
, 'b', &b
);
1301 #if __SIZEOF_SIZE_T__ != 8
1302 int bus_property_get_size(
1305 const char *interface
,
1306 const char *property
,
1307 sd_bus_message
*reply
,
1309 sd_bus_error
*error
) {
1311 uint64_t sz
= *(size_t*) userdata
;
1313 return sd_bus_message_append_basic(reply
, 't', &sz
);
1317 #if __SIZEOF_LONG__ != 8
1318 int bus_property_get_long(
1321 const char *interface
,
1322 const char *property
,
1323 sd_bus_message
*reply
,
1325 sd_bus_error
*error
) {
1327 int64_t l
= *(long*) userdata
;
1329 return sd_bus_message_append_basic(reply
, 'x', &l
);
1332 int bus_property_get_ulong(
1335 const char *interface
,
1336 const char *property
,
1337 sd_bus_message
*reply
,
1339 sd_bus_error
*error
) {
1341 uint64_t ul
= *(unsigned long*) userdata
;
1343 return sd_bus_message_append_basic(reply
, 't', &ul
);
1347 int bus_log_parse_error(int r
) {
1348 return log_error_errno(r
, "Failed to parse bus message: %m");
1351 int bus_log_create_error(int r
) {
1352 return log_error_errno(r
, "Failed to create bus message: %m");
1355 int bus_parse_unit_info(sd_bus_message
*message
, UnitInfo
*u
) {
1361 return sd_bus_message_read(
1376 int bus_append_unit_property_assignment(sd_bus_message
*m
, const char *assignment
) {
1377 const char *eq
, *field
;
1383 eq
= strchr(assignment
, '=');
1385 log_error("Not an assignment: %s", assignment
);
1389 field
= strndupa(assignment
, eq
- assignment
);
1392 if (streq(field
, "CPUQuota")) {
1396 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "CPUQuotaPerSecUSec");
1398 return bus_log_create_error(r
);
1400 r
= sd_bus_message_append(m
, "v", "t", USEC_INFINITY
);
1402 } else if (endswith(eq
, "%")) {
1405 if (sscanf(eq
, "%lf%%", &percent
) != 1 || percent
<= 0) {
1406 log_error("CPU quota '%s' invalid.", eq
);
1410 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "CPUQuotaPerSecUSec");
1412 return bus_log_create_error(r
);
1414 r
= sd_bus_message_append(m
, "v", "t", (usec_t
) percent
* USEC_PER_SEC
/ 100);
1416 log_error("CPU quota needs to be in percent.");
1421 return bus_log_create_error(r
);
1424 } else if (streq(field
, "EnvironmentFile")) {
1425 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "EnvironmentFiles");
1429 r
= sd_bus_message_append(m
, "v", "a(sb)", 1,
1430 eq
[0] == '-' ? eq
+ 1 : eq
,
1437 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, field
);
1439 return bus_log_create_error(r
);
1441 if (STR_IN_SET(field
,
1442 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1443 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1444 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1445 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
1446 "SyslogLevelPrefix")) {
1448 r
= parse_boolean(eq
);
1450 log_error("Failed to parse boolean assignment %s.", assignment
);
1454 r
= sd_bus_message_append(m
, "v", "b", r
);
1456 } else if (streq(field
, "MemoryLimit")) {
1459 if (isempty(eq
) || streq(eq
, "infinity"))
1460 bytes
= (uint64_t) -1;
1462 r
= parse_size(eq
, 1024, &bytes
);
1464 log_error("Failed to parse bytes specification %s", assignment
);
1469 r
= sd_bus_message_append(m
, "v", "t", bytes
);
1471 } else if (streq(field
, "TasksMax")) {
1474 if (isempty(eq
) || streq(eq
, "infinity"))
1477 r
= safe_atou64(eq
, &n
);
1479 log_error("Failed to parse maximum tasks specification %s", assignment
);
1484 r
= sd_bus_message_append(m
, "v", "t", n
);
1486 } else if (STR_IN_SET(field
, "CPUShares", "StartupCPUShares")) {
1489 r
= cg_cpu_shares_parse(eq
, &u
);
1491 log_error("Failed to parse %s value %s.", field
, eq
);
1495 r
= sd_bus_message_append(m
, "v", "t", u
);
1497 } else if (STR_IN_SET(field
, "BlockIOWeight", "StartupBlockIOWeight")) {
1500 r
= cg_cpu_shares_parse(eq
, &u
);
1502 log_error("Failed to parse %s value %s.", field
, eq
);
1506 r
= sd_bus_message_append(m
, "v", "t", u
);
1508 } else if (STR_IN_SET(field
,
1509 "User", "Group", "DevicePolicy", "KillMode",
1510 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1511 "StandardInput", "StandardOutput", "StandardError",
1512 "Description", "Slice", "Type", "WorkingDirectory",
1513 "RootDirectory", "SyslogIdentifier", "ProtectSystem",
1515 r
= sd_bus_message_append(m
, "v", "s", eq
);
1517 else if (streq(field
, "SyslogLevel")) {
1520 level
= log_level_from_string(eq
);
1522 log_error("Failed to parse %s value %s.", field
, eq
);
1526 r
= sd_bus_message_append(m
, "v", "i", level
);
1528 } else if (streq(field
, "SyslogFacility")) {
1531 facility
= log_facility_unshifted_from_string(eq
);
1533 log_error("Failed to parse %s value %s.", field
, eq
);
1537 r
= sd_bus_message_append(m
, "v", "i", facility
);
1539 } else if (streq(field
, "DeviceAllow")) {
1542 r
= sd_bus_message_append(m
, "v", "a(ss)", 0);
1544 const char *path
, *rwm
, *e
;
1546 e
= strchr(eq
, ' ');
1548 path
= strndupa(eq
, e
- eq
);
1555 if (!path_startswith(path
, "/dev")) {
1556 log_error("%s is not a device file in /dev.", path
);
1560 r
= sd_bus_message_append(m
, "v", "a(ss)", 1, path
, rwm
);
1563 } else if (STR_IN_SET(field
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1566 r
= sd_bus_message_append(m
, "v", "a(st)", 0);
1568 const char *path
, *bandwidth
, *e
;
1571 e
= strchr(eq
, ' ');
1573 path
= strndupa(eq
, e
- eq
);
1576 log_error("Failed to parse %s value %s.", field
, eq
);
1580 if (!path_startswith(path
, "/dev")) {
1581 log_error("%s is not a device file in /dev.", path
);
1585 r
= parse_size(bandwidth
, 1000, &bytes
);
1587 log_error("Failed to parse byte value %s.", bandwidth
);
1591 r
= sd_bus_message_append(m
, "v", "a(st)", 1, path
, bytes
);
1594 } else if (streq(field
, "BlockIODeviceWeight")) {
1597 r
= sd_bus_message_append(m
, "v", "a(st)", 0);
1599 const char *path
, *weight
, *e
;
1602 e
= strchr(eq
, ' ');
1604 path
= strndupa(eq
, e
- eq
);
1607 log_error("Failed to parse %s value %s.", field
, eq
);
1611 if (!path_startswith(path
, "/dev")) {
1612 log_error("%s is not a device file in /dev.", path
);
1616 r
= safe_atou64(weight
, &u
);
1618 log_error("Failed to parse %s value %s.", field
, weight
);
1621 r
= sd_bus_message_append(m
, "v", "a(st)", path
, u
);
1624 } else if (rlimit_from_string(field
) >= 0) {
1627 if (streq(eq
, "infinity"))
1630 r
= safe_atou64(eq
, &rl
);
1632 log_error("Invalid resource limit: %s", eq
);
1637 r
= sd_bus_message_append(m
, "v", "t", rl
);
1639 } else if (streq(field
, "Nice")) {
1642 r
= safe_atoi32(eq
, &i
);
1644 log_error("Failed to parse %s value %s.", field
, eq
);
1648 r
= sd_bus_message_append(m
, "v", "i", i
);
1650 } else if (streq(field
, "Environment")) {
1653 r
= sd_bus_message_open_container(m
, 'v', "as");
1655 return bus_log_create_error(r
);
1657 r
= sd_bus_message_open_container(m
, 'a', "s");
1659 return bus_log_create_error(r
);
1664 _cleanup_free_
char *word
= NULL
;
1666 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
);
1668 log_error("Failed to parse Environment value %s", eq
);
1674 if (!env_assignment_is_valid(word
)) {
1675 log_error("Invalid environment assignment: %s", eq
);
1679 r
= sd_bus_message_append_basic(m
, 's', word
);
1681 return bus_log_create_error(r
);
1684 r
= sd_bus_message_close_container(m
);
1686 return bus_log_create_error(r
);
1688 r
= sd_bus_message_close_container(m
);
1690 } else if (streq(field
, "KillSignal")) {
1693 sig
= signal_from_string_try_harder(eq
);
1695 log_error("Failed to parse %s value %s.", field
, eq
);
1699 r
= sd_bus_message_append(m
, "v", "i", sig
);
1701 } else if (streq(field
, "AccuracySec")) {
1704 r
= parse_sec(eq
, &u
);
1706 log_error("Failed to parse %s value %s", field
, eq
);
1710 r
= sd_bus_message_append(m
, "v", "t", u
);
1711 } else if (streq(field
, "TimerSlackNSec")) {
1714 r
= parse_nsec(eq
, &n
);
1716 log_error("Failed to parse %s value %s", field
, eq
);
1720 r
= sd_bus_message_append(m
, "v", "t", n
);
1721 } else if (streq(field
, "OOMScoreAdjust")) {
1724 r
= safe_atoi(eq
, &oa
);
1726 log_error("Failed to parse %s value %s", field
, eq
);
1730 if (!oom_score_adjust_is_valid(oa
)) {
1731 log_error("OOM score adjust value out of range");
1735 r
= sd_bus_message_append(m
, "v", "i", oa
);
1736 } else if (STR_IN_SET(field
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1739 r
= sd_bus_message_open_container(m
, 'v', "as");
1741 return bus_log_create_error(r
);
1743 r
= sd_bus_message_open_container(m
, 'a', "s");
1745 return bus_log_create_error(r
);
1750 _cleanup_free_
char *word
= NULL
;
1753 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
);
1755 log_error("Failed to parse %s value %s", field
, eq
);
1761 if (!utf8_is_valid(word
)) {
1762 log_error("Failed to parse %s value %s", field
, eq
);
1766 offset
= word
[0] == '-';
1767 if (!path_is_absolute(word
+ offset
)) {
1768 log_error("Failed to parse %s value %s", field
, eq
);
1772 path_kill_slashes(word
+ offset
);
1774 r
= sd_bus_message_append_basic(m
, 's', word
);
1776 return bus_log_create_error(r
);
1779 r
= sd_bus_message_close_container(m
);
1781 return bus_log_create_error(r
);
1783 r
= sd_bus_message_close_container(m
);
1786 log_error("Unknown assignment %s.", assignment
);
1791 return bus_log_create_error(r
);
1796 typedef struct BusWaitForJobs
{
1803 sd_bus_slot
*slot_job_removed
;
1804 sd_bus_slot
*slot_disconnected
;
1807 static int match_disconnected(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1810 log_error("Warning! D-Bus connection terminated.");
1811 sd_bus_close(sd_bus_message_get_bus(m
));
1816 static int match_job_removed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1817 const char *path
, *unit
, *result
;
1818 BusWaitForJobs
*d
= userdata
;
1826 r
= sd_bus_message_read(m
, "uoss", &id
, &path
, &unit
, &result
);
1828 bus_log_parse_error(r
);
1832 found
= set_remove(d
->jobs
, (char*) path
);
1838 if (!isempty(result
))
1839 d
->result
= strdup(result
);
1842 d
->name
= strdup(unit
);
1847 void bus_wait_for_jobs_free(BusWaitForJobs
*d
) {
1851 set_free_free(d
->jobs
);
1853 sd_bus_slot_unref(d
->slot_disconnected
);
1854 sd_bus_slot_unref(d
->slot_job_removed
);
1856 sd_bus_unref(d
->bus
);
1864 int bus_wait_for_jobs_new(sd_bus
*bus
, BusWaitForJobs
**ret
) {
1865 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*d
= NULL
;
1871 d
= new0(BusWaitForJobs
, 1);
1875 d
->bus
= sd_bus_ref(bus
);
1877 /* When we are a bus client we match by sender. Direct
1878 * connections OTOH have no initialized sender field, and
1879 * hence we ignore the sender then */
1880 r
= sd_bus_add_match(
1882 &d
->slot_job_removed
,
1885 "sender='org.freedesktop.systemd1',"
1886 "interface='org.freedesktop.systemd1.Manager',"
1887 "member='JobRemoved',"
1888 "path='/org/freedesktop/systemd1'" :
1890 "interface='org.freedesktop.systemd1.Manager',"
1891 "member='JobRemoved',"
1892 "path='/org/freedesktop/systemd1'",
1893 match_job_removed
, d
);
1897 r
= sd_bus_add_match(
1899 &d
->slot_disconnected
,
1901 "sender='org.freedesktop.DBus.Local',"
1902 "interface='org.freedesktop.DBus.Local',"
1903 "member='Disconnected'",
1904 match_disconnected
, d
);
1914 static int bus_process_wait(sd_bus
*bus
) {
1918 r
= sd_bus_process(bus
, NULL
);
1924 r
= sd_bus_wait(bus
, (uint64_t) -1);
1930 static int bus_job_get_service_result(BusWaitForJobs
*d
, char **result
) {
1931 _cleanup_free_
char *dbus_path
= NULL
;
1937 dbus_path
= unit_dbus_path_from_name(d
->name
);
1941 return sd_bus_get_property_string(d
->bus
,
1942 "org.freedesktop.systemd1",
1944 "org.freedesktop.systemd1.Service",
1950 static const struct {
1951 const char *result
, *explanation
;
1952 } explanations
[] = {
1953 { "resources", "a configured resource limit was exceeded" },
1954 { "timeout", "a timeout was exceeded" },
1955 { "exit-code", "the control process exited with error code" },
1956 { "signal", "a fatal signal was delivered to the control process" },
1957 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
1958 { "watchdog", "the service failed to send watchdog ping" },
1959 { "start-limit", "start of the service was attempted too often" }
1962 static void log_job_error_with_service_result(const char* service
, const char *result
) {
1963 _cleanup_free_
char *service_shell_quoted
= NULL
;
1967 service_shell_quoted
= shell_maybe_quote(service
);
1969 if (!isempty(result
)) {
1972 for (i
= 0; i
< ELEMENTSOF(explanations
); ++i
)
1973 if (streq(result
, explanations
[i
].result
))
1976 if (i
< ELEMENTSOF(explanations
)) {
1977 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1979 explanations
[i
].explanation
,
1980 strna(service_shell_quoted
));
1986 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1988 strna(service_shell_quoted
));
1991 /* For some results maybe additional explanation is required */
1992 if (streq_ptr(result
, "start-limit"))
1993 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1994 strna(service_shell_quoted
));
1997 static int check_wait_response(BusWaitForJobs
*d
, bool quiet
) {
2003 if (streq(d
->result
, "canceled"))
2004 log_error("Job for %s canceled.", strna(d
->name
));
2005 else if (streq(d
->result
, "timeout"))
2006 log_error("Job for %s timed out.", strna(d
->name
));
2007 else if (streq(d
->result
, "dependency"))
2008 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d
->name
));
2009 else if (streq(d
->result
, "invalid"))
2010 log_error("Job for %s invalid.", strna(d
->name
));
2011 else if (streq(d
->result
, "assert"))
2012 log_error("Assertion failed on job for %s.", strna(d
->name
));
2013 else if (streq(d
->result
, "unsupported"))
2014 log_error("Operation on or unit type of %s not supported on this system.", strna(d
->name
));
2015 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped")) {
2018 _cleanup_free_
char *result
= NULL
;
2020 q
= bus_job_get_service_result(d
, &result
);
2022 log_debug_errno(q
, "Failed to get Result property of service %s: %m", d
->name
);
2024 log_job_error_with_service_result(d
->name
, result
);
2026 log_error("Job failed. See \"journalctl -xe\" for details.");
2030 if (streq(d
->result
, "canceled"))
2032 else if (streq(d
->result
, "timeout"))
2034 else if (streq(d
->result
, "dependency"))
2036 else if (streq(d
->result
, "invalid"))
2038 else if (streq(d
->result
, "assert"))
2040 else if (streq(d
->result
, "unsupported"))
2042 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped"))
2048 int bus_wait_for_jobs(BusWaitForJobs
*d
, bool quiet
) {
2053 while (!set_isempty(d
->jobs
)) {
2056 q
= bus_process_wait(d
->bus
);
2058 return log_error_errno(q
, "Failed to wait for response: %m");
2061 q
= check_wait_response(d
, quiet
);
2062 /* Return the first error as it is most likely to be
2064 if (q
< 0 && r
== 0)
2067 log_debug_errno(q
, "Got result %s/%m for job %s", strna(d
->result
), strna(d
->name
));
2070 d
->name
= mfree(d
->name
);
2071 d
->result
= mfree(d
->result
);
2077 int bus_wait_for_jobs_add(BusWaitForJobs
*d
, const char *path
) {
2082 r
= set_ensure_allocated(&d
->jobs
, &string_hash_ops
);
2086 return set_put_strdup(d
->jobs
, path
);
2089 int bus_wait_for_jobs_one(BusWaitForJobs
*d
, const char *path
, bool quiet
) {
2092 r
= bus_wait_for_jobs_add(d
, path
);
2096 return bus_wait_for_jobs(d
, quiet
);
2099 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message
*m
, bool quiet
, UnitFileChange
**changes
, unsigned *n_changes
) {
2100 const char *type
, *path
, *source
;
2103 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sss)");
2105 return bus_log_parse_error(r
);
2107 while ((r
= sd_bus_message_read(m
, "(sss)", &type
, &path
, &source
)) > 0) {
2109 if (streq(type
, "symlink"))
2110 log_info("Created symlink from %s to %s.", path
, source
);
2112 log_info("Removed symlink %s.", path
);
2115 r
= unit_file_changes_add(changes
, n_changes
, streq(type
, "symlink") ? UNIT_FILE_SYMLINK
: UNIT_FILE_UNLINK
, path
, source
);
2120 return bus_log_parse_error(r
);
2122 r
= sd_bus_message_exit_container(m
);
2124 return bus_log_parse_error(r
);
2130 * bus_path_encode_unique() - encode unique object path
2131 * @b: bus connection or NULL
2132 * @prefix: object path prefix
2133 * @sender_id: unique-name of client, or NULL
2134 * @external_id: external ID to be chosen by client, or NULL
2135 * @ret_path: storage for encoded object path pointer
2137 * Whenever we provide a bus API that allows clients to create and manage
2138 * server-side objects, we need to provide a unique name for these objects. If
2139 * we let the server choose the name, we suffer from a race condition: If a
2140 * client creates an object asynchronously, it cannot destroy that object until
2141 * it received the method reply. It cannot know the name of the new object,
2142 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
2144 * Therefore, many APIs allow the client to choose the unique name for newly
2145 * created objects. There're two problems to solve, though:
2146 * 1) Object names are usually defined via dbus object paths, which are
2147 * usually globally namespaced. Therefore, multiple clients must be able
2148 * to choose unique object names without interference.
2149 * 2) If multiple libraries share the same bus connection, they must be
2150 * able to choose unique object names without interference.
2151 * The first problem is solved easily by prefixing a name with the
2152 * unique-bus-name of a connection. The server side must enforce this and
2153 * reject any other name. The second problem is solved by providing unique
2154 * suffixes from within sd-bus.
2156 * This helper allows clients to create unique object-paths. It uses the
2157 * template '/prefix/sender_id/external_id' and returns the new path in
2158 * @ret_path (must be freed by the caller).
2159 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2160 * NULL, this function allocates a unique suffix via @b (by requesting a new
2161 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2164 * Returns: 0 on success, negative error code on failure.
2166 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
2167 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
2168 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
2171 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
2172 assert_return(object_path_is_valid(prefix
), -EINVAL
);
2173 assert_return(ret_path
, -EINVAL
);
2176 r
= sd_bus_get_unique_name(b
, &sender_id
);
2182 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
2183 external_id
= external_buf
;
2186 sender_label
= bus_label_escape(sender_id
);
2190 external_label
= bus_label_escape(external_id
);
2191 if (!external_label
)
2194 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
, NULL
);
2203 * bus_path_decode_unique() - decode unique object path
2204 * @path: object path to decode
2205 * @prefix: object path prefix
2206 * @ret_sender: output parameter for sender-id label
2207 * @ret_external: output parameter for external-id label
2209 * This does the reverse of bus_path_encode_unique() (see its description for
2210 * details). Both trailing labels, sender-id and external-id, are unescaped and
2211 * returned in the given output parameters (the caller must free them).
2213 * Note that this function returns 0 if the path does not match the template
2214 * (see bus_path_encode_unique()), 1 if it matched.
2216 * Returns: Negative error code on failure, 0 if the given object path does not
2217 * match the template (return parameters are set to NULL), 1 if it was
2218 * parsed successfully (return parameters contain allocated labels).
2220 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
2222 char *sender
, *external
;
2224 assert(object_path_is_valid(path
));
2225 assert(object_path_is_valid(prefix
));
2227 assert(ret_external
);
2229 p
= object_path_startswith(path
, prefix
);
2232 *ret_external
= NULL
;
2239 *ret_external
= NULL
;
2243 sender
= bus_label_unescape_n(p
, q
- p
);
2244 external
= bus_label_unescape(q
+ 1);
2245 if (!sender
|| !external
) {
2251 *ret_sender
= sender
;
2252 *ret_external
= external
;
2256 bool is_kdbus_wanted(void) {
2257 _cleanup_free_
char *value
= NULL
;
2259 const bool configured
= true;
2261 const bool configured
= false;
2266 if (get_proc_cmdline_key("kdbus", NULL
) > 0)
2269 r
= get_proc_cmdline_key("kdbus=", &value
);
2273 return parse_boolean(value
) == 1;
2276 bool is_kdbus_available(void) {
2277 _cleanup_close_
int fd
= -1;
2278 struct kdbus_cmd cmd
= { .size
= sizeof(cmd
), .flags
= KDBUS_FLAG_NEGOTIATE
};
2280 if (!is_kdbus_wanted())
2283 fd
= open("/sys/fs/kdbus/control", O_RDWR
| O_CLOEXEC
| O_NONBLOCK
| O_NOCTTY
);
2287 return ioctl(fd
, KDBUS_CMD_BUS_MAKE
, &cmd
) >= 0;
2290 int bus_property_get_rlimit(
2293 const char *interface
,
2294 const char *property
,
2295 sd_bus_message
*reply
,
2297 sd_bus_error
*error
) {
2307 rl
= *(struct rlimit
**) userdata
;
2311 struct rlimit buf
= {};
2314 z
= rlimit_from_string(strstr(property
, "Limit"));
2321 /* rlim_t might have different sizes, let's map
2322 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
2324 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
2326 return sd_bus_message_append(reply
, "t", u
);