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
00017 static int _noisy_range_comparison_debug_message = 0;
00018
00019
00020 int _rpmds_debug = 0;
00021
00022
00023 int _rpmds_nopromote = 1;
00024
00025
00026
00027 int _rpmds_unspecified_epoch_noise = 0;
00028
00029
00030 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
00031 {
00032 if (ds == NULL) return NULL;
00033
00034 if (_rpmds_debug && msg != NULL)
00035 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00036
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
00047 if (_rpmds_debug && msg != NULL)
00048 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00049
00050
00051 return ds;
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
00066 if (_rpmds_debug < 0)
00067 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00068
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
00093 if (ds->Count > 0) {
00094 ds->N = hfd(ds->N, ds->Nt);
00095 ds->EVR = hfd(ds->EVR, ds->EVRt);
00096
00097 ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
00098
00099 ds->h = headerFree(ds->h);
00100 }
00101
00102
00103 ds->DNEVR = _free(ds->DNEVR);
00104
00105 (void) rpmdsUnlink(ds, ds->Type);
00106
00107
00108 memset(ds, 0, sizeof(*ds));
00109
00110 ds = _free(ds);
00111
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
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
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
00177
00178
00179 if (_rpmds_debug < 0)
00180 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00181
00182
00183 }
00184
00185
00186 exit:
00187
00188 return rpmdsLink(ds, (ds ? ds->Type : NULL));
00189
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
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
00212
00213
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
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
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
00283 t += strlen(t);
00284
00285 }
00286 t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
00287
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;
00296 ds->EVR = EVR;
00297 ds->EVRt = -1;
00298
00299 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
00300
00301 ds->i = 0;
00302 { char pre[2];
00303
00304 pre[0] = ds->Type[0];
00305
00306 pre[1] = '\0';
00307
00308 ds->DNEVR = rpmdsNewDNEVR(pre, ds);
00309
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
00344
00345 ds->N = xmalloc(sizeof(*ds->N)); ds->N[0] = N;
00346 ds->Nt = -1;
00347 ds->EVR = xmalloc(sizeof(*ds->EVR)); ds->EVR[0] = EVR;
00348 ds->EVRt = -1;
00349
00350 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
00351
00352 ds->i = 0;
00353 { char t[2];
00354
00355 t[0] = ds->Type[0];
00356
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
00392 if (ds->DNEVR != NULL)
00393 DNEVR = ds->DNEVR;
00394
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
00405 if (ds->N != NULL)
00406 N = ds->N[ds->i];
00407
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
00418 if (ds->EVR != NULL)
00419 EVR = ds->EVR[ds->i];
00420
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
00431 if (ds->Flags != NULL)
00432 Flags = ds->Flags[ds->i];
00433
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( rpmds ds)
00482
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
00494 ds->DNEVR = rpmdsNewDNEVR(t, ds);
00495
00496
00497 } else
00498 ds->i = -1;
00499
00500
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
00504
00505 }
00506
00507 return i;
00508 }
00509
00510 rpmds rpmdsInit( rpmds ds)
00511
00512 {
00513 if (ds != NULL)
00514 ds->i = -1;
00515
00516 return ds;
00517
00518 }
00519
00527 static
00528 void parseEVR(char * evr,
00529 const char ** ep,
00530 const char ** vp,
00531 const char ** rp)
00532
00533 {
00534 const char *epoch;
00535 const char *version;
00536 const char *release;
00537 char *s, *se;
00538
00539 s = evr;
00540
00541 while (*s && xisdigit(*s)) s++;
00542 se = strrchr(s, '-');
00543
00544 if (*s == ':') {
00545 epoch = evr;
00546 *s++ = '\0';
00547 version = s;
00548
00549 if (*epoch == '\0') epoch = "0";
00550
00551 } else {
00552 epoch = NULL;
00553 version = evr;
00554 }
00555
00556 if (se) {
00557
00558 *se++ = '\0';
00559
00560 release = se;
00561 } else {
00562 release = NULL;
00563 }
00564
00565
00566 if (ep) *ep = epoch;
00567 if (vp) *vp = version;
00568 if (rp) *rp = release;
00569
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
00582
00583 if (strcmp(A->N[A->i], B->N[B->i])) {
00584 result = 0;
00585 goto exit;
00586 }
00587
00588
00589 if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
00590 result = 1;
00591 goto exit;
00592 }
00593
00594
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
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
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
00628 aEVR = _free(aEVR);
00629 bEVR = _free(bEVR);
00630
00631
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
00665 if (Name == NULL) Name = "?N?";
00666 if (EVR == NULL) EVR = "?EVR?";
00667 if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
00668
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
00690 if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
00691 return 1;
00692
00693
00694
00695 provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
00696 if (provides == NULL)
00697 goto exit;
00698 if (nopromote)
00699 (void) rpmdsSetNoPromote(provides, nopromote);
00700
00701
00702
00703
00704
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
00716
00717 if (strcmp(provides->N[provides->i], req->N[req->i]))
00718 continue;
00719
00720
00721 result = rpmdsCompare(provides, req);
00722
00723
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;
00744
00745
00746 if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
00747 return rc;
00748
00749
00750
00751 (void) headerNVR(h, &pkgN, &v, &r);
00752
00753
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
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 }