7e98da058f
This change reorganizes and cleanups our patches to reduce the patch number from 314 patches to 187. That's achieved by dropping patches that are later reverted and squashing fixes for earlier patches that introduced features. There are no code changes and the diff with upstream is the same before and after the cleanup. Having fewer patches makes easier to manage the patchset and also will ease to rebase them on top of the latest grub-2.04 release. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
462 lines
12 KiB
Diff
462 lines
12 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 Distribution Package Sort for grub2-mkconfig (#1124074)
|
|
|
|
Users reported that newly installed kernels on their systems installed
|
|
with grub-mkconfig would not appear on the grub boot list in order
|
|
starting with the most recent. Added an option for rpm-based systems to
|
|
use the rpm-sort library to sort kernels instead.
|
|
|
|
Resolves rhbz#1124074
|
|
|
|
Signed-off-by: Robert Marshall <rmarshall@redhat.com>
|
|
[pjones: fix --enable-rpm-sort configure option]
|
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
---
|
|
configure.ac | 29 +++++
|
|
Makefile.util.def | 16 +++
|
|
util/grub-rpm-sort.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
.gitignore | 2 +
|
|
util/grub-mkconfig_lib.in | 11 +-
|
|
util/grub-rpm-sort.8 | 12 ++
|
|
6 files changed, 350 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 d5db2803ec4..00f1db29b1a 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -65,6 +65,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])
|
|
@@ -88,6 +89,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])
|
|
@@ -1790,6 +1792,33 @@ 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"
|
|
+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 rpm library.
|
|
+ AC_CHECK_LIB([rpm], [rpmvercmp], [],
|
|
+ [rpm_sort_excuse="rpmlib missing rpmvercmp"])
|
|
+fi
|
|
+
|
|
+if test x"$rpm_sort_excuse" = x ; then
|
|
+ LIBRPM="-lrpm";
|
|
+ AC_DEFINE([HAVE_RPM], [1],
|
|
+ [Define to 1 if you have the rpm library.])
|
|
+fi
|
|
+
|
|
+AC_SUBST([LIBRPM])
|
|
+
|
|
LIBGEOM=
|
|
if test x$host_kernel = xkfreebsd; then
|
|
AC_CHECK_LIB([geom], [geom_gettree], [],
|
|
diff --git a/Makefile.util.def b/Makefile.util.def
|
|
index 3efc5718ae8..bb21c87c8ed 100644
|
|
--- a/Makefile.util.def
|
|
+++ b/Makefile.util.def
|
|
@@ -687,6 +687,22 @@ 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 = grub-core/gnulib/libgnu.a;
|
|
+ ldadd = libgrubkern.a;
|
|
+ ldadd = '$(LIBDEVMAPPER) $(LIBRPM)';
|
|
+};
|
|
+
|
|
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/.gitignore b/.gitignore
|
|
index 43f04d47277..fa2e5b609b1 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -105,6 +105,8 @@ grub-*.tar.*
|
|
/grub*-reboot.8
|
|
/grub*-render-label
|
|
/grub*-render-label.1
|
|
+/grub*-rpm-sort
|
|
+/grub*-rpm-sort.8
|
|
/grub*-script-check
|
|
/grub*-script-check.1
|
|
/grub*-set-default
|
|
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
|
|
index 1a4a57898f9..113a41f9409 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 which gettext >/dev/null 2>/dev/null; then
|
|
:
|
|
@@ -214,6 +217,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"
|
|
@@ -230,7 +239,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"
|