Blob Blame History Raw
From 63275852afc4ab0bd0c45ac80f8f865c222759ac Mon Sep 17 00:00:00 2001
From: Luca BRUNO <luca.bruno@coreos.com>
Date: Mon, 31 May 2021 10:15:55 +0000
Subject: [PATCH 1/6] lib: temporarily fork rpmver logic

This adds an internal temporary copy of the rpm version comparison
logic from librpmio (LGPL).
It allows relaxing the minimum library version to >= 4.14.
---
 Makefile-lib.am             |   1 +
 configure.ac                |   6 +
 src/lib/rpmostree-package.c |   7 +-
 src/lib/rpmver-private.c    | 223 ++++++++++++++++++++++++++++++++++++
 src/lib/rpmver-private.h    | 108 +++++++++++++++++
 5 files changed, 344 insertions(+), 1 deletion(-)
 create mode 100644 src/lib/rpmver-private.c
 create mode 100644 src/lib/rpmver-private.h

diff --git a/Makefile-lib.am b/Makefile-lib.am
index bef049e1e7..f9d67f5c57 100644
--- a/Makefile-lib.am
+++ b/Makefile-lib.am
@@ -28,6 +28,7 @@ librpmostree_1_la_SOURCES = \
 	src/lib/rpmostree.c \
 	src/lib/rpmostree-db.c \
 	src/lib/rpmostree-package.c \
+	src/lib/rpmver-private.c \
 	$(NULL)
 
 librpmostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libpriv -I$(srcdir)/src/lib \
diff --git a/configure.ac b/configure.ac
index e763781566..ef5551657f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,6 +53,12 @@ dnl RHEL8.1 has old libarchive
 AS_IF([pkg-config --atleast-version=3.3.3 libarchive],
   [AC_DEFINE([HAVE_LIBARCHIVE_ZSTD], 1, [Define if we have libarchive with zstd])])
 
+# rpmver is available in rpm >= 4.16, el8 is still on 4.14
+AC_SEARCH_LIBS([rpmverCmp], [rpm],
+  AC_DEFINE([BUILDOPT_HAVE_RPMVER], 1, [Whether rpmver API is available in librpmio]),
+  AC_DEFINE([BUILDOPT_HAVE_RPMVER], 0, [Whether rpmver API is available in librpmio])
+)
+
 dnl We don't *actually* use this ourself, but librepo does, and libdnf gets confused
 dnl if librepo doesn't support it.
 have_zchunk=no
diff --git a/src/lib/rpmostree-package.c b/src/lib/rpmostree-package.c
index 8575c4a5ed..3bb03bfef0 100644
--- a/src/lib/rpmostree-package.c
+++ b/src/lib/rpmostree-package.c
@@ -32,12 +32,17 @@
 
 #include <string.h>
 #include <stdlib.h>
-#include <rpm/rpmver.h>
 #include "libglnx.h"
 
 #include "rpmostree-shlib-ipc-private.h"
 #include "rpmostree-package-priv.h"
 
+#if BUILDOPT_HAVE_RPMVER
+#include <rpm/rpmver.h>
+#else
+#include "rpmver-private.h"
+#endif
+
 typedef GObjectClass RpmOstreePackageClass;
 
 /* Since the class is small, we perform a poor man's polymorphism; RpmOstreePackage objects
diff --git a/src/lib/rpmver-private.c b/src/lib/rpmver-private.c
new file mode 100644
index 0000000000..117df79206
--- /dev/null
+++ b/src/lib/rpmver-private.c
@@ -0,0 +1,223 @@
+// Temporary forked internal copy of:
+// https://github.com/rpm-software-management/rpm/blob/rpm-4.16.1.3/rpmio/rpmver.c
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+/* NOTE(lucab): compatibility changes to avoid touching the source.
+ *  The *malloc functions have different behaviors when size=0, but this is not
+ *  a concern here because all calls in this file have strictly-positive size.
+ */
+#include "config.h"
+#if !BUILDOPT_HAVE_RPMVER
+#include <glib.h>
+#define xmalloc(_size) g_malloc((_size))
+#define free(_mem) g_free((_mem))
+#include "rpmver-private.h"
+
+#include <rpm/rpmstring.h>
+#include <stdlib.h>
+
+struct rpmver_s {
+    const char *e;
+    const char *v;
+    const char *r;
+    char arena[];
+};
+
+/**
+ * Split EVR into epoch, version, and release components.
+ * @param evr		[epoch:]version[-release] string
+ * @retval *ep		pointer to epoch
+ * @retval *vp		pointer to version
+ * @retval *rp		pointer to release
+ */
+static
+void parseEVR(char * evr,
+		const char ** ep,
+		const char ** vp,
+		const char ** rp)
+{
+    const char *epoch;
+    const char *version;		/* assume only version is present */
+    const char *release;
+    char *s, *se;
+
+    s = evr;
+    while (*s && risdigit(*s)) s++;	/* s points to epoch terminator */
+    se = strrchr(s, '-');		/* se points to version terminator */
+
+    if (*s == ':') {
+	epoch = evr;
+	*s++ = '\0';
+	version = s;
+	if (*epoch == '\0') epoch = "0";
+    } else {
+	epoch = NULL;	/* XXX disable epoch compare if missing */
+	version = evr;
+    }
+    if (se) {
+	*se++ = '\0';
+	release = se;
+    } else {
+	release = NULL;
+    }
+
+    if (ep) *ep = epoch;
+    if (vp) *vp = version;
+    if (rp) *rp = release;
+}
+
+int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2)
+{
+    int sense = 0;
+    int result = 0;
+
+    /* Compare {A,B} [epoch:]version[-release] */
+    if (v1->e && *v1->e && v2->e && *v2->e)
+	sense = rpmvercmp(v1->e, v2->e);
+    else if (v1->e && *v1->e && atol(v1->e) > 0) {
+	sense = 1;
+    } else if (v2->e && *v2->e && atol(v2->e) > 0)
+	sense = -1;
+
+    if (sense == 0) {
+	sense = rpmvercmp(v1->v, v2->v);
+	if (sense == 0) {
+	    if (v1->r && *v1->r && v2->r && *v2->r) {
+		sense = rpmvercmp(v1->r, v2->r);
+	    } else {
+		/* always matches if the side with no release has SENSE_EQUAL */
+		if ((v1->r && *v1->r && (f2 & RPMSENSE_EQUAL)) ||
+		    (v2->r && *v2->r && (f1 & RPMSENSE_EQUAL))) {
+		    result = 1;
+		    goto exit;
+		}
+	    }
+	}
+    }
+
+    /* Detect overlap of {A,B} range. */
+    if (sense < 0 && ((f1 & RPMSENSE_GREATER) || (f2 & RPMSENSE_LESS))) {
+	result = 1;
+    } else if (sense > 0 && ((f1 & RPMSENSE_LESS) || (f2 & RPMSENSE_GREATER))) {
+	result = 1;
+    } else if (sense == 0 &&
+	(((f1 & RPMSENSE_EQUAL) && (f2 & RPMSENSE_EQUAL)) ||
+	 ((f1 & RPMSENSE_LESS) && (f2 & RPMSENSE_LESS)) ||
+	 ((f1 & RPMSENSE_GREATER) && (f2 & RPMSENSE_GREATER)))) {
+	result = 1;
+    }
+
+exit:
+    return result;
+}
+
+static int compare_values(const char *str1, const char *str2)
+{
+    if (!str1 && !str2)
+	return 0;
+    else if (str1 && !str2)
+	return 1;
+    else if (!str1 && str2)
+	return -1;
+    return rpmvercmp(str1, str2);
+}
+
+int rpmverCmp(rpmver v1, rpmver v2)
+{
+    const char *e1 = (v1->e != NULL) ? v1->e : "0";
+    const char *e2 = (v2->e != NULL) ? v2->e : "0";
+
+    int rc = compare_values(e1, e2);
+    if (!rc) {
+	rc = compare_values(v1->v, v2->v);
+	if (!rc)
+	    rc = compare_values(v1->r, v2->r);
+    }
+    return rc;
+}
+
+uint32_t rpmverEVal(rpmver rv)
+{
+    return (rv != NULL && rv->e != NULL) ? atol(rv->e) : 0;
+}
+
+const char *rpmverE(rpmver rv)
+{
+    return (rv != NULL) ? rv->e : NULL;
+}
+
+const char *rpmverV(rpmver rv)
+{
+    return (rv != NULL) ? rv->v : NULL;
+}
+
+const char *rpmverR(rpmver rv)
+{
+    return (rv != NULL) ? rv->r : NULL;
+}
+
+char *rpmverEVR(rpmver rv)
+{
+    char *EVR = NULL;
+    if (rv) {
+	rstrscat(&EVR, rv->e ? rv-> e : "", rv->e ? ":" : "",
+		       rv->v,
+		       rv->r ? "-" : "", rv->r ? rv->r : "", NULL);
+    }
+    return EVR;
+}
+
+rpmver rpmverParse(const char *evr)
+{
+    rpmver rv = NULL;
+    if (evr && *evr) {
+	size_t evrlen = strlen(evr) + 1;
+	rv = xmalloc(sizeof(*rv) + evrlen);
+	memcpy(rv->arena, evr, evrlen);
+	parseEVR(rv->arena, &rv->e, &rv->v, &rv->r);
+    }
+    return rv;
+}
+
+rpmver rpmverNew(const char *e, const char *v, const char *r)
+{
+    rpmver rv = NULL;
+
+    if (v && *v) {
+	size_t nb = strlen(v) + 1;
+	nb += (e != NULL) ? strlen(e) + 1 : 0;
+	nb += (r != NULL) ? strlen(r) + 1 : 0;
+	rv = xmalloc(sizeof(*rv) + nb);
+
+	rv->e = NULL;
+	rv->v = NULL;
+	rv->r = NULL;
+
+	char *p = rv->arena;
+	if (e) {
+	    rv->e = p;
+	    p = stpcpy(p, e);
+	    p++;
+	}
+
+	rv->v = p;
+	p = stpcpy(p, v);
+	p++;
+
+	if (r) {
+	    rv->r = p;
+	    p = stpcpy(p, r);
+	    p++;
+	}
+    }
+    return rv;
+}
+
+rpmver rpmverFree(rpmver rv)
+{
+    if (rv) {
+	free(rv);
+    }
+    return NULL;
+}
+#endif
diff --git a/src/lib/rpmver-private.h b/src/lib/rpmver-private.h
new file mode 100644
index 0000000000..f875c2f9d3
--- /dev/null
+++ b/src/lib/rpmver-private.h
@@ -0,0 +1,108 @@
+// Temporary forked internal copy of
+// https://github.com/rpm-software-management/rpm/blob/rpm-4.16.1.3/rpmio/rpmver.h
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#ifndef _RPMVER_H
+#define _RPMVER_H
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmds.h>		/* sense flags */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// NOTE(lucab): Backported from <rpm/rpmtypes.h>.
+#ifndef rpmver
+typedef struct rpmver_s * rpmver;
+#endif
+
+/** \ingroup rpmver
+ * Segmented string compare for version or release strings.
+ *
+ * @param a		1st string
+ * @param b		2nd string
+ * @return		+1 if a is "newer", 0 if equal, -1 if b is "newer"
+ */
+int rpmvercmp(const char * a, const char * b);
+
+/** \ingroup rpmver
+ * Parse rpm version handle from evr string
+ *
+ * @param evr		[epoch:]version[-release] string
+ * @return		rpm version, NULL on invalid evr
+ */
+rpmver rpmverParse(const char *evr);
+
+/** \ingroup rpmver
+ * Create new rpm version handle from e, v, r components
+ *
+ * @param e		epoch (or NULL)
+ * @param v		version
+ * @param r		release (or NULL)
+ * @return		rpm version, NULL on invalid
+ */
+rpmver rpmverNew(const char *e, const char *v, const char *r);
+
+/** \ingroup rpmver
+ * Free rpm version handle
+ *
+ * @param rv		rpm version handle
+ * @return		NULL always
+ */
+rpmver rpmverFree(rpmver rv);
+
+/** \ingroup rpmver
+ * @param rv		rpm version handle
+ * @return		numerical value of epoch
+ */
+uint32_t rpmverEVal(rpmver rv);
+
+/** \ingroup rpmver
+ * @param rv		rpm version handle
+ * @return		epoch portion
+ */
+const char *rpmverE(rpmver rv);
+
+/** \ingroup rpmver
+ * @param rv		rpm version handle
+ * @return		version portion
+ */
+const char *rpmverV(rpmver rv);
+
+/** \ingroup rpmver
+ * @param rv		rpm version handle
+ * @return		release portion
+ */
+const char *rpmverR(rpmver rv);
+
+/** \ingroup rpmver
+ * @param rv		rpm version handle
+ * @return		formatted [E:]V[-R] string (malloced)
+ */
+char *rpmverEVR(rpmver rv);
+
+/** \ingroup rpmver
+ * Compare two rpm version handles
+ *
+ * @param v1		1st version handle
+ * @param v2		2nd version handle
+ * @return		0 if equal, -1 if v1 smaller, 1 if greater, than v2
+ */
+int rpmverCmp(rpmver v1, rpmver v2);
+
+/** \ingroup rpmver
+ * Determine whether two versioned ranges overlap.
+ * @param v1		1st version
+ * @param f1		1st sense flags
+ * @param v2		2nd version
+ * @param f2		2nd sense flags
+ * @return		1 if ranges overlap, 0 otherwise
+ */
+int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RPMVER_H */

From a74a3163b2ae315b5f95d9d7642e868794c47628 Mon Sep 17 00:00:00 2001
From: Luca BRUNO <luca.bruno@coreos.com>
Date: Mon, 31 May 2021 11:00:10 +0000
Subject: [PATCH 2/6] lib/rpmver: replace tabs with spaces

---
 src/lib/rpmver-private.c | 160 +++++++++++++++++++--------------------
 src/lib/rpmver-private.h |  60 +++++++--------
 2 files changed, 110 insertions(+), 110 deletions(-)

diff --git a/src/lib/rpmver-private.c b/src/lib/rpmver-private.c
index 117df79206..6882be0d1e 100644
--- a/src/lib/rpmver-private.c
+++ b/src/lib/rpmver-private.c
@@ -25,40 +25,40 @@ struct rpmver_s {
 
 /**
  * Split EVR into epoch, version, and release components.
- * @param evr		[epoch:]version[-release] string
- * @retval *ep		pointer to epoch
- * @retval *vp		pointer to version
- * @retval *rp		pointer to release
+ * @param evr                [epoch:]version[-release] string
+ * @retval *ep                pointer to epoch
+ * @retval *vp                pointer to version
+ * @retval *rp                pointer to release
  */
 static
 void parseEVR(char * evr,
-		const char ** ep,
-		const char ** vp,
-		const char ** rp)
+                const char ** ep,
+                const char ** vp,
+                const char ** rp)
 {
     const char *epoch;
-    const char *version;		/* assume only version is present */
+    const char *version;                /* assume only version is present */
     const char *release;
     char *s, *se;
 
     s = evr;
-    while (*s && risdigit(*s)) s++;	/* s points to epoch terminator */
-    se = strrchr(s, '-');		/* se points to version terminator */
+    while (*s && risdigit(*s)) s++;        /* s points to epoch terminator */
+    se = strrchr(s, '-');                /* se points to version terminator */
 
     if (*s == ':') {
-	epoch = evr;
-	*s++ = '\0';
-	version = s;
-	if (*epoch == '\0') epoch = "0";
+        epoch = evr;
+        *s++ = '\0';
+        version = s;
+        if (*epoch == '\0') epoch = "0";
     } else {
-	epoch = NULL;	/* XXX disable epoch compare if missing */
-	version = evr;
+        epoch = NULL;        /* XXX disable epoch compare if missing */
+        version = evr;
     }
     if (se) {
-	*se++ = '\0';
-	release = se;
+        *se++ = '\0';
+        release = se;
     } else {
-	release = NULL;
+        release = NULL;
     }
 
     if (ep) *ep = epoch;
@@ -73,38 +73,38 @@ int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2)
 
     /* Compare {A,B} [epoch:]version[-release] */
     if (v1->e && *v1->e && v2->e && *v2->e)
-	sense = rpmvercmp(v1->e, v2->e);
+        sense = rpmvercmp(v1->e, v2->e);
     else if (v1->e && *v1->e && atol(v1->e) > 0) {
-	sense = 1;
+        sense = 1;
     } else if (v2->e && *v2->e && atol(v2->e) > 0)
-	sense = -1;
+        sense = -1;
 
     if (sense == 0) {
-	sense = rpmvercmp(v1->v, v2->v);
-	if (sense == 0) {
-	    if (v1->r && *v1->r && v2->r && *v2->r) {
-		sense = rpmvercmp(v1->r, v2->r);
-	    } else {
-		/* always matches if the side with no release has SENSE_EQUAL */
-		if ((v1->r && *v1->r && (f2 & RPMSENSE_EQUAL)) ||
-		    (v2->r && *v2->r && (f1 & RPMSENSE_EQUAL))) {
-		    result = 1;
-		    goto exit;
-		}
-	    }
-	}
+        sense = rpmvercmp(v1->v, v2->v);
+        if (sense == 0) {
+            if (v1->r && *v1->r && v2->r && *v2->r) {
+                sense = rpmvercmp(v1->r, v2->r);
+            } else {
+                /* always matches if the side with no release has SENSE_EQUAL */
+                if ((v1->r && *v1->r && (f2 & RPMSENSE_EQUAL)) ||
+                    (v2->r && *v2->r && (f1 & RPMSENSE_EQUAL))) {
+                    result = 1;
+                    goto exit;
+                }
+            }
+        }
     }
 
     /* Detect overlap of {A,B} range. */
     if (sense < 0 && ((f1 & RPMSENSE_GREATER) || (f2 & RPMSENSE_LESS))) {
-	result = 1;
+        result = 1;
     } else if (sense > 0 && ((f1 & RPMSENSE_LESS) || (f2 & RPMSENSE_GREATER))) {
-	result = 1;
+        result = 1;
     } else if (sense == 0 &&
-	(((f1 & RPMSENSE_EQUAL) && (f2 & RPMSENSE_EQUAL)) ||
-	 ((f1 & RPMSENSE_LESS) && (f2 & RPMSENSE_LESS)) ||
-	 ((f1 & RPMSENSE_GREATER) && (f2 & RPMSENSE_GREATER)))) {
-	result = 1;
+        (((f1 & RPMSENSE_EQUAL) && (f2 & RPMSENSE_EQUAL)) ||
+         ((f1 & RPMSENSE_LESS) && (f2 & RPMSENSE_LESS)) ||
+         ((f1 & RPMSENSE_GREATER) && (f2 & RPMSENSE_GREATER)))) {
+        result = 1;
     }
 
 exit:
@@ -114,11 +114,11 @@ int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2)
 static int compare_values(const char *str1, const char *str2)
 {
     if (!str1 && !str2)
-	return 0;
+        return 0;
     else if (str1 && !str2)
-	return 1;
+        return 1;
     else if (!str1 && str2)
-	return -1;
+        return -1;
     return rpmvercmp(str1, str2);
 }
 
@@ -129,9 +129,9 @@ int rpmverCmp(rpmver v1, rpmver v2)
 
     int rc = compare_values(e1, e2);
     if (!rc) {
-	rc = compare_values(v1->v, v2->v);
-	if (!rc)
-	    rc = compare_values(v1->r, v2->r);
+        rc = compare_values(v1->v, v2->v);
+        if (!rc)
+            rc = compare_values(v1->r, v2->r);
     }
     return rc;
 }
@@ -160,9 +160,9 @@ char *rpmverEVR(rpmver rv)
 {
     char *EVR = NULL;
     if (rv) {
-	rstrscat(&EVR, rv->e ? rv-> e : "", rv->e ? ":" : "",
-		       rv->v,
-		       rv->r ? "-" : "", rv->r ? rv->r : "", NULL);
+        rstrscat(&EVR, rv->e ? rv-> e : "", rv->e ? ":" : "",
+                       rv->v,
+                       rv->r ? "-" : "", rv->r ? rv->r : "", NULL);
     }
     return EVR;
 }
@@ -171,10 +171,10 @@ rpmver rpmverParse(const char *evr)
 {
     rpmver rv = NULL;
     if (evr && *evr) {
-	size_t evrlen = strlen(evr) + 1;
-	rv = xmalloc(sizeof(*rv) + evrlen);
-	memcpy(rv->arena, evr, evrlen);
-	parseEVR(rv->arena, &rv->e, &rv->v, &rv->r);
+        size_t evrlen = strlen(evr) + 1;
+        rv = xmalloc(sizeof(*rv) + evrlen);
+        memcpy(rv->arena, evr, evrlen);
+        parseEVR(rv->arena, &rv->e, &rv->v, &rv->r);
     }
     return rv;
 }
@@ -184,31 +184,31 @@ rpmver rpmverNew(const char *e, const char *v, const char *r)
     rpmver rv = NULL;
 
     if (v && *v) {
-	size_t nb = strlen(v) + 1;
-	nb += (e != NULL) ? strlen(e) + 1 : 0;
-	nb += (r != NULL) ? strlen(r) + 1 : 0;
-	rv = xmalloc(sizeof(*rv) + nb);
-
-	rv->e = NULL;
-	rv->v = NULL;
-	rv->r = NULL;
-
-	char *p = rv->arena;
-	if (e) {
-	    rv->e = p;
-	    p = stpcpy(p, e);
-	    p++;
-	}
-
-	rv->v = p;
-	p = stpcpy(p, v);
-	p++;
-
-	if (r) {
-	    rv->r = p;
-	    p = stpcpy(p, r);
-	    p++;
-	}
+        size_t nb = strlen(v) + 1;
+        nb += (e != NULL) ? strlen(e) + 1 : 0;
+        nb += (r != NULL) ? strlen(r) + 1 : 0;
+        rv = xmalloc(sizeof(*rv) + nb);
+
+        rv->e = NULL;
+        rv->v = NULL;
+        rv->r = NULL;
+
+        char *p = rv->arena;
+        if (e) {
+            rv->e = p;
+            p = stpcpy(p, e);
+            p++;
+        }
+
+        rv->v = p;
+        p = stpcpy(p, v);
+        p++;
+
+        if (r) {
+            rv->r = p;
+            p = stpcpy(p, r);
+            p++;
+        }
     }
     return rv;
 }
@@ -216,7 +216,7 @@ rpmver rpmverNew(const char *e, const char *v, const char *r)
 rpmver rpmverFree(rpmver rv)
 {
     if (rv) {
-	free(rv);
+        free(rv);
     }
     return NULL;
 }
diff --git a/src/lib/rpmver-private.h b/src/lib/rpmver-private.h
index f875c2f9d3..458279e202 100644
--- a/src/lib/rpmver-private.h
+++ b/src/lib/rpmver-private.h
@@ -6,7 +6,7 @@
 #define _RPMVER_H
 
 #include <rpm/rpmtypes.h>
-#include <rpm/rpmds.h>		/* sense flags */
+#include <rpm/rpmds.h>                /* sense flags */
 
 #ifdef __cplusplus
 extern "C" {
@@ -20,84 +20,84 @@ typedef struct rpmver_s * rpmver;
 /** \ingroup rpmver
  * Segmented string compare for version or release strings.
  *
- * @param a		1st string
- * @param b		2nd string
- * @return		+1 if a is "newer", 0 if equal, -1 if b is "newer"
+ * @param a                1st string
+ * @param b                2nd string
+ * @return                +1 if a is "newer", 0 if equal, -1 if b is "newer"
  */
 int rpmvercmp(const char * a, const char * b);
 
 /** \ingroup rpmver
  * Parse rpm version handle from evr string
  *
- * @param evr		[epoch:]version[-release] string
- * @return		rpm version, NULL on invalid evr
+ * @param evr                [epoch:]version[-release] string
+ * @return                rpm version, NULL on invalid evr
  */
 rpmver rpmverParse(const char *evr);
 
 /** \ingroup rpmver
  * Create new rpm version handle from e, v, r components
  *
- * @param e		epoch (or NULL)
- * @param v		version
- * @param r		release (or NULL)
- * @return		rpm version, NULL on invalid
+ * @param e                epoch (or NULL)
+ * @param v                version
+ * @param r                release (or NULL)
+ * @return                rpm version, NULL on invalid
  */
 rpmver rpmverNew(const char *e, const char *v, const char *r);
 
 /** \ingroup rpmver
  * Free rpm version handle
  *
- * @param rv		rpm version handle
- * @return		NULL always
+ * @param rv                rpm version handle
+ * @return                NULL always
  */
 rpmver rpmverFree(rpmver rv);
 
 /** \ingroup rpmver
- * @param rv		rpm version handle
- * @return		numerical value of epoch
+ * @param rv                rpm version handle
+ * @return                numerical value of epoch
  */
 uint32_t rpmverEVal(rpmver rv);
 
 /** \ingroup rpmver
- * @param rv		rpm version handle
- * @return		epoch portion
+ * @param rv                rpm version handle
+ * @return                epoch portion
  */
 const char *rpmverE(rpmver rv);
 
 /** \ingroup rpmver
- * @param rv		rpm version handle
- * @return		version portion
+ * @param rv                rpm version handle
+ * @return                version portion
  */
 const char *rpmverV(rpmver rv);
 
 /** \ingroup rpmver
- * @param rv		rpm version handle
- * @return		release portion
+ * @param rv                rpm version handle
+ * @return                release portion
  */
 const char *rpmverR(rpmver rv);
 
 /** \ingroup rpmver
- * @param rv		rpm version handle
- * @return		formatted [E:]V[-R] string (malloced)
+ * @param rv                rpm version handle
+ * @return                formatted [E:]V[-R] string (malloced)
  */
 char *rpmverEVR(rpmver rv);
 
 /** \ingroup rpmver
  * Compare two rpm version handles
  *
- * @param v1		1st version handle
- * @param v2		2nd version handle
- * @return		0 if equal, -1 if v1 smaller, 1 if greater, than v2
+ * @param v1                1st version handle
+ * @param v2                2nd version handle
+ * @return                0 if equal, -1 if v1 smaller, 1 if greater, than v2
  */
 int rpmverCmp(rpmver v1, rpmver v2);
 
 /** \ingroup rpmver
  * Determine whether two versioned ranges overlap.
- * @param v1		1st version
- * @param f1		1st sense flags
- * @param v2		2nd version
- * @param f2		2nd sense flags
- * @return		1 if ranges overlap, 0 otherwise
+ * @param v1                1st version
+ * @param f1                1st sense flags
+ * @param v2                2nd version
+ * @param f2                2nd sense flags
+ * @return                1 if ranges overlap, 0 otherwise
  */
 int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2);