]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: show intended purpose of images in dissection output
authorLennart Poettering <lennart@poettering.net>
Fri, 19 Nov 2021 15:20:00 +0000 (16:20 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Nov 2021 21:55:49 +0000 (22:55 +0100)
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:

<snip>
      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

</snip>

src/dissect/dissect.c

index 599bc8f6d5022234d6569ca127d0f7669cc9aee1..753d4aefd7a3a7dfa602a6b6413d57336b89cc9d 100644 (file)
@@ -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();
         }