grub2/0033-Use-rpm-s-sort-for-grub2-mkconfig.patch
Adam Williamson 5e72956199 Revert "Use my sort patch instead", fix BLS ostree detection
This reverts commit 93004a8494,
because it broke Rawhide. It also tries to fixes BLS ostree
detection to work in chroots (e.g. during installation) by also
checking for /ostree/repo.
2022-03-22 18:32:24 -07:00

476 lines
13 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Marshall <rmarshall@redhat.com>
Date: Mon, 16 Mar 2015 14:14:19 -0400
Subject: [PATCH] Use rpm's sort for grub2-mkconfig
Add an option for rpm-based systems to use the rpm-sort library to sort
kernels. This avoids problems due to discrepancies between `sort -V`
and rpm.
Signed-off-by: Robert Marshall <rmarshall@redhat.com>
[pjones: fix --enable-rpm-sort configure option]
Signed-off-by: Peter Jones <pjones@redhat.com>
[thierry.vignaud: fix build with rpm-4.16]
Signed-off-by: Thierry Vignaud <thierry.vignaud@gmail.com>
[tim: fix disabling grub-rpm-sort by ./configure]
Signed-off-by: Tim Landscheidt <tim@tim-landscheidt.de>
[javierm: don't check for rpmvercmp in librpm]
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
[rharwood: commit message]
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
configure.ac | 37 ++++++
Makefile.util.def | 17 +++
util/grub-rpm-sort.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++
util/grub-mkconfig_lib.in | 11 +-
util/grub-rpm-sort.8 | 12 ++
5 files changed, 357 insertions(+), 1 deletion(-)
create mode 100644 util/grub-rpm-sort.c
create mode 100644 util/grub-rpm-sort.8
diff --git a/configure.ac b/configure.ac
index bec8535af70..643a13f9147 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,6 +72,7 @@ grub_TRANSFORM([grub-mkrelpath])
grub_TRANSFORM([grub-mkrescue])
grub_TRANSFORM([grub-probe])
grub_TRANSFORM([grub-reboot])
+grub_TRANSFORM([grub-rpm-sort])
grub_TRANSFORM([grub-script-check])
grub_TRANSFORM([grub-set-default])
grub_TRANSFORM([grub-sparc64-setup])
@@ -95,6 +96,7 @@ grub_TRANSFORM([grub-mkrescue.1])
grub_TRANSFORM([grub-mkstandalone.3])
grub_TRANSFORM([grub-ofpathname.3])
grub_TRANSFORM([grub-probe.3])
+grub_TRANSFORM([grub-rpm-sort.8])
grub_TRANSFORM([grub-reboot.3])
grub_TRANSFORM([grub-render-label.3])
grub_TRANSFORM([grub-script-check.3])
@@ -1860,6 +1862,35 @@ fi
AC_SUBST([LIBDEVMAPPER])
+AC_ARG_ENABLE([rpm-sort],
+ [AS_HELP_STRING([--enable-rpm-sort],
+ [enable native rpm sorting of kernels in grub (default=guessed)])])
+if test x"$enable_rpm_sort" = xno ; then
+ rpm_sort_excuse="explicitly disabled"
+else
+ enable_rpm_sort=yes
+fi
+
+if test x"$rpm_sort_excuse" = x ; then
+ # Check for rpmlib header.
+ AC_CHECK_HEADER([rpm/rpmlib.h], [],
+ [rpm_sort_excuse="need rpm/rpmlib header"])
+fi
+
+if test x"$rpm_sort_excuse" = x ; then
+ # Check for rpmio library.
+ AC_CHECK_LIB([rpmio], [rpmvercmp], [],
+ [rpm_sort_excuse="rpmio missing rpmvercmp"])
+fi
+
+if test x"$rpm_sort_excuse" = x ; then
+ LIBRPM="-lrpmio";
+ AC_DEFINE([HAVE_RPMIO], [1],
+ [Define to 1 if you have the rpmio library.])
+fi
+
+AC_SUBST([LIBRPM])
+
LIBGEOM=
if test x$host_kernel = xkfreebsd; then
AC_CHECK_LIB([geom], [geom_gettree], [],
@@ -2047,6 +2078,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes])
+AM_CONDITIONAL([COND_GRUB_RPM_SORT], [test x$enable_rpm_sort = xyes])
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
if test x$FONT_SOURCE != x ; then
HAVE_FONT_SOURCE=1
@@ -2168,6 +2200,11 @@ echo grub-mount: Yes
else
echo grub-mount: No "($grub_mount_excuse)"
fi
+if [ x"$rpm_sort_excuse" = x ]; then
+echo grub-rpm-sort: Yes
+else
+echo grub-rpm-sort: No "($rpm_sort_excuse)"
+fi
if [ x"$starfield_excuse" = x ]; then
echo starfield theme: Yes
echo With DejaVuSans font from $DJVU_FONT_SOURCE
diff --git a/Makefile.util.def b/Makefile.util.def
index 2c9b283a230..bc10cc79722 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -703,6 +703,23 @@ program = {
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
+program = {
+ name = grub-rpm-sort;
+ mansection = 8;
+ installdir = sbin;
+
+ common = grub-core/kern/emu/misc.c;
+ common = grub-core/kern/emu/argp_common.c;
+ common = grub-core/osdep/init.c;
+ common = util/misc.c;
+ common = util/grub-rpm-sort.c;
+
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/lib/gnulib/libgnu.a;
+ ldadd = '$(LIBDEVMAPPER) $(LIBRPM)';
+ condition = COND_GRUB_RPM_SORT;
+};
+
script = {
name = grub-mkconfig;
common = util/grub-mkconfig.in;
diff --git a/util/grub-rpm-sort.c b/util/grub-rpm-sort.c
new file mode 100644
index 00000000000..f33bd1ed568
--- /dev/null
+++ b/util/grub-rpm-sort.c
@@ -0,0 +1,281 @@
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <argp.h>
+#include <rpm/rpmlib.h>
+
+static size_t
+read_file (const char *input, char **ret)
+{
+ FILE *in;
+ size_t s;
+ size_t sz = 2048;
+ size_t offset = 0;
+ char *text;
+
+ if (!strcmp(input, "-"))
+ in = stdin;
+ else
+ in = grub_util_fopen(input, "r");
+
+ text = xmalloc (sz);
+
+ if (!in)
+ grub_util_error (_("cannot open `%s': %s"), input, strerror (errno));
+
+ while ((s = fread (text + offset, 1, sz - offset, in)) != 0)
+ {
+ offset += s;
+ if (sz - offset == 0)
+ {
+ sz += 2048;
+ text = xrealloc (text, sz);
+ }
+ }
+
+ text[offset] = '\0';
+ *ret = text;
+
+ if (in != stdin)
+ fclose(in);
+
+ return offset + 1;
+}
+
+/* returns name/version/release */
+/* NULL string pointer returned if nothing found */
+static void
+split_package_string (char *package_string, char **name,
+ char **version, char **release)
+{
+ char *package_version, *package_release;
+
+ /* Release */
+ package_release = strrchr (package_string, '-');
+
+ if (package_release != NULL)
+ *package_release++ = '\0';
+
+ *release = package_release;
+
+ /* Version */
+ package_version = strrchr(package_string, '-');
+
+ if (package_version != NULL)
+ *package_version++ = '\0';
+
+ *version = package_version;
+ /* Name */
+ *name = package_string;
+
+ /* Bubble up non-null values from release to name */
+ if (*name == NULL)
+ {
+ *name = (*version == NULL ? *release : *version);
+ *version = *release;
+ *release = NULL;
+ }
+ if (*version == NULL)
+ {
+ *version = *release;
+ *release = NULL;
+ }
+}
+
+/*
+ * package name-version-release comparator for qsort
+ * expects p, q which are pointers to character strings (char *)
+ * which will not be altered in this function
+ */
+static int
+package_version_compare (const void *p, const void *q)
+{
+ char *local_p, *local_q;
+ char *lhs_name, *lhs_version, *lhs_release;
+ char *rhs_name, *rhs_version, *rhs_release;
+ int vercmpflag = 0;
+
+ local_p = alloca (strlen (*(char * const *)p) + 1);
+ local_q = alloca (strlen (*(char * const *)q) + 1);
+
+ /* make sure these allocated */
+ assert (local_p);
+ assert (local_q);
+
+ strcpy (local_p, *(char * const *)p);
+ strcpy (local_q, *(char * const *)q);
+
+ split_package_string (local_p, &lhs_name, &lhs_version, &lhs_release);
+ split_package_string (local_q, &rhs_name, &rhs_version, &rhs_release);
+
+ /* Check Name and return if unequal */
+ vercmpflag = rpmvercmp ((lhs_name == NULL ? "" : lhs_name),
+ (rhs_name == NULL ? "" : rhs_name));
+ if (vercmpflag != 0)
+ return vercmpflag;
+
+ /* Check version and return if unequal */
+ vercmpflag = rpmvercmp ((lhs_version == NULL ? "" : lhs_version),
+ (rhs_version == NULL ? "" : rhs_version));
+ if (vercmpflag != 0)
+ return vercmpflag;
+
+ /* Check release and return the version compare value */
+ vercmpflag = rpmvercmp ((lhs_release == NULL ? "" : lhs_release),
+ (rhs_release == NULL ? "" : rhs_release));
+
+ return vercmpflag;
+}
+
+static void
+add_input (const char *filename, char ***package_names, size_t *n_package_names)
+{
+ char *orig_input_buffer = NULL;
+ char *input_buffer;
+ char *position_of_newline;
+ char **names = *package_names;
+ char **new_names = NULL;
+ size_t n_names = *n_package_names;
+
+ if (!*package_names)
+ new_names = names = xmalloc (sizeof (char *) * 2);
+
+ if (read_file (filename, &orig_input_buffer) < 2)
+ {
+ if (new_names)
+ free (new_names);
+ if (orig_input_buffer)
+ free (orig_input_buffer);
+ return;
+ }
+
+ input_buffer = orig_input_buffer;
+ while (input_buffer && *input_buffer &&
+ (position_of_newline = strchrnul (input_buffer, '\n')))
+ {
+ size_t sz = position_of_newline - input_buffer;
+ char *new;
+
+ if (sz == 0)
+ {
+ input_buffer = position_of_newline + 1;
+ continue;
+ }
+
+ new = xmalloc (sz+1);
+ strncpy (new, input_buffer, sz);
+ new[sz] = '\0';
+
+ names = xrealloc (names, sizeof (char *) * (n_names + 1));
+ names[n_names] = new;
+ n_names++;
+
+ /* move buffer ahead to next line */
+ input_buffer = position_of_newline + 1;
+ if (*position_of_newline == '\0')
+ input_buffer = NULL;
+ }
+
+ free (orig_input_buffer);
+
+ *package_names = names;
+ *n_package_names = n_names;
+}
+
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+ return (char *)text;
+}
+
+static struct argp_option options[] = {
+ { 0, }
+};
+
+struct arguments
+{
+ size_t ninputs;
+ size_t input_max;
+ char **inputs;
+};
+
+static error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+ struct arguments *arguments = state->input;
+ switch (key)
+ {
+ case ARGP_KEY_ARG:
+ assert (arguments->ninputs < arguments->input_max);
+ arguments->inputs[arguments->ninputs++] = xstrdup (arg);
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp argp = {
+ options, argp_parser, N_("[INPUT_FILES]"),
+ N_("Sort a list of strings in RPM version sort order."),
+ NULL, help_filter, NULL
+};
+
+int
+main (int argc, char *argv[])
+{
+ struct arguments arguments;
+ char **package_names = NULL;
+ size_t n_package_names = 0;
+ int i;
+
+ grub_util_host_init (&argc, &argv);
+
+ memset (&arguments, 0, sizeof (struct arguments));
+ arguments.input_max = argc+1;
+ arguments.inputs = xmalloc ((arguments.input_max + 1)
+ * sizeof (arguments.inputs[0]));
+ memset (arguments.inputs, 0, (arguments.input_max + 1)
+ * sizeof (arguments.inputs[0]));
+
+ /* Parse our arguments */
+ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
+ grub_util_error ("%s", _("Error in parsing command line arguments\n"));
+
+ /* If there's no inputs in argv, add one for stdin */
+ if (!arguments.ninputs)
+ {
+ arguments.ninputs = 1;
+ arguments.inputs[0] = xmalloc (2);
+ strcpy(arguments.inputs[0], "-");
+ }
+
+ for (i = 0; i < arguments.ninputs; i++)
+ add_input(arguments.inputs[i], &package_names, &n_package_names);
+
+ if (package_names == NULL || n_package_names < 1)
+ grub_util_error ("%s", _("Invalid input\n"));
+
+ qsort (package_names, n_package_names, sizeof (char *),
+ package_version_compare);
+
+ /* send sorted list to stdout */
+ for (i = 0; i < n_package_names; i++)
+ {
+ fprintf (stdout, "%s\n", package_names[i]);
+ free (package_names[i]);
+ }
+
+ free (package_names);
+ for (i = 0; i < arguments.ninputs; i++)
+ free (arguments.inputs[i]);
+
+ free (arguments.inputs);
+
+ return 0;
+}
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 0f6505bf3b6..42c2ea9ba50 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -33,6 +33,9 @@ fi
if test "x$grub_mkrelpath" = x; then
grub_mkrelpath="${bindir}/@grub_mkrelpath@"
fi
+if test "x$grub_rpm_sort" = x; then
+ grub_rpm_sort="${sbindir}/@grub_rpm_sort@"
+fi
if command -v gettext >/dev/null; then
:
@@ -218,6 +221,12 @@ version_sort ()
esac
}
+if [ "x$grub_rpm_sort" != x -a -x "$grub_rpm_sort" ]; then
+ kernel_sort="$grub_rpm_sort"
+else
+ kernel_sort=version_sort
+fi
+
version_test_numeric ()
{
version_test_numeric_a="$1"
@@ -234,7 +243,7 @@ version_test_numeric ()
version_test_numeric_a="$version_test_numeric_b"
version_test_numeric_b="$version_test_numeric_c"
fi
- if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | version_sort | head -n 1 | grep -qx "$version_test_numeric_b" ; then
+ if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | "$kernel_sort" | head -n 1 | grep -qx "$version_test_numeric_b" ; then
return 0
else
return 1
diff --git a/util/grub-rpm-sort.8 b/util/grub-rpm-sort.8
new file mode 100644
index 00000000000..8ce21488448
--- /dev/null
+++ b/util/grub-rpm-sort.8
@@ -0,0 +1,12 @@
+.TH GRUB-RPM-SORT 8 "Wed Feb 26 2014"
+.SH NAME
+\fBgrub-rpm-sort\fR \(em Sort input according to RPM version compare.
+
+.SH SYNOPSIS
+\fBgrub-rpm-sort\fR [OPTIONS].
+
+.SH DESCRIPTION
+You should not normally run this program directly. Use grub-mkconfig instead.
+
+.SH SEE ALSO
+.BR "info grub"