]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-util.c
Hook more properties for transient units
[thirdparty/systemd.git] / src / shared / bus-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <sys/socket.h>
23
24 #include "sd-daemon.h"
25 #include "sd-event.h"
26 #include "util.h"
27 #include "strv.h"
28 #include "macro.h"
29 #include "def.h"
30 #include "path-util.h"
31 #include "missing.h"
32 #include "set.h"
33 #include "signal-util.h"
34 #include "unit-name.h"
35
36 #include "sd-bus.h"
37 #include "bus-error.h"
38 #include "bus-label.h"
39 #include "bus-message.h"
40 #include "bus-util.h"
41 #include "bus-internal.h"
42
43 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
44 sd_event *e = userdata;
45
46 assert(m);
47 assert(e);
48
49 sd_bus_close(sd_bus_message_get_bus(m));
50 sd_event_exit(e, 0);
51
52 return 1;
53 }
54
55 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
56 _cleanup_free_ char *match = NULL;
57 const char *unique;
58 int r;
59
60 assert(e);
61 assert(bus);
62 assert(name);
63
64 /* We unregister the name here and then wait for the
65 * NameOwnerChanged signal for this event to arrive before we
66 * quit. We do this in order to make sure that any queued
67 * requests are still processed before we really exit. */
68
69 r = sd_bus_get_unique_name(bus, &unique);
70 if (r < 0)
71 return r;
72
73 r = asprintf(&match,
74 "sender='org.freedesktop.DBus',"
75 "type='signal',"
76 "interface='org.freedesktop.DBus',"
77 "member='NameOwnerChanged',"
78 "path='/org/freedesktop/DBus',"
79 "arg0='%s',"
80 "arg1='%s',"
81 "arg2=''", name, unique);
82 if (r < 0)
83 return -ENOMEM;
84
85 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
86 if (r < 0)
87 return r;
88
89 r = sd_bus_release_name(bus, name);
90 if (r < 0)
91 return r;
92
93 return 0;
94 }
95
96 int bus_event_loop_with_idle(
97 sd_event *e,
98 sd_bus *bus,
99 const char *name,
100 usec_t timeout,
101 check_idle_t check_idle,
102 void *userdata) {
103 bool exiting = false;
104 int r, code;
105
106 assert(e);
107 assert(bus);
108 assert(name);
109
110 for (;;) {
111 bool idle;
112
113 r = sd_event_get_state(e);
114 if (r < 0)
115 return r;
116 if (r == SD_EVENT_FINISHED)
117 break;
118
119 if (check_idle)
120 idle = check_idle(userdata);
121 else
122 idle = true;
123
124 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
125 if (r < 0)
126 return r;
127
128 if (r == 0 && !exiting && idle) {
129
130 r = sd_bus_try_close(bus);
131 if (r == -EBUSY)
132 continue;
133
134 /* Fallback for dbus1 connections: we
135 * unregister the name and wait for the
136 * response to come through for it */
137 if (r == -EOPNOTSUPP) {
138
139 /* Inform the service manager that we
140 * are going down, so that it will
141 * queue all further start requests,
142 * instead of assuming we are already
143 * running. */
144 sd_notify(false, "STOPPING=1");
145
146 r = bus_async_unregister_and_exit(e, bus, name);
147 if (r < 0)
148 return r;
149
150 exiting = true;
151 continue;
152 }
153
154 if (r < 0)
155 return r;
156
157 sd_event_exit(e, 0);
158 break;
159 }
160 }
161
162 r = sd_event_get_exit_code(e, &code);
163 if (r < 0)
164 return r;
165
166 return code;
167 }
168
169 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
170 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
171 int r, has_owner = 0;
172
173 assert(c);
174 assert(name);
175
176 r = sd_bus_call_method(c,
177 "org.freedesktop.DBus",
178 "/org/freedesktop/dbus",
179 "org.freedesktop.DBus",
180 "NameHasOwner",
181 error,
182 &rep,
183 "s",
184 name);
185 if (r < 0)
186 return r;
187
188 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
189 if (r < 0)
190 return sd_bus_error_set_errno(error, r);
191
192 return has_owner;
193 }
194
195 static int check_good_user(sd_bus_message *m, uid_t good_user) {
196 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
197 uid_t sender_uid;
198 int r;
199
200 assert(m);
201
202 if (good_user == UID_INVALID)
203 return 0;
204
205 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
206 if (r < 0)
207 return r;
208
209 /* Don't trust augmented credentials for authorization */
210 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
211
212 r = sd_bus_creds_get_euid(creds, &sender_uid);
213 if (r < 0)
214 return r;
215
216 return sender_uid == good_user;
217 }
218
219 int bus_test_polkit(
220 sd_bus_message *call,
221 int capability,
222 const char *action,
223 const char **details,
224 uid_t good_user,
225 bool *_challenge,
226 sd_bus_error *e) {
227
228 int r;
229
230 assert(call);
231 assert(action);
232
233 /* Tests non-interactively! */
234
235 r = check_good_user(call, good_user);
236 if (r != 0)
237 return r;
238
239 r = sd_bus_query_sender_privilege(call, capability);
240 if (r < 0)
241 return r;
242 else if (r > 0)
243 return 1;
244 #ifdef ENABLE_POLKIT
245 else {
246 _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
247 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
248 int authorized = false, challenge = false;
249 const char *sender, **k, **v;
250
251 sender = sd_bus_message_get_sender(call);
252 if (!sender)
253 return -EBADMSG;
254
255 r = sd_bus_message_new_method_call(
256 call->bus,
257 &request,
258 "org.freedesktop.PolicyKit1",
259 "/org/freedesktop/PolicyKit1/Authority",
260 "org.freedesktop.PolicyKit1.Authority",
261 "CheckAuthorization");
262 if (r < 0)
263 return r;
264
265 r = sd_bus_message_append(
266 request,
267 "(sa{sv})s",
268 "system-bus-name", 1, "name", "s", sender,
269 action);
270 if (r < 0)
271 return r;
272
273 r = sd_bus_message_open_container(request, 'a', "{ss}");
274 if (r < 0)
275 return r;
276
277 STRV_FOREACH_PAIR(k, v, details) {
278 r = sd_bus_message_append(request, "{ss}", *k, *v);
279 if (r < 0)
280 return r;
281 }
282
283 r = sd_bus_message_close_container(request);
284 if (r < 0)
285 return r;
286
287 r = sd_bus_message_append(request, "us", 0, NULL);
288 if (r < 0)
289 return r;
290
291 r = sd_bus_call(call->bus, request, 0, e, &reply);
292 if (r < 0) {
293 /* Treat no PK available as access denied */
294 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
295 sd_bus_error_free(e);
296 return -EACCES;
297 }
298
299 return r;
300 }
301
302 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
303 if (r < 0)
304 return r;
305
306 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
307 if (r < 0)
308 return r;
309
310 if (authorized)
311 return 1;
312
313 if (_challenge) {
314 *_challenge = challenge;
315 return 0;
316 }
317 }
318 #endif
319
320 return -EACCES;
321 }
322
323 #ifdef ENABLE_POLKIT
324
325 typedef struct AsyncPolkitQuery {
326 sd_bus_message *request, *reply;
327 sd_bus_message_handler_t callback;
328 void *userdata;
329 sd_bus_slot *slot;
330 Hashmap *registry;
331 } AsyncPolkitQuery;
332
333 static void async_polkit_query_free(AsyncPolkitQuery *q) {
334
335 if (!q)
336 return;
337
338 sd_bus_slot_unref(q->slot);
339
340 if (q->registry && q->request)
341 hashmap_remove(q->registry, q->request);
342
343 sd_bus_message_unref(q->request);
344 sd_bus_message_unref(q->reply);
345
346 free(q);
347 }
348
349 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
350 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
351 AsyncPolkitQuery *q = userdata;
352 int r;
353
354 assert(reply);
355 assert(q);
356
357 q->slot = sd_bus_slot_unref(q->slot);
358 q->reply = sd_bus_message_ref(reply);
359
360 r = sd_bus_message_rewind(q->request, true);
361 if (r < 0) {
362 r = sd_bus_reply_method_errno(q->request, r, NULL);
363 goto finish;
364 }
365
366 r = q->callback(q->request, q->userdata, &error_buffer);
367 r = bus_maybe_reply_error(q->request, r, &error_buffer);
368
369 finish:
370 async_polkit_query_free(q);
371
372 return r;
373 }
374
375 #endif
376
377 int bus_verify_polkit_async(
378 sd_bus_message *call,
379 int capability,
380 const char *action,
381 const char **details,
382 bool interactive,
383 uid_t good_user,
384 Hashmap **registry,
385 sd_bus_error *error) {
386
387 #ifdef ENABLE_POLKIT
388 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
389 AsyncPolkitQuery *q;
390 const char *sender, **k, **v;
391 sd_bus_message_handler_t callback;
392 void *userdata;
393 int c;
394 #endif
395 int r;
396
397 assert(call);
398 assert(action);
399 assert(registry);
400
401 r = check_good_user(call, good_user);
402 if (r != 0)
403 return r;
404
405 #ifdef ENABLE_POLKIT
406 q = hashmap_get(*registry, call);
407 if (q) {
408 int authorized, challenge;
409
410 /* This is the second invocation of this function, and
411 * there's already a response from polkit, let's
412 * process it */
413 assert(q->reply);
414
415 if (sd_bus_message_is_method_error(q->reply, NULL)) {
416 const sd_bus_error *e;
417
418 /* Copy error from polkit reply */
419 e = sd_bus_message_get_error(q->reply);
420 sd_bus_error_copy(error, e);
421
422 /* Treat no PK available as access denied */
423 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
424 return -EACCES;
425
426 return -sd_bus_error_get_errno(e);
427 }
428
429 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
430 if (r >= 0)
431 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
432
433 if (r < 0)
434 return r;
435
436 if (authorized)
437 return 1;
438
439 if (challenge)
440 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
441
442 return -EACCES;
443 }
444 #endif
445
446 r = sd_bus_query_sender_privilege(call, capability);
447 if (r < 0)
448 return r;
449 else if (r > 0)
450 return 1;
451
452 #ifdef ENABLE_POLKIT
453 if (sd_bus_get_current_message(call->bus) != call)
454 return -EINVAL;
455
456 callback = sd_bus_get_current_handler(call->bus);
457 if (!callback)
458 return -EINVAL;
459
460 userdata = sd_bus_get_current_userdata(call->bus);
461
462 sender = sd_bus_message_get_sender(call);
463 if (!sender)
464 return -EBADMSG;
465
466 c = sd_bus_message_get_allow_interactive_authorization(call);
467 if (c < 0)
468 return c;
469 if (c > 0)
470 interactive = true;
471
472 r = hashmap_ensure_allocated(registry, NULL);
473 if (r < 0)
474 return r;
475
476 r = sd_bus_message_new_method_call(
477 call->bus,
478 &pk,
479 "org.freedesktop.PolicyKit1",
480 "/org/freedesktop/PolicyKit1/Authority",
481 "org.freedesktop.PolicyKit1.Authority",
482 "CheckAuthorization");
483 if (r < 0)
484 return r;
485
486 r = sd_bus_message_append(
487 pk,
488 "(sa{sv})s",
489 "system-bus-name", 1, "name", "s", sender,
490 action);
491 if (r < 0)
492 return r;
493
494 r = sd_bus_message_open_container(pk, 'a', "{ss}");
495 if (r < 0)
496 return r;
497
498 STRV_FOREACH_PAIR(k, v, details) {
499 r = sd_bus_message_append(pk, "{ss}", *k, *v);
500 if (r < 0)
501 return r;
502 }
503
504 r = sd_bus_message_close_container(pk);
505 if (r < 0)
506 return r;
507
508 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
509 if (r < 0)
510 return r;
511
512 q = new0(AsyncPolkitQuery, 1);
513 if (!q)
514 return -ENOMEM;
515
516 q->request = sd_bus_message_ref(call);
517 q->callback = callback;
518 q->userdata = userdata;
519
520 r = hashmap_put(*registry, call, q);
521 if (r < 0) {
522 async_polkit_query_free(q);
523 return r;
524 }
525
526 q->registry = *registry;
527
528 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
529 if (r < 0) {
530 async_polkit_query_free(q);
531 return r;
532 }
533
534 return 0;
535 #endif
536
537 return -EACCES;
538 }
539
540 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
541 #ifdef ENABLE_POLKIT
542 AsyncPolkitQuery *q;
543
544 while ((q = hashmap_steal_first(registry)))
545 async_polkit_query_free(q);
546
547 hashmap_free(registry);
548 #endif
549 }
550
551 int bus_check_peercred(sd_bus *c) {
552 struct ucred ucred;
553 socklen_t l;
554 int fd;
555
556 assert(c);
557
558 fd = sd_bus_get_fd(c);
559 if (fd < 0)
560 return fd;
561
562 l = sizeof(struct ucred);
563 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
564 return -errno;
565
566 if (l != sizeof(struct ucred))
567 return -E2BIG;
568
569 if (ucred.uid != 0 && ucred.uid != geteuid())
570 return -EPERM;
571
572 return 1;
573 }
574
575 int bus_open_system_systemd(sd_bus **_bus) {
576 _cleanup_bus_unref_ sd_bus *bus = NULL;
577 int r;
578
579 assert(_bus);
580
581 if (geteuid() != 0)
582 return sd_bus_open_system(_bus);
583
584 /* If we are root and kdbus is not available, then let's talk
585 * directly to the system instance, instead of going via the
586 * bus */
587
588 r = sd_bus_new(&bus);
589 if (r < 0)
590 return r;
591
592 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
593 if (r < 0)
594 return r;
595
596 bus->bus_client = true;
597
598 r = sd_bus_start(bus);
599 if (r >= 0) {
600 *_bus = bus;
601 bus = NULL;
602 return 0;
603 }
604
605 bus = sd_bus_unref(bus);
606
607 r = sd_bus_new(&bus);
608 if (r < 0)
609 return r;
610
611 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
612 if (r < 0)
613 return r;
614
615 r = sd_bus_start(bus);
616 if (r < 0)
617 return sd_bus_open_system(_bus);
618
619 r = bus_check_peercred(bus);
620 if (r < 0)
621 return r;
622
623 *_bus = bus;
624 bus = NULL;
625
626 return 0;
627 }
628
629 int bus_open_user_systemd(sd_bus **_bus) {
630 _cleanup_bus_unref_ sd_bus *bus = NULL;
631 _cleanup_free_ char *ee = NULL;
632 const char *e;
633 int r;
634
635 /* Try via kdbus first, and then directly */
636
637 assert(_bus);
638
639 r = sd_bus_new(&bus);
640 if (r < 0)
641 return r;
642
643 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
644 return -ENOMEM;
645
646 bus->bus_client = true;
647
648 r = sd_bus_start(bus);
649 if (r >= 0) {
650 *_bus = bus;
651 bus = NULL;
652 return 0;
653 }
654
655 bus = sd_bus_unref(bus);
656
657 e = secure_getenv("XDG_RUNTIME_DIR");
658 if (!e)
659 return sd_bus_open_user(_bus);
660
661 ee = bus_address_escape(e);
662 if (!ee)
663 return -ENOMEM;
664
665 r = sd_bus_new(&bus);
666 if (r < 0)
667 return r;
668
669 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
670 if (!bus->address)
671 return -ENOMEM;
672
673 r = sd_bus_start(bus);
674 if (r < 0)
675 return sd_bus_open_user(_bus);
676
677 r = bus_check_peercred(bus);
678 if (r < 0)
679 return r;
680
681 *_bus = bus;
682 bus = NULL;
683
684 return 0;
685 }
686
687 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
688 char type;
689 const char *contents;
690 int r;
691
692 assert(name);
693 assert(property);
694
695 r = sd_bus_message_peek_type(property, &type, &contents);
696 if (r < 0)
697 return r;
698
699 switch (type) {
700
701 case SD_BUS_TYPE_STRING: {
702 const char *s;
703
704 r = sd_bus_message_read_basic(property, type, &s);
705 if (r < 0)
706 return r;
707
708 if (all || !isempty(s)) {
709 _cleanup_free_ char *escaped = NULL;
710
711 escaped = xescape(s, "\n");
712 if (!escaped)
713 return -ENOMEM;
714
715 printf("%s=%s\n", name, escaped);
716 }
717
718 return 1;
719 }
720
721 case SD_BUS_TYPE_BOOLEAN: {
722 int b;
723
724 r = sd_bus_message_read_basic(property, type, &b);
725 if (r < 0)
726 return r;
727
728 printf("%s=%s\n", name, yes_no(b));
729
730 return 1;
731 }
732
733 case SD_BUS_TYPE_UINT64: {
734 uint64_t u;
735
736 r = sd_bus_message_read_basic(property, type, &u);
737 if (r < 0)
738 return r;
739
740 /* Yes, heuristics! But we can change this check
741 * should it turn out to not be sufficient */
742
743 if (endswith(name, "Timestamp")) {
744 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
745
746 t = format_timestamp(timestamp, sizeof(timestamp), u);
747 if (t || all)
748 printf("%s=%s\n", name, strempty(t));
749
750 } else if (strstr(name, "USec")) {
751 char timespan[FORMAT_TIMESPAN_MAX];
752
753 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
754 } else
755 printf("%s=%llu\n", name, (unsigned long long) u);
756
757 return 1;
758 }
759
760 case SD_BUS_TYPE_INT64: {
761 int64_t i;
762
763 r = sd_bus_message_read_basic(property, type, &i);
764 if (r < 0)
765 return r;
766
767 printf("%s=%lld\n", name, (long long) i);
768
769 return 1;
770 }
771
772 case SD_BUS_TYPE_UINT32: {
773 uint32_t u;
774
775 r = sd_bus_message_read_basic(property, type, &u);
776 if (r < 0)
777 return r;
778
779 if (strstr(name, "UMask") || strstr(name, "Mode"))
780 printf("%s=%04o\n", name, u);
781 else
782 printf("%s=%u\n", name, (unsigned) u);
783
784 return 1;
785 }
786
787 case SD_BUS_TYPE_INT32: {
788 int32_t i;
789
790 r = sd_bus_message_read_basic(property, type, &i);
791 if (r < 0)
792 return r;
793
794 printf("%s=%i\n", name, (int) i);
795 return 1;
796 }
797
798 case SD_BUS_TYPE_DOUBLE: {
799 double d;
800
801 r = sd_bus_message_read_basic(property, type, &d);
802 if (r < 0)
803 return r;
804
805 printf("%s=%g\n", name, d);
806 return 1;
807 }
808
809 case SD_BUS_TYPE_ARRAY:
810 if (streq(contents, "s")) {
811 bool first = true;
812 const char *str;
813
814 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
815 if (r < 0)
816 return r;
817
818 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
819 _cleanup_free_ char *escaped = NULL;
820
821 if (first)
822 printf("%s=", name);
823
824 escaped = xescape(str, "\n ");
825 if (!escaped)
826 return -ENOMEM;
827
828 printf("%s%s", first ? "" : " ", escaped);
829
830 first = false;
831 }
832 if (r < 0)
833 return r;
834
835 if (first && all)
836 printf("%s=", name);
837 if (!first || all)
838 puts("");
839
840 r = sd_bus_message_exit_container(property);
841 if (r < 0)
842 return r;
843
844 return 1;
845
846 } else if (streq(contents, "y")) {
847 const uint8_t *u;
848 size_t n;
849
850 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
851 if (r < 0)
852 return r;
853
854 if (all || n > 0) {
855 unsigned int i;
856
857 printf("%s=", name);
858
859 for (i = 0; i < n; i++)
860 printf("%02x", u[i]);
861
862 puts("");
863 }
864
865 return 1;
866
867 } else if (streq(contents, "u")) {
868 uint32_t *u;
869 size_t n;
870
871 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
872 if (r < 0)
873 return r;
874
875 if (all || n > 0) {
876 unsigned int i;
877
878 printf("%s=", name);
879
880 for (i = 0; i < n; i++)
881 printf("%08x", u[i]);
882
883 puts("");
884 }
885
886 return 1;
887 }
888
889 break;
890 }
891
892 return 0;
893 }
894
895 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
896 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
897 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
898 int r;
899
900 assert(bus);
901 assert(path);
902
903 r = sd_bus_call_method(bus,
904 dest,
905 path,
906 "org.freedesktop.DBus.Properties",
907 "GetAll",
908 &error,
909 &reply,
910 "s", "");
911 if (r < 0)
912 return r;
913
914 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
915 if (r < 0)
916 return r;
917
918 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
919 const char *name;
920 const char *contents;
921
922 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
923 if (r < 0)
924 return r;
925
926 if (!filter || strv_find(filter, name)) {
927 r = sd_bus_message_peek_type(reply, NULL, &contents);
928 if (r < 0)
929 return r;
930
931 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
932 if (r < 0)
933 return r;
934
935 r = bus_print_property(name, reply, all);
936 if (r < 0)
937 return r;
938 if (r == 0) {
939 if (all)
940 printf("%s=[unprintable]\n", name);
941 /* skip what we didn't read */
942 r = sd_bus_message_skip(reply, contents);
943 if (r < 0)
944 return r;
945 }
946
947 r = sd_bus_message_exit_container(reply);
948 if (r < 0)
949 return r;
950 } else {
951 r = sd_bus_message_skip(reply, "v");
952 if (r < 0)
953 return r;
954 }
955
956 r = sd_bus_message_exit_container(reply);
957 if (r < 0)
958 return r;
959 }
960 if (r < 0)
961 return r;
962
963 r = sd_bus_message_exit_container(reply);
964 if (r < 0)
965 return r;
966
967 return 0;
968 }
969
970 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
971 sd_id128_t *p = userdata;
972 const void *v;
973 size_t n;
974 int r;
975
976 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
977 if (r < 0)
978 return r;
979
980 if (n == 0)
981 *p = SD_ID128_NULL;
982 else if (n == 16)
983 memcpy((*p).bytes, v, n);
984 else
985 return -EINVAL;
986
987 return 0;
988 }
989
990 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
991 char type;
992 int r;
993
994 r = sd_bus_message_peek_type(m, &type, NULL);
995 if (r < 0)
996 return r;
997
998 switch (type) {
999 case SD_BUS_TYPE_STRING: {
1000 const char *s;
1001 char **p = userdata;
1002
1003 r = sd_bus_message_read_basic(m, type, &s);
1004 if (r < 0)
1005 break;
1006
1007 if (isempty(s))
1008 break;
1009
1010 r = free_and_strdup(p, s);
1011 break;
1012 }
1013
1014 case SD_BUS_TYPE_ARRAY: {
1015 _cleanup_strv_free_ char **l = NULL;
1016 char ***p = userdata;
1017
1018 r = bus_message_read_strv_extend(m, &l);
1019 if (r < 0)
1020 break;
1021
1022 strv_free(*p);
1023 *p = l;
1024 l = NULL;
1025
1026 break;
1027 }
1028
1029 case SD_BUS_TYPE_BOOLEAN: {
1030 unsigned b;
1031 bool *p = userdata;
1032
1033 r = sd_bus_message_read_basic(m, type, &b);
1034 if (r < 0)
1035 break;
1036
1037 *p = b;
1038
1039 break;
1040 }
1041
1042 case SD_BUS_TYPE_UINT32: {
1043 uint64_t u;
1044 uint32_t *p = userdata;
1045
1046 r = sd_bus_message_read_basic(m, type, &u);
1047 if (r < 0)
1048 break;
1049
1050 *p = u;
1051
1052 break;
1053 }
1054
1055 case SD_BUS_TYPE_UINT64: {
1056 uint64_t t;
1057 uint64_t *p = userdata;
1058
1059 r = sd_bus_message_read_basic(m, type, &t);
1060 if (r < 0)
1061 break;
1062
1063 *p = t;
1064
1065 break;
1066 }
1067
1068 default:
1069 break;
1070 }
1071
1072 return r;
1073 }
1074
1075 int bus_message_map_all_properties(
1076 sd_bus_message *m,
1077 const struct bus_properties_map *map,
1078 void *userdata) {
1079
1080 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1081 int r;
1082
1083 assert(m);
1084 assert(map);
1085
1086 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1087 if (r < 0)
1088 return r;
1089
1090 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1091 const struct bus_properties_map *prop;
1092 const char *member;
1093 const char *contents;
1094 void *v;
1095 unsigned i;
1096
1097 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1098 if (r < 0)
1099 return r;
1100
1101 for (i = 0, prop = NULL; map[i].member; i++)
1102 if (streq(map[i].member, member)) {
1103 prop = &map[i];
1104 break;
1105 }
1106
1107 if (prop) {
1108 r = sd_bus_message_peek_type(m, NULL, &contents);
1109 if (r < 0)
1110 return r;
1111
1112 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1113 if (r < 0)
1114 return r;
1115
1116 v = (uint8_t *)userdata + prop->offset;
1117 if (map[i].set)
1118 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1119 else
1120 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1121 if (r < 0)
1122 return r;
1123
1124 r = sd_bus_message_exit_container(m);
1125 if (r < 0)
1126 return r;
1127 } else {
1128 r = sd_bus_message_skip(m, "v");
1129 if (r < 0)
1130 return r;
1131 }
1132
1133 r = sd_bus_message_exit_container(m);
1134 if (r < 0)
1135 return r;
1136 }
1137 if (r < 0)
1138 return r;
1139
1140 return sd_bus_message_exit_container(m);
1141 }
1142
1143 int bus_message_map_properties_changed(
1144 sd_bus_message *m,
1145 const struct bus_properties_map *map,
1146 void *userdata) {
1147
1148 const char *member;
1149 int r, invalidated, i;
1150
1151 assert(m);
1152 assert(map);
1153
1154 r = bus_message_map_all_properties(m, map, userdata);
1155 if (r < 0)
1156 return r;
1157
1158 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1159 if (r < 0)
1160 return r;
1161
1162 invalidated = 0;
1163 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1164 for (i = 0; map[i].member; i++)
1165 if (streq(map[i].member, member)) {
1166 ++invalidated;
1167 break;
1168 }
1169 if (r < 0)
1170 return r;
1171
1172 r = sd_bus_message_exit_container(m);
1173 if (r < 0)
1174 return r;
1175
1176 return invalidated;
1177 }
1178
1179 int bus_map_all_properties(
1180 sd_bus *bus,
1181 const char *destination,
1182 const char *path,
1183 const struct bus_properties_map *map,
1184 void *userdata) {
1185
1186 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1187 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1188 int r;
1189
1190 assert(bus);
1191 assert(destination);
1192 assert(path);
1193 assert(map);
1194
1195 r = sd_bus_call_method(
1196 bus,
1197 destination,
1198 path,
1199 "org.freedesktop.DBus.Properties",
1200 "GetAll",
1201 &error,
1202 &m,
1203 "s", "");
1204 if (r < 0)
1205 return r;
1206
1207 return bus_message_map_all_properties(m, map, userdata);
1208 }
1209
1210 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1211 int r;
1212
1213 assert(transport >= 0);
1214 assert(transport < _BUS_TRANSPORT_MAX);
1215 assert(bus);
1216
1217 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1218 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1219
1220 switch (transport) {
1221
1222 case BUS_TRANSPORT_LOCAL:
1223 if (user)
1224 r = sd_bus_default_user(bus);
1225 else
1226 r = sd_bus_default_system(bus);
1227
1228 break;
1229
1230 case BUS_TRANSPORT_REMOTE:
1231 r = sd_bus_open_system_remote(bus, host);
1232 break;
1233
1234 case BUS_TRANSPORT_MACHINE:
1235 r = sd_bus_open_system_machine(bus, host);
1236 break;
1237
1238 default:
1239 assert_not_reached("Hmm, unknown transport type.");
1240 }
1241
1242 return r;
1243 }
1244
1245 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1246 int r;
1247
1248 assert(transport >= 0);
1249 assert(transport < _BUS_TRANSPORT_MAX);
1250 assert(bus);
1251
1252 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1253 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1254
1255 switch (transport) {
1256
1257 case BUS_TRANSPORT_LOCAL:
1258 if (user)
1259 r = bus_open_user_systemd(bus);
1260 else
1261 r = bus_open_system_systemd(bus);
1262
1263 break;
1264
1265 case BUS_TRANSPORT_REMOTE:
1266 r = sd_bus_open_system_remote(bus, host);
1267 break;
1268
1269 case BUS_TRANSPORT_MACHINE:
1270 r = sd_bus_open_system_machine(bus, host);
1271 break;
1272
1273 default:
1274 assert_not_reached("Hmm, unknown transport type.");
1275 }
1276
1277 return r;
1278 }
1279
1280 int bus_property_get_bool(
1281 sd_bus *bus,
1282 const char *path,
1283 const char *interface,
1284 const char *property,
1285 sd_bus_message *reply,
1286 void *userdata,
1287 sd_bus_error *error) {
1288
1289 int b = *(bool*) userdata;
1290
1291 return sd_bus_message_append_basic(reply, 'b', &b);
1292 }
1293
1294 #if __SIZEOF_SIZE_T__ != 8
1295 int bus_property_get_size(
1296 sd_bus *bus,
1297 const char *path,
1298 const char *interface,
1299 const char *property,
1300 sd_bus_message *reply,
1301 void *userdata,
1302 sd_bus_error *error) {
1303
1304 uint64_t sz = *(size_t*) userdata;
1305
1306 return sd_bus_message_append_basic(reply, 't', &sz);
1307 }
1308 #endif
1309
1310 #if __SIZEOF_LONG__ != 8
1311 int bus_property_get_long(
1312 sd_bus *bus,
1313 const char *path,
1314 const char *interface,
1315 const char *property,
1316 sd_bus_message *reply,
1317 void *userdata,
1318 sd_bus_error *error) {
1319
1320 int64_t l = *(long*) userdata;
1321
1322 return sd_bus_message_append_basic(reply, 'x', &l);
1323 }
1324
1325 int bus_property_get_ulong(
1326 sd_bus *bus,
1327 const char *path,
1328 const char *interface,
1329 const char *property,
1330 sd_bus_message *reply,
1331 void *userdata,
1332 sd_bus_error *error) {
1333
1334 uint64_t ul = *(unsigned long*) userdata;
1335
1336 return sd_bus_message_append_basic(reply, 't', &ul);
1337 }
1338 #endif
1339
1340 int bus_log_parse_error(int r) {
1341 return log_error_errno(r, "Failed to parse bus message: %m");
1342 }
1343
1344 int bus_log_create_error(int r) {
1345 return log_error_errno(r, "Failed to create bus message: %m");
1346 }
1347
1348 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1349 assert(message);
1350 assert(u);
1351
1352 u->machine = NULL;
1353
1354 return sd_bus_message_read(
1355 message,
1356 "(ssssssouso)",
1357 &u->id,
1358 &u->description,
1359 &u->load_state,
1360 &u->active_state,
1361 &u->sub_state,
1362 &u->following,
1363 &u->unit_path,
1364 &u->job_id,
1365 &u->job_type,
1366 &u->job_path);
1367 }
1368
1369 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1370 const char *eq, *field;
1371 int r;
1372
1373 assert(m);
1374 assert(assignment);
1375
1376 eq = strchr(assignment, '=');
1377 if (!eq) {
1378 log_error("Not an assignment: %s", assignment);
1379 return -EINVAL;
1380 }
1381
1382 field = strndupa(assignment, eq - assignment);
1383 eq ++;
1384
1385 if (streq(field, "CPUQuota")) {
1386
1387 if (isempty(eq)) {
1388
1389 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1390 if (r < 0)
1391 return bus_log_create_error(r);
1392
1393 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1394
1395 } else if (endswith(eq, "%")) {
1396 double percent;
1397
1398 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1399 log_error("CPU quota '%s' invalid.", eq);
1400 return -EINVAL;
1401 }
1402
1403 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1404 if (r < 0)
1405 return bus_log_create_error(r);
1406
1407 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1408 } else {
1409 log_error("CPU quota needs to be in percent.");
1410 return -EINVAL;
1411 }
1412
1413 if (r < 0)
1414 return bus_log_create_error(r);
1415
1416 return 0;
1417 }
1418
1419 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1420 if (r < 0)
1421 return bus_log_create_error(r);
1422
1423 if (STR_IN_SET(field,
1424 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1425 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1426 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1427 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges")) {
1428
1429 r = parse_boolean(eq);
1430 if (r < 0) {
1431 log_error("Failed to parse boolean assignment %s.", assignment);
1432 return -EINVAL;
1433 }
1434
1435 r = sd_bus_message_append(m, "v", "b", r);
1436
1437 } else if (streq(field, "MemoryLimit")) {
1438 uint64_t bytes;
1439
1440 if (isempty(eq) || streq(eq, "infinity"))
1441 bytes = (uint64_t) -1;
1442 else {
1443 r = parse_size(eq, 1024, &bytes);
1444 if (r < 0) {
1445 log_error("Failed to parse bytes specification %s", assignment);
1446 return -EINVAL;
1447 }
1448 }
1449
1450 r = sd_bus_message_append(m, "v", "t", bytes);
1451
1452 } else if (streq(field, "TasksMax")) {
1453 uint64_t n;
1454
1455 if (isempty(eq) || streq(eq, "infinity"))
1456 n = (uint64_t) -1;
1457 else {
1458 r = safe_atou64(eq, &n);
1459 if (r < 0) {
1460 log_error("Failed to parse maximum tasks specification %s", assignment);
1461 return -EINVAL;
1462 }
1463 }
1464
1465 r = sd_bus_message_append(m, "v", "t", n);
1466
1467 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1468 uint64_t u;
1469
1470 r = safe_atou64(eq, &u);
1471 if (r < 0) {
1472 log_error("Failed to parse %s value %s.", field, eq);
1473 return -EINVAL;
1474 }
1475
1476 r = sd_bus_message_append(m, "v", "t", u);
1477
1478 } else if (STR_IN_SET(field,
1479 "User", "Group", "DevicePolicy", "KillMode",
1480 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1481 "StandardInput", "StandardOutput", "StandardError",
1482 "Description", "Slice", "Type"))
1483 r = sd_bus_message_append(m, "v", "s", eq);
1484
1485 else if (streq(field, "DeviceAllow")) {
1486
1487 if (isempty(eq))
1488 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1489 else {
1490 const char *path, *rwm, *e;
1491
1492 e = strchr(eq, ' ');
1493 if (e) {
1494 path = strndupa(eq, e - eq);
1495 rwm = e+1;
1496 } else {
1497 path = eq;
1498 rwm = "";
1499 }
1500
1501 if (!path_startswith(path, "/dev")) {
1502 log_error("%s is not a device file in /dev.", path);
1503 return -EINVAL;
1504 }
1505
1506 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1507 }
1508
1509 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1510
1511 if (isempty(eq))
1512 r = sd_bus_message_append(m, "v", "a(st)", 0);
1513 else {
1514 const char *path, *bandwidth, *e;
1515 uint64_t bytes;
1516
1517 e = strchr(eq, ' ');
1518 if (e) {
1519 path = strndupa(eq, e - eq);
1520 bandwidth = e+1;
1521 } else {
1522 log_error("Failed to parse %s value %s.", field, eq);
1523 return -EINVAL;
1524 }
1525
1526 if (!path_startswith(path, "/dev")) {
1527 log_error("%s is not a device file in /dev.", path);
1528 return -EINVAL;
1529 }
1530
1531 r = parse_size(bandwidth, 1000, &bytes);
1532 if (r < 0) {
1533 log_error("Failed to parse byte value %s.", bandwidth);
1534 return -EINVAL;
1535 }
1536
1537 r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
1538 }
1539
1540 } else if (streq(field, "BlockIODeviceWeight")) {
1541
1542 if (isempty(eq))
1543 r = sd_bus_message_append(m, "v", "a(st)", 0);
1544 else {
1545 const char *path, *weight, *e;
1546 uint64_t u;
1547
1548 e = strchr(eq, ' ');
1549 if (e) {
1550 path = strndupa(eq, e - eq);
1551 weight = e+1;
1552 } else {
1553 log_error("Failed to parse %s value %s.", field, eq);
1554 return -EINVAL;
1555 }
1556
1557 if (!path_startswith(path, "/dev")) {
1558 log_error("%s is not a device file in /dev.", path);
1559 return -EINVAL;
1560 }
1561
1562 r = safe_atou64(weight, &u);
1563 if (r < 0) {
1564 log_error("Failed to parse %s value %s.", field, weight);
1565 return -EINVAL;
1566 }
1567 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1568 }
1569
1570 } else if (rlimit_from_string(field) >= 0) {
1571 uint64_t rl;
1572
1573 if (streq(eq, "infinity"))
1574 rl = (uint64_t) -1;
1575 else {
1576 r = safe_atou64(eq, &rl);
1577 if (r < 0) {
1578 log_error("Invalid resource limit: %s", eq);
1579 return -EINVAL;
1580 }
1581 }
1582
1583 r = sd_bus_message_append(m, "v", "t", rl);
1584
1585 } else if (streq(field, "Nice")) {
1586 int32_t i;
1587
1588 r = safe_atoi32(eq, &i);
1589 if (r < 0) {
1590 log_error("Failed to parse %s value %s.", field, eq);
1591 return -EINVAL;
1592 }
1593
1594 r = sd_bus_message_append(m, "v", "i", i);
1595
1596 } else if (streq(field, "Environment")) {
1597
1598 r = sd_bus_message_append(m, "v", "as", 1, eq);
1599
1600 } else if (streq(field, "KillSignal")) {
1601 int sig;
1602
1603 sig = signal_from_string_try_harder(eq);
1604 if (sig < 0) {
1605 log_error("Failed to parse %s value %s.", field, eq);
1606 return -EINVAL;
1607 }
1608
1609 r = sd_bus_message_append(m, "v", "i", sig);
1610
1611 } else if (streq(field, "AccuracySec")) {
1612 usec_t u;
1613
1614 r = parse_sec(eq, &u);
1615 if (r < 0) {
1616 log_error("Failed to parse %s value %s", field, eq);
1617 return -EINVAL;
1618 }
1619
1620 r = sd_bus_message_append(m, "v", "t", u);
1621
1622 } else {
1623 log_error("Unknown assignment %s.", assignment);
1624 return -EINVAL;
1625 }
1626
1627 if (r < 0)
1628 return bus_log_create_error(r);
1629
1630 return 0;
1631 }
1632
1633 typedef struct BusWaitForJobs {
1634 sd_bus *bus;
1635 Set *jobs;
1636
1637 char *name;
1638 char *result;
1639
1640 sd_bus_slot *slot_job_removed;
1641 sd_bus_slot *slot_disconnected;
1642 } BusWaitForJobs;
1643
1644 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1645 assert(m);
1646
1647 log_error("Warning! D-Bus connection terminated.");
1648 sd_bus_close(sd_bus_message_get_bus(m));
1649
1650 return 0;
1651 }
1652
1653 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1654 const char *path, *unit, *result;
1655 BusWaitForJobs *d = userdata;
1656 uint32_t id;
1657 char *found;
1658 int r;
1659
1660 assert(m);
1661 assert(d);
1662
1663 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1664 if (r < 0) {
1665 bus_log_parse_error(r);
1666 return 0;
1667 }
1668
1669 found = set_remove(d->jobs, (char*) path);
1670 if (!found)
1671 return 0;
1672
1673 free(found);
1674
1675 if (!isempty(result))
1676 d->result = strdup(result);
1677
1678 if (!isempty(unit))
1679 d->name = strdup(unit);
1680
1681 return 0;
1682 }
1683
1684 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1685 if (!d)
1686 return;
1687
1688 set_free_free(d->jobs);
1689
1690 sd_bus_slot_unref(d->slot_disconnected);
1691 sd_bus_slot_unref(d->slot_job_removed);
1692
1693 sd_bus_unref(d->bus);
1694
1695 free(d->name);
1696 free(d->result);
1697
1698 free(d);
1699 }
1700
1701 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1702 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1703 int r;
1704
1705 assert(bus);
1706 assert(ret);
1707
1708 d = new0(BusWaitForJobs, 1);
1709 if (!d)
1710 return -ENOMEM;
1711
1712 d->bus = sd_bus_ref(bus);
1713
1714 /* When we are a bus client we match by sender. Direct
1715 * connections OTOH have no initialized sender field, and
1716 * hence we ignore the sender then */
1717 r = sd_bus_add_match(
1718 bus,
1719 &d->slot_job_removed,
1720 bus->bus_client ?
1721 "type='signal',"
1722 "sender='org.freedesktop.systemd1',"
1723 "interface='org.freedesktop.systemd1.Manager',"
1724 "member='JobRemoved',"
1725 "path='/org/freedesktop/systemd1'" :
1726 "type='signal',"
1727 "interface='org.freedesktop.systemd1.Manager',"
1728 "member='JobRemoved',"
1729 "path='/org/freedesktop/systemd1'",
1730 match_job_removed, d);
1731 if (r < 0)
1732 return r;
1733
1734 r = sd_bus_add_match(
1735 bus,
1736 &d->slot_disconnected,
1737 "type='signal',"
1738 "sender='org.freedesktop.DBus.Local',"
1739 "interface='org.freedesktop.DBus.Local',"
1740 "member='Disconnected'",
1741 match_disconnected, d);
1742 if (r < 0)
1743 return r;
1744
1745 *ret = d;
1746 d = NULL;
1747
1748 return 0;
1749 }
1750
1751 static int bus_process_wait(sd_bus *bus) {
1752 int r;
1753
1754 for (;;) {
1755 r = sd_bus_process(bus, NULL);
1756 if (r < 0)
1757 return r;
1758 if (r > 0)
1759 return 0;
1760
1761 r = sd_bus_wait(bus, (uint64_t) -1);
1762 if (r < 0)
1763 return r;
1764 }
1765 }
1766
1767 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1768 _cleanup_free_ char *dbus_path = NULL;
1769
1770 assert(d);
1771 assert(d->name);
1772 assert(result);
1773
1774 dbus_path = unit_dbus_path_from_name(d->name);
1775 if (!dbus_path)
1776 return -ENOMEM;
1777
1778 return sd_bus_get_property_string(d->bus,
1779 "org.freedesktop.systemd1",
1780 dbus_path,
1781 "org.freedesktop.systemd1.Service",
1782 "Result",
1783 NULL,
1784 result);
1785 }
1786
1787 static const struct {
1788 const char *result, *explanation;
1789 } explanations [] = {
1790 { "resources", "a configured resource limit was exceeded" },
1791 { "timeout", "a timeout was exceeded" },
1792 { "exit-code", "the control process exited with error code" },
1793 { "signal", "a fatal signal was delivered to the control process" },
1794 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
1795 { "watchdog", "the service failed to send watchdog ping" },
1796 { "start-limit", "start of the service was attempted too often" }
1797 };
1798
1799 static void log_job_error_with_service_result(const char* service, const char *result) {
1800 _cleanup_free_ char *service_shell_quoted = NULL;
1801
1802 assert(service);
1803
1804 service_shell_quoted = shell_maybe_quote(service);
1805
1806 if (!isempty(result)) {
1807 unsigned i;
1808
1809 for (i = 0; i < ELEMENTSOF(explanations); ++i)
1810 if (streq(result, explanations[i].result))
1811 break;
1812
1813 if (i < ELEMENTSOF(explanations)) {
1814 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1815 service,
1816 explanations[i].explanation,
1817 strna(service_shell_quoted));
1818
1819 goto finish;
1820 }
1821 }
1822
1823 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1824 service,
1825 strna(service_shell_quoted));
1826
1827 finish:
1828 /* For some results maybe additional explanation is required */
1829 if (streq_ptr(result, "start-limit"))
1830 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1831 strna(service_shell_quoted));
1832 }
1833
1834 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1835 int r = 0;
1836
1837 assert(d->result);
1838
1839 if (!quiet) {
1840 if (streq(d->result, "canceled"))
1841 log_error("Job for %s canceled.", strna(d->name));
1842 else if (streq(d->result, "timeout"))
1843 log_error("Job for %s timed out.", strna(d->name));
1844 else if (streq(d->result, "dependency"))
1845 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1846 else if (streq(d->result, "invalid"))
1847 log_error("Job for %s invalid.", strna(d->name));
1848 else if (streq(d->result, "assert"))
1849 log_error("Assertion failed on job for %s.", strna(d->name));
1850 else if (streq(d->result, "unsupported"))
1851 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1852 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1853 if (d->name) {
1854 int q;
1855 _cleanup_free_ char *result = NULL;
1856
1857 q = bus_job_get_service_result(d, &result);
1858 if (q < 0)
1859 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
1860
1861 log_job_error_with_service_result(d->name, result);
1862 } else
1863 log_error("Job failed. See \"journalctl -xe\" for details.");
1864 }
1865 }
1866
1867 if (streq(d->result, "canceled"))
1868 r = -ECANCELED;
1869 else if (streq(d->result, "timeout"))
1870 r = -ETIME;
1871 else if (streq(d->result, "dependency"))
1872 r = -EIO;
1873 else if (streq(d->result, "invalid"))
1874 r = -ENOEXEC;
1875 else if (streq(d->result, "assert"))
1876 r = -EPROTO;
1877 else if (streq(d->result, "unsupported"))
1878 r = -EOPNOTSUPP;
1879 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1880 r = -EIO;
1881
1882 return r;
1883 }
1884
1885 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1886 int r = 0;
1887
1888 assert(d);
1889
1890 while (!set_isempty(d->jobs)) {
1891 int q;
1892
1893 q = bus_process_wait(d->bus);
1894 if (q < 0)
1895 return log_error_errno(q, "Failed to wait for response: %m");
1896
1897 if (d->result) {
1898 q = check_wait_response(d, quiet);
1899 /* Return the first error as it is most likely to be
1900 * meaningful. */
1901 if (q < 0 && r == 0)
1902 r = q;
1903
1904 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1905 }
1906
1907 d->name = mfree(d->name);
1908 d->result = mfree(d->result);
1909 }
1910
1911 return r;
1912 }
1913
1914 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1915 int r;
1916
1917 assert(d);
1918
1919 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1920 if (r < 0)
1921 return r;
1922
1923 return set_put_strdup(d->jobs, path);
1924 }
1925
1926 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
1927 int r;
1928
1929 r = bus_wait_for_jobs_add(d, path);
1930 if (r < 0)
1931 return log_oom();
1932
1933 return bus_wait_for_jobs(d, quiet);
1934 }
1935
1936 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
1937 const char *type, *path, *source;
1938 int r;
1939
1940 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1941 if (r < 0)
1942 return bus_log_parse_error(r);
1943
1944 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1945 if (!quiet) {
1946 if (streq(type, "symlink"))
1947 log_info("Created symlink from %s to %s.", path, source);
1948 else
1949 log_info("Removed symlink %s.", path);
1950 }
1951
1952 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
1953 if (r < 0)
1954 return r;
1955 }
1956 if (r < 0)
1957 return bus_log_parse_error(r);
1958
1959 r = sd_bus_message_exit_container(m);
1960 if (r < 0)
1961 return bus_log_parse_error(r);
1962
1963 return 0;
1964 }
1965
1966 /**
1967 * bus_path_encode_unique() - encode unique object path
1968 * @b: bus connection or NULL
1969 * @prefix: object path prefix
1970 * @sender_id: unique-name of client, or NULL
1971 * @external_id: external ID to be chosen by client, or NULL
1972 * @ret_path: storage for encoded object path pointer
1973 *
1974 * Whenever we provide a bus API that allows clients to create and manage
1975 * server-side objects, we need to provide a unique name for these objects. If
1976 * we let the server choose the name, we suffer from a race condition: If a
1977 * client creates an object asynchronously, it cannot destroy that object until
1978 * it received the method reply. It cannot know the name of the new object,
1979 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1980 *
1981 * Therefore, many APIs allow the client to choose the unique name for newly
1982 * created objects. There're two problems to solve, though:
1983 * 1) Object names are usually defined via dbus object paths, which are
1984 * usually globally namespaced. Therefore, multiple clients must be able
1985 * to choose unique object names without interference.
1986 * 2) If multiple libraries share the same bus connection, they must be
1987 * able to choose unique object names without interference.
1988 * The first problem is solved easily by prefixing a name with the
1989 * unique-bus-name of a connection. The server side must enforce this and
1990 * reject any other name. The second problem is solved by providing unique
1991 * suffixes from within sd-bus.
1992 *
1993 * This helper allows clients to create unique object-paths. It uses the
1994 * template '/prefix/sender_id/external_id' and returns the new path in
1995 * @ret_path (must be freed by the caller).
1996 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1997 * NULL, this function allocates a unique suffix via @b (by requesting a new
1998 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1999 * NULL.
2000 *
2001 * Returns: 0 on success, negative error code on failure.
2002 */
2003 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2004 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2005 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2006 int r;
2007
2008 assert_return(b || (sender_id && external_id), -EINVAL);
2009 assert_return(object_path_is_valid(prefix), -EINVAL);
2010 assert_return(ret_path, -EINVAL);
2011
2012 if (!sender_id) {
2013 r = sd_bus_get_unique_name(b, &sender_id);
2014 if (r < 0)
2015 return r;
2016 }
2017
2018 if (!external_id) {
2019 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2020 external_id = external_buf;
2021 }
2022
2023 sender_label = bus_label_escape(sender_id);
2024 if (!sender_label)
2025 return -ENOMEM;
2026
2027 external_label = bus_label_escape(external_id);
2028 if (!external_label)
2029 return -ENOMEM;
2030
2031 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2032 if (!p)
2033 return -ENOMEM;
2034
2035 *ret_path = p;
2036 return 0;
2037 }
2038
2039 /**
2040 * bus_path_decode_unique() - decode unique object path
2041 * @path: object path to decode
2042 * @prefix: object path prefix
2043 * @ret_sender: output parameter for sender-id label
2044 * @ret_external: output parameter for external-id label
2045 *
2046 * This does the reverse of bus_path_encode_unique() (see its description for
2047 * details). Both trailing labels, sender-id and external-id, are unescaped and
2048 * returned in the given output parameters (the caller must free them).
2049 *
2050 * Note that this function returns 0 if the path does not match the template
2051 * (see bus_path_encode_unique()), 1 if it matched.
2052 *
2053 * Returns: Negative error code on failure, 0 if the given object path does not
2054 * match the template (return parameters are set to NULL), 1 if it was
2055 * parsed successfully (return parameters contain allocated labels).
2056 */
2057 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2058 const char *p, *q;
2059 char *sender, *external;
2060
2061 assert(object_path_is_valid(path));
2062 assert(object_path_is_valid(prefix));
2063 assert(ret_sender);
2064 assert(ret_external);
2065
2066 p = object_path_startswith(path, prefix);
2067 if (!p) {
2068 *ret_sender = NULL;
2069 *ret_external = NULL;
2070 return 0;
2071 }
2072
2073 q = strchr(p, '/');
2074 if (!q) {
2075 *ret_sender = NULL;
2076 *ret_external = NULL;
2077 return 0;
2078 }
2079
2080 sender = bus_label_unescape_n(p, q - p);
2081 external = bus_label_unescape(q + 1);
2082 if (!sender || !external) {
2083 free(sender);
2084 free(external);
2085 return -ENOMEM;
2086 }
2087
2088 *ret_sender = sender;
2089 *ret_external = external;
2090 return 1;
2091 }
2092
2093 bool is_kdbus_wanted(void) {
2094 _cleanup_free_ char *value = NULL;
2095 #ifdef ENABLE_KDBUS
2096 const bool configured = true;
2097 #else
2098 const bool configured = false;
2099 #endif
2100
2101 int r;
2102
2103 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2104 return true;
2105
2106 r = get_proc_cmdline_key("kdbus=", &value);
2107 if (r <= 0)
2108 return configured;
2109
2110 return parse_boolean(value) == 1;
2111 }
2112
2113 bool is_kdbus_available(void) {
2114 _cleanup_close_ int fd = -1;
2115 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2116
2117 if (!is_kdbus_wanted())
2118 return false;
2119
2120 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2121 if (fd < 0)
2122 return false;
2123
2124 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2125 }