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 const sd_bus_vtable manager_vtable[] = {
780 SD_BUS_VTABLE_START(0),
781 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
782 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
783 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
784 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
785 SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
786 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
787 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
788 SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
789 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
790 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
791 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
792 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
793 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
794 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
795 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
796 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
797 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
798 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
799 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
800 SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
801 SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
802 SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
803 SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
804 SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
805 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
806 SD_BUS_SIGNAL("MachineNew", "so", 0),
807 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
811 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
812 const char *path, *result, *unit;
813 Manager *m = userdata;
822 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
824 bus_log_parse_error(r);
828 machine = hashmap_get(m->machine_units, unit);
832 if (streq_ptr(path, machine->scope_job)) {
833 free(machine->scope_job);
834 machine->scope_job = NULL;
836 if (machine->started) {
837 if (streq(result, "done"))
838 machine_send_create_reply(machine, NULL);
840 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
842 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
844 machine_send_create_reply(machine, &e);
847 machine_save(machine);
850 machine_add_to_gc_queue(machine);
854 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
855 _cleanup_free_ char *unit = NULL;
856 Manager *m = userdata;
865 path = sd_bus_message_get_path(message);
869 r = unit_name_from_dbus_path(path, &unit);
870 if (r == -EINVAL) /* not for a unit */
875 machine = hashmap_get(m->machine_units, unit);
877 machine_add_to_gc_queue(machine);
882 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
883 const char *path, *unit;
884 Manager *m = userdata;
892 r = sd_bus_message_read(message, "so", &unit, &path);
894 bus_log_parse_error(r);
898 machine = hashmap_get(m->machine_units, unit);
900 machine_add_to_gc_queue(machine);
905 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
906 Manager *m = userdata;
913 r = sd_bus_message_read(message, "b", &b);
915 bus_log_parse_error(r);
921 /* systemd finished reloading, let's recheck all our machines */
922 log_debug("System manager has been reloaded, rechecking machines...");
924 HASHMAP_FOREACH(machine, m->machines, i)
925 machine_add_to_gc_queue(machine);
930 int manager_start_scope(
935 const char *description,
936 sd_bus_message *more_properties,
940 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
947 r = sd_bus_message_new_method_call(
950 "org.freedesktop.systemd1",
951 "/org/freedesktop/systemd1",
952 "org.freedesktop.systemd1.Manager",
953 "StartTransientUnit");
957 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
961 r = sd_bus_message_open_container(m, 'a', "(sv)");
965 if (!isempty(slice)) {
966 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
971 if (!isempty(description)) {
972 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
977 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
981 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
985 if (more_properties) {
986 r = sd_bus_message_copy(m, more_properties, true);
991 r = sd_bus_message_close_container(m);
995 r = sd_bus_message_append(m, "a(sa(sv))", 0);
999 r = sd_bus_call(manager->bus, m, 0, error, &reply);
1007 r = sd_bus_message_read(reply, "o", &j);
1021 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1022 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1028 r = sd_bus_call_method(
1030 "org.freedesktop.systemd1",
1031 "/org/freedesktop/systemd1",
1032 "org.freedesktop.systemd1.Manager",
1036 "ss", unit, "fail");
1038 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1039 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1044 sd_bus_error_free(error);
1055 r = sd_bus_message_read(reply, "o", &j);
1069 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1073 return sd_bus_call_method(
1075 "org.freedesktop.systemd1",
1076 "/org/freedesktop/systemd1",
1077 "org.freedesktop.systemd1.Manager",
1081 "ssi", unit, "all", signo);
1084 int manager_unit_is_active(Manager *manager, const char *unit) {
1085 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1086 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1087 _cleanup_free_ char *path = NULL;
1094 path = unit_dbus_path_from_name(unit);
1098 r = sd_bus_get_property(
1100 "org.freedesktop.systemd1",
1102 "org.freedesktop.systemd1.Unit",
1108 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1109 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1112 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1113 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1119 r = sd_bus_message_read(reply, "s", &state);
1123 return !streq(state, "inactive") && !streq(state, "failed");
1126 int manager_job_is_active(Manager *manager, const char *path) {
1127 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1128 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1134 r = sd_bus_get_property(
1136 "org.freedesktop.systemd1",
1138 "org.freedesktop.systemd1.Job",
1144 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1145 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1148 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1154 /* We don't actually care about the state really. The fact
1155 * that we could read the job state is enough for us */
1160 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1161 _cleanup_free_ char *unit = NULL;
1169 r = cg_pid_get_unit(pid, &unit);
1171 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
1173 mm = hashmap_get(m->machine_units, unit);
1182 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1188 machine = hashmap_get(m->machines, name);
1190 machine = machine_new(m, name);
1196 *_machine = machine;