]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-util.c
a61f8e70da0b18dfdc4eabce7ad6644766bd0424
[thirdparty/systemd.git] / src / shared / bus-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <inttypes.h>
6 #include <stdlib.h>
7 #include <sys/ioctl.h>
8 #include <sys/resource.h>
9 #include <sys/socket.h>
10 #include <unistd.h>
11
12 #include "sd-bus.h"
13 #include "sd-daemon.h"
14 #include "sd-event.h"
15 #include "sd-id128.h"
16
17 #include "alloc-util.h"
18 #include "bus-internal.h"
19 #include "bus-introspect.h"
20 #include "bus-label.h"
21 #include "bus-message.h"
22 #include "bus-util.h"
23 #include "cap-list.h"
24 #include "cgroup-util.h"
25 #include "escape.h"
26 #include "mountpoint-util.h"
27 #include "nsflags.h"
28 #include "parse-util.h"
29 #include "path-util.h"
30 #include "rlimit-util.h"
31 #include "socket-util.h"
32 #include "stdio-util.h"
33 #include "strv.h"
34 #include "user-util.h"
35
36 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
37 sd_event *e = userdata;
38
39 assert(m);
40 assert(e);
41
42 sd_bus_close(sd_bus_message_get_bus(m));
43 sd_event_exit(e, 0);
44
45 return 1;
46 }
47
48 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
49 const char *match;
50 const char *unique;
51 int r;
52
53 assert(e);
54 assert(bus);
55 assert(name);
56
57 /* We unregister the name here and then wait for the
58 * NameOwnerChanged signal for this event to arrive before we
59 * quit. We do this in order to make sure that any queued
60 * requests are still processed before we really exit. */
61
62 r = sd_bus_get_unique_name(bus, &unique);
63 if (r < 0)
64 return r;
65
66 match = strjoina(
67 "sender='org.freedesktop.DBus',"
68 "type='signal',"
69 "interface='org.freedesktop.DBus',"
70 "member='NameOwnerChanged',"
71 "path='/org/freedesktop/DBus',"
72 "arg0='", name, "',",
73 "arg1='", unique, "',",
74 "arg2=''");
75
76 r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
77 if (r < 0)
78 return r;
79
80 r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
81 if (r < 0)
82 return r;
83
84 return 0;
85 }
86
87 int bus_event_loop_with_idle(
88 sd_event *e,
89 sd_bus *bus,
90 const char *name,
91 usec_t timeout,
92 check_idle_t check_idle,
93 void *userdata) {
94 bool exiting = false;
95 int r, code;
96
97 assert(e);
98 assert(bus);
99 assert(name);
100
101 for (;;) {
102 bool idle;
103
104 r = sd_event_get_state(e);
105 if (r < 0)
106 return r;
107 if (r == SD_EVENT_FINISHED)
108 break;
109
110 if (check_idle)
111 idle = check_idle(userdata);
112 else
113 idle = true;
114
115 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
116 if (r < 0)
117 return r;
118
119 if (r == 0 && !exiting && idle) {
120 /* Inform the service manager that we are going down, so that it will queue all
121 * further start requests, instead of assuming we are already running. */
122 sd_notify(false, "STOPPING=1");
123
124 r = bus_async_unregister_and_exit(e, bus, name);
125 if (r < 0)
126 return r;
127
128 exiting = true;
129 continue;
130 }
131 }
132
133 r = sd_event_get_exit_code(e, &code);
134 if (r < 0)
135 return r;
136
137 return code;
138 }
139
140 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
141 _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
142 int r, has_owner = 0;
143
144 assert(c);
145 assert(name);
146
147 r = sd_bus_call_method(c,
148 "org.freedesktop.DBus",
149 "/org/freedesktop/dbus",
150 "org.freedesktop.DBus",
151 "NameHasOwner",
152 error,
153 &rep,
154 "s",
155 name);
156 if (r < 0)
157 return r;
158
159 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
160 if (r < 0)
161 return sd_bus_error_set_errno(error, r);
162
163 return has_owner;
164 }
165
166 int bus_check_peercred(sd_bus *c) {
167 struct ucred ucred;
168 int fd, r;
169
170 assert(c);
171
172 fd = sd_bus_get_fd(c);
173 if (fd < 0)
174 return fd;
175
176 r = getpeercred(fd, &ucred);
177 if (r < 0)
178 return r;
179
180 if (ucred.uid != 0 && ucred.uid != geteuid())
181 return -EPERM;
182
183 return 1;
184 }
185
186 int bus_connect_system_systemd(sd_bus **_bus) {
187 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
188 int r;
189
190 assert(_bus);
191
192 if (geteuid() != 0)
193 return sd_bus_default_system(_bus);
194
195 /* If we are root then let's talk directly to the system
196 * instance, instead of going via the bus */
197
198 r = sd_bus_new(&bus);
199 if (r < 0)
200 return r;
201
202 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
203 if (r < 0)
204 return r;
205
206 r = sd_bus_start(bus);
207 if (r < 0)
208 return sd_bus_default_system(_bus);
209
210 r = bus_check_peercred(bus);
211 if (r < 0)
212 return r;
213
214 *_bus = TAKE_PTR(bus);
215
216 return 0;
217 }
218
219 int bus_connect_user_systemd(sd_bus **_bus) {
220 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
221 _cleanup_free_ char *ee = NULL;
222 const char *e;
223 int r;
224
225 assert(_bus);
226
227 e = secure_getenv("XDG_RUNTIME_DIR");
228 if (!e)
229 return sd_bus_default_user(_bus);
230
231 ee = bus_address_escape(e);
232 if (!ee)
233 return -ENOMEM;
234
235 r = sd_bus_new(&bus);
236 if (r < 0)
237 return r;
238
239 bus->address = strjoin("unix:path=", ee, "/systemd/private");
240 if (!bus->address)
241 return -ENOMEM;
242
243 r = sd_bus_start(bus);
244 if (r < 0)
245 return sd_bus_default_user(_bus);
246
247 r = bus_check_peercred(bus);
248 if (r < 0)
249 return r;
250
251 *_bus = TAKE_PTR(bus);
252
253 return 0;
254 }
255
256 int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value) {
257 assert(name);
258
259 if (expected_value && !streq_ptr(expected_value, value))
260 return 0;
261
262 if (only_value)
263 puts(value);
264 else
265 printf("%s=%s\n", name, value);
266
267 return 0;
268 }
269
270 int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
271 va_list ap;
272 int r;
273
274 assert(name);
275 assert(fmt);
276
277 if (expected_value) {
278 _cleanup_free_ char *s = NULL;
279
280 va_start(ap, fmt);
281 r = vasprintf(&s, fmt, ap);
282 va_end(ap);
283 if (r < 0)
284 return -ENOMEM;
285
286 if (streq_ptr(expected_value, s)) {
287 if (only_value)
288 puts(s);
289 else
290 printf("%s=%s\n", name, s);
291 }
292
293 return 0;
294 }
295
296 if (!only_value)
297 printf("%s=", name);
298 va_start(ap, fmt);
299 vprintf(fmt, ap);
300 va_end(ap);
301 puts("");
302
303 return 0;
304 }
305
306 static int bus_print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
307 char type;
308 const char *contents;
309 int r;
310
311 assert(name);
312 assert(m);
313
314 r = sd_bus_message_peek_type(m, &type, &contents);
315 if (r < 0)
316 return r;
317
318 switch (type) {
319
320 case SD_BUS_TYPE_STRING: {
321 const char *s;
322
323 r = sd_bus_message_read_basic(m, type, &s);
324 if (r < 0)
325 return r;
326
327 if (all || !isempty(s)) {
328 bool good;
329
330 /* This property has a single value, so we need to take
331 * care not to print a new line, everything else is OK. */
332 good = !strchr(s, '\n');
333 bus_print_property_value(name, expected_value, value, good ? s : "[unprintable]");
334 }
335
336 return 1;
337 }
338
339 case SD_BUS_TYPE_BOOLEAN: {
340 int b;
341
342 r = sd_bus_message_read_basic(m, type, &b);
343 if (r < 0)
344 return r;
345
346 if (expected_value && parse_boolean(expected_value) != b)
347 return 1;
348
349 bus_print_property_value(name, NULL, value, yes_no(b));
350 return 1;
351 }
352
353 case SD_BUS_TYPE_UINT64: {
354 uint64_t u;
355
356 r = sd_bus_message_read_basic(m, type, &u);
357 if (r < 0)
358 return r;
359
360 /* Yes, heuristics! But we can change this check
361 * should it turn out to not be sufficient */
362
363 if (endswith(name, "Timestamp") ||
364 STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec")) {
365 char timestamp[FORMAT_TIMESTAMP_MAX];
366 const char *t;
367
368 t = format_timestamp(timestamp, sizeof(timestamp), u);
369 if (t || all)
370 bus_print_property_value(name, expected_value, value, strempty(t));
371
372 } else if (strstr(name, "USec")) {
373 char timespan[FORMAT_TIMESPAN_MAX];
374
375 (void) format_timespan(timespan, sizeof(timespan), u, 0);
376 bus_print_property_value(name, expected_value, value, timespan);
377
378 } else if (streq(name, "CoredumpFilter")) {
379 char buf[STRLEN("0xFFFFFFFF")];
380
381 xsprintf(buf, "0x%"PRIx64, u);
382 bus_print_property_value(name, expected_value, value, buf);
383
384 } else if (streq(name, "RestrictNamespaces")) {
385 _cleanup_free_ char *s = NULL;
386 const char *result;
387
388 if ((u & NAMESPACE_FLAGS_ALL) == 0)
389 result = "yes";
390 else if (FLAGS_SET(u, NAMESPACE_FLAGS_ALL))
391 result = "no";
392 else {
393 r = namespace_flags_to_string(u, &s);
394 if (r < 0)
395 return r;
396
397 result = strempty(s);
398 }
399
400 bus_print_property_value(name, expected_value, value, result);
401
402 } else if (streq(name, "MountFlags")) {
403 const char *result;
404
405 result = mount_propagation_flags_to_string(u);
406 if (!result)
407 return -EINVAL;
408
409 bus_print_property_value(name, expected_value, value, result);
410
411 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
412 _cleanup_free_ char *s = NULL;
413
414 r = capability_set_to_string_alloc(u, &s);
415 if (r < 0)
416 return r;
417
418 bus_print_property_value(name, expected_value, value, s);
419
420 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
421 (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
422 (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
423 (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
424 (endswith(name, "NSec") && u == (uint64_t) -1))
425
426 bus_print_property_value(name, expected_value, value, "[not set]");
427
428 else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
429 (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
430 (startswith(name, "Limit") && u == (uint64_t) -1) ||
431 (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
432
433 bus_print_property_value(name, expected_value, value, "infinity");
434 else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == (uint64_t) -1)
435 bus_print_property_value(name, expected_value, value, "[no data]");
436 else
437 bus_print_property_valuef(name, expected_value, value, "%"PRIu64, u);
438
439 return 1;
440 }
441
442 case SD_BUS_TYPE_INT64: {
443 int64_t i;
444
445 r = sd_bus_message_read_basic(m, type, &i);
446 if (r < 0)
447 return r;
448
449 bus_print_property_valuef(name, expected_value, value, "%"PRIi64, i);
450 return 1;
451 }
452
453 case SD_BUS_TYPE_UINT32: {
454 uint32_t u;
455
456 r = sd_bus_message_read_basic(m, type, &u);
457 if (r < 0)
458 return r;
459
460 if (strstr(name, "UMask") || strstr(name, "Mode"))
461 bus_print_property_valuef(name, expected_value, value, "%04o", u);
462
463 else if (streq(name, "UID")) {
464 if (u == UID_INVALID)
465 bus_print_property_value(name, expected_value, value, "[not set]");
466 else
467 bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
468 } else if (streq(name, "GID")) {
469 if (u == GID_INVALID)
470 bus_print_property_value(name, expected_value, value, "[not set]");
471 else
472 bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
473 } else
474 bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
475
476 return 1;
477 }
478
479 case SD_BUS_TYPE_INT32: {
480 int32_t i;
481
482 r = sd_bus_message_read_basic(m, type, &i);
483 if (r < 0)
484 return r;
485
486 bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
487 return 1;
488 }
489
490 case SD_BUS_TYPE_DOUBLE: {
491 double d;
492
493 r = sd_bus_message_read_basic(m, type, &d);
494 if (r < 0)
495 return r;
496
497 bus_print_property_valuef(name, expected_value, value, "%g", d);
498 return 1;
499 }
500
501 case SD_BUS_TYPE_ARRAY:
502 if (streq(contents, "s")) {
503 bool first = true;
504 const char *str;
505
506 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
507 if (r < 0)
508 return r;
509
510 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
511 _cleanup_free_ char *e = NULL;
512
513 e = shell_maybe_quote(str, ESCAPE_BACKSLASH_ONELINE);
514 if (!e)
515 return -ENOMEM;
516
517 if (first) {
518 if (!value)
519 printf("%s=", name);
520 first = false;
521 } else
522 fputs(" ", stdout);
523
524 fputs(e, stdout);
525 }
526 if (r < 0)
527 return r;
528
529 if (first && all && !value)
530 printf("%s=", name);
531 if (!first || all)
532 puts("");
533
534 r = sd_bus_message_exit_container(m);
535 if (r < 0)
536 return r;
537
538 return 1;
539
540 } else if (streq(contents, "y")) {
541 const uint8_t *u;
542 size_t n;
543
544 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
545 if (r < 0)
546 return r;
547
548 if (all || n > 0) {
549 unsigned i;
550
551 if (!value)
552 printf("%s=", name);
553
554 for (i = 0; i < n; i++)
555 printf("%02x", u[i]);
556
557 puts("");
558 }
559
560 return 1;
561
562 } else if (streq(contents, "u")) {
563 uint32_t *u;
564 size_t n;
565
566 r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
567 if (r < 0)
568 return r;
569
570 if (all || n > 0) {
571 unsigned i;
572
573 if (!value)
574 printf("%s=", name);
575
576 for (i = 0; i < n; i++)
577 printf("%08x", u[i]);
578
579 puts("");
580 }
581
582 return 1;
583 }
584
585 break;
586 }
587
588 return 0;
589 }
590
591 int bus_message_print_all_properties(
592 sd_bus_message *m,
593 bus_message_print_t func,
594 char **filter,
595 bool value,
596 bool all,
597 Set **found_properties) {
598
599 int r;
600
601 assert(m);
602
603 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
604 if (r < 0)
605 return r;
606
607 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
608 _cleanup_free_ char *name_with_equal = NULL;
609 const char *name, *contents, *expected_value = NULL;
610
611 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
612 if (r < 0)
613 return r;
614
615 if (found_properties) {
616 r = set_ensure_allocated(found_properties, &string_hash_ops);
617 if (r < 0)
618 return log_oom();
619
620 r = set_put(*found_properties, name);
621 if (r < 0 && r != -EEXIST)
622 return log_oom();
623 }
624
625 name_with_equal = strjoin(name, "=");
626 if (!name_with_equal)
627 return log_oom();
628
629 if (!filter || strv_find(filter, name) ||
630 (expected_value = strv_find_startswith(filter, name_with_equal))) {
631 r = sd_bus_message_peek_type(m, NULL, &contents);
632 if (r < 0)
633 return r;
634
635 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
636 if (r < 0)
637 return r;
638
639 if (func)
640 r = func(name, expected_value, m, value, all);
641 if (!func || r == 0)
642 r = bus_print_property(name, expected_value, m, value, all);
643 if (r < 0)
644 return r;
645 if (r == 0) {
646 if (all && !expected_value)
647 printf("%s=[unprintable]\n", name);
648 /* skip what we didn't read */
649 r = sd_bus_message_skip(m, contents);
650 if (r < 0)
651 return r;
652 }
653
654 r = sd_bus_message_exit_container(m);
655 if (r < 0)
656 return r;
657 } else {
658 r = sd_bus_message_skip(m, "v");
659 if (r < 0)
660 return r;
661 }
662
663 r = sd_bus_message_exit_container(m);
664 if (r < 0)
665 return r;
666 }
667 if (r < 0)
668 return r;
669
670 r = sd_bus_message_exit_container(m);
671 if (r < 0)
672 return r;
673
674 return 0;
675 }
676
677 int bus_print_all_properties(
678 sd_bus *bus,
679 const char *dest,
680 const char *path,
681 bus_message_print_t func,
682 char **filter,
683 bool value,
684 bool all,
685 Set **found_properties) {
686
687 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
688 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
689 int r;
690
691 assert(bus);
692 assert(path);
693
694 r = sd_bus_call_method(bus,
695 dest,
696 path,
697 "org.freedesktop.DBus.Properties",
698 "GetAll",
699 &error,
700 &reply,
701 "s", "");
702 if (r < 0)
703 return r;
704
705 return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
706 }
707
708 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
709 sd_id128_t *p = userdata;
710 const void *v;
711 size_t n;
712 int r;
713
714 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
715 if (r < 0)
716 return r;
717
718 if (n == 0)
719 *p = SD_ID128_NULL;
720 else if (n == 16)
721 memcpy((*p).bytes, v, n);
722 else
723 return -EINVAL;
724
725 return 0;
726 }
727
728 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
729 char type;
730 int r;
731
732 r = sd_bus_message_peek_type(m, &type, NULL);
733 if (r < 0)
734 return r;
735
736 switch (type) {
737
738 case SD_BUS_TYPE_STRING:
739 case SD_BUS_TYPE_OBJECT_PATH: {
740 const char **p = userdata;
741 const char *s;
742
743 r = sd_bus_message_read_basic(m, type, &s);
744 if (r < 0)
745 return r;
746
747 if (isempty(s))
748 s = NULL;
749
750 if (flags & BUS_MAP_STRDUP)
751 return free_and_strdup((char **) userdata, s);
752
753 *p = s;
754 return 0;
755 }
756
757 case SD_BUS_TYPE_ARRAY: {
758 _cleanup_strv_free_ char **l = NULL;
759 char ***p = userdata;
760
761 r = bus_message_read_strv_extend(m, &l);
762 if (r < 0)
763 return r;
764
765 return strv_extend_strv(p, l, false);
766 }
767
768 case SD_BUS_TYPE_BOOLEAN: {
769 int b;
770
771 r = sd_bus_message_read_basic(m, type, &b);
772 if (r < 0)
773 return r;
774
775 if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
776 *(bool*) userdata = b;
777 else
778 *(int*) userdata = b;
779
780 return 0;
781 }
782
783 case SD_BUS_TYPE_INT32:
784 case SD_BUS_TYPE_UINT32: {
785 uint32_t u, *p = userdata;
786
787 r = sd_bus_message_read_basic(m, type, &u);
788 if (r < 0)
789 return r;
790
791 *p = u;
792 return 0;
793 }
794
795 case SD_BUS_TYPE_INT64:
796 case SD_BUS_TYPE_UINT64: {
797 uint64_t t, *p = userdata;
798
799 r = sd_bus_message_read_basic(m, type, &t);
800 if (r < 0)
801 return r;
802
803 *p = t;
804 return 0;
805 }
806
807 case SD_BUS_TYPE_DOUBLE: {
808 double d, *p = userdata;
809
810 r = sd_bus_message_read_basic(m, type, &d);
811 if (r < 0)
812 return r;
813
814 *p = d;
815 return 0;
816 }}
817
818 return -EOPNOTSUPP;
819 }
820
821 int bus_message_map_all_properties(
822 sd_bus_message *m,
823 const struct bus_properties_map *map,
824 unsigned flags,
825 sd_bus_error *error,
826 void *userdata) {
827
828 int r;
829
830 assert(m);
831 assert(map);
832
833 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
834 if (r < 0)
835 return r;
836
837 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
838 const struct bus_properties_map *prop;
839 const char *member;
840 const char *contents;
841 void *v;
842 unsigned i;
843
844 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
845 if (r < 0)
846 return r;
847
848 for (i = 0, prop = NULL; map[i].member; i++)
849 if (streq(map[i].member, member)) {
850 prop = &map[i];
851 break;
852 }
853
854 if (prop) {
855 r = sd_bus_message_peek_type(m, NULL, &contents);
856 if (r < 0)
857 return r;
858
859 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
860 if (r < 0)
861 return r;
862
863 v = (uint8_t *)userdata + prop->offset;
864 if (map[i].set)
865 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
866 else
867 r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
868 if (r < 0)
869 return r;
870
871 r = sd_bus_message_exit_container(m);
872 if (r < 0)
873 return r;
874 } else {
875 r = sd_bus_message_skip(m, "v");
876 if (r < 0)
877 return r;
878 }
879
880 r = sd_bus_message_exit_container(m);
881 if (r < 0)
882 return r;
883 }
884 if (r < 0)
885 return r;
886
887 return sd_bus_message_exit_container(m);
888 }
889
890 int bus_map_all_properties(
891 sd_bus *bus,
892 const char *destination,
893 const char *path,
894 const struct bus_properties_map *map,
895 unsigned flags,
896 sd_bus_error *error,
897 sd_bus_message **reply,
898 void *userdata) {
899
900 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
901 int r;
902
903 assert(bus);
904 assert(destination);
905 assert(path);
906 assert(map);
907 assert(reply || (flags & BUS_MAP_STRDUP));
908
909 r = sd_bus_call_method(
910 bus,
911 destination,
912 path,
913 "org.freedesktop.DBus.Properties",
914 "GetAll",
915 error,
916 &m,
917 "s", "");
918 if (r < 0)
919 return r;
920
921 r = bus_message_map_all_properties(m, map, flags, error, userdata);
922 if (r < 0)
923 return r;
924
925 if (reply)
926 *reply = sd_bus_message_ref(m);
927
928 return r;
929 }
930
931 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
932 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
933 int r;
934
935 assert(transport >= 0);
936 assert(transport < _BUS_TRANSPORT_MAX);
937 assert(ret);
938
939 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
940 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
941
942 switch (transport) {
943
944 case BUS_TRANSPORT_LOCAL:
945 if (user)
946 r = sd_bus_default_user(&bus);
947 else {
948 if (sd_booted() <= 0) {
949 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
950 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
951
952 return -EHOSTDOWN;
953 }
954 r = sd_bus_default_system(&bus);
955 }
956 break;
957
958 case BUS_TRANSPORT_REMOTE:
959 r = sd_bus_open_system_remote(&bus, host);
960 break;
961
962 case BUS_TRANSPORT_MACHINE:
963 r = sd_bus_open_system_machine(&bus, host);
964 break;
965
966 default:
967 assert_not_reached("Hmm, unknown transport type.");
968 }
969 if (r < 0)
970 return r;
971
972 r = sd_bus_set_exit_on_disconnect(bus, true);
973 if (r < 0)
974 return r;
975
976 *ret = TAKE_PTR(bus);
977
978 return 0;
979 }
980
981 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
982 int r;
983
984 assert(transport >= 0);
985 assert(transport < _BUS_TRANSPORT_MAX);
986 assert(bus);
987
988 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
989 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
990
991 switch (transport) {
992
993 case BUS_TRANSPORT_LOCAL:
994 if (user)
995 r = bus_connect_user_systemd(bus);
996 else {
997 if (sd_booted() <= 0)
998 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
999 return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
1000 "System has not been booted with systemd as init system (PID 1). Can't operate.");
1001 r = bus_connect_system_systemd(bus);
1002 }
1003 break;
1004
1005 case BUS_TRANSPORT_REMOTE:
1006 r = sd_bus_open_system_remote(bus, host);
1007 break;
1008
1009 case BUS_TRANSPORT_MACHINE:
1010 r = sd_bus_open_system_machine(bus, host);
1011 break;
1012
1013 default:
1014 assert_not_reached("Hmm, unknown transport type.");
1015 }
1016
1017 return r;
1018 }
1019
1020 int bus_property_get_bool(
1021 sd_bus *bus,
1022 const char *path,
1023 const char *interface,
1024 const char *property,
1025 sd_bus_message *reply,
1026 void *userdata,
1027 sd_bus_error *error) {
1028
1029 int b = *(bool*) userdata;
1030
1031 return sd_bus_message_append_basic(reply, 'b', &b);
1032 }
1033
1034 int bus_property_set_bool(
1035 sd_bus *bus,
1036 const char *path,
1037 const char *interface,
1038 const char *property,
1039 sd_bus_message *value,
1040 void *userdata,
1041 sd_bus_error *error) {
1042
1043 int b, r;
1044
1045 r = sd_bus_message_read(value, "b", &b);
1046 if (r < 0)
1047 return r;
1048
1049 *(bool*) userdata = b;
1050 return 0;
1051 }
1052
1053 int bus_property_get_id128(
1054 sd_bus *bus,
1055 const char *path,
1056 const char *interface,
1057 const char *property,
1058 sd_bus_message *reply,
1059 void *userdata,
1060 sd_bus_error *error) {
1061
1062 sd_id128_t *id = userdata;
1063
1064 if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
1065 return sd_bus_message_append(reply, "ay", 0);
1066 else
1067 return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
1068 }
1069
1070 #if __SIZEOF_SIZE_T__ != 8
1071 int bus_property_get_size(
1072 sd_bus *bus,
1073 const char *path,
1074 const char *interface,
1075 const char *property,
1076 sd_bus_message *reply,
1077 void *userdata,
1078 sd_bus_error *error) {
1079
1080 uint64_t sz = *(size_t*) userdata;
1081
1082 return sd_bus_message_append_basic(reply, 't', &sz);
1083 }
1084 #endif
1085
1086 #if __SIZEOF_LONG__ != 8
1087 int bus_property_get_long(
1088 sd_bus *bus,
1089 const char *path,
1090 const char *interface,
1091 const char *property,
1092 sd_bus_message *reply,
1093 void *userdata,
1094 sd_bus_error *error) {
1095
1096 int64_t l = *(long*) userdata;
1097
1098 return sd_bus_message_append_basic(reply, 'x', &l);
1099 }
1100
1101 int bus_property_get_ulong(
1102 sd_bus *bus,
1103 const char *path,
1104 const char *interface,
1105 const char *property,
1106 sd_bus_message *reply,
1107 void *userdata,
1108 sd_bus_error *error) {
1109
1110 uint64_t ul = *(unsigned long*) userdata;
1111
1112 return sd_bus_message_append_basic(reply, 't', &ul);
1113 }
1114 #endif
1115
1116 /**
1117 * bus_path_encode_unique() - encode unique object path
1118 * @b: bus connection or NULL
1119 * @prefix: object path prefix
1120 * @sender_id: unique-name of client, or NULL
1121 * @external_id: external ID to be chosen by client, or NULL
1122 * @ret_path: storage for encoded object path pointer
1123 *
1124 * Whenever we provide a bus API that allows clients to create and manage
1125 * server-side objects, we need to provide a unique name for these objects. If
1126 * we let the server choose the name, we suffer from a race condition: If a
1127 * client creates an object asynchronously, it cannot destroy that object until
1128 * it received the method reply. It cannot know the name of the new object,
1129 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1130 *
1131 * Therefore, many APIs allow the client to choose the unique name for newly
1132 * created objects. There're two problems to solve, though:
1133 * 1) Object names are usually defined via dbus object paths, which are
1134 * usually globally namespaced. Therefore, multiple clients must be able
1135 * to choose unique object names without interference.
1136 * 2) If multiple libraries share the same bus connection, they must be
1137 * able to choose unique object names without interference.
1138 * The first problem is solved easily by prefixing a name with the
1139 * unique-bus-name of a connection. The server side must enforce this and
1140 * reject any other name. The second problem is solved by providing unique
1141 * suffixes from within sd-bus.
1142 *
1143 * This helper allows clients to create unique object-paths. It uses the
1144 * template '/prefix/sender_id/external_id' and returns the new path in
1145 * @ret_path (must be freed by the caller).
1146 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1147 * NULL, this function allocates a unique suffix via @b (by requesting a new
1148 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1149 * NULL.
1150 *
1151 * Returns: 0 on success, negative error code on failure.
1152 */
1153 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1154 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1155 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1156 int r;
1157
1158 assert_return(b || (sender_id && external_id), -EINVAL);
1159 assert_return(sd_bus_object_path_is_valid(prefix), -EINVAL);
1160 assert_return(ret_path, -EINVAL);
1161
1162 if (!sender_id) {
1163 r = sd_bus_get_unique_name(b, &sender_id);
1164 if (r < 0)
1165 return r;
1166 }
1167
1168 if (!external_id) {
1169 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1170 external_id = external_buf;
1171 }
1172
1173 sender_label = bus_label_escape(sender_id);
1174 if (!sender_label)
1175 return -ENOMEM;
1176
1177 external_label = bus_label_escape(external_id);
1178 if (!external_label)
1179 return -ENOMEM;
1180
1181 p = path_join(prefix, sender_label, external_label);
1182 if (!p)
1183 return -ENOMEM;
1184
1185 *ret_path = p;
1186 return 0;
1187 }
1188
1189 /**
1190 * bus_path_decode_unique() - decode unique object path
1191 * @path: object path to decode
1192 * @prefix: object path prefix
1193 * @ret_sender: output parameter for sender-id label
1194 * @ret_external: output parameter for external-id label
1195 *
1196 * This does the reverse of bus_path_encode_unique() (see its description for
1197 * details). Both trailing labels, sender-id and external-id, are unescaped and
1198 * returned in the given output parameters (the caller must free them).
1199 *
1200 * Note that this function returns 0 if the path does not match the template
1201 * (see bus_path_encode_unique()), 1 if it matched.
1202 *
1203 * Returns: Negative error code on failure, 0 if the given object path does not
1204 * match the template (return parameters are set to NULL), 1 if it was
1205 * parsed successfully (return parameters contain allocated labels).
1206 */
1207 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
1208 const char *p, *q;
1209 char *sender, *external;
1210
1211 assert(sd_bus_object_path_is_valid(path));
1212 assert(sd_bus_object_path_is_valid(prefix));
1213 assert(ret_sender);
1214 assert(ret_external);
1215
1216 p = object_path_startswith(path, prefix);
1217 if (!p) {
1218 *ret_sender = NULL;
1219 *ret_external = NULL;
1220 return 0;
1221 }
1222
1223 q = strchr(p, '/');
1224 if (!q) {
1225 *ret_sender = NULL;
1226 *ret_external = NULL;
1227 return 0;
1228 }
1229
1230 sender = bus_label_unescape_n(p, q - p);
1231 external = bus_label_unescape(q + 1);
1232 if (!sender || !external) {
1233 free(sender);
1234 free(external);
1235 return -ENOMEM;
1236 }
1237
1238 *ret_sender = sender;
1239 *ret_external = external;
1240 return 1;
1241 }
1242
1243 int bus_property_get_rlimit(
1244 sd_bus *bus,
1245 const char *path,
1246 const char *interface,
1247 const char *property,
1248 sd_bus_message *reply,
1249 void *userdata,
1250 sd_bus_error *error) {
1251
1252 const char *is_soft;
1253 struct rlimit *rl;
1254 uint64_t u;
1255 rlim_t x;
1256
1257 assert(bus);
1258 assert(reply);
1259 assert(userdata);
1260
1261 is_soft = endswith(property, "Soft");
1262
1263 rl = *(struct rlimit**) userdata;
1264 if (rl)
1265 x = is_soft ? rl->rlim_cur : rl->rlim_max;
1266 else {
1267 struct rlimit buf = {};
1268 const char *s, *p;
1269 int z;
1270
1271 /* Chop off "Soft" suffix */
1272 s = is_soft ? strndupa(property, is_soft - property) : property;
1273
1274 /* Skip over any prefix, such as "Default" */
1275 assert_se(p = strstr(s, "Limit"));
1276
1277 z = rlimit_from_string(p + 5);
1278 assert(z >= 0);
1279
1280 (void) getrlimit(z, &buf);
1281 x = is_soft ? buf.rlim_cur : buf.rlim_max;
1282 }
1283
1284 /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all
1285 * archs */
1286 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
1287
1288 return sd_bus_message_append(reply, "t", u);
1289 }
1290
1291 int bus_track_add_name_many(sd_bus_track *t, char **l) {
1292 int r = 0;
1293 char **i;
1294
1295 assert(t);
1296
1297 /* Continues adding after failure, and returns the first failure. */
1298
1299 STRV_FOREACH(i, l) {
1300 int k;
1301
1302 k = sd_bus_track_add_name(t, *i);
1303 if (k < 0 && r >= 0)
1304 r = k;
1305 }
1306
1307 return r;
1308 }
1309
1310 int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
1311 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
1312 const char *e;
1313 int r;
1314
1315 assert(ret);
1316
1317 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal
1318 * turned on. */
1319
1320 r = sd_bus_new(&bus);
1321 if (r < 0)
1322 return r;
1323
1324 if (description) {
1325 r = sd_bus_set_description(bus, description);
1326 if (r < 0)
1327 return r;
1328 }
1329
1330 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1331 if (!e)
1332 e = DEFAULT_SYSTEM_BUS_ADDRESS;
1333
1334 r = sd_bus_set_address(bus, e);
1335 if (r < 0)
1336 return r;
1337
1338 r = sd_bus_set_bus_client(bus, true);
1339 if (r < 0)
1340 return r;
1341
1342 r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
1343 if (r < 0)
1344 return r;
1345
1346 r = sd_bus_set_watch_bind(bus, true);
1347 if (r < 0)
1348 return r;
1349
1350 r = sd_bus_set_connected_signal(bus, true);
1351 if (r < 0)
1352 return r;
1353
1354 r = sd_bus_start(bus);
1355 if (r < 0)
1356 return r;
1357
1358 *ret = TAKE_PTR(bus);
1359
1360 return 0;
1361 }
1362
1363 int bus_reply_pair_array(sd_bus_message *m, char **l) {
1364 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1365 char **k, **v;
1366 int r;
1367
1368 assert(m);
1369
1370 /* Reply to the specified message with a message containing a dictionary put together from the
1371 * specified strv */
1372
1373 r = sd_bus_message_new_method_return(m, &reply);
1374 if (r < 0)
1375 return r;
1376
1377 r = sd_bus_message_open_container(reply, 'a', "{ss}");
1378 if (r < 0)
1379 return r;
1380
1381 STRV_FOREACH_PAIR(k, v, l) {
1382 r = sd_bus_message_append(reply, "{ss}", *k, *v);
1383 if (r < 0)
1384 return r;
1385 }
1386
1387 r = sd_bus_message_close_container(reply);
1388 if (r < 0)
1389 return r;
1390
1391 return sd_bus_send(NULL, reply, NULL);
1392 }
1393
1394 static void bus_message_unref_wrapper(void *m) {
1395 sd_bus_message_unref(m);
1396 }
1397
1398 const struct hash_ops bus_message_hash_ops = {
1399 .hash = trivial_hash_func,
1400 .compare = trivial_compare_func,
1401 .free_value = bus_message_unref_wrapper,
1402 };
1403
1404 /* Shorthand flavors of the sd-bus convenience helpers with destination,path,interface
1405 * strings encapsulated within a single struct.
1406 */
1407 int bus_call_method_async(
1408 sd_bus *bus,
1409 sd_bus_slot **slot,
1410 const BusLocator *locator,
1411 const char *member,
1412 sd_bus_message_handler_t callback,
1413 void *userdata,
1414 const char *types, ...) {
1415
1416 va_list ap;
1417 int r;
1418
1419 assert(locator);
1420
1421 va_start(ap, types);
1422 r = sd_bus_call_method_asyncv(bus, slot, locator->destination, locator->path, locator->interface, member, callback, userdata, types, ap);
1423 va_end(ap);
1424
1425 return r;
1426 }
1427
1428 int bus_call_method(
1429 sd_bus *bus,
1430 const BusLocator *locator,
1431 const char *member,
1432 sd_bus_error *error,
1433 sd_bus_message **reply,
1434 const char *types, ...) {
1435
1436 va_list ap;
1437 int r;
1438
1439 assert(locator);
1440
1441 va_start(ap, types);
1442 r = sd_bus_call_methodv(bus, locator->destination, locator->path, locator->interface, member, error, reply, types, ap);
1443 va_end(ap);
1444
1445 return r;
1446 }
1447
1448 int bus_get_property(
1449 sd_bus *bus,
1450 const BusLocator *locator,
1451 const char *member,
1452 sd_bus_error *error,
1453 sd_bus_message **reply,
1454 const char *type) {
1455
1456 assert(locator);
1457
1458 return sd_bus_get_property(bus, locator->destination, locator->path, locator->interface, member, error, reply, type);
1459 }
1460
1461 int bus_get_property_trivial(
1462 sd_bus *bus,
1463 const BusLocator *locator,
1464 const char *member,
1465 sd_bus_error *error,
1466 char type, void *ptr) {
1467
1468 assert(locator);
1469
1470 return sd_bus_get_property_trivial(bus, locator->destination, locator->path, locator->interface, member, error, type, ptr);
1471 }
1472
1473 int bus_get_property_string(
1474 sd_bus *bus,
1475 const BusLocator *locator,
1476 const char *member,
1477 sd_bus_error *error,
1478 char **ret) {
1479
1480 assert(locator);
1481
1482 return sd_bus_get_property_string(bus, locator->destination, locator->path, locator->interface, member, error, ret);
1483 }
1484
1485 int bus_get_property_strv(
1486 sd_bus *bus,
1487 const BusLocator *locator,
1488 const char *member,
1489 sd_bus_error *error,
1490 char ***ret) {
1491
1492 assert(locator);
1493
1494 return sd_bus_get_property_strv(bus, locator->destination, locator->path, locator->interface, member, error, ret);
1495 }
1496
1497 int bus_set_property(
1498 sd_bus *bus,
1499 const BusLocator *locator,
1500 const char *member,
1501 sd_bus_error *error,
1502 const char *type, ...) {
1503
1504 va_list ap;
1505 int r;
1506
1507 assert(locator);
1508
1509 va_start(ap, type);
1510 r = sd_bus_set_propertyv(bus, locator->destination, locator->path, locator->interface, member, error, type, ap);
1511 va_end(ap);
1512
1513 return r;
1514 }
1515
1516 int bus_match_signal(
1517 sd_bus *bus,
1518 sd_bus_slot **ret,
1519 const BusLocator *locator,
1520 const char *member,
1521 sd_bus_message_handler_t callback,
1522 void *userdata) {
1523
1524 assert(locator);
1525
1526 return sd_bus_match_signal(bus, ret, locator->destination, locator->path, locator->interface, member, callback, userdata);
1527 }
1528
1529 int bus_match_signal_async(
1530 sd_bus *bus,
1531 sd_bus_slot **ret,
1532 const BusLocator *locator,
1533 const char *member,
1534 sd_bus_message_handler_t callback,
1535 sd_bus_message_handler_t install_callback,
1536 void *userdata) {
1537
1538 assert(locator);
1539
1540 return sd_bus_match_signal_async(bus, ret, locator->destination, locator->path, locator->interface, member, callback, install_callback, userdata);
1541 }
1542
1543 int bus_message_new_method_call(
1544 sd_bus *bus,
1545 sd_bus_message **m,
1546 const BusLocator *locator,
1547 const char *member) {
1548
1549 assert(locator);
1550
1551 return sd_bus_message_new_method_call(bus, m, locator->destination, locator->path, locator->interface, member);
1552 }
1553
1554 int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, void *userdata) {
1555 int r;
1556
1557 log_debug("Registering bus object implementation for path=%s iface=%s", impl->path, impl->interface);
1558
1559 for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) {
1560 r = sd_bus_add_object_vtable(bus, NULL,
1561 impl->path,
1562 impl->interface,
1563 *p,
1564 userdata);
1565 if (r < 0)
1566 return log_error_errno(r, "Failed to register bus path %s with interface %s: %m",
1567 impl->path,
1568 impl->interface);
1569 }
1570
1571 for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) {
1572 r = sd_bus_add_fallback_vtable(bus, NULL,
1573 impl->path,
1574 impl->interface,
1575 p->vtable,
1576 p->object_find,
1577 userdata);
1578 if (r < 0)
1579 return log_error_errno(r, "Failed to register bus path %s with interface %s: %m",
1580 impl->path,
1581 impl->interface);
1582 }
1583
1584 if (impl->node_enumerator) {
1585 r = sd_bus_add_node_enumerator(bus, NULL,
1586 impl->path,
1587 impl->node_enumerator,
1588 userdata);
1589 if (r < 0)
1590 return log_error_errno(r, "Failed to add node enumerator for %s: %m",
1591 impl->path);
1592 }
1593
1594 if (impl->manager) {
1595 r = sd_bus_add_object_manager(bus, NULL, impl->path);
1596 if (r < 0)
1597 return log_error_errno(r, "Failed to add object manager for %s: %m", impl->path);
1598 }
1599
1600 for (size_t i = 0; impl->children && impl->children[i]; i++) {
1601 r = bus_add_implementation(bus, impl->children[i], userdata);
1602 if (r < 0)
1603 return r;
1604 }
1605
1606 return 0;
1607 }
1608
1609 static const BusObjectImplementation* find_implementation(
1610 const char *pattern,
1611 const BusObjectImplementation* const* bus_objects) {
1612
1613 for (size_t i = 0; bus_objects && bus_objects[i]; i++) {
1614 const BusObjectImplementation *impl = bus_objects[i];
1615
1616 if (STR_IN_SET(pattern, impl->path, impl->interface))
1617 return impl;
1618
1619 impl = find_implementation(pattern, impl->children);
1620 if (impl)
1621 return impl;
1622 }
1623
1624 return NULL;
1625 }
1626
1627 static int bus_introspect_implementation(
1628 struct introspect *intro,
1629 const BusObjectImplementation *impl) {
1630 int r;
1631
1632 for (const sd_bus_vtable **p = impl->vtables; p && *p; p++) {
1633 r = introspect_write_interface(intro, impl->interface, *p);
1634 if (r < 0)
1635 return log_error_errno(r, "Failed to write introspection data: %m");
1636 }
1637
1638 for (const BusObjectVtablePair *p = impl->fallback_vtables; p && p->vtable; p++) {
1639 r = introspect_write_interface(intro, impl->interface, p->vtable);
1640 if (r < 0)
1641 return log_error_errno(r, "Failed to write introspection data: %m");
1642 }
1643
1644 return 0;
1645 }
1646
1647 static void list_paths(
1648 FILE *out,
1649 const BusObjectImplementation* const* bus_objects) {
1650
1651 for (size_t i = 0; bus_objects[i]; i++) {
1652 fprintf(out, "%s\t%s\n", bus_objects[i]->path, bus_objects[i]->interface);
1653 if (bus_objects[i]->children)
1654 list_paths(out, bus_objects[i]->children);
1655 }
1656 }
1657
1658 int bus_introspect_implementations(
1659 FILE *out,
1660 const char *pattern,
1661 const BusObjectImplementation* const* bus_objects) {
1662
1663 const BusObjectImplementation *impl, *main_impl = NULL;
1664 _cleanup_free_ char *s = NULL;
1665 int r;
1666
1667 if (streq(pattern, "list")) {
1668 list_paths(out, bus_objects);
1669 return 0;
1670 }
1671
1672 struct introspect intro = {};
1673 bool is_interface = sd_bus_interface_name_is_valid(pattern);
1674
1675 impl = find_implementation(pattern, bus_objects);
1676 if (!impl)
1677 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
1678 "%s %s not found",
1679 is_interface ? "Interface" : "Object path",
1680 pattern);
1681
1682 /* We use trusted=false here to get all the @org.freedesktop.systemd1.Privileged annotations. */
1683 r = introspect_begin(&intro, false);
1684 if (r < 0)
1685 return log_error_errno(r, "Failed to write introspection data: %m");
1686
1687 r = introspect_write_default_interfaces(&intro, impl->manager);
1688 if (r < 0)
1689 return log_error_errno(r, "Failed to write introspection data: %m");
1690
1691 /* Check if there is a non-fallback path that applies to the given interface, also
1692 * print it. This is useful in the case of units: o.fd.systemd1.Service is declared
1693 * as a fallback vtable for o/fd/systemd1/unit, and we also want to print
1694 * o.fd.systemd1.Unit, which is the non-fallback implementation. */
1695 if (impl->fallback_vtables && is_interface)
1696 main_impl = find_implementation(impl->path, bus_objects);
1697
1698 if (main_impl)
1699 bus_introspect_implementation(&intro, main_impl);
1700
1701 if (impl != main_impl)
1702 bus_introspect_implementation(&intro, impl);
1703
1704 _cleanup_set_free_ Set *nodes = NULL;
1705
1706 for (size_t i = 0; impl->children && impl->children[i]; i++) {
1707 r = set_put_strdup(&nodes, impl->children[i]->path);
1708 if (r < 0)
1709 return log_oom();
1710 }
1711
1712 r = introspect_write_child_nodes(&intro, nodes, impl->path);
1713 if (r < 0)
1714 return r;
1715
1716 r = introspect_finish(&intro, &s);
1717 if (r < 0)
1718 return log_error_errno(r, "Failed to write introspection data: %m");
1719
1720 fputs(s, out);
1721 return 0;
1722 }