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; - tp = TAKE_PTR(f); + r = tempfn_random(p, NULL, &f); + if (r < 0) + return log_oom(); - /* 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); + 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"); - 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"); + tp = TAKE_PTR(f); - (void) copy_times(i->raw_job->disk_fd, dfd, COPY_CRTIME); - (void) copy_xattr(i->raw_job->disk_fd, NULL, dfd, NULL, 0); + /* 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); - dfd = safe_close(dfd); + 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"); - r = install_file(AT_FDCWD, tp, + (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); + + source = tp; + } else + source = i->final_path; + + 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"); - r = install_file(AT_FDCWD, t, + source = t; + } else + source = i->final_path; + + 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; }