00001
00005 #include "system.h"
00006
00007 #include <rpmcli.h>
00008
00009 #include <rpmmacro.h>
00010
00011 #include "rpmdb.h"
00012
00013 #include "rpmds.h"
00014 #include "rpmfi.h"
00015
00016 #define _RPMTE_INTERNAL
00017 #include "rpmte.h"
00018
00019 #define _RPMTS_INTERNAL
00020 #include "rpmts.h"
00021
00022 #include "debug.h"
00023
00024
00025
00026
00027
00028
00029
00030
00033 typedef struct orderListIndex_s * orderListIndex;
00034
00035
00038 struct orderListIndex_s {
00039
00040 alKey pkgKey;
00041 int orIndex;
00042 };
00043
00044
00045 int _cacheDependsRC = 1;
00046
00047
00048 const char *rpmNAME = PACKAGE;
00049
00050
00051 const char *rpmEVR = VERSION;
00052
00053
00054 int rpmFLAGS = RPMSENSE_EQUAL;
00055
00062 static int intcmp(const void * a, const void * b)
00063
00064 {
00065 const int * aptr = a;
00066 const int * bptr = b;
00067 int rc = (*aptr - *bptr);
00068 return rc;
00069 }
00070
00079 static int removePackage(rpmts ts, Header h, int dboffset,
00080 alKey depends)
00081
00082
00083 {
00084 rpmte p;
00085
00086
00087 if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) {
00088
00089 if (bsearch(&dboffset, ts->removedPackages, ts->numRemovedPackages,
00090 sizeof(*ts->removedPackages), intcmp) != NULL)
00091 return 0;
00092
00093 }
00094
00095 if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
00096 ts->allocedRemovedPackages += ts->delta;
00097 ts->removedPackages = xrealloc(ts->removedPackages,
00098 sizeof(ts->removedPackages) * ts->allocedRemovedPackages);
00099 }
00100
00101 if (ts->removedPackages != NULL) {
00102
00103 ts->removedPackages[ts->numRemovedPackages] = dboffset;
00104 ts->numRemovedPackages++;
00105
00106 if (ts->numRemovedPackages > 1)
00107 qsort(ts->removedPackages, ts->numRemovedPackages,
00108 sizeof(*ts->removedPackages), intcmp);
00109 }
00110
00111 if (ts->orderCount >= ts->orderAlloced) {
00112 ts->orderAlloced += (ts->orderCount - ts->orderAlloced) + ts->delta;
00113
00114 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
00115
00116 }
00117
00118 p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, dboffset, depends);
00119
00120 ts->order[ts->orderCount] = p;
00121 ts->orderCount++;
00122
00123
00124 return 0;
00125 }
00126
00127 int rpmtsAddInstallElement(rpmts ts, Header h,
00128 fnpyKey key, int upgrade, rpmRelocation * relocs)
00129 {
00130 uint_32 tscolor = rpmtsColor(ts);
00131 uint_32 dscolor;
00132 uint_32 hcolor;
00133 rpmdbMatchIterator mi;
00134 Header oh;
00135 uint_32 ohcolor;
00136 int isSource;
00137 int duplicate = 0;
00138 rpmtsi pi = NULL; rpmte p;
00139 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00140 const char * arch;
00141 const char * os;
00142 rpmds oldChk, newChk;
00143 rpmds obsoletes;
00144 alKey pkgKey;
00145 int xx;
00146 int ec = 0;
00147 int rc;
00148 int oc;
00149
00150
00151
00152
00153
00154 arch = NULL;
00155 xx = hge(h, RPMTAG_ARCH, NULL, (void **)&arch, NULL);
00156 os = NULL;
00157 xx = hge(h, RPMTAG_OS, NULL, (void **)&os, NULL);
00158 hcolor = hGetColor(h);
00159 pkgKey = RPMAL_NOMATCH;
00160
00161
00162 isSource = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
00163 if (isSource) {
00164 oc = ts->orderCount;
00165 goto addheader;
00166 }
00167
00168 oldChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_LESS));
00169 newChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_EQUAL|RPMSENSE_GREATER));
00170
00171 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
00172 rpmds this;
00173
00174
00175 if (rpmteType(p) == TR_REMOVED)
00176 continue;
00177
00178
00179 if (rpmteIsSource(p))
00180 continue;
00181
00182 if (tscolor) {
00183 const char * parch;
00184 const char * pos;
00185
00186 if (arch == NULL || (parch = rpmteA(p)) == NULL)
00187 continue;
00188 if (os == NULL || (pos = rpmteO(p)) == NULL)
00189 continue;
00190 if (strcmp(arch, parch) || strcmp(os, pos))
00191 continue;
00192 }
00193
00194
00195 if ((this = rpmteDS(p, RPMTAG_NAME)) == NULL)
00196 continue;
00197
00198
00199 rc = rpmdsCompare(newChk, this);
00200 if (rc != 0) {
00201 const char * pkgNEVR = rpmdsDNEVR(this);
00202 const char * addNEVR = rpmdsDNEVR(oldChk);
00203 if (rpmIsVerbose())
00204 rpmMessage(RPMMESS_WARNING,
00205 _("package %s was already added, skipping %s\n"),
00206 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
00207 (addNEVR ? addNEVR + 2 : "?addNEVR?"));
00208 ec = 1;
00209 break;
00210 }
00211
00212
00213 rc = rpmdsCompare(oldChk, this);
00214 if (rc != 0) {
00215 const char * pkgNEVR = rpmdsDNEVR(this);
00216 const char * addNEVR = rpmdsDNEVR(newChk);
00217 if (rpmIsVerbose())
00218 rpmMessage(RPMMESS_WARNING,
00219 _("package %s was already added, replacing with %s\n"),
00220 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
00221 (addNEVR ? addNEVR + 2 : "?addNEVR?"));
00222 duplicate = 1;
00223 pkgKey = rpmteAddedKey(p);
00224 break;
00225 }
00226 }
00227 pi = rpmtsiFree(pi);
00228 oldChk = rpmdsFree(oldChk);
00229 newChk = rpmdsFree(newChk);
00230
00231
00232 if (ec)
00233 goto exit;
00234
00235 addheader:
00236 if (oc >= ts->orderAlloced) {
00237 ts->orderAlloced += (oc - ts->orderAlloced) + ts->delta;
00238
00239 ts->order = xrealloc(ts->order, ts->orderAlloced * sizeof(*ts->order));
00240
00241 }
00242
00243 p = rpmteNew(ts, h, TR_ADDED, key, relocs, -1, pkgKey);
00244
00245 if (duplicate && oc < ts->orderCount) {
00246
00247
00248 ts->order[oc] = rpmteFree(ts->order[oc]);
00249
00250
00251 }
00252
00253
00254 ts->order[oc] = p;
00255
00256 if (!duplicate) {
00257 ts->orderCount++;
00258 rpmcliPackagesTotal++;
00259 }
00260
00261 pkgKey = rpmalAdd(&ts->addedPackages, pkgKey, rpmteKey(p),
00262 rpmteDS(p, RPMTAG_PROVIDENAME),
00263 rpmteFI(p, RPMTAG_BASENAMES), tscolor);
00264 if (pkgKey == RPMAL_NOMATCH) {
00265
00266 ts->order[oc] = rpmteFree(ts->order[oc]);
00267
00268 ec = 1;
00269 goto exit;
00270 }
00271 (void) rpmteSetAddedKey(p, pkgKey);
00272
00273 if (!duplicate) {
00274 ts->numAddedPackages++;
00275 }
00276
00277
00278 if (upgrade & 0x2)
00279 (void) rpmteSetHeader(p, h);
00280
00281
00282 if (!(upgrade & 0x1))
00283 goto exit;
00284
00285
00286 if (isSource)
00287 goto exit;
00288
00289
00290 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
00291 if ((ec = rpmtsOpenDB(ts, ts->dbmode)) != 0)
00292 goto exit;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
00302 while((oh = rpmdbNextIterator(mi)) != NULL) {
00303
00304
00305 ohcolor = hGetColor(oh);
00306 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
00307 continue;
00308
00309
00310 if (rpmVersionCompare(h, oh) == 0)
00311 continue;
00312
00313 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), pkgKey);
00314 }
00315 mi = rpmdbFreeIterator(mi);
00316
00317 obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME), "Obsoletes");
00318 obsoletes = rpmdsInit(obsoletes);
00319 if (obsoletes != NULL)
00320 while (rpmdsNext(obsoletes) >= 0) {
00321 const char * Name;
00322
00323 if ((Name = rpmdsN(obsoletes)) == NULL)
00324 continue;
00325
00326
00327 #if 0
00328 dscolor = rpmdsColor(obsoletes);
00329 #else
00330 dscolor = hcolor;
00331 #endif
00332
00333 if (tscolor && dscolor && !(tscolor & dscolor))
00334 continue;
00335
00336
00337 if (!strcmp(rpmteN(p), Name))
00338 continue;
00339
00340 if (Name[0] == '/')
00341 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
00342 else
00343 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
00344
00345 xx = rpmdbPruneIterator(mi,
00346 ts->removedPackages, ts->numRemovedPackages, 1);
00347
00348 while((oh = rpmdbNextIterator(mi)) != NULL) {
00349
00350 ohcolor = hGetColor(oh);
00351
00352
00353 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
00354 continue;
00355
00356
00357
00358
00359
00360 if (rpmdsEVR(obsoletes) == NULL
00361 || rpmdsAnyMatchesDep(oh, obsoletes, _rpmds_nopromote)) {
00362 const char * ohNEVRA = hGetNEVRA(oh, NULL);
00363 #ifdef DYING
00364 if (rpmVersionCompare(h, oh))
00365 #endif
00366 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), pkgKey);
00367
00368 rpmMessage(RPMMESS_DEBUG, _(" Obsoletes: %s\t\terases %s\n"),
00369 rpmdsDNEVR(obsoletes)+2, ohNEVRA);
00370
00371 ohNEVRA = _free(ohNEVRA);
00372 }
00373 }
00374 mi = rpmdbFreeIterator(mi);
00375 }
00376 obsoletes = rpmdsFree(obsoletes);
00377
00378 ec = 0;
00379
00380 exit:
00381 pi = rpmtsiFree(pi);
00382 return ec;
00383 }
00384
00385 int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
00386 {
00387 return removePackage(ts, h, dboffset, RPMAL_NOMATCH);
00388 }
00389
00397 static int unsatisfiedDepend(rpmts ts, rpmds dep, int adding)
00398
00399
00400
00401
00402 {
00403 DBT * key = alloca(sizeof(*key));
00404 DBT * data = alloca(sizeof(*data));
00405 rpmdbMatchIterator mi;
00406 const char * Name;
00407 Header h;
00408 int _cacheThisRC = 1;
00409 int rc;
00410 int xx;
00411 int retrying = 0;
00412
00413 if ((Name = rpmdsN(dep)) == NULL)
00414 return 0;
00415
00416
00417
00418
00419 if (_cacheDependsRC) {
00420 dbiIndex dbi;
00421 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
00422 if (dbi == NULL)
00423 _cacheDependsRC = 0;
00424 else {
00425 const char * DNEVR;
00426
00427 rc = -1;
00428
00429 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
00430 DBC * dbcursor = NULL;
00431 void * datap = NULL;
00432 size_t datalen = 0;
00433 size_t DNEVRlen = strlen(DNEVR);
00434
00435 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0);
00436
00437 memset(key, 0, sizeof(*key));
00438 key->data = (void *) DNEVR;
00439 key->size = DNEVRlen;
00440 memset(data, 0, sizeof(*data));
00441 data->data = datap;
00442 data->size = datalen;
00443
00444 xx = dbiGet(dbi, dbcursor, key, data, DB_SET);
00445
00446 DNEVR = key->data;
00447 DNEVRlen = key->size;
00448 datap = data->data;
00449 datalen = data->size;
00450
00451
00452 if (xx == 0 && datap && datalen == 4)
00453 memcpy(&rc, datap, datalen);
00454
00455 xx = dbiCclose(dbi, dbcursor, 0);
00456 }
00457
00458
00459 if (rc >= 0) {
00460 rpmdsNotify(dep, _("(cached)"), rc);
00461 return rc;
00462 }
00463 }
00464 }
00465
00466 retry:
00467 rc = 0;
00468
00469 #if defined(DYING) || defined(__LCLINT__)
00470 { static const char noProvidesString[] = "nada";
00471 static const char * rcProvidesString = noProvidesString;
00472 int_32 Flags = rpmdsFlags(dep);
00473 const char * start;
00474 int i;
00475
00476 if (rcProvidesString == noProvidesString)
00477 rcProvidesString = rpmGetVar(RPMVAR_PROVIDES);
00478
00479 if (rcProvidesString != NULL && !(Flags & RPMSENSE_SENSEMASK)) {
00480
00481 i = strlen(Name);
00482
00483 while ((start = strstr(rcProvidesString, Name))) {
00484
00485
00486 if (xisspace(start[i]) || start[i] == '\0' || start[i] == ',') {
00487 rpmdsNotify(dep, _("(rpmrc provides)"), rc);
00488 goto exit;
00489 }
00490
00491 rcProvidesString = start + 1;
00492 }
00493 }
00494 }
00495 #endif
00496
00497
00498
00499
00500
00501
00502 if (!strncmp(Name, "rpmlib(", sizeof("rpmlib(")-1)) {
00503 if (rpmCheckRpmlibProvides(dep)) {
00504 rpmdsNotify(dep, _("(rpmlib provides)"), rc);
00505 goto exit;
00506 }
00507 goto unsatisfied;
00508 }
00509
00510
00511 if (!strncmp(Name, "cpuinfo(", sizeof("cpuinfo(")-1))
00512 goto exit;
00513
00514
00515 if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) {
00516
00517
00518
00519
00520 if (_rpmds_nopromote)
00521 _cacheThisRC = 0;
00522 goto exit;
00523 }
00524
00525
00526 if (rpmtsGetRdb(ts) != NULL) {
00527
00528 if (Name[0] == '/') {
00529
00530
00531 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
00532
00533 (void) rpmdbPruneIterator(mi,
00534 ts->removedPackages, ts->numRemovedPackages, 1);
00535
00536 while ((h = rpmdbNextIterator(mi)) != NULL) {
00537 rpmdsNotify(dep, _("(db files)"), rc);
00538 mi = rpmdbFreeIterator(mi);
00539 goto exit;
00540 }
00541 mi = rpmdbFreeIterator(mi);
00542 }
00543
00544
00545 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
00546 (void) rpmdbPruneIterator(mi,
00547 ts->removedPackages, ts->numRemovedPackages, 1);
00548 while ((h = rpmdbNextIterator(mi)) != NULL) {
00549 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) {
00550 rpmdsNotify(dep, _("(db provides)"), rc);
00551 mi = rpmdbFreeIterator(mi);
00552 goto exit;
00553 }
00554 }
00555 mi = rpmdbFreeIterator(mi);
00556
00557 #if defined(DYING) || defined(__LCLINT__)
00558 mi = rpmtsInitIterator(ts, RPMTAG_NAME, Name, 0);
00559 (void) rpmdbPruneIterator(mi,
00560 ts->removedPackages, ts->numRemovedPackages, 1);
00561 while ((h = rpmdbNextIterator(mi)) != NULL) {
00562 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) {
00563 rpmdsNotify(dep, _("(db package)"), rc);
00564 mi = rpmdbFreeIterator(mi);
00565 goto exit;
00566 }
00567 }
00568 mi = rpmdbFreeIterator(mi);
00569 #endif
00570
00571 }
00572
00573
00574
00575
00576
00577 if (adding && !retrying && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOSUGGEST)) {
00578 if (ts->solve != NULL) {
00579 xx = (*ts->solve) (ts, dep, ts->solveData);
00580 if (xx == 0)
00581 goto exit;
00582 if (xx == -1) {
00583 retrying = 1;
00584 rpmalMakeIndex(ts->addedPackages);
00585 goto retry;
00586 }
00587 }
00588 }
00589
00590
00591 unsatisfied:
00592 rc = 1;
00593 rpmdsNotify(dep, NULL, rc);
00594
00595 exit:
00596
00597
00598
00599 if (_cacheDependsRC && _cacheThisRC) {
00600 dbiIndex dbi;
00601 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
00602 if (dbi == NULL) {
00603 _cacheDependsRC = 0;
00604 } else {
00605 const char * DNEVR;
00606 xx = 0;
00607
00608 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
00609 DBC * dbcursor = NULL;
00610 size_t DNEVRlen = strlen(DNEVR);
00611
00612 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, DB_WRITECURSOR);
00613
00614 memset(key, 0, sizeof(*key));
00615 key->data = (void *) DNEVR;
00616 key->size = DNEVRlen;
00617 memset(data, 0, sizeof(*data));
00618 data->data = &rc;
00619 data->size = sizeof(rc);
00620
00621
00622 xx = dbiPut(dbi, dbcursor, key, data, 0);
00623
00624 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
00625 }
00626
00627 if (xx)
00628 _cacheDependsRC = 0;
00629 }
00630 }
00631 return rc;
00632 }
00633
00645 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA,
00646 rpmds requires, rpmds conflicts,
00647 const char * depName, uint_32 tscolor, int adding)
00648
00649
00650
00651
00652 {
00653 uint_32 dscolor;
00654 const char * Name;
00655 int rc;
00656 int ourrc = 0;
00657
00658 requires = rpmdsInit(requires);
00659 if (requires != NULL)
00660 while (!ourrc && rpmdsNext(requires) >= 0) {
00661
00662 if ((Name = rpmdsN(requires)) == NULL)
00663 continue;
00664
00665
00666 if (depName != NULL && strcmp(depName, Name))
00667 continue;
00668
00669
00670 dscolor = rpmdsColor(requires);
00671 if (tscolor && dscolor && !(tscolor & dscolor))
00672 continue;
00673
00674 rc = unsatisfiedDepend(ts, requires, adding);
00675
00676 switch (rc) {
00677 case 0:
00678 break;
00679 case 1:
00680 { fnpyKey * suggestedKeys = NULL;
00681
00682
00683 if (ts->availablePackages != NULL) {
00684 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
00685 requires, NULL);
00686 }
00687
00688
00689 rpmdsProblem(ts->probs, pkgNEVRA, requires, suggestedKeys, adding);
00690
00691 }
00692 break;
00693 case 2:
00694 default:
00695 ourrc = 1;
00696 break;
00697 }
00698 }
00699
00700 conflicts = rpmdsInit(conflicts);
00701 if (conflicts != NULL)
00702 while (!ourrc && rpmdsNext(conflicts) >= 0) {
00703
00704 if ((Name = rpmdsN(conflicts)) == NULL)
00705 continue;
00706
00707
00708 if (depName != NULL && strcmp(depName, Name))
00709 continue;
00710
00711
00712 dscolor = rpmdsColor(conflicts);
00713 if (tscolor && dscolor && !(tscolor & dscolor))
00714 continue;
00715
00716 rc = unsatisfiedDepend(ts, conflicts, adding);
00717
00718
00719 switch (rc) {
00720 case 0:
00721 rpmdsProblem(ts->probs, pkgNEVRA, conflicts, NULL, adding);
00722 break;
00723 case 1:
00724 break;
00725 case 2:
00726 default:
00727 ourrc = 1;
00728 break;
00729 }
00730 }
00731
00732 return ourrc;
00733 }
00734
00745 static int checkPackageSet(rpmts ts, const char * dep,
00746 rpmdbMatchIterator mi, int adding)
00747
00748
00749 {
00750 int scareMem = 1;
00751 Header h;
00752 int ec = 0;
00753
00754 (void) rpmdbPruneIterator(mi,
00755 ts->removedPackages, ts->numRemovedPackages, 1);
00756 while ((h = rpmdbNextIterator(mi)) != NULL) {
00757 const char * pkgNEVRA;
00758 rpmds requires, conflicts;
00759 int rc;
00760
00761 pkgNEVRA = hGetNEVRA(h, NULL);
00762 requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
00763 (void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
00764 conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
00765 (void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote);
00766 rc = checkPackageDeps(ts, pkgNEVRA, requires, conflicts, dep, 0, adding);
00767 conflicts = rpmdsFree(conflicts);
00768 requires = rpmdsFree(requires);
00769 pkgNEVRA = _free(pkgNEVRA);
00770
00771 if (rc) {
00772 ec = 1;
00773 break;
00774 }
00775 }
00776 mi = rpmdbFreeIterator(mi);
00777
00778 return ec;
00779 }
00780
00787 static int checkDependentPackages(rpmts ts, const char * dep)
00788
00789
00790 {
00791 rpmdbMatchIterator mi;
00792 mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, dep, 0);
00793 return checkPackageSet(ts, dep, mi, 0);
00794 }
00795
00802 static int checkDependentConflicts(rpmts ts, const char * dep)
00803
00804
00805 {
00806 int rc = 0;
00807
00808 if (rpmtsGetRdb(ts) != NULL) {
00809 rpmdbMatchIterator mi;
00810 mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, dep, 0);
00811 rc = checkPackageSet(ts, dep, mi, 1);
00812 }
00813
00814 return rc;
00815 }
00816
00817 struct badDeps_s {
00818
00819 const char * pname;
00820
00821 const char * qname;
00822 };
00823
00824 #ifdef REFERENCE
00825 static struct badDeps_s {
00826 const char * pname;
00827 const char * qname;
00828 } badDeps[] = {
00829 { "libtermcap", "bash" },
00830 { "modutils", "vixie-cron" },
00831 { "ypbind", "yp-tools" },
00832 { "ghostscript-fonts", "ghostscript" },
00833
00834 { "libgnomeprint15", "gnome-print" },
00835 { "nautilus", "nautilus-mozilla" },
00836
00837 { "arts", "kdelibs-sound" },
00838
00839 { "pango-gtkbeta-devel", "pango-gtkbeta" },
00840 { "XFree86", "Mesa" },
00841 { "compat-glibc", "db2" },
00842 { "compat-glibc", "db1" },
00843 { "pam", "initscripts" },
00844 { "initscripts", "sysklogd" },
00845
00846 { "egcs-c++", "libstdc++" },
00847
00848 { "pilot-link-devel", "pilot-link" },
00849
00850 { "pam", "pamconfig" },
00851 { NULL, NULL }
00852 };
00853 #else
00854
00855 static int badDepsInitialized = 0;
00856
00857
00858 static struct badDeps_s * badDeps = NULL;
00859 #endif
00860
00863
00864 static void freeBadDeps(void)
00865
00866
00867 {
00868 if (badDeps) {
00869 struct badDeps_s * bdp;
00870 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++)
00871 bdp->pname = _free(bdp->pname);
00872 badDeps = _free(badDeps);
00873 }
00874 badDepsInitialized = 0;
00875 }
00876
00877
00886
00887 static int ignoreDep(const rpmts ts, const rpmte p, const rpmte q)
00888
00889
00890
00891
00892 {
00893 struct badDeps_s * bdp;
00894
00895 if (!badDepsInitialized) {
00896 char * s = rpmExpand("%{?_dependency_whiteout}", NULL);
00897 const char ** av = NULL;
00898 int anaconda = rpmtsFlags(ts) & RPMTRANS_FLAG_ANACONDA;
00899 int msglvl = (anaconda || (rpmtsFlags(ts) & RPMTRANS_FLAG_DEPLOOPS))
00900 ? RPMMESS_WARNING : RPMMESS_DEBUG;
00901 int ac = 0;
00902 int i;
00903
00904 if (s != NULL && *s != '\0'
00905 && !(i = poptParseArgvString(s, &ac, (const char ***)&av))
00906 && ac > 0 && av != NULL)
00907 {
00908 bdp = badDeps = xcalloc(ac+1, sizeof(*badDeps));
00909 for (i = 0; i < ac; i++, bdp++) {
00910 char * pname, * qname;
00911
00912 if (av[i] == NULL)
00913 break;
00914 pname = xstrdup(av[i]);
00915 if ((qname = strchr(pname, '>')) != NULL)
00916 *qname++ = '\0';
00917 bdp->pname = pname;
00918
00919 bdp->qname = qname;
00920
00921 rpmMessage(msglvl,
00922 _("ignore package name relation(s) [%d]\t%s -> %s\n"),
00923 i, bdp->pname, (bdp->qname ? bdp->qname : "???"));
00924 }
00925 bdp->pname = NULL;
00926 bdp->qname = NULL;
00927 }
00928 av = _free(av);
00929 s = _free(s);
00930 badDepsInitialized++;
00931 }
00932
00933
00934 if (badDeps != NULL)
00935 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++) {
00936 if (!strcmp(rpmteN(p), bdp->pname) && !strcmp(rpmteN(q), bdp->qname))
00937 return 1;
00938 }
00939 return 0;
00940
00941 }
00942
00943
00949 static void markLoop( tsortInfo tsi, rpmte q)
00950
00951
00952
00953 {
00954 rpmte p;
00955
00956
00957 while (tsi != NULL && (p = tsi->tsi_suc) != NULL) {
00958 tsi = tsi->tsi_next;
00959 if (rpmteTSI(p)->tsi_chain != NULL)
00960 continue;
00961
00962 rpmteTSI(p)->tsi_chain = q;
00963
00964 if (rpmteTSI(p)->tsi_next != NULL)
00965 markLoop(rpmteTSI(p)->tsi_next, p);
00966 }
00967
00968 }
00969
00970 static inline const char * const identifyDepend(int_32 f)
00971
00972 {
00973 f = _notpre(f);
00974 if (f & RPMSENSE_SCRIPT_PRE)
00975 return "Requires(pre):";
00976 if (f & RPMSENSE_SCRIPT_POST)
00977 return "Requires(post):";
00978 if (f & RPMSENSE_SCRIPT_PREUN)
00979 return "Requires(preun):";
00980 if (f & RPMSENSE_SCRIPT_POSTUN)
00981 return "Requires(postun):";
00982 if (f & RPMSENSE_SCRIPT_VERIFY)
00983 return "Requires(verify):";
00984 if (f & RPMSENSE_FIND_REQUIRES)
00985 return "Requires(auto):";
00986 return "Requires:";
00987 }
00988
01002
01003
01004 static const char *
01005 zapRelation(rpmte q, rpmte p,
01006 rpmds requires,
01007 int zap, int * nzaps, int msglvl)
01008
01009 {
01010 tsortInfo tsi_prev;
01011 tsortInfo tsi;
01012 const char *dp = NULL;
01013
01014 for (tsi_prev = rpmteTSI(q), tsi = rpmteTSI(q)->tsi_next;
01015 tsi != NULL;
01016
01017
01018 tsi_prev = tsi, tsi = tsi->tsi_next)
01019
01020 {
01021 int_32 Flags;
01022
01023
01024 if (tsi->tsi_suc != p)
01025 continue;
01026
01027
01028 if (requires == NULL) continue;
01029
01030 (void) rpmdsSetIx(requires, tsi->tsi_reqx);
01031
01032 Flags = rpmdsFlags(requires);
01033
01034 dp = rpmdsNewDNEVR( identifyDepend(Flags), requires);
01035
01036
01037
01038
01039
01040 if (zap) {
01041 rpmMessage(msglvl,
01042 _("removing %s \"%s\" from tsort relations.\n"),
01043 (rpmteNEVRA(p) ? rpmteNEVRA(p) : "???"), dp);
01044 rpmteTSI(p)->tsi_count--;
01045 if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next;
01046 tsi->tsi_next = NULL;
01047 tsi->tsi_suc = NULL;
01048 tsi = _free(tsi);
01049 if (nzaps)
01050 (*nzaps)++;
01051 if (zap)
01052 zap--;
01053 }
01054
01055
01056 break;
01057 }
01058 return dp;
01059 }
01060
01061
01062
01071
01072 static inline int addRelation(rpmts ts,
01073 rpmte p,
01074 unsigned char * selected,
01075 rpmds requires)
01076
01077
01078
01079 {
01080 rpmtsi qi; rpmte q;
01081 tsortInfo tsi;
01082 const char * Name;
01083 fnpyKey key;
01084 alKey pkgKey;
01085 int i = 0;
01086
01087 if ((Name = rpmdsN(requires)) == NULL)
01088 return 0;
01089
01090
01091 if (!strncmp(Name, "rpmlib(", sizeof("rpmlib(")-1))
01092 return 0;
01093
01094
01095 if (!strncmp(Name, "config(", sizeof("config(")-1))
01096 return 0;
01097
01098 pkgKey = RPMAL_NOMATCH;
01099 key = rpmalSatisfiesDepend(ts->addedPackages, requires, &pkgKey);
01100
01101
01102 if (pkgKey == RPMAL_NOMATCH)
01103 return 0;
01104
01105
01106
01107 for (qi = rpmtsiInit(ts), i = 0; (q = rpmtsiNext(qi, 0)) != NULL; i++) {
01108
01109
01110 if (rpmteType(q) == TR_REMOVED)
01111 continue;
01112
01113 if (pkgKey == rpmteAddedKey(q))
01114 break;
01115 }
01116 qi = rpmtsiFree(qi);
01117 if (q == NULL || i == ts->orderCount)
01118 return 0;
01119
01120
01121 if (ignoreDep(ts, p, q))
01122 return 0;
01123
01124
01125
01126
01127 if (selected[i] != 0)
01128 return 0;
01129
01130
01131 selected[i] = 1;
01132
01133
01134
01135 rpmteTSI(p)->tsi_count++;
01136
01137 if (rpmteDepth(p) <= rpmteDepth(q))
01138 (void) rpmteSetDepth(p, (rpmteDepth(q) + 1));
01139 if (rpmteDepth(p) > ts->maxDepth)
01140 ts->maxDepth = rpmteDepth(p);
01141
01142 tsi = xcalloc(1, sizeof(*tsi));
01143 tsi->tsi_suc = p;
01144
01145 tsi->tsi_reqx = rpmdsIx(requires);
01146
01147 tsi->tsi_next = rpmteTSI(q)->tsi_next;
01148 rpmteTSI(q)->tsi_next = tsi;
01149 rpmteTSI(q)->tsi_qcnt++;
01150 return 0;
01151 }
01152
01153
01160 static int orderListIndexCmp(const void * one, const void * two)
01161 {
01162
01163 long a = (long) ((const orderListIndex)one)->pkgKey;
01164 long b = (long) ((const orderListIndex)two)->pkgKey;
01165
01166 return (a - b);
01167 }
01168
01175
01176
01177 static void addQ( rpmte p,
01178 rpmte * qp,
01179 rpmte * rp)
01180
01181 {
01182 rpmte q, qprev;
01183
01184
01185 rpmteTSI(p)->tsi_reqx = 1;
01186
01187 if ((*rp) == NULL) {
01188
01189 (*rp) = (*qp) = p;
01190
01191 return;
01192 }
01193
01194
01195 for (qprev = NULL, q = (*qp);
01196 q != NULL;
01197 qprev = q, q = rpmteTSI(q)->tsi_suc)
01198 {
01199 if (rpmteTSI(q)->tsi_qcnt <= rpmteTSI(p)->tsi_qcnt)
01200 break;
01201 }
01202
01203 if (qprev == NULL) {
01204 rpmteTSI(p)->tsi_suc = q;
01205
01206 (*qp) = p;
01207
01208 } else if (q == NULL) {
01209 rpmteTSI(qprev)->tsi_suc = p;
01210
01211 (*rp) = p;
01212
01213 } else {
01214 rpmteTSI(p)->tsi_suc = q;
01215 rpmteTSI(qprev)->tsi_suc = p;
01216 }
01217 }
01218
01219
01220
01221
01222 int rpmtsOrder(rpmts ts)
01223 {
01224 rpmds requires;
01225 int_32 Flags;
01226 int anaconda = rpmtsFlags(ts) & RPMTRANS_FLAG_ANACONDA;
01227 rpmtsi pi; rpmte p;
01228 rpmtsi qi; rpmte q;
01229 rpmtsi ri; rpmte r;
01230 tsortInfo tsi;
01231 tsortInfo tsi_next;
01232 alKey * ordering;
01233 int orderingCount = 0;
01234 unsigned char * selected = alloca(sizeof(*selected) * (ts->orderCount + 1));
01235 int loopcheck;
01236 rpmte * newOrder;
01237 int newOrderCount = 0;
01238 orderListIndex orderList;
01239 int numOrderList;
01240 int npeer = 128;
01241 int * peer = memset(alloca(npeer*sizeof(*peer)), 0, (npeer*sizeof(*peer)));
01242 int nrescans = 10;
01243 int _printed = 0;
01244 char deptypechar;
01245 size_t tsbytes;
01246 int oType = 0;
01247 int treex;
01248 int depth;
01249 int breadth;
01250 int qlen;
01251 int i, j;
01252
01253 #ifdef DYING
01254 rpmalMakeIndex(ts->addedPackages);
01255 #endif
01256
01257 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
01258
01259
01260 if (oType == 0)
01261 numOrderList = ts->orderCount;
01262 else {
01263 numOrderList = 0;
01264 if (oType & TR_ADDED)
01265 numOrderList += ts->numAddedPackages;
01266 if (oType & TR_REMOVED)
01267 numOrderList += ts->numRemovedPackages;
01268 }
01269 ordering = alloca(sizeof(*ordering) * (numOrderList + 1));
01270 loopcheck = numOrderList;
01271 tsbytes = 0;
01272
01273 pi = rpmtsiInit(ts);
01274 while ((p = rpmtsiNext(pi, oType)) != NULL)
01275 rpmteNewTSI(p);
01276 pi = rpmtsiFree(pi);
01277
01278
01279 rpmMessage(RPMMESS_DEBUG, _("========== recording tsort relations\n"));
01280 pi = rpmtsiInit(ts);
01281 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01282
01283 if ((requires = rpmteDS(p, RPMTAG_REQUIRENAME)) == NULL)
01284 continue;
01285
01286 memset(selected, 0, sizeof(*selected) * ts->orderCount);
01287
01288
01289 selected[rpmtsiOc(pi)] = 1;
01290
01291
01292
01293
01294 requires = rpmdsInit(requires);
01295 if (requires != NULL)
01296 while (rpmdsNext(requires) >= 0) {
01297
01298 Flags = rpmdsFlags(requires);
01299
01300 switch (rpmteType(p)) {
01301 case TR_REMOVED:
01302
01303 if (isInstallPreReq(Flags)
01304 || !( isErasePreReq(Flags) ) )
01305 continue;
01306 break;
01307 case TR_ADDED:
01308
01309 if (isErasePreReq(Flags)
01310 || !( isInstallPreReq(Flags) ) )
01311 continue;
01312 break;
01313 }
01314
01315
01316 (void) addRelation(ts, p, selected, requires);
01317
01318 }
01319
01320
01321 requires = rpmdsInit(requires);
01322 if (requires != NULL)
01323 while (rpmdsNext(requires) >= 0) {
01324
01325 Flags = rpmdsFlags(requires);
01326
01327 switch (rpmteType(p)) {
01328 case TR_REMOVED:
01329
01330 if (isInstallPreReq(Flags)
01331 || ( isErasePreReq(Flags) ) )
01332 continue;
01333 break;
01334 case TR_ADDED:
01335
01336 if (isErasePreReq(Flags)
01337 || ( isInstallPreReq(Flags) ) )
01338 continue;
01339 break;
01340 }
01341
01342
01343 (void) addRelation(ts, p, selected, requires);
01344
01345 }
01346 }
01347 pi = rpmtsiFree(pi);
01348
01349
01350 treex = 0;
01351 pi = rpmtsiInit(ts);
01352 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01353 int npreds;
01354
01355 npreds = rpmteTSI(p)->tsi_count;
01356
01357 (void) rpmteSetNpreds(p, npreds);
01358 (void) rpmteSetDepth(p, 1);
01359
01360 if (npreds == 0)
01361 (void) rpmteSetTree(p, treex++);
01362 else
01363 (void) rpmteSetTree(p, -1);
01364 #ifdef UNNECESSARY
01365 (void) rpmteSetParent(p, NULL);
01366 #endif
01367
01368 }
01369 pi = rpmtsiFree(pi);
01370 ts->ntrees = treex;
01371
01372
01373 rpmMessage(RPMMESS_DEBUG, _("========== tsorting packages (order, #predecessors, #succesors, tree, depth, breadth)\n"));
01374
01375 rescan:
01376 if (pi != NULL) pi = rpmtsiFree(pi);
01377 q = r = NULL;
01378 qlen = 0;
01379 pi = rpmtsiInit(ts);
01380 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01381
01382
01383 if (anaconda)
01384 rpmteTSI(p)->tsi_qcnt = (ts->orderCount - rpmtsiOc(pi));
01385
01386 if (rpmteTSI(p)->tsi_count != 0)
01387 continue;
01388 rpmteTSI(p)->tsi_suc = NULL;
01389 addQ(p, &q, &r);
01390 qlen++;
01391 }
01392 pi = rpmtsiFree(pi);
01393
01394
01395 for (; q != NULL; q = rpmteTSI(q)->tsi_suc) {
01396
01397
01398 rpmteTSI(q)->tsi_reqx = 0;
01399
01400 if (oType != 0)
01401 switch (rpmteType(q)) {
01402 case TR_ADDED:
01403 if (!(oType & TR_ADDED))
01404 continue;
01405 break;
01406 case TR_REMOVED:
01407 if (!(oType & TR_REMOVED))
01408 continue;
01409 break;
01410 default:
01411 continue;
01412 break;
01413 }
01414 deptypechar = (rpmteType(q) == TR_REMOVED ? '-' : '+');
01415
01416 treex = rpmteTree(q);
01417 depth = rpmteDepth(q);
01418 breadth = ((depth < npeer) ? peer[depth]++ : 0);
01419 (void) rpmteSetBreadth(q, breadth);
01420
01421 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%5d%5d%5d %*s%c%s\n",
01422 orderingCount, rpmteNpreds(q),
01423 rpmteTSI(q)->tsi_qcnt,
01424 treex, depth, breadth,
01425 (2 * depth), "",
01426 deptypechar,
01427 (rpmteNEVRA(q) ? rpmteNEVRA(q) : "???"));
01428
01429 (void) rpmteSetDegree(q, 0);
01430 tsbytes += rpmtePkgFileSize(q);
01431
01432 ordering[orderingCount] = rpmteAddedKey(q);
01433 orderingCount++;
01434 qlen--;
01435 loopcheck--;
01436
01437
01438 tsi_next = rpmteTSI(q)->tsi_next;
01439 rpmteTSI(q)->tsi_next = NULL;
01440 while ((tsi = tsi_next) != NULL) {
01441 tsi_next = tsi->tsi_next;
01442 tsi->tsi_next = NULL;
01443 p = tsi->tsi_suc;
01444 if (p && (--rpmteTSI(p)->tsi_count) <= 0) {
01445
01446 (void) rpmteSetTree(p, treex);
01447 (void) rpmteSetDepth(p, depth+1);
01448 (void) rpmteSetParent(p, q);
01449 (void) rpmteSetDegree(q, rpmteDegree(q)+1);
01450
01451
01452 rpmteTSI(p)->tsi_suc = NULL;
01453 addQ(p, &rpmteTSI(q)->tsi_suc, &r);
01454 qlen++;
01455 }
01456 tsi = _free(tsi);
01457 }
01458 if (!_printed && loopcheck == qlen && rpmteTSI(q)->tsi_suc != NULL) {
01459 _printed++;
01460 (void) rpmtsUnorderedSuccessors(ts, orderingCount);
01461 rpmMessage(RPMMESS_DEBUG,
01462 _("========== successors only (%d bytes)\n"), (int)tsbytes);
01463
01464
01465 tsi = rpmteTSI(q);
01466 pi = rpmtsiInit(ts);
01467 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01468
01469 if (rpmteTSI(p)->tsi_reqx == 0)
01470 continue;
01471 tsi->tsi_suc = p;
01472 tsi = rpmteTSI(p);
01473 }
01474 pi = rpmtsiFree(pi);
01475 tsi->tsi_suc = NULL;
01476 }
01477 }
01478
01479
01480 if (loopcheck != 0) {
01481 int nzaps;
01482
01483
01484 nzaps = 0;
01485 qi = rpmtsiInit(ts);
01486 while ((q = rpmtsiNext(qi, oType)) != NULL) {
01487 rpmteTSI(q)->tsi_chain = NULL;
01488 rpmteTSI(q)->tsi_reqx = 0;
01489
01490 if (rpmteTSI(q)->tsi_count == 0)
01491 rpmteTSI(q)->tsi_count = -1;
01492 }
01493 qi = rpmtsiFree(qi);
01494
01495
01496 qi = rpmtsiInit(ts);
01497 while ((q = rpmtsiNext(qi, oType)) != NULL) {
01498 if ((tsi = rpmteTSI(q)->tsi_next) == NULL)
01499 continue;
01500 rpmteTSI(q)->tsi_next = NULL;
01501 markLoop(tsi, q);
01502 rpmteTSI(q)->tsi_next = tsi;
01503 }
01504 qi = rpmtsiFree(qi);
01505
01506
01507 ri = rpmtsiInit(ts);
01508 while ((r = rpmtsiNext(ri, oType)) != NULL)
01509 {
01510 int printed;
01511
01512 printed = 0;
01513
01514
01515 for (q = rpmteTSI(r)->tsi_chain; q != NULL;
01516 q = rpmteTSI(q)->tsi_chain)
01517 {
01518 if (rpmteTSI(q)->tsi_reqx)
01519 break;
01520 rpmteTSI(q)->tsi_reqx = 1;
01521 }
01522
01523
01524 while ((p = q) != NULL && (q = rpmteTSI(p)->tsi_chain) != NULL) {
01525 const char * dp;
01526 char buf[4096];
01527 int msglvl = (anaconda || (rpmtsFlags(ts) & RPMTRANS_FLAG_DEPLOOPS))
01528 ? RPMMESS_WARNING : RPMMESS_DEBUG;
01529 ;
01530
01531
01532 rpmteTSI(p)->tsi_chain = NULL;
01533
01534 if (!printed) {
01535 rpmMessage(msglvl, _("LOOP:\n"));
01536 printed = 1;
01537 }
01538
01539
01540 requires = rpmteDS(p, RPMTAG_REQUIRENAME);
01541 requires = rpmdsInit(requires);
01542 if (requires == NULL)
01543 continue;
01544 dp = zapRelation(q, p, requires, 1, &nzaps, msglvl);
01545
01546
01547 buf[0] = '\0';
01548 if (rpmteNEVRA(p) != NULL)
01549 (void) stpcpy(buf, rpmteNEVRA(p));
01550 rpmMessage(msglvl, " %-40s %s\n", buf,
01551 (dp ? dp : "not found!?!"));
01552
01553 dp = _free(dp);
01554 }
01555
01556
01557 for (p = r, q = rpmteTSI(r)->tsi_chain; q != NULL;
01558 p = q, q = rpmteTSI(q)->tsi_chain)
01559 {
01560
01561 rpmteTSI(p)->tsi_chain = NULL;
01562 rpmteTSI(p)->tsi_reqx = 0;
01563 }
01564 }
01565 ri = rpmtsiFree(ri);
01566
01567
01568
01569 if (nzaps && nrescans-- > 0) {
01570 rpmMessage(RPMMESS_DEBUG, _("========== continuing tsort ...\n"));
01571 goto rescan;
01572 }
01573
01574
01575 rpmMessage(RPMMESS_ERROR, _("rpmtsOrder failed, %d elements remain\n"),
01576 loopcheck);
01577 return loopcheck;
01578 }
01579
01580
01581 pi = rpmtsiInit(ts);
01582 while ((p = rpmtsiNext(pi, 0)) != NULL)
01583 rpmteFreeTSI(p);
01584 pi = rpmtsiFree(pi);
01585
01586
01587
01588
01589
01590
01591
01592 orderList = xcalloc(numOrderList, sizeof(*orderList));
01593 j = 0;
01594 pi = rpmtsiInit(ts);
01595 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01596
01597 switch (rpmteType(p)) {
01598 case TR_ADDED:
01599 orderList[j].pkgKey = rpmteAddedKey(p);
01600 break;
01601 case TR_REMOVED:
01602 orderList[j].pkgKey = RPMAL_NOMATCH;
01603 break;
01604 }
01605 orderList[j].orIndex = rpmtsiOc(pi);
01606 j++;
01607 }
01608 pi = rpmtsiFree(pi);
01609
01610 qsort(orderList, numOrderList, sizeof(*orderList), orderListIndexCmp);
01611
01612
01613 newOrder = xcalloc(ts->orderCount, sizeof(*newOrder));
01614
01615
01616 for (i = 0, newOrderCount = 0; i < orderingCount; i++)
01617 {
01618 struct orderListIndex_s key;
01619 orderListIndex needle;
01620
01621 key.pkgKey = ordering[i];
01622 needle = bsearch(&key, orderList, numOrderList,
01623 sizeof(key), orderListIndexCmp);
01624
01625 if (needle == NULL)
01626 continue;
01627
01628 j = needle->orIndex;
01629 if ((q = ts->order[j]) == NULL)
01630 continue;
01631
01632 newOrder[newOrderCount++] = q;
01633 ts->order[j] = NULL;
01634 if (anaconda)
01635 for (j = needle->orIndex + 1; j < ts->orderCount; j++) {
01636 if ((q = ts->order[j]) == NULL)
01637 break;
01638 if (rpmteType(q) == TR_REMOVED
01639 && rpmteDependsOnKey(q) == needle->pkgKey)
01640 {
01641 newOrder[newOrderCount++] = q;
01642 ts->order[j] = NULL;
01643 } else
01644 break;
01645 }
01646 }
01647
01648
01649 for (j = 0; j < ts->orderCount; j++) {
01650 if ((p = ts->order[j]) == NULL)
01651 continue;
01652 newOrder[newOrderCount++] = p;
01653 ts->order[j] = NULL;
01654 }
01655 assert(newOrderCount == ts->orderCount);
01656
01657
01658 ts->order = _free(ts->order);
01659
01660 ts->order = newOrder;
01661 ts->orderAlloced = ts->orderCount;
01662 orderList = _free(orderList);
01663
01664 #ifdef DYING
01665 rpmtsClean(ts);
01666 #endif
01667 freeBadDeps();
01668
01669 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
01670
01671 return 0;
01672 }
01673
01674
01675 int rpmtsCheck(rpmts ts)
01676 {
01677 uint_32 tscolor = rpmtsColor(ts);
01678 rpmdbMatchIterator mi = NULL;
01679 rpmtsi pi = NULL; rpmte p;
01680 int closeatexit = 0;
01681 int xx;
01682 int rc;
01683
01684 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
01685
01686
01687 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
01688 if ((rc = rpmtsOpenDB(ts, ts->dbmode)) != 0)
01689 goto exit;
01690 closeatexit = 1;
01691 }
01692
01693 ts->probs = rpmpsFree(ts->probs);
01694 ts->probs = rpmpsCreate();
01695
01696 rpmalMakeIndex(ts->addedPackages);
01697
01698
01699
01700
01701
01702 pi = rpmtsiInit(ts);
01703 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01704 rpmds provides;
01705
01706
01707 rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s/%s 0x%x\n",
01708 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01709
01710 rc = checkPackageDeps(ts, rpmteNEVRA(p),
01711 rpmteDS(p, RPMTAG_REQUIRENAME),
01712 rpmteDS(p, RPMTAG_CONFLICTNAME),
01713 NULL,
01714 tscolor, 1);
01715 if (rc)
01716 goto exit;
01717
01718 rc = 0;
01719 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
01720 provides = rpmdsInit(provides);
01721 if (provides != NULL)
01722 while (rpmdsNext(provides) >= 0) {
01723 const char * Name;
01724
01725 if ((Name = rpmdsN(provides)) == NULL)
01726 continue;
01727
01728
01729 if (!checkDependentConflicts(ts, Name))
01730 continue;
01731 rc = 1;
01732 break;
01733 }
01734 if (rc)
01735 goto exit;
01736 }
01737 pi = rpmtsiFree(pi);
01738
01739
01740
01741
01742 pi = rpmtsiInit(ts);
01743 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
01744 rpmds provides;
01745 rpmfi fi;
01746
01747
01748 rpmMessage(RPMMESS_DEBUG, "========== --- %s %s/%s 0x%x\n",
01749 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01750
01751
01752 #if defined(DYING) || defined(__LCLINT__)
01753
01754
01755 rc = checkDependentPackages(ts, rpmteN(p));
01756 if (rc)
01757 goto exit;
01758 #endif
01759
01760 rc = 0;
01761 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
01762 provides = rpmdsInit(provides);
01763 if (provides != NULL)
01764 while (rpmdsNext(provides) >= 0) {
01765 const char * Name;
01766
01767 if ((Name = rpmdsN(provides)) == NULL)
01768 continue;
01769
01770
01771 if (!checkDependentPackages(ts, Name))
01772 continue;
01773 rc = 1;
01774 break;
01775 }
01776 if (rc)
01777 goto exit;
01778
01779 rc = 0;
01780 fi = rpmteFI(p, RPMTAG_BASENAMES);
01781 fi = rpmfiInit(fi, 0);
01782 while (rpmfiNext(fi) >= 0) {
01783 const char * fn = rpmfiFN(fi);
01784
01785
01786 if (!checkDependentPackages(ts, fn))
01787 continue;
01788 rc = 1;
01789 break;
01790 }
01791 if (rc)
01792 goto exit;
01793 }
01794 pi = rpmtsiFree(pi);
01795
01796 rc = 0;
01797
01798 exit:
01799 mi = rpmdbFreeIterator(mi);
01800 pi = rpmtsiFree(pi);
01801
01802 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
01803
01804
01805 if (closeatexit)
01806 xx = rpmtsCloseDB(ts);
01807 else if (_cacheDependsRC)
01808 xx = rpmdbCloseDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS);
01809
01810 return rc;
01811 }