diff options
Diffstat (limited to 'src/machine/machinectl.c')
-rw-r--r-- | src/machine/machinectl.c | 415 |
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); |