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