mirror of
https://github.com/systemd/systemd.git
synced 2025-02-04 21:47:31 +03:00
Merge pull request #29525 from poettering/confext-sysext-multimodal
dissect: make sure we can dissect and inspect DDIs that are both confext *and* sysext
This commit is contained in:
commit
0e3986bc1c
@ -10,7 +10,9 @@ typedef enum ImageClass {
|
||||
IMAGE_MACHINE,
|
||||
IMAGE_PORTABLE,
|
||||
IMAGE_SYSEXT,
|
||||
_IMAGE_CLASS_EXTENSION_FIRST = IMAGE_SYSEXT, /* First "extension" image type, so that we can easily generically iterate through them */
|
||||
IMAGE_CONFEXT,
|
||||
_IMAGE_CLASS_EXTENSION_LAST = IMAGE_CONFEXT, /* Last "extension image type */
|
||||
_IMAGE_CLASS_MAX,
|
||||
_IMAGE_CLASS_INVALID = -EINVAL,
|
||||
} ImageClass;
|
||||
|
@ -755,23 +755,6 @@ static int parse_argv_as_mount_helper(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int strv_pair_to_json(char **l, JsonVariant **ret) {
|
||||
_cleanup_strv_free_ char **jl = NULL;
|
||||
|
||||
STRV_FOREACH_PAIR(a, b, l) {
|
||||
char *j;
|
||||
|
||||
j = strjoin(*a, "=", *b);
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
if (strv_consume(&jl, j) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return json_variant_new_array_strv(ret, jl);
|
||||
}
|
||||
|
||||
static void strv_pair_print(char **l, const char *prefix) {
|
||||
assert(prefix);
|
||||
|
||||
@ -782,24 +765,40 @@ static void strv_pair_print(char **l, const char *prefix) {
|
||||
printf("%*s %s=%s\n", (int) strlen(prefix), "", *p, *q);
|
||||
}
|
||||
|
||||
static int get_extension_scopes(DissectedImage *m, char ***ret_scopes) {
|
||||
static int get_extension_scopes(DissectedImage *m, ImageClass class, char ***ret_scopes) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
const char *e;
|
||||
const char *e, *field_name;
|
||||
char **release_data;
|
||||
|
||||
assert(m);
|
||||
assert(ret_scopes);
|
||||
|
||||
switch (class) {
|
||||
|
||||
case IMAGE_SYSEXT:
|
||||
release_data = m->sysext_release;
|
||||
field_name = "SYSEXT_SCOPE";
|
||||
break;
|
||||
|
||||
case IMAGE_CONFEXT:
|
||||
release_data = m->confext_release;
|
||||
field_name = "CONFEXT_SCOPE";
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If there's no extension-release file its not a system extension. Otherwise the SYSEXT_SCOPE
|
||||
* field for sysext images and the CONFEXT_SCOPE field for confext images indicates which scope
|
||||
* it is for — and it defaults to "system" + "portable" if unset. */
|
||||
if (!m->extension_release) {
|
||||
|
||||
if (!release_data) {
|
||||
*ret_scopes = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
e = strv_env_pairs_get(m->extension_release, "SYSEXT_SCOPE");
|
||||
if (!e)
|
||||
e = strv_env_pairs_get(m->extension_release, "CONFEXT_SCOPE");
|
||||
e = strv_env_pairs_get(release_data, field_name);
|
||||
if (e)
|
||||
l = strv_split(e, WHITESPACE);
|
||||
else
|
||||
@ -860,7 +859,6 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire image metadata: %m");
|
||||
else if (arg_json_format_flags & JSON_FORMAT_OFF) {
|
||||
_cleanup_strv_free_ char **extension_scopes = NULL;
|
||||
|
||||
if (!sd_id128_is_null(m->image_uuid))
|
||||
printf("Image UUID: %s\n", SD_ID128_TO_UUID_STRING(m->image_uuid));
|
||||
@ -877,91 +875,82 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
|
||||
"OS Release:");
|
||||
strv_pair_print(m->initrd_release,
|
||||
"initrd R.:");
|
||||
strv_pair_print(m->extension_release,
|
||||
" Ext. Rel.:");
|
||||
strv_pair_print(m->sysext_release,
|
||||
" sysext R.:");
|
||||
strv_pair_print(m->confext_release,
|
||||
"confext R.:");
|
||||
|
||||
if (m->hostname ||
|
||||
!sd_id128_is_null(m->machine_id) ||
|
||||
!strv_isempty(m->machine_info) ||
|
||||
!strv_isempty(m->os_release) ||
|
||||
!strv_isempty(m->initrd_release) ||
|
||||
!strv_isempty(m->extension_release))
|
||||
!strv_isempty(m->sysext_release) ||
|
||||
!strv_isempty(m->confext_release))
|
||||
putc('\n', stdout);
|
||||
|
||||
printf(" Use As: %s bootable system for UEFI\n", COLOR_MARK_BOOL(m->partitions[PARTITION_ESP].found));
|
||||
|
||||
if (m->has_init_system >= 0)
|
||||
printf(" %s bootable system for container\n", COLOR_MARK_BOOL(m->has_init_system));
|
||||
|
||||
printf(" Use As: %s bootable system for UEFI\n",
|
||||
COLOR_MARK_BOOL(dissected_image_is_bootable_uefi(m)));
|
||||
printf(" %s bootable system for container\n",
|
||||
COLOR_MARK_BOOL(dissected_image_is_bootable_os(m)));
|
||||
printf(" %s portable service\n",
|
||||
COLOR_MARK_BOOL(strv_env_pairs_get(m->os_release, "PORTABLE_PREFIXES")));
|
||||
COLOR_MARK_BOOL(dissected_image_is_portable(m)));
|
||||
printf(" %s initrd\n",
|
||||
COLOR_MARK_BOOL(!strv_isempty(m->initrd_release)));
|
||||
COLOR_MARK_BOOL(dissected_image_is_initrd(m)));
|
||||
|
||||
r = get_extension_scopes(m, &extension_scopes);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse scope: %m");
|
||||
for (ImageClass c = _IMAGE_CLASS_EXTENSION_FIRST; c <= _IMAGE_CLASS_EXTENSION_LAST; c++) {
|
||||
const char *string_class = image_class_to_string(c);
|
||||
_cleanup_strv_free_ char **extension_scopes = NULL;
|
||||
|
||||
const char *string_class = image_class_to_string(m->image_class);
|
||||
printf(" %s %s extension for system\n",
|
||||
COLOR_MARK_BOOL(strv_contains(extension_scopes, "system")), string_class);
|
||||
printf(" %s %s extension for initrd\n",
|
||||
COLOR_MARK_BOOL(strv_contains(extension_scopes, "initrd")), string_class);
|
||||
printf(" %s %s extension for portable service\n",
|
||||
COLOR_MARK_BOOL(strv_contains(extension_scopes, "portable")), string_class);
|
||||
r = get_extension_scopes(m, c, &extension_scopes);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse scopes: %m");
|
||||
|
||||
printf(" %s %s for system\n",
|
||||
COLOR_MARK_BOOL(strv_contains(extension_scopes, "system")), string_class);
|
||||
printf(" %s %s for portable service\n",
|
||||
COLOR_MARK_BOOL(strv_contains(extension_scopes, "portable")), string_class);
|
||||
printf(" %s %s for initrd\n",
|
||||
COLOR_MARK_BOOL(strv_contains(extension_scopes, "initrd")), string_class);
|
||||
}
|
||||
|
||||
putc('\n', stdout);
|
||||
} else {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL, *irdr = NULL, *exr = NULL;
|
||||
_cleanup_strv_free_ char **extension_scopes = NULL;
|
||||
_cleanup_strv_free_ char **sysext_scopes = NULL, **confext_scopes = NULL;
|
||||
|
||||
if (!strv_isempty(m->machine_info)) {
|
||||
r = strv_pair_to_json(m->machine_info, &mi);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (!strv_isempty(m->os_release)) {
|
||||
r = strv_pair_to_json(m->os_release, &osr);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (!strv_isempty(m->initrd_release)) {
|
||||
r = strv_pair_to_json(m->initrd_release, &irdr);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (!strv_isempty(m->extension_release)) {
|
||||
r = strv_pair_to_json(m->extension_release, &exr);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = get_extension_scopes(m, &extension_scopes);
|
||||
r = get_extension_scopes(m, IMAGE_SYSEXT, &sysext_scopes);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse scope: %m");
|
||||
return log_error_errno(r, "Failed to parse sysext scopes: %m");
|
||||
|
||||
r = get_extension_scopes(m, IMAGE_CONFEXT, &confext_scopes);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse confext scopes: %m");
|
||||
|
||||
Architecture a = dissected_image_architecture(m);
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(bn)),
|
||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(m->image_uuid), "imageUuid", JSON_BUILD_UUID(m->image_uuid)),
|
||||
JSON_BUILD_PAIR("size", JSON_BUILD_INTEGER(size)),
|
||||
JSON_BUILD_PAIR_CONDITION(size != UINT64_MAX, "size", JSON_BUILD_INTEGER(size)),
|
||||
JSON_BUILD_PAIR("sectorSize", JSON_BUILD_INTEGER(m->sector_size)),
|
||||
JSON_BUILD_PAIR_CONDITION(a >= 0, "architecture", JSON_BUILD_STRING(architecture_to_string(a))),
|
||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(m->image_uuid), "imageUuid", JSON_BUILD_UUID(m->image_uuid)),
|
||||
JSON_BUILD_PAIR_CONDITION(m->hostname, "hostname", JSON_BUILD_STRING(m->hostname)),
|
||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(m->machine_id), "machineId", JSON_BUILD_ID128(m->machine_id)),
|
||||
JSON_BUILD_PAIR_CONDITION(mi, "machineInfo", JSON_BUILD_VARIANT(mi)),
|
||||
JSON_BUILD_PAIR_CONDITION(osr, "osRelease", JSON_BUILD_VARIANT(osr)),
|
||||
JSON_BUILD_PAIR_CONDITION(osr, "initrdRelease", JSON_BUILD_VARIANT(irdr)),
|
||||
JSON_BUILD_PAIR_CONDITION(exr, "extensionRelease", JSON_BUILD_VARIANT(exr)),
|
||||
JSON_BUILD_PAIR("useBootableUefi", JSON_BUILD_BOOLEAN(m->partitions[PARTITION_ESP].found)),
|
||||
JSON_BUILD_PAIR_CONDITION(m->has_init_system >= 0, "useBootableContainer", JSON_BUILD_BOOLEAN(m->has_init_system)),
|
||||
JSON_BUILD_PAIR("useInitrd", JSON_BUILD_BOOLEAN(!strv_isempty(m->initrd_release))),
|
||||
JSON_BUILD_PAIR("usePortableService", JSON_BUILD_BOOLEAN(strv_env_pairs_get(m->os_release, "PORTABLE_MATCHES"))),
|
||||
JSON_BUILD_PAIR("ExtensionType", JSON_BUILD_STRING(image_class_to_string(m->image_class))),
|
||||
JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "system"))),
|
||||
JSON_BUILD_PAIR("useInitRDExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "initrd"))),
|
||||
JSON_BUILD_PAIR("usePortableExtension", JSON_BUILD_BOOLEAN(strv_contains(extension_scopes, "portable")))));
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->machine_info), "machineInfo", JSON_BUILD_STRV_ENV_PAIR(m->machine_info)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->os_release), "osRelease", JSON_BUILD_STRV_ENV_PAIR(m->os_release)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->initrd_release), "initrdRelease", JSON_BUILD_STRV_ENV_PAIR(m->initrd_release)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->sysext_release), "sysextRelease", JSON_BUILD_STRV_ENV_PAIR(m->sysext_release)),
|
||||
JSON_BUILD_PAIR_CONDITION(!strv_isempty(m->confext_release), "confextRelease", JSON_BUILD_STRV_ENV_PAIR(m->confext_release)),
|
||||
JSON_BUILD_PAIR("useBootableUefi", JSON_BUILD_BOOLEAN(dissected_image_is_bootable_uefi(m))),
|
||||
JSON_BUILD_PAIR("useBootableContainer", JSON_BUILD_BOOLEAN(dissected_image_is_bootable_os(m))),
|
||||
JSON_BUILD_PAIR("useInitrd", JSON_BUILD_BOOLEAN(dissected_image_is_initrd(m))),
|
||||
JSON_BUILD_PAIR("usePortableService", JSON_BUILD_BOOLEAN(dissected_image_is_portable(m))),
|
||||
JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "system"))),
|
||||
JSON_BUILD_PAIR("useInitRDSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "initrd"))),
|
||||
JSON_BUILD_PAIR("usePortableSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "portable"))),
|
||||
JSON_BUILD_PAIR("useConfigurationExtension", JSON_BUILD_BOOLEAN(strv_contains(confext_scopes, "system"))),
|
||||
JSON_BUILD_PAIR("useInitRDConfigurationExtension", JSON_BUILD_BOOLEAN(strv_contains(confext_scopes, "initrd"))),
|
||||
JSON_BUILD_PAIR("usePortableConfigurationExtension", JSON_BUILD_BOOLEAN(strv_contains(confext_scopes, "portable")))));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
@ -101,7 +101,8 @@ static Image *image_free(Image *i) {
|
||||
free(i->hostname);
|
||||
strv_free(i->machine_info);
|
||||
strv_free(i->os_release);
|
||||
strv_free(i->extension_release);
|
||||
strv_free(i->sysext_release);
|
||||
strv_free(i->confext_release);
|
||||
|
||||
return mfree(i);
|
||||
}
|
||||
@ -1180,10 +1181,9 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
||||
|
||||
case IMAGE_SUBVOLUME:
|
||||
case IMAGE_DIRECTORY: {
|
||||
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **extension_release = NULL;
|
||||
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **sysext_release = NULL, **confext_release = NULL;
|
||||
_cleanup_free_ char *hostname = NULL, *path = NULL;
|
||||
sd_id128_t machine_id = SD_ID128_NULL;
|
||||
_cleanup_free_ char *hostname = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
if (i->class == IMAGE_SYSEXT) {
|
||||
r = extension_has_forbidden_content(i->path);
|
||||
@ -1223,16 +1223,20 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read os-release in image, ignoring: %m");
|
||||
|
||||
r = load_extension_release_pairs(i->path, i->class, i->name, /* relax_extension_release_check= */ false, &extension_release);
|
||||
r = load_extension_release_pairs(i->path, IMAGE_SYSEXT, i->name, /* relax_extension_release_check= */ false, &sysext_release);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read extension-release in image, ignoring: %m");
|
||||
log_debug_errno(r, "Failed to read sysext-release in image, ignoring: %m");
|
||||
|
||||
r = load_extension_release_pairs(i->path, IMAGE_CONFEXT, i->name, /* relax_extension_release_check= */ false, &confext_release);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read confext-release in image, ignoring: %m");
|
||||
|
||||
free_and_replace(i->hostname, hostname);
|
||||
i->machine_id = machine_id;
|
||||
strv_free_and_replace(i->machine_info, machine_info);
|
||||
strv_free_and_replace(i->os_release, os_release);
|
||||
strv_free_and_replace(i->extension_release, extension_release);
|
||||
|
||||
strv_free_and_replace(i->sysext_release, sysext_release);
|
||||
strv_free_and_replace(i->confext_release, confext_release);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1271,7 +1275,8 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
||||
i->machine_id = m->machine_id;
|
||||
strv_free_and_replace(i->machine_info, m->machine_info);
|
||||
strv_free_and_replace(i->os_release, m->os_release);
|
||||
strv_free_and_replace(i->extension_release, m->extension_release);
|
||||
strv_free_and_replace(i->sysext_release, m->sysext_release);
|
||||
strv_free_and_replace(i->confext_release, m->confext_release);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -45,7 +45,8 @@ typedef struct Image {
|
||||
sd_id128_t machine_id;
|
||||
char **machine_info;
|
||||
char **os_release;
|
||||
char **extension_release;
|
||||
char **sysext_release;
|
||||
char **confext_release;
|
||||
|
||||
bool metadata_valid:1;
|
||||
bool discoverable:1; /* true if we know for sure that image_find() would find the image given just the short name */
|
||||
@ -80,6 +81,17 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy);
|
||||
|
||||
bool image_in_search_path(ImageClass class, const char *root, const char *image);
|
||||
|
||||
static inline char **image_extension_release(Image *image, ImageClass class) {
|
||||
assert(image);
|
||||
|
||||
if (class == IMAGE_SYSEXT)
|
||||
return image->sysext_release;
|
||||
if (class == IMAGE_CONFEXT)
|
||||
return image->confext_release;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool IMAGE_IS_HIDDEN(const struct Image *i) {
|
||||
assert(i);
|
||||
|
||||
|
@ -1665,7 +1665,8 @@ DissectedImage* dissected_image_unref(DissectedImage *m) {
|
||||
strv_free(m->machine_info);
|
||||
strv_free(m->os_release);
|
||||
strv_free(m->initrd_release);
|
||||
strv_free(m->extension_release);
|
||||
strv_free(m->confext_release);
|
||||
strv_free(m->sysext_release);
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
@ -3352,7 +3353,8 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
META_MACHINE_INFO,
|
||||
META_OS_RELEASE,
|
||||
META_INITRD_RELEASE,
|
||||
META_EXTENSION_RELEASE,
|
||||
META_SYSEXT_RELEASE,
|
||||
META_CONFEXT_RELEASE,
|
||||
META_HAS_INIT_SYSTEM,
|
||||
_META_MAX,
|
||||
};
|
||||
@ -3361,15 +3363,16 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
[META_HOSTNAME] = "/etc/hostname\0",
|
||||
[META_MACHINE_ID] = "/etc/machine-id\0",
|
||||
[META_MACHINE_INFO] = "/etc/machine-info\0",
|
||||
[META_OS_RELEASE] = ("/etc/os-release\0"
|
||||
"/usr/lib/os-release\0"),
|
||||
[META_INITRD_RELEASE] = ("/etc/initrd-release\0"
|
||||
"/usr/lib/initrd-release\0"),
|
||||
[META_EXTENSION_RELEASE] = "extension-release\0", /* Used only for logging. */
|
||||
[META_OS_RELEASE] = "/etc/os-release\0"
|
||||
"/usr/lib/os-release\0",
|
||||
[META_INITRD_RELEASE] = "/etc/initrd-release\0"
|
||||
"/usr/lib/initrd-release\0",
|
||||
[META_SYSEXT_RELEASE] = "sysext-release\0", /* String used only for logging. */
|
||||
[META_CONFEXT_RELEASE] = "confext-release\0", /* ditto */
|
||||
[META_HAS_INIT_SYSTEM] = "has-init-system\0", /* ditto */
|
||||
};
|
||||
|
||||
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **extension_release = NULL;
|
||||
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL;
|
||||
_cleanup_close_pair_ int error_pipe[2] = PIPE_EBADF;
|
||||
_cleanup_(rmdir_and_freep) char *t = NULL;
|
||||
_cleanup_(sigkill_waitp) pid_t child = 0;
|
||||
@ -3379,12 +3382,10 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
int fds[2 * _META_MAX], r, v;
|
||||
int has_init_system = -1;
|
||||
ssize_t n;
|
||||
ImageClass image_class = IMAGE_SYSEXT;
|
||||
|
||||
BLOCK_SIGNALS(SIGCHLD);
|
||||
|
||||
assert(m);
|
||||
assert(image_class);
|
||||
|
||||
for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) {
|
||||
if (!paths[n_meta_initialized]) {
|
||||
@ -3439,40 +3440,46 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
|
||||
switch (k) {
|
||||
|
||||
case META_EXTENSION_RELEASE: {
|
||||
/* As per the os-release spec, if the image is an extension it will have a file
|
||||
* named after the image name in extension-release.d/ - we use the image name
|
||||
* and try to resolve it with the extension-release helpers, as sometimes
|
||||
* the image names are mangled on deployment and do not match anymore.
|
||||
* Unlike other paths this is not fixed, and the image name
|
||||
* can be mangled on deployment, so by calling into the helper
|
||||
* we allow a fallback that matches on the first extension-release
|
||||
* file found in the directory, if one named after the image cannot
|
||||
* be found first. */
|
||||
ImageClass class = IMAGE_SYSEXT;
|
||||
r = open_extension_release(t, IMAGE_SYSEXT, m->image_name, /* relax_extension_release_check= */ false, NULL, &fd);
|
||||
if (r == -ENOENT) {
|
||||
r = open_extension_release(t, IMAGE_CONFEXT, m->image_name, /* relax_extension_release_check= */ false, NULL, &fd);
|
||||
if (r >= 0)
|
||||
class = IMAGE_CONFEXT;
|
||||
}
|
||||
case META_SYSEXT_RELEASE:
|
||||
/* As per the os-release spec, if the image is an extension it will have a
|
||||
* file named after the image name in extension-release.d/ - we use the image
|
||||
* name and try to resolve it with the extension-release helpers, as
|
||||
* sometimes the image names are mangled on deployment and do not match
|
||||
* anymore. Unlike other paths this is not fixed, and the image name can be
|
||||
* mangled on deployment, so by calling into the helper we allow a fallback
|
||||
* that matches on the first extension-release file found in the directory,
|
||||
* if one named after the image cannot be found first. */
|
||||
r = open_extension_release(
|
||||
t,
|
||||
IMAGE_SYSEXT,
|
||||
m->image_name,
|
||||
/* relax_extension_release_check= */ false,
|
||||
/* ret_path= */ NULL,
|
||||
&fd);
|
||||
if (r < 0)
|
||||
fd = r;
|
||||
break;
|
||||
|
||||
case META_CONFEXT_RELEASE:
|
||||
/* As above */
|
||||
r = open_extension_release(
|
||||
t,
|
||||
IMAGE_CONFEXT,
|
||||
m->image_name,
|
||||
/* relax_extension_release_check= */ false,
|
||||
/* ret_path= */ NULL,
|
||||
&fd);
|
||||
if (r < 0)
|
||||
fd = r;
|
||||
else {
|
||||
r = loop_write(fds[2*k+1], &class, sizeof(class));
|
||||
if (r < 0)
|
||||
goto inner_fail; /* Propagate the error to the parent */
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case META_HAS_INIT_SYSTEM: {
|
||||
bool found = false;
|
||||
|
||||
FOREACH_STRING(init,
|
||||
"/usr/lib/systemd/systemd", /* systemd on /usr merged system */
|
||||
"/lib/systemd/systemd", /* systemd on /usr non-merged systems */
|
||||
"/usr/lib/systemd/systemd", /* systemd on /usr/ merged system */
|
||||
"/lib/systemd/systemd", /* systemd on /usr/ non-merged systems */
|
||||
"/sbin/init") { /* traditional path the Linux kernel invokes */
|
||||
|
||||
r = chase(init, t, CHASE_PREFIX_ROOT, NULL, NULL);
|
||||
@ -3587,23 +3594,19 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
|
||||
break;
|
||||
|
||||
case META_EXTENSION_RELEASE: {
|
||||
ImageClass cl = IMAGE_SYSEXT;
|
||||
size_t nr;
|
||||
|
||||
errno = 0;
|
||||
nr = fread(&cl, 1, sizeof(cl), f);
|
||||
if (nr != sizeof(cl))
|
||||
log_debug_errno(errno_or_else(EIO), "Failed to read class of extension image: %m");
|
||||
else {
|
||||
image_class = cl;
|
||||
r = load_env_file_pairs(f, "extension-release", &extension_release);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read extension release file of image: %m");
|
||||
}
|
||||
case META_SYSEXT_RELEASE:
|
||||
r = load_env_file_pairs(f, "sysext-release", &sysext_release);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read sysext release file of image: %m");
|
||||
|
||||
break;
|
||||
|
||||
case META_CONFEXT_RELEASE:
|
||||
r = load_env_file_pairs(f, "confext-release", &confext_release);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read confext release file of image: %m");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case META_HAS_INIT_SYSTEM: {
|
||||
bool b = false;
|
||||
@ -3641,9 +3644,9 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
strv_free_and_replace(m->machine_info, machine_info);
|
||||
strv_free_and_replace(m->os_release, os_release);
|
||||
strv_free_and_replace(m->initrd_release, initrd_release);
|
||||
strv_free_and_replace(m->extension_release, extension_release);
|
||||
strv_free_and_replace(m->sysext_release, sysext_release);
|
||||
strv_free_and_replace(m->confext_release, confext_release);
|
||||
m->has_init_system = has_init_system;
|
||||
m->image_class = image_class;
|
||||
|
||||
finish:
|
||||
for (unsigned k = 0; k < n_meta_initialized; k++)
|
||||
|
@ -6,11 +6,13 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "architecture.h"
|
||||
#include "env-util.h"
|
||||
#include "gpt.h"
|
||||
#include "list.h"
|
||||
#include "loop-util.h"
|
||||
#include "macro.h"
|
||||
#include "os-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
typedef struct DissectedImage DissectedImage;
|
||||
typedef struct DissectedPartition DissectedPartition;
|
||||
@ -108,9 +110,9 @@ struct DissectedImage {
|
||||
char **machine_info;
|
||||
char **os_release;
|
||||
char **initrd_release;
|
||||
char **extension_release;
|
||||
char **confext_release;
|
||||
char **sysext_release;
|
||||
int has_init_system;
|
||||
ImageClass image_class;
|
||||
};
|
||||
|
||||
struct MountOptions {
|
||||
@ -169,6 +171,22 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
|
||||
|
||||
Architecture dissected_image_architecture(DissectedImage *m);
|
||||
|
||||
static inline bool dissected_image_is_bootable_os(DissectedImage *m) {
|
||||
return m && m->has_init_system > 0;
|
||||
}
|
||||
|
||||
static inline bool dissected_image_is_bootable_uefi(DissectedImage *m) {
|
||||
return m && m->partitions[PARTITION_ESP].found && dissected_image_is_bootable_os(m);
|
||||
}
|
||||
|
||||
static inline bool dissected_image_is_portable(DissectedImage *m) {
|
||||
return m && strv_env_pairs_get(m->os_release, "PORTABLE_PREFIXES");
|
||||
}
|
||||
|
||||
static inline bool dissected_image_is_initrd(DissectedImage *m) {
|
||||
return m && !strv_isempty(m->initrd_release);
|
||||
}
|
||||
|
||||
DecryptedImage* decrypted_image_ref(DecryptedImage *p);
|
||||
DecryptedImage* decrypted_image_unref(DecryptedImage *p);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref);
|
||||
|
@ -3709,6 +3709,49 @@ int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_STRV_ENV_PAIR: {
|
||||
char **l;
|
||||
|
||||
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
l = va_arg(ap, char **);
|
||||
|
||||
_cleanup_strv_free_ char **el = NULL;
|
||||
STRV_FOREACH_PAIR(x, y, l) {
|
||||
char *n = NULL;
|
||||
|
||||
n = strjoin(*x, "=", *y);
|
||||
if (!n) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = strv_consume(&el, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (current->n_suppress == 0) {
|
||||
r = json_variant_new_array_strv(&add, el);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 1;
|
||||
|
||||
if (current->expect == EXPECT_TOPLEVEL)
|
||||
current->expect = EXPECT_END;
|
||||
else if (current->expect == EXPECT_OBJECT_VALUE)
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
else
|
||||
assert(current->expect == EXPECT_ARRAY_ELEMENT);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_BASE64:
|
||||
case _JSON_BUILD_BASE32HEX:
|
||||
case _JSON_BUILD_HEX:
|
||||
|
@ -266,6 +266,7 @@ enum {
|
||||
_JSON_BUILD_VARIANT_ARRAY,
|
||||
_JSON_BUILD_LITERAL,
|
||||
_JSON_BUILD_STRV,
|
||||
_JSON_BUILD_STRV_ENV_PAIR,
|
||||
_JSON_BUILD_BASE64,
|
||||
_JSON_BUILD_BASE32HEX,
|
||||
_JSON_BUILD_HEX,
|
||||
@ -304,6 +305,7 @@ enum {
|
||||
#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, (JsonVariant **) { v }, (size_t) { n }
|
||||
#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, (const char*) { l }
|
||||
#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, (char**) { l }
|
||||
#define JSON_BUILD_STRV_ENV_PAIR(l) _JSON_BUILD_STRV_ENV_PAIR, (char**) { l }
|
||||
#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, (const void*) { p }, (size_t) { n }
|
||||
#define JSON_BUILD_BASE32HEX(p, n) _JSON_BUILD_BASE32HEX, (const void*) { p }, (size_t) { n }
|
||||
#define JSON_BUILD_HEX(p, n) _JSON_BUILD_HEX, (const void*) { p }, (size_t) { n }
|
||||
|
@ -741,7 +741,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
host_os_release_version_id,
|
||||
host_os_release_api_level,
|
||||
in_initrd() ? "initrd" : "system",
|
||||
img->extension_release,
|
||||
image_extension_release(img, arg_image_class),
|
||||
arg_image_class);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -31,8 +31,8 @@ fi
|
||||
|
||||
systemd-dissect --no-pager /usr/share/minimal_0.raw | grep -q '✓ portable service'
|
||||
systemd-dissect --no-pager /usr/share/minimal_1.raw | grep -q '✓ portable service'
|
||||
systemd-dissect --no-pager /usr/share/app0.raw | grep -q '✓ sysext extension for portable service'
|
||||
systemd-dissect --no-pager /usr/share/app1.raw | grep -q '✓ sysext extension for portable service'
|
||||
systemd-dissect --no-pager /usr/share/app0.raw | grep -q '✓ sysext for portable service'
|
||||
systemd-dissect --no-pager /usr/share/app1.raw | grep -q '✓ sysext for portable service'
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
mkdir -p /run/systemd/system/systemd-portabled.service.d/
|
||||
|
@ -573,8 +573,8 @@ echo "MARKER_SYSEXT_123" >testkit/usr/lib/testfile
|
||||
mksquashfs testkit/ testkit.raw
|
||||
cp testkit.raw /run/extensions/
|
||||
unsquashfs -l /run/extensions/testkit.raw
|
||||
systemd-dissect --no-pager /run/extensions/testkit.raw | grep -q '✓ sysext extension for portable service'
|
||||
systemd-dissect --no-pager /run/extensions/testkit.raw | grep -q '✓ sysext extension for system'
|
||||
systemd-dissect --no-pager /run/extensions/testkit.raw | grep -q '✓ sysext for portable service'
|
||||
systemd-dissect --no-pager /run/extensions/testkit.raw | grep -q '✓ sysext for system'
|
||||
systemd-sysext merge
|
||||
systemd-sysext status
|
||||
grep -q -F "MARKER_SYSEXT_123" /usr/lib/testfile
|
||||
@ -589,8 +589,8 @@ echo "MARKER_CONFEXT_123" >testjob/etc/testfile
|
||||
mksquashfs testjob/ testjob.raw
|
||||
cp testjob.raw /run/confexts/
|
||||
unsquashfs -l /run/confexts/testjob.raw
|
||||
systemd-dissect --no-pager /run/confexts/testjob.raw | grep -q '✓ confext extension for system'
|
||||
systemd-dissect --no-pager /run/confexts/testjob.raw | grep -q '✓ confext extension for portable service'
|
||||
systemd-dissect --no-pager /run/confexts/testjob.raw | grep -q '✓ confext for system'
|
||||
systemd-dissect --no-pager /run/confexts/testjob.raw | grep -q '✓ confext for portable service'
|
||||
systemd-confext merge
|
||||
systemd-confext status
|
||||
grep -q -F "MARKER_CONFEXT_123" /etc/testfile
|
||||
|
Loading…
x
Reference in New Issue
Block a user