diff --git a/src/import/export.c b/src/import/export.c
index ee65cc8d36..ac81b2fbab 100644
--- a/src/import/export.c
+++ b/src/import/export.c
@@ -23,6 +23,7 @@
#include "verbs.h"
static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN;
+static ImageClass arg_class = IMAGE_MACHINE;
static void determine_compression_from_filename(const char *p) {
@@ -63,7 +64,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
int r, fd;
if (hostname_is_valid(argv[1], 0)) {
- r = image_find(IMAGE_MACHINE, argv[1], NULL, &image);
+ r = image_find(arg_class, argv[1], NULL, &image);
if (r == -ENOENT)
return log_error_errno(r, "Machine image %s not found.", argv[1]);
if (r < 0)
@@ -135,7 +136,7 @@ static int export_raw(int argc, char *argv[], void *userdata) {
int r, fd;
if (hostname_is_valid(argv[1], 0)) {
- r = image_find(IMAGE_MACHINE, argv[1], NULL, &image);
+ r = image_find(arg_class, argv[1], NULL, &image);
if (r == -ENOENT)
return log_error_errno(r, "Machine image %s not found.", argv[1]);
if (r < 0)
@@ -190,14 +191,16 @@ static int export_raw(int argc, char *argv[], void *userdata) {
static int help(int argc, char *argv[], void *userdata) {
printf("%1$s [OPTIONS...] {COMMAND} ...\n"
- "\n%4$sExport container or virtual machine images.%5$s\n"
+ "\n%4$sExport disk images.%5$s\n"
"\n%2$sCommands:%3$s\n"
" tar NAME [FILE] Export a TAR image\n"
" raw NAME [FILE] Export a RAW image\n"
"\n%2$sOptions:%3$s\n"
" -h --help Show this help\n"
" --version Show package version\n"
- " --format=FORMAT Select format\n",
+ " --format=FORMAT Select format\n"
+ " --class=CLASS Select image class (machine, sysext, confext,\n"
+ " portable)\n",
program_invocation_short_name,
ansi_underline(),
ansi_normal(),
@@ -212,12 +215,14 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_FORMAT,
+ ARG_CLASS,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "format", required_argument, NULL, ARG_FORMAT },
+ { "class", required_argument, NULL, ARG_CLASS },
{}
};
@@ -250,6 +255,13 @@ static int parse_argv(int argc, char *argv[]) {
"Unknown format: %s", optarg);
break;
+ case ARG_CLASS:
+ arg_class = image_class_from_string(optarg);
+ if (arg_class < 0)
+ return log_error_errno(arg_class, "Failed to parse --class= argument: %s", optarg);
+
+ break;
+
case '?':
return -EINVAL;
diff --git a/src/import/import-common.h b/src/import/import-common.h
index edde7fd8bd..2bb2075462 100644
--- a/src/import/import-common.h
+++ b/src/import/import-common.h
@@ -27,6 +27,8 @@ typedef enum ImportFlags {
/* The supported flags for the tar and the raw pulling */
IMPORT_PULL_FLAGS_MASK_TAR = IMPORT_FLAGS_MASK_TAR|IMPORT_PULL_SETTINGS,
IMPORT_PULL_FLAGS_MASK_RAW = IMPORT_FLAGS_MASK_RAW|IMPORT_PULL_SETTINGS|IMPORT_PULL_ROOTHASH|IMPORT_PULL_ROOTHASH_SIGNATURE|IMPORT_PULL_VERITY,
+
+ _IMPORT_FLAGS_INVALID = -EINVAL,
} ImportFlags;
int import_fork_tar_c(const char *path, pid_t *ret);
diff --git a/src/import/import-fs.c b/src/import/import-fs.c
index a89c835f57..e37fd7b41d 100644
--- a/src/import/import-fs.c
+++ b/src/import/import-fs.c
@@ -31,7 +31,8 @@ static bool arg_btrfs_subvol = true;
static bool arg_btrfs_quota = true;
static bool arg_sync = true;
static bool arg_direct = false;
-static const char *arg_image_root = "/var/lib/machines";
+static const char *arg_image_root = NULL;
+static ImageClass arg_class = IMAGE_MACHINE;
typedef struct ProgressInfo {
RateLimit limit;
@@ -143,7 +144,7 @@ static int import_fs(int argc, char *argv[], void *userdata) {
return log_oom();
if (!arg_force) {
- r = image_find(IMAGE_MACHINE, local, NULL, NULL);
+ r = image_find(arg_class, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
@@ -266,7 +267,9 @@ static int help(int argc, char *argv[], void *userdata) {
" instead of a directory\n"
" --btrfs-quota=BOOL Controls whether to set up quota for btrfs\n"
" subvolume\n"
- " --sync=BOOL Controls whether to sync() before completing\n",
+ " --sync=BOOL Controls whether to sync() before completing\n"
+ " --class=CLASS Select image class (machine, sysext, confext,\n"
+ " portable)\n",
program_invocation_short_name,
ansi_underline(),
ansi_normal(),
@@ -287,6 +290,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_BTRFS_SUBVOL,
ARG_BTRFS_QUOTA,
ARG_SYNC,
+ ARG_CLASS,
};
static const struct option options[] = {
@@ -299,6 +303,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "btrfs-subvol", required_argument, NULL, ARG_BTRFS_SUBVOL },
{ "btrfs-quota", required_argument, NULL, ARG_BTRFS_QUOTA },
{ "sync", required_argument, NULL, ARG_SYNC },
+ { "class", required_argument, NULL, ARG_CLASS },
{}
};
@@ -354,6 +359,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
+ case ARG_CLASS:
+ arg_class = image_class_from_string(optarg);
+ if (arg_class < 0)
+ return log_error_errno(arg_class, "Failed to parse --class= argument: %s", optarg);
+
+ break;
+
case '?':
return -EINVAL;
@@ -361,6 +373,9 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached();
}
+ if (!arg_image_root)
+ arg_image_root = image_root_to_string(arg_class);
+
return 1;
}
diff --git a/src/import/import-raw.c b/src/import/import-raw.c
index f7ed163d86..ee9b297bfe 100644
--- a/src/import/import-raw.c
+++ b/src/import/import-raw.c
@@ -95,8 +95,9 @@ int raw_import_new(
int r;
assert(ret);
+ assert(image_root);
- root = strdup(image_root ?: "/var/lib/machines");
+ root = strdup(image_root);
if (!root)
return -ENOMEM;
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 90202709ec..39df11b5ff 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -97,8 +97,9 @@ int tar_import_new(
int r;
assert(ret);
+ assert(image_root);
- root = strdup(image_root ?: "/var/lib/machines");
+ root = strdup(image_root);
if (!root)
return -ENOMEM;
diff --git a/src/import/import.c b/src/import/import.c
index 50059870a0..22ce6f5aaa 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -25,9 +25,10 @@
#include "terminal-util.h"
#include "verbs.h"
-static const char *arg_image_root = "/var/lib/machines";
+static const char *arg_image_root = NULL;
static ImportFlags arg_import_flags = IMPORT_BTRFS_SUBVOL | IMPORT_BTRFS_QUOTA | IMPORT_CONVERT_QCOW2 | IMPORT_SYNC;
static uint64_t arg_offset = UINT64_MAX, arg_size_max = UINT64_MAX;
+static ImageClass arg_class = IMAGE_MACHINE;
static int normalize_local(const char *local, char **ret) {
_cleanup_free_ char *ll = NULL;
@@ -61,7 +62,7 @@ static int normalize_local(const char *local, char **ret) {
local = "imported";
if (!FLAGS_SET(arg_import_flags, IMPORT_FORCE)) {
- r = image_find(IMAGE_MACHINE, local, NULL, NULL);
+ r = image_find(arg_class, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
@@ -266,7 +267,7 @@ static int import_raw(int argc, char *argv[], void *userdata) {
static int help(int argc, char *argv[], void *userdata) {
printf("%1$s [OPTIONS...] {COMMAND} ...\n"
- "\n%4$sImport container or virtual machine images.%5$s\n"
+ "\n%4$sImport disk images.%5$s\n"
"\n%2$sCommands:%3$s\n"
" tar FILE [NAME] Import a TAR image\n"
" raw FILE [NAME] Import a RAW image\n"
@@ -285,7 +286,9 @@ static int help(int argc, char *argv[], void *userdata) {
" regular disk images\n"
" --sync=BOOL Controls whether to sync() before completing\n"
" --offset=BYTES Offset to seek to in destination\n"
- " --size-max=BYTES Maximum number of bytes to write to destination\n",
+ " --size-max=BYTES Maximum number of bytes to write to destination\n"
+ " --class=CLASS Select image class (machine, sysext, confext,\n"
+ " portable)\n",
program_invocation_short_name,
ansi_underline(),
ansi_normal(),
@@ -309,6 +312,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SYNC,
ARG_OFFSET,
ARG_SIZE_MAX,
+ ARG_CLASS,
};
static const struct option options[] = {
@@ -324,6 +328,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "sync", required_argument, NULL, ARG_SYNC },
{ "offset", required_argument, NULL, ARG_OFFSET },
{ "size-max", required_argument, NULL, ARG_SIZE_MAX },
+ { "class", required_argument, NULL, ARG_CLASS },
{}
};
@@ -416,6 +421,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
+ case ARG_CLASS:
+ arg_class = image_class_from_string(optarg);
+ if (arg_class < 0)
+ return log_error_errno(arg_class, "Failed to parse --class= argument: %s", optarg);
+
+ break;
+
case '?':
return -EINVAL;
@@ -432,6 +444,9 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_offset != UINT64_MAX && !FLAGS_SET(arg_import_flags, IMPORT_DIRECT))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File offset only supported in --direct mode.");
+ if (!arg_image_root)
+ arg_image_root = image_root_to_string(arg_class);
+
return 1;
}
diff --git a/src/import/importd.c b/src/import/importd.c
index dbf2fba4ab..47dfb2dfaf 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -14,16 +14,19 @@
#include "common-signal.h"
#include "constants.h"
#include "daemon-util.h"
+#include "discover-image.h"
#include "env-util.h"
#include "event-util.h"
#include "fd-util.h"
#include "float.h"
#include "hostname-util.h"
+#include "import-common.h"
#include "import-util.h"
#include "machine-pool.h"
#include "main-func.h"
#include "missing_capability.h"
#include "mkdir-label.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"
@@ -64,9 +67,8 @@ struct Transfer {
char *remote;
char *local;
- bool force_local;
- bool read_only;
-
+ ImageClass class;
+ ImportFlags flags;
char *format;
PidRef pidref;
@@ -382,6 +384,8 @@ static int transfer_start(Transfer *t) {
NULL, /* tar, raw */
NULL, /* --verify= */
NULL, /* verify argument */
+ NULL, /* --class= */
+ NULL, /* class argument */
NULL, /* maybe --force */
NULL, /* maybe --read-only */
NULL, /* if so: the actual URL */
@@ -457,9 +461,14 @@ static int transfer_start(Transfer *t) {
cmd[k++] = import_verify_to_string(t->verify);
}
- if (t->force_local)
+ if (t->class != IMAGE_MACHINE) {
+ cmd[k++] = "--class";
+ cmd[k++] = image_class_to_string(t->class);
+ }
+
+ if (FLAGS_SET(t->flags, IMPORT_FORCE))
cmd[k++] = "--force";
- if (t->read_only)
+ if (FLAGS_SET(t->flags, IMPORT_READ_ONLY))
cmd[k++] = "--read-only";
if (t->format) {
@@ -702,12 +711,13 @@ static Transfer *manager_find(Manager *m, TransferType type, const char *remote)
static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(transfer_unrefp) Transfer *t = NULL;
- int fd, force, read_only, r;
- const char *local, *object;
+ ImageClass class = _IMAGE_CLASS_INVALID;
Manager *m = ASSERT_PTR(userdata);
+ const char *local;
TransferType type;
struct stat st;
- uint32_t id;
+ uint64_t flags;
+ int fd, r;
assert(msg);
@@ -722,9 +732,34 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (r == 0)
return 1; /* Will call us back */
- r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only);
- if (r < 0)
- return r;
+ if (endswith(sd_bus_message_get_member(msg), "Ex")) {
+ const char *sclass;
+
+ r = sd_bus_message_read(msg, "hsst", &fd, &local, &sclass, &flags);
+ if (r < 0)
+ return r;
+
+ class = image_class_from_string(sclass);
+ if (class < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image class '%s' not known", sclass);
+
+ if (flags & ~(IMPORT_READ_ONLY|IMPORT_FORCE))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Flags 0x%" PRIx64 " invalid", flags);
+ } else {
+ int force, read_only;
+
+ r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only);
+ if (r < 0)
+ return r;
+
+ class = IMAGE_MACHINE;
+
+ flags = 0;
+ SET_FLAG(flags, IMPORT_FORCE, force);
+ SET_FLAG(flags, IMPORT_READ_ONLY, read_only);
+ }
if (fstat(fd, &st) < 0)
return -errno;
@@ -736,11 +771,13 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Local name %s is invalid", local);
- r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
- if (r < 0)
- return r;
+ if (class == IMAGE_MACHINE) {
+ r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
+ if (r < 0)
+ return r;
+ }
- type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ?
+ type = startswith(sd_bus_message_get_member(msg), "ImportTar") ?
TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW;
r = transfer_new(m, &t);
@@ -748,8 +785,8 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
return r;
t->type = type;
- t->force_local = force;
- t->read_only = read_only;
+ t->class = class;
+ t->flags = flags;
t->local = strdup(local);
if (!t->local)
@@ -763,19 +800,21 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (r < 0)
return r;
- object = t->object_path;
- id = t->id;
- t = NULL;
+ r = sd_bus_reply_method_return(msg, "uo", t->id, t->object_path);
+ if (r < 0)
+ return r;
- return sd_bus_reply_method_return(msg, "uo", id, object);
+ TAKE_PTR(t);
+ return 1;
}
static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(transfer_unrefp) Transfer *t = NULL;
- int fd, force, read_only, r;
- const char *local, *object;
+ ImageClass class = _IMAGE_CLASS_INVALID;
Manager *m = ASSERT_PTR(userdata);
- uint32_t id;
+ const char *local;
+ uint64_t flags;
+ int fd, r;
assert(msg);
@@ -790,9 +829,34 @@ static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *e
if (r == 0)
return 1; /* Will call us back */
- r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only);
- if (r < 0)
- return r;
+ if (endswith(sd_bus_message_get_member(msg), "Ex")) {
+ const char *sclass;
+
+ r = sd_bus_message_read(msg, "hsst", &fd, &local, &sclass, &flags);
+ if (r < 0)
+ return r;
+
+ class = image_class_from_string(sclass);
+ if (class < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image class '%s' not known", sclass);
+
+ if (flags & ~(IMPORT_READ_ONLY|IMPORT_FORCE))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Flags 0x%" PRIx64 " invalid", flags);
+ } else {
+ int force, read_only;
+
+ r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only);
+ if (r < 0)
+ return r;
+
+ class = IMAGE_MACHINE;
+
+ flags = 0;
+ SET_FLAG(flags, IMPORT_FORCE, force);
+ SET_FLAG(flags, IMPORT_READ_ONLY, read_only);
+ }
r = fd_verify_directory(fd);
if (r < 0)
@@ -802,17 +866,19 @@ static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *e
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Local name %s is invalid", local);
- r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
- if (r < 0)
- return r;
+ if (class == IMAGE_MACHINE) {
+ r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
+ if (r < 0)
+ return r;
+ }
r = transfer_new(m, &t);
if (r < 0)
return r;
t->type = TRANSFER_IMPORT_FS;
- t->force_local = force;
- t->read_only = read_only;
+ t->class = class;
+ t->flags = flags;
t->local = strdup(local);
if (!t->local)
@@ -826,21 +892,23 @@ static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *e
if (r < 0)
return r;
- object = t->object_path;
- id = t->id;
- t = NULL;
+ r = sd_bus_reply_method_return(msg, "uo", t->id, t->object_path);
+ if (r < 0)
+ return r;
- return sd_bus_reply_method_return(msg, "uo", id, object);
+ TAKE_PTR(t);
+ return 1;
}
static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(transfer_unrefp) Transfer *t = NULL;
- int fd, r;
- const char *local, *object, *format;
+ ImageClass class = _IMAGE_CLASS_INVALID;
Manager *m = ASSERT_PTR(userdata);
+ const char *local, *format;
TransferType type;
+ uint64_t flags;
struct stat st;
- uint32_t id;
+ int fd, r;
assert(msg);
@@ -855,9 +923,29 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (r == 0)
return 1; /* Will call us back */
- r = sd_bus_message_read(msg, "shs", &local, &fd, &format);
- if (r < 0)
- return r;
+ if (endswith(sd_bus_message_get_member(msg), "Ex")) {
+ const char *sclass;
+
+ r = sd_bus_message_read(msg, "sshst", &local, &sclass, &fd, &format, &flags);
+ if (r < 0)
+ return r;
+
+ class = image_class_from_string(sclass);
+ if (class < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image class '%s' not known", sclass);
+
+ if (flags != 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Flags 0x%" PRIx64 " invalid", flags);
+ } else {
+ r = sd_bus_message_read(msg, "shs", &local, &fd, &format);
+ if (r < 0)
+ return r;
+
+ class = IMAGE_MACHINE;
+ flags = 0;
+ }
if (!hostname_is_valid(local, 0))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@@ -869,7 +957,7 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode))
return -EINVAL;
- type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ?
+ type = startswith(sd_bus_message_get_member(msg), "ExportTar") ?
TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW;
r = transfer_new(m, &t);
@@ -877,6 +965,8 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
return r;
t->type = type;
+ t->class = class;
+ t->flags = flags;
if (!isempty(format)) {
t->format = strdup(format);
@@ -896,21 +986,23 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
if (r < 0)
return r;
- object = t->object_path;
- id = t->id;
- t = NULL;
+ r = sd_bus_reply_method_return(msg, "uo", t->id, t->object_path);
+ if (r < 0)
+ return r;
- return sd_bus_reply_method_return(msg, "uo", id, object);
+ TAKE_PTR(t);
+ return 1;
}
static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(transfer_unrefp) Transfer *t = NULL;
- const char *remote, *local, *verify, *object;
+ ImageClass class = _IMAGE_CLASS_INVALID;
+ const char *remote, *local, *verify;
Manager *m = ASSERT_PTR(userdata);
- ImportVerify v;
TransferType type;
- int force, r;
- uint32_t id;
+ uint64_t flags;
+ ImportVerify v;
+ int r;
assert(msg);
@@ -925,9 +1017,33 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
if (r == 0)
return 1; /* Will call us back */
- r = sd_bus_message_read(msg, "sssb", &remote, &local, &verify, &force);
- if (r < 0)
- return r;
+ if (endswith(sd_bus_message_get_member(msg), "Ex")) {
+ const char *sclass;
+
+ r = sd_bus_message_read(msg, "sssst", &remote, &local, &sclass, &verify, &flags);
+ if (r < 0)
+ return r;
+
+ class = image_class_from_string(sclass);
+ if (class < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image class '%s' not known", sclass);
+
+ if (flags & ~(IMPORT_FORCE|IMPORT_READ_ONLY))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Flags 0x%" PRIx64 " invalid", flags);
+ } else {
+ int force;
+
+ r = sd_bus_message_read(msg, "sssb", &remote, &local, &verify, &force);
+ if (r < 0)
+ return r;
+
+ class = IMAGE_MACHINE;
+
+ flags = 0;
+ SET_FLAG(flags, IMPORT_FORCE, force);
+ }
if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@@ -947,11 +1063,13 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Unknown verification mode %s", verify);
- r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
- if (r < 0)
- return r;
+ if (class == IMAGE_MACHINE) {
+ r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
+ if (r < 0)
+ return r;
+ }
- type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ?
+ type = startswith(sd_bus_message_get_member(msg), "PullTar") ?
TRANSFER_PULL_TAR : TRANSFER_PULL_RAW;
if (manager_find(m, type, remote))
@@ -964,7 +1082,8 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
t->type = type;
t->verify = v;
- t->force_local = force;
+ t->flags = flags;
+ t->class = class;
t->remote = strdup(remote);
if (!t->remote)
@@ -980,40 +1099,81 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
if (r < 0)
return r;
- object = t->object_path;
- id = t->id;
- t = NULL;
+ r = sd_bus_reply_method_return(msg, "uo", t->id, t->object_path);
+ if (r < 0)
+ return r;
- return sd_bus_reply_method_return(msg, "uo", id, object);
+ TAKE_PTR(t);
+ return 1;
}
static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = ASSERT_PTR(userdata);
+ ImageClass class = _IMAGE_CLASS_INVALID;
Transfer *t;
int r;
assert(msg);
+ bool ex = endswith(sd_bus_message_get_member(msg), "Ex");
+ if (ex) {
+ const char *sclass;
+ uint64_t flags;
+
+ r = sd_bus_message_read(msg, "st", &sclass, &flags);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ if (!isempty(sclass)) {
+ class = image_class_from_string(sclass);
+ if (class < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Image class '%s' not known", sclass);
+ }
+
+ if (flags != 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Flags 0x%" PRIx64 " invalid", flags);
+ }
+
r = sd_bus_message_new_method_return(msg, &reply);
if (r < 0)
return r;
- r = sd_bus_message_open_container(reply, 'a', "(usssdo)");
+ if (ex)
+ r = sd_bus_message_open_container(reply, 'a', "(ussssdo)");
+ else
+ r = sd_bus_message_open_container(reply, 'a', "(usssdo)");
if (r < 0)
return r;
HASHMAP_FOREACH(t, m->transfers) {
- r = sd_bus_message_append(
- reply,
- "(usssdo)",
- t->id,
- transfer_type_to_string(t->type),
- t->remote,
- t->local,
- transfer_percent_as_double(t),
- t->object_path);
+ if (class >= 0 && class != t->class)
+ continue;
+
+ if (ex)
+ r = sd_bus_message_append(
+ reply,
+ "(ussssdo)",
+ t->id,
+ transfer_type_to_string(t->type),
+ t->remote,
+ t->local,
+ image_class_to_string(t->class),
+ transfer_percent_as_double(t),
+ t->object_path);
+ else
+ r = sd_bus_message_append(
+ reply,
+ "(usssdo)",
+ t->id,
+ transfer_type_to_string(t->type),
+ t->remote,
+ t->local,
+ transfer_percent_as_double(t),
+ t->object_path);
if (r < 0)
return r;
}
@@ -1059,7 +1219,7 @@ static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_er
r = bus_verify_polkit_async(
msg,
- "org.freedesktop.import1.pull",
+ "org.freedesktop.import1.cancel",
/* details= */ NULL,
&m->polkit_registry,
error);
@@ -1212,6 +1372,17 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_import_tar_or_raw,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ImportTarEx",
+ "hsst",
+ SD_BUS_PARAM(fd)
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_import_tar_or_raw,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ImportRaw",
"hsbb",
SD_BUS_PARAM(fd)
@@ -1223,6 +1394,17 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_import_tar_or_raw,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ImportRawEx",
+ "hsst",
+ SD_BUS_PARAM(fd)
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_import_tar_or_raw,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ImportFileSystem",
"hsbb",
SD_BUS_PARAM(fd)
@@ -1234,6 +1416,17 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_import_fs,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ImportFileSystemEx",
+ "hsst",
+ SD_BUS_PARAM(fd)
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_import_fs,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ExportTar",
"shs",
SD_BUS_PARAM(local_name)
@@ -1244,6 +1437,18 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_export_tar_or_raw,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ExportTarEx",
+ "sshst",
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(fd)
+ SD_BUS_PARAM(format)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_export_tar_or_raw,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ExportRaw",
"shs",
SD_BUS_PARAM(local_name)
@@ -1254,6 +1459,18 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_export_tar_or_raw,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ExportRawEx",
+ "sshst",
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(fd)
+ SD_BUS_PARAM(format)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_export_tar_or_raw,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("PullTar",
"sssb",
SD_BUS_PARAM(url)
@@ -1265,6 +1482,18 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_pull_tar_or_raw,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("PullTarEx",
+ "sssst",
+ SD_BUS_PARAM(url)
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(verify_mode)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_pull_tar_or_raw,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("PullRaw",
"sssb",
SD_BUS_PARAM(url)
@@ -1276,12 +1505,32 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_PARAM(transfer_path),
method_pull_tar_or_raw,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("PullRawEx",
+ "sssst",
+ SD_BUS_PARAM(url)
+ SD_BUS_PARAM(local_name)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(verify_mode)
+ SD_BUS_PARAM(flags),
+ "uo",
+ SD_BUS_PARAM(transfer_id)
+ SD_BUS_PARAM(transfer_path),
+ method_pull_tar_or_raw,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ListTransfers",
NULL,,
"a(usssdo)",
SD_BUS_PARAM(transfers),
method_list_transfers,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ListTransfersEx",
+ "st",
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(flags),
+ "a(ussssdo)",
+ SD_BUS_PARAM(transfers),
+ method_list_transfers,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("CancelTransfer",
"u",
SD_BUS_PARAM(transfer_id),
diff --git a/src/import/org.freedesktop.import1.conf b/src/import/org.freedesktop.import1.conf
index d252ff6460..f775aa061c 100644
--- a/src/import/org.freedesktop.import1.conf
+++ b/src/import/org.freedesktop.import1.conf
@@ -42,6 +42,10 @@
send_interface="org.freedesktop.import1.Manager"
send_member="ListTransfers"/>
+
+
@@ -50,30 +54,58 @@
send_interface="org.freedesktop.import1.Manager"
send_member="ImportTar"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/import/org.freedesktop.import1.policy b/src/import/org.freedesktop.import1.policy
index 88e436dc3a..45c11def67 100644
--- a/src/import/org.freedesktop.import1.policy
+++ b/src/import/org.freedesktop.import1.policy
@@ -19,8 +19,8 @@
https://systemd.io
- Import a VM or container image
- Authentication is required to import a VM or container image
+ Import a disk image
+ Authentication is required to import an image
auth_admin
auth_admin
@@ -29,8 +29,8 @@
- Export a VM or container image
- Authentication is required to export a VM or container image
+ Export a disk image
+ Authentication is required to export disk image
auth_admin
auth_admin
@@ -39,8 +39,18 @@
- Download a VM or container image
- Authentication is required to download a VM or container image
+ Download a disk image
+ Authentication is required to download a disk image
+
+ auth_admin
+ auth_admin
+ auth_admin_keep
+
+
+
+
+ Cancel transfer of a disk image
+ Authentication is required to cancel the ongoing transfer of a disk image
auth_admin
auth_admin
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index 7839057769..4fca08437c 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -37,11 +37,9 @@ int pull_find_old_etags(
int r;
assert(url);
+ assert(image_root);
assert(etags);
- if (!image_root)
- image_root = "/var/lib/machines";
-
_cleanup_free_ char *escaped_url = xescape(url, FILENAME_ESCAPE);
if (!escaped_url)
return -ENOMEM;
@@ -128,11 +126,9 @@ int pull_make_path(const char *url, const char *etag, const char *image_root, co
char *path;
assert(url);
+ assert(image_root);
assert(ret);
- if (!image_root)
- image_root = "/var/lib/machines";
-
escaped_url = xescape(url, FILENAME_ESCAPE);
if (!escaped_url)
return -ENOMEM;
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index ebe479fb80..50785fe431 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -60,7 +60,7 @@ struct RawPull {
void *userdata;
char *local; /* In PULL_DIRECT mode the path we are supposed to place things in, otherwise the
- * machine name of the final copy we make */
+ * image name of the final copy we make */
char *final_path;
char *temp_path;
@@ -127,8 +127,9 @@ int raw_pull_new(
int r;
assert(ret);
+ assert(image_root);
- root = strdup(image_root ?: "/var/lib/machines");
+ root = strdup(image_root);
if (!root)
return -ENOMEM;
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index 99d8ff0553..ae573f1b54 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -106,9 +106,10 @@ int tar_pull_new(
_cleanup_free_ char *root = NULL;
int r;
+ assert(image_root);
assert(ret);
- root = strdup(image_root ?: "/var/lib/machines");
+ root = strdup(image_root);
if (!root)
return -ENOMEM;
diff --git a/src/import/pull.c b/src/import/pull.c
index 518755b61d..f281ab04fd 100644
--- a/src/import/pull.c
+++ b/src/import/pull.c
@@ -26,11 +26,12 @@
#include "verbs.h"
#include "web-util.h"
-static const char *arg_image_root = "/var/lib/machines";
+static const char *arg_image_root = NULL;
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
static ImportFlags arg_import_flags = IMPORT_PULL_SETTINGS | IMPORT_PULL_ROOTHASH | IMPORT_PULL_ROOTHASH_SIGNATURE | IMPORT_PULL_VERITY | IMPORT_BTRFS_SUBVOL | IMPORT_BTRFS_QUOTA | IMPORT_CONVERT_QCOW2 | IMPORT_SYNC;
static uint64_t arg_offset = UINT64_MAX, arg_size_max = UINT64_MAX;
static char *arg_checksum = NULL;
+static ImageClass arg_class = IMAGE_MACHINE;
STATIC_DESTRUCTOR_REGISTER(arg_checksum, freep);
@@ -64,7 +65,7 @@ static int normalize_local(const char *local, const char *url, char **ret) {
local);
if (!FLAGS_SET(arg_import_flags, IMPORT_FORCE)) {
- r = image_find(IMAGE_MACHINE, local, NULL, NULL);
+ r = image_find(arg_class, local, NULL, NULL);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
@@ -241,7 +242,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
static int help(int argc, char *argv[], void *userdata) {
printf("%1$s [OPTIONS...] {COMMAND} ...\n"
- "\n%4$sDownload container or virtual machine images.%5$s\n"
+ "\n%4$sDownload disk images.%5$s\n"
"\n%2$sCommands:%3$s\n"
" tar URL [NAME] Download a TAR image\n"
" raw URL [NAME] Download a RAW image\n"
@@ -267,7 +268,9 @@ static int help(int argc, char *argv[], void *userdata) {
" regular disk images\n"
" --sync=BOOL Controls whether to sync() before completing\n"
" --offset=BYTES Offset to seek to in destination\n"
- " --size-max=BYTES Maximum number of bytes to write to destination\n",
+ " --size-max=BYTES Maximum number of bytes to write to destination\n"
+ " --class=CLASS Select image class (machine, sysext, confext,\n"
+ " portable)\n",
program_invocation_short_name,
ansi_underline(),
ansi_normal(),
@@ -296,6 +299,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SYNC,
ARG_OFFSET,
ARG_SIZE_MAX,
+ ARG_CLASS,
};
static const struct option options[] = {
@@ -316,10 +320,12 @@ static int parse_argv(int argc, char *argv[]) {
{ "sync", required_argument, NULL, ARG_SYNC },
{ "offset", required_argument, NULL, ARG_OFFSET },
{ "size-max", required_argument, NULL, ARG_SIZE_MAX },
+ { "class", required_argument, NULL, ARG_CLASS },
{}
};
int c, r;
+ bool auto_settings = true;
assert(argc >= 0);
assert(argv);
@@ -381,6 +387,7 @@ static int parse_argv(int argc, char *argv[]) {
return r;
SET_FLAG(arg_import_flags, IMPORT_PULL_SETTINGS, r);
+ auto_settings = false;
break;
case ARG_ROOTHASH:
@@ -478,6 +485,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
+ case ARG_CLASS:
+ arg_class = image_class_from_string(optarg);
+ if (arg_class < 0)
+ return log_error_errno(arg_class, "Failed to parse --class= argument: %s", optarg);
+
+ break;
+
case '?':
return -EINVAL;
@@ -497,6 +511,13 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_checksum && (arg_import_flags & (IMPORT_PULL_SETTINGS|IMPORT_PULL_ROOTHASH|IMPORT_PULL_ROOTHASH_SIGNATURE|IMPORT_PULL_VERITY)) != 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Literal checksum verification only supported if no associated files are downloaded.");
+ if (!arg_image_root)
+ arg_image_root = image_root_to_string(arg_class);
+
+ /* .nspawn settings files only really make sense for machine images, not for sysext/confext/portable */
+ if (auto_settings && arg_class != IMAGE_MACHINE)
+ arg_import_flags &= ~IMPORT_PULL_SETTINGS;
+
return 1;
}
diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c
index 72f20c8eb7..00d32a9c87 100644
--- a/src/shared/discover-image.c
+++ b/src/shared/discover-image.c
@@ -99,6 +99,15 @@ static const char* image_class_suffix_table[_IMAGE_CLASS_MAX] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(image_class_suffix, ImageClass);
+static const char *const image_root_table[_IMAGE_CLASS_MAX] = {
+ [IMAGE_MACHINE] = "/var/lib/machines",
+ [IMAGE_PORTABLE] = "/var/lib/portables",
+ [IMAGE_SYSEXT] = "/var/lib/extensions",
+ [IMAGE_CONFEXT] = "/var/lib/confexts",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root, ImageClass);
+
static Image *image_free(Image *i) {
assert(i);
diff --git a/src/shared/discover-image.h b/src/shared/discover-image.h
index a30a3d92ba..350c3a22cc 100644
--- a/src/shared/discover-image.h
+++ b/src/shared/discover-image.h
@@ -119,4 +119,6 @@ static inline bool IMAGE_IS_HOST(const struct Image *i) {
int image_to_json(const struct Image *i, JsonVariant **ret);
+const char *image_root_to_string(ImageClass c) _const_;
+
extern const struct hash_ops image_hash_ops;