8 #define _RPMDS_INTERNAL
14 * Enable noisy range comparison debugging message?
17 static int _noisy_range_comparison_debug_message = 0;
23 int _rpmds_nopromote = 1;
26 /*@-exportheadervar@*/
27 int _rpmds_unspecified_epoch_noise = 0;
28 /*@=exportheadervar@*/
30 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
32 if (ds == NULL) return NULL;
34 if (_rpmds_debug && msg != NULL)
35 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
41 rpmds XrpmdsLink(rpmds ds, const char * msg, const char * fn, unsigned ln)
43 if (ds == NULL) return NULL;
47 if (_rpmds_debug && msg != NULL)
48 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
51 /*@-refcounttrans@*/ return ds; /*@=refcounttrans@*/
54 rpmds rpmdsFree(rpmds ds)
56 HFD_t hfd = headerFreeData;
63 return rpmdsUnlink(ds, ds->Type);
67 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
70 if (ds->tagN == RPMTAG_PROVIDENAME) {
71 tagEVR = RPMTAG_PROVIDEVERSION;
72 tagF = RPMTAG_PROVIDEFLAGS;
74 if (ds->tagN == RPMTAG_REQUIRENAME) {
75 tagEVR = RPMTAG_REQUIREVERSION;
76 tagF = RPMTAG_REQUIREFLAGS;
78 if (ds->tagN == RPMTAG_CONFLICTNAME) {
79 tagEVR = RPMTAG_CONFLICTVERSION;
80 tagF = RPMTAG_CONFLICTFLAGS;
82 if (ds->tagN == RPMTAG_OBSOLETENAME) {
83 tagEVR = RPMTAG_OBSOLETEVERSION;
84 tagF = RPMTAG_OBSOLETEFLAGS;
86 if (ds->tagN == RPMTAG_TRIGGERNAME) {
87 tagEVR = RPMTAG_TRIGGERVERSION;
88 tagF = RPMTAG_TRIGGERFLAGS;
94 ds->N = hfd(ds->N, ds->Nt);
95 ds->EVR = hfd(ds->EVR, ds->EVRt);
97 ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
99 ds->h = headerFree(ds->h);
103 ds->DNEVR = _free(ds->DNEVR);
104 ds->Color = _free(ds->Color);
105 ds->Refs = _free(ds->Refs);
107 (void) rpmdsUnlink(ds, ds->Type);
108 /*@-refcounttrans -usereleased@*/
110 memset(ds, 0, sizeof(*ds)); /* XXX trash and burn */
113 /*@=refcounttrans =usereleased@*/
117 rpmds rpmdsNew(Header h, rpmTag tagN, int scareMem)
120 (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry);
128 if (tagN == RPMTAG_PROVIDENAME) {
130 tagEVR = RPMTAG_PROVIDEVERSION;
131 tagF = RPMTAG_PROVIDEFLAGS;
133 if (tagN == RPMTAG_REQUIRENAME) {
135 tagEVR = RPMTAG_REQUIREVERSION;
136 tagF = RPMTAG_REQUIREFLAGS;
138 if (tagN == RPMTAG_CONFLICTNAME) {
140 tagEVR = RPMTAG_CONFLICTVERSION;
141 tagF = RPMTAG_CONFLICTFLAGS;
143 if (tagN == RPMTAG_OBSOLETENAME) {
145 tagEVR = RPMTAG_OBSOLETEVERSION;
146 tagF = RPMTAG_OBSOLETEFLAGS;
148 if (tagN == RPMTAG_TRIGGERNAME) {
150 tagEVR = RPMTAG_TRIGGERVERSION;
151 tagF = RPMTAG_TRIGGERFLAGS;
156 if (hge(h, tagN, &Nt, (void **) &N, &Count)
157 && N != NULL && Count > 0)
161 ds = xcalloc(1, sizeof(*ds));
163 ds->h = (scareMem ? headerLink(h) : NULL);
172 xx = hge(h, tagEVR, &ds->EVRt, (void **) &ds->EVR, NULL);
173 xx = hge(h, tagF, &ds->Ft, (void **) &ds->Flags, NULL);
175 if (!scareMem && ds->Flags != NULL)
176 ds->Flags = memcpy(xmalloc(ds->Count * sizeof(*ds->Flags)),
177 ds->Flags, ds->Count * sizeof(*ds->Flags));
179 ds->Color = xcalloc(Count, sizeof(*ds->Color));
180 ds->Refs = xcalloc(Count, sizeof(*ds->Refs));
183 if (_rpmds_debug < 0)
184 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
191 /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
192 return rpmdsLink(ds, (ds ? ds->Type : NULL));
196 char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds)
202 if (dspfx) nb += strlen(dspfx) + 1;
204 if (ds->N[ds->i]) nb += strlen(ds->N[ds->i]);
205 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
206 if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
208 if (ds->Flags[ds->i] & RPMSENSE_LESS) nb++;
209 if (ds->Flags[ds->i] & RPMSENSE_GREATER) nb++;
210 if (ds->Flags[ds->i] & RPMSENSE_EQUAL) nb++;
212 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
213 if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
215 nb += strlen(ds->EVR[ds->i]);
220 t = tbuf = xmalloc(nb + 1);
222 t = stpcpy(t, dspfx);
226 t = stpcpy(t, ds->N[ds->i]);
227 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
228 if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
229 if (t != tbuf) *t++ = ' ';
230 if (ds->Flags[ds->i] & RPMSENSE_LESS) *t++ = '<';
231 if (ds->Flags[ds->i] & RPMSENSE_GREATER) *t++ = '>';
232 if (ds->Flags[ds->i] & RPMSENSE_EQUAL) *t++ = '=';
234 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
235 if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
236 if (t != tbuf) *t++ = ' ';
237 t = stpcpy(t, ds->EVR[ds->i]);
244 rpmds rpmdsThis(Header h, rpmTag tagN, int_32 Flags)
246 HGE_t hge = (HGE_t) headerGetEntryMinMemory;
249 const char * n, * v, * r;
251 const char ** N, ** EVR;
255 if (tagN == RPMTAG_PROVIDENAME) {
258 if (tagN == RPMTAG_REQUIRENAME) {
261 if (tagN == RPMTAG_CONFLICTNAME) {
264 if (tagN == RPMTAG_OBSOLETENAME) {
267 if (tagN == RPMTAG_TRIGGERNAME) {
272 xx = headerNVR(h, &n, &v, &r);
274 xx = hge(h, RPMTAG_EPOCH, NULL, (void **)&ep, NULL);
276 t = xmalloc(sizeof(*N) + strlen(n) + 1);
278 N = (const char **) t;
284 t = xmalloc(sizeof(*EVR) +
285 (ep ? 20 : 0) + strlen(v) + strlen(r) + sizeof("-"));
286 EVR = (const char **) t;
291 sprintf(t, "%d:", *ep);
294 t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
297 ds = xcalloc(1, sizeof(*ds));
303 ds->Nt = -1; /* XXX to insure that hfd will free */
305 ds->EVRt = -1; /* XXX to insure that hfd will free */
307 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
312 pre[0] = ds->Type[0];
315 /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
316 ds->DNEVR = rpmdsNewDNEVR(pre, ds);
321 return rpmdsLink(ds, (ds ? ds->Type : NULL));
324 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
329 if (tagN == RPMTAG_PROVIDENAME) {
332 if (tagN == RPMTAG_REQUIRENAME) {
335 if (tagN == RPMTAG_CONFLICTNAME) {
338 if (tagN == RPMTAG_OBSOLETENAME) {
341 if (tagN == RPMTAG_TRIGGERNAME) {
346 ds = xcalloc(1, sizeof(*ds));
353 ds->N = xmalloc(sizeof(*ds->N)); ds->N[0] = N;
354 ds->Nt = -1; /* XXX to insure that hfd will free */
355 ds->EVR = xmalloc(sizeof(*ds->EVR)); ds->EVR[0] = EVR;
356 ds->EVRt = -1; /* XXX to insure that hfd will free */
358 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
366 ds->DNEVR = rpmdsNewDNEVR(t, ds);
370 return rpmdsLink(ds, (ds ? ds->Type : NULL));
373 int rpmdsCount(const rpmds ds)
375 return (ds != NULL ? ds->Count : 0);
378 int rpmdsIx(const rpmds ds)
380 return (ds != NULL ? ds->i : -1);
383 int rpmdsSetIx(rpmds ds, int ix)
394 const char * rpmdsDNEVR(const rpmds ds)
396 const char * DNEVR = NULL;
398 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
400 if (ds->DNEVR != NULL)
407 const char * rpmdsN(const rpmds ds)
409 const char * N = NULL;
411 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
420 const char * rpmdsEVR(const rpmds ds)
422 const char * EVR = NULL;
424 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
427 EVR = ds->EVR[ds->i];
433 int_32 rpmdsFlags(const rpmds ds)
437 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
439 if (ds->Flags != NULL)
440 Flags = ds->Flags[ds->i];
446 rpmTag rpmdsTagN(const rpmds ds)
455 int rpmdsNoPromote(const rpmds ds)
460 nopromote = ds->nopromote;
464 int rpmdsSetNoPromote(rpmds ds, int nopromote)
469 onopromote = ds->nopromote;
470 ds->nopromote = nopromote;
475 int_32 rpmdsColor(const rpmds ds)
479 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
481 if (ds->Color != NULL)
482 Color = ds->Color[ds->i];
488 int_32 rpmdsSetColor(const rpmds ds, int_32 color)
492 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
494 if (ds->Color != NULL) {
495 ocolor = ds->Color[ds->i];
496 ds->Color[ds->i] = color;
503 int_32 rpmdsRefs(const rpmds ds)
507 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
509 if (ds->Refs != NULL)
510 Refs = ds->Refs[ds->i];
516 int_32 rpmdsSetRefs(const rpmds ds, int_32 refs)
520 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
522 if (ds->Refs != NULL) {
523 orefs = ds->Refs[ds->i];
524 ds->Refs[ds->i] = refs;
531 void rpmdsNotify(rpmds ds, const char * where, int rc)
533 if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
535 if (!(ds->Type != NULL && ds->DNEVR != NULL))
538 rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
539 (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
540 (rc ? _("NO ") : _("YES")),
541 (where != NULL ? where : ""));
544 int rpmdsNext(/*@null@*/ rpmds ds)
549 if (ds != NULL && ++ds->i >= 0) {
550 if (ds->i < ds->Count) {
553 ds->DNEVR = _free(ds->DNEVR);
554 t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
557 ds->DNEVR = rpmdsNewDNEVR(t, ds);
564 if (_rpmds_debug < 0 && i != -1)
565 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
573 rpmds rpmdsInit(/*@null@*/ rpmds ds)
584 static const char ** rpmdsDupArgv(const char ** argv, int argc)
592 for (ac = 0; ac < argc; ac++) {
593 assert(argv[ac] != NULL);
594 nb += strlen(argv[ac]) + 1;
596 nb += (ac + 1) * sizeof(*av);
599 t = (char *) (av + ac + 1);
600 for (ac = 0; ac < argc; ac++) {
602 t = stpcpy(t, argv[ac]) + 1;
609 static rpmds rpmdsDup(const rpmds ods)
612 rpmds ds = xcalloc(1, sizeof(*ds));
615 ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
617 ds->Type = ods->Type;
619 ds->tagN = ods->tagN;
620 ds->Count = ods->Count;
625 nb = (ds->Count+1) * sizeof(*ds->N);
626 ds->N = (ds->h != NULL
627 ? memcpy(xmalloc(nb), ods->N, nb)
628 : rpmdsDupArgv(ods->N, ods->Count) );
631 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
632 /*@-nullderef -nullpass@*/
633 assert(ds->EVR != NULL);
634 assert(ds->Flags != NULL);
636 nb = (ds->Count+1) * sizeof(*ds->EVR);
637 ds->EVR = (ds->h != NULL
638 ? memcpy(xmalloc(nb), ods->EVR, nb)
639 : rpmdsDupArgv(ods->EVR, ods->Count) );
640 ds->EVRt = ods->EVRt;
642 nb = (ds->Count * sizeof(*ds->Flags));
643 ds->Flags = (ds->h != NULL
645 : memcpy(xmalloc(nb), ods->Flags, nb) );
647 /*@=nullderef =nullpass@*/
649 /*@-compmempass@*/ /* FIX: ds->Flags is kept, not only */
650 return rpmdsLink(ds, (ds ? ds->Type : NULL));
655 int rpmdsFind(rpmds ds, rpmds ods)
659 if (ds == NULL || ods == NULL)
664 while (ds->l < ds->u) {
665 ds->i = (ds->l + ds->u) / 2;
667 comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
669 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
671 if (comparison == 0 && ods->EVR && ds->EVR)
672 comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
673 if (comparison == 0 && ods->Flags && ds->Flags)
674 comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
679 else if (comparison > 0)
687 int rpmdsMerge(rpmds * dsp, rpmds ods)
696 if (dsp == NULL || ods == NULL)
699 /* If not initialized yet, dup the 1st entry. */
704 *dsp = rpmdsDup(ods);
714 ods = rpmdsInit(ods);
716 while (rpmdsNext(ods) >= 0) {
718 * If this entry is already present, don't bother.
720 if (rpmdsFind(ds, ods) >= 0)
726 for (j = ds->Count; j > ds->u; j--)
727 ds->N[j] = ds->N[j-1];
728 ds->N[ds->u] = ods->N[ods->i];
729 N = rpmdsDupArgv(ds->N, ds->Count+1);
730 ds->N = _free(ds->N);
733 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
735 assert(ds->EVR != NULL);
736 assert(ds->Flags != NULL);
738 for (j = ds->Count; j > ds->u; j--)
739 ds->EVR[j] = ds->EVR[j-1];
740 ds->EVR[ds->u] = ods->EVR[ods->i];
741 EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
742 ds->EVR = _free(ds->EVR);
745 Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
747 memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
748 if (ds->u < ds->Count)
749 memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
750 Flags[ds->u] = ods->Flags[ods->i];
751 ds->Flags = _free(ds->Flags);
766 * Split EVR into epoch, version, and release components.
767 * @param evr [epoch:]version[-release] string
768 * @retval *ep pointer to epoch
769 * @retval *vp pointer to version
770 * @retval *rp pointer to release
773 void parseEVR(char * evr,
774 /*@exposed@*/ /*@out@*/ const char ** ep,
775 /*@exposed@*/ /*@out@*/ const char ** vp,
776 /*@exposed@*/ /*@out@*/ const char ** rp)
777 /*@modifies *ep, *vp, *rp @*/
778 /*@requires maxSet(ep) >= 0 /\ maxSet(vp) >= 0 /\ maxSet(rp) >= 0 @*/
781 const char *version; /* assume only version is present */
786 while (*s && xisdigit(*s)) s++; /* s points to epoch terminator */
787 se = strrchr(s, '-'); /* se points to version terminator */
794 if (*epoch == '\0') epoch = "0";
797 epoch = NULL; /* XXX disable epoch compare if missing */
810 if (vp) *vp = version;
811 if (rp) *rp = release;
814 int rpmdsCompare(const rpmds A, const rpmds B)
816 const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
817 const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
819 const char *aE, *aV, *aR, *bE, *bV, *bR;
824 /* Different names don't overlap. */
825 if (strcmp(A->N[A->i], B->N[B->i])) {
830 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
832 if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
837 /* Same name. If either A or B is an existence test, always overlap. */
838 if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
843 /* If either EVR is non-existent or empty, always overlap. */
844 if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i])) {
849 /* Both AEVR and BEVR exist. */
851 aEVR = xstrdup(A->EVR[A->i]);
852 parseEVR(aEVR, &aE, &aV, &aR);
853 bEVR = xstrdup(B->EVR[B->i]);
854 parseEVR(bEVR, &bE, &bV, &bR);
857 /* Compare {A,B} [epoch:]version[-release] */
859 if (aE && *aE && bE && *bE)
860 sense = rpmvercmp(aE, bE);
861 else if (aE && *aE && atol(aE) > 0) {
863 int lvl = (_rpmds_unspecified_epoch_noise ? RPMMESS_WARNING : RPMMESS_DEBUG);
864 rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
869 } else if (bE && *bE && atol(bE) > 0)
873 sense = rpmvercmp(aV, bV);
874 if (sense == 0 && aR && *aR && bR && *bR) {
875 sense = rpmvercmp(aR, bR);
882 /* Detect overlap of {A,B} range. */
884 if (sense < 0 && ((A->Flags[A->i] & RPMSENSE_GREATER) || (B->Flags[B->i] & RPMSENSE_LESS))) {
886 } else if (sense > 0 && ((A->Flags[A->i] & RPMSENSE_LESS) || (B->Flags[B->i] & RPMSENSE_GREATER))) {
888 } else if (sense == 0 &&
889 (((A->Flags[A->i] & RPMSENSE_EQUAL) && (B->Flags[B->i] & RPMSENSE_EQUAL)) ||
890 ((A->Flags[A->i] & RPMSENSE_LESS) && (B->Flags[B->i] & RPMSENSE_LESS)) ||
891 ((A->Flags[A->i] & RPMSENSE_GREATER) && (B->Flags[B->i] & RPMSENSE_GREATER)))) {
897 if (_noisy_range_comparison_debug_message)
898 rpmMessage(RPMMESS_DEBUG, _(" %s A %s\tB %s\n"),
899 (result ? _("YES") : _("NO ")), aDepend, bDepend);
900 aDepend = _free(aDepend);
901 bDepend = _free(bDepend);
905 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
906 const fnpyKey * suggestedKeys, int adding)
908 const char * Name = rpmdsN(ds);
909 const char * DNEVR = rpmdsDNEVR(ds);
910 const char * EVR = rpmdsEVR(ds);
914 if (ps == NULL) return;
917 if (Name == NULL) Name = "?N?";
918 if (EVR == NULL) EVR = "?EVR?";
919 if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
922 rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
923 pkgNEVR, ds->Type, DNEVR+2);
925 switch ((unsigned)DNEVR[0]) {
926 case 'C': type = RPMPROB_CONFLICT; break;
928 case 'R': type = RPMPROB_REQUIRES; break;
931 key = (suggestedKeys ? suggestedKeys[0] : NULL);
932 rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
935 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
938 rpmds provides = NULL;
941 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
942 if (req->EVR == NULL || req->Flags == NULL)
946 if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
950 /* Get provides information from header */
951 provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
952 if (provides == NULL)
953 goto exit; /* XXX should never happen */
955 (void) rpmdsSetNoPromote(provides, nopromote);
958 * Rpm prior to 3.0.3 did not have versioned provides.
959 * If no provides version info is available, match any/all requires
962 if (provides->EVR == NULL) {
968 if (provides != NULL)
969 while (rpmdsNext(provides) >= 0) {
971 /* Filter out provides that came along for the ride. */
973 if (strcmp(provides->N[provides->i], req->N[req->i]))
977 result = rpmdsCompare(provides, req);
979 /* If this provide matches the require, we're done. */
985 provides = rpmdsFree(provides);
990 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
992 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
993 const char * pkgN, * v, * r;
997 int_32 pkgFlags = RPMSENSE_EQUAL;
999 int rc = 1; /* XXX assume match, names already match here */
1001 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
1002 if (req->EVR == NULL || req->Flags == NULL)
1006 if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
1010 /* Get package information from header */
1011 (void) headerNVR(h, &pkgN, &v, &r);
1014 t = alloca(21 + strlen(v) + 1 + strlen(r) + 1);
1017 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
1018 sprintf(t, "%d:", *epoch);
1022 (void) stpcpy( stpcpy( stpcpy(t, v) , "-") , r);
1025 if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
1027 (void) rpmdsSetNoPromote(pkg, nopromote);
1028 rc = rpmdsCompare(pkg, req);
1029 pkg = rpmdsFree(pkg);