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
00489 static void parseEVR(char * evr,
00490 const char ** ep,
00491 const char ** vp,
00492 const char ** rp)
00493
00494 {
00495 const char *epoch;
00496 const char *version;
00497 const char *release;
00498 char *s, *se;
00499
00500 s = evr;
00501 while (*s && xisdigit(*s)) s++;
00502 se = strrchr(s, '-');
00503
00504 if (*s == ':') {
00505 epoch = evr;
00506 *s++ = '\0';
00507 version = s;
00508 if (*epoch == '\0') epoch = "0";
00509 } else {
00510 epoch = NULL;
00511 version = evr;
00512 }
00513 if (se) {
00514 *se++ = '\0';
00515 release = se;
00516 } else {
00517 release = NULL;
00518 }
00519
00520 if (ep) *ep = epoch;
00521 if (vp) *vp = version;
00522 if (rp) *rp = release;
00523 }
00524
00525 const char *rpmNAME = PACKAGE;
00526 const char *rpmEVR = VERSION;
00527 int rpmFLAGS = RPMSENSE_EQUAL;
00528
00529 int rpmRangesOverlap(const char * AName, const char * AEVR, int AFlags,
00530 const char * BName, const char * BEVR, int BFlags)
00531 {
00532 const char *aDepend = printDepend(NULL, AName, AEVR, AFlags);
00533 const char *bDepend = printDepend(NULL, BName, BEVR, BFlags);
00534 char *aEVR, *bEVR;
00535 const char *aE, *aV, *aR, *bE, *bV, *bR;
00536 int result;
00537 int sense;
00538
00539
00540 if (strcmp(AName, BName)) {
00541 result = 0;
00542 goto exit;
00543 }
00544
00545
00546 if (!((AFlags & RPMSENSE_SENSEMASK) && (BFlags & RPMSENSE_SENSEMASK))) {
00547 result = 1;
00548 goto exit;
00549 }
00550
00551
00552 if (!(AEVR && *AEVR && BEVR && *BEVR)) {
00553 result = 1;
00554 goto exit;
00555 }
00556
00557
00558 aEVR = xstrdup(AEVR);
00559 parseEVR(aEVR, &aE, &aV, &aR);
00560 bEVR = xstrdup(BEVR);
00561 parseEVR(bEVR, &bE, &bV, &bR);
00562
00563
00564 sense = 0;
00565 if (aE && *aE && bE && *bE)
00566 sense = rpmvercmp(aE, bE);
00567 else if (aE && *aE && atol(aE) > 0) {
00568
00569 rpmMessage(RPMMESS_DEBUG, _("the \"B\" dependency needs an epoch (assuming same as \"A\")\n\tA %s\tB %s\n"),
00570 aDepend, bDepend);
00571 sense = 0;
00572 } else if (bE && *bE && atol(bE) > 0)
00573 sense = -1;
00574
00575 if (sense == 0) {
00576 sense = rpmvercmp(aV, bV);
00577 if (sense == 0 && aR && *aR && bR && *bR) {
00578 sense = rpmvercmp(aR, bR);
00579 }
00580 }
00581 aEVR = _free(aEVR);
00582 bEVR = _free(bEVR);
00583
00584
00585 result = 0;
00586 if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) {
00587 result = 1;
00588 } else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) {
00589 result = 1;
00590 } else if (sense == 0 &&
00591 (((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) ||
00592 ((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) ||
00593 ((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) {
00594 result = 1;
00595 }
00596
00597 exit:
00598 rpmMessage(RPMMESS_DEBUG, _(" %s A %s\tB %s\n"),
00599 (result ? _("YES") : _("NO ")), aDepend, bDepend);
00600 aDepend = _free(aDepend);
00601 bDepend = _free(bDepend);
00602 return result;
00603 }
00604
00605
00606 typedef int (*dbrecMatch_t) (Header h, const char *reqName, const char * reqEVR, int reqFlags);
00607
00608
00609 static int rangeMatchesDepFlags (Header h,
00610 const char * reqName, const char * reqEVR, int reqFlags)
00611
00612 {
00613 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00614 HFD_t hfd = headerFreeData;
00615 rpmTagType pnt, pvt;
00616 const char ** provides;
00617 const char ** providesEVR;
00618 int_32 * provideFlags;
00619 int providesCount;
00620 int result;
00621 int i;
00622
00623 if (!(reqFlags & RPMSENSE_SENSEMASK) || !reqEVR || !strlen(reqEVR))
00624 return 1;
00625
00626
00627
00628
00629
00630
00631 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt,
00632 (void **) &providesEVR, &providesCount))
00633 return 1;
00634
00635 (void) hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
00636
00637 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
00638 {
00639 providesEVR = hfd(providesEVR, pvt);
00640 return 0;
00641 }
00642
00643 result = 0;
00644 for (i = 0; i < providesCount; i++) {
00645
00646
00647 if (strcmp(provides[i], reqName))
00648 continue;
00649
00650 result = rpmRangesOverlap(provides[i], providesEVR[i], provideFlags[i],
00651 reqName, reqEVR, reqFlags);
00652
00653
00654 if (result)
00655 break;
00656 }
00657
00658 provides = hfd(provides, pnt);
00659 providesEVR = hfd(providesEVR, pvt);
00660
00661 return result;
00662 }
00663
00664 int headerMatchesDepFlags(Header h,
00665 const char * reqName, const char * reqEVR, int reqFlags)
00666 {
00667 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00668 const char *name, *version, *release;
00669 int_32 * epoch;
00670 const char *pkgEVR;
00671 char *p;
00672 int pkgFlags = RPMSENSE_EQUAL;
00673
00674 if (!((reqFlags & RPMSENSE_SENSEMASK) && reqEVR && *reqEVR))
00675 return 1;
00676
00677
00678 (void) headerNVR(h, &name, &version, &release);
00679
00680 pkgEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00681 *p = '\0';
00682 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00683 sprintf(p, "%d:", *epoch);
00684 while (*p != '\0')
00685 p++;
00686 }
00687 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00688
00689 return rpmRangesOverlap(name, pkgEVR, pkgFlags, reqName, reqEVR, reqFlags);
00690 }
00691
00692 rpmTransactionSet rpmtransCreateSet(rpmdb rpmdb, const char * rootDir)
00693 {
00694 rpmTransactionSet ts;
00695 int rootLen;
00696
00697 if (!rootDir) rootDir = "";
00698
00699 ts = xcalloc(1, sizeof(*ts));
00700 ts->filesystemCount = 0;
00701 ts->filesystems = NULL;
00702 ts->di = NULL;
00703
00704 ts->rpmdb = rpmdb;
00705
00706 ts->scriptFd = NULL;
00707 ts->id = 0;
00708 ts->delta = 5;
00709
00710 ts->numRemovedPackages = 0;
00711 ts->allocedRemovedPackages = ts->delta;
00712 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
00713 sizeof(*ts->removedPackages));
00714
00715
00716 rootLen = strlen(rootDir);
00717 if (!(rootLen && rootDir[rootLen - 1] == '/')) {
00718 char * t;
00719
00720 t = alloca(rootLen + 2);
00721 *t = '\0';
00722 (void) stpcpy( stpcpy(t, rootDir), "/");
00723 rootDir = t;
00724 }
00725
00726 ts->rootDir = xstrdup(rootDir);
00727 ts->currDir = NULL;
00728 ts->chrootDone = 0;
00729
00730 ts->addedPackages.delta = ts->delta;
00731 alCreate(&ts->addedPackages);
00732 ts->availablePackages.delta = ts->delta;
00733 alCreate(&ts->availablePackages);
00734
00735 ts->orderAlloced = ts->delta;
00736 ts->orderCount = 0;
00737 ts->order = xcalloc(ts->orderAlloced, sizeof(*ts->order));
00738
00739 return ts;
00740 }
00741
00748 static int intcmp(const void * a, const void * b)
00749 {
00750 const int * aptr = a;
00751 const int * bptr = b;
00752 int rc = (*aptr - *bptr);
00753 return rc;
00754 }
00755
00763 static int removePackage(rpmTransactionSet ts, int dboffset, int depends)
00764
00765 {
00766
00767
00768 if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) {
00769 if (bsearch(&dboffset, ts->removedPackages, ts->numRemovedPackages,
00770 sizeof(int), intcmp) != NULL)
00771 return 0;
00772 }
00773
00774 if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
00775 ts->allocedRemovedPackages += ts->delta;
00776 ts->removedPackages = xrealloc(ts->removedPackages,
00777 sizeof(int *) * ts->allocedRemovedPackages);
00778 }
00779
00780 if (ts->removedPackages != NULL) {
00781 ts->removedPackages[ts->numRemovedPackages++] = dboffset;
00782 qsort(ts->removedPackages, ts->numRemovedPackages, sizeof(int), intcmp);
00783 }
00784
00785 if (ts->orderCount == ts->orderAlloced) {
00786 ts->orderAlloced += ts->delta;
00787 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00788 }
00789
00790 ts->order[ts->orderCount].type = TR_REMOVED;
00791 ts->order[ts->orderCount].u.removed.dboffset = dboffset;
00792 ts->order[ts->orderCount++].u.removed.dependsOnIndex = depends;
00793
00794 return 0;
00795 }
00796
00797 int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
00798 const void * key, int upgrade, rpmRelocation * relocs)
00799 {
00800 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00801 HFD_t hfd = headerFreeData;
00802 rpmTagType ont, ovt;
00803
00804 const char * name;
00805 int count;
00806 const char ** obsoletes;
00807 int alNum;
00808
00809
00810
00811
00812
00813
00814
00815 if (ts->orderCount == ts->orderAlloced) {
00816 ts->orderAlloced += ts->delta;
00817 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00818 }
00819 ts->order[ts->orderCount].type = TR_ADDED;
00820 if (ts->addedPackages.list == NULL)
00821 return 0;
00822
00823 alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
00824 ts->addedPackages.list;
00825 ts->order[ts->orderCount++].u.addedIndex = alNum;
00826
00827 if (!upgrade || ts->rpmdb == NULL)
00828 return 0;
00829
00830
00831 if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
00832 return 0;
00833
00834 (void) headerNVR(h, &name, NULL, NULL);
00835
00836 { rpmdbMatchIterator mi;
00837 Header h2;
00838
00839 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, name, 0);
00840 while((h2 = rpmdbNextIterator(mi)) != NULL) {
00841 if (rpmVersionCompare(h, h2))
00842 (void) removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
00843 else {
00844 uint_32 *p, multiLibMask = 0, oldmultiLibMask = 0;
00845
00846 if (hge(h2, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL))
00847 oldmultiLibMask = *p;
00848 if (hge(h, RPMTAG_MULTILIBS, NULL, (void **) &p, NULL))
00849 multiLibMask = *p;
00850 if (oldmultiLibMask && multiLibMask
00851 && !(oldmultiLibMask & multiLibMask)) {
00852 ts->addedPackages.list[alNum].multiLib = multiLibMask;
00853 }
00854 }
00855 }
00856 mi = rpmdbFreeIterator(mi);
00857 }
00858
00859 if (hge(h, RPMTAG_OBSOLETENAME, &ont, (void **) &obsoletes, &count)) {
00860 const char ** obsoletesEVR;
00861 int_32 * obsoletesFlags;
00862 int j;
00863
00864 (void) hge(h, RPMTAG_OBSOLETEVERSION, &ovt, (void **) &obsoletesEVR,
00865 NULL);
00866 (void) hge(h, RPMTAG_OBSOLETEFLAGS, NULL, (void **) &obsoletesFlags,
00867 NULL);
00868
00869 for (j = 0; j < count; j++) {
00870
00871
00872 if (!strcmp(name, obsoletes[j]))
00873 continue;
00874
00875 { rpmdbMatchIterator mi;
00876 Header h2;
00877
00878 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, obsoletes[j], 0);
00879
00880 (void) rpmdbPruneIterator(mi,
00881 ts->removedPackages, ts->numRemovedPackages, 1);
00882
00883 while((h2 = rpmdbNextIterator(mi)) != NULL) {
00884
00885
00886
00887
00888 if (obsoletesEVR == NULL ||
00889 headerMatchesDepFlags(h2,
00890 obsoletes[j], obsoletesEVR[j], obsoletesFlags[j]))
00891 {
00892 (void) removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
00893 }
00894 }
00895 mi = rpmdbFreeIterator(mi);
00896 }
00897 }
00898
00899 obsoletesEVR = hfd(obsoletesEVR, ovt);
00900 obsoletes = hfd(obsoletes, ont);
00901 }
00902
00903 return 0;
00904 }
00905
00906 void rpmtransAvailablePackage(rpmTransactionSet ts, Header h, const void * key)
00907 {
00908 struct availablePackage * al;
00909 al = alAddPackage(&ts->availablePackages, h, key, NULL, NULL);
00910 }
00911
00912 int rpmtransRemovePackage(rpmTransactionSet ts, int dboffset)
00913 {
00914 return removePackage(ts, dboffset, -1);
00915 }
00916
00917 rpmTransactionSet rpmtransFree(rpmTransactionSet ts)
00918 {
00919 if (ts) {
00920 alFree(&ts->addedPackages);
00921 alFree(&ts->availablePackages);
00922 ts->di = _free(ts->di);
00923 ts->removedPackages = _free(ts->removedPackages);
00924 ts->order = _free(ts->order);
00925 if (ts->scriptFd != NULL)
00926 ts->scriptFd =
00927 fdFree(ts->scriptFd, "rpmtransSetScriptFd (rpmtransFree");
00928 ts->rootDir = _free(ts->rootDir);
00929 ts->currDir = _free(ts->currDir);
00930
00931 ts = _free(ts);
00932 }
00933 return NULL;
00934 }
00935
00936 rpmDependencyConflict rpmdepFreeConflicts(rpmDependencyConflict conflicts,
00937 int numConflicts)
00938 {
00939 int i;
00940
00941 if (conflicts)
00942 for (i = 0; i < numConflicts; i++) {
00943 conflicts[i].byHeader = headerFree(conflicts[i].byHeader);
00944 conflicts[i].byName = _free(conflicts[i].byName);
00945 conflicts[i].byVersion = _free(conflicts[i].byVersion);
00946 conflicts[i].byRelease = _free(conflicts[i].byRelease);
00947 conflicts[i].needsName = _free(conflicts[i].needsName);
00948 conflicts[i].needsVersion = _free(conflicts[i].needsVersion);
00949 conflicts[i].suggestedPackages = _free(conflicts[i].suggestedPackages);
00950 }
00951
00952 return (conflicts = _free(conflicts));
00953 }
00954
00962 static struct availablePackage **
00963 alAllFileSatisfiesDepend(const availableList al,
00964 const char * keyType, const char * fileName)
00965
00966 {
00967 int i, found;
00968 const char * dirName;
00969 const char * baseName;
00970 struct dirInfo_s dirNeedle;
00971 dirInfo dirMatch;
00972 struct availablePackage ** ret;
00973
00974
00975 if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
00976 return NULL;
00977
00978 { char * t;
00979 dirName = t = xstrdup(fileName);
00980 if ((t = strrchr(t, '/')) != NULL) {
00981 t++;
00982 *t = '\0';
00983 }
00984 }
00985
00986 dirNeedle.dirName = (char *) dirName;
00987 dirNeedle.dirNameLen = strlen(dirName);
00988 dirMatch = bsearch(&dirNeedle, al->dirs, al->numDirs,
00989 sizeof(dirNeedle), dirInfoCompare);
00990 if (dirMatch == NULL) {
00991 dirName = _free(dirName);
00992 return NULL;
00993 }
00994
00995
00996 while (dirMatch > al->dirs && dirInfoCompare(dirMatch-1, &dirNeedle) == 0)
00997 dirMatch--;
00998
00999
01000 baseName = strrchr(fileName, '/') + 1;
01001
01002
01003 for (found = 0, ret = NULL;
01004 dirMatch <= al->dirs + al->numDirs &&
01005 dirInfoCompare(dirMatch, &dirNeedle) == 0;
01006 dirMatch++)
01007 {
01008
01009 for (i = 0; i < dirMatch->numFiles; i++) {
01010 if (dirMatch->files[i].baseName == NULL ||
01011 strcmp(dirMatch->files[i].baseName, baseName))
01012 continue;
01013
01014
01015
01016
01017
01018 if (al->list[dirMatch->files[i].pkgNum].multiLib &&
01019 !isFileMULTILIB(dirMatch->files[i].fileFlags))
01020 continue;
01021
01022 if (keyType)
01023 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added files)\n"),
01024 keyType, fileName);
01025
01026 ret = xrealloc(ret, (found+2) * sizeof(*ret));
01027 if (ret)
01028 ret[found++] = al->list + dirMatch->files[i].pkgNum;
01029 break;
01030 }
01031 }
01032
01033 dirName = _free(dirName);
01034
01035 if (ret)
01036 ret[found] = NULL;
01037
01038 return ret;
01039 }
01040
01041 #ifdef DYING
01042
01049 static struct availablePackage *
01050 alFileSatisfiesDepend(const availableList al,
01051 const char * keyType, const char * fileName)
01052
01053 {
01054 struct availablePackage * ret;
01055 struct availablePackage ** tmp =
01056 alAllFileSatisfiesDepend(al, keyType, fileName);
01057
01058 if (tmp) {
01059 ret = tmp[0];
01060 tmp = _free(tmp);
01061 return ret;
01062 }
01063 return NULL;
01064 }
01065 #endif
01066
01077 static struct availablePackage **
01078 alAllSatisfiesDepend(const availableList al,
01079 const char * keyType, const char * keyDepend,
01080 const char * keyName, const char * keyEVR, int keyFlags)
01081
01082 {
01083 struct availableIndexEntry needle, * match;
01084 struct availablePackage * p, ** ret = NULL;
01085 int i, rc, found;
01086
01087 if (*keyName == '/') {
01088 ret = alAllFileSatisfiesDepend(al, keyType, keyName);
01089
01090 if (ret != NULL && *ret != NULL)
01091 return ret;
01092 }
01093
01094 if (!al->index.size || al->index.index == NULL) return NULL;
01095
01096 needle.entry = keyName;
01097 needle.entryLen = strlen(keyName);
01098 match = bsearch(&needle, al->index.index, al->index.size,
01099 sizeof(*al->index.index), indexcmp);
01100
01101 if (match == NULL) return NULL;
01102
01103
01104 while (match > al->index.index && indexcmp(match-1, &needle) == 0)
01105 match--;
01106
01107 for (ret = NULL, found = 0;
01108 match < al->index.index + al->index.size &&
01109 indexcmp(match, &needle) == 0;
01110 match++)
01111 {
01112
01113 p = match->package;
01114 rc = 0;
01115 switch (match->type) {
01116 case IET_PROVIDES:
01117 i = match->entryIx;
01118 { const char * proEVR;
01119 int proFlags;
01120
01121 proEVR = (p->providesEVR ? p->providesEVR[i] : NULL);
01122 proFlags = (p->provideFlags ? p->provideFlags[i] : 0);
01123 rc = rpmRangesOverlap(p->provides[i], proEVR, proFlags,
01124 keyName, keyEVR, keyFlags);
01125 if (rc)
01126 break;
01127 }
01128 if (keyType && keyDepend && rc)
01129 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added provide)\n"),
01130 keyType, keyDepend+2);
01131 break;
01132 }
01133
01134 if (rc) {
01135 ret = xrealloc(ret, (found + 2) * sizeof(*ret));
01136 if (ret)
01137 ret[found++] = p;
01138 }
01139 }
01140
01141 if (ret)
01142 ret[found] = NULL;
01143
01144 return ret;
01145 }
01146
01158 static inline struct availablePackage *
01159 alSatisfiesDepend(const availableList al,
01160 const char * keyType, const char * keyDepend,
01161 const char * keyName, const char * keyEVR, int keyFlags)
01162
01163 {
01164 struct availablePackage * ret;
01165 struct availablePackage ** tmp =
01166 alAllSatisfiesDepend(al, keyType, keyDepend, keyName, keyEVR, keyFlags);
01167
01168 if (tmp) {
01169 ret = tmp[0];
01170 tmp = _free(tmp);
01171 return ret;
01172 }
01173 return NULL;
01174 }
01175
01188 static int unsatisfiedDepend(rpmTransactionSet ts,
01189 const char * keyType, const char * keyDepend,
01190 const char * keyName, const char * keyEVR, int keyFlags,
01191 struct availablePackage *** suggestion)
01192
01193 {
01194 rpmdbMatchIterator mi;
01195 Header h;
01196 int rc = 0;
01197
01198 if (suggestion) *suggestion = NULL;
01199
01200
01201
01202
01203 if (_cacheDependsRC) {
01204 dbiIndex dbi;
01205 dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
01206 if (dbi == NULL)
01207 _cacheDependsRC = 0;
01208 else {
01209 DBC * dbcursor = NULL;
01210 size_t keylen = strlen(keyDepend);
01211 void * datap = NULL;
01212 size_t datalen = 0;
01213 int xx;
01214 xx = dbiCopen(dbi, &dbcursor, 0);
01215
01216 xx = dbiGet(dbi, dbcursor, (void **)&keyDepend, &keylen, &datap, &datalen, 0);
01217
01218 if (xx == 0 && datap && datalen == 4) {
01219 memcpy(&rc, datap, datalen);
01220 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s %-s (cached)\n"),
01221 keyType, keyDepend, (rc ? _("NO ") : _("YES")));
01222 xx = dbiCclose(dbi, NULL, 0);
01223
01224 if (suggestion && rc == 1)
01225 *suggestion = alAllSatisfiesDepend(&ts->availablePackages,
01226 NULL, NULL, keyName, keyEVR, keyFlags);
01227
01228 return rc;
01229 }
01230 xx = dbiCclose(dbi, dbcursor, 0);
01231 }
01232 }
01233
01234 #ifdef DYING
01235 { static const char noProvidesString[] = "nada";
01236 static const char * rcProvidesString = noProvidesString;
01237 const char * start;
01238 int i;
01239
01240 if (rcProvidesString == noProvidesString)
01241 rcProvidesString = rpmGetVar(RPMVAR_PROVIDES);
01242
01243 if (rcProvidesString != NULL && !(keyFlags & RPMSENSE_SENSEMASK)) {
01244 i = strlen(keyName);
01245
01246 while ((start = strstr(rcProvidesString, keyName))) {
01247
01248 if (xisspace(start[i]) || start[i] == '\0' || start[i] == ',') {
01249 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmrc provides)\n"),
01250 keyType, keyDepend+2);
01251 goto exit;
01252 }
01253 rcProvidesString = start + 1;
01254 }
01255 }
01256 }
01257 #endif
01258
01259
01260
01261
01262
01263
01264 if (!strncmp(keyName, "rpmlib(", sizeof("rpmlib(")-1)) {
01265 if (rpmCheckRpmlibProvides(keyName, keyEVR, keyFlags)) {
01266 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmlib provides)\n"),
01267 keyType, keyDepend+2);
01268 goto exit;
01269 }
01270 goto unsatisfied;
01271 }
01272
01273 if (alSatisfiesDepend(&ts->addedPackages, keyType, keyDepend,
01274 keyName, keyEVR, keyFlags))
01275 {
01276 goto exit;
01277 }
01278
01279
01280 if (ts->rpmdb != NULL) {
01281 if (*keyName == '/') {
01282
01283
01284 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_BASENAMES, keyName, 0);
01285
01286 (void) rpmdbPruneIterator(mi,
01287 ts->removedPackages, ts->numRemovedPackages, 1);
01288
01289 while ((h = rpmdbNextIterator(mi)) != NULL) {
01290 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db files)\n"),
01291 keyType, keyDepend+2);
01292 mi = rpmdbFreeIterator(mi);
01293 goto exit;
01294 }
01295 mi = rpmdbFreeIterator(mi);
01296 }
01297
01298 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_PROVIDENAME, keyName, 0);
01299 (void) rpmdbPruneIterator(mi,
01300 ts->removedPackages, ts->numRemovedPackages, 1);
01301 while ((h = rpmdbNextIterator(mi)) != NULL) {
01302 if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
01303 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db provides)\n"),
01304 keyType, keyDepend+2);
01305 mi = rpmdbFreeIterator(mi);
01306 goto exit;
01307 }
01308 }
01309 mi = rpmdbFreeIterator(mi);
01310
01311 #ifndef DYING
01312 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, keyName, 0);
01313 (void) rpmdbPruneIterator(mi,
01314 ts->removedPackages, ts->numRemovedPackages, 1);
01315 while ((h = rpmdbNextIterator(mi)) != NULL) {
01316 if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
01317 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db package)\n"),
01318 keyType, keyDepend+2);
01319 mi = rpmdbFreeIterator(mi);
01320 goto exit;
01321 }
01322 }
01323 mi = rpmdbFreeIterator(mi);
01324 #endif
01325
01326 }
01327
01328 if (suggestion)
01329 *suggestion = alAllSatisfiesDepend(&ts->availablePackages, NULL, NULL,
01330 keyName, keyEVR, keyFlags);
01331
01332 unsatisfied:
01333 rpmMessage(RPMMESS_DEBUG, _("%s: %-45s NO\n"), keyType, keyDepend+2);
01334 rc = 1;
01335
01336 exit:
01337
01338
01339
01340 if (_cacheDependsRC) {
01341 dbiIndex dbi;
01342 dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
01343 if (dbi == NULL) {
01344 _cacheDependsRC = 0;
01345 } else {
01346 DBC * dbcursor = NULL;
01347 int xx;
01348 xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR);
01349 xx = dbiPut(dbi, dbcursor, keyDepend, strlen(keyDepend), &rc, sizeof(rc), 0);
01350 if (xx)
01351 _cacheDependsRC = 0;
01352 #if 0
01353 else
01354 rpmMessage(RPMMESS_DEBUG, _("%s: (%s, %s) added to Depends cache.\n"), keyType, keyDepend, (rc ? _("NO ") : _("YES")));
01355 #endif
01356 xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR);
01357 }
01358 }
01359 return rc;
01360 }
01361
01371 static int checkPackageDeps(rpmTransactionSet ts, problemsSet psp,
01372 Header h, const char * keyName, uint_32 multiLib)
01373
01374 {
01375 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01376 HFD_t hfd = headerFreeData;
01377 rpmTagType rnt, rvt;
01378 rpmTagType cnt, cvt;
01379 const char * name, * version, * release;
01380 const char ** requires;
01381 const char ** requiresEVR = NULL;
01382 int_32 * requireFlags = NULL;
01383 int requiresCount = 0;
01384 const char ** conflicts;
01385 const char ** conflictsEVR = NULL;
01386 int_32 * conflictFlags = NULL;
01387 int conflictsCount = 0;
01388 rpmTagType type;
01389 int i, rc;
01390 int ourrc = 0;
01391 struct availablePackage ** suggestion;
01392
01393 (void) headerNVR(h, &name, &version, &release);
01394
01395 if (!hge(h, RPMTAG_REQUIRENAME, &rnt, (void **) &requires, &requiresCount))
01396 {
01397 requiresCount = 0;
01398 rvt = RPM_STRING_ARRAY_TYPE;
01399 } else {
01400 (void)hge(h, RPMTAG_REQUIREFLAGS, NULL, (void **) &requireFlags, NULL);
01401 (void)hge(h, RPMTAG_REQUIREVERSION, &rvt, (void **) &requiresEVR, NULL);
01402 }
01403
01404 for (i = 0; i < requiresCount && !ourrc; i++) {
01405 const char * keyDepend;
01406
01407
01408 if (keyName && strcmp(keyName, requires[i]))
01409 continue;
01410
01411
01412
01413 if (multiLib && !isDependsMULTILIB(requireFlags[i]))
01414 continue;
01415
01416 keyDepend = printDepend("R",
01417 requires[i], requiresEVR[i], requireFlags[i]);
01418
01419 rc = unsatisfiedDepend(ts, " Requires", keyDepend,
01420 requires[i], requiresEVR[i], requireFlags[i], &suggestion);
01421
01422 switch (rc) {
01423 case 0:
01424 break;
01425 case 1:
01426 rpmMessage(RPMMESS_DEBUG, _("package %s-%s-%s require not satisfied: %s\n"),
01427 name, version, release, keyDepend+2);
01428
01429 if (psp->num == psp->alloced) {
01430 psp->alloced += 5;
01431 psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
01432 psp->alloced);
01433 }
01434
01435 { rpmDependencyConflict pp = psp->problems + psp->num;
01436 pp->byHeader = headerLink(h);
01437 pp->byName = xstrdup(name);
01438 pp->byVersion = xstrdup(version);
01439 pp->byRelease = xstrdup(release);
01440 pp->needsName = xstrdup(requires[i]);
01441 pp->needsVersion = xstrdup(requiresEVR[i]);
01442 pp->needsFlags = requireFlags[i];
01443 pp->sense = RPMDEP_SENSE_REQUIRES;
01444
01445 if (suggestion) {
01446 int j;
01447 for (j = 0; suggestion[j]; j++)
01448 {};
01449 pp->suggestedPackages =
01450 xmalloc( (j + 1) * sizeof(*pp->suggestedPackages) );
01451 for (j = 0; suggestion[j]; j++)
01452 pp->suggestedPackages[j] = suggestion[j]->key;
01453 pp->suggestedPackages[j] = NULL;
01454 } else {
01455 pp->suggestedPackages = NULL;
01456 }
01457 }
01458
01459 psp->num++;
01460 break;
01461 case 2:
01462 default:
01463 ourrc = 1;
01464 break;
01465 }
01466 keyDepend = _free(keyDepend);
01467 }
01468
01469 if (requiresCount) {
01470 requiresEVR = hfd(requiresEVR, rvt);
01471 requires = hfd(requires, rnt);
01472 }
01473
01474 if (!hge(h, RPMTAG_CONFLICTNAME, &cnt, (void **)&conflicts, &conflictsCount))
01475 {
01476 conflictsCount = 0;
01477 cvt = RPM_STRING_ARRAY_TYPE;
01478 } else {
01479 (void) hge(h, RPMTAG_CONFLICTFLAGS, &type,
01480 (void **) &conflictFlags, &conflictsCount);
01481 (void) hge(h, RPMTAG_CONFLICTVERSION, &cvt,
01482 (void **) &conflictsEVR, &conflictsCount);
01483 }
01484
01485 for (i = 0; i < conflictsCount && !ourrc; i++) {
01486 const char * keyDepend;
01487
01488
01489 if (keyName && strcmp(keyName, conflicts[i]))
01490 continue;
01491
01492
01493
01494 if (multiLib && !isDependsMULTILIB(conflictFlags[i]))
01495 continue;
01496
01497 keyDepend = printDepend("C", conflicts[i], conflictsEVR[i], conflictFlags[i]);
01498
01499 rc = unsatisfiedDepend(ts, "Conflicts", keyDepend,
01500 conflicts[i], conflictsEVR[i], conflictFlags[i], NULL);
01501
01502
01503 switch (rc) {
01504 case 0:
01505 rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
01506 name, keyDepend+2);
01507
01508 if (psp->num == psp->alloced) {
01509 psp->alloced += 5;
01510 psp->problems = xrealloc(psp->problems,
01511 sizeof(*psp->problems) * psp->alloced);
01512 }
01513
01514 { rpmDependencyConflict pp = psp->problems + psp->num;
01515 pp->byHeader = headerLink(h);
01516 pp->byName = xstrdup(name);
01517 pp->byVersion = xstrdup(version);
01518 pp->byRelease = xstrdup(release);
01519 pp->needsName = xstrdup(conflicts[i]);
01520 pp->needsVersion = xstrdup(conflictsEVR[i]);
01521 pp->needsFlags = conflictFlags[i];
01522 pp->sense = RPMDEP_SENSE_CONFLICTS;
01523 pp->suggestedPackages = NULL;
01524 }
01525
01526 psp->num++;
01527 break;
01528 case 1:
01529 break;
01530 case 2:
01531 default:
01532 ourrc = 1;
01533 break;
01534 }
01535 keyDepend = _free(keyDepend);
01536 }
01537
01538 if (conflictsCount) {
01539 conflictsEVR = hfd(conflictsEVR, cvt);
01540 conflicts = hfd(conflicts, cnt);
01541 }
01542
01543 return ourrc;
01544 }
01545
01556 static int checkPackageSet(rpmTransactionSet ts, problemsSet psp,
01557 const char * key, rpmdbMatchIterator mi)
01558
01559 {
01560 Header h;
01561 int rc = 0;
01562
01563 (void) rpmdbPruneIterator(mi,
01564 ts->removedPackages, ts->numRemovedPackages, 1);
01565 while ((h = rpmdbNextIterator(mi)) != NULL) {
01566 if (checkPackageDeps(ts, psp, h, key, 0)) {
01567 rc = 1;
01568 break;
01569 }
01570 }
01571 mi = rpmdbFreeIterator(mi);
01572
01573 return rc;
01574 }
01575
01583 static int checkDependentPackages(rpmTransactionSet ts,
01584 problemsSet psp, const char * key)
01585
01586 {
01587 rpmdbMatchIterator mi;
01588 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_REQUIRENAME, key, 0);
01589 return checkPackageSet(ts, psp, key, mi);
01590 }
01591
01599 static int checkDependentConflicts(rpmTransactionSet ts,
01600 problemsSet psp, const char * key)
01601
01602 {
01603 int rc = 0;
01604
01605 if (ts->rpmdb) {
01606 rpmdbMatchIterator mi;
01607 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_CONFLICTNAME, key, 0);
01608 rc = checkPackageSet(ts, psp, key, mi);
01609 }
01610
01611 return rc;
01612 }
01613
01614 struct badDeps_s {
01615 const char * pname;
01616 const char * qname;
01617 };
01618
01619 #ifdef DYING
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 #else
01649 static struct badDeps_s * badDeps = NULL;
01650 #endif
01651
01659 static int ignoreDep(const struct availablePackage * p,
01660 const struct availablePackage * q)
01661
01662 {
01663 struct badDeps_s * bdp;
01664 static int _initialized = 0;
01665 const char ** av = NULL;
01666 int ac = 0;
01667
01668 if (!_initialized) {
01669 char * s = rpmExpand("%{?_dependency_whiteout}", NULL);
01670 int i;
01671
01672 if (s != NULL && *s != '\0'
01673 && !(i = poptParseArgvString(s, &ac, (const char ***)&av))
01674 && ac > 0 && av != NULL)
01675 {
01676 bdp = badDeps = xcalloc(ac+1, sizeof(*badDeps));
01677 for (i = 0; i < ac; i++, bdp++) {
01678 char * p, * q;
01679
01680 if (av[i] == NULL)
01681 break;
01682 p = xstrdup(av[i]);
01683 if ((q = strchr(p, '>')) != NULL)
01684 *q++ = '\0';
01685 bdp->pname = p;
01686 bdp->qname = q;
01687 rpmMessage(RPMMESS_DEBUG,
01688 _("ignore package name relation(s) [%d]\t%s -> %s\n"),
01689 i, bdp->pname, bdp->qname);
01690 }
01691 bdp->pname = bdp->qname = NULL;
01692 }
01693 av = _free(av);
01694 s = _free(s);
01695 _initialized++;
01696 }
01697
01698 if (badDeps != NULL)
01699 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++) {
01700 if (!strcmp(p->name, bdp->pname) && !strcmp(q->name, bdp->qname))
01701 return 1;
01702 }
01703 return 0;
01704 }
01705
01711 static void markLoop( tsortInfo tsi,
01712 struct availablePackage * q)
01713
01714
01715 {
01716 struct availablePackage * p;
01717
01718 while (tsi != NULL && (p = tsi->tsi_suc) != NULL) {
01719 tsi = tsi->tsi_next;
01720 if (p->tsi.tsi_pkg != NULL)
01721 continue;
01722 p->tsi.tsi_pkg = q;
01723 if (p->tsi.tsi_next != NULL)
01724 markLoop(p->tsi.tsi_next, p);
01725 }
01726 }
01727
01728 static inline const char * const identifyDepend(int_32 f)
01729 {
01730 if (isLegacyPreReq(f))
01731 return "PreReq:";
01732 f = _notpre(f);
01733 if (f & RPMSENSE_SCRIPT_PRE)
01734 return "Requires(pre):";
01735 if (f & RPMSENSE_SCRIPT_POST)
01736 return "Requires(post):";
01737 if (f & RPMSENSE_SCRIPT_PREUN)
01738 return "Requires(preun):";
01739 if (f & RPMSENSE_SCRIPT_POSTUN)
01740 return "Requires(postun):";
01741 if (f & RPMSENSE_SCRIPT_VERIFY)
01742 return "Requires(verify):";
01743 if (f & RPMSENSE_FIND_REQUIRES)
01744 return "Requires(auto):";
01745 return "Requires:";
01746 }
01747
01759 static const char *
01760 zapRelation(struct availablePackage * q, struct availablePackage * p,
01761 int zap, int * nzaps)
01762
01763 {
01764 tsortInfo tsi_prev;
01765 tsortInfo tsi;
01766 const char *dp = NULL;
01767
01768 for (tsi_prev = &q->tsi, tsi = q->tsi.tsi_next;
01769 tsi != NULL;
01770
01771
01772 tsi_prev = tsi, tsi = tsi->tsi_next)
01773
01774 {
01775 int j;
01776
01777 if (tsi->tsi_suc != p)
01778 continue;
01779 if (p->requires == NULL) continue;
01780 if (p->requireFlags == NULL) continue;
01781 if (p->requiresEVR == NULL) continue;
01782
01783 j = tsi->tsi_reqx;
01784 dp = printDepend( identifyDepend(p->requireFlags[j]),
01785 p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
01786
01787
01788
01789
01790 if (zap && !(p->requireFlags[j] & RPMSENSE_PREREQ)) {
01791 rpmMessage(RPMMESS_DEBUG,
01792 _("removing %s-%s-%s \"%s\" from tsort relations.\n"),
01793 p->name, p->version, p->release, dp);
01794 p->tsi.tsi_count--;
01795 if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next;
01796 tsi->tsi_next = NULL;
01797 tsi->tsi_suc = NULL;
01798 tsi = _free(tsi);
01799 if (nzaps)
01800 (*nzaps)++;
01801 if (zap)
01802 zap--;
01803 }
01804
01805 break;
01806 }
01807 return dp;
01808 }
01809
01818 static inline int addRelation( const rpmTransactionSet ts,
01819 struct availablePackage * p, unsigned char * selected, int j)
01820
01821 {
01822 struct availablePackage * q;
01823 tsortInfo tsi;
01824 int matchNum;
01825
01826 if (!p->requires || !p->requiresEVR || !p->requireFlags)
01827 return 0;
01828
01829 q = alSatisfiesDepend(&ts->addedPackages, NULL, NULL,
01830 p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
01831
01832
01833 if (q == NULL)
01834 return 0;
01835
01836
01837 if (!strncmp(p->requires[j], "rpmlib(", sizeof("rpmlib(")-1))
01838 return 0;
01839
01840
01841 if (ignoreDep(p, q))
01842 return 0;
01843
01844
01845
01846 matchNum = q - ts->addedPackages.list;
01847 if (selected[matchNum] != 0)
01848 return 0;
01849 selected[matchNum] = 1;
01850
01851
01852 p->tsi.tsi_count++;
01853 if (p->depth <= q->depth)
01854 p->depth = q->depth + 1;
01855
01856 tsi = xmalloc(sizeof(*tsi));
01857 tsi->tsi_suc = p;
01858 tsi->tsi_reqx = j;
01859 tsi->tsi_next = q->tsi.tsi_next;
01860 q->tsi.tsi_next = tsi;
01861 q->tsi.tsi_qcnt++;
01862 return 0;
01863 }
01864
01871 static int orderListIndexCmp(const void * one, const void * two)
01872 {
01873 int a = ((const struct orderListIndex *)one)->alIndex;
01874 int b = ((const struct orderListIndex *)two)->alIndex;
01875 return (a - b);
01876 }
01877
01884 static void addQ(struct availablePackage * p,
01885 struct availablePackage ** qp,
01886 struct availablePackage ** rp)
01887
01888 {
01889 struct availablePackage *q, *qprev;
01890
01891
01892 p->tsi.tsi_reqx = 1;
01893
01894 if ((*rp) == NULL) {
01895 (*rp) = (*qp) = p;
01896 return;
01897 }
01898 for (qprev = NULL, q = (*qp); q != NULL; qprev = q, q = q->tsi.tsi_suc) {
01899 if (q->tsi.tsi_qcnt <= p->tsi.tsi_qcnt)
01900 break;
01901 }
01902 if (qprev == NULL) {
01903 p->tsi.tsi_suc = q;
01904 (*qp) = p;
01905 } else if (q == NULL) {
01906 qprev->tsi.tsi_suc = p;
01907 (*rp) = p;
01908 } else {
01909 p->tsi.tsi_suc = q;
01910 qprev->tsi.tsi_suc = p;
01911 }
01912 }
01913
01914 int rpmdepOrder(rpmTransactionSet ts)
01915 {
01916 int npkgs = ts->addedPackages.size;
01917 #ifdef DYING
01918 int chainsaw = ts->transFlags & RPMTRANS_FLAG_CHAINSAW;
01919 #else
01920 int chainsaw = 0;
01921 #endif
01922 struct availablePackage * p;
01923 struct availablePackage * q;
01924 struct availablePackage * r;
01925 tsortInfo tsi;
01926 tsortInfo tsi_next;
01927 int * ordering = alloca(sizeof(*ordering) * (npkgs + 1));
01928 int orderingCount = 0;
01929 unsigned char * selected = alloca(sizeof(*selected) * (npkgs + 1));
01930 int loopcheck;
01931 transactionElement newOrder;
01932 int newOrderCount = 0;
01933 struct orderListIndex * orderList;
01934 int nrescans = 10;
01935 int _printed = 0;
01936 int treex;
01937 int depth;
01938 int qlen;
01939 int i, j;
01940
01941 alMakeIndex(&ts->addedPackages);
01942 alMakeIndex(&ts->availablePackages);
01943
01944
01945 loopcheck = npkgs;
01946
01947
01948 rpmMessage(RPMMESS_DEBUG, _("========== recording tsort relations\n"));
01949 if ((p = ts->addedPackages.list) != NULL)
01950 for (i = 0; i < npkgs; i++, p++) {
01951 int matchNum;
01952
01953 if (p->requiresCount <= 0)
01954 continue;
01955
01956 memset(selected, 0, sizeof(*selected) * npkgs);
01957
01958
01959 matchNum = p - ts->addedPackages.list;
01960 selected[matchNum] = 1;
01961
01962
01963
01964
01965 for (j = 0; j < p->requiresCount; j++) {
01966
01967 if (p->requireFlags == NULL) continue;
01968
01969
01970
01971 if (isErasePreReq(p->requireFlags[j]) ||
01972 !( isInstallPreReq(p->requireFlags[j]) ||
01973 isLegacyPreReq(p->requireFlags[j]) ))
01974 continue;
01975
01976
01977 (void) addRelation(ts, p, selected, j);
01978
01979 }
01980
01981
01982 for (j = 0; j < p->requiresCount; j++) {
01983
01984 if (p->requireFlags == NULL) continue;
01985
01986
01987
01988 if (isErasePreReq(p->requireFlags[j]) ||
01989 ( isInstallPreReq(p->requireFlags[j]) ||
01990 isLegacyPreReq(p->requireFlags[j]) ))
01991 continue;
01992
01993
01994 (void) addRelation(ts, p, selected, j);
01995
01996 }
01997 }
01998
01999
02000 treex = 0;
02001 if ((p = ts->addedPackages.list) != NULL)
02002 for (i = 0; i < npkgs; i++, p++) {
02003 p->npreds = p->tsi.tsi_count;
02004 p->tree = (p->npreds == 0 ? treex++ : -1);
02005 }
02006
02007
02008 rpmMessage(RPMMESS_DEBUG, _("========== tsorting packages (order, #predecessors, #succesors, tree, depth)\n"));
02009
02010 rescan:
02011 q = r = NULL;
02012 qlen = 0;
02013 if ((p = ts->addedPackages.list) != NULL)
02014 for (i = 0; i < npkgs; i++, p++) {
02015
02016
02017 if (!chainsaw)
02018 p->tsi.tsi_qcnt = (npkgs - i);
02019
02020 if (p->tsi.tsi_count != 0)
02021 continue;
02022 p->tsi.tsi_suc = NULL;
02023 addQ(p, &q, &r);
02024 qlen++;
02025 }
02026
02027
02028 for (; q != NULL; q = q->tsi.tsi_suc) {
02029
02030
02031 q->tsi.tsi_reqx = 0;
02032
02033 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%5d%5d %*s %s-%s-%s\n",
02034 orderingCount, q->npreds, q->tsi.tsi_qcnt,
02035 q->tree, q->depth,
02036 2*q->depth, "",
02037 q->name, q->version, q->release);
02038
02039 treex = q->tree;
02040 depth = q->depth;
02041 q->degree = 0;
02042
02043 ordering[orderingCount++] = q - ts->addedPackages.list;
02044 qlen--;
02045 loopcheck--;
02046
02047
02048 tsi_next = q->tsi.tsi_next;
02049 q->tsi.tsi_next = NULL;
02050 while ((tsi = tsi_next) != NULL) {
02051 tsi_next = tsi->tsi_next;
02052 tsi->tsi_next = NULL;
02053 p = tsi->tsi_suc;
02054 if (p && (--p->tsi.tsi_count) <= 0) {
02055
02056 p->tree = treex;
02057 p->depth = depth + 1;
02058 p->parent = q;
02059 q->degree++;
02060
02061
02062 p->tsi.tsi_suc = NULL;
02063
02064 addQ(p, &q->tsi.tsi_suc, &r);
02065
02066 qlen++;
02067 }
02068 tsi = _free(tsi);
02069 }
02070 if (!_printed && loopcheck == qlen && q->tsi.tsi_suc != NULL) {
02071 _printed++;
02072 rpmMessage(RPMMESS_DEBUG,
02073 _("========== successors only (presentation order)\n"));
02074
02075
02076 tsi = &q->tsi;
02077 if ((p = ts->addedPackages.list) != NULL)
02078 for (i = 0; i < npkgs; i++, p++) {
02079
02080 if (p->tsi.tsi_reqx == 0)
02081 continue;
02082 tsi->tsi_suc = p;
02083 tsi = &p->tsi;
02084 }
02085 tsi->tsi_suc = NULL;
02086 }
02087 }
02088
02089
02090 if (loopcheck != 0) {
02091 int nzaps;
02092
02093
02094 nzaps = 0;
02095 if ((q = ts->addedPackages.list) != NULL)
02096 for (i = 0; i < npkgs; i++, q++) {
02097 q->tsi.tsi_pkg = NULL;
02098 q->tsi.tsi_reqx = 0;
02099
02100 if (q->tsi.tsi_count == 0)
02101 q->tsi.tsi_count = -1;
02102 }
02103
02104
02105 if ((q = ts->addedPackages.list) != NULL)
02106 for (i = 0; i < npkgs; i++, q++) {
02107 if ((tsi = q->tsi.tsi_next) == NULL)
02108 continue;
02109 q->tsi.tsi_next = NULL;
02110 markLoop(tsi, q);
02111 q->tsi.tsi_next = tsi;
02112 }
02113
02114
02115 if ((r = ts->addedPackages.list) != NULL)
02116 for (i = 0; i < npkgs; i++, r++) {
02117 int printed;
02118
02119 printed = 0;
02120
02121
02122 for (q = r->tsi.tsi_pkg; q != NULL; q = q->tsi.tsi_pkg) {
02123 if (q->tsi.tsi_reqx)
02124 break;
02125 q->tsi.tsi_reqx = 1;
02126 }
02127
02128
02129 while ((p = q) != NULL && (q = p->tsi.tsi_pkg) != NULL) {
02130 const char * dp;
02131 char buf[4096];
02132
02133
02134 p->tsi.tsi_pkg = NULL;
02135
02136 if (!printed) {
02137 rpmMessage(RPMMESS_DEBUG, _("LOOP:\n"));
02138 printed = 1;
02139 }
02140
02141
02142 dp = zapRelation(q, p, 1, &nzaps);
02143
02144
02145 sprintf(buf, "%s-%s-%s", p->name, p->version, p->release);
02146 rpmMessage(RPMMESS_DEBUG, " %-40s %s\n", buf,
02147 (dp ? dp : "not found!?!"));
02148
02149 dp = _free(dp);
02150 }
02151
02152
02153 for (p = r, q = r->tsi.tsi_pkg;
02154 q != NULL;
02155 p = q, q = q->tsi.tsi_pkg)
02156 {
02157
02158 p->tsi.tsi_pkg = NULL;
02159 p->tsi.tsi_reqx = 0;
02160 }
02161 }
02162
02163
02164
02165 if (nzaps && nrescans-- > 0) {
02166 rpmMessage(RPMMESS_DEBUG, _("========== continuing tsort ...\n"));
02167 goto rescan;
02168 }
02169 return 1;
02170 }
02171
02172
02173
02174
02175
02176
02177
02178 orderList = xmalloc(npkgs * sizeof(*orderList));
02179 for (i = 0, j = 0; i < ts->orderCount; i++) {
02180 if (ts->order[i].type == TR_ADDED) {
02181 orderList[j].alIndex = ts->order[i].u.addedIndex;
02182 orderList[j].orIndex = i;
02183 j++;
02184 }
02185 }
02186 assert(j <= npkgs);
02187
02188 qsort(orderList, npkgs, sizeof(*orderList), orderListIndexCmp);
02189
02190 newOrder = xmalloc(ts->orderCount * sizeof(*newOrder));
02191 for (i = 0, newOrderCount = 0; i < orderingCount; i++) {
02192 struct orderListIndex * needle, key;
02193
02194 key.alIndex = ordering[i];
02195 needle = bsearch(&key, orderList, npkgs, sizeof(key),orderListIndexCmp);
02196
02197 if (needle == NULL) continue;
02198
02199 newOrder[newOrderCount++] = ts->order[needle->orIndex];
02200 for (j = needle->orIndex + 1; j < ts->orderCount; j++) {
02201 if (ts->order[j].type == TR_REMOVED &&
02202 ts->order[j].u.removed.dependsOnIndex == needle->alIndex) {
02203 newOrder[newOrderCount++] = ts->order[j];
02204 } else
02205 break;
02206 }
02207 }
02208
02209 for (i = 0; i < ts->orderCount; i++) {
02210 if (ts->order[i].type == TR_REMOVED &&
02211 ts->order[i].u.removed.dependsOnIndex == -1) {
02212 newOrder[newOrderCount++] = ts->order[i];
02213 }
02214 }
02215 assert(newOrderCount == ts->orderCount);
02216
02217 ts->order = _free(ts->order);
02218 ts->order = newOrder;
02219 ts->orderAlloced = ts->orderCount;
02220 orderList = _free(orderList);
02221
02222 return 0;
02223 }
02224
02231 static int rpmdbCloseDBI( rpmdb db, int rpmtag)
02232
02233 {
02234 int dbix;
02235 int rc = 0;
02236
02237 if (db == NULL || db->_dbi == NULL || dbiTags == NULL)
02238 return 0;
02239
02240 for (dbix = 0; dbix < dbiTagsMax; dbix++) {
02241 if (dbiTags[dbix] != rpmtag)
02242 continue;
02243 if (db->_dbi[dbix] != NULL) {
02244 int xx;
02245
02246 xx = dbiClose(db->_dbi[dbix], 0);
02247 if (xx && rc == 0) rc = xx;
02248 db->_dbi[dbix] = NULL;
02249
02250 }
02251 break;
02252 }
02253 return rc;
02254 }
02255
02256 int rpmdepCheck(rpmTransactionSet ts,
02257 rpmDependencyConflict * conflicts, int * numConflicts)
02258 {
02259 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
02260 HFD_t hfd = headerFreeData;
02261 rpmdbMatchIterator mi = NULL;
02262 Header h = NULL;
02263 struct availablePackage * p;
02264 problemsSet ps;
02265 int npkgs;
02266 int i, j;
02267 int rc;
02268
02269 npkgs = ts->addedPackages.size;
02270
02271 ps = xcalloc(1, sizeof(*ps));
02272 ps->alloced = 5;
02273 ps->num = 0;
02274 ps->problems = xcalloc(ps->alloced, sizeof(*ps->problems));
02275
02276 *conflicts = NULL;
02277 *numConflicts = 0;
02278
02279 alMakeIndex(&ts->addedPackages);
02280 alMakeIndex(&ts->availablePackages);
02281
02282
02283
02284
02285
02286 if ((p = ts->addedPackages.list) != NULL)
02287 for (i = 0; i < npkgs; i++, p++)
02288 {
02289
02290 rpmMessage(RPMMESS_DEBUG, "========== +++ %s-%s-%s\n" ,
02291 p->name, p->version, p->release);
02292 rc = checkPackageDeps(ts, ps, p->h, NULL, p->multiLib);
02293 if (rc)
02294 goto exit;
02295
02296
02297 rc = checkDependentConflicts(ts, ps, p->name);
02298 if (rc)
02299 goto exit;
02300
02301 if (p->providesCount == 0 || p->provides == NULL)
02302 continue;
02303
02304 rc = 0;
02305 for (j = 0; j < p->providesCount; j++) {
02306
02307 if (!checkDependentConflicts(ts, ps, p->provides[j]))
02308 continue;
02309 rc = 1;
02310 break;
02311 }
02312 if (rc)
02313 goto exit;
02314 }
02315
02316
02317
02318
02319 if (ts->numRemovedPackages > 0) {
02320 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
02321 (void) rpmdbAppendIterator(mi,
02322 ts->removedPackages, ts->numRemovedPackages);
02323 while ((h = rpmdbNextIterator(mi)) != NULL) {
02324
02325 { const char * name, * version, * release;
02326 (void) headerNVR(h, &name, &version, &release);
02327 rpmMessage(RPMMESS_DEBUG, "========== --- %s-%s-%s\n" ,
02328 name, version, release);
02329
02330
02331 rc = checkDependentPackages(ts, ps, name);
02332 if (rc)
02333 goto exit;
02334 }
02335
02336 { const char ** provides;
02337 int providesCount;
02338 rpmTagType pnt;
02339
02340 if (hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides,
02341 &providesCount))
02342 {
02343 rc = 0;
02344 for (j = 0; j < providesCount; j++) {
02345
02346 if (!checkDependentPackages(ts, ps, provides[j]))
02347 continue;
02348 rc = 1;
02349 break;
02350 }
02351 provides = hfd(provides, pnt);
02352 if (rc)
02353 goto exit;
02354 }
02355 }
02356
02357 { const char ** baseNames, ** dirNames;
02358 int_32 * dirIndexes;
02359 rpmTagType dnt, bnt;
02360 int fileCount;
02361 char * fileName = NULL;
02362 int fileAlloced = 0;
02363 int len;
02364
02365 if (hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &fileCount))
02366 {
02367 (void) hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL);
02368 (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes,
02369 NULL);
02370 rc = 0;
02371 for (j = 0; j < fileCount; j++) {
02372 len = strlen(baseNames[j]) + 1 +
02373 strlen(dirNames[dirIndexes[j]]);
02374 if (len > fileAlloced) {
02375 fileAlloced = len * 2;
02376 fileName = xrealloc(fileName, fileAlloced);
02377 }
02378 *fileName = '\0';
02379 (void) stpcpy( stpcpy(fileName, dirNames[dirIndexes[j]]) , baseNames[j]);
02380
02381 if (!checkDependentPackages(ts, ps, fileName))
02382 continue;
02383 rc = 1;
02384 break;
02385 }
02386
02387 fileName = _free(fileName);
02388 baseNames = hfd(baseNames, bnt);
02389 dirNames = hfd(dirNames, dnt);
02390 if (rc)
02391 goto exit;
02392 }
02393 }
02394
02395 }
02396 mi = rpmdbFreeIterator(mi);
02397 }
02398
02399 if (ps->num) {
02400 *conflicts = ps->problems;
02401 ps->problems = NULL;
02402 *numConflicts = ps->num;
02403 }
02404 rc = 0;
02405
02406 exit:
02407 mi = rpmdbFreeIterator(mi);
02408 ps->problems = _free(ps->problems);
02409 ps = _free(ps);
02410 if (_cacheDependsRC)
02411 (void) rpmdbCloseDBI(ts->rpmdb, RPMDBI_DEPENDS);
02412 return rc;
02413 }