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