importd: add support for downloading sysext/confext/portable images too

This adds "Ex" versions of all bus calls import implements, that make
two changes:

1. A "class" parameter is added that allows choosing between
   machine/sysext/confext/portable images to download. Depending on the
   chose class the target directory is selected differently (i.e. not
   just /var/lib/machines/, but alternatively /var/lib/portables/,
   /var/lib/extensions/, /var/lib/confexts/.

2. The boolean flags are replaced by a 64bit flags parameter.
This commit is contained in:
Lennart Poettering 2024-02-22 09:43:01 +01:00
parent 83d7411209
commit 7af5785d77
15 changed files with 473 additions and 106 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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),

View file

@ -42,6 +42,10 @@
send_interface="org.freedesktop.import1.Manager"
send_member="ListTransfers"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ListTransfersEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="CancelTransfer"/>
@ -50,30 +54,58 @@
send_interface="org.freedesktop.import1.Manager"
send_member="ImportTar"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ImportTarEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ImportRaw"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ImportRawEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ImportFileSystem"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ImportFileSystemEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ExportTar"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ExportTarEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ExportRaw"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="ExportRawEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="PullTar"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="PullTarEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="PullRaw"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Manager"
send_member="PullRawEx"/>
<allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Transfer"
send_member="Cancel"/>

View file

@ -19,8 +19,8 @@
<vendor_url>https://systemd.io</vendor_url>
<action id="org.freedesktop.import1.import">
<description gettext-domain="systemd">Import a VM or container image</description>
<message gettext-domain="systemd">Authentication is required to import a VM or container image</message>
<description gettext-domain="systemd">Import a disk image</description>
<message gettext-domain="systemd">Authentication is required to import an image</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
@ -29,8 +29,8 @@
</action>
<action id="org.freedesktop.import1.export">
<description gettext-domain="systemd">Export a VM or container image</description>
<message gettext-domain="systemd">Authentication is required to export a VM or container image</message>
<description gettext-domain="systemd">Export a disk image</description>
<message gettext-domain="systemd">Authentication is required to export disk image</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
@ -39,8 +39,18 @@
</action>
<action id="org.freedesktop.import1.pull">
<description gettext-domain="systemd">Download a VM or container image</description>
<message gettext-domain="systemd">Authentication is required to download a VM or container image</message>
<description gettext-domain="systemd">Download a disk image</description>
<message gettext-domain="systemd">Authentication is required to download a disk image</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.import1.cancel">
<description gettext-domain="systemd">Cancel transfer of a disk image</description>
<message gettext-domain="systemd">Authentication is required to cancel the ongoing transfer of a disk image</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;