diff -up s390-tools-2.9.0/zipl/src/Makefile.blscfg-rpm-nvr-sort s390-tools-2.9.0/zipl/src/Makefile --- s390-tools-2.9.0/zipl/src/Makefile.blscfg-rpm-nvr-sort 2019-05-22 08:16:17.317273801 -0400 +++ s390-tools-2.9.0/zipl/src/Makefile 2019-05-22 08:18:02.947273801 -0400 @@ -7,7 +7,7 @@ ALL_CPPFLAGS += -I../include -I../boot \ -D_FILE_OFFSET_BITS=64 $(NO_PIE_CFLAGS) ALL_LDFLAGS += -Wl,-z,noexecstack $(NO_PIE_LDFLAGS) -libs = $(rootdir)/libutil/libutil.a +libs = $(rootdir)/libutil/libutil.a -lrpmio objects = misc.o error.o scan.o job.o boot.o bootmap.o disk.o \ install.o zipl.o $(rootdir)/zipl/boot/data.o diff -up s390-tools-2.9.0/zipl/src/scan.c.blscfg-rpm-nvr-sort s390-tools-2.9.0/zipl/src/scan.c --- s390-tools-2.9.0/zipl/src/scan.c.blscfg-rpm-nvr-sort 2019-05-21 09:13:36.000000000 -0400 +++ s390-tools-2.9.0/zipl/src/scan.c 2019-05-22 08:16:17.317273801 -0400 @@ -33,6 +33,8 @@ #include "lib/util_base.h" +#include + #include "boot.h" #include "error.h" #include "misc.h" @@ -653,13 +655,103 @@ bls_filter(const struct dirent *ent) return strncmp(ent->d_name + offset, ".conf", strlen(".conf")) == 0; } +/* 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 == NULL) { + *name = (*version == NULL ? *release : *version); + *version = *release; + *release = NULL; + } + if (*version == NULL) { + *version = *release; + *release = NULL; + } +} static int -bls_sort(const struct dirent **ent_a, const struct dirent **ent_b) +split_cmp(char *nvr0, char *nvr1, int has_name) +{ + int ret = 0; + char *name0, *version0, *release0; + char *name1, *version1, *release1; + + split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0); + split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1); + + if (has_name) { + ret = rpmvercmp(name0 == NULL ? "" : name0, + name1 == NULL ? "" : name1); + if (ret != 0) + return ret; + } + + ret = rpmvercmp(version0 == NULL ? "" : version0, + version1 == NULL ? "" : version1); + if (ret != 0) + return ret; + + ret = rpmvercmp(release0 == NULL ? "" : release0, + release1 == NULL ? "" : release1); + return ret; +} + +/* return 1: filename0 is newer than filename1 */ +/* 0: filename0 and filename1 are the same version */ +/* -1: filename1 is newer than filename0 */ +static int bls_cmp(const char *filename0, const char *filename1) { - return strverscmp((*ent_a)->d_name, (*ent_b)->d_name); + char *id0, *id1; + int l, r; + + id0 = strdup(filename0); + id1 = strdup(filename1); + + l = strlen(id0); + if (l > 5 && strcmp(id0 + l - 5, ".conf")) + id0[l-5] = '\0'; + + l = strlen(id1); + if (l > 5 && strcmp(id1 + l - 5, ".conf")) + id1[l-5] = '\0'; + + r = split_cmp(id0, id1, 1); + + free(id0); + free(id1); + + return r; } +static int +bls_sort(const struct dirent **ent_a, const struct dirent **ent_b) +{ + return bls_cmp((*ent_a)->d_name, (*ent_b)->d_name); +} static int scan_append_section_heading(struct scan_token* scan, int* index, char* name);