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(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 rpmteTSI(p)->tsi_count++;
01953
01954 if (rpmteDepth(p) <= rpmteDepth(q))
01955 (void) rpmteSetDepth(p, (rpmteDepth(q) + 1));
01956 if (rpmteDepth(p) > ts->maxDepth)
01957 ts->maxDepth = rpmteDepth(p);
01958
01959 tsi = xcalloc(1, sizeof(*tsi));
01960 tsi->tsi_suc = p;
01961
01962 tsi->tsi_tagn = rpmdsTagN(requires);
01963 tsi->tsi_reqx = rpmdsIx(requires);
01964
01965 tsi->tsi_next = rpmteTSI(q)->tsi_next;
01966 rpmteTSI(q)->tsi_next = tsi;
01967 rpmteTSI(q)->tsi_qcnt++;
01968 return 0;
01969 }
01970
01971
01978 static int orderListIndexCmp(const void * one, const void * two)
01979 {
01980
01981 long a = (long) ((const orderListIndex)one)->pkgKey;
01982 long b = (long) ((const orderListIndex)two)->pkgKey;
01983
01984 return (a - b);
01985 }
01986
01994
01995
01996 static void addQ( rpmte p,
01997 rpmte * qp,
01998 rpmte * rp,
01999 uint_32 prefcolor)
02000
02001 {
02002 rpmte q, qprev;
02003
02004
02005 rpmteTSI(p)->tsi_queued = 1;
02006
02007 if ((*rp) == NULL) {
02008
02009 (*rp) = (*qp) = p;
02010
02011 return;
02012 }
02013
02014
02015 for (qprev = NULL, q = (*qp);
02016 q != NULL;
02017 qprev = q, q = rpmteTSI(q)->tsi_suc)
02018 {
02019
02020 if (rpmteColor(p) != prefcolor && rpmteColor(p) != rpmteColor(q))
02021 continue;
02022
02023
02024 if (rpmteType(p) == TR_REMOVED && rpmteType(p) != rpmteType(q))
02025 continue;
02026 if (rpmteTSI(q)->tsi_qcnt <= rpmteTSI(p)->tsi_qcnt)
02027 break;
02028 }
02029
02030 if (qprev == NULL) {
02031 rpmteTSI(p)->tsi_suc = q;
02032
02033 (*qp) = p;
02034
02035 } else if (q == NULL) {
02036 rpmteTSI(qprev)->tsi_suc = p;
02037
02038 (*rp) = p;
02039
02040 } else {
02041 rpmteTSI(p)->tsi_suc = q;
02042 rpmteTSI(qprev)->tsi_suc = p;
02043 }
02044 }
02045
02046
02047
02048
02049 #ifdef NOTYET
02050 static uint32_t _autobits = _notpre(_ALL_REQUIRES_MASK);
02051 #define isAuto(_x) ((_x) & _autobits)
02052 #else
02053 static uint32_t _autobits = 0xffffffff;
02054 #define isAuto(_x) (1)
02055 #endif
02056
02057
02058 int rpmtsOrder(rpmts ts)
02059 {
02060 rpmds requires;
02061 int_32 Flags;
02062 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA;
02063 uint_32 prefcolor = rpmtsPrefColor(ts);
02064 rpmtsi pi; rpmte p;
02065 rpmtsi qi; rpmte q;
02066 rpmtsi ri; rpmte r;
02067 tsortInfo tsi;
02068 tsortInfo tsi_next;
02069 alKey * ordering;
02070 int orderingCount = 0;
02071 unsigned char * selected = alloca(sizeof(*selected) * (ts->orderCount + 1));
02072 int loopcheck;
02073 rpmte * newOrder;
02074 int newOrderCount = 0;
02075 orderListIndex orderList;
02076 int numOrderList;
02077 int npeer = 128;
02078 int * peer = memset(alloca(npeer*sizeof(*peer)), 0, (npeer*sizeof(*peer)));
02079 int nrescans = 10;
02080 int _printed = 0;
02081 char deptypechar;
02082 size_t tsbytes;
02083 int oType = 0;
02084 int treex;
02085 int depth;
02086 int breadth;
02087 int qlen;
02088 int i, j;
02089
02090 #ifdef DYING
02091 rpmalMakeIndex(ts->addedPackages);
02092 #endif
02093
02094
02095 pi = rpmtsiInit(ts);
02096 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
02097 alKey pkgKey;
02098 fnpyKey key;
02099 uint_32 tscolor = rpmtsColor(ts);
02100 pkgKey = RPMAL_NOMATCH;
02101
02102 key = (fnpyKey) p;
02103
02104 pkgKey = rpmalAdd(&ts->erasedPackages, pkgKey, key,
02105 rpmteDS(p, RPMTAG_PROVIDENAME),
02106 rpmteFI(p, RPMTAG_BASENAMES), tscolor);
02107
02108 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages);
02109 (void) rpmteSetAddedKey(p, pkgKey);
02110 }
02111 pi = rpmtsiFree(pi);
02112 rpmalMakeIndex(ts->erasedPackages);
02113
02114 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
02115
02116
02117 if (oType == 0)
02118 numOrderList = ts->orderCount;
02119 else {
02120 numOrderList = 0;
02121 if (oType & TR_ADDED)
02122 numOrderList += ts->numAddedPackages;
02123 if (oType & TR_REMOVED)
02124 numOrderList += ts->numRemovedPackages;
02125 }
02126 ordering = alloca(sizeof(*ordering) * (numOrderList + 1));
02127 loopcheck = numOrderList;
02128 tsbytes = 0;
02129
02130 pi = rpmtsiInit(ts);
02131 while ((p = rpmtsiNext(pi, oType)) != NULL)
02132 rpmteNewTSI(p);
02133 pi = rpmtsiFree(pi);
02134
02135
02136 rpmMessage(RPMMESS_DEBUG, D_("========== recording tsort relations\n"));
02137 pi = rpmtsiInit(ts);
02138 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02139
02140 memset(selected, 0, sizeof(*selected) * ts->orderCount);
02141
02142 if ((requires = rpmteDS(p, RPMTAG_REQUIRENAME)) != NULL) {
02143
02144
02145 selected[rpmtsiOc(pi)] = 1;
02146
02147
02148
02149
02150 requires = rpmdsInit(requires);
02151 if (requires != NULL)
02152 while (rpmdsNext(requires) >= 0) {
02153
02154 Flags = rpmdsFlags(requires);
02155 if (!isAuto(Flags))
02156 continue;
02157
02158 switch (rpmteType(p)) {
02159 case TR_REMOVED:
02160
02161 if (!isErasePreReq(Flags))
02162 continue;
02163 break;
02164 case TR_ADDED:
02165
02166 if (!isInstallPreReq(Flags))
02167 continue;
02168 break;
02169 }
02170
02171
02172 (void) addRelation(ts, p, selected, requires);
02173
02174 }
02175
02176
02177 requires = rpmdsInit(requires);
02178 if (requires != NULL)
02179 while (rpmdsNext(requires) >= 0) {
02180
02181 Flags = rpmdsFlags(requires);
02182 if (!isAuto(Flags))
02183 continue;
02184
02185 switch (rpmteType(p)) {
02186 case TR_REMOVED:
02187
02188 if (isErasePreReq(Flags))
02189 continue;
02190 break;
02191 case TR_ADDED:
02192
02193 if (isInstallPreReq(Flags))
02194 continue;
02195 break;
02196 }
02197
02198
02199 (void) addRelation(ts, p, selected, requires);
02200
02201 }
02202 }
02203
02204
02205
02206 if (rpmteType(p) == TR_REMOVED && p->flink.Pkgid && p->flink.Pkgid[0]) {
02207
02208 qi = rpmtsiInit(ts);
02209 while ((q = rpmtsiNext(qi, TR_ADDED)) != NULL) {
02210 if (strcmp(q->pkgid, p->flink.Pkgid[0]))
02211 continue;
02212 requires = rpmdsFromPRCO(q->PRCO, RPMTAG_NAME);
02213 if (requires != NULL) {
02214
02215 p->type = TR_ADDED;
02216 (void) addRelation(ts, p, selected, requires);
02217 p->type = TR_REMOVED;
02218 }
02219 }
02220 qi = rpmtsiFree(qi);
02221 }
02222
02223 if (_autobits != 0xffffffff)
02224 {
02225
02226
02227 requires = rpmdsInit(rpmteDS(p, RPMTAG_DIRNAMES));
02228 if (requires != NULL)
02229 while (rpmdsNext(requires) >= 0) {
02230
02231
02232 (void) addRelation(ts, p, selected, requires);
02233
02234 }
02235
02236
02237 requires = rpmdsInit(rpmteDS(p, RPMTAG_FILELINKTOS));
02238 if (requires != NULL)
02239 while (rpmdsNext(requires) >= 0) {
02240
02241
02242 (void) addRelation(ts, p, selected, requires);
02243
02244 }
02245 }
02246
02247 }
02248 pi = rpmtsiFree(pi);
02249
02250
02251 treex = 0;
02252 pi = rpmtsiInit(ts);
02253 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02254 int npreds;
02255
02256 npreds = rpmteTSI(p)->tsi_count;
02257
02258 (void) rpmteSetNpreds(p, npreds);
02259 (void) rpmteSetDepth(p, 0);
02260
02261 if (npreds == 0) {
02262 treex++;
02263 (void) rpmteSetTree(p, treex);
02264 (void) rpmteSetBreadth(p, treex);
02265 } else
02266 (void) rpmteSetTree(p, -1);
02267 #ifdef UNNECESSARY
02268 (void) rpmteSetParent(p, NULL);
02269 #endif
02270
02271 }
02272 pi = rpmtsiFree(pi);
02273 ts->ntrees = treex;
02274
02275
02276 rpmMessage(RPMMESS_DEBUG, D_("========== tsorting packages (order, #predecessors, #succesors, tree, Ldepth, Rbreadth)\n"));
02277
02278 rescan:
02279 if (pi != NULL) pi = rpmtsiFree(pi);
02280 q = r = NULL;
02281 qlen = 0;
02282 pi = rpmtsiInit(ts);
02283 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02284
02285
02286 if (anaconda)
02287 rpmteTSI(p)->tsi_qcnt = (ts->orderCount - rpmtsiOc(pi));
02288
02289 if (rpmteTSI(p)->tsi_count != 0)
02290 continue;
02291 rpmteTSI(p)->tsi_suc = NULL;
02292 addQ(p, &q, &r, prefcolor);
02293 qlen++;
02294 }
02295 pi = rpmtsiFree(pi);
02296
02297
02298 for (; q != NULL; q = rpmteTSI(q)->tsi_suc) {
02299
02300
02301 rpmteTSI(q)->tsi_queued = 0;
02302
02303 if (oType != 0)
02304 switch (rpmteType(q)) {
02305 case TR_ADDED:
02306 if (!(oType & TR_ADDED))
02307 continue;
02308 break;
02309 case TR_REMOVED:
02310 if (!(oType & TR_REMOVED))
02311 continue;
02312 break;
02313 default:
02314 continue;
02315 break;
02316 }
02317 deptypechar = (rpmteType(q) == TR_REMOVED ? '-' : '+');
02318
02319 treex = rpmteTree(q);
02320 depth = rpmteDepth(q);
02321 breadth = ((depth < npeer) ? peer[depth]++ : 0);
02322 (void) rpmteSetBreadth(q, breadth);
02323
02324 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%5d%5d%5d %*s%c%s\n",
02325 orderingCount, rpmteNpreds(q),
02326 rpmteTSI(q)->tsi_qcnt,
02327 treex, depth, breadth,
02328 (2 * depth), "",
02329 deptypechar,
02330 (rpmteNEVRA(q) ? rpmteNEVRA(q) : "???"));
02331
02332 (void) rpmteSetDegree(q, 0);
02333 tsbytes += rpmtePkgFileSize(q);
02334
02335 ordering[orderingCount] = rpmteAddedKey(q);
02336 orderingCount++;
02337 qlen--;
02338 loopcheck--;
02339
02340
02341 tsi_next = rpmteTSI(q)->tsi_next;
02342 rpmteTSI(q)->tsi_next = NULL;
02343 while ((tsi = tsi_next) != NULL) {
02344 tsi_next = tsi->tsi_next;
02345 tsi->tsi_next = NULL;
02346 p = tsi->tsi_suc;
02347 if (p && (--rpmteTSI(p)->tsi_count) <= 0) {
02348
02349 (void) rpmteSetTree(p, treex);
02350 (void) rpmteSetDepth(p, depth+1);
02351 (void) rpmteSetParent(p, q);
02352 (void) rpmteSetDegree(q, rpmteDegree(q)+1);
02353
02354
02355 rpmteTSI(p)->tsi_suc = NULL;
02356
02357 addQ(p, &rpmteTSI(q)->tsi_suc, &r, prefcolor);
02358
02359 qlen++;
02360 }
02361 tsi = _free(tsi);
02362 }
02363 if (!_printed && loopcheck == qlen && rpmteTSI(q)->tsi_suc != NULL) {
02364 _printed++;
02365 (void) rpmtsUnorderedSuccessors(ts, orderingCount);
02366 rpmMessage(RPMMESS_DEBUG,
02367 D_("========== successors only (%d bytes)\n"), (int)tsbytes);
02368
02369
02370 tsi = rpmteTSI(q);
02371 pi = rpmtsiInit(ts);
02372 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02373
02374 if (rpmteTSI(p)->tsi_queued == 0)
02375 continue;
02376 tsi->tsi_suc = p;
02377 tsi = rpmteTSI(p);
02378 }
02379 pi = rpmtsiFree(pi);
02380 tsi->tsi_suc = NULL;
02381 }
02382 }
02383
02384
02385 if (loopcheck != 0) {
02386 int nzaps;
02387
02388
02389 nzaps = 0;
02390 qi = rpmtsiInit(ts);
02391 while ((q = rpmtsiNext(qi, oType)) != NULL) {
02392 rpmteTSI(q)->tsi_chain = NULL;
02393 rpmteTSI(q)->tsi_queued = 0;
02394
02395 if (rpmteTSI(q)->tsi_count == 0)
02396 rpmteTSI(q)->tsi_count = -1;
02397 }
02398 qi = rpmtsiFree(qi);
02399
02400
02401 qi = rpmtsiInit(ts);
02402 while ((q = rpmtsiNext(qi, oType)) != NULL) {
02403 if ((tsi = rpmteTSI(q)->tsi_next) == NULL)
02404 continue;
02405 rpmteTSI(q)->tsi_next = NULL;
02406 markLoop(tsi, q);
02407 rpmteTSI(q)->tsi_next = tsi;
02408 }
02409 qi = rpmtsiFree(qi);
02410
02411
02412 ri = rpmtsiInit(ts);
02413 while ((r = rpmtsiNext(ri, oType)) != NULL)
02414 {
02415 int printed;
02416
02417 printed = 0;
02418
02419
02420 for (q = rpmteTSI(r)->tsi_chain; q != NULL;
02421 q = rpmteTSI(q)->tsi_chain)
02422 {
02423 if (rpmteTSI(q)->tsi_queued)
02424 break;
02425 rpmteTSI(q)->tsi_queued = 1;
02426 }
02427
02428
02429 while ((p = q) != NULL && (q = rpmteTSI(p)->tsi_chain) != NULL) {
02430 const char * dp;
02431 char buf[4096];
02432 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS))
02433 ? RPMMESS_WARNING : RPMMESS_ERROR;
02434 ;
02435
02436
02437 rpmteTSI(p)->tsi_chain = NULL;
02438
02439 if (!printed) {
02440 rpmMessage(msglvl, _("LOOP:\n"));
02441 printed = 1;
02442 }
02443
02444
02445 dp = zapRelation(q, p, 1, &nzaps, msglvl);
02446
02447
02448 buf[0] = '\0';
02449 if (rpmteNEVRA(p) != NULL)
02450 (void) stpcpy(buf, rpmteNEVRA(p));
02451 rpmMessage(msglvl, " %-40s %s\n", buf,
02452 (dp ? dp : "not found!?!"));
02453
02454 dp = _free(dp);
02455 }
02456
02457
02458 for (p = r, q = rpmteTSI(r)->tsi_chain; q != NULL;
02459 p = q, q = rpmteTSI(q)->tsi_chain)
02460 {
02461
02462 rpmteTSI(p)->tsi_chain = NULL;
02463 rpmteTSI(p)->tsi_queued = 0;
02464 }
02465 }
02466 ri = rpmtsiFree(ri);
02467
02468
02469
02470 if (nzaps && nrescans-- > 0) {
02471 rpmMessage(RPMMESS_DEBUG, D_("========== continuing tsort ...\n"));
02472 goto rescan;
02473 }
02474
02475
02476 rpmMessage(RPMMESS_ERROR, _("rpmtsOrder failed, %d elements remain\n"),
02477 loopcheck);
02478
02479 #ifdef NOTYET
02480
02481 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
02482 #endif
02483
02484 return loopcheck;
02485 }
02486
02487
02488 pi = rpmtsiInit(ts);
02489 while ((p = rpmtsiNext(pi, 0)) != NULL)
02490 rpmteFreeTSI(p);
02491 pi = rpmtsiFree(pi);
02492
02493
02494
02495
02496 orderList = xcalloc(numOrderList, sizeof(*orderList));
02497 j = 0;
02498 pi = rpmtsiInit(ts);
02499 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02500
02501 orderList[j].pkgKey = rpmteAddedKey(p);
02502 orderList[j].orIndex = rpmtsiOc(pi);
02503 j++;
02504 }
02505 pi = rpmtsiFree(pi);
02506
02507 qsort(orderList, numOrderList, sizeof(*orderList), orderListIndexCmp);
02508
02509
02510 newOrder = xcalloc(ts->orderCount, sizeof(*newOrder));
02511
02512
02513 for (i = 0, newOrderCount = 0; i < orderingCount; i++)
02514 {
02515 struct orderListIndex_s key;
02516 orderListIndex needle;
02517
02518 key.pkgKey = ordering[i];
02519 needle = bsearch(&key, orderList, numOrderList,
02520 sizeof(key), orderListIndexCmp);
02521 if (needle == NULL)
02522 continue;
02523
02524 j = needle->orIndex;
02525 if ((q = ts->order[j]) == NULL || needle->pkgKey == RPMAL_NOMATCH)
02526 continue;
02527
02528 newOrder[newOrderCount++] = q;
02529 ts->order[j] = NULL;
02530 }
02531
02532
02533 assert(newOrderCount == ts->orderCount);
02534
02535
02536 ts->order = _free(ts->order);
02537
02538 ts->order = newOrder;
02539 ts->orderAlloced = ts->orderCount;
02540 orderList = _free(orderList);
02541
02542 #ifdef DYING
02543 rpmtsClean(ts);
02544 #endif
02545 freeBadDeps();
02546
02547 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
02548
02549 return 0;
02550 }
02551
02552
02553 int rpmtsCheck(rpmts ts)
02554 {
02555 const char * depName = NULL;;
02556 rpmdepFlags depFlags = rpmtsDFlags(ts);
02557 uint_32 tscolor = rpmtsColor(ts);
02558 rpmdbMatchIterator mi = NULL;
02559 rpmtsi pi = NULL; rpmte p;
02560 int closeatexit = 0;
02561 int xx;
02562 int rc;
02563
02564 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
02565
02566
02567 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
02568 if ((rc = rpmtsOpenDB(ts, ts->dbmode)) != 0)
02569 goto exit;
02570 closeatexit = 1;
02571 }
02572
02573 ts->probs = rpmpsFree(ts->probs);
02574 ts->probs = rpmpsCreate();
02575
02576 rpmalMakeIndex(ts->addedPackages);
02577
02578
02579
02580
02581
02582 pi = rpmtsiInit(ts);
02583 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
02584 rpmds provides, requires, conflicts, dirnames, linktos;
02585
02586
02587 rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s/%s 0x%x\n",
02588 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02589
02590 requires = (!(depFlags & RPMDEPS_FLAG_NOREQUIRES)
02591 ? rpmteDS(p, RPMTAG_REQUIRENAME) : NULL);
02592 conflicts = (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS)
02593 ? rpmteDS(p, RPMTAG_CONFLICTNAME) : NULL);
02594 dirnames = (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS)
02595 ? rpmteDS(p, RPMTAG_DIRNAMES) : NULL);
02596 linktos = (!(depFlags & RPMDEPS_FLAG_NOLINKTOS)
02597 ? rpmteDS(p, RPMTAG_FILELINKTOS) : NULL);
02598
02599 rc = checkPackageDeps(ts, rpmteNEVRA(p),
02600 requires, conflicts, dirnames, linktos,
02601 NULL, tscolor, 1);
02602 if (rc)
02603 goto exit;
02604
02605 rc = 0;
02606 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
02607 provides = rpmdsInit(provides);
02608 if (provides != NULL)
02609 while (rpmdsNext(provides) >= 0) {
02610 depName = _free(depName);
02611 depName = xstrdup(rpmdsN(provides));
02612
02613 #ifdef NOTYET
02614 if (rpmdsNSType(provides) == RPMNS_TYPE_ENVVAR) {
02615 const char * EVR = rpmdsEVR(provides);
02616 if (rpmdsNegateRC(provides, 0))
02617 EVR = NULL;
02618 rc = envPut(depName, EVR);
02619 if (!rc)
02620 continue;
02621 break;
02622 }
02623 #endif
02624
02625
02626 if (!checkDependentConflicts(ts, depName))
02627 continue;
02628 rc = 1;
02629 break;
02630 }
02631 if (rc)
02632 goto exit;
02633 }
02634 pi = rpmtsiFree(pi);
02635
02636
02637
02638
02639 pi = rpmtsiInit(ts);
02640 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
02641 rpmds provides;
02642 rpmfi fi;
02643
02644
02645 rpmMessage(RPMMESS_DEBUG, "========== --- %s %s/%s 0x%x\n",
02646 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02647
02648
02649 rc = 0;
02650 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
02651 provides = rpmdsInit(provides);
02652 if (provides != NULL)
02653 while (rpmdsNext(provides) >= 0) {
02654 depName = _free(depName);
02655 depName = xstrdup(rpmdsN(provides));
02656
02657
02658 if (!checkDependentPackages(ts, depName))
02659 continue;
02660 rc = 1;
02661 break;
02662 }
02663 if (rc)
02664 goto exit;
02665
02666 rc = 0;
02667 fi = rpmteFI(p, RPMTAG_BASENAMES);
02668 fi = rpmfiInit(fi, 0);
02669 while (rpmfiNext(fi) >= 0) {
02670 depName = _free(depName);
02671 depName = xstrdup(rpmfiFN(fi));
02672
02673 if (!checkDependentPackages(ts, depName))
02674 continue;
02675 rc = 1;
02676 break;
02677 }
02678 if (rc)
02679 goto exit;
02680 }
02681 pi = rpmtsiFree(pi);
02682
02683
02684
02685
02686 { const char * tsNEVRA = "transaction dependencies";
02687 rpmds R = rpmdsFromPRCO(ts->PRCO, RPMTAG_REQUIRENAME);
02688 rpmds C = rpmdsFromPRCO(ts->PRCO, RPMTAG_CONFLICTNAME);
02689 rpmds D = NULL;
02690 rpmds L = NULL;
02691 const char * dep = NULL;
02692 int adding = 2;
02693 tscolor = 0;
02694 rc = checkPackageDeps(ts, tsNEVRA, R, C, D, L, dep, tscolor, adding);
02695 if (rc)
02696 goto exit;
02697 }
02698
02699 rc = 0;
02700
02701 exit:
02702 mi = rpmdbFreeIterator(mi);
02703 pi = rpmtsiFree(pi);
02704 depName = _free(depName);
02705
02706 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
02707
02708
02709 if (closeatexit)
02710 xx = rpmtsCloseDB(ts);
02711 #if defined(CACHE_DEPENDENCY_RESULT)
02712 else if (_cacheDependsRC)
02713 xx = rpmdbCloseDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS);
02714 #endif
02715
02716
02717 #ifdef NOTYET
02718
02719 { rpmps ps = rpmtsProblems(ts);
02720 if (rc || rpmpsNumProblems(ps) > 0)
02721 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
02722 ps = rpmpsFree(ps);
02723 }
02724 #endif
02725
02726 return rc;
02727 }