]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machinectl.c
Merge pull request #25081 from keszybz/test-local-addresses-fail
[thirdparty/systemd.git] / src / machine / machinectl.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <arpa/inet.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <getopt.h>
7 #include <math.h>
8 #include <net/if.h>
9 #include <netinet/in.h>
10 #include <sys/mount.h>
11 #include <sys/socket.h>
12 #include <unistd.h>
13
14 #include "sd-bus.h"
15
16 #include "alloc-util.h"
17 #include "bus-common-errors.h"
18 #include "bus-error.h"
19 #include "bus-locator.h"
20 #include "bus-map-properties.h"
21 #include "bus-print-properties.h"
22 #include "bus-unit-procs.h"
23 #include "bus-unit-util.h"
24 #include "bus-wait-for-jobs.h"
25 #include "cgroup-show.h"
26 #include "cgroup-util.h"
27 #include "copy.h"
28 #include "def.h"
29 #include "env-util.h"
30 #include "fd-util.h"
31 #include "format-table.h"
32 #include "hostname-util.h"
33 #include "import-util.h"
34 #include "locale-util.h"
35 #include "log.h"
36 #include "logs-show.h"
37 #include "machine-dbus.h"
38 #include "macro.h"
39 #include "main-func.h"
40 #include "mkdir.h"
41 #include "nulstr-util.h"
42 #include "pager.h"
43 #include "parse-argument.h"
44 #include "parse-util.h"
45 #include "path-util.h"
46 #include "pretty-print.h"
47 #include "process-util.h"
48 #include "ptyfwd.h"
49 #include "rlimit-util.h"
50 #include "sigbus.h"
51 #include "signal-util.h"
52 #include "sort-util.h"
53 #include "spawn-ask-password-agent.h"
54 #include "spawn-polkit-agent.h"
55 #include "stdio-util.h"
56 #include "string-table.h"
57 #include "strv.h"
58 #include "terminal-util.h"
59 #include "unit-name.h"
60 #include "verbs.h"
61 #include "web-util.h"
62
63 static char **arg_property = NULL;
64 static bool arg_all = false;
65 static BusPrintPropertyFlags arg_print_flags = 0;
66 static bool arg_full = false;
67 static PagerFlags arg_pager_flags = 0;
68 static bool arg_legend = true;
69 static const char *arg_kill_whom = NULL;
70 static int arg_signal = SIGTERM;
71 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
72 static const char *arg_host = NULL;
73 static bool arg_read_only = false;
74 static bool arg_mkdir = false;
75 static bool arg_quiet = false;
76 static bool arg_ask_password = true;
77 static unsigned arg_lines = 10;
78 static OutputMode arg_output = OUTPUT_SHORT;
79 static bool arg_force = false;
80 static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
81 static const char* arg_format = NULL;
82 static const char *arg_uid = NULL;
83 static char **arg_setenv = NULL;
84 static unsigned arg_max_addresses = 1;
85
86 STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
87 STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
88
89 static OutputFlags get_output_flags(void) {
90 return
91 FLAGS_SET(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) * OUTPUT_SHOW_ALL |
92 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
93 colors_enabled() * OUTPUT_COLOR |
94 !arg_quiet * OUTPUT_WARN_CUTOFF;
95 }
96
97 static int call_get_os_release(sd_bus *bus, const char *method, const char *name, const char *query, ...) {
98 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
99 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
100 const char *k, *v, *iter, **query_res = NULL;
101 size_t count = 0, awaited_args = 0;
102 va_list ap;
103 int r;
104
105 assert(bus);
106 assert(name);
107 assert(query);
108
109 NULSTR_FOREACH(iter, query)
110 awaited_args++;
111 query_res = newa0(const char *, awaited_args);
112
113 r = bus_call_method(bus, bus_machine_mgr, method, &error, &reply, "s", name);
114 if (r < 0)
115 return log_debug_errno(r, "Failed to call '%s()': %s", method, bus_error_message(&error, r));
116
117 r = sd_bus_message_enter_container(reply, 'a', "{ss}");
118 if (r < 0)
119 return bus_log_parse_error(r);
120
121 while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
122 count = 0;
123 NULSTR_FOREACH(iter, query) {
124 if (streq(k, iter)) {
125 query_res[count] = v;
126 break;
127 }
128 count++;
129 }
130 }
131 if (r < 0)
132 return bus_log_parse_error(r);
133
134 r = sd_bus_message_exit_container(reply);
135 if (r < 0)
136 return bus_log_parse_error(r);
137
138 va_start(ap, query);
139 for (count = 0; count < awaited_args; count++) {
140 char *val, **out;
141
142 out = va_arg(ap, char **);
143 assert(out);
144 if (query_res[count]) {
145 val = strdup(query_res[count]);
146 if (!val) {
147 va_end(ap);
148 return -ENOMEM;
149 }
150 *out = val;
151 }
152 }
153 va_end(ap);
154
155 return 0;
156 }
157
158 static int call_get_addresses(
159 sd_bus *bus,
160 const char *name,
161 int ifi,
162 const char *prefix,
163 const char *prefix2,
164 char **ret) {
165
166 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
167 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
168 _cleanup_free_ char *addresses = NULL;
169 unsigned n = 0;
170 int r;
171
172 assert(bus);
173 assert(name);
174 assert(prefix);
175 assert(prefix2);
176
177 r = bus_call_method(bus, bus_machine_mgr, "GetMachineAddresses", NULL, &reply, "s", name);
178 if (r < 0)
179 return log_debug_errno(r, "Could not get addresses: %s", bus_error_message(&error, r));
180
181 addresses = strdup(prefix);
182 if (!addresses)
183 return log_oom();
184 prefix = "";
185
186 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
187 if (r < 0)
188 return bus_log_parse_error(r);
189
190 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
191 int family;
192 const void *a;
193 size_t sz;
194 char buf_ifi[1 + DECIMAL_STR_MAX(int)] = "";
195
196 r = sd_bus_message_read(reply, "i", &family);
197 if (r < 0)
198 return bus_log_parse_error(r);
199
200 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
201 if (r < 0)
202 return bus_log_parse_error(r);
203
204 if (family == AF_INET6 && ifi > 0)
205 xsprintf(buf_ifi, "%%%i", ifi);
206
207 if (!strextend(&addresses, prefix, IN_ADDR_TO_STRING(family, a), buf_ifi))
208 return log_oom();
209
210 r = sd_bus_message_exit_container(reply);
211 if (r < 0)
212 return bus_log_parse_error(r);
213
214 prefix = prefix2;
215
216 n++;
217 }
218 if (r < 0)
219 return bus_log_parse_error(r);
220
221 r = sd_bus_message_exit_container(reply);
222 if (r < 0)
223 return bus_log_parse_error(r);
224
225 *ret = TAKE_PTR(addresses);
226 return (int) n;
227 }
228
229 static int show_table(Table *table, const char *word) {
230 int r;
231
232 assert(table);
233 assert(word);
234
235 if (table_get_rows(table) > 1 || OUTPUT_MODE_IS_JSON(arg_output)) {
236 r = table_set_sort(table, (size_t) 0);
237 if (r < 0)
238 return table_log_sort_error(r);
239
240 table_set_header(table, arg_legend);
241
242 if (OUTPUT_MODE_IS_JSON(arg_output))
243 r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO);
244 else
245 r = table_print(table, NULL);
246 if (r < 0)
247 return table_log_print_error(r);
248 }
249
250 if (arg_legend) {
251 if (table_get_rows(table) > 1)
252 printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word);
253 else
254 printf("No %s.\n", word);
255 }
256
257 return 0;
258 }
259
260 static int list_machines(int argc, char *argv[], void *userdata) {
261 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
262 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
263 _cleanup_(table_unrefp) Table *table = NULL;
264 sd_bus *bus = ASSERT_PTR(userdata);
265 int r;
266
267 pager_open(arg_pager_flags);
268
269 r = bus_call_method(bus, bus_machine_mgr, "ListMachines", &error, &reply, NULL);
270 if (r < 0)
271 return log_error_errno(r, "Could not get machines: %s", bus_error_message(&error, r));
272
273 table = table_new("machine", "class", "service", "os", "version",
274 arg_max_addresses > 0 ? "addresses" : NULL);
275 if (!table)
276 return log_oom();
277
278 table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
279 if (!arg_full && arg_max_addresses > 0 && arg_max_addresses < UINT_MAX)
280 table_set_cell_height_max(table, arg_max_addresses);
281
282 if (arg_full)
283 table_set_width(table, 0);
284
285 r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
286 if (r < 0)
287 return bus_log_parse_error(r);
288
289 for (;;) {
290 _cleanup_free_ char *os = NULL, *version_id = NULL, *addresses = NULL;
291 const char *name, *class, *service;
292
293 r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, NULL);
294 if (r < 0)
295 return bus_log_parse_error(r);
296 if (r == 0)
297 break;
298
299 if (name[0] == '.' && !arg_all)
300 continue;
301
302 (void) call_get_os_release(
303 bus,
304 "GetMachineOSRelease",
305 name,
306 "ID\0"
307 "VERSION_ID\0",
308 &os,
309 &version_id);
310
311 r = table_add_many(table,
312 TABLE_STRING, empty_to_null(name),
313 TABLE_STRING, empty_to_null(class),
314 TABLE_STRING, empty_to_null(service),
315 TABLE_STRING, empty_to_null(os),
316 TABLE_STRING, empty_to_null(version_id));
317 if (r < 0)
318 return table_log_add_error(r);
319
320 if (arg_max_addresses > 0) {
321 (void) call_get_addresses(bus, name, 0, "", "\n", &addresses);
322
323 r = table_add_many(table,
324 TABLE_STRING, empty_to_null(addresses));
325 if (r < 0)
326 return table_log_add_error(r);
327 }
328 }
329
330 r = sd_bus_message_exit_container(reply);
331 if (r < 0)
332 return bus_log_parse_error(r);
333
334 return show_table(table, "machines");
335 }
336
337 static int list_images(int argc, char *argv[], void *userdata) {
338
339 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
340 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
341 _cleanup_(table_unrefp) Table *table = NULL;
342 sd_bus *bus = ASSERT_PTR(userdata);
343 int r;
344
345 pager_open(arg_pager_flags);
346
347 r = bus_call_method(bus, bus_machine_mgr, "ListImages", &error, &reply, NULL);
348 if (r < 0)
349 return log_error_errno(r, "Could not get images: %s", bus_error_message(&error, r));
350
351 table = table_new("name", "type", "ro", "usage", "created", "modified");
352 if (!table)
353 return log_oom();
354
355 if (arg_full)
356 table_set_width(table, 0);
357
358 (void) table_set_align_percent(table, TABLE_HEADER_CELL(3), 100);
359
360 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
361 if (r < 0)
362 return bus_log_parse_error(r);
363
364 for (;;) {
365 uint64_t crtime, mtime, size;
366 const char *name, *type;
367 int ro_int;
368
369 r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &ro_int, &crtime, &mtime, &size, NULL);
370 if (r < 0)
371 return bus_log_parse_error(r);
372 if (r == 0)
373 break;
374
375 if (name[0] == '.' && !arg_all)
376 continue;
377
378 r = table_add_many(table,
379 TABLE_STRING, name,
380 TABLE_STRING, type,
381 TABLE_BOOLEAN, ro_int,
382 TABLE_SET_COLOR, ro_int ? ansi_highlight_red() : NULL,
383 TABLE_SIZE, size,
384 TABLE_TIMESTAMP, crtime,
385 TABLE_TIMESTAMP, mtime);
386 if (r < 0)
387 return table_log_add_error(r);
388 }
389
390 r = sd_bus_message_exit_container(reply);
391 if (r < 0)
392 return bus_log_parse_error(r);
393
394 return show_table(table, "images");
395 }
396
397 static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
398 _cleanup_free_ char *cgroup = NULL;
399 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
400 int r;
401 unsigned c;
402
403 assert(bus);
404 assert(unit);
405
406 r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup);
407 if (r < 0)
408 return r;
409
410 if (isempty(cgroup))
411 return 0;
412
413 c = columns();
414 if (c > 18)
415 c -= 18;
416 else
417 c = 0;
418
419 r = unit_show_processes(bus, unit, cgroup, "\t\t ", c, get_output_flags(), &error);
420 if (r == -EBADR) {
421
422 if (arg_transport == BUS_TRANSPORT_REMOTE)
423 return 0;
424
425 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
426
427 if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
428 return 0;
429
430 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags());
431 } else if (r < 0)
432 return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r));
433
434 return 0;
435 }
436
437 static int print_os_release(sd_bus *bus, const char *method, const char *name, const char *prefix) {
438 _cleanup_free_ char *pretty = NULL;
439 int r;
440
441 assert(bus);
442 assert(name);
443 assert(prefix);
444
445 r = call_get_os_release(bus, method, name, "PRETTY_NAME\0", &pretty, NULL);
446 if (r < 0)
447 return r;
448
449 if (pretty)
450 printf("%s%s\n", prefix, pretty);
451
452 return 0;
453 }
454
455 static int print_uid_shift(sd_bus *bus, const char *name) {
456 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
457 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
458 uint32_t shift;
459 int r;
460
461 assert(bus);
462 assert(name);
463
464 r = bus_call_method(bus, bus_machine_mgr, "GetMachineUIDShift", &error, &reply, "s", name);
465 if (r < 0)
466 return log_debug_errno(r, "Failed to query UID/GID shift: %s", bus_error_message(&error, r));
467
468 r = sd_bus_message_read(reply, "u", &shift);
469 if (r < 0)
470 return r;
471
472 if (shift == 0) /* Don't show trivial mappings */
473 return 0;
474
475 printf(" UID Shift: %" PRIu32 "\n", shift);
476 return 0;
477 }
478
479 typedef struct MachineStatusInfo {
480 const char *name;
481 sd_id128_t id;
482 const char *class;
483 const char *service;
484 const char *unit;
485 const char *root_directory;
486 pid_t leader;
487 struct dual_timestamp timestamp;
488 int *netif;
489 size_t n_netif;
490 } MachineStatusInfo;
491
492 static void machine_status_info_clear(MachineStatusInfo *info) {
493 if (info) {
494 free(info->netif);
495 zero(*info);
496 }
497 }
498
499 static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
500 _cleanup_free_ char *addresses = NULL, *s1 = NULL, *s2 = NULL;
501 int ifi = -1;
502
503 assert(bus);
504 assert(i);
505
506 fputs(strna(i->name), stdout);
507
508 if (!sd_id128_is_null(i->id))
509 printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
510 else
511 putchar('\n');
512
513 s1 = strdup(strempty(FORMAT_TIMESTAMP_RELATIVE(i->timestamp.realtime)));
514 s2 = strdup(strempty(FORMAT_TIMESTAMP(i->timestamp.realtime)));
515
516 if (!isempty(s1))
517 printf("\t Since: %s; %s\n", strna(s2), s1);
518 else if (!isempty(s2))
519 printf("\t Since: %s\n", s2);
520
521 if (i->leader > 0) {
522 _cleanup_free_ char *t = NULL;
523
524 printf("\t Leader: %u", (unsigned) i->leader);
525
526 (void) get_process_comm(i->leader, &t);
527 if (t)
528 printf(" (%s)", t);
529
530 putchar('\n');
531 }
532
533 if (i->service) {
534 printf("\t Service: %s", i->service);
535
536 if (i->class)
537 printf("; class %s", i->class);
538
539 putchar('\n');
540 } else if (i->class)
541 printf("\t Class: %s\n", i->class);
542
543 if (i->root_directory)
544 printf("\t Root: %s\n", i->root_directory);
545
546 if (i->n_netif > 0) {
547 fputs("\t Iface:", stdout);
548
549 for (size_t c = 0; c < i->n_netif; c++) {
550 char name[IF_NAMESIZE];
551
552 if (format_ifname(i->netif[c], name) >= 0) {
553 fputc(' ', stdout);
554 fputs(name, stdout);
555
556 if (ifi < 0)
557 ifi = i->netif[c];
558 else
559 ifi = 0;
560 } else
561 printf(" %i", i->netif[c]);
562 }
563
564 fputc('\n', stdout);
565 }
566
567 if (call_get_addresses(bus, i->name, ifi,
568 "\t Address: ", "\n\t ",
569 &addresses) > 0) {
570 fputs(addresses, stdout);
571 fputc('\n', stdout);
572 }
573
574 print_os_release(bus, "GetMachineOSRelease", i->name, "\t OS: ");
575
576 print_uid_shift(bus, i->name);
577
578 if (i->unit) {
579 printf("\t Unit: %s\n", i->unit);
580 show_unit_cgroup(bus, i->unit, i->leader);
581
582 if (arg_transport == BUS_TRANSPORT_LOCAL)
583
584 show_journal_by_unit(
585 stdout,
586 i->unit,
587 NULL,
588 arg_output,
589 0,
590 i->timestamp.monotonic,
591 arg_lines,
592 0,
593 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
594 SD_JOURNAL_LOCAL_ONLY,
595 true,
596 NULL);
597 }
598 }
599
600 static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
601 MachineStatusInfo *i = userdata;
602 size_t l;
603 const void *v;
604 int r;
605
606 assert_cc(sizeof(int32_t) == sizeof(int));
607 r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
608 if (r < 0)
609 return r;
610 if (r == 0)
611 return -EBADMSG;
612
613 i->n_netif = l / sizeof(int32_t);
614 i->netif = memdup(v, l);
615 if (!i->netif)
616 return -ENOMEM;
617
618 return 0;
619 }
620
621 static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
622
623 static const struct bus_properties_map map[] = {
624 { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
625 { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
626 { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
627 { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
628 { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
629 { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
630 { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) },
631 { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) },
632 { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
633 { "NetworkInterfaces", "ai", map_netif, 0 },
634 {}
635 };
636
637 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
638 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
639 _cleanup_(machine_status_info_clear) MachineStatusInfo info = {};
640 int r;
641
642 assert(verb);
643 assert(bus);
644 assert(path);
645 assert(new_line);
646
647 r = bus_map_all_properties(bus,
648 "org.freedesktop.machine1",
649 path,
650 map,
651 0,
652 &error,
653 &m,
654 &info);
655 if (r < 0)
656 return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
657
658 if (*new_line)
659 printf("\n");
660 *new_line = true;
661
662 print_machine_status_info(bus, &info);
663
664 return r;
665 }
666
667 static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) {
668 int r;
669
670 assert(bus);
671 assert(path);
672 assert(new_line);
673
674 if (*new_line)
675 printf("\n");
676
677 *new_line = true;
678
679 r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_print_flags, NULL);
680 if (r < 0)
681 log_error_errno(r, "Could not get properties: %m");
682
683 return r;
684 }
685
686 static int show_machine(int argc, char *argv[], void *userdata) {
687
688 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
689 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
690 bool properties, new_line = false;
691 sd_bus *bus = ASSERT_PTR(userdata);
692 int r = 0;
693
694 properties = !strstr(argv[0], "status");
695
696 pager_open(arg_pager_flags);
697
698 if (properties && argc <= 1) {
699
700 /* If no argument is specified, inspect the manager
701 * itself */
702 r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line);
703 if (r < 0)
704 return r;
705 }
706
707 for (int i = 1; i < argc; i++) {
708 const char *path = NULL;
709
710 r = bus_call_method(bus, bus_machine_mgr, "GetMachine", &error, &reply, "s", argv[i]);
711 if (r < 0)
712 return log_error_errno(r, "Could not get path to machine: %s", bus_error_message(&error, r));
713
714 r = sd_bus_message_read(reply, "o", &path);
715 if (r < 0)
716 return bus_log_parse_error(r);
717
718 if (properties)
719 r = show_machine_properties(bus, path, &new_line);
720 else
721 r = show_machine_info(argv[0], bus, path, &new_line);
722 }
723
724 return r;
725 }
726
727 static int print_image_hostname(sd_bus *bus, const char *name) {
728 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
729 const char *hn;
730 int r;
731
732 r = bus_call_method(bus, bus_machine_mgr, "GetImageHostname", NULL, &reply, "s", name);
733 if (r < 0)
734 return r;
735
736 r = sd_bus_message_read(reply, "s", &hn);
737 if (r < 0)
738 return r;
739
740 if (!isempty(hn))
741 printf("\tHostname: %s\n", hn);
742
743 return 0;
744 }
745
746 static int print_image_machine_id(sd_bus *bus, const char *name) {
747 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
748 sd_id128_t id = SD_ID128_NULL;
749 const void *p;
750 size_t size;
751 int r;
752
753 r = bus_call_method(bus, bus_machine_mgr, "GetImageMachineID", NULL, &reply, "s", name);
754 if (r < 0)
755 return r;
756
757 r = sd_bus_message_read_array(reply, 'y', &p, &size);
758 if (r < 0)
759 return r;
760
761 if (size == sizeof(sd_id128_t))
762 memcpy(&id, p, size);
763
764 if (!sd_id128_is_null(id))
765 printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id));
766
767 return 0;
768 }
769
770 static int print_image_machine_info(sd_bus *bus, const char *name) {
771 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
772 int r;
773
774 r = bus_call_method(bus, bus_machine_mgr, "GetImageMachineInfo", NULL, &reply, "s", name);
775 if (r < 0)
776 return r;
777
778 r = sd_bus_message_enter_container(reply, 'a', "{ss}");
779 if (r < 0)
780 return r;
781
782 for (;;) {
783 const char *p, *q;
784
785 r = sd_bus_message_read(reply, "{ss}", &p, &q);
786 if (r < 0)
787 return r;
788 if (r == 0)
789 break;
790
791 if (streq(p, "DEPLOYMENT"))
792 printf(" Deployment: %s\n", q);
793 }
794
795 r = sd_bus_message_exit_container(reply);
796 if (r < 0)
797 return r;
798
799 return 0;
800 }
801
802 typedef struct ImageStatusInfo {
803 const char *name;
804 const char *path;
805 const char *type;
806 bool read_only;
807 usec_t crtime;
808 usec_t mtime;
809 uint64_t usage;
810 uint64_t limit;
811 uint64_t usage_exclusive;
812 uint64_t limit_exclusive;
813 } ImageStatusInfo;
814
815 static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
816 assert(bus);
817 assert(i);
818
819 if (i->name) {
820 fputs(i->name, stdout);
821 putchar('\n');
822 }
823
824 if (i->type)
825 printf("\t Type: %s\n", i->type);
826
827 if (i->path)
828 printf("\t Path: %s\n", i->path);
829
830 (void) print_image_hostname(bus, i->name);
831 (void) print_image_machine_id(bus, i->name);
832 (void) print_image_machine_info(bus, i->name);
833
834 print_os_release(bus, "GetImageOSRelease", i->name, "\t OS: ");
835
836 printf("\t RO: %s%s%s\n",
837 i->read_only ? ansi_highlight_red() : "",
838 i->read_only ? "read-only" : "writable",
839 i->read_only ? ansi_normal() : "");
840
841 if (timestamp_is_set(i->crtime))
842 printf("\t Created: %s; %s\n",
843 FORMAT_TIMESTAMP(i->crtime), FORMAT_TIMESTAMP_RELATIVE(i->crtime));
844
845 if (timestamp_is_set(i->mtime))
846 printf("\tModified: %s; %s\n",
847 FORMAT_TIMESTAMP(i->mtime), FORMAT_TIMESTAMP_RELATIVE(i->mtime));
848
849 if (i->usage != UINT64_MAX) {
850 if (i->usage_exclusive != i->usage && i->usage_exclusive != UINT64_MAX)
851 printf("\t Usage: %s (exclusive: %s)\n",
852 FORMAT_BYTES(i->usage), FORMAT_BYTES(i->usage_exclusive));
853 else
854 printf("\t Usage: %s\n", FORMAT_BYTES(i->usage));
855 }
856
857 if (i->limit != UINT64_MAX) {
858 if (i->limit_exclusive != i->limit && i->limit_exclusive != UINT64_MAX)
859 printf("\t Limit: %s (exclusive: %s)\n",
860 FORMAT_BYTES(i->limit), FORMAT_BYTES(i->limit_exclusive));
861 else
862 printf("\t Limit: %s\n", FORMAT_BYTES(i->limit));
863 }
864 }
865
866 static int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
867
868 static const struct bus_properties_map map[] = {
869 { "Name", "s", NULL, offsetof(ImageStatusInfo, name) },
870 { "Path", "s", NULL, offsetof(ImageStatusInfo, path) },
871 { "Type", "s", NULL, offsetof(ImageStatusInfo, type) },
872 { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) },
873 { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
874 { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
875 { "Usage", "t", NULL, offsetof(ImageStatusInfo, usage) },
876 { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
877 { "UsageExclusive", "t", NULL, offsetof(ImageStatusInfo, usage_exclusive) },
878 { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
879 {}
880 };
881
882 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
883 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
884 ImageStatusInfo info = {};
885 int r;
886
887 assert(bus);
888 assert(path);
889 assert(new_line);
890
891 r = bus_map_all_properties(bus,
892 "org.freedesktop.machine1",
893 path,
894 map,
895 BUS_MAP_BOOLEAN_AS_BOOL,
896 &error,
897 &m,
898 &info);
899 if (r < 0)
900 return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
901
902 if (*new_line)
903 printf("\n");
904 *new_line = true;
905
906 print_image_status_info(bus, &info);
907
908 return r;
909 }
910
911 typedef struct PoolStatusInfo {
912 const char *path;
913 uint64_t usage;
914 uint64_t limit;
915 } PoolStatusInfo;
916
917 static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) {
918 if (i->path)
919 printf("\t Path: %s\n", i->path);
920
921 if (i->usage != UINT64_MAX)
922 printf("\t Usage: %s\n", FORMAT_BYTES(i->usage));
923
924 if (i->limit != UINT64_MAX)
925 printf("\t Limit: %s\n", FORMAT_BYTES(i->limit));
926 }
927
928 static int show_pool_info(sd_bus *bus) {
929
930 static const struct bus_properties_map map[] = {
931 { "PoolPath", "s", NULL, offsetof(PoolStatusInfo, path) },
932 { "PoolUsage", "t", NULL, offsetof(PoolStatusInfo, usage) },
933 { "PoolLimit", "t", NULL, offsetof(PoolStatusInfo, limit) },
934 {}
935 };
936
937 PoolStatusInfo info = {
938 .usage = UINT64_MAX,
939 .limit = UINT64_MAX,
940 };
941
942 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
943 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
944 int r;
945
946 assert(bus);
947
948 r = bus_map_all_properties(bus,
949 "org.freedesktop.machine1",
950 "/org/freedesktop/machine1",
951 map,
952 0,
953 &error,
954 &m,
955 &info);
956 if (r < 0)
957 return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r));
958
959 print_pool_status_info(bus, &info);
960
961 return 0;
962 }
963
964 static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
965 int r;
966
967 assert(bus);
968 assert(path);
969 assert(new_line);
970
971 if (*new_line)
972 printf("\n");
973
974 *new_line = true;
975
976 r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_print_flags, NULL);
977 if (r < 0)
978 log_error_errno(r, "Could not get properties: %m");
979
980 return r;
981 }
982
983 static int show_image(int argc, char *argv[], void *userdata) {
984
985 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
986 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
987 bool properties, new_line = false;
988 sd_bus *bus = ASSERT_PTR(userdata);
989 int r = 0;
990
991 properties = !strstr(argv[0], "status");
992
993 pager_open(arg_pager_flags);
994
995 if (argc <= 1) {
996
997 /* If no argument is specified, inspect the manager
998 * itself */
999
1000 if (properties)
1001 r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line);
1002 else
1003 r = show_pool_info(bus);
1004 if (r < 0)
1005 return r;
1006 }
1007
1008 for (int i = 1; i < argc; i++) {
1009 const char *path = NULL;
1010
1011 r = bus_call_method(bus, bus_machine_mgr, "GetImage", &error, &reply, "s", argv[i]);
1012 if (r < 0)
1013 return log_error_errno(r, "Could not get path to image: %s", bus_error_message(&error, r));
1014
1015 r = sd_bus_message_read(reply, "o", &path);
1016 if (r < 0)
1017 return bus_log_parse_error(r);
1018
1019 if (properties)
1020 r = show_image_properties(bus, path, &new_line);
1021 else
1022 r = show_image_info(bus, path, &new_line);
1023 }
1024
1025 return r;
1026 }
1027
1028 static int kill_machine(int argc, char *argv[], void *userdata) {
1029 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1030 sd_bus *bus = ASSERT_PTR(userdata);
1031 int r;
1032
1033 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1034
1035 if (!arg_kill_whom)
1036 arg_kill_whom = "all";
1037
1038 for (int i = 1; i < argc; i++) {
1039 r = bus_call_method(
1040 bus,
1041 bus_machine_mgr,
1042 "KillMachine",
1043 &error,
1044 NULL,
1045 "ssi", argv[i], arg_kill_whom, arg_signal);
1046 if (r < 0)
1047 return log_error_errno(r, "Could not kill machine: %s", bus_error_message(&error, r));
1048 }
1049
1050 return 0;
1051 }
1052
1053 static int reboot_machine(int argc, char *argv[], void *userdata) {
1054 arg_kill_whom = "leader";
1055 arg_signal = SIGINT; /* sysvinit + systemd */
1056
1057 return kill_machine(argc, argv, userdata);
1058 }
1059
1060 static int poweroff_machine(int argc, char *argv[], void *userdata) {
1061 arg_kill_whom = "leader";
1062 arg_signal = SIGRTMIN+4; /* only systemd */
1063
1064 return kill_machine(argc, argv, userdata);
1065 }
1066
1067 static int terminate_machine(int argc, char *argv[], void *userdata) {
1068 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1069 sd_bus *bus = ASSERT_PTR(userdata);
1070 int r;
1071
1072 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1073
1074 for (int i = 1; i < argc; i++) {
1075 r = bus_call_method(bus, bus_machine_mgr, "TerminateMachine", &error, NULL, "s", argv[i]);
1076 if (r < 0)
1077 return log_error_errno(r, "Could not terminate machine: %s", bus_error_message(&error, r));
1078 }
1079
1080 return 0;
1081 }
1082
1083 static const char *select_copy_method(bool copy_from, bool force) {
1084 if (force)
1085 return copy_from ? "CopyFromMachineWithFlags" : "CopyToMachineWithFlags";
1086 else
1087 return copy_from ? "CopyFromMachine" : "CopyToMachine";
1088 }
1089
1090 static int copy_files(int argc, char *argv[], void *userdata) {
1091 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1092 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1093 _cleanup_free_ char *abs_host_path = NULL;
1094 char *dest, *host_path, *container_path;
1095 sd_bus *bus = ASSERT_PTR(userdata);
1096 bool copy_from;
1097 int r;
1098
1099 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1100
1101 copy_from = streq(argv[0], "copy-from");
1102 dest = argv[3] ?: argv[2];
1103 host_path = copy_from ? dest : argv[2];
1104 container_path = copy_from ? argv[2] : dest;
1105
1106 if (!path_is_absolute(host_path)) {
1107 r = path_make_absolute_cwd(host_path, &abs_host_path);
1108 if (r < 0)
1109 return log_error_errno(r, "Failed to make path absolute: %m");
1110
1111 host_path = abs_host_path;
1112 }
1113
1114 r = bus_message_new_method_call(
1115 bus,
1116 &m,
1117 bus_machine_mgr,
1118 select_copy_method(copy_from, arg_force));
1119 if (r < 0)
1120 return bus_log_create_error(r);
1121
1122 r = sd_bus_message_append(
1123 m,
1124 "sss",
1125 argv[1],
1126 copy_from ? container_path : host_path,
1127 copy_from ? host_path : container_path);
1128 if (r < 0)
1129 return bus_log_create_error(r);
1130
1131 if (arg_force) {
1132 r = sd_bus_message_append(m, "t", MACHINE_COPY_REPLACE);
1133 if (r < 0)
1134 return bus_log_create_error(r);
1135 }
1136
1137 /* This is a slow operation, hence turn off any method call timeouts */
1138 r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL);
1139 if (r < 0)
1140 return log_error_errno(r, "Failed to copy: %s", bus_error_message(&error, r));
1141
1142 return 0;
1143 }
1144
1145 static int bind_mount(int argc, char *argv[], void *userdata) {
1146 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1147 sd_bus *bus = ASSERT_PTR(userdata);
1148 int r;
1149
1150 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1151
1152 r = bus_call_method(
1153 bus,
1154 bus_machine_mgr,
1155 "BindMountMachine",
1156 &error,
1157 NULL,
1158 "sssbb",
1159 argv[1],
1160 argv[2],
1161 argv[3],
1162 arg_read_only,
1163 arg_mkdir);
1164 if (r < 0)
1165 return log_error_errno(r, "Failed to bind mount: %s", bus_error_message(&error, r));
1166
1167 return 0;
1168 }
1169
1170 static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
1171 PTYForward ** forward = (PTYForward**) userdata;
1172 int r;
1173
1174 assert(m);
1175 assert(forward);
1176
1177 if (*forward) {
1178 /* If the forwarder is already initialized, tell it to
1179 * exit on the next vhangup(), so that we still flush
1180 * out what might be queued and exit then. */
1181
1182 r = pty_forward_set_ignore_vhangup(*forward, false);
1183 if (r >= 0)
1184 return 0;
1185
1186 log_error_errno(r, "Failed to set ignore_vhangup flag: %m");
1187 }
1188
1189 /* On error, or when the forwarder is not initialized yet, quit immediately */
1190 sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), EXIT_FAILURE);
1191 return 0;
1192 }
1193
1194 static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) {
1195 char last_char = 0;
1196 bool machine_died;
1197 int r;
1198
1199 assert(event);
1200 assert(master >= 0);
1201 assert(name);
1202
1203 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
1204
1205 if (!arg_quiet) {
1206 if (streq(name, ".host"))
1207 log_info("Connected to the local host. Press ^] three times within 1s to exit session.");
1208 else
1209 log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name);
1210 }
1211
1212 (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
1213 (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
1214
1215 r = pty_forward_new(event, master, flags, forward);
1216 if (r < 0)
1217 return log_error_errno(r, "Failed to create PTY forwarder: %m");
1218
1219 r = sd_event_loop(event);
1220 if (r < 0)
1221 return log_error_errno(r, "Failed to run event loop: %m");
1222
1223 pty_forward_get_last_char(*forward, &last_char);
1224
1225 machine_died =
1226 (flags & PTY_FORWARD_IGNORE_VHANGUP) &&
1227 pty_forward_get_ignore_vhangup(*forward) == 0;
1228
1229 *forward = pty_forward_free(*forward);
1230
1231 if (last_char != '\n')
1232 fputc('\n', stdout);
1233
1234 if (!arg_quiet) {
1235 if (machine_died)
1236 log_info("Machine %s terminated.", name);
1237 else if (streq(name, ".host"))
1238 log_info("Connection to the local host terminated.");
1239 else
1240 log_info("Connection to machine %s terminated.", name);
1241 }
1242
1243 return 0;
1244 }
1245
1246 static int parse_machine_uid(const char *spec, const char **machine, char **uid) {
1247 /*
1248 * Whatever is specified in the spec takes priority over global arguments.
1249 */
1250 char *_uid = NULL;
1251 const char *_machine = NULL;
1252
1253 if (spec) {
1254 const char *at;
1255
1256 at = strchr(spec, '@');
1257 if (at) {
1258 if (at == spec)
1259 /* Do the same as ssh and refuse "@host". */
1260 return -EINVAL;
1261
1262 _machine = at + 1;
1263 _uid = strndup(spec, at - spec);
1264 if (!_uid)
1265 return -ENOMEM;
1266 } else
1267 _machine = spec;
1268 };
1269
1270 if (arg_uid && !_uid) {
1271 _uid = strdup(arg_uid);
1272 if (!_uid)
1273 return -ENOMEM;
1274 }
1275
1276 *uid = _uid;
1277 *machine = isempty(_machine) ? ".host" : _machine;
1278 return 0;
1279 }
1280
1281 static int login_machine(int argc, char *argv[], void *userdata) {
1282 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1283 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1284 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
1285 _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
1286 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
1287 int master = -1, r;
1288 sd_bus *bus = ASSERT_PTR(userdata);
1289 const char *match, *machine;
1290
1291 if (!strv_isempty(arg_setenv) || arg_uid)
1292 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1293 "--setenv= and --uid= are not supported for 'login'. Use 'shell' instead.");
1294
1295 if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE))
1296 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1297 "Login only supported on local machines.");
1298
1299 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1300
1301 r = sd_event_default(&event);
1302 if (r < 0)
1303 return log_error_errno(r, "Failed to get event loop: %m");
1304
1305 r = sd_bus_attach_event(bus, event, 0);
1306 if (r < 0)
1307 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1308
1309 machine = argc < 2 || isempty(argv[1]) ? ".host" : argv[1];
1310
1311 match = strjoina("type='signal',"
1312 "sender='org.freedesktop.machine1',"
1313 "path='/org/freedesktop/machine1',",
1314 "interface='org.freedesktop.machine1.Manager',"
1315 "member='MachineRemoved',"
1316 "arg0='", machine, "'");
1317
1318 r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward);
1319 if (r < 0)
1320 return log_error_errno(r, "Failed to request machine removal match: %m");
1321
1322 r = bus_call_method(bus, bus_machine_mgr, "OpenMachineLogin", &error, &reply, "s", machine);
1323 if (r < 0)
1324 return log_error_errno(r, "Failed to get login PTY: %s", bus_error_message(&error, r));
1325
1326 r = sd_bus_message_read(reply, "hs", &master, NULL);
1327 if (r < 0)
1328 return bus_log_parse_error(r);
1329
1330 return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_VHANGUP, machine);
1331 }
1332
1333 static int shell_machine(int argc, char *argv[], void *userdata) {
1334 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
1335 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1336 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
1337 _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
1338 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
1339 int master = -1, r;
1340 sd_bus *bus = ASSERT_PTR(userdata);
1341 const char *match, *machine, *path;
1342 _cleanup_free_ char *uid = NULL;
1343
1344 if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE))
1345 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1346 "Shell only supported on local machines.");
1347
1348 /* Pass $TERM to shell session, if not explicitly specified. */
1349 if (!strv_find_prefix(arg_setenv, "TERM=")) {
1350 const char *t;
1351
1352 t = strv_find_prefix(environ, "TERM=");
1353 if (t) {
1354 if (strv_extend(&arg_setenv, t) < 0)
1355 return log_oom();
1356 }
1357 }
1358
1359 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1360
1361 r = sd_event_default(&event);
1362 if (r < 0)
1363 return log_error_errno(r, "Failed to get event loop: %m");
1364
1365 r = sd_bus_attach_event(bus, event, 0);
1366 if (r < 0)
1367 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1368
1369 r = parse_machine_uid(argc >= 2 ? argv[1] : NULL, &machine, &uid);
1370 if (r < 0)
1371 return log_error_errno(r, "Failed to parse machine specification: %m");
1372
1373 match = strjoina("type='signal',"
1374 "sender='org.freedesktop.machine1',"
1375 "path='/org/freedesktop/machine1',",
1376 "interface='org.freedesktop.machine1.Manager',"
1377 "member='MachineRemoved',"
1378 "arg0='", machine, "'");
1379
1380 r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward);
1381 if (r < 0)
1382 return log_error_errno(r, "Failed to request machine removal match: %m");
1383
1384 r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "OpenMachineShell");
1385 if (r < 0)
1386 return bus_log_create_error(r);
1387
1388 path = argc < 3 || isempty(argv[2]) ? NULL : argv[2];
1389
1390 r = sd_bus_message_append(m, "sss", machine, uid, path);
1391 if (r < 0)
1392 return bus_log_create_error(r);
1393
1394 r = sd_bus_message_append_strv(m, strv_length(argv) <= 3 ? NULL : argv + 2);
1395 if (r < 0)
1396 return bus_log_create_error(r);
1397
1398 r = sd_bus_message_append_strv(m, arg_setenv);
1399 if (r < 0)
1400 return bus_log_create_error(r);
1401
1402 r = sd_bus_call(bus, m, 0, &error, &reply);
1403 if (r < 0)
1404 return log_error_errno(r, "Failed to get shell PTY: %s", bus_error_message(&error, r));
1405
1406 r = sd_bus_message_read(reply, "hs", &master, NULL);
1407 if (r < 0)
1408 return bus_log_parse_error(r);
1409
1410 return process_forward(event, &forward, master, 0, machine);
1411 }
1412
1413 static int remove_image(int argc, char *argv[], void *userdata) {
1414 sd_bus *bus = ASSERT_PTR(userdata);
1415 int r;
1416
1417 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1418
1419 for (int i = 1; i < argc; i++) {
1420 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1421 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1422
1423 r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "RemoveImage");
1424 if (r < 0)
1425 return bus_log_create_error(r);
1426
1427 r = sd_bus_message_append(m, "s", argv[i]);
1428 if (r < 0)
1429 return bus_log_create_error(r);
1430
1431 /* This is a slow operation, hence turn off any method call timeouts */
1432 r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL);
1433 if (r < 0)
1434 return log_error_errno(r, "Could not remove image: %s", bus_error_message(&error, r));
1435 }
1436
1437 return 0;
1438 }
1439
1440 static int rename_image(int argc, char *argv[], void *userdata) {
1441 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1442 sd_bus *bus = ASSERT_PTR(userdata);
1443 int r;
1444
1445 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1446
1447 r = bus_call_method(
1448 bus,
1449 bus_machine_mgr,
1450 "RenameImage",
1451 &error,
1452 NULL,
1453 "ss", argv[1], argv[2]);
1454 if (r < 0)
1455 return log_error_errno(r, "Could not rename image: %s", bus_error_message(&error, r));
1456
1457 return 0;
1458 }
1459
1460 static int clone_image(int argc, char *argv[], void *userdata) {
1461 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1462 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1463 sd_bus *bus = ASSERT_PTR(userdata);
1464 int r;
1465
1466 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1467
1468 r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "CloneImage");
1469 if (r < 0)
1470 return bus_log_create_error(r);
1471
1472 r = sd_bus_message_append(m, "ssb", argv[1], argv[2], arg_read_only);
1473 if (r < 0)
1474 return bus_log_create_error(r);
1475
1476 /* This is a slow operation, hence turn off any method call timeouts */
1477 r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL);
1478 if (r < 0)
1479 return log_error_errno(r, "Could not clone image: %s", bus_error_message(&error, r));
1480
1481 return 0;
1482 }
1483
1484 static int read_only_image(int argc, char *argv[], void *userdata) {
1485 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1486 sd_bus *bus = ASSERT_PTR(userdata);
1487 int b = true, r;
1488
1489 if (argc > 2) {
1490 b = parse_boolean(argv[2]);
1491 if (b < 0)
1492 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1493 "Failed to parse boolean argument: %s",
1494 argv[2]);
1495 }
1496
1497 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1498
1499 r = bus_call_method(bus, bus_machine_mgr, "MarkImageReadOnly", &error, NULL, "sb", argv[1], b);
1500 if (r < 0)
1501 return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, r));
1502
1503 return 0;
1504 }
1505
1506 static int image_exists(sd_bus *bus, const char *name) {
1507 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1508 int r;
1509
1510 assert(bus);
1511 assert(name);
1512
1513 r = bus_call_method(bus, bus_machine_mgr, "GetImage", &error, NULL, "s", name);
1514 if (r < 0) {
1515 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_IMAGE))
1516 return 0;
1517
1518 return log_error_errno(r, "Failed to check whether image %s exists: %s", name, bus_error_message(&error, r));
1519 }
1520
1521 return 1;
1522 }
1523
1524 static int make_service_name(const char *name, char **ret) {
1525 int r;
1526
1527 assert(name);
1528 assert(ret);
1529
1530 if (!hostname_is_valid(name, 0))
1531 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1532 "Invalid machine name %s.", name);
1533
1534 r = unit_name_build("systemd-nspawn", name, ".service", ret);
1535 if (r < 0)
1536 return log_error_errno(r, "Failed to build unit name: %m");
1537
1538 return 0;
1539 }
1540
1541 static int start_machine(int argc, char *argv[], void *userdata) {
1542 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1543 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
1544 sd_bus *bus = ASSERT_PTR(userdata);
1545 int r;
1546
1547 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1548 ask_password_agent_open_if_enabled(arg_transport, arg_ask_password);
1549
1550 r = bus_wait_for_jobs_new(bus, &w);
1551 if (r < 0)
1552 return log_oom();
1553
1554 for (int i = 1; i < argc; i++) {
1555 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1556 _cleanup_free_ char *unit = NULL;
1557 const char *object;
1558
1559 r = make_service_name(argv[i], &unit);
1560 if (r < 0)
1561 return r;
1562
1563 r = image_exists(bus, argv[i]);
1564 if (r < 0)
1565 return r;
1566 if (r == 0)
1567 return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
1568 "Machine image '%s' does not exist.",
1569 argv[i]);
1570
1571 r = bus_call_method(
1572 bus,
1573 bus_systemd_mgr,
1574 "StartUnit",
1575 &error,
1576 &reply,
1577 "ss", unit, "fail");
1578 if (r < 0)
1579 return log_error_errno(r, "Failed to start unit: %s", bus_error_message(&error, r));
1580
1581 r = sd_bus_message_read(reply, "o", &object);
1582 if (r < 0)
1583 return bus_log_parse_error(r);
1584
1585 r = bus_wait_for_jobs_add(w, object);
1586 if (r < 0)
1587 return log_oom();
1588 }
1589
1590 r = bus_wait_for_jobs(w, arg_quiet, NULL);
1591 if (r < 0)
1592 return r;
1593
1594 return 0;
1595 }
1596
1597 static int enable_machine(int argc, char *argv[], void *userdata) {
1598 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
1599 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1600 InstallChange *changes = NULL;
1601 size_t n_changes = 0;
1602 const char *method = NULL;
1603 sd_bus *bus = ASSERT_PTR(userdata);
1604 int r;
1605
1606 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1607
1608 method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles";
1609
1610 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
1611 if (r < 0)
1612 return bus_log_create_error(r);
1613
1614 r = sd_bus_message_open_container(m, 'a', "s");
1615 if (r < 0)
1616 return bus_log_create_error(r);
1617
1618 for (int i = 1; i < argc; i++) {
1619 _cleanup_free_ char *unit = NULL;
1620
1621 r = make_service_name(argv[i], &unit);
1622 if (r < 0)
1623 return r;
1624
1625 r = image_exists(bus, argv[i]);
1626 if (r < 0)
1627 return r;
1628 if (r == 0)
1629 return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
1630 "Machine image '%s' does not exist.",
1631 argv[i]);
1632
1633 r = sd_bus_message_append(m, "s", unit);
1634 if (r < 0)
1635 return bus_log_create_error(r);
1636 }
1637
1638 r = sd_bus_message_close_container(m);
1639 if (r < 0)
1640 return bus_log_create_error(r);
1641
1642 if (streq(argv[0], "enable"))
1643 r = sd_bus_message_append(m, "bb", false, false);
1644 else
1645 r = sd_bus_message_append(m, "b", false);
1646 if (r < 0)
1647 return bus_log_create_error(r);
1648
1649 r = sd_bus_call(bus, m, 0, &error, &reply);
1650 if (r < 0)
1651 return log_error_errno(r, "Failed to enable or disable unit: %s", bus_error_message(&error, r));
1652
1653 if (streq(argv[0], "enable")) {
1654 r = sd_bus_message_read(reply, "b", NULL);
1655 if (r < 0)
1656 return bus_log_parse_error(r);
1657 }
1658
1659 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
1660 if (r < 0)
1661 goto finish;
1662
1663 r = bus_call_method(bus, bus_systemd_mgr, "Reload", &error, NULL, NULL);
1664 if (r < 0) {
1665 log_error("Failed to reload daemon: %s", bus_error_message(&error, r));
1666 goto finish;
1667 }
1668
1669 r = 0;
1670
1671 finish:
1672 install_changes_free(changes, n_changes);
1673
1674 return r;
1675 }
1676
1677 static int match_log_message(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1678 const char **our_path = userdata, *line;
1679 unsigned priority;
1680 int r;
1681
1682 assert(m);
1683 assert(our_path);
1684
1685 r = sd_bus_message_read(m, "us", &priority, &line);
1686 if (r < 0) {
1687 bus_log_parse_error(r);
1688 return 0;
1689 }
1690
1691 if (!streq_ptr(*our_path, sd_bus_message_get_path(m)))
1692 return 0;
1693
1694 if (arg_quiet && LOG_PRI(priority) >= LOG_INFO)
1695 return 0;
1696
1697 log_full(priority, "%s", line);
1698 return 0;
1699 }
1700
1701 static int match_transfer_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1702 const char **our_path = userdata, *path, *result;
1703 uint32_t id;
1704 int r;
1705
1706 assert(m);
1707 assert(our_path);
1708
1709 r = sd_bus_message_read(m, "uos", &id, &path, &result);
1710 if (r < 0) {
1711 bus_log_parse_error(r);
1712 return 0;
1713 }
1714
1715 if (!streq_ptr(*our_path, path))
1716 return 0;
1717
1718 sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), !streq_ptr(result, "done"));
1719 return 0;
1720 }
1721
1722 static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1723 assert(s);
1724 assert(si);
1725
1726 if (!arg_quiet)
1727 log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to abort transfer.", PTR_TO_UINT32(userdata));
1728
1729 sd_event_exit(sd_event_source_get_event(s), EINTR);
1730 return 0;
1731 }
1732
1733 static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
1734 _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
1735 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1736 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1737 _cleanup_(sd_event_unrefp) sd_event* event = NULL;
1738 const char *path = NULL;
1739 uint32_t id;
1740 int r;
1741
1742 assert(bus);
1743 assert(m);
1744
1745 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
1746
1747 r = sd_event_default(&event);
1748 if (r < 0)
1749 return log_error_errno(r, "Failed to get event loop: %m");
1750
1751 r = sd_bus_attach_event(bus, event, 0);
1752 if (r < 0)
1753 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1754
1755 r = bus_match_signal_async(
1756 bus,
1757 &slot_job_removed,
1758 bus_import_mgr,
1759 "TransferRemoved",
1760 match_transfer_removed, NULL, &path);
1761 if (r < 0)
1762 return log_error_errno(r, "Failed to request match: %m");
1763
1764 r = sd_bus_match_signal_async(
1765 bus,
1766 &slot_log_message,
1767 "org.freedesktop.import1",
1768 NULL,
1769 "org.freedesktop.import1.Transfer",
1770 "LogMessage",
1771 match_log_message, NULL, &path);
1772 if (r < 0)
1773 return log_error_errno(r, "Failed to request match: %m");
1774
1775 r = sd_bus_call(bus, m, 0, &error, &reply);
1776 if (r < 0)
1777 return log_error_errno(r, "Failed to transfer image: %s", bus_error_message(&error, r));
1778
1779 r = sd_bus_message_read(reply, "uo", &id, &path);
1780 if (r < 0)
1781 return bus_log_parse_error(r);
1782
1783 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
1784
1785 if (!arg_quiet)
1786 log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id);
1787
1788 (void) sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
1789 (void) sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
1790
1791 r = sd_event_loop(event);
1792 if (r < 0)
1793 return log_error_errno(r, "Failed to run event loop: %m");
1794
1795 return -r;
1796 }
1797
1798 static int import_tar(int argc, char *argv[], void *userdata) {
1799 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1800 _cleanup_free_ char *ll = NULL, *fn = NULL;
1801 const char *local = NULL, *path = NULL;
1802 _cleanup_close_ int fd = -1;
1803 sd_bus *bus = ASSERT_PTR(userdata);
1804 int r;
1805
1806 if (argc >= 2)
1807 path = empty_or_dash_to_null(argv[1]);
1808
1809 if (argc >= 3)
1810 local = empty_or_dash_to_null(argv[2]);
1811 else if (path) {
1812 r = path_extract_filename(path, &fn);
1813 if (r < 0)
1814 return log_error_errno(r, "Cannot extract container name from filename: %m");
1815 if (r == O_DIRECTORY)
1816 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
1817 "Path '%s' refers to directory, but we need a regular file: %m", path);
1818
1819 local = fn;
1820 }
1821 if (!local)
1822 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1823 "Need either path or local name.");
1824
1825 r = tar_strip_suffixes(local, &ll);
1826 if (r < 0)
1827 return log_oom();
1828
1829 local = ll;
1830
1831 if (!hostname_is_valid(local, 0))
1832 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1833 "Local name %s is not a suitable machine name.",
1834 local);
1835
1836 if (path) {
1837 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
1838 if (fd < 0)
1839 return log_error_errno(errno, "Failed to open %s: %m", path);
1840 }
1841
1842 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportTar");
1843 if (r < 0)
1844 return bus_log_create_error(r);
1845
1846 r = sd_bus_message_append(
1847 m,
1848 "hsbb",
1849 fd >= 0 ? fd : STDIN_FILENO,
1850 local,
1851 arg_force,
1852 arg_read_only);
1853 if (r < 0)
1854 return bus_log_create_error(r);
1855
1856 return transfer_image_common(bus, m);
1857 }
1858
1859 static int import_raw(int argc, char *argv[], void *userdata) {
1860 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1861 _cleanup_free_ char *ll = NULL, *fn = NULL;
1862 const char *local = NULL, *path = NULL;
1863 _cleanup_close_ int fd = -1;
1864 sd_bus *bus = ASSERT_PTR(userdata);
1865 int r;
1866
1867 if (argc >= 2)
1868 path = empty_or_dash_to_null(argv[1]);
1869
1870 if (argc >= 3)
1871 local = empty_or_dash_to_null(argv[2]);
1872 else if (path) {
1873 r = path_extract_filename(path, &fn);
1874 if (r < 0)
1875 return log_error_errno(r, "Cannot extract container name from filename: %m");
1876 if (r == O_DIRECTORY)
1877 return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
1878 "Path '%s' refers to directory, but we need a regular file: %m", path);
1879
1880 local = fn;
1881 }
1882 if (!local)
1883 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1884 "Need either path or local name.");
1885
1886 r = raw_strip_suffixes(local, &ll);
1887 if (r < 0)
1888 return log_oom();
1889
1890 local = ll;
1891
1892 if (!hostname_is_valid(local, 0))
1893 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1894 "Local name %s is not a suitable machine name.",
1895 local);
1896
1897 if (path) {
1898 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
1899 if (fd < 0)
1900 return log_error_errno(errno, "Failed to open %s: %m", path);
1901 }
1902
1903 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportRaw");
1904 if (r < 0)
1905 return bus_log_create_error(r);
1906
1907 r = sd_bus_message_append(
1908 m,
1909 "hsbb",
1910 fd >= 0 ? fd : STDIN_FILENO,
1911 local,
1912 arg_force,
1913 arg_read_only);
1914 if (r < 0)
1915 return bus_log_create_error(r);
1916
1917 return transfer_image_common(bus, m);
1918 }
1919
1920 static int import_fs(int argc, char *argv[], void *userdata) {
1921 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1922 const char *local = NULL, *path = NULL;
1923 _cleanup_free_ char *fn = NULL;
1924 _cleanup_close_ int fd = -1;
1925 sd_bus *bus = ASSERT_PTR(userdata);
1926 int r;
1927
1928 if (argc >= 2)
1929 path = empty_or_dash_to_null(argv[1]);
1930
1931 if (argc >= 3)
1932 local = empty_or_dash_to_null(argv[2]);
1933 else if (path) {
1934 r = path_extract_filename(path, &fn);
1935 if (r < 0)
1936 return log_error_errno(r, "Cannot extract container name from filename: %m");
1937
1938 local = fn;
1939 }
1940 if (!local)
1941 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1942 "Need either path or local name.");
1943
1944 if (!hostname_is_valid(local, 0))
1945 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1946 "Local name %s is not a suitable machine name.",
1947 local);
1948
1949 if (path) {
1950 fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
1951 if (fd < 0)
1952 return log_error_errno(errno, "Failed to open directory '%s': %m", path);
1953 }
1954
1955 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportFileSystem");
1956 if (r < 0)
1957 return bus_log_create_error(r);
1958
1959 r = sd_bus_message_append(
1960 m,
1961 "hsbb",
1962 fd >= 0 ? fd : STDIN_FILENO,
1963 local,
1964 arg_force,
1965 arg_read_only);
1966 if (r < 0)
1967 return bus_log_create_error(r);
1968
1969 return transfer_image_common(bus, m);
1970 }
1971
1972 static void determine_compression_from_filename(const char *p) {
1973 if (arg_format)
1974 return;
1975
1976 if (!p)
1977 return;
1978
1979 if (endswith(p, ".xz"))
1980 arg_format = "xz";
1981 else if (endswith(p, ".gz"))
1982 arg_format = "gzip";
1983 else if (endswith(p, ".bz2"))
1984 arg_format = "bzip2";
1985 }
1986
1987 static int export_tar(int argc, char *argv[], void *userdata) {
1988 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1989 _cleanup_close_ int fd = -1;
1990 const char *local = NULL, *path = NULL;
1991 sd_bus *bus = ASSERT_PTR(userdata);
1992 int r;
1993
1994 local = argv[1];
1995 if (!hostname_is_valid(local, 0))
1996 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1997 "Machine name %s is not valid.", local);
1998
1999 if (argc >= 3)
2000 path = argv[2];
2001 path = empty_or_dash_to_null(path);
2002
2003 if (path) {
2004 determine_compression_from_filename(path);
2005
2006 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
2007 if (fd < 0)
2008 return log_error_errno(errno, "Failed to open %s: %m", path);
2009 }
2010
2011 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportTar");
2012 if (r < 0)
2013 return bus_log_create_error(r);
2014
2015 r = sd_bus_message_append(
2016 m,
2017 "shs",
2018 local,
2019 fd >= 0 ? fd : STDOUT_FILENO,
2020 arg_format);
2021 if (r < 0)
2022 return bus_log_create_error(r);
2023
2024 return transfer_image_common(bus, m);
2025 }
2026
2027 static int export_raw(int argc, char *argv[], void *userdata) {
2028 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2029 _cleanup_close_ int fd = -1;
2030 const char *local = NULL, *path = NULL;
2031 sd_bus *bus = ASSERT_PTR(userdata);
2032 int r;
2033
2034 local = argv[1];
2035 if (!hostname_is_valid(local, 0))
2036 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2037 "Machine name %s is not valid.", local);
2038
2039 if (argc >= 3)
2040 path = argv[2];
2041 path = empty_or_dash_to_null(path);
2042
2043 if (path) {
2044 determine_compression_from_filename(path);
2045
2046 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
2047 if (fd < 0)
2048 return log_error_errno(errno, "Failed to open %s: %m", path);
2049 }
2050
2051 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportRaw");
2052 if (r < 0)
2053 return bus_log_create_error(r);
2054
2055 r = sd_bus_message_append(
2056 m,
2057 "shs",
2058 local,
2059 fd >= 0 ? fd : STDOUT_FILENO,
2060 arg_format);
2061 if (r < 0)
2062 return bus_log_create_error(r);
2063
2064 return transfer_image_common(bus, m);
2065 }
2066
2067 static int pull_tar(int argc, char *argv[], void *userdata) {
2068 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2069 _cleanup_free_ char *l = NULL, *ll = NULL;
2070 const char *local, *remote;
2071 sd_bus *bus = ASSERT_PTR(userdata);
2072 int r;
2073
2074 remote = argv[1];
2075 if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
2076 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2077 "URL '%s' is not valid.", remote);
2078
2079 if (argc >= 3)
2080 local = argv[2];
2081 else {
2082 r = import_url_last_component(remote, &l);
2083 if (r < 0)
2084 return log_error_errno(r, "Failed to get final component of URL: %m");
2085
2086 local = l;
2087 }
2088
2089 local = empty_or_dash_to_null(local);
2090
2091 if (local) {
2092 r = tar_strip_suffixes(local, &ll);
2093 if (r < 0)
2094 return log_oom();
2095
2096 local = ll;
2097
2098 if (!hostname_is_valid(local, 0))
2099 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2100 "Local name %s is not a suitable machine name.",
2101 local);
2102 }
2103
2104 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullTar");
2105 if (r < 0)
2106 return bus_log_create_error(r);
2107
2108 r = sd_bus_message_append(
2109 m,
2110 "sssb",
2111 remote,
2112 local,
2113 import_verify_to_string(arg_verify),
2114 arg_force);
2115 if (r < 0)
2116 return bus_log_create_error(r);
2117
2118 return transfer_image_common(bus, m);
2119 }
2120
2121 static int pull_raw(int argc, char *argv[], void *userdata) {
2122 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2123 _cleanup_free_ char *l = NULL, *ll = NULL;
2124 const char *local, *remote;
2125 sd_bus *bus = ASSERT_PTR(userdata);
2126 int r;
2127
2128 remote = argv[1];
2129 if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
2130 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2131 "URL '%s' is not valid.", remote);
2132
2133 if (argc >= 3)
2134 local = argv[2];
2135 else {
2136 r = import_url_last_component(remote, &l);
2137 if (r < 0)
2138 return log_error_errno(r, "Failed to get final component of URL: %m");
2139
2140 local = l;
2141 }
2142
2143 local = empty_or_dash_to_null(local);
2144
2145 if (local) {
2146 r = raw_strip_suffixes(local, &ll);
2147 if (r < 0)
2148 return log_oom();
2149
2150 local = ll;
2151
2152 if (!hostname_is_valid(local, 0))
2153 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2154 "Local name %s is not a suitable machine name.",
2155 local);
2156 }
2157
2158 r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullRaw");
2159 if (r < 0)
2160 return bus_log_create_error(r);
2161
2162 r = sd_bus_message_append(
2163 m,
2164 "sssb",
2165 remote,
2166 local,
2167 import_verify_to_string(arg_verify),
2168 arg_force);
2169 if (r < 0)
2170 return bus_log_create_error(r);
2171
2172 return transfer_image_common(bus, m);
2173 }
2174
2175 typedef struct TransferInfo {
2176 uint32_t id;
2177 const char *type;
2178 const char *remote;
2179 const char *local;
2180 double progress;
2181 } TransferInfo;
2182
2183 static int compare_transfer_info(const TransferInfo *a, const TransferInfo *b) {
2184 return strcmp(a->local, b->local);
2185 }
2186
2187 static int list_transfers(int argc, char *argv[], void *userdata) {
2188 size_t max_type = STRLEN("TYPE"), max_local = STRLEN("LOCAL"), max_remote = STRLEN("REMOTE");
2189 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2190 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2191 _cleanup_free_ TransferInfo *transfers = NULL;
2192 const char *type, *remote, *local;
2193 sd_bus *bus = userdata;
2194 uint32_t id, max_id = 0;
2195 size_t n_transfers = 0;
2196 double progress;
2197 int r;
2198
2199 pager_open(arg_pager_flags);
2200
2201 r = bus_call_method(bus, bus_import_mgr, "ListTransfers", &error, &reply, NULL);
2202 if (r < 0)
2203 return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, r));
2204
2205 r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
2206 if (r < 0)
2207 return bus_log_parse_error(r);
2208
2209 while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, NULL)) > 0) {
2210 size_t l;
2211
2212 if (!GREEDY_REALLOC(transfers, n_transfers + 1))
2213 return log_oom();
2214
2215 transfers[n_transfers].id = id;
2216 transfers[n_transfers].type = type;
2217 transfers[n_transfers].remote = remote;
2218 transfers[n_transfers].local = local;
2219 transfers[n_transfers].progress = progress;
2220
2221 l = strlen(type);
2222 if (l > max_type)
2223 max_type = l;
2224
2225 l = strlen(remote);
2226 if (l > max_remote)
2227 max_remote = l;
2228
2229 l = strlen(local);
2230 if (l > max_local)
2231 max_local = l;
2232
2233 if (id > max_id)
2234 max_id = id;
2235
2236 n_transfers++;
2237 }
2238 if (r < 0)
2239 return bus_log_parse_error(r);
2240
2241 r = sd_bus_message_exit_container(reply);
2242 if (r < 0)
2243 return bus_log_parse_error(r);
2244
2245 typesafe_qsort(transfers, n_transfers, compare_transfer_info);
2246
2247 if (arg_legend && n_transfers > 0)
2248 printf("%-*s %-*s %-*s %-*s %-*s\n",
2249 (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID",
2250 (int) 7, "PERCENT",
2251 (int) max_type, "TYPE",
2252 (int) max_local, "LOCAL",
2253 (int) max_remote, "REMOTE");
2254
2255 for (size_t j = 0; j < n_transfers; j++)
2256
2257 if (transfers[j].progress < 0)
2258 printf("%*" PRIu32 " %*s %-*s %-*s %-*s\n",
2259 (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
2260 (int) 7, "n/a",
2261 (int) max_type, transfers[j].type,
2262 (int) max_local, transfers[j].local,
2263 (int) max_remote, transfers[j].remote);
2264 else
2265 printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
2266 (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
2267 (int) 6, (unsigned) (transfers[j].progress * 100),
2268 (int) max_type, transfers[j].type,
2269 (int) max_local, transfers[j].local,
2270 (int) max_remote, transfers[j].remote);
2271
2272 if (arg_legend) {
2273 if (n_transfers > 0)
2274 printf("\n%zu transfers listed.\n", n_transfers);
2275 else
2276 printf("No transfers.\n");
2277 }
2278
2279 return 0;
2280 }
2281
2282 static int cancel_transfer(int argc, char *argv[], void *userdata) {
2283 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2284 sd_bus *bus = ASSERT_PTR(userdata);
2285 int r;
2286
2287 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
2288
2289 for (int i = 1; i < argc; i++) {
2290 uint32_t id;
2291
2292 r = safe_atou32(argv[i], &id);
2293 if (r < 0)
2294 return log_error_errno(r, "Failed to parse transfer id: %s", argv[i]);
2295
2296 r = bus_call_method(bus, bus_import_mgr, "CancelTransfer", &error, NULL, "u", id);
2297 if (r < 0)
2298 return log_error_errno(r, "Could not cancel transfer: %s", bus_error_message(&error, r));
2299 }
2300
2301 return 0;
2302 }
2303
2304 static int set_limit(int argc, char *argv[], void *userdata) {
2305 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2306 sd_bus *bus = userdata;
2307 uint64_t limit;
2308 int r;
2309
2310 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
2311
2312 if (STR_IN_SET(argv[argc-1], "-", "none", "infinity"))
2313 limit = UINT64_MAX;
2314 else {
2315 r = parse_size(argv[argc-1], 1024, &limit);
2316 if (r < 0)
2317 return log_error_errno(r, "Failed to parse size: %s", argv[argc-1]);
2318 }
2319
2320 if (argc > 2)
2321 /* With two arguments changes the quota limit of the
2322 * specified image */
2323 r = bus_call_method(bus, bus_machine_mgr, "SetImageLimit", &error, NULL, "st", argv[1], limit);
2324 else
2325 /* With one argument changes the pool quota limit */
2326 r = bus_call_method(bus, bus_machine_mgr, "SetPoolLimit", &error, NULL, "t", limit);
2327
2328 if (r < 0)
2329 return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r));
2330
2331 return 0;
2332 }
2333
2334 static int clean_images(int argc, char *argv[], void *userdata) {
2335 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
2336 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2337 uint64_t usage, total = 0;
2338 sd_bus *bus = userdata;
2339 const char *name;
2340 unsigned c = 0;
2341 int r;
2342
2343 polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
2344
2345 r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "CleanPool");
2346 if (r < 0)
2347 return bus_log_create_error(r);
2348
2349 r = sd_bus_message_append(m, "s", arg_all ? "all" : "hidden");
2350 if (r < 0)
2351 return bus_log_create_error(r);
2352
2353 /* This is a slow operation, hence permit a longer time for completion. */
2354 r = sd_bus_call(bus, m, USEC_INFINITY, &error, &reply);
2355 if (r < 0)
2356 return log_error_errno(r, "Could not clean pool: %s", bus_error_message(&error, r));
2357
2358 r = sd_bus_message_enter_container(reply, 'a', "(st)");
2359 if (r < 0)
2360 return bus_log_parse_error(r);
2361
2362 while ((r = sd_bus_message_read(reply, "(st)", &name, &usage)) > 0) {
2363 if (usage == UINT64_MAX) {
2364 log_info("Removed image '%s'", name);
2365 total = UINT64_MAX;
2366 } else {
2367 log_info("Removed image '%s'. Freed exclusive disk space: %s",
2368 name, FORMAT_BYTES(usage));
2369 if (total != UINT64_MAX)
2370 total += usage;
2371 }
2372 c++;
2373 }
2374
2375 r = sd_bus_message_exit_container(reply);
2376 if (r < 0)
2377 return bus_log_parse_error(r);
2378
2379 if (total == UINT64_MAX)
2380 log_info("Removed %u images in total.", c);
2381 else
2382 log_info("Removed %u images in total. Total freed exclusive disk space: %s.",
2383 c, FORMAT_BYTES(total));
2384
2385 return 0;
2386 }
2387
2388 static int help(int argc, char *argv[], void *userdata) {
2389 _cleanup_free_ char *link = NULL;
2390 int r;
2391
2392 pager_open(arg_pager_flags);
2393
2394 r = terminal_urlify_man("machinectl", "1", &link);
2395 if (r < 0)
2396 return log_oom();
2397
2398 printf("%s [OPTIONS...] COMMAND ...\n\n"
2399 "%sSend control commands to or query the virtual machine and container%s\n"
2400 "%sregistration manager.%s\n"
2401 "\nMachine Commands:\n"
2402 " list List running VMs and containers\n"
2403 " status NAME... Show VM/container details\n"
2404 " show [NAME...] Show properties of one or more VMs/containers\n"
2405 " start NAME... Start container as a service\n"
2406 " login [NAME] Get a login prompt in a container or on the\n"
2407 " local host\n"
2408 " shell [[USER@]NAME [COMMAND...]]\n"
2409 " Invoke a shell (or other command) in a container\n"
2410 " or on the local host\n"
2411 " enable NAME... Enable automatic container start at boot\n"
2412 " disable NAME... Disable automatic container start at boot\n"
2413 " poweroff NAME... Power off one or more containers\n"
2414 " reboot NAME... Reboot one or more containers\n"
2415 " terminate NAME... Terminate one or more VMs/containers\n"
2416 " kill NAME... Send signal to processes of a VM/container\n"
2417 " copy-to NAME PATH [PATH] Copy files from the host to a container\n"
2418 " copy-from NAME PATH [PATH] Copy files from a container to the host\n"
2419 " bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n"
2420 "Image Commands:\n"
2421 " list-images Show available container and VM images\n"
2422 " image-status [NAME...] Show image details\n"
2423 " show-image [NAME...] Show properties of image\n"
2424 " clone NAME NAME Clone an image\n"
2425 " rename NAME NAME Rename an image\n"
2426 " read-only NAME [BOOL] Mark or unmark image read-only\n"
2427 " remove NAME... Remove an image\n"
2428 " set-limit [NAME] BYTES Set image or pool size limit (disk quota)\n"
2429 " clean Remove hidden (or all) images\n\n"
2430 "Image Transfer Commands:\n"
2431 " pull-tar URL [NAME] Download a TAR container image\n"
2432 " pull-raw URL [NAME] Download a RAW container or VM image\n"
2433 " import-tar FILE [NAME] Import a local TAR container image\n"
2434 " import-raw FILE [NAME] Import a local RAW container or VM image\n"
2435 " import-fs DIRECTORY [NAME] Import a local directory container image\n"
2436 " export-tar NAME [FILE] Export a TAR container image locally\n"
2437 " export-raw NAME [FILE] Export a RAW container or VM image locally\n"
2438 " list-transfers Show list of downloads in progress\n"
2439 " cancel-transfer Cancel a download\n"
2440 "\nOptions:\n"
2441 " -h --help Show this help\n"
2442 " --version Show package version\n"
2443 " --no-pager Do not pipe output into a pager\n"
2444 " --no-legend Do not show the headers and footers\n"
2445 " --no-ask-password Do not ask for system passwords\n"
2446 " -H --host=[USER@]HOST Operate on remote host\n"
2447 " -M --machine=CONTAINER Operate on local container\n"
2448 " -p --property=NAME Show only properties by this name\n"
2449 " -q --quiet Suppress output\n"
2450 " -a --all Show all properties, including empty ones\n"
2451 " --value When showing properties, only print the value\n"
2452 " -l --full Do not ellipsize output\n"
2453 " --kill-whom=WHOM Whom to send signal to\n"
2454 " -s --signal=SIGNAL Which signal to send\n"
2455 " --uid=USER Specify user ID to invoke shell as\n"
2456 " -E --setenv=VAR[=VALUE] Add an environment variable for shell\n"
2457 " --read-only Create read-only bind mount\n"
2458 " --mkdir Create directory before bind mounting, if missing\n"
2459 " -n --lines=INTEGER Number of journal entries to show\n"
2460 " --max-addresses=INTEGER Number of internet addresses to show at most\n"
2461 " -o --output=STRING Change journal output mode (short, short-precise,\n"
2462 " short-iso, short-iso-precise, short-full,\n"
2463 " short-monotonic, short-unix, short-delta,\n"
2464 " json, json-pretty, json-sse, json-seq, cat,\n"
2465 " verbose, export, with-unit)\n"
2466 " --verify=MODE Verification mode for downloaded images (no,\n"
2467 " checksum, signature)\n"
2468 " --force Download image even if already exists\n"
2469 "\nSee the %s for details.\n",
2470 program_invocation_short_name,
2471 ansi_highlight(),
2472 ansi_normal(),
2473 ansi_highlight(),
2474 ansi_normal(),
2475 link);
2476
2477 return 0;
2478 }
2479
2480 static int parse_argv(int argc, char *argv[]) {
2481
2482 enum {
2483 ARG_VERSION = 0x100,
2484 ARG_NO_PAGER,
2485 ARG_NO_LEGEND,
2486 ARG_VALUE,
2487 ARG_KILL_WHOM,
2488 ARG_READ_ONLY,
2489 ARG_MKDIR,
2490 ARG_NO_ASK_PASSWORD,
2491 ARG_VERIFY,
2492 ARG_FORCE,
2493 ARG_FORMAT,
2494 ARG_UID,
2495 ARG_MAX_ADDRESSES,
2496 };
2497
2498 static const struct option options[] = {
2499 { "help", no_argument, NULL, 'h' },
2500 { "version", no_argument, NULL, ARG_VERSION },
2501 { "property", required_argument, NULL, 'p' },
2502 { "all", no_argument, NULL, 'a' },
2503 { "value", no_argument, NULL, ARG_VALUE },
2504 { "full", no_argument, NULL, 'l' },
2505 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
2506 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
2507 { "kill-whom", required_argument, NULL, ARG_KILL_WHOM },
2508 { "signal", required_argument, NULL, 's' },
2509 { "host", required_argument, NULL, 'H' },
2510 { "machine", required_argument, NULL, 'M' },
2511 { "read-only", no_argument, NULL, ARG_READ_ONLY },
2512 { "mkdir", no_argument, NULL, ARG_MKDIR },
2513 { "quiet", no_argument, NULL, 'q' },
2514 { "lines", required_argument, NULL, 'n' },
2515 { "output", required_argument, NULL, 'o' },
2516 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
2517 { "verify", required_argument, NULL, ARG_VERIFY },
2518 { "force", no_argument, NULL, ARG_FORCE },
2519 { "format", required_argument, NULL, ARG_FORMAT },
2520 { "uid", required_argument, NULL, ARG_UID },
2521 { "setenv", required_argument, NULL, 'E' },
2522 { "max-addresses", required_argument, NULL, ARG_MAX_ADDRESSES },
2523 {}
2524 };
2525
2526 bool reorder = false;
2527 int c, r, shell = -1;
2528
2529 assert(argc >= 0);
2530 assert(argv);
2531
2532 for (;;) {
2533 static const char option_string[] = "-hp:als:H:M:qn:o:E:";
2534
2535 c = getopt_long(argc, argv, option_string + reorder, options, NULL);
2536 if (c < 0)
2537 break;
2538
2539 switch (c) {
2540
2541 case 1: /* getopt_long() returns 1 if "-" was the first character of the option string, and a
2542 * non-option argument was discovered. */
2543
2544 assert(!reorder);
2545
2546 /* We generally are fine with the fact that getopt_long() reorders the command line, and looks
2547 * for switches after the main verb. However, for "shell" we really don't want that, since we
2548 * want that switches specified after the machine name are passed to the program to execute,
2549 * and not processed by us. To make this possible, we'll first invoke getopt_long() with
2550 * reordering disabled (i.e. with the "-" prefix in the option string), looking for the first
2551 * non-option parameter. If it's the verb "shell" we remember its position and continue
2552 * processing options. In this case, as soon as we hit the next non-option argument we found
2553 * the machine name, and stop further processing. If the first non-option argument is any other
2554 * verb than "shell" we switch to normal reordering mode and continue processing arguments
2555 * normally. */
2556
2557 if (shell >= 0) {
2558 /* If we already found the "shell" verb on the command line, and now found the next
2559 * non-option argument, then this is the machine name and we should stop processing
2560 * further arguments. */
2561 optind --; /* don't process this argument, go one step back */
2562 goto done;
2563 }
2564 if (streq(optarg, "shell"))
2565 /* Remember the position of the "shell" verb, and continue processing normally. */
2566 shell = optind - 1;
2567 else {
2568 int saved_optind;
2569
2570 /* OK, this is some other verb. In this case, turn on reordering again, and continue
2571 * processing normally. */
2572 reorder = true;
2573
2574 /* We changed the option string. getopt_long() only looks at it again if we invoke it
2575 * at least once with a reset option index. Hence, let's reset the option index here,
2576 * then invoke getopt_long() again (ignoring what it has to say, after all we most
2577 * likely already processed it), and the bump the option index so that we read the
2578 * intended argument again. */
2579 saved_optind = optind;
2580 optind = 0;
2581 (void) getopt_long(argc, argv, option_string + reorder, options, NULL);
2582 optind = saved_optind - 1; /* go one step back, process this argument again */
2583 }
2584
2585 break;
2586
2587 case 'h':
2588 return help(0, NULL, NULL);
2589
2590 case ARG_VERSION:
2591 return version();
2592
2593 case 'p':
2594 r = strv_extend(&arg_property, optarg);
2595 if (r < 0)
2596 return log_oom();
2597
2598 /* If the user asked for a particular
2599 * property, show it to them, even if it is
2600 * empty. */
2601 SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
2602 break;
2603
2604 case 'a':
2605 SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_SHOW_EMPTY, true);
2606 arg_all = true;
2607 break;
2608
2609 case ARG_VALUE:
2610 SET_FLAG(arg_print_flags, BUS_PRINT_PROPERTY_ONLY_VALUE, true);
2611 break;
2612
2613 case 'l':
2614 arg_full = true;
2615 break;
2616
2617 case 'n':
2618 if (safe_atou(optarg, &arg_lines) < 0)
2619 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2620 "Failed to parse lines '%s'", optarg);
2621 break;
2622
2623 case 'o':
2624 if (streq(optarg, "help")) {
2625 DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
2626 return 0;
2627 }
2628
2629 r = output_mode_from_string(optarg);
2630 if (r < 0)
2631 return log_error_errno(r, "Unknown output '%s'.", optarg);
2632 arg_output = r;
2633
2634 if (OUTPUT_MODE_IS_JSON(arg_output))
2635 arg_legend = false;
2636 break;
2637
2638 case ARG_NO_PAGER:
2639 arg_pager_flags |= PAGER_DISABLE;
2640 break;
2641
2642 case ARG_NO_LEGEND:
2643 arg_legend = false;
2644 break;
2645
2646 case ARG_KILL_WHOM:
2647 arg_kill_whom = optarg;
2648 break;
2649
2650 case 's':
2651 r = parse_signal_argument(optarg, &arg_signal);
2652 if (r <= 0)
2653 return r;
2654 break;
2655
2656 case ARG_NO_ASK_PASSWORD:
2657 arg_ask_password = false;
2658 break;
2659
2660 case 'H':
2661 arg_transport = BUS_TRANSPORT_REMOTE;
2662 arg_host = optarg;
2663 break;
2664
2665 case 'M':
2666 arg_transport = BUS_TRANSPORT_MACHINE;
2667 arg_host = optarg;
2668 break;
2669
2670 case ARG_READ_ONLY:
2671 arg_read_only = true;
2672 break;
2673
2674 case ARG_MKDIR:
2675 arg_mkdir = true;
2676 break;
2677
2678 case 'q':
2679 arg_quiet = true;
2680 break;
2681
2682 case ARG_VERIFY:
2683 if (streq(optarg, "help")) {
2684 DUMP_STRING_TABLE(import_verify, ImportVerify, _IMPORT_VERIFY_MAX);
2685 return 0;
2686 }
2687
2688 r = import_verify_from_string(optarg);
2689 if (r < 0)
2690 return log_error_errno(r, "Failed to parse --verify= setting: %s", optarg);
2691 arg_verify = r;
2692 break;
2693
2694 case ARG_FORCE:
2695 arg_force = true;
2696 break;
2697
2698 case ARG_FORMAT:
2699 if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2"))
2700 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2701 "Unknown format: %s", optarg);
2702
2703 arg_format = optarg;
2704 break;
2705
2706 case ARG_UID:
2707 arg_uid = optarg;
2708 break;
2709
2710 case 'E':
2711 r = strv_env_replace_strdup_passthrough(&arg_setenv, optarg);
2712 if (r < 0)
2713 return log_error_errno(r, "Cannot assign environment variable %s: %m", optarg);
2714 break;
2715
2716 case ARG_MAX_ADDRESSES:
2717 if (streq(optarg, "all"))
2718 arg_max_addresses = UINT_MAX;
2719 else if (safe_atou(optarg, &arg_max_addresses) < 0)
2720 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2721 "Invalid number of addresses: %s", optarg);
2722 break;
2723
2724 case '?':
2725 return -EINVAL;
2726
2727 default:
2728 assert_not_reached();
2729 }
2730 }
2731
2732 done:
2733 if (shell >= 0) {
2734 char *t;
2735
2736 /* We found the "shell" verb while processing the argument list. Since we turned off reordering of the
2737 * argument list initially let's readjust it now, and move the "shell" verb to the back. */
2738
2739 optind -= 1; /* place the option index where the "shell" verb will be placed */
2740
2741 t = argv[shell];
2742 for (int i = shell; i < optind; i++)
2743 argv[i] = argv[i+1];
2744 argv[optind] = t;
2745 }
2746
2747 return 1;
2748 }
2749
2750 static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
2751
2752 static const Verb verbs[] = {
2753 { "help", VERB_ANY, VERB_ANY, 0, help },
2754 { "list", VERB_ANY, 1, VERB_DEFAULT, list_machines },
2755 { "list-images", VERB_ANY, 1, 0, list_images },
2756 { "status", 2, VERB_ANY, 0, show_machine },
2757 { "image-status", VERB_ANY, VERB_ANY, 0, show_image },
2758 { "show", VERB_ANY, VERB_ANY, 0, show_machine },
2759 { "show-image", VERB_ANY, VERB_ANY, 0, show_image },
2760 { "terminate", 2, VERB_ANY, 0, terminate_machine },
2761 { "reboot", 2, VERB_ANY, 0, reboot_machine },
2762 { "poweroff", 2, VERB_ANY, 0, poweroff_machine },
2763 { "stop", 2, VERB_ANY, 0, poweroff_machine }, /* Convenience alias */
2764 { "kill", 2, VERB_ANY, 0, kill_machine },
2765 { "login", VERB_ANY, 2, 0, login_machine },
2766 { "shell", VERB_ANY, VERB_ANY, 0, shell_machine },
2767 { "bind", 3, 4, 0, bind_mount },
2768 { "copy-to", 3, 4, 0, copy_files },
2769 { "copy-from", 3, 4, 0, copy_files },
2770 { "remove", 2, VERB_ANY, 0, remove_image },
2771 { "rename", 3, 3, 0, rename_image },
2772 { "clone", 3, 3, 0, clone_image },
2773 { "read-only", 2, 3, 0, read_only_image },
2774 { "start", 2, VERB_ANY, 0, start_machine },
2775 { "enable", 2, VERB_ANY, 0, enable_machine },
2776 { "disable", 2, VERB_ANY, 0, enable_machine },
2777 { "import-tar", 2, 3, 0, import_tar },
2778 { "import-raw", 2, 3, 0, import_raw },
2779 { "import-fs", 2, 3, 0, import_fs },
2780 { "export-tar", 2, 3, 0, export_tar },
2781 { "export-raw", 2, 3, 0, export_raw },
2782 { "pull-tar", 2, 3, 0, pull_tar },
2783 { "pull-raw", 2, 3, 0, pull_raw },
2784 { "list-transfers", VERB_ANY, 1, 0, list_transfers },
2785 { "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer },
2786 { "set-limit", 2, 3, 0, set_limit },
2787 { "clean", VERB_ANY, 1, 0, clean_images },
2788 {}
2789 };
2790
2791 return dispatch_verb(argc, argv, verbs, bus);
2792 }
2793
2794 static int run(int argc, char *argv[]) {
2795 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
2796 int r;
2797
2798 setlocale(LC_ALL, "");
2799 log_setup();
2800
2801 /* The journal merging logic potentially needs a lot of fds. */
2802 (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
2803
2804 sigbus_install();
2805
2806 r = parse_argv(argc, argv);
2807 if (r <= 0)
2808 return r;
2809
2810 r = bus_connect_transport(arg_transport, arg_host, false, &bus);
2811 if (r < 0)
2812 return bus_log_connect_error(r, arg_transport);
2813
2814 (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
2815
2816 return machinectl_main(argc, argv, bus);
2817 }
2818
2819 DEFINE_MAIN_FUNCTION(run);