]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: parse, store and show extension-release info
authorLuca Boccassi <luca.boccassi@microsoft.com>
Wed, 27 Jan 2021 13:03:37 +0000 (13:03 +0000)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Wed, 17 Feb 2021 21:45:31 +0000 (21:45 +0000)
src/dissect/dissect.c
src/shared/dissect-image.c
src/shared/dissect-image.h

index f8f34dcc4dd832e420b95cc74a33fd40688a2aad..85102d3efa4ce28d7b9182956d3411848a93fe8a 100644 (file)
@@ -412,13 +412,23 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
                                        *p, *q);
                 }
 
+                if (!strv_isempty(m->extension_release)) {
+                        char **p, **q;
+
+                        STRV_FOREACH_PAIR(p, q, m->extension_release)
+                                printf("%s %s=%s\n",
+                                       p == m->extension_release ? "Extension Release:" : "                  ",
+                                       *p, *q);
+                }
+
                 if (m->hostname ||
                     !sd_id128_is_null(m->machine_id) ||
                     !strv_isempty(m->machine_info) ||
+                    !strv_isempty(m->extension_release) ||
                     !strv_isempty(m->os_release))
                         putc('\n', stdout);
         } else {
-                _cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL;
+                _cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL, *exr = NULL;
 
                 if (!strv_isempty(m->machine_info)) {
                         r = strv_pair_to_json(m->machine_info, &mi);
@@ -432,13 +442,20 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
                                 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 = json_build(&v, JSON_BUILD_OBJECT(
                                                JSON_BUILD_PAIR("name", JSON_BUILD_STRING(basename(arg_image))),
                                                JSON_BUILD_PAIR("size", JSON_BUILD_INTEGER(size)),
                                                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, "osRelease", JSON_BUILD_VARIANT(osr)),
+                                               JSON_BUILD_PAIR_CONDITION(exr, "extensionRelease", JSON_BUILD_VARIANT(exr))));
                 if (r < 0)
                         return log_oom();
         }
index d557b46e9094c3e43f3126515ede196612b833bc..2799f4f268ef43b82751c18e5ed15cca9ed0a2a7 100644 (file)
@@ -23,6 +23,7 @@
 #include "def.h"
 #include "device-nodes.h"
 #include "device-util.h"
+#include "discover-image.h"
 #include "dissect-image.h"
 #include "dm-util.h"
 #include "env-file.h"
@@ -1230,6 +1231,7 @@ DissectedImage* dissected_image_unref(DissectedImage *m) {
         free(m->hostname);
         strv_free(m->machine_info);
         strv_free(m->os_release);
+        strv_free(m->extension_release);
 
         return mfree(m);
 }
@@ -1400,7 +1402,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
         /* Returns:
          *
          *  -ENXIO        → No root partition found
-         *  -EMEDIUMTYPE  → DISSECT_IMAGE_VALIDATE_OS set but no os-release file found
+         *  -EMEDIUMTYPE  → DISSECT_IMAGE_VALIDATE_OS set but no os-release/extension-release file found
          *  -EUNATCH      → Encrypted partition found for which no dm-crypt was set up yet
          *  -EUCLEAN      → fsck for file system failed
          *  -EBUSY        → File system already mounted/used elsewhere (kernel)
@@ -1430,8 +1432,13 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
                         r = path_is_os_tree(where);
                         if (r < 0)
                                 return r;
-                        if (r == 0)
-                                return -EMEDIUMTYPE;
+                        if (r == 0) {
+                                r = path_is_extension_tree(where, m->image_name);
+                                if (r < 0)
+                                        return r;
+                                if (r == 0)
+                                        return -EMEDIUMTYPE;
+                        }
                 }
         }
 
@@ -1511,7 +1518,7 @@ int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t u
         if (r == -ENXIO)
                 return log_error_errno(r, "Not root file system found in image.");
         if (r == -EMEDIUMTYPE)
-                return log_error_errno(r, "No suitable os-release file in image found.");
+                return log_error_errno(r, "No suitable os-release/extension-release file in image found.");
         if (r == -EUNATCH)
                 return log_error_errno(r, "Encrypted file system discovered, but decryption not requested.");
         if (r == -EUCLEAN)
@@ -2237,18 +2244,20 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
                 META_MACHINE_ID,
                 META_MACHINE_INFO,
                 META_OS_RELEASE,
+                META_EXTENSION_RELEASE,
                 _META_MAX,
         };
 
-        static const char *const paths[_META_MAX] = {
-                [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"),
+        static const char *paths[_META_MAX] = {
+                [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_EXTENSION_RELEASE] = NULL,
         };
 
-        _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL;
+        _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **extension_release = NULL;
         _cleanup_close_pair_ int error_pipe[2] = { -1, -1 };
         _cleanup_(rmdir_and_freep) char *t = NULL;
         _cleanup_(sigkill_waitp) pid_t child = 0;
@@ -2262,11 +2271,21 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
 
         assert(m);
 
-        for (; n_meta_initialized < _META_MAX; n_meta_initialized ++)
+        /* 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/ */
+        if (m->image_name)
+                paths[META_EXTENSION_RELEASE] = strjoina("/usr/lib/extension-release.d/extension-release.", m->image_name);
+        else
+                log_debug("No image name available, will skip extension-release metadata");
+
+        for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) {
+                if (!paths[n_meta_initialized])
+                        continue;
                 if (pipe2(fds + 2*n_meta_initialized, O_CLOEXEC) < 0) {
                         r = -errno;
                         goto finish;
                 }
+        }
 
         r = mkdtemp_malloc("/tmp/dissect-XXXXXX", &t);
         if (r < 0)
@@ -2296,6 +2315,9 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
                         _cleanup_close_ int fd = -ENOENT;
                         const char *p;
 
+                        if (!paths[k])
+                                continue;
+
                         fds[2*k] = safe_close(fds[2*k]);
 
                         NULSTR_FOREACH(p, paths[k]) {
@@ -2326,6 +2348,9 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
         for (k = 0; k < _META_MAX; k++) {
                 _cleanup_fclose_ FILE *f = NULL;
 
+                if (!paths[k])
+                        continue;
+
                 fds[2*k+1] = safe_close(fds[2*k+1]);
 
                 f = take_fdopen(&fds[2*k], "r");
@@ -2376,6 +2401,13 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
                                 log_debug_errno(r, "Failed to read OS release file: %m");
 
                         break;
+
+                case META_EXTENSION_RELEASE:
+                        r = load_env_file_pairs(f, "extension-release", &extension_release);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to read extension release file: %m");
+
+                        break;
                 }
         }
 
@@ -2399,10 +2431,14 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
         m->machine_id = machine_id;
         strv_free_and_replace(m->machine_info, machine_info);
         strv_free_and_replace(m->os_release, os_release);
+        strv_free_and_replace(m->extension_release, extension_release);
 
 finish:
-        for (k = 0; k < n_meta_initialized; k++)
+        for (k = 0; k < n_meta_initialized; k++) {
+                if (!paths[k])
+                        continue;
                 safe_close_pair(fds + 2*k);
+        }
 
         return r;
 }
index fc120b29b47215150b4c8c3eb9392cbf12d85b98..89078500007aaf38b73e7357ca61e7f3f14bfaff 100644 (file)
@@ -102,6 +102,7 @@ struct DissectedImage {
         sd_id128_t machine_id;
         char **machine_info;
         char **os_release;
+        char **extension_release;
 };
 
 struct MountOptions {