6 #include <rpm/rpmtypes.h>
7 #include <rpm/rpmlib.h> /* rpmvercmp */
8 #include <rpm/rpmstring.h>
9 #include <rpm/rpmlog.h>
10 #include <rpm/rpmstrpool.h>
12 #include "lib/rpmds_internal.h"
18 int _rpmds_nopromote = 1;
21 * A package dependency set.
24 rpmstrPool pool; /*!< String pool. */
25 const char * Type; /*!< Tag name. */
26 char * DNEVR; /*!< Formatted dependency string. */
27 rpmsid * N; /*!< Dependency name id's (pool) */
28 rpmsid * EVR; /*!< Dependency EVR id's (pool) */
29 rpmsenseFlags * Flags; /*!< Bit(s) identifying context/comparison. */
30 rpm_color_t * Color; /*!< Bit(s) calculated from file color(s). */
31 rpmTagVal tagN; /*!< Header tag. */
32 int32_t Count; /*!< No. of elements */
33 unsigned int instance; /*!< From rpmdb instance? */
34 int i; /*!< Element index. */
35 unsigned l; /*!< Low element (bsearch). */
36 unsigned u; /*!< High element (bsearch). */
37 int nopromote; /*!< Don't promote Epoch: in rpmdsCompare()? */
38 int nrefs; /*!< Reference count. */
41 static int dsType(rpmTagVal tag,
42 const char ** Type, rpmTagVal * tagEVR, rpmTagVal * tagF)
46 rpmTagVal evr = RPMTAG_NOT_FOUND;
47 rpmTagVal f = RPMTAG_NOT_FOUND;
49 if (tag == RPMTAG_PROVIDENAME) {
51 evr = RPMTAG_PROVIDEVERSION;
52 f = RPMTAG_PROVIDEFLAGS;
53 } else if (tag == RPMTAG_REQUIRENAME) {
55 evr = RPMTAG_REQUIREVERSION;
56 f = RPMTAG_REQUIREFLAGS;
57 } else if (tag == RPMTAG_CONFLICTNAME) {
59 evr = RPMTAG_CONFLICTVERSION;
60 f = RPMTAG_CONFLICTFLAGS;
61 } else if (tag == RPMTAG_OBSOLETENAME) {
63 evr = RPMTAG_OBSOLETEVERSION;
64 f = RPMTAG_OBSOLETEFLAGS;
65 } else if (tag == RPMTAG_ORDERNAME) {
67 evr = RPMTAG_ORDERVERSION;
68 f = RPMTAG_ORDERFLAGS;
69 } else if (tag == RPMTAG_TRIGGERNAME) {
71 evr = RPMTAG_TRIGGERVERSION;
72 f = RPMTAG_TRIGGERFLAGS;
73 } else if (tag == RPMTAG_ENHANCESNAME) {
75 evr = RPMTAG_ENHANCESVERSION;
76 f = RPMTAG_ENHANCESFLAGS;
81 if (tagEVR) *tagEVR = evr;
86 rpmsid rpmdsNIdIndex(rpmds ds, int i)
89 if (ds != NULL && i >= 0 && i < ds->Count && ds->N != NULL)
94 rpmsid rpmdsEVRIdIndex(rpmds ds, int i)
97 if (ds != NULL && i >= 0 && i < ds->Count && ds->EVR != NULL)
101 const char * rpmdsNIndex(rpmds ds, int i)
103 const char * N = NULL;
104 if (ds != NULL && i >= 0 && i < ds->Count && ds->N != NULL)
105 N = rpmstrPoolStr(ds->pool, ds->N[i]);
109 const char * rpmdsEVRIndex(rpmds ds, int i)
111 const char * EVR = NULL;
112 if (ds != NULL && i >= 0 && i < ds->Count && ds->EVR != NULL)
113 EVR = rpmstrPoolStr(ds->pool, ds->EVR[i]);
117 rpmsenseFlags rpmdsFlagsIndex(rpmds ds, int i)
119 rpmsenseFlags Flags = 0;
120 if (ds != NULL && i >= 0 && i < ds->Count && ds->Flags != NULL)
121 Flags = ds->Flags[i];
125 rpm_color_t rpmdsColorIndex(rpmds ds, int i)
127 rpm_color_t Color = 0;
128 if (ds != NULL && i >= 0 && i < ds->Count && ds->Color != NULL)
129 Color = ds->Color[i];
132 static rpmds rpmdsUnlink(rpmds ds)
139 rpmds rpmdsLink(rpmds ds)
146 rpmds rpmdsFree(rpmds ds)
148 rpmTagVal tagEVR, tagF;
154 return rpmdsUnlink(ds);
156 if (dsType(ds->tagN, NULL, &tagEVR, &tagF))
160 ds->N = _free(ds->N);
161 ds->EVR = _free(ds->EVR);
162 ds->Flags = _free(ds->Flags);
165 ds->pool = rpmstrPoolFree(ds->pool);
166 ds->DNEVR = _free(ds->DNEVR);
167 ds->Color = _free(ds->Color);
169 (void) rpmdsUnlink(ds);
170 memset(ds, 0, sizeof(*ds)); /* XXX trash and burn */
175 static rpmds rpmdsCreate(rpmstrPool pool,
176 rpmTagVal tagN, const char * Type, int Count,
177 unsigned int instance)
179 rpmds ds = xcalloc(1, sizeof(*ds));
181 ds->pool = (pool != NULL) ? rpmstrPoolLink(pool) : rpmstrPoolCreate();
185 ds->instance = instance;
186 ds->nopromote = _rpmds_nopromote;
189 return rpmdsLink(ds);
192 rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags)
194 rpmTagVal tagEVR, tagF;
197 struct rpmtd_s names;
198 if (dsType(tagN, &Type, &tagEVR, &tagF))
201 if (headerGet(h, tagN, &names, HEADERGET_MINMEM)) {
202 struct rpmtd_s evr, flags;
204 ds = rpmdsCreate(pool, tagN, Type,
205 rpmtdCount(&names), headerGetInstance(h));
207 ds->N = rpmtdToPool(&names, ds->pool);
208 headerGet(h, tagEVR, &evr, HEADERGET_MINMEM);
209 ds->EVR = rpmtdToPool(&evr, ds->pool);
210 headerGet(h, tagF, &flags, HEADERGET_ALLOC);
211 ds->Flags = flags.data;
212 /* ensure rpmlib() requires always have RPMSENSE_RPMLIB flag set */
213 if (tagN == RPMTAG_REQUIRENAME && ds->Flags) {
214 for (int i = 0; i < ds->Count; i++) {
215 if (!(rpmdsFlagsIndex(ds, i) & RPMSENSE_RPMLIB)) {
216 const char *N = rpmdsNIndex(ds, i);
217 if (rstreqn(N, "rpmlib(", sizeof("rpmlib(")-1))
218 ds->Flags[i] |= RPMSENSE_RPMLIB;
222 rpmtdFreeData(&names);
225 /* freeze the pool to save memory, but only if private pool */
226 if (ds->pool != pool)
227 rpmstrPoolFreeze(ds->pool, 0);
234 rpmds rpmdsNew(Header h, rpmTagVal tagN, int flags)
236 return rpmdsNewPool(NULL, h, tagN, flags);
239 char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds)
241 const char * N = rpmdsN(ds);
242 const char * EVR = rpmdsEVR(ds);
243 rpmsenseFlags Flags = rpmdsFlags(ds);
248 if (dspfx) nb += strlen(dspfx) + 1;
249 if (N) nb += strlen(N);
250 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
251 if (Flags & RPMSENSE_SENSEMASK) {
253 if (Flags & RPMSENSE_LESS) nb++;
254 if (Flags & RPMSENSE_GREATER) nb++;
255 if (Flags & RPMSENSE_EQUAL) nb++;
257 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
263 t = tbuf = xmalloc(nb + 1);
265 t = stpcpy(t, dspfx);
270 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
271 if (Flags & RPMSENSE_SENSEMASK) {
272 if (t != tbuf) *t++ = ' ';
273 if (Flags & RPMSENSE_LESS) *t++ = '<';
274 if (Flags & RPMSENSE_GREATER) *t++ = '>';
275 if (Flags & RPMSENSE_EQUAL) *t++ = '=';
277 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
279 if (t != tbuf) *t++ = ' ';
286 static rpmds singleDSPool(rpmstrPool pool, rpmTagVal tagN,
287 rpmsid N, rpmsid EVR, rpmsenseFlags Flags,
288 unsigned int instance, rpm_color_t Color)
293 if (dsType(tagN, &Type, NULL, NULL))
296 ds = rpmdsCreate(pool, tagN, Type, 1, instance);
298 ds->N = xmalloc(1 * sizeof(*ds->N));
300 ds->EVR = xmalloc(1 * sizeof(*ds->EVR));
302 ds->Flags = xmalloc(sizeof(*ds->Flags));
303 ds->Flags[0] = Flags;
306 rpmdsSetColor(ds, Color);
312 static rpmds singleDS(rpmstrPool pool, rpmTagVal tagN,
313 const char * N, const char * EVR,
314 rpmsenseFlags Flags, unsigned int instance,
317 rpmds ds = singleDSPool(pool, tagN, 0, 0, Flags, instance, Color);
319 /* now that we have a pool, we can insert our N & EVR strings */
320 ds->N[0] = rpmstrPoolId(ds->pool, N ? N : "", 1);
321 ds->EVR[0] = rpmstrPoolId(ds->pool, EVR ? EVR : "", 1);
322 /* freeze the pool to save memory, but only if private pool */
323 if (ds->pool != pool)
324 rpmstrPoolFreeze(ds->pool, 0);
329 rpmds rpmdsThisPool(rpmstrPool pool,
330 Header h, rpmTagVal tagN, rpmsenseFlags Flags)
332 char *evr = headerGetAsString(h, RPMTAG_EVR);
333 rpmds ds = singleDS(pool, tagN, headerGetString(h, RPMTAG_NAME),
334 evr, Flags, headerGetInstance(h), 0);
339 rpmds rpmdsThis(Header h, rpmTagVal tagN, rpmsenseFlags Flags)
341 return rpmdsThisPool(NULL, h, tagN, Flags);
344 rpmds rpmdsSinglePool(rpmstrPool pool,rpmTagVal tagN,
345 const char * N, const char * EVR, rpmsenseFlags Flags)
347 return singleDS(pool, tagN, N, EVR, Flags, 0, 0);
350 rpmds rpmdsSingle(rpmTagVal tagN, const char * N, const char * EVR, rpmsenseFlags Flags)
352 return rpmdsSinglePool(NULL, tagN, N, EVR, Flags);
355 rpmds rpmdsCurrent(rpmds ds)
358 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
359 /* Using parent's pool so we can just use the same id's */
360 cds = singleDSPool(ds->pool, ds->tagN, ds->N[ds->i], ds->EVR[ds->i],
361 rpmdsFlags(ds), ds->instance, rpmdsColor(ds));
366 int rpmdsCount(const rpmds ds)
368 return (ds != NULL ? ds->Count : 0);
371 int rpmdsIx(const rpmds ds)
373 return (ds != NULL ? ds->i : -1);
376 int rpmdsSetIx(rpmds ds, int ix)
383 ds->DNEVR = _free(ds->DNEVR);
388 const char * rpmdsDNEVR(const rpmds ds)
390 const char * DNEVR = NULL;
392 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
393 if (ds->DNEVR == NULL) {
394 char t[2] = { ds->Type[0], '\0' };
395 ds->DNEVR = rpmdsNewDNEVR(t, ds);
402 rpmsid rpmdsNId(rpmds ds)
404 return (ds != NULL) ? rpmdsNIdIndex(ds, ds->i) : 0;
407 rpmsid rpmdsEVRId(rpmds ds)
409 return (ds != NULL) ? rpmdsEVRIdIndex(ds, ds->i) : 0;
412 const char * rpmdsN(const rpmds ds)
414 return (ds != NULL) ? rpmdsNIndex(ds, ds->i) : NULL;
417 const char * rpmdsEVR(const rpmds ds)
419 return (ds != NULL) ? rpmdsEVRIndex(ds, ds->i) : NULL;
422 rpmsenseFlags rpmdsFlags(const rpmds ds)
424 return (ds != NULL) ? rpmdsFlagsIndex(ds, ds->i) : 0;
427 rpmTagVal rpmdsTagN(const rpmds ds)
429 rpmTagVal tagN = RPMTAG_NOT_FOUND;
436 unsigned int rpmdsInstance(rpmds ds)
438 return (ds != NULL) ? ds->instance : 0;
441 int rpmdsNoPromote(const rpmds ds)
446 nopromote = ds->nopromote;
450 int rpmdsSetNoPromote(rpmds ds, int nopromote)
455 onopromote = ds->nopromote;
456 ds->nopromote = nopromote;
461 rpm_color_t rpmdsColor(const rpmds ds)
463 return (ds != NULL) ? rpmdsColorIndex(ds, ds->i) : 0;
466 rpm_color_t rpmdsSetColor(const rpmds ds, rpm_color_t color)
468 rpm_color_t ocolor = 0;
470 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
471 if (ds->Color == NULL) {
472 ds->Color = xcalloc(ds->Count, sizeof(*ds->Color));
474 ocolor = ds->Color[ds->i];
475 ds->Color[ds->i] = color;
480 void rpmdsNotify(rpmds ds, const char * where, int rc)
486 if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
488 if (!(ds->Type != NULL && (DNEVR = rpmdsDNEVR(ds)) != NULL))
491 rpmlog(RPMLOG_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
492 (rstreq(DNEVR, "cached") ? DNEVR : DNEVR+2),
493 (rc ? _("NO ") : _("YES")),
494 (where != NULL ? where : ""));
497 int rpmdsNext(rpmds ds)
501 if (ds != NULL && ++ds->i >= 0) {
502 if (ds->i < ds->Count) {
504 ds->DNEVR = _free(ds->DNEVR);
508 if (_rpmds_debug < 0 && i != -1)
509 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
516 rpmds rpmdsInit(rpmds ds)
520 ds->DNEVR = _free(ds->DNEVR);
525 static rpmds rpmdsDup(const rpmds ods)
527 rpmds ds = rpmdsCreate(ods->pool, ods->tagN, ods->Type,
528 ods->Count, ods->instance);
534 ds->nopromote = ods->nopromote;
536 nb = ds->Count * sizeof(*ds->N);
537 ds->N = memcpy(xmalloc(nb), ods->N, nb);
539 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
541 nb = ds->Count * sizeof(*ds->EVR);
542 ds->EVR = memcpy(xmalloc(nb), ods->EVR, nb);
546 nb = ds->Count * sizeof(*ds->Flags);
547 ds->Flags = memcpy(xmalloc(nb), ods->Flags, nb);
554 int rpmdsFind(rpmds ds, const rpmds ods)
557 const char *N, *ON = rpmdsN(ods);
558 const char *EVR, *OEVR = rpmdsEVR(ods);
559 rpmsenseFlags Flags, OFlags = rpmdsFlags(ods);
560 int rc = -1; /* assume not found */
562 if (ds == NULL || ods == NULL)
567 while (ds->l < ds->u) {
568 ds->i = (ds->l + ds->u) / 2;
572 Flags = rpmdsFlags(ds);
574 comparison = strcmp(ON, N);
576 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
577 if (comparison == 0 && OEVR && EVR)
578 comparison = strcmp(OEVR, EVR);
579 if (comparison == 0 && OFlags && Flags)
580 comparison = OFlags - Flags;
584 else if (comparison > 0)
594 int rpmdsMerge(rpmds * dsp, rpmds ods)
599 if (dsp == NULL || ods == NULL)
602 /* If not initialized yet, dup the 1st entry. */
606 *dsp = rpmdsDup(ods);
613 /* Ensure EVR and Flags exist */
615 ds->EVR = xcalloc(ds->Count, sizeof(*ds->EVR));
616 if (ds->Flags == NULL)
617 ds->Flags = xcalloc(ds->Count, sizeof(*ds->Flags));
623 ods = rpmdsInit(ods);
624 while (rpmdsNext(ods) >= 0) {
627 * If this entry is already present, don't bother.
629 if (rpmdsFind(ds, ods) >= 0)
633 * Insert new entry. Ensure pool is unfrozen to allow additions.
635 rpmstrPoolUnfreeze(ds->pool);
636 ds->N = xrealloc(ds->N, (ds->Count+1) * sizeof(*ds->N));
637 if (ds->u < ds->Count) {
638 memmove(ds->N + ds->u + 1, ds->N + ds->u,
639 (ds->Count - ds->u) * sizeof(*ds->N));
641 ds->N[ds->u] = rpmstrPoolId(ds->pool, rpmdsN(ods), 1);
643 ds->EVR = xrealloc(ds->EVR, (ds->Count+1) * sizeof(*ds->EVR));
644 if (ds->u < ds->Count) {
645 memmove(ds->EVR + ds->u + 1, ds->EVR + ds->u,
646 (ds->Count - ds->u) * sizeof(*ds->EVR));
648 OEVR = rpmdsEVR(ods);
649 ds->EVR[ds->u] = rpmstrPoolId(ds->pool, OEVR ? OEVR : "", 1);
651 ds->Flags = xrealloc(ds->Flags, (ds->Count+1) * sizeof(*ds->Flags));
652 if (ds->u < ds->Count) {
653 memmove(ds->Flags + ds->u + 1, ds->Flags + ds->u,
654 (ds->Count - ds->u) * sizeof(*ds->Flags));
656 ds->Flags[ds->u] = rpmdsFlags(ods);
667 int rpmdsSearch(rpmds ds, rpmds ods)
671 const char *ON = rpmdsN(ods);
673 if (ds == NULL || ods == NULL)
676 /* Binary search to find the [l,u) subset that contains N */
683 comparison = strcmp(ON, rpmdsNIndex(ds, i));
687 else if (comparison > 0)
690 /* Set l to 1st member of set that contains N. */
691 if (!rstreq(ON, rpmdsNIndex(ds, l)))
693 while (l > 0 && rstreq(ON, rpmdsNIndex(ds, l-1)))
695 /* Set u to 1st member of set that does not contain N. */
696 if (u >= ds->Count || !rstreq(ON, rpmdsNIndex(ds, u)))
698 while (++u < ds->Count) {
699 if (!rstreq(ON, rpmdsNIndex(ds, u)))
706 /* Check each member of [l,u) subset for ranges overlap. */
709 int save = rpmdsSetIx(ds, l-1);
710 while ((l = rpmdsNext(ds)) >= 0 && (l < u)) {
711 if ((i = rpmdsCompare(ods, ds)) != 0)
714 /* Return element index that overlaps, or -1. */
718 (void) rpmdsSetIx(ds, save);
725 * Split EVR into epoch, version, and release components.
726 * @param evr [epoch:]version[-release] string
727 * @retval *ep pointer to epoch
728 * @retval *vp pointer to version
729 * @retval *rp pointer to release
732 void parseEVR(char * evr,
738 const char *version; /* assume only version is present */
743 while (*s && risdigit(*s)) s++; /* s points to epoch terminator */
744 se = strrchr(s, '-'); /* se points to version terminator */
750 if (*epoch == '\0') epoch = "0";
752 epoch = NULL; /* XXX disable epoch compare if missing */
763 if (vp) *vp = version;
764 if (rp) *rp = release;
767 static inline int rpmdsCompareEVR(const char *AEVR, uint32_t AFlags,
768 const char *BEVR, uint32_t BFlags,
771 const char *aE, *aV, *aR, *bE, *bV, *bR;
772 char *aEVR = xstrdup(AEVR);
773 char *bEVR = xstrdup(BEVR);
777 parseEVR(aEVR, &aE, &aV, &aR);
778 parseEVR(bEVR, &bE, &bV, &bR);
780 /* Compare {A,B} [epoch:]version[-release] */
781 if (aE && *aE && bE && *bE)
782 sense = rpmvercmp(aE, bE);
783 else if (aE && *aE && atol(aE) > 0) {
788 } else if (bE && *bE && atol(bE) > 0)
792 sense = rpmvercmp(aV, bV);
794 if (aR && *aR && bR && *bR) {
795 sense = rpmvercmp(aR, bR);
797 /* always matches if the side with no release has SENSE_EQUAL */
798 if ((aR && *aR && (BFlags & RPMSENSE_EQUAL)) ||
799 (bR && *bR && (AFlags & RPMSENSE_EQUAL))) {
809 /* Detect overlap of {A,B} range. */
810 if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) {
812 } else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) {
814 } else if (sense == 0 &&
815 (((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) ||
816 ((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) ||
817 ((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) {
827 int rpmdsCompareIndex(rpmds A, int aix, rpmds B, int bix)
829 const char *AEVR, *BEVR;
830 rpmsenseFlags AFlags, BFlags;
833 /* Different names don't overlap. */
834 if (!rpmstrPoolStreq(A->pool, rpmdsNIdIndex(A, aix),
835 B->pool, rpmdsNIdIndex(B, bix))) {
840 /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
841 if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
846 /* Same name. If either A or B is an existence test, always overlap. */
847 AFlags = rpmdsFlagsIndex(A, aix);
848 BFlags = rpmdsFlagsIndex(B, bix);
849 if (!((AFlags & RPMSENSE_SENSEMASK) && (BFlags & RPMSENSE_SENSEMASK))) {
854 AEVR = rpmdsEVRIndex(A, aix);
855 BEVR = rpmdsEVRIndex(B, bix);
856 if (!(AEVR && *AEVR && BEVR && *BEVR)) {
857 /* If either EVR is non-existent or empty, always overlap. */
860 /* Both AEVR and BEVR exist, compare [epoch:]version[-release]. */
861 result = rpmdsCompareEVR(AEVR, AFlags, BEVR, BFlags, B->nopromote);
868 int rpmdsCompare(const rpmds A, const rpmds B)
870 return rpmdsCompareIndex(A, A->i, B, B->i);
873 int rpmdsMatches(rpmstrPool pool, Header h, int prix,
874 rpmds req, int selfevr, int nopromote)
877 rpmTagVal tag = RPMTAG_PROVIDENAME;
880 /* Get provides information from header */
882 provides = rpmdsThisPool(pool, h, tag, RPMSENSE_EQUAL);
884 provides = rpmdsNewPool(pool, h, tag, 0);
886 rpmdsSetNoPromote(provides, nopromote);
889 * For a self-provide and indexed provide, we only need one comparison.
890 * Otherwise loop through the provides until match or end.
892 if (prix >= 0 || selfevr) {
894 rpmdsSetIx(provides, prix);
895 result = rpmdsCompare(provides, req);
897 provides = rpmdsInit(provides);
898 while (rpmdsNext(provides) >= 0) {
899 result = rpmdsCompare(provides, req);
900 /* If this provide matches the require, we're done. */
910 int rpmdsMatchesDep (const Header h, int ix, const rpmds req, int nopromote)
912 return rpmdsMatches(NULL, h, ix, req, 0, nopromote);
915 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
917 return rpmdsMatches(NULL, h, -1, req, 0, nopromote);
920 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
922 return rpmdsMatches(NULL, h, -1, req, 1, nopromote);
927 struct rpmlibProvides_s {
928 const char * featureName;
929 const char * featureEVR;
930 rpmsenseFlags featureFlags;
931 const char * featureDescription;
934 static const struct rpmlibProvides_s rpmlibProvides[] = {
935 { "rpmlib(VersionedDependencies)", "3.0.3-1",
936 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
937 N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
938 { "rpmlib(CompressedFileNames)", "3.0.4-1",
939 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
940 N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
942 { "rpmlib(PayloadIsBzip2)", "3.0.5-1",
943 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
944 N_("package payload can be compressed using bzip2.") },
947 { "rpmlib(PayloadIsXz)", "5.2-1",
948 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
949 N_("package payload can be compressed using xz.") },
950 { "rpmlib(PayloadIsLzma)", "4.4.2-1",
951 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
952 N_("package payload can be compressed using lzma.") },
954 { "rpmlib(PayloadFilesHavePrefix)", "4.0-1",
955 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
956 N_("package payload file(s) have \"./\" prefix.") },
957 { "rpmlib(ExplicitPackageProvide)", "4.0-1",
958 (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
959 N_("package name-version-release is not implicitly provided.") },
960 { "rpmlib(HeaderLoadSortsTags)", "4.0.1-1",
962 N_("header tags are always sorted after being loaded.") },
963 { "rpmlib(ScriptletInterpreterArgs)", "4.0.3-1",
965 N_("the scriptlet interpreter can use arguments from header.") },
966 { "rpmlib(PartialHardlinkSets)", "4.0.4-1",
968 N_("a hardlink file set may be installed without being complete.") },
969 { "rpmlib(ConcurrentAccess)", "4.1-1",
971 N_("package scriptlets may access the rpm database while installing.") },
973 { "rpmlib(BuiltinLuaScripts)", "4.2.2-1",
975 N_("internal support for lua scripts.") },
977 { "rpmlib(FileDigests)", "4.6.0-1",
979 N_("file digest algorithm is per package configurable") },
981 { "rpmlib(FileCaps)", "4.6.1-1",
983 N_("support for POSIX.1e file capabilities") },
985 { "rpmlib(ScriptletExpansion)", "4.9.0-1",
987 N_("package scriptlets can be expanded at install time.") },
988 { "rpmlib(TildeInVersions)", "4.10.0-1",
990 N_("dependency comparison supports versions with tilde.") },
991 { NULL, NULL, 0, NULL }
995 int rpmdsRpmlibPool(rpmstrPool pool, rpmds * dsp, const void * tblp)
997 const struct rpmlibProvides_s * rltblp = tblp;
998 const struct rpmlibProvides_s * rlp;
1002 rltblp = rpmlibProvides;
1004 for (rlp = rltblp; rlp->featureName != NULL && rc == 0; rlp++) {
1005 rpmds ds = rpmdsSinglePool(pool, RPMTAG_PROVIDENAME, rlp->featureName,
1006 rlp->featureEVR, rlp->featureFlags);
1007 rc = rpmdsMerge(dsp, ds);
1010 /* freeze the pool to save memory, but only if private pool */
1011 if (*dsp && (*dsp)->pool != pool)
1012 rpmstrPoolFreeze((*dsp)->pool, 0);
1016 int rpmdsRpmlib(rpmds * dsp, const void * tblp)
1018 return rpmdsRpmlibPool(NULL, dsp, tblp);
1021 rpmstrPool rpmdsPool(rpmds ds)
1023 return (ds != NULL) ? ds->pool : NULL;