]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machined-dbus.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / machine / machined-dbus.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "sd-id128.h"
26
27 #include "alloc-util.h"
28 #include "btrfs-util.h"
29 #include "bus-common-errors.h"
30 #include "bus-util.h"
31 #include "cgroup-util.h"
32 #include "fd-util.h"
33 #include "fileio.h"
34 #include "format-util.h"
35 #include "hostname-util.h"
36 #include "image-dbus.h"
37 #include "io-util.h"
38 #include "machine-dbus.h"
39 #include "machine-image.h"
40 #include "machine-pool.h"
41 #include "machined.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 #include "stdio-util.h"
45 #include "strv.h"
46 #include "unit-name.h"
47 #include "user-util.h"
48
49 static int property_get_pool_path(
50 sd_bus *bus,
51 const char *path,
52 const char *interface,
53 const char *property,
54 sd_bus_message *reply,
55 void *userdata,
56 sd_bus_error *error) {
57
58 assert(bus);
59 assert(reply);
60
61 return sd_bus_message_append(reply, "s", "/var/lib/machines");
62 }
63
64 static int property_get_pool_usage(
65 sd_bus *bus,
66 const char *path,
67 const char *interface,
68 const char *property,
69 sd_bus_message *reply,
70 void *userdata,
71 sd_bus_error *error) {
72
73 _cleanup_close_ int fd = -1;
74 uint64_t usage = (uint64_t) -1;
75 struct stat st;
76
77 assert(bus);
78 assert(reply);
79
80 /* We try to read the quota info from /var/lib/machines, as
81 * well as the usage of the loopback file
82 * /var/lib/machines.raw, and pick the larger value. */
83
84 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
85 if (fd >= 0) {
86 BtrfsQuotaInfo q;
87
88 if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
89 usage = q.referenced;
90 }
91
92 if (stat("/var/lib/machines.raw", &st) >= 0) {
93 if (usage == (uint64_t) -1 || st.st_blocks * 512ULL > usage)
94 usage = st.st_blocks * 512ULL;
95 }
96
97 return sd_bus_message_append(reply, "t", usage);
98 }
99
100 static int property_get_pool_limit(
101 sd_bus *bus,
102 const char *path,
103 const char *interface,
104 const char *property,
105 sd_bus_message *reply,
106 void *userdata,
107 sd_bus_error *error) {
108
109 _cleanup_close_ int fd = -1;
110 uint64_t size = (uint64_t) -1;
111 struct stat st;
112
113 assert(bus);
114 assert(reply);
115
116 /* We try to read the quota limit from /var/lib/machines, as
117 * well as the size of the loopback file
118 * /var/lib/machines.raw, and pick the smaller value. */
119
120 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
121 if (fd >= 0) {
122 BtrfsQuotaInfo q;
123
124 if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0)
125 size = q.referenced_max;
126 }
127
128 if (stat("/var/lib/machines.raw", &st) >= 0) {
129 if (size == (uint64_t) -1 || (uint64_t) st.st_size < size)
130 size = st.st_size;
131 }
132
133 return sd_bus_message_append(reply, "t", size);
134 }
135
136 static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
137 _cleanup_free_ char *p = NULL;
138 Manager *m = userdata;
139 Machine *machine;
140 const char *name;
141 int r;
142
143 assert(message);
144 assert(m);
145
146 r = sd_bus_message_read(message, "s", &name);
147 if (r < 0)
148 return r;
149
150 machine = hashmap_get(m->machines, name);
151 if (!machine)
152 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
153
154 p = machine_bus_path(machine);
155 if (!p)
156 return -ENOMEM;
157
158 return sd_bus_reply_method_return(message, "o", p);
159 }
160
161 static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
162 _cleanup_free_ char *p = NULL;
163 Manager *m = userdata;
164 const char *name;
165 int r;
166
167 assert(message);
168 assert(m);
169
170 r = sd_bus_message_read(message, "s", &name);
171 if (r < 0)
172 return r;
173
174 r = image_find(name, NULL);
175 if (r == 0)
176 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
177 if (r < 0)
178 return r;
179
180 p = image_bus_path(name);
181 if (!p)
182 return -ENOMEM;
183
184 return sd_bus_reply_method_return(message, "o", p);
185 }
186
187 static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
188 _cleanup_free_ char *p = NULL;
189 Manager *m = userdata;
190 Machine *machine = NULL;
191 pid_t pid;
192 int r;
193
194 assert(message);
195 assert(m);
196
197 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
198
199 r = sd_bus_message_read(message, "u", &pid);
200 if (r < 0)
201 return r;
202
203 if (pid < 0)
204 return -EINVAL;
205
206 if (pid == 0) {
207 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
208
209 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
210 if (r < 0)
211 return r;
212
213 r = sd_bus_creds_get_pid(creds, &pid);
214 if (r < 0)
215 return r;
216 }
217
218 r = manager_get_machine_by_pid(m, pid, &machine);
219 if (r < 0)
220 return r;
221 if (!machine)
222 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
223
224 p = machine_bus_path(machine);
225 if (!p)
226 return -ENOMEM;
227
228 return sd_bus_reply_method_return(message, "o", p);
229 }
230
231 static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) {
232 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
233 Manager *m = userdata;
234 Machine *machine;
235 Iterator i;
236 int r;
237
238 assert(message);
239 assert(m);
240
241 r = sd_bus_message_new_method_return(message, &reply);
242 if (r < 0)
243 return sd_bus_error_set_errno(error, r);
244
245 r = sd_bus_message_open_container(reply, 'a', "(ssso)");
246 if (r < 0)
247 return sd_bus_error_set_errno(error, r);
248
249 HASHMAP_FOREACH(machine, m->machines, i) {
250 _cleanup_free_ char *p = NULL;
251
252 p = machine_bus_path(machine);
253 if (!p)
254 return -ENOMEM;
255
256 r = sd_bus_message_append(reply, "(ssso)",
257 machine->name,
258 strempty(machine_class_to_string(machine->class)),
259 machine->service,
260 p);
261 if (r < 0)
262 return sd_bus_error_set_errno(error, r);
263 }
264
265 r = sd_bus_message_close_container(reply);
266 if (r < 0)
267 return sd_bus_error_set_errno(error, r);
268
269 return sd_bus_send(NULL, reply, NULL);
270 }
271
272 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
273 const char *name, *service, *class, *root_directory;
274 const int32_t *netif = NULL;
275 MachineClass c;
276 uint32_t leader;
277 sd_id128_t id;
278 const void *v;
279 Machine *m;
280 size_t n, n_netif = 0;
281 int r;
282
283 assert(manager);
284 assert(message);
285 assert(_m);
286
287 r = sd_bus_message_read(message, "s", &name);
288 if (r < 0)
289 return r;
290 if (!machine_name_is_valid(name))
291 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
292
293 r = sd_bus_message_read_array(message, 'y', &v, &n);
294 if (r < 0)
295 return r;
296 if (n == 0)
297 id = SD_ID128_NULL;
298 else if (n == 16)
299 memcpy(&id, v, n);
300 else
301 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
302
303 r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
304 if (r < 0)
305 return r;
306
307 if (read_network) {
308 size_t i;
309
310 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
311 if (r < 0)
312 return r;
313
314 n_netif /= sizeof(int32_t);
315
316 for (i = 0; i < n_netif; i++) {
317 if (netif[i] <= 0)
318 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
319 }
320 }
321
322 if (isempty(class))
323 c = _MACHINE_CLASS_INVALID;
324 else {
325 c = machine_class_from_string(class);
326 if (c < 0)
327 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
328 }
329
330 if (leader == 1)
331 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
332
333 if (!isempty(root_directory) && !path_is_absolute(root_directory))
334 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
335
336 if (leader == 0) {
337 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
338
339 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
340 if (r < 0)
341 return r;
342
343 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
344
345 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
346 if (r < 0)
347 return r;
348 }
349
350 if (hashmap_get(manager->machines, name))
351 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
352
353 r = manager_add_machine(manager, name, &m);
354 if (r < 0)
355 return r;
356
357 m->leader = leader;
358 m->class = c;
359 m->id = id;
360
361 if (!isempty(service)) {
362 m->service = strdup(service);
363 if (!m->service) {
364 r = -ENOMEM;
365 goto fail;
366 }
367 }
368
369 if (!isempty(root_directory)) {
370 m->root_directory = strdup(root_directory);
371 if (!m->root_directory) {
372 r = -ENOMEM;
373 goto fail;
374 }
375 }
376
377 if (n_netif > 0) {
378 assert_cc(sizeof(int32_t) == sizeof(int));
379 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
380 if (!m->netif) {
381 r = -ENOMEM;
382 goto fail;
383 }
384
385 m->n_netif = n_netif;
386 }
387
388 *_m = m;
389
390 return 1;
391
392 fail:
393 machine_add_to_gc_queue(m);
394 return r;
395 }
396
397 static int method_create_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
398 Manager *manager = userdata;
399 Machine *m = NULL;
400 int r;
401
402 assert(message);
403 assert(manager);
404
405 r = method_create_or_register_machine(manager, message, read_network, &m, error);
406 if (r < 0)
407 return r;
408
409 r = sd_bus_message_enter_container(message, 'a', "(sv)");
410 if (r < 0)
411 goto fail;
412
413 r = machine_start(m, message, error);
414 if (r < 0)
415 goto fail;
416
417 m->create_message = sd_bus_message_ref(message);
418 return 1;
419
420 fail:
421 machine_add_to_gc_queue(m);
422 return r;
423 }
424
425 static int method_create_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) {
426 return method_create_machine_internal(message, true, userdata, error);
427 }
428
429 static int method_create_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
430 return method_create_machine_internal(message, false, userdata, error);
431 }
432
433 static int method_register_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
434 Manager *manager = userdata;
435 _cleanup_free_ char *p = NULL;
436 Machine *m = NULL;
437 int r;
438
439 assert(message);
440 assert(manager);
441
442 r = method_create_or_register_machine(manager, message, read_network, &m, error);
443 if (r < 0)
444 return r;
445
446 r = cg_pid_get_unit(m->leader, &m->unit);
447 if (r < 0) {
448 r = sd_bus_error_set_errnof(error, r,
449 "Failed to determine unit of process "PID_FMT" : %m",
450 m->leader);
451 goto fail;
452 }
453
454 r = machine_start(m, NULL, error);
455 if (r < 0)
456 goto fail;
457
458 p = machine_bus_path(m);
459 if (!p) {
460 r = -ENOMEM;
461 goto fail;
462 }
463
464 return sd_bus_reply_method_return(message, "o", p);
465
466 fail:
467 machine_add_to_gc_queue(m);
468 return r;
469 }
470
471 static int method_register_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) {
472 return method_register_machine_internal(message, true, userdata, error);
473 }
474
475 static int method_register_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
476 return method_register_machine_internal(message, false, userdata, error);
477 }
478
479 static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
480 Manager *m = userdata;
481 Machine *machine;
482 const char *name;
483 int r;
484
485 assert(message);
486 assert(m);
487
488 r = sd_bus_message_read(message, "s", &name);
489 if (r < 0)
490 return sd_bus_error_set_errno(error, r);
491
492 machine = hashmap_get(m->machines, name);
493 if (!machine)
494 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
495
496 return bus_machine_method_terminate(message, machine, error);
497 }
498
499 static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
500 Manager *m = userdata;
501 Machine *machine;
502 const char *name;
503 int r;
504
505 assert(message);
506 assert(m);
507
508 r = sd_bus_message_read(message, "s", &name);
509 if (r < 0)
510 return sd_bus_error_set_errno(error, r);
511
512 machine = hashmap_get(m->machines, name);
513 if (!machine)
514 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
515
516 return bus_machine_method_kill(message, machine, error);
517 }
518
519 static int method_get_machine_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
520 Manager *m = userdata;
521 Machine *machine;
522 const char *name;
523 int r;
524
525 assert(message);
526 assert(m);
527
528 r = sd_bus_message_read(message, "s", &name);
529 if (r < 0)
530 return sd_bus_error_set_errno(error, r);
531
532 machine = hashmap_get(m->machines, name);
533 if (!machine)
534 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
535
536 return bus_machine_method_get_addresses(message, machine, error);
537 }
538
539 static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
540 Manager *m = userdata;
541 Machine *machine;
542 const char *name;
543 int r;
544
545 assert(message);
546 assert(m);
547
548 r = sd_bus_message_read(message, "s", &name);
549 if (r < 0)
550 return sd_bus_error_set_errno(error, r);
551
552 machine = hashmap_get(m->machines, name);
553 if (!machine)
554 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
555
556 return bus_machine_method_get_os_release(message, machine, error);
557 }
558
559 static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
560 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
561 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
562 Manager *m = userdata;
563 Image *image;
564 Iterator i;
565 int r;
566
567 assert(message);
568 assert(m);
569
570 images = hashmap_new(&string_hash_ops);
571 if (!images)
572 return -ENOMEM;
573
574 r = image_discover(images);
575 if (r < 0)
576 return r;
577
578 r = sd_bus_message_new_method_return(message, &reply);
579 if (r < 0)
580 return r;
581
582 r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
583 if (r < 0)
584 return r;
585
586 HASHMAP_FOREACH(image, images, i) {
587 _cleanup_free_ char *p = NULL;
588
589 p = image_bus_path(image->name);
590 if (!p)
591 return -ENOMEM;
592
593 r = sd_bus_message_append(reply, "(ssbttto)",
594 image->name,
595 image_type_to_string(image->type),
596 image->read_only,
597 image->crtime,
598 image->mtime,
599 image->usage,
600 p);
601 if (r < 0)
602 return r;
603 }
604
605 r = sd_bus_message_close_container(reply);
606 if (r < 0)
607 return r;
608
609 return sd_bus_send(NULL, reply, NULL);
610 }
611
612 static int method_open_machine_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
613 Manager *m = userdata;
614 Machine *machine;
615 const char *name;
616 int r;
617
618 assert(message);
619 assert(m);
620
621 r = sd_bus_message_read(message, "s", &name);
622 if (r < 0)
623 return sd_bus_error_set_errno(error, r);
624
625 machine = hashmap_get(m->machines, name);
626 if (!machine)
627 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
628
629 return bus_machine_method_open_pty(message, machine, error);
630 }
631
632 static int method_open_machine_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
633 Manager *m = userdata;
634 Machine *machine;
635 const char *name;
636 int r;
637
638 assert(message);
639 assert(m);
640
641 r = sd_bus_message_read(message, "s", &name);
642 if (r < 0)
643 return r;
644
645 machine = hashmap_get(m->machines, name);
646 if (!machine)
647 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
648
649 return bus_machine_method_open_login(message, machine, error);
650 }
651
652 static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
653 Manager *m = userdata;
654 Machine *machine;
655 const char *name;
656
657 int r;
658
659 assert(message);
660 assert(m);
661
662 r = sd_bus_message_read(message, "s", &name);
663 if (r < 0)
664 return r;
665
666 machine = hashmap_get(m->machines, name);
667 if (!machine)
668 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
669
670 return bus_machine_method_open_shell(message, machine, error);
671 }
672
673 static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
674 Manager *m = userdata;
675 Machine *machine;
676 const char *name;
677 int r;
678
679 assert(message);
680 assert(m);
681
682 r = sd_bus_message_read(message, "s", &name);
683 if (r < 0)
684 return r;
685
686 machine = hashmap_get(m->machines, name);
687 if (!machine)
688 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
689
690 return bus_machine_method_bind_mount(message, machine, error);
691 }
692
693 static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
694 Manager *m = userdata;
695 Machine *machine;
696 const char *name;
697 int r;
698
699 assert(message);
700 assert(m);
701
702 r = sd_bus_message_read(message, "s", &name);
703 if (r < 0)
704 return r;
705
706 machine = hashmap_get(m->machines, name);
707 if (!machine)
708 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
709
710 return bus_machine_method_copy(message, machine, error);
711 }
712
713 static int method_open_machine_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
714 Manager *m = userdata;
715 Machine *machine;
716 const char *name;
717 int r;
718
719 assert(message);
720 assert(m);
721
722 r = sd_bus_message_read(message, "s", &name);
723 if (r < 0)
724 return r;
725
726 machine = hashmap_get(m->machines, name);
727 if (!machine)
728 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
729
730 return bus_machine_method_open_root_directory(message, machine, error);
731 }
732
733 static int method_get_machine_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) {
734 Manager *m = userdata;
735 Machine *machine;
736 const char *name;
737 int r;
738
739 assert(message);
740 assert(m);
741
742 r = sd_bus_message_read(message, "s", &name);
743 if (r < 0)
744 return r;
745
746 machine = hashmap_get(m->machines, name);
747 if (!machine)
748 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
749
750 return bus_machine_method_get_uid_shift(message, machine, error);
751 }
752
753 static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
754 _cleanup_(image_unrefp) Image* i = NULL;
755 const char *name;
756 int r;
757
758 assert(message);
759
760 r = sd_bus_message_read(message, "s", &name);
761 if (r < 0)
762 return r;
763
764 if (!image_name_is_valid(name))
765 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
766
767 r = image_find(name, &i);
768 if (r < 0)
769 return r;
770 if (r == 0)
771 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
772
773 i->userdata = userdata;
774 return bus_image_method_remove(message, i, error);
775 }
776
777 static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
778 _cleanup_(image_unrefp) Image* i = NULL;
779 const char *old_name;
780 int r;
781
782 assert(message);
783
784 r = sd_bus_message_read(message, "s", &old_name);
785 if (r < 0)
786 return r;
787
788 if (!image_name_is_valid(old_name))
789 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
790
791 r = image_find(old_name, &i);
792 if (r < 0)
793 return r;
794 if (r == 0)
795 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
796
797 i->userdata = userdata;
798 return bus_image_method_rename(message, i, error);
799 }
800
801 static int method_clone_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
802 _cleanup_(image_unrefp) Image *i = NULL;
803 const char *old_name;
804 int r;
805
806 assert(message);
807
808 r = sd_bus_message_read(message, "s", &old_name);
809 if (r < 0)
810 return r;
811
812 if (!image_name_is_valid(old_name))
813 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
814
815 r = image_find(old_name, &i);
816 if (r < 0)
817 return r;
818 if (r == 0)
819 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
820
821 i->userdata = userdata;
822 return bus_image_method_clone(message, i, error);
823 }
824
825 static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) {
826 _cleanup_(image_unrefp) Image *i = NULL;
827 const char *name;
828 int r;
829
830 assert(message);
831
832 r = sd_bus_message_read(message, "s", &name);
833 if (r < 0)
834 return r;
835
836 if (!image_name_is_valid(name))
837 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
838
839 r = image_find(name, &i);
840 if (r < 0)
841 return r;
842 if (r == 0)
843 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
844
845 i->userdata = userdata;
846 return bus_image_method_mark_read_only(message, i, error);
847 }
848
849 static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
850 _cleanup_(image_unrefp) Image *i = NULL;
851 const char *name;
852 int r;
853
854 assert(message);
855
856 r = sd_bus_message_read(message, "s", &name);
857 if (r < 0)
858 return r;
859
860 if (!image_name_is_valid(name))
861 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
862
863 r = image_find(name, &i);
864 if (r < 0)
865 return r;
866 if (r == 0)
867 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
868
869 i->userdata = userdata;
870 return bus_image_method_get_os_release(message, i, error);
871 }
872
873 static int clean_pool_done(Operation *operation, int ret, sd_bus_error *error) {
874 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
875 _cleanup_fclose_ FILE *f = NULL;
876 bool success;
877 size_t n;
878 int r;
879
880 assert(operation);
881 assert(operation->extra_fd >= 0);
882
883 if (lseek(operation->extra_fd, 0, SEEK_SET) == (off_t) -1)
884 return -errno;
885
886 f = fdopen(operation->extra_fd, "re");
887 if (!f)
888 return -errno;
889
890 operation->extra_fd = -1;
891
892 /* The resulting temporary file starts with a boolean value that indicates success or not. */
893 errno = 0;
894 n = fread(&success, 1, sizeof(success), f);
895 if (n != sizeof(success))
896 return ret < 0 ? ret : (errno != 0 ? -errno : -EIO);
897
898 if (ret < 0) {
899 _cleanup_free_ char *name = NULL;
900
901 /* The clean-up operation failed. In this case the resulting temporary file should contain a boolean
902 * set to false followed by the name of the failed image. Let's try to read this and use it for the
903 * error message. If we can't read it, don't mind, and return the naked error. */
904
905 if (success) /* The resulting temporary file could not be updated, ignore it. */
906 return ret;
907
908 r = read_nul_string(f, &name);
909 if (r < 0 || isempty(name)) /* Same here... */
910 return ret;
911
912 return sd_bus_error_set_errnof(error, ret, "Failed to remove image %s: %m", name);
913 }
914
915 assert(success);
916
917 r = sd_bus_message_new_method_return(operation->message, &reply);
918 if (r < 0)
919 return r;
920
921 r = sd_bus_message_open_container(reply, 'a', "(st)");
922 if (r < 0)
923 return r;
924
925 /* On success the resulting temporary file will contain a list of image names that were removed followed by
926 * their size on disk. Let's read that and turn it into a bus message. */
927 for (;;) {
928 _cleanup_free_ char *name = NULL;
929 uint64_t size;
930
931 r = read_nul_string(f, &name);
932 if (r < 0)
933 return r;
934 if (isempty(name)) /* reached the end */
935 break;
936
937 errno = 0;
938 n = fread(&size, 1, sizeof(size), f);
939 if (n != sizeof(size))
940 return errno != 0 ? -errno : -EIO;
941
942 r = sd_bus_message_append(reply, "(st)", name, size);
943 if (r < 0)
944 return r;
945 }
946
947 r = sd_bus_message_close_container(reply);
948 if (r < 0)
949 return r;
950
951 return sd_bus_send(NULL, reply, NULL);
952 }
953
954 static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_error *error) {
955 enum {
956 REMOVE_ALL,
957 REMOVE_HIDDEN,
958 } mode;
959
960 _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
961 _cleanup_close_ int result_fd = -1;
962 Manager *m = userdata;
963 Operation *operation;
964 const char *mm;
965 pid_t child;
966 int r;
967
968 assert(message);
969
970 if (m->n_operations >= OPERATIONS_MAX)
971 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
972
973 r = sd_bus_message_read(message, "s", &mm);
974 if (r < 0)
975 return r;
976
977 if (streq(mm, "all"))
978 mode = REMOVE_ALL;
979 else if (streq(mm, "hidden"))
980 mode = REMOVE_HIDDEN;
981 else
982 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mode '%s'.", mm);
983
984 r = bus_verify_polkit_async(
985 message,
986 CAP_SYS_ADMIN,
987 "org.freedesktop.machine1.manage-machines",
988 NULL,
989 false,
990 UID_INVALID,
991 &m->polkit_registry,
992 error);
993 if (r < 0)
994 return r;
995 if (r == 0)
996 return 1; /* Will call us back */
997
998 if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
999 return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
1000
1001 /* Create a temporary file we can dump information about deleted images into. We use a temporary file for this
1002 * instead of a pipe or so, since this might grow quit large in theory and we don't want to process this
1003 * continuously */
1004 result_fd = open_tmpfile_unlinkable(NULL, O_RDWR|O_CLOEXEC);
1005 if (result_fd < 0)
1006 return -errno;
1007
1008 /* This might be a slow operation, run it asynchronously in a background process */
1009 child = fork();
1010 if (child < 0)
1011 return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
1012
1013 if (child == 0) {
1014 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
1015 bool success = true;
1016 Image *image;
1017 Iterator i;
1018 ssize_t l;
1019
1020 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
1021
1022 images = hashmap_new(&string_hash_ops);
1023 if (!images) {
1024 r = -ENOMEM;
1025 goto child_fail;
1026 }
1027
1028 r = image_discover(images);
1029 if (r < 0)
1030 goto child_fail;
1031
1032 l = write(result_fd, &success, sizeof(success));
1033 if (l < 0) {
1034 r = -errno;
1035 goto child_fail;
1036 }
1037
1038 HASHMAP_FOREACH(image, images, i) {
1039
1040 /* We can't remove vendor images (i.e. those in /usr) */
1041 if (IMAGE_IS_VENDOR(image))
1042 continue;
1043
1044 if (IMAGE_IS_HOST(image))
1045 continue;
1046
1047 if (mode == REMOVE_HIDDEN && !IMAGE_IS_HIDDEN(image))
1048 continue;
1049
1050 r = image_remove(image);
1051 if (r == -EBUSY) /* keep images that are currently being used. */
1052 continue;
1053 if (r < 0) {
1054 /* If the operation failed, let's override everything we wrote, and instead write there at which image we failed. */
1055 success = false;
1056 (void) ftruncate(result_fd, 0);
1057 (void) lseek(result_fd, 0, SEEK_SET);
1058 (void) write(result_fd, &success, sizeof(success));
1059 (void) write(result_fd, image->name, strlen(image->name)+1);
1060 goto child_fail;
1061 }
1062
1063 l = write(result_fd, image->name, strlen(image->name)+1);
1064 if (l < 0) {
1065 r = -errno;
1066 goto child_fail;
1067 }
1068
1069 l = write(result_fd, &image->usage_exclusive, sizeof(image->usage_exclusive));
1070 if (l < 0) {
1071 r = -errno;
1072 goto child_fail;
1073 }
1074 }
1075
1076 result_fd = safe_close(result_fd);
1077 _exit(EXIT_SUCCESS);
1078
1079 child_fail:
1080 (void) write(errno_pipe_fd[1], &r, sizeof(r));
1081 _exit(EXIT_FAILURE);
1082 }
1083
1084 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
1085
1086 /* The clean-up might take a while, hence install a watch on the child and return */
1087
1088 r = operation_new(m, NULL, child, message, errno_pipe_fd[0], &operation);
1089 if (r < 0) {
1090 (void) sigkill_wait(child);
1091 return r;
1092 }
1093
1094 operation->extra_fd = result_fd;
1095 operation->done = clean_pool_done;
1096
1097 result_fd = -1;
1098 errno_pipe_fd[0] = -1;
1099
1100 return 1;
1101 }
1102
1103 static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1104 Manager *m = userdata;
1105 uint64_t limit;
1106 int r;
1107
1108 assert(message);
1109
1110 r = sd_bus_message_read(message, "t", &limit);
1111 if (r < 0)
1112 return r;
1113 if (!FILE_SIZE_VALID_OR_INFINITY(limit))
1114 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
1115
1116 r = bus_verify_polkit_async(
1117 message,
1118 CAP_SYS_ADMIN,
1119 "org.freedesktop.machine1.manage-machines",
1120 NULL,
1121 false,
1122 UID_INVALID,
1123 &m->polkit_registry,
1124 error);
1125 if (r < 0)
1126 return r;
1127 if (r == 0)
1128 return 1; /* Will call us back */
1129
1130 /* Set up the machine directory if necessary */
1131 r = setup_machine_directory(limit, error);
1132 if (r < 0)
1133 return r;
1134
1135 /* Resize the backing loopback device, if there is one, except if we asked to drop any limit */
1136 if (limit != (uint64_t) -1) {
1137 r = btrfs_resize_loopback("/var/lib/machines", limit, false);
1138 if (r == -ENOTTY)
1139 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
1140 if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
1141 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
1142 }
1143
1144 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit);
1145
1146 r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit);
1147 if (r == -ENOTTY)
1148 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
1149 if (r < 0)
1150 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
1151
1152 return sd_bus_reply_method_return(message, NULL);
1153 }
1154
1155 static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1156 _cleanup_(image_unrefp) Image *i = NULL;
1157 const char *name;
1158 int r;
1159
1160 assert(message);
1161
1162 r = sd_bus_message_read(message, "s", &name);
1163 if (r < 0)
1164 return r;
1165
1166 if (!image_name_is_valid(name))
1167 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
1168
1169 r = image_find(name, &i);
1170 if (r < 0)
1171 return r;
1172 if (r == 0)
1173 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
1174
1175 i->userdata = userdata;
1176 return bus_image_method_set_limit(message, i, error);
1177 }
1178
1179 static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1180 _cleanup_fclose_ FILE *f = NULL;
1181 Manager *m = userdata;
1182 const char *name, *p;
1183 Machine *machine;
1184 uint32_t uid;
1185 int r;
1186
1187 r = sd_bus_message_read(message, "su", &name, &uid);
1188 if (r < 0)
1189 return r;
1190
1191 if (!uid_is_valid(uid))
1192 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
1193
1194 machine = hashmap_get(m->machines, name);
1195 if (!machine)
1196 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1197
1198 if (machine->class != MACHINE_CONTAINER)
1199 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
1200
1201 p = procfs_file_alloca(machine->leader, "uid_map");
1202 f = fopen(p, "re");
1203 if (!f)
1204 return -errno;
1205
1206 for (;;) {
1207 uid_t uid_base, uid_shift, uid_range, converted;
1208 int k;
1209
1210 errno = 0;
1211 k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
1212 if (k < 0 && feof(f))
1213 break;
1214 if (k != 3) {
1215 if (ferror(f) && errno > 0)
1216 return -errno;
1217
1218 return -EIO;
1219 }
1220
1221 if (uid < uid_base || uid >= uid_base + uid_range)
1222 continue;
1223
1224 converted = uid - uid_base + uid_shift;
1225 if (!uid_is_valid(converted))
1226 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
1227
1228 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
1229 }
1230
1231 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name);
1232 }
1233
1234 static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1235 Manager *m = userdata;
1236 Machine *machine;
1237 uid_t uid;
1238 Iterator i;
1239 int r;
1240
1241 r = sd_bus_message_read(message, "u", &uid);
1242 if (r < 0)
1243 return r;
1244 if (!uid_is_valid(uid))
1245 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
1246 if (uid < 0x10000)
1247 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
1248
1249 HASHMAP_FOREACH(machine, m->machines, i) {
1250 _cleanup_fclose_ FILE *f = NULL;
1251 char p[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
1252
1253 if (machine->class != MACHINE_CONTAINER)
1254 continue;
1255
1256 xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader);
1257 f = fopen(p, "re");
1258 if (!f) {
1259 log_warning_errno(errno, "Failed top open %s, ignoring,", p);
1260 continue;
1261 }
1262
1263 for (;;) {
1264 _cleanup_free_ char *o = NULL;
1265 uid_t uid_base, uid_shift, uid_range, converted;
1266 int k;
1267
1268 errno = 0;
1269 k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
1270 if (k < 0 && feof(f))
1271 break;
1272 if (k != 3) {
1273 if (ferror(f) && errno > 0)
1274 return -errno;
1275
1276 return -EIO;
1277 }
1278
1279 if (uid < uid_shift || uid >= uid_shift + uid_range)
1280 continue;
1281
1282 converted = (uid - uid_shift + uid_base);
1283 if (!uid_is_valid(converted))
1284 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
1285
1286 o = machine_bus_path(machine);
1287 if (!o)
1288 return -ENOMEM;
1289
1290 return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
1291 }
1292 }
1293
1294 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
1295 }
1296
1297 static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
1298 _cleanup_fclose_ FILE *f = NULL;
1299 Manager *m = groupdata;
1300 const char *name, *p;
1301 Machine *machine;
1302 uint32_t gid;
1303 int r;
1304
1305 r = sd_bus_message_read(message, "su", &name, &gid);
1306 if (r < 0)
1307 return r;
1308
1309 if (!gid_is_valid(gid))
1310 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1311
1312 machine = hashmap_get(m->machines, name);
1313 if (!machine)
1314 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1315
1316 if (machine->class != MACHINE_CONTAINER)
1317 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
1318
1319 p = procfs_file_alloca(machine->leader, "gid_map");
1320 f = fopen(p, "re");
1321 if (!f)
1322 return -errno;
1323
1324 for (;;) {
1325 gid_t gid_base, gid_shift, gid_range, converted;
1326 int k;
1327
1328 errno = 0;
1329 k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
1330 if (k < 0 && feof(f))
1331 break;
1332 if (k != 3) {
1333 if (ferror(f) && errno > 0)
1334 return -errno;
1335
1336 return -EIO;
1337 }
1338
1339 if (gid < gid_base || gid >= gid_base + gid_range)
1340 continue;
1341
1342 converted = gid - gid_base + gid_shift;
1343 if (!gid_is_valid(converted))
1344 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1345
1346 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
1347 }
1348
1349 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name);
1350 }
1351
1352 static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
1353 Manager *m = groupdata;
1354 Machine *machine;
1355 gid_t gid;
1356 Iterator i;
1357 int r;
1358
1359 r = sd_bus_message_read(message, "u", &gid);
1360 if (r < 0)
1361 return r;
1362 if (!gid_is_valid(gid))
1363 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1364 if (gid < 0x10000)
1365 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
1366
1367 HASHMAP_FOREACH(machine, m->machines, i) {
1368 _cleanup_fclose_ FILE *f = NULL;
1369 char p[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1];
1370
1371 if (machine->class != MACHINE_CONTAINER)
1372 continue;
1373
1374 xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader);
1375 f = fopen(p, "re");
1376 if (!f) {
1377 log_warning_errno(errno, "Failed top open %s, ignoring,", p);
1378 continue;
1379 }
1380
1381 for (;;) {
1382 _cleanup_free_ char *o = NULL;
1383 gid_t gid_base, gid_shift, gid_range, converted;
1384 int k;
1385
1386 errno = 0;
1387 k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
1388 if (k < 0 && feof(f))
1389 break;
1390 if (k != 3) {
1391 if (ferror(f) && errno > 0)
1392 return -errno;
1393
1394 return -EIO;
1395 }
1396
1397 if (gid < gid_shift || gid >= gid_shift + gid_range)
1398 continue;
1399
1400 converted = (gid - gid_shift + gid_base);
1401 if (!gid_is_valid(converted))
1402 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1403
1404 o = machine_bus_path(machine);
1405 if (!o)
1406 return -ENOMEM;
1407
1408 return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
1409 }
1410 }
1411
1412 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
1413 }
1414
1415 const sd_bus_vtable manager_vtable[] = {
1416 SD_BUS_VTABLE_START(0),
1417 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
1418 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
1419 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
1420 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1421 SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
1422 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1423 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
1424 SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
1425 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
1426 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
1427 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
1428 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
1429 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1430 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1431 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
1432 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
1433 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
1434 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
1435 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell, SD_BUS_VTABLE_UNPRIVILEGED),
1436 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1437 SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1438 SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
1439 SD_BUS_METHOD("OpenMachineRootDirectory", "s", "h", method_open_machine_root_directory, SD_BUS_VTABLE_UNPRIVILEGED),
1440 SD_BUS_METHOD("GetMachineUIDShift", "s", "u", method_get_machine_uid_shift, SD_BUS_VTABLE_UNPRIVILEGED),
1441 SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
1442 SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
1443 SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
1444 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
1445 SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
1446 SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
1447 SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
1448 SD_BUS_METHOD("CleanPool", "s", "a(st)", method_clean_pool, SD_BUS_VTABLE_UNPRIVILEGED),
1449 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
1450 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
1451 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
1452 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
1453 SD_BUS_SIGNAL("MachineNew", "so", 0),
1454 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1455 SD_BUS_VTABLE_END
1456 };
1457
1458 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1459 const char *path, *result, *unit;
1460 Manager *m = userdata;
1461 Machine *machine;
1462 uint32_t id;
1463 int r;
1464
1465 assert(message);
1466 assert(m);
1467
1468 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
1469 if (r < 0) {
1470 bus_log_parse_error(r);
1471 return 0;
1472 }
1473
1474 machine = hashmap_get(m->machine_units, unit);
1475 if (!machine)
1476 return 0;
1477
1478 if (streq_ptr(path, machine->scope_job)) {
1479 machine->scope_job = mfree(machine->scope_job);
1480
1481 if (machine->started) {
1482 if (streq(result, "done"))
1483 machine_send_create_reply(machine, NULL);
1484 else {
1485 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
1486
1487 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
1488
1489 machine_send_create_reply(machine, &e);
1490 }
1491 }
1492
1493 machine_save(machine);
1494 }
1495
1496 machine_add_to_gc_queue(machine);
1497 return 0;
1498 }
1499
1500 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1501 _cleanup_free_ char *unit = NULL;
1502 const char *path;
1503 Manager *m = userdata;
1504 Machine *machine;
1505 int r;
1506
1507 assert(message);
1508 assert(m);
1509
1510 path = sd_bus_message_get_path(message);
1511 if (!path)
1512 return 0;
1513
1514 r = unit_name_from_dbus_path(path, &unit);
1515 if (r == -EINVAL) /* not for a unit */
1516 return 0;
1517 if (r < 0) {
1518 log_oom();
1519 return 0;
1520 }
1521
1522 machine = hashmap_get(m->machine_units, unit);
1523 if (!machine)
1524 return 0;
1525
1526 machine_add_to_gc_queue(machine);
1527 return 0;
1528 }
1529
1530 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1531 const char *path, *unit;
1532 Manager *m = userdata;
1533 Machine *machine;
1534 int r;
1535
1536 assert(message);
1537 assert(m);
1538
1539 r = sd_bus_message_read(message, "so", &unit, &path);
1540 if (r < 0) {
1541 bus_log_parse_error(r);
1542 return 0;
1543 }
1544
1545 machine = hashmap_get(m->machine_units, unit);
1546 if (!machine)
1547 return 0;
1548
1549 machine_add_to_gc_queue(machine);
1550 return 0;
1551 }
1552
1553 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1554 Manager *m = userdata;
1555 Machine *machine;
1556 Iterator i;
1557 int b, r;
1558
1559 assert(message);
1560 assert(m);
1561
1562 r = sd_bus_message_read(message, "b", &b);
1563 if (r < 0) {
1564 bus_log_parse_error(r);
1565 return 0;
1566 }
1567 if (b)
1568 return 0;
1569
1570 /* systemd finished reloading, let's recheck all our machines */
1571 log_debug("System manager has been reloaded, rechecking machines...");
1572
1573 HASHMAP_FOREACH(machine, m->machines, i)
1574 machine_add_to_gc_queue(machine);
1575
1576 return 0;
1577 }
1578
1579 int manager_start_scope(
1580 Manager *manager,
1581 const char *scope,
1582 pid_t pid,
1583 const char *slice,
1584 const char *description,
1585 sd_bus_message *more_properties,
1586 sd_bus_error *error,
1587 char **job) {
1588
1589 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1590 int r;
1591
1592 assert(manager);
1593 assert(scope);
1594 assert(pid > 1);
1595
1596 r = sd_bus_message_new_method_call(
1597 manager->bus,
1598 &m,
1599 "org.freedesktop.systemd1",
1600 "/org/freedesktop/systemd1",
1601 "org.freedesktop.systemd1.Manager",
1602 "StartTransientUnit");
1603 if (r < 0)
1604 return r;
1605
1606 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
1607 if (r < 0)
1608 return r;
1609
1610 r = sd_bus_message_open_container(m, 'a', "(sv)");
1611 if (r < 0)
1612 return r;
1613
1614 if (!isempty(slice)) {
1615 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
1616 if (r < 0)
1617 return r;
1618 }
1619
1620 if (!isempty(description)) {
1621 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
1622 if (r < 0)
1623 return r;
1624 }
1625
1626 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
1627 if (r < 0)
1628 return r;
1629
1630 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
1631 if (r < 0)
1632 return r;
1633
1634 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", UINT64_C(16384));
1635 if (r < 0)
1636 return bus_log_create_error(r);
1637
1638 if (more_properties) {
1639 r = sd_bus_message_copy(m, more_properties, true);
1640 if (r < 0)
1641 return r;
1642 }
1643
1644 r = sd_bus_message_close_container(m);
1645 if (r < 0)
1646 return r;
1647
1648 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1649 if (r < 0)
1650 return r;
1651
1652 r = sd_bus_call(manager->bus, m, 0, error, &reply);
1653 if (r < 0)
1654 return r;
1655
1656 if (job) {
1657 const char *j;
1658 char *copy;
1659
1660 r = sd_bus_message_read(reply, "o", &j);
1661 if (r < 0)
1662 return r;
1663
1664 copy = strdup(j);
1665 if (!copy)
1666 return -ENOMEM;
1667
1668 *job = copy;
1669 }
1670
1671 return 1;
1672 }
1673
1674 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1675 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1676 int r;
1677
1678 assert(manager);
1679 assert(unit);
1680
1681 r = sd_bus_call_method(
1682 manager->bus,
1683 "org.freedesktop.systemd1",
1684 "/org/freedesktop/systemd1",
1685 "org.freedesktop.systemd1.Manager",
1686 "StopUnit",
1687 error,
1688 &reply,
1689 "ss", unit, "fail");
1690 if (r < 0) {
1691 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1692 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1693
1694 if (job)
1695 *job = NULL;
1696
1697 sd_bus_error_free(error);
1698 return 0;
1699 }
1700
1701 return r;
1702 }
1703
1704 if (job) {
1705 const char *j;
1706 char *copy;
1707
1708 r = sd_bus_message_read(reply, "o", &j);
1709 if (r < 0)
1710 return r;
1711
1712 copy = strdup(j);
1713 if (!copy)
1714 return -ENOMEM;
1715
1716 *job = copy;
1717 }
1718
1719 return 1;
1720 }
1721
1722 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1723 assert(manager);
1724 assert(unit);
1725
1726 return sd_bus_call_method(
1727 manager->bus,
1728 "org.freedesktop.systemd1",
1729 "/org/freedesktop/systemd1",
1730 "org.freedesktop.systemd1.Manager",
1731 "KillUnit",
1732 error,
1733 NULL,
1734 "ssi", unit, "all", signo);
1735 }
1736
1737 int manager_unit_is_active(Manager *manager, const char *unit) {
1738 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1739 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1740 _cleanup_free_ char *path = NULL;
1741 const char *state;
1742 int r;
1743
1744 assert(manager);
1745 assert(unit);
1746
1747 path = unit_dbus_path_from_name(unit);
1748 if (!path)
1749 return -ENOMEM;
1750
1751 r = sd_bus_get_property(
1752 manager->bus,
1753 "org.freedesktop.systemd1",
1754 path,
1755 "org.freedesktop.systemd1.Unit",
1756 "ActiveState",
1757 &error,
1758 &reply,
1759 "s");
1760 if (r < 0) {
1761 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1762 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1763 return true;
1764
1765 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1766 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1767 return false;
1768
1769 return r;
1770 }
1771
1772 r = sd_bus_message_read(reply, "s", &state);
1773 if (r < 0)
1774 return -EINVAL;
1775
1776 return !STR_IN_SET(state, "inactive", "failed");
1777 }
1778
1779 int manager_job_is_active(Manager *manager, const char *path) {
1780 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1781 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1782 int r;
1783
1784 assert(manager);
1785 assert(path);
1786
1787 r = sd_bus_get_property(
1788 manager->bus,
1789 "org.freedesktop.systemd1",
1790 path,
1791 "org.freedesktop.systemd1.Job",
1792 "State",
1793 &error,
1794 &reply,
1795 "s");
1796 if (r < 0) {
1797 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1798 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1799 return true;
1800
1801 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1802 return false;
1803
1804 return r;
1805 }
1806
1807 /* We don't actually care about the state really. The fact
1808 * that we could read the job state is enough for us */
1809
1810 return true;
1811 }
1812
1813 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1814 Machine *mm;
1815 int r;
1816
1817 assert(m);
1818 assert(pid >= 1);
1819 assert(machine);
1820
1821 mm = hashmap_get(m->machine_leaders, PID_TO_PTR(pid));
1822 if (!mm) {
1823 _cleanup_free_ char *unit = NULL;
1824
1825 r = cg_pid_get_unit(pid, &unit);
1826 if (r >= 0)
1827 mm = hashmap_get(m->machine_units, unit);
1828 }
1829 if (!mm)
1830 return 0;
1831
1832 *machine = mm;
1833 return 1;
1834 }
1835
1836 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1837 Machine *machine;
1838
1839 assert(m);
1840 assert(name);
1841
1842 machine = hashmap_get(m->machines, name);
1843 if (!machine) {
1844 machine = machine_new(m, _MACHINE_CLASS_INVALID, name);
1845 if (!machine)
1846 return -ENOMEM;
1847 }
1848
1849 if (_machine)
1850 *_machine = machine;
1851
1852 return 0;
1853 }
1854
1855 int bus_reply_pair_array(sd_bus_message *m, char **l) {
1856 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1857 char **k, **v;
1858 int r;
1859
1860 r = sd_bus_message_new_method_return(m, &reply);
1861 if (r < 0)
1862 return r;
1863
1864 r = sd_bus_message_open_container(reply, 'a', "{ss}");
1865 if (r < 0)
1866 return r;
1867
1868 STRV_FOREACH_PAIR(k, v, l) {
1869 r = sd_bus_message_append(reply, "{ss}", *k, *v);
1870 if (r < 0)
1871 return r;
1872 }
1873
1874 r = sd_bus_message_close_container(reply);
1875 if (r < 0)
1876 return r;
1877
1878 return sd_bus_send(NULL, reply, NULL);
1879
1880 }