1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "path-util.h"
28 #include "unit-name.h"
30 #include "bus-common-errors.h"
31 #include "cgroup-util.h"
32 #include "btrfs-util.h"
33 #include "machine-image.h"
34 #include "image-dbus.h"
36 #include "machine-dbus.h"
38 static int property_get_pool_path(
41 const char *interface,
43 sd_bus_message *reply,
45 sd_bus_error *error) {
50 return sd_bus_message_append(reply, "s", "/var/lib/machines");
53 static int property_get_pool_usage(
56 const char *interface,
58 sd_bus_message *reply,
60 sd_bus_error *error) {
62 _cleanup_close_ int fd = -1;
63 uint64_t usage = (uint64_t) -1;
69 /* We try to read the quota info from /var/lib/machines, as
70 * well as the usage of the loopback file
71 * /var/lib/machines.raw, and pick the larger value. */
73 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
77 if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
81 if (stat("/var/lib/machines.raw", &st) >= 0) {
82 if (usage == (uint64_t) -1 || st.st_blocks * 512ULL > usage)
83 usage = st.st_blocks * 512ULL;
86 return sd_bus_message_append(reply, "t", usage);
89 static int property_get_pool_limit(
92 const char *interface,
94 sd_bus_message *reply,
96 sd_bus_error *error) {
98 _cleanup_close_ int fd = -1;
99 uint64_t size = (uint64_t) -1;
105 /* We try to read the quota limit from /var/lib/machines, as
106 * well as the size of the loopback file
107 * /var/lib/machines.raw, and pick the smaller value. */
109 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
113 if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
114 size = q.referred_max;
117 if (stat("/var/lib/machines.raw", &st) >= 0) {
118 if (size == (uint64_t) -1 || (uint64_t) st.st_size < size)
122 return sd_bus_message_append(reply, "t", size);
125 static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
126 _cleanup_free_ char *p = NULL;
127 Manager *m = userdata;
136 r = sd_bus_message_read(message, "s", &name);
140 machine = hashmap_get(m->machines, name);
142 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
144 p = machine_bus_path(machine);
148 return sd_bus_reply_method_return(message, "o", p);
151 static int method_get_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
152 _cleanup_free_ char *p = NULL;
153 Manager *m = userdata;
161 r = sd_bus_message_read(message, "s", &name);
165 r = image_find(name, NULL);
167 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
171 p = image_bus_path(name);
175 return sd_bus_reply_method_return(message, "o", p);
178 static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
179 _cleanup_free_ char *p = NULL;
180 Manager *m = userdata;
181 Machine *machine = NULL;
189 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
191 r = sd_bus_message_read(message, "u", &pid);
196 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
198 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
202 r = sd_bus_creds_get_pid(creds, &pid);
207 r = manager_get_machine_by_pid(m, pid, &machine);
211 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
213 p = machine_bus_path(machine);
217 return sd_bus_reply_method_return(message, "o", p);
220 static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
221 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
222 Manager *m = userdata;
231 r = sd_bus_message_new_method_return(message, &reply);
233 return sd_bus_error_set_errno(error, r);
235 r = sd_bus_message_open_container(reply, 'a', "(ssso)");
237 return sd_bus_error_set_errno(error, r);
239 HASHMAP_FOREACH(machine, m->machines, i) {
240 _cleanup_free_ char *p = NULL;
242 p = machine_bus_path(machine);
246 r = sd_bus_message_append(reply, "(ssso)",
248 strempty(machine_class_to_string(machine->class)),
252 return sd_bus_error_set_errno(error, r);
255 r = sd_bus_message_close_container(reply);
257 return sd_bus_error_set_errno(error, r);
259 return sd_bus_send(bus, reply, NULL);
262 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
263 const char *name, *service, *class, *root_directory;
264 const int32_t *netif = NULL;
270 size_t n, n_netif = 0;
277 r = sd_bus_message_read(message, "s", &name);
280 if (!machine_name_is_valid(name))
281 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
283 r = sd_bus_message_read_array(message, 'y', &v, &n);
291 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
293 r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
300 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
304 n_netif /= sizeof(int32_t);
306 for (i = 0; i < n_netif; i++) {
308 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
313 c = _MACHINE_CLASS_INVALID;
315 c = machine_class_from_string(class);
317 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
321 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
323 if (!isempty(root_directory) && !path_is_absolute(root_directory))
324 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
327 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
329 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
333 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
335 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
340 if (hashmap_get(manager->machines, name))
341 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
343 r = manager_add_machine(manager, name, &m);
351 if (!isempty(service)) {
352 m->service = strdup(service);
359 if (!isempty(root_directory)) {
360 m->root_directory = strdup(root_directory);
361 if (!m->root_directory) {
368 assert_cc(sizeof(int32_t) == sizeof(int));
369 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
375 m->n_netif = n_netif;
383 machine_add_to_gc_queue(m);
387 static int method_create_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
388 Manager *manager = userdata;
392 r = method_create_or_register_machine(manager, message, read_network, &m, error);
396 r = sd_bus_message_enter_container(message, 'a', "(sv)");
400 r = machine_start(m, message, error);
404 m->create_message = sd_bus_message_ref(message);
408 machine_add_to_gc_queue(m);
412 static int method_create_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
413 return method_create_machine_internal(bus, message, true, userdata, error);
416 static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
417 return method_create_machine_internal(bus, message, false, userdata, error);
420 static int method_register_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
421 Manager *manager = userdata;
422 _cleanup_free_ char *p = NULL;
426 r = method_create_or_register_machine(manager, message, read_network, &m, error);
430 r = cg_pid_get_unit(m->leader, &m->unit);
432 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
436 r = machine_start(m, NULL, error);
440 p = machine_bus_path(m);
446 return sd_bus_reply_method_return(message, "o", p);
449 machine_add_to_gc_queue(m);
453 static int method_register_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
454 return method_register_machine_internal(bus, message, true, userdata, error);
457 static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
458 return method_register_machine_internal(bus, message, false, userdata, error);
461 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
462 Manager *m = userdata;
471 r = sd_bus_message_read(message, "s", &name);
473 return sd_bus_error_set_errno(error, r);
475 machine = hashmap_get(m->machines, name);
477 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
479 return bus_machine_method_terminate(bus, message, machine, error);
482 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
483 Manager *m = userdata;
492 r = sd_bus_message_read(message, "s", &name);
494 return sd_bus_error_set_errno(error, r);
496 machine = hashmap_get(m->machines, name);
498 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
500 return bus_machine_method_kill(bus, message, machine, error);
503 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
504 Manager *m = userdata;
513 r = sd_bus_message_read(message, "s", &name);
515 return sd_bus_error_set_errno(error, r);
517 machine = hashmap_get(m->machines, name);
519 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
521 return bus_machine_method_get_addresses(bus, message, machine, error);
524 static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
525 Manager *m = userdata;
534 r = sd_bus_message_read(message, "s", &name);
536 return sd_bus_error_set_errno(error, r);
538 machine = hashmap_get(m->machines, name);
540 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
542 return bus_machine_method_get_os_release(bus, message, machine, error);
545 static int method_list_images(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
546 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
547 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
548 Manager *m = userdata;
557 images = hashmap_new(&string_hash_ops);
561 r = image_discover(images);
565 r = sd_bus_message_new_method_return(message, &reply);
569 r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
573 HASHMAP_FOREACH(image, images, i) {
574 _cleanup_free_ char *p = NULL;
576 p = image_bus_path(image->name);
580 r = sd_bus_message_append(reply, "(ssbttto)",
582 image_type_to_string(image->type),
592 r = sd_bus_message_close_container(reply);
596 return sd_bus_send(bus, reply, NULL);
599 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
600 Manager *m = userdata;
609 r = sd_bus_message_read(message, "s", &name);
611 return sd_bus_error_set_errno(error, r);
613 machine = hashmap_get(m->machines, name);
615 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
617 return bus_machine_method_open_pty(bus, message, machine, error);
620 static int method_open_machine_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
621 Manager *m = userdata;
630 r = sd_bus_message_read(message, "s", &name);
634 machine = hashmap_get(m->machines, name);
636 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
638 return bus_machine_method_open_login(bus, message, machine, error);
641 static int method_bind_mount_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
642 Manager *m = userdata;
651 r = sd_bus_message_read(message, "s", &name);
655 machine = hashmap_get(m->machines, name);
657 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
659 return bus_machine_method_bind_mount(bus, message, machine, error);
662 static int method_copy_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
663 Manager *m = userdata;
672 r = sd_bus_message_read(message, "s", &name);
676 machine = hashmap_get(m->machines, name);
678 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
680 return bus_machine_method_copy(bus, message, machine, error);
683 static int method_remove_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
684 _cleanup_(image_unrefp) Image* i = NULL;
691 r = sd_bus_message_read(message, "s", &name);
695 if (!image_name_is_valid(name))
696 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
698 r = image_find(name, &i);
702 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
704 i->userdata = userdata;
705 return bus_image_method_remove(bus, message, i, error);
708 static int method_rename_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
709 _cleanup_(image_unrefp) Image* i = NULL;
710 const char *old_name;
716 r = sd_bus_message_read(message, "s", &old_name);
720 if (!image_name_is_valid(old_name))
721 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
723 r = image_find(old_name, &i);
727 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
729 i->userdata = userdata;
730 return bus_image_method_rename(bus, message, i, error);
733 static int method_clone_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
734 _cleanup_(image_unrefp) Image *i = NULL;
735 const char *old_name;
739 r = sd_bus_message_read(message, "s", &old_name);
743 if (!image_name_is_valid(old_name))
744 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
746 r = image_find(old_name, &i);
750 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
752 i->userdata = userdata;
753 return bus_image_method_clone(bus, message, i, error);
756 static int method_mark_image_read_only(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
757 _cleanup_(image_unrefp) Image *i = NULL;
762 r = sd_bus_message_read(message, "s", &name);
766 if (!image_name_is_valid(name))
767 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
769 r = image_find(name, &i);
773 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
775 i->userdata = userdata;
776 return bus_image_method_mark_read_only(bus, message, i, error);
779 static int method_set_pool_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
780 Manager *m = userdata;
785 r = sd_bus_message_read(message, "t", &limit);
789 r = bus_verify_polkit_async(
792 "org.freedesktop.machine1.manage-machines",
800 return 1; /* Will call us back */
802 r = btrfs_resize_loopback("/var/lib/machines", limit);
803 if (r < 0 && r != -ENODEV)
804 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
806 r = btrfs_quota_limit("/var/lib/machines", limit);
808 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
810 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
812 return sd_bus_reply_method_return(message, NULL);
815 static int method_set_image_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
816 _cleanup_(image_unrefp) Image *i = NULL;
821 r = sd_bus_message_read(message, "s", &name);
825 if (!image_name_is_valid(name))
826 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
828 r = image_find(name, &i);
832 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
834 i->userdata = userdata;
835 return bus_image_method_set_limit(bus, message, i, error);
838 const sd_bus_vtable manager_vtable[] = {
839 SD_BUS_VTABLE_START(0),
840 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
841 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
842 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
843 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
844 SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
845 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
846 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
847 SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
848 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
849 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
850 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
851 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
852 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
853 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
854 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
855 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
856 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
857 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
858 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
859 SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
860 SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
861 SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
862 SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
863 SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
864 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
865 SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
866 SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
867 SD_BUS_SIGNAL("MachineNew", "so", 0),
868 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
872 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
873 const char *path, *result, *unit;
874 Manager *m = userdata;
883 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
885 bus_log_parse_error(r);
889 machine = hashmap_get(m->machine_units, unit);
893 if (streq_ptr(path, machine->scope_job)) {
894 free(machine->scope_job);
895 machine->scope_job = NULL;
897 if (machine->started) {
898 if (streq(result, "done"))
899 machine_send_create_reply(machine, NULL);
901 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
903 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
905 machine_send_create_reply(machine, &e);
908 machine_save(machine);
911 machine_add_to_gc_queue(machine);
915 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
916 _cleanup_free_ char *unit = NULL;
917 Manager *m = userdata;
926 path = sd_bus_message_get_path(message);
930 r = unit_name_from_dbus_path(path, &unit);
931 if (r == -EINVAL) /* not for a unit */
936 machine = hashmap_get(m->machine_units, unit);
938 machine_add_to_gc_queue(machine);
943 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
944 const char *path, *unit;
945 Manager *m = userdata;
953 r = sd_bus_message_read(message, "so", &unit, &path);
955 bus_log_parse_error(r);
959 machine = hashmap_get(m->machine_units, unit);
961 machine_add_to_gc_queue(machine);
966 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
967 Manager *m = userdata;
974 r = sd_bus_message_read(message, "b", &b);
976 bus_log_parse_error(r);
982 /* systemd finished reloading, let's recheck all our machines */
983 log_debug("System manager has been reloaded, rechecking machines...");
985 HASHMAP_FOREACH(machine, m->machines, i)
986 machine_add_to_gc_queue(machine);
991 int manager_start_scope(
996 const char *description,
997 sd_bus_message *more_properties,
1001 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1008 r = sd_bus_message_new_method_call(
1011 "org.freedesktop.systemd1",
1012 "/org/freedesktop/systemd1",
1013 "org.freedesktop.systemd1.Manager",
1014 "StartTransientUnit");
1018 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
1022 r = sd_bus_message_open_container(m, 'a', "(sv)");
1026 if (!isempty(slice)) {
1027 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
1032 if (!isempty(description)) {
1033 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
1038 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
1042 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
1046 if (more_properties) {
1047 r = sd_bus_message_copy(m, more_properties, true);
1052 r = sd_bus_message_close_container(m);
1056 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1060 r = sd_bus_call(manager->bus, m, 0, error, &reply);
1068 r = sd_bus_message_read(reply, "o", &j);
1082 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1083 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1089 r = sd_bus_call_method(
1091 "org.freedesktop.systemd1",
1092 "/org/freedesktop/systemd1",
1093 "org.freedesktop.systemd1.Manager",
1097 "ss", unit, "fail");
1099 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1100 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1105 sd_bus_error_free(error);
1116 r = sd_bus_message_read(reply, "o", &j);
1130 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1134 return sd_bus_call_method(
1136 "org.freedesktop.systemd1",
1137 "/org/freedesktop/systemd1",
1138 "org.freedesktop.systemd1.Manager",
1142 "ssi", unit, "all", signo);
1145 int manager_unit_is_active(Manager *manager, const char *unit) {
1146 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1147 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1148 _cleanup_free_ char *path = NULL;
1155 path = unit_dbus_path_from_name(unit);
1159 r = sd_bus_get_property(
1161 "org.freedesktop.systemd1",
1163 "org.freedesktop.systemd1.Unit",
1169 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1170 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1173 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1174 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1180 r = sd_bus_message_read(reply, "s", &state);
1184 return !streq(state, "inactive") && !streq(state, "failed");
1187 int manager_job_is_active(Manager *manager, const char *path) {
1188 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1189 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1195 r = sd_bus_get_property(
1197 "org.freedesktop.systemd1",
1199 "org.freedesktop.systemd1.Job",
1205 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1206 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1209 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1215 /* We don't actually care about the state really. The fact
1216 * that we could read the job state is enough for us */
1221 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1222 _cleanup_free_ char *unit = NULL;
1230 r = cg_pid_get_unit(pid, &unit);
1232 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
1234 mm = hashmap_get(m->machine_units, unit);
1243 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1249 machine = hashmap_get(m->machines, name);
1251 machine = machine_new(m, name);
1257 *_machine = machine;