chiark / gitweb /
machined: fix writability check for GPT images
[elogind.git] / src / machine / machined-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <pwd.h>
26 #include <sys/capability.h>
27
28 #include "sd-id128.h"
29 #include "sd-messages.h"
30 #include "strv.h"
31 #include "mkdir.h"
32 #include "path-util.h"
33 #include "special.h"
34 #include "fileio-label.h"
35 #include "label.h"
36 #include "utf8.h"
37 #include "unit-name.h"
38 #include "bus-util.h"
39 #include "bus-common-errors.h"
40 #include "time-util.h"
41 #include "cgroup-util.h"
42 #include "image.h"
43 #include "machined.h"
44
45 static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
46         _cleanup_free_ char *p = NULL;
47         Manager *m = userdata;
48         Machine *machine;
49         const char *name;
50         int r;
51
52         assert(bus);
53         assert(message);
54         assert(m);
55
56         r = sd_bus_message_read(message, "s", &name);
57         if (r < 0)
58                 return r;
59
60         machine = hashmap_get(m->machines, name);
61         if (!machine)
62                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
63
64         p = machine_bus_path(machine);
65         if (!p)
66                 return -ENOMEM;
67
68         return sd_bus_reply_method_return(message, "o", p);
69 }
70
71 static int method_get_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
72         _cleanup_free_ char *p = NULL;
73         Manager *m = userdata;
74         const char *name;
75         int r;
76
77         assert(bus);
78         assert(message);
79         assert(m);
80
81         r = sd_bus_message_read(message, "s", &name);
82         if (r < 0)
83                 return r;
84
85         r = image_find(name, NULL);
86         if (r == 0)
87                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
88         if (r < 0)
89                 return r;
90
91         p = image_bus_path(name);
92         if (!p)
93                 return -ENOMEM;
94
95         return sd_bus_reply_method_return(message, "o", p);
96 }
97
98 static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
99         _cleanup_free_ char *p = NULL;
100         Manager *m = userdata;
101         Machine *machine = NULL;
102         pid_t pid;
103         int r;
104
105         assert(bus);
106         assert(message);
107         assert(m);
108
109         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
110
111         r = sd_bus_message_read(message, "u", &pid);
112         if (r < 0)
113                 return r;
114
115         if (pid == 0) {
116                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
117
118                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
119                 if (r < 0)
120                         return r;
121
122                 r = sd_bus_creds_get_pid(creds, &pid);
123                 if (r < 0)
124                         return r;
125         }
126
127         r = manager_get_machine_by_pid(m, pid, &machine);
128         if (r < 0)
129                 return r;
130         if (!machine)
131                 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
132
133         p = machine_bus_path(machine);
134         if (!p)
135                 return -ENOMEM;
136
137         return sd_bus_reply_method_return(message, "o", p);
138 }
139
140 static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
141         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
142         Manager *m = userdata;
143         Machine *machine;
144         Iterator i;
145         int r;
146
147         assert(bus);
148         assert(message);
149         assert(m);
150
151         r = sd_bus_message_new_method_return(message, &reply);
152         if (r < 0)
153                 return sd_bus_error_set_errno(error, r);
154
155         r = sd_bus_message_open_container(reply, 'a', "(ssso)");
156         if (r < 0)
157                 return sd_bus_error_set_errno(error, r);
158
159         HASHMAP_FOREACH(machine, m->machines, i) {
160                 _cleanup_free_ char *p = NULL;
161
162                 p = machine_bus_path(machine);
163                 if (!p)
164                         return -ENOMEM;
165
166                 r = sd_bus_message_append(reply, "(ssso)",
167                                           machine->name,
168                                           strempty(machine_class_to_string(machine->class)),
169                                           machine->service,
170                                           p);
171                 if (r < 0)
172                         return sd_bus_error_set_errno(error, r);
173         }
174
175         r = sd_bus_message_close_container(reply);
176         if (r < 0)
177                 return sd_bus_error_set_errno(error, r);
178
179         return sd_bus_send(bus, reply, NULL);
180 }
181
182 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
183         const char *name, *service, *class, *root_directory;
184         const int32_t *netif = NULL;
185         MachineClass c;
186         uint32_t leader;
187         sd_id128_t id;
188         const void *v;
189         Machine *m;
190         size_t n, n_netif = 0;
191         int r;
192
193         assert(manager);
194         assert(message);
195         assert(_m);
196
197         r = sd_bus_message_read(message, "s", &name);
198         if (r < 0)
199                 return r;
200         if (!machine_name_is_valid(name))
201                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
202
203         r = sd_bus_message_read_array(message, 'y', &v, &n);
204         if (r < 0)
205                 return r;
206         if (n == 0)
207                 id = SD_ID128_NULL;
208         else if (n == 16)
209                 memcpy(&id, v, n);
210         else
211                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
212
213         r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
214         if (r < 0)
215                 return r;
216
217         if (read_network) {
218                 size_t i;
219
220                 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
221                 if (r < 0)
222                         return r;
223
224                 n_netif /= sizeof(int32_t);
225
226                 for (i = 0; i < n_netif; i++) {
227                         if (netif[i] <= 0)
228                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
229                 }
230         }
231
232         if (isempty(class))
233                 c = _MACHINE_CLASS_INVALID;
234         else {
235                 c = machine_class_from_string(class);
236                 if (c < 0)
237                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
238         }
239
240         if (leader == 1)
241                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
242
243         if (!isempty(root_directory) && !path_is_absolute(root_directory))
244                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
245
246         if (leader == 0) {
247                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
248
249                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
250                 if (r < 0)
251                         return r;
252
253                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
254
255                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
256                 if (r < 0)
257                         return r;
258         }
259
260         if (hashmap_get(manager->machines, name))
261                 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
262
263         r = manager_add_machine(manager, name, &m);
264         if (r < 0)
265                 return r;
266
267         m->leader = leader;
268         m->class = c;
269         m->id = id;
270
271         if (!isempty(service)) {
272                 m->service = strdup(service);
273                 if (!m->service) {
274                         r = -ENOMEM;
275                         goto fail;
276                 }
277         }
278
279         if (!isempty(root_directory)) {
280                 m->root_directory = strdup(root_directory);
281                 if (!m->root_directory) {
282                         r = -ENOMEM;
283                         goto fail;
284                 }
285         }
286
287         if (n_netif > 0) {
288                 assert_cc(sizeof(int32_t) == sizeof(int));
289                 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
290                 if (!m->netif) {
291                         r = -ENOMEM;
292                         goto fail;
293                 }
294
295                 m->n_netif = n_netif;
296         }
297
298         *_m = m;
299
300         return 1;
301
302 fail:
303         machine_add_to_gc_queue(m);
304         return r;
305 }
306
307 static int method_create_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
308         Manager *manager = userdata;
309         Machine *m = NULL;
310         int r;
311
312         r = method_create_or_register_machine(manager, message, read_network, &m, error);
313         if (r < 0)
314                 return r;
315
316         r = sd_bus_message_enter_container(message, 'a', "(sv)");
317         if (r < 0)
318                 goto fail;
319
320         r = machine_start(m, message, error);
321         if (r < 0)
322                 goto fail;
323
324         m->create_message = sd_bus_message_ref(message);
325         return 1;
326
327 fail:
328         machine_add_to_gc_queue(m);
329         return r;
330 }
331
332 static int method_create_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
333         return method_create_machine_internal(bus, message, true, userdata, error);
334 }
335
336 static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
337         return method_create_machine_internal(bus, message, false, userdata, error);
338 }
339
340 static int method_register_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
341         Manager *manager = userdata;
342         _cleanup_free_ char *p = NULL;
343         Machine *m = NULL;
344         int r;
345
346         r = method_create_or_register_machine(manager, message, read_network, &m, error);
347         if (r < 0)
348                 return r;
349
350         r = cg_pid_get_unit(m->leader, &m->unit);
351         if (r < 0) {
352                 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
353                 goto fail;
354         }
355
356         m->registered = true;
357
358         r = machine_start(m, NULL, error);
359         if (r < 0)
360                 goto fail;
361
362         p = machine_bus_path(m);
363         if (!p) {
364                 r = -ENOMEM;
365                 goto fail;
366         }
367
368         return sd_bus_reply_method_return(message, "o", p);
369
370 fail:
371         machine_add_to_gc_queue(m);
372         return r;
373 }
374
375 static int method_register_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
376         return method_register_machine_internal(bus, message, true, userdata, error);
377 }
378
379 static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
380         return method_register_machine_internal(bus, message, false, userdata, error);
381 }
382
383 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
384         Manager *m = userdata;
385         Machine *machine;
386         const char *name;
387         int r;
388
389         assert(bus);
390         assert(message);
391         assert(m);
392
393         r = sd_bus_message_read(message, "s", &name);
394         if (r < 0)
395                 return sd_bus_error_set_errno(error, r);
396
397         machine = hashmap_get(m->machines, name);
398         if (!machine)
399                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
400
401         return bus_machine_method_terminate(bus, message, machine, error);
402 }
403
404 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
405         Manager *m = userdata;
406         Machine *machine;
407         const char *name;
408         int r;
409
410         assert(bus);
411         assert(message);
412         assert(m);
413
414         r = sd_bus_message_read(message, "s", &name);
415         if (r < 0)
416                 return sd_bus_error_set_errno(error, r);
417
418         machine = hashmap_get(m->machines, name);
419         if (!machine)
420                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
421
422         return bus_machine_method_kill(bus, message, machine, error);
423 }
424
425 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
426         Manager *m = userdata;
427         Machine *machine;
428         const char *name;
429         int r;
430
431         assert(bus);
432         assert(message);
433         assert(m);
434
435         r = sd_bus_message_read(message, "s", &name);
436         if (r < 0)
437                 return sd_bus_error_set_errno(error, r);
438
439         machine = hashmap_get(m->machines, name);
440         if (!machine)
441                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
442
443         return bus_machine_method_get_addresses(bus, message, machine, error);
444 }
445
446 static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
447         Manager *m = userdata;
448         Machine *machine;
449         const char *name;
450         int r;
451
452         assert(bus);
453         assert(message);
454         assert(m);
455
456         r = sd_bus_message_read(message, "s", &name);
457         if (r < 0)
458                 return sd_bus_error_set_errno(error, r);
459
460         machine = hashmap_get(m->machines, name);
461         if (!machine)
462                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
463
464         return bus_machine_method_get_os_release(bus, message, machine, error);
465 }
466
467 static int method_list_images(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
468         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
469         _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
470         Manager *m = userdata;
471         Image *image;
472         Iterator i;
473         int r;
474
475         assert(bus);
476         assert(message);
477         assert(m);
478
479         images = hashmap_new(&string_hash_ops);
480         if (!images)
481                 return -ENOMEM;
482
483         r = image_discover(images);
484         if (r < 0)
485                 return r;
486
487         r = sd_bus_message_new_method_return(message, &reply);
488         if (r < 0)
489                 return r;
490
491         r = sd_bus_message_open_container(reply, 'a', "(ssbo)");
492         if (r < 0)
493                 return r;
494
495         HASHMAP_FOREACH(image, images, i) {
496                 _cleanup_free_ char *p = NULL;
497
498                 p = image_bus_path(image->name);
499                 if (!p)
500                         return -ENOMEM;
501
502                 r = sd_bus_message_append(reply, "(ssbo)",
503                                           image->name,
504                                           image_type_to_string(image->type),
505                                           image->read_only,
506                                           p);
507                 if (r < 0)
508                         return r;
509         }
510
511         r = sd_bus_message_close_container(reply);
512         if (r < 0)
513                 return r;
514
515         return sd_bus_send(bus, reply, NULL);
516 }
517
518 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
519         Manager *m = userdata;
520         Machine *machine;
521         const char *name;
522         int r;
523
524         assert(bus);
525         assert(message);
526         assert(m);
527
528         r = sd_bus_message_read(message, "s", &name);
529         if (r < 0)
530                 return sd_bus_error_set_errno(error, r);
531
532         machine = hashmap_get(m->machines, name);
533         if (!machine)
534                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
535
536         return bus_machine_method_open_pty(bus, message, machine, error);
537 }
538
539 static int method_open_machine_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
540         Manager *m = userdata;
541         Machine *machine;
542         const char *name;
543         int r;
544
545         assert(bus);
546         assert(message);
547         assert(m);
548
549         r = sd_bus_message_read(message, "s", &name);
550         if (r < 0)
551                 return sd_bus_error_set_errno(error, r);
552
553         machine = hashmap_get(m->machines, name);
554         if (!machine)
555                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
556
557         return bus_machine_method_open_login(bus, message, machine, error);
558 }
559
560 const sd_bus_vtable manager_vtable[] = {
561         SD_BUS_VTABLE_START(0),
562         SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
563         SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
564         SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
565         SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
566         SD_BUS_METHOD("ListImages", NULL, "a(ssbo)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
567         SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
568         SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
569         SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
570         SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
571         SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
572         SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
573         SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
574         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
575         SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
576         SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
577         SD_BUS_SIGNAL("MachineNew", "so", 0),
578         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
579         SD_BUS_VTABLE_END
580 };
581
582 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
583         const char *path, *result, *unit;
584         Manager *m = userdata;
585         Machine *machine;
586         uint32_t id;
587         int r;
588
589         assert(bus);
590         assert(message);
591         assert(m);
592
593         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
594         if (r < 0) {
595                 bus_log_parse_error(r);
596                 return r;
597         }
598
599         machine = hashmap_get(m->machine_units, unit);
600         if (!machine)
601                 return 0;
602
603         if (streq_ptr(path, machine->scope_job)) {
604                 free(machine->scope_job);
605                 machine->scope_job = NULL;
606
607                 if (machine->started) {
608                         if (streq(result, "done"))
609                                 machine_send_create_reply(machine, NULL);
610                         else {
611                                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
612
613                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
614
615                                 machine_send_create_reply(machine, &e);
616                         }
617                 } else
618                         machine_save(machine);
619         }
620
621         machine_add_to_gc_queue(machine);
622         return 0;
623 }
624
625 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
626         _cleanup_free_ char *unit = NULL;
627         Manager *m = userdata;
628         Machine *machine;
629         const char *path;
630         int r;
631
632         assert(bus);
633         assert(message);
634         assert(m);
635
636         path = sd_bus_message_get_path(message);
637         if (!path)
638                 return 0;
639
640         r = unit_name_from_dbus_path(path, &unit);
641         if (r < 0)
642                 return r;
643
644         machine = hashmap_get(m->machine_units, unit);
645         if (machine)
646                 machine_add_to_gc_queue(machine);
647
648         return 0;
649 }
650
651 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
652         const char *path, *unit;
653         Manager *m = userdata;
654         Machine *machine;
655         int r;
656
657         assert(bus);
658         assert(message);
659         assert(m);
660
661         r = sd_bus_message_read(message, "so", &unit, &path);
662         if (r < 0) {
663                 bus_log_parse_error(r);
664                 return r;
665         }
666
667         machine = hashmap_get(m->machine_units, unit);
668         if (machine)
669                 machine_add_to_gc_queue(machine);
670
671         return 0;
672 }
673
674 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
675         Manager *m = userdata;
676         Machine *machine;
677         Iterator i;
678         int b, r;
679
680         assert(bus);
681
682         r = sd_bus_message_read(message, "b", &b);
683         if (r < 0) {
684                 bus_log_parse_error(r);
685                 return r;
686         }
687         if (b)
688                 return 0;
689
690         /* systemd finished reloading, let's recheck all our machines */
691         log_debug("System manager has been reloaded, rechecking machines...");
692
693         HASHMAP_FOREACH(machine, m->machines, i)
694                 machine_add_to_gc_queue(machine);
695
696         return 0;
697 }
698
699 int manager_start_scope(
700                 Manager *manager,
701                 const char *scope,
702                 pid_t pid,
703                 const char *slice,
704                 const char *description,
705                 sd_bus_message *more_properties,
706                 sd_bus_error *error,
707                 char **job) {
708
709         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
710         int r;
711
712         assert(manager);
713         assert(scope);
714         assert(pid > 1);
715
716         r = sd_bus_message_new_method_call(
717                         manager->bus,
718                         &m,
719                         "org.freedesktop.systemd1",
720                         "/org/freedesktop/systemd1",
721                         "org.freedesktop.systemd1.Manager",
722                         "StartTransientUnit");
723         if (r < 0)
724                 return r;
725
726         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
727         if (r < 0)
728                 return r;
729
730         r = sd_bus_message_open_container(m, 'a', "(sv)");
731         if (r < 0)
732                 return r;
733
734         if (!isempty(slice)) {
735                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
736                 if (r < 0)
737                         return r;
738         }
739
740         if (!isempty(description)) {
741                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
742                 if (r < 0)
743                         return r;
744         }
745
746         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
747         if (r < 0)
748                 return r;
749
750         r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
751         if (r < 0)
752                 return r;
753
754         if (more_properties) {
755                 r = sd_bus_message_copy(m, more_properties, true);
756                 if (r < 0)
757                         return r;
758         }
759
760         r = sd_bus_message_close_container(m);
761         if (r < 0)
762                 return r;
763
764         r = sd_bus_message_append(m, "a(sa(sv))", 0);
765         if (r < 0)
766                 return r;
767
768         r = sd_bus_call(manager->bus, m, 0, error, &reply);
769         if (r < 0)
770                 return r;
771
772         if (job) {
773                 const char *j;
774                 char *copy;
775
776                 r = sd_bus_message_read(reply, "o", &j);
777                 if (r < 0)
778                         return r;
779
780                 copy = strdup(j);
781                 if (!copy)
782                         return -ENOMEM;
783
784                 *job = copy;
785         }
786
787         return 1;
788 }
789
790 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
791         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
792         int r;
793
794         assert(manager);
795         assert(unit);
796
797         r = sd_bus_call_method(
798                         manager->bus,
799                         "org.freedesktop.systemd1",
800                         "/org/freedesktop/systemd1",
801                         "org.freedesktop.systemd1.Manager",
802                         "StopUnit",
803                         error,
804                         &reply,
805                         "ss", unit, "fail");
806         if (r < 0) {
807                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
808                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
809
810                         if (job)
811                                 *job = NULL;
812
813                         sd_bus_error_free(error);
814                         return 0;
815                 }
816
817                 return r;
818         }
819
820         if (job) {
821                 const char *j;
822                 char *copy;
823
824                 r = sd_bus_message_read(reply, "o", &j);
825                 if (r < 0)
826                         return r;
827
828                 copy = strdup(j);
829                 if (!copy)
830                         return -ENOMEM;
831
832                 *job = copy;
833         }
834
835         return 1;
836 }
837
838 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
839         assert(manager);
840         assert(unit);
841
842         return sd_bus_call_method(
843                         manager->bus,
844                         "org.freedesktop.systemd1",
845                         "/org/freedesktop/systemd1",
846                         "org.freedesktop.systemd1.Manager",
847                         "KillUnit",
848                         error,
849                         NULL,
850                         "ssi", unit, "all", signo);
851 }
852
853 int manager_unit_is_active(Manager *manager, const char *unit) {
854         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
855         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
856         _cleanup_free_ char *path = NULL;
857         const char *state;
858         int r;
859
860         assert(manager);
861         assert(unit);
862
863         path = unit_dbus_path_from_name(unit);
864         if (!path)
865                 return -ENOMEM;
866
867         r = sd_bus_get_property(
868                         manager->bus,
869                         "org.freedesktop.systemd1",
870                         path,
871                         "org.freedesktop.systemd1.Unit",
872                         "ActiveState",
873                         &error,
874                         &reply,
875                         "s");
876         if (r < 0) {
877                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
878                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
879                         return true;
880
881                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
882                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
883                         return false;
884
885                 return r;
886         }
887
888         r = sd_bus_message_read(reply, "s", &state);
889         if (r < 0)
890                 return -EINVAL;
891
892         return !streq(state, "inactive") && !streq(state, "failed");
893 }
894
895 int manager_job_is_active(Manager *manager, const char *path) {
896         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
897         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
898         int r;
899
900         assert(manager);
901         assert(path);
902
903         r = sd_bus_get_property(
904                         manager->bus,
905                         "org.freedesktop.systemd1",
906                         path,
907                         "org.freedesktop.systemd1.Job",
908                         "State",
909                         &error,
910                         &reply,
911                         "s");
912         if (r < 0) {
913                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
914                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
915                         return true;
916
917                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
918                         return false;
919
920                 return r;
921         }
922
923         /* We don't actually care about the state really. The fact
924          * that we could read the job state is enough for us */
925
926         return true;
927 }
928
929 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
930         _cleanup_free_ char *unit = NULL;
931         Machine *mm;
932         int r;
933
934         assert(m);
935         assert(pid >= 1);
936         assert(machine);
937
938         r = cg_pid_get_unit(pid, &unit);
939         if (r < 0)
940                 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
941         else
942                 mm = hashmap_get(m->machine_units, unit);
943
944         if (!mm)
945                 return 0;
946
947         *machine = mm;
948         return 1;
949 }
950
951 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
952         Machine *machine;
953
954         assert(m);
955         assert(name);
956
957         machine = hashmap_get(m->machines, name);
958         if (!machine) {
959                 machine = machine_new(m, name);
960                 if (!machine)
961                         return -ENOMEM;
962         }
963
964         if (_machine)
965                 *_machine = machine;
966
967         return 0;
968 }