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