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