#include "bus-error.h"
#include "bus-locator.h"
#include "bus-util.h"
+#include "discover-image.h"
#include "fd-util.h"
#include "format-table.h"
#include "hostname-util.h"
+#include "import-common.h"
#include "import-util.h"
#include "locale-util.h"
#include "log.h"
#include "macro.h"
#include "main-func.h"
+#include "os-util.h"
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
static bool arg_legend = true;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static const char *arg_host = NULL;
-static bool arg_read_only = false;
+static ImportFlags arg_import_flags = 0;
static bool arg_quiet = false;
static bool arg_ask_password = true;
-static bool arg_force = false;
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
static const char* arg_format = NULL;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
+static ImageClass arg_image_class = _IMAGE_CLASS_INVALID;
+
+static int settle_image_class(void) {
+
+ if (arg_image_class < 0) {
+ _cleanup_free_ char *j = NULL;
+
+ for (ImageClass class = 0; class < _IMAGE_CLASS_MAX; class++)
+ if (strextendf_with_separator(&j, ", ", "%s (downloads to %s/)",
+ image_class_to_string(class),
+ image_root_to_string(class)) < 0)
+ return log_oom();
+
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "No image class specified, retry with --class= set to one of: %s.", j);
+ }
+
+ return 0;
+}
static int match_log_message(sd_bus_message *m, void *userdata, sd_bus_error *error) {
const char **our_path = userdata, *line;
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
if (argc >= 2)
path = empty_or_dash_to_null(argv[1]);
return log_error_errno(errno, "Failed to open %s: %m", path);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportTar");
- 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 (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportTar");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsbb",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ FLAGS_SET(arg_import_flags, IMPORT_FORCE),
+ FLAGS_SET(arg_import_flags, IMPORT_READ_ONLY));
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportTarEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsst",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ image_class_to_string(arg_image_class),
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ }
if (r < 0)
return bus_log_create_error(r);
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
if (argc >= 2)
path = empty_or_dash_to_null(argv[1]);
return log_error_errno(errno, "Failed to open %s: %m", path);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportRaw");
- 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 (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportRaw");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsbb",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ FLAGS_SET(arg_import_flags, IMPORT_FORCE),
+ FLAGS_SET(arg_import_flags, IMPORT_READ_ONLY));
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportRawEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsst",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ image_class_to_string(arg_image_class),
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ }
if (r < 0)
return bus_log_create_error(r);
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
if (argc >= 2)
path = empty_or_dash_to_null(argv[1]);
return log_error_errno(errno, "Failed to open directory '%s': %m", path);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportFileSystem");
+ if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportFileSystem");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsbb",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ FLAGS_SET(arg_import_flags, IMPORT_FORCE),
+ FLAGS_SET(arg_import_flags, IMPORT_READ_ONLY));
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ImportFileSystemEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsst",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ image_class_to_string(arg_image_class),
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ }
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);
}
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
local = argv[1];
if (!hostname_is_valid(local, 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return log_error_errno(errno, "Failed to open %s: %m", path);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportTar");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(
- m,
- "shs",
- local,
- fd >= 0 ? fd : STDOUT_FILENO,
- arg_format);
+ if (arg_image_class == IMAGE_MACHINE && arg_import_flags == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportTar");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "shs",
+ local,
+ fd >= 0 ? fd : STDOUT_FILENO,
+ arg_format);
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportTarEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sshst",
+ local,
+ image_class_to_string(arg_image_class),
+ fd >= 0 ? fd : STDOUT_FILENO,
+ arg_format,
+ /* flags= */ 0);
+ }
if (r < 0)
return bus_log_create_error(r);
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
local = argv[1];
if (!hostname_is_valid(local, 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return log_error_errno(errno, "Failed to open %s: %m", path);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportRaw");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(
- m,
- "shs",
- local,
- fd >= 0 ? fd : STDOUT_FILENO,
- arg_format);
+ if (arg_image_class == IMAGE_MACHINE && arg_import_flags == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportRaw");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "shs",
+ local,
+ fd >= 0 ? fd : STDOUT_FILENO,
+ arg_format);
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "ExportRawEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sshst",
+ local,
+ image_class_to_string(arg_image_class),
+ fd >= 0 ? fd : STDOUT_FILENO,
+ arg_format,
+ /* flags= */ 0);
+ }
if (r < 0)
return bus_log_create_error(r);
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
remote = argv[1];
if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
local);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullTar");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(
- m,
- "sssb",
- remote,
- local,
- import_verify_to_string(arg_verify),
- arg_force);
+ if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullTar");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sssb",
+ remote,
+ local,
+ import_verify_to_string(arg_verify),
+ FLAGS_SET(arg_import_flags, IMPORT_FORCE));
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullTarEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sssst",
+ remote,
+ local,
+ image_class_to_string(arg_image_class),
+ import_verify_to_string(arg_verify),
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ }
if (r < 0)
return bus_log_create_error(r);
sd_bus *bus = ASSERT_PTR(userdata);
int r;
+ r = settle_image_class();
+ if (r < 0)
+ return r;
+
remote = argv[1];
if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
local);
}
- r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullRaw");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(
- m,
- "sssb",
- remote,
- local,
- import_verify_to_string(arg_verify),
- arg_force);
+ if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullRaw");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sssb",
+ remote,
+ local,
+ import_verify_to_string(arg_verify),
+ FLAGS_SET(arg_import_flags, IMPORT_FORCE));
+ } else {
+ r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullRawEx");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "sssst",
+ remote,
+ local,
+ image_class_to_string(arg_image_class),
+ import_verify_to_string(arg_verify),
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ }
if (r < 0)
return bus_log_create_error(r);
pager_open(arg_pager_flags);
- r = bus_call_method(bus, bus_import_mgr, "ListTransfers", &error, &reply, NULL);
- if (r < 0)
- return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, r));
+ bool ex;
+ r = bus_call_method(bus, bus_import_mgr, "ListTransfersEx", &error, &reply, NULL);
+ if (r < 0) {
+ if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
+ sd_bus_error_free(&error);
- r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
+ r = bus_call_method(bus, bus_import_mgr, "ListTransfers", &error, &reply, NULL);
+ }
+ if (r < 0)
+ return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, r));
+
+ ex = false;
+ r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
+ } else {
+ ex = true;
+ r = sd_bus_message_enter_container(reply, 'a', "(ussssdo)");
+ }
if (r < 0)
return bus_log_parse_error(r);
- t = table_new("id", "progress", "type", "local", "remote");
+ t = table_new("id", "progress", "type", "class", "local", "remote");
if (!t)
return log_oom();
- (void) table_set_sort(t, (size_t) 3, (size_t) 0);
+ (void) table_set_sort(t, (size_t) 4, (size_t) 0);
table_set_ersatz_string(t, TABLE_ERSATZ_DASH);
for (;;) {
- const char *type, *remote, *local;
+ const char *type, *remote, *local, *class = "machine";
double progress;
uint32_t id;
- r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, NULL);
+ if (ex)
+ r = sd_bus_message_read(reply, "(ussssdo)", &id, &type, &remote, &local, &class, &progress, NULL);
+ else
+ r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, NULL);
if (r < 0)
return bus_log_parse_error(r);
if (r == 0)
r = table_add_many(
t,
TABLE_STRING, type,
+ TABLE_STRING, class,
TABLE_STRING, local,
TABLE_STRING, remote,
TABLE_SET_URL, remote);
return log_oom();
printf("%1$s [OPTIONS...] COMMAND ...\n\n"
- "%5$sDownload machine images%6$s\n"
- "\n%3$sImage Transfer Commands:%4$s\n"
+ "%5$sDownload, import or export disk images%6$s\n"
+ "\n%3$sCommands:%4$s\n"
" pull-tar URL [NAME] Download a TAR container image\n"
" pull-raw URL [NAME] Download a RAW container or VM image\n"
" import-tar FILE [NAME] Import a local TAR container 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"
+ " list-transfers Show list of transfers in progress\n"
+ " cancel-transfer [ID...] Cancel a transfer\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-ask-password Do not ask for system passwords\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
- " --read-only Create read-only bind mount\n"
+ " --read-only Create read-only image\n"
" -q --quiet Suppress output\n"
" --json=pretty|short|off Generate JSON output\n"
" -j Equvilant to --json=pretty on TTY, --json=short\n"
" --verify=MODE Verification mode for downloaded images (no,\n"
" checksum, signature)\n"
" --format=xz|gzip|bzip2 Desired output format for export\n"
- " --force Download image even if already exists\n"
+ " --force Install image even if already exists\n"
+ " -m --class=machine Install as machine image\n"
+ " -P --class=portable Install as portable service image\n"
+ " -S --class=sysext Install as system extension image\n"
+ " -C --class=confext Install as configuration extension image\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,
ARG_VERIFY,
ARG_FORCE,
ARG_FORMAT,
+ ARG_CLASS,
};
static const struct option options[] = {
{ "verify", required_argument, NULL, ARG_VERIFY },
{ "force", no_argument, NULL, ARG_FORCE },
{ "format", required_argument, NULL, ARG_FORMAT },
+ { "class", required_argument, NULL, ARG_CLASS },
{}
};
assert(argv);
for (;;) {
- c = getopt_long(argc, argv, "hH:M:jq", options, NULL);
+ c = getopt_long(argc, argv, "hH:M:jqmPSC", options, NULL);
if (c < 0)
break;
break;
case ARG_READ_ONLY:
- arg_read_only = true;
+ arg_import_flags |= IMPORT_READ_ONLY;
break;
case 'q':
break;
case ARG_FORCE:
- arg_force = true;
+ arg_import_flags |= IMPORT_FORCE;
break;
case ARG_FORMAT:
arg_legend = false;
break;
+ case ARG_CLASS:
+ arg_image_class = image_class_from_string(optarg);
+ if (arg_image_class < 0)
+ return log_error_errno(arg_image_class, "Failed to parse --class= parameter: %s", optarg);
+ break;
+
+ case 'm':
+ arg_image_class = IMAGE_MACHINE;
+ break;
+
+ case 'P':
+ arg_image_class = IMAGE_PORTABLE;
+ break;
+
+ case 'S':
+ arg_image_class = IMAGE_SYSEXT;
+ break;
+
+ case 'C':
+ arg_image_class = IMAGE_CONFEXT;
+ break;
+
case '?':
return -EINVAL;