summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/import/import-common.h26
-rw-r--r--src/import/importctl.c36
-rw-r--r--src/import/importd.c7
-rw-r--r--src/import/pull-raw.c83
-rw-r--r--src/import/pull-tar.c68
-rw-r--r--src/import/pull.c22
6 files changed, 163 insertions, 79 deletions
diff --git a/src/import/import-common.h b/src/import/import-common.h
index 2bb2075462..219802492d 100644
--- a/src/import/import-common.h
+++ b/src/import/import-common.h
@@ -6,27 +6,31 @@
#include "sd-event.h"
typedef enum ImportFlags {
+ /* Public Flags (i.e. accessible via D-Bus, must stay stable! */
IMPORT_FORCE = 1 << 0, /* replace existing image */
IMPORT_READ_ONLY = 1 << 1, /* make generated image read-only */
- IMPORT_BTRFS_SUBVOL = 1 << 2, /* tar: preferably create images as btrfs subvols */
- IMPORT_BTRFS_QUOTA = 1 << 3, /* tar: set up btrfs quota for new subvolume as child of parent subvolume */
- IMPORT_CONVERT_QCOW2 = 1 << 4, /* raw: if we detect a qcow2 image, unpack it */
- IMPORT_DIRECT = 1 << 5, /* import without rename games */
- IMPORT_SYNC = 1 << 6, /* fsync() right before we are done */
+ IMPORT_PULL_KEEP_DOWNLOAD = 1 << 2, /* keep a pristine copy of the downloaded file around */
+
+ /* Private flags */
+ IMPORT_BTRFS_SUBVOL = 1 << 3, /* tar: preferably create images as btrfs subvols */
+ IMPORT_BTRFS_QUOTA = 1 << 4, /* tar: set up btrfs quota for new subvolume as child of parent subvolume */
+ IMPORT_CONVERT_QCOW2 = 1 << 5, /* raw: if we detect a qcow2 image, unpack it */
+ IMPORT_DIRECT = 1 << 6, /* import without rename games */
+ IMPORT_SYNC = 1 << 7, /* fsync() right before we are done */
/* When pulling these flags are defined too */
- IMPORT_PULL_SETTINGS = 1 << 7, /* download .nspawn settings file */
- IMPORT_PULL_ROOTHASH = 1 << 8, /* only for raw: download .roothash file for verity */
- IMPORT_PULL_ROOTHASH_SIGNATURE = 1 << 9, /* only for raw: download .roothash.p7s file for verity */
- IMPORT_PULL_VERITY = 1 << 10, /* only for raw: download .verity file for verity */
+ IMPORT_PULL_SETTINGS = 1 << 8, /* download .nspawn settings file */
+ IMPORT_PULL_ROOTHASH = 1 << 9, /* only for raw: download .roothash file for verity */
+ IMPORT_PULL_ROOTHASH_SIGNATURE = 1 << 10, /* only for raw: download .roothash.p7s file for verity */
+ IMPORT_PULL_VERITY = 1 << 11, /* only for raw: download .verity file for verity */
/* The supported flags for the tar and the raw importing */
IMPORT_FLAGS_MASK_TAR = IMPORT_FORCE|IMPORT_READ_ONLY|IMPORT_BTRFS_SUBVOL|IMPORT_BTRFS_QUOTA|IMPORT_DIRECT|IMPORT_SYNC,
IMPORT_FLAGS_MASK_RAW = IMPORT_FORCE|IMPORT_READ_ONLY|IMPORT_CONVERT_QCOW2|IMPORT_DIRECT|IMPORT_SYNC,
/* 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_PULL_FLAGS_MASK_TAR = IMPORT_FLAGS_MASK_TAR|IMPORT_PULL_KEEP_DOWNLOAD|IMPORT_PULL_SETTINGS,
+ IMPORT_PULL_FLAGS_MASK_RAW = IMPORT_FLAGS_MASK_RAW|IMPORT_PULL_KEEP_DOWNLOAD|IMPORT_PULL_SETTINGS|IMPORT_PULL_ROOTHASH|IMPORT_PULL_ROOTHASH_SIGNATURE|IMPORT_PULL_VERITY,
_IMPORT_FLAGS_INVALID = -EINVAL,
} ImportFlags;
diff --git a/src/import/importctl.c b/src/import/importctl.c
index 1fc13e1326..688e583d07 100644
--- a/src/import/importctl.c
+++ b/src/import/importctl.c
@@ -37,6 +37,7 @@ static bool arg_legend = true;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static const char *arg_host = NULL;
static ImportFlags arg_import_flags = 0;
+static ImportFlags arg_import_flags_mask = 0; /* Indicates which flags have been explicitly set to on or to off */
static bool arg_quiet = false;
static bool arg_ask_password = true;
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
@@ -59,6 +60,11 @@ static int settle_image_class(void) {
"No image class specified, retry with --class= set to one of: %s.", j);
}
+ /* Keep the original pristine downloaded file as a copy only when dealing with machine images,
+ * because unlike sysext/confext/portable they are typically modified during runtime. */
+ if (!FLAGS_SET(arg_import_flags_mask, IMPORT_PULL_KEEP_DOWNLOAD))
+ SET_FLAG(arg_import_flags, IMPORT_PULL_KEEP_DOWNLOAD, arg_image_class == IMAGE_MACHINE);
+
return 0;
}
@@ -586,7 +592,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
local);
}
- if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~IMPORT_FORCE) == 0) {
r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullTar");
if (r < 0)
return bus_log_create_error(r);
@@ -610,7 +616,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
local,
image_class_to_string(arg_image_class),
import_verify_to_string(arg_verify),
- (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY|IMPORT_PULL_KEEP_DOWNLOAD));
}
if (r < 0)
return bus_log_create_error(r);
@@ -659,7 +665,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
local);
}
- if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~(IMPORT_FORCE|IMPORT_READ_ONLY)) == 0) {
+ if (arg_image_class == IMAGE_MACHINE && (arg_image_class & ~IMPORT_FORCE) == 0) {
r = bus_message_new_method_call(bus, &m, bus_import_mgr, "PullRaw");
if (r < 0)
return bus_log_create_error(r);
@@ -683,7 +689,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
local,
image_class_to_string(arg_image_class),
import_verify_to_string(arg_verify),
- (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY));
+ (uint64_t) arg_import_flags & (IMPORT_FORCE|IMPORT_READ_ONLY|IMPORT_PULL_KEEP_DOWNLOAD));
}
if (r < 0)
return bus_log_create_error(r);
@@ -860,6 +866,8 @@ static int help(int argc, char *argv[], void *userdata) {
" -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"
+ " --keep-download=BOOL Control whether to keep pristine copy of download\n"
+ " -N Shortcut for --keep-download=no\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,
@@ -884,6 +892,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_FORCE,
ARG_FORMAT,
ARG_CLASS,
+ ARG_KEEP_DOWNLOAD,
};
static const struct option options[] = {
@@ -901,6 +910,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "force", no_argument, NULL, ARG_FORCE },
{ "format", required_argument, NULL, ARG_FORMAT },
{ "class", required_argument, NULL, ARG_CLASS },
+ { "keep-download", required_argument, NULL, ARG_KEEP_DOWNLOAD },
{}
};
@@ -910,7 +920,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argv);
for (;;) {
- c = getopt_long(argc, argv, "hH:M:jqmPSC", options, NULL);
+ c = getopt_long(argc, argv, "hH:M:jqmPSCN", options, NULL);
if (c < 0)
break;
@@ -946,6 +956,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_READ_ONLY:
arg_import_flags |= IMPORT_READ_ONLY;
+ arg_import_flags_mask |= IMPORT_READ_ONLY;
break;
case 'q':
@@ -966,6 +977,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_FORCE:
arg_import_flags |= IMPORT_FORCE;
+ arg_import_flags_mask |= IMPORT_FORCE;
break;
case ARG_FORMAT:
@@ -1011,6 +1023,20 @@ static int parse_argv(int argc, char *argv[]) {
arg_image_class = IMAGE_CONFEXT;
break;
+ case ARG_KEEP_DOWNLOAD:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --keep-download= value: %s", optarg);
+
+ SET_FLAG(arg_import_flags, IMPORT_PULL_KEEP_DOWNLOAD, r);
+ arg_import_flags_mask |= IMPORT_PULL_KEEP_DOWNLOAD;
+ break;
+
+ case 'N':
+ arg_import_flags_mask &= ~IMPORT_PULL_KEEP_DOWNLOAD;
+ arg_import_flags_mask |= IMPORT_PULL_KEEP_DOWNLOAD;
+ break;
+
case '?':
return -EINVAL;
diff --git a/src/import/importd.c b/src/import/importd.c
index 41c329b0f2..a07ceb2288 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -386,6 +386,7 @@ static int transfer_start(Transfer *t) {
NULL, /* verify argument */
NULL, /* --class= */
NULL, /* class argument */
+ NULL, /* --keep-download= */
NULL, /* maybe --force */
NULL, /* maybe --read-only */
NULL, /* if so: the actual URL */
@@ -466,6 +467,10 @@ static int transfer_start(Transfer *t) {
cmd[k++] = image_class_to_string(t->class);
}
+ if (IN_SET(t->type, TRANSFER_PULL_TAR, TRANSFER_PULL_RAW))
+ cmd[k++] = FLAGS_SET(t->flags, IMPORT_PULL_KEEP_DOWNLOAD) ?
+ "--keep-download=yes" : "--keep-download=no";
+
if (FLAGS_SET(t->flags, IMPORT_FORCE))
cmd[k++] = "--force";
if (FLAGS_SET(t->flags, IMPORT_READ_ONLY))
@@ -1041,7 +1046,7 @@ 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,
"Image class '%s' not known", sclass);
- if (flags & ~(IMPORT_FORCE|IMPORT_READ_ONLY))
+ if (flags & ~(IMPORT_FORCE|IMPORT_READ_ONLY|IMPORT_PULL_KEEP_DOWNLOAD))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Flags 0x%" PRIx64 " invalid", flags);
} else {
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 50785fe431..f3e6b3af8c 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -311,7 +311,7 @@ static int raw_pull_copy_auxiliary_file(
const char *suffix,
char **path /* input + output (!) */) {
- const char *local;
+ _cleanup_free_ char *local = NULL;
int r;
assert(i);
@@ -322,21 +322,29 @@ static int raw_pull_copy_auxiliary_file(
if (r < 0)
return r;
- local = strjoina(i->image_root, "/", i->local, suffix);
+ local = strjoin(i->image_root, "/", i->local, suffix);
+ if (!local)
+ return log_oom();
- r = copy_file_atomic(
- *path,
- local,
- 0644,
- COPY_REFLINK |
- (FLAGS_SET(i->flags, IMPORT_FORCE) ? COPY_REPLACE : 0) |
- (FLAGS_SET(i->flags, IMPORT_SYNC) ? COPY_FSYNC_FULL : 0));
+ if (FLAGS_SET(i->flags, IMPORT_PULL_KEEP_DOWNLOAD))
+ r = copy_file_atomic(
+ *path,
+ local,
+ 0644,
+ COPY_REFLINK |
+ (FLAGS_SET(i->flags, IMPORT_FORCE) ? COPY_REPLACE : 0) |
+ (FLAGS_SET(i->flags, IMPORT_SYNC) ? COPY_FSYNC_FULL : 0));
+ else
+ r = install_file(AT_FDCWD, *path,
+ AT_FDCWD, local,
+ (i->flags & IMPORT_FORCE ? INSTALL_REPLACE : 0) |
+ (i->flags & IMPORT_SYNC ? INSTALL_SYNCFS : 0));
if (r == -EEXIST)
log_warning_errno(r, "File %s already exists, not replacing.", local);
else if (r == -ENOENT)
log_debug_errno(r, "Skipping creation of auxiliary file, since none was found.");
else if (r < 0)
- log_warning_errno(r, "Failed to copy file %s, ignoring: %m", local);
+ log_warning_errno(r, "Failed to install file %s, ignoring: %m", local);
else
log_info("Created new file %s.", local);
@@ -345,9 +353,7 @@ static int raw_pull_copy_auxiliary_file(
static int raw_pull_make_local_copy(RawPull *i) {
_cleanup_(unlink_and_freep) char *tp = NULL;
- _cleanup_free_ char *f = NULL;
- _cleanup_close_ int dfd = -EBADF;
- const char *p;
+ _cleanup_free_ char *p = NULL;
int r;
assert(i);
@@ -375,38 +381,49 @@ static int raw_pull_make_local_copy(RawPull *i) {
return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m");
}
- p = strjoina(i->image_root, "/", i->local, ".raw");
-
- r = tempfn_random(p, NULL, &f);
- if (r < 0)
+ p = strjoin(i->image_root, "/", i->local, ".raw");
+ if (!p)
return log_oom();
- dfd = open(f, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
- if (dfd < 0)
- return log_error_errno(errno, "Failed to create writable copy of image: %m");
+ const char *source;
+ if (FLAGS_SET(i->flags, IMPORT_PULL_KEEP_DOWNLOAD)) {
+ _cleanup_close_ int dfd = -EBADF;
+ _cleanup_free_ char *f = NULL;
+
+ r = tempfn_random(p, NULL, &f);
+ if (r < 0)
+ return log_oom();
- tp = TAKE_PTR(f);
+ dfd = open(f, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
+ if (dfd < 0)
+ return log_error_errno(errno, "Failed to create writable copy of image: %m");
- /* Turn off COW writing. This should greatly improve performance on COW file systems like btrfs,
- * since it reduces fragmentation caused by not allowing in-place writes. */
- (void) import_set_nocow_and_log(dfd, tp);
+ tp = TAKE_PTR(f);
- r = copy_bytes(i->raw_job->disk_fd, dfd, UINT64_MAX, COPY_REFLINK);
- if (r < 0)
- return log_error_errno(r, "Failed to make writable copy of image: %m");
+ /* Turn off COW writing. This should greatly improve performance on COW file systems like btrfs,
+ * since it reduces fragmentation caused by not allowing in-place writes. */
+ (void) import_set_nocow_and_log(dfd, tp);
+
+ r = copy_bytes(i->raw_job->disk_fd, dfd, UINT64_MAX, COPY_REFLINK);
+ if (r < 0)
+ return log_error_errno(r, "Failed to make writable copy of image: %m");
+
+ (void) copy_times(i->raw_job->disk_fd, dfd, COPY_CRTIME);
+ (void) copy_xattr(i->raw_job->disk_fd, NULL, dfd, NULL, 0);
- (void) copy_times(i->raw_job->disk_fd, dfd, COPY_CRTIME);
- (void) copy_xattr(i->raw_job->disk_fd, NULL, dfd, NULL, 0);
+ dfd = safe_close(dfd);
- dfd = safe_close(dfd);
+ source = tp;
+ } else
+ source = i->final_path;
- r = install_file(AT_FDCWD, tp,
+ r = install_file(AT_FDCWD, source,
AT_FDCWD, p,
(i->flags & IMPORT_FORCE ? INSTALL_REPLACE : 0) |
(i->flags & IMPORT_READ_ONLY ? INSTALL_READ_ONLY : 0) |
(i->flags & IMPORT_SYNC ? INSTALL_FSYNC_FULL : 0));
if (r < 0)
- return log_error_errno(errno, "Failed to move local image into place '%s': %m", p);
+ return log_error_errno(r, "Failed to move local image into place '%s': %m", p);
tp = mfree(tp);
@@ -628,7 +645,7 @@ static void raw_pull_job_on_finished(PullJob *j) {
r = install_file(AT_FDCWD, i->temp_path,
AT_FDCWD, i->final_path,
- INSTALL_READ_ONLY|
+ (i->flags & IMPORT_PULL_KEEP_DOWNLOAD ? INSTALL_READ_ONLY : 0) |
(i->flags & IMPORT_SYNC ? INSTALL_FSYNC_FULL : 0));
if (r < 0) {
log_error_errno(r, "Failed to move raw file to '%s': %m", i->final_path);
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index ae573f1b54..7fc71fe6f3 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -221,6 +221,7 @@ static int tar_pull_determine_path(
static int tar_pull_make_local_copy(TarPull *i) {
_cleanup_(rm_rf_subvolume_and_freep) char *t = NULL;
_cleanup_free_ char *p = NULL;
+ const char *source;
int r;
assert(i);
@@ -235,24 +236,29 @@ static int tar_pull_make_local_copy(TarPull *i) {
if (!p)
return log_oom();
- r = tempfn_random(p, NULL, &t);
- if (r < 0)
- return log_error_errno(r, "Failed to generate temporary filename for %s: %m", p);
+ if (FLAGS_SET(i->flags, IMPORT_PULL_KEEP_DOWNLOAD)) {
+ r = tempfn_random(p, NULL, &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate temporary filename for %s: %m", p);
- if (i->flags & IMPORT_BTRFS_SUBVOL)
- r = btrfs_subvol_snapshot_at(
- AT_FDCWD, i->final_path,
- AT_FDCWD, t,
- (i->flags & IMPORT_BTRFS_QUOTA ? BTRFS_SNAPSHOT_QUOTA : 0)|
- BTRFS_SNAPSHOT_FALLBACK_COPY|
- BTRFS_SNAPSHOT_FALLBACK_DIRECTORY|
- BTRFS_SNAPSHOT_RECURSIVE);
- else
- r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to create local image: %m");
+ if (i->flags & IMPORT_BTRFS_SUBVOL)
+ r = btrfs_subvol_snapshot_at(
+ AT_FDCWD, i->final_path,
+ AT_FDCWD, t,
+ (i->flags & IMPORT_BTRFS_QUOTA ? BTRFS_SNAPSHOT_QUOTA : 0)|
+ BTRFS_SNAPSHOT_FALLBACK_COPY|
+ BTRFS_SNAPSHOT_FALLBACK_DIRECTORY|
+ BTRFS_SNAPSHOT_RECURSIVE);
+ else
+ r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create local image: %m");
+
+ source = t;
+ } else
+ source = i->final_path;
- r = install_file(AT_FDCWD, t,
+ r = install_file(AT_FDCWD, source,
AT_FDCWD, p,
(i->flags & IMPORT_FORCE ? INSTALL_REPLACE : 0) |
(i->flags & IMPORT_READ_ONLY ? INSTALL_READ_ONLY : 0) |
@@ -265,28 +271,36 @@ static int tar_pull_make_local_copy(TarPull *i) {
log_info("Created new local image '%s'.", i->local);
if (FLAGS_SET(i->flags, IMPORT_PULL_SETTINGS)) {
- const char *local_settings;
+ _cleanup_free_ char *local_settings = NULL;
assert(i->settings_job);
r = tar_pull_determine_path(i, ".nspawn", &i->settings_path);
if (r < 0)
return r;
- local_settings = strjoina(i->image_root, "/", i->local, ".nspawn");
+ local_settings = strjoin(i->image_root, "/", i->local, ".nspawn");
+ if (!local_settings)
+ return log_oom();
- r = copy_file_atomic(
- i->settings_path,
- local_settings,
- 0664,
- COPY_REFLINK |
- (FLAGS_SET(i->flags, IMPORT_FORCE) ? COPY_REPLACE : 0) |
- (FLAGS_SET(i->flags, IMPORT_SYNC) ? COPY_FSYNC_FULL : 0));
+ if (FLAGS_SET(i->flags, IMPORT_PULL_KEEP_DOWNLOAD))
+ r = copy_file_atomic(
+ i->settings_path,
+ local_settings,
+ 0664,
+ COPY_REFLINK |
+ (FLAGS_SET(i->flags, IMPORT_FORCE) ? COPY_REPLACE : 0) |
+ (FLAGS_SET(i->flags, IMPORT_SYNC) ? COPY_FSYNC_FULL : 0));
+ else
+ r = install_file(AT_FDCWD, i->settings_path,
+ AT_FDCWD, local_settings,
+ (i->flags & IMPORT_FORCE ? INSTALL_REPLACE : 0) |
+ (i->flags & IMPORT_SYNC ? INSTALL_SYNCFS : 0));
if (r == -EEXIST)
log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
else if (r == -ENOENT)
log_debug_errno(r, "Skipping creation of settings file, since none was found.");
else if (r < 0)
- log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings);
+ log_warning_errno(r, "Failed to install settings files %s, ignoring: %m", local_settings);
else
log_info("Created new settings file %s.", local_settings);
}
@@ -435,7 +449,7 @@ static void tar_pull_job_on_finished(PullJob *j) {
r = install_file(
AT_FDCWD, i->temp_path,
AT_FDCWD, i->final_path,
- INSTALL_READ_ONLY|
+ (i->flags & IMPORT_PULL_KEEP_DOWNLOAD ? INSTALL_READ_ONLY : 0) |
(i->flags & IMPORT_SYNC ? INSTALL_SYNCFS : 0));
if (r < 0) {
log_error_errno(r, "Failed to rename to final image name to %s: %m", i->final_path);
diff --git a/src/import/pull.c b/src/import/pull.c
index 19cfbe0d8d..d4ad0b2ea3 100644
--- a/src/import/pull.c
+++ b/src/import/pull.c
@@ -270,7 +270,9 @@ static int help(int argc, char *argv[], void *userdata) {
" --offset=BYTES Offset to seek to in 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",
+ " portable)\n"
+ " --keep-download=BOOL Keep a copy pristine copy of the downloaded file\n"
+ " around\n",
program_invocation_short_name,
ansi_underline(),
ansi_normal(),
@@ -300,6 +302,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_OFFSET,
ARG_SIZE_MAX,
ARG_CLASS,
+ ARG_KEEP_DOWNLOAD,
};
static const struct option options[] = {
@@ -321,11 +324,12 @@ static int parse_argv(int argc, char *argv[]) {
{ "offset", required_argument, NULL, ARG_OFFSET },
{ "size-max", required_argument, NULL, ARG_SIZE_MAX },
{ "class", required_argument, NULL, ARG_CLASS },
+ { "keep-download", required_argument, NULL, ARG_KEEP_DOWNLOAD },
{}
};
int c, r;
- bool auto_settings = true;
+ bool auto_settings = true, auto_keep_download = true;
assert(argc >= 0);
assert(argv);
@@ -492,6 +496,15 @@ static int parse_argv(int argc, char *argv[]) {
break;
+ case ARG_KEEP_DOWNLOAD:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --keep-download= argument: %s", optarg);
+
+ SET_FLAG(arg_import_flags, IMPORT_PULL_KEEP_DOWNLOAD, r);
+ auto_keep_download = false;
+ break;
+
case '?':
return -EINVAL;
@@ -518,6 +531,11 @@ static int parse_argv(int argc, char *argv[]) {
if (auto_settings && arg_class != IMAGE_MACHINE)
arg_import_flags &= ~IMPORT_PULL_SETTINGS;
+ /* Keep the original pristine downloaded file as a copy only when dealing with machine images,
+ * because unlike sysext/confext/portable they are typically modified during runtime. */
+ if (auto_keep_download)
+ SET_FLAG(arg_import_flags, IMPORT_PULL_KEEP_DOWNLOAD, arg_class == IMAGE_MACHINE);
+
return 1;
}