X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fmachine%2Fmachinectl.c;h=728cd42629fe41c7395d02bf5ad4035fd6e86e87;hb=56b921c3d863f0e098f60f934e6c5880575c68ab;hp=11b2c004b86fdf51584b4b7f9bfa933fd00f1940;hpb=3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3;p=elogind.git diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 11b2c004b..728cd4262 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -71,7 +71,7 @@ static bool arg_ask_password = true; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_force = false; -static const char* arg_verify = NULL; +static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; static const char* arg_dkr_index_url = NULL; static void pager_open_if_enabled(void) { @@ -1355,7 +1355,6 @@ static int login_machine(int argc, char *argv[], void *userdata) { int master = -1, r, ret = 0; sd_bus *bus = userdata; const char *pty, *match; - sigset_t mask; char last_char = 0; bool machine_died; @@ -1417,9 +1416,7 @@ static int login_machine(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_parse_error(r); - assert_se(sigemptyset(&mask) == 0); - sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1); - assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); + sigprocmask_many(SIG_BLOCK, SIGWINCH, SIGTERM, SIGINT, -1); log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", argv[1]); @@ -1736,19 +1733,14 @@ static int enable_machine(int argc, char *argv[], void *userdata) { return 0; } -typedef struct PullContext { - const char *path; - int result; -} PullContext; - static int match_log_message(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { - PullContext *c = userdata; - const char *line; + const char **our_path = userdata, *line; unsigned priority; int r; assert(bus); assert(m); + assert(our_path); r = sd_bus_message_read(m, "us", &priority, &line); if (r < 0) { @@ -1756,7 +1748,7 @@ static int match_log_message(sd_bus *bus, sd_bus_message *m, void *userdata, sd_ return 0; } - if (!streq_ptr(c->path, sd_bus_message_get_path(m))) + if (!streq_ptr(*our_path, sd_bus_message_get_path(m))) return 0; if (arg_quiet && LOG_PRI(priority) >= LOG_INFO) @@ -1767,14 +1759,13 @@ static int match_log_message(sd_bus *bus, sd_bus_message *m, void *userdata, sd_ } static int match_transfer_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { - PullContext *c = userdata; - const char *path, *result; + const char **our_path = userdata, *path, *result; uint32_t id; int r; assert(bus); assert(m); - assert(c); + assert(our_path); r = sd_bus_message_read(m, "uos", &id, &path, &result); if (r < 0) { @@ -1782,10 +1773,21 @@ static int match_transfer_removed(sd_bus *bus, sd_bus_message *m, void *userdata return 0; } - if (!streq_ptr(c->path, path)) + if (!streq_ptr(*our_path, path)) return 0; - c->result = streq_ptr(result, "done"); + sd_event_exit(sd_bus_get_event(bus), !streq_ptr(result, "done")); + return 0; +} + +static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + assert(s); + assert(si); + + if (!arg_quiet) + log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to arbort transfer.", PTR_TO_UINT32(userdata)); + + sd_event_exit(sd_event_source_get_event(s), EINTR); return 0; } @@ -1793,9 +1795,8 @@ static int pull_image_common(sd_bus *bus, sd_bus_message *m) { _cleanup_bus_slot_unref_ sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - PullContext c = { - .result = -1, - }; + _cleanup_event_unref_ sd_event* event = NULL; + const char *path = NULL; uint32_t id; int r; @@ -1804,6 +1805,14 @@ static int pull_image_common(sd_bus *bus, sd_bus_message *m) { polkit_agent_open_if_enabled(); + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get event loop: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); if (r < 0) return bus_log_create_error(r); @@ -1816,7 +1825,7 @@ static int pull_image_common(sd_bus *bus, sd_bus_message *m) { "interface='org.freedesktop.import1.Manager'," "member='TransferRemoved'," "path='/org/freedesktop/import1'", - match_transfer_removed, &c); + match_transfer_removed, &path); if (r < 0) return log_error_errno(r, "Failed to install match: %m"); @@ -1827,7 +1836,7 @@ static int pull_image_common(sd_bus *bus, sd_bus_message *m) { "sender='org.freedesktop.import1'," "interface='org.freedesktop.import1.Transfer'," "member='LogMessage'", - match_log_message, &c); + match_log_message, &path); if (r < 0) return log_error_errno(r, "Failed to install match: %m"); @@ -1837,25 +1846,23 @@ static int pull_image_common(sd_bus *bus, sd_bus_message *m) { return r; } - r = sd_bus_message_read(reply, "uo", &id, &c.path); + r = sd_bus_message_read(reply, "uo", &id, &path); if (r < 0) return bus_log_parse_error(r); - for (;;) { - r = sd_bus_process(bus, NULL); - if (r < 0) - return r; + sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1); - /* The match sets this to NULL when we are done */ - if (c.result >= 0) - break; + if (!arg_quiet) + log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id); - r = sd_bus_wait(bus, (uint64_t) -1); - if (r < 0) - return r; - } + 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)); - return c.result ? 0 : -EINVAL; + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return -r; } static int pull_tar(int argc, char *argv[], void *userdata) { @@ -1914,7 +1921,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) { "sssb", remote, local, - arg_verify, + import_verify_to_string(arg_verify), arg_force); if (r < 0) return bus_log_create_error(r); @@ -1978,7 +1985,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) { "sssb", remote, local, - arg_verify, + import_verify_to_string(arg_verify), arg_force); if (r < 0) return bus_log_create_error(r); @@ -1993,7 +2000,7 @@ static int pull_dkr(int argc, char *argv[], void *userdata) { sd_bus *bus = userdata; int r; - if (!streq_ptr(arg_dkr_index_url, "no")) { + if (arg_verify != IMPORT_VERIFY_NO) { log_error("Imports from DKR do not support image verification, please pass --verify=no."); return -EINVAL; } @@ -2051,7 +2058,7 @@ static int pull_dkr(int argc, char *argv[], void *userdata) { remote, tag, local, - arg_verify, + import_verify_to_string(arg_verify), arg_force); if (r < 0) return bus_log_create_error(r); @@ -2064,6 +2071,7 @@ typedef struct TransferInfo { const char *type; const char *remote; const char *local; + double progress; } TransferInfo; static int compare_transfer_info(const void *a, const void *b) { @@ -2081,6 +2089,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) { const char *type, *remote, *local, *object; sd_bus *bus = userdata; uint32_t id, max_id = 0; + double progress; int r; pager_open_if_enabled(); @@ -2099,11 +2108,11 @@ static int list_transfers(int argc, char *argv[], void *userdata) { return r; } - r = sd_bus_message_enter_container(reply, 'a', "(ussso)"); + r = sd_bus_message_enter_container(reply, 'a', "(usssdo)"); if (r < 0) return bus_log_parse_error(r); - while ((r = sd_bus_message_read(reply, "(ussso)", &id, &type, &remote, &local, &object)) > 0) { + while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, &object)) > 0) { size_t l; if (!GREEDY_REALLOC(transfers, n_allocated, n_transfers + 1)) @@ -2113,6 +2122,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) { transfers[n_transfers].type = type; transfers[n_transfers].remote = remote; transfers[n_transfers].local = local; + transfers[n_transfers].progress = progress; l = strlen(type); if (l > max_type) @@ -2141,15 +2151,17 @@ static int list_transfers(int argc, char *argv[], void *userdata) { qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info); if (arg_legend) - printf("%-*s %-*s %-*s %-*s\n", + printf("%-*s %-*s %-*s %-*s %-*s\n", (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID", + (int) 7, "PERCENT", (int) max_type, "TYPE", (int) max_local, "LOCAL", (int) max_remote, "REMOTE"); for (j = 0; j < n_transfers; j++) - printf("%*" PRIu32 " %-*s %-*s %-*s\n", + 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); @@ -2218,8 +2230,8 @@ static int help(int argc, char *argv[], void *userdata) { " -o --output=STRING Change journal output mode (short,\n" " short-monotonic, verbose, export, json,\n" " json-pretty, json-sse, cat)\n" - " --verify=MODE Verification mode for downloaded images (no, sum,\n" - " signature)\n" + " --verify=MODE Verification mode for downloaded images (no,\n" + " checksum, signature)\n" " --force Download image even if already exists\n" " --dkr-index-url=URL Specify the index URL to use for DKR image\n" " downloads\n\n" @@ -2239,18 +2251,18 @@ static int help(int argc, char *argv[], void *userdata) { " copy-from NAME PATH [PATH] Copy files from a container to the host\n" " bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n" "Image Commands:\n" - " list-images Show available images\n" + " list-images Show available container and VM images\n" " image-status NAME... Show image details\n" " show-image NAME... Show properties of image\n" " clone NAME NAME Clone an image\n" " rename NAME NAME Rename an image\n" " read-only NAME [BOOL] Mark or unmark image read-only\n" " remove NAME... Remove an image\n\n" - "Transfer Commands:\n" - " pull-tar URL [NAME] Download a TAR image\n" - " pull-raw URL [NAME] Download a RAW image\n" - " pull-dkr REMOTE [NAME] Download a DKR image\n" - " list-transfers Show list of current downloads\n" + "Image Transfer Commands:\n" + " pull-tar URL [NAME] Download a TAR container image\n" + " pull-raw URL [NAME] Download a RAW container or VM image\n" + " pull-dkr REMOTE [NAME] Download a DKR container image\n" + " list-transfers Show list of downloads in progress\n" " cancel-transfer Cancel a download\n" , program_invocation_short_name); @@ -2394,7 +2406,11 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_VERIFY: - arg_verify = optarg; + arg_verify = import_verify_from_string(optarg); + if (arg_verify < 0) { + log_error("Failed to parse --verify= setting: %s", optarg); + return -EINVAL; + } break; case ARG_FORCE: