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