]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/machine/machined-dbus.c
mount-util: fix typo
[thirdparty/systemd.git] / src / machine / machined-dbus.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
1ee306e1 2
1ee306e1 3#include <unistd.h>
1ee306e1 4
64943cac 5#include "sd-bus.h"
c3350683 6#include "sd-id128.h"
3ffd4af2 7
b5efdb8a 8#include "alloc-util.h"
96aad8d1 9#include "bus-common-errors.h"
9b71e4ab 10#include "bus-locator.h"
ab33edb0 11#include "bus-message-util.h"
64943cac 12#include "bus-object.h"
269e4d2d 13#include "bus-polkit.h"
ff43267c 14#include "bus-util.h"
23c80348 15#include "cgroup-util.h"
57f1b61b 16#include "discover-image.h"
66855de7 17#include "errno-util.h"
3ffd4af2 18#include "fd-util.h"
03c2b288 19#include "fileio.h"
f97b34a6 20#include "format-util.h"
64943cac 21#include "hashmap.h"
25300b5a 22#include "hostname-util.h"
5a99c9d7 23#include "image.h"
3ffd4af2 24#include "image-dbus.h"
a90fb858 25#include "io-util.h"
1cf40697 26#include "machine.h"
3ffd4af2 27#include "machine-dbus.h"
c3350683 28#include "machined.h"
119d332d 29#include "namespace-util.h"
ff43267c 30#include "operation.h"
6ef06723 31#include "os-util.h"
3ffd4af2 32#include "path-util.h"
d80af3b9 33#include "socket-util.h"
64943cac 34#include "string-util.h"
3ffd4af2 35#include "strv.h"
64943cac 36#include "unit-def.h"
b1d4f8e1 37#include "user-util.h"
1ee306e1 38
1075316a
DDM
39static int property_get_pool_path(
40 sd_bus *bus,
41 const char *path,
42 const char *interface,
43 const char *property,
44 sd_bus_message *reply,
45 void *userdata,
46 sd_bus_error *error) {
47
48 _cleanup_free_ char *poolpath = NULL;
49 Manager *m = ASSERT_PTR(userdata);
50
51 assert(bus);
52 assert(reply);
53
54 (void) image_get_pool_path(m->runtime_scope, IMAGE_MACHINE, &poolpath);
55
56 return sd_bus_message_append(reply, "s", strempty(poolpath));
57}
160e3793
LP
58
59static int property_get_pool_usage(
60 sd_bus *bus,
61 const char *path,
62 const char *interface,
63 const char *property,
64 sd_bus_message *reply,
65 void *userdata,
66 sd_bus_error *error) {
67
1075316a 68 Manager *m = ASSERT_PTR(userdata);
f5fbe71d 69 uint64_t usage = UINT64_MAX;
160e3793
LP
70
71 assert(bus);
72 assert(reply);
73
1075316a 74 (void) image_get_pool_usage(m->runtime_scope, IMAGE_MACHINE, &usage);
160e3793 75
160e3793
LP
76 return sd_bus_message_append(reply, "t", usage);
77}
78
79static int property_get_pool_limit(
80 sd_bus *bus,
81 const char *path,
82 const char *interface,
83 const char *property,
84 sd_bus_message *reply,
85 void *userdata,
86 sd_bus_error *error) {
87
1075316a 88 Manager *m = ASSERT_PTR(userdata);
f5fbe71d 89 uint64_t size = UINT64_MAX;
160e3793
LP
90
91 assert(bus);
92 assert(reply);
93
1075316a 94 (void) image_get_pool_limit(m->runtime_scope, IMAGE_MACHINE, &size);
160e3793 95
160e3793
LP
96 return sd_bus_message_append(reply, "t", size);
97}
98
19070062 99static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683 100 _cleanup_free_ char *p = NULL;
99534007 101 Manager *m = ASSERT_PTR(userdata);
c3350683
LP
102 Machine *machine;
103 const char *name;
104 int r;
105
c3350683 106 assert(message);
c3350683
LP
107
108 r = sd_bus_message_read(message, "s", &name);
109 if (r < 0)
ebcf1f97 110 return r;
c3350683
LP
111
112 machine = hashmap_get(m->machines, name);
113 if (!machine)
ebcf1f97 114 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
c3350683
LP
115
116 p = machine_bus_path(machine);
117 if (!p)
ebcf1f97 118 return -ENOMEM;
c3350683 119
df2d202e 120 return sd_bus_reply_method_return(message, "o", p);
c3350683
LP
121}
122
19070062 123static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c2ce6a3d 124 _cleanup_free_ char *p = NULL;
99534007 125 _unused_ Manager *m = ASSERT_PTR(userdata);
c2ce6a3d
LP
126 const char *name;
127 int r;
128
c2ce6a3d 129 assert(message);
c2ce6a3d
LP
130
131 r = sd_bus_message_read(message, "s", &name);
132 if (r < 0)
133 return r;
134
1c0ade2e 135 r = image_find(m->runtime_scope, IMAGE_MACHINE, name, NULL, NULL);
3a6ce860 136 if (r == -ENOENT)
c2ce6a3d
LP
137 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
138 if (r < 0)
139 return r;
140
141 p = image_bus_path(name);
142 if (!p)
143 return -ENOMEM;
144
145 return sd_bus_reply_method_return(message, "o", p);
146}
147
19070062 148static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
f6cb4d4a 149 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
c3350683 150 _cleanup_free_ char *p = NULL;
99534007 151 Manager *m = ASSERT_PTR(userdata);
c3350683 152 Machine *machine = NULL;
4e724d9c 153 pid_t pid;
c3350683
LP
154 int r;
155
c3350683 156 assert(message);
c3350683 157
4e724d9c
LP
158 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
159
c3350683
LP
160 r = sd_bus_message_read(message, "u", &pid);
161 if (r < 0)
ebcf1f97 162 return r;
c3350683 163
07b38ba5 164 if (pid < 0)
06820eaf
LP
165 return -EINVAL;
166
f6cb4d4a
IK
167 pidref = PIDREF_MAKE_FROM_PID(pid);
168
4e724d9c 169 if (pid == 0) {
4afd3348 170 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
5b12334d 171
f6cb4d4a 172 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD, &creds);
5b12334d
LP
173 if (r < 0)
174 return r;
175
f6cb4d4a 176 r = bus_creds_get_pidref(creds, &pidref);
4e724d9c 177 if (r < 0)
ebcf1f97 178 return r;
4e724d9c
LP
179 }
180
f6cb4d4a 181 r = manager_get_machine_by_pidref(m, &pidref, &machine);
c3350683 182 if (r < 0)
ebcf1f97 183 return r;
85ab917b 184 if (r == 0)
de0671ee 185 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
c3350683
LP
186
187 p = machine_bus_path(machine);
188 if (!p)
ebcf1f97 189 return -ENOMEM;
c3350683 190
df2d202e 191 return sd_bus_reply_method_return(message, "o", p);
c3350683
LP
192}
193
19070062 194static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 195 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
99534007 196 Manager *m = ASSERT_PTR(userdata);
c3350683 197 Machine *machine;
c3350683
LP
198 int r;
199
c3350683 200 assert(message);
c3350683 201
df2d202e 202 r = sd_bus_message_new_method_return(message, &reply);
c3350683 203 if (r < 0)
ebcf1f97 204 return sd_bus_error_set_errno(error, r);
c3350683
LP
205
206 r = sd_bus_message_open_container(reply, 'a', "(ssso)");
207 if (r < 0)
ebcf1f97 208 return sd_bus_error_set_errno(error, r);
c3350683 209
90e74a66 210 HASHMAP_FOREACH(machine, m->machines) {
c3350683
LP
211 _cleanup_free_ char *p = NULL;
212
213 p = machine_bus_path(machine);
214 if (!p)
ebcf1f97 215 return -ENOMEM;
c3350683
LP
216
217 r = sd_bus_message_append(reply, "(ssso)",
218 machine->name,
219 strempty(machine_class_to_string(machine->class)),
220 machine->service,
221 p);
222 if (r < 0)
ebcf1f97 223 return sd_bus_error_set_errno(error, r);
c3350683 224 }
1ee306e1 225
c3350683
LP
226 r = sd_bus_message_close_container(reply);
227 if (r < 0)
ebcf1f97 228 return sd_bus_error_set_errno(error, r);
c3350683 229
51cc3825 230 return sd_bus_message_send(reply);
c3350683
LP
231}
232
d80af3b9
LB
233static int machine_add_from_params(
234 Manager *manager,
235 sd_bus_message *message,
236 const char *polkit_action,
237 const char *name,
238 MachineClass c,
239 sd_id128_t id,
240 const char *service,
241 PidRef *leader_pidref,
242 PidRef *supervisor_pidref,
243 const char *root_directory,
244 const int32_t *netif,
245 size_t n_netif,
246 unsigned cid,
247 const char *ssh_address,
248 const char *ssh_private_key_path,
249 Machine **ret,
250 sd_bus_error *error) {
251
252 Machine *m;
253 int r;
254
255 assert(manager);
256 assert(message);
257 assert(name);
258 assert(ret);
259
260 if (leader_pidref->pid == 1)
261 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
262 if (supervisor_pidref->pid == 1)
263 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supervisor PID");
264
265 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
266 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
267 if (r < 0)
268 return r;
269
270 uid_t uid;
271 r = sd_bus_creds_get_euid(creds, &uid);
272 if (r < 0)
273 return r;
274
275 /* Ensure an unprivileged user cannot claim any process they don't control as their own machine */
722dc736
LP
276 switch (manager->runtime_scope) {
277
278 case RUNTIME_SCOPE_SYSTEM:
279 /* In system mode root may register anything */
280 if (uid == 0)
281 break;
282
283 /* And non-root may only register things if they own the userns */
d80af3b9
LB
284 r = process_is_owned_by_uid(leader_pidref, uid);
285 if (r < 0)
286 return r;
722dc736
LP
287 if (r > 0)
288 break;
289
290 /* Nothing else may */
291 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only root may register machines for other users");
292
293 case RUNTIME_SCOPE_USER:
294 /* In user mode the user owning our instance may register anything. */
295 if (uid == getuid())
296 break;
297
298 /* Nothing else may */
299 return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Other users may not register machines with us, sorry.");
300
301 default:
302 assert_not_reached();
d80af3b9
LB
303 }
304
f5fa86f9
LP
305 if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
306 const char *details[] = {
307 "name", name,
308 "class", machine_class_to_string(c),
309 NULL
310 };
311
312 r = bus_verify_polkit_async(
313 message,
314 polkit_action,
315 details,
316 &manager->polkit_registry,
317 error);
318 if (r < 0)
319 return r;
320 if (r == 0)
321 return 0; /* Will call us back */
322 }
d80af3b9
LB
323
324 r = manager_add_machine(manager, name, &m);
325 if (r < 0)
326 return r;
327
328 m->leader = TAKE_PIDREF(*leader_pidref);
329 m->supervisor = TAKE_PIDREF(*supervisor_pidref);
330 m->class = c;
331 m->id = id;
332 m->uid = uid;
333 m->vsock_cid = cid;
334
335 if (!isempty(service)) {
336 m->service = strdup(service);
337 if (!m->service) {
338 r = -ENOMEM;
339 goto fail;
340 }
341 }
342
343 if (!isempty(root_directory)) {
344 m->root_directory = strdup(root_directory);
345 if (!m->root_directory) {
346 r = -ENOMEM;
347 goto fail;
348 }
349 }
350
351 if (n_netif > 0) {
352 assert_cc(sizeof(int32_t) == sizeof(int));
353 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
354 if (!m->netif) {
355 r = -ENOMEM;
356 goto fail;
357 }
358
359 m->n_netif = n_netif;
360 }
361
362 if (!isempty(ssh_address)) {
363 m->ssh_address = strdup(ssh_address);
364 if (!m->ssh_address) {
365 r = -ENOMEM;
366 goto fail;
367 }
368 }
369
370 if (!isempty(ssh_private_key_path)) {
371 m->ssh_private_key_path = strdup(ssh_private_key_path);
372 if (!m->ssh_private_key_path) {
373 r = -ENOMEM;
374 goto fail;
375 }
376 }
377
378 *ret = m;
379 return 1;
380
381fail:
382 machine_add_to_gc_queue(m);
383 return r;
384}
385
4198ff4c
LP
386static int method_create_or_register_machine(
387 Manager *manager,
388 sd_bus_message *message,
adaff8eb 389 const char *polkit_action,
4198ff4c
LP
390 Machine **ret,
391 sd_bus_error *error) {
392
97754cd1 393 _cleanup_(pidref_done) PidRef leader_pidref = PIDREF_NULL, supervisor_pidref = PIDREF_NULL;
8aec412f 394 const char *name, *service, *class, *root_directory;
9b5ed6fe 395 const int32_t *netif = NULL;
1ee306e1
LP
396 MachineClass c;
397 uint32_t leader;
398 sd_id128_t id;
4db747b0 399 size_t n_netif = 0;
c3350683 400 int r;
1ee306e1 401
c3350683 402 assert(manager);
89f7c846 403 assert(message);
4198ff4c 404 assert(ret);
1ee306e1 405
c3350683
LP
406 r = sd_bus_message_read(message, "s", &name);
407 if (r < 0)
ebcf1f97 408 return r;
52ef5dd7 409 if (!hostname_is_valid(name, 0))
1b09b81c 410 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
1ee306e1 411
4db747b0 412 r = bus_message_read_id128(message, &id);
c3350683 413 if (r < 0)
1b09b81c 414 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
1ee306e1 415
c3350683
LP
416 r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
417 if (r < 0)
ebcf1f97 418 return r;
1ee306e1 419
d80af3b9 420 if (endswith(sd_bus_message_get_member(message), "WithNetwork")) {
9b5ed6fe
LP
421 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
422 if (r < 0)
423 return r;
424
425 n_netif /= sizeof(int32_t);
426
d007c583 427 for (size_t i = 0; i < n_netif; i++) {
9b5ed6fe
LP
428 if (netif[i] <= 0)
429 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
430 }
431 }
432
1ee306e1
LP
433 if (isempty(class))
434 c = _MACHINE_CLASS_INVALID;
435 else {
436 c = machine_class_from_string(class);
437 if (c < 0)
1b09b81c 438 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
1ee306e1
LP
439 }
440
c3350683 441 if (leader == 1)
1b09b81c 442 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
1ee306e1 443
0c18c0de 444 if (!isempty(root_directory) && (!path_is_absolute(root_directory) || !path_is_valid(root_directory)))
1b09b81c 445 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
1ee306e1 446
c3350683 447 if (leader == 0) {
97754cd1
LP
448 /* If no PID is specified, the client is the leader */
449 r = bus_query_sender_pidref(message, &leader_pidref);
5b12334d 450 if (r < 0)
92a6f214
LP
451 return sd_bus_error_set_errnof(error, r, "Failed to pin client process: %m");
452 } else {
97754cd1
LP
453 /* If a PID is specified that's the leader, but if the client process is different from it, than that's the supervisor */
454 r = pidref_set_pid(&leader_pidref, leader);
c3350683 455 if (r < 0)
92a6f214 456 return sd_bus_error_set_errnof(error, r, "Failed to pin process " PID_FMT ": %m", (pid_t) leader);
97754cd1
LP
457
458 _cleanup_(pidref_done) PidRef client_pidref = PIDREF_NULL;
459 r = bus_query_sender_pidref(message, &client_pidref);
460 if (r < 0)
461 return sd_bus_error_set_errnof(error, r, "Failed to pin client process: %m");
462
463 if (!pidref_equal(&client_pidref, &leader_pidref))
464 supervisor_pidref = TAKE_PIDREF(client_pidref);
c3350683 465 }
554604b3 466
1ee306e1 467 if (hashmap_get(manager->machines, name))
ebcf1f97 468 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
1ee306e1 469
d80af3b9
LB
470 return machine_add_from_params(
471 manager,
472 message,
473 polkit_action,
474 name,
475 c,
476 id,
477 service,
478 &leader_pidref,
479 &supervisor_pidref,
480 root_directory,
481 netif,
482 n_netif,
483 /* cid= */ 0,
484 /* ssh_address= */ NULL,
485 /* ssh_private_key_path= */ NULL,
486 ret,
487 error);
488}
489
490static int method_create_or_register_machine_ex(
491 Manager *manager,
492 sd_bus_message *message,
493 const char *polkit_action,
494 Machine **ret,
495 sd_bus_error *error) {
496
497 const char *name = NULL, *service = NULL, *class = NULL, *root_directory = NULL, *ssh_address = NULL, *ssh_private_key_path = NULL;
498 _cleanup_(pidref_done) PidRef leader_pidref = PIDREF_NULL, supervisor_pidref = PIDREF_NULL;
499 sd_id128_t id = SD_ID128_NULL;
500 const int32_t *netif = NULL;
501 size_t n_netif = 0;
502 unsigned cid = 0;
503 MachineClass c;
504 uint64_t leader_pidfdid = 0;
505 uint32_t leader_pid = 0;
506 int r, leader_pidfd = -EBADF;
507
508 assert(manager);
509 assert(message);
510 assert(ret);
511
512 r = sd_bus_message_read(message, "s", &name);
276d2001
LP
513 if (r < 0)
514 return r;
d80af3b9
LB
515 if (!hostname_is_valid(name, 0))
516 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
276d2001 517
d80af3b9 518 r = sd_bus_message_enter_container(message, 'a', "(sv)");
276d2001
LP
519 if (r < 0)
520 return r;
521
d80af3b9
LB
522 for (;;) {
523 const char *key;
524
525 r = sd_bus_message_enter_container(message, 'r', "sv");
119d332d
LB
526 if (r < 0)
527 return r;
528 if (r == 0)
d80af3b9 529 break;
119d332d 530
d80af3b9
LB
531 r = sd_bus_message_read(message, "s", &key);
532 if (r < 0)
533 return r;
790f5162 534
d80af3b9
LB
535 r = sd_bus_message_enter_container(message, 'v', NULL);
536 if (r < 0)
537 return r;
790f5162 538
d80af3b9
LB
539 if (streq(key, "Id")) {
540 r = bus_message_read_id128(message, &id);
541 if (r < 0)
542 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
543 } else if (streq(key, "Service")) {
544 r = sd_bus_message_read(message, "s", &service);
545 if (r < 0)
546 return r;
547 } else if (streq(key, "Class")) {
548 r = sd_bus_message_read(message, "s", &class);
549 if (r < 0)
550 return r;
551 } else if (streq(key, "LeaderPID")) {
552 r = sd_bus_message_read(message, "u", &leader_pid);
553 if (r < 0)
554 return r;
555 } else if (streq(key, "LeaderPIDFD")) {
556 r = sd_bus_message_read(message, "h", &leader_pidfd);
557 if (r < 0)
558 return r;
559 } else if (streq(key, "LeaderPIDFDID")) {
560 r = sd_bus_message_read(message, "t", &leader_pidfdid);
561 if (r < 0)
562 return r;
563 } else if (streq(key, "RootDirectory")) {
564 r = sd_bus_message_read(message, "s", &root_directory);
565 if (r < 0)
566 return r;
567 } else if (streq(key, "NetworkInterfaces")) {
568 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
569 if (r < 0)
570 return r;
571
572 n_netif /= sizeof(int32_t);
573
574 for (size_t i = 0; i < n_netif; i++)
575 if (netif[i] <= 0)
576 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
577 } else if (streq(key, "VSockCID")) {
578 r = sd_bus_message_read(message, "u", &cid);
579 if (r < 0)
580 return r;
581
582 if (!VSOCK_CID_IS_REGULAR(cid))
583 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "JSON field 'vSockCid' is not a regular VSOCK CID.");
584 } else if (streq(key, "SSHAddress")) {
585 r = sd_bus_message_read(message, "s", &ssh_address);
586 if (r < 0)
587 return r;
588 } else if (streq(key, "SSHPrivateKeyPath")) {
589 r = sd_bus_message_read(message, "s", &ssh_private_key_path);
590 if (r < 0)
591 return r;
592 } else
593 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown property '%s'", key);
594
595 r = sd_bus_message_exit_container(message);
596 if (r < 0)
597 return r;
598
599 r = sd_bus_message_exit_container(message);
600 if (r < 0)
601 return r;
602 }
603
604 r = sd_bus_message_exit_container(message);
1ee306e1 605 if (r < 0)
ebcf1f97 606 return r;
1ee306e1 607
d80af3b9
LB
608 if (isempty(class))
609 c = _MACHINE_CLASS_INVALID;
610 else {
611 c = machine_class_from_string(class);
612 if (c < 0)
613 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
1ee306e1
LP
614 }
615
d80af3b9
LB
616 if (!isempty(root_directory) && (!path_is_absolute(root_directory) || !path_is_valid(root_directory)))
617 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
1ee306e1 618
d80af3b9
LB
619 if (hashmap_get(manager->machines, name))
620 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
621
622 /* If a PID is specified that's the leader, but if the client process is different from it, than that's the supervisor */
623 if (leader_pidfd >= 0) {
624 r = pidref_set_pidfd(&leader_pidref, leader_pidfd);
625 if (r < 0)
626 return sd_bus_error_set_errnof(error, r, "Failed to parse PIDFD %d: %m", leader_pidfd);
627
628 if (leader_pid > 0 && leader_pidref.pid != (pid_t) leader_pid)
629 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "LeaderPID and LeaderPIDFD refer to different processes");
630 if (leader_pidfdid > 0) {
631 r = pidref_acquire_pidfd_id(&leader_pidref);
632 if (r >= 0 && leader_pidref.fd_id != leader_pidfdid)
633 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "LeaderPIDFDID does not match the inode number of LeaderPIDFD");
9b5ed6fe 634 }
d80af3b9
LB
635 } else if (leader_pid > 0 && leader_pidfdid > 0) {
636 r = pidref_set_pid_and_pidfd_id(&leader_pidref, leader_pid, leader_pidfdid);
637 if (r < 0)
638 return sd_bus_error_set_errnof(error, r, "Failed to pin process " PID_FMT " by PIDFDID %" PRIu64 ": %m", (pid_t) leader_pid, leader_pidfdid);
639 } else if (leader_pid > 0 || leader_pidfdid > 0)
640 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Both LeaderPID and LeaderPIDFDID must be specified to identify the leader process by PIDFDID");
9b5ed6fe 641
d80af3b9
LB
642 if (pidref_is_set(&leader_pidref)) {
643 _cleanup_(pidref_done) PidRef client_pidref = PIDREF_NULL;
644 r = bus_query_sender_pidref(message, &client_pidref);
645 if (r < 0)
646 return sd_bus_error_set_errnof(error, r, "Failed to pin client process: %m");
9b5ed6fe 647
d80af3b9
LB
648 if (!pidref_equal(&client_pidref, &leader_pidref))
649 supervisor_pidref = TAKE_PIDREF(client_pidref);
650 } else {
651 /* If no PID is specified, the client is the leader */
652 r = bus_query_sender_pidref(message, &leader_pidref);
653 if (r < 0)
654 return sd_bus_error_set_errnof(error, r, "Failed to pin client process: %m");
655 }
89f7c846 656
d80af3b9
LB
657 return machine_add_from_params(
658 manager,
659 message,
660 polkit_action,
661 name,
662 c,
663 id,
664 service,
665 &leader_pidref,
666 &supervisor_pidref,
667 root_directory,
668 netif,
669 n_netif,
670 cid,
671 ssh_address,
672 ssh_private_key_path,
673 ret,
674 error);
89f7c846
LP
675}
676
d80af3b9 677static int method_create_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 678 Manager *manager = ASSERT_PTR(userdata);
89f7c846
LP
679 Machine *m = NULL;
680 int r;
681
19070062 682 assert(message);
19070062 683
d80af3b9
LB
684 if (sd_bus_message_is_method_call(message, NULL, "CreateMachineEx"))
685 r = method_create_or_register_machine_ex(manager, message, "org.freedesktop.machine1.create-machines", &m, error);
686 else
687 r = method_create_or_register_machine(manager, message, "org.freedesktop.machine1.create-machine", &m, error);
89f7c846
LP
688 if (r < 0)
689 return r;
790f5162
LP
690 if (r == 0)
691 return 1; /* Will call us back */
89f7c846
LP
692
693 r = sd_bus_message_enter_container(message, 'a', "(sv)");
694 if (r < 0)
695 goto fail;
696
ebcf1f97
LP
697 r = machine_start(m, message, error);
698 if (r < 0)
1ee306e1
LP
699 goto fail;
700
c3350683 701 m->create_message = sd_bus_message_ref(message);
c3350683 702 return 1;
1ee306e1
LP
703
704fail:
a3e7f417 705 machine_add_to_gc_queue(m);
89f7c846
LP
706 return r;
707}
1ee306e1 708
d80af3b9 709static int method_register_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 710 Manager *manager = ASSERT_PTR(userdata);
89f7c846
LP
711 _cleanup_free_ char *p = NULL;
712 Machine *m = NULL;
713 int r;
714
19070062 715 assert(message);
19070062 716
d80af3b9
LB
717 if (sd_bus_message_is_method_call(message, NULL, "RegisterMachineEx"))
718 r = method_create_or_register_machine_ex(manager, message, "org.freedesktop.machine1.register-machine", &m, error);
719 else
720 r = method_create_or_register_machine(manager, message, "org.freedesktop.machine1.register-machine", &m, error);
89f7c846
LP
721 if (r < 0)
722 return r;
790f5162
LP
723 if (r == 0)
724 return 1; /* Will call us back */
89f7c846 725
f5fa86f9
LP
726 switch (manager->runtime_scope) {
727 case RUNTIME_SCOPE_USER:
728 r = cg_pidref_get_user_unit_full(&m->leader, &m->unit, &m->subgroup);
729 break;
730
731 case RUNTIME_SCOPE_SYSTEM:
732 r = cg_pidref_get_unit_full(&m->leader, &m->unit, &m->subgroup);
733 break;
734
735 default:
736 assert_not_reached();
737 }
89f7c846 738 if (r < 0) {
048c386e
ZJS
739 r = sd_bus_error_set_errnof(error, r,
740 "Failed to determine unit of process "PID_FMT" : %m",
d8854ff1 741 m->leader.pid);
89f7c846
LP
742 goto fail;
743 }
744
74546a7e
LP
745 if (!empty_or_root(m->subgroup)) {
746 /* If this is not a top-level cgroup, then we need the cgroup path to be able to watch when
747 * it empties */
748
b525a72f 749 r = cg_pidref_get_path(&m->leader, &m->cgroup);
74546a7e
LP
750 if (r < 0) {
751 r = sd_bus_error_set_errnof(error, r,
752 "Failed to determine cgroup of process "PID_FMT" : %m",
753 m->leader.pid);
754 goto fail;
755 }
756 }
757
89f7c846
LP
758 r = machine_start(m, NULL, error);
759 if (r < 0)
760 goto fail;
761
762 p = machine_bus_path(m);
763 if (!p) {
764 r = -ENOMEM;
765 goto fail;
766 }
767
768 return sd_bus_reply_method_return(message, "o", p);
769
770fail:
771 machine_add_to_gc_queue(m);
1ee306e1
LP
772 return r;
773}
774
eecf0181 775static int redirect_method_to_machine(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) {
c3350683
LP
776 Machine *machine;
777 const char *name;
1ee306e1
LP
778 int r;
779
1ee306e1
LP
780 assert(message);
781 assert(m);
eecf0181 782 assert(method);
1ee306e1 783
c3350683
LP
784 r = sd_bus_message_read(message, "s", &name);
785 if (r < 0)
ebcf1f97 786 return sd_bus_error_set_errno(error, r);
1ee306e1 787
c3350683
LP
788 machine = hashmap_get(m->machines, name);
789 if (!machine)
ebcf1f97 790 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1ee306e1 791
eecf0181 792 return method(message, machine, error);
c3350683 793}
1ee306e1 794
ef8ff92e
ZJS
795static int method_unregister_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
796 return redirect_method_to_machine(message, userdata, error, bus_machine_method_unregister);
797}
798
eecf0181
LP
799static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
800 return redirect_method_to_machine(message, userdata, error, bus_machine_method_terminate);
801}
1ee306e1 802
eecf0181
LP
803static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
804 return redirect_method_to_machine(message, userdata, error, bus_machine_method_kill);
878cd7e9
LP
805}
806
19070062 807static int method_get_machine_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 808 return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_addresses);
c3350683 809}
1ee306e1 810
1f815bf1
SL
811static int method_get_machine_ssh_info(sd_bus_message *message, void *userdata, sd_bus_error *error) {
812 return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_ssh_info);
813}
814
19070062 815static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 816 return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_os_release);
717603e3
LP
817}
818
19070062 819static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 820 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
624d3698 821 Manager *m = ASSERT_PTR(userdata);
cd61c3bf
LP
822 int r;
823
cd61c3bf 824 assert(message);
cd61c3bf 825
624d3698
YW
826 _cleanup_hashmap_free_ Hashmap *images = NULL;
827 r = image_discover(m->runtime_scope, IMAGE_MACHINE, NULL, &images);
cd61c3bf
LP
828 if (r < 0)
829 return r;
830
831 r = sd_bus_message_new_method_return(message, &reply);
832 if (r < 0)
833 return r;
834
b6b18498 835 r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
cd61c3bf
LP
836 if (r < 0)
837 return r;
838
624d3698 839 Image *image;
90e74a66 840 HASHMAP_FOREACH(image, images) {
cd61c3bf
LP
841 _cleanup_free_ char *p = NULL;
842
843 p = image_bus_path(image->name);
844 if (!p)
845 return -ENOMEM;
846
b6b18498 847 r = sd_bus_message_append(reply, "(ssbttto)",
cd61c3bf
LP
848 image->name,
849 image_type_to_string(image->type),
ee327e08 850 image_is_read_only(image),
10f9c755
LP
851 image->crtime,
852 image->mtime,
c19de711 853 image->usage,
cd61c3bf
LP
854 p);
855 if (r < 0)
856 return r;
857 }
858
859 r = sd_bus_message_close_container(reply);
860 if (r < 0)
861 return r;
862
51cc3825 863 return sd_bus_message_send(reply);
cd61c3bf
LP
864}
865
19070062 866static int method_open_machine_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 867 return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_pty);
40205d70
LP
868}
869
19070062 870static int method_open_machine_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 871 return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_login);
5f8cc96a
LP
872}
873
49af9e13 874static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 875 return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_shell);
49af9e13
LP
876}
877
19070062 878static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 879 return redirect_method_to_machine(message, userdata, error, bus_machine_method_bind_mount);
90adaa25
LP
880}
881
19070062 882static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 883 return redirect_method_to_machine(message, userdata, error, bus_machine_method_copy);
0370612e
LP
884}
885
ae203207 886static int method_open_machine_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 887 return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_root_directory);
ae203207
LP
888}
889
3401419b 890static int method_get_machine_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) {
eecf0181 891 return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_uid_shift);
3401419b
LP
892}
893
9b06c1e1 894static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) {
08682124 895 const char *name;
c6aeb9b5 896 Image *i;
08682124
LP
897 int r;
898
08682124 899 assert(message);
9b06c1e1
LP
900 assert(m);
901 assert(method);
08682124
LP
902
903 r = sd_bus_message_read(message, "s", &name);
904 if (r < 0)
905 return r;
906
907 if (!image_name_is_valid(name))
908 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
909
c6aeb9b5 910 r = manager_acquire_image(m, name, &i);
3a6ce860
LP
911 if (r == -ENOENT)
912 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
08682124
LP
913 if (r < 0)
914 return r;
08682124 915
9b06c1e1 916 return method(message, i, error);
08682124
LP
917}
918
9b06c1e1
LP
919static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
920 return redirect_method_to_image(message, userdata, error, bus_image_method_remove);
921}
ebd93cb6 922
9b06c1e1
LP
923static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
924 return redirect_method_to_image(message, userdata, error, bus_image_method_rename);
ebd93cb6
LP
925}
926
19070062 927static int method_clone_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 928 return redirect_method_to_image(message, userdata, error, bus_image_method_clone);
ebd93cb6
LP
929}
930
19070062 931static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 932 return redirect_method_to_image(message, userdata, error, bus_image_method_mark_read_only);
ebd93cb6
LP
933}
934
cf30a8c1 935static int method_get_image_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 936 return redirect_method_to_image(message, userdata, error, bus_image_method_get_hostname);
cf30a8c1
LP
937}
938
939static int method_get_image_machine_id(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 940 return redirect_method_to_image(message, userdata, error, bus_image_method_get_machine_id);
cf30a8c1
LP
941}
942
943static int method_get_image_machine_info(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 944 return redirect_method_to_image(message, userdata, error, bus_image_method_get_machine_info);
cf30a8c1
LP
945}
946
9153b02b 947static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 948 return redirect_method_to_image(message, userdata, error, bus_image_method_get_os_release);
9153b02b
LP
949}
950
5a99c9d7 951static int clean_pool_done(Operation *operation, int child_error, sd_bus_error *error) {
03c2b288 952 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5a99c9d7 953 _cleanup_fclose_ FILE *file = NULL;
03c2b288
LP
954 int r;
955
956 assert(operation);
5a99c9d7 957 assert(operation->message);
03c2b288
LP
958 assert(operation->extra_fd >= 0);
959
5a99c9d7
IK
960 file = take_fdopen(&operation->extra_fd, "r");
961 if (!file)
962 return log_debug_errno(errno, "Failed to take opened tmp file's fd: %m");
03c2b288 963
5a99c9d7
IK
964 r = clean_pool_read_first_entry(file, child_error, error);
965 if (r < 0)
966 return r;
03c2b288
LP
967
968 r = sd_bus_message_new_method_return(operation->message, &reply);
969 if (r < 0)
970 return r;
971
972 r = sd_bus_message_open_container(reply, 'a', "(st)");
973 if (r < 0)
974 return r;
975
976 /* On success the resulting temporary file will contain a list of image names that were removed followed by
977 * their size on disk. Let's read that and turn it into a bus message. */
978 for (;;) {
979 _cleanup_free_ char *name = NULL;
5a99c9d7 980 uint64_t usage;
03c2b288 981
5a99c9d7 982 r = clean_pool_read_next_entry(file, &name, &usage);
03c2b288
LP
983 if (r < 0)
984 return r;
5a99c9d7 985 if (r == 0)
03c2b288
LP
986 break;
987
5a99c9d7 988 r = sd_bus_message_append(reply, "(st)", name, usage);
03c2b288
LP
989 if (r < 0)
990 return r;
991 }
992
993 r = sd_bus_message_close_container(reply);
994 if (r < 0)
995 return r;
996
51cc3825 997 return sd_bus_message_send(reply);
03c2b288
LP
998}
999
d94c2b06 1000static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_error *error) {
5a99c9d7 1001 ImageCleanPoolMode mode;
d94c2b06 1002 Manager *m = userdata;
03c2b288 1003 Operation *operation;
d94c2b06 1004 const char *mm;
d94c2b06
LP
1005 int r;
1006
1007 assert(message);
1008
03c2b288 1009 if (m->n_operations >= OPERATIONS_MAX)
1b09b81c 1010 return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
03c2b288 1011
d94c2b06
LP
1012 r = sd_bus_message_read(message, "s", &mm);
1013 if (r < 0)
1014 return r;
1015
1016 if (streq(mm, "all"))
5a99c9d7 1017 mode = IMAGE_CLEAN_POOL_REMOVE_ALL;
d94c2b06 1018 else if (streq(mm, "hidden"))
5a99c9d7 1019 mode = IMAGE_CLEAN_POOL_REMOVE_HIDDEN;
d94c2b06
LP
1020 else
1021 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mode '%s'.", mm);
1022
f5fa86f9
LP
1023 if (m->runtime_scope != RUNTIME_SCOPE_USER) {
1024 const char *details[] = {
1025 "verb", "clean_pool",
1026 "mode", mm,
1027 NULL
1028 };
1029
1030 r = bus_verify_polkit_async(
1031 message,
1032 "org.freedesktop.machine1.manage-machines",
1033 details,
1034 &m->polkit_registry,
1035 error);
1036 if (r < 0)
1037 return r;
1038 if (r == 0)
1039 return 1; /* Will call us back */
1040 }
d94c2b06 1041
5a99c9d7 1042 r = image_clean_pool_operation(m, mode, &operation);
4c253ed1 1043 if (r < 0)
5a99c9d7 1044 return log_debug_errno(r, "Failed to clean pool of images: %m");
03c2b288 1045
5a99c9d7 1046 operation_attach_bus_reply(operation, message);
03c2b288 1047 operation->done = clean_pool_done;
03c2b288 1048 return 1;
d94c2b06
LP
1049}
1050
19070062 1051static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d6ce17c7
LP
1052 Manager *m = userdata;
1053 uint64_t limit;
1054 int r;
1055
19070062
LP
1056 assert(message);
1057
d6ce17c7
LP
1058 r = sd_bus_message_read(message, "t", &limit);
1059 if (r < 0)
1060 return r;
a90fb858 1061 if (!FILE_SIZE_VALID_OR_INFINITY(limit))
1b09b81c 1062 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
d6ce17c7 1063
f5fa86f9
LP
1064 if (m->runtime_scope != RUNTIME_SCOPE_USER) {
1065 const char *details[] = {
1066 "verb", "set_pool_limit",
1067 NULL
1068 };
1069
1070 r = bus_verify_polkit_async(
1071 message,
1072 "org.freedesktop.machine1.manage-machines",
1073 details,
1074 &m->polkit_registry,
1075 error);
1076 if (r < 0)
1077 return r;
1078 if (r == 0)
1079 return 1; /* Will call us back */
1080 }
d6ce17c7 1081
4cee5eed 1082 /* Set up the machine directory if necessary */
1075316a
DDM
1083 r = image_setup_pool(
1084 m->runtime_scope,
1085 IMAGE_MACHINE,
1086 /* use_btrfs_subvol= */ true,
1087 /* use_btrfs_quota= */ true);
4cee5eed 1088 if (r < 0)
1075316a 1089 return sd_bus_error_set_errnof(error, r, "Failed to set up machine pool: %m");
4cee5eed 1090
e1b3319b 1091 r = image_set_pool_limit(m->runtime_scope, IMAGE_MACHINE, limit);
efe47f58 1092 if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
1b09b81c 1093 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
26166c88 1094 if (r < 0)
d6ce17c7
LP
1095 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
1096
1097 return sd_bus_reply_method_return(message, NULL);
1098}
1099
19070062 1100static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b06c1e1 1101 return redirect_method_to_image(message, userdata, error, bus_image_method_set_limit);
d6ce17c7
LP
1102}
1103
c01ff965 1104static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c01ff965 1105 Manager *m = userdata;
74d1b7d2 1106 const char *name;
c01ff965
LP
1107 Machine *machine;
1108 uint32_t uid;
74d1b7d2 1109 uid_t converted;
c01ff965
LP
1110 int r;
1111
1112 r = sd_bus_message_read(message, "su", &name, &uid);
1113 if (r < 0)
1114 return r;
1115
c077529b 1116 if (!uid_is_valid(uid))
c01ff965
LP
1117 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
1118
1119 machine = hashmap_get(m->machines, name);
1120 if (!machine)
1121 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1122
a79366e2 1123 if (machine->class != MACHINE_CONTAINER)
1b09b81c 1124 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
a79366e2 1125
74d1b7d2
LP
1126 r = machine_translate_uid(machine, uid, &converted);
1127 if (r == -ESRCH)
1128 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name);
1129 if (r < 0)
1130 return r;
c01ff965 1131
74d1b7d2 1132 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
c01ff965
LP
1133}
1134
1135static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
74d1b7d2 1136 _cleanup_free_ char *o = NULL;
c01ff965
LP
1137 Manager *m = userdata;
1138 Machine *machine;
74d1b7d2 1139 uid_t uid, converted;
c01ff965
LP
1140 int r;
1141
1142 r = sd_bus_message_read(message, "u", &uid);
1143 if (r < 0)
1144 return r;
c077529b 1145 if (!uid_is_valid(uid))
c01ff965
LP
1146 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
1147 if (uid < 0x10000)
1148 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
1149
74d1b7d2
LP
1150 r = manager_find_machine_for_uid(m, uid, &machine, &converted);
1151 if (r < 0)
1152 return r;
1153 if (!r)
1154 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
c01ff965 1155
74d1b7d2
LP
1156 o = machine_bus_path(machine);
1157 if (!o)
1158 return -ENOMEM;
c01ff965 1159
74d1b7d2 1160 return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
c01ff965
LP
1161}
1162
74d1b7d2
LP
1163static int method_map_from_machine_group(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1164 Manager *m = userdata;
1165 const char *name;
c01ff965 1166 Machine *machine;
74d1b7d2 1167 gid_t converted;
c01ff965
LP
1168 uint32_t gid;
1169 int r;
1170
1171 r = sd_bus_message_read(message, "su", &name, &gid);
1172 if (r < 0)
1173 return r;
1174
c077529b 1175 if (!gid_is_valid(gid))
c01ff965
LP
1176 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1177
1178 machine = hashmap_get(m->machines, name);
1179 if (!machine)
1180 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1181
a79366e2 1182 if (machine->class != MACHINE_CONTAINER)
1b09b81c 1183 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
a79366e2 1184
74d1b7d2
LP
1185 r = machine_translate_gid(machine, gid, &converted);
1186 if (r == -ESRCH)
1187 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching group mappings.", name);
1188 if (r < 0)
1189 return r;
c01ff965 1190
74d1b7d2 1191 return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
c01ff965
LP
1192}
1193
74d1b7d2
LP
1194static int method_map_to_machine_group(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1195 _cleanup_free_ char *o = NULL;
1196 Manager *m = userdata;
c01ff965 1197 Machine *machine;
74d1b7d2 1198 gid_t gid, converted;
c01ff965
LP
1199 int r;
1200
1201 r = sd_bus_message_read(message, "u", &gid);
1202 if (r < 0)
1203 return r;
c077529b 1204 if (!gid_is_valid(gid))
c01ff965
LP
1205 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
1206 if (gid < 0x10000)
1207 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
1208
74d1b7d2
LP
1209 r = manager_find_machine_for_gid(m, gid, &machine, &converted);
1210 if (r < 0)
1211 return r;
1212 if (!r)
1213 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
c01ff965 1214
74d1b7d2
LP
1215 o = machine_bus_path(machine);
1216 if (!o)
1217 return -ENOMEM;
c01ff965 1218
74d1b7d2 1219 return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
c01ff965
LP
1220}
1221
c3350683
LP
1222const sd_bus_vtable manager_vtable[] = {
1223 SD_BUS_VTABLE_START(0),
bbe17ca1 1224
160e3793
LP
1225 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
1226 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
1227 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
bbe17ca1 1228
d5e4e60b
A
1229 SD_BUS_METHOD_WITH_ARGS("GetMachine",
1230 SD_BUS_ARGS("s", name),
1231 SD_BUS_RESULT("o", machine),
1232 method_get_machine,
1233 SD_BUS_VTABLE_UNPRIVILEGED),
1234 SD_BUS_METHOD_WITH_ARGS("GetImage",
1235 SD_BUS_ARGS("s", name),
1236 SD_BUS_RESULT("o", image),
1237 method_get_image,
1238 SD_BUS_VTABLE_UNPRIVILEGED),
1239 SD_BUS_METHOD_WITH_ARGS("GetMachineByPID",
1240 SD_BUS_ARGS("u", pid),
1241 SD_BUS_RESULT("o", machine),
1242 method_get_machine_by_pid,
1243 SD_BUS_VTABLE_UNPRIVILEGED),
1244 SD_BUS_METHOD_WITH_ARGS("ListMachines",
1245 SD_BUS_NO_ARGS,
1246 SD_BUS_RESULT("a(ssso)", machines),
1247 method_list_machines,
1248 SD_BUS_VTABLE_UNPRIVILEGED),
1249 SD_BUS_METHOD_WITH_ARGS("ListImages",
1250 SD_BUS_NO_ARGS,
1251 SD_BUS_RESULT("a(ssbttto)", images),
1252 method_list_images,
1253 SD_BUS_VTABLE_UNPRIVILEGED),
1254 SD_BUS_METHOD_WITH_ARGS("CreateMachine",
1255 SD_BUS_ARGS("s", name, "ay", id, "s", service, "s", class, "u", leader, "s", root_directory, "a(sv)", scope_properties),
1256 SD_BUS_RESULT("o", path),
790f5162
LP
1257 method_create_machine,
1258 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1259 SD_BUS_METHOD_WITH_ARGS("CreateMachineWithNetwork",
1260 SD_BUS_ARGS("s", name, "ay", id, "s", service, "s", class, "u", leader, "s", root_directory, "ai", ifindices, "a(sv)", scope_properties),
1261 SD_BUS_RESULT("o", path),
d80af3b9
LB
1262 method_create_machine,
1263 SD_BUS_VTABLE_UNPRIVILEGED),
1264 SD_BUS_METHOD_WITH_ARGS("CreateMachineEx",
1265 SD_BUS_ARGS("s", name, "a(sv)", properties, "a(sv)", scope_properties),
1266 SD_BUS_RESULT("o", path),
1267 method_create_machine,
790f5162 1268 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1269 SD_BUS_METHOD_WITH_ARGS("RegisterMachine",
1270 SD_BUS_ARGS("s", name, "ay", id, "s", service, "s", class, "u", leader, "s", root_directory),
1271 SD_BUS_RESULT("o", path),
790f5162
LP
1272 method_register_machine,
1273 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1274 SD_BUS_METHOD_WITH_ARGS("RegisterMachineWithNetwork",
1275 SD_BUS_ARGS("s", name, "ay", id, "s", service, "s", class, "u", leader, "s", root_directory, "ai", ifindices),
1276 SD_BUS_RESULT("o", path),
d80af3b9
LB
1277 method_register_machine,
1278 SD_BUS_VTABLE_UNPRIVILEGED),
1279 SD_BUS_METHOD_WITH_ARGS("RegisterMachineEx",
1280 SD_BUS_ARGS("s", name, "a(sv)", properties),
1281 SD_BUS_RESULT("o", path),
1282 method_register_machine,
790f5162 1283 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1284 SD_BUS_METHOD_WITH_ARGS("UnregisterMachine",
1285 SD_BUS_ARGS("s", name),
1286 SD_BUS_NO_RESULT,
1287 method_unregister_machine,
1288 SD_BUS_VTABLE_UNPRIVILEGED),
1289 SD_BUS_METHOD_WITH_ARGS("TerminateMachine",
1290 SD_BUS_ARGS("s", id),
1291 SD_BUS_NO_RESULT,
1292 method_terminate_machine,
1293 SD_BUS_VTABLE_UNPRIVILEGED),
1294 SD_BUS_METHOD_WITH_ARGS("KillMachine",
3ae0e545 1295 SD_BUS_ARGS("s", name, "s", whom, "i", signal),
d5e4e60b
A
1296 SD_BUS_NO_RESULT,
1297 method_kill_machine,
1298 SD_BUS_VTABLE_UNPRIVILEGED),
1299 SD_BUS_METHOD_WITH_ARGS("GetMachineAddresses",
1300 SD_BUS_ARGS("s", name),
1301 SD_BUS_RESULT("a(iay)", addresses),
1302 method_get_machine_addresses,
1303 SD_BUS_VTABLE_UNPRIVILEGED),
1f815bf1
SL
1304 SD_BUS_METHOD_WITH_ARGS("GetMachineSSHInfo",
1305 SD_BUS_ARGS("s", name),
1306 SD_BUS_RESULT("s", ssh_address, "s", ssh_private_key_path),
1307 method_get_machine_ssh_info,
1308 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1309 SD_BUS_METHOD_WITH_ARGS("GetMachineOSRelease",
1310 SD_BUS_ARGS("s", name),
1311 SD_BUS_RESULT("a{ss}", fields),
1312 method_get_machine_os_release,
1313 SD_BUS_VTABLE_UNPRIVILEGED),
1314 SD_BUS_METHOD_WITH_ARGS("OpenMachinePTY",
1315 SD_BUS_ARGS("s", name),
1316 SD_BUS_RESULT("h", pty, "s", pty_path),
1317 method_open_machine_pty,
020d6c1d 1318 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1319 SD_BUS_METHOD_WITH_ARGS("OpenMachineLogin",
1320 SD_BUS_ARGS("s", name),
1321 SD_BUS_RESULT("h", pty, "s", pty_path),
1322 method_open_machine_login,
1323 SD_BUS_VTABLE_UNPRIVILEGED),
1324 SD_BUS_METHOD_WITH_ARGS("OpenMachineShell",
1325 SD_BUS_ARGS("s", name, "s", user, "s", path, "as", args, "as", environment),
1326 SD_BUS_RESULT("h", pty, "s", pty_path),
1327 method_open_machine_shell,
1328 SD_BUS_VTABLE_UNPRIVILEGED),
1329 SD_BUS_METHOD_WITH_ARGS("BindMountMachine",
1330 SD_BUS_ARGS("s", name, "s", source, "s", destination, "b", read_only, "b", mkdir),
1331 SD_BUS_NO_RESULT,
1332 method_bind_mount_machine,
1333 SD_BUS_VTABLE_UNPRIVILEGED),
1334 SD_BUS_METHOD_WITH_ARGS("CopyFromMachine",
1335 SD_BUS_ARGS("s", name, "s", source, "s", destination),
1336 SD_BUS_NO_RESULT,
1337 method_copy_machine,
1338 SD_BUS_VTABLE_UNPRIVILEGED),
1339 SD_BUS_METHOD_WITH_ARGS("CopyToMachine",
1340 SD_BUS_ARGS("s", name, "s", source, "s", destination),
1341 SD_BUS_NO_RESULT,
1342 method_copy_machine,
1343 SD_BUS_VTABLE_UNPRIVILEGED),
ae03e1a9
AW
1344 SD_BUS_METHOD_WITH_ARGS("CopyFromMachineWithFlags",
1345 SD_BUS_ARGS("s", name, "s", source, "s", destination, "t", flags),
1346 SD_BUS_NO_RESULT,
1347 method_copy_machine,
1348 SD_BUS_VTABLE_UNPRIVILEGED),
1349 SD_BUS_METHOD_WITH_ARGS("CopyToMachineWithFlags",
1350 SD_BUS_ARGS("s", name, "s", source, "s", destination, "t", flags),
1351 SD_BUS_NO_RESULT,
1352 method_copy_machine,
1353 SD_BUS_VTABLE_UNPRIVILEGED),
d5e4e60b
A
1354 SD_BUS_METHOD_WITH_ARGS("OpenMachineRootDirectory",
1355 SD_BUS_ARGS("s", name),
1356 SD_BUS_RESULT("h", fd),
1357 method_open_machine_root_directory,
1358 SD_BUS_VTABLE_UNPRIVILEGED),
1359 SD_BUS_METHOD_WITH_ARGS("GetMachineUIDShift",
1360 SD_BUS_ARGS("s", name),
1361 SD_BUS_RESULT("u", shift),
1362 method_get_machine_uid_shift,
1363 SD_BUS_VTABLE_UNPRIVILEGED),
1364 SD_BUS_METHOD_WITH_ARGS("RemoveImage",
1365 SD_BUS_ARGS("s", name),
1366 SD_BUS_NO_RESULT,
1367 method_remove_image,
1368 SD_BUS_VTABLE_UNPRIVILEGED),
1369 SD_BUS_METHOD_WITH_ARGS("RenameImage",
1370 SD_BUS_ARGS("s", name, "s", new_name),
1371 SD_BUS_NO_RESULT,
1372 method_rename_image,
1373 SD_BUS_VTABLE_UNPRIVILEGED),
1374 SD_BUS_METHOD_WITH_ARGS("CloneImage",
1375 SD_BUS_ARGS("s", name, "s", new_name, "b", read_only),
1376 SD_BUS_NO_RESULT,
1377 method_clone_image,
1378 SD_BUS_VTABLE_UNPRIVILEGED),
1379 SD_BUS_METHOD_WITH_ARGS("MarkImageReadOnly",
1380 SD_BUS_ARGS("s", name, "b", read_only),
1381 SD_BUS_NO_RESULT,
1382 method_mark_image_read_only,
1383 SD_BUS_VTABLE_UNPRIVILEGED),
1384 SD_BUS_METHOD_WITH_ARGS("GetImageHostname",
1385 SD_BUS_ARGS("s", name),
1386 SD_BUS_RESULT("s", hostname),
1387 method_get_image_hostname,
1388 SD_BUS_VTABLE_UNPRIVILEGED),
1389 SD_BUS_METHOD_WITH_ARGS("GetImageMachineID",
1390 SD_BUS_ARGS("s", name),
1391 SD_BUS_RESULT("ay", id),
1392 method_get_image_machine_id,
1393 SD_BUS_VTABLE_UNPRIVILEGED),
1394 SD_BUS_METHOD_WITH_ARGS("GetImageMachineInfo",
1395 SD_BUS_ARGS("s", name),
1396 SD_BUS_RESULT("a{ss}", machine_info),
1397 method_get_image_machine_info,
1398 SD_BUS_VTABLE_UNPRIVILEGED),
1399 SD_BUS_METHOD_WITH_ARGS("GetImageOSRelease",
1400 SD_BUS_ARGS("s", name),
1401 SD_BUS_RESULT("a{ss}", os_release),
1402 method_get_image_os_release,
1403 SD_BUS_VTABLE_UNPRIVILEGED),
1404 SD_BUS_METHOD_WITH_ARGS("SetPoolLimit",
1405 SD_BUS_ARGS("t", size),
1406 SD_BUS_NO_RESULT,
1407 method_set_pool_limit,
1408 SD_BUS_VTABLE_UNPRIVILEGED),
1409 SD_BUS_METHOD_WITH_ARGS("SetImageLimit",
1410 SD_BUS_ARGS("s", name, "t", size),
1411 SD_BUS_NO_RESULT,
1412 method_set_image_limit,
1413 SD_BUS_VTABLE_UNPRIVILEGED),
1414 SD_BUS_METHOD_WITH_ARGS("CleanPool",
1415 SD_BUS_ARGS("s", mode),
1416 SD_BUS_RESULT("a(st)",images),
1417 method_clean_pool,
1418 SD_BUS_VTABLE_UNPRIVILEGED),
1419 SD_BUS_METHOD_WITH_ARGS("MapFromMachineUser",
1420 SD_BUS_ARGS("s", name, "u", uid_inner),
1421 SD_BUS_RESULT("u", uid_outer),
1422 method_map_from_machine_user,
1423 SD_BUS_VTABLE_UNPRIVILEGED),
1424 SD_BUS_METHOD_WITH_ARGS("MapToMachineUser",
1425 SD_BUS_ARGS("u", uid_outer),
1426 SD_BUS_RESULT("s", machine_name, "o", machine_path, "u", uid_inner),
1427 method_map_to_machine_user,
1428 SD_BUS_VTABLE_UNPRIVILEGED),
1429 SD_BUS_METHOD_WITH_ARGS("MapFromMachineGroup",
1430 SD_BUS_ARGS("s", name, "u", gid_inner),
1431 SD_BUS_RESULT("u", gid_outer),
1432 method_map_from_machine_group,
1433 SD_BUS_VTABLE_UNPRIVILEGED),
1434 SD_BUS_METHOD_WITH_ARGS("MapToMachineGroup",
1435 SD_BUS_ARGS("u", gid_outer),
1436 SD_BUS_RESULT("s", machine_name, "o", machine_path, "u", gid_inner),
1437 method_map_to_machine_group,
1438 SD_BUS_VTABLE_UNPRIVILEGED),
1439
1440 SD_BUS_SIGNAL_WITH_ARGS("MachineNew",
1441 SD_BUS_ARGS("s", machine, "o", path),
1442 0),
1443 SD_BUS_SIGNAL_WITH_ARGS("MachineRemoved",
1444 SD_BUS_ARGS("s", machine, "o", path),
1445 0),
bbe17ca1 1446
c3350683
LP
1447 SD_BUS_VTABLE_END
1448};
1ee306e1 1449
4faa530c
ZJS
1450const BusObjectImplementation manager_object = {
1451 "/org/freedesktop/machine1",
1452 "org.freedesktop.machine1.Manager",
1453 .vtables = BUS_VTABLES(manager_vtable),
1454 .children = BUS_IMPLEMENTATIONS( &machine_object,
1455 &image_object ),
1456};
1457
19070062 1458int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683 1459 const char *path, *result, *unit;
99534007 1460 Manager *m = ASSERT_PTR(userdata);
c3350683
LP
1461 Machine *machine;
1462 uint32_t id;
1463 int r;
1ee306e1 1464
1ee306e1
LP
1465 assert(message);
1466
c3350683
LP
1467 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
1468 if (r < 0) {
ebcf1f97 1469 bus_log_parse_error(r);
65d73cf0 1470 return 0;
c3350683 1471 }
6797c324 1472
85ab917b 1473 machine = hashmap_get(m->machines_by_unit, unit);
c3350683
LP
1474 if (!machine)
1475 return 0;
6797c324 1476
c3350683 1477 if (streq_ptr(path, machine->scope_job)) {
491ac9f2 1478 machine->scope_job = mfree(machine->scope_job);
6797c324 1479
c3350683
LP
1480 if (machine->started) {
1481 if (streq(result, "done"))
1482 machine_send_create_reply(machine, NULL);
1483 else {
4afd3348 1484 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
6797c324 1485
ebcf1f97 1486 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
6797c324 1487
ebcf1f97 1488 machine_send_create_reply(machine, &e);
c3350683 1489 }
49f3fffd
LP
1490 }
1491
1492 machine_save(machine);
1ee306e1
LP
1493 }
1494
c3350683
LP
1495 machine_add_to_gc_queue(machine);
1496 return 0;
1ee306e1
LP
1497}
1498
19070062 1499int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683 1500 _cleanup_free_ char *unit = NULL;
49f3fffd 1501 const char *path;
99534007 1502 Manager *m = ASSERT_PTR(userdata);
c3350683 1503 Machine *machine;
ebcf1f97 1504 int r;
554604b3 1505
c3350683 1506 assert(message);
554604b3 1507
c3350683
LP
1508 path = sd_bus_message_get_path(message);
1509 if (!path)
554604b3 1510 return 0;
554604b3 1511
ebcf1f97 1512 r = unit_name_from_dbus_path(path, &unit);
e5f5b5b9
LP
1513 if (r == -EINVAL) /* not for a unit */
1514 return 0;
9ed794a3 1515 if (r < 0) {
9b420b3c
LP
1516 log_oom();
1517 return 0;
1518 }
554604b3 1519
85ab917b 1520 machine = hashmap_get(m->machines_by_unit, unit);
9b420b3c
LP
1521 if (!machine)
1522 return 0;
1523
9b420b3c 1524 machine_add_to_gc_queue(machine);
c3350683
LP
1525 return 0;
1526}
554604b3 1527
19070062 1528int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683 1529 const char *path, *unit;
99534007 1530 Manager *m = ASSERT_PTR(userdata);
c3350683
LP
1531 Machine *machine;
1532 int r;
554604b3 1533
c3350683 1534 assert(message);
554604b3 1535
c3350683
LP
1536 r = sd_bus_message_read(message, "so", &unit, &path);
1537 if (r < 0) {
ebcf1f97 1538 bus_log_parse_error(r);
9b420b3c 1539 return 0;
554604b3
LP
1540 }
1541
85ab917b 1542 machine = hashmap_get(m->machines_by_unit, unit);
9b420b3c
LP
1543 if (!machine)
1544 return 0;
1545
9b420b3c 1546 machine_add_to_gc_queue(machine);
c3350683
LP
1547 return 0;
1548}
554604b3 1549
19070062 1550int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 1551 Manager *m = ASSERT_PTR(userdata);
a658cafa 1552 Machine *machine;
c3350683 1553 int b, r;
554604b3 1554
19070062 1555 assert(message);
554604b3 1556
c3350683
LP
1557 r = sd_bus_message_read(message, "b", &b);
1558 if (r < 0) {
ebcf1f97 1559 bus_log_parse_error(r);
65d73cf0 1560 return 0;
554604b3 1561 }
a658cafa
LP
1562 if (b)
1563 return 0;
554604b3 1564
a658cafa
LP
1565 /* systemd finished reloading, let's recheck all our machines */
1566 log_debug("System manager has been reloaded, rechecking machines...");
554604b3 1567
90e74a66 1568 HASHMAP_FOREACH(machine, m->machines)
a658cafa 1569 machine_add_to_gc_queue(machine);
554604b3
LP
1570
1571 return 0;
1572}
1573
b92d0b4c
LP
1574int manager_unref_unit(
1575 Manager *m,
1576 const char *unit,
1577 sd_bus_error *error) {
1578
1579 assert(m);
1580 assert(unit);
1581
f5fa86f9 1582 return bus_call_method(m->api_bus, bus_systemd_mgr, "UnrefUnit", error, NULL, "s", unit);
b92d0b4c
LP
1583}
1584
c3350683 1585int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
4afd3348 1586 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1ee306e1
LP
1587 int r;
1588
1589 assert(manager);
1590 assert(unit);
1591
f5fa86f9 1592 r = bus_call_method(manager->api_bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail");
1ee306e1 1593 if (r < 0) {
955a6329
ZJS
1594 if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT,
1595 BUS_ERROR_LOAD_FAILED)) {
6797c324
LP
1596
1597 if (job)
1598 *job = NULL;
1599
c3350683 1600 sd_bus_error_free(error);
6797c324
LP
1601 return 0;
1602 }
1603
1ee306e1
LP
1604 return r;
1605 }
1606
1607 if (job) {
1608 const char *j;
1609 char *copy;
1610
c3350683
LP
1611 r = sd_bus_message_read(reply, "o", &j);
1612 if (r < 0)
1613 return r;
1ee306e1
LP
1614
1615 copy = strdup(j);
1616 if (!copy)
1617 return -ENOMEM;
1618
1619 *job = copy;
1620 }
1621
6797c324 1622 return 1;
1ee306e1
LP
1623}
1624
d5feeb37 1625int manager_kill_unit(Manager *manager, const char *unit, const char *subgroup, int signo, sd_bus_error *reterr_error) {
1ee306e1
LP
1626 assert(manager);
1627 assert(unit);
1628
d5feeb37 1629 if (empty_or_root(subgroup))
f5fa86f9 1630 return bus_call_method(manager->api_bus, bus_systemd_mgr, "KillUnit", reterr_error, NULL, "ssi", unit, "all", signo);
d5feeb37 1631
f5fa86f9 1632 return bus_call_method(manager->api_bus, bus_systemd_mgr, "KillUnitSubgroup", reterr_error, NULL, "sssi", unit, "cgroup", subgroup, signo);
1ee306e1
LP
1633}
1634
ca02f658 1635int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *reterr_error) {
4afd3348
LP
1636 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1637 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1ee306e1 1638 _cleanup_free_ char *path = NULL;
1ee306e1 1639 const char *state;
1ee306e1
LP
1640 int r;
1641
1642 assert(manager);
1643 assert(unit);
1644
1ee306e1
LP
1645 path = unit_dbus_path_from_name(unit);
1646 if (!path)
1647 return -ENOMEM;
1648
c3350683 1649 r = sd_bus_get_property(
f5fa86f9 1650 manager->api_bus,
1ee306e1
LP
1651 "org.freedesktop.systemd1",
1652 path,
c3350683
LP
1653 "org.freedesktop.systemd1.Unit",
1654 "ActiveState",
1ee306e1 1655 &error,
c3350683
LP
1656 &reply,
1657 "s");
1ee306e1 1658 if (r < 0) {
ac004f4c 1659 if (bus_error_is_connection(&error))
6797c324 1660 return true;
6797c324 1661
955a6329
ZJS
1662 if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT,
1663 BUS_ERROR_LOAD_FAILED))
6797c324 1664 return false;
6797c324 1665
ca02f658 1666 sd_bus_error_move(reterr_error, &error);
1ee306e1
LP
1667 return r;
1668 }
1669
c3350683
LP
1670 r = sd_bus_message_read(reply, "s", &state);
1671 if (r < 0)
1ee306e1 1672 return -EINVAL;
1ee306e1 1673
9b420b3c 1674 return !STR_IN_SET(state, "inactive", "failed");
1ee306e1 1675}
bd16acf3 1676
ca02f658 1677int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *reterr_error) {
4afd3348
LP
1678 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1679 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
c3350683 1680 int r;
bd16acf3 1681
c3350683
LP
1682 assert(manager);
1683 assert(path);
bd16acf3 1684
c3350683 1685 r = sd_bus_get_property(
f5fa86f9 1686 manager->api_bus,
c3350683
LP
1687 "org.freedesktop.systemd1",
1688 path,
1689 "org.freedesktop.systemd1.Job",
1690 "State",
1691 &error,
1692 &reply,
1693 "s");
1694 if (r < 0) {
ac004f4c 1695 if (bus_error_is_connection(&error))
c3350683 1696 return true;
bd16acf3 1697
c3350683
LP
1698 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1699 return false;
bd16acf3 1700
ca02f658 1701 sd_bus_error_move(reterr_error, &error);
bd16acf3 1702 return r;
c3350683 1703 }
bd16acf3 1704
c3350683
LP
1705 /* We don't actually care about the state really. The fact
1706 * that we could read the job state is enough for us */
bd16acf3 1707
c3350683 1708 return true;
bd16acf3 1709}