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 */
1081 r
= safe_fork("(sd-clean)", FORK_RESET_SIGNALS
, &child
);
1083 return sd_bus_error_set_errnof(error
, r
, "Failed to fork(): %m");
1085 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
1086 bool success
= true;
1091 errno_pipe_fd
[0] = safe_close(errno_pipe_fd
[0]);
1093 images
= hashmap_new(&string_hash_ops
);
1099 r
= image_discover(images
);
1103 l
= write(result_fd
, &success
, sizeof(success
));
1109 HASHMAP_FOREACH(image
, images
, i
) {
1111 /* We can't remove vendor images (i.e. those in /usr) */
1112 if (IMAGE_IS_VENDOR(image
))
1115 if (IMAGE_IS_HOST(image
))
1118 if (mode
== REMOVE_HIDDEN
&& !IMAGE_IS_HIDDEN(image
))
1121 r
= image_remove(image
);
1122 if (r
== -EBUSY
) /* keep images that are currently being used. */
1125 /* If the operation failed, let's override everything we wrote, and instead write there at which image we failed. */
1127 (void) ftruncate(result_fd
, 0);
1128 (void) lseek(result_fd
, 0, SEEK_SET
);
1129 (void) write(result_fd
, &success
, sizeof(success
));
1130 (void) write(result_fd
, image
->name
, strlen(image
->name
)+1);
1134 l
= write(result_fd
, image
->name
, strlen(image
->name
)+1);
1140 l
= write(result_fd
, &image
->usage_exclusive
, sizeof(image
->usage_exclusive
));
1147 result_fd
= safe_close(result_fd
);
1148 _exit(EXIT_SUCCESS
);
1151 (void) write(errno_pipe_fd
[1], &r
, sizeof(r
));
1152 _exit(EXIT_FAILURE
);
1155 errno_pipe_fd
[1] = safe_close(errno_pipe_fd
[1]);
1157 /* The clean-up might take a while, hence install a watch on the child and return */
1159 r
= operation_new(m
, NULL
, child
, message
, errno_pipe_fd
[0], &operation
);
1161 (void) sigkill_wait(child
);
1165 operation
->extra_fd
= result_fd
;
1166 operation
->done
= clean_pool_done
;
1169 errno_pipe_fd
[0] = -1;
1174 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1175 Manager
*m
= userdata
;
1181 r
= sd_bus_message_read(message
, "t", &limit
);
1184 if (!FILE_SIZE_VALID_OR_INFINITY(limit
))
1185 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "New limit out of range");
1187 r
= bus_verify_polkit_async(
1190 "org.freedesktop.machine1.manage-machines",
1194 &m
->polkit_registry
,
1199 return 1; /* Will call us back */
1201 /* Set up the machine directory if necessary */
1202 r
= setup_machine_directory(limit
, error
);
1206 /* Resize the backing loopback device, if there is one, except if we asked to drop any limit */
1207 if (limit
!= (uint64_t) -1) {
1208 r
= btrfs_resize_loopback("/var/lib/machines", limit
, false);
1210 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
1211 if (r
< 0 && r
!= -ENODEV
) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
1212 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust loopback limit: %m");
1215 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit
);
1217 r
= btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit
);
1219 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
1221 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
1223 return sd_bus_reply_method_return(message
, NULL
);
1226 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1227 _cleanup_(image_unrefp
) Image
*i
= NULL
;
1233 r
= sd_bus_message_read(message
, "s", &name
);
1237 if (!image_name_is_valid(name
))
1238 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
1240 r
= image_find(name
, &i
);
1244 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
1246 i
->userdata
= userdata
;
1247 return bus_image_method_set_limit(message
, i
, error
);
1250 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1251 _cleanup_fclose_
FILE *f
= NULL
;
1252 Manager
*m
= userdata
;
1253 const char *name
, *p
;
1258 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
1262 if (!uid_is_valid(uid
))
1263 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1265 machine
= hashmap_get(m
->machines
, name
);
1267 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1269 if (machine
->class != MACHINE_CONTAINER
)
1270 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1272 p
= procfs_file_alloca(machine
->leader
, "uid_map");
1278 uid_t uid_base
, uid_shift
, uid_range
, converted
;
1282 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
1283 if (k
< 0 && feof(f
))
1286 if (ferror(f
) && errno
> 0)
1292 if (uid
< uid_base
|| uid
>= uid_base
+ uid_range
)
1295 converted
= uid
- uid_base
+ uid_shift
;
1296 if (!uid_is_valid(converted
))
1297 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1299 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1302 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
1305 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1306 Manager
*m
= userdata
;
1312 r
= sd_bus_message_read(message
, "u", &uid
);
1315 if (!uid_is_valid(uid
))
1316 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1318 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
1320 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1321 _cleanup_fclose_
FILE *f
= NULL
;
1322 char p
[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1324 if (machine
->class != MACHINE_CONTAINER
)
1327 xsprintf(p
, "/proc/" UID_FMT
"/uid_map", machine
->leader
);
1330 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1335 _cleanup_free_
char *o
= NULL
;
1336 uid_t uid_base
, uid_shift
, uid_range
, converted
;
1340 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
1341 if (k
< 0 && feof(f
))
1344 if (ferror(f
) && errno
> 0)
1350 if (uid
< uid_shift
|| uid
>= uid_shift
+ uid_range
)
1353 converted
= (uid
- uid_shift
+ uid_base
);
1354 if (!uid_is_valid(converted
))
1355 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1357 o
= machine_bus_path(machine
);
1361 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1365 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
1368 static int method_map_from_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1369 _cleanup_fclose_
FILE *f
= NULL
;
1370 Manager
*m
= groupdata
;
1371 const char *name
, *p
;
1376 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
1380 if (!gid_is_valid(gid
))
1381 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1383 machine
= hashmap_get(m
->machines
, name
);
1385 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1387 if (machine
->class != MACHINE_CONTAINER
)
1388 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1390 p
= procfs_file_alloca(machine
->leader
, "gid_map");
1396 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1400 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1401 if (k
< 0 && feof(f
))
1404 if (ferror(f
) && errno
> 0)
1410 if (gid
< gid_base
|| gid
>= gid_base
+ gid_range
)
1413 converted
= gid
- gid_base
+ gid_shift
;
1414 if (!gid_is_valid(converted
))
1415 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1417 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1420 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1423 static int method_map_to_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1424 Manager
*m
= groupdata
;
1430 r
= sd_bus_message_read(message
, "u", &gid
);
1433 if (!gid_is_valid(gid
))
1434 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1436 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1438 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1439 _cleanup_fclose_
FILE *f
= NULL
;
1440 char p
[STRLEN("/proc//gid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1442 if (machine
->class != MACHINE_CONTAINER
)
1445 xsprintf(p
, "/proc/" GID_FMT
"/gid_map", machine
->leader
);
1448 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1453 _cleanup_free_
char *o
= NULL
;
1454 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1458 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1459 if (k
< 0 && feof(f
))
1462 if (ferror(f
) && errno
> 0)
1468 if (gid
< gid_shift
|| gid
>= gid_shift
+ gid_range
)
1471 converted
= (gid
- gid_shift
+ gid_base
);
1472 if (!gid_is_valid(converted
))
1473 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1475 o
= machine_bus_path(machine
);
1479 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1483 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1486 const sd_bus_vtable manager_vtable
[] = {
1487 SD_BUS_VTABLE_START(0),
1488 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1489 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1490 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1491 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1492 SD_BUS_METHOD("GetImage", "s", "o", method_get_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1493 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
1494 SD_BUS_METHOD("ListMachines", NULL
, "a(ssso)", method_list_machines
, SD_BUS_VTABLE_UNPRIVILEGED
),
1495 SD_BUS_METHOD("ListImages", NULL
, "a(ssbttto)", method_list_images
, SD_BUS_VTABLE_UNPRIVILEGED
),
1496 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine
, 0),
1497 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network
, 0),
1498 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine
, 0),
1499 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network
, 0),
1500 SD_BUS_METHOD("TerminateMachine", "s", NULL
, method_terminate_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1501 SD_BUS_METHOD("KillMachine", "ssi", NULL
, method_kill_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1502 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses
, SD_BUS_VTABLE_UNPRIVILEGED
),
1503 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1504 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty
, 0),
1505 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login
, SD_BUS_VTABLE_UNPRIVILEGED
),
1506 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell
, SD_BUS_VTABLE_UNPRIVILEGED
),
1507 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL
, method_bind_mount_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1508 SD_BUS_METHOD("CopyFromMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1509 SD_BUS_METHOD("CopyToMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1510 SD_BUS_METHOD("OpenMachineRootDirectory", "s", "h", method_open_machine_root_directory
, SD_BUS_VTABLE_UNPRIVILEGED
),
1511 SD_BUS_METHOD("GetMachineUIDShift", "s", "u", method_get_machine_uid_shift
, SD_BUS_VTABLE_UNPRIVILEGED
),
1512 SD_BUS_METHOD("RemoveImage", "s", NULL
, method_remove_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1513 SD_BUS_METHOD("RenameImage", "ss", NULL
, method_rename_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1514 SD_BUS_METHOD("CloneImage", "ssb", NULL
, method_clone_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1515 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL
, method_mark_image_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
1516 SD_BUS_METHOD("GetImageHostname", "s", "s", method_get_image_hostname
, SD_BUS_VTABLE_UNPRIVILEGED
),
1517 SD_BUS_METHOD("GetImageMachineID", "s", "ay", method_get_image_machine_id
, SD_BUS_VTABLE_UNPRIVILEGED
),
1518 SD_BUS_METHOD("GetImageMachineInfo", "s", "a{ss}", method_get_image_machine_info
, SD_BUS_VTABLE_UNPRIVILEGED
),
1519 SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1520 SD_BUS_METHOD("SetPoolLimit", "t", NULL
, method_set_pool_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1521 SD_BUS_METHOD("SetImageLimit", "st", NULL
, method_set_image_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1522 SD_BUS_METHOD("CleanPool", "s", "a(st)", method_clean_pool
, SD_BUS_VTABLE_UNPRIVILEGED
),
1523 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1524 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1525 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1526 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1527 SD_BUS_SIGNAL("MachineNew", "so", 0),
1528 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1532 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1533 const char *path
, *result
, *unit
;
1534 Manager
*m
= userdata
;
1542 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1544 bus_log_parse_error(r
);
1548 machine
= hashmap_get(m
->machine_units
, unit
);
1552 if (streq_ptr(path
, machine
->scope_job
)) {
1553 machine
->scope_job
= mfree(machine
->scope_job
);
1555 if (machine
->started
) {
1556 if (streq(result
, "done"))
1557 machine_send_create_reply(machine
, NULL
);
1559 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
1561 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1563 machine_send_create_reply(machine
, &e
);
1567 machine_save(machine
);
1570 machine_add_to_gc_queue(machine
);
1574 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1575 _cleanup_free_
char *unit
= NULL
;
1577 Manager
*m
= userdata
;
1584 path
= sd_bus_message_get_path(message
);
1588 r
= unit_name_from_dbus_path(path
, &unit
);
1589 if (r
== -EINVAL
) /* not for a unit */
1596 machine
= hashmap_get(m
->machine_units
, unit
);
1600 machine_add_to_gc_queue(machine
);
1604 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1605 const char *path
, *unit
;
1606 Manager
*m
= userdata
;
1613 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1615 bus_log_parse_error(r
);
1619 machine
= hashmap_get(m
->machine_units
, unit
);
1623 machine_add_to_gc_queue(machine
);
1627 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1628 Manager
*m
= userdata
;
1636 r
= sd_bus_message_read(message
, "b", &b
);
1638 bus_log_parse_error(r
);
1644 /* systemd finished reloading, let's recheck all our machines */
1645 log_debug("System manager has been reloaded, rechecking machines...");
1647 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1648 machine_add_to_gc_queue(machine
);
1653 int manager_start_scope(
1658 const char *description
,
1659 sd_bus_message
*more_properties
,
1660 sd_bus_error
*error
,
1663 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
1670 r
= sd_bus_message_new_method_call(
1673 "org.freedesktop.systemd1",
1674 "/org/freedesktop/systemd1",
1675 "org.freedesktop.systemd1.Manager",
1676 "StartTransientUnit");
1680 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
1684 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
1688 if (!isempty(slice
)) {
1689 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
1694 if (!isempty(description
)) {
1695 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
1700 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
1704 r
= sd_bus_message_append(m
, "(sv)", "Delegate", "b", 1);
1708 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", UINT64_C(16384));
1710 return bus_log_create_error(r
);
1712 if (more_properties
) {
1713 r
= sd_bus_message_copy(m
, more_properties
, true);
1718 r
= sd_bus_message_close_container(m
);
1722 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
1726 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
1734 r
= sd_bus_message_read(reply
, "o", &j
);
1748 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1749 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1755 r
= sd_bus_call_method(
1757 "org.freedesktop.systemd1",
1758 "/org/freedesktop/systemd1",
1759 "org.freedesktop.systemd1.Manager",
1763 "ss", unit
, "fail");
1765 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1766 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
1771 sd_bus_error_free(error
);
1782 r
= sd_bus_message_read(reply
, "o", &j
);
1796 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1800 return sd_bus_call_method(
1802 "org.freedesktop.systemd1",
1803 "/org/freedesktop/systemd1",
1804 "org.freedesktop.systemd1.Manager",
1808 "ssi", unit
, "all", signo
);
1811 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1812 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1813 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1814 _cleanup_free_
char *path
= NULL
;
1821 path
= unit_dbus_path_from_name(unit
);
1825 r
= sd_bus_get_property(
1827 "org.freedesktop.systemd1",
1829 "org.freedesktop.systemd1.Unit",
1835 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1836 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1839 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1840 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
1846 r
= sd_bus_message_read(reply
, "s", &state
);
1850 return !STR_IN_SET(state
, "inactive", "failed");
1853 int manager_job_is_active(Manager
*manager
, const char *path
) {
1854 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1855 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1861 r
= sd_bus_get_property(
1863 "org.freedesktop.systemd1",
1865 "org.freedesktop.systemd1.Job",
1871 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1872 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1875 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1881 /* We don't actually care about the state really. The fact
1882 * that we could read the job state is enough for us */
1887 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1895 mm
= hashmap_get(m
->machine_leaders
, PID_TO_PTR(pid
));
1897 _cleanup_free_
char *unit
= NULL
;
1899 r
= cg_pid_get_unit(pid
, &unit
);
1901 mm
= hashmap_get(m
->machine_units
, unit
);
1910 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1916 machine
= hashmap_get(m
->machines
, name
);
1918 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1924 *_machine
= machine
;
1929 int bus_reply_pair_array(sd_bus_message
*m
, char **l
) {
1930 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1934 r
= sd_bus_message_new_method_return(m
, &reply
);
1938 r
= sd_bus_message_open_container(reply
, 'a', "{ss}");
1942 STRV_FOREACH_PAIR(k
, v
, l
) {
1943 r
= sd_bus_message_append(reply
, "{ss}", *k
, *v
);
1948 r
= sd_bus_message_close_container(reply
);
1952 return sd_bus_send(NULL
, reply
, NULL
);