From 994c9c70a166c5e5c383cf651b6cb4077e8f183e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Nov 2021 16:20:00 +0100 Subject: dissect: show intended purpose of images in dissection output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this the tool will show whether an image is intended to be a bootable OS image, a system extension, or a portable service image. Example output with this patch: Name: image_53.raw Size: 3.2G Machine ID: bb9f2921198040feb7c82270bf66e4b8 OS Release: NAME=Fedora VERSION=34 (Thirty Four) … PRIVACY_POLICY_URL=https://fedoraproject.org/wiki/Legal:PrivacyPolicy IMAGE_VERSION=53 Use As: ✓ bootable system for UEFI ✓ bootable system for container ✗ portable service ✗ extension for system ✗ extension for initrd ✗ extension for portable service RW DESIGNATOR PARTITION UUID PARTITION LABEL FSTYPE ARCHITECTURE VERITY GROWFS NODE PARTNO rw root d56af2b4-35eb-2e40-8f08-2d3b7012b0fc Root Partition btrfs x86-64 no no /dev/loop1p2 2 rw esp e3d11339-05c1-a74a-ae77-aae76812c134 ESP System Partition vfat - - no /dev/loop1p1 1 … --- src/dissect/dissect.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 599bc8f6d5..753d4aefd7 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -11,6 +11,7 @@ #include "chase-symlinks.h" #include "copy.h" #include "dissect-image.h" +#include "env-util.h" #include "fd-util.h" #include "fileio.h" #include "format-table.h" @@ -382,6 +383,33 @@ static void strv_pair_print(char **l, const char *prefix) { } } +static int get_sysext_scopes(DissectedImage *m, char ***ret_scopes) { + _cleanup_strv_free_ char **l = NULL; + const char *e; + + assert(m); + assert(ret_scopes); + + /* If there's no extension-release file its not a system extension. Otherwise the SYSEXT_SCOPE field + * indicates which scope it is for — and it defaults to "system" + "portable" if unset. */ + + if (!m->extension_release) { + *ret_scopes = NULL; + return 0; + } + + e = strv_env_pairs_get(m->extension_release, "SYSEXT_SCOPE"); + if (e) + l = strv_split(e, WHITESPACE); + else + l = strv_new("system", "portable"); + if (!l) + return -ENOMEM; + + *ret_scopes = TAKE_PTR(l); + return 1; +} + static int action_dissect(DissectedImage *m, LoopDevice *d) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; _cleanup_(table_unrefp) Table *t = NULL; @@ -419,6 +447,8 @@ 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 **sysext_scopes = NULL; + if (m->hostname) printf(" Hostname: %s\n", m->hostname); @@ -438,8 +468,30 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { !strv_isempty(m->os_release) || !strv_isempty(m->extension_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(" %s portable service\n", + COLOR_MARK_BOOL(strv_env_pairs_get(m->os_release, "PORTABLE_PREFIXES"))); + + r = get_sysext_scopes(m, &sysext_scopes); + if (r < 0) + return log_error_errno(r, "Failed to parse SYSEXT_SCOPE: %m"); + + printf(" %s extension for system\n", + COLOR_MARK_BOOL(strv_contains(sysext_scopes, "system"))); + printf(" %s extension for initrd\n", + COLOR_MARK_BOOL(strv_contains(sysext_scopes, "initrd"))); + printf(" %s extension for portable service\n", + COLOR_MARK_BOOL(strv_contains(sysext_scopes, "portable"))); + + putc('\n', stdout); } else { _cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL, *exr = NULL; + _cleanup_strv_free_ char **sysext_scopes = NULL; if (!strv_isempty(m->machine_info)) { r = strv_pair_to_json(m->machine_info, &mi); @@ -459,6 +511,10 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { return log_oom(); } + r = get_sysext_scopes(m, &sysext_scopes); + if (r < 0) + return log_error_errno(r, "Failed to parse SYSEXT_SCOPE: %m"); + r = json_build(&v, JSON_BUILD_OBJECT( JSON_BUILD_PAIR("name", JSON_BUILD_STRING(basename(arg_image))), JSON_BUILD_PAIR("size", JSON_BUILD_INTEGER(size)), @@ -466,7 +522,13 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { 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(exr, "extensionRelease", JSON_BUILD_VARIANT(exr)))); + 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("usePortableService", JSON_BUILD_BOOLEAN(strv_env_pairs_get(m->os_release, "PORTABLE_MATCHES"))), + JSON_BUILD_PAIR("useSystemExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "system"))), + JSON_BUILD_PAIR("useInitRDExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "initrd"))), + JSON_BUILD_PAIR("usePortableExtension", JSON_BUILD_BOOLEAN(strv_contains(sysext_scopes, "portable"))))); if (r < 0) return log_oom(); } -- cgit v1.2.1