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