1998-07-26 05:00:26 +08:00
|
|
|
#include "system.h"
|
1998-07-31 06:09:42 +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
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availablePackage {
|
1996-06-10 10:36:07 +08:00
|
|
|
Header h;
|
|
|
|
char ** provides;
|
1997-05-01 03:28:09 +08:00
|
|
|
char ** files;
|
1996-06-10 10:36:07 +08:00
|
|
|
char * name, * version, * release;
|
1998-11-07 06:12:01 +08:00
|
|
|
int epoch, hasEpoch, providesCount, filesCount;
|
1996-07-18 10:25:13 +08:00
|
|
|
void * key;
|
1996-06-10 10:36:07 +08:00
|
|
|
} ;
|
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
enum indexEntryType { IET_NAME, IET_PROVIDES, IET_FILE };
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availableIndexEntry {
|
|
|
|
struct availablePackage * package;
|
1996-07-11 00:29:24 +08:00
|
|
|
char * entry;
|
1997-05-01 03:28:09 +08:00
|
|
|
enum indexEntryType type;
|
1996-07-11 00:29:24 +08:00
|
|
|
} ;
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availableIndex {
|
1997-05-01 03:28:09 +08:00
|
|
|
struct availableIndexEntry * index ;
|
1996-07-18 04:02:28 +08:00
|
|
|
int size;
|
|
|
|
} ;
|
|
|
|
|
|
|
|
struct availableList {
|
|
|
|
struct availablePackage * list;
|
|
|
|
struct availableIndex index;
|
|
|
|
int size, alloced;
|
|
|
|
};
|
|
|
|
|
1996-06-10 10:36:07 +08:00
|
|
|
struct rpmDependencyCheck {
|
|
|
|
rpmdb db; /* may be NULL */
|
|
|
|
int * removedPackages;
|
|
|
|
int numRemovedPackages, allocedRemovedPackages;
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availableList addedPackages, availablePackages;
|
1996-06-10 10:36:07 +08:00
|
|
|
};
|
|
|
|
|
1996-06-11 01:42:57 +08:00
|
|
|
struct problemsSet {
|
|
|
|
struct rpmDependencyConflict * problems;
|
|
|
|
int num;
|
|
|
|
int alloced;
|
|
|
|
};
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
static void alMakeIndex(struct availableList * al);
|
|
|
|
static void alCreate(struct availableList * al);
|
|
|
|
static void alFreeIndex(struct availableList * al);
|
|
|
|
static void alFree(struct availableList * al);
|
1996-07-18 10:25:13 +08:00
|
|
|
static void alAddPackage(struct availableList * al, Header h, void * key);
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1996-06-10 10:36:07 +08:00
|
|
|
static int intcmp(const void * a, const void *b);
|
1996-07-18 04:02:28 +08:00
|
|
|
static int indexcmp(const void * a, const void *b);
|
1996-07-11 00:29:24 +08:00
|
|
|
static int unsatisfiedDepend(rpmDependencies rpmdep, char * reqName,
|
1996-07-18 10:25:13 +08:00
|
|
|
char * reqVersion, int reqFlags,
|
|
|
|
struct availablePackage ** suggestion);
|
1996-06-11 01:42:57 +08:00
|
|
|
static int checkDependentPackages(rpmDependencies rpmdep,
|
1997-05-01 03:28:09 +08:00
|
|
|
struct problemsSet * psp, char * key);
|
1996-07-11 00:29:24 +08:00
|
|
|
static int checkPackageDeps(rpmDependencies rpmdep, struct problemsSet * psp,
|
1996-06-11 01:42:57 +08:00
|
|
|
Header h, const char * requirement);
|
1996-07-11 00:29:24 +08:00
|
|
|
static int dbrecMatchesDepFlags(rpmDependencies rpmdep, int recOffset,
|
|
|
|
char * reqVersion, int reqFlags);
|
1996-07-18 10:25:13 +08:00
|
|
|
struct availablePackage * alSatisfiesDepend(struct availableList * al,
|
|
|
|
char * reqName, char * reqVersion,
|
|
|
|
int reqFlags);
|
1996-10-21 03:31:21 +08:00
|
|
|
static int checkDependentConflicts(rpmDependencies rpmdep,
|
|
|
|
struct problemsSet * psp, char * package);
|
|
|
|
static int checkPackageSet(rpmDependencies rpmdep, struct problemsSet * psp,
|
1996-11-19 02:02:36 +08:00
|
|
|
char * package, dbiIndexSet * matches);
|
1997-07-02 00:24:08 +08:00
|
|
|
static int addOrderedPack(rpmDependencies rpmdep,
|
|
|
|
struct availablePackage * package,
|
|
|
|
void ** ordering, int * orderNumPtr,
|
1997-10-04 00:08:45 +08:00
|
|
|
int * selected, int selectionClass,
|
1997-07-18 23:03:35 +08:00
|
|
|
int satisfyDepends, char ** errorStack);
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
static void alCreate(struct availableList * al) {
|
|
|
|
al->list = malloc(sizeof(*al->list) * 5);
|
|
|
|
al->alloced = 5;
|
|
|
|
al->size = 0;
|
|
|
|
|
|
|
|
al->index.index = NULL;
|
|
|
|
alFreeIndex(al);
|
1998-03-05 00:52:59 +08:00
|
|
|
}
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
static void alFreeIndex(struct availableList * al) {
|
|
|
|
if (al->index.size) {
|
|
|
|
free(al->index.index);
|
|
|
|
al->index.index = NULL;
|
|
|
|
al->index.size = 0;
|
|
|
|
}
|
|
|
|
}
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
static void alFree(struct availableList * al) {
|
1997-05-01 03:28:09 +08:00
|
|
|
int i;
|
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);
|
1997-05-01 03:28:09 +08:00
|
|
|
if (al->list[i].files)
|
|
|
|
free(al->list[i].files);
|
|
|
|
}
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1996-07-27 03:24:02 +08:00
|
|
|
if (al->alloced) free(al->list);
|
1996-07-18 04:02:28 +08:00
|
|
|
alFreeIndex(al);
|
|
|
|
}
|
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
static void alAddPackage(struct availableList * al, Header h, void * key) {
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availablePackage * p;
|
|
|
|
|
|
|
|
if (al->size == al->alloced) {
|
|
|
|
al->alloced += 5;
|
|
|
|
al->list = realloc(al->list, sizeof(*al->list) * al->alloced);
|
|
|
|
}
|
|
|
|
|
|
|
|
p = al->list + al->size++;
|
|
|
|
p->h = h;
|
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
headerGetEntry(p->h, RPMTAG_NAME, NULL, (void **) &p->name, NULL);
|
|
|
|
headerGetEntry(p->h, RPMTAG_VERSION, NULL, (void **) &p->version, NULL);
|
|
|
|
headerGetEntry(p->h, RPMTAG_RELEASE, NULL, (void **) &p->release, NULL);
|
1998-11-07 06:12:01 +08:00
|
|
|
p->hasEpoch = headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &p->epoch,
|
1997-05-01 03:28:09 +08:00
|
|
|
NULL);
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_PROVIDES, NULL, (void **) &p->provides,
|
1996-07-18 04:02:28 +08:00
|
|
|
&p->providesCount)) {
|
|
|
|
p->providesCount = 0;
|
|
|
|
p->provides = NULL;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
p->key = key;
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
alFreeIndex(al);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void alMakeIndex(struct availableList * al) {
|
|
|
|
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) {
|
|
|
|
ai->index = malloc(sizeof(*ai->index) * ai->size);
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
struct availablePackage * alSatisfiesDepend(struct availableList * al,
|
|
|
|
char * reqName, char * reqVersion,
|
|
|
|
int reqFlags) {
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availableIndexEntry needle, * match;
|
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
if (!al->index.size) return NULL;
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
needle.entry = reqName;
|
|
|
|
match = bsearch(&needle, al->index.index, al->index.size,
|
1998-03-05 00:52:59 +08:00
|
|
|
sizeof(*al->index.index), indexcmp);
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
if (!match) return NULL;
|
1997-05-01 03:28:09 +08:00
|
|
|
if (match->type != IET_NAME) return match->package;
|
1996-07-18 04:02:28 +08:00
|
|
|
|
|
|
|
if (headerMatchesDepFlags(match->package->h, reqVersion, reqFlags))
|
1996-07-18 10:25:13 +08:00
|
|
|
return match->package;
|
1996-07-18 04:02:28 +08:00
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
return NULL;
|
1996-07-18 04:02:28 +08:00
|
|
|
}
|
|
|
|
|
1998-03-05 00:52:59 +08:00
|
|
|
static int indexcmp(const void * a, const void *b) {
|
1996-07-18 04:02:28 +08:00
|
|
|
const struct availableIndexEntry * aptr = a;
|
|
|
|
const struct availableIndexEntry * bptr = b;
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1996-07-11 00:29:24 +08:00
|
|
|
return strcmp(aptr->entry, bptr->entry);
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
|
|
|
|
int intcmp(const void * a, const void *b) {
|
|
|
|
const int * aptr = a;
|
|
|
|
const int * bptr = b;
|
|
|
|
|
|
|
|
if (*aptr < *bptr)
|
|
|
|
return -1;
|
|
|
|
else if (*aptr == *bptr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmDependencies rpmdepDependencies(rpmdb db) {
|
|
|
|
rpmDependencies rpmdep;
|
|
|
|
|
|
|
|
rpmdep = malloc(sizeof(*rpmdep));
|
|
|
|
rpmdep->db = db;
|
|
|
|
rpmdep->numRemovedPackages = 0;
|
|
|
|
rpmdep->allocedRemovedPackages = 5;
|
|
|
|
rpmdep->removedPackages = malloc(sizeof(int) *
|
|
|
|
rpmdep->allocedRemovedPackages);
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
alCreate(&rpmdep->addedPackages);
|
|
|
|
alCreate(&rpmdep->availablePackages);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
|
|
|
return rpmdep;
|
|
|
|
}
|
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
void rpmdepUpgradePackage(rpmDependencies rpmdep, Header h, void * key) {
|
1996-07-11 00:29:24 +08:00
|
|
|
/* this is an install followed by uninstalls */
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1996-07-11 00:29:24 +08:00
|
|
|
char * name;
|
1997-09-17 07:16:21 +08:00
|
|
|
int count, i, j;
|
|
|
|
char ** obsoletes;
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
alAddPackage(&rpmdep->addedPackages, h, key);
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1998-11-17 05:40:28 +08:00
|
|
|
if (rpmdep->db == NULL) return;
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1997-09-17 07:16:21 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, &count);
|
1996-07-11 00:29:24 +08:00
|
|
|
|
|
|
|
if (!rpmdbFindPackage(rpmdep->db, name, &matches)) {
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
|
|
|
rpmdepRemovePackage(rpmdep, matches.recs[i].recOffset);
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
1996-07-12 02:12:40 +08:00
|
|
|
}
|
1997-09-17 07:16:21 +08:00
|
|
|
|
|
|
|
if (headerGetEntry(h, RPMTAG_OBSOLETES, NULL, (void *) &obsoletes,
|
|
|
|
&count)) {
|
|
|
|
for (j = 0; j < count; j++) {
|
|
|
|
if (!rpmdbFindPackage(rpmdep->db, obsoletes[j], &matches)) {
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
|
|
|
rpmdepRemovePackage(rpmdep, matches.recs[i].recOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(obsoletes);
|
|
|
|
}
|
1996-07-11 00:29:24 +08:00
|
|
|
}
|
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
void rpmdepAddPackage(rpmDependencies rpmdep, Header h, void * key) {
|
|
|
|
alAddPackage(&rpmdep->addedPackages, h, key);
|
1996-07-18 10:25:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void rpmdepAvailablePackage(rpmDependencies rpmdep, Header h, void * key) {
|
|
|
|
alAddPackage(&rpmdep->availablePackages, h, key);
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void rpmdepRemovePackage(rpmDependencies rpmdep, int dboffset) {
|
|
|
|
if (rpmdep->numRemovedPackages == rpmdep->allocedRemovedPackages) {
|
|
|
|
rpmdep->allocedRemovedPackages += 5;
|
|
|
|
rpmdep->removedPackages = realloc(rpmdep->removedPackages,
|
|
|
|
sizeof(int *) * rpmdep->allocedRemovedPackages);
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmdep->removedPackages[rpmdep->numRemovedPackages++] = dboffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpmdepDone(rpmDependencies rpmdep) {
|
1996-08-07 23:47:04 +08:00
|
|
|
alFree(&rpmdep->addedPackages);
|
|
|
|
alFree(&rpmdep->availablePackages);
|
|
|
|
free(rpmdep->removedPackages);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1996-08-07 23:47:04 +08:00
|
|
|
free(rpmdep);
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpmdepFreeConflicts(struct rpmDependencyConflict * conflicts, int
|
|
|
|
numConflicts) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < numConflicts; i++) {
|
1998-02-25 03:43:14 +08:00
|
|
|
headerFree(conflicts[i].byHeader);
|
1996-08-07 23:47:04 +08:00
|
|
|
free(conflicts[i].byName);
|
|
|
|
free(conflicts[i].byVersion);
|
|
|
|
free(conflicts[i].byRelease);
|
|
|
|
free(conflicts[i].needsName);
|
|
|
|
free(conflicts[i].needsVersion);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(conflicts);
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int rpmdepCheck(rpmDependencies rpmdep,
|
|
|
|
struct rpmDependencyConflict ** conflicts, int * numConflicts) {
|
1996-07-18 04:02:28 +08:00
|
|
|
struct availablePackage * p;
|
|
|
|
int i, j;
|
1997-05-01 03:28:09 +08:00
|
|
|
char ** provides, ** files;
|
|
|
|
int providesCount, fileCount;
|
1996-06-11 01:42:57 +08:00
|
|
|
int type;
|
|
|
|
char * name;
|
|
|
|
Header h;
|
|
|
|
struct problemsSet ps;
|
|
|
|
|
|
|
|
ps.alloced = 5;
|
|
|
|
ps.num = 0;
|
|
|
|
ps.problems = malloc(sizeof(struct rpmDependencyConflict) * ps.alloced);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
|
|
|
*conflicts = NULL;
|
|
|
|
*numConflicts = 0;
|
|
|
|
|
|
|
|
qsort(rpmdep->removedPackages, rpmdep->numRemovedPackages,
|
|
|
|
sizeof(int), intcmp);
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
alMakeIndex(&rpmdep->addedPackages);
|
|
|
|
alMakeIndex(&rpmdep->availablePackages);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
|
|
|
/* look at all of the added packages and make sure their dependencies
|
|
|
|
are satisfied */
|
1996-07-18 04:02:28 +08:00
|
|
|
p = rpmdep->addedPackages.list;
|
|
|
|
for (i = 0; i < rpmdep->addedPackages.size; i++, p++) {
|
1996-07-11 00:29:24 +08:00
|
|
|
if (checkPackageDeps(rpmdep, &ps, p->h, NULL)) {
|
1996-06-11 01:42:57 +08:00
|
|
|
free(ps.problems);
|
|
|
|
return 1;
|
|
|
|
}
|
1996-10-21 03:31:21 +08:00
|
|
|
if (checkDependentConflicts(rpmdep, &ps, p->name)) {
|
|
|
|
free(ps.problems);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (headerGetEntry(p->h, RPMTAG_PROVIDES, &type, (void **) &provides,
|
1996-10-21 03:31:21 +08:00
|
|
|
&providesCount)) {
|
|
|
|
for (j = 0; j < providesCount; j++) {
|
|
|
|
if (checkDependentConflicts(rpmdep, &ps, provides[j])) {
|
|
|
|
free(ps.problems);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* now look at the removed packages and make sure they aren't critical */
|
|
|
|
for (i = 0; i < rpmdep->numRemovedPackages; i++) {
|
|
|
|
h = rpmdbGetRecord(rpmdep->db, rpmdep->removedPackages[i]);
|
1998-11-17 05:40:28 +08:00
|
|
|
if (h == NULL) {
|
1997-05-01 03:28:09 +08:00
|
|
|
rpmError(RPMERR_DBCORRUPT,
|
1998-01-10 03:10:54 +08:00
|
|
|
_("cannot read header at %d for dependency check"),
|
|
|
|
rpmdep->removedPackages[i]);
|
1996-06-11 01:42:57 +08:00
|
|
|
free(ps.problems);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &providesCount);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
|
|
|
if (checkDependentPackages(rpmdep, &ps, name)) {
|
|
|
|
free(ps.problems);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-06-11 01:42:57 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_PROVIDES, NULL, (void **) &provides,
|
1996-07-27 04:11:08 +08:00
|
|
|
&providesCount)) {
|
1997-05-01 03:28:09 +08:00
|
|
|
for (j = 0; j < providesCount; j++) {
|
|
|
|
if (checkDependentPackages(rpmdep, &ps, provides[j])) {
|
|
|
|
free(provides);
|
|
|
|
free(ps.problems);
|
|
|
|
headerFree(h);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(provides);
|
1996-07-27 04:11:08 +08:00
|
|
|
}
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &files,
|
|
|
|
&fileCount)) {
|
|
|
|
for (j = 0; j < fileCount; j++) {
|
|
|
|
if (checkDependentPackages(rpmdep, &ps, files[j])) {
|
|
|
|
free(files);
|
|
|
|
free(ps.problems);
|
|
|
|
headerFree(h);
|
|
|
|
return 1;
|
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
1997-05-01 03:28:09 +08:00
|
|
|
|
|
|
|
free(files);
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
1996-07-27 04:11:08 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
1996-06-11 01:42:57 +08:00
|
|
|
if (!ps.num)
|
|
|
|
free(ps.problems);
|
1996-06-10 10:36:07 +08:00
|
|
|
else {
|
1996-06-11 01:42:57 +08:00
|
|
|
*conflicts = ps.problems;
|
|
|
|
*numConflicts = ps.num;
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 2 == error */
|
|
|
|
/* 1 == dependency not satisfied */
|
1996-07-11 00:29:24 +08:00
|
|
|
static int unsatisfiedDepend(rpmDependencies rpmdep, char * reqName,
|
1996-07-18 10:25:13 +08:00
|
|
|
char * reqVersion, int reqFlags,
|
|
|
|
struct availablePackage ** suggestion) {
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1996-06-10 10:36:07 +08:00
|
|
|
int i;
|
1997-07-24 02:32:15 +08:00
|
|
|
char * rcProvidesString;
|
|
|
|
char * start;
|
|
|
|
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("dependencies: looking for %s\n"), reqName);
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
if (suggestion) *suggestion = NULL;
|
|
|
|
|
1997-07-24 02:32:15 +08:00
|
|
|
if (!(reqFlags & RPMSENSE_SENSEMASK) &&
|
|
|
|
(rcProvidesString = rpmGetVar(RPMVAR_PROVIDES))) {
|
|
|
|
i = strlen(reqName);
|
|
|
|
while ((start = strstr(rcProvidesString, reqName))) {
|
|
|
|
if (isspace(start[i]) || !start[i])
|
|
|
|
return 0;
|
1998-07-01 02:52:54 +08:00
|
|
|
rcProvidesString = start + 1;
|
1997-07-24 02:32:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
if (alSatisfiesDepend(&rpmdep->addedPackages, reqName, reqVersion,
|
|
|
|
reqFlags))
|
|
|
|
return 0;
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1998-11-17 05:40:28 +08:00
|
|
|
if (rpmdep->db != NULL) {
|
1997-05-01 03:28:09 +08:00
|
|
|
if (*reqName == '/') {
|
|
|
|
/* reqFlags better be 0! */
|
|
|
|
if (!rpmdbFindByFile(rpmdep->db, reqName, &matches)) {
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
|
|
|
if (bsearch(&matches.recs[i].recOffset,
|
|
|
|
rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages,
|
1997-05-08 02:24:05 +08:00
|
|
|
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);
|
|
|
|
if (i < matches.count) return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!reqFlags && !rpmdbFindByProvides(rpmdep->db, reqName,
|
|
|
|
&matches)) {
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
|
|
|
if (bsearch(&matches.recs[i].recOffset,
|
|
|
|
rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages,
|
1997-05-08 02:24:05 +08:00
|
|
|
sizeof(int), intcmp))
|
1997-05-01 03:28:09 +08:00
|
|
|
continue;
|
1996-07-18 10:25:13 +08:00
|
|
|
break;
|
|
|
|
}
|
1997-05-01 03:28:09 +08:00
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
if (i < matches.count) return 0;
|
1996-07-11 00:29:24 +08:00
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
if (!rpmdbFindPackage(rpmdep->db, reqName, &matches)) {
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
|
|
|
if (bsearch(&matches.recs[i].recOffset,
|
|
|
|
rpmdep->removedPackages,
|
|
|
|
rpmdep->numRemovedPackages,
|
1997-05-08 02:24:05 +08:00
|
|
|
sizeof(int), intcmp))
|
1997-05-01 03:28:09 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (dbrecMatchesDepFlags(rpmdep, matches.recs[i].recOffset,
|
|
|
|
reqVersion, reqFlags)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dbiFreeIndexRecord(matches);
|
|
|
|
if (i < matches.count) return 0;
|
|
|
|
}
|
1996-07-18 10:25:13 +08:00
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
if (suggestion)
|
|
|
|
*suggestion = alSatisfiesDepend(&rpmdep->availablePackages, reqName,
|
|
|
|
reqVersion, reqFlags);
|
1996-07-18 10:25:13 +08:00
|
|
|
|
1996-06-10 10:36:07 +08:00
|
|
|
return 1;
|
|
|
|
}
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
static int checkPackageSet(rpmDependencies rpmdep, struct problemsSet * psp,
|
1996-11-19 02:02:36 +08:00
|
|
|
char * package, dbiIndexSet * matches) {
|
1996-06-11 01:42:57 +08:00
|
|
|
int i;
|
1996-10-21 03:31:21 +08:00
|
|
|
Header h;
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
for (i = 0; i < matches->count; i++) {
|
|
|
|
if (bsearch(&matches->recs[i].recOffset, rpmdep->removedPackages,
|
1997-05-08 02:24:05 +08:00
|
|
|
rpmdep->numRemovedPackages, sizeof(int), intcmp))
|
1996-06-11 01:42:57 +08:00
|
|
|
continue;
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
h = rpmdbGetRecord(rpmdep->db, matches->recs[i].recOffset);
|
1998-11-17 05:40:28 +08:00
|
|
|
if (h == NULL) {
|
1998-01-10 03:10:54 +08:00
|
|
|
rpmError(RPMERR_DBCORRUPT,
|
|
|
|
_("cannot read header at %d for dependency check"),
|
|
|
|
rpmdep->removedPackages[i]);
|
1996-06-11 01:42:57 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
if (checkPackageDeps(rpmdep, psp, h, package)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-06-11 01:42:57 +08:00
|
|
|
return 1;
|
1996-07-27 03:52:05 +08:00
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
static int checkDependentPackages(rpmDependencies rpmdep,
|
1997-05-01 03:28:09 +08:00
|
|
|
struct problemsSet * psp, char * key) {
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1996-10-21 03:31:21 +08:00
|
|
|
int rc;
|
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
if (rpmdbFindByRequiredBy(rpmdep->db, key, &matches)) {
|
1996-10-21 03:31:21 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-05-01 03:28:09 +08:00
|
|
|
rc = checkPackageSet(rpmdep, psp, key, &matches);
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiFreeIndexRecord(matches);
|
1996-10-21 03:31:21 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int checkDependentConflicts(rpmDependencies rpmdep,
|
|
|
|
struct problemsSet * psp, char * package) {
|
1996-11-19 02:02:36 +08:00
|
|
|
dbiIndexSet matches;
|
1996-10-21 03:31:21 +08:00
|
|
|
int rc;
|
|
|
|
|
1998-11-17 05:40:28 +08:00
|
|
|
if (rpmdep->db == NULL) return 0;
|
1996-12-06 06:13:46 +08:00
|
|
|
|
|
|
|
if (rpmdbFindByConflicts(rpmdep->db, package, &matches)) {
|
1996-10-21 03:31:21 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = checkPackageSet(rpmdep, psp, package, &matches);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
1996-07-11 00:29:24 +08:00
|
|
|
static int checkPackageDeps(rpmDependencies rpmdep, struct problemsSet * psp,
|
1996-06-11 01:42:57 +08:00
|
|
|
Header h, const char * requirement) {
|
1996-07-11 00:29:24 +08:00
|
|
|
char ** requires, ** requiresVersion;
|
1996-06-11 01:42:57 +08:00
|
|
|
char * name, * version, * release;
|
1996-10-21 03:31:21 +08:00
|
|
|
char ** conflicts, ** conflictsVersion;
|
|
|
|
int requiresCount = 0, conflictsCount;
|
1996-06-11 01:42:57 +08:00
|
|
|
int type, count;
|
|
|
|
int i, rc;
|
1996-10-21 03:31:21 +08:00
|
|
|
int ourrc = 0;
|
|
|
|
int * requireFlags, * conflictsFlags;
|
1996-07-18 10:25:13 +08:00
|
|
|
struct availablePackage * suggestion;
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_REQUIRENAME, &type, (void **) &requires,
|
1996-10-21 03:31:21 +08:00
|
|
|
&requiresCount)) {
|
|
|
|
requiresCount = 0;
|
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_REQUIREFLAGS, &type, (void **) &requireFlags,
|
1996-10-21 03:31:21 +08:00
|
|
|
&requiresCount);
|
1997-05-01 03:28:09 +08:00
|
|
|
headerGetEntry(h, RPMTAG_REQUIREVERSION, &type,
|
|
|
|
(void **) &requiresVersion,
|
1996-10-21 03:31:21 +08:00
|
|
|
&requiresCount);
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_CONFLICTNAME, &type, (void **) &conflicts,
|
1996-10-21 03:31:21 +08:00
|
|
|
&conflictsCount)) {
|
|
|
|
conflictsCount = 0;
|
|
|
|
} else {
|
1997-05-01 03:28:09 +08:00
|
|
|
headerGetEntry(h, RPMTAG_CONFLICTFLAGS, &type,
|
|
|
|
(void **) &conflictsFlags, &conflictsCount);
|
|
|
|
headerGetEntry(h, RPMTAG_CONFLICTVERSION, &type,
|
|
|
|
(void **) &conflictsVersion,
|
1996-10-21 03:31:21 +08:00
|
|
|
&conflictsCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < requiresCount && !ourrc; i++) {
|
1996-06-11 01:42:57 +08:00
|
|
|
if (requirement && strcmp(requirement, requires[i])) continue;
|
|
|
|
|
1996-07-18 04:02:28 +08:00
|
|
|
rc = unsatisfiedDepend(rpmdep, requires[i], requiresVersion[i],
|
1996-07-18 10:25:13 +08:00
|
|
|
requireFlags[i], &suggestion);
|
1996-06-11 01:42:57 +08:00
|
|
|
if (rc == 1) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
|
1997-05-01 03:28:09 +08:00
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version,
|
|
|
|
&count);
|
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release,
|
|
|
|
&count);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("package %s require not satisfied: %s\n"),
|
1996-06-11 01:42:57 +08:00
|
|
|
name, requires[i]);
|
|
|
|
|
|
|
|
if (psp->num == psp->alloced) {
|
|
|
|
psp->alloced += 5;
|
|
|
|
psp->problems = realloc(psp->problems, sizeof(*psp->problems) *
|
|
|
|
psp->alloced);
|
|
|
|
}
|
1998-02-25 03:43:14 +08:00
|
|
|
psp->problems[psp->num].byHeader = headerCopy(h);
|
1996-08-07 23:47:04 +08:00
|
|
|
psp->problems[psp->num].byName = strdup(name);
|
|
|
|
psp->problems[psp->num].byVersion = strdup(version);
|
|
|
|
psp->problems[psp->num].byRelease = strdup(release);
|
|
|
|
psp->problems[psp->num].needsName = strdup(requires[i]);
|
|
|
|
psp->problems[psp->num].needsVersion = strdup(requiresVersion[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++;
|
1996-10-21 03:31:21 +08:00
|
|
|
} else if (rc == 2) {
|
1996-06-11 01:42:57 +08:00
|
|
|
/* something went wrong! */
|
1996-10-21 03:31:21 +08:00
|
|
|
ourrc = 1;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
for (i = 0; i < conflictsCount && !ourrc; i++) {
|
|
|
|
if (requirement && strcmp(requirement, conflicts[i])) continue;
|
1996-06-11 01:42:57 +08:00
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
rc = unsatisfiedDepend(rpmdep, conflicts[i], conflictsVersion[i],
|
|
|
|
conflictsFlags[i], NULL);
|
|
|
|
|
|
|
|
/* 1 == unsatisfied, 0 == satsisfied */
|
|
|
|
if (rc == 0) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
|
1997-05-01 03:28:09 +08:00
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version,
|
|
|
|
&count);
|
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release,
|
|
|
|
&count);
|
1996-10-21 03:31:21 +08:00
|
|
|
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
|
1996-10-21 03:31:21 +08:00
|
|
|
name, conflicts[i]);
|
|
|
|
|
|
|
|
if (psp->num == psp->alloced) {
|
|
|
|
psp->alloced += 5;
|
|
|
|
psp->problems = realloc(psp->problems, sizeof(*psp->problems) *
|
|
|
|
psp->alloced);
|
|
|
|
}
|
1998-02-25 03:43:14 +08:00
|
|
|
psp->problems[psp->num].byHeader = headerCopy(h);
|
1996-10-21 03:31:21 +08:00
|
|
|
psp->problems[psp->num].byName = strdup(name);
|
|
|
|
psp->problems[psp->num].byVersion = strdup(version);
|
|
|
|
psp->problems[psp->num].byRelease = strdup(release);
|
|
|
|
psp->problems[psp->num].needsName = strdup(conflicts[i]);
|
|
|
|
psp->problems[psp->num].needsVersion = strdup(conflictsVersion[i]);
|
|
|
|
psp->problems[psp->num].needsFlags = conflictsFlags[i];
|
|
|
|
psp->problems[psp->num].sense = RPMDEP_SENSE_CONFLICTS;
|
|
|
|
psp->problems[psp->num].suggestedPackage = NULL;
|
|
|
|
|
|
|
|
psp->num++;
|
|
|
|
} else if (rc == 2) {
|
|
|
|
/* something went wrong! */
|
|
|
|
ourrc = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (conflictsCount) {
|
|
|
|
free(conflictsVersion);
|
|
|
|
free(conflicts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (requiresCount) {
|
|
|
|
free(requiresVersion);
|
|
|
|
free(requires);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ourrc;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
1998-03-28 00:46:39 +08:00
|
|
|
int headerMatchesDepFlags(Header h, char * reqInfo, int reqFlags) {
|
1996-08-21 00:29:19 +08:00
|
|
|
char * name, * version, * release, * chptr;
|
|
|
|
char * reqVersion = reqInfo;
|
|
|
|
char * reqRelease = NULL;
|
1996-07-11 00:29:24 +08:00
|
|
|
int type, count;
|
1998-11-07 06:12:01 +08:00
|
|
|
int_32 * epoch;
|
1996-07-11 00:29:24 +08:00
|
|
|
char buf[20];
|
|
|
|
int result = 0;
|
|
|
|
int sense;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_NAME, &type, (void *) &name, &count);
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1998-05-11 02:37:35 +08:00
|
|
|
if (!(reqFlags & RPMSENSE_SENSEMASK) || !reqInfo || !strlen(reqInfo)) {
|
1996-07-11 00:29:24 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if (reqFlags & RPMSENSE_SERIAL) {
|
1998-11-07 06:12:01 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_EPOCH, &type, (void *) &epoch, &count)) {
|
1996-07-11 00:29:24 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1998-11-07 06:12:01 +08:00
|
|
|
sprintf(buf, "%d", *epoch);
|
1996-07-11 00:29:24 +08:00
|
|
|
version = buf;
|
1996-08-21 00:29:19 +08:00
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_VERSION, &type, (void *) &version, &count);
|
1996-08-21 00:29:19 +08:00
|
|
|
chptr = strrchr(reqInfo, '-');
|
|
|
|
if (chptr) {
|
|
|
|
reqVersion = alloca(strlen(reqInfo) + 1);
|
|
|
|
strcpy(reqVersion, reqInfo);
|
|
|
|
reqVersion[chptr - reqInfo] = '\0';
|
|
|
|
reqRelease = reqVersion + (chptr - reqInfo) + 1;
|
|
|
|
if (*reqRelease)
|
1996-11-19 02:02:36 +08:00
|
|
|
headerGetEntry(h, RPMTAG_RELEASE, &type, (void *) &release, &count);
|
1996-08-21 00:29:19 +08:00
|
|
|
else
|
|
|
|
reqRelease = NULL;
|
|
|
|
}
|
|
|
|
}
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1997-01-16 00:23:50 +08:00
|
|
|
sense = rpmvercmp(version, reqVersion);
|
1996-08-21 00:29:19 +08:00
|
|
|
if (!sense && reqRelease) {
|
|
|
|
/* if a release number is given, use it to break ties */
|
1997-01-16 00:23:50 +08:00
|
|
|
sense = rpmvercmp(release, reqRelease);
|
1996-08-21 00:29:19 +08:00
|
|
|
}
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
if ((reqFlags & RPMSENSE_LESS) && sense < 0) {
|
1996-07-11 00:29:24 +08:00
|
|
|
result = 1;
|
1996-11-19 02:02:36 +08:00
|
|
|
} else if ((reqFlags & RPMSENSE_EQUAL) && sense == 0) {
|
1996-07-11 00:29:24 +08:00
|
|
|
result = 1;
|
1996-11-19 02:02:36 +08:00
|
|
|
} else if ((reqFlags & RPMSENSE_GREATER) && sense > 0) {
|
1996-07-11 00:29:24 +08:00
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dbrecMatchesDepFlags(rpmDependencies rpmdep, int recOffset,
|
|
|
|
char * reqVersion, int reqFlags) {
|
|
|
|
Header h;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
h = rpmdbGetRecord(rpmdep->db, recOffset);
|
1998-11-17 05:40:28 +08:00
|
|
|
if (h == NULL) {
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("dbrecMatchesDepFlags() failed to read header"));
|
1996-07-11 00:29:24 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = headerMatchesDepFlags(h, reqVersion, reqFlags);
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(h);
|
1996-07-11 00:29:24 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
1997-07-02 00:24:08 +08:00
|
|
|
|
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 */
|
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
static int addOrderedPack(rpmDependencies rpmdep,
|
|
|
|
struct availablePackage * package,
|
|
|
|
void ** ordering, int * orderNumPtr,
|
1997-10-04 00:08:45 +08:00
|
|
|
int * selected, int selectionClass,
|
1997-07-18 23:03:35 +08:00
|
|
|
int satisfyDepends, char ** errorStack) {
|
1997-07-02 00:24:08 +08:00
|
|
|
char ** requires, ** requiresVersion;
|
|
|
|
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;
|
1997-10-04 00:08:45 +08:00
|
|
|
int i, rc;
|
1997-07-02 00:24:08 +08:00
|
|
|
struct availablePackage * match;
|
1997-07-18 23:03:35 +08:00
|
|
|
char * errorString;
|
|
|
|
char ** stack;
|
|
|
|
|
|
|
|
*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';
|
|
|
|
|
|
|
|
while ((++stack) < errorStack) {
|
|
|
|
strcat(errorString, *stack);
|
|
|
|
strcat(errorString, " ");
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
if (headerGetEntry(package->h, RPMTAG_REQUIRENAME, NULL,
|
|
|
|
(void **) &requires, &requiresCount)) {
|
|
|
|
headerGetEntry(package->h, RPMTAG_REQUIREFLAGS, NULL,
|
|
|
|
(void **) &requireFlags, NULL);
|
|
|
|
headerGetEntry(package->h, RPMTAG_REQUIREVERSION, NULL,
|
|
|
|
(void **) &requiresVersion, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < requiresCount; i++) {
|
|
|
|
if (satisfyDepends || (requireFlags[i] & RPMSENSE_PREREQ)) {
|
|
|
|
match = alSatisfiesDepend(&rpmdep->addedPackages,
|
|
|
|
requires[i], requiresVersion[i],
|
|
|
|
requireFlags[i]);
|
|
|
|
/* broken dependencies don't concern us */
|
|
|
|
if (!match) continue;
|
1997-07-09 02:41:10 +08:00
|
|
|
|
|
|
|
/* let this package satisfy its own predependencies */
|
|
|
|
if (match == package) continue;
|
|
|
|
|
1997-07-09 02:48:36 +08:00
|
|
|
/* the package has already been selected */
|
1997-10-04 00:08:45 +08:00
|
|
|
matchNum = match - rpmdep->addedPackages.list;
|
|
|
|
if (selected[matchNum] == -1 ||
|
|
|
|
selected[matchNum] == selectionClass)
|
1997-07-09 02:48:36 +08:00
|
|
|
continue;
|
1997-10-04 00:08:45 +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);
|
1998-04-17 00:23:19 +08:00
|
|
|
|
|
|
|
/* FIXME: I suspect we should free things here */
|
|
|
|
if (rc) return 1;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
|
|
|
}
|
1998-05-06 07:12:17 +08:00
|
|
|
|
|
|
|
free(requires);
|
|
|
|
free(requiresVersion);
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* whew -- add this package */
|
|
|
|
ordering[(*orderNumPtr)++] = package->key;
|
1997-10-04 00:08:45 +08:00
|
|
|
selected[packageNum] = -1;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmdepOrder(rpmDependencies rpmdep, void *** keysListPtr) {
|
|
|
|
int i;
|
1997-10-04 00:08:45 +08:00
|
|
|
int * selected;
|
1997-07-02 00:24:08 +08:00
|
|
|
void ** order;
|
|
|
|
int orderNum;
|
1997-07-18 23:03:35 +08:00
|
|
|
char ** errorStack;
|
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;
|
|
|
|
|
1997-07-02 00:24:08 +08:00
|
|
|
order = malloc(sizeof(*order) * (rpmdep->addedPackages.size + 1));
|
|
|
|
orderNum = 0;
|
|
|
|
|
|
|
|
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,
|
1997-10-04 00:08:45 +08:00
|
|
|
order, &orderNum, selected, 1, 0, errorStack)) {
|
1997-07-02 00:24:08 +08:00
|
|
|
free(order);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
order[orderNum] = NULL;
|
|
|
|
*keysListPtr = order;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|