1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
9 #include "btrfs-util.h"
10 #include "bus-common-errors.h"
11 #include "bus-get-properties.h"
12 #include "bus-locator.h"
13 #include "bus-message-util.h"
14 #include "bus-object.h"
15 #include "bus-polkit.h"
17 #include "cgroup-util.h"
18 #include "discover-image.h"
19 #include "errno-util.h"
22 #include "format-util.h"
24 #include "hostname-util.h"
26 #include "image-dbus.h"
29 #include "machine-dbus.h"
30 #include "machine-pool.h"
32 #include "namespace-util.h"
33 #include "operation.h"
35 #include "path-util.h"
36 #include "socket-util.h"
37 #include "string-util.h"
40 #include "user-util.h"
42 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_pool_path
, "s", "/var/lib/machines");
44 static int property_get_pool_usage(
47 const char *interface
,
49 sd_bus_message
*reply
,
51 sd_bus_error
*error
) {
53 _cleanup_close_
int fd
= -EBADF
;
54 uint64_t usage
= UINT64_MAX
;
59 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
63 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
67 return sd_bus_message_append(reply
, "t", usage
);
70 static int property_get_pool_limit(
73 const char *interface
,
75 sd_bus_message
*reply
,
77 sd_bus_error
*error
) {
79 _cleanup_close_
int fd
= -EBADF
;
80 uint64_t size
= UINT64_MAX
;
85 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
89 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
90 size
= q
.referenced_max
;
93 return sd_bus_message_append(reply
, "t", size
);
96 static int method_get_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
97 _cleanup_free_
char *p
= NULL
;
98 Manager
*m
= ASSERT_PTR(userdata
);
105 r
= sd_bus_message_read(message
, "s", &name
);
109 machine
= hashmap_get(m
->machines
, name
);
111 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
113 p
= machine_bus_path(machine
);
117 return sd_bus_reply_method_return(message
, "o", p
);
120 static int method_get_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
121 _cleanup_free_
char *p
= NULL
;
122 _unused_ Manager
*m
= ASSERT_PTR(userdata
);
128 r
= sd_bus_message_read(message
, "s", &name
);
132 r
= image_find(m
->runtime_scope
, IMAGE_MACHINE
, name
, NULL
, NULL
);
134 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
138 p
= image_bus_path(name
);
142 return sd_bus_reply_method_return(message
, "o", p
);
145 static int method_get_machine_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
146 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
147 _cleanup_free_
char *p
= NULL
;
148 Manager
*m
= ASSERT_PTR(userdata
);
149 Machine
*machine
= NULL
;
155 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
157 r
= sd_bus_message_read(message
, "u", &pid
);
164 pidref
= PIDREF_MAKE_FROM_PID(pid
);
167 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
169 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
|SD_BUS_CREDS_PIDFD
, &creds
);
173 r
= bus_creds_get_pidref(creds
, &pidref
);
178 r
= manager_get_machine_by_pidref(m
, &pidref
, &machine
);
182 return sd_bus_error_setf(error
, BUS_ERROR_NO_MACHINE_FOR_PID
, "PID "PID_FMT
" does not belong to any known machine", pid
);
184 p
= machine_bus_path(machine
);
188 return sd_bus_reply_method_return(message
, "o", p
);
191 static int method_list_machines(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
192 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
193 Manager
*m
= ASSERT_PTR(userdata
);
199 r
= sd_bus_message_new_method_return(message
, &reply
);
201 return sd_bus_error_set_errno(error
, r
);
203 r
= sd_bus_message_open_container(reply
, 'a', "(ssso)");
205 return sd_bus_error_set_errno(error
, r
);
207 HASHMAP_FOREACH(machine
, m
->machines
) {
208 _cleanup_free_
char *p
= NULL
;
210 p
= machine_bus_path(machine
);
214 r
= sd_bus_message_append(reply
, "(ssso)",
216 strempty(machine_class_to_string(machine
->class)),
220 return sd_bus_error_set_errno(error
, r
);
223 r
= sd_bus_message_close_container(reply
);
225 return sd_bus_error_set_errno(error
, r
);
227 return sd_bus_message_send(reply
);
230 static int machine_add_from_params(
232 sd_bus_message
*message
,
233 const char *polkit_action
,
238 PidRef
*leader_pidref
,
239 PidRef
*supervisor_pidref
,
240 const char *root_directory
,
241 const int32_t *netif
,
244 const char *ssh_address
,
245 const char *ssh_private_key_path
,
247 sd_bus_error
*error
) {
257 if (leader_pidref
->pid
== 1)
258 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
259 if (supervisor_pidref
->pid
== 1)
260 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid supervisor PID");
262 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
263 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
268 r
= sd_bus_creds_get_euid(creds
, &uid
);
272 /* Ensure an unprivileged user cannot claim any process they don't control as their own machine */
274 r
= process_is_owned_by_uid(leader_pidref
, uid
);
278 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only root may register machines for other users");
281 if (manager
->runtime_scope
!= RUNTIME_SCOPE_USER
) {
282 const char *details
[] = {
284 "class", machine_class_to_string(c
),
288 r
= bus_verify_polkit_async(
292 &manager
->polkit_registry
,
297 return 0; /* Will call us back */
300 r
= manager_add_machine(manager
, name
, &m
);
304 m
->leader
= TAKE_PIDREF(*leader_pidref
);
305 m
->supervisor
= TAKE_PIDREF(*supervisor_pidref
);
311 if (!isempty(service
)) {
312 m
->service
= strdup(service
);
319 if (!isempty(root_directory
)) {
320 m
->root_directory
= strdup(root_directory
);
321 if (!m
->root_directory
) {
328 assert_cc(sizeof(int32_t) == sizeof(int));
329 m
->netif
= memdup(netif
, sizeof(int32_t) * n_netif
);
335 m
->n_netif
= n_netif
;
338 if (!isempty(ssh_address
)) {
339 m
->ssh_address
= strdup(ssh_address
);
340 if (!m
->ssh_address
) {
346 if (!isempty(ssh_private_key_path
)) {
347 m
->ssh_private_key_path
= strdup(ssh_private_key_path
);
348 if (!m
->ssh_private_key_path
) {
358 machine_add_to_gc_queue(m
);
362 static int method_create_or_register_machine(
364 sd_bus_message
*message
,
365 const char *polkit_action
,
367 sd_bus_error
*error
) {
369 _cleanup_(pidref_done
) PidRef leader_pidref
= PIDREF_NULL
, supervisor_pidref
= PIDREF_NULL
;
370 const char *name
, *service
, *class, *root_directory
;
371 const int32_t *netif
= NULL
;
382 r
= sd_bus_message_read(message
, "s", &name
);
385 if (!hostname_is_valid(name
, 0))
386 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine name");
388 r
= bus_message_read_id128(message
, &id
);
390 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine ID parameter");
392 r
= sd_bus_message_read(message
, "ssus", &service
, &class, &leader
, &root_directory
);
396 if (endswith(sd_bus_message_get_member(message
), "WithNetwork")) {
397 r
= sd_bus_message_read_array(message
, 'i', (const void**) &netif
, &n_netif
);
401 n_netif
/= sizeof(int32_t);
403 for (size_t i
= 0; i
< n_netif
; i
++) {
405 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid network interface index %i", netif
[i
]);
410 c
= _MACHINE_CLASS_INVALID
;
412 c
= machine_class_from_string(class);
414 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine class parameter");
418 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
420 if (!isempty(root_directory
) && (!path_is_absolute(root_directory
) || !path_is_valid(root_directory
)))
421 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Root directory must be empty or an absolute path");
424 /* If no PID is specified, the client is the leader */
425 r
= bus_query_sender_pidref(message
, &leader_pidref
);
427 return sd_bus_error_set_errnof(error
, r
, "Failed to pin client process: %m");
429 /* If a PID is specified that's the leader, but if the client process is different from it, than that's the supervisor */
430 r
= pidref_set_pid(&leader_pidref
, leader
);
432 return sd_bus_error_set_errnof(error
, r
, "Failed to pin process " PID_FMT
": %m", (pid_t
) leader
);
434 _cleanup_(pidref_done
) PidRef client_pidref
= PIDREF_NULL
;
435 r
= bus_query_sender_pidref(message
, &client_pidref
);
437 return sd_bus_error_set_errnof(error
, r
, "Failed to pin client process: %m");
439 if (!pidref_equal(&client_pidref
, &leader_pidref
))
440 supervisor_pidref
= TAKE_PIDREF(client_pidref
);
443 if (hashmap_get(manager
->machines
, name
))
444 return sd_bus_error_setf(error
, BUS_ERROR_MACHINE_EXISTS
, "Machine '%s' already exists", name
);
446 return machine_add_from_params(
460 /* ssh_address= */ NULL
,
461 /* ssh_private_key_path= */ NULL
,
466 static int method_create_or_register_machine_ex(
468 sd_bus_message
*message
,
469 const char *polkit_action
,
471 sd_bus_error
*error
) {
473 const char *name
= NULL
, *service
= NULL
, *class = NULL
, *root_directory
= NULL
, *ssh_address
= NULL
, *ssh_private_key_path
= NULL
;
474 _cleanup_(pidref_done
) PidRef leader_pidref
= PIDREF_NULL
, supervisor_pidref
= PIDREF_NULL
;
475 sd_id128_t id
= SD_ID128_NULL
;
476 const int32_t *netif
= NULL
;
480 uint64_t leader_pidfdid
= 0;
481 uint32_t leader_pid
= 0;
482 int r
, leader_pidfd
= -EBADF
;
488 r
= sd_bus_message_read(message
, "s", &name
);
491 if (!hostname_is_valid(name
, 0))
492 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine name");
494 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
501 r
= sd_bus_message_enter_container(message
, 'r', "sv");
507 r
= sd_bus_message_read(message
, "s", &key
);
511 r
= sd_bus_message_enter_container(message
, 'v', NULL
);
515 if (streq(key
, "Id")) {
516 r
= bus_message_read_id128(message
, &id
);
518 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine ID parameter");
519 } else if (streq(key
, "Service")) {
520 r
= sd_bus_message_read(message
, "s", &service
);
523 } else if (streq(key
, "Class")) {
524 r
= sd_bus_message_read(message
, "s", &class);
527 } else if (streq(key
, "LeaderPID")) {
528 r
= sd_bus_message_read(message
, "u", &leader_pid
);
531 } else if (streq(key
, "LeaderPIDFD")) {
532 r
= sd_bus_message_read(message
, "h", &leader_pidfd
);
535 } else if (streq(key
, "LeaderPIDFDID")) {
536 r
= sd_bus_message_read(message
, "t", &leader_pidfdid
);
539 } else if (streq(key
, "RootDirectory")) {
540 r
= sd_bus_message_read(message
, "s", &root_directory
);
543 } else if (streq(key
, "NetworkInterfaces")) {
544 r
= sd_bus_message_read_array(message
, 'i', (const void**) &netif
, &n_netif
);
548 n_netif
/= sizeof(int32_t);
550 for (size_t i
= 0; i
< n_netif
; i
++)
552 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid network interface index %i", netif
[i
]);
553 } else if (streq(key
, "VSockCID")) {
554 r
= sd_bus_message_read(message
, "u", &cid
);
558 if (!VSOCK_CID_IS_REGULAR(cid
))
559 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "JSON field 'vSockCid' is not a regular VSOCK CID.");
560 } else if (streq(key
, "SSHAddress")) {
561 r
= sd_bus_message_read(message
, "s", &ssh_address
);
564 } else if (streq(key
, "SSHPrivateKeyPath")) {
565 r
= sd_bus_message_read(message
, "s", &ssh_private_key_path
);
569 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown property '%s'", key
);
571 r
= sd_bus_message_exit_container(message
);
575 r
= sd_bus_message_exit_container(message
);
580 r
= sd_bus_message_exit_container(message
);
585 c
= _MACHINE_CLASS_INVALID
;
587 c
= machine_class_from_string(class);
589 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine class parameter");
592 if (!isempty(root_directory
) && (!path_is_absolute(root_directory
) || !path_is_valid(root_directory
)))
593 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Root directory must be empty or an absolute path");
595 if (hashmap_get(manager
->machines
, name
))
596 return sd_bus_error_setf(error
, BUS_ERROR_MACHINE_EXISTS
, "Machine '%s' already exists", name
);
598 /* If a PID is specified that's the leader, but if the client process is different from it, than that's the supervisor */
599 if (leader_pidfd
>= 0) {
600 r
= pidref_set_pidfd(&leader_pidref
, leader_pidfd
);
602 return sd_bus_error_set_errnof(error
, r
, "Failed to parse PIDFD %d: %m", leader_pidfd
);
604 if (leader_pid
> 0 && leader_pidref
.pid
!= (pid_t
) leader_pid
)
605 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "LeaderPID and LeaderPIDFD refer to different processes");
606 if (leader_pidfdid
> 0) {
607 r
= pidref_acquire_pidfd_id(&leader_pidref
);
608 if (r
>= 0 && leader_pidref
.fd_id
!= leader_pidfdid
)
609 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "LeaderPIDFDID does not match the inode number of LeaderPIDFD");
611 } else if (leader_pid
> 0 && leader_pidfdid
> 0) {
612 r
= pidref_set_pid_and_pidfd_id(&leader_pidref
, leader_pid
, leader_pidfdid
);
614 return sd_bus_error_set_errnof(error
, r
, "Failed to pin process " PID_FMT
" by PIDFDID %" PRIu64
": %m", (pid_t
) leader_pid
, leader_pidfdid
);
615 } else if (leader_pid
> 0 || leader_pidfdid
> 0)
616 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Both LeaderPID and LeaderPIDFDID must be specified to identify the leader process by PIDFDID");
618 if (pidref_is_set(&leader_pidref
)) {
619 _cleanup_(pidref_done
) PidRef client_pidref
= PIDREF_NULL
;
620 r
= bus_query_sender_pidref(message
, &client_pidref
);
622 return sd_bus_error_set_errnof(error
, r
, "Failed to pin client process: %m");
624 if (!pidref_equal(&client_pidref
, &leader_pidref
))
625 supervisor_pidref
= TAKE_PIDREF(client_pidref
);
627 /* If no PID is specified, the client is the leader */
628 r
= bus_query_sender_pidref(message
, &leader_pidref
);
630 return sd_bus_error_set_errnof(error
, r
, "Failed to pin client process: %m");
633 return machine_add_from_params(
648 ssh_private_key_path
,
653 static int method_create_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
654 Manager
*manager
= ASSERT_PTR(userdata
);
660 if (sd_bus_message_is_method_call(message
, NULL
, "CreateMachineEx"))
661 r
= method_create_or_register_machine_ex(manager
, message
, "org.freedesktop.machine1.create-machines", &m
, error
);
663 r
= method_create_or_register_machine(manager
, message
, "org.freedesktop.machine1.create-machine", &m
, error
);
667 return 1; /* Will call us back */
669 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
673 r
= machine_start(m
, message
, error
);
677 m
->create_message
= sd_bus_message_ref(message
);
681 machine_add_to_gc_queue(m
);
685 static int method_register_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
686 Manager
*manager
= ASSERT_PTR(userdata
);
687 _cleanup_free_
char *p
= NULL
;
693 if (sd_bus_message_is_method_call(message
, NULL
, "RegisterMachineEx"))
694 r
= method_create_or_register_machine_ex(manager
, message
, "org.freedesktop.machine1.register-machine", &m
, error
);
696 r
= method_create_or_register_machine(manager
, message
, "org.freedesktop.machine1.register-machine", &m
, error
);
700 return 1; /* Will call us back */
702 switch (manager
->runtime_scope
) {
703 case RUNTIME_SCOPE_USER
:
704 r
= cg_pidref_get_user_unit_full(&m
->leader
, &m
->unit
, &m
->subgroup
);
707 case RUNTIME_SCOPE_SYSTEM
:
708 r
= cg_pidref_get_unit_full(&m
->leader
, &m
->unit
, &m
->subgroup
);
712 assert_not_reached();
715 r
= sd_bus_error_set_errnof(error
, r
,
716 "Failed to determine unit of process "PID_FMT
" : %m",
721 if (!empty_or_root(m
->subgroup
)) {
722 /* If this is not a top-level cgroup, then we need the cgroup path to be able to watch when
725 r
= cg_pidref_get_path(&m
->leader
, &m
->cgroup
);
727 r
= sd_bus_error_set_errnof(error
, r
,
728 "Failed to determine cgroup of process "PID_FMT
" : %m",
734 r
= machine_start(m
, NULL
, error
);
738 p
= machine_bus_path(m
);
744 return sd_bus_reply_method_return(message
, "o", p
);
747 machine_add_to_gc_queue(m
);
751 static int redirect_method_to_machine(sd_bus_message
*message
, Manager
*m
, sd_bus_error
*error
, sd_bus_message_handler_t method
) {
760 r
= sd_bus_message_read(message
, "s", &name
);
762 return sd_bus_error_set_errno(error
, r
);
764 machine
= hashmap_get(m
->machines
, name
);
766 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
768 return method(message
, machine
, error
);
771 static int method_unregister_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
772 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_unregister
);
775 static int method_terminate_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
776 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_terminate
);
779 static int method_kill_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
780 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_kill
);
783 static int method_get_machine_addresses(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
784 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_addresses
);
787 static int method_get_machine_ssh_info(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
788 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_ssh_info
);
791 static int method_get_machine_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
792 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_os_release
);
795 static int method_list_images(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
796 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
797 Manager
*m
= ASSERT_PTR(userdata
);
802 _cleanup_hashmap_free_ Hashmap
*images
= NULL
;
803 r
= image_discover(m
->runtime_scope
, IMAGE_MACHINE
, NULL
, &images
);
807 r
= sd_bus_message_new_method_return(message
, &reply
);
811 r
= sd_bus_message_open_container(reply
, 'a', "(ssbttto)");
816 HASHMAP_FOREACH(image
, images
) {
817 _cleanup_free_
char *p
= NULL
;
819 p
= image_bus_path(image
->name
);
823 r
= sd_bus_message_append(reply
, "(ssbttto)",
825 image_type_to_string(image
->type
),
826 image_is_read_only(image
),
835 r
= sd_bus_message_close_container(reply
);
839 return sd_bus_message_send(reply
);
842 static int method_open_machine_pty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
843 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_pty
);
846 static int method_open_machine_login(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
847 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_login
);
850 static int method_open_machine_shell(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
851 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_shell
);
854 static int method_bind_mount_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
855 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_bind_mount
);
858 static int method_copy_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
859 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_copy
);
862 static int method_open_machine_root_directory(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
863 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_root_directory
);
866 static int method_get_machine_uid_shift(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
867 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_uid_shift
);
870 static int redirect_method_to_image(sd_bus_message
*message
, Manager
*m
, sd_bus_error
*error
, sd_bus_message_handler_t method
) {
879 r
= sd_bus_message_read(message
, "s", &name
);
883 if (!image_name_is_valid(name
))
884 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
886 r
= manager_acquire_image(m
, name
, &i
);
888 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
892 return method(message
, i
, error
);
895 static int method_remove_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
896 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_remove
);
899 static int method_rename_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
900 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_rename
);
903 static int method_clone_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
904 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_clone
);
907 static int method_mark_image_read_only(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
908 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_mark_read_only
);
911 static int method_get_image_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
912 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_hostname
);
915 static int method_get_image_machine_id(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
916 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_machine_id
);
919 static int method_get_image_machine_info(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
920 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_machine_info
);
923 static int method_get_image_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
924 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_os_release
);
927 static int clean_pool_done(Operation
*operation
, int child_error
, sd_bus_error
*error
) {
928 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
929 _cleanup_fclose_
FILE *file
= NULL
;
933 assert(operation
->message
);
934 assert(operation
->extra_fd
>= 0);
936 file
= take_fdopen(&operation
->extra_fd
, "r");
938 return log_debug_errno(errno
, "Failed to take opened tmp file's fd: %m");
940 r
= clean_pool_read_first_entry(file
, child_error
, error
);
944 r
= sd_bus_message_new_method_return(operation
->message
, &reply
);
948 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
952 /* On success the resulting temporary file will contain a list of image names that were removed followed by
953 * their size on disk. Let's read that and turn it into a bus message. */
955 _cleanup_free_
char *name
= NULL
;
958 r
= clean_pool_read_next_entry(file
, &name
, &usage
);
964 r
= sd_bus_message_append(reply
, "(st)", name
, usage
);
969 r
= sd_bus_message_close_container(reply
);
973 return sd_bus_message_send(reply
);
976 static int method_clean_pool(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
977 ImageCleanPoolMode mode
;
978 Manager
*m
= userdata
;
979 Operation
*operation
;
985 if (m
->n_operations
>= OPERATIONS_MAX
)
986 return sd_bus_error_set(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Too many ongoing operations.");
988 r
= sd_bus_message_read(message
, "s", &mm
);
992 if (streq(mm
, "all"))
993 mode
= IMAGE_CLEAN_POOL_REMOVE_ALL
;
994 else if (streq(mm
, "hidden"))
995 mode
= IMAGE_CLEAN_POOL_REMOVE_HIDDEN
;
997 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mode '%s'.", mm
);
999 if (m
->runtime_scope
!= RUNTIME_SCOPE_USER
) {
1000 const char *details
[] = {
1001 "verb", "clean_pool",
1006 r
= bus_verify_polkit_async(
1008 "org.freedesktop.machine1.manage-machines",
1010 &m
->polkit_registry
,
1015 return 1; /* Will call us back */
1018 r
= image_clean_pool_operation(m
, mode
, &operation
);
1020 return log_debug_errno(r
, "Failed to clean pool of images: %m");
1022 operation_attach_bus_reply(operation
, message
);
1023 operation
->done
= clean_pool_done
;
1027 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1028 Manager
*m
= userdata
;
1034 r
= sd_bus_message_read(message
, "t", &limit
);
1037 if (!FILE_SIZE_VALID_OR_INFINITY(limit
))
1038 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "New limit out of range");
1040 if (m
->runtime_scope
!= RUNTIME_SCOPE_USER
) {
1041 const char *details
[] = {
1042 "verb", "set_pool_limit",
1046 r
= bus_verify_polkit_async(
1048 "org.freedesktop.machine1.manage-machines",
1050 &m
->polkit_registry
,
1055 return 1; /* Will call us back */
1058 /* Set up the machine directory if necessary */
1059 r
= setup_machine_directory(error
, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
1063 r
= image_set_pool_limit(m
->runtime_scope
, IMAGE_MACHINE
, limit
);
1064 if (ERRNO_IS_NEG_NOT_SUPPORTED(r
))
1065 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
1067 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
1069 return sd_bus_reply_method_return(message
, NULL
);
1072 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1073 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_set_limit
);
1076 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1077 Manager
*m
= userdata
;
1084 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
1088 if (!uid_is_valid(uid
))
1089 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1091 machine
= hashmap_get(m
->machines
, name
);
1093 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1095 if (machine
->class != MACHINE_CONTAINER
)
1096 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1098 r
= machine_translate_uid(machine
, uid
, &converted
);
1100 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
1104 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1107 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1108 _cleanup_free_
char *o
= NULL
;
1109 Manager
*m
= userdata
;
1111 uid_t uid
, converted
;
1114 r
= sd_bus_message_read(message
, "u", &uid
);
1117 if (!uid_is_valid(uid
))
1118 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
1120 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
1122 r
= manager_find_machine_for_uid(m
, uid
, &machine
, &converted
);
1126 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
1128 o
= machine_bus_path(machine
);
1132 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1135 static int method_map_from_machine_group(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1136 Manager
*m
= userdata
;
1143 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
1147 if (!gid_is_valid(gid
))
1148 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1150 machine
= hashmap_get(m
->machines
, name
);
1152 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1154 if (machine
->class != MACHINE_CONTAINER
)
1155 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1157 r
= machine_translate_gid(machine
, gid
, &converted
);
1159 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1163 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1166 static int method_map_to_machine_group(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1167 _cleanup_free_
char *o
= NULL
;
1168 Manager
*m
= userdata
;
1170 gid_t gid
, converted
;
1173 r
= sd_bus_message_read(message
, "u", &gid
);
1176 if (!gid_is_valid(gid
))
1177 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1179 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1181 r
= manager_find_machine_for_gid(m
, gid
, &machine
, &converted
);
1185 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1187 o
= machine_bus_path(machine
);
1191 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1194 const sd_bus_vtable manager_vtable
[] = {
1195 SD_BUS_VTABLE_START(0),
1197 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1198 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1199 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1201 SD_BUS_METHOD_WITH_ARGS("GetMachine",
1202 SD_BUS_ARGS("s", name
),
1203 SD_BUS_RESULT("o", machine
),
1205 SD_BUS_VTABLE_UNPRIVILEGED
),
1206 SD_BUS_METHOD_WITH_ARGS("GetImage",
1207 SD_BUS_ARGS("s", name
),
1208 SD_BUS_RESULT("o", image
),
1210 SD_BUS_VTABLE_UNPRIVILEGED
),
1211 SD_BUS_METHOD_WITH_ARGS("GetMachineByPID",
1212 SD_BUS_ARGS("u", pid
),
1213 SD_BUS_RESULT("o", machine
),
1214 method_get_machine_by_pid
,
1215 SD_BUS_VTABLE_UNPRIVILEGED
),
1216 SD_BUS_METHOD_WITH_ARGS("ListMachines",
1218 SD_BUS_RESULT("a(ssso)", machines
),
1219 method_list_machines
,
1220 SD_BUS_VTABLE_UNPRIVILEGED
),
1221 SD_BUS_METHOD_WITH_ARGS("ListImages",
1223 SD_BUS_RESULT("a(ssbttto)", images
),
1225 SD_BUS_VTABLE_UNPRIVILEGED
),
1226 SD_BUS_METHOD_WITH_ARGS("CreateMachine",
1227 SD_BUS_ARGS("s", name
, "ay", id
, "s", service
, "s", class, "u", leader
, "s", root_directory
, "a(sv)", scope_properties
),
1228 SD_BUS_RESULT("o", path
),
1229 method_create_machine
,
1230 SD_BUS_VTABLE_UNPRIVILEGED
),
1231 SD_BUS_METHOD_WITH_ARGS("CreateMachineWithNetwork",
1232 SD_BUS_ARGS("s", name
, "ay", id
, "s", service
, "s", class, "u", leader
, "s", root_directory
, "ai", ifindices
, "a(sv)", scope_properties
),
1233 SD_BUS_RESULT("o", path
),
1234 method_create_machine
,
1235 SD_BUS_VTABLE_UNPRIVILEGED
),
1236 SD_BUS_METHOD_WITH_ARGS("CreateMachineEx",
1237 SD_BUS_ARGS("s", name
, "a(sv)", properties
, "a(sv)", scope_properties
),
1238 SD_BUS_RESULT("o", path
),
1239 method_create_machine
,
1240 SD_BUS_VTABLE_UNPRIVILEGED
),
1241 SD_BUS_METHOD_WITH_ARGS("RegisterMachine",
1242 SD_BUS_ARGS("s", name
, "ay", id
, "s", service
, "s", class, "u", leader
, "s", root_directory
),
1243 SD_BUS_RESULT("o", path
),
1244 method_register_machine
,
1245 SD_BUS_VTABLE_UNPRIVILEGED
),
1246 SD_BUS_METHOD_WITH_ARGS("RegisterMachineWithNetwork",
1247 SD_BUS_ARGS("s", name
, "ay", id
, "s", service
, "s", class, "u", leader
, "s", root_directory
, "ai", ifindices
),
1248 SD_BUS_RESULT("o", path
),
1249 method_register_machine
,
1250 SD_BUS_VTABLE_UNPRIVILEGED
),
1251 SD_BUS_METHOD_WITH_ARGS("RegisterMachineEx",
1252 SD_BUS_ARGS("s", name
, "a(sv)", properties
),
1253 SD_BUS_RESULT("o", path
),
1254 method_register_machine
,
1255 SD_BUS_VTABLE_UNPRIVILEGED
),
1256 SD_BUS_METHOD_WITH_ARGS("UnregisterMachine",
1257 SD_BUS_ARGS("s", name
),
1259 method_unregister_machine
,
1260 SD_BUS_VTABLE_UNPRIVILEGED
),
1261 SD_BUS_METHOD_WITH_ARGS("TerminateMachine",
1262 SD_BUS_ARGS("s", id
),
1264 method_terminate_machine
,
1265 SD_BUS_VTABLE_UNPRIVILEGED
),
1266 SD_BUS_METHOD_WITH_ARGS("KillMachine",
1267 SD_BUS_ARGS("s", name
, "s", whom
, "i", signal
),
1269 method_kill_machine
,
1270 SD_BUS_VTABLE_UNPRIVILEGED
),
1271 SD_BUS_METHOD_WITH_ARGS("GetMachineAddresses",
1272 SD_BUS_ARGS("s", name
),
1273 SD_BUS_RESULT("a(iay)", addresses
),
1274 method_get_machine_addresses
,
1275 SD_BUS_VTABLE_UNPRIVILEGED
),
1276 SD_BUS_METHOD_WITH_ARGS("GetMachineSSHInfo",
1277 SD_BUS_ARGS("s", name
),
1278 SD_BUS_RESULT("s", ssh_address
, "s", ssh_private_key_path
),
1279 method_get_machine_ssh_info
,
1280 SD_BUS_VTABLE_UNPRIVILEGED
),
1281 SD_BUS_METHOD_WITH_ARGS("GetMachineOSRelease",
1282 SD_BUS_ARGS("s", name
),
1283 SD_BUS_RESULT("a{ss}", fields
),
1284 method_get_machine_os_release
,
1285 SD_BUS_VTABLE_UNPRIVILEGED
),
1286 SD_BUS_METHOD_WITH_ARGS("OpenMachinePTY",
1287 SD_BUS_ARGS("s", name
),
1288 SD_BUS_RESULT("h", pty
, "s", pty_path
),
1289 method_open_machine_pty
,
1290 SD_BUS_VTABLE_UNPRIVILEGED
),
1291 SD_BUS_METHOD_WITH_ARGS("OpenMachineLogin",
1292 SD_BUS_ARGS("s", name
),
1293 SD_BUS_RESULT("h", pty
, "s", pty_path
),
1294 method_open_machine_login
,
1295 SD_BUS_VTABLE_UNPRIVILEGED
),
1296 SD_BUS_METHOD_WITH_ARGS("OpenMachineShell",
1297 SD_BUS_ARGS("s", name
, "s", user
, "s", path
, "as", args
, "as", environment
),
1298 SD_BUS_RESULT("h", pty
, "s", pty_path
),
1299 method_open_machine_shell
,
1300 SD_BUS_VTABLE_UNPRIVILEGED
),
1301 SD_BUS_METHOD_WITH_ARGS("BindMountMachine",
1302 SD_BUS_ARGS("s", name
, "s", source
, "s", destination
, "b", read_only
, "b", mkdir
),
1304 method_bind_mount_machine
,
1305 SD_BUS_VTABLE_UNPRIVILEGED
),
1306 SD_BUS_METHOD_WITH_ARGS("CopyFromMachine",
1307 SD_BUS_ARGS("s", name
, "s", source
, "s", destination
),
1309 method_copy_machine
,
1310 SD_BUS_VTABLE_UNPRIVILEGED
),
1311 SD_BUS_METHOD_WITH_ARGS("CopyToMachine",
1312 SD_BUS_ARGS("s", name
, "s", source
, "s", destination
),
1314 method_copy_machine
,
1315 SD_BUS_VTABLE_UNPRIVILEGED
),
1316 SD_BUS_METHOD_WITH_ARGS("CopyFromMachineWithFlags",
1317 SD_BUS_ARGS("s", name
, "s", source
, "s", destination
, "t", flags
),
1319 method_copy_machine
,
1320 SD_BUS_VTABLE_UNPRIVILEGED
),
1321 SD_BUS_METHOD_WITH_ARGS("CopyToMachineWithFlags",
1322 SD_BUS_ARGS("s", name
, "s", source
, "s", destination
, "t", flags
),
1324 method_copy_machine
,
1325 SD_BUS_VTABLE_UNPRIVILEGED
),
1326 SD_BUS_METHOD_WITH_ARGS("OpenMachineRootDirectory",
1327 SD_BUS_ARGS("s", name
),
1328 SD_BUS_RESULT("h", fd
),
1329 method_open_machine_root_directory
,
1330 SD_BUS_VTABLE_UNPRIVILEGED
),
1331 SD_BUS_METHOD_WITH_ARGS("GetMachineUIDShift",
1332 SD_BUS_ARGS("s", name
),
1333 SD_BUS_RESULT("u", shift
),
1334 method_get_machine_uid_shift
,
1335 SD_BUS_VTABLE_UNPRIVILEGED
),
1336 SD_BUS_METHOD_WITH_ARGS("RemoveImage",
1337 SD_BUS_ARGS("s", name
),
1339 method_remove_image
,
1340 SD_BUS_VTABLE_UNPRIVILEGED
),
1341 SD_BUS_METHOD_WITH_ARGS("RenameImage",
1342 SD_BUS_ARGS("s", name
, "s", new_name
),
1344 method_rename_image
,
1345 SD_BUS_VTABLE_UNPRIVILEGED
),
1346 SD_BUS_METHOD_WITH_ARGS("CloneImage",
1347 SD_BUS_ARGS("s", name
, "s", new_name
, "b", read_only
),
1350 SD_BUS_VTABLE_UNPRIVILEGED
),
1351 SD_BUS_METHOD_WITH_ARGS("MarkImageReadOnly",
1352 SD_BUS_ARGS("s", name
, "b", read_only
),
1354 method_mark_image_read_only
,
1355 SD_BUS_VTABLE_UNPRIVILEGED
),
1356 SD_BUS_METHOD_WITH_ARGS("GetImageHostname",
1357 SD_BUS_ARGS("s", name
),
1358 SD_BUS_RESULT("s", hostname
),
1359 method_get_image_hostname
,
1360 SD_BUS_VTABLE_UNPRIVILEGED
),
1361 SD_BUS_METHOD_WITH_ARGS("GetImageMachineID",
1362 SD_BUS_ARGS("s", name
),
1363 SD_BUS_RESULT("ay", id
),
1364 method_get_image_machine_id
,
1365 SD_BUS_VTABLE_UNPRIVILEGED
),
1366 SD_BUS_METHOD_WITH_ARGS("GetImageMachineInfo",
1367 SD_BUS_ARGS("s", name
),
1368 SD_BUS_RESULT("a{ss}", machine_info
),
1369 method_get_image_machine_info
,
1370 SD_BUS_VTABLE_UNPRIVILEGED
),
1371 SD_BUS_METHOD_WITH_ARGS("GetImageOSRelease",
1372 SD_BUS_ARGS("s", name
),
1373 SD_BUS_RESULT("a{ss}", os_release
),
1374 method_get_image_os_release
,
1375 SD_BUS_VTABLE_UNPRIVILEGED
),
1376 SD_BUS_METHOD_WITH_ARGS("SetPoolLimit",
1377 SD_BUS_ARGS("t", size
),
1379 method_set_pool_limit
,
1380 SD_BUS_VTABLE_UNPRIVILEGED
),
1381 SD_BUS_METHOD_WITH_ARGS("SetImageLimit",
1382 SD_BUS_ARGS("s", name
, "t", size
),
1384 method_set_image_limit
,
1385 SD_BUS_VTABLE_UNPRIVILEGED
),
1386 SD_BUS_METHOD_WITH_ARGS("CleanPool",
1387 SD_BUS_ARGS("s", mode
),
1388 SD_BUS_RESULT("a(st)",images
),
1390 SD_BUS_VTABLE_UNPRIVILEGED
),
1391 SD_BUS_METHOD_WITH_ARGS("MapFromMachineUser",
1392 SD_BUS_ARGS("s", name
, "u", uid_inner
),
1393 SD_BUS_RESULT("u", uid_outer
),
1394 method_map_from_machine_user
,
1395 SD_BUS_VTABLE_UNPRIVILEGED
),
1396 SD_BUS_METHOD_WITH_ARGS("MapToMachineUser",
1397 SD_BUS_ARGS("u", uid_outer
),
1398 SD_BUS_RESULT("s", machine_name
, "o", machine_path
, "u", uid_inner
),
1399 method_map_to_machine_user
,
1400 SD_BUS_VTABLE_UNPRIVILEGED
),
1401 SD_BUS_METHOD_WITH_ARGS("MapFromMachineGroup",
1402 SD_BUS_ARGS("s", name
, "u", gid_inner
),
1403 SD_BUS_RESULT("u", gid_outer
),
1404 method_map_from_machine_group
,
1405 SD_BUS_VTABLE_UNPRIVILEGED
),
1406 SD_BUS_METHOD_WITH_ARGS("MapToMachineGroup",
1407 SD_BUS_ARGS("u", gid_outer
),
1408 SD_BUS_RESULT("s", machine_name
, "o", machine_path
, "u", gid_inner
),
1409 method_map_to_machine_group
,
1410 SD_BUS_VTABLE_UNPRIVILEGED
),
1412 SD_BUS_SIGNAL_WITH_ARGS("MachineNew",
1413 SD_BUS_ARGS("s", machine
, "o", path
),
1415 SD_BUS_SIGNAL_WITH_ARGS("MachineRemoved",
1416 SD_BUS_ARGS("s", machine
, "o", path
),
1422 const BusObjectImplementation manager_object
= {
1423 "/org/freedesktop/machine1",
1424 "org.freedesktop.machine1.Manager",
1425 .vtables
= BUS_VTABLES(manager_vtable
),
1426 .children
= BUS_IMPLEMENTATIONS( &machine_object
,
1430 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1431 const char *path
, *result
, *unit
;
1432 Manager
*m
= ASSERT_PTR(userdata
);
1439 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1441 bus_log_parse_error(r
);
1445 machine
= hashmap_get(m
->machines_by_unit
, unit
);
1449 if (streq_ptr(path
, machine
->scope_job
)) {
1450 machine
->scope_job
= mfree(machine
->scope_job
);
1452 if (machine
->started
) {
1453 if (streq(result
, "done"))
1454 machine_send_create_reply(machine
, NULL
);
1456 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
1458 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1460 machine_send_create_reply(machine
, &e
);
1464 machine_save(machine
);
1467 machine_add_to_gc_queue(machine
);
1471 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1472 _cleanup_free_
char *unit
= NULL
;
1474 Manager
*m
= ASSERT_PTR(userdata
);
1480 path
= sd_bus_message_get_path(message
);
1484 r
= unit_name_from_dbus_path(path
, &unit
);
1485 if (r
== -EINVAL
) /* not for a unit */
1492 machine
= hashmap_get(m
->machines_by_unit
, unit
);
1496 machine_add_to_gc_queue(machine
);
1500 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1501 const char *path
, *unit
;
1502 Manager
*m
= ASSERT_PTR(userdata
);
1508 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1510 bus_log_parse_error(r
);
1514 machine
= hashmap_get(m
->machines_by_unit
, unit
);
1518 machine_add_to_gc_queue(machine
);
1522 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1523 Manager
*m
= ASSERT_PTR(userdata
);
1529 r
= sd_bus_message_read(message
, "b", &b
);
1531 bus_log_parse_error(r
);
1537 /* systemd finished reloading, let's recheck all our machines */
1538 log_debug("System manager has been reloaded, rechecking machines...");
1540 HASHMAP_FOREACH(machine
, m
->machines
)
1541 machine_add_to_gc_queue(machine
);
1546 int manager_unref_unit(
1549 sd_bus_error
*error
) {
1554 return bus_call_method(m
->api_bus
, bus_systemd_mgr
, "UnrefUnit", error
, NULL
, "s", unit
);
1557 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1558 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1564 r
= bus_call_method(manager
->api_bus
, bus_systemd_mgr
, "StopUnit", error
, &reply
, "ss", unit
, "fail");
1566 if (sd_bus_error_has_names(error
, BUS_ERROR_NO_SUCH_UNIT
,
1567 BUS_ERROR_LOAD_FAILED
)) {
1572 sd_bus_error_free(error
);
1583 r
= sd_bus_message_read(reply
, "o", &j
);
1597 int manager_kill_unit(Manager
*manager
, const char *unit
, const char *subgroup
, int signo
, sd_bus_error
*reterr_error
) {
1601 if (empty_or_root(subgroup
))
1602 return bus_call_method(manager
->api_bus
, bus_systemd_mgr
, "KillUnit", reterr_error
, NULL
, "ssi", unit
, "all", signo
);
1604 return bus_call_method(manager
->api_bus
, bus_systemd_mgr
, "KillUnitSubgroup", reterr_error
, NULL
, "sssi", unit
, "cgroup", subgroup
, signo
);
1607 int manager_unit_is_active(Manager
*manager
, const char *unit
, sd_bus_error
*reterr_error
) {
1608 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1609 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1610 _cleanup_free_
char *path
= NULL
;
1617 path
= unit_dbus_path_from_name(unit
);
1621 r
= sd_bus_get_property(
1623 "org.freedesktop.systemd1",
1625 "org.freedesktop.systemd1.Unit",
1631 if (bus_error_is_connection(&error
))
1634 if (sd_bus_error_has_names(&error
, BUS_ERROR_NO_SUCH_UNIT
,
1635 BUS_ERROR_LOAD_FAILED
))
1638 sd_bus_error_move(reterr_error
, &error
);
1642 r
= sd_bus_message_read(reply
, "s", &state
);
1646 return !STR_IN_SET(state
, "inactive", "failed");
1649 int manager_job_is_active(Manager
*manager
, const char *path
, sd_bus_error
*reterr_error
) {
1650 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1651 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1657 r
= sd_bus_get_property(
1659 "org.freedesktop.systemd1",
1661 "org.freedesktop.systemd1.Job",
1667 if (bus_error_is_connection(&error
))
1670 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1673 sd_bus_error_move(reterr_error
, &error
);
1677 /* We don't actually care about the state really. The fact
1678 * that we could read the job state is enough for us */