RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  j...@rpm5.org
  Module: rpm                              Date:   11-Jan-2009 19:50:31
  Branch: rpm-5_1                          Handle: 2009011118502902

  Modified files:           (Branch: rpm-5_1)
    rpm                     CHANGES macros.in
    rpm/build               parsePreamble.c parseReqs.c
    rpm/lib                 rpmds.c
    rpm/python              header-py.c
    rpm/rpmdb               librpmdb.vers rpmdpkg.c rpmdpkg.h rpmevr.c
                            rpmevr.h rpmns.c rpmns.h

  Log:
    -  rpmbuild: enumerate all the lexical patterns in parsePreamble().
    -  rpmbuild: enable pattern validation for simple package identifiers.
    -  rpmbuild: add tag data validation pattern checks.
    -  EVRtuple: handle EVR_t opaquely in python labelCompare().
    -  EVRtuple: postpone committing to single "missing" value for now.
    -  EVRtuple: attempt rpmEVRparse() during parseRCPOT().
        no error returns from rpmEVRparse() to trigger the message yet, todo++.
    -  EVRtuple: teach --whatneeds/--needswhat to use EVR_t opaquely.
    -  EVRtuple: add rpmEVR{new,free} creator and destructors.
    -  EVRtuple: mark the old EVRD parser for destruction.
    -  EVRtuple: use the new EVRD pattern parser, reverse the assert check.
    -  EVRtuple: precedence permutation for rpmdsCompare().
    -  EVRtuple: precedence permutation for rpmVersionCompare().
    -  EVRtuple: blueprint new <-> old parsers with an assert.
    -  EVRtuple: parse EVRD using RPMMIRE_REGEX & evr_tuple_match.
    -  EVRtuple: wire up evr_tuple_match RE pattern match.
    -  EVRtuple: wire up evr_tuple_order precedence permutation.
    -  EVRtuple: use array for tuple storage.

  Summary:
    Revision    Changes     Path
    1.2288.2.176+18 -0      rpm/CHANGES
    2.171.2.5   +65 -14     rpm/build/parsePreamble.c
    2.52.4.1    +19 -0      rpm/build/parseReqs.c
    2.94.2.6    +60 -21     rpm/lib/rpmds.c
    1.241.2.8   +11 -11     rpm/macros.in
    1.93.2.1    +12 -10     rpm/python/header-py.c
    1.43.2.6    +7  -0      rpm/rpmdb/librpmdb.vers
    1.6.2.3     +15 -13     rpm/rpmdb/rpmdpkg.c
    1.2.2.3     +1  -1      rpm/rpmdb/rpmdpkg.h
    1.29.2.3    +318 -43    rpm/rpmdb/rpmevr.c
    1.9.2.3     +48 -8      rpm/rpmdb/rpmevr.h
    1.10.2.4    +32 -24     rpm/rpmdb/rpmns.c
    1.3.2.3     +2  -2      rpm/rpmdb/rpmns.h
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/CHANGES
  ============================================================================
  $ cvs diff -u -r1.2288.2.175 -r1.2288.2.176 CHANGES
  --- rpm/CHANGES       11 Jan 2009 17:23:20 -0000      1.2288.2.175
  +++ rpm/CHANGES       11 Jan 2009 18:50:29 -0000      1.2288.2.176
  @@ -1,4 +1,22 @@
   5.1.6 -> 5.1.7:
  +    - jbj: rpmbuild: enumerate all the lexical patterns in parsePreamble().
  +    - jbj: rpmbuild: enable pattern validation for simple package 
identifiers.
  +    - jbj: rpmbuild: add tag data validation pattern checks.
  +    - jbj: EVRtuple: handle EVR_t opaquely in python labelCompare().
  +    - jbj: EVRtuple: postpone committing to single "missing" value for now.
  +    - jbj: EVRtuple: attempt rpmEVRparse() during parseRCPOT().
  +        no error returns from rpmEVRparse() to trigger the message yet, 
todo++.
  +    - jbj: EVRtuple: teach --whatneeds/--needswhat to use EVR_t opaquely.
  +    - jbj: EVRtuple: add rpmEVR{new,free} creator and destructors.
  +    - jbj: EVRtuple: mark the old EVRD parser for destruction.
  +    - jbj: EVRtuple: use the new EVRD pattern parser, reverse the assert 
check.
  +    - jbj: EVRtuple: precedence permutation for rpmdsCompare().
  +    - jbj: EVRtuple: precedence permutation for rpmVersionCompare().
  +    - jbj: EVRtuple: blueprint new <-> old parsers with an assert.
  +    - jbj: EVRtuple: parse EVRD using RPMMIRE_REGEX & evr_tuple_match.
  +    - jbj: EVRtuple: wire up evr_tuple_match RE pattern match.
  +    - jbj: EVRtuple: wire up evr_tuple_order precedence permutation.
  +    - jbj: EVRtuple: use array for tuple storage.
       - rse: EVRtuple: macro configuration parameterization.
       - jbj: add FNM_EXTMATCH to default flags w RPMMIRE_GLOB.
       - jbj: rpmsw: change bytes accumulator to unsigned long long.
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/build/parsePreamble.c
  ============================================================================
  $ cvs diff -u -r2.171.2.4 -r2.171.2.5 parsePreamble.c
  --- rpm/build/parsePreamble.c 18 Jun 2008 20:01:52 -0000      2.171.2.4
  +++ rpm/build/parsePreamble.c 11 Jan 2009 18:50:31 -0000      2.171.2.5
  @@ -6,6 +6,10 @@
   #include "system.h"
   
   #include <rpmio.h>
  +#include <rpmlog.h>
  +#include <rpmurl.h>
  +#include <argv.h>
  +#include <mire.h>
   
   #define      _RPMEVR_INTERNAL
   #define      _RPMTAG_INTERNAL        /* XXX rpmTags->aTags */
  @@ -22,6 +26,7 @@
       RPMTAG_EPOCH,
       RPMTAG_VERSION,
       RPMTAG_RELEASE,
  +    RPMTAG_DISTEPOCH,
       RPMTAG_LICENSE,
       RPMTAG_GROUP,            /* XXX permissive. */
       RPMTAG_SUMMARY,          /* XXX permissive. */
  @@ -92,7 +97,7 @@
   static int parseSimplePart(Spec spec, /*...@out@*/char ** Np,
                /*...@out@*/rpmParseState *flag)
        /*...@globals internalst...@*/
  -     /*...@modifies *name, *flag, internalState @*/
  +     /*...@modifies *Np, *flag, internalState, spec->line @*/
   {
       char * s, * se;
       int rc = 0;              /* assume failure */
  @@ -214,6 +219,7 @@
   
   /**
    */
  +/*...@null@*/
   static inline char * findLastChar(char * s)
        /*...@modifies *s @*/
   {
  @@ -236,7 +242,8 @@
   /**
    */
   static int isMemberInEntry(Header h, const char *name, rpmTag tag)
  -     /*...@*/
  +     /*...@globals internalState @*/
  +     /*...@modifies internalState @*/
   {
       HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
       int rc = -1;
  @@ -261,8 +268,8 @@
   /**
    */
   static int checkForValidArchitectures(Spec spec)
  -     /*...@globals rpmGlobalMacroContext, h_errno @*/
  -     /*...@modifies rpmGlobalMacroContext @*/
  +     /*...@globals rpmGlobalMacroContext, h_errno, internalState @*/
  +     /*...@modifies rpmGlobalMacroContext, internalState @*/
   {
       const char *arch = rpmExpand("%{_target_cpu}", NULL);
       const char *os = rpmExpand("%{_target_os}", NULL);
  @@ -298,7 +305,7 @@
    * @return           RPMRC_OK if OK
    */
   static rpmRC checkForRequired(Header h, const char * NVR)
  -     /*...@modifies h @*/
  +     /*...@*/
   {
       rpmTag * p;
       rpmRC rc = RPMRC_OK;
  @@ -322,7 +329,8 @@
    * @return           RPMRC_OK if OK
    */
   static rpmRC checkForDuplicates(Header h, const char * NVR)
  -     /*...@modifies h @*/
  +     /*...@globals internalState @*/
  +     /*...@modifies h, internalState @*/
   {
       HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
       HeaderIterator hi;
  @@ -356,7 +364,9 @@
   } optionalTags[] = {
       { RPMTAG_VENDOR,         "%{vendor}" },
       { RPMTAG_PACKAGER,               "%{packager}" },
  +    { RPMTAG_DISTEPOCH,      "%{distepoch}" },
       { RPMTAG_DISTRIBUTION,   "%{distribution}" },
  +    { RPMTAG_DISTTAG,                "%{disttag}" },
       { RPMTAG_DISTURL,                "%{disturl}" },
       { 0xffffffff,            "%{class}" },
       { -1, NULL }
  @@ -365,8 +375,8 @@
   /**
    */
   static void fillOutMainPackage(Header h)
  -     /*...@globals rpmGlobalMacroContext, h_errno @*/
  -     /*...@modifies h, rpmGlobalMacroContext @*/
  +     /*...@globals rpmGlobalMacroContext, h_errno, internalState @*/
  +     /*...@modifies h, rpmGlobalMacroContext, internalState @*/
   {
       HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
       struct optionalTag *ot;
  @@ -490,10 +500,10 @@
        he->tag = RPMTAG_XPM;
       else
        he->tag = tagValue("Icon");
  -     he->t = RPM_BIN_TYPE;
  -     he->p.ui8p = icon;
  -     he->c = nb;
  -     xx = headerPut(h, he, 0);
  +    he->t = RPM_BIN_TYPE;
  +    he->p.ui8p = icon;
  +    he->c = (rpmTagCount)nb;
  +    xx = headerPut(h, he, 0);
       rc = 0;
       
   exit:
  @@ -550,6 +560,39 @@
   extern int noLang;
   /*...@=redecl@*/
   
  +static rpmRC tagValidate(Spec spec, rpmTag tag, const char * value)
  +     /*...@*/
  +{
  +    const char * tagN = tagName(tag);
  +    const char * pattern = rpmExpand("%{?pattern_", tagN, "}", NULL);
  +    rpmRC ec = RPMRC_OK;
  +
  +    if (pattern && *pattern) {
  +     miRE mire;
  +     int xx;
  +
  +     mire = mireNew(RPMMIRE_REGEX, tag);
  +     xx = mireSetCOptions(mire, RPMMIRE_REGEX, 0, 0, NULL);
  +     if (!xx)
  +         xx = mireRegcomp(mire, pattern);
  +     if (!xx)
  +         xx = mireRegexec(mire, value, strlen(value));
  +     if (!xx)
  +         ec = RPMRC_OK;
  +     else {
  +         rpmlog(RPMLOG_ERR, _("line %d: invalid tag value(\"%s\") %s: %s\n"),
  +                 spec->lineNum, pattern, tagN, spec->line);
  +         ec = RPMRC_FAIL;
  +     }
  +
  +     mire = mireFree(mire);
  +    }
  +
  +    pattern = _free(pattern);
  +
  +    return ec;
  +}
  +
   /**
    */
   static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
  @@ -559,7 +602,7 @@
                spec->sources, spec->numSources, spec->noSource,
                spec->sourceHeader, spec->BANames, spec->BACount,
                spec->line,
  -             pkg->header, pkg->autoProv, pkg->autoReq,
  +             pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch,
                rpmGlobalMacroContext, fileSystem, internalState @*/
   {
       HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
  @@ -591,6 +634,10 @@
       }
       end = findLastChar(field);
   
  +    /* Validate tag data content. */
  +    if (tagValidate(spec, tag, field) != RPMRC_OK)
  +     return RPMRC_FAIL;
  +
       /* See if this is multi-token */
       end = field;
       SKIPNONSPACE(end);
  @@ -601,6 +648,7 @@
       case RPMTAG_NAME:
       case RPMTAG_VERSION:
       case RPMTAG_RELEASE:
  +    case RPMTAG_DISTEPOCH:
       case RPMTAG_URL:
       case RPMTAG_DISTTAG:
       case RPMTAG_REPOTAG:
  @@ -681,7 +729,7 @@
                he->p.ptr = _free(he->p.ptr);
                return RPMRC_FAIL;
            }
  -         len = strlen(he->p.argv[he->c]);
  +         len = (int)strlen(he->p.argv[he->c]);
            if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
                rpmlog(RPMLOG_ERR,
                         _("line %d: Prefixes must not end with \"/\": %s\n"),
  @@ -847,8 +895,10 @@
        break;
       }
   
  +/*...@-usereleased@*/
       if (macro)
        addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
  +/*...@=usereleased@*/
       
       return RPMRC_OK;
   }
  @@ -871,6 +921,7 @@
       {RPMTAG_NAME,            0, 0, "name"},
       {RPMTAG_VERSION,         0, 0, "version"},
       {RPMTAG_RELEASE,         0, 0, "release"},
  +    {RPMTAG_DISTEPOCH,               0, 0, "distepoch"},
       {RPMTAG_EPOCH,           0, 0, "epoch"},
       {RPMTAG_EPOCH,           0, 1, "serial"},
       {RPMTAG_SUMMARY,         1, 0, "summary"},
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/build/parseReqs.c
  ============================================================================
  $ cvs diff -u -r2.52 -r2.52.4.1 parseReqs.c
  --- rpm/build/parseReqs.c     17 Dec 2007 07:07:41 -0000      2.52
  +++ rpm/build/parseReqs.c     11 Jan 2009 18:50:31 -0000      2.52.4.1
  @@ -6,10 +6,13 @@
   #include "system.h"
   
   #include <rpmio.h>
  +#include <rpmlog.h>
   #define      _RPMEVR_INTERNAL
   #include "rpmbuild.h"
   #include "debug.h"
   
  +/*...@access EVR_t @*/
  +
   #define      SKIPWHITE(_x)   {while(*(_x) && (xisspace(*_x) || *(_x) == 
',')) (_x)++;}
   #define      SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == 
',')) (_x)++;}
   
  @@ -152,6 +155,22 @@
        } else
            EVR = NULL;
   
  +     /* Make sure that EVR is parseable during install. */
  +     if (EVR != NULL) {
  +         EVR_t evr = memset(alloca(sizeof(*evr)), 0, sizeof(*evr));
  +         int xx = rpmEVRparse(xstrdup(EVR), evr);
  +
  +         evr->str = _free(evr->str);
  +         if (xx != 0) {
  +             rpmlog(RPMLOG_ERR,
  +                      _("line %d: EVR does not parse: %s\n"),
  +                      spec->lineNum, spec->line);
  +             N = _free(N);
  +             EVR = _free(EVR);
  +             return RPMRC_FAIL;
  +         }
  +     }
  +
        (void) addReqProv(spec, h, tagN, N, EVR, Flags, index);
   
        N = _free(N);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/rpmds.c
  ============================================================================
  $ cvs diff -u -r2.94.2.5 -r2.94.2.6 rpmds.c
  --- rpm/lib/rpmds.c   10 Dec 2008 20:31:53 -0000      2.94.2.5
  +++ rpm/lib/rpmds.c   11 Jan 2009 18:50:31 -0000      2.94.2.6
  @@ -81,9 +81,9 @@
   #include <rpmio_internal.h>  /* XXX fdGetFILE */
   #include <rpmcb.h>           /* XXX fnpyKey */
   #include <rpmmacro.h>
  -#include <rpmlib.h>
   #include <argv.h>
   
  +#include <rpmlib.h>
   #include <rpmtag.h>
   
   #define      _RPMDS_INTERNAL
  @@ -526,6 +526,7 @@
       uint32_t E;
       const char ** N, ** EVR;
       char * t;
  +    size_t nb;
       int xx;
   
       if (tagN == RPMTAG_NAME)
  @@ -550,7 +551,8 @@
       t = stpcpy(t, Name);
       Name = _free(Name);
   
  -    t = xmalloc(sizeof(*EVR) + 20 + strlen(V) + strlen(R) + sizeof("-"));
  +    nb = sizeof(*EVR) + 20 + strlen(V) + strlen(R) + sizeof("-");
  +    t = xmalloc(nb);
       EVR = (const char **) t;
       t += sizeof(*EVR);
       *t = '\0';
  @@ -1592,6 +1594,7 @@
   /*...@unchecked@*/ /*...@observer@*/ /*...@owned@*/ /*...@relnull@*/
   const char *_sysinfo_path = NULL;
   
  +/*...@-nullassign@*/
   /*...@unchecked@*/ /*...@observer@*/ /*...@relnull@*/
   static const char *_sysinfo_tags[] = {
       "Providename",
  @@ -1602,6 +1605,7 @@
       "Filelinktos",
       NULL
   };
  +/*...@=nullassign@*/
   
   int rpmdsSysinfo(rpmPRCO PRCO, const char * fn)
        /*...@globals _sysinfo_path @*/
  @@ -3571,6 +3575,26 @@
       return rc;
   }
   
  +/*...@unchecked@*/ /*...@null@*/
  +static const char * evr_tuple_order = NULL;
  +
  +/**
  + * Return precedence permutation string.
  + * @return           precedence permutation
  + */
  +/*...@observer@*/
  +static const char * rpmdsEVRorder(void)
  +     /*...@*/
  +{
  +    if (evr_tuple_order == NULL) {
  +     evr_tuple_order = rpmExpand("%{?evr_tuple_order}", NULL);
  +     if (evr_tuple_order == NULL || evr_tuple_order[0] == '\0')
  +         evr_tuple_order = xstrdup("EVR");
  +    }
  +assert(evr_tuple_order != NULL && evr_tuple_order[0] != '\0');
  +    return evr_tuple_order;
  +}
  +
   int rpmdsCompare(const rpmds A, const rpmds B)
   {
       const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
  @@ -3581,6 +3605,7 @@
       evrFlags bFlags = B->ns.Flags;
       int (*EVRcmp) (const char *a, const char *b);
       int result = 1;
  +    const char * s;
       int sense;
       int xx;
   
  @@ -3613,26 +3638,40 @@
       EVRcmp = (A->EVRcmp && B->EVRcmp && A->EVRcmp == B->EVRcmp)
        ? A->EVRcmp : rpmvercmp;
   
  -    /* Compare {A,B} [epoch:]version[-release] */
  +    /* Compare {A,B} [epoch:]version[-release][:distepoch] */
       sense = 0;
  -    if (a->E && *a->E && b->E && *b->E)
  -/*...@i@*/   sense = EVRcmp(a->E, b->E);
  -    else if (a->E && *a->E && atol(a->E) > 0) {
  -     if (!B->nopromote) {
  -         int lvl = (_rpmds_unspecified_epoch_noise  ? RPMLOG_WARNING : 
RPMLOG_DEBUG);
  -         rpmlog(lvl, _("The \"B\" dependency needs an epoch (assuming same 
epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
  -             aDepend, bDepend);
  -         sense = 0;
  -     } else
  -         sense = 1;
  -    } else if (b->E && *b->E && atol(b->E) > 0)
  -     sense = -1;
  -
  -    if (sense == 0) {
  -/*...@i@*/   sense = EVRcmp(a->V, b->V);
  -     if (sense == 0 && a->R && *a->R && b->R && *b->R)
  -/*...@i@*/       sense = EVRcmp(a->R, b->R);
  +    for (s = rpmdsEVRorder(); *s; s++) {
  +     int ix;
  +        switch ((int)*s) {
  +        default:        continue;       /*...@notreached@*/ break;
  +        case 'E':
  +         ix = RPMEVR_E;
  +         if (a->F[ix] && *a->F[ix] && b->F[ix] && *b->F[ix])
  +             /*...@switchbreak@*/ break;
  +         /* XXX Special handling for missing Epoch: tags hysteria */
  +         if (a->F[ix] && *a->F[ix] && atol(a->F[ix]) > 0) {
  +             if (!B->nopromote) {
  +                 int lvl = (_rpmds_unspecified_epoch_noise
  +                     ? RPMLOG_WARNING : RPMLOG_DEBUG);
  +                 rpmlog(lvl, _("The \"B\" dependency needs an epoch 
(assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
  +                     aDepend, bDepend);
  +                 sense = 0;
  +             } else
  +                 sense = 1;
  +         } else
  +         if (b->F[ix] && *b->F[ix] && atol(b->F[ix]) > 0)
  +             sense = -1;
  +         /*...@switchbreak@*/ break;
  +        case 'V':    ix = RPMEVR_V;  /*...@switchbreak@*/break;
  +        case 'R':    ix = RPMEVR_R;  /*...@switchbreak@*/break;
  +        case 'D':    ix = RPMEVR_D;  /*...@switchbreak@*/break;
  +        }
  +     if (a->F[ix] && *a->F[ix] && b->F[ix] && *b->F[ix])
  +/*...@i@*/       sense = EVRcmp(a->F[ix], b->F[ix]);
  +     if (sense)
  +         break;
       }
  +
       a->str = _free(a->str);
       b->str = _free(b->str);
   
  @@ -3793,7 +3832,7 @@
        sprintf(t, "%d:", E);
        t += strlen(t);
       }
  -    (void) stpcpy( stpcpy( stpcpy(t, V) , "-") , R);
  +    t = stpcpy( stpcpy( stpcpy(t, V) , "-") , R);
       V = _free(V);
       R = _free(R);
   
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/macros.in
  ============================================================================
  $ cvs diff -u -r1.241.2.7 -r1.241.2.8 macros.in
  --- rpm/macros.in     11 Jan 2009 02:30:06 -0000      1.241.2.7
  +++ rpm/macros.in     11 Jan 2009 18:50:29 -0000      1.241.2.8
  @@ -1,7 +1,7 @@
   #/*! \page config_macros Default configuration: @USRLIBRPM@/macros
   # \verbatim
   #
  -# $Id: macros.in,v 1.241.2.7 2009/01/11 02:30:06 jbj Exp $
  +# $Id: macros.in,v 1.241.2.8 2009/01/11 18:50:29 jbj Exp $
   #
   # This is a global RPM configuration file. All changes made here will
   # be lost when the rpm package is upgraded. Any per-system configuration
  @@ -1027,25 +1027,25 @@
   # STEP 1: Match the string and capture regex parts
   #                      1          2           3             4
   #                      X     ":"  X        "-"X          ":"X
  -#%evr_tuple_match  ^(?:([^:-]+):)?([^:-]+)(?:-([^:-]+))?(?::([^:-]+))?$
  +%evr_tuple_match  ^(?:([^:-]+):)?([^:-]+)(?:-([^:-]+))?(?::([^:-]+))?$
      
   # STEP 2: Assemble <E,V,R,D> tuple from regex parts
   # <E,V,R,D>         case 1:  case 2:  case 3:  case 4:  case 5:  case 6:
   #                   X:X-X:X  X:X-X    X:X      X:       X-X      X
   # %evr_tuple_select 1234     123_     12__     1___     _23_     _2__
  -#%evr_tuple_select 123_
  +%evr_tuple_select 123_
   
   # STEP 3: Configure the comparison order of the <E,V,R,D> tuple elements
  -#%evr_tuple_order  EVR
  +%evr_tuple_order  EVR
   
   # data validation patterns for identifier tags
  -#%pattern_Name               [A-Za-z0-9]+[A-Za-z0-9+._-]*
  -#%pattern_Epoch              [0-9]+
  -#%pattern_Version    [A-Za-z0-9+._]+
  -#%pattern_Release    [A-Za-z0-9+._]+
  -#%pattern_Disttag    [A-Za-z0-9]+
  -#%pattern_Repotag    [A-Za-z0-9]+
  -#%pattern_Distepoch  [A-Za-z0-9.]+
  +%pattern_Name                [A-Za-z0-9]+[A-Za-z0-9+._-]*
  +%pattern_Epoch               [0-9]+
  +%pattern_Version     [A-Za-z0-9+._]+
  +%pattern_Release     [A-Za-z0-9+._]+
  +%pattern_Disttag     [A-Za-z0-9]+
  +%pattern_Repotag     [A-Za-z0-9]+
  +%pattern_Distepoch   [A-Za-z0-9.]+
   #%pattern_Url
   #%pattern_Cvsid
   #%pattern_Group
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/python/header-py.c
  ============================================================================
  $ cvs diff -u -r1.93 -r1.93.2.1 header-py.c
  --- rpm/python/header-py.c    12 Mar 2008 19:41:12 -0000      1.93
  +++ rpm/python/header-py.c    11 Jan 2009 18:50:30 -0000      1.93.2.1
  @@ -828,22 +828,24 @@
   
   PyObject * labelCompare (PyObject * self, PyObject * args)
   {
  -    EVR_t A = memset(alloca(sizeof(*A)), 0, sizeof(*A));
  -    EVR_t B = memset(alloca(sizeof(*B)), 0, sizeof(*B));
  +    EVR_t a = rpmEVRnew(RPMSENSE_EQUAL, 1);
  +    EVR_t b = rpmEVRnew(RPMSENSE_EQUAL, 1);
       int rc;
   
  +    /* XXX FIXME: labelCompare cannot specify Distepoch: field */
       if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
  -                     &A->E, &A->V, &A->R, &B->E, &B->V, &B->R))
  +                     &a->F[RPMEVR_E], &a->F[RPMEVR_V], &a->F[RPMEVR_R],
  +                     &b->F[RPMEVR_E], &b->F[RPMEVR_V], &b->F[RPMEVR_R]))
  +    {
  +     a = rpmEVRfree(a);
  +     b = rpmEVRfree(b);
        return NULL;
  +    }
   
  -    if (A->E == NULL)        A->E = "0";
  -    if (B->E == NULL)        B->E = "0";
  -    if (A->V == NULL)        A->E = "";
  -    if (B->V == NULL)        B->E = "";
  -    if (A->R == NULL)        A->E = "";
  -    if (B->R == NULL)        B->E = "";
  +    rc = rpmEVRcompare(a, b);
   
  -    rc = rpmEVRcompare(A, B);
  +    a = rpmEVRfree(a);
  +    b = rpmEVRfree(b);
   
       return Py_BuildValue("i", rc);
   }
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/librpmdb.vers
  ============================================================================
  $ cvs diff -u -r1.43.2.5 -r1.43.2.6 librpmdb.vers
  --- rpm/rpmdb/librpmdb.vers   10 Jan 2009 22:32:58 -0000      1.43.2.5
  +++ rpm/rpmdb/librpmdb.vers   11 Jan 2009 18:50:30 -0000      1.43.2.6
  @@ -24,7 +24,9 @@
       fpLookup;
       fpLookupList;
       _hdr_debug;
  +    _hdr_fastdatalength;
       _hdr_getops;
  +    _hdr_lazytagswab;
       _hdr_loadops;
       _hdr_stats;
       headerAddI18NString;
  @@ -42,6 +44,8 @@
       headerSetBaseURL;
       headerGetDigest;
       headerSetDigest;
  +    headerGetRpmdb;
  +    headerSetRpmdb;
       headerGetInstance;
       headerSetInstance;
       headerGetMagic;
  @@ -119,6 +123,9 @@
       rpmEVRcmp;
       rpmEVRcompare;
       rpmEVRflags;
  +    rpmEVRfree;
  +    rpmEVRnew;
  +    rpmEVRoverlap;
       rpmEVRparse;
       _rpmns_debug;
       _rpmns_N_at_A;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmdpkg.c
  ============================================================================
  $ cvs diff -u -r1.6.2.2 -r1.6.2.3 rpmdpkg.c
  --- rpm/rpmdb/rpmdpkg.c       10 Jan 2009 22:32:58 -0000      1.6.2.2
  +++ rpm/rpmdb/rpmdpkg.c       11 Jan 2009 18:50:30 -0000      1.6.2.3
  @@ -4,6 +4,7 @@
   #include "system.h"
   
   #include <rpmio.h>
  +#include <rpmtag.h>
   
   #define      _RPMEVR_INTERNAL
   #include <rpmdpkg.h>
  @@ -19,24 +20,25 @@
   static inline int dpkgEVRctype(char x)
        /*...@*/
   {
  +    int c = (int)x;
       return (
          x == '~' ? -1 
  -     : xisdigit(x) ? 0
  -     : !x ? 0 \
  -     : xisalpha(x) ? x
  -     : x + 256
  +     : xisdigit(c) ? 0
  +     : x == '\0' ? 0 \
  +     : xisalpha(c) ? c
  +     : c + 256
       );
   }
   
   int dpkgEVRcmp(const char *a, const char *b)
   {
  -    if (!a) a = "";
  -    if (!b) b = "";
  +    if (a == NULL) a = "";
  +    if (b == NULL) b = "";
   
       while (*a || *b) {
        int first_diff= 0;
   
  -     while ( (*a && !xisdigit(*a)) || (*b && !xisdigit(*b)) ) {
  +     while ( (*a && !xisdigit((int)*a)) || (*b && !xisdigit((int)*b)) ) {
            int vc = dpkgEVRctype(*a);
            int rc = dpkgEVRctype(*b);
            if (vc != rc) return vc - rc;
  @@ -45,12 +47,12 @@
   
        while (*a == '0') a++;
        while (*b == '0') b++;
  -     while (xisdigit(*a) && xisdigit(*b)) {
  -         if (!first_diff) first_diff = *a - *b;
  +     while (xisdigit((int)*a) && xisdigit((int)*b)) {
  +         if (!first_diff) first_diff = (int)(*a - *b);
            a++; b++;
        }
  -     if (xisdigit(*a)) return 1;
  -     if (xisdigit(*b)) return -1;
  +     if (xisdigit((int)*a)) return 1;
  +     if (xisdigit((int)*b)) return -1;
        if (first_diff) return first_diff;
       }
       return 0;
  @@ -67,6 +69,6 @@
   
       if (a->Elong > b->Elong) return 1;
       if (a->Elong < b->Elong) return -1;
  -    r = dpkgEVRcmp(a->V, b->V);  if (r) return r;
  -    return dpkgEVRcmp(a->R, b->R);
  +    r = dpkgEVRcmp(a->F[RPMEVR_V], b->F[RPMEVR_V]);  if (r) return r;
  +    return dpkgEVRcmp(a->F[RPMEVR_R], b->F[RPMEVR_R]);
   }
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmdpkg.h
  ============================================================================
  $ cvs diff -u -r1.2.2.2 -r1.2.2.3 rpmdpkg.h
  --- rpm/rpmdb/rpmdpkg.h       10 Jan 2009 22:32:58 -0000      1.2.2.2
  +++ rpm/rpmdb/rpmdpkg.h       11 Jan 2009 18:50:30 -0000      1.2.2.3
  @@ -25,7 +25,7 @@
    * @param b          2nd string
    * @return           +1 if a is "newer", 0 if equal, -1 if b is "newer"
    */
  -int dpkgEVRcmp(const char *a, const char *b)
  +int dpkgEVRcmp(/*...@null@*/ const char *a, /*...@null@*/ const char *b)
        /*...@*/;
   
   /** \ingroup rpmds
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmevr.c
  ============================================================================
  $ cvs diff -u -r1.29.2.2 -r1.29.2.3 rpmevr.c
  --- rpm/rpmdb/rpmevr.c        10 Jan 2009 22:32:58 -0000      1.29.2.2
  +++ rpm/rpmdb/rpmevr.c        11 Jan 2009 18:50:30 -0000      1.29.2.3
  @@ -4,7 +4,11 @@
   #include "system.h"
   
   #include <rpmio.h>
  +#include <rpmmacro.h>
  +#define      _MIRE_INTERNAL
  +#include <mire.h>
   
  +#include <rpmtag.h>
   #define      _RPMEVR_INTERNAL
   #include <rpmevr.h>
   
  @@ -17,9 +21,36 @@
   #define MAX(x, y) ( ((x)>(y))?(x):(y) )
   #endif
   
  +EVR_t rpmEVRnew(uint32_t Flags, int initialize)
  +{
  +    EVR_t evr = xcalloc(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;
  +}
  +
  +EVR_t rpmEVRfree(EVR_t evr)
  +{
  +    if (evr != NULL) {
  +     evr->str = _free(evr->str);
  +     memset(evr, 0, sizeof(*evr));
  +     evr = _free(evr);
  +    }
  +    return NULL;
  +}
  +
   /* XXX Force digits to beat alphas. See bugzilla #50977. */
   /*...@unchecked@*/
  +#if defined(RPM_VENDOR_MANDRIVA) /* old-comparision-behaviour */
   static int _invert_digits_alphas_comparison = -1;
  +#else
  +static int _invert_digits_alphas_comparison = 1;
  +#endif
   
   /* XXX Punctuation characters that are not treated as alphas */
   /*...@unchecked@*/ /*...@observer@*/
  @@ -44,42 +75,37 @@
   int rpmEVRcmp(const char * a, const char * b)
        /*...@*/
   {
  -    const char * ae, * be;
  -    int rc = 0;
  +    const char * ae = NULL, * be = NULL;
  +    int rc = 0;              /* assume equal */
   
       /* Compare version strings segment by segment. */
       for (; *a && *b && rc == 0; a = ae, b = be) {
   
        /* Skip leading non-alpha, non-digit characters. */
  -     while (*a && !(xisdigit(*a) || xisrpmalpha(*a))) a++;
  -     while (*b && !(xisdigit(*b) || xisrpmalpha(*b))) b++;
  +     while (*a && !(xisdigit((int)*a) || xisrpmalpha((int)*a))) a++;
  +     while (*b && !(xisdigit((int)*b) || xisrpmalpha((int)*b))) b++;
   
  +     /* Wildcard comparison? */
  +     /* Note: limited to suffix-only wildcard matching at the moment. */
  +     if (a[0] == '*' && a[1] == '\0') {
  +            be = strchr(b, '\0');    /* XXX be = b + strlen(b); */
  +     } else
  +     if (b[0] == '*' && b[1] == '\0') {
  +            ae = strchr(a, '\0');    /* XXX ae = a + strlen(a); */
  +     } else
        /* Digit string comparison? */
  -#if defined(RPM_VENDOR_OPENPKG) /* support-wildcards-in-EVR-comparison */
  -        if (a[0] == '*') {
  -            ae = a + 1;
  -            if ((be = strchr(b, a[1])) == NULL)
  -                be = b;
  -        }
  -        else if (b[0] == '*') {
  -            be = b + 1;
  -            if ((ae = strchr(a, b[1])) == NULL)
  -                ae = a;
  -        }
  -        else
  -#endif
  -     if (xisdigit(*a) || xisdigit(*b)) {
  +     if (xisdigit((int)*a) || xisdigit((int)*b)) {
            /* Discard leading zeroes. */
  -         while (a[0] == '0' && xisdigit(a[1])) a++;
  -         while (b[0] == '0' && xisdigit(b[1])) b++;
  +         while (a[0] == '0' && xisdigit((int)a[1])) a++;
  +         while (b[0] == '0' && xisdigit((int)b[1])) b++;
   
            /* Find end of digit strings. */
  -         ae = a; while (xisdigit(*ae)) ae++;
  -         be = b; while (xisdigit(*be)) be++;
  +         ae = a; while (xisdigit((int)*ae)) ae++;
  +         be = b; while (xisdigit((int)*be)) be++;
   
            /* Calculate digit comparison return code. */
            if (a == ae || b == be)
  -             rc = (*b - *a) * _invert_digits_alphas_comparison;
  +             rc = (int)(*a - *b) * _invert_digits_alphas_comparison;
            else {
                rc = (ae - a) - (be - b);
                if (!rc)
  @@ -87,8 +113,8 @@
            }
        } else {
            /* Find end of alpha strings. */
  -         ae = a; while (xisrpmalpha(*ae)) ae++;
  -         be = b; while (xisrpmalpha(*be)) be++;
  +         ae = a; while (xisrpmalpha((int)*ae)) ae++;
  +         be = b; while (xisrpmalpha((int)*be)) be++;
   
            /* Calculate alpha comparison return code. */
            rc = strncmp(a, b, MAX((ae - a), (be - b)));
  @@ -97,7 +123,7 @@
   
       /* Longer string wins. */
       if (!rc)
  -     rc = (*a - *b);
  +     rc = (int)(*a - *b);
   
       /* Force strict -1, 0, 1 return. */
       rc = (rc > 0 ? 1
  @@ -106,33 +132,147 @@
       return rc;
   }
   
  -int rpmEVRparse(const char * evrstr, EVR_t evr)
  +/*...@unchecked@*/ /*...@observer@*/ /*...@null@*/
  +static const char * _evr_tuple_match = 
"^(?:([^:-]+):)?([^:-]+)(?:-([^:-]+))?(?::([^:-]+))?$";
  +/*...@unchecked@*/ /*...@null@*/
  +static const char * evr_tuple_match = NULL;
  +/*...@unchecked@*/ /*...@null@*/
  +static miRE evr_tuple_mire = NULL;
  +/*...@unchecked@*/
  +static int evr_tuple_nmire;
  +
  +static miRE rpmEVRmire(void)
  +     /*...@*/
  +{
  +    if (evr_tuple_mire == NULL) {
  +     int xx;
  +     evr_tuple_match = rpmExpand("%{?evr_tuple_match}", NULL);
  +     if (evr_tuple_match == NULL || evr_tuple_match[0] == '\0')
  +         evr_tuple_match = xstrdup(_evr_tuple_match);
  +
  +#ifdef       NOTYET  /* XXX avoid need for evr_tuple_nmire */
  +     evr_tuple_mire = mireNew(RPMMIRE_REGEX, 0);
  +     xx = mireSetCOptions(evr_tuple_mire, RPMMIRE_REGEX, 0, 0, NULL);
  +     xx = mireRegcomp(evr_tuple_mire, evr_tuple_match);
  +#else
  +     xx = mireAppend(RPMMIRE_REGEX, 0, evr_tuple_match, NULL,
  +             &evr_tuple_mire, &evr_tuple_nmire);
  +#endif
  +
  +    }
  +assert(evr_tuple_match != NULL && evr_tuple_mire != NULL);
  +    return evr_tuple_mire;
  +}
  +
  +#ifndef      DYING
  +static int oldrpmEVRparse(const char * evrstr, EVR_t evr)
        /*...@modifies evrstr, evr @*/
   {
       char *s = xstrdup(evrstr);
       char *se;
  +    char *se2;
   
       evr->str = se = s;
  -    while (*se && xisdigit(*se)) se++;       /* se points to epoch 
terminator */
  +    se2 = se;
  +    while (*se && xisdigit((int)*se)) se++; /* se points to epoch terminator 
*/
   
       if (*se == ':') {
  -     evr->E = s;
  +     evr->F[RPMEVR_E] = s;
        *se++ = '\0';
  -     evr->V = se;
  -     if (*evr->E == '\0') evr->E = "0";
  -     evr->Elong = strtoul(evr->E, NULL, 10);
  +     evr->F[RPMEVR_V] = se;
  +     se2 = se;
  +     if (*evr->F[RPMEVR_E] == '\0') evr->F[RPMEVR_E] = "0";
  +     evr->Elong = strtoul(evr->F[RPMEVR_E], NULL, 10);
       } else {
  -     evr->E = NULL;  /* XXX disable epoch compare if missing */
  -     evr->V = s;
  +     evr->F[RPMEVR_E] = NULL; /* XXX disable epoch compare if missing */
  +     evr->F[RPMEVR_V] = s;
        evr->Elong = 0;
       }
  -    se = strrchr(se, '-');           /* se points to version terminator */
  +    se = strrchr(se, ':');           /* se points to release terminator */
  +    if (se) {
  +     *se++ = '\0';
  +     evr->F[RPMEVR_D] = se;
  +    } else {
  +     evr->F[RPMEVR_D] = NULL;
  +    }
  +    se = strrchr(se2, '-');          /* se points to version terminator */
       if (se) {
        *se++ = '\0';
  -     evr->R = se;
  +     evr->F[RPMEVR_R] = se;
       } else {
  -     evr->R = NULL;
  +     evr->F[RPMEVR_R] = NULL;
       }
  +
  +    return 0;
  +}
  +#endif
  +
  +int rpmEVRparse(const char * evrstr, EVR_t evr)
  +     /*...@modifies evrstr, evr @*/
  +{
  +    miRE mire = rpmEVRmire();
  +    int noffsets = 6 * 3;
  +    int offsets[6 * 3];
  +    size_t nb;
  +    int xx;
  +    int i;
  +
  +    memset(evr, 0, sizeof(*evr));
  +    evr->str = xstrdup(evrstr);
  +    nb = strlen(evr->str);
  +
  +    memset(offsets, -1, sizeof(offsets));
  +    xx = mireSetEOptions(mire, offsets, noffsets);
  +
  +    xx = mireRegexec(mire, evr->str, strlen(evr->str));
  +
  +    for (i = 0; i < noffsets; i += 2) {
  +     int ix;
  +
  +     if (offsets[i] < 0)
  +         continue;
  +
  +     switch (i/2) {
  +     default:
  +     case 0: continue;       /*...@notreached@*/ break;
  +     case 1: ix = RPMEVR_E;  /*...@switchbreak@*/break;
  +     case 2: ix = RPMEVR_V;  /*...@switchbreak@*/break;
  +     case 3: ix = RPMEVR_R;  /*...@switchbreak@*/break;
  +     case 4: ix = RPMEVR_D;  /*...@switchbreak@*/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';
  +     }
  +
  +    }
  +
  +    evr->Elong = evr->F[RPMEVR_E] ? strtoul(evr->F[RPMEVR_E], NULL, 10) : 0;
  +
  +    xx = mireSetEOptions(mire, NULL, 0);
  +
  +#ifndef      DYING
  +    {        EVR_t Oevr = memset(alloca(sizeof(*Oevr)), 0, sizeof(*Oevr));
  +
  +     xx = oldrpmEVRparse(evrstr, Oevr);
  +assert(Oevr->Elong == evr->Elong);
  +
  +     for (i = 0; i < 5; i++) {
  +         if (Oevr->F[i] == NULL && evr->F[i] == NULL)
  +             continue;
  +         if (Oevr->F[i] == NULL || evr->F[i] == NULL
  +          || strcmp(Oevr->F[i], evr->F[i]))
  +             fprintf(stderr, "==> \"%s\" %d strcmp(%s,%s)\n",
  +                     evrstr, i, Oevr->F[i], evr->F[i]);
  +     }
  +     Oevr->str = _free(Oevr->str);
  +    }
  +#endif       /* DYING */
  +
       return 0;
   }
   
  @@ -148,20 +288,94 @@
       return rpmvercmp(a, b);
   }
   
  +/*...@unchecked@*/ /*...@null@*/
  +static const char * evr_tuple_order = NULL;
  +
  +/**
  + * Return precedence permutation string.
  + * @return           precedence permutation
  + */
  +/*...@observer@*/
  +static const char * rpmEVRorder(void)
  +     /*...@*/
  +{
  +    if (evr_tuple_order == NULL) {
  +     evr_tuple_order = rpmExpand("%{?evr_tuple_order}", NULL);
  +     if (evr_tuple_order == NULL || evr_tuple_order[0] == '\0')
  +         evr_tuple_order = xstrdup("EVR");
  +    }
  +assert(evr_tuple_order != NULL && evr_tuple_order[0] != '\0');
  +    return evr_tuple_order;
  +}
  +
   int rpmEVRcompare(const EVR_t a, const EVR_t b)
   {
  +    const char * s;
       int rc = 0;
   
  -    if (!rc)
  -     rc = compare_values(a->E, b->E);
  -    if (!rc)
  -     rc = compare_values(a->V, b->V);
  -    if (!rc)
  -     rc = compare_values(a->R, b->R);
  +assert(a->F[RPMEVR_E] != NULL);
  +assert(a->F[RPMEVR_V] != NULL);
  +assert(a->F[RPMEVR_R] != NULL);
  +assert(a->F[RPMEVR_D] != NULL);
  +assert(b->F[RPMEVR_E] != NULL);
  +assert(b->F[RPMEVR_V] != NULL);
  +assert(b->F[RPMEVR_R] != NULL);
  +assert(b->F[RPMEVR_D] != NULL);
  +
  +    for (s = rpmEVRorder(); *s; s++) {
  +     int ix;
  +     switch ((int)*s) {
  +     default:        continue;       /*...@notreached@*/ break;
  +     case 'E':       ix = RPMEVR_E;  /*...@switchbreak@*/break;
  +     case 'V':       ix = RPMEVR_V;  /*...@switchbreak@*/break;
  +     case 'R':       ix = RPMEVR_R;  /*...@switchbreak@*/break;
  +     case 'D':       ix = RPMEVR_D;  /*...@switchbreak@*/break;
  +     }
  +     rc = compare_values(a->F[ix], b->F[ix]);
  +     if (rc)
  +         break;
  +    }
       return rc;
   }
   
  +int rpmEVRoverlap(EVR_t a, EVR_t b)
  +{
  +    rpmsenseFlags aF = a->Flags;
  +    rpmsenseFlags bF = b->Flags;
  +    int sense;
  +    int result;
  +
  +    /* XXX HACK: postpone committing to single "missing" value for now. */
  +    if (a->F[RPMEVR_E] == NULL)      a->F[RPMEVR_E] = "0";
  +    if (b->F[RPMEVR_E] == NULL)      b->F[RPMEVR_E] = "0";
  +    if (a->F[RPMEVR_V] == NULL)      a->F[RPMEVR_V] = "";
  +    if (b->F[RPMEVR_V] == NULL)      b->F[RPMEVR_V] = "";
  +    if (a->F[RPMEVR_R] == NULL)      a->F[RPMEVR_R] = "";
  +    if (b->F[RPMEVR_R] == NULL)      b->F[RPMEVR_R] = "";
  +    if (a->F[RPMEVR_D] == NULL)      a->F[RPMEVR_D] = "";
  +    if (b->F[RPMEVR_D] == NULL)      b->F[RPMEVR_D] = "";
  +    sense = rpmEVRcompare(a, b);
  +
  +    /* Detect overlap of {A,B} range. */
  +    if (aF == RPMSENSE_NOTEQUAL || bF == RPMSENSE_NOTEQUAL)
  +        result = (sense != 0);
  +    else if (sense < 0 && ((aF & RPMSENSE_GREATER) || (bF & RPMSENSE_LESS)))
  +        result = 1;
  +    else if (sense > 0 && ((aF & RPMSENSE_LESS) || (bF & RPMSENSE_GREATER)))
  +        result = 1;
  +    else if (sense == 0 &&
  +        (((aF & RPMSENSE_EQUAL) && (bF & RPMSENSE_EQUAL)) ||
  +         ((aF & RPMSENSE_LESS) && (bF & RPMSENSE_LESS)) ||
  +         ((aF & RPMSENSE_GREATER) && (bF & RPMSENSE_GREATER))))
  +        result = 1;
  +    else
  +        result = 0;
  +    return result;
  +}
  +
  +/*...@-redecl@*/
   int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp;
  +/*...@=redecl@*/
   
   /**
    */
  @@ -205,3 +419,64 @@
       }
       return Flags;
   }
  +
  +int rpmVersionCompare(Header A, Header B)
  +{
  +    HE_t Ahe = memset(alloca(sizeof(*Ahe)), 0, sizeof(*Ahe));
  +    HE_t Bhe = memset(alloca(sizeof(*Bhe)), 0, sizeof(*Bhe));
  +    const char * one, * two;
  +    uint32_t Eone, Etwo;
  +    const char * s;
  +    int rc = 0;
  +    int xx;
  +
  +    for (s = rpmEVRorder(); *s; s++) {
  +     switch ((int)*s) {
  +     default:        continue;       /*...@notreached@*/ break;
  +     case 'E':
  +         Ahe->tag = RPMTAG_EPOCH;
  +         xx = headerGet(A, Ahe, 0);
  +         Eone = (xx && Ahe->p.ui32p ? Ahe->p.ui32p[0] : 0);
  +         Bhe->tag = RPMTAG_EPOCH;
  +         xx = headerGet(B, Bhe, 0);
  +         Etwo = (xx && Bhe->p.ui32p ? Bhe->p.ui32p[0] : 0);
  +         if (Eone < Etwo)
  +             rc = -1;
  +         else if (Eone > Etwo)
  +             rc = 1;
  +         /*...@switchbreak@*/ break;
  +     case 'V':
  +         Ahe->tag = RPMTAG_VERSION;
  +         xx = headerGet(A, Ahe, 0);
  +         one = (xx && Ahe->p.str ? Ahe->p.str : "");
  +         Bhe->tag = RPMTAG_VERSION;
  +         xx = headerGet(B, Bhe, 0);
  +         two = (xx && Bhe->p.str ? Bhe->p.str : "");
  +         rc = rpmvercmp(one, two);
  +         /*...@switchbreak@*/ break;
  +     case 'R':
  +         Ahe->tag = RPMTAG_RELEASE;
  +         xx = headerGet(A, Ahe, 0);
  +         one = (xx && Ahe->p.str ? Ahe->p.str : "");
  +         Bhe->tag = RPMTAG_RELEASE;
  +         xx = headerGet(B, Bhe, 0);
  +         two = (xx && Bhe->p.str ? Bhe->p.str : "");
  +         rc = rpmvercmp(one, two);
  +         /*...@switchbreak@*/ break;
  +     case 'D':
  +         Ahe->tag = RPMTAG_DISTEPOCH;
  +         xx = headerGet(A, Ahe, 0);
  +         one = (xx && Ahe->p.str ? Ahe->p.str : "");
  +         Bhe->tag = RPMTAG_DISTEPOCH;
  +         xx = headerGet(B, Bhe, 0);
  +         two = (xx && Bhe->p.str ? Bhe->p.str : "");
  +         rc = rpmvercmp(one, two);
  +         /*...@switchbreak@*/ break;
  +     }
  +     Ahe->p.ptr = _free(Ahe->p.ptr);
  +     Bhe->p.ptr = _free(Bhe->p.ptr);
  +     if (rc)
  +         break;
  +    }
  +    return rc;
  +}
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmevr.h
  ============================================================================
  $ cvs diff -u -r1.9.2.2 -r1.9.2.3 rpmevr.h
  --- rpm/rpmdb/rpmevr.h        10 Jan 2009 22:32:58 -0000      1.9.2.2
  +++ rpm/rpmdb/rpmevr.h        11 Jan 2009 18:50:30 -0000      1.9.2.3
  @@ -81,14 +81,15 @@
    */
   struct EVR_s {
       const char * str;                /*!< EVR storage */
  -/*...@observer@*/ /*...@null@*/
  -    const char * E;          /*!< Epoch */
  -    unsigned long Elong;
  -/*...@observer@*/ /*...@null@*/
  -    const char * V;          /*!< Version */
  -/*...@observer@*/ /*...@null@*/
  -    const char * R;          /*!< Release */
  +#ifndef      DYING
  +    unsigned long Elong;     /*!< E converted to integer. */
  +#endif
       evrFlags 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
   };
   
   #define      RPMSENSE_TRIGGER        \
  @@ -122,6 +123,24 @@
   #endif       /* _RPMEVR_INTERNAL */
   
   /** \ingroup rpmds
  + * Create a new EVR container.
  + * @param flags              EVR inequality flags
  + * @param initialize Should empty defaults be initialized?
  + * @return           initialized EVR container
  + */
  +EVR_t rpmEVRnew(uint32_t flags, int initialize)
  +        /*...@*/;
  +
  +/** \ingroup rpmtd
  + * Destroy an EVR container.
  + * @param            EVR container
  + * @return           NULL always
  + */
  +/*...@null@*/
  +EVR_t rpmEVRfree(/*...@only@*/ EVR_t evr)
  +        /*...@modifies evr @*/;
  +
  +/** \ingroup rpmds
    * Segmented string compare.
    * @param a          1st string
    * @param b          2nd string
  @@ -140,7 +159,7 @@
        /*...@modifies evrstr, evr @*/;
   
   /** \ingroup rpmds
  - * Compare EVR containers.
  + * Compare EVR containers for equality.
    * @param a          1st EVR container
    * @param b          2nd EVR container
    * @return           +1 if a is "newer", 0 if equal, -1 if b is "newer"
  @@ -149,6 +168,15 @@
        /*...@*/;
   
   /** \ingroup rpmds
  + * Compare EVR containers for overlap.
  + * @param a          1st EVR container
  + * @param b          2nd EVR container
  + * @return           1 if EVR inequalities overlap, 0 otherwise
  + */
  +int rpmEVRoverlap(EVR_t a, EVR_t b)
  +     /*...@*/;
  +
  +/** \ingroup rpmds
    * Segmented string compare vector.
    * @param a          1st string
    * @param b          2nd string
  @@ -166,6 +194,18 @@
   rpmsenseFlags rpmEVRflags(/*...@null@*/const char *op, /*...@null@*/const 
char **end)
        /*...@modifies *end @*/;
   
  +/**
  + * Compare headers to determine which header is "newer".
  + * @deprecated Use rpmdsCompare instead.
  + * @todo     Eliminate in rpm-5.1.
  + * @param A          1st header
  + * @param B          2nd header
  + * @return           result of comparison
  + */
  +int rpmVersionCompare(Header A, Header B)
  +     /*...@globals internalState @*/
  +     /*...@modifies internalState @*/;
  +
   #ifdef __cplusplus
   }
   #endif
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmns.c
  ============================================================================
  $ cvs diff -u -r1.10.2.3 -r1.10.2.4 rpmns.c
  --- rpm/rpmdb/rpmns.c 11 Jan 2009 03:18:33 -0000      1.10.2.3
  +++ rpm/rpmdb/rpmns.c 11 Jan 2009 18:50:30 -0000      1.10.2.4
  @@ -5,18 +5,19 @@
   
   #include <rpmio_internal.h>  /* XXX rpmioSlurp */
   #include <rpmmacro.h>
  +#include <rpmcb.h>
   
   #define      _RPMPGP_INTERNAL
   #include <rpmpgp.h>
   
   #include <rpmlib.h>          /* XXX RPMRC_OK */
  +#include <rpmtag.h>
   #define      _RPMEVR_INTERNAL
   #include <rpmevr.h>
   #define      _RPMNS_INTERNAL
   #include <rpmns.h>
  -
  -#include <rpmcb.h>
   #include <rpmdb.h>
  +
   #include <rpmps.h>
   #define      _RPMTS_INTERNAL         /* XXX ts->pkpkt, ts->pkpktlen */
   #include <rpmts.h>
  @@ -183,12 +184,12 @@
       Type = rpmnsProbe(str);
       if (Type != RPMNS_TYPE_UNKNOWN)
        return Type;
  -    for (s = str; *s; s++) {
  +    for (s = str; *s != '\0'; s++) {
        if (s[0] == '(' || s[strlen(s)-1] == ')')
            return RPMNS_TYPE_NAMESPACE;
        if (s[0] == '.' && s[1] == 's' && s[2] == 'o')
            return RPMNS_TYPE_DSO;
  -     if (s[0] == '.' && xisdigit(s[-1]) && xisdigit(s[1]))
  +     if (s[0] == '.' && xisdigit((int)s[-1]) && xisdigit((int)s[1]))
            return RPMNS_TYPE_VERSION;
        if (_rpmns_N_at_A && _rpmns_N_at_A[0]) {
            if (s[0] == _rpmns_N_at_A[0] && rpmnsArch(s+1))
  @@ -278,10 +279,10 @@
       if (c >= '0' && c <= '9')
        return (unsigned char)(c - '0');
       if (c >= 'A' && c <= 'F')
  -     return (unsigned char)((c - 'A') + 10);
  +     return (unsigned char)((int)(c - 'A') + 10);
       if (c >= 'a' && c <= 'f')
  -     return (unsigned char)((c - 'a') + 10);
  -    return 0;
  +     return (unsigned char)((int)(c - 'a') + 10);
  +    return '\0';
   }
   
   rpmRC rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn,
  @@ -300,7 +301,10 @@
       int xx;
   
   if (_rpmns_debug)
  -fprintf(stderr, "==> check(%s, %s, %s, %s)\n", fn, sigfn, pubfn, pubid);
  +fprintf(stderr, "==> check(%s, %s, %s, %s)\n", fn,
  +(sigfn ? sigfn : "(null)"),
  +(pubfn ? pubfn : "(null)"),
  +(pubid ? pubid : "(null)"));
   
       /* Load the signature. Use sigfn if specified, otherwise clearsign. */
       if (sigfn && *sigfn) {
  @@ -308,7 +312,7 @@
        xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
        if (xx != PGPARMOR_SIGNATURE) {
   if (_rpmns_debug)
  -fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, 
(unsigned int)sigpktlen, xx);
  +fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, 
(unsigned)sigpktlen, xx);
            _sigfn = _free(_sigfn);
            goto exit;
        }
  @@ -318,7 +322,7 @@
        xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
        if (xx != PGPARMOR_SIGNATURE) {
   if (_rpmns_debug)
  -fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, 
(unsigned int)sigpktlen, xx);
  +fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, 
(unsigned)sigpktlen, xx);
            _sigfn = _free(_sigfn);
            goto exit;
        }
  @@ -327,22 +331,24 @@
       xx = pgpPrtPkts((uint8_t *)sigpkt, sigpktlen, dig, printing);
       if (xx) {
   if (_rpmns_debug)
  -fprintf(stderr, "==> pgpPrtPkts SIG %p[%u] ret %d\n", sigpkt, (unsigned 
int)sigpktlen, xx);
  +fprintf(stderr, "==> pgpPrtPkts SIG %p[%u] ret %d\n", sigpkt, 
(unsigned)sigpktlen, xx);
        goto exit;
       }
   
       sigp = pgpGetSignature(dig);
   
  -    if (sigp->version != 3 && sigp->version != 4) {
  +    if (sigp->version != (uint8_t)3 && sigp->version != (uint8_t)4) {
   if (_rpmns_debug)
  -fprintf(stderr, "==> unverifiable V%d\n", sigp->version);
  +fprintf(stderr, "==> unverifiable V%u\n", (unsigned)sigp->version);
        goto exit;
       }
   
       /* Load the pubkey. Use pubfn if specified, otherwise rpmdb keyring. */
       if (pubfn && *pubfn) {
        const char * _pubfn = rpmExpand(pubfn, NULL);
  -     xx = pgpReadPkts(_pubfn, (uint8_t **)&ts->pkpkt, &ts->pkpktlen);
  +/*...@-type@*/
  +     xx = pgpReadPkts(_pubfn, &ts->pkpkt, &ts->pkpktlen);
  +/*...@=type@*/
        if (xx != PGPARMOR_PUBKEY) {
   if (_rpmns_debug)
   fprintf(stderr, "==> pgpReadPkts(%s) PUB %p[%u] ret %d\n", _pubfn, 
ts->pkpkt, (unsigned int)ts->pkpktlen, xx);
  @@ -395,7 +401,7 @@
        xx = memcmp(t, s + (8 - ns), ns);
   
        /* XXX HACK: V4 RSA key id's are wonky atm. */
  -     if (pubp->pubkey_algo == PGPPUBKEYALGO_RSA)
  +     if (pubp->pubkey_algo == (uint8_t)PGPPUBKEYALGO_RSA)
            xx = 0;
   
        if (xx) {
  @@ -412,10 +418,10 @@
        && sigp->hash_algo == pubp->hash_algo
   #endif
       /* XXX HACK: V4 RSA key id's are wonky atm. */
  -     && (pubp->pubkey_algo == PGPPUBKEYALGO_RSA || !memcmp(sigp->signid, 
pubp->signid, sizeof(sigp->signid))) ) ) {
  +     && (pubp->pubkey_algo == (uint8_t)PGPPUBKEYALGO_RSA || 
!memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid))) ) ) {
   if (_rpmns_debug) {
   fprintf(stderr, "==> mismatch between signature and pubkey\n");
  -fprintf(stderr, "\tpubkey_algo: %u  %u\n", sigp->pubkey_algo, 
pubp->pubkey_algo);
  +fprintf(stderr, "\tpubkey_algo: %u  %u\n", (unsigned)sigp->pubkey_algo, 
(unsigned)pubp->pubkey_algo);
   fprintf(stderr, "\tsignid: %08X %08X    %08X %08X\n",
   pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4), 
   pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4));
  @@ -424,7 +430,7 @@
       }
   
       /* Compute the message digest. */
  -    ctx = rpmDigestInit(sigp->hash_algo, RPMDIGEST_NONE);
  +    ctx = rpmDigestInit((pgpHashAlgo)sigp->hash_algo, RPMDIGEST_NONE);
   
       {        
        static const char clrtxt[] = "-----BEGIN PGP SIGNED MESSAGE-----";
  @@ -436,7 +442,7 @@
   
        if (!(_rc == 0 && b != NULL && blen > 0)) {
   if (_rpmns_debug)
  -fprintf(stderr, "==> rpmioSlurp(%s) MSG %p[%u] ret %d\n", _fn, b, (unsigned 
int)blen, _rc);
  +fprintf(stderr, "==> rpmioSlurp(%s) MSG ret %d\n", _fn, _rc);
            b = _free(b);
            _fn = _free(_fn);
            goto exit;
  @@ -479,12 +485,12 @@
   
       if (sigp->hash != NULL)
        xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
  -    if (sigp->version == 4) {
  -     uint32_t nb = sigp->hashlen;
  +    if (sigp->version == (uint8_t)4) {
  +     uint32_t nb = (uint32_t)sigp->hashlen;
        uint8_t trailer[6];
  -     nb = htonl(nb);
  +     nb = (uint32_t)htonl(nb);
        trailer[0] = sigp->version;
  -     trailer[1] = 0xff;
  +     trailer[1] = (uint8_t)0xff;
        memcpy(trailer+2, &nb, sizeof(nb));
        xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
       }
  @@ -503,7 +509,7 @@
       }
       if (rc != RPMRC_OK) {
   if (_rpmns_debug)
  -fprintf(stderr, "==> can't load pubkey_algo(%u)\n", sigp->pubkey_algo);
  +fprintf(stderr, "==> can't load pubkey_algo(%u)\n", 
(unsigned)sigp->pubkey_algo);
        goto exit;
       }
   
  @@ -524,7 +530,9 @@
       sigpkt = _free(sigpkt);
       ts->pkpkt = _free(ts->pkpkt);
       ts->pkpktlen = 0;
  +/*...@-nullstate@*/
       rpmtsCleanDig(ts);
  +/*...@=nullstate@*/
   
   if (_rpmns_debug)
   fprintf(stderr, "============================ verify: %s\n",
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmns.h
  ============================================================================
  $ cvs diff -u -r1.3.2.2 -r1.3.2.3 rpmns.h
  --- rpm/rpmdb/rpmns.h 10 Jan 2009 22:32:58 -0000      1.3.2.2
  +++ rpm/rpmdb/rpmns.h 11 Jan 2009 18:50:30 -0000      1.3.2.3
  @@ -132,8 +132,8 @@
                /*...@null@*/ const char * pubfn,
                /*...@null@*/ const char * pubid,
                int flags)
  -     /*...@globals fileSystem @*/
  -     /*...@modifies fileSystem @*/;
  +     /*...@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState 
@*/
  +     /*...@modifies _ts, rpmGlobalMacroContext, fileSystem, internalState 
@*/;
   
   #ifdef __cplusplus
   }
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to