Blame SOURCES/0240-blscfg-sort-everything-with-rpm-package-comparison.patch

d9d99f
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
d9d99f
From: Peter Jones <pjones@redhat.com>
d9d99f
Date: Mon, 15 Oct 2018 15:08:33 -0400
d9d99f
Subject: [PATCH] blscfg: sort everything with rpm *package* comparison
d9d99f
d9d99f
This makes comparisons use the n-v-r tuple, and compare name with name,
d9d99f
version with version, and release with release.
d9d99f
d9d99f
Related: rhbz#1638103
d9d99f
d9d99f
Signed-off-by: Peter Jones <pjones@redhat.com>
d9d99f
---
d9d99f
 grub-core/commands/blscfg.c | 118 ++++++++++++++++++++++++++++++++++++++++----
d9d99f
 1 file changed, 108 insertions(+), 10 deletions(-)
d9d99f
d9d99f
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
d9d99f
index 3847572dabd..347128c9ddd 100644
d9d99f
--- a/grub-core/commands/blscfg.c
d9d99f
+++ b/grub-core/commands/blscfg.c
d9d99f
@@ -206,7 +206,7 @@ static int vercmp(const char * a, const char * b)
d9d99f
     int isnum;
d9d99f
     int ret = 0;
d9d99f
 
d9d99f
-  grub_dprintf("blscfg", "%s got here\n", __func__);
d9d99f
+    grub_dprintf("blscfg", "%s got here\n", __func__);
d9d99f
     if (!grub_strcmp(a, b))
d9d99f
 	    return 0;
d9d99f
 
d9d99f
@@ -315,6 +315,81 @@ finish:
d9d99f
     return ret;
d9d99f
 }
d9d99f
 
d9d99f
+/* returns name/version/release */
d9d99f
+/* NULL string pointer returned if nothing found */
d9d99f
+static void
d9d99f
+split_package_string (char *package_string, char **name,
d9d99f
+                     char **version, char **release)
d9d99f
+{
d9d99f
+  char *package_version, *package_release;
d9d99f
+
d9d99f
+  /* Release */
d9d99f
+  package_release = grub_strrchr (package_string, '-');
d9d99f
+
d9d99f
+  if (package_release != NULL)
d9d99f
+      *package_release++ = '\0';
d9d99f
+
d9d99f
+  *release = package_release;
d9d99f
+
d9d99f
+  if (name == NULL)
d9d99f
+    {
d9d99f
+      *version = package_string;
d9d99f
+    }
d9d99f
+  else
d9d99f
+    {
d9d99f
+      /* Version */
d9d99f
+      package_version = grub_strrchr(package_string, '-');
d9d99f
+
d9d99f
+      if (package_version != NULL)
d9d99f
+	*package_version++ = '\0';
d9d99f
+
d9d99f
+      *version = package_version;
d9d99f
+      /* Name */
d9d99f
+      *name = package_string;
d9d99f
+    }
d9d99f
+
d9d99f
+  /* Bubble up non-null values from release to name */
d9d99f
+  if (name != NULL && *name == NULL)
d9d99f
+    {
d9d99f
+      *name = (*version == NULL ? *release : *version);
d9d99f
+      *version = *release;
d9d99f
+      *release = NULL;
d9d99f
+    }
d9d99f
+  if (*version == NULL)
d9d99f
+    {
d9d99f
+      *version = *release;
d9d99f
+      *release = NULL;
d9d99f
+    }
d9d99f
+}
d9d99f
+
d9d99f
+static int
d9d99f
+split_cmp(char *nvr0, char *nvr1, int has_name)
d9d99f
+{
d9d99f
+  int ret = 0;
d9d99f
+  char *name0, *version0, *release0;
d9d99f
+  char *name1, *version1, *release1;
d9d99f
+
d9d99f
+  split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0);
d9d99f
+  split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1);
d9d99f
+
d9d99f
+  if (has_name)
d9d99f
+    {
d9d99f
+      ret = vercmp(name0 == NULL ? "" : name0,
d9d99f
+		   name1 == NULL ? "" : name1);
d9d99f
+      if (ret != 0)
d9d99f
+	return ret;
d9d99f
+    }
d9d99f
+
d9d99f
+  ret = vercmp(version0 == NULL ? "" : version0,
d9d99f
+	       version1 == NULL ? "" : version1);
d9d99f
+  if (ret != 0)
d9d99f
+    return ret;
d9d99f
+
d9d99f
+  ret = vercmp(release0 == NULL ? "" : release0,
d9d99f
+	       release1 == NULL ? "" : release1);
d9d99f
+  return ret;
d9d99f
+}
d9d99f
+
d9d99f
 /* return 1: p0 is newer than p1 */
d9d99f
 /*        0: p0 and p1 are the same version */
d9d99f
 /*       -1: p1 is newer than p0 */
d9d99f
@@ -323,18 +398,41 @@ static int bls_cmp(const void *p0, const void *p1, void *state)
d9d99f
   struct bls_entry * e0 = *(struct bls_entry **)p0;
d9d99f
   struct bls_entry * e1 = *(struct bls_entry **)p1;
d9d99f
   bool use_version = *(bool *)state;
d9d99f
-  const char *v0, *v1;
d9d99f
-  int r;
d9d99f
+  char *v0, *v1;
d9d99f
+  char *id0, *id1;
d9d99f
+  int l, r;
d9d99f
 
d9d99f
-  if (use_version) {
d9d99f
-    v0 = bls_get_val(e0, "version", NULL);
d9d99f
-    v1 = bls_get_val(e1, "version", NULL);
d9d99f
+  if (use_version)
d9d99f
+    {
d9d99f
+      v0 = grub_strdup(bls_get_val(e0, "version", NULL));
d9d99f
+      v1 = grub_strdup(bls_get_val(e1, "version", NULL));
d9d99f
 
d9d99f
-    if ((r = vercmp(v0, v1)) != 0)
d9d99f
-      return r;
d9d99f
-  }
d9d99f
+      r = split_cmp(v0, v1, 0);
d9d99f
 
d9d99f
-  return vercmp(e0->filename, e1->filename);
d9d99f
+      grub_free(v0);
d9d99f
+      grub_free(v1);
d9d99f
+
d9d99f
+      if (r != 0)
d9d99f
+	return r;
d9d99f
+    }
d9d99f
+
d9d99f
+  id0 = grub_strdup(e0->filename);
d9d99f
+  id1 = grub_strdup(e1->filename);
d9d99f
+
d9d99f
+  l = grub_strlen(id0);
d9d99f
+  if (l > 5 && grub_strcmp(id0 + l - 5, ".conf"))
d9d99f
+    id0[l-5] = '\0';
d9d99f
+
d9d99f
+  l = grub_strlen(id1);
d9d99f
+  if (l > 5 && grub_strcmp(id1 + l - 5, ".conf"))
d9d99f
+    id1[l-5] = '\0';
d9d99f
+
d9d99f
+  r = split_cmp(id0, id1, 1);
d9d99f
+
d9d99f
+  grub_free(id0);
d9d99f
+  grub_free(id1);
d9d99f
+
d9d99f
+  return r;
d9d99f
 }
d9d99f
 
d9d99f
 struct read_entry_info {