diff options
-rw-r--r-- | Makefile.PL | 2 | ||||
-rw-r--r-- | URPM.xs | 121 |
2 files changed, 117 insertions, 6 deletions
diff --git a/Makefile.PL b/Makefile.PL index a35ba66..eb008bb 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -54,7 +54,7 @@ my $ldflags = `pkg-config --libs rpm`; if ($hversion ge hexversion("4.4.90") && $hversion lt hexversion("4.7")) { # rpm.org version push @rpmflags, "-DRPM_ORG"; - $ldflags .= ' -lrpmbuild'; + $ldflags .= ' -lrpmbuild -lpcreposix'; } my $ccflags = join(' ', '-Wall -Wextra -fno-strict-aliasing', @rpmflags); @@ -29,11 +29,127 @@ #undef Fstat #ifdef RPM_ORG +#include <pcreposix.h> +#include <rpm/rpmlib.h> +#include <rpm/rpmds.h> + static inline void *_free(const void * p) { if (p != NULL) free((void *)p); return NULL; } typedef struct rpmSpec_s * Spec; + +typedef struct EVR_s { + const char * str; /*!< EVR storage */ + unsigned long Elong; /*!< E converted to integer. */ + rpmsenseFlags Flags; /*!< EVR comparison flags. */ + const char * F[5]; /*!< Parsed fields (\1=E, \2=V, \3=R, \4=D). */ +#define RPMEVR_E 1 +#define RPMEVR_V 2 +#define RPMEVR_R 3 +#define RPMEVR_D 4 +} * EVR_t; + +static EVR_t rpmEVRnew(uint32_t Flags, int initialize) { + EVR_t evr = calloc(1, sizeof(*evr)); + evr->Flags = Flags; + if (initialize) { + evr->F[RPMEVR_E] = "0"; + evr->F[RPMEVR_V] = ""; + evr->F[RPMEVR_R] = ""; + evr->F[RPMEVR_D] = ""; + } + return evr; +} + +static EVR_t rpmEVRfree(EVR_t evr) { + if (evr != NULL) { + evr->str = _free(evr->str); + memset(evr, 0, sizeof(*evr)); + evr = _free(evr); + } + return NULL; +} + +static struct regexp_s { + int initialized; + regex_t regexp; +} re = { .initialized = 0 }; + +static const char evr_tuple_match[] = "^(?:([^:-]+):)?([^:-]+)(?:-([^:-]+))?(?::([^:-]+))?$"; + +static int rpmEVRparse(const char * evrstr, EVR_t evr) { + int noffsets = 6 * 3; + int offsets[6 * 3]; + size_t nb; + int xx; + int i; + + if(re.initialized == 0) + xx = pcreposix_regcomp(&(re.regexp), evr_tuple_match, REG_EXTENDED | REG_NEWLINE), + re.initialized = 1; + + memset(evr, 0, sizeof(*evr)); + evr->str = strdup(evrstr); + nb = strlen(evr->str); + + memset(offsets, -1, sizeof(offsets)); + + xx = pcreposix_regexec(&(re.regexp), evr->str, + noffsets/3, (regmatch_t *)offsets, 0); + + for (i = 0; i < noffsets; i += 2) { + int ix; + + if (offsets[i] < 0) + continue; + + switch (i/2) { + default: + case 0: continue; break; + case 1: ix = RPMEVR_E; break; + case 2: ix = RPMEVR_V; break; + case 3: ix = RPMEVR_R; break; + case 4: ix = RPMEVR_D; break; + } + +assert(offsets[i ] >= 0 && offsets[i ] <= (int)nb); +assert(offsets[i+1] >= 0 && offsets[i+1] <= (int)nb); + { char * te = (char *) evr->str; + evr->F[ix] = te + offsets[i]; + te += offsets[i+1]; + *te = '\0'; + } + + } + + if (evr->F[RPMEVR_E] == NULL) evr->F[RPMEVR_E] = "0"; + + evr->Elong = strtoul(evr->F[RPMEVR_E], NULL, 10); + + return 0; +} + +static int rpmEVRcompare(const EVR_t a, const EVR_t b) { + const char * s; + int rc = 0; + + for (s = "EVRD"; *s != '\0'; s++) { + int ix; + switch ((int)*s) { + default: continue; break; + case 'E': ix = RPMEVR_E; break; + case 'V': ix = RPMEVR_V; break; + case 'R': ix = RPMEVR_R; break; + case 'D': ix = RPMEVR_D; break; + } + rc = rpmvercmp(a->F[ix] ? a->F[ix] : "", b->F[ix] ? b->F[ix] : ""); + if (rc) + break; + } + return rc; +} + #else #include <rpm/rpm46compat.h> #endif @@ -296,10 +412,6 @@ get_nvra(Header h) { static int do_rpmEVRcmp(const char *a, const char *b) { int compare; -#ifdef RPM_ORG - /* TODO: implement EVR_t & friends locally? */ - compare = rpmvercmp(a, b); -#else EVR_t lEVR, rEVR; lEVR = rpmEVRnew(RPMSENSE_EQUAL, 0), @@ -309,7 +421,6 @@ do_rpmEVRcmp(const char *a, const char *b) { compare = rpmEVRcompare(lEVR, rEVR); lEVR = rpmEVRfree(lEVR), rEVR = rpmEVRfree(rEVR); -#endif return compare; } |