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