summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pkg_install/lib
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2002-06-24 16:03:24 +0000
committermarkm <markm@FreeBSD.org>2002-06-24 16:03:24 +0000
commit8f058b4f92a8cd167524bace0f2b9f989a6fed17 (patch)
tree032be2ec1e27bc433f682c593ac36e767015fb2c /usr.sbin/pkg_install/lib
parente102a9b6dd829c7b39358e1bed4ae6be3a6758d7 (diff)
downloadFreeBSD-src-8f058b4f92a8cd167524bace0f2b9f989a6fed17.zip
FreeBSD-src-8f058b4f92a8cd167524bace0f2b9f989a6fed17.tar.gz
C replacement for the Perl5 code.
Submitted by: reg
Diffstat (limited to 'usr.sbin/pkg_install/lib')
-rw-r--r--usr.sbin/pkg_install/lib/lib.h2
-rw-r--r--usr.sbin/pkg_install/lib/version.c139
2 files changed, 134 insertions, 7 deletions
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
index 5a11712..6a01fac 100644
--- a/usr.sbin/pkg_install/lib/lib.h
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -203,6 +203,8 @@ int requiredby(const char *, struct reqr_by_head **, Boolean, Boolean);
/* Version */
int verscmp(Package *, int, int);
+const char *version_of(const char *, int *, int *);
+int version_cmp(const char *, const char *);
/* Externs */
extern Boolean Verbose;
diff --git a/usr.sbin/pkg_install/lib/version.c b/usr.sbin/pkg_install/lib/version.c
index dca95cc..8241961 100644
--- a/usr.sbin/pkg_install/lib/version.c
+++ b/usr.sbin/pkg_install/lib/version.c
@@ -14,6 +14,15 @@
* Maxim Sobolev
* 31 July 2001
*
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+
+/*
* Routines to assist with PLIST_FMT_VER numbers in the packing
* lists.
*
@@ -23,13 +32,6 @@
* value insted of the hash of an object this links points to.
*
*/
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-
int
verscmp(Package *pkg, int major, int minor)
{
@@ -44,3 +46,126 @@ verscmp(Package *pkg, int major, int minor)
return rval;
}
+
+/*
+ * version_of(pkgname, epoch, revision) returns a pointer to the version
+ * portion of a package name and the two special components.
+ *
+ * Jeremy D. Lea.
+ */
+const char *
+version_of(const char *pkgname, int *epoch, int *revision)
+{
+ char *ch;
+
+ if (pkgname == NULL)
+ errx(2, "%s: Passed NULL pkgname.", __func__);
+ if (epoch != NULL) {
+ if ((ch = strrchr(pkgname, ',')) == NULL)
+ *epoch = 0;
+ else
+ *epoch = atoi(&ch[1]);
+ }
+ if (revision != NULL) {
+ if ((ch = strrchr(pkgname, '_')) == NULL)
+ *revision = 0;
+ else
+ *revision = atoi(&ch[1]);
+ }
+ /* Cheat if we are just passed a version, not a valid package name */
+ if ((ch = strrchr(pkgname, '-')) == NULL)
+ return pkgname;
+ else
+ return &ch[1];
+}
+
+/*
+ * version_cmp(pkg1, pkg2) returns -1, 0 or 1 depending on if the version
+ * components of pkg1 is less than, equal to or greater than pkg2. No
+ * comparision of the basenames is done.
+ *
+ * The port verison is defined by:
+ * ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
+ * ${PORTEPOCH} supercedes ${PORTVERSION} supercedes ${PORTREVISION}.
+ * See the commit log for revision 1.349 of ports/Mk/bsd.port.mk
+ * for more information.
+ *
+ * The epoch and revision are defined to be a single number, while the rest
+ * of the version should conform to the porting guidelines. It can contain
+ * multiple components, seperated by a period, including letters.
+ *
+ * The tests below allow for significantly more latitude in the version
+ * numbers than is allowed in the guidelines. No point in wasting user's
+ * time enforcing them here. That's what flamewars are for.
+ *
+ * Jeremy D. Lea.
+ */
+int
+version_cmp(const char *pkg1, const char *pkg2)
+{
+ const char *c1, *c2, *v1, *v2;
+ char *t1, *t2;
+ int e1, e2, r1, r2, n1, n2;
+
+ v1 = version_of(pkg1, &e1, &r1);
+ v2 = version_of(pkg2, &e2, &r2);
+ /* Minor optimisation. */
+ if (strcmp(v1, v2) == 0)
+ return 0;
+ /* First compare epoch. */
+ if (e1 != e2)
+ return (e1 < e2 ? -1 : 1);
+ else {
+ /*
+ * We walk down the versions, trying to convert to numbers.
+ * We terminate when we reach an underscore, a comma or the
+ * string terminator, thanks to a nasty trick with strchr().
+ * strtol() conveniently gobbles up the chars it converts.
+ */
+ c1 = strchr("_,", v1[0]);
+ c2 = strchr("_,", v2[0]);
+ while (c1 == NULL && c2 == NULL) {
+ n1 = strtol(v1, &t1, 10);
+ n2 = strtol(v2, &t2, 10);
+ if (n1 != n2)
+ return (n1 < n2 ? -1 : 1);
+ /*
+ * The numbers are equal, check for letters. Assume they're
+ * letters purely because strtol() didn't chomp them.
+ */
+ c1 = strchr("_,.", t1[0]);
+ c2 = strchr("_,.", t2[0]);
+ if (c1 == NULL && c2 == NULL) {
+ /* Both have letters. Compare them. */
+ if (t1[0] != t2[0])
+ return (t1[0] < t2[0] ? -1 : 1);
+ /* Boring. The letters are equal. Carry on. */
+ v1 = &t1[1], v2 = &t2[1];
+ } else if (c1 == NULL) {
+ /*
+ * Letters are strange. After a number, a letter counts
+ * as greater, but after a period it's less.
+ */
+ return (isdigit(v1[0]) ? 1 : -1);
+ } else if (c2 == NULL) {
+ return (isdigit(v2[0]) ? -1 : 1);
+ } else {
+ /* Neither were letters. Advance over the period. */
+ v1 = (t1[0] == '.' ? &t1[1] : t1);
+ v2 = (t2[0] == '.' ? &t2[1] : t2);
+ }
+ c1 = strchr("_,", v1[0]);
+ c2 = strchr("_,", v2[0]);
+ }
+ /* If we got here, check if one version has something left. */
+ if (c1 == NULL)
+ return (isdigit(v1[0]) ? 1 : -1);
+ if (c2 == NULL)
+ return (isdigit(v2[0]) ? -1 : 1);
+ /* We've run out of version. Try the revision... */
+ if (r1 != r2)
+ return (r1 < r2 ? -1 : 1);
+ else
+ return 0;
+ }
+}
OpenPOWER on IntegriCloud