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