static bool arg_btrfs_quota = true;
static bool arg_sync = true;
static bool arg_direct = false;
-static const char *arg_image_root = NULL;
+static char *arg_image_root = NULL;
static ImageClass arg_class = IMAGE_MACHINE;
static RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
+STATIC_DESTRUCTOR_REGISTER(arg_image_root, freep);
+
typedef struct ProgressInfo {
RateLimit limit;
char *path;
break;
case ARG_IMAGE_ROOT:
- arg_image_root = optarg;
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image_root);
+ if (r < 0)
+ return r;
+
break;
case ARG_READ_ONLY:
assert_not_reached();
}
- if (!arg_image_root)
- arg_image_root = image_root_to_string(arg_class);
+ if (!arg_image_root) {
+ r = image_root_pick(arg_runtime_scope < 0 ? RUNTIME_SCOPE_SYSTEM : arg_runtime_scope, arg_class, /* runtime= */ false, &arg_image_root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to pick image root: %m");
+ }
return 1;
}
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
+#include "runtime-scope.h"
#include "specifier.h"
#include "string-util.h"
#include "unit-name.h"
if (!GREEDY_REALLOC(arg_transfers, arg_n_transfers + 1))
return log_oom();
- const char *image_root = runtime ? image_root_runtime_to_string(class) : image_root_to_string(class);
+ _cleanup_free_ char *image_root = NULL;
+ r = image_root_pick(RUNTIME_SCOPE_SYSTEM, class, runtime, &image_root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to pick image root: %m");
_cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL;
r = sd_json_buildo(
.type = type,
.local = TAKE_PTR(local),
.remote = TAKE_PTR(remote),
- .image_root = image_root,
+ .image_root = TAKE_PTR(image_root),
.json = TAKE_PTR(j),
.blockdev = blockdev,
};
#include "string-util.h"
#include "verbs.h"
-static const char *arg_image_root = NULL;
+static 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 RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
+STATIC_DESTRUCTOR_REGISTER(arg_image_root, freep);
+
static int normalize_local(const char *local, char **ret) {
_cleanup_free_ char *ll = NULL;
int r;
break;
case ARG_IMAGE_ROOT:
- arg_image_root = optarg;
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image_root);
+ if (r < 0)
+ return r;
+
break;
case ARG_READ_ONLY:
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);
+ if (!arg_image_root) {
+ r = image_root_pick(arg_runtime_scope < 0 ? RUNTIME_SCOPE_SYSTEM : arg_runtime_scope, arg_class, /* runtime= */ false, &arg_image_root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to pick image root: %m");
+ }
return 1;
}
#define PROGRESS_PREFIX "Total:"
static int settle_image_class(void) {
+ int r;
if (arg_image_class < 0) {
_cleanup_free_ char *j = NULL;
- for (ImageClass class = 0; class < _IMAGE_CLASS_MAX; class++)
+ for (ImageClass class = 0; class < _IMAGE_CLASS_MAX; class++) {
+ _cleanup_free_ char *root = NULL;
+
+ r = image_root_pick(arg_runtime_scope, class, /* runtime= */ false, &root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to pick image root: %m");
+
if (strextendf_with_separator(&j, ", ", "%s (downloads to %s/)",
image_class_to_string(class),
- image_root_to_string(class)) < 0)
+ root) < 0)
return log_oom();
+ }
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No image class specified, retry with --class= set to one of: %s.", j);
#include "verbs.h"
#include "web-util.h"
-static const char *arg_image_root = NULL;
+static 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 RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
STATIC_DESTRUCTOR_REGISTER(arg_checksum, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image_root, freep);
static int normalize_local(const char *local, const char *url, char **ret) {
_cleanup_free_ char *ll = NULL;
break;
case ARG_IMAGE_ROOT:
- arg_image_root = optarg;
+ r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image_root);
+ if (r < 0)
+ return r;
+
break;
case ARG_VERIFY: {
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);
+ if (!arg_image_root) {
+ r = image_root_pick(arg_runtime_scope < 0 ? RUNTIME_SCOPE_SYSTEM : arg_runtime_scope, arg_class, /* runtime= */ false, &arg_image_root);
+ if (r < 0)
+ return log_error_errno(r, "Failed to pick image root: %m");
+ }
/* .nspawn settings files only really make sense for machine images, not for sysext/confext/portable */
if (auto_settings && arg_class != IMAGE_MACHINE)
[IMAGE_CONFEXT] = "/var/lib/confexts",
};
-DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root, ImageClass);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(image_root, ImageClass);
static const char *const image_root_runtime_table[_IMAGE_CLASS_MAX] = {
[IMAGE_MACHINE] = "/run/machines",
[IMAGE_CONFEXT] = "/run/confexts",
};
-DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root_runtime, ImageClass);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(image_root_runtime, ImageClass);
static const char *const image_dirname_table[_IMAGE_CLASS_MAX] = {
[IMAGE_MACHINE] = "machines",
};
DEFINE_STRING_TABLE_LOOKUP(image_type, ImageType);
+
+int image_root_pick(
+ RuntimeScope scope,
+ ImageClass c,
+ bool runtime,
+ char **ret) {
+
+ int r;
+
+ assert(scope >= 0);
+ assert(scope < _RUNTIME_SCOPE_MAX);
+ assert(c >= 0);
+ assert(c < _IMAGE_CLASS_MAX);
+ assert(ret);
+
+ /* Picks the primary target directory for downloads, depending on invocation contexts */
+
+ _cleanup_free_ char *s = NULL;
+ switch (scope) {
+
+ case RUNTIME_SCOPE_SYSTEM: {
+ s = strdup(runtime ? image_root_runtime_to_string(c) : image_root_to_string(c));
+ if (!s)
+ return -ENOMEM;
+
+ break;
+ }
+
+ case RUNTIME_SCOPE_USER:
+ r = sd_path_lookup(runtime ? SD_PATH_USER_RUNTIME : SD_PATH_USER_STATE_PRIVATE, "machines", &s);
+ if (r < 0)
+ return r;
+
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ *ret = TAKE_PTR(s);
+ return 0;
+}
int image_to_json(const struct Image *i, sd_json_variant **ret);
-const char* image_root_to_string(ImageClass c) _const_;
-const char* image_root_runtime_to_string(ImageClass c) _const_;
+int image_root_pick(RuntimeScope scope, ImageClass c, bool runtime, char **ret);
extern const struct hash_ops image_hash_ops;