]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machined-dbus.c
Merge pull request #2331 from yuwata/journal-remote-unit-v2
[thirdparty/systemd.git] / src / machine / machined-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 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 <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "sd-id128.h"
27
28 #include "alloc-util.h"
29 #include "btrfs-util.h"
30 #include "bus-common-errors.h"
31 #include "bus-util.h"
32 #include "cgroup-util.h"
33 #include "fd-util.h"
34 #include "formats-util.h"
35 #include "hostname-util.h"
36 #include "image-dbus.h"
37 #include "machine-dbus.h"
38 #include "machine-image.h"
39 #include "machine-pool.h"
40 #include "machined.h"
41 #include "path-util.h"
42 #include "process-util.h"
43 #include "stdio-util.h"
44 #include "strv.h"
45 #include "unit-name.h"
46 #include "user-util.h"
47
48 static int property_get_pool_path(
49 sd_bus *bus,
50 const char *path,
51 const char *interface,
52 const char *property,
53 sd_bus_message *reply,
54 void *userdata,
55 sd_bus_error *error) {
56
57 assert(bus);
58 assert(reply);
59
60 return sd_bus_message_append(reply, "s", "/var/lib/machines");
61 }
62
63 static int property_get_pool_usage(
64 sd_bus *bus,
65 const char *path,
66 const char *interface,
67 const char *property,
68 sd_bus_message *reply,
69 void *userdata,
70 sd_bus_error *error) {
71
72 _cleanup_close_ int fd = -1;
73 uint64_t usage = (uint64_t) -1;
74 struct stat st;
75
76 assert(bus);
77 assert(reply);
78
79 /* We try to read the quota info from /var/lib/machines, as
80 * well as the usage of the loopback file
81 * /var/lib/machines.raw, and pick the larger value. */
82
83 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
84 if (fd >= 0) {
85 BtrfsQuotaInfo q;
86
87 if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
88 usage = q.referenced;
89 }
90
91 if (stat("/var/lib/machines.raw", &st) >= 0) {
92 if (usage == (uint64_t) -1 || st.st_blocks * 512ULL > usage)
93 usage = st.st_blocks * 512ULL;
94 }
95
96 return sd_bus_message_append(reply, "t", usage);
97 }
98
99 static int property_get_pool_limit(
100 sd_bus *bus,
101 const char *path,
102 const char *interface,
103 const char *property,
104 sd_bus_message *reply,
105 void *userdata,
106 sd_bus_error *error) {
107
108 _cleanup_close_ int fd = -1;
109 uint64_t size = (uint64_t) -1;
110 struct stat st;
111
112 assert(bus);
113 assert(reply);
114
115 /* We try to read the quota limit from /var/lib/machines, as
116 * well as the size of the loopback file
117 * /var/lib/machines.raw, and pick the smaller value. */
118
119 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
120 if (fd >= 0) {
121 BtrfsQuotaInfo q;
122
123 if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
124 size = q.referenced_max;
125 }
126
127 if (stat("/var/lib/machines.raw", &st) >= 0) {
128 if (size == (uint64_t) -1 || (uint64_t) st.st_size < size)
129 size = st.st_size;
130 }
131
132 return sd_bus_message_append(reply, "t", size);
133 }
134
135 static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
136 _cleanup_free_ char *p = NULL;
137 Manager *m = userdata;
138 Machine *machine;
139 const char *name;
140 int r;
141
142 assert(message);
143 assert(m);
144
145 r = sd_bus_message_read(message, "s", &name);
146 if (r < 0)
147 return r;
148
149 machine = hashmap_get(m->machines, name);
150 if (!machine)
151 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
152
153 p = machine_bus_path(machine);
154 if (!p)
155 return -ENOMEM;
156
157 return sd_bus_reply_method_return(message, "o", p);
158 }
159
160 static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
161 _cleanup_free_ char *p = NULL;
162 Manager *m = userdata;
163 const char *name;
164 int r;
165
166 assert(message);
167 assert(m);
168
169 r = sd_bus_message_read(message, "s", &name);
170 if (r < 0)
171 return r;
172
173 r = image_find(name, NULL);
174 if (r == 0)
175 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
176 if (r < 0)
177 return r;
178
179 p = image_bus_path(name);
180 if (!p)
181 return -ENOMEM;
182
183 return sd_bus_reply_method_return(message, "o", p);
184 }
185
186 static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
187 _cleanup_free_ char *p = NULL;
188 Manager *m = userdata;
189 Machine *machine = NULL;
190 pid_t pid;
191 int r;
192
193 assert(message);
194 assert(m);
195
196 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
197
198 r = sd_bus_message_read(message, "u", &pid);
199 if (r < 0)
200 return r;
201
202 if (pid < 0)
203 return -EINVAL;
204
205 if (pid == 0) {
206 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
207
208 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
209 if (r < 0)
210 return r;
211
212 r = sd_bus_creds_get_pid(creds, &pid);
213 if (r < 0)
214 return r;
215 }
216
217 r = manager_get_machine_by_pid(m, pid, &machine);
218 if (r < 0)
219 return r;
220 if (!machine)
221 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
222
223 p = machine_bus_path(machine);
224 if (!p)
225 return -ENOMEM;
226
227 return sd_bus_reply_method_return(message, "o", p);
228 }
229
230 static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) {
231 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
232 Manager *m = userdata;
233 Machine *machine;
234 Iterator i;
235 int r;
236
237 assert(message);
238 assert(m);
239
240 r = sd_bus_message_new_method_return(message, &reply);
241 if (r < 0)
242 return sd_bus_error_set_errno(error, r);
243
244 r = sd_bus_message_open_container(reply, 'a', "(ssso)");
245 if (r < 0)
246 return sd_bus_error_set_errno(error, r);
247
248 HASHMAP_FOREACH(machine, m->machines, i) {
249 _cleanup_free_ char *p = NULL;
250
251 p = machine_bus_path(machine);
252 if (!p)
253 return -ENOMEM;
254
255 r = sd_bus_message_append(reply, "(ssso)",
256 machine->name,
257 strempty(machine_class_to_string(machine->class)),
258 machine->service,
259 p);
260 if (r < 0)
261 return sd_bus_error_set_errno(error, r);
262 }
263
264 r = sd_bus_message_close_container(reply);
265 if (r < 0)
266 return sd_bus_error_set_errno(error, r);
267
268 return sd_bus_send(NULL, reply, NULL);
269 }
270
271 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
272 const char *name, *service, *class, *root_directory;
273 const int32_t *netif = NULL;
274 MachineClass c;
275 uint32_t leader;
276 sd_id128_t id;
277 const void *v;
278 Machine *m;
279 size_t n, n_netif = 0;
280 int r;
281
282 assert(manager);
283 assert(message);
284 assert(_m);
285
286 r = sd_bus_message_read(message, "s", &name);
287 if (r < 0)
288 return r;
289 if (!machine_name_is_valid(name))
290 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
291
292 r = sd_bus_message_read_array(message, 'y', &v, &n);
293 if (r < 0)
294 return r;
295 if (n == 0)
296 id = SD_ID128_NULL;
297 else if (n == 16)
298 memcpy(&id, v, n);
299 else
300 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
301
302 r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
303 if (r < 0)
304 return r;
305
306 if (read_network) {
307 size_t i;
308
309 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
310 if (r < 0)
311 return r;
312
313 n_netif /= sizeof(int32_t);
314
315 for (i = 0; i < n_netif; i++) {
316 if (netif[i] <= 0)
317 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
318 }
319 }
320
321 if (isempty(class))
322 c = _MACHINE_CLASS_INVALID;
323 else {
324 c = machine_class_from_string(class);
325 if (c < 0)
326 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
327 }
328
329 if (leader == 1)
330 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
331
332 if (!isempty(root_directory) && !path_is_absolute(root_directory))
333 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
334
335 if (leader == 0) {
336 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
337
338 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
339 if (r < 0)
340 return r;
341
342 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
343
344 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
345 if (r < 0)
346 return r;
347 }
348
349 if (hashmap_get(manager->machines, name))
350 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
351
352 r = manager_add_machine(manager, name, &m);
353 if (r < 0)
354 return r;
355
356 m->leader = leader;
357 m->class = c;
358 m->id = id;
359
360 if (!isempty(service)) {
361 m->service = strdup(service);
362 if (!m->service) {
363 r = -ENOMEM;
364 goto fail;
365 }
366 }
367
368 if (!isempty(root_directory)) {
369 m->root_directory = strdup(root_directory);
370 if (!m->root_directory) {
371 r = -ENOMEM;
372 goto fail;
373 }
374 }
375
376 if (n_netif > 0) {
377 assert_cc(sizeof(int32_t) == sizeof(int));
378 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
379 if (!m->netif) {
380 r = -ENOMEM;
381 goto fail;
382 }
383
384 m->n_netif = n_netif;
385 }
386
387 *_m = m;
388
389 return 1;
390
391 fail:
392 machine_add_to_gc_queue(m);
393 return r;
394 }
395
396 static int method_create_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
397 Manager *manager = userdata;
398 Machine *m = NULL;
399 int r;
400
401 assert(message);
402 assert(manager);
403
404 r = method_create_or_register_machine(manager, message, read_network, &m, error);
405 if (r < 0)
406 return r;
407
408 r = sd_bus_message_enter_container(message, 'a', "(sv)");
409 if (r < 0)
410 goto fail;
411
412 r = machine_start(m, message, error);
413 if (r < 0)
414 goto fail;
415
416 m->create_message = sd_bus_message_ref(message);
417 return 1;
418
419 fail:
420 machine_add_to_gc_queue(m);
421 return r;
422 }
423
424 static int method_create_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) {
425 return method_create_machine_internal(message, true, userdata, error);
426 }
427
428 static int method_create_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
429 return method_create_machine_internal(message, false, userdata, error);
430 }
431
432 static int method_register_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
433 Manager *manager = userdata;
434 _cleanup_free_ char *p = NULL;
435 Machine *m = NULL;
436 int r;
437
438 assert(message);
439 assert(manager);
440
441 r = method_create_or_register_machine(manager, message, read_network, &m, error);
442 if (r < 0)
443 return r;
444
445 r = cg_pid_get_unit(m->leader, &m->unit);
446 if (r < 0) {
447 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
448 goto fail;
449 }
450
451 r = machine_start(m, NULL, error);
452 if (r < 0)
453 goto fail;
454
455 p = machine_bus_path(m);
456 if (!p) {
457 r = -ENOMEM;
458 goto fail;
459 }
460
461 return sd_bus_reply_method_return(message, "o", p);
462
463 fail:
464 machine_add_to_gc_queue(m);
465 return r;
466 }
467
468 static int method_register_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) {
469 return method_register_machine_internal(message, true, userdata, error);
470 }
471
472 static int method_register_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
473 return method_register_machine_internal(message, false, userdata, error);
474 }
475
476 static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
477 Manager *m = userdata;
478 Machine *machine;
479 const char *name;
480 int r;
481
482 assert(message);
483 assert(m);
484
485 r = sd_bus_message_read(message, "s", &name);
486 if (r < 0)
487 return sd_bus_error_set_errno(error, r);
488
489 machine = hashmap_get(m->machines, name);
490 if (!machine)
491 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
492
493 return bus_machine_method_terminate(message, machine, error);
494 }
495
496 static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
497 Manager *m = userdata;
498 Machine *machine;
499 const char *name;
500 int r;
501
502 assert(message);
503 assert(m);
504
505 r = sd_bus_message_read(message, "s", &name);
506 if (r < 0)
507 return sd_bus_error_set_errno(error, r);
508
509 machine = hashmap_get(m->machines, name);
510 if (!machine)
511 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
512
513 return bus_machine_method_kill(message, machine, error);
514 }
515
516 static int method_get_machine_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
517 Manager *m = userdata;
518 Machine *machine;
519 const char *name;
520 int r;
521
522 assert(message);
523 assert(m);
524
525 r = sd_bus_message_read(message, "s", &name);
526 if (r < 0)
527 return sd_bus_error_set_errno(error, r);
528
529 machine = hashmap_get(m->machines, name);
530 if (!machine)
531 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
532
533 return bus_machine_method_get_addresses(message, machine, error);
534 }
535
536 static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
537 Manager *m = userdata;
538 Machine *machine;
539 const char *name;
540 int r;
541
542 assert(message);
543 assert(m);
544
545 r = sd_bus_message_read(message, "s", &name);
546 if (r < 0)
547 return sd_bus_error_set_errno(error, r);
548
549 machine = hashmap_get(m->machines, name);
550 if (!machine)
551 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
552
553 return bus_machine_method_get_os_release(message, machine, error);
554 }
555
556 static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
557 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
558 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
559 Manager *m = userdata;
560 Image *image;
561 Iterator i;
562 int r;
563
564 assert(message);
565 assert(m);
566
567 images = hashmap_new(&string_hash_ops);
568 if (!images)
569 return -ENOMEM;
570
571 r = image_discover(images);
572 if (r < 0)
573 return r;
574
575 r = sd_bus_message_new_method_return(message, &reply);
576 if (r < 0)
577 return r;
578
579 r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
580 if (r < 0)
581 return r;
582
583 HASHMAP_FOREACH(image, images, i) {
584 _cleanup_free_ char *p = NULL;
585
586 p = image_bus_path(image->name);
587 if (!p)
588 return -ENOMEM;
589
590 r = sd_bus_message_append(reply, "(ssbttto)",
591 image->name,
592 image_type_to_string(image->type),
593 image->read_only,
594 image->crtime,
595 image->mtime,
596 image->usage,
597 p);
598 if (r < 0)
599 return r;
600 }
601
602 r = sd_bus_message_close_container(reply);
603 if (r < 0)
604 return r;
605
606 return sd_bus_send(NULL, reply, NULL);
607 }
608
609 static int method_open_machine_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
610 Manager *m = userdata;
611 Machine *machine;
612 const char *name;
613 int r;
614
615 assert(message);
616 assert(m);
617
618 r = sd_bus_message_read(message, "s", &name);
619 if (r < 0)
620 return sd_bus_error_set_errno(error, r);
621
622 machine = hashmap_get(m->machines, name);
623 if (!machine)
624 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
625
626 return bus_machine_method_open_pty(message, machine, error);
627 }
628
629 static int method_open_machine_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
630 Manager *m = userdata;
631 Machine *machine;
632 const char *name;
633 int r;
634
635 assert(message);
636 assert(m);
637
638 r = sd_bus_message_read(message, "s", &name);
639 if (r < 0)
640 return r;
641
642 machine = hashmap_get(m->machines, name);
643 if (!machine)
644 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
645
646 return bus_machine_method_open_login(message, machine, error);
647 }
648
649 static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
650 Manager *m = userdata;
651 Machine *machine;
652 const char *name;
653
654 int r;
655
656 assert(message);
657 assert(m);
658
659 r = sd_bus_message_read(message, "s", &name);
660 if (r < 0)
661 return r;
662
663 machine = hashmap_get(m->machines, name);
664 if (!machine)
665 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
666
667 return bus_machine_method_open_shell(message, machine, error);
668 }
669
670 static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
671 Manager *m = userdata;
672 Machine *machine;
673 const char *name;
674 int r;
675
676 assert(message);
677 assert(m);
678
679 r = sd_bus_message_read(message, "s", &name);
680 if (r < 0)
681 return r;
682
683 machine = hashmap_get(m->machines, name);
684 if (!machine)
685 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
686
687 return bus_machine_method_bind_mount(message, machine, error);
688 }
689
690 static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
691 Manager *m = userdata;
692 Machine *machine;
693 const char *name;
694 int r;
695
696 assert(message);
697 assert(m);
698
699 r = sd_bus_message_read(message, "s", &name);
700 if (r < 0)
701 return r;
702
703 machine = hashmap_get(m->machines, name);
704 if (!machine)
705 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
706
707 return bus_machine_method_copy(message, machine, error);
708 }
709
710 static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
711 _cleanup_(image_unrefp) Image* i = NULL;
712 const char *name;
713 int r;
714
715 assert(message);
716
717 r = sd_bus_message_read(message, "s", &name);
718 if (r < 0)
719 return r;
720
721 if (!image_name_is_valid(name))
722 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
723
724 r = image_find(name, &i);
725 if (r < 0)
726 return r;
727 if (r == 0)
728 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
729
730 i->userdata = userdata;
731 return bus_image_method_remove(message, i, error);
732 }
733
734 static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
735 _cleanup_(image_unrefp) Image* i = NULL;
736 const char *old_name;
737 int r;
738
739 assert(message);
740
741 r = sd_bus_message_read(message, "s", &old_name);
742 if (r < 0)
743 return r;
744
745 if (!image_name_is_valid(old_name))
746 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
747
748 r = image_find(old_name, &i);
749 if (r < 0)
750 return r;
751 if (r == 0)
752 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
753
754 i->userdata = userdata;
755 return bus_image_method_rename(message, i, error);
756 }
757
758 static int method_clone_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
759 _cleanup_(image_unrefp) Image *i = NULL;
760 const char *old_name;
761 int r;
762
763 assert(message);
764
765 r = sd_bus_message_read(message, "s", &old_name);
766 if (r < 0)
767 return r;
768
769 if (!image_name_is_valid(old_name))
770 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
771
772 r = image_find(old_name, &i);
773 if (r < 0)
774 return r;
775 if (r == 0)
776 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
777
778 i->userdata = userdata;
779 return bus_image_method_clone(message, i, error);
780 }
781
782 static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) {
783 _cleanup_(image_unrefp) Image *i = NULL;
784 const char *name;
785 int r;
786
787 assert(message);
788
789 r = sd_bus_message_read(message, "s", &name);
790 if (r < 0)
791 return r;
792
793 if (!image_name_is_valid(name))
794 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
795
796 r = image_find(name, &i);
797 if (r < 0)
798 return r;
799 if (r == 0)
800 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
801
802 i->userdata = userdata;
803 return bus_image_method_mark_read_only(message, i, error);
804 }
805
806 static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
807 Manager *m = userdata;
808 uint64_t limit;
809 int r;
810
811 assert(message);
812
813 r = sd_bus_message_read(message, "t", &limit);
814 if (r < 0)
815 return r;
816
817 r = bus_verify_polkit_async(
818 message,
819 CAP_SYS_ADMIN,
820 "org.freedesktop.machine1.manage-machines",
821 NULL,
822 false,
823 UID_INVALID,
824 &m->polkit_registry,
825 error);
826 if (r < 0)
827 return r;
828 if (r == 0)
829 return 1; /* Will call us back */
830
831 /* Set up the machine directory if necessary */
832 r = setup_machine_directory(limit, error);
833 if (r < 0)
834 return r;
835
836 r = btrfs_resize_loopback("/var/lib/machines", limit, false);
837 if (r == -ENOTTY)
838 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
839 if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
840 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
841
842 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit);
843
844 r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit);
845 if (r == -ENOTTY)
846 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
847 if (r < 0)
848 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
849
850 return sd_bus_reply_method_return(message, NULL);
851 }
852
853 static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
854 _cleanup_(image_unrefp) Image *i = NULL;
855 const char *name;
856 int r;
857
858 assert(message);
859
860 r = sd_bus_message_read(message, "s", &name);
861 if (r < 0)
862 return r;
863
864 if (!image_name_is_valid(name))
865 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
866
867 r = image_find(name, &i);
868 if (r < 0)
869 return r;
870 if (r == 0)
871 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
872
873 i->userdata = userdata;
874 return bus_image_method_set_limit(message, i, error);
875 }
876
877 static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
878 _cleanup_fclose_ FILE *f = NULL;
879 Manager *m = userdata;
880 const char *name, *p;
881 Machine *machine;
882 uint32_t uid;
883 int r;
884
885 r = sd_bus_message_read(message, "su", &name, &uid);
886 if (r < 0)
887 return r;
888
889 if (!uid_is_valid(uid))
890 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
891
892 machine = hashmap_get(m->machines, name);
893 if (!machine)
894 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
895
896 if (machine->class != MACHINE_CONTAINER)
897 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
898
899 p = procfs_file_alloca(machine->leader, "uid_map");
900 f = fopen(p, "re");
901 if (!f)
902 return -errno;
903
904 for (;;) {
905 uid_t uid_base, uid_shift, uid_range, converted;
906 int k;
907
908 errno = 0;
909 k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
910 if (k < 0 && feof(f))
911 break;
912 if (k != 3) {
913 if (ferror(f) && errno > 0)
914 return -errno;
915
916 return -EIO;
917 }
918
919 if (uid < uid_base || uid >= uid_base + uid_range)
920 continue;
921
922 converted = uid - uid_base + uid_shift;
923 if (!uid_is_valid(converted))
924 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
925
926 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
927 }
928
929 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name);
930 }
931
932 static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
933 Manager *m = userdata;
934 Machine *machine;
935 uid_t uid;
936 Iterator i;
937 int r;
938
939 r = sd_bus_message_read(message, "u", &uid);
940 if (r < 0)
941 return r;
942 if (!uid_is_valid(uid))
943 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
944 if (uid < 0x10000)
945 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
946
947 HASHMAP_FOREACH(machine, m->machines, i) {
948 _cleanup_fclose_ FILE *f = NULL;
949 char p[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
950
951 if (machine->class != MACHINE_CONTAINER)
952 continue;
953
954 xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader);
955 f = fopen(p, "re");
956 if (!f) {
957 log_warning_errno(errno, "Failed top open %s, ignoring,", p);
958 continue;
959 }
960
961 for (;;) {
962 _cleanup_free_ char *o = NULL;
963 uid_t uid_base, uid_shift, uid_range, converted;
964 int k;
965
966 errno = 0;
967 k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
968 if (k < 0 && feof(f))
969 break;
970 if (k != 3) {
971 if (ferror(f) && errno > 0)
972 return -errno;
973
974 return -EIO;
975 }
976
977 if (uid < uid_shift || uid >= uid_shift + uid_range)
978 continue;
979
980 converted = (uid - uid_shift + uid_base);
981 if (!uid_is_valid(converted))
982 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
983
984 o = machine_bus_path(machine);
985 if (!o)
986 return -ENOMEM;
987
988 return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
989 }
990 }
991
992 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
993 }
994
995 static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
996 _cleanup_fclose_ FILE *f = NULL;
997 Manager *m = groupdata;
998 const char *name, *p;
999 Machine *machine;
1000 uint32_t gid;
1001 int r;
1002
1003 r = sd_bus_message_read(message, "su", &name, &gid);
1004 if (r < 0)
1005 return r;
1006
1007 if (!gid_is_valid(gid))
1008 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1009
1010 machine = hashmap_get(m->machines, name);
1011 if (!machine)
1012 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1013
1014 if (machine->class != MACHINE_CONTAINER)
1015 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
1016
1017 p = procfs_file_alloca(machine->leader, "gid_map");
1018 f = fopen(p, "re");
1019 if (!f)
1020 return -errno;
1021
1022 for (;;) {
1023 gid_t gid_base, gid_shift, gid_range, converted;
1024 int k;
1025
1026 errno = 0;
1027 k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
1028 if (k < 0 && feof(f))
1029 break;
1030 if (k != 3) {
1031 if (ferror(f) && errno > 0)
1032 return -errno;
1033
1034 return -EIO;
1035 }
1036
1037 if (gid < gid_base || gid >= gid_base + gid_range)
1038 continue;
1039
1040 converted = gid - gid_base + gid_shift;
1041 if (!gid_is_valid(converted))
1042 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1043
1044 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
1045 }
1046
1047 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name);
1048 }
1049
1050 static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
1051 Manager *m = groupdata;
1052 Machine *machine;
1053 gid_t gid;
1054 Iterator i;
1055 int r;
1056
1057 r = sd_bus_message_read(message, "u", &gid);
1058 if (r < 0)
1059 return r;
1060 if (!gid_is_valid(gid))
1061 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1062 if (gid < 0x10000)
1063 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
1064
1065 HASHMAP_FOREACH(machine, m->machines, i) {
1066 _cleanup_fclose_ FILE *f = NULL;
1067 char p[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1];
1068
1069 if (machine->class != MACHINE_CONTAINER)
1070 continue;
1071
1072 xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader);
1073 f = fopen(p, "re");
1074 if (!f) {
1075 log_warning_errno(errno, "Failed top open %s, ignoring,", p);
1076 continue;
1077 }
1078
1079 for (;;) {
1080 _cleanup_free_ char *o = NULL;
1081 gid_t gid_base, gid_shift, gid_range, converted;
1082 int k;
1083
1084 errno = 0;
1085 k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
1086 if (k < 0 && feof(f))
1087 break;
1088 if (k != 3) {
1089 if (ferror(f) && errno > 0)
1090 return -errno;
1091
1092 return -EIO;
1093 }
1094
1095 if (gid < gid_shift || gid >= gid_shift + gid_range)
1096 continue;
1097
1098 converted = (gid - gid_shift + gid_base);
1099 if (!gid_is_valid(converted))
1100 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1101
1102 o = machine_bus_path(machine);
1103 if (!o)
1104 return -ENOMEM;
1105
1106 return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
1107 }
1108 }
1109
1110 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
1111 }
1112
1113 const sd_bus_vtable manager_vtable[] = {
1114 SD_BUS_VTABLE_START(0),
1115 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
1116 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
1117 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
1118 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1119 SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
1120 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1121 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
1122 SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
1123 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
1124 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
1125 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
1126 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
1127 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1128 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1129 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
1130 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
1131 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
1132 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
1133 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell, SD_BUS_VTABLE_UNPRIVILEGED),
1134 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1135 SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1136 SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1137 SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
1138 SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
1139 SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
1140 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
1141 SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
1142 SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
1143 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
1144 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
1145 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
1146 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
1147 SD_BUS_SIGNAL("MachineNew", "so", 0),
1148 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1149 SD_BUS_VTABLE_END
1150 };
1151
1152 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1153 const char *path, *result, *unit;
1154 Manager *m = userdata;
1155 Machine *machine;
1156 uint32_t id;
1157 int r;
1158
1159 assert(message);
1160 assert(m);
1161
1162 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
1163 if (r < 0) {
1164 bus_log_parse_error(r);
1165 return 0;
1166 }
1167
1168 machine = hashmap_get(m->machine_units, unit);
1169 if (!machine)
1170 return 0;
1171
1172 if (streq_ptr(path, machine->scope_job)) {
1173 machine->scope_job = mfree(machine->scope_job);
1174
1175 if (machine->started) {
1176 if (streq(result, "done"))
1177 machine_send_create_reply(machine, NULL);
1178 else {
1179 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
1180
1181 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
1182
1183 machine_send_create_reply(machine, &e);
1184 }
1185 }
1186
1187 machine_save(machine);
1188 }
1189
1190 machine_add_to_gc_queue(machine);
1191 return 0;
1192 }
1193
1194 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1195 _cleanup_free_ char *unit = NULL;
1196 const char *path;
1197 Manager *m = userdata;
1198 Machine *machine;
1199 int r;
1200
1201 assert(message);
1202 assert(m);
1203
1204 path = sd_bus_message_get_path(message);
1205 if (!path)
1206 return 0;
1207
1208 r = unit_name_from_dbus_path(path, &unit);
1209 if (r == -EINVAL) /* not for a unit */
1210 return 0;
1211 if (r < 0){
1212 log_oom();
1213 return 0;
1214 }
1215
1216 machine = hashmap_get(m->machine_units, unit);
1217 if (!machine)
1218 return 0;
1219
1220 machine_add_to_gc_queue(machine);
1221 return 0;
1222 }
1223
1224 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1225 const char *path, *unit;
1226 Manager *m = userdata;
1227 Machine *machine;
1228 int r;
1229
1230 assert(message);
1231 assert(m);
1232
1233 r = sd_bus_message_read(message, "so", &unit, &path);
1234 if (r < 0) {
1235 bus_log_parse_error(r);
1236 return 0;
1237 }
1238
1239 machine = hashmap_get(m->machine_units, unit);
1240 if (!machine)
1241 return 0;
1242
1243 machine_add_to_gc_queue(machine);
1244 return 0;
1245 }
1246
1247 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1248 Manager *m = userdata;
1249 Machine *machine;
1250 Iterator i;
1251 int b, r;
1252
1253 assert(message);
1254 assert(m);
1255
1256 r = sd_bus_message_read(message, "b", &b);
1257 if (r < 0) {
1258 bus_log_parse_error(r);
1259 return 0;
1260 }
1261 if (b)
1262 return 0;
1263
1264 /* systemd finished reloading, let's recheck all our machines */
1265 log_debug("System manager has been reloaded, rechecking machines...");
1266
1267 HASHMAP_FOREACH(machine, m->machines, i)
1268 machine_add_to_gc_queue(machine);
1269
1270 return 0;
1271 }
1272
1273 int manager_start_scope(
1274 Manager *manager,
1275 const char *scope,
1276 pid_t pid,
1277 const char *slice,
1278 const char *description,
1279 sd_bus_message *more_properties,
1280 sd_bus_error *error,
1281 char **job) {
1282
1283 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1284 int r;
1285
1286 assert(manager);
1287 assert(scope);
1288 assert(pid > 1);
1289
1290 r = sd_bus_message_new_method_call(
1291 manager->bus,
1292 &m,
1293 "org.freedesktop.systemd1",
1294 "/org/freedesktop/systemd1",
1295 "org.freedesktop.systemd1.Manager",
1296 "StartTransientUnit");
1297 if (r < 0)
1298 return r;
1299
1300 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
1301 if (r < 0)
1302 return r;
1303
1304 r = sd_bus_message_open_container(m, 'a', "(sv)");
1305 if (r < 0)
1306 return r;
1307
1308 if (!isempty(slice)) {
1309 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
1310 if (r < 0)
1311 return r;
1312 }
1313
1314 if (!isempty(description)) {
1315 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
1316 if (r < 0)
1317 return r;
1318 }
1319
1320 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
1321 if (r < 0)
1322 return r;
1323
1324 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
1325 if (r < 0)
1326 return r;
1327
1328 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
1329 if (r < 0)
1330 return bus_log_create_error(r);
1331
1332 if (more_properties) {
1333 r = sd_bus_message_copy(m, more_properties, true);
1334 if (r < 0)
1335 return r;
1336 }
1337
1338 r = sd_bus_message_close_container(m);
1339 if (r < 0)
1340 return r;
1341
1342 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1343 if (r < 0)
1344 return r;
1345
1346 r = sd_bus_call(manager->bus, m, 0, error, &reply);
1347 if (r < 0)
1348 return r;
1349
1350 if (job) {
1351 const char *j;
1352 char *copy;
1353
1354 r = sd_bus_message_read(reply, "o", &j);
1355 if (r < 0)
1356 return r;
1357
1358 copy = strdup(j);
1359 if (!copy)
1360 return -ENOMEM;
1361
1362 *job = copy;
1363 }
1364
1365 return 1;
1366 }
1367
1368 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1369 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1370 int r;
1371
1372 assert(manager);
1373 assert(unit);
1374
1375 r = sd_bus_call_method(
1376 manager->bus,
1377 "org.freedesktop.systemd1",
1378 "/org/freedesktop/systemd1",
1379 "org.freedesktop.systemd1.Manager",
1380 "StopUnit",
1381 error,
1382 &reply,
1383 "ss", unit, "fail");
1384 if (r < 0) {
1385 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1386 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1387
1388 if (job)
1389 *job = NULL;
1390
1391 sd_bus_error_free(error);
1392 return 0;
1393 }
1394
1395 return r;
1396 }
1397
1398 if (job) {
1399 const char *j;
1400 char *copy;
1401
1402 r = sd_bus_message_read(reply, "o", &j);
1403 if (r < 0)
1404 return r;
1405
1406 copy = strdup(j);
1407 if (!copy)
1408 return -ENOMEM;
1409
1410 *job = copy;
1411 }
1412
1413 return 1;
1414 }
1415
1416 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1417 assert(manager);
1418 assert(unit);
1419
1420 return sd_bus_call_method(
1421 manager->bus,
1422 "org.freedesktop.systemd1",
1423 "/org/freedesktop/systemd1",
1424 "org.freedesktop.systemd1.Manager",
1425 "KillUnit",
1426 error,
1427 NULL,
1428 "ssi", unit, "all", signo);
1429 }
1430
1431 int manager_unit_is_active(Manager *manager, const char *unit) {
1432 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1433 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1434 _cleanup_free_ char *path = NULL;
1435 const char *state;
1436 int r;
1437
1438 assert(manager);
1439 assert(unit);
1440
1441 path = unit_dbus_path_from_name(unit);
1442 if (!path)
1443 return -ENOMEM;
1444
1445 r = sd_bus_get_property(
1446 manager->bus,
1447 "org.freedesktop.systemd1",
1448 path,
1449 "org.freedesktop.systemd1.Unit",
1450 "ActiveState",
1451 &error,
1452 &reply,
1453 "s");
1454 if (r < 0) {
1455 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1456 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1457 return true;
1458
1459 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1460 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1461 return false;
1462
1463 return r;
1464 }
1465
1466 r = sd_bus_message_read(reply, "s", &state);
1467 if (r < 0)
1468 return -EINVAL;
1469
1470 return !STR_IN_SET(state, "inactive", "failed");
1471 }
1472
1473 int manager_job_is_active(Manager *manager, const char *path) {
1474 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1475 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1476 int r;
1477
1478 assert(manager);
1479 assert(path);
1480
1481 r = sd_bus_get_property(
1482 manager->bus,
1483 "org.freedesktop.systemd1",
1484 path,
1485 "org.freedesktop.systemd1.Job",
1486 "State",
1487 &error,
1488 &reply,
1489 "s");
1490 if (r < 0) {
1491 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1492 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1493 return true;
1494
1495 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1496 return false;
1497
1498 return r;
1499 }
1500
1501 /* We don't actually care about the state really. The fact
1502 * that we could read the job state is enough for us */
1503
1504 return true;
1505 }
1506
1507 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1508 Machine *mm;
1509 int r;
1510
1511 assert(m);
1512 assert(pid >= 1);
1513 assert(machine);
1514
1515 mm = hashmap_get(m->machine_leaders, PID_TO_PTR(pid));
1516 if (!mm) {
1517 _cleanup_free_ char *unit = NULL;
1518
1519 r = cg_pid_get_unit(pid, &unit);
1520 if (r >= 0)
1521 mm = hashmap_get(m->machine_units, unit);
1522 }
1523 if (!mm)
1524 return 0;
1525
1526 *machine = mm;
1527 return 1;
1528 }
1529
1530 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1531 Machine *machine;
1532
1533 assert(m);
1534 assert(name);
1535
1536 machine = hashmap_get(m->machines, name);
1537 if (!machine) {
1538 machine = machine_new(m, _MACHINE_CLASS_INVALID, name);
1539 if (!machine)
1540 return -ENOMEM;
1541 }
1542
1543 if (_machine)
1544 *_machine = machine;
1545
1546 return 0;
1547 }