Main Page Modules Data Structures File List Data Fields Globals Related Pages

# lib/rpmds.c

Go to the documentation of this file.

    00001
    00004 #include "system.h"
    00005
    00006 #include <rpmlib.h>
    00007
    00008 #define _RPMDS_INTERNAL
    00009 #include "rpmds.h"
    00010
    00011 #include "debug.h"
    00012
    00016 /*@unchecked@*/
    00017 static int _noisy_range_comparison_debug_message = 0;
    00018
    00019 /*@unchecked@*/
    00020 int _rpmds_debug = 0;
    00021
    00022 /*@unchecked@*/
    00023 int _rpmds_nopromote = 1;
    00024
    00025 /*@unchecked@*/
    00026 /*@-exportheadervar@*/
    00027 int _rpmds_unspecified_epoch_noise = 0;
    00028 /*@=exportheadervar@*/
    00029
    00030 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
    00031 {
    00032     if (ds == NULL) return NULL;
    00033 /*@-modfilesys@*/
    00034 if (_rpmds_debug && msg != NULL)
    00035 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
    00036 /*@=modfilesys@*/
    00037     ds->nrefs--;
    00038     return NULL;
    00039 }
    00040
    00041 rpmds XrpmdsLink(rpmds ds, const char * msg, const char * fn, unsigned ln)
    00042 {
    00043     if (ds == NULL) return NULL;
    00044     ds->nrefs++;
    00045
    00046 /*@-modfilesys@*/
    00047 if (_rpmds_debug && msg != NULL)
    00048 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
    00049 /*@=modfilesys@*/
    00050
    00051     /*@-refcounttrans@*/ return ds; /*@=refcounttrans@*/
    00052 }
    00053
    00054 rpmds rpmdsFree(rpmds ds)
    00055 {
    00056     HFD_t hfd = headerFreeData;
    00057     rpmTag tagEVR, tagF;
    00058
    00059     if (ds == NULL)
    00060         return NULL;
    00061
    00062     if (ds->nrefs > 1)
    00063         return rpmdsUnlink(ds, ds->Type);
    00064
    00065 /*@-modfilesys@*/
    00066 if (_rpmds_debug < 0)
    00067 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
    00068 /*@=modfilesys@*/
    00069
    00070     if (ds->tagN == RPMTAG_PROVIDENAME) {
    00071         tagEVR = RPMTAG_PROVIDEVERSION;
    00072         tagF = RPMTAG_PROVIDEFLAGS;
    00073     } else
    00074     if (ds->tagN == RPMTAG_REQUIRENAME) {
    00075         tagEVR = RPMTAG_REQUIREVERSION;
    00076         tagF = RPMTAG_REQUIREFLAGS;
    00077     } else
    00078     if (ds->tagN == RPMTAG_CONFLICTNAME) {
    00079         tagEVR = RPMTAG_CONFLICTVERSION;
    00080         tagF = RPMTAG_CONFLICTFLAGS;
    00081     } else
    00082     if (ds->tagN == RPMTAG_OBSOLETENAME) {
    00083         tagEVR = RPMTAG_OBSOLETEVERSION;
    00084         tagF = RPMTAG_OBSOLETEFLAGS;
    00085     } else
    00086     if (ds->tagN == RPMTAG_TRIGGERNAME) {
    00087         tagEVR = RPMTAG_TRIGGERVERSION;
    00088         tagF = RPMTAG_TRIGGERFLAGS;
    00089     } else
    00090         return NULL;
    00091
    00092     /*@-branchstate@*/
    00093     if (ds->Count > 0) {
    00094         ds->N = hfd(ds->N, ds->Nt);
    00095         ds->EVR = hfd(ds->EVR, ds->EVRt);
    00096         /*@-evalorder@*/
    00097         ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
    00098         /*@=evalorder@*/
    00099         ds->h = headerFree(ds->h);
    00100     }
    00101     /*@=branchstate@*/
    00102
    00103     ds->DNEVR = _free(ds->DNEVR);
    00104
    00105     (void) rpmdsUnlink(ds, ds->Type);
    00106     /*@-refcounttrans -usereleased@*/
    00107 /*@-boundswrite@*/
    00108     memset(ds, 0, sizeof(*ds));         /* XXX trash and burn */
    00109 /*@=boundswrite@*/
    00110     ds = _free(ds);
    00111     /*@=refcounttrans =usereleased@*/
    00112     return NULL;
    00113 }
    00114
    00115 rpmds rpmdsNew(Header h, rpmTag tagN, int scareMem)
    00116 {
    00117     HGE_t hge =
    00118         (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry);
    00119     rpmTag tagEVR, tagF;
    00120     rpmds ds = NULL;
    00121     const char * Type;
    00122     const char ** N;
    00123     rpmTagType Nt;
    00124     int_32 Count;
    00125
    00126     if (tagN == RPMTAG_PROVIDENAME) {
    00127         Type = "Provides";
    00128         tagEVR = RPMTAG_PROVIDEVERSION;
    00129         tagF = RPMTAG_PROVIDEFLAGS;
    00130     } else
    00131     if (tagN == RPMTAG_REQUIRENAME) {
    00132         Type = "Requires";
    00133         tagEVR = RPMTAG_REQUIREVERSION;
    00134         tagF = RPMTAG_REQUIREFLAGS;
    00135     } else
    00136     if (tagN == RPMTAG_CONFLICTNAME) {
    00137         Type = "Conflicts";
    00138         tagEVR = RPMTAG_CONFLICTVERSION;
    00139         tagF = RPMTAG_CONFLICTFLAGS;
    00140     } else
    00141     if (tagN == RPMTAG_OBSOLETENAME) {
    00142         Type = "Obsoletes";
    00143         tagEVR = RPMTAG_OBSOLETEVERSION;
    00144         tagF = RPMTAG_OBSOLETEFLAGS;
    00145     } else
    00146     if (tagN == RPMTAG_TRIGGERNAME) {
    00147         Type = "Trigger";
    00148         tagEVR = RPMTAG_TRIGGERVERSION;
    00149         tagF = RPMTAG_TRIGGERFLAGS;
    00150     } else
    00151         goto exit;
    00152
    00153     /*@-branchstate@*/
    00154     if (hge(h, tagN, &Nt, (void **) &N, &Count)
    00155      && N != NULL && Count > 0)
    00156     {
    00157         int xx;
    00158
    00159         ds = xcalloc(1, sizeof(*ds));
    00160         ds->Type = Type;
    00161         ds->h = (scareMem ? headerLink(h) : NULL);
    00162         ds->i = -1;
    00163         ds->DNEVR = NULL;
    00164         ds->tagN = tagN;
    00165         ds->N = N;
    00166         ds->Nt = Nt;
    00167         ds->Count = Count;
    00168         ds->nopromote = 0;
    00169
    00170         xx = hge(h, tagEVR, &ds->EVRt, (void **) &ds->EVR, NULL);
    00171         xx = hge(h, tagF, &ds->Ft, (void **) &ds->Flags, NULL);
    00172 /*@-boundsread@*/
    00173         if (!scareMem && ds->Flags != NULL)
    00174             ds->Flags = memcpy(xmalloc(ds->Count * sizeof(*ds->Flags)),
    00175                                 ds->Flags, ds->Count * sizeof(*ds->Flags));
    00176 /*@=boundsread@*/
    00177
    00178 /*@-modfilesys@*/
    00179 if (_rpmds_debug < 0)
    00180 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
    00181 /*@=modfilesys@*/
    00182
    00183     }
    00184     /*@=branchstate@*/
    00185
    00186 exit:
    00187     /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
    00188     return rpmdsLink(ds, (ds ? ds->Type : NULL));
    00189     /*@=nullstate@*/
    00190 }
    00191
    00192 char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds)
    00193 {
    00194     char * tbuf, * t;
    00195     size_t nb;
    00196
    00197     nb = 0;
    00198     if (dspfx)  nb += strlen(dspfx) + 1;
    00199 /*@-boundsread@*/
    00200     if (ds->N[ds->i])   nb += strlen(ds->N[ds->i]);
    00201     if (ds->Flags[ds->i] & RPMSENSE_SENSEMASK) {
    00202         if (nb) nb++;
    00203         if (ds->Flags[ds->i] & RPMSENSE_LESS)   nb++;
    00204         if (ds->Flags[ds->i] & RPMSENSE_GREATER) nb++;
    00205         if (ds->Flags[ds->i] & RPMSENSE_EQUAL)  nb++;
    00206     }
    00207     if (ds->EVR[ds->i] && *ds->EVR[ds->i]) {
    00208         if (nb) nb++;
    00209         nb += strlen(ds->EVR[ds->i]);
    00210     }
    00211 /*@=boundsread@*/
    00212
    00213 /*@-boundswrite@*/
    00214     t = tbuf = xmalloc(nb + 1);
    00215     if (dspfx) {
    00216         t = stpcpy(t, dspfx);
    00217         *t++ = ' ';
    00218     }
    00219     if (ds->N[ds->i])
    00220         t = stpcpy(t, ds->N[ds->i]);
    00221     if (ds->Flags[ds->i] & RPMSENSE_SENSEMASK) {
    00222         if (t != tbuf)  *t++ = ' ';
    00223         if (ds->Flags[ds->i] & RPMSENSE_LESS)   *t++ = '<';
    00224         if (ds->Flags[ds->i] & RPMSENSE_GREATER) *t++ = '>';
    00225         if (ds->Flags[ds->i] & RPMSENSE_EQUAL)  *t++ = '=';
    00226     }
    00227     if (ds->EVR[ds->i] && *ds->EVR[ds->i]) {
    00228         if (t != tbuf)  *t++ = ' ';
    00229         t = stpcpy(t, ds->EVR[ds->i]);
    00230     }
    00231     *t = '\0';
    00232 /*@=boundswrite@*/
    00233     return tbuf;
    00234 }
    00235
    00236 rpmds rpmdsThis(Header h, rpmTag tagN, int_32 Flags)
    00237 {
    00238     HGE_t hge = (HGE_t) headerGetEntryMinMemory;
    00239     rpmds ds = NULL;
    00240     const char * Type;
    00241     const char * n, * v, * r;
    00242     int_32 * ep;
    00243     const char ** N, ** EVR;
    00244     char * t;
    00245     int xx;
    00246
    00247     if (tagN == RPMTAG_PROVIDENAME) {
    00248         Type = "Provides";
    00249     } else
    00250     if (tagN == RPMTAG_REQUIRENAME) {
    00251         Type = "Requires";
    00252     } else
    00253     if (tagN == RPMTAG_CONFLICTNAME) {
    00254         Type = "Conflicts";
    00255     } else
    00256     if (tagN == RPMTAG_OBSOLETENAME) {
    00257         Type = "Obsoletes";
    00258     } else
    00259     if (tagN == RPMTAG_TRIGGERNAME) {
    00260         Type = "Trigger";
    00261     } else
    00262         goto exit;
    00263
    00264     xx = headerNVR(h, &n, &v, &r);
    00265     ep = NULL;
    00266     xx = hge(h, RPMTAG_EPOCH, NULL, (void **)&ep, NULL);
    00267
    00268     t = xmalloc(sizeof(*N) + strlen(n) + 1);
    00269 /*@-boundswrite@*/
    00270     N = (const char **) t;
    00271     t += sizeof(*N);
    00272     N[0] = t;
    00273     t = stpcpy(t, n);
    00274
    00275     t = xmalloc(sizeof(*EVR) +
    00276                 (ep ? 20 : 0) + strlen(v) + strlen(r) + sizeof("-"));
    00277     EVR = (const char **) t;
    00278     t += sizeof(*EVR);
    00279     EVR[0] = t;
    00280     if (ep) {
    00281         sprintf(t, "%d:", *ep);
    00282 /*@-compdef@*/
    00283         t += strlen(t);
    00284 /*@=compdef@*/
    00285     }
    00286     t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
    00287 /*@=boundswrite@*/
    00288
    00289     ds = xcalloc(1, sizeof(*ds));
    00290     ds->h = NULL;
    00291     ds->Type = Type;
    00292     ds->tagN = tagN;
    00293     ds->Count = 1;
    00294     ds->N = N;
    00295     ds->Nt = -1;        /* XXX to insure that hfd will free */
    00296     ds->EVR = EVR;
    00297     ds->EVRt = -1;      /* XXX to insure that hfd will free */
    00298 /*@-boundswrite@*/
    00299     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
    00300 /*@=boundswrite@*/
    00301     ds->i = 0;
    00302     {   char pre[2];
    00303 /*@-boundsread@*/
    00304         pre[0] = ds->Type[0];
    00305 /*@=boundsread@*/
    00306         pre[1] = '\0';
    00307         /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
    00308         ds->DNEVR = rpmdsNewDNEVR(pre, ds);
    00309         /*@=nullstate@*/
    00310     }
    00311
    00312 exit:
    00313     return rpmdsLink(ds, (ds ? ds->Type : NULL));
    00314 }
    00315
    00316 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
    00317 {
    00318     rpmds ds = NULL;
    00319     const char * Type;
    00320
    00321     if (tagN == RPMTAG_PROVIDENAME) {
    00322         Type = "Provides";
    00323     } else
    00324     if (tagN == RPMTAG_REQUIRENAME) {
    00325         Type = "Requires";
    00326     } else
    00327     if (tagN == RPMTAG_CONFLICTNAME) {
    00328         Type = "Conflicts";
    00329     } else
    00330     if (tagN == RPMTAG_OBSOLETENAME) {
    00331         Type = "Obsoletes";
    00332     } else
    00333     if (tagN == RPMTAG_TRIGGERNAME) {
    00334         Type = "Trigger";
    00335     } else
    00336         goto exit;
    00337
    00338     ds = xcalloc(1, sizeof(*ds));
    00339     ds->h = NULL;
    00340     ds->Type = Type;
    00341     ds->tagN = tagN;
    00342     ds->Count = 1;
    00343     /*@-assignexpose@*/
    00344 /*@-boundswrite@*/
    00345     ds->N = xmalloc(sizeof(*ds->N));            ds->N[0] = N;
    00346     ds->Nt = -1;        /* XXX to insure that hfd will free */
    00347     ds->EVR = xmalloc(sizeof(*ds->EVR));        ds->EVR[0] = EVR;
    00348     ds->EVRt = -1;      /* XXX to insure that hfd will free */
    00349     /*@=assignexpose@*/
    00350     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
    00351 /*@=boundswrite@*/
    00352     ds->i = 0;
    00353     {   char t[2];
    00354 /*@-boundsread@*/
    00355         t[0] = ds->Type[0];
    00356 /*@=boundsread@*/
    00357         t[1] = '\0';
    00358         ds->DNEVR = rpmdsNewDNEVR(t, ds);
    00359     }
    00360
    00361 exit:
    00362     return rpmdsLink(ds, (ds ? ds->Type : NULL));
    00363 }
    00364
    00365 int rpmdsCount(const rpmds ds)
    00366 {
    00367     return (ds != NULL ? ds->Count : 0);
    00368 }
    00369
    00370 int rpmdsIx(const rpmds ds)
    00371 {
    00372     return (ds != NULL ? ds->i : -1);
    00373 }
    00374
    00375 int rpmdsSetIx(rpmds ds, int ix)
    00376 {
    00377     int i = -1;
    00378
    00379     if (ds != NULL) {
    00380         i = ds->i;
    00381         ds->i = ix;
    00382     }
    00383     return i;
    00384 }
    00385
    00386 const char * rpmdsDNEVR(const rpmds ds)
    00387 {
    00388     const char * DNEVR = NULL;
    00389
    00390     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
    00391 /*@-boundsread@*/
    00392         if (ds->DNEVR != NULL)
    00393             DNEVR = ds->DNEVR;
    00394 /*@=boundsread@*/
    00395     }
    00396     return DNEVR;
    00397 }
    00398
    00399 const char * rpmdsN(const rpmds ds)
    00400 {
    00401     const char * N = NULL;
    00402
    00403     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
    00404 /*@-boundsread@*/
    00405         if (ds->N != NULL)
    00406             N = ds->N[ds->i];
    00407 /*@=boundsread@*/
    00408     }
    00409     return N;
    00410 }
    00411
    00412 const char * rpmdsEVR(const rpmds ds)
    00413 {
    00414     const char * EVR = NULL;
    00415
    00416     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
    00417 /*@-boundsread@*/
    00418         if (ds->EVR != NULL)
    00419             EVR = ds->EVR[ds->i];
    00420 /*@=boundsread@*/
    00421     }
    00422     return EVR;
    00423 }
    00424
    00425 int_32 rpmdsFlags(const rpmds ds)
    00426 {
    00427     int_32 Flags = 0;
    00428
    00429     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
    00430 /*@-boundsread@*/
    00431         if (ds->Flags != NULL)
    00432             Flags = ds->Flags[ds->i];
    00433 /*@=boundsread@*/
    00434     }
    00435     return Flags;
    00436 }
    00437
    00438 rpmTag rpmdsTagN(const rpmds ds)
    00439 {
    00440     rpmTag tagN = 0;
    00441
    00442     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
    00443         tagN = ds->tagN;
    00444     }
    00445     return tagN;
    00446 }
    00447
    00448 int rpmdsNoPromote(const rpmds ds)
    00449 {
    00450     int nopromote = 0;
    00451
    00452     if (ds != NULL)
    00453         nopromote = ds->nopromote;
    00454     return nopromote;
    00455 }
    00456
    00457 int rpmdsSetNoPromote(rpmds ds, int nopromote)
    00458 {
    00459     int onopromote = 0;
    00460
    00461     if (ds != NULL) {
    00462         onopromote = ds->nopromote;
    00463         ds->nopromote = nopromote;
    00464     }
    00465     return onopromote;
    00466 }
    00467
    00468 void rpmdsNotify(rpmds ds, const char * where, int rc)
    00469 {
    00470     if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
    00471         return;
    00472     if (!(ds->Type != NULL && ds->DNEVR != NULL))
    00473         return;
    00474
    00475     rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
    00476                 (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
    00477                 (rc ? _("NO ") : _("YES")),
    00478                 (where != NULL ? where : ""));
    00479 }
    00480
    00481 int rpmdsNext(/*@null@*/ rpmds ds)
    00482         /*@modifies ds @*/
    00483 {
    00484     int i = -1;
    00485
    00486     if (ds != NULL && ++ds->i >= 0) {
    00487         if (ds->i < ds->Count) {
    00488             char t[2];
    00489             i = ds->i;
    00490             ds->DNEVR = _free(ds->DNEVR);
    00491             t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
    00492             t[1] = '\0';
    00493             /*@-nullstate@*/
    00494             ds->DNEVR = rpmdsNewDNEVR(t, ds);
    00495             /*@=nullstate@*/
    00496
    00497         } else
    00498             ds->i = -1;
    00499
    00500 /*@-modfilesys @*/
    00501 if (_rpmds_debug  < 0 && i != -1)
    00502 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
    00503 /*@=modfilesys @*/
    00504
    00505     }
    00506
    00507     return i;
    00508 }
    00509
    00510 rpmds rpmdsInit(/*@null@*/ rpmds ds)
    00511         /*@modifies ds @*/
    00512 {
    00513     if (ds != NULL)
    00514         ds->i = -1;
    00515     /*@-refcounttrans@*/
    00516     return ds;
    00517     /*@=refcounttrans@*/
    00518 }
    00519
    00527 static
    00528 void parseEVR(char * evr,
    00529                 /*@exposed@*/ /*@out@*/ const char ** ep,
    00530                 /*@exposed@*/ /*@out@*/ const char ** vp,
    00531                 /*@exposed@*/ /*@out@*/ const char ** rp)
    00532         /*@modifies *ep, *vp, *rp @*/
    00533 {
    00534     const char *epoch;
    00535     const char *version;                /* assume only version is present */
    00536     const char *release;
    00537     char *s, *se;
    00538
    00539     s = evr;
    00540 /*@-boundsread@*/
    00541     while (*s && xisdigit(*s)) s++;     /* s points to epoch terminator */
    00542     se = strrchr(s, '-');               /* se points to version terminator */
    00543
    00544     if (*s == ':') {
    00545         epoch = evr;
    00546         *s++ = '\0';
    00547         version = s;
    00548         /*@-branchstate@*/
    00549         if (*epoch == '\0') epoch = "0";
    00550         /*@=branchstate@*/
    00551     } else {
    00552         epoch = NULL;   /* XXX disable epoch compare if missing */
    00553         version = evr;
    00554     }
    00555 /*@=boundsread@*/
    00556     if (se) {
    00557 /*@-boundswrite@*/
    00558         *se++ = '\0';
    00559 /*@=boundswrite@*/
    00560         release = se;
    00561     } else {
    00562         release = NULL;
    00563     }
    00564
    00565 /*@-boundswrite@*/
    00566     if (ep) *ep = epoch;
    00567     if (vp) *vp = version;
    00568     if (rp) *rp = release;
    00569 /*@=boundswrite@*/
    00570 }
    00571
    00572 int rpmdsCompare(const rpmds A, const rpmds B)
    00573 {
    00574     const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
    00575     const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
    00576     char *aEVR, *bEVR;
    00577     const char *aE, *aV, *aR, *bE, *bV, *bR;
    00578     int result;
    00579     int sense;
    00580
    00581 /*@-boundsread@*/
    00582     /* Different names don't overlap. */
    00583     if (strcmp(A->N[A->i], B->N[B->i])) {
    00584         result = 0;
    00585         goto exit;
    00586     }
    00587
    00588     /* Same name. If either A or B is an existence test, always overlap. */
    00589     if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
    00590         result = 1;
    00591         goto exit;
    00592     }
    00593
    00594     /* If either EVR is non-existent or empty, always overlap. */
    00595     if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i])) {
    00596         result = 1;
    00597         goto exit;
    00598     }
    00599
    00600     /* Both AEVR and BEVR exist. */
    00601     aEVR = xstrdup(A->EVR[A->i]);
    00602     parseEVR(aEVR, &aE, &aV, &aR);
    00603     bEVR = xstrdup(B->EVR[B->i]);
    00604     parseEVR(bEVR, &bE, &bV, &bR);
    00605
    00606     /* Compare {A,B} [epoch:]version[-release] */
    00607     sense = 0;
    00608     if (aE && *aE && bE && *bE)
    00609         sense = rpmvercmp(aE, bE);
    00610     else if (aE && *aE && atol(aE) > 0) {
    00611         if (!B->nopromote) {
    00612             int lvl = (_rpmds_unspecified_epoch_noise  ? RPMMESS_WARNING : RPMMESS_DEBUG);
    00613             rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
    00614                 aDepend, bDepend);
    00615             sense = 0;
    00616         } else
    00617             sense = 1;
    00618     } else if (bE && *bE && atol(bE) > 0)
    00619         sense = -1;
    00620
    00621     if (sense == 0) {
    00622         sense = rpmvercmp(aV, bV);
    00623         if (sense == 0 && aR && *aR && bR && *bR) {
    00624             sense = rpmvercmp(aR, bR);
    00625         }
    00626     }
    00627 /*@=boundsread@*/
    00628     aEVR = _free(aEVR);
    00629     bEVR = _free(bEVR);
    00630
    00631     /* Detect overlap of {A,B} range. */
    00632     result = 0;
    00633     if (sense < 0 && ((A->Flags[A->i] & RPMSENSE_GREATER) || (B->Flags[B->i] & RPMSENSE_LESS))) {
    00634         result = 1;
    00635     } else if (sense > 0 && ((A->Flags[A->i] & RPMSENSE_LESS) || (B->Flags[B->i] & RPMSENSE_GREATER))) {
    00636         result = 1;
    00637     } else if (sense == 0 &&
    00638         (((A->Flags[A->i] & RPMSENSE_EQUAL) && (B->Flags[B->i] & RPMSENSE_EQUAL)) ||
    00639          ((A->Flags[A->i] & RPMSENSE_LESS) && (B->Flags[B->i] & RPMSENSE_LESS)) ||
    00640          ((A->Flags[A->i] & RPMSENSE_GREATER) && (B->Flags[B->i] & RPMSENSE_GREATER)))) {
    00641         result = 1;
    00642     }
    00643
    00644 exit:
    00645     if (_noisy_range_comparison_debug_message)
    00646     rpmMessage(RPMMESS_DEBUG, _("  %s    A %s\tB %s\n"),
    00647         (result ? _("YES") : _("NO ")), aDepend, bDepend);
    00648     aDepend = _free(aDepend);
    00649     bDepend = _free(bDepend);
    00650     return result;
    00651 }
    00652
    00653 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
    00654         const fnpyKey * suggestedKeys, int adding)
    00655 {
    00656     const char * Name =  rpmdsN(ds);
    00657     const char * DNEVR = rpmdsDNEVR(ds);
    00658     const char * EVR = rpmdsEVR(ds);
    00659     rpmProblemType type;
    00660     fnpyKey key;
    00661
    00662     if (ps == NULL) return;
    00663
    00664     /*@-branchstate@*/
    00665     if (Name == NULL) Name = "?N?";
    00666     if (EVR == NULL) EVR = "?EVR?";
    00667     if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
    00668     /*@=branchstate@*/
    00669
    00670     rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
    00671             pkgNEVR, ds->Type, DNEVR+2);
    00672
    00673     switch ((unsigned)DNEVR[0]) {
    00674     case 'C':   type = RPMPROB_CONFLICT;        break;
    00675     default:
    00676     case 'R':   type = RPMPROB_REQUIRES;        break;
    00677     }
    00678
    00679     key = (suggestedKeys ? suggestedKeys[0] : NULL);
    00680     rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
    00681 }
    00682
    00683 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
    00684 {
    00685     int scareMem = 1;
    00686     rpmds provides = NULL;
    00687     int result = 0;
    00688
    00689 /*@-boundsread@*/
    00690     if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
    00691         return 1;
    00692 /*@=boundsread@*/
    00693
    00694     /* Get provides information from header */
    00695     provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
    00696     if (provides == NULL)
    00697         goto exit;      /* XXX should never happen */
    00698     if (nopromote)
    00699         (void) rpmdsSetNoPromote(provides, nopromote);
    00700
    00701     /*
    00702      * Rpm prior to 3.0.3 did not have versioned provides.
    00703      * If no provides version info is available, match any/all requires
    00704      * with same name.
    00705      */
    00706     if (provides->EVR == NULL) {
    00707         result = 1;
    00708         goto exit;
    00709     }
    00710
    00711     result = 0;
    00712     if (provides != NULL)
    00713     while (rpmdsNext(provides) >= 0) {
    00714
    00715         /* Filter out provides that came along for the ride. */
    00716 /*@-boundsread@*/
    00717         if (strcmp(provides->N[provides->i], req->N[req->i]))
    00718             continue;
    00719 /*@=boundsread@*/
    00720
    00721         result = rpmdsCompare(provides, req);
    00722
    00723         /* If this provide matches the require, we're done. */
    00724         if (result)
    00725             break;
    00726     }
    00727
    00728 exit:
    00729     provides = rpmdsFree(provides);
    00730
    00731     return result;
    00732 }
    00733
    00734 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
    00735 {
    00736     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00737     const char * pkgN, * v, * r;
    00738     int_32 * epoch;
    00739     const char * pkgEVR;
    00740     char * t;
    00741     int_32 pkgFlags = RPMSENSE_EQUAL;
    00742     rpmds pkg;
    00743     int rc = 1; /* XXX assume match, names already match here */
    00744
    00745 /*@-boundsread@*/
    00746     if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
    00747         return rc;
    00748 /*@=boundsread@*/
    00749
    00750     /* Get package information from header */
    00751     (void) headerNVR(h, &pkgN, &v, &r);
    00752
    00753 /*@-boundswrite@*/
    00754     t = alloca(21 + strlen(v) + 1 + strlen(r) + 1);
    00755     pkgEVR = t;
    00756     *t = '\0';
    00757     if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
    00758         sprintf(t, "%d:", *epoch);
    00759         while (*t != '\0')
    00760             t++;
    00761     }
    00762     (void) stpcpy( stpcpy( stpcpy(t, v) , "-") , r);
    00763 /*@=boundswrite@*/
    00764
    00765     if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
    00766         if (nopromote)
    00767             (void) rpmdsSetNoPromote(pkg, nopromote);
    00768         rc = rpmdsCompare(pkg, req);
    00769         pkg = rpmdsFree(pkg);
    00770     }
    00771
    00772     return rc;
    00773 }