00001
00005
00006 int _depends_debug = 0;
00007
00008
00009 #include "system.h"
00010
00011 #include <rpmlib.h>
00012
00013 #include "depends.h"
00014 #include "rpmdb.h"
00015
00016 #include "debug.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 int headerNVR(Header h, const char **np, const char **vp, const char **rp)
00029 {
00030 int type;
00031 int count;
00032
00033 if (np) {
00034 if (!(headerGetEntry(h, RPMTAG_NAME, &type, (void **) np, &count)
00035 && type == RPM_STRING_TYPE && count == 1))
00036 *np = NULL;
00037 }
00038 if (vp) {
00039 if (!(headerGetEntry(h, RPMTAG_VERSION, &type, (void **) vp, &count)
00040 && type == RPM_STRING_TYPE && count == 1))
00041 *vp = NULL;
00042 }
00043 if (rp) {
00044 if (!(headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) rp, &count)
00045 && type == RPM_STRING_TYPE && count == 1))
00046 *rp = NULL;
00047 }
00048 return 0;
00049 }
00050
00059 static char * printDepend(const char * depend, const char * key,
00060 const char * keyEVR, int keyFlags)
00061
00062 {
00063 char * tbuf, * t;
00064 size_t nb;
00065
00066 nb = 0;
00067 if (depend) nb += strlen(depend) + 1;
00068 if (key) nb += strlen(key);
00069 if (keyFlags & RPMSENSE_SENSEMASK) {
00070 if (nb) nb++;
00071 if (keyFlags & RPMSENSE_LESS) nb++;
00072 if (keyFlags & RPMSENSE_GREATER) nb++;
00073 if (keyFlags & RPMSENSE_EQUAL) nb++;
00074 }
00075 if (keyEVR && *keyEVR) {
00076 if (nb) nb++;
00077 nb += strlen(keyEVR);
00078 }
00079
00080 t = tbuf = xmalloc(nb + 1);
00081 if (depend) {
00082 while(*depend != '\0') *t++ = *depend++;
00083 *t++ = ' ';
00084 }
00085 if (key)
00086 while(*key != '\0') *t++ = *key++;
00087 if (keyFlags & RPMSENSE_SENSEMASK) {
00088 if (t != tbuf) *t++ = ' ';
00089 if (keyFlags & RPMSENSE_LESS) *t++ = '<';
00090 if (keyFlags & RPMSENSE_GREATER) *t++ = '>';
00091 if (keyFlags & RPMSENSE_EQUAL) *t++ = '=';
00092 }
00093 if (keyEVR && *keyEVR) {
00094 if (t != tbuf) *t++ = ' ';
00095 while(*keyEVR != '\0') *t++ = *keyEVR++;
00096 }
00097 *t = '\0';
00098 return tbuf;
00099 }
00100
00101 #ifdef UNUSED
00102 static const char *buildEVR(int_32 *e, const char *v, const char *r)
00103 {
00104 const char *pEVR;
00105 char *p;
00106
00107 pEVR = p = xmalloc(21 + strlen(v) + 1 + strlen(r) + 1);
00108 *p = '\0';
00109 if (e) {
00110 sprintf(p, "%d:", *e);
00111 while (*p)
00112 p++;
00113 }
00114 (void) stpcpy( stpcpy( stpcpy(p, v) , "-") , r);
00115 return pEVR;
00116 }
00117 #endif
00118
00119 struct orderListIndex {
00120 int alIndex;
00121 int orIndex;
00122 };
00123
00128 static void alFreeIndex(availableList al)
00129
00130 {
00131 if (al->index.size) {
00132 al->index.index = _free(al->index.index);
00133 al->index.size = 0;
00134 }
00135 }
00136
00141 static void alCreate(availableList al)
00142
00143 {
00144 al->alloced = al->delta;
00145 al->size = 0;
00146 al->list = xcalloc(al->alloced, sizeof(*al->list));
00147
00148 al->index.index = NULL;
00149 al->index.size = 0;
00150
00151 al->numDirs = 0;
00152 al->dirs = NULL;
00153 }
00154
00159 static void alFree(availableList al)
00160
00161 {
00162 HFD_t hfd = headerFreeData;
00163 struct availablePackage * p;
00164 rpmRelocation * r;
00165 int i;
00166
00167 if ((p = al->list) != NULL)
00168 for (i = 0; i < al->size; i++, p++) {
00169
00170 { struct tsortInfo * tsi;
00171 while ((tsi = p->tsi.tsi_next) != NULL) {
00172 p->tsi.tsi_next = tsi->tsi_next;
00173 tsi->tsi_next = NULL;
00174 tsi = _free(tsi);
00175 }
00176 }
00177
00178 p->provides = hfd(p->provides, -1);
00179 p->providesEVR = hfd(p->providesEVR, -1);
00180 p->requires = hfd(p->requires, -1);
00181 p->requiresEVR = hfd(p->requiresEVR, -1);
00182 p->baseNames = hfd(p->baseNames, -1);
00183 p->h = headerFree(p->h);
00184
00185 if (p->relocs) {
00186 for (r = p->relocs; (r->oldPath || r->newPath); r++) {
00187 r->oldPath = _free(r->oldPath);
00188 r->newPath = _free(r->newPath);
00189 }
00190 p->relocs = _free(p->relocs);
00191 }
00192 if (p->fd != NULL)
00193 p->fd = fdFree(p->fd, "alAddPackage (alFree)");
00194 }
00195
00196 if (al->dirs != NULL)
00197 for (i = 0; i < al->numDirs; i++) {
00198 al->dirs[i].dirName = _free(al->dirs[i].dirName);
00199 al->dirs[i].files = _free(al->dirs[i].files);
00200 }
00201
00202 al->dirs = _free(al->dirs);
00203 al->numDirs = 0;
00204 al->list = _free(al->list);
00205 al->alloced = 0;
00206 alFreeIndex(al);
00207 }
00208
00215 static int dirInfoCompare(const void * one, const void * two)
00216 {
00217 const dirInfo a = (const dirInfo) one;
00218 const dirInfo b = (const dirInfo) two;
00219 int lenchk = a->dirNameLen - b->dirNameLen;
00220
00221 if (lenchk)
00222 return lenchk;
00223
00224
00225 return strcmp(a->dirName, b->dirName);
00226 }
00227
00237 static struct availablePackage *
00238 alAddPackage(availableList al,
00239 Header h, const void * key,
00240 FD_t fd, rpmRelocation * relocs)
00241
00242 {
00243 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00244 HFD_t hfd = headerFreeData;
00245 rpmTagType dnt, bnt;
00246 struct availablePackage * p;
00247 rpmRelocation * r;
00248 int i;
00249 int_32 * dirIndexes;
00250 const char ** dirNames;
00251 int numDirs, dirNum;
00252 int * dirMapping;
00253 struct dirInfo_s dirNeedle;
00254 dirInfo dirMatch;
00255 int first, last, fileNum;
00256 int origNumDirs;
00257 int pkgNum;
00258 uint_32 multiLibMask = 0;
00259 uint_32 * fileFlags = NULL;
00260 uint_32 * pp = NULL;
00261
00262 if (al->size == al->alloced) {
00263 al->alloced += al->delta;
00264 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
00265 }
00266
00267 pkgNum = al->size++;
00268 p = al->list + pkgNum;
00269 p->h = headerLink(h);
00270 p->depth = p->npreds = 0;
00271 memset(&p->tsi, 0, sizeof(p->tsi));
00272 p->multiLib = 0;
00273
00274 (void) headerNVR(p->h, &p->name, &p->version, &p->release);
00275
00276
00277
00278
00279
00280 if (hge(p->h, RPMTAG_MULTILIBS, NULL, (void **) &pp, NULL))
00281 multiLibMask = *pp;
00282
00283 if (multiLibMask) {
00284 for (i = 0; i < pkgNum - 1; i++) {
00285 if (!strcmp (p->name, al->list[i].name)
00286 && hge(al->list[i].h, RPMTAG_MULTILIBS, NULL,
00287 (void **) &pp, NULL)
00288 && !rpmVersionCompare(p->h, al->list[i].h)
00289 && *pp && !(*pp & multiLibMask))
00290 p->multiLib = multiLibMask;
00291 }
00292 }
00293
00294 if (!hge(h, RPMTAG_EPOCH, NULL, (void **) &p->epoch, NULL))
00295 p->epoch = NULL;
00296
00297 if (!hge(h, RPMTAG_PROVIDENAME, NULL, (void **) &p->provides,
00298 &p->providesCount)) {
00299 p->providesCount = 0;
00300 p->provides = NULL;
00301 p->providesEVR = NULL;
00302 p->provideFlags = NULL;
00303 } else {
00304 if (!hge(h, RPMTAG_PROVIDEVERSION,
00305 NULL, (void **) &p->providesEVR, NULL))
00306 p->providesEVR = NULL;
00307 if (!hge(h, RPMTAG_PROVIDEFLAGS,
00308 NULL, (void **) &p->provideFlags, NULL))
00309 p->provideFlags = NULL;
00310 }
00311
00312 if (!hge(h, RPMTAG_REQUIRENAME, NULL, (void **) &p->requires,
00313 &p->requiresCount)) {
00314 p->requiresCount = 0;
00315 p->requires = NULL;
00316 p->requiresEVR = NULL;
00317 p->requireFlags = NULL;
00318 } else {
00319 if (!hge(h, RPMTAG_REQUIREVERSION,
00320 NULL, (void **) &p->requiresEVR, NULL))
00321 p->requiresEVR = NULL;
00322 if (!hge(h, RPMTAG_REQUIREFLAGS,
00323 NULL, (void **) &p->requireFlags, NULL))
00324 p->requireFlags = NULL;
00325 }
00326
00327 if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **)&p->baseNames, &p->filesCount))
00328 {
00329 p->filesCount = 0;
00330 p->baseNames = NULL;
00331 } else {
00332 (void) hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, &numDirs);
00333 (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00334 (void) hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlags, NULL);
00335
00336
00337
00338 dirMapping = alloca(sizeof(*dirMapping) * numDirs);
00339
00340
00341
00342 al->dirs = xrealloc(al->dirs,
00343 sizeof(*al->dirs) * (al->numDirs + numDirs));
00344 origNumDirs = al->numDirs;
00345
00346 for (dirNum = 0; dirNum < numDirs; dirNum++) {
00347 dirNeedle.dirName = (char *) dirNames[dirNum];
00348 dirNeedle.dirNameLen = strlen(dirNames[dirNum]);
00349 dirMatch = bsearch(&dirNeedle, al->dirs, origNumDirs,
00350 sizeof(dirNeedle), dirInfoCompare);
00351 if (dirMatch) {
00352 dirMapping[dirNum] = dirMatch - al->dirs;
00353 } else {
00354 dirMapping[dirNum] = al->numDirs;
00355 al->dirs[al->numDirs].dirName = xstrdup(dirNames[dirNum]);
00356 al->dirs[al->numDirs].dirNameLen = strlen(dirNames[dirNum]);
00357 al->dirs[al->numDirs].files = NULL;
00358 al->dirs[al->numDirs].numFiles = 0;
00359 al->numDirs++;
00360 }
00361 }
00362
00363 dirNames = hfd(dirNames, dnt);
00364
00365 first = 0;
00366 while (first < p->filesCount) {
00367 last = first;
00368 while ((last + 1) < p->filesCount) {
00369 if (dirIndexes[first] != dirIndexes[last + 1])
00370 break;
00371 last++;
00372 }
00373
00374 dirMatch = al->dirs + dirMapping[dirIndexes[first]];
00375 dirMatch->files = xrealloc(dirMatch->files,
00376 sizeof(*dirMatch->files) *
00377 (dirMatch->numFiles + last - first + 1));
00378 for (fileNum = first; fileNum <= last; fileNum++) {
00379 dirMatch->files[dirMatch->numFiles].baseName =
00380 p->baseNames[fileNum];
00381 dirMatch->files[dirMatch->numFiles].pkgNum = pkgNum;
00382 dirMatch->files[dirMatch->numFiles].fileFlags =
00383 fileFlags[fileNum];
00384 dirMatch->numFiles++;
00385 }
00386
00387 first = last + 1;
00388 }
00389
00390 if (origNumDirs + al->numDirs)
00391 qsort(al->dirs, al->numDirs, sizeof(dirNeedle), dirInfoCompare);
00392
00393 }
00394
00395 p->key = key;
00396 p->fd = (fd != NULL ? fdLink(fd, "alAddPackage") : NULL);
00397
00398 if (relocs) {
00399 for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++)
00400 {};
00401 p->relocs = xmalloc((i + 1) * sizeof(*p->relocs));
00402
00403 for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
00404 p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
00405 p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
00406 }
00407 p->relocs[i].oldPath = NULL;
00408 p->relocs[i].newPath = NULL;
00409 } else {
00410 p->relocs = NULL;
00411 }
00412
00413 alFreeIndex(al);
00414
00415 return p;
00416 }
00417
00424 static int indexcmp(const void * one, const void * two)
00425 {
00426 const struct availableIndexEntry * a = one;
00427 const struct availableIndexEntry * b = two;
00428 int lenchk = a->entryLen - b->entryLen;
00429
00430 if (lenchk)
00431 return lenchk;
00432
00433 return strcmp(a->entry, b->entry);
00434 }
00435
00440 static void alMakeIndex(availableList al)
00441
00442 {
00443 struct availableIndex * ai = &al->index;
00444 int i, j, k;
00445
00446 if (ai->size || al->list == NULL) return;
00447
00448 for (i = 0; i < al->size; i++)
00449 ai->size += al->list[i].providesCount;
00450
00451 if (ai->size) {
00452 ai->index = xcalloc(ai->size, sizeof(*ai->index));
00453
00454 k = 0;
00455 for (i = 0; i < al->size; i++) {
00456 for (j = 0; j < al->list[i].providesCount; j++) {
00457
00458
00459 if (al->list[i].multiLib &&
00460 !isDependsMULTILIB(al->list[i].provideFlags[j])) {
00461 ai->size--;
00462 continue;
00463 }
00464
00465 ai->index[k].package = al->list + i;
00466 ai->index[k].entry = al->list[i].provides[j];
00467 ai->index[k].entryLen = strlen(al->list[i].provides[j]);
00468 ai->index[k].type = IET_PROVIDES;
00469 k++;
00470 }
00471 }
00472
00473 qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00474 }
00475 }
00476
00484 static void parseEVR(char * evr,
00485 const char ** ep,
00486 const char ** vp,
00487 const char ** rp)
00488
00489 {
00490 const char *epoch;
00491 const char *version;
00492 const char *release;
00493 char *s, *se;
00494
00495 s = evr;
00496 while (*s && xisdigit(*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 aEVR = _free(aEVR);
00577 bEVR = _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 aDepend = _free(aDepend);
00596 bDepend = _free(bDepend);
00597 return result;
00598 }
00599
00600
00601 typedef int (*dbrecMatch_t) (Header h, const char *reqName, const char * reqEVR, int reqFlags);
00602
00603
00604 static int rangeMatchesDepFlags (Header h,
00605 const char * reqName, const char * reqEVR, int reqFlags)
00606
00607 {
00608 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00609 HFD_t hfd = headerFreeData;
00610 rpmTagType pnt, pvt;
00611 const char ** provides;
00612 const char ** providesEVR;
00613 int_32 * provideFlags;
00614 int providesCount;
00615 int result;
00616 int i;
00617
00618 if (!(reqFlags & RPMSENSE_SENSEMASK) || !reqEVR || !strlen(reqEVR))
00619 return 1;
00620
00621
00622
00623
00624
00625
00626 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt,
00627 (void **) &providesEVR, &providesCount))
00628 return 1;
00629
00630 (void) hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
00631
00632 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
00633 {
00634 providesEVR = hfd(providesEVR, pvt);
00635 return 0;
00636 }
00637
00638 result = 0;
00639 for (i = 0; i < providesCount; i++) {
00640
00641
00642 if (strcmp(provides[i], reqName))
00643 continue;
00644
00645 result = rpmRangesOverlap(provides[i], providesEVR[i], provideFlags[i],
00646 reqName, reqEVR, reqFlags);
00647
00648
00649 if (result)
00650 break;
00651 }
00652
00653 provides = hfd(provides, pnt);
00654 providesEVR = hfd(providesEVR, pvt);
00655
00656 return result;
00657 }
00658
00659 int headerMatchesDepFlags(Header h,
00660 const char * reqName, const char * reqEVR, int reqFlags)
00661 {
00662 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00663 const char *name, *version, *release;
00664 int_32 * epoch;
00665 const char *pkgEVR;
00666 char *p;
00667 int pkgFlags = RPMSENSE_EQUAL;
00668
00669 if (!((reqFlags & RPMSENSE_SENSEMASK) && reqEVR && *reqEVR))
00670 return 1;
00671
00672
00673 (void) headerNVR(h, &name, &version, &release);
00674
00675 pkgEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00676 *p = '\0';
00677 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00678 sprintf(p, "%d:", *epoch);
00679 while (*p != '\0')
00680 p++;
00681 }
00682 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00683
00684 return rpmRangesOverlap(name, pkgEVR, pkgFlags, reqName, reqEVR, reqFlags);
00685 }
00686
00687 rpmTransactionSet rpmtransCreateSet(rpmdb rpmdb, const char * rootDir)
00688 {
00689 rpmTransactionSet ts;
00690 int rootLen;
00691
00692 if (!rootDir) rootDir = "";
00693
00694 ts = xcalloc(1, sizeof(*ts));
00695 ts->filesystemCount = 0;
00696 ts->filesystems = NULL;
00697 ts->di = NULL;
00698
00699 ts->rpmdb = rpmdb;
00700
00701 ts->scriptFd = NULL;
00702 ts->id = 0;
00703 ts->delta = 5;
00704
00705 ts->numRemovedPackages = 0;
00706 ts->allocedRemovedPackages = ts->delta;
00707 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
00708 sizeof(*ts->removedPackages));
00709
00710
00711 rootLen = strlen(rootDir);
00712 if (!(rootLen && rootDir[rootLen - 1] == '/')) {
00713 char * t;
00714
00715 t = alloca(rootLen + 2);
00716 *t = '\0';
00717 (void) stpcpy( stpcpy(t, rootDir), "/");
00718 rootDir = t;
00719 }
00720
00721 ts->rootDir = xstrdup(rootDir);
00722 ts->currDir = NULL;
00723 ts->chrootDone = 0;
00724
00725 ts->addedPackages.delta = ts->delta;
00726 alCreate(&ts->addedPackages);
00727 ts->availablePackages.delta = ts->delta;
00728 alCreate(&ts->availablePackages);
00729
00730 ts->orderAlloced = ts->delta;
00731 ts->orderCount = 0;
00732 ts->order = xcalloc(ts->orderAlloced, sizeof(*ts->order));
00733
00734 return ts;
00735 }
00736
00743 static int intcmp(const void * a, const void * b)
00744 {
00745 const int * aptr = a;
00746 const int * bptr = b;
00747 int rc = (*aptr - *bptr);
00748 return rc;
00749 }
00750
00758 static int removePackage(rpmTransactionSet ts, int dboffset, int depends)
00759
00760 {
00761
00762
00763 if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) {
00764 if (bsearch(&dboffset, ts->removedPackages, ts->numRemovedPackages,
00765 sizeof(int), intcmp) != NULL)
00766 return 0;
00767 }
00768
00769 if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
00770 ts->allocedRemovedPackages += ts->delta;
00771 ts->removedPackages = xrealloc(ts->removedPackages,
00772 sizeof(int *) * ts->allocedRemovedPackages);
00773 }
00774
00775 if (ts->removedPackages != NULL) {
00776 ts->removedPackages[ts->numRemovedPackages++] = dboffset;
00777 qsort(ts->removedPackages, ts->numRemovedPackages, sizeof(int), intcmp);
00778 }
00779
00780 if (ts->orderCount == ts->orderAlloced) {
00781 ts->orderAlloced += ts->delta;
00782 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00783 }
00784
00785 ts->order[ts->orderCount].type = TR_REMOVED;
00786 ts->order[ts->orderCount].u.removed.dboffset = dboffset;
00787 ts->order[ts->orderCount++].u.removed.dependsOnIndex = depends;
00788
00789 return 0;
00790 }
00791
00792 int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
00793 const void * key, int upgrade, rpmRelocation * relocs)
00794 {
00795 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00796 HFD_t hfd = headerFreeData;
00797 rpmTagType ont, ovt;
00798
00799 const char * name;
00800 int count;
00801 const char ** obsoletes;
00802 int alNum;
00803
00804
00805
00806
00807
00808
00809
00810 if (ts->orderCount == ts->orderAlloced) {
00811 ts->orderAlloced += ts->delta;
00812 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00813 }
00814 ts->order[ts->orderCount].type = TR_ADDED;
00815 if (ts->addedPackages.list == NULL)
00816 return 0;
00817
00818 alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
00819 ts->addedPackages.list;
00820 ts->order[ts->orderCount++].u.addedIndex = alNum;
00821
00822 if (!upgrade || ts->rpmdb == NULL)
00823 return 0;
00824
00825
00826 if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
00827 return 0;
00828
00829 (void) headerNVR(h, &name, NULL, NULL);
00830
00831 { rpmdbMatchIterator mi;
00832 Header h2;
00833
00834 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, name, 0);
00835 while((h2 = rpmdbNextIterator(mi)) != NULL) {
00836 if (rpmVersionCompare(h, h2))
00837 (void) removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
00838 else {
00839 uint_32 *p, multiLibMask = 0, oldmultiLibMask = 0;
00840
00841 if (hge(h2, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL))
00842 oldmultiLibMask = *p;
00843 if (hge(h, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL))
00844 multiLibMask = *p;
00845 if (oldmultiLibMask && multiLibMask
00846 && !(oldmultiLibMask & multiLibMask)) {
00847 ts->addedPackages.list[alNum].multiLib = multiLibMask;
00848 }
00849 }
00850 }
00851 mi = rpmdbFreeIterator(mi);
00852 }
00853
00854 if (hge(h, RPMTAG_OBSOLETENAME, &ont, (void **) &obsoletes, &count)) {
00855 const char ** obsoletesEVR;
00856 int_32 * obsoletesFlags;
00857 int j;
00858
00859 (void) hge(h, RPMTAG_OBSOLETEVERSION, &ovt, (void **) &obsoletesEVR,
00860 NULL);
00861 (void) hge(h, RPMTAG_OBSOLETEFLAGS, NULL, (void **) &obsoletesFlags,
00862 NULL);
00863
00864 for (j = 0; j < count; j++) {
00865
00866
00867 if (!strcmp(name, obsoletes[j]))
00868 continue;
00869
00870 { rpmdbMatchIterator mi;
00871 Header h2;
00872
00873 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, obsoletes[j], 0);
00874
00875 (void) rpmdbPruneIterator(mi,
00876 ts->removedPackages, ts->numRemovedPackages, 1);
00877
00878 while((h2 = rpmdbNextIterator(mi)) != NULL) {
00879
00880
00881
00882
00883 if (obsoletesEVR == NULL ||
00884 headerMatchesDepFlags(h2,
00885 obsoletes[j], obsoletesEVR[j], obsoletesFlags[j]))
00886 {
00887 (void) removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
00888 }
00889 }
00890 mi = rpmdbFreeIterator(mi);
00891 }
00892 }
00893
00894 obsoletesEVR = hfd(obsoletesEVR, ovt);
00895 obsoletes = hfd(obsoletes, ont);
00896 }
00897
00898 return 0;
00899 }
00900
00901 void rpmtransAvailablePackage(rpmTransactionSet ts, Header h, const void * key)
00902 {
00903 struct availablePackage * al;
00904 al = alAddPackage(&ts->availablePackages, h, key, NULL, NULL);
00905 }
00906
00907 int rpmtransRemovePackage(rpmTransactionSet ts, int dboffset)
00908 {
00909 return removePackage(ts, dboffset, -1);
00910 }
00911
00912 rpmTransactionSet rpmtransFree(rpmTransactionSet ts)
00913 {
00914 if (ts) {
00915 alFree(&ts->addedPackages);
00916 alFree(&ts->availablePackages);
00917 ts->di = _free(ts->di);
00918 ts->removedPackages = _free(ts->removedPackages);
00919 ts->order = _free(ts->order);
00920 if (ts->scriptFd != NULL)
00921 ts->scriptFd =
00922 fdFree(ts->scriptFd, "rpmtransSetScriptFd (rpmtransFree");
00923 ts->rootDir = _free(ts->rootDir);
00924 ts->currDir = _free(ts->currDir);
00925
00926 ts = _free(ts);
00927 }
00928 return NULL;
00929 }
00930
00931 rpmDependencyConflict rpmdepFreeConflicts(rpmDependencyConflict conflicts,
00932 int numConflicts)
00933 {
00934 int i;
00935
00936 if (conflicts)
00937 for (i = 0; i < numConflicts; i++) {
00938 conflicts[i].byHeader = headerFree(conflicts[i].byHeader);
00939 conflicts[i].byName = _free(conflicts[i].byName);
00940 conflicts[i].byVersion = _free(conflicts[i].byVersion);
00941 conflicts[i].byRelease = _free(conflicts[i].byRelease);
00942 conflicts[i].needsName = _free(conflicts[i].needsName);
00943 conflicts[i].needsVersion = _free(conflicts[i].needsVersion);
00944 conflicts[i].suggestedPackages = _free(conflicts[i].suggestedPackages);
00945 }
00946
00947 return (conflicts = _free(conflicts));
00948 }
00949
00957 static struct availablePackage **
00958 alAllFileSatisfiesDepend(const availableList al,
00959 const char * keyType, const char * fileName)
00960
00961 {
00962 int i, found;
00963 const char * dirName;
00964 const char * baseName;
00965 struct dirInfo_s dirNeedle;
00966 dirInfo dirMatch;
00967 struct availablePackage ** ret;
00968
00969
00970 if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
00971 return NULL;
00972
00973 { char * t;
00974 dirName = t = xstrdup(fileName);
00975 if ((t = strrchr(t, '/')) != NULL) {
00976 t++;
00977 *t = '\0';
00978 }
00979 }
00980
00981 dirNeedle.dirName = (char *) dirName;
00982 dirNeedle.dirNameLen = strlen(dirName);
00983 dirMatch = bsearch(&dirNeedle, al->dirs, al->numDirs,
00984 sizeof(dirNeedle), dirInfoCompare);
00985 if (dirMatch == NULL) {
00986 dirName = _free(dirName);
00987 return NULL;
00988 }
00989
00990
00991 while (dirMatch > al->dirs && dirInfoCompare(dirMatch-1, &dirNeedle) == 0)
00992 dirMatch--;
00993
00994
00995 baseName = strrchr(fileName, '/') + 1;
00996
00997
00998 for (found = 0, ret = NULL;
00999 dirMatch <= al->dirs + al->numDirs &&
01000 dirInfoCompare(dirMatch, &dirNeedle) == 0;
01001 dirMatch++)
01002 {
01003
01004 for (i = 0; i < dirMatch->numFiles; i++) {
01005 if (dirMatch->files[i].baseName == NULL ||
01006 strcmp(dirMatch->files[i].baseName, baseName))
01007 continue;
01008
01009
01010
01011
01012
01013 if (al->list[dirMatch->files[i].pkgNum].multiLib &&
01014 !isFileMULTILIB(dirMatch->files[i].fileFlags))
01015 continue;
01016
01017 if (keyType)
01018 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added files)\n"),
01019 keyType, fileName);
01020
01021 ret = xrealloc(ret, (found+2) * sizeof(*ret));
01022 if (ret)
01023 ret[found++] = al->list + dirMatch->files[i].pkgNum;
01024 break;
01025 }
01026 }
01027
01028 dirName = _free(dirName);
01029
01030 if (ret)
01031 ret[found] = NULL;
01032
01033 return ret;
01034 }
01035
01036 #ifdef DYING
01037
01044 static struct availablePackage *
01045 alFileSatisfiesDepend(const availableList al,
01046 const char * keyType, const char * fileName)
01047
01048 {
01049 struct availablePackage * ret;
01050 struct availablePackage ** tmp =
01051 alAllFileSatisfiesDepend(al, keyType, fileName);
01052
01053 if (tmp) {
01054 ret = tmp[0];
01055 tmp = _free(tmp);
01056 return ret;
01057 }
01058 return NULL;
01059 }
01060 #endif
01061
01072 static struct availablePackage **
01073 alAllSatisfiesDepend(const availableList al,
01074 const char * keyType, const char * keyDepend,
01075 const char * keyName, const char * keyEVR, int keyFlags)
01076
01077 {
01078 struct availableIndexEntry needle, * match;
01079 struct availablePackage * p, ** ret = NULL;
01080 int i, rc, found;
01081
01082 if (*keyName == '/') {
01083 ret = alAllFileSatisfiesDepend(al, keyType, keyName);
01084
01085 if (ret != NULL && *ret != NULL)
01086 return ret;
01087 }
01088
01089 if (!al->index.size || al->index.index == NULL) return NULL;
01090
01091 needle.entry = keyName;
01092 needle.entryLen = strlen(keyName);
01093 match = bsearch(&needle, al->index.index, al->index.size,
01094 sizeof(*al->index.index), indexcmp);
01095
01096 if (match == NULL) return NULL;
01097
01098
01099 while (match > al->index.index && indexcmp(match-1,&needle) == 0)
01100 match--;
01101
01102 for (ret = NULL, found = 0;
01103 match <= al->index.index + al->index.size &&
01104 indexcmp(match,&needle) == 0;
01105 match++)
01106 {
01107
01108 p = match->package;
01109 rc = 0;
01110 switch (match->type) {
01111 case IET_PROVIDES:
01112 for (i = 0; i < p->providesCount; i++) {
01113 const char * proEVR;
01114 int proFlags;
01115
01116
01117 if (strcmp(p->provides[i], keyName))
01118 continue;
01119
01120 proEVR = (p->providesEVR ? p->providesEVR[i] : NULL);
01121 proFlags = (p->provideFlags ? p->provideFlags[i] : 0);
01122 rc = rpmRangesOverlap(p->provides[i], proEVR, proFlags,
01123 keyName, keyEVR, keyFlags);
01124 if (rc)
01125 break;
01126 }
01127 if (keyType && keyDepend && rc)
01128 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added provide)\n"),
01129 keyType, keyDepend+2);
01130 break;
01131 }
01132
01133 if (rc) {
01134 ret = xrealloc(ret, (found + 2) * sizeof(*ret));
01135 if (ret)
01136 ret[found++] = p;
01137 }
01138 }
01139
01140 if (ret)
01141 ret[found] = NULL;
01142
01143 return ret;
01144 }
01145
01157 static inline struct availablePackage *
01158 alSatisfiesDepend(const availableList al,
01159 const char * keyType, const char * keyDepend,
01160 const char * keyName, const char * keyEVR, int keyFlags)
01161
01162 {
01163 struct availablePackage * ret;
01164 struct availablePackage ** tmp =
01165 alAllSatisfiesDepend(al, keyType, keyDepend, keyName, keyEVR, keyFlags);
01166
01167 if (tmp) {
01168 ret = tmp[0];
01169 tmp = _free(tmp);
01170 return ret;
01171 }
01172 return NULL;
01173 }
01174
01187 static int unsatisfiedDepend(rpmTransactionSet ts,
01188 const char * keyType, const char * keyDepend,
01189 const char * keyName, const char * keyEVR, int keyFlags,
01190 struct availablePackage *** suggestion)
01191
01192 {
01193 static int _cacheDependsRC = 1;
01194 rpmdbMatchIterator mi;
01195 Header h;
01196 int rc = 0;
01197
01198 if (suggestion) *suggestion = NULL;
01199
01200
01201
01202
01203 if (_cacheDependsRC) {
01204 dbiIndex dbi;
01205 dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
01206 if (dbi == NULL)
01207 _cacheDependsRC = 0;
01208 else {
01209 DBC * dbcursor = NULL;
01210 size_t keylen = strlen(keyDepend);
01211 void * datap = NULL;
01212 size_t datalen = 0;
01213 int xx;
01214 xx = dbiCopen(dbi, &dbcursor, 0);
01215
01216 xx = dbiGet(dbi, dbcursor, (void **)&keyDepend, &keylen, &datap, &datalen, 0);
01217
01218 if (xx == 0 && datap && datalen == 4) {
01219 memcpy(&rc, datap, datalen);
01220 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s %-s (cached)\n"),
01221 keyType, keyDepend, (rc ? _("NO ") : _("YES")));
01222 xx = dbiCclose(dbi, NULL, 0);
01223
01224 if (suggestion && rc == 1)
01225 *suggestion = alAllSatisfiesDepend(&ts->availablePackages,
01226 NULL, NULL, keyName, keyEVR, keyFlags);
01227
01228 return rc;
01229 }
01230 xx = dbiCclose(dbi, dbcursor, 0);
01231 }
01232 }
01233
01234 #ifdef DYING
01235 { static const char noProvidesString[] = "nada";
01236 static const char * rcProvidesString = noProvidesString;
01237 const char * start;
01238 int i;
01239
01240 if (rcProvidesString == noProvidesString)
01241 rcProvidesString = rpmGetVar(RPMVAR_PROVIDES);
01242
01243 if (rcProvidesString != NULL && !(keyFlags & RPMSENSE_SENSEMASK)) {
01244 i = strlen(keyName);
01245
01246 while ((start = strstr(rcProvidesString, keyName))) {
01247
01248 if (xisspace(start[i]) || start[i] == '\0' || start[i] == ',') {
01249 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmrc provides)\n"),
01250 keyType, keyDepend+2);
01251 goto exit;
01252 }
01253 rcProvidesString = start + 1;
01254 }
01255 }
01256 }
01257 #endif
01258
01259
01260
01261
01262
01263
01264 if (!strncmp(keyName, "rpmlib(", sizeof("rpmlib(")-1)) {
01265 if (rpmCheckRpmlibProvides(keyName, keyEVR, keyFlags)) {
01266 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmlib provides)\n"),
01267 keyType, keyDepend+2);
01268 goto exit;
01269 }
01270 goto unsatisfied;
01271 }
01272
01273 if (alSatisfiesDepend(&ts->addedPackages, keyType, keyDepend,
01274 keyName, keyEVR, keyFlags))
01275 {
01276 goto exit;
01277 }
01278
01279
01280 if (ts->rpmdb != NULL) {
01281 if (*keyName == '/') {
01282
01283
01284 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_BASENAMES, keyName, 0);
01285
01286 (void) rpmdbPruneIterator(mi,
01287 ts->removedPackages, ts->numRemovedPackages, 1);
01288
01289 while ((h = rpmdbNextIterator(mi)) != NULL) {
01290 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db files)\n"),
01291 keyType, keyDepend+2);
01292 mi = rpmdbFreeIterator(mi);
01293 goto exit;
01294 }
01295 mi = rpmdbFreeIterator(mi);
01296 }
01297
01298 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_PROVIDENAME, keyName, 0);
01299 (void) rpmdbPruneIterator(mi,
01300 ts->removedPackages, ts->numRemovedPackages, 1);
01301 while ((h = rpmdbNextIterator(mi)) != NULL) {
01302 if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
01303 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db provides)\n"),
01304 keyType, keyDepend+2);
01305 mi = rpmdbFreeIterator(mi);
01306 goto exit;
01307 }
01308 }
01309 mi = rpmdbFreeIterator(mi);
01310
01311 #ifndef DYING
01312 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, keyName, 0);
01313 (void) rpmdbPruneIterator(mi,
01314 ts->removedPackages, ts->numRemovedPackages, 1);
01315 while ((h = rpmdbNextIterator(mi)) != NULL) {
01316 if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
01317 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db package)\n"),
01318 keyType, keyDepend+2);
01319 mi = rpmdbFreeIterator(mi);
01320 goto exit;
01321 }
01322 }
01323 mi = rpmdbFreeIterator(mi);
01324 #endif
01325
01326 }
01327
01328 if (suggestion)
01329 *suggestion = alAllSatisfiesDepend(&ts->availablePackages, NULL, NULL,
01330 keyName, keyEVR, keyFlags);
01331
01332 unsatisfied:
01333 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s NO\n"), keyType, keyDepend+2);
01334 rc = 1;
01335
01336 exit:
01337
01338
01339
01340 if (_cacheDependsRC) {
01341 dbiIndex dbi;
01342 dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
01343 if (dbi == NULL) {
01344 _cacheDependsRC = 0;
01345 } else {
01346 DBC * dbcursor = NULL;
01347 int xx;
01348 xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR);
01349 xx = dbiPut(dbi, dbcursor, keyDepend, strlen(keyDepend), &rc, sizeof(rc), 0);
01350 if (xx)
01351 _cacheDependsRC = 0;
01352 #if 0
01353 else
01354 rpmMessage(RPMMESS_DEBUG, _("%s: (%s, %s) added to Depends cache.\n"), keyType, keyDepend, (rc ? _("NO ") : _("YES")));
01355 #endif
01356 xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR);
01357 }
01358 }
01359 return rc;
01360 }
01361
01371 static int checkPackageDeps(rpmTransactionSet ts, problemsSet psp,
01372 Header h, const char * keyName, uint_32 multiLib)
01373
01374 {
01375 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01376 HFD_t hfd = headerFreeData;
01377 rpmTagType rnt, rvt;
01378 rpmTagType cnt, cvt;
01379 const char * name, * version, * release;
01380 const char ** requires;
01381 const char ** requiresEVR = NULL;
01382 int_32 * requireFlags = NULL;
01383 int requiresCount = 0;
01384 const char ** conflicts;
01385 const char ** conflictsEVR = NULL;
01386 int_32 * conflictFlags = NULL;
01387 int conflictsCount = 0;
01388 rpmTagType type;
01389 int i, rc;
01390 int ourrc = 0;
01391 struct availablePackage ** suggestion;
01392
01393 (void) headerNVR(h, &name, &version, &release);
01394
01395 if (!hge(h, RPMTAG_REQUIRENAME, &rnt, (void **) &requires, &requiresCount))
01396 {
01397 requiresCount = 0;
01398 rvt = RPM_STRING_ARRAY_TYPE;
01399 } else {
01400 (void)hge(h, RPMTAG_REQUIREFLAGS, NULL, (void **) &requireFlags, NULL);
01401 (void)hge(h, RPMTAG_REQUIREVERSION, &rvt, (void **) &requiresEVR, NULL);
01402 }
01403
01404 for (i = 0; i < requiresCount && !ourrc; i++) {
01405 const char * keyDepend;
01406
01407
01408 if (keyName && strcmp(keyName, requires[i]))
01409 continue;
01410
01411
01412
01413 if (multiLib && !isDependsMULTILIB(requireFlags[i]))
01414 continue;
01415
01416 keyDepend = printDepend("R",
01417 requires[i], requiresEVR[i], requireFlags[i]);
01418
01419 rc = unsatisfiedDepend(ts, " Requires", keyDepend,
01420 requires[i], requiresEVR[i], requireFlags[i], &suggestion);
01421
01422 switch (rc) {
01423 case 0:
01424 break;
01425 case 1:
01426 rpmMessage(RPMMESS_DEBUG, _("package %s-%s-%s require not satisfied: %s\n"),
01427 name, version, release, keyDepend+2);
01428
01429 if (psp->num == psp->alloced) {
01430 psp->alloced += 5;
01431 psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
01432 psp->alloced);
01433 }
01434
01435 { rpmDependencyConflict pp = psp->problems + psp->num;
01436 pp->byHeader = headerLink(h);
01437 pp->byName = xstrdup(name);
01438 pp->byVersion = xstrdup(version);
01439 pp->byRelease = xstrdup(release);
01440 pp->needsName = xstrdup(requires[i]);
01441 pp->needsVersion = xstrdup(requiresEVR[i]);
01442 pp->needsFlags = requireFlags[i];
01443 pp->sense = RPMDEP_SENSE_REQUIRES;
01444
01445 if (suggestion) {
01446 int j;
01447 for (j = 0; suggestion[j]; j++)
01448 {};
01449 pp->suggestedPackages =
01450 xmalloc( (j + 1) * sizeof(*pp->suggestedPackages) );
01451 for (j = 0; suggestion[j]; j++)
01452 pp->suggestedPackages[j] = suggestion[j]->key;
01453 pp->suggestedPackages[j] = NULL;
01454 } else {
01455 pp->suggestedPackages = NULL;
01456 }
01457 }
01458
01459 psp->num++;
01460 break;
01461 case 2:
01462 default:
01463 ourrc = 1;
01464 break;
01465 }
01466 keyDepend = _free(keyDepend);
01467 }
01468
01469 if (requiresCount) {
01470 requiresEVR = hfd(requiresEVR, rvt);
01471 requires = hfd(requires, rnt);
01472 }
01473
01474 if (!hge(h, RPMTAG_CONFLICTNAME, &cnt, (void **)&conflicts, &conflictsCount))
01475 {
01476 conflictsCount = 0;
01477 cvt = RPM_STRING_ARRAY_TYPE;
01478 } else {
01479 (void) hge(h, RPMTAG_CONFLICTFLAGS, &type,
01480 (void **) &conflictFlags, &conflictsCount);
01481 (void) hge(h, RPMTAG_CONFLICTVERSION, &cvt,
01482 (void **) &conflictsEVR, &conflictsCount);
01483 }
01484
01485 for (i = 0; i < conflictsCount && !ourrc; i++) {
01486 const char * keyDepend;
01487
01488
01489 if (keyName && strcmp(keyName, conflicts[i]))
01490 continue;
01491
01492
01493
01494 if (multiLib && !isDependsMULTILIB(conflictFlags[i]))
01495 continue;
01496
01497 keyDepend = printDepend("C", conflicts[i], conflictsEVR[i], conflictFlags[i]);
01498
01499 rc = unsatisfiedDepend(ts, "Conflicts", keyDepend,
01500 conflicts[i], conflictsEVR[i], conflictFlags[i], NULL);
01501
01502
01503 switch (rc) {
01504 case 0:
01505 rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
01506 name, keyDepend+2);
01507
01508 if (psp->num == psp->alloced) {
01509 psp->alloced += 5;
01510 psp->problems = xrealloc(psp->problems,
01511 sizeof(*psp->problems) * psp->alloced);
01512 }
01513
01514 { rpmDependencyConflict pp = psp->problems + psp->num;
01515 pp->byHeader = headerLink(h);
01516 pp->byName = xstrdup(name);
01517 pp->byVersion = xstrdup(version);
01518 pp->byRelease = xstrdup(release);
01519 pp->needsName = xstrdup(conflicts[i]);
01520 pp->needsVersion = xstrdup(conflictsEVR[i]);
01521 pp->needsFlags = conflictFlags[i];
01522 pp->sense = RPMDEP_SENSE_CONFLICTS;
01523 pp->suggestedPackages = NULL;
01524 }
01525
01526 psp->num++;
01527 break;
01528 case 1:
01529 break;
01530 case 2:
01531 default:
01532 ourrc = 1;
01533 break;
01534 }
01535 keyDepend = _free(keyDepend);
01536 }
01537
01538 if (conflictsCount) {
01539 conflictsEVR = hfd(conflictsEVR, cvt);
01540 conflicts = hfd(conflicts, cnt);
01541 }
01542
01543 return ourrc;
01544 }
01545
01556 static int checkPackageSet(rpmTransactionSet ts, problemsSet psp,
01557 const char * key, rpmdbMatchIterator mi)
01558
01559 {
01560 Header h;
01561 int rc = 0;
01562
01563 (void) rpmdbPruneIterator(mi,
01564 ts->removedPackages, ts->numRemovedPackages, 1);
01565 while ((h = rpmdbNextIterator(mi)) != NULL) {
01566 if (checkPackageDeps(ts, psp, h, key, 0)) {
01567 rc = 1;
01568 break;
01569 }
01570 }
01571 mi = rpmdbFreeIterator(mi);
01572
01573 return rc;
01574 }
01575
01583 static int checkDependentPackages(rpmTransactionSet ts,
01584 problemsSet psp, const char * key)
01585
01586 {
01587 rpmdbMatchIterator mi;
01588 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_REQUIRENAME, key, 0);
01589 return checkPackageSet(ts, psp, key, mi);
01590 }
01591
01599 static int checkDependentConflicts(rpmTransactionSet ts,
01600 problemsSet psp, const char * key)
01601
01602 {
01603 int rc = 0;
01604
01605 if (ts->rpmdb) {
01606 rpmdbMatchIterator mi;
01607 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_CONFLICTNAME, key, 0);
01608 rc = checkPackageSet(ts, psp, key, mi);
01609 }
01610
01611 return rc;
01612 }
01613
01614
01615
01616
01617
01618 #define DEPENDENCY_WHITEOUT
01619
01620 #if defined(DEPENDENCY_WHITEOUT)
01621 static struct badDeps_s {
01622 const char * pname;
01623 const char * qname;
01624 } badDeps[] = {
01625 { "libtermcap", "bash" },
01626 { "modutils", "vixie-cron" },
01627 { "ypbind", "yp-tools" },
01628 { "ghostscript-fonts", "ghostscript" },
01629
01630 { "libgnomeprint15", "gnome-print" },
01631 { "nautilus", "nautilus-mozilla" },
01632
01633 { "arts", "kdelibs-sound" },
01634
01635 { "pango-gtkbeta-devel", "pango-gtkbeta" },
01636 { "XFree86", "Mesa" },
01637 { "compat-glibc", "db2" },
01638 { "compat-glibc", "db1" },
01639 { "pam", "initscripts" },
01640 { "initscripts", "sysklogd" },
01641
01642 { "egcs-c++", "libstdc++" },
01643
01644 { "pilot-link-devel", "pilot-link" },
01645
01646 { "pam", "pamconfig" },
01647 { NULL, NULL }
01648 };
01649
01650 static int ignoreDep(const struct availablePackage * p,
01651 const struct availablePackage * q)
01652
01653 {
01654 struct badDeps_s * bdp = badDeps;
01655
01656 while (bdp->pname != NULL && bdp->qname != NULL) {
01657 if (!strcmp(p->name, bdp->pname) && !strcmp(q->name, bdp->qname))
01658 return 1;
01659 bdp++;
01660 }
01661 return 0;
01662 }
01663 #endif
01664
01670 static void markLoop( struct tsortInfo * tsi,
01671 struct availablePackage * q)
01672
01673
01674 {
01675 struct availablePackage * p;
01676
01677 while (tsi != NULL && (p = tsi->tsi_suc) != NULL) {
01678 tsi = tsi->tsi_next;
01679 if (p->tsi.tsi_pkg != NULL)
01680 continue;
01681 p->tsi.tsi_pkg = q;
01682 if (p->tsi.tsi_next != NULL)
01683 markLoop(p->tsi.tsi_next, p);
01684 }
01685 }
01686
01687 static inline const char * const identifyDepend(int_32 f)
01688 {
01689 if (isLegacyPreReq(f))
01690 return "PreReq:";
01691 f = _notpre(f);
01692 if (f & RPMSENSE_SCRIPT_PRE)
01693 return "Requires(pre):";
01694 if (f & RPMSENSE_SCRIPT_POST)
01695 return "Requires(post):";
01696 if (f & RPMSENSE_SCRIPT_PREUN)
01697 return "Requires(preun):";
01698 if (f & RPMSENSE_SCRIPT_POSTUN)
01699 return "Requires(postun):";
01700 if (f & RPMSENSE_SCRIPT_VERIFY)
01701 return "Requires(verify):";
01702 if (f & RPMSENSE_FIND_REQUIRES)
01703 return "Requires(auto):";
01704 return "Requires:";
01705 }
01706
01718 static const char *
01719 zapRelation(struct availablePackage * q, struct availablePackage * p,
01720 int zap, int * nzaps)
01721
01722 {
01723 struct tsortInfo * tsi_prev;
01724 struct tsortInfo * tsi;
01725 const char *dp = NULL;
01726
01727 for (tsi_prev = &q->tsi, tsi = q->tsi.tsi_next;
01728 tsi != NULL;
01729
01730
01731 tsi_prev = tsi, tsi = tsi->tsi_next)
01732
01733 {
01734 int j;
01735
01736 if (tsi->tsi_suc != p)
01737 continue;
01738 if (p->requires == NULL) continue;
01739 if (p->requireFlags == NULL) continue;
01740 if (p->requiresEVR == NULL) continue;
01741
01742 j = tsi->tsi_reqx;
01743 dp = printDepend( identifyDepend(p->requireFlags[j]),
01744 p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
01745
01746
01747
01748
01749 if (zap && !(p->requireFlags[j] & RPMSENSE_PREREQ)) {
01750 rpmMessage(RPMMESS_DEBUG,
01751 _("removing %s-%s-%s \"%s\" from tsort relations.\n"),
01752 p->name, p->version, p->release, dp);
01753 p->tsi.tsi_count--;
01754 if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next;
01755 tsi->tsi_next = NULL;
01756 tsi->tsi_suc = NULL;
01757 tsi = _free(tsi);
01758 if (nzaps)
01759 (*nzaps)++;
01760 if (zap)
01761 zap--;
01762 }
01763
01764 break;
01765 }
01766 return dp;
01767 }
01768
01777 static inline int addRelation( const rpmTransactionSet ts,
01778 struct availablePackage * p, unsigned char * selected, int j)
01779
01780 {
01781 struct availablePackage * q;
01782 struct tsortInfo * tsi;
01783 int matchNum;
01784
01785 if (!p->requires || !p->requiresEVR || !p->requireFlags)
01786 return 0;
01787
01788 q = alSatisfiesDepend(&ts->addedPackages, NULL, NULL,
01789 p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
01790
01791
01792 if (q == NULL)
01793 return 0;
01794
01795
01796 if (!strncmp(p->requires[j], "rpmlib(", sizeof("rpmlib(")-1))
01797 return 0;
01798
01799 #if defined(DEPENDENCY_WHITEOUT)
01800
01801 if (ignoreDep(p, q))
01802 return 0;
01803 #endif
01804
01805
01806
01807 matchNum = q - ts->addedPackages.list;
01808 if (selected[matchNum] != 0)
01809 return 0;
01810 selected[matchNum] = 1;
01811
01812
01813 p->tsi.tsi_count++;
01814 if (p->depth <= q->depth)
01815 p->depth = q->depth + 1;
01816
01817 tsi = xmalloc(sizeof(*tsi));
01818 tsi->tsi_suc = p;
01819 tsi->tsi_reqx = j;
01820 tsi->tsi_next = q->tsi.tsi_next;
01821 q->tsi.tsi_next = tsi;
01822 q->tsi.tsi_qcnt++;
01823 return 0;
01824 }
01825
01832 static int orderListIndexCmp(const void * one, const void * two)
01833 {
01834 int a = ((const struct orderListIndex *)one)->alIndex;
01835 int b = ((const struct orderListIndex *)two)->alIndex;
01836 return (a - b);
01837 }
01838
01845 static void addQ(struct availablePackage * p,
01846 struct availablePackage ** qp,
01847 struct availablePackage ** rp)
01848
01849 {
01850 struct availablePackage *q, *qprev;
01851
01852 if ((*rp) == NULL) {
01853 (*rp) = (*qp) = p;
01854 return;
01855 }
01856 for (qprev = NULL, q = (*qp); q != NULL; qprev = q, q = q->tsi.tsi_suc) {
01857 if (q->tsi.tsi_qcnt <= p->tsi.tsi_qcnt)
01858 break;
01859 }
01860 if (qprev == NULL) {
01861 p->tsi.tsi_suc = q;
01862 (*qp) = p;
01863 } else if (q == NULL) {
01864 qprev->tsi.tsi_suc = p;
01865 (*rp) = p;
01866 } else {
01867 p->tsi.tsi_suc = q;
01868 qprev->tsi.tsi_suc = p;
01869 }
01870 }
01871
01872 int rpmdepOrder(rpmTransactionSet ts)
01873 {
01874 int npkgs = ts->addedPackages.size;
01875 int chainsaw = ts->transFlags & RPMTRANS_FLAG_CHAINSAW;
01876 struct availablePackage * p;
01877 struct availablePackage * q;
01878 struct availablePackage * r;
01879 struct tsortInfo * tsi;
01880 struct tsortInfo * tsi_next;
01881 int * ordering = alloca(sizeof(*ordering) * (npkgs + 1));
01882 int orderingCount = 0;
01883 unsigned char * selected = alloca(sizeof(*selected) * (npkgs + 1));
01884 int loopcheck;
01885 struct transactionElement * newOrder;
01886 int newOrderCount = 0;
01887 struct orderListIndex * orderList;
01888 int nrescans = 10;
01889 int _printed = 0;
01890 int qlen;
01891 int i, j;
01892
01893 alMakeIndex(&ts->addedPackages);
01894 alMakeIndex(&ts->availablePackages);
01895
01896
01897 loopcheck = npkgs;
01898
01899
01900 rpmMessage(RPMMESS_DEBUG, _("========== recording tsort relations\n"));
01901 if ((p = ts->addedPackages.list) != NULL)
01902 for (i = 0; i < npkgs; i++, p++) {
01903 int matchNum;
01904
01905 if (p->requiresCount <= 0)
01906 continue;
01907
01908 memset(selected, 0, sizeof(*selected) * npkgs);
01909
01910
01911 matchNum = p - ts->addedPackages.list;
01912 selected[matchNum] = 1;
01913
01914
01915
01916
01917 for (j = 0; j < p->requiresCount; j++) {
01918
01919 if (p->requireFlags == NULL) continue;
01920
01921
01922
01923 if (isErasePreReq(p->requireFlags[j]) ||
01924 !( isInstallPreReq(p->requireFlags[j]) ||
01925 isLegacyPreReq(p->requireFlags[j]) ))
01926 continue;
01927
01928
01929 (void) addRelation(ts, p, selected, j);
01930
01931 }
01932
01933
01934 for (j = 0; j < p->requiresCount; j++) {
01935
01936 if (p->requireFlags == NULL) continue;
01937
01938
01939
01940 if (isErasePreReq(p->requireFlags[j]) ||
01941 ( isInstallPreReq(p->requireFlags[j]) ||
01942 isLegacyPreReq(p->requireFlags[j]) ))
01943 continue;
01944
01945
01946 (void) addRelation(ts, p, selected, j);
01947
01948 }
01949 }
01950
01951
01952 if ((p = ts->addedPackages.list) != NULL)
01953 for (i = 0; i < npkgs; i++, p++) {
01954 p->npreds = p->tsi.tsi_count;
01955 }
01956
01957
01958 rpmMessage(RPMMESS_DEBUG, _("========== tsorting packages (order, #predecessors, #succesors, depth)\n"));
01959
01960 rescan:
01961 q = r = NULL;
01962 qlen = 0;
01963 if ((p = ts->addedPackages.list) != NULL)
01964 for (i = 0; i < npkgs; i++, p++) {
01965
01966
01967 if (!chainsaw)
01968 p->tsi.tsi_qcnt = (npkgs - i);
01969
01970 if (p->tsi.tsi_count != 0)
01971 continue;
01972 p->tsi.tsi_suc = NULL;
01973 addQ(p, &q, &r);
01974 qlen++;
01975 }
01976
01977
01978 for (; q != NULL; q = q->tsi.tsi_suc) {
01979
01980 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%3d %*s %s-%s-%s\n",
01981 orderingCount, q->npreds, q->tsi.tsi_qcnt, q->depth,
01982 2*q->depth, "",
01983 q->name, q->version, q->release);
01984 ordering[orderingCount++] = q - ts->addedPackages.list;
01985 qlen--;
01986 loopcheck--;
01987
01988
01989 tsi_next = q->tsi.tsi_next;
01990 q->tsi.tsi_next = NULL;
01991 while ((tsi = tsi_next) != NULL) {
01992 tsi_next = tsi->tsi_next;
01993 tsi->tsi_next = NULL;
01994 p = tsi->tsi_suc;
01995 if (p && (--p->tsi.tsi_count) <= 0) {
01996
01997 p->tsi.tsi_suc = NULL;
01998
01999 addQ(p, &q->tsi.tsi_suc, &r);
02000
02001 qlen++;
02002 }
02003 tsi = _free(tsi);
02004 }
02005 if (!_printed && loopcheck == qlen && q->tsi.tsi_suc != NULL) {
02006 _printed++;
02007 rpmMessage(RPMMESS_DEBUG,
02008 _("========== successors only (presentation order)\n"));
02009 }
02010 }
02011
02012
02013 if (loopcheck != 0) {
02014 int nzaps;
02015
02016
02017 nzaps = 0;
02018 if ((q = ts->addedPackages.list) != NULL)
02019 for (i = 0; i < npkgs; i++, q++) {
02020 q->tsi.tsi_pkg = NULL;
02021 q->tsi.tsi_reqx = 0;
02022
02023 if (q->tsi.tsi_count == 0)
02024 q->tsi.tsi_count = -1;
02025 }
02026
02027
02028 if ((q = ts->addedPackages.list) != NULL)
02029 for (i = 0; i < npkgs; i++, q++) {
02030 if ((tsi = q->tsi.tsi_next) == NULL)
02031 continue;
02032 q->tsi.tsi_next = NULL;
02033 markLoop(tsi, q);
02034 q->tsi.tsi_next = tsi;
02035 }
02036
02037
02038 if ((r = ts->addedPackages.list) != NULL)
02039 for (i = 0; i < npkgs; i++, r++) {
02040 int printed;
02041
02042 printed = 0;
02043
02044
02045 for (q = r->tsi.tsi_pkg; q != NULL; q = q->tsi.tsi_pkg) {
02046 if (q->tsi.tsi_reqx)
02047 break;
02048 q->tsi.tsi_reqx = 1;
02049 }
02050
02051
02052 while ((p = q) != NULL && (q = p->tsi.tsi_pkg) != NULL) {
02053 const char * dp;
02054 char buf[4096];
02055
02056
02057 p->tsi.tsi_pkg = NULL;
02058
02059 if (!printed) {
02060 rpmMessage(RPMMESS_DEBUG, _("LOOP:\n"));
02061 printed = 1;
02062 }
02063
02064
02065 dp = zapRelation(q, p, 1, &nzaps);
02066
02067
02068 sprintf(buf, "%s-%s-%s", p->name, p->version, p->release);
02069 rpmMessage(RPMMESS_DEBUG, " %-40s %s\n", buf,
02070 (dp ? dp : "not found!?!"));
02071
02072 dp = _free(dp);
02073 }
02074
02075
02076 for (p = r, q = r->tsi.tsi_pkg;
02077 q != NULL;
02078 p = q, q = q->tsi.tsi_pkg)
02079 {
02080
02081 p->tsi.tsi_pkg = NULL;
02082 p->tsi.tsi_reqx = 0;
02083 }
02084 }
02085
02086
02087
02088 if (nzaps && nrescans-- > 0) {
02089 rpmMessage(RPMMESS_DEBUG, _("========== continuing tsort ...\n"));
02090 goto rescan;
02091 }
02092 return 1;
02093 }
02094
02095
02096
02097
02098
02099
02100
02101 orderList = xmalloc(npkgs * sizeof(*orderList));
02102 for (i = 0, j = 0; i < ts->orderCount; i++) {
02103 if (ts->order[i].type == TR_ADDED) {
02104 orderList[j].alIndex = ts->order[i].u.addedIndex;
02105 orderList[j].orIndex = i;
02106 j++;
02107 }
02108 }
02109 assert(j <= npkgs);
02110
02111 qsort(orderList, npkgs, sizeof(*orderList), orderListIndexCmp);
02112
02113 newOrder = xmalloc(ts->orderCount * sizeof(*newOrder));
02114 for (i = 0, newOrderCount = 0; i < orderingCount; i++) {
02115 struct orderListIndex * needle, key;
02116
02117 key.alIndex = ordering[i];
02118 needle = bsearch(&key, orderList, npkgs, sizeof(key),orderListIndexCmp);
02119
02120 if (needle == NULL) continue;
02121
02122 newOrder[newOrderCount++] = ts->order[needle->orIndex];
02123 for (j = needle->orIndex + 1; j < ts->orderCount; j++) {
02124 if (ts->order[j].type == TR_REMOVED &&
02125 ts->order[j].u.removed.dependsOnIndex == needle->alIndex) {
02126 newOrder[newOrderCount++] = ts->order[j];
02127 } else
02128 break;
02129 }
02130 }
02131
02132 for (i = 0; i < ts->orderCount; i++) {
02133 if (ts->order[i].type == TR_REMOVED &&
02134 ts->order[i].u.removed.dependsOnIndex == -1) {
02135 newOrder[newOrderCount++] = ts->order[i];
02136 }
02137 }
02138 assert(newOrderCount == ts->orderCount);
02139
02140 ts->order = _free(ts->order);
02141 ts->order = newOrder;
02142 ts->orderAlloced = ts->orderCount;
02143 orderList = _free(orderList);
02144
02145 return 0;
02146 }
02147
02148 int rpmdepCheck(rpmTransactionSet ts,
02149 rpmDependencyConflict * conflicts, int * numConflicts)
02150 {
02151 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
02152 HFD_t hfd = headerFreeData;
02153 rpmdbMatchIterator mi = NULL;
02154 Header h = NULL;
02155 struct availablePackage * p;
02156 problemsSet ps;
02157 int npkgs;
02158 int i, j;
02159 int rc;
02160
02161 npkgs = ts->addedPackages.size;
02162
02163 ps = xcalloc(1, sizeof(*ps));
02164 ps->alloced = 5;
02165 ps->num = 0;
02166 ps->problems = xcalloc(ps->alloced, sizeof(*ps->problems));
02167
02168 *conflicts = NULL;
02169 *numConflicts = 0;
02170
02171 alMakeIndex(&ts->addedPackages);
02172 alMakeIndex(&ts->availablePackages);
02173
02174
02175
02176
02177
02178 if ((p = ts->addedPackages.list) != NULL)
02179 for (i = 0; i < npkgs; i++, p++)
02180 {
02181
02182 rpmMessage(RPMMESS_DEBUG, ("========== +++ %s-%s-%s\n"),
02183 p->name, p->version, p->release);
02184 rc = checkPackageDeps(ts, ps, p->h, NULL, p->multiLib);
02185 if (rc)
02186 goto exit;
02187
02188
02189 rc = checkDependentConflicts(ts, ps, p->name);
02190 if (rc)
02191 goto exit;
02192
02193 if (p->providesCount == 0 || p->provides == NULL)
02194 continue;
02195
02196 rc = 0;
02197 for (j = 0; j < p->providesCount; j++) {
02198
02199 if (!checkDependentConflicts(ts, ps, p->provides[j]))
02200 continue;
02201 rc = 1;
02202 break;
02203 }
02204 if (rc)
02205 goto exit;
02206 }
02207
02208
02209
02210
02211 if (ts->numRemovedPackages > 0) {
02212 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
02213 (void) rpmdbAppendIterator(mi,
02214 ts->removedPackages, ts->numRemovedPackages);
02215 while ((h = rpmdbNextIterator(mi)) != NULL) {
02216
02217 { const char * name, * version, * release;
02218 (void) headerNVR(h, &name, &version, &release);
02219 rpmMessage(RPMMESS_DEBUG, ("========== --- %s-%s-%s\n"),
02220 name, version, release);
02221
02222
02223 rc = checkDependentPackages(ts, ps, name);
02224 if (rc)
02225 goto exit;
02226 }
02227
02228 { const char ** provides;
02229 int providesCount;
02230 rpmTagType pnt;
02231
02232 if (hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides,
02233 &providesCount))
02234 {
02235 rc = 0;
02236 for (j = 0; j < providesCount; j++) {
02237
02238 if (!checkDependentPackages(ts, ps, provides[j]))
02239 continue;
02240 rc = 1;
02241 break;
02242 }
02243 provides = hfd(provides, pnt);
02244 if (rc)
02245 goto exit;
02246 }
02247 }
02248
02249 { const char ** baseNames, ** dirNames;
02250 int_32 * dirIndexes;
02251 rpmTagType dnt, bnt;
02252 int fileCount;
02253 char * fileName = NULL;
02254 int fileAlloced = 0;
02255 int len;
02256
02257 if (hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &fileCount))
02258 {
02259 (void) hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL);
02260 (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes,
02261 NULL);
02262 rc = 0;
02263 for (j = 0; j < fileCount; j++) {
02264 len = strlen(baseNames[j]) + 1 +
02265 strlen(dirNames[dirIndexes[j]]);
02266 if (len > fileAlloced) {
02267 fileAlloced = len * 2;
02268 fileName = xrealloc(fileName, fileAlloced);
02269 }
02270 *fileName = '\0';
02271 (void) stpcpy( stpcpy(fileName, dirNames[dirIndexes[j]]) , baseNames[j]);
02272
02273 if (!checkDependentPackages(ts, ps, fileName))
02274 continue;
02275 rc = 1;
02276 break;
02277 }
02278
02279 fileName = _free(fileName);
02280 baseNames = hfd(baseNames, bnt);
02281 dirNames = hfd(dirNames, dnt);
02282 if (rc)
02283 goto exit;
02284 }
02285 }
02286
02287 }
02288 mi = rpmdbFreeIterator(mi);
02289 }
02290
02291 if (ps->num) {
02292 *conflicts = ps->problems;
02293 ps->problems = NULL;
02294 *numConflicts = ps->num;
02295 }
02296 rc = 0;
02297
02298 exit:
02299 mi = rpmdbFreeIterator(mi);
02300 ps->problems = _free(ps->problems);
02301 ps = _free(ps);
02302 return rc;
02303 }