1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
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.
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.
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/>.
27 #include "alloc-util.h"
28 #include "btrfs-util.h"
29 #include "bus-common-errors.h"
31 #include "cgroup-util.h"
34 #include "format-util.h"
35 #include "hostname-util.h"
36 #include "image-dbus.h"
38 #include "machine-dbus.h"
39 #include "machine-image.h"
40 #include "machine-pool.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 #include "stdio-util.h"
46 #include "unit-name.h"
47 #include "user-util.h"
49 static int property_get_pool_path(
52 const char *interface
,
54 sd_bus_message
*reply
,
56 sd_bus_error
*error
) {
61 return sd_bus_message_append(reply
, "s", "/var/lib/machines");
64 static int property_get_pool_usage(
67 const char *interface
,
69 sd_bus_message
*reply
,
71 sd_bus_error
*error
) {
73 _cleanup_close_
int fd
= -1;
74 uint64_t usage
= (uint64_t) -1;
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. */
84 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
88 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
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;
97 return sd_bus_message_append(reply
, "t", usage
);
100 static int property_get_pool_limit(
103 const char *interface
,
104 const char *property
,
105 sd_bus_message
*reply
,
107 sd_bus_error
*error
) {
109 _cleanup_close_
int fd
= -1;
110 uint64_t size
= (uint64_t) -1;
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. */
120 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
124 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
125 size
= q
.referenced_max
;
128 if (stat("/var/lib/machines.raw", &st
) >= 0) {
129 if (size
== (uint64_t) -1 || (uint64_t) st
.st_size
< size
)
133 return sd_bus_message_append(reply
, "t", size
);
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
;
146 r
= sd_bus_message_read(message
, "s", &name
);
150 machine
= hashmap_get(m
->machines
, name
);
152 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
154 p
= machine_bus_path(machine
);
158 return sd_bus_reply_method_return(message
, "o", p
);
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
;
170 r
= sd_bus_message_read(message
, "s", &name
);
174 r
= image_find(name
, NULL
);
176 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
180 p
= image_bus_path(name
);
184 return sd_bus_reply_method_return(message
, "o", p
);
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
;
197 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
199 r
= sd_bus_message_read(message
, "u", &pid
);
207 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
209 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
213 r
= sd_bus_creds_get_pid(creds
, &pid
);
218 r
= manager_get_machine_by_pid(m
, pid
, &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
);
224 p
= machine_bus_path(machine
);
228 return sd_bus_reply_method_return(message
, "o", p
);
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
;
241 r
= sd_bus_message_new_method_return(message
, &reply
);
243 return sd_bus_error_set_errno(error
, r
);
245 r
= sd_bus_message_open_container(reply
, 'a', "(ssso)");
247 return sd_bus_error_set_errno(error
, r
);
249 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
250 _cleanup_free_
char *p
= NULL
;
252 p
= machine_bus_path(machine
);
256 r
= sd_bus_message_append(reply
, "(ssso)",
258 strempty(machine_class_to_string(machine
->class)),
262 return sd_bus_error_set_errno(error
, r
);
265 r
= sd_bus_message_close_container(reply
);
267 return sd_bus_error_set_errno(error
, r
);
269 return sd_bus_send(NULL
, reply
, NULL
);
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
;
280 size_t n
, n_netif
= 0;
287 r
= sd_bus_message_read(message
, "s", &name
);
290 if (!machine_name_is_valid(name
))
291 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine name");
293 r
= sd_bus_message_read_array(message
, 'y', &v
, &n
);
301 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine ID parameter");
303 r
= sd_bus_message_read(message
, "ssus", &service
, &class, &leader
, &root_directory
);
310 r
= sd_bus_message_read_array(message
, 'i', (const void**) &netif
, &n_netif
);
314 n_netif
/= sizeof(int32_t);
316 for (i
= 0; i
< n_netif
; i
++) {
318 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid network interface index %i", netif
[i
]);
323 c
= _MACHINE_CLASS_INVALID
;
325 c
= machine_class_from_string(class);
327 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine class parameter");
331 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
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");
337 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
339 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
343 assert_cc(sizeof(uint32_t) == sizeof(pid_t
));
345 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
350 if (hashmap_get(manager
->machines
, name
))
351 return sd_bus_error_setf(error
, BUS_ERROR_MACHINE_EXISTS
, "Machine '%s' already exists", name
);
353 r
= manager_add_machine(manager
, name
, &m
);
361 if (!isempty(service
)) {
362 m
->service
= strdup(service
);
369 if (!isempty(root_directory
)) {
370 m
->root_directory
= strdup(root_directory
);
371 if (!m
->root_directory
) {
378 assert_cc(sizeof(int32_t) == sizeof(int));
379 m
->netif
= memdup(netif
, sizeof(int32_t) * n_netif
);
385 m
->n_netif
= n_netif
;
393 machine_add_to_gc_queue(m
);
397 static int method_create_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
398 Manager
*manager
= userdata
;
405 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
409 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
413 r
= machine_start(m
, message
, error
);
417 m
->create_message
= sd_bus_message_ref(message
);
421 machine_add_to_gc_queue(m
);
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
);
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
);
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
;
442 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
446 r
= cg_pid_get_unit(m
->leader
, &m
->unit
);
448 r
= sd_bus_error_set_errnof(error
, r
,
449 "Failed to determine unit of process "PID_FMT
" : %m",
454 r
= machine_start(m
, NULL
, error
);
458 p
= machine_bus_path(m
);
464 return sd_bus_reply_method_return(message
, "o", p
);
467 machine_add_to_gc_queue(m
);
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
);
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
);
479 static int method_terminate_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
480 Manager
*m
= userdata
;
488 r
= sd_bus_message_read(message
, "s", &name
);
490 return sd_bus_error_set_errno(error
, r
);
492 machine
= hashmap_get(m
->machines
, name
);
494 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
496 return bus_machine_method_terminate(message
, machine
, error
);
499 static int method_kill_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
500 Manager
*m
= userdata
;
508 r
= sd_bus_message_read(message
, "s", &name
);
510 return sd_bus_error_set_errno(error
, r
);
512 machine
= hashmap_get(m
->machines
, name
);
514 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
516 return bus_machine_method_kill(message
, machine
, error
);
519 static int method_get_machine_addresses(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
520 Manager
*m
= userdata
;
528 r
= sd_bus_message_read(message
, "s", &name
);
530 return sd_bus_error_set_errno(error
, r
);
532 machine
= hashmap_get(m
->machines
, name
);
534 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
536 return bus_machine_method_get_addresses(message
, machine
, error
);
539 static int method_get_machine_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
540 Manager
*m
= userdata
;
548 r
= sd_bus_message_read(message
, "s", &name
);
550 return sd_bus_error_set_errno(error
, r
);
552 machine
= hashmap_get(m
->machines
, name
);
554 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
556 return bus_machine_method_get_os_release(message
, machine
, error
);
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
;
570 images
= hashmap_new(&string_hash_ops
);
574 r
= image_discover(images
);
578 r
= sd_bus_message_new_method_return(message
, &reply
);
582 r
= sd_bus_message_open_container(reply
, 'a', "(ssbttto)");
586 HASHMAP_FOREACH(image
, images
, i
) {
587 _cleanup_free_
char *p
= NULL
;
589 p
= image_bus_path(image
->name
);
593 r
= sd_bus_message_append(reply
, "(ssbttto)",
595 image_type_to_string(image
->type
),
605 r
= sd_bus_message_close_container(reply
);
609 return sd_bus_send(NULL
, reply
, NULL
);
612 static int method_open_machine_pty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
613 Manager
*m
= userdata
;
621 r
= sd_bus_message_read(message
, "s", &name
);
623 return sd_bus_error_set_errno(error
, r
);
625 machine
= hashmap_get(m
->machines
, name
);
627 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
629 return bus_machine_method_open_pty(message
, machine
, error
);
632 static int method_open_machine_login(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
633 Manager
*m
= userdata
;
641 r
= sd_bus_message_read(message
, "s", &name
);
645 machine
= hashmap_get(m
->machines
, name
);
647 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
649 return bus_machine_method_open_login(message
, machine
, error
);
652 static int method_open_machine_shell(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
653 Manager
*m
= userdata
;
662 r
= sd_bus_message_read(message
, "s", &name
);
666 machine
= hashmap_get(m
->machines
, name
);
668 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
670 return bus_machine_method_open_shell(message
, machine
, error
);
673 static int method_bind_mount_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
674 Manager
*m
= userdata
;
682 r
= sd_bus_message_read(message
, "s", &name
);
686 machine
= hashmap_get(m
->machines
, name
);
688 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
690 return bus_machine_method_bind_mount(message
, machine
, error
);
693 static int method_copy_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
694 Manager
*m
= userdata
;
702 r
= sd_bus_message_read(message
, "s", &name
);
706 machine
= hashmap_get(m
->machines
, name
);
708 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
710 return bus_machine_method_copy(message
, machine
, error
);
713 static int method_open_machine_root_directory(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
714 Manager
*m
= userdata
;
722 r
= sd_bus_message_read(message
, "s", &name
);
726 machine
= hashmap_get(m
->machines
, name
);
728 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
730 return bus_machine_method_open_root_directory(message
, machine
, error
);
733 static int method_get_machine_uid_shift(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
734 Manager
*m
= userdata
;
742 r
= sd_bus_message_read(message
, "s", &name
);
746 machine
= hashmap_get(m
->machines
, name
);
748 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
750 return bus_machine_method_get_uid_shift(message
, machine
, error
);
753 static int method_remove_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
754 _cleanup_(image_unrefp
) Image
* i
= NULL
;
760 r
= sd_bus_message_read(message
, "s", &name
);
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
);
767 r
= image_find(name
, &i
);
771 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
773 i
->userdata
= userdata
;
774 return bus_image_method_remove(message
, i
, error
);
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
;
784 r
= sd_bus_message_read(message
, "s", &old_name
);
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
);
791 r
= image_find(old_name
, &i
);
795 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", old_name
);
797 i
->userdata
= userdata
;
798 return bus_image_method_rename(message
, i
, error
);
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
;
808 r
= sd_bus_message_read(message
, "s", &old_name
);
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
);
815 r
= image_find(old_name
, &i
);
819 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", old_name
);
821 i
->userdata
= userdata
;
822 return bus_image_method_clone(message
, i
, error
);
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
;
832 r
= sd_bus_message_read(message
, "s", &name
);
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
);
839 r
= image_find(name
, &i
);
843 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
845 i
->userdata
= userdata
;
846 return bus_image_method_mark_read_only(message
, i
, error
);
849 static int method_get_image_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
850 _cleanup_(image_unrefp
) Image
*i
= NULL
;
856 r
= sd_bus_message_read(message
, "s", &name
);
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
);
863 r
= image_find(name
, &i
);
867 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
869 i
->userdata
= userdata
;
870 return bus_image_method_get_hostname(message
, i
, error
);
873 static int method_get_image_machine_id(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
874 _cleanup_(image_unrefp
) Image
*i
= NULL
;
880 r
= sd_bus_message_read(message
, "s", &name
);
884 if (!image_name_is_valid(name
))
885 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
887 r
= image_find(name
, &i
);
891 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
893 i
->userdata
= userdata
;
894 return bus_image_method_get_machine_id(message
, i
, error
);
897 static int method_get_image_machine_info(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
898 _cleanup_(image_unrefp
) Image
*i
= NULL
;
904 r
= sd_bus_message_read(message
, "s", &name
);
908 if (!image_name_is_valid(name
))
909 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
911 r
= image_find(name
, &i
);
915 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
917 i
->userdata
= userdata
;
918 return bus_image_method_get_machine_info(message
, i
, error
);
921 static int method_get_image_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
922 _cleanup_(image_unrefp
) Image
*i
= NULL
;
928 r
= sd_bus_message_read(message
, "s", &name
);
932 if (!image_name_is_valid(name
))
933 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
935 r
= image_find(name
, &i
);
939 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
941 i
->userdata
= userdata
;
942 return bus_image_method_get_os_release(message
, i
, error
);
945 static int clean_pool_done(Operation
*operation
, int ret
, sd_bus_error
*error
) {
946 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
947 _cleanup_fclose_
FILE *f
= NULL
;
953 assert(operation
->extra_fd
>= 0);
955 if (lseek(operation
->extra_fd
, 0, SEEK_SET
) == (off_t
) -1)
958 f
= fdopen(operation
->extra_fd
, "re");
962 operation
->extra_fd
= -1;
964 /* The resulting temporary file starts with a boolean value that indicates success or not. */
966 n
= fread(&success
, 1, sizeof(success
), f
);
967 if (n
!= sizeof(success
))
968 return ret
< 0 ? ret
: (errno
!= 0 ? -errno
: -EIO
);
971 _cleanup_free_
char *name
= NULL
;
973 /* The clean-up operation failed. In this case the resulting temporary file should contain a boolean
974 * set to false followed by the name of the failed image. Let's try to read this and use it for the
975 * error message. If we can't read it, don't mind, and return the naked error. */
977 if (success
) /* The resulting temporary file could not be updated, ignore it. */
980 r
= read_nul_string(f
, &name
);
981 if (r
< 0 || isempty(name
)) /* Same here... */
984 return sd_bus_error_set_errnof(error
, ret
, "Failed to remove image %s: %m", name
);
989 r
= sd_bus_message_new_method_return(operation
->message
, &reply
);
993 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
997 /* On success the resulting temporary file will contain a list of image names that were removed followed by
998 * their size on disk. Let's read that and turn it into a bus message. */
1000 _cleanup_free_
char *name
= NULL
;
1003 r
= read_nul_string(f
, &name
);
1006 if (isempty(name
)) /* reached the end */
1010 n
= fread(&size
, 1, sizeof(size
), f
);
1011 if (n
!= sizeof(size
))
1012 return errno
!= 0 ? -errno
: -EIO
;
1014 r
= sd_bus_message_append(reply
, "(st)", name
, size
);
1019 r
= sd_bus_message_close_container(reply
);
1023 return sd_bus_send(NULL
, reply
, NULL
);
1026 static int method_clean_pool(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1032 _cleanup_close_pair_
int errno_pipe_fd
[2] = { -1, -1 };
1033 _cleanup_close_
int result_fd
= -1;
1034 Manager
*m
= userdata
;
1035 Operation
*operation
;
1042 if (m
->n_operations
>= OPERATIONS_MAX
)
1043 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Too many ongoing operations.");
1045 r
= sd_bus_message_read(message
, "s", &mm
);
1049 if (streq(mm
, "all"))
1051 else if (streq(mm
, "hidden"))
1052 mode
= REMOVE_HIDDEN
;
1054 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mode '%s'.", mm
);
1056 r
= bus_verify_polkit_async(
1059 "org.freedesktop.machine1.manage-machines",
1063 &m
->polkit_registry
,
1068 return 1; /* Will call us back */
1070 if (pipe2(errno_pipe_fd
, O_CLOEXEC
|O_NONBLOCK
) < 0)
1071 return sd_bus_error_set_errnof(error
, errno
, "Failed to create pipe: %m");
1073 /* Create a temporary file we can dump information about deleted images into. We use a temporary file for this
1074 * instead of a pipe or so, since this might grow quit large in theory and we don't want to process this
1076 result_fd
= open_tmpfile_unlinkable(NULL
, O_RDWR
|O_CLOEXEC
);
1080 /* This might be a slow operation, run it asynchronously in a background process */
1083 return sd_bus_error_set_errnof(error
, errno
, "Failed to fork(): %m");
1086 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
1087 bool success
= true;
1092 errno_pipe_fd
[0] = safe_close(errno_pipe_fd
[0]);
1094 images
= hashmap_new(&string_hash_ops
);
1100 r
= image_discover(images
);
1104 l
= write(result_fd
, &success
, sizeof(success
));
1110 HASHMAP_FOREACH(image
, images
, i
) {
1112 /* We can't remove vendor images (i.e. those in /usr) */
1113 if (IMAGE_IS_VENDOR(image
))
1116 if (IMAGE_IS_HOST(image
))
1119 if (mode
== REMOVE_HIDDEN
&& !IMAGE_IS_HIDDEN(image
))
1122 r
= image_remove(image
);
1123 if (r
== -EBUSY
) /* keep images that are currently being used. */
1126 /* If the operation failed, let's override everything we wrote, and instead write there at which image we failed. */
1128 (void) ftruncate(result_fd
, 0);
1129 (void) lseek(result_fd
, 0, SEEK_SET
);
1130 (void) write(result_fd
, &success
, sizeof(success
));
1131 (void) write(result_fd
, image
->name
, strlen(image
->name
)+1);
1135 l
= write(result_fd
, image
->name
, strlen(image
->name
)+1);
1141 l
= write(result_fd
, &image
->usage_exclusive
, sizeof(image
->usage_exclusive
));
1148 result_fd
= safe_close(result_fd
);
1149 _exit(EXIT_SUCCESS
);
1152 (void) write(errno_pipe_fd
[1], &r
, sizeof(r
));
1153 _exit(EXIT_FAILURE
);
1156 errno_pipe_fd
[1] = safe_close(errno_pipe_fd
[1]);
1158 /* The clean-up might take a while, hence install a watch on the child and return */
1160 r
= operation_new(m
, NULL
, child
, message
, errno_pipe_fd
[0], &operation
);
1162 (void) sigkill_wait(child
);
1166 operation
->extra_fd
= result_fd
;
1167 operation
->done
= clean_pool_done
;
1170 errno_pipe_fd
[0] = -1;
1175 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1176 Manager
*m
= userdata
;
1182 r
= sd_bus_message_read(message
, "t", &limit
);
1185 if (!FILE_SIZE_VALID_OR_INFINITY(limit
))
1186 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "New limit out of range");
1188 r
= bus_verify_polkit_async(
1191 "org.freedesktop.machine1.manage-machines",
1195 &m
->polkit_registry
,
1200 return 1; /* Will call us back */
1202 /* Set up the machine directory if necessary */
1203 r
= setup_machine_directory(limit
, error
);
1207 /* Resize the backing loopback device, if there is one, except if we asked to drop any limit */
1208 if (limit
!= (uint64_t) -1) {
1209 r
= btrfs_resize_loopback("/var/lib/machines", limit
, false);
1211 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
1212 if (r
< 0 && r
!= -ENODEV
) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
1213 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust loopback limit: %m");
1216 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit
);
1218 r
= btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit
);
1220 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
1222 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
1224 return sd_bus_reply_method_return(message
, NULL
);
1227 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1228 _cleanup_(image_unrefp
) Image
*i
= NULL
;
1234 r
= sd_bus_message_read(message
, "s", &name
);
1238 if (!image_name_is_valid(name
))
1239 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
1241 r
= image_find(name
, &i
);
1245 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
1247 i
->userdata
= userdata
;
1248 return bus_image_method_set_limit(message
, i
, error
);
1251 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1252 _cleanup_fclose_
FILE *f
= NULL
;
1253 Manager
*m
= userdata
;
1254 const char *name
, *p
;
1259 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
1263 if (!uid_is_valid(uid
))
1264 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1266 machine
= hashmap_get(m
->machines
, name
);
1268 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1270 if (machine
->class != MACHINE_CONTAINER
)
1271 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1273 p
= procfs_file_alloca(machine
->leader
, "uid_map");
1279 uid_t uid_base
, uid_shift
, uid_range
, converted
;
1283 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
1284 if (k
< 0 && feof(f
))
1287 if (ferror(f
) && errno
> 0)
1293 if (uid
< uid_base
|| uid
>= uid_base
+ uid_range
)
1296 converted
= uid
- uid_base
+ uid_shift
;
1297 if (!uid_is_valid(converted
))
1298 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1300 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1303 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
1306 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1307 Manager
*m
= userdata
;
1313 r
= sd_bus_message_read(message
, "u", &uid
);
1316 if (!uid_is_valid(uid
))
1317 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1319 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
1321 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1322 _cleanup_fclose_
FILE *f
= NULL
;
1323 char p
[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1325 if (machine
->class != MACHINE_CONTAINER
)
1328 xsprintf(p
, "/proc/" UID_FMT
"/uid_map", machine
->leader
);
1331 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1336 _cleanup_free_
char *o
= NULL
;
1337 uid_t uid_base
, uid_shift
, uid_range
, converted
;
1341 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
1342 if (k
< 0 && feof(f
))
1345 if (ferror(f
) && errno
> 0)
1351 if (uid
< uid_shift
|| uid
>= uid_shift
+ uid_range
)
1354 converted
= (uid
- uid_shift
+ uid_base
);
1355 if (!uid_is_valid(converted
))
1356 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1358 o
= machine_bus_path(machine
);
1362 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1366 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
1369 static int method_map_from_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1370 _cleanup_fclose_
FILE *f
= NULL
;
1371 Manager
*m
= groupdata
;
1372 const char *name
, *p
;
1377 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
1381 if (!gid_is_valid(gid
))
1382 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1384 machine
= hashmap_get(m
->machines
, name
);
1386 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1388 if (machine
->class != MACHINE_CONTAINER
)
1389 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1391 p
= procfs_file_alloca(machine
->leader
, "gid_map");
1397 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1401 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1402 if (k
< 0 && feof(f
))
1405 if (ferror(f
) && errno
> 0)
1411 if (gid
< gid_base
|| gid
>= gid_base
+ gid_range
)
1414 converted
= gid
- gid_base
+ gid_shift
;
1415 if (!gid_is_valid(converted
))
1416 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1418 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1421 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1424 static int method_map_to_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1425 Manager
*m
= groupdata
;
1431 r
= sd_bus_message_read(message
, "u", &gid
);
1434 if (!gid_is_valid(gid
))
1435 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1437 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1439 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1440 _cleanup_fclose_
FILE *f
= NULL
;
1441 char p
[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1443 if (machine
->class != MACHINE_CONTAINER
)
1446 xsprintf(p
, "/proc/" GID_FMT
"/gid_map", machine
->leader
);
1449 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1454 _cleanup_free_
char *o
= NULL
;
1455 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1459 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1460 if (k
< 0 && feof(f
))
1463 if (ferror(f
) && errno
> 0)
1469 if (gid
< gid_shift
|| gid
>= gid_shift
+ gid_range
)
1472 converted
= (gid
- gid_shift
+ gid_base
);
1473 if (!gid_is_valid(converted
))
1474 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1476 o
= machine_bus_path(machine
);
1480 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1484 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1487 const sd_bus_vtable manager_vtable
[] = {
1488 SD_BUS_VTABLE_START(0),
1489 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1490 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1491 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1492 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1493 SD_BUS_METHOD("GetImage", "s", "o", method_get_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1494 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
1495 SD_BUS_METHOD("ListMachines", NULL
, "a(ssso)", method_list_machines
, SD_BUS_VTABLE_UNPRIVILEGED
),
1496 SD_BUS_METHOD("ListImages", NULL
, "a(ssbttto)", method_list_images
, SD_BUS_VTABLE_UNPRIVILEGED
),
1497 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine
, 0),
1498 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network
, 0),
1499 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine
, 0),
1500 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network
, 0),
1501 SD_BUS_METHOD("TerminateMachine", "s", NULL
, method_terminate_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1502 SD_BUS_METHOD("KillMachine", "ssi", NULL
, method_kill_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1503 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses
, SD_BUS_VTABLE_UNPRIVILEGED
),
1504 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1505 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty
, 0),
1506 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login
, SD_BUS_VTABLE_UNPRIVILEGED
),
1507 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell
, SD_BUS_VTABLE_UNPRIVILEGED
),
1508 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL
, method_bind_mount_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1509 SD_BUS_METHOD("CopyFromMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1510 SD_BUS_METHOD("CopyToMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1511 SD_BUS_METHOD("OpenMachineRootDirectory", "s", "h", method_open_machine_root_directory
, SD_BUS_VTABLE_UNPRIVILEGED
),
1512 SD_BUS_METHOD("GetMachineUIDShift", "s", "u", method_get_machine_uid_shift
, SD_BUS_VTABLE_UNPRIVILEGED
),
1513 SD_BUS_METHOD("RemoveImage", "s", NULL
, method_remove_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1514 SD_BUS_METHOD("RenameImage", "ss", NULL
, method_rename_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1515 SD_BUS_METHOD("CloneImage", "ssb", NULL
, method_clone_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1516 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL
, method_mark_image_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
1517 SD_BUS_METHOD("GetImageHostname", "s", "s", method_get_image_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1518 SD_BUS_METHOD("GetImageMachineID", "s", "ay", method_get_image_machine_id
, SD_BUS_VTABLE_UNPRIVILEGED
),
1519 SD_BUS_METHOD("GetImageMachineInfo", "s", "a{ss}", method_get_image_machine_info
, SD_BUS_VTABLE_UNPRIVILEGED
),
1520 SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1521 SD_BUS_METHOD("SetPoolLimit", "t", NULL
, method_set_pool_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1522 SD_BUS_METHOD("SetImageLimit", "st", NULL
, method_set_image_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1523 SD_BUS_METHOD("CleanPool", "s", "a(st)", method_clean_pool
, SD_BUS_VTABLE_UNPRIVILEGED
),
1524 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1525 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1526 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1527 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1528 SD_BUS_SIGNAL("MachineNew", "so", 0),
1529 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1533 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1534 const char *path
, *result
, *unit
;
1535 Manager
*m
= userdata
;
1543 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1545 bus_log_parse_error(r
);
1549 machine
= hashmap_get(m
->machine_units
, unit
);
1553 if (streq_ptr(path
, machine
->scope_job
)) {
1554 machine
->scope_job
= mfree(machine
->scope_job
);
1556 if (machine
->started
) {
1557 if (streq(result
, "done"))
1558 machine_send_create_reply(machine
, NULL
);
1560 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
1562 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1564 machine_send_create_reply(machine
, &e
);
1568 machine_save(machine
);
1571 machine_add_to_gc_queue(machine
);
1575 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1576 _cleanup_free_
char *unit
= NULL
;
1578 Manager
*m
= userdata
;
1585 path
= sd_bus_message_get_path(message
);
1589 r
= unit_name_from_dbus_path(path
, &unit
);
1590 if (r
== -EINVAL
) /* not for a unit */
1597 machine
= hashmap_get(m
->machine_units
, unit
);
1601 machine_add_to_gc_queue(machine
);
1605 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1606 const char *path
, *unit
;
1607 Manager
*m
= userdata
;
1614 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1616 bus_log_parse_error(r
);
1620 machine
= hashmap_get(m
->machine_units
, unit
);
1624 machine_add_to_gc_queue(machine
);
1628 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1629 Manager
*m
= userdata
;
1637 r
= sd_bus_message_read(message
, "b", &b
);
1639 bus_log_parse_error(r
);
1645 /* systemd finished reloading, let's recheck all our machines */
1646 log_debug("System manager has been reloaded, rechecking machines...");
1648 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1649 machine_add_to_gc_queue(machine
);
1654 int manager_start_scope(
1659 const char *description
,
1660 sd_bus_message
*more_properties
,
1661 sd_bus_error
*error
,
1664 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
1671 r
= sd_bus_message_new_method_call(
1674 "org.freedesktop.systemd1",
1675 "/org/freedesktop/systemd1",
1676 "org.freedesktop.systemd1.Manager",
1677 "StartTransientUnit");
1681 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
1685 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
1689 if (!isempty(slice
)) {
1690 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
1695 if (!isempty(description
)) {
1696 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
1701 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
1705 r
= sd_bus_message_append(m
, "(sv)", "Delegate", "b", 1);
1709 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", UINT64_C(16384));
1711 return bus_log_create_error(r
);
1713 if (more_properties
) {
1714 r
= sd_bus_message_copy(m
, more_properties
, true);
1719 r
= sd_bus_message_close_container(m
);
1723 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
1727 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
1735 r
= sd_bus_message_read(reply
, "o", &j
);
1749 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1750 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1756 r
= sd_bus_call_method(
1758 "org.freedesktop.systemd1",
1759 "/org/freedesktop/systemd1",
1760 "org.freedesktop.systemd1.Manager",
1764 "ss", unit
, "fail");
1766 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1767 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
1772 sd_bus_error_free(error
);
1783 r
= sd_bus_message_read(reply
, "o", &j
);
1797 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1801 return sd_bus_call_method(
1803 "org.freedesktop.systemd1",
1804 "/org/freedesktop/systemd1",
1805 "org.freedesktop.systemd1.Manager",
1809 "ssi", unit
, "all", signo
);
1812 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1813 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1814 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1815 _cleanup_free_
char *path
= NULL
;
1822 path
= unit_dbus_path_from_name(unit
);
1826 r
= sd_bus_get_property(
1828 "org.freedesktop.systemd1",
1830 "org.freedesktop.systemd1.Unit",
1836 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1837 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1840 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1841 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
1847 r
= sd_bus_message_read(reply
, "s", &state
);
1851 return !STR_IN_SET(state
, "inactive", "failed");
1854 int manager_job_is_active(Manager
*manager
, const char *path
) {
1855 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1856 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1862 r
= sd_bus_get_property(
1864 "org.freedesktop.systemd1",
1866 "org.freedesktop.systemd1.Job",
1872 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1873 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1876 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1882 /* We don't actually care about the state really. The fact
1883 * that we could read the job state is enough for us */
1888 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1896 mm
= hashmap_get(m
->machine_leaders
, PID_TO_PTR(pid
));
1898 _cleanup_free_
char *unit
= NULL
;
1900 r
= cg_pid_get_unit(pid
, &unit
);
1902 mm
= hashmap_get(m
->machine_units
, unit
);
1911 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1917 machine
= hashmap_get(m
->machines
, name
);
1919 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1925 *_machine
= machine
;
1930 int bus_reply_pair_array(sd_bus_message
*m
, char **l
) {
1931 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1935 r
= sd_bus_message_new_method_return(m
, &reply
);
1939 r
= sd_bus_message_open_container(reply
, 'a', "{ss}");
1943 STRV_FOREACH_PAIR(k
, v
, l
) {
1944 r
= sd_bus_message_append(reply
, "{ss}", *k
, *v
);
1949 r
= sd_bus_message_close_container(reply
);
1953 return sd_bus_send(NULL
, reply
, NULL
);