[Rpm-maint] [PATCH] Recognize "<epoch>:" as a part of a label (ticket #117)

Ales Kozumplik akozumpl at redhat.com
Wed Nov 16 10:17:24 UTC 2011


- for instance this works now:
  $ rpm -q perl-4:5.14.1-188.fc16.x86_64
  perl-5.14.1-188.fc16.x86_64
---
 lib/rpmdb.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index e249998..7d4b31e 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -118,6 +118,31 @@ static unsigned int uintId(unsigned int a)
 }
 
 /** \ingroup dbi
+ * Return (newly allocated) integer of the epoch.
+ * @param s		version string optionally containing epoch number
+ * @retval version	only the version part of s
+ * @return		epoch integer within the [0; UINT32_MAX] interval,
+ *                      or -1 for no epoch
+ */
+static long int splitEpoch(const char *s, const char **version)
+{
+    long int e;
+    char *end;
+    int saveerrno = errno;
+
+    *version = s;
+    e = strtol(s, &end, 10);
+    if (*end == ':' && e >= 0 && e <= UINT32_MAX) {
+	*version = end + 1;
+    } else {
+	e = -1;
+    }
+
+    errno = saveerrno;
+    return e;
+}
+
+/** \ingroup dbi
  * Return handle for an index database.
  * @param db		rpm database
  * @param rpmtag	rpm tag
@@ -1026,6 +1051,7 @@ int rpmdbCountPackages(rpmdb db, const char * name)
  * @param db		rpmdb handle
  * @param dbc		index database cursor
  * @param name		package name
+ * @param epoch 	package epoch (-1 for any epoch)
  * @param version	package version (can be a pattern)
  * @param release	package release (can be a pattern)
  * @retval matches	set of header instances that match
@@ -1033,6 +1059,7 @@ int rpmdbCountPackages(rpmdb db, const char * name)
  */
 static rpmRC dbiFindMatches(rpmdb db, dbiCursor dbc,
 		const char * name,
+		long int epoch,
 		const char * version,
 		const char * release,
 		dbiIndexSet * matches)
@@ -1045,7 +1072,7 @@ static rpmRC dbiFindMatches(rpmdb db, dbiCursor dbc,
 
     if (rc != 0) {
 	return (rc == DB_NOTFOUND) ? RPMRC_NOTFOUND : RPMRC_FAIL;
-    } else if (version == NULL && release == NULL) {
+    } else if (epoch < 0 && version == NULL && release == NULL) {
 	return RPMRC_OK;
     }
 
@@ -1075,6 +1102,14 @@ static rpmRC dbiFindMatches(rpmdb db, dbiCursor dbc,
 	}
 
 	h = rpmdbNextIterator(mi);
+
+	if (epoch >= 0 && h) {
+	    struct rpmtd_s td;
+	    headerGet(h, RPMTAG_EPOCH, &td, HEADERGET_MINMEM);
+	    if (epoch != rpmtdGetNumber(&td))
+		h = NULL;
+	    rpmtdFreeData(&td);
+	}
 	if (h)
 	    (*matches)->recs[gotMatches++] = (*matches)->recs[i];
 	else
@@ -1101,7 +1136,7 @@ exit:
  * @todo Name must be an exact match, as name is a db key.
  * @param db		rpmdb handle
  * @param dbi		index database handle (always RPMDBI_NAME)
- * @param arg		name[-version[-release]] string
+ * @param arg		name[-[epoch:]version[-release]] string
  * @retval matches	set of header instances that match
  * @return 		RPMRC_OK on match, RPMRC_NOMATCH or RPMRC_FAIL
  */
@@ -1110,25 +1145,27 @@ static rpmRC dbiFindByLabel(rpmdb db, dbiIndex dbi, const char * arg,
 {
     size_t arglen = (arg != NULL) ? strlen(arg) : 0;
     char localarg[arglen+1];
+    long int epoch;
+    const char * version;
     const char * release;
     char * s;
     char c;
     int brackets;
     rpmRC rc;
     dbiCursor dbc;
- 
+
     if (arglen == 0) return RPMRC_NOTFOUND;
 
     dbc = dbiCursorInit(dbi, 0);
     /* did they give us just a name? */
-    rc = dbiFindMatches(db, dbc, arg, NULL, NULL, matches);
+    rc = dbiFindMatches(db, dbc, arg, -1, NULL, NULL, matches);
     if (rc != RPMRC_NOTFOUND)
 	goto exit;
 
     /* FIX: double indirection */
     *matches = dbiIndexSetFree(*matches);
 
-    /* maybe a name and a release */
+    /* maybe a name-[epoch:]version ? */
     s = stpcpy(localarg, arg);
 
     c = '\0';
@@ -1154,13 +1191,15 @@ static rpmRC dbiFindByLabel(rpmdb db, dbiIndex dbi, const char * arg,
     }
 
     *s = '\0';
-    rc = dbiFindMatches(db, dbc, localarg, s + 1, NULL, matches);
+
+    epoch = splitEpoch(s + 1, &version);
+    rc = dbiFindMatches(db, dbc, localarg, epoch, version, NULL, matches);
     if (rc != RPMRC_NOTFOUND) goto exit;
 
     /* FIX: double indirection */
     *matches = dbiIndexSetFree(*matches);
-    
-    /* how about name-version-release? */
+
+    /* how about name-[epoch:]version-release? */
 
     release = s + 1;
 
@@ -1187,7 +1226,8 @@ static rpmRC dbiFindByLabel(rpmdb db, dbiIndex dbi, const char * arg,
 
     *s = '\0';
    	/* FIX: *matches may be NULL. */
-    rc = dbiFindMatches(db, dbc, localarg, s + 1, release, matches);
+    epoch = splitEpoch(s + 1, &version);
+    rc = dbiFindMatches(db, dbc, localarg, epoch, version, release, matches);
 exit:
     dbiCursorFree(dbc);
     return rc;
-- 
1.7.7.3



More information about the Rpm-maint mailing list