]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
kernel-install: add command to list installed kernels
authorLennart Poettering <lennart@poettering.net>
Mon, 6 Nov 2023 09:30:58 +0000 (10:30 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 7 Nov 2023 15:07:05 +0000 (16:07 +0100)
This simply dumps the dirs in /usr/lib/modules/ and whether they contain
a vmlinuz binary.

man/kernel-install.xml
src/kernel-install/kernel-install.c

index f7a5d8a76b70f555457b2c69a4dd5a5fae3b480c..fd96510d0745c22318a5c1ee28788720a12cc7da 100644 (file)
       <arg choice="opt"><replaceable>KERNEL-IMAGE</replaceable></arg>
       <arg choice="opt" rep="repeat"><replaceable>INITRD-FILE</replaceable></arg>
     </cmdsynopsis>
+    <cmdsynopsis>
+      <command>kernel-install</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="plain">list</arg>
+    </cmdsynopsis>
   </refsynopsisdiv>
 
   <refsect1>
           <xi:include href="version-info.xml" xpointer="v251"/>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><command>list</command></term>
+        <listitem>
+          <para>Shows the various installed kernels. This enumerates the subdirectories of
+          <filename>/usr/lib/modules/</filename>, and shows whether a kernel image is installed there.</para>
+
+          <xi:include href="version-info.xml" xpointer="v255"/>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
       <xi:include href="standard-options.xml" xpointer="no-pager"/>
       <xi:include href="standard-options.xml" xpointer="json" />
       <xi:include href="standard-options.xml" xpointer="image-policy-open" />
+      <xi:include href="standard-options.xml" xpointer="no-legend"/>
     </variablelist>
   </refsect1>
 
index cae93362b693c3779dba694c3f3c7d422d5ef255..aaafe098b7cbfd8dfe22be52839baaf100001006 100644 (file)
@@ -3,10 +3,11 @@
 #include <getopt.h>
 #include <stdbool.h>
 
-#include "build.h"
 #include "boot-entry.h"
+#include "build.h"
 #include "chase.h"
 #include "conf-files.h"
+#include "dirent-util.h"
 #include "env-file.h"
 #include "env-util.h"
 #include "exec-util.h"
@@ -23,6 +24,7 @@
 #include "parse-argument.h"
 #include "path-util.h"
 #include "pretty-print.h"
+#include "recurse-dir.h"
 #include "rm-rf.h"
 #include "stat-util.h"
 #include "string-table.h"
@@ -40,6 +42,7 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 static char *arg_root = NULL;
 static char *arg_image = NULL;
 static ImagePolicy *arg_image_policy = NULL;
+static bool arg_legend = true;
 
 STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
@@ -1183,6 +1186,68 @@ static int verb_inspect(int argc, char *argv[], void *userdata) {
         return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, /* show_header= */ false);
 }
 
+static int verb_list(int argc, char *argv[], void *userdata) {
+        _cleanup_close_ int fd = -EBADF;
+        int r;
+
+        fd = open("/usr/lib/modules", O_DIRECTORY|O_RDONLY|O_CLOEXEC);
+        if (fd < 0)
+                return log_error_errno(fd, "Failed to open /usr/lib/modules/: %m");
+
+        _cleanup_free_ DirectoryEntries *de = NULL;
+        r = readdir_all(fd, RECURSE_DIR_SORT|RECURSE_DIR_IGNORE_DOT, &de);
+        if (r < 0)
+                return log_error_errno(r, "Failed to numerate /usr/lib/modules/ contents: %m");
+
+        _cleanup_(table_unrefp) Table *table = NULL;
+        table = table_new("version", "has kernel", "path");
+        if (!table)
+                return log_oom();
+
+        table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
+        table_set_align_percent(table, table_get_cell(table, 0, 1), 100);
+
+        FOREACH_ARRAY(d, de->entries, de->n_entries) {
+
+                _cleanup_free_ char *j = path_join("/usr/lib/modules/", (*d)->d_name);
+                if (!j)
+                        return log_oom();
+
+                r = dirent_ensure_type(fd, *d);
+                if (r < 0) {
+                        if (r != -ENOENT) /* don't log if just gone by now */
+                                log_debug_errno(r, "Failed to check if '%s' is a directory, ignoring: %m", j);
+                        continue;
+                }
+
+                if ((*d)->d_type != DT_DIR)
+                        continue;
+
+                _cleanup_free_ char *fn = path_join((*d)->d_name, "vmlinuz");
+                if (!fn)
+                        return log_oom();
+
+                bool exists;
+                if (faccessat(fd, fn, F_OK, AT_SYMLINK_NOFOLLOW) < 0) {
+                        if (errno != ENOENT)
+                                log_debug_errno(errno, "Failed to check if '/usr/lib/modules/%s/vmlinuz' exists, ignoring: %m", (*d)->d_name);
+
+                        exists = false;
+                } else
+                        exists = true;
+
+                r = table_add_many(table,
+                                   TABLE_STRING, (*d)->d_name,
+                                   TABLE_BOOLEAN_CHECKMARK, exists,
+                                   TABLE_SET_COLOR, ansi_highlight_green_red(exists),
+                                   TABLE_PATH, j);
+                if (r < 0)
+                        return table_log_add_error(r);
+        }
+
+        return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
+}
+
 static int help(void) {
         _cleanup_free_ char *link = NULL;
         int r;
@@ -1192,13 +1257,13 @@ static int help(void) {
                 return log_oom();
 
         printf("%1$s [OPTIONS...] COMMAND ...\n\n"
-               "%2$sAdd and remove kernel and initrd images to and from /boot%3$s\n"
-               "\nUsage:\n"
+               "%5$sAdd and remove kernel and initrd images to and from /boot/%6$s\n"
+               "\n%3$sUsage:%4$s\n"
                "  kernel-install [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD ...]\n"
                "  kernel-install [OPTIONS...] remove KERNEL-VERSION\n"
                "  kernel-install [OPTIONS...] inspect [KERNEL-VERSION] KERNEL-IMAGE [INITRD ...]\n"
-               "\n"
-               "Options:\n"
+               "  kernel-install [OPTIONS...] list\n"
+               "\n%3$sOptions:%4$s\n"
                "  -h --help                    Show this help\n"
                "     --version                 Show package version\n"
                "  -v --verbose                 Increase verbosity\n"
@@ -1210,6 +1275,7 @@ static int help(void) {
                "                               Entry token to use for this installation\n"
                "     --no-pager                Do not pipe inspect output into a pager\n"
                "     --json=pretty|short|off   Generate JSON output\n"
+               "     --no-legend               Do not show the headers and footers\n"
                "     --root=PATH               Operate on an alternate filesystem root\n"
                "     --image=PATH              Operate on disk image as filesystem root\n"
                "     --image-policy=POLICY     Specify disk image dissection policy\n"
@@ -1218,11 +1284,13 @@ static int help(void) {
                "  installkernel  [OPTIONS...] VERSION VMLINUZ [MAP] [INSTALLATION-DIR]\n"
                "(The optional arguments are passed by kernel build system, but ignored.)\n"
                "\n"
-               "See the %4$s for details.\n",
+               "See the %2$s for details.\n",
                program_invocation_short_name,
-               ansi_highlight(),
+               link,
+               ansi_underline(),
                ansi_normal(),
-               link);
+               ansi_highlight(),
+               ansi_normal());
 
         return 0;
 }
@@ -1230,6 +1298,7 @@ static int help(void) {
 static int parse_argv(int argc, char *argv[], Context *c) {
         enum {
                 ARG_VERSION = 0x100,
+                ARG_NO_LEGEND,
                 ARG_ESP_PATH,
                 ARG_BOOT_PATH,
                 ARG_MAKE_ENTRY_DIRECTORY,
@@ -1253,6 +1322,7 @@ static int parse_argv(int argc, char *argv[], Context *c) {
                 { "root",                 required_argument, NULL, ARG_ROOT                 },
                 { "image",                required_argument, NULL, ARG_IMAGE                },
                 { "image-policy",         required_argument, NULL, ARG_IMAGE_POLICY         },
+                { "no-legend",            no_argument,       NULL, ARG_NO_LEGEND            },
                 {}
         };
         int t, r;
@@ -1269,6 +1339,10 @@ static int parse_argv(int argc, char *argv[], Context *c) {
                 case ARG_VERSION:
                         return version();
 
+                case ARG_NO_LEGEND:
+                        arg_legend = false;
+                        break;
+
                 case 'v':
                         log_set_max_level(LOG_DEBUG);
                         arg_verbose = true;
@@ -1350,6 +1424,7 @@ static int run(int argc, char* argv[]) {
                 { "add",         3,        VERB_ANY, 0,            verb_add            },
                 { "remove",      2,        VERB_ANY, 0,            verb_remove         },
                 { "inspect",     1,        VERB_ANY, VERB_DEFAULT, verb_inspect        },
+                { "list",        1,        1,        0,            verb_list           },
                 {}
         };
         _cleanup_(context_done) Context c = {