00001
00005 int _depends_debug = 0;
00006
00007 #include "system.h"
00008
00009 #include <rpmlib.h>
00010
00011 #include "depends.h"
00012 #include "rpmdb.h"
00013 #include "misc.h"
00014 #include "debug.h"
00015
00016
00017
00018
00019
00020
00021
00027 static void * _free( const void * this) {
00028 if (this) free((void *)this);
00029 return NULL;
00030 }
00031
00032 int headerNVR(Header h, const char **np, const char **vp, const char **rp)
00033 {
00034 int type, count;
00035 if (np) {
00036 if (!(headerGetEntry(h, RPMTAG_NAME, &type, (void **) np, &count)
00037 && type == RPM_STRING_TYPE && count == 1))
00038 *np = NULL;
00039 }
00040 if (vp) {
00041 if (!(headerGetEntry(h, RPMTAG_VERSION, &type, (void **) vp, &count)
00042 && type == RPM_STRING_TYPE && count == 1))
00043 *vp = NULL;
00044 }
00045 if (rp) {
00046 if (!(headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) rp, &count)
00047 && type == RPM_STRING_TYPE && count == 1))
00048 *rp = NULL;
00049 }
00050 return 0;
00051 }
00052
00061 static char *printDepend(const char * depend, const char * key,
00062 const char * keyEVR, int keyFlags)
00063 {
00064 char *tbuf, *t;
00065 size_t nb;
00066
00067 nb = 0;
00068 if (depend) nb += strlen(depend) + 1;
00069 if (key) nb += strlen(key);
00070 if (keyFlags & RPMSENSE_SENSEMASK) {
00071 if (nb) nb++;
00072 if (keyFlags & RPMSENSE_LESS) nb++;
00073 if (keyFlags & RPMSENSE_GREATER) nb++;
00074 if (keyFlags & RPMSENSE_EQUAL) nb++;
00075 }
00076 if (keyEVR && *keyEVR) {
00077 if (nb) nb++;
00078 nb += strlen(keyEVR);
00079 }
00080
00081 t = tbuf = xmalloc(nb + 1);
00082 if (depend) {
00083 while(*depend) *t++ = *depend++;
00084 *t++ = ' ';
00085 }
00086 if (key)
00087 while(*key) *t++ = *key++;
00088 if (keyFlags & RPMSENSE_SENSEMASK) {
00089 if (t != tbuf) *t++ = ' ';
00090 if (keyFlags & RPMSENSE_LESS) *t++ = '<';
00091 if (keyFlags & RPMSENSE_GREATER) *t++ = '>';
00092 if (keyFlags & RPMSENSE_EQUAL) *t++ = '=';
00093 }
00094 if (keyEVR && *keyEVR) {
00095 if (t != tbuf) *t++ = ' ';
00096 while(*keyEVR) *t++ = *keyEVR++;
00097 }
00098 *t = '\0';
00099 return tbuf;
00100 }
00101
00102 #ifdef UNUSED
00103 static const char *buildEVR(int_32 *e, const char *v, const char *r)
00104 {
00105 const char *pEVR;
00106 char *p;
00107
00108 pEVR = p = xmalloc(21 + strlen(v) + 1 + strlen(r) + 1);
00109 *p = '\0';
00110 if (e) {
00111 sprintf(p, "%d:", *e);
00112 while (*p)
00113 p++;
00114 }
00115 (void) stpcpy( stpcpy( stpcpy(p, v) , "-") , r);
00116 return pEVR;
00117 }
00118 #endif
00119
00120 struct orderListIndex {
00121 int alIndex;
00122 int orIndex;
00123 };
00124
00129 static void alFreeIndex(struct availableList * al)
00130
00131 {
00132 if (al->index.size) {
00133 al->index.index = _free(al->index.index);
00134 al->index.size = 0;
00135 }
00136 }
00137
00142 static void alCreate(struct availableList * al)
00143
00144 {
00145 al->alloced = al->delta;
00146 al->size = 0;
00147 al->list = xcalloc(al->alloced, sizeof(*al->list));
00148
00149 al->index.index = NULL;
00150 al->index.size = 0;
00151
00152 al->numDirs = 0;
00153 al->dirs = NULL;
00154 }
00155
00160 static void alFree(struct availableList * al)
00161 {
00162 HFD_t hfd = headerFreeData;
00163 struct availablePackage * p;
00164 rpmRelocation * r;
00165 int i;
00166
00167 for (i = 0, p = al->list; i < al->size; i++, p++) {
00168
00169 { struct tsortInfo * tsi;
00170 while ((tsi = p->tsi.tsi_next) != NULL) {
00171 p->tsi.tsi_next = tsi->tsi_next;
00172 tsi->tsi_next = NULL;
00173 tsi = _free(tsi);
00174 }
00175 }
00176
00177 p->provides = hfd(p->provides, -1);
00178 p->providesEVR = hfd(p->providesEVR, -1);
00179 p->requires = hfd(p->requires, -1);
00180 p->requiresEVR = hfd(p->requiresEVR, -1);
00181 p->baseNames = hfd(p->baseNames, -1);
00182 if (p->h) headerFree(p->h);
00183
00184 if (p->relocs) {
00185 for (r = p->relocs; (r->oldPath || r->newPath); r++) {
00186 r->oldPath = _free(r->oldPath);
00187 r->newPath = _free(r->newPath);
00188 }
00189 p->relocs = _free(p->relocs);
00190 }
00191 if (p->fd)
00192 p->fd = fdFree(p->fd, "alAddPackage (alFree)");
00193 }
00194
00195 for (i = 0; i < al->numDirs; i++) {
00196 al->dirs[i].dirName = _free(al->dirs[i].dirName);
00197 al->dirs[i].files = _free(al->dirs[i].files);
00198 }
00199
00200 if (al->numDirs && al->dirs)
00201 al->dirs = _free(al->dirs);
00202 if (al->alloced && al->list)
00203 al->list = _free(al->list);
00204 alFreeIndex(al);
00205 }
00206
00213 static int dirInfoCompare(const void * one, const void * two)
00214 {
00215 const struct dirInfo * a = one;
00216 const struct dirInfo * b = two;
00217 int lenchk = a->dirNameLen - b->dirNameLen;
00218
00219 if (lenchk)
00220 return lenchk;
00221
00222
00223 return strcmp(a->dirName, b->dirName);
00224 }
00225
00235 static struct availablePackage * alAddPackage(struct availableList * al,
00236 Header h, const void * key,
00237 FD_t fd, rpmRelocation * relocs)
00238 {
00239 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00240 HFD_t hfd = headerFreeData;
00241 int dnt, bnt;
00242 struct availablePackage * p;
00243 rpmRelocation * r;
00244 int i;
00245 int_32 * dirIndexes;
00246 const char ** dirNames;
00247 int numDirs, dirNum;
00248 int * dirMapping;
00249 struct dirInfo dirNeedle;
00250 struct dirInfo * dirMatch;
00251 int first, last, fileNum;
00252 int origNumDirs;
00253 int pkgNum;
00254 uint_32 multiLibMask = 0;
00255 uint_32 * fileFlags = NULL;
00256 uint_32 * pp = NULL;
00257
00258 if (al->size == al->alloced) {
00259 al->alloced += al->delta;
00260 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
00261 }
00262
00263 pkgNum = al->size++;
00264 p = al->list + pkgNum;
00265 p->h = headerLink(h);
00266 p->depth = p->npreds = 0;
00267 memset(&p->tsi, 0, sizeof(p->tsi));
00268 p->multiLib = 0;
00269
00270 headerNVR(p->h, &p->name, &p->version, &p->release);
00271
00272
00273
00274
00275
00276 if (hge(p->h, RPMTAG_MULTILIBS, NULL, (void **) &pp, NULL))
00277 multiLibMask = *pp;
00278
00279 if (multiLibMask) {
00280 for (i = 0; i < pkgNum - 1; i++) {
00281 if (!strcmp (p->name, al->list[i].name)
00282 && hge(al->list[i].h, RPMTAG_MULTILIBS, NULL,
00283 (void **) &pp, NULL)
00284 && !rpmVersionCompare(p->h, al->list[i].h)
00285 && *pp && !(*pp & multiLibMask))
00286 p->multiLib = multiLibMask;
00287 }
00288 }
00289
00290 if (!hge(h, RPMTAG_EPOCH, NULL, (void **) &p->epoch, NULL))
00291 p->epoch = NULL;
00292
00293 if (!hge(h, RPMTAG_PROVIDENAME, NULL, (void **) &p->provides,
00294 &p->providesCount)) {
00295 p->providesCount = 0;
00296 p->provides = NULL;
00297 p->providesEVR = NULL;
00298 p->provideFlags = NULL;
00299 } else {
00300 if (!hge(h, RPMTAG_PROVIDEVERSION,
00301 NULL, (void **) &p->providesEVR, NULL))
00302 p->providesEVR = NULL;
00303 if (!hge(h, RPMTAG_PROVIDEFLAGS,
00304 NULL, (void **) &p->provideFlags, NULL))
00305 p->provideFlags = NULL;
00306 }
00307
00308 if (!hge(h, RPMTAG_REQUIRENAME, NULL, (void **) &p->requires,
00309 &p->requiresCount)) {
00310 p->requiresCount = 0;
00311 p->requires = NULL;
00312 p->requiresEVR = NULL;
00313 p->requireFlags = NULL;
00314 } else {
00315 if (!hge(h, RPMTAG_REQUIREVERSION,
00316 NULL, (void **) &p->requiresEVR, NULL))
00317 p->requiresEVR = NULL;
00318 if (!hge(h, RPMTAG_REQUIREFLAGS,
00319 NULL, (void **) &p->requireFlags, NULL))
00320 p->requireFlags = NULL;
00321 }
00322
00323 if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **) &p->baseNames, &p->filesCount))
00324 {
00325 p->filesCount = 0;
00326 p->baseNames = NULL;
00327 } else {
00328 hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, &numDirs);
00329 hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00330 hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlags, NULL);
00331
00332
00333
00334 dirMapping = alloca(sizeof(*dirMapping) * numDirs);
00335
00336
00337
00338 al->dirs = xrealloc(al->dirs,
00339 sizeof(*al->dirs) * (al->numDirs + numDirs));
00340 origNumDirs = al->numDirs;
00341
00342 for (dirNum = 0; dirNum < numDirs; dirNum++) {
00343 dirNeedle.dirName = (char *) dirNames[dirNum];
00344 dirNeedle.dirNameLen = strlen(dirNames[dirNum]);
00345 dirMatch = bsearch(&dirNeedle, al->dirs, origNumDirs,
00346 sizeof(dirNeedle), dirInfoCompare);
00347 if (dirMatch) {
00348 dirMapping[dirNum] = dirMatch - al->dirs;
00349 } else {
00350 dirMapping[dirNum] = al->numDirs;
00351 al->dirs[al->numDirs].dirName = xstrdup(dirNames[dirNum]);
00352 al->dirs[al->numDirs].dirNameLen = strlen(dirNames[dirNum]);
00353 al->dirs[al->numDirs].files = NULL;
00354 al->dirs[al->numDirs].numFiles = 0;
00355 al->numDirs++;
00356 }
00357 }
00358
00359 dirNames = hfd(dirNames, dnt);
00360
00361 first = 0;
00362 while (first < p->filesCount) {
00363 last = first;
00364 while ((last + 1) < p->filesCount) {
00365 if (dirIndexes[first] != dirIndexes[last + 1]) break;
00366 last++;
00367 }
00368
00369 dirMatch = al->dirs + dirMapping[dirIndexes[first]];
00370 dirMatch->files = xrealloc(dirMatch->files,
00371 sizeof(*dirMatch->files) *
00372 (dirMatch->numFiles + last - first + 1));
00373 for (fileNum = first; fileNum <= last; fileNum++) {
00374 dirMatch->files[dirMatch->numFiles].baseName =
00375 p->baseNames[fileNum];
00376 dirMatch->files[dirMatch->numFiles].pkgNum = pkgNum;
00377 dirMatch->files[dirMatch->numFiles].fileFlags =
00378 fileFlags[fileNum];
00379 dirMatch->numFiles++;
00380 }
00381
00382 first = last + 1;
00383 }
00384
00385 if (origNumDirs + al->numDirs)
00386 qsort(al->dirs, al->numDirs, sizeof(dirNeedle), dirInfoCompare);
00387
00388 }
00389
00390 p->key = key;
00391 p->fd = (fd ? fdLink(fd, "alAddPackage") : NULL);
00392
00393 if (relocs) {
00394 for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++);
00395 p->relocs = xmalloc(sizeof(*p->relocs) * (i + 1));
00396
00397 for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
00398 p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
00399 p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
00400 }
00401 p->relocs[i].oldPath = NULL;
00402 p->relocs[i].newPath = NULL;
00403 } else {
00404 p->relocs = NULL;
00405 }
00406
00407 alFreeIndex(al);
00408
00409 return p;
00410 }
00411
00418 static int indexcmp(const void * one, const void * two)
00419 {
00420 const struct availableIndexEntry * a = one;
00421 const struct availableIndexEntry * b = two;
00422 int lenchk = a->entryLen - b->entryLen;
00423
00424 if (lenchk)
00425 return lenchk;
00426
00427 return strcmp(a->entry, b->entry);
00428 }
00429
00434 static void alMakeIndex(struct availableList * al)
00435
00436 {
00437 struct availableIndex * ai = &al->index;
00438 int i, j, k;
00439
00440 if (ai->size) return;
00441
00442 for (i = 0; i < al->size; i++)
00443 ai->size += al->list[i].providesCount;
00444
00445 if (ai->size) {
00446 ai->index = xcalloc(ai->size, sizeof(*ai->index));
00447
00448 k = 0;
00449 for (i = 0; i < al->size; i++) {
00450 for (j = 0; j < al->list[i].providesCount; j++) {
00451
00452
00453 if (al->list[i].multiLib &&
00454 !isDependsMULTILIB(al->list[i].provideFlags[j])) {
00455 ai->size--;
00456 continue;
00457 }
00458
00459 ai->index[k].package = al->list + i;
00460 ai->index[k].entry = al->list[i].provides[j];
00461 ai->index[k].entryLen = strlen(al->list[i].provides[j]);
00462 ai->index[k].type = IET_PROVIDES;
00463 k++;
00464 }
00465 }
00466
00467 qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00468 }
00469 }
00470
00477 static int intcmp(const void * a, const void *b)
00478 {
00479 const int * aptr = a;
00480 const int * bptr = b;
00481 int rc = (*aptr - *bptr);
00482 return rc;
00483 }
00484
00492 static void parseEVR(char *evr,
00493 const char **ep,
00494 const char **vp,
00495 const char **rp)
00496 {
00497 const char *epoch;
00498 const char *version;
00499 const char *release;
00500 char *s, *se;
00501
00502 s = evr;
00503 while (*s && isdigit(*s)) s++;
00504 se = strrchr(s, '-');
00505
00506 if (*s == ':') {
00507 epoch = evr;
00508 *s++ = '\0';
00509 version = s;
00510 if (*epoch == '\0') epoch = "0";
00511 } else {
00512 epoch = NULL;
00513 version = evr;
00514 }
00515 if (se) {
00516 *se++ = '\0';
00517 release = se;
00518 } else {
00519 release = NULL;
00520 }
00521
00522 if (ep) *ep = epoch;
00523 if (vp) *vp = version;
00524 if (rp) *rp = release;
00525 }
00526
00527 const char *rpmNAME = PACKAGE;
00528 const char *rpmEVR = VERSION;
00529 int rpmFLAGS = RPMSENSE_EQUAL;
00530
00531 int rpmRangesOverlap(const char *AName, const char *AEVR, int AFlags,
00532 const char *BName, const char *BEVR, int BFlags)
00533 {
00534 const char *aDepend = printDepend(NULL, AName, AEVR, AFlags);
00535 const char *bDepend = printDepend(NULL, BName, BEVR, BFlags);
00536 char *aEVR, *bEVR;
00537 const char *aE, *aV, *aR, *bE, *bV, *bR;
00538 int result;
00539 int sense;
00540
00541
00542 if (strcmp(AName, BName)) {
00543 result = 0;
00544 goto exit;
00545 }
00546
00547
00548 if (!((AFlags & RPMSENSE_SENSEMASK) && (BFlags & RPMSENSE_SENSEMASK))) {
00549 result = 1;
00550 goto exit;
00551 }
00552
00553
00554 if (!(AEVR && *AEVR && BEVR && *BEVR)) {
00555 result = 1;
00556 goto exit;
00557 }
00558
00559
00560 aEVR = xstrdup(AEVR);
00561 parseEVR(aEVR, &aE, &aV, &aR);
00562 bEVR = xstrdup(BEVR);
00563 parseEVR(bEVR, &bE, &bV, &bR);
00564
00565
00566 sense = 0;
00567 if (aE && *aE && bE && *bE)
00568 sense = rpmvercmp(aE, bE);
00569 else if (aE && *aE && atol(aE) > 0) {
00570
00571 rpmMessage(RPMMESS_DEBUG, _("the \"B\" dependency needs an epoch (assuming same as \"A\")\n\tA %s\tB %s\n"),
00572 aDepend, bDepend);
00573 sense = 0;
00574 } else if (bE && *bE && atol(bE) > 0)
00575 sense = -1;
00576
00577 if (sense == 0) {
00578 sense = rpmvercmp(aV, bV);
00579 if (sense == 0 && aR && *aR && bR && *bR) {
00580 sense = rpmvercmp(aR, bR);
00581 }
00582 }
00583 aEVR = _free(aEVR);
00584 bEVR = _free(bEVR);
00585
00586
00587 result = 0;
00588 if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) {
00589 result = 1;
00590 } else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) {
00591 result = 1;
00592 } else if (sense == 0 &&
00593 (((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) ||
00594 ((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) ||
00595 ((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) {
00596 result = 1;
00597 }
00598
00599 exit:
00600 rpmMessage(RPMMESS_DEBUG, _(" %s A %s\tB %s\n"),
00601 (result ? "YES" : "NO "), aDepend, bDepend);
00602 aDepend = _free(aDepend);
00603 bDepend = _free(bDepend);
00604 return result;
00605 }
00606
00607 typedef int (*dbrecMatch_t) (Header h, const char *reqName, const char * reqEVR, int reqFlags);
00608
00609 static int rangeMatchesDepFlags (Header h, const char *reqName, const char * reqEVR, int reqFlags)
00610 {
00611 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00612 HFD_t hfd = headerFreeData;
00613 int pnt, pvt;
00614 const char ** provides;
00615 const char ** providesEVR;
00616 int_32 * provideFlags;
00617 int providesCount;
00618 int result;
00619 int type;
00620 int i;
00621
00622 if (!(reqFlags & RPMSENSE_SENSEMASK) || !reqEVR || !strlen(reqEVR))
00623 return 1;
00624
00625
00626
00627
00628
00629
00630 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt,
00631 (void **) &providesEVR, &providesCount))
00632 return 1;
00633
00634 hge(h, RPMTAG_PROVIDEFLAGS, &type, (void **) &provideFlags, &providesCount);
00635
00636 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
00637 {
00638 providesEVR = hfd(providesEVR, pvt);
00639 return 0;
00640 }
00641
00642 result = 0;
00643 for (i = 0; i < providesCount; i++) {
00644
00645
00646 if (strcmp(provides[i], reqName))
00647 continue;
00648
00649 result = rpmRangesOverlap(provides[i], providesEVR[i], provideFlags[i],
00650 reqName, reqEVR, reqFlags);
00651
00652
00653 if (result)
00654 break;
00655 }
00656
00657 provides = hfd(provides, pnt);
00658 providesEVR = hfd(providesEVR, pvt);
00659
00660 return result;
00661 }
00662
00663 int headerMatchesDepFlags(Header h,
00664 const char * reqName, const char * reqEVR, int reqFlags)
00665 {
00666 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00667 const char *name, *version, *release;
00668 int_32 * epoch;
00669 const char *pkgEVR;
00670 char *p;
00671 int pkgFlags = RPMSENSE_EQUAL;
00672
00673 if (!((reqFlags & RPMSENSE_SENSEMASK) && reqEVR && *reqEVR))
00674 return 1;
00675
00676
00677 headerNVR(h, &name, &version, &release);
00678
00679 pkgEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00680 *p = '\0';
00681 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00682 sprintf(p, "%d:", *epoch);
00683 while (*p)
00684 p++;
00685 }
00686 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00687
00688 return rpmRangesOverlap(name, pkgEVR, pkgFlags, reqName, reqEVR, reqFlags);
00689 }
00690
00691 rpmTransactionSet rpmtransCreateSet(rpmdb rpmdb, const char * rootDir)
00692 {
00693 rpmTransactionSet ts;
00694 int rootLen;
00695
00696 if (!rootDir) rootDir = "";
00697
00698 ts = xcalloc(1, sizeof(*ts));
00699 ts->filesystemCount = 0;
00700 ts->filesystems = NULL;
00701 ts->di = NULL;
00702 ts->rpmdb = rpmdb;
00703 ts->scriptFd = NULL;
00704 ts->id = 0;
00705 ts->delta = 5;
00706
00707 ts->numRemovedPackages = 0;
00708 ts->allocedRemovedPackages = ts->delta;
00709 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
00710 sizeof(*ts->removedPackages));
00711
00712
00713 rootLen = strlen(rootDir);
00714 if (!(rootLen && rootDir[rootLen - 1] == '/')) {
00715 char * t;
00716
00717 t = alloca(rootLen + 2);
00718 *t = '\0';
00719 (void) stpcpy( stpcpy(t, rootDir), "/");
00720 rootDir = t;
00721 }
00722
00723 ts->rootDir = xstrdup(rootDir);
00724 ts->currDir = NULL;
00725 ts->chrootDone = 0;
00726
00727 ts->addedPackages.delta = ts->delta;
00728 alCreate(&ts->addedPackages);
00729 ts->availablePackages.delta = ts->delta;
00730 alCreate(&ts->availablePackages);
00731
00732 ts->orderAlloced = ts->delta;
00733 ts->orderCount = 0;
00734 ts->order = xcalloc(ts->orderAlloced, sizeof(*ts->order));
00735
00736 return ts;
00737 }
00738
00745 static void removePackage(rpmTransactionSet ts, int dboffset, int depends)
00746
00747 {
00748 if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
00749 ts->allocedRemovedPackages += ts->delta;
00750 ts->removedPackages = xrealloc(ts->removedPackages,
00751 sizeof(int *) * ts->allocedRemovedPackages);
00752 }
00753
00754 ts->removedPackages[ts->numRemovedPackages++] = dboffset;
00755
00756 if (ts->orderCount == ts->orderAlloced) {
00757 ts->orderAlloced += ts->delta;
00758 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00759 }
00760
00761 ts->order[ts->orderCount].type = TR_REMOVED;
00762 ts->order[ts->orderCount].u.removed.dboffset = dboffset;
00763 ts->order[ts->orderCount++].u.removed.dependsOnIndex = depends;
00764 }
00765
00766 int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
00767 const void * key, int upgrade, rpmRelocation * relocs)
00768 {
00769 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00770 HFD_t hfd = headerFreeData;
00771 int ont, ovt;
00772
00773 const char * name;
00774 int count;
00775 const char ** obsoletes;
00776 int alNum;
00777
00778
00779
00780
00781
00782
00783
00784 if (ts->orderCount == ts->orderAlloced) {
00785 ts->orderAlloced += ts->delta;
00786 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00787 }
00788 ts->order[ts->orderCount].type = TR_ADDED;
00789 alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
00790 ts->addedPackages.list;
00791 ts->order[ts->orderCount++].u.addedIndex = alNum;
00792
00793 if (!upgrade || ts->rpmdb == NULL)
00794 return 0;
00795
00796
00797 if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
00798 return 0;
00799
00800 headerNVR(h, &name, NULL, NULL);
00801
00802 { rpmdbMatchIterator mi;
00803 Header h2;
00804
00805 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, name, 0);
00806 while((h2 = rpmdbNextIterator(mi)) != NULL) {
00807 if (rpmVersionCompare(h, h2))
00808 removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
00809 else {
00810 uint_32 *p, multiLibMask = 0, oldmultiLibMask = 0;
00811
00812 if (hge(h2, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL))
00813 oldmultiLibMask = *p;
00814 if (hge(h, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL))
00815 multiLibMask = *p;
00816 if (oldmultiLibMask && multiLibMask
00817 && !(oldmultiLibMask & multiLibMask)) {
00818 ts->addedPackages.list[alNum].multiLib = multiLibMask;
00819 }
00820 }
00821 }
00822 rpmdbFreeIterator(mi);
00823 }
00824
00825 if (hge(h, RPMTAG_OBSOLETENAME, &ont, (void **) &obsoletes, &count)) {
00826 const char **obsoletesEVR;
00827 int_32 *obsoletesFlags;
00828 int j;
00829
00830 hge(h, RPMTAG_OBSOLETEVERSION, &ovt, (void **) &obsoletesEVR, NULL);
00831 hge(h, RPMTAG_OBSOLETEFLAGS, NULL, (void **) &obsoletesFlags, NULL);
00832
00833 for (j = 0; j < count; j++) {
00834
00835
00836 if (!strcmp(name, obsoletes[j]))
00837 continue;
00838
00839 { rpmdbMatchIterator mi;
00840 Header h2;
00841
00842 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, obsoletes[j], 0);
00843
00844 rpmdbPruneIterator(mi,
00845 ts->removedPackages, ts->numRemovedPackages, 1);
00846
00847 while((h2 = rpmdbNextIterator(mi)) != NULL) {
00848
00849
00850
00851
00852 if (obsoletesEVR == NULL ||
00853 headerMatchesDepFlags(h2,
00854 obsoletes[j], obsoletesEVR[j], obsoletesFlags[j]))
00855 {
00856 removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
00857 }
00858 }
00859 rpmdbFreeIterator(mi);
00860 }
00861 }
00862
00863 obsoletesEVR = hfd(obsoletesEVR, ovt);
00864 obsoletes = hfd(obsoletes, ont);
00865 }
00866
00867 return 0;
00868 }
00869
00870 void rpmtransAvailablePackage(rpmTransactionSet ts, Header h, const void * key)
00871 {
00872 struct availablePackage * al;
00873 al = alAddPackage(&ts->availablePackages, h, key, NULL, NULL);
00874 }
00875
00876 void rpmtransRemovePackage(rpmTransactionSet ts, int dboffset)
00877 {
00878 removePackage(ts, dboffset, -1);
00879 }
00880
00881 void rpmtransFree(rpmTransactionSet ts)
00882 {
00883 alFree(&ts->addedPackages);
00884 alFree(&ts->availablePackages);
00885 ts->di = _free(ts->di);
00886 ts->removedPackages = _free(ts->removedPackages);
00887 ts->order = _free(ts->order);
00888 if (ts->scriptFd)
00889 ts->scriptFd = fdFree(ts->scriptFd, "rpmtransSetScriptFd (rpmtransFree");
00890 ts->rootDir = _free(ts->rootDir);
00891 ts->currDir = _free(ts->currDir);
00892
00893 ts = _free(ts);
00894 }
00895
00896 void rpmdepFreeConflicts(struct rpmDependencyConflict * conflicts,
00897 int numConflicts)
00898 {
00899 int i;
00900
00901 for (i = 0; i < numConflicts; i++) {
00902 headerFree(conflicts[i].byHeader);
00903 conflicts[i].byName = _free(conflicts[i].byName);
00904 conflicts[i].byVersion = _free(conflicts[i].byVersion);
00905 conflicts[i].byRelease = _free(conflicts[i].byRelease);
00906 conflicts[i].needsName = _free(conflicts[i].needsName);
00907 conflicts[i].needsVersion = _free(conflicts[i].needsVersion);
00908 }
00909
00910 conflicts = _free(conflicts);
00911 }
00912
00920 static struct availablePackage *
00921 alFileSatisfiesDepend(struct availableList * al,
00922 const char * keyType, const char * fileName)
00923 {
00924 int i;
00925 const char * dirName;
00926 const char * baseName;
00927 struct dirInfo dirNeedle;
00928 struct dirInfo * dirMatch;
00929
00930 if (al->numDirs == 0)
00931 return NULL;
00932
00933 { char * chptr = xstrdup(fileName);
00934 dirName = chptr;
00935 chptr = strrchr(chptr, '/');
00936 chptr++;
00937 *chptr = '\0';
00938 }
00939
00940 dirNeedle.dirName = (char *) dirName;
00941 dirNeedle.dirNameLen = strlen(dirName);
00942 dirMatch = bsearch(&dirNeedle, al->dirs, al->numDirs,
00943 sizeof(dirNeedle), dirInfoCompare);
00944 dirName = _free(dirName);
00945 if (!dirMatch) return NULL;
00946
00947 baseName = strrchr(fileName, '/') + 1;
00948
00949
00950 for (i = 0; i < dirMatch->numFiles; i++) {
00951 if (!strcmp(dirMatch->files[i].baseName, baseName)) {
00952
00953
00954
00955 if (al->list[dirMatch->files[i].pkgNum].multiLib &&
00956 !isFileMULTILIB(dirMatch->files[i].fileFlags))
00957 continue;
00958
00959 if (keyType)
00960 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added files)\n"),
00961 keyType, fileName);
00962 return al->list + dirMatch->files[i].pkgNum;
00963 }
00964 }
00965
00966 return NULL;
00967 }
00968
00979 static struct availablePackage * alSatisfiesDepend(
00980 struct availableList * al,
00981 const char * keyType, const char * keyDepend,
00982 const char * keyName, const char * keyEVR, int keyFlags)
00983 {
00984 struct availableIndexEntry needle, * match;
00985 struct availablePackage * p;
00986 int i, rc;
00987
00988 if (*keyName == '/')
00989 return alFileSatisfiesDepend(al, keyType, keyName);
00990
00991 if (!al->index.size) return NULL;
00992
00993 needle.entry = keyName;
00994 needle.entryLen = strlen(keyName);
00995 match = bsearch(&needle, al->index.index, al->index.size,
00996 sizeof(*al->index.index), indexcmp);
00997
00998 if (match == NULL) return NULL;
00999
01000 p = match->package;
01001 rc = 0;
01002 switch (match->type) {
01003 case IET_PROVIDES:
01004 for (i = 0; i < p->providesCount; i++) {
01005 const char *proEVR;
01006 int proFlags;
01007
01008
01009 if (strcmp(p->provides[i], keyName))
01010 continue;
01011
01012 proEVR = (p->providesEVR ? p->providesEVR[i] : NULL);
01013 proFlags = (p->provideFlags ? p->provideFlags[i] : 0);
01014 rc = rpmRangesOverlap(p->provides[i], proEVR, proFlags,
01015 keyName, keyEVR, keyFlags);
01016 if (rc) break;
01017 }
01018 if (keyType && keyDepend && rc)
01019 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added provide)\n"),
01020 keyType, keyDepend+2);
01021 break;
01022 }
01023
01024 if (rc)
01025 return p;
01026
01027 return NULL;
01028 }
01029
01041 static int unsatisfiedDepend(rpmTransactionSet ts,
01042 const char * keyType, const char * keyDepend,
01043 const char * keyName, const char * keyEVR, int keyFlags,
01044 struct availablePackage ** suggestion)
01045 {
01046 static int _cacheDependsRC = 1;
01047 rpmdbMatchIterator mi;
01048 Header h;
01049 int rc = 0;
01050
01051 if (suggestion) *suggestion = NULL;
01052
01053
01054
01055
01056 if (_cacheDependsRC) {
01057 dbiIndex dbi;
01058 dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
01059 if (dbi == NULL)
01060 _cacheDependsRC = 0;
01061 else {
01062 DBC * dbcursor = NULL;
01063 size_t keylen = strlen(keyDepend);
01064 void * datap = NULL;
01065 size_t datalen = 0;
01066 int xx;
01067 xx = dbiCopen(dbi, &dbcursor, 0);
01068 xx = dbiGet(dbi, dbcursor, (void **)&keyDepend, &keylen, &datap, &datalen, 0);
01069 if (xx == 0 && datap && datalen == 4) {
01070 memcpy(&rc, datap, datalen);
01071 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s %-3s (cached)\n"),
01072 keyType, keyDepend, (rc ? "NO" : "YES"));
01073 xx = dbiCclose(dbi, NULL, 0);
01074 return rc;
01075 }
01076 xx = dbiCclose(dbi, dbcursor, 0);
01077 }
01078 }
01079
01080 #ifndef DYING
01081 { const char * rcProvidesString;
01082 const char * start;
01083 int i;
01084
01085 if (!(keyFlags & RPMSENSE_SENSEMASK) &&
01086 (rcProvidesString = rpmGetVar(RPMVAR_PROVIDES))) {
01087 i = strlen(keyName);
01088 while ((start = strstr(rcProvidesString, keyName))) {
01089 if (isspace(start[i]) || start[i] == '\0' || start[i] == ',') {
01090 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmrc provides)\n"),
01091 keyType, keyDepend+2);
01092 goto exit;
01093 }
01094 rcProvidesString = start + 1;
01095 }
01096 }
01097 }
01098 #endif
01099
01100
01101
01102
01103
01104
01105 if (!strncmp(keyName, "rpmlib(", sizeof("rpmlib(")-1)) {
01106 if (rpmCheckRpmlibProvides(keyName, keyEVR, keyFlags)) {
01107 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmlib provides)\n"),
01108 keyType, keyDepend+2);
01109 goto exit;
01110 }
01111 goto unsatisfied;
01112 }
01113
01114 if (alSatisfiesDepend(&ts->addedPackages, keyType, keyDepend, keyName, keyEVR, keyFlags)) {
01115 goto exit;
01116 }
01117
01118
01119 if (ts->rpmdb != NULL) {
01120 if (*keyName == '/') {
01121
01122
01123 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_BASENAMES, keyName, 0);
01124
01125 rpmdbPruneIterator(mi,
01126 ts->removedPackages, ts->numRemovedPackages, 1);
01127
01128 while ((h = rpmdbNextIterator(mi)) != NULL) {
01129 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db files)\n"),
01130 keyType, keyDepend+2);
01131 rpmdbFreeIterator(mi);
01132 goto exit;
01133 }
01134 rpmdbFreeIterator(mi);
01135 }
01136
01137 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_PROVIDENAME, keyName, 0);
01138 rpmdbPruneIterator(mi,
01139 ts->removedPackages, ts->numRemovedPackages, 1);
01140 while ((h = rpmdbNextIterator(mi)) != NULL) {
01141 if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
01142 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db provides)\n"),
01143 keyType, keyDepend+2);
01144 rpmdbFreeIterator(mi);
01145 goto exit;
01146 }
01147 }
01148 rpmdbFreeIterator(mi);
01149
01150 #ifndef DYING
01151 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, keyName, 0);
01152 rpmdbPruneIterator(mi,
01153 ts->removedPackages, ts->numRemovedPackages, 1);
01154 while ((h = rpmdbNextIterator(mi)) != NULL) {
01155 if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
01156 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db package)\n"),
01157 keyType, keyDepend+2);
01158 rpmdbFreeIterator(mi);
01159 goto exit;
01160 }
01161 }
01162 rpmdbFreeIterator(mi);
01163 #endif
01164
01165 }
01166
01167 if (suggestion)
01168 *suggestion = alSatisfiesDepend(&ts->availablePackages, NULL, NULL,
01169 keyName, keyEVR, keyFlags);
01170
01171 unsatisfied:
01172 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s NO\n"), keyType, keyDepend+2);
01173 rc = 1;
01174
01175 exit:
01176
01177
01178
01179 if (_cacheDependsRC) {
01180 dbiIndex dbi;
01181 dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
01182 if (dbi == NULL) {
01183 _cacheDependsRC = 0;
01184 } else {
01185 DBC * dbcursor = NULL;
01186 int xx;
01187 xx = dbiCopen(dbi, &dbcursor, 0);
01188 xx = dbiPut(dbi, dbcursor, keyDepend, strlen(keyDepend), &rc, sizeof(rc), 0);
01189 if (xx)
01190 _cacheDependsRC = 0;
01191 #if 0
01192 else
01193 rpmMessage(RPMMESS_DEBUG, _("%s: (%s, %s) added to Depends cache.\n"), keyType, keyDepend, (rc ? "NO" : "YES"));
01194 #endif
01195 xx = dbiCclose(dbi, dbcursor, 0);
01196 }
01197 }
01198 return rc;
01199 }
01200
01201 static int checkPackageDeps(rpmTransactionSet ts, struct problemsSet * psp,
01202 Header h, const char * keyName, uint_32 multiLib)
01203 {
01204 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01205 HFD_t hfd = headerFreeData;
01206 int rnt, rvt;
01207 int cnt, cvt;
01208 const char * name, * version, * release;
01209 const char ** requires;
01210 const char ** requiresEVR = NULL;
01211 int_32 * requireFlags = NULL;
01212 int requiresCount = 0;
01213 const char ** conflicts;
01214 const char ** conflictsEVR = NULL;
01215 int_32 * conflictFlags = NULL;
01216 int conflictsCount = 0;
01217 int type;
01218 int i, rc;
01219 int ourrc = 0;
01220 struct availablePackage * suggestion;
01221
01222 headerNVR(h, &name, &version, &release);
01223
01224 if (!hge(h, RPMTAG_REQUIRENAME, &rnt, (void **) &requires, &requiresCount)) {
01225 requiresCount = 0;
01226 } else {
01227 hge(h, RPMTAG_REQUIREFLAGS, &type, (void **) &requireFlags,
01228 &requiresCount);
01229 hge(h, RPMTAG_REQUIREVERSION, &rvt,
01230 (void **) &requiresEVR, &requiresCount);
01231 }
01232
01233 for (i = 0; i < requiresCount && !ourrc; i++) {
01234 const char * keyDepend;
01235
01236
01237 if (keyName && strcmp(keyName, requires[i]))
01238 continue;
01239
01240
01241
01242 if (multiLib && !isDependsMULTILIB(requireFlags[i]))
01243 continue;
01244
01245 keyDepend = printDepend("R", requires[i], requiresEVR[i], requireFlags[i]);
01246
01247 rc = unsatisfiedDepend(ts, " Requires", keyDepend,
01248 requires[i], requiresEVR[i], requireFlags[i], &suggestion);
01249
01250 switch (rc) {
01251 case 0:
01252 break;
01253 case 1:
01254 rpmMessage(RPMMESS_DEBUG, _("package %s-%s-%s require not satisfied: %s\n"),
01255 name, version, release, keyDepend+2);
01256
01257 if (psp->num == psp->alloced) {
01258 psp->alloced += 5;
01259 psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
01260 psp->alloced);
01261 }
01262 psp->problems[psp->num].byHeader = headerLink(h);
01263 psp->problems[psp->num].byName = xstrdup(name);
01264 psp->problems[psp->num].byVersion = xstrdup(version);
01265 psp->problems[psp->num].byRelease = xstrdup(release);
01266 psp->problems[psp->num].needsName = xstrdup(requires[i]);
01267 psp->problems[psp->num].needsVersion = xstrdup(requiresEVR[i]);
01268 psp->problems[psp->num].needsFlags = requireFlags[i];
01269 psp->problems[psp->num].sense = RPMDEP_SENSE_REQUIRES;
01270
01271 if (suggestion)
01272 psp->problems[psp->num].suggestedPackage = suggestion->key;
01273 else
01274 psp->problems[psp->num].suggestedPackage = NULL;
01275
01276 psp->num++;
01277 break;
01278 case 2:
01279 default:
01280 ourrc = 1;
01281 break;
01282 }
01283 keyDepend = _free(keyDepend);
01284 }
01285
01286 if (requiresCount) {
01287 requiresEVR = hfd(requiresEVR, rvt);
01288 requires = hfd(requires, rnt);
01289 }
01290
01291 if (!hge(h, RPMTAG_CONFLICTNAME, &cnt, (void **)&conflicts, &conflictsCount))
01292 {
01293 conflictsCount = 0;
01294 } else {
01295 hge(h, RPMTAG_CONFLICTFLAGS, &type,
01296 (void **) &conflictFlags, &conflictsCount);
01297 hge(h, RPMTAG_CONFLICTVERSION, &cvt,
01298 (void **) &conflictsEVR, &conflictsCount);
01299 }
01300
01301 for (i = 0; i < conflictsCount && !ourrc; i++) {
01302 const char * keyDepend;
01303
01304
01305 if (keyName && strcmp(keyName, conflicts[i]))
01306 continue;
01307
01308
01309
01310 if (multiLib && !isDependsMULTILIB(conflictFlags[i]))
01311 continue;
01312
01313 keyDepend = printDepend("C", conflicts[i], conflictsEVR[i], conflictFlags[i]);
01314
01315 rc = unsatisfiedDepend(ts, "Conflicts", keyDepend,
01316 conflicts[i], conflictsEVR[i], conflictFlags[i], NULL);
01317
01318
01319 switch (rc) {
01320 case 0:
01321 rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
01322 name, keyDepend+2);
01323
01324 if (psp->num == psp->alloced) {
01325 psp->alloced += 5;
01326 psp->problems = xrealloc(psp->problems,
01327 sizeof(*psp->problems) * psp->alloced);
01328 }
01329 psp->problems[psp->num].byHeader = headerLink(h);
01330 psp->problems[psp->num].byName = xstrdup(name);
01331 psp->problems[psp->num].byVersion = xstrdup(version);
01332 psp->problems[psp->num].byRelease = xstrdup(release);
01333 psp->problems[psp->num].needsName = xstrdup(conflicts[i]);
01334 psp->problems[psp->num].needsVersion = xstrdup(conflictsEVR[i]);
01335 psp->problems[psp->num].needsFlags = conflictFlags[i];
01336 psp->problems[psp->num].sense = RPMDEP_SENSE_CONFLICTS;
01337 psp->problems[psp->num].suggestedPackage = NULL;
01338
01339 psp->num++;
01340 break;
01341 case 1:
01342 break;
01343 case 2:
01344 default:
01345 ourrc = 1;
01346 break;
01347 }
01348 keyDepend = _free(keyDepend);
01349 }
01350
01351 if (conflictsCount) {
01352 conflictsEVR = hfd(conflictsEVR, cvt);
01353 conflicts = hfd(conflicts, cnt);
01354 }
01355
01356 return ourrc;
01357 }
01358
01363 static int checkPackageSet(rpmTransactionSet ts, struct problemsSet * psp,
01364 const char * key, rpmdbMatchIterator mi)
01365 {
01366 Header h;
01367 int rc = 0;
01368
01369 rpmdbPruneIterator(mi, ts->removedPackages, ts->numRemovedPackages, 1);
01370 while ((h = rpmdbNextIterator(mi)) != NULL) {
01371 if (checkPackageDeps(ts, psp, h, key, 0)) {
01372 rc = 1;
01373 break;
01374 }
01375 }
01376 rpmdbFreeIterator(mi);
01377
01378 return rc;
01379 }
01380
01384 static int checkDependentPackages(rpmTransactionSet ts,
01385 struct problemsSet * psp, const char * key)
01386 {
01387 rpmdbMatchIterator mi;
01388 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_REQUIRENAME, key, 0);
01389 return checkPackageSet(ts, psp, key, mi);
01390 }
01391
01395 static int checkDependentConflicts(rpmTransactionSet ts,
01396 struct problemsSet * psp, const char * key)
01397 {
01398 int rc = 0;
01399
01400 if (ts->rpmdb) {
01401 rpmdbMatchIterator mi;
01402 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_CONFLICTNAME, key, 0);
01403 rc = checkPackageSet(ts, psp, key, mi);
01404 }
01405
01406 return rc;
01407 }
01408
01409
01410
01411
01412
01413 #define DEPENDENCY_WHITEOUT
01414
01415 #if defined(DEPENDENCY_WHITEOUT)
01416 static struct badDeps_s {
01417 const char * pname;
01418 const char * qname;
01419 } badDeps[] = {
01420 { "libtermcap", "bash" },
01421 { "modutils", "vixie-cron" },
01422 { "ypbind", "yp-tools" },
01423 { "ghostscript-fonts", "ghostscript" },
01424
01425 { "arts", "kdelibs-sound" },
01426
01427 { "pango-gtkbeta-devel", "pango-gtkbeta" },
01428 { "XFree86", "Mesa" },
01429 { "compat-glibc", "db2" },
01430 { "compat-glibc", "db1" },
01431 { "pam", "initscripts" },
01432 { "kernel", "initscripts" },
01433 { "initscripts", "sysklogd" },
01434
01435 { "egcs-c++", "libstdc++" },
01436
01437 { "pilot-link-devel", "pilot-link" },
01438
01439 { "pam", "pamconfig" },
01440 { NULL, NULL }
01441 };
01442
01443 static int ignoreDep(struct availablePackage * p, struct availablePackage * q)
01444 {
01445 struct badDeps_s *bdp;
01446
01447 for (bdp = badDeps; bdp->pname != NULL; bdp++) {
01448 if (!strcmp(p->name, bdp->pname) && !strcmp(q->name, bdp->qname))
01449 return 1;
01450 }
01451 return 0;
01452 }
01453 #endif
01454
01460 static void markLoop(struct tsortInfo * tsi, struct availablePackage * q)
01461 {
01462 struct availablePackage * p;
01463
01464 while (tsi != NULL) {
01465 p = tsi->tsi_suc;
01466 tsi = tsi->tsi_next;
01467 if (p->tsi.tsi_pkg != NULL)
01468 continue;
01469 p->tsi.tsi_pkg = q;
01470 markLoop(p->tsi.tsi_next, p);
01471 }
01472 }
01473
01474 static inline const char * const identifyDepend(int_32 f) {
01475 if (isLegacyPreReq(f))
01476 return "PreReq:";
01477 f = _notpre(f);
01478 if (f & RPMSENSE_SCRIPT_PRE)
01479 return "Requires(pre):";
01480 if (f & RPMSENSE_SCRIPT_POST)
01481 return "Requires(post):";
01482 if (f & RPMSENSE_SCRIPT_PREUN)
01483 return "Requires(preun):";
01484 if (f & RPMSENSE_SCRIPT_POSTUN)
01485 return "Requires(postun):";
01486 if (f & RPMSENSE_SCRIPT_VERIFY)
01487 return "Requires(verify):";
01488 if (f & RPMSENSE_FIND_REQUIRES)
01489 return "Requires(auto):";
01490 return "Requires:";
01491 }
01492
01504 static const char *
01505 zapRelation(struct availablePackage * q, struct availablePackage * p,
01506 int zap, int * nzaps)
01507 {
01508 struct tsortInfo * tsi_prev;
01509 struct tsortInfo * tsi;
01510 const char *dp = NULL;
01511
01512 if (q == NULL)
01513 return dp;
01514 for (tsi_prev = &q->tsi, tsi = q->tsi.tsi_next;
01515 tsi != NULL;
01516 tsi_prev = tsi, tsi = tsi->tsi_next)
01517 {
01518 int j;
01519
01520 if (tsi->tsi_suc != p)
01521 continue;
01522 j = tsi->tsi_reqx;
01523 dp = printDepend( identifyDepend(p->requireFlags[j]),
01524 p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534 if (zap && !(p->requireFlags[j] & RPMSENSE_PREREQ)) {
01535 rpmMessage(RPMMESS_WARNING,
01536 _("removing %s-%s-%s \"%s\" from tsort relations.\n"),
01537 p->name, p->version, p->release, dp);
01538 p->tsi.tsi_count--;
01539 tsi_prev->tsi_next = tsi->tsi_next;
01540 tsi->tsi_next = NULL;
01541 tsi->tsi_suc = NULL;
01542 tsi = _free(tsi);
01543 if (nzaps)
01544 (*nzaps)++;
01545 if (zap)
01546 zap--;
01547 }
01548 break;
01549 }
01550 return dp;
01551 }
01552
01561 static inline int addRelation( const rpmTransactionSet ts,
01562 struct availablePackage * p, unsigned char * selected, int j)
01563 {
01564 struct availablePackage * q;
01565 struct tsortInfo * tsi;
01566 int matchNum;
01567
01568 q = alSatisfiesDepend(&ts->addedPackages, NULL, NULL,
01569 p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
01570
01571
01572 if (q == NULL)
01573 return 0;
01574
01575
01576 if (!strncmp(p->requires[j], "rpmlib(", sizeof("rpmlib(")-1))
01577 return 0;
01578
01579 #if defined(DEPENDENCY_WHITEOUT)
01580
01581 if (ignoreDep(p, q))
01582 return 0;
01583 #endif
01584
01585
01586
01587 matchNum = q - ts->addedPackages.list;
01588 if (selected[matchNum])
01589 return 0;
01590 selected[matchNum] = 1;
01591
01592
01593 p->tsi.tsi_count++;
01594 if (p->depth <= q->depth)
01595 p->depth = q->depth + 1;
01596
01597 tsi = xmalloc(sizeof(*tsi));
01598 tsi->tsi_suc = p;
01599 tsi->tsi_reqx = j;
01600 tsi->tsi_next = q->tsi.tsi_next;
01601 q->tsi.tsi_next = tsi;
01602 q->tsi.tsi_qcnt++;
01603 return 0;
01604 }
01605
01612 static int orderListIndexCmp(const void * one, const void * two)
01613 {
01614 int a = ((const struct orderListIndex *)one)->alIndex;
01615 int b = ((const struct orderListIndex *)two)->alIndex;
01616 return (a - b);
01617 }
01618
01625 static void addQ( struct availablePackage * p,
01626 struct availablePackage ** qp,
01627 struct availablePackage ** rp)
01628 {
01629 struct availablePackage *q, *qprev;
01630
01631 if ((*rp) == NULL) {
01632 (*rp) = (*qp) = p;
01633 return;
01634 }
01635 for (qprev = NULL, q = (*qp); q != NULL; qprev = q, q = q->tsi.tsi_suc) {
01636 if (q->tsi.tsi_qcnt <= p->tsi.tsi_qcnt)
01637 break;
01638 }
01639 if (qprev == NULL) {
01640 p->tsi.tsi_suc = q;
01641 (*qp) = p;
01642 } else if (q == NULL) {
01643 qprev->tsi.tsi_suc = p;
01644 (*rp) = p;
01645 } else {
01646 p->tsi.tsi_suc = q;
01647 qprev->tsi.tsi_suc = p;
01648 }
01649 }
01650
01651 int rpmdepOrder(rpmTransactionSet ts)
01652 {
01653 int npkgs = ts->addedPackages.size;
01654 int chainsaw = ts->transFlags & RPMTRANS_FLAG_CHAINSAW;
01655 struct availablePackage * p;
01656 struct availablePackage * q;
01657 struct availablePackage * r;
01658 struct tsortInfo * tsi;
01659 struct tsortInfo * tsi_next;
01660 int * ordering = alloca(sizeof(*ordering) * (npkgs + 1));
01661 int orderingCount = 0;
01662 unsigned char * selected = alloca(sizeof(*selected) * (npkgs + 1));
01663 int loopcheck;
01664 struct transactionElement * newOrder;
01665 int newOrderCount = 0;
01666 struct orderListIndex * orderList;
01667 int nrescans = 10;
01668 int _printed = 0;
01669 int qlen;
01670 int i, j;
01671
01672 alMakeIndex(&ts->addedPackages);
01673 alMakeIndex(&ts->availablePackages);
01674
01675
01676 loopcheck = npkgs;
01677
01678
01679 rpmMessage(RPMMESS_DEBUG, _("========== recording tsort relations\n"));
01680 for (i = 0, p = ts->addedPackages.list; i < npkgs; i++, p++) {
01681 int matchNum;
01682
01683 if (p->requiresCount <= 0)
01684 continue;
01685
01686 memset(selected, 0, sizeof(*selected) * npkgs);
01687
01688
01689 matchNum = p - ts->addedPackages.list;
01690 selected[matchNum] = 1;
01691
01692
01693
01694
01695 for (j = 0; j < p->requiresCount; j++) {
01696
01697
01698
01699 if (isErasePreReq(p->requireFlags[j]) ||
01700 !( isInstallPreReq(p->requireFlags[j]) ||
01701 isLegacyPreReq(p->requireFlags[j]) ))
01702 continue;
01703
01704
01705 (void) addRelation(ts, p, selected, j);
01706
01707 }
01708
01709
01710 for (j = 0; j < p->requiresCount; j++) {
01711
01712
01713
01714 if (isErasePreReq(p->requireFlags[j]) ||
01715 ( isInstallPreReq(p->requireFlags[j]) ||
01716 isLegacyPreReq(p->requireFlags[j]) ))
01717 continue;
01718
01719
01720 (void) addRelation(ts, p, selected, j);
01721
01722 }
01723 }
01724
01725
01726 for (i = 0, p = ts->addedPackages.list; i < npkgs; i++, p++) {
01727 p->npreds = p->tsi.tsi_count;
01728 }
01729
01730
01731 rpmMessage(RPMMESS_DEBUG, _("========== tsorting packages\n"));
01732
01733 rescan:
01734 q = r = NULL;
01735 qlen = 0;
01736 for (i = 0, p = ts->addedPackages.list; i < npkgs; i++, p++) {
01737
01738
01739 if (!chainsaw)
01740 p->tsi.tsi_qcnt = (npkgs - i);
01741
01742 if (p->tsi.tsi_count != 0)
01743 continue;
01744 p->tsi.tsi_suc = NULL;
01745 addQ(p, &q, &r);
01746 qlen++;
01747 }
01748
01749
01750 for (; q != NULL; q = q->tsi.tsi_suc) {
01751
01752 rpmMessage(RPMMESS_DEBUG, "%4d%4d%4d%4d %*s %s-%s-%s\n",
01753 orderingCount, q->npreds, q->tsi.tsi_qcnt, q->depth,
01754 2*q->depth, "",
01755 q->name, q->version, q->release);
01756 ordering[orderingCount++] = q - ts->addedPackages.list;
01757 qlen--;
01758 loopcheck--;
01759
01760
01761 tsi_next = q->tsi.tsi_next;
01762 q->tsi.tsi_next = NULL;
01763 while ((tsi = tsi_next) != NULL) {
01764 tsi_next = tsi->tsi_next;
01765 tsi->tsi_next = NULL;
01766 p = tsi->tsi_suc;
01767 if ((--p->tsi.tsi_count) <= 0) {
01768
01769 p->tsi.tsi_suc = NULL;
01770 addQ(p, &q->tsi.tsi_suc, &r);
01771 qlen++;
01772 }
01773 tsi = _free(tsi);
01774 }
01775 if (!_printed && loopcheck == qlen && q->tsi.tsi_suc != NULL) {
01776 _printed++;
01777 rpmMessage(RPMMESS_DEBUG,
01778 _("========== successors only (presentation order)\n"));
01779 }
01780 }
01781
01782
01783 if (loopcheck != 0) {
01784 int nzaps;
01785
01786
01787 nzaps = 0;
01788 for (i = 0, q = ts->addedPackages.list; i < npkgs; i++, q++) {
01789 q->tsi.tsi_pkg = NULL;
01790 q->tsi.tsi_reqx = 0;
01791
01792 if (q->tsi.tsi_count == 0)
01793 q->tsi.tsi_count = -1;
01794 }
01795
01796
01797 for (i = 0, q = ts->addedPackages.list; i < npkgs; i++, q++) {
01798 if ((tsi = q->tsi.tsi_next) == NULL)
01799 continue;
01800 q->tsi.tsi_next = NULL;
01801 markLoop(tsi, q);
01802 q->tsi.tsi_next = tsi;
01803 }
01804
01805
01806 for (i = 0, r = ts->addedPackages.list; i < npkgs; i++, r++) {
01807 int printed;
01808
01809 printed = 0;
01810
01811
01812 for (q = r->tsi.tsi_pkg; q != NULL; q = q->tsi.tsi_pkg) {
01813 if (q->tsi.tsi_reqx)
01814 break;
01815 q->tsi.tsi_reqx = 1;
01816 }
01817
01818
01819 while ((p = q) != NULL && (q = p->tsi.tsi_pkg) != NULL) {
01820 const char * dp;
01821 char buf[4096];
01822
01823
01824 p->tsi.tsi_pkg = NULL;
01825
01826 if (!printed) {
01827 rpmMessage(RPMMESS_WARNING, _("LOOP:\n"));
01828 printed = 1;
01829 }
01830
01831
01832 dp = zapRelation(q, p, 1, &nzaps);
01833
01834
01835 sprintf(buf, "%s-%s-%s", p->name, p->version, p->release);
01836 rpmMessage(RPMMESS_WARNING, " %-40s %s\n", buf, dp);
01837
01838 dp = _free((void *)dp);
01839 }
01840
01841
01842 for (p = r, q = r->tsi.tsi_pkg;
01843 q != NULL;
01844 p = q, q = q->tsi.tsi_pkg)
01845 {
01846
01847 p->tsi.tsi_pkg = NULL;
01848 p->tsi.tsi_reqx = 0;
01849 }
01850 }
01851
01852
01853
01854 if (nzaps && nrescans-- > 0) {
01855 rpmMessage(RPMMESS_DEBUG, _("========== continuing tsort ...\n"));
01856 goto rescan;
01857 }
01858 return 1;
01859 }
01860
01861
01862
01863
01864
01865
01866
01867 orderList = xmalloc(sizeof(*orderList) * npkgs);
01868 for (i = 0, j = 0; i < ts->orderCount; i++) {
01869 if (ts->order[i].type == TR_ADDED) {
01870 orderList[j].alIndex = ts->order[i].u.addedIndex;
01871 orderList[j].orIndex = i;
01872 j++;
01873 }
01874 }
01875 assert(j <= npkgs);
01876
01877 qsort(orderList, npkgs, sizeof(*orderList), orderListIndexCmp);
01878
01879 newOrder = xmalloc(sizeof(*newOrder) * ts->orderCount);
01880 for (i = 0, newOrderCount = 0; i < orderingCount; i++) {
01881 struct orderListIndex * needle, key;
01882
01883 key.alIndex = ordering[i];
01884 needle = bsearch(&key, orderList, npkgs, sizeof(key),orderListIndexCmp);
01885
01886
01887 newOrder[newOrderCount++] = ts->order[needle->orIndex];
01888 for (j = needle->orIndex + 1; j < ts->orderCount; j++) {
01889 if (ts->order[j].type == TR_REMOVED &&
01890 ts->order[j].u.removed.dependsOnIndex == needle->alIndex) {
01891 newOrder[newOrderCount++] = ts->order[j];
01892 } else {
01893 break;
01894 }
01895 }
01896 }
01897
01898 for (i = 0; i < ts->orderCount; i++) {
01899 if (ts->order[i].type == TR_REMOVED &&
01900 ts->order[i].u.removed.dependsOnIndex == -1) {
01901 newOrder[newOrderCount++] = ts->order[i];
01902 }
01903 }
01904 assert(newOrderCount == ts->orderCount);
01905
01906 ts->order = _free(ts->order);
01907 ts->order = newOrder;
01908 ts->orderAlloced = ts->orderCount;
01909 orderList = _free(orderList);
01910
01911 return 0;
01912 }
01913
01914 int rpmdepCheck(rpmTransactionSet ts,
01915 struct