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 "path-util.h"
42 #include "signal-util.h"
43 #include "string-util.h"
45 #include "unit-name.h"
49 static int name_owner_change_callback(sd_bus_message
*m
, void *userdata
, sd_bus_error
*ret_error
) {
50 sd_event
*e
= userdata
;
55 sd_bus_close(sd_bus_message_get_bus(m
));
61 int bus_async_unregister_and_exit(sd_event
*e
, sd_bus
*bus
, const char *name
) {
62 _cleanup_free_
char *match
= NULL
;
70 /* We unregister the name here and then wait for the
71 * NameOwnerChanged signal for this event to arrive before we
72 * quit. We do this in order to make sure that any queued
73 * requests are still processed before we really exit. */
75 r
= sd_bus_get_unique_name(bus
, &unique
);
80 "sender='org.freedesktop.DBus',"
82 "interface='org.freedesktop.DBus',"
83 "member='NameOwnerChanged',"
84 "path='/org/freedesktop/DBus',"
87 "arg2=''", name
, unique
);
91 r
= sd_bus_add_match(bus
, NULL
, match
, name_owner_change_callback
, e
);
95 r
= sd_bus_release_name(bus
, name
);
102 int bus_event_loop_with_idle(
107 check_idle_t check_idle
,
109 bool exiting
= false;
119 r
= sd_event_get_state(e
);
122 if (r
== SD_EVENT_FINISHED
)
126 idle
= check_idle(userdata
);
130 r
= sd_event_run(e
, exiting
|| !idle
? (uint64_t) -1 : timeout
);
134 if (r
== 0 && !exiting
&& idle
) {
136 r
= sd_bus_try_close(bus
);
140 /* Fallback for dbus1 connections: we
141 * unregister the name and wait for the
142 * response to come through for it */
143 if (r
== -EOPNOTSUPP
) {
145 /* Inform the service manager that we
146 * are going down, so that it will
147 * queue all further start requests,
148 * instead of assuming we are already
150 sd_notify(false, "STOPPING=1");
152 r
= bus_async_unregister_and_exit(e
, bus
, name
);
168 r
= sd_event_get_exit_code(e
, &code
);
175 int bus_name_has_owner(sd_bus
*c
, const char *name
, sd_bus_error
*error
) {
176 _cleanup_bus_message_unref_ sd_bus_message
*rep
= NULL
;
177 int r
, has_owner
= 0;
182 r
= sd_bus_call_method(c
,
183 "org.freedesktop.DBus",
184 "/org/freedesktop/dbus",
185 "org.freedesktop.DBus",
194 r
= sd_bus_message_read_basic(rep
, 'b', &has_owner
);
196 return sd_bus_error_set_errno(error
, r
);
201 static int check_good_user(sd_bus_message
*m
, uid_t good_user
) {
202 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
208 if (good_user
== UID_INVALID
)
211 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_EUID
, &creds
);
215 /* Don't trust augmented credentials for authorization */
216 assert_return((sd_bus_creds_get_augmented_mask(creds
) & SD_BUS_CREDS_EUID
) == 0, -EPERM
);
218 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
222 return sender_uid
== good_user
;
226 sd_bus_message
*call
,
229 const char **details
,
239 /* Tests non-interactively! */
241 r
= check_good_user(call
, good_user
);
245 r
= sd_bus_query_sender_privilege(call
, capability
);
252 _cleanup_bus_message_unref_ sd_bus_message
*request
= NULL
;
253 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
254 int authorized
= false, challenge
= false;
255 const char *sender
, **k
, **v
;
257 sender
= sd_bus_message_get_sender(call
);
261 r
= sd_bus_message_new_method_call(
264 "org.freedesktop.PolicyKit1",
265 "/org/freedesktop/PolicyKit1/Authority",
266 "org.freedesktop.PolicyKit1.Authority",
267 "CheckAuthorization");
271 r
= sd_bus_message_append(
274 "system-bus-name", 1, "name", "s", sender
,
279 r
= sd_bus_message_open_container(request
, 'a', "{ss}");
283 STRV_FOREACH_PAIR(k
, v
, details
) {
284 r
= sd_bus_message_append(request
, "{ss}", *k
, *v
);
289 r
= sd_bus_message_close_container(request
);
293 r
= sd_bus_message_append(request
, "us", 0, NULL
);
297 r
= sd_bus_call(call
->bus
, request
, 0, e
, &reply
);
299 /* Treat no PK available as access denied */
300 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
)) {
301 sd_bus_error_free(e
);
308 r
= sd_bus_message_enter_container(reply
, 'r', "bba{ss}");
312 r
= sd_bus_message_read(reply
, "bb", &authorized
, &challenge
);
320 *_challenge
= challenge
;
331 typedef struct AsyncPolkitQuery
{
332 sd_bus_message
*request
, *reply
;
333 sd_bus_message_handler_t callback
;
339 static void async_polkit_query_free(AsyncPolkitQuery
*q
) {
344 sd_bus_slot_unref(q
->slot
);
346 if (q
->registry
&& q
->request
)
347 hashmap_remove(q
->registry
, q
->request
);
349 sd_bus_message_unref(q
->request
);
350 sd_bus_message_unref(q
->reply
);
355 static int async_polkit_callback(sd_bus_message
*reply
, void *userdata
, sd_bus_error
*error
) {
356 _cleanup_bus_error_free_ sd_bus_error error_buffer
= SD_BUS_ERROR_NULL
;
357 AsyncPolkitQuery
*q
= userdata
;
363 q
->slot
= sd_bus_slot_unref(q
->slot
);
364 q
->reply
= sd_bus_message_ref(reply
);
366 r
= sd_bus_message_rewind(q
->request
, true);
368 r
= sd_bus_reply_method_errno(q
->request
, r
, NULL
);
372 r
= q
->callback(q
->request
, q
->userdata
, &error_buffer
);
373 r
= bus_maybe_reply_error(q
->request
, r
, &error_buffer
);
376 async_polkit_query_free(q
);
383 int bus_verify_polkit_async(
384 sd_bus_message
*call
,
387 const char **details
,
391 sd_bus_error
*error
) {
394 _cleanup_bus_message_unref_ sd_bus_message
*pk
= NULL
;
396 const char *sender
, **k
, **v
;
397 sd_bus_message_handler_t callback
;
407 r
= check_good_user(call
, good_user
);
412 q
= hashmap_get(*registry
, call
);
414 int authorized
, challenge
;
416 /* This is the second invocation of this function, and
417 * there's already a response from polkit, let's
421 if (sd_bus_message_is_method_error(q
->reply
, NULL
)) {
422 const sd_bus_error
*e
;
424 /* Copy error from polkit reply */
425 e
= sd_bus_message_get_error(q
->reply
);
426 sd_bus_error_copy(error
, e
);
428 /* Treat no PK available as access denied */
429 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
))
432 return -sd_bus_error_get_errno(e
);
435 r
= sd_bus_message_enter_container(q
->reply
, 'r', "bba{ss}");
437 r
= sd_bus_message_read(q
->reply
, "bb", &authorized
, &challenge
);
446 return sd_bus_error_set(error
, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED
, "Interactive authentication required.");
452 r
= sd_bus_query_sender_privilege(call
, capability
);
459 if (sd_bus_get_current_message(call
->bus
) != call
)
462 callback
= sd_bus_get_current_handler(call
->bus
);
466 userdata
= sd_bus_get_current_userdata(call
->bus
);
468 sender
= sd_bus_message_get_sender(call
);
472 c
= sd_bus_message_get_allow_interactive_authorization(call
);
478 r
= hashmap_ensure_allocated(registry
, NULL
);
482 r
= sd_bus_message_new_method_call(
485 "org.freedesktop.PolicyKit1",
486 "/org/freedesktop/PolicyKit1/Authority",
487 "org.freedesktop.PolicyKit1.Authority",
488 "CheckAuthorization");
492 r
= sd_bus_message_append(
495 "system-bus-name", 1, "name", "s", sender
,
500 r
= sd_bus_message_open_container(pk
, 'a', "{ss}");
504 STRV_FOREACH_PAIR(k
, v
, details
) {
505 r
= sd_bus_message_append(pk
, "{ss}", *k
, *v
);
510 r
= sd_bus_message_close_container(pk
);
514 r
= sd_bus_message_append(pk
, "us", !!interactive
, NULL
);
518 q
= new0(AsyncPolkitQuery
, 1);
522 q
->request
= sd_bus_message_ref(call
);
523 q
->callback
= callback
;
524 q
->userdata
= userdata
;
526 r
= hashmap_put(*registry
, call
, q
);
528 async_polkit_query_free(q
);
532 q
->registry
= *registry
;
534 r
= sd_bus_call_async(call
->bus
, &q
->slot
, pk
, async_polkit_callback
, q
, 0);
536 async_polkit_query_free(q
);
546 void bus_verify_polkit_async_registry_free(Hashmap
*registry
) {
550 while ((q
= hashmap_steal_first(registry
)))
551 async_polkit_query_free(q
);
553 hashmap_free(registry
);
557 int bus_check_peercred(sd_bus
*c
) {
564 fd
= sd_bus_get_fd(c
);
568 l
= sizeof(struct ucred
);
569 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &ucred
, &l
) < 0)
572 if (l
!= sizeof(struct ucred
))
575 if (ucred
.uid
!= 0 && ucred
.uid
!= geteuid())
581 int bus_connect_system_systemd(sd_bus
**_bus
) {
582 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
588 return sd_bus_default_system(_bus
);
590 /* If we are root and kdbus is not available, then let's talk
591 * directly to the system instance, instead of going via the
594 r
= sd_bus_new(&bus
);
598 r
= sd_bus_set_address(bus
, KERNEL_SYSTEM_BUS_ADDRESS
);
602 bus
->bus_client
= true;
604 r
= sd_bus_start(bus
);
611 bus
= sd_bus_unref(bus
);
613 r
= sd_bus_new(&bus
);
617 r
= sd_bus_set_address(bus
, "unix:path=/run/systemd/private");
621 r
= sd_bus_start(bus
);
623 return sd_bus_default_system(_bus
);
625 r
= bus_check_peercred(bus
);
635 int bus_connect_user_systemd(sd_bus
**_bus
) {
636 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
637 _cleanup_free_
char *ee
= NULL
;
641 /* Try via kdbus first, and then directly */
645 r
= sd_bus_new(&bus
);
649 if (asprintf(&bus
->address
, KERNEL_USER_BUS_ADDRESS_FMT
, getuid()) < 0)
652 bus
->bus_client
= true;
654 r
= sd_bus_start(bus
);
661 bus
= sd_bus_unref(bus
);
663 e
= secure_getenv("XDG_RUNTIME_DIR");
665 return sd_bus_default_user(_bus
);
667 ee
= bus_address_escape(e
);
671 r
= sd_bus_new(&bus
);
675 bus
->address
= strjoin("unix:path=", ee
, "/systemd/private", NULL
);
679 r
= sd_bus_start(bus
);
681 return sd_bus_default_user(_bus
);
683 r
= bus_check_peercred(bus
);
693 int bus_print_property(const char *name
, sd_bus_message
*property
, bool all
) {
695 const char *contents
;
701 r
= sd_bus_message_peek_type(property
, &type
, &contents
);
707 case SD_BUS_TYPE_STRING
: {
710 r
= sd_bus_message_read_basic(property
, type
, &s
);
714 if (all
|| !isempty(s
)) {
715 _cleanup_free_
char *escaped
= NULL
;
717 escaped
= xescape(s
, "\n");
721 printf("%s=%s\n", name
, escaped
);
727 case SD_BUS_TYPE_BOOLEAN
: {
730 r
= sd_bus_message_read_basic(property
, type
, &b
);
734 printf("%s=%s\n", name
, yes_no(b
));
739 case SD_BUS_TYPE_UINT64
: {
742 r
= sd_bus_message_read_basic(property
, type
, &u
);
746 /* Yes, heuristics! But we can change this check
747 * should it turn out to not be sufficient */
749 if (endswith(name
, "Timestamp")) {
750 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
752 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
754 printf("%s=%s\n", name
, strempty(t
));
756 } else if (strstr(name
, "USec")) {
757 char timespan
[FORMAT_TIMESPAN_MAX
];
759 printf("%s=%s\n", name
, format_timespan(timespan
, sizeof(timespan
), u
, 0));
761 printf("%s=%llu\n", name
, (unsigned long long) u
);
766 case SD_BUS_TYPE_INT64
: {
769 r
= sd_bus_message_read_basic(property
, type
, &i
);
773 printf("%s=%lld\n", name
, (long long) i
);
778 case SD_BUS_TYPE_UINT32
: {
781 r
= sd_bus_message_read_basic(property
, type
, &u
);
785 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
786 printf("%s=%04o\n", name
, u
);
788 printf("%s=%u\n", name
, (unsigned) u
);
793 case SD_BUS_TYPE_INT32
: {
796 r
= sd_bus_message_read_basic(property
, type
, &i
);
800 printf("%s=%i\n", name
, (int) i
);
804 case SD_BUS_TYPE_DOUBLE
: {
807 r
= sd_bus_message_read_basic(property
, type
, &d
);
811 printf("%s=%g\n", name
, d
);
815 case SD_BUS_TYPE_ARRAY
:
816 if (streq(contents
, "s")) {
820 r
= sd_bus_message_enter_container(property
, SD_BUS_TYPE_ARRAY
, contents
);
824 while((r
= sd_bus_message_read_basic(property
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
825 _cleanup_free_
char *escaped
= NULL
;
830 escaped
= xescape(str
, "\n ");
834 printf("%s%s", first
? "" : " ", escaped
);
846 r
= sd_bus_message_exit_container(property
);
852 } else if (streq(contents
, "y")) {
856 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
865 for (i
= 0; i
< n
; i
++)
866 printf("%02x", u
[i
]);
873 } else if (streq(contents
, "u")) {
877 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
886 for (i
= 0; i
< n
; i
++)
887 printf("%08x", u
[i
]);
901 int bus_print_all_properties(sd_bus
*bus
, const char *dest
, const char *path
, char **filter
, bool all
) {
902 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
903 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
909 r
= sd_bus_call_method(bus
,
912 "org.freedesktop.DBus.Properties",
920 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
924 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
926 const char *contents
;
928 r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &name
);
932 if (!filter
|| strv_find(filter
, name
)) {
933 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
937 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
941 r
= bus_print_property(name
, reply
, all
);
946 printf("%s=[unprintable]\n", name
);
947 /* skip what we didn't read */
948 r
= sd_bus_message_skip(reply
, contents
);
953 r
= sd_bus_message_exit_container(reply
);
957 r
= sd_bus_message_skip(reply
, "v");
962 r
= sd_bus_message_exit_container(reply
);
969 r
= sd_bus_message_exit_container(reply
);
976 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
977 sd_id128_t
*p
= userdata
;
982 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
989 memcpy((*p
).bytes
, v
, n
);
996 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
1000 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
1005 case SD_BUS_TYPE_STRING
: {
1007 char **p
= userdata
;
1009 r
= sd_bus_message_read_basic(m
, type
, &s
);
1016 r
= free_and_strdup(p
, s
);
1020 case SD_BUS_TYPE_ARRAY
: {
1021 _cleanup_strv_free_
char **l
= NULL
;
1022 char ***p
= userdata
;
1024 r
= bus_message_read_strv_extend(m
, &l
);
1035 case SD_BUS_TYPE_BOOLEAN
: {
1039 r
= sd_bus_message_read_basic(m
, type
, &b
);
1048 case SD_BUS_TYPE_UINT32
: {
1050 uint32_t *p
= userdata
;
1052 r
= sd_bus_message_read_basic(m
, type
, &u
);
1061 case SD_BUS_TYPE_UINT64
: {
1063 uint64_t *p
= userdata
;
1065 r
= sd_bus_message_read_basic(m
, type
, &t
);
1081 int bus_message_map_all_properties(
1083 const struct bus_properties_map
*map
,
1086 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1092 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
1096 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1097 const struct bus_properties_map
*prop
;
1099 const char *contents
;
1103 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
1107 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
1108 if (streq(map
[i
].member
, member
)) {
1114 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
1118 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
1122 v
= (uint8_t *)userdata
+ prop
->offset
;
1124 r
= prop
->set(sd_bus_message_get_bus(m
), member
, m
, &error
, v
);
1126 r
= map_basic(sd_bus_message_get_bus(m
), member
, m
, &error
, v
);
1130 r
= sd_bus_message_exit_container(m
);
1134 r
= sd_bus_message_skip(m
, "v");
1139 r
= sd_bus_message_exit_container(m
);
1146 return sd_bus_message_exit_container(m
);
1149 int bus_message_map_properties_changed(
1151 const struct bus_properties_map
*map
,
1155 int r
, invalidated
, i
;
1160 r
= bus_message_map_all_properties(m
, map
, userdata
);
1164 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "s");
1169 while ((r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
)) > 0)
1170 for (i
= 0; map
[i
].member
; i
++)
1171 if (streq(map
[i
].member
, member
)) {
1178 r
= sd_bus_message_exit_container(m
);
1185 int bus_map_all_properties(
1187 const char *destination
,
1189 const struct bus_properties_map
*map
,
1192 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
1193 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1197 assert(destination
);
1201 r
= sd_bus_call_method(
1205 "org.freedesktop.DBus.Properties",
1213 return bus_message_map_all_properties(m
, map
, userdata
);
1216 int bus_connect_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1219 assert(transport
>= 0);
1220 assert(transport
< _BUS_TRANSPORT_MAX
);
1223 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1224 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1226 switch (transport
) {
1228 case BUS_TRANSPORT_LOCAL
:
1230 r
= sd_bus_default_user(bus
);
1232 r
= sd_bus_default_system(bus
);
1236 case BUS_TRANSPORT_REMOTE
:
1237 r
= sd_bus_open_system_remote(bus
, host
);
1240 case BUS_TRANSPORT_MACHINE
:
1241 r
= sd_bus_open_system_machine(bus
, host
);
1245 assert_not_reached("Hmm, unknown transport type.");
1251 int bus_connect_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
1254 assert(transport
>= 0);
1255 assert(transport
< _BUS_TRANSPORT_MAX
);
1258 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1259 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -EOPNOTSUPP
);
1261 switch (transport
) {
1263 case BUS_TRANSPORT_LOCAL
:
1265 r
= bus_connect_user_systemd(bus
);
1267 r
= bus_connect_system_systemd(bus
);
1271 case BUS_TRANSPORT_REMOTE
:
1272 r
= sd_bus_open_system_remote(bus
, host
);
1275 case BUS_TRANSPORT_MACHINE
:
1276 r
= sd_bus_open_system_machine(bus
, host
);
1280 assert_not_reached("Hmm, unknown transport type.");
1286 int bus_property_get_bool(
1289 const char *interface
,
1290 const char *property
,
1291 sd_bus_message
*reply
,
1293 sd_bus_error
*error
) {
1295 int b
= *(bool*) userdata
;
1297 return sd_bus_message_append_basic(reply
, 'b', &b
);
1300 #if __SIZEOF_SIZE_T__ != 8
1301 int bus_property_get_size(
1304 const char *interface
,
1305 const char *property
,
1306 sd_bus_message
*reply
,
1308 sd_bus_error
*error
) {
1310 uint64_t sz
= *(size_t*) userdata
;
1312 return sd_bus_message_append_basic(reply
, 't', &sz
);
1316 #if __SIZEOF_LONG__ != 8
1317 int bus_property_get_long(
1320 const char *interface
,
1321 const char *property
,
1322 sd_bus_message
*reply
,
1324 sd_bus_error
*error
) {
1326 int64_t l
= *(long*) userdata
;
1328 return sd_bus_message_append_basic(reply
, 'x', &l
);
1331 int bus_property_get_ulong(
1334 const char *interface
,
1335 const char *property
,
1336 sd_bus_message
*reply
,
1338 sd_bus_error
*error
) {
1340 uint64_t ul
= *(unsigned long*) userdata
;
1342 return sd_bus_message_append_basic(reply
, 't', &ul
);
1346 int bus_log_parse_error(int r
) {
1347 return log_error_errno(r
, "Failed to parse bus message: %m");
1350 int bus_log_create_error(int r
) {
1351 return log_error_errno(r
, "Failed to create bus message: %m");
1354 int bus_parse_unit_info(sd_bus_message
*message
, UnitInfo
*u
) {
1360 return sd_bus_message_read(
1375 int bus_append_unit_property_assignment(sd_bus_message
*m
, const char *assignment
) {
1376 const char *eq
, *field
;
1382 eq
= strchr(assignment
, '=');
1384 log_error("Not an assignment: %s", assignment
);
1388 field
= strndupa(assignment
, eq
- assignment
);
1391 if (streq(field
, "CPUQuota")) {
1395 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "CPUQuotaPerSecUSec");
1397 return bus_log_create_error(r
);
1399 r
= sd_bus_message_append(m
, "v", "t", USEC_INFINITY
);
1401 } else if (endswith(eq
, "%")) {
1404 if (sscanf(eq
, "%lf%%", &percent
) != 1 || percent
<= 0) {
1405 log_error("CPU quota '%s' invalid.", eq
);
1409 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "CPUQuotaPerSecUSec");
1411 return bus_log_create_error(r
);
1413 r
= sd_bus_message_append(m
, "v", "t", (usec_t
) percent
* USEC_PER_SEC
/ 100);
1415 log_error("CPU quota needs to be in percent.");
1420 return bus_log_create_error(r
);
1423 } else if (streq(field
, "EnvironmentFile")) {
1424 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, "EnvironmentFiles");
1428 r
= sd_bus_message_append(m
, "v", "a(sb)", 1,
1429 eq
[0] == '-' ? eq
+ 1 : eq
,
1436 r
= sd_bus_message_append_basic(m
, SD_BUS_TYPE_STRING
, field
);
1438 return bus_log_create_error(r
);
1440 if (STR_IN_SET(field
,
1441 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1442 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1443 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1444 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
1445 "SyslogLevelPrefix")) {
1447 r
= parse_boolean(eq
);
1449 log_error("Failed to parse boolean assignment %s.", assignment
);
1453 r
= sd_bus_message_append(m
, "v", "b", r
);
1455 } else if (streq(field
, "MemoryLimit")) {
1458 if (isempty(eq
) || streq(eq
, "infinity"))
1459 bytes
= (uint64_t) -1;
1461 r
= parse_size(eq
, 1024, &bytes
);
1463 log_error("Failed to parse bytes specification %s", assignment
);
1468 r
= sd_bus_message_append(m
, "v", "t", bytes
);
1470 } else if (streq(field
, "TasksMax")) {
1473 if (isempty(eq
) || streq(eq
, "infinity"))
1476 r
= safe_atou64(eq
, &n
);
1478 log_error("Failed to parse maximum tasks specification %s", assignment
);
1483 r
= sd_bus_message_append(m
, "v", "t", n
);
1485 } else if (STR_IN_SET(field
, "CPUShares", "StartupCPUShares")) {
1488 r
= cg_cpu_shares_parse(eq
, &u
);
1490 log_error("Failed to parse %s value %s.", field
, eq
);
1494 r
= sd_bus_message_append(m
, "v", "t", u
);
1496 } else if (STR_IN_SET(field
, "BlockIOWeight", "StartupBlockIOWeight")) {
1499 r
= cg_cpu_shares_parse(eq
, &u
);
1501 log_error("Failed to parse %s value %s.", field
, eq
);
1505 r
= sd_bus_message_append(m
, "v", "t", u
);
1507 } else if (STR_IN_SET(field
,
1508 "User", "Group", "DevicePolicy", "KillMode",
1509 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1510 "StandardInput", "StandardOutput", "StandardError",
1511 "Description", "Slice", "Type", "WorkingDirectory",
1512 "RootDirectory", "SyslogIdentifier", "ProtectSystem",
1514 r
= sd_bus_message_append(m
, "v", "s", eq
);
1516 else if (streq(field
, "SyslogLevel")) {
1519 level
= log_level_from_string(eq
);
1521 log_error("Failed to parse %s value %s.", field
, eq
);
1525 r
= sd_bus_message_append(m
, "v", "i", level
);
1527 } else if (streq(field
, "SyslogFacility")) {
1530 facility
= log_facility_unshifted_from_string(eq
);
1532 log_error("Failed to parse %s value %s.", field
, eq
);
1536 r
= sd_bus_message_append(m
, "v", "i", facility
);
1538 } else if (streq(field
, "DeviceAllow")) {
1541 r
= sd_bus_message_append(m
, "v", "a(ss)", 0);
1543 const char *path
, *rwm
, *e
;
1545 e
= strchr(eq
, ' ');
1547 path
= strndupa(eq
, e
- eq
);
1554 if (!path_startswith(path
, "/dev")) {
1555 log_error("%s is not a device file in /dev.", path
);
1559 r
= sd_bus_message_append(m
, "v", "a(ss)", 1, path
, rwm
);
1562 } else if (STR_IN_SET(field
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1565 r
= sd_bus_message_append(m
, "v", "a(st)", 0);
1567 const char *path
, *bandwidth
, *e
;
1570 e
= strchr(eq
, ' ');
1572 path
= strndupa(eq
, e
- eq
);
1575 log_error("Failed to parse %s value %s.", field
, eq
);
1579 if (!path_startswith(path
, "/dev")) {
1580 log_error("%s is not a device file in /dev.", path
);
1584 r
= parse_size(bandwidth
, 1000, &bytes
);
1586 log_error("Failed to parse byte value %s.", bandwidth
);
1590 r
= sd_bus_message_append(m
, "v", "a(st)", 1, path
, bytes
);
1593 } else if (streq(field
, "BlockIODeviceWeight")) {
1596 r
= sd_bus_message_append(m
, "v", "a(st)", 0);
1598 const char *path
, *weight
, *e
;
1601 e
= strchr(eq
, ' ');
1603 path
= strndupa(eq
, e
- eq
);
1606 log_error("Failed to parse %s value %s.", field
, eq
);
1610 if (!path_startswith(path
, "/dev")) {
1611 log_error("%s is not a device file in /dev.", path
);
1615 r
= safe_atou64(weight
, &u
);
1617 log_error("Failed to parse %s value %s.", field
, weight
);
1620 r
= sd_bus_message_append(m
, "v", "a(st)", path
, u
);
1623 } else if (rlimit_from_string(field
) >= 0) {
1626 if (streq(eq
, "infinity"))
1629 r
= safe_atou64(eq
, &rl
);
1631 log_error("Invalid resource limit: %s", eq
);
1636 r
= sd_bus_message_append(m
, "v", "t", rl
);
1638 } else if (streq(field
, "Nice")) {
1641 r
= safe_atoi32(eq
, &i
);
1643 log_error("Failed to parse %s value %s.", field
, eq
);
1647 r
= sd_bus_message_append(m
, "v", "i", i
);
1649 } else if (streq(field
, "Environment")) {
1652 r
= sd_bus_message_open_container(m
, 'v', "as");
1654 return bus_log_create_error(r
);
1656 r
= sd_bus_message_open_container(m
, 'a', "s");
1658 return bus_log_create_error(r
);
1663 _cleanup_free_
char *word
= NULL
;
1665 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
);
1667 log_error("Failed to parse Environment value %s", eq
);
1673 if (!env_assignment_is_valid(word
)) {
1674 log_error("Invalid environment assignment: %s", eq
);
1678 r
= sd_bus_message_append_basic(m
, 's', word
);
1680 return bus_log_create_error(r
);
1683 r
= sd_bus_message_close_container(m
);
1685 return bus_log_create_error(r
);
1687 r
= sd_bus_message_close_container(m
);
1689 } else if (streq(field
, "KillSignal")) {
1692 sig
= signal_from_string_try_harder(eq
);
1694 log_error("Failed to parse %s value %s.", field
, eq
);
1698 r
= sd_bus_message_append(m
, "v", "i", sig
);
1700 } else if (streq(field
, "AccuracySec")) {
1703 r
= parse_sec(eq
, &u
);
1705 log_error("Failed to parse %s value %s", field
, eq
);
1709 r
= sd_bus_message_append(m
, "v", "t", u
);
1710 } else if (streq(field
, "TimerSlackNSec")) {
1713 r
= parse_nsec(eq
, &n
);
1715 log_error("Failed to parse %s value %s", field
, eq
);
1719 r
= sd_bus_message_append(m
, "v", "t", n
);
1720 } else if (streq(field
, "OOMScoreAdjust")) {
1723 r
= safe_atoi(eq
, &oa
);
1725 log_error("Failed to parse %s value %s", field
, eq
);
1729 if (!oom_score_adjust_is_valid(oa
)) {
1730 log_error("OOM score adjust value out of range");
1734 r
= sd_bus_message_append(m
, "v", "i", oa
);
1735 } else if (STR_IN_SET(field
, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1738 r
= sd_bus_message_open_container(m
, 'v', "as");
1740 return bus_log_create_error(r
);
1742 r
= sd_bus_message_open_container(m
, 'a', "s");
1744 return bus_log_create_error(r
);
1749 _cleanup_free_
char *word
= NULL
;
1752 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
);
1754 log_error("Failed to parse %s value %s", field
, eq
);
1760 if (!utf8_is_valid(word
)) {
1761 log_error("Failed to parse %s value %s", field
, eq
);
1765 offset
= word
[0] == '-';
1766 if (!path_is_absolute(word
+ offset
)) {
1767 log_error("Failed to parse %s value %s", field
, eq
);
1771 path_kill_slashes(word
+ offset
);
1773 r
= sd_bus_message_append_basic(m
, 's', word
);
1775 return bus_log_create_error(r
);
1778 r
= sd_bus_message_close_container(m
);
1780 return bus_log_create_error(r
);
1782 r
= sd_bus_message_close_container(m
);
1784 } else if (streq(field
, "RuntimeDirectory")) {
1787 r
= sd_bus_message_open_container(m
, 'v', "as");
1789 return bus_log_create_error(r
);
1791 r
= sd_bus_message_open_container(m
, 'a', "s");
1793 return bus_log_create_error(r
);
1798 _cleanup_free_
char *word
= NULL
;
1800 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_QUOTES
);
1802 return log_error_errno(r
, "Failed to parse %s value %s", field
, eq
);
1807 r
= sd_bus_message_append_basic(m
, 's', word
);
1809 return bus_log_create_error(r
);
1812 r
= sd_bus_message_close_container(m
);
1814 return bus_log_create_error(r
);
1816 r
= sd_bus_message_close_container(m
);
1819 log_error("Unknown assignment %s.", assignment
);
1824 return bus_log_create_error(r
);
1829 typedef struct BusWaitForJobs
{
1836 sd_bus_slot
*slot_job_removed
;
1837 sd_bus_slot
*slot_disconnected
;
1840 static int match_disconnected(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1843 log_error("Warning! D-Bus connection terminated.");
1844 sd_bus_close(sd_bus_message_get_bus(m
));
1849 static int match_job_removed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1850 const char *path
, *unit
, *result
;
1851 BusWaitForJobs
*d
= userdata
;
1859 r
= sd_bus_message_read(m
, "uoss", &id
, &path
, &unit
, &result
);
1861 bus_log_parse_error(r
);
1865 found
= set_remove(d
->jobs
, (char*) path
);
1871 if (!isempty(result
))
1872 d
->result
= strdup(result
);
1875 d
->name
= strdup(unit
);
1880 void bus_wait_for_jobs_free(BusWaitForJobs
*d
) {
1884 set_free_free(d
->jobs
);
1886 sd_bus_slot_unref(d
->slot_disconnected
);
1887 sd_bus_slot_unref(d
->slot_job_removed
);
1889 sd_bus_unref(d
->bus
);
1897 int bus_wait_for_jobs_new(sd_bus
*bus
, BusWaitForJobs
**ret
) {
1898 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*d
= NULL
;
1904 d
= new0(BusWaitForJobs
, 1);
1908 d
->bus
= sd_bus_ref(bus
);
1910 /* When we are a bus client we match by sender. Direct
1911 * connections OTOH have no initialized sender field, and
1912 * hence we ignore the sender then */
1913 r
= sd_bus_add_match(
1915 &d
->slot_job_removed
,
1918 "sender='org.freedesktop.systemd1',"
1919 "interface='org.freedesktop.systemd1.Manager',"
1920 "member='JobRemoved',"
1921 "path='/org/freedesktop/systemd1'" :
1923 "interface='org.freedesktop.systemd1.Manager',"
1924 "member='JobRemoved',"
1925 "path='/org/freedesktop/systemd1'",
1926 match_job_removed
, d
);
1930 r
= sd_bus_add_match(
1932 &d
->slot_disconnected
,
1934 "sender='org.freedesktop.DBus.Local',"
1935 "interface='org.freedesktop.DBus.Local',"
1936 "member='Disconnected'",
1937 match_disconnected
, d
);
1947 static int bus_process_wait(sd_bus
*bus
) {
1951 r
= sd_bus_process(bus
, NULL
);
1957 r
= sd_bus_wait(bus
, (uint64_t) -1);
1963 static int bus_job_get_service_result(BusWaitForJobs
*d
, char **result
) {
1964 _cleanup_free_
char *dbus_path
= NULL
;
1970 dbus_path
= unit_dbus_path_from_name(d
->name
);
1974 return sd_bus_get_property_string(d
->bus
,
1975 "org.freedesktop.systemd1",
1977 "org.freedesktop.systemd1.Service",
1983 static const struct {
1984 const char *result
, *explanation
;
1985 } explanations
[] = {
1986 { "resources", "a configured resource limit was exceeded" },
1987 { "timeout", "a timeout was exceeded" },
1988 { "exit-code", "the control process exited with error code" },
1989 { "signal", "a fatal signal was delivered to the control process" },
1990 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
1991 { "watchdog", "the service failed to send watchdog ping" },
1992 { "start-limit", "start of the service was attempted too often" }
1995 static void log_job_error_with_service_result(const char* service
, const char *result
) {
1996 _cleanup_free_
char *service_shell_quoted
= NULL
;
2000 service_shell_quoted
= shell_maybe_quote(service
);
2002 if (!isempty(result
)) {
2005 for (i
= 0; i
< ELEMENTSOF(explanations
); ++i
)
2006 if (streq(result
, explanations
[i
].result
))
2009 if (i
< ELEMENTSOF(explanations
)) {
2010 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
2012 explanations
[i
].explanation
,
2013 strna(service_shell_quoted
));
2019 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
2021 strna(service_shell_quoted
));
2024 /* For some results maybe additional explanation is required */
2025 if (streq_ptr(result
, "start-limit"))
2026 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
2027 strna(service_shell_quoted
));
2030 static int check_wait_response(BusWaitForJobs
*d
, bool quiet
) {
2036 if (streq(d
->result
, "canceled"))
2037 log_error("Job for %s canceled.", strna(d
->name
));
2038 else if (streq(d
->result
, "timeout"))
2039 log_error("Job for %s timed out.", strna(d
->name
));
2040 else if (streq(d
->result
, "dependency"))
2041 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d
->name
));
2042 else if (streq(d
->result
, "invalid"))
2043 log_error("Job for %s invalid.", strna(d
->name
));
2044 else if (streq(d
->result
, "assert"))
2045 log_error("Assertion failed on job for %s.", strna(d
->name
));
2046 else if (streq(d
->result
, "unsupported"))
2047 log_error("Operation on or unit type of %s not supported on this system.", strna(d
->name
));
2048 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped")) {
2051 _cleanup_free_
char *result
= NULL
;
2053 q
= bus_job_get_service_result(d
, &result
);
2055 log_debug_errno(q
, "Failed to get Result property of service %s: %m", d
->name
);
2057 log_job_error_with_service_result(d
->name
, result
);
2059 log_error("Job failed. See \"journalctl -xe\" for details.");
2063 if (streq(d
->result
, "canceled"))
2065 else if (streq(d
->result
, "timeout"))
2067 else if (streq(d
->result
, "dependency"))
2069 else if (streq(d
->result
, "invalid"))
2071 else if (streq(d
->result
, "assert"))
2073 else if (streq(d
->result
, "unsupported"))
2075 else if (!streq(d
->result
, "done") && !streq(d
->result
, "skipped"))
2081 int bus_wait_for_jobs(BusWaitForJobs
*d
, bool quiet
) {
2086 while (!set_isempty(d
->jobs
)) {
2089 q
= bus_process_wait(d
->bus
);
2091 return log_error_errno(q
, "Failed to wait for response: %m");
2094 q
= check_wait_response(d
, quiet
);
2095 /* Return the first error as it is most likely to be
2097 if (q
< 0 && r
== 0)
2100 log_debug_errno(q
, "Got result %s/%m for job %s", strna(d
->result
), strna(d
->name
));
2103 d
->name
= mfree(d
->name
);
2104 d
->result
= mfree(d
->result
);
2110 int bus_wait_for_jobs_add(BusWaitForJobs
*d
, const char *path
) {
2115 r
= set_ensure_allocated(&d
->jobs
, &string_hash_ops
);
2119 return set_put_strdup(d
->jobs
, path
);
2122 int bus_wait_for_jobs_one(BusWaitForJobs
*d
, const char *path
, bool quiet
) {
2125 r
= bus_wait_for_jobs_add(d
, path
);
2129 return bus_wait_for_jobs(d
, quiet
);
2132 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message
*m
, bool quiet
, UnitFileChange
**changes
, unsigned *n_changes
) {
2133 const char *type
, *path
, *source
;
2136 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sss)");
2138 return bus_log_parse_error(r
);
2140 while ((r
= sd_bus_message_read(m
, "(sss)", &type
, &path
, &source
)) > 0) {
2142 if (streq(type
, "symlink"))
2143 log_info("Created symlink from %s to %s.", path
, source
);
2145 log_info("Removed symlink %s.", path
);
2148 r
= unit_file_changes_add(changes
, n_changes
, streq(type
, "symlink") ? UNIT_FILE_SYMLINK
: UNIT_FILE_UNLINK
, path
, source
);
2153 return bus_log_parse_error(r
);
2155 r
= sd_bus_message_exit_container(m
);
2157 return bus_log_parse_error(r
);
2163 * bus_path_encode_unique() - encode unique object path
2164 * @b: bus connection or NULL
2165 * @prefix: object path prefix
2166 * @sender_id: unique-name of client, or NULL
2167 * @external_id: external ID to be chosen by client, or NULL
2168 * @ret_path: storage for encoded object path pointer
2170 * Whenever we provide a bus API that allows clients to create and manage
2171 * server-side objects, we need to provide a unique name for these objects. If
2172 * we let the server choose the name, we suffer from a race condition: If a
2173 * client creates an object asynchronously, it cannot destroy that object until
2174 * it received the method reply. It cannot know the name of the new object,
2175 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
2177 * Therefore, many APIs allow the client to choose the unique name for newly
2178 * created objects. There're two problems to solve, though:
2179 * 1) Object names are usually defined via dbus object paths, which are
2180 * usually globally namespaced. Therefore, multiple clients must be able
2181 * to choose unique object names without interference.
2182 * 2) If multiple libraries share the same bus connection, they must be
2183 * able to choose unique object names without interference.
2184 * The first problem is solved easily by prefixing a name with the
2185 * unique-bus-name of a connection. The server side must enforce this and
2186 * reject any other name. The second problem is solved by providing unique
2187 * suffixes from within sd-bus.
2189 * This helper allows clients to create unique object-paths. It uses the
2190 * template '/prefix/sender_id/external_id' and returns the new path in
2191 * @ret_path (must be freed by the caller).
2192 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2193 * NULL, this function allocates a unique suffix via @b (by requesting a new
2194 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2197 * Returns: 0 on success, negative error code on failure.
2199 int bus_path_encode_unique(sd_bus
*b
, const char *prefix
, const char *sender_id
, const char *external_id
, char **ret_path
) {
2200 _cleanup_free_
char *sender_label
= NULL
, *external_label
= NULL
;
2201 char external_buf
[DECIMAL_STR_MAX(uint64_t)], *p
;
2204 assert_return(b
|| (sender_id
&& external_id
), -EINVAL
);
2205 assert_return(object_path_is_valid(prefix
), -EINVAL
);
2206 assert_return(ret_path
, -EINVAL
);
2209 r
= sd_bus_get_unique_name(b
, &sender_id
);
2215 xsprintf(external_buf
, "%"PRIu64
, ++b
->cookie
);
2216 external_id
= external_buf
;
2219 sender_label
= bus_label_escape(sender_id
);
2223 external_label
= bus_label_escape(external_id
);
2224 if (!external_label
)
2227 p
= strjoin(prefix
, "/", sender_label
, "/", external_label
, NULL
);
2236 * bus_path_decode_unique() - decode unique object path
2237 * @path: object path to decode
2238 * @prefix: object path prefix
2239 * @ret_sender: output parameter for sender-id label
2240 * @ret_external: output parameter for external-id label
2242 * This does the reverse of bus_path_encode_unique() (see its description for
2243 * details). Both trailing labels, sender-id and external-id, are unescaped and
2244 * returned in the given output parameters (the caller must free them).
2246 * Note that this function returns 0 if the path does not match the template
2247 * (see bus_path_encode_unique()), 1 if it matched.
2249 * Returns: Negative error code on failure, 0 if the given object path does not
2250 * match the template (return parameters are set to NULL), 1 if it was
2251 * parsed successfully (return parameters contain allocated labels).
2253 int bus_path_decode_unique(const char *path
, const char *prefix
, char **ret_sender
, char **ret_external
) {
2255 char *sender
, *external
;
2257 assert(object_path_is_valid(path
));
2258 assert(object_path_is_valid(prefix
));
2260 assert(ret_external
);
2262 p
= object_path_startswith(path
, prefix
);
2265 *ret_external
= NULL
;
2272 *ret_external
= NULL
;
2276 sender
= bus_label_unescape_n(p
, q
- p
);
2277 external
= bus_label_unescape(q
+ 1);
2278 if (!sender
|| !external
) {
2284 *ret_sender
= sender
;
2285 *ret_external
= external
;
2289 bool is_kdbus_wanted(void) {
2290 _cleanup_free_
char *value
= NULL
;
2292 const bool configured
= true;
2294 const bool configured
= false;
2299 if (get_proc_cmdline_key("kdbus", NULL
) > 0)
2302 r
= get_proc_cmdline_key("kdbus=", &value
);
2306 return parse_boolean(value
) == 1;
2309 bool is_kdbus_available(void) {
2310 _cleanup_close_
int fd
= -1;
2311 struct kdbus_cmd cmd
= { .size
= sizeof(cmd
), .flags
= KDBUS_FLAG_NEGOTIATE
};
2313 if (!is_kdbus_wanted())
2316 fd
= open("/sys/fs/kdbus/control", O_RDWR
| O_CLOEXEC
| O_NONBLOCK
| O_NOCTTY
);
2320 return ioctl(fd
, KDBUS_CMD_BUS_MAKE
, &cmd
) >= 0;
2323 int bus_property_get_rlimit(
2326 const char *interface
,
2327 const char *property
,
2328 sd_bus_message
*reply
,
2330 sd_bus_error
*error
) {
2340 rl
= *(struct rlimit
**) userdata
;
2344 struct rlimit buf
= {};
2347 z
= rlimit_from_string(strstr(property
, "Limit"));
2354 /* rlim_t might have different sizes, let's map
2355 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
2357 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
2359 return sd_bus_message_append(reply
, "t", u
);