Merge pull request #29876 from poettering/kernel-install-all
add "kernel-install list" and "kernel-install add-all"
This commit is contained in:
@@ -1086,9 +1086,6 @@ Features:
|
||||
uses RootDirectory= or RootImage=. (Might also over-mount
|
||||
/sys/class/dmi/id/*{uuid,serial} with /dev/null).
|
||||
|
||||
* kernel-install:
|
||||
- add --all switch for rerunning kernel-install for all installed kernels
|
||||
|
||||
* doc: prep a document explaining resolved's internal objects, i.e. Query
|
||||
vs. Question vs. Transaction vs. Stream and so on.
|
||||
|
||||
|
||||
+68
-10
@@ -44,6 +44,11 @@
|
||||
<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>
|
||||
@@ -81,15 +86,17 @@
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>add</command>
|
||||
<replaceable>KERNEL-VERSION</replaceable>
|
||||
<replaceable>KERNEL-IMAGE</replaceable> [<replaceable>INITRD-FILE</replaceable> ...]
|
||||
<command>add [[[<replaceable>KERNEL-VERSION</replaceable>] <replaceable>KERNEL-IMAGE</replaceable>] [<replaceable>INITRD-FILE</replaceable> ...]]</command>
|
||||
</term>
|
||||
|
||||
<listitem>
|
||||
<para>This command expects a kernel version string and a path to a kernel image file as arguments.
|
||||
Optionally, one or more initrd images may be specified as well (note that plugins might generate
|
||||
additional ones).</para>
|
||||
<para>This command takes a kernel version string and a path to a kernel image file as arguments. If
|
||||
the former is omitted, specified as an empty string or as "-" it defaults to the current kernel
|
||||
version, i.e. the same string <command>uname -r</command> returns. If the latter is omitted,
|
||||
specified as an empty string or as "-" defaults to
|
||||
<filename>/usr/lib/modules/<replaceable>KERNEL_VERSION</replaceable>/vmlinuz</filename>. Optionally,
|
||||
one or more initrd images may be specified as well (note that plugins might generate additional
|
||||
ones).</para>
|
||||
|
||||
<para>The executable files from <filename>/usr/lib/kernel/install.d/*.install</filename> and
|
||||
<filename>/etc/kernel/install.d/*.install</filename> (i.e. the plugins) are called with the
|
||||
@@ -144,6 +151,20 @@
|
||||
<xi:include href="version-info.xml" xpointer="v198"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>add-all</command>
|
||||
</term>
|
||||
|
||||
<listitem>
|
||||
<para>This is the same as <command>add</command> (see above), but invokes the operation iteratively
|
||||
for every installed kernel in <filename>/usr/lib/modules/</filename>. This operation is only
|
||||
supported on systems where the kernel image is installed in
|
||||
<filename>/usr/lib/modules/<replaceable>KERNEL-VERSION</replaceable>/vmlinuz</filename>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>remove <replaceable>KERNEL-VERSION</replaceable></command></term>
|
||||
<listitem>
|
||||
@@ -179,17 +200,28 @@
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>inspect [[<replaceable>KERNEL-VERSION</replaceable>] <replaceable>KERNEL-IMAGE</replaceable>] [<replaceable>INITRD-FILE</replaceable> ...]</command>
|
||||
<command>inspect [[[<replaceable>KERNEL-VERSION</replaceable>] <replaceable>KERNEL-IMAGE</replaceable>] [<replaceable>INITRD-FILE</replaceable> ...]]</command>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Takes the same parameters as <command>add</command>.</para>
|
||||
|
||||
<para>Shows the various paths and parameters configured or auto-detected. In particular shows the
|
||||
values of the various <varname>$KERNEL_INSTALL_*</varname> environment variables listed
|
||||
below. The <option>--json</option> option can be used to get the output of this verb as a JSON
|
||||
object.</para>
|
||||
values of the various <varname>$KERNEL_INSTALL_*</varname> environment variables listed below, as
|
||||
they would be passed to plugins. The <option>--json</option> option can be used to get the output
|
||||
of this verb as a JSON object.</para>
|
||||
|
||||
<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>
|
||||
|
||||
@@ -332,6 +364,7 @@
|
||||
<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>
|
||||
|
||||
@@ -641,6 +674,31 @@
|
||||
<xi:include href="version-info.xml" xpointer="v255"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>/usr/lib/modules/<replaceable>KERNEL-VERSION/</replaceable></filename></term>
|
||||
|
||||
<listitem>
|
||||
<para>Location for installed kernel modules and other kernel related resources. For each locally
|
||||
installed kernel a directory named after the kernel version (<command>uname -r</command>) is
|
||||
kept.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>/usr/lib/modules/<replaceable>KERNEL-VERSION/vmlinuz</replaceable></filename></term>
|
||||
|
||||
<listitem>
|
||||
<para>Location for installed kernel images. This is the recommended location for OS package
|
||||
managers to install kernel images into (as applicable), from which <command>kernel-install
|
||||
add</command> then copies it into the final boot partition.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>For various cases listed above, if the <varname>$KERNEL_INSTALL_CONF_ROOT</varname> environment
|
||||
|
||||
@@ -301,3 +301,24 @@ bool version_is_valid(const char *s);
|
||||
bool version_is_valid_versionspec(const char *s);
|
||||
|
||||
ssize_t strlevenshtein(const char *x, const char *y);
|
||||
|
||||
static inline int strdup_or_null(const char *s, char **ret) {
|
||||
char *c;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* This is a lot like strdup(), but is happy with NULL strings, and does not treat that as error, but
|
||||
* copies the NULL value. */
|
||||
|
||||
if (!s) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = strdup(s);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/utsname.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"
|
||||
@@ -14,6 +16,7 @@
|
||||
#include "fileio.h"
|
||||
#include "find-esp.h"
|
||||
#include "format-table.h"
|
||||
#include "fs-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "image-policy.h"
|
||||
#include "kernel-image.h"
|
||||
@@ -23,6 +26,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 +44,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);
|
||||
@@ -96,6 +101,8 @@ typedef struct Context {
|
||||
char **envp;
|
||||
} Context;
|
||||
|
||||
#define CONTEXT_NULL (Context) { .rfd = -EBADF }
|
||||
|
||||
static void context_done(Context *c) {
|
||||
assert(c);
|
||||
|
||||
@@ -120,6 +127,75 @@ static void context_done(Context *c) {
|
||||
safe_close(c->rfd);
|
||||
}
|
||||
|
||||
static int context_copy(const Context *source, Context *ret) {
|
||||
int r;
|
||||
|
||||
assert(source);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_(context_done) Context copy = (Context) {
|
||||
.rfd = -EBADF,
|
||||
.action = source->action,
|
||||
.machine_id = source->machine_id,
|
||||
.machine_id_is_random = source->machine_id_is_random,
|
||||
.kernel_image_type = source->kernel_image_type,
|
||||
.layout = source->layout,
|
||||
.entry_token_type = source->entry_token_type,
|
||||
};
|
||||
|
||||
copy.rfd = fd_reopen(source->rfd, O_CLOEXEC|O_DIRECTORY|O_PATH);
|
||||
if (copy.rfd < 0)
|
||||
return copy.rfd;
|
||||
|
||||
r = strdup_or_null(source->layout_other, ©.layout_other);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->conf_root, ©.conf_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->boot_root, ©.boot_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->entry_token, ©.entry_token);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->entry_dir, ©.entry_dir);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->version, ©.version);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->kernel, ©.kernel);
|
||||
if (r < 0)
|
||||
return r;
|
||||
copy.initrds = strv_copy(source->initrds);
|
||||
if (!copy.initrds)
|
||||
return -ENOMEM;
|
||||
r = strdup_or_null(source->initrd_generator, ©.initrd_generator);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->uki_generator, ©.uki_generator);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strdup_or_null(source->staging_area, ©.staging_area);
|
||||
if (r < 0)
|
||||
return r;
|
||||
copy.plugins = strv_copy(source->plugins);
|
||||
if (!copy.plugins)
|
||||
return -ENOMEM;
|
||||
copy.argv = strv_copy(source->argv);
|
||||
if (!copy.argv)
|
||||
return -ENOMEM;
|
||||
copy.envp = strv_copy(source->envp);
|
||||
if (!copy.envp)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = copy;
|
||||
copy = CONTEXT_NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_open_root(Context *c) {
|
||||
assert(c);
|
||||
assert(c->rfd < 0);
|
||||
@@ -1019,11 +1095,67 @@ static bool bypass(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int do_add(
|
||||
Context *c,
|
||||
const char *version,
|
||||
const char *kernel,
|
||||
char **initrds) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(version);
|
||||
assert(kernel);
|
||||
|
||||
r = context_set_version(c, version);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_set_kernel(c, kernel);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_set_initrds(c, initrds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_prepare_execution(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return context_execute(c);
|
||||
}
|
||||
|
||||
static int kernel_from_version(const char *version, char **ret_kernel) {
|
||||
_cleanup_free_ char *vmlinuz = NULL;
|
||||
int r;
|
||||
|
||||
assert(version);
|
||||
|
||||
vmlinuz = path_join("/usr/lib/modules/", version, "/vmlinuz");
|
||||
if (!vmlinuz)
|
||||
return log_oom();
|
||||
|
||||
r = laccess(vmlinuz, F_OK);
|
||||
if (r < 0) {
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "Kernel image not installed to '%s', requiring manual kernel image path specification.", vmlinuz);
|
||||
|
||||
return log_error_errno(r, "Failed to determin if kernel image is installed to '%s': %m", vmlinuz);
|
||||
}
|
||||
|
||||
*ret_kernel = TAKE_PTR(vmlinuz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_add(int argc, char *argv[], void *userdata) {
|
||||
Context *c = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *vmlinuz = NULL;
|
||||
const char *version, *kernel;
|
||||
char **initrds;
|
||||
struct utsname un;
|
||||
int r;
|
||||
|
||||
assert(argc >= 3);
|
||||
assert(argv);
|
||||
|
||||
if (arg_root)
|
||||
@@ -1034,23 +1166,106 @@ static int verb_add(int argc, char *argv[], void *userdata) {
|
||||
|
||||
c->action = ACTION_ADD;
|
||||
|
||||
r = context_set_version(c, argv[1]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* We use the same order of arguments that "inspect" introduced, i.e. if only on argument is
|
||||
* specified we take it as the kernel path, not the version, i.e. it's the first argument that is
|
||||
* optional, not the 2nd. */
|
||||
version = argc > 2 ? empty_or_dash_to_null(argv[1]) : NULL;
|
||||
kernel = argc > 2 ? empty_or_dash_to_null(argv[2]) :
|
||||
(argc > 1 ? empty_or_dash_to_null(argv[1]) : NULL);
|
||||
initrds = strv_skip(argv, 3);
|
||||
|
||||
r = context_set_kernel(c, argv[2]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!version) {
|
||||
assert_se(uname(&un) >= 0);
|
||||
version = un.release;
|
||||
}
|
||||
|
||||
r = context_set_initrds(c, strv_skip(argv, 3));
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!kernel) {
|
||||
r = kernel_from_version(version, &vmlinuz);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_prepare_execution(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
kernel = vmlinuz;
|
||||
}
|
||||
|
||||
return context_execute(c);
|
||||
return do_add(c, version, kernel, initrds);
|
||||
}
|
||||
|
||||
static int verb_add_all(int argc, char *argv[], void *userdata) {
|
||||
Context *c = ASSERT_PTR(userdata);
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
size_t n = 0;
|
||||
int ret = 0, r;
|
||||
|
||||
assert(argv);
|
||||
|
||||
if (bypass())
|
||||
return 0;
|
||||
|
||||
c->action = ACTION_ADD;
|
||||
|
||||
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");
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
log_notice("Not adding version '%s', because kernel image not found.", (*d)->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_(context_done) Context copy = CONTEXT_NULL;
|
||||
|
||||
r = context_copy(c, ©);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to copy execution context: %m");
|
||||
|
||||
_cleanup_free_ char *full = path_join("/usr/lib/modules/", fn);
|
||||
if (!full)
|
||||
return log_oom();
|
||||
|
||||
r = do_add(©,
|
||||
/* version= */ (*d)->d_name,
|
||||
/* kernel= */ full,
|
||||
/* initrds= */ NULL);
|
||||
RET_GATHER(ret, r);
|
||||
|
||||
if (r >= 0)
|
||||
n++;
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
log_info("Installed %zu kernels.", n);
|
||||
else if (ret == 0)
|
||||
ret = log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No kernels to install found.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run_as_installkernel(int argc, char *argv[], Context *c) {
|
||||
@@ -1082,6 +1297,10 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
|
||||
|
||||
c->action = ACTION_REMOVE;
|
||||
|
||||
/* Note, we do not automatically derive the kernel version to remove from uname() here (unlike we do
|
||||
* it for the "add" verb), since we don't want to make it too easy to uninstall your running
|
||||
* kernel, as a safety precaution */
|
||||
|
||||
r = context_set_version(c, argv[1]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1096,28 +1315,49 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
|
||||
static int verb_inspect(int argc, char *argv[], void *userdata) {
|
||||
Context *c = ASSERT_PTR(userdata);
|
||||
_cleanup_(table_unrefp) Table *t = NULL;
|
||||
_cleanup_free_ char *vmlinuz = NULL;
|
||||
const char *version, *kernel;
|
||||
char **initrds;
|
||||
struct utsname un;
|
||||
int r;
|
||||
|
||||
c->action = ACTION_INSPECT;
|
||||
|
||||
if (argc == 2) {
|
||||
r = context_set_kernel(c, argv[1]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (argc >= 3) {
|
||||
r = context_set_version(c, argv[1]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
/* When only a single parameter is specified 'inspect' it's the kernel image path, and not the kernel
|
||||
* version. i.e. it's the first argument that is optional, not the 2nd. That's a bit unfortunate, but
|
||||
* we keep the behaviour for compatibility. If users want to specify only the version (and have the
|
||||
* kernel image path derived automatically), then they may specify an empty string or "dash" as
|
||||
* kernel image path. */
|
||||
version = argc > 2 ? empty_or_dash_to_null(argv[1]) : NULL;
|
||||
kernel = argc > 2 ? empty_or_dash_to_null(argv[2]) :
|
||||
(argc > 1 ? empty_or_dash_to_null(argv[1]) : NULL);
|
||||
initrds = strv_skip(argv, 3);
|
||||
|
||||
r = context_set_kernel(c, argv[2]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_set_initrds(c, strv_skip(argv, 3));
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!version) {
|
||||
assert_se(uname(&un) >= 0);
|
||||
version = un.release;
|
||||
}
|
||||
|
||||
if (!kernel) {
|
||||
r = kernel_from_version(version, &vmlinuz);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
kernel = vmlinuz;
|
||||
}
|
||||
|
||||
r = context_set_version(c, version);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_set_kernel(c, kernel);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_set_initrds(c, initrds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = context_prepare_execution(c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1183,6 +1423,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 +1494,15 @@ 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"
|
||||
" kernel-install [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD ...]\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...] add-all\n"
|
||||
" kernel-install [OPTIONS...] remove KERNEL-VERSION\n"
|
||||
" kernel-install [OPTIONS...] inspect [KERNEL-VERSION] KERNEL-IMAGE [INITRD ...]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" kernel-install [OPTIONS...] inspect [[[KERNEL-VERSION] KERNEL-IMAGE]\n"
|
||||
" [INITRD ...]]\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 +1514,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 +1523,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 +1537,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 +1561,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 +1578,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;
|
||||
@@ -1347,9 +1660,11 @@ static int parse_argv(int argc, char *argv[], Context *c) {
|
||||
|
||||
static int run(int argc, char* argv[]) {
|
||||
static const Verb verbs[] = {
|
||||
{ "add", 3, VERB_ANY, 0, verb_add },
|
||||
{ "add", 1, VERB_ANY, 0, verb_add },
|
||||
{ "add-all", 1, 1, 0, verb_add_all },
|
||||
{ "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 = {
|
||||
|
||||
@@ -71,7 +71,7 @@ grep -qE 'image' "$BOOT_ROOT/the-token/1.1.1/linux"
|
||||
grep -qE 'initrd' "$BOOT_ROOT/the-token/1.1.1/initrd"
|
||||
grep -qE 'DTBDTB' "$BOOT_ROOT/the-token/1.1.1/whatever.dtb"
|
||||
|
||||
"$kernel_install" inspect
|
||||
test -f /usr/lib/modules/"$(uname -r)"/vmlinuz && "$kernel_install" inspect
|
||||
"$kernel_install" inspect "$D/sources/linux"
|
||||
|
||||
"$kernel_install" -v remove 1.1.1
|
||||
|
||||
Reference in New Issue
Block a user