]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
manager: add taint flag "support-ended" 23962/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 9 Jul 2022 16:00:33 +0000 (18:00 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 10 Jul 2022 12:33:52 +0000 (14:33 +0200)
In the welcome line, use NAME= as the fallback for PRETTY_NAME=.
PRETTY_NAME= doesn't have to be set, but NAME= should.

Example output:
---
Welcome to Fedora Linux 37 (Rawhide Prerelease)!

[  !!  ] This OS version (Fedora Linux 37 (Rawhide Prerelease)) is past its end-of-support date (1999-01-01)
Queued start job for default target graphical.target.
[  OK  ] Created slice system-getty.slice.
---

man/org.freedesktop.systemd1.xml
src/basic/os-util.c
src/basic/os-util.h
src/core/main.c
src/core/manager.c
src/test/test-os-util.c

index 6a532def9686243f8f1bdee24b22da5520bdda92..7803cc9cf9334c125493029d7dbf0018bf139f78 100644 (file)
@@ -1544,6 +1544,15 @@ node /org/freedesktop/systemd1 {
           UTC.</para></listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><literal>support-ended</literal></term>
+
+          <listitem><para>The system is running past the end of support declared by the vendor. See the
+          description of <varname>SUPPORT_END=</varname> in
+          <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+          </para></listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><literal>old-kernel</literal></term>
 
index 880fb7e6bbf13a8232eae2edff1d9b5ffb0ff8eb..96ba683276824b4d211dff4a2c968277dcfd1957 100644 (file)
@@ -317,3 +317,38 @@ int load_extension_release_pairs(const char *root, const char *extension, char *
 
         return load_env_file_pairs(f, p, ret);
 }
+
+int os_release_support_ended(const char *support_end, bool quiet) {
+        _cleanup_free_ char *_support_end_alloc = NULL;
+        int r;
+
+        if (!support_end) {
+                /* If the caller has the variably handy, they can pass it in. If not, we'll read it
+                 * ourselves. */
+
+                r = parse_os_release(NULL,
+                                     "SUPPORT_END", &_support_end_alloc);
+                if (r < 0)
+                        return log_full_errno((r == -ENOENT || quiet) ? LOG_DEBUG : LOG_WARNING, r,
+                                              "Failed to read os-release file, ignoring: %m");
+                if (!_support_end_alloc)
+                        return false;  /* no end date defined */
+
+                support_end = _support_end_alloc;
+        }
+
+        struct tm tm = {};
+
+        const char *k = strptime(support_end, "%Y-%m-%d", &tm);
+        if (!k || *k)
+                return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
+                                      "Failed to parse SUPPORT_END= in os-release file, ignoring: %m");
+
+        time_t eol = mktime(&tm);
+        if (eol == (time_t) -1)
+                return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
+                                      "Failed to convert SUPPORT_END= in os-release file, ignoring: %m");
+
+        usec_t ts = now(CLOCK_REALTIME);
+        return DIV_ROUND_UP(ts, USEC_PER_SEC) > (usec_t) eol;
+}
index 271b35fa4efe1eb29f901c0aa863ce6fc5d2cc10..6883ceaf986895eee00456a3683c1d5e92f08a85 100644 (file)
@@ -31,3 +31,5 @@ int _parse_os_release(const char *root, ...) _sentinel_;
 int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
 int load_os_release_pairs(const char *root, char ***ret);
 int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
+
+int os_release_support_ended(const char *support_end, bool quiet);
index 94c757e21e02899b962e91673af6949e226f9efb..aee66051db8fb0098b12570d446c7005f9bcc1d9 100644 (file)
@@ -1312,29 +1312,46 @@ static int enforce_syscall_archs(Set *archs) {
         return 0;
 }
 
-static int status_welcome(void) {
-        _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
+static int os_release_status(void) {
+        _cleanup_free_ char *pretty_name = NULL, *name = NULL, *version = NULL,
+                            *ansi_color = NULL, *support_end = NULL;
         int r;
 
-        if (!show_status_on(arg_show_status))
-                return 0;
-
         r = parse_os_release(NULL,
                              "PRETTY_NAME", &pretty_name,
-                             "ANSI_COLOR", &ansi_color);
+                             "NAME",        &name,
+                             "VERSION",     &version,
+                             "ANSI_COLOR",  &ansi_color,
+                             "SUPPORT_END", &support_end);
         if (r < 0)
-                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
-                               "Failed to read os-release file, ignoring: %m");
+                return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Failed to read os-release file, ignoring: %m");
 
-        if (log_get_show_color())
-                return status_printf(NULL, 0,
-                                     "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
-                                     isempty(ansi_color) ? "1" : ansi_color,
-                                     isempty(pretty_name) ? "Linux" : pretty_name);
-        else
-                return status_printf(NULL, 0,
-                                     "\nWelcome to %s!\n",
-                                     isempty(pretty_name) ? "Linux" : pretty_name);
+        const char *label = empty_to_null(pretty_name) ?: empty_to_null(name) ?: "Linux";
+
+        if (show_status_on(arg_show_status)) {
+                if (log_get_show_color())
+                        status_printf(NULL, 0,
+                                      "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+                                      empty_to_null(ansi_color) ?: "1",
+                                      label);
+                else
+                        status_printf(NULL, 0,
+                                      "\nWelcome to %s!\n",
+                                      label);
+        }
+
+        if (support_end && os_release_support_ended(support_end, false) > 0)
+                /* pretty_name may include the version already, so we'll print the version only if we
+                 * have it and we're not using pretty_name. */
+                status_printf(ANSI_HIGHLIGHT_RED "  !!  " ANSI_NORMAL, 0,
+                              "This OS version (%s%s%s) is past its end-of-support date (%s)",
+                              label,
+                              (pretty_name || !version) ? "" : " version ",
+                              (pretty_name || !version) ? "" : version,
+                              support_end);
+
+        return 0;
 }
 
 static int write_container_id(void) {
@@ -2100,7 +2117,7 @@ static int initialize_runtime(
                                 return r;
                         }
 
-                        status_welcome();
+                        (void) os_release_status();
                         (void) hostname_setup(true);
                         /* Force transient machine-id on first boot. */
                         machine_id_setup(NULL, first_boot, arg_machine_id, NULL);
index 9c0a686b2ab708a2327d915afb884307d750786e..c7598b1e2afc2b121da9b126c19e5591d8893353 100644 (file)
@@ -61,6 +61,7 @@
 #include "manager-serialize.h"
 #include "memory-util.h"
 #include "mkdir-label.h"
+#include "os-util.h"
 #include "parse-util.h"
 #include "path-lookup.h"
 #include "path-util.h"
@@ -4475,7 +4476,7 @@ char* manager_taint_string(const Manager *m) {
 
         assert(m);
 
-        const char* stage[12] = {};
+        const char* stage[13] = {};
         size_t n = 0;
 
         if (m->taint_usr)
@@ -4494,6 +4495,9 @@ char* manager_taint_string(const Manager *m) {
         if (clock_is_localtime(NULL) > 0)
                 stage[n++] = "local-hwclock";
 
+        if (os_release_support_ended(NULL, true) > 0)
+                stage[n++] = "support-ended";
+
         _cleanup_free_ char *destination = NULL;
         if (readlink_malloc("/var/run", &destination) < 0 ||
             !PATH_IN_SET(destination, "../run", "/run"))
index 2cee6470c4a2f8236e11c710e9bbba518e634ce9..0cfc1e3dbf9a6709cbadc500e076f43dc9f5af3c 100644 (file)
@@ -72,4 +72,18 @@ TEST(load_os_release_pairs) {
         assert_se(unsetenv("SYSTEMD_OS_RELEASE") == 0);
 }
 
+TEST(os_release_support_ended) {
+        int r;
+
+        assert_se(os_release_support_ended("1999-01-01", false) == true);
+        assert_se(os_release_support_ended("2037-12-31", false) == false);
+        assert_se(os_release_support_ended("-1-1-1", true) == -EINVAL);
+
+        r = os_release_support_ended(NULL, false);
+        if (r < 0)
+                log_info_errno(r, "Failed to check host: %m");
+        else
+                log_info_errno(r, "Host is supported: %s", yes_no(!r));
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);