00001
00005 #include "system.h"
00006
00007 #include "rpmio_internal.h"
00008 #include <rpmcli.h>
00009
00010 #include <rpmmacro.h>
00011 #include <envvar.h>
00012 #include <ugid.h>
00013
00014
00015 #define CACHE_DEPENDENCY_RESULT 1
00016 #if defined(CACHE_DEPENDENCY_RESULT)
00017 #define _RPMDB_INTERNAL
00018 #endif
00019 #include "rpmdb.h"
00020
00021 #define _RPMEVR_INTERNAL
00022 #include "rpmds.h"
00023 #include "rpmfi.h"
00024
00025 #define _RPMTE_INTERNAL
00026 #include "rpmte.h"
00027
00028 #define _RPMTS_INTERNAL
00029 #include "rpmts.h"
00030
00031 #include "debug.h"
00032
00033
00034
00035
00036
00037
00038
00039
00042 typedef struct orderListIndex_s * orderListIndex;
00043
00044
00047 struct orderListIndex_s {
00048
00049 alKey pkgKey;
00050 int orIndex;
00051 };
00052
00053
00054 #if defined(CACHE_DEPENDENCY_RESULT)
00055 int _cacheDependsRC = CACHE_DEPENDENCY_RESULT;
00056 #endif
00057
00058
00059 const char *rpmNAME = PACKAGE;
00060
00061
00062 const char *rpmEVR = VERSION;
00063
00064
00065 int rpmFLAGS = RPMSENSE_EQUAL;
00066
00073 static int intcmp(const void * a, const void * b)
00074
00075 {
00076 const int * aptr = a;
00077 const int * bptr = b;
00078 int rc = (*aptr - *bptr);
00079 return rc;
00080 }
00081
00091 static int removePackage(rpmts ts, Header h, int dboffset,
00092 int * indexp,
00093 alKey depends)
00094
00095
00096 {
00097 rpmte p;
00098
00099
00100 if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) {
00101 int * needle = NULL;
00102
00103 needle = bsearch(&dboffset, ts->removedPackages, ts->numRemovedPackages,
00104 sizeof(*ts->removedPackages), intcmp);
00105 if (needle != NULL) {
00106
00107 if (indexp != NULL)
00108 *indexp = needle - ts->removedPackages;
00109 return 0;
00110 }
00111
00112 }
00113
00114 if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
00115 ts->allocedRemovedPackages += ts->delta;
00116 ts->removedPackages = xrealloc(ts->removedPackages,
00117 sizeof(ts->removedPackages) * ts->allocedRemovedPackages);
00118 }
00119
00120 if (ts->removedPackages != NULL) {
00121
00122 ts->removedPackages[ts->numRemovedPackages] = dboffset;
00123 ts->numRemovedPackages++;
00124
00125 if (ts->numRemovedPackages > 1)
00126 qsort(ts->removedPackages, ts->numRemovedPackages,
00127 sizeof(*ts->removedPackages), intcmp);
00128 }
00129
00130 if (ts->orderCount >= ts->orderAlloced) {
00131 ts->orderAlloced += (ts->orderCount - ts->orderAlloced) + ts->delta;
00132
00133 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00134
00135 }
00136
00137 p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, dboffset, depends);
00138
00139 ts->order[ts->orderCount] = p;
00140 if (indexp != NULL)
00141 *indexp = ts->orderCount;
00142 ts->orderCount++;
00143
00144
00145
00146 return 0;
00147
00148 }
00149
00156 static int rpmHeadersIdentical(Header first, Header second)
00157
00158 {
00159 const char * one, * two;
00160 rpmds A, B;
00161 int rc;
00162
00163 if (!headerGetEntry(first, RPMTAG_HDRID, NULL, &one, NULL))
00164 one = NULL;
00165 if (!headerGetEntry(second, RPMTAG_HDRID, NULL, &two, NULL))
00166 two = NULL;
00167
00168 if (one && two)
00169 return ((strcmp(one, two) == 0) ? 1 : 0);
00170 if (one && !two)
00171 return 0;
00172 if (!one && two)
00173 return 0;
00174
00175 A = rpmdsThis(first, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
00176 B = rpmdsThis(second, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
00177 rc = rpmdsCompare(A, B);
00178 A = rpmdsFree(A);
00179 B = rpmdsFree(B);
00180 return rc;
00181 }
00182
00183
00184
00185 static rpmTag _upgrade_tag;
00186 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL)
00187
00188 static rpmTag _debuginfo_tag;
00189 #endif
00190
00191 static rpmTag _obsolete_tag;
00192
00201 static int rpmtsAddUpgrades(rpmts ts, rpmte p, uint32_t hcolor, Header h)
00202 {
00203 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00204 uint32_t tscolor = rpmtsColor(ts);
00205 alKey pkgKey = rpmteAddedKey(p);
00206 uint32_t ohcolor;
00207 rpmdbMatchIterator mi;
00208 Header oh;
00209 int xx;
00210
00211 if (_upgrade_tag == 0) {
00212 const char * t = rpmExpand("%{?_upgrade_tag}", NULL);
00213
00214 _upgrade_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
00215
00216 t = _free(t);
00217 }
00218
00219 mi = rpmtsInitIterator(ts, _upgrade_tag, rpmteN(p), 0);
00220 while((oh = rpmdbNextIterator(mi)) != NULL) {
00221 int lastx;
00222 rpmte q;
00223
00224
00225 ohcolor = hGetColor(oh);
00226 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
00227 continue;
00228
00229 #if defined(SUPPORT_ORIGINTID)
00230
00231 he->tag = RPMTAG_ORIGINTID;
00232 xx = headerGet(oh, he, 0);
00233 if (xx && he->p.ui32p != NULL) {
00234 if (p->originTid[0] == 0 || p->originTid[0] > he->p.ui32p[0]
00235 || (he->c > 1 && p->originTid[0] == he->p.ui32p[0] && p->originTid[1] > he->p.ui32p[1]))
00236 {
00237 p->originTid[0] = he->p.ui32p[0];
00238 p->originTid[1] = (he->c > 1 ? he->p.ui32p[1] : 0);
00239 }
00240 he->p.ptr = _free(he->p.ptr);
00241 }
00242 he->tag = RPMTAG_ORIGINTIME;
00243 xx = headerGet(oh, he, 0);
00244 if (xx && he->p.ui32p != NULL) {
00245 if (p->originTime[0] == 0 || p->originTime[0] > he->p.ui32p[0]
00246 || (he->c > 1 && p->originTime[0] == he->p.ui32p[0] && p->originTime[1] > he->p.ui32p[1]))
00247 {
00248 p->originTime[0] = he->p.ui32p[0];
00249 p->originTime[1] = (he->c > 1 ? he->p.ui32p[1] : 0);
00250 }
00251 he->p.ptr = _free(he->p.ptr);
00252 }
00253 #endif
00254
00255
00256 if (rpmHeadersIdentical(h, oh))
00257 continue;
00258
00259
00260 lastx = -1;
00261 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), &lastx, pkgKey);
00262 assert(lastx >= 0 && lastx < ts->orderCount);
00263 q = ts->order[lastx];
00264
00265
00266 xx = rpmteChain(p, q, oh, "Upgrades");
00267
00268
00269 rpmlog(RPMLOG_DEBUG, D_(" upgrade erases %s\n"), rpmteNEVRA(q));
00270
00271
00272 }
00273 mi = rpmdbFreeIterator(mi);
00274
00275 return 0;
00276 }
00277
00278 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL)
00279
00285 static inline int chkSuffix(const char * fn, const char * suffix)
00286
00287 {
00288 size_t flen = strlen(fn);
00289 size_t slen = strlen(suffix);
00290 return (flen > slen && !strcmp(fn + flen - slen, suffix));
00291 }
00292
00301 static int rpmtsEraseDebuginfo(rpmts ts, rpmte p, Header h, alKey pkgKey)
00302 {
00303 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00304 const void *keyval = NULL;
00305 size_t keylen = 0;
00306 size_t nrefs = 0;
00307 uint32_t debuginfoInstance = 0;
00308 Header debuginfoHeader = NULL;
00309 rpmdbMatchIterator mi;
00310 Header oh;
00311 int xx;
00312
00313
00314 if (_debuginfo_tag == 0) {
00315 const char * t = rpmExpand("%{?_debuginfo_tag}", NULL);
00316
00317 _debuginfo_tag = (*t != '\0' && !strcmp(t, "pkgid")
00318 ? RPMTAG_SOURCEPKGID : RPMTAG_SOURCERPM);
00319
00320 t = _free(t);
00321 }
00322
00323
00324 switch (_debuginfo_tag) {
00325 default: return 0; break;
00326 case RPMTAG_SOURCERPM: keyval = rpmteSourcerpm(p); break;
00327 }
00328
00329
00330 mi = rpmtsInitIterator(ts, _debuginfo_tag, keyval, keylen);
00331 xx = rpmdbPruneIterator(mi, ts->removedPackages, ts->numRemovedPackages, 1);
00332 while((oh = rpmdbNextIterator(mi)) != NULL) {
00333
00334 if (rpmHeadersIdentical(h, oh))
00335 continue;
00336
00337 he->tag = RPMTAG_NAME;
00338 xx = headerGet(oh, he, 0);
00339 if (!xx || he->p.str == NULL)
00340 continue;
00341
00342 if (chkSuffix(he->p.str, "-debuginfo")) {
00343 debuginfoInstance = rpmdbGetIteratorOffset(mi);
00344 debuginfoHeader = headerLink(oh);
00345 } else
00346 nrefs++;
00347 he->p.str = _free(he->p.str);
00348 }
00349 mi = rpmdbFreeIterator(mi);
00350
00351
00352 if (nrefs == 0 && debuginfoInstance > 0 && debuginfoHeader != NULL) {
00353 int lastx = -1;
00354 rpmte q;
00355
00356
00357 lastx = -1;
00358 xx = removePackage(ts, debuginfoHeader, debuginfoInstance,
00359 &lastx, pkgKey);
00360 assert(lastx >= 0 && lastx < ts->orderCount);
00361 q = ts->order[lastx];
00362
00363
00364
00365 if (pkgKey != RPMAL_NOMATCH)
00366 xx = rpmteChain(p, q, oh, "Upgrades");
00367
00368
00369 rpmlog(RPMLOG_DEBUG, D_(" lastref erases %s\n"), rpmteNEVRA(q));
00370
00371
00372 }
00373 debuginfoHeader = headerFree(debuginfoHeader);
00374
00375 return nrefs;
00376 }
00377 #endif
00378
00386 static int rpmtsAddObsoletes(rpmts ts, rpmte p, uint32_t hcolor)
00387 {
00388 uint32_t tscolor = rpmtsColor(ts);
00389 alKey pkgKey = rpmteAddedKey(p);
00390 uint32_t ohcolor;
00391 rpmds obsoletes;
00392 uint32_t dscolor;
00393 rpmdbMatchIterator mi;
00394 Header oh;
00395 int xx;
00396
00397 if (_obsolete_tag == 0) {
00398 const char *t = rpmExpand("%{?_obsolete_tag}", NULL);
00399
00400 _obsolete_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
00401
00402 t = _free(t);
00403 }
00404
00405 obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME), "Obsoletes");
00406 obsoletes = rpmdsInit(obsoletes);
00407 if (obsoletes != NULL)
00408 while (rpmdsNext(obsoletes) >= 0) {
00409 const char * Name;
00410
00411 if ((Name = rpmdsN(obsoletes)) == NULL)
00412 continue;
00413
00414
00415 #if 0
00416
00417 dscolor = rpmdsColor(obsoletes);
00418 #else
00419 dscolor = hcolor;
00420 #endif
00421 if (tscolor && dscolor && !(tscolor & dscolor))
00422 continue;
00423
00424
00425 if (!strcmp(rpmteN(p), Name))
00426 continue;
00427
00428
00429 if (Name[0] == '/')
00430 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
00431 else
00432 mi = rpmtsInitIterator(ts, _obsolete_tag, Name, 0);
00433
00434 xx = rpmdbPruneIterator(mi,
00435 ts->removedPackages, ts->numRemovedPackages, 1);
00436
00437 while((oh = rpmdbNextIterator(mi)) != NULL) {
00438 int lastx;
00439 rpmte q;
00440
00441
00442 ohcolor = hGetColor(oh);
00443
00444
00445
00446 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
00447 continue;
00448
00449
00450
00451
00452
00453 if (!(rpmdsEVR(obsoletes) == NULL
00454 || rpmdsAnyMatchesDep(oh, obsoletes, _rpmds_nopromote)))
00455 continue;
00456
00457
00458 lastx = -1;
00459 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), &lastx, pkgKey);
00460 assert(lastx >= 0 && lastx < ts->orderCount);
00461 q = ts->order[lastx];
00462
00463
00464 xx = rpmteChain(p, q, oh, "Obsoletes");
00465
00466
00467 rpmlog(RPMLOG_DEBUG, D_(" Obsoletes: %s\t\terases %s\n"),
00468 rpmdsDNEVR(obsoletes)+2, rpmteNEVRA(q));
00469
00470 }
00471 mi = rpmdbFreeIterator(mi);
00472 }
00473 obsoletes = rpmdsFree(obsoletes);
00474
00475 return 0;
00476 }
00477
00478
00479 int rpmtsAddInstallElement(rpmts ts, Header h,
00480 fnpyKey key, int upgrade, rpmRelocation relocs)
00481 {
00482 rpmdepFlags depFlags = rpmtsDFlags(ts);
00483 uint_32 tscolor = rpmtsColor(ts);
00484 uint_32 hcolor;
00485 int isSource;
00486 int duplicate = 0;
00487 rpmtsi pi = NULL; rpmte p;
00488 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00489 const char * arch;
00490 const char * os;
00491 rpmds oldChk, newChk;
00492 alKey pkgKey;
00493 int xx;
00494 int ec = 0;
00495 int rc;
00496 int oc;
00497
00498 hcolor = hGetColor(h);
00499 pkgKey = RPMAL_NOMATCH;
00500
00501
00502
00503
00504 isSource = (headerIsEntry(h, RPMTAG_SOURCERPM) == 0) ;
00505 if (isSource) {
00506 oc = ts->orderCount;
00507 goto addheader;
00508 }
00509
00510
00511
00512
00513 arch = NULL;
00514 xx = hge(h, RPMTAG_ARCH, NULL, &arch, NULL);
00515 os = NULL;
00516 xx = hge(h, RPMTAG_OS, NULL, &os, NULL);
00517 if (nplatpat > 1) {
00518 const char * platform = NULL;
00519
00520 if (hge(h, RPMTAG_PLATFORM, NULL, &platform, NULL))
00521 platform = xstrdup(platform);
00522 else
00523 platform = rpmExpand(arch, "-unknown-", os, NULL);
00524
00525 rc = rpmPlatformScore(platform, platpat, nplatpat);
00526 if (rc <= 0) {
00527 const char * pkgNEVR = hGetNEVRA(h, NULL);
00528 rpmps ps = rpmtsProblems(ts);
00529 rpmpsAppend(ps, RPMPROB_BADPLATFORM, pkgNEVR, key,
00530 platform, NULL, NULL, 0);
00531 ps = rpmpsFree(ps);
00532 pkgNEVR = _free(pkgNEVR);
00533 ec = 1;
00534 }
00535 platform = _free(platform);
00536 if (ec)
00537 goto exit;
00538 }
00539
00540
00541
00542
00543 if (!upgrade) {
00544 oc = ts->orderCount;
00545 goto addheader;
00546 }
00547
00548
00549
00550
00551 oldChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_LESS));
00552 newChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_EQUAL|RPMSENSE_GREATER));
00553
00554 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
00555 rpmds this;
00556
00557
00558 if (rpmteType(p) == TR_REMOVED)
00559 continue;
00560
00561
00562 if (rpmteIsSource(p))
00563 continue;
00564
00565 if (tscolor) {
00566 const char * parch;
00567 const char * pos;
00568
00569 if (arch == NULL || (parch = rpmteA(p)) == NULL)
00570 continue;
00571
00572 if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') {
00573 if (arch[0] != parch[0]) continue;
00574 if (arch[2] != parch[2]) continue;
00575 if (arch[3] != parch[3]) continue;
00576 } else if (strcmp(arch, parch))
00577 continue;
00578 if (os == NULL || (pos = rpmteO(p)) == NULL)
00579 continue;
00580
00581 if (strcmp(os, pos))
00582 continue;
00583 }
00584
00585
00586 if ((this = rpmteDS(p, RPMTAG_NAME)) == NULL)
00587 continue;
00588
00589
00590 rc = rpmdsCompare(newChk, this);
00591 if (rc != 0) {
00592 const char * pkgNEVR = rpmdsDNEVR(this);
00593 const char * addNEVR = rpmdsDNEVR(oldChk);
00594 if (rpmIsVerbose())
00595 rpmMessage(RPMMESS_WARNING,
00596 _("package %s was already added, skipping %s\n"),
00597 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
00598 (addNEVR ? addNEVR + 2 : "?addNEVR?"));
00599 ec = 1;
00600 break;
00601 }
00602
00603
00604 rc = rpmdsCompare(oldChk, this);
00605 if (rc != 0) {
00606 const char * pkgNEVR = rpmdsDNEVR(this);
00607 const char * addNEVR = rpmdsDNEVR(newChk);
00608 if (rpmIsVerbose())
00609 rpmMessage(RPMMESS_WARNING,
00610 _("package %s was already added, replacing with %s\n"),
00611 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
00612 (addNEVR ? addNEVR + 2 : "?addNEVR?"));
00613 duplicate = 1;
00614 pkgKey = rpmteAddedKey(p);
00615 break;
00616 }
00617 }
00618 pi = rpmtsiFree(pi);
00619 oldChk = rpmdsFree(oldChk);
00620 newChk = rpmdsFree(newChk);
00621
00622
00623 if (ec)
00624 goto exit;
00625
00626 addheader:
00627 if (oc >= ts->orderAlloced) {
00628 ts->orderAlloced += (oc - ts->orderAlloced) + ts->delta;
00629
00630 ts->order = xrealloc(ts->order, ts->orderAlloced * sizeof(*ts->order));
00631
00632 }
00633
00634 p = rpmteNew(ts, h, TR_ADDED, key, relocs, -1, pkgKey);
00635 assert(p != NULL);
00636
00637 if (duplicate && oc < ts->orderCount) {
00638
00639
00640 ts->order[oc] = rpmteFree(ts->order[oc]);
00641
00642
00643 }
00644
00645
00646 ts->order[oc] = p;
00647
00648 if (!duplicate) {
00649 ts->orderCount++;
00650 rpmcliPackagesTotal++;
00651 }
00652
00653 pkgKey = rpmalAdd(&ts->addedPackages, pkgKey, rpmteKey(p),
00654 rpmteDS(p, RPMTAG_PROVIDENAME),
00655 rpmteFI(p, RPMTAG_BASENAMES), tscolor);
00656 if (pkgKey == RPMAL_NOMATCH) {
00657
00658 ts->order[oc] = rpmteFree(ts->order[oc]);
00659
00660 ts->teInstall = NULL;
00661 ec = 1;
00662 goto exit;
00663 }
00664 (void) rpmteSetAddedKey(p, pkgKey);
00665
00666 if (!duplicate) {
00667 ts->numAddedPackages++;
00668 }
00669
00670 ts->teInstall = ts->order[oc];
00671
00672
00673 if (upgrade & 0x2)
00674 (void) rpmteSetHeader(p, h);
00675
00676
00677 if (!(upgrade & 0x1))
00678 goto exit;
00679
00680
00681
00682 if (isSource)
00683 goto exit;
00684
00685
00686 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
00687 if ((ec = rpmtsOpenDB(ts, ts->dbmode)) != 0)
00688 goto exit;
00689 }
00690
00691
00692 if (!(depFlags & RPMDEPS_FLAG_NOUPGRADE)) {
00693 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL)
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 xx = rpmtsEraseDebuginfo(ts, p, h, pkgKey);
00704 if (!chkSuffix(rpmteN(p), "-debuginfo") || xx == 0)
00705 #endif
00706 xx = rpmtsAddUpgrades(ts, p, hcolor, h);
00707 }
00708
00709
00710 if (!(depFlags & RPMDEPS_FLAG_NOOBSOLETES)) {
00711 xx = rpmtsAddObsoletes(ts, p, hcolor);
00712 }
00713 ec = 0;
00714
00715 exit:
00716 pi = rpmtsiFree(pi);
00717 return ec;
00718 }
00719
00720 int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
00721 {
00722 int oc = -1;
00723 int rc = removePackage(ts, h, dboffset, &oc, RPMAL_NOMATCH);
00724 if (rc == 0 && oc >= 0 && oc < ts->orderCount) {
00725 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL)
00726 (void) rpmtsEraseDebuginfo(ts, ts->order[oc], h, RPMAL_NOMATCH);
00727 #endif
00728 ts->teErase = ts->order[oc];
00729 } else
00730 ts->teErase = NULL;
00731 return rc;
00732 }
00733
00741 static int unsatisfiedDepend(rpmts ts, rpmds dep, int adding)
00742
00743
00744
00745
00746 {
00747 DBT * key = alloca(sizeof(*key));
00748 DBT * data = alloca(sizeof(*data));
00749 rpmdbMatchIterator mi;
00750 nsType NSType;
00751 const char * Name;
00752 int_32 Flags;
00753 Header h;
00754 #if defined(CACHE_DEPENDENCY_RESULT)
00755 int _cacheThisRC = 1;
00756 #endif
00757 int rc;
00758 int xx;
00759 int retries = 10;
00760
00761 if ((Name = rpmdsN(dep)) == NULL)
00762 return 0;
00763 Flags = rpmdsFlags(dep);
00764 NSType = rpmdsNSType(dep);
00765
00766
00767
00768
00769 #if defined(CACHE_DEPENDENCY_RESULT)
00770 if (_cacheDependsRC) {
00771 dbiIndex dbi;
00772 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
00773 if (dbi == NULL)
00774 _cacheDependsRC = 0;
00775 else {
00776 const char * DNEVR;
00777
00778 rc = -1;
00779
00780 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
00781 DBC * dbcursor = NULL;
00782 void * datap = NULL;
00783 size_t datalen = 0;
00784 size_t DNEVRlen = strlen(DNEVR);
00785
00786 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, 0);
00787
00788 memset(key, 0, sizeof(*key));
00789 key->data = (void *) DNEVR;
00790 key->size = DNEVRlen;
00791 memset(data, 0, sizeof(*data));
00792 data->data = datap;
00793 data->size = datalen;
00794
00795 xx = dbiGet(dbi, dbcursor, key, data, DB_SET);
00796
00797 DNEVR = key->data;
00798 DNEVRlen = key->size;
00799 datap = data->data;
00800 datalen = data->size;
00801
00802
00803 if (xx == 0 && datap && datalen == 4)
00804 memcpy(&rc, datap, datalen);
00805
00806 xx = dbiCclose(dbi, dbcursor, 0);
00807 }
00808
00809
00810 if (rc >= 0) {
00811 rpmdsNotify(dep, _("(cached)"), rc);
00812 return rpmdsNegateRC(dep, rc);
00813 }
00814 }
00815 }
00816 #endif
00817
00818 retry:
00819 rc = 0;
00820
00821
00822 if (NSType == RPMNS_TYPE_FUNCTION) {
00823 xx = rpmExpandNumeric(Name);
00824 rc = (xx ? 0 : 1);
00825 if (Flags & RPMSENSE_MISSINGOK)
00826 goto unsatisfied;
00827 rpmdsNotify(dep, _("(function probe)"), rc);
00828 goto exit;
00829 }
00830
00831 #if 0
00832
00833 if (NSType == RPMNS_TYPE_USER) {
00834 const char *s;
00835 uid_t uid = 0;
00836 s = Name; while (*s && xisdigit(*s)) s++;
00837
00838 if (*s)
00839 xx = unameToUid(Name, &uid);
00840 else {
00841 uid = strtol(Name, NULL, 10);
00842 xx = (uidToUname(uid) ? 0 : -1);
00843 }
00844 rc = (xx >= 0 ? 0 : 1);
00845 if (Flags & RPMSENSE_MISSINGOK)
00846 goto unsatisfied;
00847 rpmdsNotify(dep, _("(user lookup)"), rc);
00848 goto exit;
00849 }
00850 if (NSType == RPMNS_TYPE_GROUP) {
00851 const char *s;
00852 gid_t gid = 0;
00853 s = Name; while (*s && xisdigit(*s)) s++;
00854
00855 if (*s)
00856 xx = gnameToGid(Name, &gid);
00857 else {
00858 gid = strtol(Name, NULL, 10);
00859 xx = (gidToGname(gid) ? 0 : -1);
00860 }
00861 rc = (xx >= 0 ? 0 : 1);
00862 if (Flags & RPMSENSE_MISSINGOK)
00863 goto unsatisfied;
00864 rpmdsNotify(dep, _("(group lookup)"), rc);
00865 goto exit;
00866 }
00867 #endif
00868
00869
00870 if (NSType == RPMNS_TYPE_ACCESS) {
00871 rc = rpmioAccess(Name, NULL, X_OK);
00872 if (Flags & RPMSENSE_MISSINGOK)
00873 goto unsatisfied;
00874 rpmdsNotify(dep, _("(access probe)"), rc);
00875 goto exit;
00876 }
00877
00878
00879 if (NSType == RPMNS_TYPE_MOUNTED) {
00880 const char ** fs = NULL;
00881 int nfs = 0;
00882 int i = 0;
00883
00884 xx = rpmtsInitDSI(ts);
00885 fs = ts->filesystems;
00886 nfs = ts->filesystemCount;
00887
00888 if (fs != NULL)
00889 for (i = 0; i < nfs; i++) {
00890 if (!strcmp(fs[i], Name))
00891 break;
00892 }
00893 rc = (i < nfs ? 0 : 1);
00894 if (Flags & RPMSENSE_MISSINGOK)
00895 goto unsatisfied;
00896 rpmdsNotify(dep, _("(mtab probe)"), rc);
00897 goto exit;
00898 }
00899
00900 if (NSType == RPMNS_TYPE_DISKSPACE) {
00901 size_t nb = strlen(Name);
00902 rpmDiskSpaceInfo dsi = NULL;
00903 const char ** fs = NULL;
00904 size_t fslen = 0, longest = 0;
00905 int nfs = 0;
00906 int i = 0;
00907
00908 xx = rpmtsInitDSI(ts);
00909 fs = ts->filesystems;
00910 nfs = ts->filesystemCount;
00911
00912 if (fs != NULL)
00913 for (i = 0; i < nfs; i++) {
00914 fslen = strlen(fs[i]);
00915 if (fslen > nb)
00916 continue;
00917 if (strncmp(fs[i], Name, fslen))
00918 continue;
00919 if (fslen > 1 && Name[fslen] != '/' && Name[fslen] != '\0')
00920 continue;
00921 if (fslen < longest)
00922 continue;
00923 longest = fslen;
00924 dsi = ts->dsi + i;
00925 }
00926 if (dsi == NULL)
00927 rc = 1;
00928 else {
00929 char * end = NULL;
00930 long long needed = strtoll(rpmdsEVR(dep), &end, 0);
00931
00932 if (end && *end) {
00933 if (strchr("Gg", end[0]) && strchr("Bb", end[1]) && !end[2])
00934 needed *= 1024 * 1024 * 1024;
00935 if (strchr("Mm", end[0]) && strchr("Bb", end[1]) && !end[2])
00936 needed *= 1024 * 1024;
00937 if (strchr("Kk", end[0]) && strchr("Bb", end[1]) && !end[2])
00938 needed *= 1024;
00939 } else
00940 needed *= 1024 * 1024;
00941
00942 needed = BLOCK_ROUND(needed, dsi->f_bsize);
00943 xx = (dsi->f_bavail - needed);
00944 if ((Flags & RPMSENSE_LESS) && xx < 0) rc = 0;
00945 else if ((Flags & RPMSENSE_GREATER) && xx > 0) rc = 0;
00946 else if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0;
00947 else rc = 1;
00948 }
00949 if (Flags & RPMSENSE_MISSINGOK)
00950 goto unsatisfied;
00951 rpmdsNotify(dep, _("(diskspace probe)"), rc);
00952 goto exit;
00953 }
00954
00955 if (NSType == RPMNS_TYPE_DIGEST) {
00956 const char * EVR = rpmdsEVR(dep);
00957 FD_t fd = Fopen(Name, "r");
00958
00959 rc = 1;
00960 if (fd && !Ferror(fd)) {
00961 pgpHashAlgo digestHashAlgo = PGPHASHALGO_MD5;
00962 DIGEST_CTX ctx = rpmDigestInit(digestHashAlgo, RPMDIGEST_NONE);
00963 const char * digest = NULL;
00964 size_t digestlen = 0;
00965 int asAscii = 1;
00966 size_t nbuf = 8 * BUFSIZ;
00967 char * buf = alloca(nbuf);
00968 size_t nb;
00969
00970 while ((nb = Fread(buf, sizeof(buf[0]), nbuf, fd)) > 0)
00971 xx = rpmDigestUpdate(ctx, buf, nb);
00972 xx = Fclose(fd); fd = NULL;
00973 xx = rpmDigestFinal(ctx, &digest, &digestlen, asAscii);
00974
00975 xx = (EVR && *EVR && digest && *digest) ? strcmp(EVR, digest) : -1;
00976
00977 if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0;
00978 }
00979 if (Flags & RPMSENSE_MISSINGOK)
00980 goto unsatisfied;
00981 rpmdsNotify(dep, _("(digest probe)"), rc);
00982 goto exit;
00983 }
00984
00985 if (NSType == RPMNS_TYPE_GNUPG) {
00986 static const char gnupg_pre[] = "%(%{__gpg} -qv ";
00987 static const char gnupg_post[] = " 2>/dev/null; echo $?)";
00988 const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL);
00989
00990 rc = (t && t[0] == '0') ? 0 : 1;
00991 t = _free(t);
00992 if (Flags & RPMSENSE_MISSINGOK)
00993 goto unsatisfied;
00994 rpmdsNotify(dep, _("(gnupg probe)"), rc);
00995 goto exit;
00996 }
00997
00998 if (NSType == RPMNS_TYPE_MACRO) {
00999 static const char macro_pre[] = "%{?";
01000 static const char macro_post[] = ":0}";
01001 const char * a = rpmExpand(macro_pre, Name, macro_post, NULL);
01002
01003 rc = (a && a[0] == '0') ? 0 : 1;
01004 a = _free(a);
01005 if (Flags & RPMSENSE_MISSINGOK)
01006 goto unsatisfied;
01007 rpmdsNotify(dep, _("(macro probe)"), rc);
01008 goto exit;
01009 }
01010
01011 if (NSType == RPMNS_TYPE_ENVVAR) {
01012 const char * a = envGet(Name);
01013 const char * b = rpmdsEVR(dep);
01014
01015
01016 if (!(b && *b))
01017 rc = (!(a && *a));
01018 else {
01019 int sense = (a && *a) ? strcmp(a, b) : -1;
01020
01021 if ((Flags & RPMSENSE_SENSEMASK) == RPMSENSE_NOTEQUAL)
01022 rc = (sense == 0);
01023 else if (sense < 0 && (Flags & RPMSENSE_LESS))
01024 rc = 0;
01025 else if (sense > 0 && (Flags & RPMSENSE_GREATER))
01026 rc = 0;
01027 else if (sense == 0 && (Flags & RPMSENSE_EQUAL))
01028 rc = 0;
01029 else
01030 rc = (sense != 0);
01031 }
01032
01033 if (Flags & RPMSENSE_MISSINGOK)
01034 goto unsatisfied;
01035 rpmdsNotify(dep, _("(envvar probe)"), rc);
01036 goto exit;
01037 }
01038
01039 if (NSType == RPMNS_TYPE_RUNNING) {
01040 char *t = NULL;
01041 pid_t pid = strtol(Name, &t, 10);
01042
01043 if (t == NULL || *t != '\0') {
01044 const char * fn = rpmGetPath("%{_varrun}/", Name, ".pid", NULL);
01045 FD_t fd = NULL;
01046
01047 if (fn && *fn != '%' && (fd = Fopen(fn, "r")) && !Ferror(fd)) {
01048 char buf[32];
01049 size_t nb = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
01050
01051 if (nb > 0)
01052 pid = strtol(buf, &t, 10);
01053 } else
01054 pid = 0;
01055 if (fd != NULL)
01056 (void) Fclose(fd);
01057 fn = _free(fn);
01058 }
01059 rc = (pid > 0 ? (kill(pid, 0) < 0 && errno == ESRCH) : 1);
01060 if (Flags & RPMSENSE_MISSINGOK)
01061 goto unsatisfied;
01062 rpmdsNotify(dep, _("(running probe)"), rc);
01063 goto exit;
01064 }
01065
01066
01067
01068 if (!rpmioAccess("/etc/rpm/sysinfo", NULL, R_OK)) {
01069 #ifdef NOTYET
01070 rpmTag tagN = (Name[0] == '/' ? RPMTAG_DIRNAMES : RPMTAG_PROVIDENAME);
01071 #else
01072 rpmTag tagN = RPMTAG_PROVIDENAME;
01073 #endif
01074 rpmds P = rpmdsFromPRCO(ts->PRCO, tagN);
01075 if (rpmdsSearch(P, dep) >= 0) {
01076 rpmdsNotify(dep, _("(sysinfo provides)"), rc);
01077 goto exit;
01078 }
01079 }
01080
01081
01082
01083
01084
01085
01086 if (NSType == RPMNS_TYPE_RPMLIB) {
01087 static rpmds rpmlibP = NULL;
01088 static int oneshot = -1;
01089
01090 if (oneshot)
01091 oneshot = rpmdsRpmlib(&rpmlibP, NULL);
01092 if (rpmlibP == NULL)
01093 goto unsatisfied;
01094
01095 if (rpmdsSearch(rpmlibP, dep) >= 0) {
01096 rpmdsNotify(dep, _("(rpmlib provides)"), rc);
01097 goto exit;
01098 }
01099 goto unsatisfied;
01100 }
01101
01102 if (NSType == RPMNS_TYPE_CPUINFO) {
01103 static rpmds cpuinfoP = NULL;
01104 static int oneshot = -1;
01105
01106 if (oneshot)
01107 oneshot = rpmdsCpuinfo(&cpuinfoP, NULL);
01108 if (cpuinfoP == NULL)
01109 goto unsatisfied;
01110
01111 if (rpmdsSearch(cpuinfoP, dep) >= 0) {
01112 rpmdsNotify(dep, _("(cpuinfo provides)"), rc);
01113 goto exit;
01114 }
01115 goto unsatisfied;
01116 }
01117
01118 if (NSType == RPMNS_TYPE_GETCONF) {
01119 static rpmds getconfP = NULL;
01120 static int oneshot = -1;
01121
01122 if (oneshot)
01123 oneshot = rpmdsGetconf(&getconfP, NULL);
01124 if (getconfP == NULL)
01125 goto unsatisfied;
01126
01127 if (rpmdsSearch(getconfP, dep) >= 0) {
01128 rpmdsNotify(dep, _("(getconf provides)"), rc);
01129 goto exit;
01130 }
01131 goto unsatisfied;
01132 }
01133
01134 if (NSType == RPMNS_TYPE_UNAME) {
01135 static rpmds unameP = NULL;
01136 static int oneshot = -1;
01137
01138 if (oneshot)
01139 oneshot = rpmdsUname(&unameP, NULL);
01140 if (unameP == NULL)
01141 goto unsatisfied;
01142
01143 if (rpmdsSearch(unameP, dep) >= 0) {
01144 rpmdsNotify(dep, _("(uname provides)"), rc);
01145 goto exit;
01146 }
01147 goto unsatisfied;
01148 }
01149
01150 if (NSType == RPMNS_TYPE_SONAME) {
01151 rpmds sonameP = NULL;
01152 rpmPRCO PRCO = rpmdsNewPRCO(NULL);
01153 char * fn = strcpy(alloca(strlen(Name)+1), Name);
01154 int flags = 0;
01155 rpmds ds;
01156
01157
01158 if (*fn != '/')
01159 goto unsatisfied;
01160 fn[strlen(fn)-1] = '\0';
01161
01162
01163 xx = rpmdsELF(fn, flags, rpmdsMergePRCO, PRCO);
01164 sonameP = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
01165 if (!(xx == 0 && sonameP != NULL))
01166 goto unsatisfied;
01167
01168
01169 ds = rpmdsSingle(rpmdsTagN(dep), rpmdsEVR(dep), "", Flags);
01170 xx = rpmdsSearch(sonameP, ds);
01171 ds = rpmdsFree(ds);
01172 PRCO = rpmdsFreePRCO(PRCO);
01173
01174
01175 if (xx >= 0) {
01176 rpmdsNotify(dep, _("(soname provides)"), rc);
01177 goto exit;
01178 }
01179 goto unsatisfied;
01180 }
01181
01182
01183 if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) {
01184 #if defined(CACHE_DEPENDENCY_RESULT)
01185
01186
01187
01188
01189 if (_rpmds_nopromote)
01190 _cacheThisRC = 0;
01191 #endif
01192 goto exit;
01193 }
01194
01195
01196 if (rpmtsGetRdb(ts) != NULL) {
01197
01198 if (Name[0] == '/') {
01199
01200
01201 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
01202 (void) rpmdbPruneIterator(mi,
01203 ts->removedPackages, ts->numRemovedPackages, 1);
01204 while ((h = rpmdbNextIterator(mi)) != NULL) {
01205 rpmdsNotify(dep, _("(db files)"), rc);
01206 mi = rpmdbFreeIterator(mi);
01207 goto exit;
01208 }
01209 mi = rpmdbFreeIterator(mi);
01210 }
01211
01212
01213 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
01214 (void) rpmdbPruneIterator(mi,
01215 ts->removedPackages, ts->numRemovedPackages, 1);
01216 while ((h = rpmdbNextIterator(mi)) != NULL) {
01217 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) {
01218 rpmdsNotify(dep, _("(db provides)"), rc);
01219 mi = rpmdbFreeIterator(mi);
01220 goto exit;
01221 }
01222 }
01223 mi = rpmdbFreeIterator(mi);
01224
01225 }
01226
01227
01228
01229
01230
01231 if (adding == 1 && retries > 0 && !(rpmtsDFlags(ts) & RPMDEPS_FLAG_NOSUGGEST)) {
01232 if (ts->solve != NULL) {
01233 xx = (*ts->solve) (ts, dep, ts->solveData);
01234 if (xx == 0)
01235 goto exit;
01236 if (xx == -1) {
01237 retries--;
01238 rpmalMakeIndex(ts->addedPackages);
01239 goto retry;
01240 }
01241 }
01242 }
01243
01244
01245 unsatisfied:
01246 if (Flags & RPMSENSE_MISSINGOK) {
01247 rc = 0;
01248 _cacheThisRC = 0;
01249 rpmdsNotify(dep, _("(hint skipped)"), rc);
01250 } else {
01251 rc = 1;
01252 rpmdsNotify(dep, NULL, rc);
01253 }
01254
01255 exit:
01256
01257
01258
01259 #if defined(CACHE_DEPENDENCY_RESULT)
01260 if (_cacheDependsRC && _cacheThisRC) {
01261 dbiIndex dbi;
01262 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
01263 if (dbi == NULL) {
01264 _cacheDependsRC = 0;
01265 } else {
01266 const char * DNEVR;
01267 xx = 0;
01268
01269 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
01270 DBC * dbcursor = NULL;
01271 size_t DNEVRlen = strlen(DNEVR);
01272
01273 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, DB_WRITECURSOR);
01274
01275 memset(key, 0, sizeof(*key));
01276 key->data = (void *) DNEVR;
01277 key->size = DNEVRlen;
01278 memset(data, 0, sizeof(*data));
01279 data->data = &rc;
01280 data->size = sizeof(rc);
01281
01282
01283 xx = dbiPut(dbi, dbcursor, key, data, 0);
01284
01285 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
01286 }
01287
01288 if (xx)
01289 _cacheDependsRC = 0;
01290 }
01291 }
01292 #endif
01293
01294 return rpmdsNegateRC(dep, rc);
01295 }
01296
01310 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA,
01311 rpmds requires,
01312 rpmds conflicts,
01313 rpmds dirnames,
01314 rpmds linktos,
01315 const char * depName, uint_32 tscolor, int adding)
01316
01317
01318
01319
01320 {
01321 rpmps ps = rpmtsProblems(ts);
01322 uint_32 dscolor;
01323 const char * Name;
01324 int rc;
01325 int ourrc = 0;
01326 int dirname_deps;
01327 int symlink_deps;
01328
01329 requires = rpmdsInit(requires);
01330 if (requires != NULL)
01331 while (!ourrc && rpmdsNext(requires) >= 0) {
01332
01333 if ((Name = rpmdsN(requires)) == NULL)
01334 continue;
01335
01336
01337 if (depName != NULL && strcmp(depName, Name))
01338 continue;
01339
01340
01341 dscolor = rpmdsColor(requires);
01342 if (tscolor && dscolor && !(tscolor & dscolor))
01343 continue;
01344
01345 rc = unsatisfiedDepend(ts, requires, adding);
01346
01347 switch (rc) {
01348 case 0:
01349 break;
01350 case 1:
01351 { fnpyKey * suggestedKeys = NULL;
01352
01353
01354 if (ts->availablePackages != NULL) {
01355 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
01356 requires, NULL);
01357 }
01358
01359
01360 rpmdsProblem(ps, pkgNEVRA, requires, suggestedKeys, adding);
01361
01362 }
01363 break;
01364 case 2:
01365 default:
01366 ourrc = 1;
01367 break;
01368 }
01369 }
01370
01371 conflicts = rpmdsInit(conflicts);
01372 if (conflicts != NULL)
01373 while (!ourrc && rpmdsNext(conflicts) >= 0) {
01374
01375 if ((Name = rpmdsN(conflicts)) == NULL)
01376 continue;
01377
01378
01379 if (depName != NULL && strcmp(depName, Name))
01380 continue;
01381
01382
01383 dscolor = rpmdsColor(conflicts);
01384 if (tscolor && dscolor && !(tscolor & dscolor))
01385 continue;
01386
01387 rc = unsatisfiedDepend(ts, conflicts, adding);
01388
01389
01390 switch (rc) {
01391 case 0:
01392 rpmdsProblem(ps, pkgNEVRA, conflicts, NULL, adding);
01393 break;
01394 case 1:
01395 break;
01396 case 2:
01397 default:
01398 ourrc = 1;
01399 break;
01400 }
01401 }
01402
01403 dirname_deps = rpmExpandNumeric("%{?_check_dirname_deps}%{?!_check_dirname_deps:1}");
01404 if (dirname_deps) {
01405 dirnames = rpmdsInit(dirnames);
01406 if (dirnames != NULL)
01407 while (!ourrc && rpmdsNext(dirnames) >= 0) {
01408
01409 if ((Name = rpmdsN(dirnames)) == NULL)
01410 continue;
01411
01412
01413 if (depName != NULL && strcmp(depName, Name))
01414 continue;
01415
01416
01417 dscolor = rpmdsColor(dirnames);
01418 if (tscolor && dscolor && !(tscolor & dscolor))
01419 continue;
01420
01421 rc = unsatisfiedDepend(ts, dirnames, adding);
01422
01423 switch (rc) {
01424 case 0:
01425 break;
01426 case 1:
01427 { fnpyKey * suggestedKeys = NULL;
01428
01429
01430 if (ts->availablePackages != NULL) {
01431 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
01432 dirnames, NULL);
01433 }
01434
01435
01436 rpmdsProblem(ps, pkgNEVRA, dirnames, suggestedKeys, adding);
01437
01438 }
01439 break;
01440 case 2:
01441 default:
01442 ourrc = 1;
01443 break;
01444 }
01445 }
01446 }
01447
01448 symlink_deps = rpmExpandNumeric("%{?_check_symlink_deps}%{?!_check_symlink_deps:1}");
01449 if (symlink_deps) {
01450 linktos = rpmdsInit(linktos);
01451 if (linktos != NULL)
01452 while (!ourrc && rpmdsNext(linktos) >= 0) {
01453
01454 if ((Name = rpmdsN(linktos)) == NULL)
01455 continue;
01456 if (*Name == '\0')
01457 continue;
01458
01459
01460 if (depName != NULL && strcmp(depName, Name))
01461 continue;
01462
01463
01464 dscolor = rpmdsColor(linktos);
01465 if (tscolor && dscolor && !(tscolor & dscolor))
01466 continue;
01467 }
01468
01469 rc = unsatisfiedDepend(ts, linktos, adding);
01470
01471 switch (rc) {
01472 case 0:
01473 break;
01474 case 1:
01475 { fnpyKey * suggestedKeys = NULL;
01476
01477
01478 if (ts->availablePackages != NULL) {
01479 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
01480 linktos, NULL);
01481 }
01482
01483
01484 rpmdsProblem(ps, pkgNEVRA, linktos, suggestedKeys, adding);
01485
01486 }
01487 break;
01488 case 2:
01489 default:
01490 ourrc = 1;
01491 break;
01492 }
01493 }
01494
01495 ps = rpmpsFree(ps);
01496 return ourrc;
01497 }
01498
01509 static int checkPackageSet(rpmts ts, const char * depName,
01510 rpmdbMatchIterator mi, int adding)
01511
01512
01513 {
01514 rpmdepFlags depFlags = rpmtsDFlags(ts);
01515 uint_32 tscolor = rpmtsColor(ts);
01516 int scareMem = 0;
01517 Header h;
01518 int ec = 0;
01519
01520 (void) rpmdbPruneIterator(mi,
01521 ts->removedPackages, ts->numRemovedPackages, 1);
01522 while ((h = rpmdbNextIterator(mi)) != NULL) {
01523 const char * pkgNEVRA;
01524 rpmds requires = NULL;
01525 rpmds conflicts = NULL;
01526 rpmds dirnames = NULL;
01527 rpmds linktos = NULL;
01528 int rc;
01529
01530 pkgNEVRA = hGetNEVRA(h, NULL);
01531 if (!(depFlags & RPMDEPS_FLAG_NOREQUIRES))
01532 requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
01533 if (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS))
01534 conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
01535 if (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS))
01536 dirnames = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem);
01537 if (!(depFlags & RPMDEPS_FLAG_NOLINKTOS))
01538 linktos = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem);
01539
01540 (void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
01541 (void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote);
01542 (void) rpmdsSetNoPromote(dirnames, _rpmds_nopromote);
01543 (void) rpmdsSetNoPromote(linktos, _rpmds_nopromote);
01544
01545 rc = checkPackageDeps(ts, pkgNEVRA,
01546 requires, conflicts, dirnames, linktos,
01547 depName, tscolor, adding);
01548
01549 linktos = rpmdsFree(linktos);
01550 dirnames = rpmdsFree(dirnames);
01551 conflicts = rpmdsFree(conflicts);
01552 requires = rpmdsFree(requires);
01553 pkgNEVRA = _free(pkgNEVRA);
01554
01555 if (rc) {
01556 ec = 1;
01557 break;
01558 }
01559 }
01560 mi = rpmdbFreeIterator(mi);
01561
01562 return ec;
01563 }
01564
01571 static int checkDependentPackages(rpmts ts, const char * depName)
01572
01573
01574 {
01575 int rc = 0;
01576
01577
01578 if (rpmtsGetRdb(ts) != NULL) {
01579 rpmdbMatchIterator mi;
01580 mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, depName, 0);
01581 rc = checkPackageSet(ts, depName, mi, 0);
01582 }
01583 return rc;
01584 }
01585
01592 static int checkDependentConflicts(rpmts ts, const char * depName)
01593
01594
01595 {
01596 int rc = 0;
01597
01598
01599 if (rpmtsGetRdb(ts) != NULL) {
01600 rpmdbMatchIterator mi;
01601 mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, depName, 0);
01602 rc = checkPackageSet(ts, depName, mi, 1);
01603 }
01604
01605 return rc;
01606 }
01607
01608 struct badDeps_s {
01609
01610 const char * pname;
01611
01612 const char * qname;
01613 };
01614
01615 #ifdef REFERENCE
01616 static struct badDeps_s {
01617 const char * pname;
01618 const char * qname;
01619 } badDeps[] = {
01620 { "libtermcap", "bash" },
01621 { "modutils", "vixie-cron" },
01622 { "ypbind", "yp-tools" },
01623 { "ghostscript-fonts", "ghostscript" },
01624
01625 { "libgnomeprint15", "gnome-print" },
01626 { "nautilus", "nautilus-mozilla" },
01627
01628 { "arts", "kdelibs-sound" },
01629
01630 { "pango-gtkbeta-devel", "pango-gtkbeta" },
01631 { "XFree86", "Mesa" },
01632 { "compat-glibc", "db2" },
01633 { "compat-glibc", "db1" },
01634 { "pam", "initscripts" },
01635 { "initscripts", "sysklogd" },
01636
01637 { "egcs-c++", "libstdc++" },
01638
01639 { "pilot-link-devel", "pilot-link" },
01640
01641 { "pam", "pamconfig" },
01642 { NULL, NULL }
01643 };
01644 #else
01645
01646 static int badDepsInitialized = 0;
01647
01648
01649 static struct badDeps_s * badDeps = NULL;
01650 #endif
01651
01654
01655 static void freeBadDeps(void)
01656
01657
01658 {
01659 if (badDeps) {
01660 struct badDeps_s * bdp;
01661 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++)
01662 bdp->pname = _free(bdp->pname);
01663 badDeps = _free(badDeps);
01664 }
01665 badDepsInitialized = 0;
01666 }
01667
01668
01677
01678 static int ignoreDep(const rpmts ts, const rpmte p, const rpmte q)
01679
01680
01681
01682
01683 {
01684 struct badDeps_s * bdp;
01685
01686 if (!badDepsInitialized) {
01687 char * s = rpmExpand("%{?_dependency_whiteout}", NULL);
01688 const char ** av = NULL;
01689 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA;
01690 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS))
01691 ? RPMMESS_WARNING : RPMMESS_DEBUG;
01692 int ac = 0;
01693 int i;
01694
01695 if (s != NULL && *s != '\0'
01696 && !(i = poptParseArgvString(s, &ac, (const char ***)&av))
01697 && ac > 0 && av != NULL)
01698 {
01699 bdp = badDeps = xcalloc(ac+1, sizeof(*badDeps));
01700 for (i = 0; i < ac; i++, bdp++) {
01701 char * pname, * qname;
01702
01703 if (av[i] == NULL)
01704 break;
01705 pname = xstrdup(av[i]);
01706 if ((qname = strchr(pname, '>')) != NULL)
01707 *qname++ = '\0';
01708 bdp->pname = pname;
01709
01710 bdp->qname = qname;
01711
01712 rpmMessage(msglvl,
01713 _("ignore package name relation(s) [%d]\t%s -> %s\n"),
01714 i, bdp->pname, (bdp->qname ? bdp->qname : "???"));
01715 }
01716 bdp->pname = NULL;
01717 bdp->qname = NULL;
01718 }
01719 av = _free(av);
01720 s = _free(s);
01721 badDepsInitialized++;
01722 }
01723
01724
01725 if (badDeps != NULL)
01726 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++) {
01727 if (!strcmp(rpmteN(p), bdp->pname) && !strcmp(rpmteN(q), bdp->qname))
01728 return 1;
01729 }
01730 return 0;
01731
01732 }
01733
01734
01740 static void markLoop( tsortInfo tsi, rpmte q)
01741
01742
01743
01744 {
01745 rpmte p;
01746
01747
01748 while (tsi != NULL && (p = tsi->tsi_suc) != NULL) {
01749 tsi = tsi->tsi_next;
01750 if (rpmteTSI(p)->tsi_chain != NULL)
01751 continue;
01752
01753 rpmteTSI(p)->tsi_chain = q;
01754
01755 if (rpmteTSI(p)->tsi_next != NULL)
01756 markLoop(rpmteTSI(p)->tsi_next, p);
01757 }
01758
01759 }
01760
01761
01762
01763
01764
01765
01766 static inline const char * identifyDepend(int_32 f)
01767
01768 {
01769 f = _notpre(f);
01770 if (f & RPMSENSE_SCRIPT_PRE)
01771 return "Requires(pre):";
01772 if (f & RPMSENSE_SCRIPT_POST)
01773 return "Requires(post):";
01774 if (f & RPMSENSE_SCRIPT_PREUN)
01775 return "Requires(preun):";
01776 if (f & RPMSENSE_SCRIPT_POSTUN)
01777 return "Requires(postun):";
01778 if (f & RPMSENSE_SCRIPT_VERIFY)
01779 return "Requires(verify):";
01780 if (f & RPMSENSE_MISSINGOK)
01781 return "Requires(hint):";
01782 if (f & RPMSENSE_FIND_REQUIRES)
01783 return "Requires(auto):";
01784 return "Requires:";
01785 }
01786
01799
01800
01801 static const char *
01802 zapRelation(rpmte q, rpmte p,
01803 int zap, int * nzaps, int msglvl)
01804
01805
01806 {
01807 rpmds requires;
01808 tsortInfo tsi_prev;
01809 tsortInfo tsi;
01810 const char *dp = NULL;
01811
01812 for (tsi_prev = rpmteTSI(q), tsi = rpmteTSI(q)->tsi_next;
01813 tsi != NULL;
01814
01815
01816 tsi_prev = tsi, tsi = tsi->tsi_next)
01817
01818 {
01819 int_32 Flags;
01820
01821
01822 if (tsi->tsi_suc != p)
01823 continue;
01824
01825
01826 requires = rpmteDS((rpmteType(p) == TR_REMOVED ? q : p), tsi->tsi_tagn);
01827 if (requires == NULL) continue;
01828
01829 (void) rpmdsSetIx(requires, tsi->tsi_reqx);
01830
01831 Flags = rpmdsFlags(requires);
01832
01833 dp = rpmdsNewDNEVR( identifyDepend(Flags), requires);
01834
01835
01836
01837
01838
01839 if (zap) {
01840 rpmMessage(msglvl,
01841 _("removing %s \"%s\" from tsort relations.\n"),
01842 (rpmteNEVRA(p) ? rpmteNEVRA(p) : "???"), dp);
01843 rpmteTSI(p)->tsi_count--;
01844 if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next;
01845 tsi->tsi_next = NULL;
01846 tsi->tsi_suc = NULL;
01847 tsi = _free(tsi);
01848 if (nzaps)
01849 (*nzaps)++;
01850 if (zap)
01851 zap--;
01852 }
01853
01854
01855 break;
01856 }
01857 return dp;
01858 }
01859
01860
01861
01870
01871 static inline int addRelation(rpmts ts,
01872 rpmte p,
01873 unsigned char * selected,
01874 rpmds requires)
01875
01876
01877
01878 {
01879 rpmtsi qi; rpmte q;
01880 tsortInfo tsi;
01881 nsType NSType = rpmdsNSType(requires);
01882 fnpyKey key;
01883 int teType = rpmteType(p);
01884 alKey pkgKey;
01885 int i = 0;
01886 rpmal al = (teType == TR_ADDED ? ts->addedPackages : ts->erasedPackages);
01887
01888
01889 switch (NSType) {
01890 case RPMNS_TYPE_RPMLIB:
01891 case RPMNS_TYPE_CPUINFO:
01892 case RPMNS_TYPE_GETCONF:
01893 case RPMNS_TYPE_UNAME:
01894 case RPMNS_TYPE_SONAME:
01895 case RPMNS_TYPE_ACCESS:
01896 case RPMNS_TYPE_USER:
01897 case RPMNS_TYPE_GROUP:
01898 case RPMNS_TYPE_MOUNTED:
01899 case RPMNS_TYPE_DISKSPACE:
01900 case RPMNS_TYPE_DIGEST:
01901 case RPMNS_TYPE_GNUPG:
01902 case RPMNS_TYPE_MACRO:
01903 case RPMNS_TYPE_ENVVAR:
01904 case RPMNS_TYPE_RUNNING:
01905 return 0;
01906 break;
01907 default:
01908 break;
01909 }
01910
01911 { const char * Name = rpmdsN(requires);
01912
01913
01914 if (Name == NULL || !strncmp(Name, "config(", sizeof("config(")-1))
01915 return 0;
01916 }
01917
01918 pkgKey = RPMAL_NOMATCH;
01919 key = rpmalSatisfiesDepend(al, requires, &pkgKey);
01920
01921
01922 if (pkgKey == RPMAL_NOMATCH)
01923 return 0;
01924
01925
01926
01927 if (teType == TR_REMOVED)
01928 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages);
01929
01930 for (qi = rpmtsiInit(ts), i = 0; (q = rpmtsiNext(qi, 0)) != NULL; i++) {
01931 if (pkgKey == rpmteAddedKey(q))
01932 break;
01933 }
01934 qi = rpmtsiFree(qi);
01935 if (q == NULL || i >= ts->orderCount)
01936 return 0;
01937
01938
01939 if (ignoreDep(ts, p, q))
01940 return 0;
01941
01942
01943
01944 if (selected[i] != 0)
01945 return 0;
01946
01947
01948 selected[i] = 1;
01949
01950
01951
01952 if (teType == TR_REMOVED) {
01953 rpmte r = p;
01954 p = q;
01955 q = r;
01956 }
01957
01958
01959 rpmteTSI(p)->tsi_count++;
01960
01961 if (rpmteDepth(p) <= rpmteDepth(q))
01962 (void) rpmteSetDepth(p, (rpmteDepth(q) + 1));
01963 if (rpmteDepth(p) > ts->maxDepth)
01964 ts->maxDepth = rpmteDepth(p);
01965
01966 tsi = xcalloc(1, sizeof(*tsi));
01967 tsi->tsi_suc = p;
01968
01969 tsi->tsi_tagn = rpmdsTagN(requires);
01970 tsi->tsi_reqx = rpmdsIx(requires);
01971
01972 tsi->tsi_next = rpmteTSI(q)->tsi_next;
01973 rpmteTSI(q)->tsi_next = tsi;
01974 rpmteTSI(q)->tsi_qcnt++;
01975
01976 return 0;
01977 }
01978
01979
01986 static int orderListIndexCmp(const void * one, const void * two)
01987 {
01988
01989 long a = (long) ((const orderListIndex)one)->pkgKey;
01990 long b = (long) ((const orderListIndex)two)->pkgKey;
01991
01992 return (a - b);
01993 }
01994
02002
02003
02004 static void addQ( rpmte p,
02005 rpmte * qp,
02006 rpmte * rp,
02007 uint_32 prefcolor)
02008
02009 {
02010 rpmte q, qprev;
02011
02012
02013 rpmteTSI(p)->tsi_queued = 1;
02014
02015 if ((*rp) == NULL) {
02016
02017 (*rp) = (*qp) = p;
02018
02019 return;
02020 }
02021
02022
02023 for (qprev = NULL, q = (*qp);
02024 q != NULL;
02025 qprev = q, q = rpmteTSI(q)->tsi_suc)
02026 {
02027
02028 if (rpmteColor(p) != prefcolor && rpmteColor(p) != rpmteColor(q))
02029 continue;
02030
02031
02032 if (rpmteType(p) == TR_REMOVED && rpmteType(p) != rpmteType(q))
02033 continue;
02034 if (rpmteTSI(q)->tsi_qcnt <= rpmteTSI(p)->tsi_qcnt)
02035 break;
02036 }
02037
02038 if (qprev == NULL) {
02039 rpmteTSI(p)->tsi_suc = q;
02040
02041 (*qp) = p;
02042
02043 } else if (q == NULL) {
02044 rpmteTSI(qprev)->tsi_suc = p;
02045
02046 (*rp) = p;
02047
02048 } else {
02049 rpmteTSI(p)->tsi_suc = q;
02050 rpmteTSI(qprev)->tsi_suc = p;
02051 }
02052 }
02053
02054
02055
02056
02057 #ifdef NOTYET
02058 static uint32_t _autobits = _notpre(_ALL_REQUIRES_MASK);
02059 #define isAuto(_x) ((_x) & _autobits)
02060 #else
02061 static uint32_t _autobits = 0xffffffff;
02062 #define isAuto(_x) (1)
02063 #endif
02064
02065
02066 int rpmtsOrder(rpmts ts)
02067 {
02068 rpmds requires;
02069 int_32 Flags;
02070 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA;
02071 uint_32 prefcolor = rpmtsPrefColor(ts);
02072 rpmtsi pi; rpmte p;
02073 rpmtsi qi; rpmte q;
02074 rpmtsi ri; rpmte r;
02075 tsortInfo tsi;
02076 tsortInfo tsi_next;
02077 alKey * ordering;
02078 int orderingCount = 0;
02079 unsigned char * selected = alloca(sizeof(*selected) * (ts->orderCount + 1));
02080 int loopcheck;
02081 rpmte * newOrder;
02082 int newOrderCount = 0;
02083 orderListIndex orderList;
02084 int numOrderList;
02085 int npeer = 128;
02086 int * peer = memset(alloca(npeer*sizeof(*peer)), 0, (npeer*sizeof(*peer)));
02087 int nrescans = 10;
02088 int _printed = 0;
02089 char deptypechar;
02090 size_t tsbytes;
02091 int oType = 0;
02092 int treex;
02093 int depth;
02094 int breadth;
02095 int qlen;
02096 int i, j;
02097
02098 #ifdef DYING
02099 rpmalMakeIndex(ts->addedPackages);
02100 #endif
02101
02102
02103 pi = rpmtsiInit(ts);
02104 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
02105 alKey pkgKey;
02106 fnpyKey key;
02107 uint_32 tscolor = rpmtsColor(ts);
02108 pkgKey = RPMAL_NOMATCH;
02109
02110 key = (fnpyKey) p;
02111
02112 pkgKey = rpmalAdd(&ts->erasedPackages, pkgKey, key,
02113 rpmteDS(p, RPMTAG_PROVIDENAME),
02114 rpmteFI(p, RPMTAG_BASENAMES), tscolor);
02115
02116 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages);
02117 (void) rpmteSetAddedKey(p, pkgKey);
02118 }
02119 pi = rpmtsiFree(pi);
02120 rpmalMakeIndex(ts->erasedPackages);
02121
02122 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
02123
02124
02125 if (oType == 0)
02126 numOrderList = ts->orderCount;
02127 else {
02128 numOrderList = 0;
02129 if (oType & TR_ADDED)
02130 numOrderList += ts->numAddedPackages;
02131 if (oType & TR_REMOVED)
02132 numOrderList += ts->numRemovedPackages;
02133 }
02134 ordering = alloca(sizeof(*ordering) * (numOrderList + 1));
02135 loopcheck = numOrderList;
02136 tsbytes = 0;
02137
02138 pi = rpmtsiInit(ts);
02139 while ((p = rpmtsiNext(pi, oType)) != NULL)
02140 rpmteNewTSI(p);
02141 pi = rpmtsiFree(pi);
02142
02143
02144 rpmMessage(RPMMESS_DEBUG, D_("========== recording tsort relations\n"));
02145 pi = rpmtsiInit(ts);
02146 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02147
02148 memset(selected, 0, sizeof(*selected) * ts->orderCount);
02149
02150 if ((requires = rpmteDS(p, RPMTAG_REQUIRENAME)) != NULL) {
02151
02152
02153 selected[rpmtsiOc(pi)] = 1;
02154
02155
02156
02157
02158 requires = rpmdsInit(requires);
02159 if (requires != NULL)
02160 while (rpmdsNext(requires) >= 0) {
02161
02162 Flags = rpmdsFlags(requires);
02163 if (!isAuto(Flags))
02164 continue;
02165
02166 switch (rpmteType(p)) {
02167 case TR_REMOVED:
02168
02169 if (!isErasePreReq(Flags))
02170 continue;
02171 break;
02172 case TR_ADDED:
02173
02174 if (!isInstallPreReq(Flags))
02175 continue;
02176 break;
02177 }
02178
02179
02180 (void) addRelation(ts, p, selected, requires);
02181
02182 }
02183
02184
02185 requires = rpmdsInit(requires);
02186 if (requires != NULL)
02187 while (rpmdsNext(requires) >= 0) {
02188
02189 Flags = rpmdsFlags(requires);
02190 if (!isAuto(Flags))
02191 continue;
02192
02193 switch (rpmteType(p)) {
02194 case TR_REMOVED:
02195
02196 if (isErasePreReq(Flags))
02197 continue;
02198 break;
02199 case TR_ADDED:
02200
02201 if (isInstallPreReq(Flags))
02202 continue;
02203 break;
02204 }
02205
02206
02207 (void) addRelation(ts, p, selected, requires);
02208
02209 }
02210 }
02211
02212
02213
02214 if (rpmteType(p) == TR_REMOVED && p->flink.Pkgid && p->flink.Pkgid[0]) {
02215
02216 qi = rpmtsiInit(ts);
02217 while ((q = rpmtsiNext(qi, TR_ADDED)) != NULL) {
02218 if (strcmp(q->pkgid, p->flink.Pkgid[0]))
02219 continue;
02220 requires = rpmdsFromPRCO(q->PRCO, RPMTAG_NAME);
02221 if (requires != NULL) {
02222
02223 p->type = TR_ADDED;
02224 (void) addRelation(ts, p, selected, requires);
02225 p->type = TR_REMOVED;
02226 }
02227 }
02228 qi = rpmtsiFree(qi);
02229 }
02230
02231 if (_autobits != 0xffffffff)
02232 {
02233
02234
02235 requires = rpmdsInit(rpmteDS(p, RPMTAG_DIRNAMES));
02236 if (requires != NULL)
02237 while (rpmdsNext(requires) >= 0) {
02238
02239
02240 (void) addRelation(ts, p, selected, requires);
02241
02242 }
02243
02244
02245 requires = rpmdsInit(rpmteDS(p, RPMTAG_FILELINKTOS));
02246 if (requires != NULL)
02247 while (rpmdsNext(requires) >= 0) {
02248
02249
02250 (void) addRelation(ts, p, selected, requires);
02251
02252 }
02253 }
02254
02255 }
02256 pi = rpmtsiFree(pi);
02257
02258
02259 treex = 0;
02260 pi = rpmtsiInit(ts);
02261 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02262 int npreds;
02263
02264 npreds = rpmteTSI(p)->tsi_count;
02265
02266 (void) rpmteSetNpreds(p, npreds);
02267 (void) rpmteSetDepth(p, 0);
02268
02269 if (npreds == 0) {
02270 treex++;
02271 (void) rpmteSetTree(p, treex);
02272 (void) rpmteSetBreadth(p, treex);
02273 } else
02274 (void) rpmteSetTree(p, -1);
02275 #ifdef UNNECESSARY
02276 (void) rpmteSetParent(p, NULL);
02277 #endif
02278
02279 }
02280 pi = rpmtsiFree(pi);
02281 ts->ntrees = treex;
02282
02283
02284 rpmMessage(RPMMESS_DEBUG, D_("========== tsorting packages (order, #predecessors, #succesors, tree, Ldepth, Rbreadth)\n"));
02285
02286 rescan:
02287 if (pi != NULL) pi = rpmtsiFree(pi);
02288 q = r = NULL;
02289 qlen = 0;
02290 pi = rpmtsiInit(ts);
02291 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02292
02293
02294 if (anaconda)
02295 rpmteTSI(p)->tsi_qcnt = (ts->orderCount - rpmtsiOc(pi));
02296
02297 if (rpmteTSI(p)->tsi_count != 0)
02298 continue;
02299 rpmteTSI(p)->tsi_suc = NULL;
02300 addQ(p, &q, &r, prefcolor);
02301 qlen++;
02302 }
02303 pi = rpmtsiFree(pi);
02304
02305
02306 for (; q != NULL; q = rpmteTSI(q)->tsi_suc) {
02307
02308
02309 rpmteTSI(q)->tsi_queued = 0;
02310
02311 if (oType != 0)
02312 switch (rpmteType(q)) {
02313 case TR_ADDED:
02314 if (!(oType & TR_ADDED))
02315 continue;
02316 break;
02317 case TR_REMOVED:
02318 if (!(oType & TR_REMOVED))
02319 continue;
02320 break;
02321 default:
02322 continue;
02323 break;
02324 }
02325 deptypechar = (rpmteType(q) == TR_REMOVED ? '-' : '+');
02326
02327 treex = rpmteTree(q);
02328 depth = rpmteDepth(q);
02329 breadth = ((depth < npeer) ? peer[depth]++ : 0);
02330 (void) rpmteSetBreadth(q, breadth);
02331
02332 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%5d%5d%5d %*s%c%s\n",
02333 orderingCount, rpmteNpreds(q),
02334 rpmteTSI(q)->tsi_qcnt,
02335 treex, depth, breadth,
02336 (2 * depth), "",
02337 deptypechar,
02338 (rpmteNEVRA(q) ? rpmteNEVRA(q) : "???"));
02339
02340 (void) rpmteSetDegree(q, 0);
02341 tsbytes += rpmtePkgFileSize(q);
02342
02343 ordering[orderingCount] = rpmteAddedKey(q);
02344 orderingCount++;
02345 qlen--;
02346 loopcheck--;
02347
02348
02349 tsi_next = rpmteTSI(q)->tsi_next;
02350 rpmteTSI(q)->tsi_next = NULL;
02351 while ((tsi = tsi_next) != NULL) {
02352 tsi_next = tsi->tsi_next;
02353 tsi->tsi_next = NULL;
02354 p = tsi->tsi_suc;
02355 if (p && (--rpmteTSI(p)->tsi_count) <= 0) {
02356
02357 (void) rpmteSetTree(p, treex);
02358 (void) rpmteSetDepth(p, depth+1);
02359 (void) rpmteSetParent(p, q);
02360 (void) rpmteSetDegree(q, rpmteDegree(q)+1);
02361
02362
02363 rpmteTSI(p)->tsi_suc = NULL;
02364
02365 addQ(p, &rpmteTSI(q)->tsi_suc, &r, prefcolor);
02366
02367 qlen++;
02368 }
02369 tsi = _free(tsi);
02370 }
02371 if (!_printed && loopcheck == qlen && rpmteTSI(q)->tsi_suc != NULL) {
02372 _printed++;
02373 (void) rpmtsUnorderedSuccessors(ts, orderingCount);
02374 rpmMessage(RPMMESS_DEBUG,
02375 D_("========== successors only (%d bytes)\n"), (int)tsbytes);
02376
02377
02378 tsi = rpmteTSI(q);
02379 pi = rpmtsiInit(ts);
02380 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02381
02382 if (rpmteTSI(p)->tsi_queued == 0)
02383 continue;
02384 tsi->tsi_suc = p;
02385 tsi = rpmteTSI(p);
02386 }
02387 pi = rpmtsiFree(pi);
02388 tsi->tsi_suc = NULL;
02389 }
02390 }
02391
02392
02393 if (loopcheck != 0) {
02394 int nzaps;
02395
02396
02397 nzaps = 0;
02398 qi = rpmtsiInit(ts);
02399 while ((q = rpmtsiNext(qi, oType)) != NULL) {
02400 rpmteTSI(q)->tsi_chain = NULL;
02401 rpmteTSI(q)->tsi_queued = 0;
02402
02403 if (rpmteTSI(q)->tsi_count == 0)
02404 rpmteTSI(q)->tsi_count = -1;
02405 }
02406 qi = rpmtsiFree(qi);
02407
02408
02409 qi = rpmtsiInit(ts);
02410 while ((q = rpmtsiNext(qi, oType)) != NULL) {
02411 if ((tsi = rpmteTSI(q)->tsi_next) == NULL)
02412 continue;
02413 rpmteTSI(q)->tsi_next = NULL;
02414 markLoop(tsi, q);
02415 rpmteTSI(q)->tsi_next = tsi;
02416 }
02417 qi = rpmtsiFree(qi);
02418
02419
02420 ri = rpmtsiInit(ts);
02421 while ((r = rpmtsiNext(ri, oType)) != NULL)
02422 {
02423 int printed;
02424
02425 printed = 0;
02426
02427
02428 for (q = rpmteTSI(r)->tsi_chain; q != NULL;
02429 q = rpmteTSI(q)->tsi_chain)
02430 {
02431 if (rpmteTSI(q)->tsi_queued)
02432 break;
02433 rpmteTSI(q)->tsi_queued = 1;
02434 }
02435
02436
02437 while ((p = q) != NULL && (q = rpmteTSI(p)->tsi_chain) != NULL) {
02438 const char * dp;
02439 char buf[4096];
02440 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS))
02441 ? RPMMESS_WARNING : RPMMESS_ERROR;
02442 ;
02443
02444
02445 rpmteTSI(p)->tsi_chain = NULL;
02446
02447 if (!printed) {
02448 rpmMessage(msglvl, _("LOOP:\n"));
02449 printed = 1;
02450 }
02451
02452
02453 dp = zapRelation(q, p, 1, &nzaps, msglvl);
02454
02455
02456 buf[0] = '\0';
02457 if (rpmteNEVRA(p) != NULL)
02458 (void) stpcpy(buf, rpmteNEVRA(p));
02459 rpmMessage(msglvl, " %-40s %s\n", buf,
02460 (dp ? dp : "not found!?!"));
02461
02462 dp = _free(dp);
02463 }
02464
02465
02466 for (p = r, q = rpmteTSI(r)->tsi_chain; q != NULL;
02467 p = q, q = rpmteTSI(q)->tsi_chain)
02468 {
02469
02470 rpmteTSI(p)->tsi_chain = NULL;
02471 rpmteTSI(p)->tsi_queued = 0;
02472 }
02473 }
02474 ri = rpmtsiFree(ri);
02475
02476
02477
02478 if (nzaps && nrescans-- > 0) {
02479 rpmMessage(RPMMESS_DEBUG, D_("========== continuing tsort ...\n"));
02480 goto rescan;
02481 }
02482
02483
02484 rpmMessage(RPMMESS_ERROR, _("rpmtsOrder failed, %d elements remain\n"),
02485 loopcheck);
02486
02487 #ifdef NOTYET
02488
02489 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
02490 #endif
02491
02492 return loopcheck;
02493 }
02494
02495
02496 pi = rpmtsiInit(ts);
02497 while ((p = rpmtsiNext(pi, 0)) != NULL)
02498 rpmteFreeTSI(p);
02499 pi = rpmtsiFree(pi);
02500
02501
02502
02503
02504 orderList = xcalloc(numOrderList, sizeof(*orderList));
02505 j = 0;
02506 pi = rpmtsiInit(ts);
02507 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02508
02509 orderList[j].pkgKey = rpmteAddedKey(p);
02510 orderList[j].orIndex = rpmtsiOc(pi);
02511 j++;
02512 }
02513 pi = rpmtsiFree(pi);
02514
02515 qsort(orderList, numOrderList, sizeof(*orderList), orderListIndexCmp);
02516
02517
02518 newOrder = xcalloc(ts->orderCount, sizeof(*newOrder));
02519
02520
02521 for (i = 0, newOrderCount = 0; i < orderingCount; i++)
02522 {
02523 struct orderListIndex_s key;
02524 orderListIndex needle;
02525
02526 key.pkgKey = ordering[i];
02527 needle = bsearch(&key, orderList, numOrderList,
02528 sizeof(key), orderListIndexCmp);
02529 if (needle == NULL)
02530 continue;
02531
02532 j = needle->orIndex;
02533 if ((q = ts->order[j]) == NULL || needle->pkgKey == RPMAL_NOMATCH)
02534 continue;
02535
02536 newOrder[newOrderCount++] = q;
02537 ts->order[j] = NULL;
02538 }
02539
02540
02541 assert(newOrderCount == ts->orderCount);
02542
02543
02544 ts->order = _free(ts->order);
02545
02546 ts->order = newOrder;
02547 ts->orderAlloced = ts->orderCount;
02548 orderList = _free(orderList);
02549
02550 #ifdef DYING
02551 rpmtsClean(ts);
02552 #endif
02553 freeBadDeps();
02554
02555 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
02556
02557 return 0;
02558 }
02559
02560
02561 int rpmtsCheck(rpmts ts)
02562 {
02563 const char * depName = NULL;;
02564 rpmdepFlags depFlags = rpmtsDFlags(ts);
02565 uint_32 tscolor = rpmtsColor(ts);
02566 rpmdbMatchIterator mi = NULL;
02567 rpmtsi pi = NULL; rpmte p;
02568 int closeatexit = 0;
02569 int xx;
02570 int rc;
02571
02572 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
02573
02574
02575 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
02576 if ((rc = rpmtsOpenDB(ts, ts->dbmode)) != 0)
02577 goto exit;
02578 closeatexit = 1;
02579 }
02580
02581 ts->probs = rpmpsFree(ts->probs);
02582 ts->probs = rpmpsCreate();
02583
02584 rpmalMakeIndex(ts->addedPackages);
02585
02586
02587
02588
02589
02590 pi = rpmtsiInit(ts);
02591 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
02592 rpmds provides, requires, conflicts, dirnames, linktos;
02593
02594
02595 rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s/%s 0x%x\n",
02596 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02597
02598 requires = (!(depFlags & RPMDEPS_FLAG_NOREQUIRES)
02599 ? rpmteDS(p, RPMTAG_REQUIRENAME) : NULL);
02600 conflicts = (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS)
02601 ? rpmteDS(p, RPMTAG_CONFLICTNAME) : NULL);
02602 dirnames = (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS)
02603 ? rpmteDS(p, RPMTAG_DIRNAMES) : NULL);
02604 linktos = (!(depFlags & RPMDEPS_FLAG_NOLINKTOS)
02605 ? rpmteDS(p, RPMTAG_FILELINKTOS) : NULL);
02606
02607 rc = checkPackageDeps(ts, rpmteNEVRA(p),
02608 requires, conflicts, dirnames, linktos,
02609 NULL, tscolor, 1);
02610 if (rc)
02611 goto exit;
02612
02613 rc = 0;
02614 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
02615 provides = rpmdsInit(provides);
02616 if (provides != NULL)
02617 while (rpmdsNext(provides) >= 0) {
02618 depName = _free(depName);
02619 depName = xstrdup(rpmdsN(provides));
02620
02621 #ifdef NOTYET
02622 if (rpmdsNSType(provides) == RPMNS_TYPE_ENVVAR) {
02623 const char * EVR = rpmdsEVR(provides);
02624 if (rpmdsNegateRC(provides, 0))
02625 EVR = NULL;
02626 rc = envPut(depName, EVR);
02627 if (!rc)
02628 continue;
02629 break;
02630 }
02631 #endif
02632
02633
02634 if (!checkDependentConflicts(ts, depName))
02635 continue;
02636 rc = 1;
02637 break;
02638 }
02639 if (rc)
02640 goto exit;
02641 }
02642 pi = rpmtsiFree(pi);
02643
02644
02645
02646
02647 pi = rpmtsiInit(ts);
02648 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
02649 rpmds provides;
02650 rpmfi fi;
02651
02652
02653 rpmMessage(RPMMESS_DEBUG, "========== --- %s %s/%s 0x%x\n",
02654 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02655
02656
02657 rc = 0;
02658 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
02659 provides = rpmdsInit(provides);
02660 if (provides != NULL)
02661 while (rpmdsNext(provides) >= 0) {
02662 depName = _free(depName);
02663 depName = xstrdup(rpmdsN(provides));
02664
02665
02666 if (!checkDependentPackages(ts, depName))
02667 continue;
02668 rc = 1;
02669 break;
02670 }
02671 if (rc)
02672 goto exit;
02673
02674 rc = 0;
02675 fi = rpmteFI(p, RPMTAG_BASENAMES);
02676 fi = rpmfiInit(fi, 0);
02677 while (rpmfiNext(fi) >= 0) {
02678 depName = _free(depName);
02679 depName = xstrdup(rpmfiFN(fi));
02680
02681 if (!checkDependentPackages(ts, depName))
02682 continue;
02683 rc = 1;
02684 break;
02685 }
02686 if (rc)
02687 goto exit;
02688 }
02689 pi = rpmtsiFree(pi);
02690
02691
02692
02693
02694 { const char * tsNEVRA = "transaction dependencies";
02695 rpmds R = rpmdsFromPRCO(ts->PRCO, RPMTAG_REQUIRENAME);
02696 rpmds C = rpmdsFromPRCO(ts->PRCO, RPMTAG_CONFLICTNAME);
02697 rpmds D = NULL;
02698 rpmds L = NULL;
02699 const char * dep = NULL;
02700 int adding = 2;
02701 tscolor = 0;
02702 rc = checkPackageDeps(ts, tsNEVRA, R, C, D, L, dep, tscolor, adding);
02703 if (rc)
02704 goto exit;
02705 }
02706
02707 rc = 0;
02708
02709 exit:
02710 mi = rpmdbFreeIterator(mi);
02711 pi = rpmtsiFree(pi);
02712 depName = _free(depName);
02713
02714 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
02715
02716
02717 if (closeatexit)
02718 xx = rpmtsCloseDB(ts);
02719 #if defined(CACHE_DEPENDENCY_RESULT)
02720 else if (_cacheDependsRC)
02721 xx = rpmdbCloseDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS);
02722 #endif
02723
02724
02725 #ifdef NOTYET
02726
02727 { rpmps ps = rpmtsProblems(ts);
02728 if (rc || rpmpsNumProblems(ps) > 0)
02729 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
02730 ps = rpmpsFree(ps);
02731 }
02732 #endif
02733
02734 return rc;
02735 }