|
|
2ff057 |
/** \ingroup rpmdep
|
|
|
2ff057 |
* \file lib/rpmds.c
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
#include "system.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <rpm/rpmtypes.h>
|
|
|
2ff057 |
#include <rpm/rpmlib.h> /* rpmvercmp */
|
|
|
2ff057 |
#include <rpm/rpmstring.h>
|
|
|
2ff057 |
#include <rpm/rpmlog.h>
|
|
|
2ff057 |
#include <rpm/rpmstrpool.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "lib/rpmds_internal.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "debug.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
int _rpmds_debug = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
int _rpmds_nopromote = 1;
|
|
|
2ff057 |
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
* A package dependency set.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
struct rpmds_s {
|
|
|
2ff057 |
rpmstrPool pool; /*!< String pool. */
|
|
|
2ff057 |
const char * Type; /*!< Tag name. */
|
|
|
2ff057 |
char * DNEVR; /*!< Formatted dependency string. */
|
|
|
2ff057 |
rpmsid * N; /*!< Dependency name id's (pool) */
|
|
|
2ff057 |
rpmsid * EVR; /*!< Dependency EVR id's (pool) */
|
|
|
2ff057 |
rpmsenseFlags * Flags; /*!< Bit(s) identifying context/comparison. */
|
|
|
2ff057 |
rpm_color_t * Color; /*!< Bit(s) calculated from file color(s). */
|
|
|
2ff057 |
rpmTagVal tagN; /*!< Header tag. */
|
|
|
2ff057 |
int32_t Count; /*!< No. of elements */
|
|
|
2ff057 |
unsigned int instance; /*!< From rpmdb instance? */
|
|
|
2ff057 |
int i; /*!< Element index. */
|
|
|
2ff057 |
int nopromote; /*!< Don't promote Epoch: in rpmdsCompare()? */
|
|
|
2ff057 |
int nrefs; /*!< Reference count. */
|
|
|
2ff057 |
int *ti; /*!< Trigger index. */
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
static int dsType(rpmTagVal tag,
|
|
|
2ff057 |
const char ** Type, rpmTagVal * tagEVR, rpmTagVal * tagF,
|
|
|
2ff057 |
rpmTagVal * tagTi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 0;
|
|
|
2ff057 |
const char *t = NULL;
|
|
|
2ff057 |
rpmTagVal evr = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
rpmTagVal f = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
rpmTagVal ti = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (tag == RPMTAG_PROVIDENAME) {
|
|
|
2ff057 |
t = "Provides";
|
|
|
2ff057 |
evr = RPMTAG_PROVIDEVERSION;
|
|
|
2ff057 |
f = RPMTAG_PROVIDEFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_REQUIRENAME) {
|
|
|
2ff057 |
t = "Requires";
|
|
|
2ff057 |
evr = RPMTAG_REQUIREVERSION;
|
|
|
2ff057 |
f = RPMTAG_REQUIREFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_SUPPLEMENTNAME) {
|
|
|
2ff057 |
t = "Supplements";
|
|
|
2ff057 |
evr = RPMTAG_SUPPLEMENTVERSION;
|
|
|
2ff057 |
f = RPMTAG_SUPPLEMENTFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_ENHANCENAME) {
|
|
|
2ff057 |
t = "Enhances";
|
|
|
2ff057 |
evr = RPMTAG_ENHANCEVERSION;
|
|
|
2ff057 |
f = RPMTAG_ENHANCEFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_RECOMMENDNAME) {
|
|
|
2ff057 |
t = "Recommends";
|
|
|
2ff057 |
evr = RPMTAG_RECOMMENDVERSION;
|
|
|
2ff057 |
f = RPMTAG_RECOMMENDFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_SUGGESTNAME) {
|
|
|
2ff057 |
t = "Suggests";
|
|
|
2ff057 |
evr = RPMTAG_SUGGESTVERSION;
|
|
|
2ff057 |
f = RPMTAG_SUGGESTFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_CONFLICTNAME) {
|
|
|
2ff057 |
t = "Conflicts";
|
|
|
2ff057 |
evr = RPMTAG_CONFLICTVERSION;
|
|
|
2ff057 |
f = RPMTAG_CONFLICTFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_OBSOLETENAME) {
|
|
|
2ff057 |
t = "Obsoletes";
|
|
|
2ff057 |
evr = RPMTAG_OBSOLETEVERSION;
|
|
|
2ff057 |
f = RPMTAG_OBSOLETEFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_ORDERNAME) {
|
|
|
2ff057 |
t = "Order";
|
|
|
2ff057 |
evr = RPMTAG_ORDERVERSION;
|
|
|
2ff057 |
f = RPMTAG_ORDERFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_TRIGGERNAME) {
|
|
|
2ff057 |
t = "Trigger";
|
|
|
2ff057 |
evr = RPMTAG_TRIGGERVERSION;
|
|
|
2ff057 |
f = RPMTAG_TRIGGERFLAGS;
|
|
|
2ff057 |
ti = RPMTAG_TRIGGERINDEX;
|
|
|
2ff057 |
} else if (tag == RPMTAG_OLDSUGGESTSNAME) {
|
|
|
2ff057 |
t = "Oldsuggests";
|
|
|
2ff057 |
evr = RPMTAG_OLDSUGGESTSVERSION;
|
|
|
2ff057 |
f = RPMTAG_OLDSUGGESTSFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_OLDENHANCESNAME) {
|
|
|
2ff057 |
t = "Oldenhances";
|
|
|
2ff057 |
evr = RPMTAG_OLDENHANCESVERSION;
|
|
|
2ff057 |
f = RPMTAG_OLDENHANCESFLAGS;
|
|
|
2ff057 |
} else if (tag == RPMTAG_FILETRIGGERNAME) {
|
|
|
2ff057 |
t = "FileTrigger";
|
|
|
2ff057 |
evr = RPMTAG_FILETRIGGERVERSION;
|
|
|
2ff057 |
f = RPMTAG_FILETRIGGERFLAGS;
|
|
|
2ff057 |
ti = RPMTAG_FILETRIGGERINDEX;
|
|
|
2ff057 |
} else if (tag == RPMTAG_TRANSFILETRIGGERNAME) {
|
|
|
2ff057 |
t = "TransFileTrigger";
|
|
|
2ff057 |
evr = RPMTAG_TRANSFILETRIGGERVERSION;
|
|
|
2ff057 |
f = RPMTAG_TRANSFILETRIGGERFLAGS;
|
|
|
2ff057 |
ti = RPMTAG_TRANSFILETRIGGERINDEX;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
rc = 1;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (Type) *Type = t;
|
|
|
2ff057 |
if (tagEVR) *tagEVR = evr;
|
|
|
2ff057 |
if (tagF) *tagF = f;
|
|
|
2ff057 |
if (tagTi) *tagTi = ti;
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static char tagNToChar(rpmTagVal tagN)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
switch (tagN) {
|
|
|
2ff057 |
default:
|
|
|
2ff057 |
return 'R';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_REQUIRENAME:
|
|
|
2ff057 |
return 'R';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_PROVIDENAME:
|
|
|
2ff057 |
return 'P';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_RECOMMENDNAME:
|
|
|
2ff057 |
return 'r';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_SUGGESTNAME:
|
|
|
2ff057 |
return 's';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_SUPPLEMENTNAME:
|
|
|
2ff057 |
return 'S';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_ENHANCENAME:
|
|
|
2ff057 |
return 'e';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_CONFLICTNAME:
|
|
|
2ff057 |
return 'C';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_OBSOLETENAME:
|
|
|
2ff057 |
return 'O';
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal rpmdsDToTagN(char deptype)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagN = RPMTAG_REQUIRENAME;
|
|
|
2ff057 |
switch (deptype) {
|
|
|
2ff057 |
default:
|
|
|
2ff057 |
tagN = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'P':
|
|
|
2ff057 |
tagN = RPMTAG_PROVIDENAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'R':
|
|
|
2ff057 |
tagN = RPMTAG_REQUIRENAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'r':
|
|
|
2ff057 |
tagN = RPMTAG_RECOMMENDNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 's':
|
|
|
2ff057 |
tagN = RPMTAG_SUGGESTNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'S':
|
|
|
2ff057 |
tagN = RPMTAG_SUPPLEMENTNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'e':
|
|
|
2ff057 |
tagN = RPMTAG_ENHANCENAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'C':
|
|
|
2ff057 |
tagN = RPMTAG_CONFLICTNAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 'O':
|
|
|
2ff057 |
tagN = RPMTAG_OBSOLETENAME;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return tagN;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsid rpmdsNIdIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmsid id = 0;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->N != NULL)
|
|
|
2ff057 |
id = ds->N[i];
|
|
|
2ff057 |
return id;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsid rpmdsEVRIdIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmsid id = 0;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->EVR != NULL)
|
|
|
2ff057 |
id = ds->EVR[i];
|
|
|
2ff057 |
return id;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
const char * rpmdsNIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char * N = NULL;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->N != NULL)
|
|
|
2ff057 |
N = rpmstrPoolStr(ds->pool, ds->N[i]);
|
|
|
2ff057 |
return N;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
const char * rpmdsEVRIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char * EVR = NULL;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->EVR != NULL)
|
|
|
2ff057 |
EVR = rpmstrPoolStr(ds->pool, ds->EVR[i]);
|
|
|
2ff057 |
return EVR;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsenseFlags rpmdsFlagsIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmsenseFlags Flags = 0;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->Flags != NULL)
|
|
|
2ff057 |
Flags = ds->Flags[i];
|
|
|
2ff057 |
return Flags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsTiIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int ti = -1;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->ti != NULL)
|
|
|
2ff057 |
ti = ds->ti[i];
|
|
|
2ff057 |
return ti;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmdsColorIndex(rpmds ds, int i)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpm_color_t Color = 0;
|
|
|
2ff057 |
if (ds != NULL && i >= 0 && i < ds->Count && ds->Color != NULL)
|
|
|
2ff057 |
Color = ds->Color[i];
|
|
|
2ff057 |
return Color;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
static rpmds rpmdsUnlink(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ds)
|
|
|
2ff057 |
ds->nrefs--;
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsLink(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ds)
|
|
|
2ff057 |
ds->nrefs++;
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsFree(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagEVR, tagF, tagTi;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds == NULL)
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds->nrefs > 1)
|
|
|
2ff057 |
return rpmdsUnlink(ds);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (dsType(ds->tagN, NULL, &tagEVR, &tagF, &tagTi))
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds->Count > 0) {
|
|
|
2ff057 |
ds->N = _free(ds->N);
|
|
|
2ff057 |
ds->EVR = _free(ds->EVR);
|
|
|
2ff057 |
ds->Flags = _free(ds->Flags);
|
|
|
2ff057 |
ds->ti = _free(ds->ti);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->pool = rpmstrPoolFree(ds->pool);
|
|
|
2ff057 |
ds->DNEVR = _free(ds->DNEVR);
|
|
|
2ff057 |
ds->Color = _free(ds->Color);
|
|
|
2ff057 |
|
|
|
2ff057 |
(void) rpmdsUnlink(ds);
|
|
|
2ff057 |
memset(ds, 0, sizeof(*ds)); /* XXX trash and burn */
|
|
|
2ff057 |
ds = _free(ds);
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmds rpmdsCreate(rpmstrPool pool,
|
|
|
2ff057 |
rpmTagVal tagN, const char * Type, int Count,
|
|
|
2ff057 |
unsigned int instance)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds ds = xcalloc(1, sizeof(*ds));
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->pool = (pool != NULL) ? rpmstrPoolLink(pool) : rpmstrPoolCreate();
|
|
|
2ff057 |
ds->tagN = tagN;
|
|
|
2ff057 |
ds->Type = Type;
|
|
|
2ff057 |
ds->Count = Count;
|
|
|
2ff057 |
ds->instance = instance;
|
|
|
2ff057 |
ds->nopromote = _rpmds_nopromote;
|
|
|
2ff057 |
ds->i = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
return rpmdsLink(ds);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagEVR, tagF, tagTi;
|
|
|
2ff057 |
rpmds ds = NULL;
|
|
|
2ff057 |
const char * Type;
|
|
|
2ff057 |
struct rpmtd_s names;
|
|
|
2ff057 |
if (dsType(tagN, &Type, &tagEVR, &tagF, &tagTi))
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (headerGet(h, tagN, &names, HEADERGET_MINMEM)) {
|
|
|
2ff057 |
struct rpmtd_s evr, flags, tindices;
|
|
|
2ff057 |
rpm_count_t count = rpmtdCount(&names);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerGet(h, tagEVR, &evr, HEADERGET_MINMEM);
|
|
|
2ff057 |
if (evr.count && evr.count != count) {
|
|
|
2ff057 |
rpmtdFreeData(&evr);
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
headerGet(h, tagF, &flags, HEADERGET_ALLOC);
|
|
|
2ff057 |
if (flags.count && flags.count != count) {
|
|
|
2ff057 |
rpmtdFreeData(&flags);
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (tagTi != RPMTAG_NOT_FOUND) {
|
|
|
2ff057 |
headerGet(h, tagTi, &tindices, HEADERGET_ALLOC);
|
|
|
2ff057 |
if (tindices.count && tindices.count != count) {
|
|
|
2ff057 |
rpmtdFreeData(&tindices);
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
ds = rpmdsCreate(pool, tagN, Type, count, headerGetInstance(h));
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->N = names.count ? rpmtdToPool(&names, ds->pool) : NULL;
|
|
|
2ff057 |
ds->EVR = evr.count ? rpmtdToPool(&evr, ds->pool): NULL;
|
|
|
2ff057 |
ds->Flags = flags.data;
|
|
|
2ff057 |
if (tagTi != RPMTAG_NOT_FOUND) {
|
|
|
2ff057 |
ds->ti = tindices.data;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* ensure rpmlib() requires always have RPMSENSE_RPMLIB flag set */
|
|
|
2ff057 |
if (tagN == RPMTAG_REQUIRENAME && ds->Flags) {
|
|
|
2ff057 |
for (int i = 0; i < ds->Count; i++) {
|
|
|
2ff057 |
if (!(rpmdsFlagsIndex(ds, i) & RPMSENSE_RPMLIB)) {
|
|
|
2ff057 |
const char *N = rpmdsNIndex(ds, i);
|
|
|
2ff057 |
if (rstreqn(N, "rpmlib(", sizeof("rpmlib(")-1))
|
|
|
2ff057 |
ds->Flags[i] |= RPMSENSE_RPMLIB;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmtdFreeData(&names);
|
|
|
2ff057 |
rpmtdFreeData(&evr);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* freeze the pool to save memory, but only if private pool */
|
|
|
2ff057 |
if (ds->pool != pool)
|
|
|
2ff057 |
rpmstrPoolFreeze(ds->pool, 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsNew(Header h, rpmTagVal tagN, int flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsNewPool(NULL, h, tagN, flags);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char * N = rpmdsN(ds);
|
|
|
2ff057 |
const char * EVR = rpmdsEVR(ds);
|
|
|
2ff057 |
rpmsenseFlags Flags = rpmdsFlags(ds);
|
|
|
2ff057 |
char * tbuf, * t;
|
|
|
2ff057 |
size_t nb;
|
|
|
2ff057 |
|
|
|
2ff057 |
nb = 0;
|
|
|
2ff057 |
if (dspfx) nb += strlen(dspfx) + 1;
|
|
|
2ff057 |
if (N) nb += strlen(N);
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (Flags & RPMSENSE_SENSEMASK) {
|
|
|
2ff057 |
if (nb) nb++;
|
|
|
2ff057 |
if (Flags & RPMSENSE_LESS) nb++;
|
|
|
2ff057 |
if (Flags & RPMSENSE_GREATER) nb++;
|
|
|
2ff057 |
if (Flags & RPMSENSE_EQUAL) nb++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (EVR && *EVR) {
|
|
|
2ff057 |
if (nb) nb++;
|
|
|
2ff057 |
nb += strlen(EVR);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
t = tbuf = xmalloc(nb + 1);
|
|
|
2ff057 |
if (dspfx) {
|
|
|
2ff057 |
t = stpcpy(t, dspfx);
|
|
|
2ff057 |
*t++ = ' ';
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (N)
|
|
|
2ff057 |
t = stpcpy(t, N);
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (Flags & RPMSENSE_SENSEMASK) {
|
|
|
2ff057 |
if (t != tbuf) *t++ = ' ';
|
|
|
2ff057 |
if (Flags & RPMSENSE_LESS) *t++ = '<';
|
|
|
2ff057 |
if (Flags & RPMSENSE_GREATER) *t++ = '>';
|
|
|
2ff057 |
if (Flags & RPMSENSE_EQUAL) *t++ = '=';
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (EVR && *EVR) {
|
|
|
2ff057 |
if (t != tbuf) *t++ = ' ';
|
|
|
2ff057 |
t = stpcpy(t, EVR);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
*t = '\0';
|
|
|
2ff057 |
return tbuf;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmds singleDSPool(rpmstrPool pool, rpmTagVal tagN,
|
|
|
2ff057 |
rpmsid N, rpmsid EVR, rpmsenseFlags Flags,
|
|
|
2ff057 |
unsigned int instance, rpm_color_t Color,
|
|
|
2ff057 |
int triggerIndex)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds ds = NULL;
|
|
|
2ff057 |
const char * Type;
|
|
|
2ff057 |
rpmTagVal tagTi;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (dsType(tagN, &Type, NULL, NULL, &tagTi))
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
ds = rpmdsCreate(pool, tagN, Type, 1, instance);
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->N = xmalloc(1 * sizeof(*ds->N));
|
|
|
2ff057 |
ds->N[0] = N;
|
|
|
2ff057 |
ds->EVR = xmalloc(1 * sizeof(*ds->EVR));
|
|
|
2ff057 |
ds->EVR[0] = EVR;
|
|
|
2ff057 |
ds->Flags = xmalloc(sizeof(*ds->Flags));
|
|
|
2ff057 |
ds->Flags[0] = Flags;
|
|
|
2ff057 |
if (tagTi != RPMTAG_NOT_FOUND) {
|
|
|
2ff057 |
ds->ti = xmalloc(sizeof(*ds->ti));
|
|
|
2ff057 |
ds->ti[0] = triggerIndex;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ds->i = 0;
|
|
|
2ff057 |
if (Color)
|
|
|
2ff057 |
rpmdsSetColor(ds, Color);
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmds singleDS(rpmstrPool pool, rpmTagVal tagN,
|
|
|
2ff057 |
const char * N, const char * EVR,
|
|
|
2ff057 |
rpmsenseFlags Flags, unsigned int instance,
|
|
|
2ff057 |
rpm_color_t Color, int triggerIndex)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds ds = singleDSPool(pool, tagN, 0, 0, Flags, instance, Color,
|
|
|
2ff057 |
triggerIndex);
|
|
|
2ff057 |
if (ds) {
|
|
|
2ff057 |
/* now that we have a pool, we can insert our N & EVR strings */
|
|
|
2ff057 |
ds->N[0] = rpmstrPoolId(ds->pool, N ? N : "", 1);
|
|
|
2ff057 |
ds->EVR[0] = rpmstrPoolId(ds->pool, EVR ? EVR : "", 1);
|
|
|
2ff057 |
/* freeze the pool to save memory, but only if private pool */
|
|
|
2ff057 |
if (ds->pool != pool)
|
|
|
2ff057 |
rpmstrPoolFreeze(ds->pool, 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsThisPool(rpmstrPool pool,
|
|
|
2ff057 |
Header h, rpmTagVal tagN, rpmsenseFlags Flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
char *evr = headerGetAsString(h, RPMTAG_EVR);
|
|
|
2ff057 |
rpmds ds = singleDS(pool, tagN, headerGetString(h, RPMTAG_NAME),
|
|
|
2ff057 |
evr, Flags, headerGetInstance(h), 0, 0);
|
|
|
2ff057 |
free(evr);
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsThis(Header h, rpmTagVal tagN, rpmsenseFlags Flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsThisPool(NULL, h, tagN, Flags);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsSinglePool(rpmstrPool pool,rpmTagVal tagN,
|
|
|
2ff057 |
const char * N, const char * EVR, rpmsenseFlags Flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return singleDS(pool, tagN, N, EVR, Flags, 0, 0, 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsSinglePoolTix(rpmstrPool pool,rpmTagVal tagN,
|
|
|
2ff057 |
const char * N, const char * EVR,
|
|
|
2ff057 |
rpmsenseFlags Flags, int triggerIndex)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return singleDS(pool, tagN, N, EVR, Flags, 0, 0, triggerIndex);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsSingle(rpmTagVal tagN, const char * N, const char * EVR, rpmsenseFlags Flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsSinglePool(NULL, tagN, N, EVR, Flags);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsCurrent(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds cds = NULL;
|
|
|
2ff057 |
int ti = -1;
|
|
|
2ff057 |
if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
|
|
|
2ff057 |
if (ds->ti)
|
|
|
2ff057 |
ti = ds->ti[ds->i];
|
|
|
2ff057 |
/* Using parent's pool so we can just use the same id's */
|
|
|
2ff057 |
cds = singleDSPool(ds->pool, ds->tagN, ds->N[ds->i], ds->EVR[ds->i],
|
|
|
2ff057 |
rpmdsFlags(ds), ds->instance, rpmdsColor(ds), ti);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return cds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsFilterTi(rpmds ds, int ti)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int i, i2, tiCount = 0;
|
|
|
2ff057 |
rpmds fds;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds == NULL || !ds->ti || !ds->Count)
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
for (i = 0; i < ds->Count; i++) {
|
|
|
2ff057 |
if (ds->ti[i] == ti)
|
|
|
2ff057 |
tiCount++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (!tiCount)
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
fds = rpmdsCreate(ds->pool, ds->tagN, ds->Type, tiCount, ds->instance);
|
|
|
2ff057 |
|
|
|
2ff057 |
fds->N = xmalloc(tiCount * sizeof(*fds->N));
|
|
|
2ff057 |
fds->EVR = xmalloc(tiCount * sizeof(*fds->EVR));
|
|
|
2ff057 |
fds->Flags = xmalloc(tiCount * sizeof(*fds->Flags));
|
|
|
2ff057 |
fds->ti = xmalloc(tiCount * sizeof(*fds->ti));
|
|
|
2ff057 |
fds->i = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
i2 = 0;
|
|
|
2ff057 |
for (i = 0; i < ds->Count; i++) {
|
|
|
2ff057 |
if (ds->ti[i] == ti) {
|
|
|
2ff057 |
fds->N[i2] = ds->N[i];
|
|
|
2ff057 |
fds->EVR[i2] = ds->EVR[i];
|
|
|
2ff057 |
fds->Flags[i2] = ds->Flags[i];
|
|
|
2ff057 |
fds->ti[i2] = ds->ti[i];
|
|
|
2ff057 |
i2++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
return fds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsPutToHeader(rpmds ds, Header h)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagN = rpmdsTagN(ds);
|
|
|
2ff057 |
rpmTagVal tagEVR = rpmdsTagEVR(ds);
|
|
|
2ff057 |
rpmTagVal tagF = rpmdsTagF(ds);
|
|
|
2ff057 |
rpmTagVal tagTi = rpmdsTagTi(ds);
|
|
|
2ff057 |
if (!tagN)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds pi = rpmdsInit(ds);
|
|
|
2ff057 |
while (rpmdsNext(pi) >= 0) {
|
|
|
2ff057 |
rpmsenseFlags flags = rpmdsFlags(pi);
|
|
|
2ff057 |
uint32_t index = rpmdsTi(pi);
|
|
|
2ff057 |
headerPutString(h, tagN, rpmdsN(pi));
|
|
|
2ff057 |
headerPutString(h, tagEVR, rpmdsEVR(pi));
|
|
|
2ff057 |
headerPutUint32(h, tagF, &flags, 1);
|
|
|
2ff057 |
if (tagTi != RPMTAG_NOT_FOUND) {
|
|
|
2ff057 |
headerPutUint32(h, tagTi, &index, 1);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsCount(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL ? ds->Count : 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsIx(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL ? ds->i : -1);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsSetIx(rpmds ds, int ix)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int i = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL) {
|
|
|
2ff057 |
i = ds->i;
|
|
|
2ff057 |
ds->i = ix;
|
|
|
2ff057 |
ds->DNEVR = _free(ds->DNEVR);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return i;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
char rpmdsD(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ds != NULL) {
|
|
|
2ff057 |
return tagNToChar(ds->tagN);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
return '\0';
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
const char * rpmdsDNEVR(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char * DNEVR = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
|
|
|
2ff057 |
if (ds->DNEVR == NULL) {
|
|
|
2ff057 |
char t[2] = { tagNToChar(ds->tagN), '\0' };
|
|
|
2ff057 |
ds->DNEVR = rpmdsNewDNEVR(t, ds);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
DNEVR = ds->DNEVR;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return DNEVR;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsid rpmdsNId(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsNIdIndex(ds, ds->i) : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsid rpmdsEVRId(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsEVRIdIndex(ds, ds->i) : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
const char * rpmdsN(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsNIndex(ds, ds->i) : NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
const char * rpmdsEVR(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsEVRIndex(ds, ds->i) : NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsenseFlags rpmdsFlags(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsFlagsIndex(ds, ds->i) : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsTi(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsTiIndex(ds, ds->i) : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal rpmdsTagN(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagN = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL)
|
|
|
2ff057 |
tagN = ds->tagN;
|
|
|
2ff057 |
return tagN;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal rpmdsTagEVR(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagEVR = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL)
|
|
|
2ff057 |
dsType(ds->tagN, NULL, &tagEVR, NULL, NULL);
|
|
|
2ff057 |
return tagEVR;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal rpmdsTagF(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagF = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL)
|
|
|
2ff057 |
dsType(ds->tagN, NULL, NULL, &tagF, NULL);
|
|
|
2ff057 |
return tagF;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmTagVal rpmdsTagTi(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmTagVal tagTi = RPMTAG_NOT_FOUND;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL)
|
|
|
2ff057 |
dsType(ds->tagN, NULL, NULL, NULL, &tagTi);
|
|
|
2ff057 |
return tagTi;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
unsigned int rpmdsInstance(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? ds->instance : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsNoPromote(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int nopromote = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL)
|
|
|
2ff057 |
nopromote = ds->nopromote;
|
|
|
2ff057 |
return nopromote;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsSetNoPromote(rpmds ds, int nopromote)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int onopromote = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL) {
|
|
|
2ff057 |
onopromote = ds->nopromote;
|
|
|
2ff057 |
ds->nopromote = nopromote;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return onopromote;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmdsColor(const rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? rpmdsColorIndex(ds, ds->i) : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmdsSetColor(const rpmds ds, rpm_color_t color)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpm_color_t ocolor = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
|
|
|
2ff057 |
if (ds->Color == NULL) {
|
|
|
2ff057 |
ds->Color = xcalloc(ds->Count, sizeof(*ds->Color));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ocolor = ds->Color[ds->i];
|
|
|
2ff057 |
ds->Color[ds->i] = color;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ocolor;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmdsNotify(rpmds ds, const char * where, int rc)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *DNEVR;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (!rpmIsDebug())
|
|
|
2ff057 |
return;
|
|
|
2ff057 |
if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
|
|
|
2ff057 |
return;
|
|
|
2ff057 |
if (!(ds->Type != NULL && (DNEVR = rpmdsDNEVR(ds)) != NULL))
|
|
|
2ff057 |
return;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
|
|
|
2ff057 |
(rstreq(DNEVR, "cached") ? DNEVR : DNEVR+2),
|
|
|
2ff057 |
(rc ? _("NO ") : _("YES")),
|
|
|
2ff057 |
(where != NULL ? where : ""));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsNext(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int i = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds != NULL && ++ds->i >= 0) {
|
|
|
2ff057 |
if (ds->i < ds->Count) {
|
|
|
2ff057 |
i = ds->i;
|
|
|
2ff057 |
ds->DNEVR = _free(ds->DNEVR);
|
|
|
2ff057 |
} else
|
|
|
2ff057 |
ds->i = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (_rpmds_debug < 0 && i != -1)
|
|
|
2ff057 |
fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
|
|
|
2ff057 |
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
return i;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds rpmdsInit(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ds != NULL) {
|
|
|
2ff057 |
ds->i = -1;
|
|
|
2ff057 |
ds->DNEVR = _free(ds->DNEVR);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmds rpmdsDup(const rpmds ods)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds ds = rpmdsCreate(ods->pool, ods->tagN, ods->Type,
|
|
|
2ff057 |
ods->Count, ods->instance);
|
|
|
2ff057 |
size_t nb;
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->i = ods->i;
|
|
|
2ff057 |
ds->nopromote = ods->nopromote;
|
|
|
2ff057 |
|
|
|
2ff057 |
nb = ds->Count * sizeof(*ds->N);
|
|
|
2ff057 |
ds->N = memcpy(xmalloc(nb), ods->N, nb);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (ods->EVR) {
|
|
|
2ff057 |
nb = ds->Count * sizeof(*ds->EVR);
|
|
|
2ff057 |
ds->EVR = memcpy(xmalloc(nb), ods->EVR, nb);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ods->Flags) {
|
|
|
2ff057 |
nb = ds->Count * sizeof(*ds->Flags);
|
|
|
2ff057 |
ds->Flags = memcpy(xmalloc(nb), ods->Flags, nb);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ods->ti) {
|
|
|
2ff057 |
nb = ds->Count * sizeof(*ds->ti);
|
|
|
2ff057 |
ds->ti = memcpy(xmalloc(nb), ods->ti, nb);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
return ds;
|
|
|
2ff057 |
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static int doFind(rpmds ds, const rpmds ods, unsigned int *he)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int comparison;
|
|
|
2ff057 |
const char *N, *ON = rpmdsN(ods);
|
|
|
2ff057 |
const char *EVR, *OEVR = rpmdsEVR(ods);
|
|
|
2ff057 |
rpmsenseFlags Flags, OFlags = rpmdsFlags(ods);
|
|
|
2ff057 |
int index, Oindex = rpmdsTi(ods);
|
|
|
2ff057 |
int rc = -1; /* assume not found */
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds == NULL || ods == NULL)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
unsigned int l = 0;
|
|
|
2ff057 |
unsigned int u = ds->Count;
|
|
|
2ff057 |
while (l < u) {
|
|
|
2ff057 |
ds->i = (l + u) / 2;
|
|
|
2ff057 |
|
|
|
2ff057 |
N = rpmdsN(ds);
|
|
|
2ff057 |
EVR = rpmdsEVR(ds);
|
|
|
2ff057 |
Flags = rpmdsFlags(ds);
|
|
|
2ff057 |
index = rpmdsTi(ds);
|
|
|
2ff057 |
|
|
|
2ff057 |
comparison = strcmp(ON, N);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (comparison == 0 && OEVR && EVR)
|
|
|
2ff057 |
comparison = strcmp(OEVR, EVR);
|
|
|
2ff057 |
if (comparison == 0)
|
|
|
2ff057 |
comparison = OFlags - Flags;
|
|
|
2ff057 |
if (comparison == 0)
|
|
|
2ff057 |
comparison = Oindex - index;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (comparison < 0)
|
|
|
2ff057 |
u = ds->i;
|
|
|
2ff057 |
else if (comparison > 0)
|
|
|
2ff057 |
l = ds->i + 1;
|
|
|
2ff057 |
else {
|
|
|
2ff057 |
rc = ds->i;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (he)
|
|
|
2ff057 |
*he = u;
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsFind(rpmds ds, const rpmds ods)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return doFind(ds, ods, NULL);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsMerge(rpmds * dsp, rpmds ods)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds ds;
|
|
|
2ff057 |
int save;
|
|
|
2ff057 |
int ocount;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (dsp == NULL || ods == NULL)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
ocount = rpmdsCount(*dsp);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If not initialized yet, dup the 1st entry. */
|
|
|
2ff057 |
if (*dsp == NULL) {
|
|
|
2ff057 |
save = ods->Count;
|
|
|
2ff057 |
ods->Count = 1;
|
|
|
2ff057 |
*dsp = rpmdsDup(ods);
|
|
|
2ff057 |
ods->Count = save;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ds = *dsp;
|
|
|
2ff057 |
if (ds == NULL)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Ensure EVR and Flags exist */
|
|
|
2ff057 |
if (ds->EVR == NULL)
|
|
|
2ff057 |
ds->EVR = xcalloc(ds->Count, sizeof(*ds->EVR));
|
|
|
2ff057 |
if (ds->Flags == NULL)
|
|
|
2ff057 |
ds->Flags = xcalloc(ds->Count, sizeof(*ds->Flags));
|
|
|
2ff057 |
if (ds->ti == NULL && ods->ti) {
|
|
|
2ff057 |
int i;
|
|
|
2ff057 |
ds->ti = xcalloc(ds->Count, sizeof(*ds->ti));
|
|
|
2ff057 |
for (i = 0; i < ds->Count; i++)
|
|
|
2ff057 |
ds->ti[i] = -1;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Add new entries.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
save = ods->i;
|
|
|
2ff057 |
ods = rpmdsInit(ods);
|
|
|
2ff057 |
while (rpmdsNext(ods) >= 0) {
|
|
|
2ff057 |
const char *OEVR;
|
|
|
2ff057 |
unsigned int u;
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* If this entry is already present, don't bother.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
if (doFind(ds, ods, &u) >= 0)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Insert new entry. Ensure pool is unfrozen to allow additions.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
rpmstrPoolUnfreeze(ds->pool);
|
|
|
2ff057 |
ds->N = xrealloc(ds->N, (ds->Count+1) * sizeof(*ds->N));
|
|
|
2ff057 |
if (u < ds->Count) {
|
|
|
2ff057 |
memmove(ds->N + u + 1, ds->N + u,
|
|
|
2ff057 |
(ds->Count - u) * sizeof(*ds->N));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ds->N[u] = rpmstrPoolId(ds->pool, rpmdsN(ods), 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->EVR = xrealloc(ds->EVR, (ds->Count+1) * sizeof(*ds->EVR));
|
|
|
2ff057 |
if (u < ds->Count) {
|
|
|
2ff057 |
memmove(ds->EVR + u + 1, ds->EVR + u,
|
|
|
2ff057 |
(ds->Count - u) * sizeof(*ds->EVR));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
OEVR = rpmdsEVR(ods);
|
|
|
2ff057 |
ds->EVR[u] = rpmstrPoolId(ds->pool, OEVR ? OEVR : "", 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->Flags = xrealloc(ds->Flags, (ds->Count+1) * sizeof(*ds->Flags));
|
|
|
2ff057 |
if (u < ds->Count) {
|
|
|
2ff057 |
memmove(ds->Flags + u + 1, ds->Flags + u,
|
|
|
2ff057 |
(ds->Count - u) * sizeof(*ds->Flags));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ds->Flags[u] = rpmdsFlags(ods);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds->ti || ods->ti) {
|
|
|
2ff057 |
ds->ti = xrealloc(ds->ti, (ds->Count+1) * sizeof(*ds->ti));
|
|
|
2ff057 |
if (u < ds->Count) {
|
|
|
2ff057 |
memmove(ds->ti + u + 1, ds->ti + u,
|
|
|
2ff057 |
(ds->Count - u) * sizeof(*ds->ti));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ds->ti[u] = rpmdsTi(ods);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
ds->i = ds->Count;
|
|
|
2ff057 |
ds->Count++;
|
|
|
2ff057 |
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ods->i = save;
|
|
|
2ff057 |
return (ds->Count - ocount);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsSearch(rpmds ds, rpmds ods)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int comparison;
|
|
|
2ff057 |
int i, l, u;
|
|
|
2ff057 |
const char *ON = rpmdsN(ods);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ds == NULL || ods == NULL)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Binary search to find the [l,u) subset that contains N */
|
|
|
2ff057 |
i = -1;
|
|
|
2ff057 |
l = 0;
|
|
|
2ff057 |
u = ds->Count;
|
|
|
2ff057 |
while (l < u) {
|
|
|
2ff057 |
i = (l + u) / 2;
|
|
|
2ff057 |
|
|
|
2ff057 |
comparison = strcmp(ON, rpmdsNIndex(ds, i));
|
|
|
2ff057 |
|
|
|
2ff057 |
if (comparison < 0)
|
|
|
2ff057 |
u = i;
|
|
|
2ff057 |
else if (comparison > 0)
|
|
|
2ff057 |
l = i + 1;
|
|
|
2ff057 |
else {
|
|
|
2ff057 |
/* Set l to 1st member of set that contains N. */
|
|
|
2ff057 |
if (!rstreq(ON, rpmdsNIndex(ds, l)))
|
|
|
2ff057 |
l = i;
|
|
|
2ff057 |
while (l > 0 && rstreq(ON, rpmdsNIndex(ds, l-1)))
|
|
|
2ff057 |
l--;
|
|
|
2ff057 |
/* Set u to 1st member of set that does not contain N. */
|
|
|
2ff057 |
if (u >= ds->Count || !rstreq(ON, rpmdsNIndex(ds, u)))
|
|
|
2ff057 |
u = i;
|
|
|
2ff057 |
while (++u < ds->Count) {
|
|
|
2ff057 |
if (!rstreq(ON, rpmdsNIndex(ds, u)))
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Check each member of [l,u) subset for ranges overlap. */
|
|
|
2ff057 |
i = -1;
|
|
|
2ff057 |
if (l < u) {
|
|
|
2ff057 |
int save = rpmdsSetIx(ds, l-1);
|
|
|
2ff057 |
while ((l = rpmdsNext(ds)) >= 0 && (l < u)) {
|
|
|
2ff057 |
if ((i = rpmdsCompare(ods, ds)) != 0)
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* Return element index that overlaps, or -1. */
|
|
|
2ff057 |
if (i)
|
|
|
2ff057 |
i = rpmdsIx(ds);
|
|
|
2ff057 |
else {
|
|
|
2ff057 |
(void) rpmdsSetIx(ds, save);
|
|
|
2ff057 |
i = -1;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return i;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
* Split EVR into epoch, version, and release components.
|
|
|
2ff057 |
* @param evr [epoch:]version[-release] string
|
|
|
2ff057 |
* @retval *ep pointer to epoch
|
|
|
2ff057 |
* @retval *vp pointer to version
|
|
|
2ff057 |
* @retval *rp pointer to release
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static
|
|
|
2ff057 |
void parseEVR(char * evr,
|
|
|
2ff057 |
const char ** ep,
|
|
|
2ff057 |
const char ** vp,
|
|
|
2ff057 |
const char ** rp)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *epoch;
|
|
|
2ff057 |
const char *version; /* assume only version is present */
|
|
|
2ff057 |
const char *release;
|
|
|
2ff057 |
char *s, *se;
|
|
|
2ff057 |
|
|
|
2ff057 |
s = evr;
|
|
|
2ff057 |
while (*s && risdigit(*s)) s++; /* s points to epoch terminator */
|
|
|
2ff057 |
se = strrchr(s, '-'); /* se points to version terminator */
|
|
|
2ff057 |
|
|
|
2ff057 |
if (*s == ':') {
|
|
|
2ff057 |
epoch = evr;
|
|
|
2ff057 |
*s++ = '\0';
|
|
|
2ff057 |
version = s;
|
|
|
2ff057 |
if (*epoch == '\0') epoch = "0";
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
epoch = NULL; /* XXX disable epoch compare if missing */
|
|
|
2ff057 |
version = evr;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (se) {
|
|
|
2ff057 |
*se++ = '\0';
|
|
|
2ff057 |
release = se;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
release = NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ep) *ep = epoch;
|
|
|
2ff057 |
if (vp) *vp = version;
|
|
|
2ff057 |
if (rp) *rp = release;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static inline int rpmdsCompareEVR(const char *AEVR, uint32_t AFlags,
|
|
|
2ff057 |
const char *BEVR, uint32_t BFlags,
|
|
|
2ff057 |
int nopromote)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *aE, *aV, *aR, *bE, *bV, *bR;
|
|
|
2ff057 |
char *aEVR = xstrdup(AEVR);
|
|
|
2ff057 |
char *bEVR = xstrdup(BEVR);
|
|
|
2ff057 |
int sense = 0;
|
|
|
2ff057 |
int result = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
parseEVR(aEVR, &aE, &aV, &aR;;
|
|
|
2ff057 |
parseEVR(bEVR, &bE, &bV, &bR;;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Compare {A,B} [epoch:]version[-release] */
|
|
|
2ff057 |
if (aE && *aE && bE && *bE)
|
|
|
2ff057 |
sense = rpmvercmp(aE, bE);
|
|
|
2ff057 |
else if (aE && *aE && atol(aE) > 0) {
|
|
|
2ff057 |
if (!nopromote) {
|
|
|
2ff057 |
sense = 0;
|
|
|
2ff057 |
} else
|
|
|
2ff057 |
sense = 1;
|
|
|
2ff057 |
} else if (bE && *bE && atol(bE) > 0)
|
|
|
2ff057 |
sense = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (sense == 0) {
|
|
|
2ff057 |
sense = rpmvercmp(aV, bV);
|
|
|
2ff057 |
if (sense == 0) {
|
|
|
2ff057 |
if (aR && *aR && bR && *bR) {
|
|
|
2ff057 |
sense = rpmvercmp(aR, bR);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
/* always matches if the side with no release has SENSE_EQUAL */
|
|
|
2ff057 |
if ((aR && *aR && (BFlags & RPMSENSE_EQUAL)) ||
|
|
|
2ff057 |
(bR && *bR && (AFlags & RPMSENSE_EQUAL))) {
|
|
|
2ff057 |
aEVR = _free(aEVR);
|
|
|
2ff057 |
bEVR = _free(bEVR);
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Detect overlap of {A,B} range. */
|
|
|
2ff057 |
if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) {
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
} else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) {
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
} else if (sense == 0 &&
|
|
|
2ff057 |
(((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) ||
|
|
|
2ff057 |
((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) ||
|
|
|
2ff057 |
((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) {
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
free(aEVR);
|
|
|
2ff057 |
free(bEVR);
|
|
|
2ff057 |
return result;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsCompareIndex(rpmds A, int aix, rpmds B, int bix)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *AEVR, *BEVR;
|
|
|
2ff057 |
rpmsenseFlags AFlags, BFlags;
|
|
|
2ff057 |
int result;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Different names don't overlap. */
|
|
|
2ff057 |
if (!rpmstrPoolStreq(A->pool, rpmdsNIdIndex(A, aix),
|
|
|
2ff057 |
B->pool, rpmdsNIdIndex(B, bix))) {
|
|
|
2ff057 |
result = 0;
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
|
|
|
2ff057 |
if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Same name. If either A or B is an existence test, always overlap. */
|
|
|
2ff057 |
AFlags = rpmdsFlagsIndex(A, aix);
|
|
|
2ff057 |
BFlags = rpmdsFlagsIndex(B, bix);
|
|
|
2ff057 |
if (!((AFlags & RPMSENSE_SENSEMASK) && (BFlags & RPMSENSE_SENSEMASK))) {
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
AEVR = rpmdsEVRIndex(A, aix);
|
|
|
2ff057 |
BEVR = rpmdsEVRIndex(B, bix);
|
|
|
2ff057 |
if (!(AEVR && *AEVR && BEVR && *BEVR)) {
|
|
|
2ff057 |
/* If either EVR is non-existent or empty, always overlap. */
|
|
|
2ff057 |
result = 1;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
/* Both AEVR and BEVR exist, compare [epoch:]version[-release]. */
|
|
|
2ff057 |
result = rpmdsCompareEVR(AEVR, AFlags, BEVR, BFlags, B->nopromote);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
return result;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsCompare(const rpmds A, const rpmds B)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsCompareIndex(A, A->i, B, B->i);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsMatches(rpmstrPool pool, Header h, int prix,
|
|
|
2ff057 |
rpmds req, int selfevr, int nopromote)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmds provides;
|
|
|
2ff057 |
rpmTagVal tag = RPMTAG_PROVIDENAME;
|
|
|
2ff057 |
int result = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Get provides information from header */
|
|
|
2ff057 |
if (selfevr)
|
|
|
2ff057 |
provides = rpmdsThisPool(pool, h, tag, RPMSENSE_EQUAL);
|
|
|
2ff057 |
else
|
|
|
2ff057 |
provides = rpmdsNewPool(pool, h, tag, 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmdsSetNoPromote(provides, nopromote);
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* For a self-provide and indexed provide, we only need one comparison.
|
|
|
2ff057 |
* Otherwise loop through the provides until match or end.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
if (prix >= 0 || selfevr) {
|
|
|
2ff057 |
if (prix >= 0)
|
|
|
2ff057 |
rpmdsSetIx(provides, prix);
|
|
|
2ff057 |
result = rpmdsCompare(provides, req);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
provides = rpmdsInit(provides);
|
|
|
2ff057 |
while (rpmdsNext(provides) >= 0) {
|
|
|
2ff057 |
result = rpmdsCompare(provides, req);
|
|
|
2ff057 |
/* If this provide matches the require, we're done. */
|
|
|
2ff057 |
if (result)
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmdsFree(provides);
|
|
|
2ff057 |
return result;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsMatchesDep (const Header h, int ix, const rpmds req, int nopromote)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsMatches(NULL, h, ix, req, 0, nopromote);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsMatches(NULL, h, -1, req, 0, nopromote);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsMatches(NULL, h, -1, req, 1, nopromote);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
struct rpmlibProvides_s {
|
|
|
2ff057 |
const char * featureName;
|
|
|
2ff057 |
const char * featureEVR;
|
|
|
2ff057 |
rpmsenseFlags featureFlags;
|
|
|
2ff057 |
const char * featureDescription;
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
static const struct rpmlibProvides_s rpmlibProvides[] = {
|
|
|
2ff057 |
{ "rpmlib(VersionedDependencies)", "3.0.3-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
|
|
|
2ff057 |
{ "rpmlib(CompressedFileNames)", "3.0.4-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
|
|
|
2ff057 |
#if HAVE_BZLIB_H
|
|
|
2ff057 |
{ "rpmlib(PayloadIsBzip2)", "3.0.5-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package payload can be compressed using bzip2.") },
|
|
|
2ff057 |
#endif
|
|
|
2ff057 |
#if HAVE_LZMA_H
|
|
|
2ff057 |
{ "rpmlib(PayloadIsXz)", "5.2-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package payload can be compressed using xz.") },
|
|
|
2ff057 |
{ "rpmlib(PayloadIsLzma)", "4.4.2-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package payload can be compressed using lzma.") },
|
|
|
2ff057 |
#endif
|
|
|
2ff057 |
{ "rpmlib(PayloadFilesHavePrefix)", "4.0-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package payload file(s) have \"./\" prefix.") },
|
|
|
2ff057 |
{ "rpmlib(ExplicitPackageProvide)", "4.0-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package name-version-release is not implicitly provided.") },
|
|
|
2ff057 |
{ "rpmlib(HeaderLoadSortsTags)", "4.0.1-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("header tags are always sorted after being loaded.") },
|
|
|
2ff057 |
{ "rpmlib(ScriptletInterpreterArgs)", "4.0.3-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("the scriptlet interpreter can use arguments from header.") },
|
|
|
2ff057 |
{ "rpmlib(PartialHardlinkSets)", "4.0.4-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("a hardlink file set may be installed without being complete.") },
|
|
|
2ff057 |
{ "rpmlib(ConcurrentAccess)", "4.1-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package scriptlets may access the rpm database while installing.") },
|
|
|
2ff057 |
#ifdef WITH_LUA
|
|
|
2ff057 |
{ "rpmlib(BuiltinLuaScripts)", "4.2.2-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("internal support for lua scripts.") },
|
|
|
2ff057 |
#endif
|
|
|
2ff057 |
{ "rpmlib(FileDigests)", "4.6.0-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("file digest algorithm is per package configurable") },
|
|
|
2ff057 |
#ifdef WITH_CAP
|
|
|
2ff057 |
{ "rpmlib(FileCaps)", "4.6.1-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("support for POSIX.1e file capabilities") },
|
|
|
2ff057 |
#endif
|
|
|
2ff057 |
{ "rpmlib(ScriptletExpansion)", "4.9.0-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package scriptlets can be expanded at install time.") },
|
|
|
2ff057 |
{ "rpmlib(TildeInVersions)", "4.10.0-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("dependency comparison supports versions with tilde.") },
|
|
Igor Gnatenko |
36aee4 |
{ "rpmlib(CaretInVersions)", "4.15.0-1",
|
|
Igor Gnatenko |
36aee4 |
( RPMSENSE_EQUAL),
|
|
Igor Gnatenko |
36aee4 |
N_("dependency comparison supports versions with caret.") },
|
|
|
2ff057 |
{ "rpmlib(LargeFiles)", "4.12.0-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("support files larger than 4GB") },
|
|
|
2ff057 |
{ "rpmlib(RichDependencies)", "4.12.0-1",
|
|
|
2ff057 |
( RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("support for rich dependencies.") },
|
|
|
2ff057 |
#ifdef HAVE_ZSTD
|
|
|
2ff057 |
{ "rpmlib(PayloadIsZstd)", "5.4.18-1",
|
|
|
2ff057 |
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
|
|
|
2ff057 |
N_("package payload can be compressed using zstd.") },
|
|
|
2ff057 |
#endif
|
|
|
2ff057 |
{ NULL, NULL, 0, NULL }
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsRpmlibPool(rpmstrPool pool, rpmds * dsp, const void * tblp)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const struct rpmlibProvides_s * rltblp = tblp;
|
|
|
2ff057 |
const struct rpmlibProvides_s * rlp;
|
|
|
2ff057 |
int rc = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rltblp == NULL)
|
|
|
2ff057 |
rltblp = rpmlibProvides;
|
|
|
2ff057 |
|
|
|
2ff057 |
for (rlp = rltblp; rlp->featureName != NULL && rc >= 0; rlp++) {
|
|
|
2ff057 |
rpmds ds = rpmdsSinglePool(pool, RPMTAG_PROVIDENAME, rlp->featureName,
|
|
|
2ff057 |
rlp->featureEVR, rlp->featureFlags);
|
|
|
2ff057 |
rc = rpmdsMerge(dsp, ds);
|
|
|
2ff057 |
rpmdsFree(ds);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* freeze the pool to save memory, but only if private pool */
|
|
|
2ff057 |
if (*dsp && (*dsp)->pool != pool)
|
|
|
2ff057 |
rpmstrPoolFreeze((*dsp)->pool, 0);
|
|
|
2ff057 |
return (rc < 0) ? -1 : 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsRpmlib(rpmds * dsp, const void * tblp)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmdsRpmlibPool(NULL, dsp, tblp);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmstrPool rpmdsPool(rpmds ds)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ds != NULL) ? ds->pool : NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsenseFlags rpmSanitizeDSFlags(rpmTagVal tagN, rpmsenseFlags Flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmsenseFlags extra = RPMSENSE_ANY;
|
|
|
2ff057 |
switch (tagN) {
|
|
|
2ff057 |
case RPMTAG_PROVIDENAME:
|
|
|
2ff057 |
extra = Flags & RPMSENSE_FIND_PROVIDES;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_TRIGGERNAME:
|
|
|
2ff057 |
case RPMTAG_FILETRIGGERNAME:
|
|
|
2ff057 |
case RPMTAG_TRANSFILETRIGGERNAME:
|
|
|
2ff057 |
extra = Flags & RPMSENSE_TRIGGER;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_RECOMMENDNAME:
|
|
|
2ff057 |
case RPMTAG_SUGGESTNAME:
|
|
|
2ff057 |
case RPMTAG_SUPPLEMENTNAME:
|
|
|
2ff057 |
case RPMTAG_ENHANCENAME:
|
|
|
2ff057 |
case RPMTAG_REQUIRENAME:
|
|
|
2ff057 |
extra = Flags & (_ALL_REQUIRES_MASK);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case RPMTAG_CONFLICTNAME:
|
|
|
2ff057 |
extra = Flags;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
default:
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return (Flags & RPMSENSE_SENSEMASK) | extra;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static struct ReqComp {
|
|
|
2ff057 |
const char * token;
|
|
|
2ff057 |
rpmsenseFlags sense;
|
|
|
2ff057 |
} const ReqComparisons[] = {
|
|
|
2ff057 |
{ "<=", RPMSENSE_LESS | RPMSENSE_EQUAL},
|
|
|
2ff057 |
{ "=<", RPMSENSE_LESS | RPMSENSE_EQUAL},
|
|
|
2ff057 |
{ "<", RPMSENSE_LESS},
|
|
|
2ff057 |
|
|
|
2ff057 |
{ "==", RPMSENSE_EQUAL},
|
|
|
2ff057 |
{ "=", RPMSENSE_EQUAL},
|
|
|
2ff057 |
|
|
|
2ff057 |
{ ">=", RPMSENSE_GREATER | RPMSENSE_EQUAL},
|
|
|
2ff057 |
{ "=>", RPMSENSE_GREATER | RPMSENSE_EQUAL},
|
|
|
2ff057 |
{ ">", RPMSENSE_GREATER},
|
|
|
2ff057 |
|
|
|
2ff057 |
{ NULL, 0 },
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmsenseFlags rpmParseDSFlags(const char *str, size_t len)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const struct ReqComp *rc;
|
|
|
2ff057 |
for (rc = ReqComparisons; rc->token != NULL; rc++)
|
|
|
2ff057 |
if (len == strlen(rc->token) && rstreqn(str, rc->token, len))
|
|
|
2ff057 |
return rc->sense;
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static struct RichOpComp {
|
|
|
2ff057 |
const char * token;
|
|
|
2ff057 |
rpmrichOp op;
|
|
|
2ff057 |
} const RichOps[] = {
|
|
|
2ff057 |
{ "and", RPMRICHOP_AND},
|
|
|
2ff057 |
{ "or", RPMRICHOP_OR},
|
|
|
2ff057 |
{ "if", RPMRICHOP_IF},
|
|
|
2ff057 |
{ "unless", RPMRICHOP_UNLESS},
|
|
|
2ff057 |
{ "else", RPMRICHOP_ELSE},
|
|
|
2ff057 |
{ "with", RPMRICHOP_WITH},
|
|
|
2ff057 |
{ "without", RPMRICHOP_WITHOUT},
|
|
|
2ff057 |
{ NULL, 0 },
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmdsIsRich(rpmds dep)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char * n = rpmdsN(dep);
|
|
|
2ff057 |
return (n && n[0] == '(');
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmRC parseRichDepOp(const char **dstrp, rpmrichOp *opp, char **emsg)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *p = *dstrp, *pe = p;
|
|
|
2ff057 |
const struct RichOpComp *ro;
|
|
|
2ff057 |
|
|
|
2ff057 |
while (*pe && !risspace(*pe) && *pe != ')')
|
|
|
2ff057 |
pe++;
|
|
|
2ff057 |
for (ro = RichOps; ro->token != NULL; ro++)
|
|
|
2ff057 |
if (pe - p == strlen(ro->token) && rstreqn(p, ro->token, pe - p)) {
|
|
|
2ff057 |
*opp = ro->op;
|
|
|
2ff057 |
*dstrp = pe;
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Unknown rich dependency op '%.*s'"), (int)(pe - p), p);
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
const char *rpmrichOpStr(rpmrichOp op)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (op == RPMRICHOP_SINGLE)
|
|
|
2ff057 |
return "SINGLE";
|
|
|
2ff057 |
if (op == RPMRICHOP_AND)
|
|
|
2ff057 |
return "and";
|
|
|
2ff057 |
if (op == RPMRICHOP_OR)
|
|
|
2ff057 |
return "or";
|
|
|
2ff057 |
if (op == RPMRICHOP_IF)
|
|
|
2ff057 |
return "if";
|
|
|
2ff057 |
if (op == RPMRICHOP_UNLESS)
|
|
|
2ff057 |
return "unless";
|
|
|
2ff057 |
if (op == RPMRICHOP_ELSE)
|
|
|
2ff057 |
return "else";
|
|
|
2ff057 |
if (op == RPMRICHOP_WITH)
|
|
|
2ff057 |
return "with";
|
|
|
2ff057 |
if (op == RPMRICHOP_WITHOUT)
|
|
|
2ff057 |
return "without";
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
#define SKIPWHITE(_x) {while (*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;}
|
|
|
2ff057 |
#define SKIPNONWHITEX(_x){int bl = 0; while (*(_x) &&!(risspace(*_x) || *(_x) == ',' || (*(_x) == ')' && bl-- <= 0))) if (*(_x)++ == '(') bl++;}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmRC parseSimpleDep(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *p = *dstrp;
|
|
|
2ff057 |
const char *n, *e = 0;
|
|
|
2ff057 |
int nl, el = 0;
|
|
|
2ff057 |
rpmsenseFlags sense = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
n = p;
|
|
|
2ff057 |
SKIPNONWHITEX(p);
|
|
|
2ff057 |
nl = p - n;
|
|
|
2ff057 |
if (nl == 0) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Name required"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
SKIPWHITE(p);
|
|
|
2ff057 |
if (*p) {
|
|
|
2ff057 |
const char *pe = p;
|
|
|
2ff057 |
|
|
|
2ff057 |
SKIPNONWHITEX(pe);
|
|
|
2ff057 |
sense = rpmParseDSFlags(p, pe - p);
|
|
|
2ff057 |
if (sense) {
|
|
|
2ff057 |
p = pe;
|
|
|
2ff057 |
SKIPWHITE(p);
|
|
|
2ff057 |
e = p;
|
|
|
2ff057 |
SKIPNONWHITEX(p);
|
|
|
2ff057 |
el = p - e;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (e && el == 0) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Version required"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (cb && cb(cbdata, RPMRICH_PARSE_SIMPLE, n, nl, e, el, sense, RPMRICHOP_SINGLE, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
*dstrp = p;
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
#define RICHPARSE_CHECK (1 << 0)
|
|
|
2ff057 |
#define RICHPARSE_NO_WITH (1 << 1)
|
|
|
2ff057 |
#define RICHPARSE_NO_AND (1 << 2)
|
|
|
2ff057 |
#define RICHPARSE_NO_OR (1 << 3)
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmRC rpmrichParseCheck(rpmrichOp op, int check, char **emsg)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if ((op == RPMRICHOP_WITH || op == RPMRICHOP_WITHOUT) && (check & RICHPARSE_NO_WITH) != 0) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Illegal ops in with/without"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if ((check & RICHPARSE_CHECK) == 0)
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
if ((op == RPMRICHOP_AND || op == RPMRICHOP_IF) && (check & RICHPARSE_NO_AND) != 0) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Illegal context for 'unless', please use 'or' instead"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if ((op == RPMRICHOP_OR || op == RPMRICHOP_UNLESS) && (check & RICHPARSE_NO_OR) != 0) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Illegal context for 'if', please use 'and' instead"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmRC rpmrichParseInternal(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata, int *checkp)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *p = *dstrp, *pe;
|
|
|
2ff057 |
rpmrichOp op = RPMRICHOP_SINGLE, firstop = RPMRICHOP_SINGLE, chainop = 0;
|
|
|
2ff057 |
int check = checkp ? *checkp : 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (cb && cb(cbdata, RPMRICH_PARSE_ENTER, p, 0, 0, 0, 0, op, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
if (*p++ != '(') {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Rich dependency does not start with '('"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
for (;;) {
|
|
|
2ff057 |
SKIPWHITE(p);
|
|
|
2ff057 |
if (*p == ')') {
|
|
|
2ff057 |
if (emsg) {
|
|
|
2ff057 |
if (chainop)
|
|
|
2ff057 |
rasprintf(emsg, _("Missing argument to rich dependency op"));
|
|
|
2ff057 |
else
|
|
|
2ff057 |
rasprintf(emsg, _("Empty rich dependency"));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (*p == '(') {
|
|
|
2ff057 |
int subcheck = check & RICHPARSE_CHECK;
|
|
|
2ff057 |
if (rpmrichParseInternal(&p, emsg, cb, cbdata, &subcheck) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
if (op == RPMRICHOP_IF || op == RPMRICHOP_UNLESS)
|
|
|
2ff057 |
subcheck &= ~(RICHPARSE_NO_AND | RICHPARSE_NO_OR);
|
|
|
2ff057 |
check |= subcheck;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
if (parseSimpleDep(&p, emsg, cb, cbdata) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
SKIPWHITE(p);
|
|
|
2ff057 |
if (!*p) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Unterminated rich dependency: %s"), *dstrp);
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (*p == ')')
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
pe = p;
|
|
|
2ff057 |
if (parseRichDepOp(&pe, &op, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
if (firstop == RPMRICHOP_SINGLE)
|
|
|
2ff057 |
firstop = op;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (op == RPMRICHOP_ELSE && (chainop == RPMRICHOP_IF || chainop == RPMRICHOP_UNLESS))
|
|
|
2ff057 |
chainop = 0;
|
|
|
2ff057 |
if (chainop && op != chainop) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Cannot chain different ops"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (chainop && op != RPMRICHOP_AND && op != RPMRICHOP_OR && op != RPMRICHOP_WITH) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Can only chain and/or/with ops"));
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (cb && cb(cbdata, RPMRICH_PARSE_OP, p, pe - p, 0, 0, 0, op, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
chainop = op;
|
|
|
2ff057 |
p = pe;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* check for illegal combinations */
|
|
|
2ff057 |
if (rpmrichParseCheck(firstop, check, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* update check data */
|
|
|
2ff057 |
if (firstop == RPMRICHOP_IF)
|
|
|
2ff057 |
check |= RICHPARSE_NO_OR;
|
|
|
2ff057 |
if (firstop == RPMRICHOP_UNLESS)
|
|
|
2ff057 |
check |= RICHPARSE_NO_AND;
|
|
|
2ff057 |
if (op == RPMRICHOP_AND || op == RPMRICHOP_OR)
|
|
|
2ff057 |
check &= ~(RICHPARSE_NO_AND | RICHPARSE_NO_OR);
|
|
|
2ff057 |
if (op != RPMRICHOP_SINGLE && op != RPMRICHOP_WITH && op != RPMRICHOP_WITHOUT && op != RPMRICHOP_OR)
|
|
|
2ff057 |
check |= RICHPARSE_NO_WITH;
|
|
|
2ff057 |
|
|
|
2ff057 |
p++;
|
|
|
2ff057 |
if (cb && cb(cbdata, RPMRICH_PARSE_LEAVE, *dstrp, p - *dstrp , 0, 0, 0, op, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
*dstrp = p;
|
|
|
2ff057 |
if (checkp)
|
|
|
2ff057 |
*checkp |= check;
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC rpmrichParse(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return rpmrichParseInternal(dstrp, emsg, cb, cbdata, NULL);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC rpmrichParseForTag(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata, rpmTagVal tagN)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int check = RICHPARSE_CHECK;
|
|
|
2ff057 |
if (rpmrichParseInternal(dstrp, emsg, cb, cbdata, &check) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
switch (tagN) {
|
|
|
2ff057 |
case RPMTAG_CONFLICTNAME:
|
|
|
2ff057 |
case RPMTAG_SUPPLEMENTNAME:
|
|
|
2ff057 |
case RPMTAG_ENHANCENAME:
|
|
|
2ff057 |
if (rpmrichParseCheck(RPMRICHOP_OR, check, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
default:
|
|
|
2ff057 |
if (rpmrichParseCheck(RPMRICHOP_AND, check, emsg) != RPMRC_OK)
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
struct rpmdsParseRichDepData {
|
|
|
2ff057 |
rpmds dep;
|
|
|
2ff057 |
rpmsenseFlags depflags;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmds leftds;
|
|
|
2ff057 |
rpmds rightds;
|
|
|
2ff057 |
rpmrichOp op;
|
|
|
2ff057 |
|
|
|
2ff057 |
int depth;
|
|
|
2ff057 |
const char *rightstart;
|
|
|
2ff057 |
int dochain;
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmRC rpmdsParseRichDepCB(void *cbdata, rpmrichParseType type,
|
|
|
2ff057 |
const char *n, int nl, const char *e, int el, rpmsenseFlags sense,
|
|
|
2ff057 |
rpmrichOp op, char **emsg) {
|
|
|
2ff057 |
struct rpmdsParseRichDepData *data = cbdata;
|
|
|
2ff057 |
rpmds ds = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (type == RPMRICH_PARSE_ENTER)
|
|
|
2ff057 |
data->depth++;
|
|
|
2ff057 |
else if (type == RPMRICH_PARSE_LEAVE) {
|
|
|
2ff057 |
if (--data->depth == 0 && data->dochain && data->rightstart) {
|
|
|
2ff057 |
/* chain op hack, construct a sub-ds from the right side of the chain */
|
|
|
2ff057 |
char *right = xmalloc(n + nl - data->rightstart + 2);
|
|
|
2ff057 |
right[0] = '(';
|
|
|
2ff057 |
strncpy(right + 1, data->rightstart, n + nl - data->rightstart);
|
|
|
2ff057 |
right[n + nl - data->rightstart + 1] = 0;
|
|
|
2ff057 |
data->rightds = rpmdsFree(data->rightds);
|
|
|
2ff057 |
ds = singleDS(data->dep->pool, data->dep->tagN, 0, 0, data->depflags, 0, 0, 0);
|
|
|
2ff057 |
ds->N[0] = rpmstrPoolId(ds->pool, right, 1);
|
|
|
2ff057 |
ds->EVR[0] = rpmstrPoolId(ds->pool, "", 1);
|
|
|
2ff057 |
data->rightds = ds;
|
|
|
2ff057 |
free(right);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (data->depth != 1)
|
|
|
2ff057 |
return RPMRC_OK; /* we're only interested in top-level parsing */
|
|
|
2ff057 |
if ((type == RPMRICH_PARSE_SIMPLE || type == RPMRICH_PARSE_LEAVE) && !data->dochain) {
|
|
|
2ff057 |
if (type == RPMRICH_PARSE_SIMPLE && data->dep->tagN == RPMTAG_REQUIRENAME && nl > 7 &&
|
|
|
2ff057 |
rstreqn(n, "rpmlib(", sizeof("rpmlib(")-1))
|
|
|
2ff057 |
sense |= RPMSENSE_RPMLIB;
|
|
|
2ff057 |
ds = singleDS(data->dep->pool, data->dep->tagN, 0, 0, sense | data->depflags, 0, 0, 0);
|
|
|
2ff057 |
ds->N[0] = rpmstrPoolIdn(ds->pool, n, nl, 1);
|
|
|
2ff057 |
ds->EVR[0] = rpmstrPoolIdn(ds->pool, e ? e : "", el, 1);
|
|
|
2ff057 |
if (!data->leftds)
|
|
|
2ff057 |
data->leftds = ds;
|
|
|
2ff057 |
else {
|
|
|
2ff057 |
data->rightds = ds;
|
|
|
2ff057 |
data->rightstart = n;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (type == RPMRICH_PARSE_OP) {
|
|
|
2ff057 |
if (data->op != RPMRICHOP_SINGLE)
|
|
|
2ff057 |
data->dochain = 1; /* this is a chained op */
|
|
|
2ff057 |
else
|
|
|
2ff057 |
data->op = op;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC rpmdsParseRichDep(rpmds dep, rpmds *leftds, rpmds *rightds, rpmrichOp *op, char **emsg)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmRC rc;
|
|
|
2ff057 |
struct rpmdsParseRichDepData data;
|
|
|
2ff057 |
const char *depstr = rpmdsN(dep);
|
|
|
2ff057 |
memset(&data, 0, sizeof(data));
|
|
|
2ff057 |
data.dep = dep;
|
|
|
2ff057 |
data.op = RPMRICHOP_SINGLE;
|
|
|
2ff057 |
data.depflags = rpmdsFlags(dep) & ~(RPMSENSE_SENSEMASK | RPMSENSE_MISSINGOK);
|
|
|
2ff057 |
rc = rpmrichParse(&depstr, emsg, rpmdsParseRichDepCB, &data);
|
|
|
2ff057 |
if (rc == RPMRC_OK && *depstr) {
|
|
|
2ff057 |
if (emsg)
|
|
|
2ff057 |
rasprintf(emsg, _("Junk after rich dependency"));
|
|
|
2ff057 |
rc = RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (rc != RPMRC_OK) {
|
|
|
2ff057 |
rpmdsFree(data.leftds);
|
|
|
2ff057 |
rpmdsFree(data.rightds);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
*leftds = data.leftds;
|
|
|
2ff057 |
*rightds = data.rightds;
|
|
|
2ff057 |
*op = data.op;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|