1998-07-26 05:00:26 +08:00
|
|
|
#include "system.h"
|
1998-07-31 06:09:42 +08:00
|
|
|
|
1999-07-14 05:37:57 +08:00
|
|
|
#include <rpmlib.h>
|
1997-01-18 00:20:18 +08:00
|
|
|
|
1998-03-28 00:46:39 +08:00
|
|
|
#include "depends.h"
|
1996-07-11 00:29:24 +08:00
|
|
|
#include "misc.h"
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
/*@access rpmdb@*/
|
|
|
|
/*@access rpmTransactionSet@*/
|
|
|
|
|
1999-08-07 06:52:49 +08:00
|
|
|
int headerNVR(Header h, const char **np, const char **vp, const char **rp)
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
|
|
|
int type, count;
|
1999-08-07 06:52:49 +08:00
|
|
|
if (np && !headerGetEntry(h, RPMTAG_NAME, &type, (void **) np, &count))
|
|
|
|
*np = NULL;
|
|
|
|
if (vp && !headerGetEntry(h, RPMTAG_VERSION, &type, (void **) vp, &count))
|
|
|
|
*vp = NULL;
|
|
|
|
if (rp && !headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) rp, &count))
|
|
|
|
*rp = NULL;
|
1999-07-23 01:48:31 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
static /*@only@*/ char *printDepend(const char * key, const char * keyEVR,
|
|
|
|
int keyFlags)
|
|
|
|
{
|
|
|
|
char *tbuf, *t;
|
|
|
|
size_t nb;
|
|
|
|
|
|
|
|
nb = 0;
|
|
|
|
if (key) nb += strlen(key);
|
|
|
|
if (keyFlags) {
|
|
|
|
if (nb) nb++;
|
|
|
|
if (keyFlags & RPMSENSE_LESS) nb++;
|
|
|
|
if (keyFlags & RPMSENSE_GREATER) nb++;
|
|
|
|
if (keyFlags & RPMSENSE_EQUAL) nb++;
|
|
|
|
}
|
|
|
|
if (keyEVR) {
|
|
|
|
if (nb) nb++;
|
|
|
|
nb += strlen(keyEVR);
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
t = tbuf = xmalloc(nb + 1);
|
1999-09-19 08:29:44 +08:00
|
|
|
if (key)
|
|
|
|
while(*key) *t++ = *key++;
|
|
|
|
if (keyFlags) {
|
|
|
|
if (t != tbuf) *t++ = ' ';
|
|
|
|
if (keyFlags & RPMSENSE_LESS) *t++ = '<';
|
|
|
|
if (keyFlags & RPMSENSE_GREATER) *t++ = '>';
|
|
|
|
if (keyFlags & RPMSENSE_EQUAL) *t++ = '=';
|
|
|
|
}
|
|
|
|
if (keyEVR) {
|
|
|
|
if (t != tbuf) *t++ = ' ';
|
|
|
|
while(*keyEVR) *t++ = *keyEVR++;
|
|
|
|
}
|
|
|
|
*t = '\0';
|
|
|
|
return tbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static /*@only@*/ char *buildEVR(int_32 *e, const char *v, const char *r)
|
|
|
|
{
|
1999-09-21 11:22:53 +08:00
|
|
|
char *pEVR = xmalloc(21 + strlen(v) + 1 + strlen(r) + 1);
|
1999-09-19 08:29:44 +08:00
|
|
|
*pEVR = '\0';
|
|
|
|
if (e)
|
|
|
|
sprintf(pEVR, "%d:", *e);
|
|
|
|
strcat(pEVR, v);
|
|
|
|
strcat(pEVR, "-");
|
|
|
|
strcat(pEVR, r);
|
|
|
|
return pEVR;
|
|
|
|
}
|
|
|
|
|
1999-04-05 05:26:36 +08:00
|
|
|
struct orderListIndex {
|
|
|
|
int alIndex;
|
|
|
|
int orIndex;
|
|
|
|
};
|
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
static void alFreeIndex(struct availableList * al)
|
|
|
|
{
|
|
|
|
if (al->index.size) {
|
|
|
|
if (al->index.index)
|
|
|
|
free(al->index.index);
|
|
|
|
al->index.index = NULL;
|
|
|
|
al->index.size = 0;
|
|
|
|
}
|
|
|
|
}
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
static void alCreate(/*@out@*/struct availableList * al)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
1996-07-18 04:02:28 +08:00
|
|
|
al->alloced = 5;
|
|
|
|
al->size = 0;
|
1999-09-21 11:22:53 +08:00
|
|
|
al->list = xcalloc(al->alloced, sizeof(*al->list));
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
al->index.index = NULL;
|
1999-09-19 08:29:44 +08:00
|
|
|
al->index.size = 0;
|
1996-07-18 04:02:28 +08:00
|
|
|
alFreeIndex(al);
|
1998-03-05 00:52:59 +08:00
|
|
|
}
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
static void alFree(/*@only@*/struct availableList * al)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
1997-05-01 03:28:09 +08:00
|
|
|
int i;
|
1999-05-24 02:34:30 +08:00
|
|
|
rpmRelocation * r;
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
for (i = 0; i < al->size; i++) {
|
1996-07-18 04:02:28 +08:00
|
|
|
if (al->list[i].provides)
|
|
|
|
free(al->list[i].provides);
|
1999-09-19 23:27:37 +08:00
|
|
|
if (al->list[i].providesEVR)
|
|
|
|
free(al->list[i].providesEVR);
|
1997-05-01 03:28:09 +08:00
|
|
|
if (al->list[i].files)
|
|
|
|
free(al->list[i].files);
|
1999-01-06 10:29:42 +08:00
|
|
|
headerFree(al->list[i].h);
|
1999-05-24 02:34:30 +08:00
|
|
|
|
|
|
|
if (al->list[i].relocs) {
|
1999-08-07 07:44:25 +08:00
|
|
|
for (r = al->list[i].relocs; (r->oldPath || r->newPath); r++) {
|
1999-08-07 06:52:49 +08:00
|
|
|
if (r->oldPath) xfree(r->oldPath);
|
|
|
|
if (r->newPath) xfree(r->newPath);
|
1999-05-24 02:34:30 +08:00
|
|
|
}
|
|
|
|
free(al->list[i].relocs);
|
|
|
|
}
|
1997-05-01 03:28:09 +08:00
|
|
|
}
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (al->alloced && al->list)
|
|
|
|
free(al->list);
|
|
|
|
al->list = NULL;
|
1996-07-18 04:02:28 +08:00
|
|
|
alFreeIndex(al);
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
static /*@exposed@*/ struct availablePackage * alAddPackage(struct availableList * al,
|
1999-04-05 05:26:36 +08:00
|
|
|
Header h, const void * key,
|
1999-07-14 06:00:05 +08:00
|
|
|
FD_t fd, rpmRelocation * relocs)
|
|
|
|
{
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availablePackage * p;
|
1999-05-24 02:34:30 +08:00
|
|
|
rpmRelocation * r;
|
|
|
|
int i;
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
if (al->size == al->alloced) {
|
|
|
|
al->alloced += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
|
1996-07-18 04:02:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
p = al->list + al->size++;
|
1999-09-21 11:22:53 +08:00
|
|
|
p->h = headerLink(h); /* XXX reference held by transaction set */
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1999-07-23 01:48:31 +08:00
|
|
|
headerNVR(p->h, &p->name, &p->version, &p->release);
|
|
|
|
|
1999-09-15 00:04:03 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &p->epoch, NULL))
|
|
|
|
p->epoch = NULL;
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1999-07-23 01:48:31 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_PROVIDENAME, NULL, (void **) &p->provides,
|
1996-07-18 04:02:28 +08:00
|
|
|
&p->providesCount)) {
|
|
|
|
p->providesCount = 0;
|
|
|
|
p->provides = NULL;
|
1999-09-19 08:29:44 +08:00
|
|
|
p->providesEVR = NULL;
|
|
|
|
p->provideFlags = NULL;
|
|
|
|
} else {
|
|
|
|
if (!headerGetEntry(h, RPMTAG_PROVIDEVERSION,
|
|
|
|
NULL, (void **) &p->providesEVR, NULL))
|
|
|
|
p->providesEVR = NULL;
|
|
|
|
if (!headerGetEntry(h, RPMTAG_PROVIDEFLAGS,
|
|
|
|
NULL, (void **) &p->provideFlags, NULL))
|
|
|
|
p->provideFlags = NULL;
|
1996-07-18 04:02:28 +08:00
|
|
|
}
|
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &p->files,
|
|
|
|
&p->filesCount)) {
|
|
|
|
p->filesCount = 0;
|
|
|
|
p->files = NULL;
|
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
/* We don't use these entries (and rpm >= 2 never have) and they are
|
1998-12-17 05:58:53 +08:00
|
|
|
pretty misleading. Let's just get rid of them so they don't confuse
|
|
|
|
anyone. */
|
|
|
|
if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
|
|
|
|
headerRemoveEntry(h, RPMTAG_FILEUIDS);
|
|
|
|
if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
|
|
|
|
headerRemoveEntry(h, RPMTAG_FILEGIDS);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
p->key = key;
|
1998-12-17 05:58:53 +08:00
|
|
|
p->fd = fd;
|
1996-07-18 10:25:13 +08:00
|
|
|
|
1999-05-24 02:34:30 +08:00
|
|
|
if (relocs) {
|
|
|
|
for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++);
|
1999-09-21 11:22:53 +08:00
|
|
|
p->relocs = xmalloc(sizeof(*p->relocs) * (i + 1));
|
1999-05-24 02:34:30 +08:00
|
|
|
|
|
|
|
for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
|
1999-09-21 11:22:53 +08:00
|
|
|
p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
|
|
|
|
p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
|
1999-05-24 02:34:30 +08:00
|
|
|
}
|
|
|
|
p->relocs[i].oldPath = NULL;
|
|
|
|
p->relocs[i].newPath = NULL;
|
|
|
|
} else {
|
|
|
|
p->relocs = NULL;
|
|
|
|
}
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
alFreeIndex(al);
|
1999-04-05 05:26:36 +08:00
|
|
|
|
|
|
|
return p;
|
1996-07-18 04:02:28 +08:00
|
|
|
}
|
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
static int indexcmp(const void * a, const void *b)
|
|
|
|
{
|
|
|
|
const struct availableIndexEntry * aptr = a;
|
|
|
|
const struct availableIndexEntry * bptr = b;
|
|
|
|
|
|
|
|
return strcmp(aptr->entry, bptr->entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void alMakeIndex(struct availableList * al)
|
|
|
|
{
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availableIndex * ai = &al->index;
|
|
|
|
int i, j, k;
|
|
|
|
|
|
|
|
if (ai->size) return;
|
|
|
|
|
|
|
|
ai->size = al->size;
|
|
|
|
for (i = 0; i < al->size; i++) {
|
|
|
|
ai->size += al->list[i].providesCount;
|
|
|
|
}
|
1997-05-01 03:28:09 +08:00
|
|
|
for (i = 0; i < al->size; i++) {
|
|
|
|
ai->size += al->list[i].filesCount;
|
|
|
|
}
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
if (ai->size) {
|
1999-09-21 11:22:53 +08:00
|
|
|
ai->index = xcalloc(ai->size, sizeof(*ai->index));
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
k = 0;
|
|
|
|
for (i = 0; i < al->size; i++) {
|
|
|
|
ai->index[k].package = al->list + i;
|
|
|
|
ai->index[k].entry = al->list[i].name;
|
1997-05-01 03:28:09 +08:00
|
|
|
ai->index[k].type = IET_NAME;
|
1996-07-18 04:02:28 +08:00
|
|
|
k++;
|
|
|
|
|
|
|
|
for (j = 0; j < al->list[i].providesCount; j++) {
|
|
|
|
ai->index[k].package = al->list + i;
|
|
|
|
ai->index[k].entry = al->list[i].provides[j];
|
1997-05-01 03:28:09 +08:00
|
|
|
ai->index[k].type = IET_PROVIDES;
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < al->list[i].filesCount; j++) {
|
|
|
|
ai->index[k].package = al->list + i;
|
|
|
|
ai->index[k].entry = al->list[i].files[j];
|
|
|
|
ai->index[k].type = IET_FILE;
|
1996-07-18 04:02:28 +08:00
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-03-05 00:52:59 +08:00
|
|
|
qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
|
1996-07-18 04:02:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
static int intcmp(const void * a, const void *b)
|
|
|
|
{
|
1996-06-10 10:36:07 +08:00
|
|
|
const int * aptr = a;
|
|
|
|
const int * bptr = b;
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (*aptr < *bptr)
|
1996-06-10 10:36:07 +08:00
|
|
|
return -1;
|
|
|
|
else if (*aptr == *bptr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
static void parseEVR(char *evr, /*@exposed@*/ /*@out@*/const char **ep, /*@exposed@*/ /*@out@*/const char **vp, /*@exposed@*/ /*@out@*/const char **rp) /*@modifies evr,*ep,*vp,*rp @*/
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
1999-09-14 13:41:13 +08:00
|
|
|
const char *epoch;
|
|
|
|
const char *version; /* assume only version is present */
|
|
|
|
const char *release;
|
1999-07-23 01:48:31 +08:00
|
|
|
char *s, *se;
|
|
|
|
|
|
|
|
s = evr;
|
|
|
|
while (*s && isdigit(*s)) s++; /* s points to epoch terminator */
|
|
|
|
se = strrchr(s, '-'); /* se points to version terminator */
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (*s == ':') {
|
|
|
|
epoch = evr;
|
|
|
|
*s++ = '\0';
|
|
|
|
version = s;
|
|
|
|
if (*epoch == '\0') epoch = "0";
|
|
|
|
} else {
|
1999-09-15 00:04:03 +08:00
|
|
|
epoch = NULL; /* XXX disable epoch compare if missing */
|
1999-09-14 13:41:13 +08:00
|
|
|
version = evr;
|
1999-07-23 01:48:31 +08:00
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
if (se) {
|
|
|
|
*se++ = '\0';
|
|
|
|
release = se;
|
|
|
|
} else {
|
|
|
|
release = NULL;
|
|
|
|
}
|
|
|
|
|
1999-07-23 01:48:31 +08:00
|
|
|
if (ep) *ep = epoch;
|
|
|
|
if (vp) *vp = version;
|
|
|
|
if (rp) *rp = release;
|
|
|
|
}
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
static char *rpmName = PACKAGE;
|
|
|
|
static char *rpmEVR = VERSION;
|
|
|
|
static int rpmFlags = RPMSENSE_EQUAL;
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
static int rangesOverlap(const char *AName, const char *AEVR, int AFlags,
|
|
|
|
const char *BName, const char *BEVR, int BFlags)
|
1999-08-25 06:26:55 +08:00
|
|
|
{
|
1999-09-14 13:41:13 +08:00
|
|
|
char *aEVR, *bEVR;
|
|
|
|
const char *aE, *aV, *aR, *bE, *bV, *bR;
|
1999-08-25 06:26:55 +08:00
|
|
|
int result;
|
|
|
|
int sense;
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Different names don't overlap. */
|
1999-09-19 08:29:44 +08:00
|
|
|
if (strcmp(AName, BName)) {
|
|
|
|
result = 0;
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
/* Same name. If either A or B is an existence test, always overlap. */
|
1999-09-19 08:29:44 +08:00
|
|
|
if (!((AFlags & RPMSENSE_SENSEMASK) && (BFlags & RPMSENSE_SENSEMASK))) {
|
|
|
|
result = 1;
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
/* If either EVR is non-existent or empty, always overlap. */
|
1999-09-19 08:29:44 +08:00
|
|
|
if (!(AEVR && *AEVR && BEVR && *BEVR)) {
|
|
|
|
result = 1;
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-08-25 06:26:55 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Both AEVR and BEVR exist. */
|
1999-09-21 11:22:53 +08:00
|
|
|
aEVR = xstrdup(AEVR);
|
1999-09-14 13:41:13 +08:00
|
|
|
parseEVR(aEVR, &aE, &aV, &aR);
|
1999-09-21 11:22:53 +08:00
|
|
|
bEVR = xstrdup(BEVR);
|
1999-09-14 13:41:13 +08:00
|
|
|
parseEVR(bEVR, &bE, &bV, &bR);
|
1999-08-25 06:26:55 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Compare {A,B} [epoch:]version[-release] */
|
1999-09-20 21:23:46 +08:00
|
|
|
sense = 0;
|
1999-09-19 23:27:37 +08:00
|
|
|
if (aE && *aE && bE && *bE)
|
|
|
|
sense = rpmvercmp(aE, bE);
|
|
|
|
else if (aE && *aE)
|
|
|
|
sense = 1;
|
|
|
|
else if (bE && *bE)
|
|
|
|
sense = -1;
|
1999-08-25 06:26:55 +08:00
|
|
|
if (sense == 0) {
|
1999-09-14 13:41:13 +08:00
|
|
|
sense = rpmvercmp(aV, bV);
|
|
|
|
if (sense == 0 && aR && *aR && bR && *bR) {
|
|
|
|
sense = rpmvercmp(aR, bR);
|
1999-08-25 06:26:55 +08:00
|
|
|
}
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
free(aEVR);
|
|
|
|
free(bEVR);
|
1999-08-25 06:26:55 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Detect overlap of {A,B} range. */
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 0;
|
1999-09-14 13:41:13 +08:00
|
|
|
if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) {
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 1;
|
1999-09-14 13:41:13 +08:00
|
|
|
} else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) {
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 1;
|
1999-09-14 13:41:13 +08:00
|
|
|
} else if (sense == 0 &&
|
|
|
|
(((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) ||
|
|
|
|
((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) ||
|
|
|
|
((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) {
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
exit:
|
1999-08-25 06:26:55 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
typedef int (*dbrecMatch_t) (Header h, const char *reqName, const char * reqEVR, int reqFlags);
|
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
static int rangeMatchesDepFlags (Header h, const char *reqName, const char * reqEVR, int reqFlags)
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
1999-09-12 05:10:02 +08:00
|
|
|
const char ** provides;
|
|
|
|
const char ** providesEVR;
|
1999-09-14 13:41:13 +08:00
|
|
|
int_32 * provideFlags;
|
1999-07-23 01:48:31 +08:00
|
|
|
int providesCount;
|
|
|
|
int result;
|
|
|
|
int type;
|
|
|
|
int i;
|
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
if (!(reqFlags & RPMSENSE_SENSEMASK) || !reqEVR || !strlen(reqEVR))
|
1999-07-23 01:48:31 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Get provides information from header */
|
|
|
|
/*
|
|
|
|
* Rpm prior to 3.0.3 does not have versioned provides.
|
|
|
|
* If no provides version info is available, match any requires.
|
|
|
|
*/
|
|
|
|
if (!headerGetEntry(h, RPMTAG_PROVIDEVERSION, &type,
|
1999-09-12 05:10:02 +08:00
|
|
|
(void **) &providesEVR, &providesCount))
|
1999-07-23 01:48:31 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
headerGetEntry(h, RPMTAG_PROVIDEFLAGS, &type,
|
1999-09-14 13:41:13 +08:00
|
|
|
(void **) &provideFlags, &providesCount);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
|
|
|
if (!headerGetEntry(h, RPMTAG_PROVIDENAME, &type,
|
|
|
|
(void **) &provides, &providesCount)) {
|
1999-09-12 05:10:02 +08:00
|
|
|
if (providesEVR) xfree(providesEVR);
|
1999-07-23 01:48:31 +08:00
|
|
|
return 0; /* XXX should never happen */
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
for (i = 0; i < providesCount; i++) {
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
result = rangesOverlap(provides[i], providesEVR[i], provideFlags[i],
|
|
|
|
reqName, reqEVR, reqFlags);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* If this provide matches the require, we're done. */
|
1999-07-23 01:48:31 +08:00
|
|
|
if (result)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (provides) xfree(provides);
|
1999-09-12 05:10:02 +08:00
|
|
|
if (providesEVR) xfree(providesEVR);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
int headerMatchesDepFlags(Header h, const char *reqName, const char * reqEVR, int reqFlags)
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
1999-09-14 13:41:13 +08:00
|
|
|
const char *name, *version, *release;
|
1999-09-15 00:04:03 +08:00
|
|
|
int_32 * epoch;
|
1999-09-14 13:41:13 +08:00
|
|
|
char *pkgEVR;
|
|
|
|
int pkgFlags = RPMSENSE_EQUAL;
|
|
|
|
int type, count;
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (!((reqFlags & RPMSENSE_SENSEMASK) && reqEVR && *reqEVR))
|
1999-07-23 01:48:31 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Get package information from header */
|
1999-09-14 13:41:13 +08:00
|
|
|
headerNVR(h, &name, &version, &release);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
pkgEVR = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
|
|
|
|
*pkgEVR = '\0';
|
1999-09-15 00:04:03 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_EPOCH, &type, (void **) &epoch, &count))
|
|
|
|
sprintf(pkgEVR, "%d:", *epoch);
|
1999-09-14 13:41:13 +08:00
|
|
|
strcat(pkgEVR, version);
|
|
|
|
strcat(pkgEVR, "-");
|
|
|
|
strcat(pkgEVR, release);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
return rangesOverlap(name, pkgEVR, pkgFlags, reqName, reqEVR, reqFlags);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
static inline int dbrecMatchesDepFlags(rpmTransactionSet rpmdep, int recOffset,
|
1999-09-12 05:10:02 +08:00
|
|
|
const char * reqName, const char * reqEVR,
|
1999-07-23 01:48:31 +08:00
|
|
|
int reqFlags, dbrecMatch_t matchDepFlags)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
1996-06-11 01:42:57 +08:00
|
|
|
Header h;
|
1999-07-14 06:00:05 +08:00
|
|
|
int rc;
|
1996-10-21 03:31:21 +08:00
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
h = rpmdbGetRecord(rpmdep->db, recOffset);
|
|
|
|
if (h == NULL) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("dbrecMatchesDepFlags() failed to read header"));
|
|
|
|
return 0;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
rc = matchDepFlags(h, reqName, reqEVR, reqFlags);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
headerFree(h);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
return rc;
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
1999-08-21 05:05:18 +08:00
|
|
|
rpmTransactionSet rpmtransCreateSet(rpmdb db, const char * root)
|
|
|
|
{
|
|
|
|
rpmTransactionSet rpmdep;
|
|
|
|
int rootLength;
|
|
|
|
|
|
|
|
if (!root) root = "";
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
rpmdep = xmalloc(sizeof(*rpmdep));
|
1999-08-21 05:05:18 +08:00
|
|
|
rpmdep->db = db;
|
|
|
|
rpmdep->scriptFd = NULL;
|
|
|
|
rpmdep->numRemovedPackages = 0;
|
|
|
|
rpmdep->allocedRemovedPackages = 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
rpmdep->removedPackages = xcalloc(rpmdep->allocedRemovedPackages,
|
|
|
|
sizeof(*rpmdep->removedPackages));
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
/* This canonicalizes the root */
|
|
|
|
rootLength = strlen(root);
|
|
|
|
if (root && root[rootLength] == '/') {
|
|
|
|
char * newRootdir;
|
|
|
|
|
|
|
|
newRootdir = alloca(rootLength + 2);
|
|
|
|
strcpy(newRootdir, root);
|
|
|
|
newRootdir[rootLength++] = '/';
|
|
|
|
newRootdir[rootLength] = '\0';
|
|
|
|
root = newRootdir;
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
rpmdep->root = xstrdup(root);
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
alCreate(&rpmdep->addedPackages);
|
|
|
|
alCreate(&rpmdep->availablePackages);
|
|
|
|
|
|
|
|
rpmdep->orderAlloced = 5;
|
|
|
|
rpmdep->orderCount = 0;
|
1999-09-22 01:21:57 +08:00
|
|
|
rpmdep->order = xcalloc(rpmdep->orderAlloced, sizeof(*rpmdep->order)); /* XXX memory leak */
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
return rpmdep;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void removePackage(rpmTransactionSet rpmdep, int dboffset, int depends)
|
|
|
|
{
|
|
|
|
if (rpmdep->numRemovedPackages == rpmdep->allocedRemovedPackages) {
|
|
|
|
rpmdep->allocedRemovedPackages += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
rpmdep->removedPackages = xrealloc(rpmdep->removedPackages,
|
1999-08-21 05:05:18 +08:00
|
|
|
sizeof(int *) * rpmdep->allocedRemovedPackages);
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmdep->removedPackages[rpmdep->numRemovedPackages++] = dboffset;
|
|
|
|
|
|
|
|
if (rpmdep->orderCount == rpmdep->orderAlloced) {
|
|
|
|
rpmdep->orderAlloced += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
rpmdep->order = xrealloc(rpmdep->order,
|
1999-08-21 05:05:18 +08:00
|
|
|
sizeof(*rpmdep->order) * rpmdep->orderAlloced);
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmdep->order[rpmdep->orderCount].type = TR_REMOVED;
|
|
|
|
rpmdep->order[rpmdep->orderCount].u.removed.dboffset = dboffset;
|
|
|
|
rpmdep->order[rpmdep->orderCount++].u.removed.dependsOnIndex = depends;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd,
|
|
|
|
const void * key, int upgrade, rpmRelocation * relocs)
|
|
|
|
{
|
|
|
|
/* this is an install followed by uninstalls */
|
|
|
|
dbiIndexSet matches;
|
|
|
|
char * name;
|
|
|
|
int count, i, j;
|
|
|
|
const char ** obsoletes;
|
|
|
|
int alNum;
|
|
|
|
int * caps;
|
|
|
|
|
|
|
|
/* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
|
|
|
|
if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Make sure we've implemented all of the capabilities we need */
|
|
|
|
if (headerGetEntry(h, RPMTAG_CAPABILITY, NULL, (void **)&caps, &count)) {
|
|
|
|
if (count != 1 || *caps) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: handling upgrades like this is *almost* okay. It doesn't
|
|
|
|
check to make sure we're upgrading to a newer version, and it
|
|
|
|
makes it difficult to generate a return code based on the number of
|
|
|
|
packages which failed. */
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-08-21 05:05:18 +08:00
|
|
|
if (rpmdep->orderCount == rpmdep->orderAlloced) {
|
|
|
|
rpmdep->orderAlloced += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
rpmdep->order = xrealloc(rpmdep->order,
|
1999-08-21 05:05:18 +08:00
|
|
|
sizeof(*rpmdep->order) * rpmdep->orderAlloced);
|
|
|
|
}
|
|
|
|
rpmdep->order[rpmdep->orderCount].type = TR_ADDED;
|
1999-09-18 05:08:32 +08:00
|
|
|
alNum = alAddPackage(&rpmdep->addedPackages, h, key, fd, relocs) -
|
1999-08-21 05:05:18 +08:00
|
|
|
rpmdep->addedPackages.list;
|
|
|
|
rpmdep->order[rpmdep->orderCount++].u.addedIndex = alNum;
|
|
|
|
|
|
|
|
if (!upgrade || rpmdep->db == NULL) return 0;
|
|
|
|
|
|
|
|
headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, &count);
|
|
|
|
|
|
|
|
if (!rpmdbFindPackage(rpmdep->db, name, &matches)) {
|
|
|
|
|
|
|
|
for (i = 0; i < dbiIndexSetCount(matches); i++) {
|
1999-09-18 05:08:32 +08:00
|
|
|
Header h2;
|
1999-08-21 05:05:18 +08:00
|
|
|
h2 = rpmdbGetRecord(rpmdep->db, dbiIndexRecordOffset(matches, i));
|
|
|
|
if (h2 == NULL)
|
|
|
|
continue;
|
|
|
|
if (rpmVersionCompare(h, h2))
|
|
|
|
removePackage(rpmdep, dbiIndexRecordOffset(matches, i), alNum);
|
|
|
|
headerFree(h2);
|
|
|
|
}
|
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (headerGetEntry(h, RPMTAG_OBSOLETENAME, NULL, (void **) &obsoletes, &count)) {
|
1999-09-12 05:10:02 +08:00
|
|
|
const char **obsoletesEVR;
|
|
|
|
int_32 *obsoletesFlags;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
headerGetEntry(h, RPMTAG_OBSOLETEVERSION, NULL, (void **) &obsoletesEVR, NULL);
|
1999-08-25 06:26:55 +08:00
|
|
|
headerGetEntry(h, RPMTAG_OBSOLETEFLAGS, NULL, (void **) &obsoletesFlags, NULL);
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
for (j = 0; j < count; j++) {
|
1999-09-12 07:57:59 +08:00
|
|
|
|
|
|
|
/* XXX avoid self-obsoleting packages. */
|
|
|
|
if (!strcmp(name, obsoletes[j]))
|
|
|
|
continue;
|
|
|
|
|
1999-08-21 05:05:18 +08:00
|
|
|
if (rpmdbFindPackage(rpmdep->db, obsoletes[j], &matches))
|
|
|
|
continue;
|
|
|
|
for (i = 0; i < dbiIndexSetCount(matches); i++) {
|
|
|
|
unsigned int recOffset = dbiIndexRecordOffset(matches, i);
|
|
|
|
if (bsearch(&recOffset,
|
|
|
|
rpmdep->removedPackages, rpmdep->numRemovedPackages,
|
|
|
|
sizeof(int), intcmp))
|
|
|
|
continue;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
/*
|
|
|
|
* Rpm prior to 3.0.3 does not have versioned obsoletes.
|
|
|
|
* If no obsoletes version info is available, match all names.
|
|
|
|
*/
|
1999-09-12 05:10:02 +08:00
|
|
|
if (obsoletesEVR == NULL ||
|
1999-08-25 06:26:55 +08:00
|
|
|
dbrecMatchesDepFlags(rpmdep, recOffset,
|
1999-09-12 05:10:02 +08:00
|
|
|
obsoletes[j], obsoletesEVR[j], obsoletesFlags[j],
|
1999-08-25 06:26:55 +08:00
|
|
|
headerMatchesDepFlags)) {
|
1999-08-21 05:05:18 +08:00
|
|
|
removePackage(rpmdep, recOffset, alNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
}
|
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
if (obsoletesEVR) free(obsoletesEVR);
|
1999-08-21 05:05:18 +08:00
|
|
|
free(obsoletes);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpmtransAvailablePackage(rpmTransactionSet rpmdep, Header h, void * key)
|
|
|
|
{
|
1999-09-18 05:08:32 +08:00
|
|
|
struct availablePackage * al;
|
|
|
|
al = alAddPackage(&rpmdep->availablePackages, h, key, NULL, NULL);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void rpmtransRemovePackage(rpmTransactionSet rpmdep, int dboffset)
|
|
|
|
{
|
|
|
|
removePackage(rpmdep, dboffset, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpmtransFree(rpmTransactionSet rpmdep)
|
|
|
|
{
|
|
|
|
alFree(&rpmdep->addedPackages);
|
|
|
|
alFree(&rpmdep->availablePackages);
|
|
|
|
free(rpmdep->removedPackages);
|
1999-09-18 05:08:32 +08:00
|
|
|
xfree(rpmdep->root);
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
free(rpmdep);
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpmdepFreeConflicts(struct rpmDependencyConflict * conflicts, int
|
|
|
|
numConflicts)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < numConflicts; i++) {
|
|
|
|
headerFree(conflicts[i].byHeader);
|
|
|
|
free(conflicts[i].byName);
|
|
|
|
free(conflicts[i].byVersion);
|
|
|
|
free(conflicts[i].byRelease);
|
|
|
|
free(conflicts[i].needsName);
|
|
|
|
free(conflicts[i].needsVersion);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(conflicts);
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
static /*@exposed@*/ struct availablePackage * alSatisfiesDepend(struct availableList * al,
|
|
|
|
const char * keyName, const char * keyEVR, int keyFlags)
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
|
|
|
struct availableIndexEntry needle, * match;
|
1999-09-19 08:29:44 +08:00
|
|
|
struct availablePackage *p;
|
|
|
|
int i, rc;
|
1999-07-23 01:48:31 +08:00
|
|
|
|
|
|
|
if (!al->index.size) return NULL;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
needle.entry = keyName;
|
1999-07-23 01:48:31 +08:00
|
|
|
match = bsearch(&needle, al->index.index, al->index.size,
|
|
|
|
sizeof(*al->index.index), indexcmp);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (match == NULL) return NULL;
|
|
|
|
|
|
|
|
p = match->package;
|
|
|
|
rc = 0;
|
|
|
|
switch (match->type) {
|
|
|
|
case IET_NAME:
|
|
|
|
{ char *pEVR;
|
|
|
|
int pFlags = RPMSENSE_EQUAL;
|
|
|
|
pEVR = buildEVR(p->epoch, p->version, p->release);
|
|
|
|
rc = rangesOverlap(p->name, pEVR, pFlags, keyName, keyEVR, keyFlags);
|
|
|
|
free(pEVR);
|
|
|
|
} break;
|
|
|
|
case IET_PROVIDES:
|
|
|
|
for (i = 0; i < p->providesCount; i++) {
|
1999-09-20 21:23:46 +08:00
|
|
|
const char *proEVR;
|
|
|
|
int proFlags;
|
|
|
|
|
|
|
|
/* Filter out provides that came along for the ride. */
|
|
|
|
if (strcmp(p->provides[i], keyName)) continue;
|
|
|
|
|
|
|
|
proEVR = (p->providesEVR ? p->providesEVR[i] : NULL);
|
|
|
|
proFlags = (p->provideFlags ? p->provideFlags[i] : 0);
|
1999-09-20 21:04:44 +08:00
|
|
|
rc = rangesOverlap(p->provides[i], proEVR, proFlags,
|
|
|
|
keyName, keyEVR, keyFlags);
|
1999-09-19 08:29:44 +08:00
|
|
|
if (rc) break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IET_FILE:
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (rc)
|
|
|
|
return p;
|
1999-07-23 01:48:31 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
1996-06-10 10:36:07 +08:00
|
|
|
/* 2 == error */
|
|
|
|
/* 1 == dependency not satisfied */
|
1999-09-18 05:08:32 +08:00
|
|
|
static int unsatisfiedDepend(rpmTransactionSet rpmdep, const char * keyName,
|
|
|
|
const char * keyEVR, int keyFlags,
|
|
|
|
/*@out@*/struct availablePackage ** suggestion)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
1999-09-19 08:29:44 +08:00
|
|
|
const char *keyDepend = printDepend(keyName, keyEVR, keyFlags);
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1999-09-19 08:29:44 +08:00
|
|
|
int rc = 0; /* assume dependency is satisfied */
|
1996-06-10 10:36:07 +08:00
|
|
|
int i;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("dependencies: looking for %s\n"), keyDepend);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
if (suggestion) *suggestion = NULL;
|
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
{ const char * rcProvidesString;
|
|
|
|
const char * start;
|
1999-09-14 13:41:13 +08:00
|
|
|
if (!(keyFlags & RPMSENSE_SENSEMASK) &&
|
1997-07-24 02:32:15 +08:00
|
|
|
(rcProvidesString = rpmGetVar(RPMVAR_PROVIDES))) {
|
1999-09-14 13:41:13 +08:00
|
|
|
i = strlen(keyName);
|
|
|
|
while ((start = strstr(rcProvidesString, keyName))) {
|
1999-09-12 05:10:02 +08:00
|
|
|
if (isspace(start[i]) || start[i] == '\0' || start[i] == ',')
|
1999-09-19 08:29:44 +08:00
|
|
|
goto exit;
|
1998-07-01 02:52:54 +08:00
|
|
|
rcProvidesString = start + 1;
|
1997-07-24 02:32:15 +08:00
|
|
|
}
|
|
|
|
}
|
1999-09-12 05:10:02 +08:00
|
|
|
}
|
1997-07-24 02:32:15 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (alSatisfiesDepend(&rpmdep->addedPackages, keyName, keyEVR, keyFlags))
|
1999-09-19 08:29:44 +08:00
|
|
|
goto exit;
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1998-11-17 05:40:28 +08:00
|
|
|
if (rpmdep->db != NULL) {
|
1999-09-14 13:41:13 +08:00
|
|
|
if (*keyName == '/') {
|
|
|
|
/* keyFlags better be 0! */
|
|
|
|
if (!rpmdbFindByFile(rpmdep->db, keyName, &matches)) {
|
1998-11-20 02:10:28 +08:00
|
|
|
for (i = 0; i < dbiIndexSetCount(matches); i++) {
|
|
|
|
unsigned int recOffset = dbiIndexRecordOffset(matches, i);
|
1999-09-18 05:08:32 +08:00
|
|
|
if (bsearch(&recOffset,
|
|
|
|
rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages,
|
|
|
|
sizeof(int), intcmp))
|
1997-05-01 03:28:09 +08:00
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
1996-07-18 10:25:13 +08:00
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
1999-09-19 08:29:44 +08:00
|
|
|
if (i < dbiIndexSetCount(matches)) goto exit;
|
1997-05-01 03:28:09 +08:00
|
|
|
}
|
1999-02-03 03:43:35 +08:00
|
|
|
}
|
1997-05-01 03:28:09 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (!rpmdbFindByProvides(rpmdep->db, keyName, &matches)) {
|
1999-02-03 03:43:35 +08:00
|
|
|
for (i = 0; i < dbiIndexSetCount(matches); i++) {
|
|
|
|
unsigned int recOffset = dbiIndexRecordOffset(matches, i);
|
|
|
|
if (bsearch(&recOffset,
|
1999-09-18 05:08:32 +08:00
|
|
|
rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages,
|
|
|
|
sizeof(int), intcmp))
|
1999-02-03 03:43:35 +08:00
|
|
|
continue;
|
1999-07-23 01:48:31 +08:00
|
|
|
if (dbrecMatchesDepFlags(rpmdep, recOffset,
|
1999-09-14 13:41:13 +08:00
|
|
|
keyName, keyEVR, keyFlags, rangeMatchesDepFlags)) {
|
1999-07-23 01:48:31 +08:00
|
|
|
break;
|
|
|
|
}
|
1996-07-11 00:29:24 +08:00
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1999-02-03 03:43:35 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
1999-09-19 08:29:44 +08:00
|
|
|
if (i < dbiIndexSetCount(matches)) goto exit;
|
1999-02-03 03:43:35 +08:00
|
|
|
}
|
1997-05-01 03:28:09 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (!rpmdbFindPackage(rpmdep->db, keyName, &matches)) {
|
1999-02-03 03:43:35 +08:00
|
|
|
for (i = 0; i < dbiIndexSetCount(matches); i++) {
|
|
|
|
unsigned int recOffset = dbiIndexRecordOffset(matches, i);
|
|
|
|
if (bsearch(&recOffset,
|
1999-09-18 05:08:32 +08:00
|
|
|
rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages,
|
|
|
|
sizeof(int), intcmp))
|
1999-02-03 03:43:35 +08:00
|
|
|
continue;
|
|
|
|
|
1999-07-23 01:48:31 +08:00
|
|
|
if (dbrecMatchesDepFlags(rpmdep, recOffset,
|
1999-09-14 13:41:13 +08:00
|
|
|
keyName, keyEVR, keyFlags, headerMatchesDepFlags)) {
|
1999-02-03 03:43:35 +08:00
|
|
|
break;
|
1997-05-01 03:28:09 +08:00
|
|
|
}
|
|
|
|
}
|
1999-02-03 03:43:35 +08:00
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
1999-09-19 08:29:44 +08:00
|
|
|
if (i < dbiIndexSetCount(matches)) goto exit;
|
1996-07-18 10:25:13 +08:00
|
|
|
}
|
1999-08-25 06:26:55 +08:00
|
|
|
|
|
|
|
/*
|
1999-09-12 05:10:02 +08:00
|
|
|
* New features in rpm spec files add implicit dependencies on rpm
|
|
|
|
* version. Provide implicit rpm version in last ditch effort to
|
|
|
|
* satisfy an rpm dependency.
|
1999-08-25 06:26:55 +08:00
|
|
|
*/
|
1999-09-14 13:41:13 +08:00
|
|
|
if (rangesOverlap(keyName, keyEVR, keyFlags, rpmName, rpmEVR, rpmFlags))
|
1999-09-19 08:29:44 +08:00
|
|
|
goto exit;
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (suggestion)
|
|
|
|
*suggestion = alSatisfiesDepend(&rpmdep->availablePackages, keyName,
|
1999-09-14 13:41:13 +08:00
|
|
|
keyEVR, keyFlags);
|
1996-07-18 10:25:13 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
rc = 1; /* dependency is unsatisfied */
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (keyDepend)
|
|
|
|
xfree(keyDepend);
|
|
|
|
|
|
|
|
return rc;
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1998-12-17 05:58:53 +08:00
|
|
|
static int checkPackageDeps(rpmTransactionSet rpmdep, struct problemsSet * psp,
|
1999-09-19 08:29:44 +08:00
|
|
|
Header h, const char *keyName)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
1999-07-23 01:48:31 +08:00
|
|
|
const char * name, * version, * release;
|
1999-09-18 05:08:32 +08:00
|
|
|
const char ** requires, ** requiresEVR = NULL;
|
|
|
|
const char ** conflicts, ** conflictsEVR = NULL;
|
1999-09-19 08:29:44 +08:00
|
|
|
int requiresCount = 0, conflictsCount = 0;
|
1999-07-23 01:48:31 +08:00
|
|
|
int type;
|
1996-06-11 01:42:57 +08:00
|
|
|
int i, rc;
|
1996-10-21 03:31:21 +08:00
|
|
|
int ourrc = 0;
|
1999-09-18 05:08:32 +08:00
|
|
|
int_32 * requireFlags = NULL, * conflictFlags = NULL;
|
1996-07-18 10:25:13 +08:00
|
|
|
struct availablePackage * suggestion;
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
headerNVR(h, &name, &version, &release);
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_REQUIRENAME, &type, (void **) &requires,
|
1996-10-21 03:31:21 +08:00
|
|
|
&requiresCount)) {
|
|
|
|
requiresCount = 0;
|
|
|
|
} else {
|
1999-09-18 05:08:32 +08:00
|
|
|
headerGetEntry(h, RPMTAG_REQUIREFLAGS, &type, (void **) &requireFlags,
|
1996-10-21 03:31:21 +08:00
|
|
|
&requiresCount);
|
1999-09-18 05:08:32 +08:00
|
|
|
headerGetEntry(h, RPMTAG_REQUIREVERSION, &type,
|
1999-09-12 05:10:02 +08:00
|
|
|
(void **) &requiresEVR, &requiresCount);
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < requiresCount && !ourrc; i++) {
|
1999-09-19 08:29:44 +08:00
|
|
|
const char *keyDepend;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Filter out requires that came along for the ride. */
|
|
|
|
if (keyName && strcmp(keyName, requires[i]))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
keyDepend = printDepend(requires[i], requiresEVR[i], requireFlags[i]);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
rc = unsatisfiedDepend(rpmdep, requires[i], requiresEVR[i],
|
1996-07-18 10:25:13 +08:00
|
|
|
requireFlags[i], &suggestion);
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
switch (rc) {
|
1999-09-19 08:29:44 +08:00
|
|
|
case 0: /* requirements are satisfied. */
|
1999-09-14 13:41:13 +08:00
|
|
|
break;
|
1999-09-19 08:29:44 +08:00
|
|
|
case 1: /* requirements are not satisfied. */
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("package %s require not satisfied: %s\n"),
|
1999-09-19 08:29:44 +08:00
|
|
|
name, keyDepend);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-06-11 01:42:57 +08:00
|
|
|
if (psp->num == psp->alloced) {
|
|
|
|
psp->alloced += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
|
1996-06-11 01:42:57 +08:00
|
|
|
psp->alloced);
|
|
|
|
}
|
1998-12-17 05:58:53 +08:00
|
|
|
psp->problems[psp->num].byHeader = headerLink(h);
|
1999-09-21 11:22:53 +08:00
|
|
|
psp->problems[psp->num].byName = xstrdup(name);
|
|
|
|
psp->problems[psp->num].byVersion = xstrdup(version);
|
|
|
|
psp->problems[psp->num].byRelease = xstrdup(release);
|
|
|
|
psp->problems[psp->num].needsName = xstrdup(requires[i]);
|
|
|
|
psp->problems[psp->num].needsVersion = xstrdup(requiresEVR[i]);
|
1996-07-11 00:29:24 +08:00
|
|
|
psp->problems[psp->num].needsFlags = requireFlags[i];
|
|
|
|
psp->problems[psp->num].sense = RPMDEP_SENSE_REQUIRES;
|
1996-07-20 06:26:00 +08:00
|
|
|
|
|
|
|
if (suggestion)
|
|
|
|
psp->problems[psp->num].suggestedPackage = suggestion->key;
|
|
|
|
else
|
|
|
|
psp->problems[psp->num].suggestedPackage = NULL;
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1996-06-11 01:42:57 +08:00
|
|
|
psp->num++;
|
1999-09-14 13:41:13 +08:00
|
|
|
break;
|
|
|
|
case 2: /* something went wrong! */
|
|
|
|
default:
|
1996-10-21 03:31:21 +08:00
|
|
|
ourrc = 1;
|
1999-09-14 13:41:13 +08:00
|
|
|
break;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
1999-09-19 08:29:44 +08:00
|
|
|
xfree(keyDepend);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (requiresCount) {
|
|
|
|
free(requiresEVR);
|
|
|
|
free(requires);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!headerGetEntry(h, RPMTAG_CONFLICTNAME, &type, (void **) &conflicts,
|
|
|
|
&conflictsCount)) {
|
|
|
|
conflictsCount = 0;
|
|
|
|
} else {
|
|
|
|
headerGetEntry(h, RPMTAG_CONFLICTFLAGS, &type,
|
|
|
|
(void **) &conflictFlags, &conflictsCount);
|
|
|
|
headerGetEntry(h, RPMTAG_CONFLICTVERSION, &type,
|
|
|
|
(void **) &conflictsEVR, &conflictsCount);
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
for (i = 0; i < conflictsCount && !ourrc; i++) {
|
1999-09-19 08:29:44 +08:00
|
|
|
const char *keyDepend;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Filter out conflicts that came along for the ride. */
|
|
|
|
if (keyName && strcmp(keyName, conflicts[i]))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
keyDepend = printDepend(conflicts[i], conflictsEVR[i], conflictFlags[i]);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
rc = unsatisfiedDepend(rpmdep, conflicts[i], conflictsEVR[i],
|
1999-09-14 13:41:13 +08:00
|
|
|
conflictFlags[i], NULL);
|
1996-10-21 03:31:21 +08:00
|
|
|
|
|
|
|
/* 1 == unsatisfied, 0 == satsisfied */
|
1999-09-14 13:41:13 +08:00
|
|
|
switch (rc) {
|
1999-09-19 08:29:44 +08:00
|
|
|
case 0: /* conflicts exist. */
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
|
1999-09-19 08:29:44 +08:00
|
|
|
name, keyDepend);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
if (psp->num == psp->alloced) {
|
|
|
|
psp->alloced += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
|
1996-10-21 03:31:21 +08:00
|
|
|
psp->alloced);
|
|
|
|
}
|
1998-12-17 05:58:53 +08:00
|
|
|
psp->problems[psp->num].byHeader = headerLink(h);
|
1999-09-21 11:22:53 +08:00
|
|
|
psp->problems[psp->num].byName = xstrdup(name);
|
|
|
|
psp->problems[psp->num].byVersion = xstrdup(version);
|
|
|
|
psp->problems[psp->num].byRelease = xstrdup(release);
|
|
|
|
psp->problems[psp->num].needsName = xstrdup(conflicts[i]);
|
|
|
|
psp->problems[psp->num].needsVersion = xstrdup(conflictsEVR[i]);
|
1999-09-14 13:41:13 +08:00
|
|
|
psp->problems[psp->num].needsFlags = conflictFlags[i];
|
1996-10-21 03:31:21 +08:00
|
|
|
psp->problems[psp->num].sense = RPMDEP_SENSE_CONFLICTS;
|
|
|
|
psp->problems[psp->num].suggestedPackage = NULL;
|
|
|
|
|
|
|
|
psp->num++;
|
1999-09-14 13:41:13 +08:00
|
|
|
break;
|
1999-09-19 08:29:44 +08:00
|
|
|
case 1: /* conflicts don't exist. */
|
1999-09-14 13:41:13 +08:00
|
|
|
break;
|
|
|
|
case 2: /* something went wrong! */
|
|
|
|
default:
|
1996-10-21 03:31:21 +08:00
|
|
|
ourrc = 1;
|
1999-09-14 13:41:13 +08:00
|
|
|
break;
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
1999-09-19 08:29:44 +08:00
|
|
|
xfree(keyDepend);
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (conflictsCount) {
|
1999-09-12 05:10:02 +08:00
|
|
|
free(conflictsEVR);
|
1996-10-21 03:31:21 +08:00
|
|
|
free(conflicts);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ourrc;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Adding: check name/provides key against each conflict match. */
|
|
|
|
/* Erasing: check name/provides/filename key against each requiredby match. */
|
1999-09-18 05:08:32 +08:00
|
|
|
static int checkPackageSet(rpmTransactionSet rpmdep, struct problemsSet * psp,
|
1999-09-19 08:29:44 +08:00
|
|
|
const char *key, dbiIndexSet *matches)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
|
|
|
Header h;
|
1999-09-14 13:41:13 +08:00
|
|
|
int i;
|
1999-07-14 06:00:05 +08:00
|
|
|
|
|
|
|
for (i = 0; i < matches->count; i++) {
|
|
|
|
unsigned int recOffset = dbiIndexRecordOffset(*matches, i);
|
1999-09-18 05:08:32 +08:00
|
|
|
if (bsearch(&recOffset, rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages, sizeof(int), intcmp))
|
1999-07-14 06:00:05 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
h = rpmdbGetRecord(rpmdep->db, recOffset);
|
|
|
|
if (h == NULL) {
|
1999-09-18 05:08:32 +08:00
|
|
|
rpmError(RPMERR_DBCORRUPT,
|
1999-07-14 06:00:05 +08:00
|
|
|
_("cannot read header at %d for dependency check"),
|
|
|
|
rpmdep->removedPackages[i]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (checkPackageDeps(rpmdep, psp, h, key)) {
|
1999-07-14 06:00:05 +08:00
|
|
|
headerFree(h);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
headerFree(h);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Erasing: check name/provides/filename key against requiredby matches. */
|
1999-09-18 05:08:32 +08:00
|
|
|
static int checkDependentPackages(rpmTransactionSet rpmdep,
|
1999-09-19 08:29:44 +08:00
|
|
|
struct problemsSet * psp, const char * key)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
|
|
|
dbiIndexSet matches;
|
|
|
|
int rc;
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (rpmdbFindByRequiredBy(rpmdep->db, key, &matches))
|
1999-07-14 06:00:05 +08:00
|
|
|
return 0;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
rc = checkPackageSet(rpmdep, psp, key, &matches);
|
1999-07-14 06:00:05 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Adding: check name/provides key against conflicts matches. */
|
1999-09-18 05:08:32 +08:00
|
|
|
static int checkDependentConflicts(rpmTransactionSet rpmdep,
|
1999-09-19 08:29:44 +08:00
|
|
|
struct problemsSet * psp, const char * key)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
|
|
|
dbiIndexSet matches;
|
|
|
|
int rc;
|
|
|
|
|
1999-09-15 00:04:03 +08:00
|
|
|
if (rpmdep->db == NULL)
|
|
|
|
return 0;
|
1999-07-14 06:00:05 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (rpmdbFindByConflicts(rpmdep->db, key, &matches))
|
1999-07-14 06:00:05 +08:00
|
|
|
return 0;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
rc = checkPackageSet(rpmdep, psp, key, &matches);
|
1999-07-14 06:00:05 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
1997-10-04 00:08:45 +08:00
|
|
|
/* selection status is one of:
|
|
|
|
|
|
|
|
-1: selected
|
|
|
|
0: not selected
|
|
|
|
> 0: selection class
|
|
|
|
|
|
|
|
the current selection pass is included as a separate parameter, and is
|
|
|
|
incremented when satisfying a prerequisite */
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
static int addOrderedPack(rpmTransactionSet rpmdep,
|
1997-07-02 00:24:08 +08:00
|
|
|
struct availablePackage * package,
|
1999-09-18 05:08:32 +08:00
|
|
|
int * ordering, int * orderNumPtr,
|
1997-10-04 00:08:45 +08:00
|
|
|
int * selected, int selectionClass,
|
1999-07-23 01:48:31 +08:00
|
|
|
int satisfyDepends, const char ** errorStack)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
1999-08-25 06:26:55 +08:00
|
|
|
const char ** requires;
|
1999-09-12 05:10:02 +08:00
|
|
|
const char ** requiresEVR;
|
1997-07-02 00:24:08 +08:00
|
|
|
int_32 * requireFlags;
|
|
|
|
int requiresCount;
|
1997-10-04 00:08:45 +08:00
|
|
|
int matchNum;
|
1997-07-02 00:24:08 +08:00
|
|
|
int packageNum = package - rpmdep->addedPackages.list;
|
1999-08-25 06:26:55 +08:00
|
|
|
int i;
|
1997-07-02 00:24:08 +08:00
|
|
|
struct availablePackage * match;
|
1997-07-18 23:03:35 +08:00
|
|
|
char * errorString;
|
1999-07-23 01:48:31 +08:00
|
|
|
const char ** stack;
|
1999-08-25 06:26:55 +08:00
|
|
|
int rc = 0;
|
1997-07-18 23:03:35 +08:00
|
|
|
|
|
|
|
*errorStack++ = package->name;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
1997-10-04 00:08:45 +08:00
|
|
|
if (selected[packageNum] > 0) {
|
1997-07-18 23:03:35 +08:00
|
|
|
i = 0;
|
|
|
|
stack = errorStack - 1;
|
|
|
|
while (*(--stack)) {
|
|
|
|
i += strlen(*stack) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
errorString = alloca(i + 2);
|
|
|
|
*errorString = '\0';
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1997-07-18 23:03:35 +08:00
|
|
|
while ((++stack) < errorStack) {
|
|
|
|
strcat(errorString, *stack);
|
|
|
|
strcat(errorString, " ");
|
|
|
|
}
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1998-01-10 03:10:54 +08:00
|
|
|
rpmError(RPMMESS_PREREQLOOP, _("loop in prerequisite chain: %s"),
|
1997-07-18 23:03:35 +08:00
|
|
|
errorString);
|
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1997-10-04 00:08:45 +08:00
|
|
|
selected[packageNum] = selectionClass;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (headerGetEntry(package->h, RPMTAG_REQUIRENAME, NULL,
|
1997-07-02 00:24:08 +08:00
|
|
|
(void **) &requires, &requiresCount)) {
|
1999-09-18 05:08:32 +08:00
|
|
|
headerGetEntry(package->h, RPMTAG_REQUIREFLAGS, NULL,
|
1997-07-02 00:24:08 +08:00
|
|
|
(void **) &requireFlags, NULL);
|
1999-09-18 05:08:32 +08:00
|
|
|
headerGetEntry(package->h, RPMTAG_REQUIREVERSION, NULL,
|
1999-09-12 05:10:02 +08:00
|
|
|
(void **) &requiresEVR, NULL);
|
1997-07-02 00:24:08 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
for (i = 0; rc == 0 && i < requiresCount; i++) {
|
|
|
|
if (!(satisfyDepends || (requireFlags[i] & RPMSENSE_PREREQ)))
|
|
|
|
continue;
|
|
|
|
match = alSatisfiesDepend(&rpmdep->addedPackages,
|
1999-09-12 05:10:02 +08:00
|
|
|
requires[i], requiresEVR[i], requireFlags[i]);
|
1999-08-25 06:26:55 +08:00
|
|
|
/* broken dependencies don't concern us */
|
|
|
|
if (!match) continue;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
/* let this package satisfy its own predependencies */
|
|
|
|
if (match == package) continue;
|
1997-07-09 02:41:10 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
/* the package has already been selected */
|
|
|
|
matchNum = match - rpmdep->addedPackages.list;
|
|
|
|
if(selected[matchNum] == -1 || selected[matchNum] == selectionClass)
|
|
|
|
continue;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
if (requireFlags[i] & RPMSENSE_PREREQ)
|
|
|
|
rc = addOrderedPack(rpmdep, match, ordering, orderNumPtr,
|
|
|
|
selected, selectionClass + 1, 1, errorStack);
|
|
|
|
else
|
|
|
|
rc = addOrderedPack(rpmdep, match, ordering, orderNumPtr,
|
|
|
|
selected, selectionClass, 1, errorStack);
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
1998-05-06 07:12:17 +08:00
|
|
|
|
|
|
|
free(requires);
|
1999-09-12 05:10:02 +08:00
|
|
|
free(requiresEVR);
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* whew -- add this package */
|
1999-08-25 06:26:55 +08:00
|
|
|
if (rc == 0) {
|
|
|
|
ordering[(*orderNumPtr)++] = packageNum;
|
|
|
|
selected[packageNum] = -1;
|
|
|
|
}
|
1997-07-02 00:24:08 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
return rc;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
static int orderListIndexCmp(const void * one, const void * two)
|
|
|
|
{
|
|
|
|
const struct orderListIndex * a = one;
|
|
|
|
const struct orderListIndex * b = two;
|
|
|
|
|
|
|
|
if (a->alIndex < b->alIndex)
|
|
|
|
return -1;
|
|
|
|
if (a->alIndex > b->alIndex)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmdepOrder(rpmTransactionSet rpmdep)
|
|
|
|
{
|
1999-04-05 05:26:36 +08:00
|
|
|
int i, j;
|
1997-10-04 00:08:45 +08:00
|
|
|
int * selected;
|
1999-04-05 05:26:36 +08:00
|
|
|
int * ordering;
|
|
|
|
int orderingCount;
|
1999-07-23 01:48:31 +08:00
|
|
|
const char ** errorStack;
|
1999-04-05 05:26:36 +08:00
|
|
|
struct transactionElement * newOrder;
|
|
|
|
int newOrderCount = 0;
|
|
|
|
struct orderListIndex * orderList, * needle, key;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
1997-07-16 09:39:54 +08:00
|
|
|
alMakeIndex(&rpmdep->addedPackages);
|
|
|
|
alMakeIndex(&rpmdep->availablePackages);
|
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
selected = alloca(sizeof(*selected) * rpmdep->addedPackages.size);
|
|
|
|
memset(selected, 0, sizeof(*selected) * rpmdep->addedPackages.size);
|
|
|
|
|
1997-07-18 23:03:35 +08:00
|
|
|
errorStack = alloca(sizeof(*errorStack) * (rpmdep->addedPackages.size + 1));
|
|
|
|
*errorStack++ = NULL;
|
|
|
|
|
1999-04-05 05:26:36 +08:00
|
|
|
ordering = alloca(sizeof(*ordering) * (rpmdep->addedPackages.size + 1));
|
|
|
|
orderingCount = 0;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
|
|
|
for (i = 0; i < rpmdep->addedPackages.size; i++) {
|
1997-10-04 00:08:45 +08:00
|
|
|
if (!selected[i]) {
|
1997-07-02 00:24:08 +08:00
|
|
|
if (addOrderedPack(rpmdep, rpmdep->addedPackages.list + i,
|
1999-09-18 05:08:32 +08:00
|
|
|
ordering, &orderingCount, selected, 1, 0,
|
1999-04-05 05:26:36 +08:00
|
|
|
errorStack)) {
|
1997-07-02 00:24:08 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-04-05 05:26:36 +08:00
|
|
|
/* The order ends up as installed packages followed by removed packages,
|
|
|
|
with removes for upgrades immediately follwing the installation of
|
1999-09-18 05:08:32 +08:00
|
|
|
the new package. This would be easier if we could sort the
|
1999-04-05 05:26:36 +08:00
|
|
|
addedPackages array, but we store indexes into it in various places. */
|
1999-09-21 11:22:53 +08:00
|
|
|
orderList = xmalloc(sizeof(*orderList) * rpmdep->addedPackages.size);
|
1999-04-05 05:26:36 +08:00
|
|
|
for (i = 0, j = 0; i < rpmdep->orderCount; i++) {
|
|
|
|
if (rpmdep->order[i].type == TR_ADDED) {
|
|
|
|
orderList[j].alIndex = rpmdep->order[i].u.addedIndex;
|
|
|
|
orderList[j].orIndex = i;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
1999-04-14 01:26:43 +08:00
|
|
|
if (j > rpmdep->addedPackages.size) abort();
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
qsort(orderList, rpmdep->addedPackages.size, sizeof(*orderList),
|
1999-04-05 05:26:36 +08:00
|
|
|
orderListIndexCmp);
|
|
|
|
|
1999-09-22 01:21:57 +08:00
|
|
|
newOrder = xmalloc(sizeof(*newOrder) * rpmdep->orderCount); /* XXX memory leak */
|
1999-04-05 05:26:36 +08:00
|
|
|
for (i = 0, newOrderCount = 0; i < orderingCount; i++) {
|
|
|
|
key.alIndex = ordering[i];
|
|
|
|
needle = bsearch(&key, orderList, rpmdep->addedPackages.size,
|
|
|
|
sizeof(key), orderListIndexCmp);
|
|
|
|
/* bsearch should never, ever fail */
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-04-05 05:26:36 +08:00
|
|
|
newOrder[newOrderCount++] = rpmdep->order[needle->orIndex];
|
|
|
|
for (j = needle->orIndex + 1; j < rpmdep->orderCount; j++) {
|
|
|
|
if (rpmdep->order[j].type == TR_REMOVED &&
|
|
|
|
rpmdep->order[j].u.removed.dependsOnIndex == needle->alIndex) {
|
|
|
|
newOrder[newOrderCount++] = rpmdep->order[j];
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < rpmdep->orderCount; i++) {
|
1999-09-18 05:08:32 +08:00
|
|
|
if (rpmdep->order[i].type == TR_REMOVED &&
|
1999-04-05 05:26:36 +08:00
|
|
|
rpmdep->order[i].u.removed.dependsOnIndex == -1) {
|
|
|
|
newOrder[newOrderCount++] = rpmdep->order[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-04-14 01:26:43 +08:00
|
|
|
if (newOrderCount != rpmdep->orderCount) abort();
|
|
|
|
|
1999-04-05 05:26:36 +08:00
|
|
|
free(rpmdep->order);
|
|
|
|
rpmdep->order = newOrder;
|
|
|
|
rpmdep->orderAlloced = rpmdep->orderCount;
|
|
|
|
free(orderList);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
int rpmdepCheck(rpmTransactionSet rpmdep,
|
1999-07-14 06:00:05 +08:00
|
|
|
struct rpmDependencyConflict ** conflicts, int * numConflicts)
|
|
|
|
{
|
|
|
|
struct availablePackage * p;
|
|
|
|
int i, j;
|
1999-09-14 13:41:13 +08:00
|
|
|
const char ** files;
|
|
|
|
int fileCount;
|
|
|
|
int rc;
|
|
|
|
Header h = NULL;
|
1999-07-14 06:00:05 +08:00
|
|
|
struct problemsSet ps;
|
1999-04-05 05:26:36 +08:00
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
ps.alloced = 5;
|
|
|
|
ps.num = 0;
|
1999-09-21 11:22:53 +08:00
|
|
|
ps.problems = xcalloc(ps.alloced, sizeof(struct rpmDependencyConflict));
|
1999-07-14 06:00:05 +08:00
|
|
|
|
|
|
|
*conflicts = NULL;
|
|
|
|
*numConflicts = 0;
|
|
|
|
|
|
|
|
qsort(rpmdep->removedPackages, rpmdep->numRemovedPackages,
|
|
|
|
sizeof(int), intcmp);
|
|
|
|
|
|
|
|
alMakeIndex(&rpmdep->addedPackages);
|
|
|
|
alMakeIndex(&rpmdep->availablePackages);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
/* look at all of the added packages and make sure their dependencies
|
|
|
|
are satisfied */
|
|
|
|
p = rpmdep->addedPackages.list;
|
|
|
|
for (i = 0; i < rpmdep->addedPackages.size; i++, p++) {
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (checkPackageDeps(rpmdep, &ps, p->h, NULL))
|
1999-09-14 13:41:13 +08:00
|
|
|
goto exit;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Adding: check name against conflicts matches. */
|
|
|
|
if (checkDependentConflicts(rpmdep, &ps, p->name))
|
1999-09-14 13:41:13 +08:00
|
|
|
goto exit;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (p->providesCount == 0 || p->provides == NULL)
|
|
|
|
continue;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
rc = 0;
|
1999-09-19 08:29:44 +08:00
|
|
|
for (j = 0; j < p->providesCount; j++) {
|
|
|
|
/* Adding: check provides key against conflicts matches. */
|
|
|
|
if (checkDependentConflicts(rpmdep, &ps, p->provides[j])) {
|
1999-09-14 13:41:13 +08:00
|
|
|
rc = 1;
|
|
|
|
break;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
if (rc) goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* now look at the removed packages and make sure they aren't critical */
|
|
|
|
for (i = 0; i < rpmdep->numRemovedPackages; i++) {
|
1999-09-19 08:29:44 +08:00
|
|
|
const char *name;
|
1999-09-18 05:08:32 +08:00
|
|
|
const char ** provides;
|
|
|
|
int providesCount;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
1999-07-14 06:00:05 +08:00
|
|
|
h = rpmdbGetRecord(rpmdep->db, rpmdep->removedPackages[i]);
|
|
|
|
if (h == NULL) {
|
1999-09-18 05:08:32 +08:00
|
|
|
rpmError(RPMERR_DBCORRUPT,
|
1999-07-14 06:00:05 +08:00
|
|
|
_("cannot read header at %d for dependency check"),
|
|
|
|
rpmdep->removedPackages[i]);
|
1999-09-14 13:41:13 +08:00
|
|
|
goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
headerNVR(h, &name, NULL, NULL);
|
1999-07-14 06:00:05 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Erasing: check name against requiredby matches. */
|
|
|
|
if (checkDependentPackages(rpmdep, &ps, name))
|
1999-09-14 13:41:13 +08:00
|
|
|
goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_PROVIDENAME, NULL, (void **) &provides,
|
1999-07-14 06:00:05 +08:00
|
|
|
&providesCount)) {
|
1999-09-14 13:41:13 +08:00
|
|
|
rc = 0;
|
1999-07-14 06:00:05 +08:00
|
|
|
for (j = 0; j < providesCount; j++) {
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Erasing: check provides against requiredby matches. */
|
|
|
|
if (checkDependentPackages(rpmdep, &ps, provides[j])) {
|
1999-09-14 13:41:13 +08:00
|
|
|
rc = 1;
|
|
|
|
break;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(provides);
|
1999-09-14 13:41:13 +08:00
|
|
|
if (rc) goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &files,
|
1999-07-14 06:00:05 +08:00
|
|
|
&fileCount)) {
|
1999-09-14 13:41:13 +08:00
|
|
|
rc = 0;
|
1999-07-14 06:00:05 +08:00
|
|
|
for (j = 0; j < fileCount; j++) {
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Erasing: check filename against requiredby matches. */
|
|
|
|
if (checkDependentPackages(rpmdep, &ps, files[j])) {
|
1999-09-14 13:41:13 +08:00
|
|
|
rc = 1;
|
|
|
|
break;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(files);
|
1999-09-14 13:41:13 +08:00
|
|
|
if (rc) goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
headerFree(h); h = NULL;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (!ps.num) {
|
1999-07-14 06:00:05 +08:00
|
|
|
free(ps.problems);
|
1999-09-18 05:08:32 +08:00
|
|
|
} else {
|
1999-07-14 06:00:05 +08:00
|
|
|
*conflicts = ps.problems;
|
|
|
|
*numConflicts = ps.num;
|
|
|
|
}
|
1999-09-18 05:08:32 +08:00
|
|
|
ps.problems = NULL;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
|
|
|
return 0;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
exit:
|
1999-09-21 11:22:53 +08:00
|
|
|
if (h) {
|
|
|
|
headerFree(h);
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
if (ps.problems) free(ps.problems);
|
|
|
|
return 1;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|