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_quota_limit("/var/lib/machines", limit);
804 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
806 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
808 return sd_bus_reply_method_return(message, NULL);
811 static int method_set_image_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
812 _cleanup_(image_unrefp) Image *i = NULL;
817 r = sd_bus_message_read(message, "s", &name);
821 if (!image_name_is_valid(name))
822 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
824 r = image_find(name, &i);
828 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
830 i->userdata = userdata;
831 return bus_image_method_set_limit(bus, message, i, error);
834 const sd_bus_vtable manager_vtable[] = {
835 SD_BUS_VTABLE_START(0),
836 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
837 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
838 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
839 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
840 SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
841 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
842 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
843 SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
844 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
845 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
846 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
847 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
848 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
849 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
850 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
851 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
852 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
853 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
854 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
855 SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
856 SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
857 SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
858 SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
859 SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
860 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
861 SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
862 SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
863 SD_BUS_SIGNAL("MachineNew", "so", 0),
864 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
868 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
869 const char *path, *result, *unit;
870 Manager *m = userdata;
879 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
881 bus_log_parse_error(r);
885 machine = hashmap_get(m->machine_units, unit);
889 if (streq_ptr(path, machine->scope_job)) {
890 free(machine->scope_job);
891 machine->scope_job = NULL;
893 if (machine->started) {
894 if (streq(result, "done"))
895 machine_send_create_reply(machine, NULL);
897 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
899 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
901 machine_send_create_reply(machine, &e);
904 machine_save(machine);
907 machine_add_to_gc_queue(machine);
911 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
912 _cleanup_free_ char *unit = NULL;
913 Manager *m = userdata;
922 path = sd_bus_message_get_path(message);
926 r = unit_name_from_dbus_path(path, &unit);
927 if (r == -EINVAL) /* not for a unit */
932 machine = hashmap_get(m->machine_units, unit);
934 machine_add_to_gc_queue(machine);
939 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
940 const char *path, *unit;
941 Manager *m = userdata;
949 r = sd_bus_message_read(message, "so", &unit, &path);
951 bus_log_parse_error(r);
955 machine = hashmap_get(m->machine_units, unit);
957 machine_add_to_gc_queue(machine);
962 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
963 Manager *m = userdata;
970 r = sd_bus_message_read(message, "b", &b);
972 bus_log_parse_error(r);
978 /* systemd finished reloading, let's recheck all our machines */
979 log_debug("System manager has been reloaded, rechecking machines...");
981 HASHMAP_FOREACH(machine, m->machines, i)
982 machine_add_to_gc_queue(machine);
987 int manager_start_scope(
992 const char *description,
993 sd_bus_message *more_properties,
997 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1004 r = sd_bus_message_new_method_call(
1007 "org.freedesktop.systemd1",
1008 "/org/freedesktop/systemd1",
1009 "org.freedesktop.systemd1.Manager",
1010 "StartTransientUnit");
1014 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
1018 r = sd_bus_message_open_container(m, 'a', "(sv)");
1022 if (!isempty(slice)) {
1023 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
1028 if (!isempty(description)) {
1029 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
1034 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
1038 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
1042 if (more_properties) {
1043 r = sd_bus_message_copy(m, more_properties, true);
1048 r = sd_bus_message_close_container(m);
1052 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1056 r = sd_bus_call(manager->bus, m, 0, error, &reply);
1064 r = sd_bus_message_read(reply, "o", &j);
1078 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1079 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1085 r = sd_bus_call_method(
1087 "org.freedesktop.systemd1",
1088 "/org/freedesktop/systemd1",
1089 "org.freedesktop.systemd1.Manager",
1093 "ss", unit, "fail");
1095 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1096 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1101 sd_bus_error_free(error);
1112 r = sd_bus_message_read(reply, "o", &j);
1126 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1130 return sd_bus_call_method(
1132 "org.freedesktop.systemd1",
1133 "/org/freedesktop/systemd1",
1134 "org.freedesktop.systemd1.Manager",
1138 "ssi", unit, "all", signo);
1141 int manager_unit_is_active(Manager *manager, const char *unit) {
1142 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1143 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1144 _cleanup_free_ char *path = NULL;
1151 path = unit_dbus_path_from_name(unit);
1155 r = sd_bus_get_property(
1157 "org.freedesktop.systemd1",
1159 "org.freedesktop.systemd1.Unit",
1165 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1166 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1169 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1170 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1176 r = sd_bus_message_read(reply, "s", &state);
1180 return !streq(state, "inactive") && !streq(state, "failed");
1183 int manager_job_is_active(Manager *manager, const char *path) {
1184 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1185 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1191 r = sd_bus_get_property(
1193 "org.freedesktop.systemd1",
1195 "org.freedesktop.systemd1.Job",
1201 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1202 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1205 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1211 /* We don't actually care about the state really. The fact
1212 * that we could read the job state is enough for us */
1217 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1218 _cleanup_free_ char *unit = NULL;
1226 r = cg_pid_get_unit(pid, &unit);
1228 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
1230 mm = hashmap_get(m->machine_units, unit);
1239 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1245 machine = hashmap_get(m->machines, name);
1247 machine = machine_new(m, name);
1253 *_machine = machine;