summaryrefslogtreecommitdiff
path: root/src/machine/machinectl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/machine/machinectl.c')
-rw-r--r--src/machine/machinectl.c415
1 files changed, 232 insertions, 183 deletions
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index d656681daf..44e6c76035 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -5,6 +5,7 @@
#include <fcntl.h>
#include <getopt.h>
#include <locale.h>
+#include <math.h>
#include <net/if.h>
#include <netinet/in.h>
#include <string.h>
@@ -22,6 +23,7 @@
#include "cgroup-show.h"
#include "cgroup-util.h"
#include "copy.h"
+#include "def.h"
#include "env-util.h"
#include "fd-util.h"
#include "format-table.h"
@@ -31,12 +33,15 @@
#include "log.h"
#include "logs-show.h"
#include "macro.h"
+#include "main-func.h"
#include "mkdir.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
+#include "pretty-print.h"
#include "process-util.h"
#include "ptyfwd.h"
+#include "rlimit-util.h"
#include "sigbus.h"
#include "signal-util.h"
#include "spawn-polkit-agent.h"
@@ -55,12 +60,12 @@ static char **arg_property = NULL;
static bool arg_all = false;
static bool arg_value = false;
static bool arg_full = false;
-static bool arg_no_pager = false;
+static PagerFlags arg_pager_flags = 0;
static bool arg_legend = true;
static const char *arg_kill_who = NULL;
static int arg_signal = SIGTERM;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static char *arg_host = NULL;
+static const char *arg_host = NULL;
static bool arg_read_only = false;
static bool arg_mkdir = false;
static bool arg_quiet = false;
@@ -74,6 +79,9 @@ static const char *arg_uid = NULL;
static char **arg_setenv = NULL;
static int arg_addrs = 1;
+STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
+
static OutputFlags get_output_flags(void) {
return
arg_all * OUTPUT_SHOW_ALL |
@@ -229,7 +237,7 @@ static int call_get_addresses(sd_bus *bus, const char *name, int ifi, const char
if (truncate) {
- if (!strextend(&addresses, special_glyph(ELLIPSIS), NULL))
+ if (!strextend(&addresses, special_glyph(SPECIAL_GLYPH_ELLIPSIS), NULL))
return -ENOMEM;
}
@@ -251,7 +259,10 @@ static int show_table(Table *table, const char *word) {
table_set_header(table, arg_legend);
- r = table_print(table, NULL);
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO);
+ else
+ r = table_print(table, NULL);
if (r < 0)
return log_error_errno(r, "Failed to show table: %m");
}
@@ -276,7 +287,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
assert(bus);
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(bus,
"org.freedesktop.machine1",
@@ -289,7 +300,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Could not get machines: %s", bus_error_message(&error, r));
- table = table_new("MACHINE", "CLASS", "SERVICE", "OS", "VERSION", "ADDRESSES");
+ table = table_new("machine", "class", "service", "os", "version", "addresses");
if (!table)
return log_oom();
@@ -324,7 +335,7 @@ static int list_machines(int argc, char *argv[], void *userdata) {
name,
0,
"",
- "",
+ " ",
arg_addrs,
&addresses);
@@ -356,7 +367,7 @@ static int list_images(int argc, char *argv[], void *userdata) {
assert(bus);
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(bus,
"org.freedesktop.machine1",
@@ -369,7 +380,7 @@ static int list_images(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Could not get images: %s", bus_error_message(&error, r));
- table = table_new("NAME", "TYPE", "RO", "USAGE", "CREATED", "MODIFIED");
+ table = table_new("name", "type", "ro", "usage", "created", "modified");
if (!table)
return log_oom();
@@ -467,20 +478,6 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
return 0;
}
-static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2, int n_addr) {
- _cleanup_free_ char *s = NULL;
- int r;
-
- r = call_get_addresses(bus, name, ifi, prefix, prefix2, n_addr, &s);
- if (r < 0)
- return r;
-
- if (r > 0)
- fputs(s, stdout);
-
- return r;
-}
-
static int print_os_release(sd_bus *bus, const char *method, const char *name, const char *prefix) {
_cleanup_free_ char *pretty = NULL;
int r;
@@ -540,7 +537,7 @@ typedef struct MachineStatusInfo {
pid_t leader;
struct dual_timestamp timestamp;
int *netif;
- unsigned n_netif;
+ size_t n_netif;
} MachineStatusInfo;
static void machine_status_info_clear(MachineStatusInfo *info) {
@@ -553,6 +550,7 @@ static void machine_status_info_clear(MachineStatusInfo *info) {
static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX];
char since2[FORMAT_TIMESTAMP_MAX];
+ _cleanup_free_ char *addresses = NULL;
const char *s1, *s2;
int ifi = -1;
@@ -600,7 +598,7 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
printf("\t Root: %s\n", i->root_directory);
if (i->n_netif > 0) {
- unsigned c;
+ size_t c;
fputs("\t Iface:", stdout);
@@ -622,11 +620,12 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
fputc('\n', stdout);
}
- if (print_addresses(bus, i->name, ifi,
- "\t Address: ",
- "\n\t ",
- ALL_IP_ADDRESSES) > 0)
+ if (call_get_addresses(bus, i->name, ifi,
+ "\t Address: ", "\n\t ", ALL_IP_ADDRESSES,
+ &addresses) > 0) {
+ fputs(addresses, stdout);
fputc('\n', stdout);
+ }
print_os_release(bus, "GetMachineOSRelease", i->name, "\t OS: ");
@@ -751,7 +750,7 @@ static int show_machine(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (properties && argc <= 1) {
@@ -773,10 +772,8 @@ static int show_machine(int argc, char *argv[], void *userdata) {
&error,
&reply,
"s", argv[i]);
- if (r < 0) {
- log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not get path to machine: %s", bus_error_message(&error, -r));
r = sd_bus_message_read(reply, "o", &path);
if (r < 0)
@@ -1091,7 +1088,7 @@ static int show_image(int argc, char *argv[], void *userdata) {
properties = !strstr(argv[0], "status");
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
if (argc <= 1) {
@@ -1118,10 +1115,8 @@ static int show_image(int argc, char *argv[], void *userdata) {
&error,
&reply,
"s", argv[i]);
- if (r < 0) {
- log_error("Could not get path to image: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not get path to image: %s", bus_error_message(&error, -r));
r = sd_bus_message_read(reply, "o", &path);
if (r < 0)
@@ -1158,10 +1153,8 @@ static int kill_machine(int argc, char *argv[], void *userdata) {
&error,
NULL,
"ssi", argv[i], arg_kill_who, arg_signal);
- if (r < 0) {
- log_error("Could not kill machine: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not kill machine: %s", bus_error_message(&error, -r));
}
return 0;
@@ -1200,10 +1193,8 @@ static int terminate_machine(int argc, char *argv[], void *userdata) {
&error,
NULL,
"s", argv[i]);
- if (r < 0) {
- log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not terminate machine: %s", bus_error_message(&error, -r));
}
return 0;
@@ -1285,10 +1276,8 @@ static int bind_mount(int argc, char *argv[], void *userdata) {
argv[3],
arg_read_only,
arg_mkdir);
- if (r < 0) {
- log_error("Failed to bind mount: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind mount: %s", bus_error_message(&error, -r));
return 0;
}
@@ -1335,8 +1324,8 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT
log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name);
}
- sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
- sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+ (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
r = pty_forward_new(event, master, flags, forward);
if (r < 0)
@@ -1459,10 +1448,8 @@ static int login_machine(int argc, char *argv[], void *userdata) {
&error,
&reply,
"s", machine);
- if (r < 0) {
- log_error("Failed to get login PTY: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get login PTY: %s", bus_error_message(&error, -r));
r = sd_bus_message_read(reply, "hs", &master, NULL);
if (r < 0)
@@ -1550,10 +1537,8 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to get shell PTY: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get shell PTY: %s", bus_error_message(&error, -r));
r = sd_bus_message_read(reply, "hs", &master, NULL);
if (r < 0)
@@ -1615,10 +1600,8 @@ static int rename_image(int argc, char *argv[], void *userdata) {
&error,
NULL,
"ss", argv[1], argv[2]);
- if (r < 0) {
- log_error("Could not rename image: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not rename image: %s", bus_error_message(&error, -r));
return 0;
}
@@ -1681,10 +1664,8 @@ static int read_only_image(int argc, char *argv[], void *userdata) {
&error,
NULL,
"sb", argv[1], b);
- if (r < 0) {
- log_error("Could not mark image read-only: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, -r));
return 0;
}
@@ -1721,10 +1702,9 @@ static int make_service_name(const char *name, char **ret) {
assert(name);
assert(ret);
- if (!machine_name_is_valid(name)) {
- log_error("Invalid machine name %s.", name);
- return -EINVAL;
- }
+ if (!machine_name_is_valid(name))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid machine name %s.", name);
r = unit_name_build("systemd-nspawn", name, ".service", ret);
if (r < 0)
@@ -1773,10 +1753,8 @@ static int start_machine(int argc, char *argv[], void *userdata) {
&error,
&reply,
"ss", unit, "fail");
- if (r < 0) {
- log_error("Failed to start unit: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to start unit: %s", bus_error_message(&error, -r));
r = sd_bus_message_read(reply, "o", &object);
if (r < 0)
@@ -1855,10 +1833,8 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to enable or disable unit: %s", bus_error_message(&error, -r));
if (streq(argv[0], "enable")) {
r = sd_bus_message_read(reply, "b", NULL);
@@ -1993,12 +1969,10 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
return log_error_errno(r, "Failed to request match: %m");
r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to transfer image: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to transfer image: %s", bus_error_message(&error, -r));
- r = sd_bus_message_read(reply, "uo", &id, NULL);
+ r = sd_bus_message_read(reply, "uo", &id, &path);
if (r < 0)
return bus_log_parse_error(r);
@@ -2007,8 +1981,8 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
if (!arg_quiet)
log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id);
- sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
- sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
+ (void) sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
+ (void) sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
r = sd_event_loop(event);
if (r < 0)
@@ -2017,28 +1991,38 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
return -r;
}
+static const char *nullify_dash(const char *p) {
+ if (isempty(p))
+ return NULL;
+
+ if (streq(p, "-"))
+ return NULL;
+
+ return p;
+}
+
static int import_tar(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_free_ char *ll = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *ll = NULL, *fn = NULL;
const char *local = NULL, *path = NULL;
+ _cleanup_close_ int fd = -1;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2)
- path = argv[1];
- if (isempty(path) || streq(path, "-"))
- path = NULL;
+ path = nullify_dash(argv[1]);
if (argc >= 3)
- local = argv[2];
- else if (path)
- local = basename(path);
- if (isempty(local) || streq(local, "-"))
- local = NULL;
+ local = nullify_dash(argv[2]);
+ else if (path) {
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Cannot extract container name from filename: %m");
+ local = fn;
+ }
if (!local) {
log_error("Need either path or local name.");
return -EINVAL;
@@ -2086,26 +2070,26 @@ static int import_tar(int argc, char *argv[], void *userdata) {
static int import_raw(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_free_ char *ll = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *ll = NULL, *fn = NULL;
const char *local = NULL, *path = NULL;
+ _cleanup_close_ int fd = -1;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2)
- path = argv[1];
- if (isempty(path) || streq(path, "-"))
- path = NULL;
+ path = nullify_dash(argv[1]);
if (argc >= 3)
- local = argv[2];
- else if (path)
- local = basename(path);
- if (isempty(local) || streq(local, "-"))
- local = NULL;
+ local = nullify_dash(argv[2]);
+ else if (path) {
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Cannot extract container name from filename: %m");
+ local = fn;
+ }
if (!local) {
log_error("Need either path or local name.");
return -EINVAL;
@@ -2151,6 +2135,67 @@ static int import_raw(int argc, char *argv[], void *userdata) {
return transfer_image_common(bus, m);
}
+static int import_fs(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ const char *local = NULL, *path = NULL;
+ _cleanup_free_ char *fn = NULL;
+ _cleanup_close_ int fd = -1;
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ if (argc >= 2)
+ path = nullify_dash(argv[1]);
+
+ if (argc >= 3)
+ local = nullify_dash(argv[2]);
+ else if (path) {
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Cannot extract container name from filename: %m");
+
+ local = fn;
+ }
+ if (!local) {
+ log_error("Need either path or local name.");
+ return -EINVAL;
+ }
+
+ if (!machine_name_is_valid(local)) {
+ log_error("Local name %s is not a suitable machine name.", local);
+ return -EINVAL;
+ }
+
+ if (path) {
+ fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open directory '%s': %m", path);
+ }
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.import1",
+ "/org/freedesktop/import1",
+ "org.freedesktop.import1.Manager",
+ "ImportFileSystem");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsbb",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ arg_force,
+ arg_read_only);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return transfer_image_common(bus, m);
+}
+
static void determine_compression_from_filename(const char *p) {
if (arg_format)
return;
@@ -2402,10 +2447,8 @@ typedef struct TransferInfo {
double progress;
} TransferInfo;
-static int compare_transfer_info(const void *a, const void *b) {
- const TransferInfo *x = a, *y = b;
-
- return strcmp(x->local, y->local);
+static int compare_transfer_info(const TransferInfo *a, const TransferInfo *b) {
+ return strcmp(a->local, b->local);
}
static int list_transfers(int argc, char *argv[], void *userdata) {
@@ -2420,7 +2463,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
double progress;
int r;
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
r = sd_bus_call_method(bus,
"org.freedesktop.import1",
@@ -2430,10 +2473,8 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
&error,
&reply,
NULL);
- if (r < 0) {
- log_error("Could not get transfers: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, -r));
r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
if (r < 0)
@@ -2475,7 +2516,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info);
+ typesafe_qsort(transfers, n_transfers, compare_transfer_info);
if (arg_legend && n_transfers > 0)
printf("%-*s %-*s %-*s %-*s %-*s\n",
@@ -2486,12 +2527,21 @@ static int list_transfers(int argc, char *argv[], void *userdata) {
(int) max_remote, "REMOTE");
for (j = 0; j < n_transfers; j++)
- printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
- (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
- (int) 6, (unsigned) (transfers[j].progress * 100),
- (int) max_type, transfers[j].type,
- (int) max_local, transfers[j].local,
- (int) max_remote, transfers[j].remote);
+
+ if (transfers[j].progress < 0)
+ printf("%*" PRIu32 " %*s %-*s %-*s %-*s\n",
+ (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
+ (int) 7, "n/a",
+ (int) max_type, transfers[j].type,
+ (int) max_local, transfers[j].local,
+ (int) max_remote, transfers[j].remote);
+ else
+ printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
+ (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
+ (int) 6, (unsigned) (transfers[j].progress * 100),
+ (int) max_type, transfers[j].type,
+ (int) max_local, transfers[j].local,
+ (int) max_remote, transfers[j].remote);
if (arg_legend) {
if (n_transfers > 0)
@@ -2528,10 +2578,8 @@ static int cancel_transfer(int argc, char *argv[], void *userdata) {
&error,
NULL,
"u", id);
- if (r < 0) {
- log_error("Could not cancel transfer: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not cancel transfer: %s", bus_error_message(&error, -r));
}
return 0;
@@ -2637,7 +2685,14 @@ static int clean_images(int argc, char *argv[], void *userdata) {
}
static int help(int argc, char *argv[], void *userdata) {
- (void) pager_open(arg_no_pager, false);
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ (void) pager_open(arg_pager_flags);
+
+ r = terminal_urlify_man("machinectl", "1", &link);
+ if (r < 0)
+ return log_oom();
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the virtual machine and container\n"
@@ -2665,7 +2720,8 @@ static int help(int argc, char *argv[], void *userdata) {
" -o --output=STRING Change journal output mode (short, short-precise,\n"
" short-iso, short-iso-precise, short-full,\n"
" short-monotonic, short-unix, verbose, export,\n"
- " json, json-pretty, json-sse, cat)\n"
+ " json, json-pretty, json-sse, json-seq, cat,\n"
+ " with-unit)\n"
" --verify=MODE Verification mode for downloaded images (no,\n"
" checksum, signature)\n"
" --force Download image even if already exists\n\n"
@@ -2703,11 +2759,15 @@ static int help(int argc, char *argv[], void *userdata) {
" pull-raw URL [NAME] Download a RAW container or VM image\n"
" import-tar FILE [NAME] Import a local TAR container image\n"
" import-raw FILE [NAME] Import a local RAW container or VM image\n"
+ " import-fs DIRECTORY [NAME] Import a local directory container image\n"
" export-tar NAME [FILE] Export a TAR container image locally\n"
" export-raw NAME [FILE] Export a RAW container or VM image locally\n"
" list-transfers Show list of downloads in progress\n"
" cancel-transfer Cancel a download\n"
- , program_invocation_short_name);
+ "\nSee the %s for details.\n"
+ , program_invocation_short_name
+ , link
+ );
return 0;
}
@@ -2849,10 +2909,9 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'n':
- if (safe_atou(optarg, &arg_lines) < 0) {
- log_error("Failed to parse lines '%s'", optarg);
- return -EINVAL;
- }
+ if (safe_atou(optarg, &arg_lines) < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse lines '%s'", optarg);
break;
case 'o':
@@ -2862,14 +2921,16 @@ static int parse_argv(int argc, char *argv[]) {
}
arg_output = output_mode_from_string(optarg);
- if (arg_output < 0) {
- log_error("Unknown output '%s'.", optarg);
- return -EINVAL;
- }
+ if (arg_output < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unknown output '%s'.", optarg);
+
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ arg_legend = false;
break;
case ARG_NO_PAGER:
- arg_no_pager = true;
+ arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_NO_LEGEND:
@@ -2887,10 +2948,9 @@ static int parse_argv(int argc, char *argv[]) {
}
arg_signal = signal_from_string(optarg);
- if (arg_signal < 0) {
- log_error("Failed to parse signal string %s.", optarg);
- return -EINVAL;
- }
+ if (arg_signal < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse signal string %s.", optarg);
break;
case ARG_NO_ASK_PASSWORD:
@@ -2926,10 +2986,9 @@ static int parse_argv(int argc, char *argv[]) {
}
arg_verify = import_verify_from_string(optarg);
- if (arg_verify < 0) {
- log_error("Failed to parse --verify= setting: %s", optarg);
- return -EINVAL;
- }
+ if (arg_verify < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to parse --verify= setting: %s", optarg);
break;
case ARG_FORCE:
@@ -2937,10 +2996,9 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_FORMAT:
- if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) {
- log_error("Unknown format: %s", optarg);
- return -EINVAL;
- }
+ if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Unknown format: %s", optarg);
arg_format = optarg;
break;
@@ -2950,10 +3008,9 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'E':
- if (!env_assignment_is_valid(optarg)) {
- log_error("Environment assignment invalid: %s", optarg);
- return -EINVAL;
- }
+ if (!env_assignment_is_valid(optarg))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Environment assignment invalid: %s", optarg);
r = strv_extend(&arg_setenv, optarg);
if (r < 0)
@@ -2963,13 +3020,12 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_NUMBER_IPS:
if (streq(optarg, "all"))
arg_addrs = ALL_IP_ADDRESSES;
- else if (safe_atoi(optarg, &arg_addrs) < 0) {
- log_error("Invalid number of IPs");
- return -EINVAL;
- } else if (arg_addrs < 0) {
- log_error("Number of IPs cannot be negative");
- return -EINVAL;
- }
+ else if (safe_atoi(optarg, &arg_addrs) < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid number of IPs");
+ else if (arg_addrs < 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Number of IPs cannot be negative");
break;
case '?':
@@ -3028,6 +3084,7 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
{ "disable", 2, VERB_ANY, 0, enable_machine },
{ "import-tar", 2, 3, 0, import_tar },
{ "import-raw", 2, 3, 0, import_raw },
+ { "import-fs", 2, 3, 0, import_fs },
{ "export-tar", 2, 3, 0, export_tar },
{ "export-raw", 2, 3, 0, export_raw },
{ "pull-tar", 2, 3, 0, pull_tar },
@@ -3042,38 +3099,30 @@ static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
return dispatch_verb(argc, argv, verbs, bus);
}
-int main(int argc, char*argv[]) {
- sd_bus *bus = NULL;
+static int run(int argc, char *argv[]) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
+
+ /* The journal merging logic potentially needs a lot of fds. */
+ (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
+
sigbus_install();
r = parse_argv(argc, argv);
if (r <= 0)
- goto finish;
+ return r;
r = bus_connect_transport(arg_transport, arg_host, false, &bus);
- if (r < 0) {
- log_error_errno(r, "Failed to create bus connection: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to create bus connection: %m");
(void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
- r = machinectl_main(argc, argv, bus);
-
-finish:
- /* make sure we terminate the bus connection first, and then close the
- * pager, see issue #3543 for the details. */
- sd_bus_flush_close_unref(bus);
- pager_close();
- polkit_agent_close();
-
- strv_free(arg_property);
- strv_free(arg_setenv);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return machinectl_main(argc, argv, bus);
}
+
+DEFINE_MAIN_FUNCTION(run);