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, _(" 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, _(" 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 if (!rpmioAccess("/etc/rpm/sysinfo", NULL, R_OK)) {
00845 #ifdef NOTYET
00846 rpmTag tagN = (Name[0] == '/' ? RPMTAG_DIRNAMES : RPMTAG_PROVIDENAME);
00847 #else
00848 rpmTag tagN = RPMTAG_PROVIDENAME;
00849 #endif
00850 rpmds P = rpmdsFromPRCO(ts->PRCO, tagN);
00851 if (rpmdsSearch(P, dep) >= 0) {
00852 rpmdsNotify(dep, _("(sysinfo provides)"), rc);
00853 goto exit;
00854 }
00855 }
00856
00857
00858
00859
00860
00861
00862 if (NSType == RPMNS_TYPE_RPMLIB) {
00863 static rpmds rpmlibP = NULL;
00864 static int oneshot = -1;
00865
00866 if (oneshot)
00867 oneshot = rpmdsRpmlib(&rpmlibP, NULL);
00868 if (rpmlibP == NULL)
00869 goto unsatisfied;
00870
00871 if (rpmdsSearch(rpmlibP, dep) >= 0) {
00872 rpmdsNotify(dep, _("(rpmlib provides)"), rc);
00873 goto exit;
00874 }
00875 goto unsatisfied;
00876 }
00877
00878 if (NSType == RPMNS_TYPE_CPUINFO) {
00879 static rpmds cpuinfoP = NULL;
00880 static int oneshot = -1;
00881
00882 if (oneshot)
00883 oneshot = rpmdsCpuinfo(&cpuinfoP, NULL);
00884 if (cpuinfoP == NULL)
00885 goto unsatisfied;
00886
00887 if (rpmdsSearch(cpuinfoP, dep) >= 0) {
00888 rpmdsNotify(dep, _("(cpuinfo provides)"), rc);
00889 goto exit;
00890 }
00891 goto unsatisfied;
00892 }
00893
00894 if (NSType == RPMNS_TYPE_GETCONF) {
00895 static rpmds getconfP = NULL;
00896 static int oneshot = -1;
00897
00898 if (oneshot)
00899 oneshot = rpmdsGetconf(&getconfP, NULL);
00900 if (getconfP == NULL)
00901 goto unsatisfied;
00902
00903 if (rpmdsSearch(getconfP, dep) >= 0) {
00904 rpmdsNotify(dep, _("(getconf provides)"), rc);
00905 goto exit;
00906 }
00907 goto unsatisfied;
00908 }
00909
00910 if (NSType == RPMNS_TYPE_UNAME) {
00911 static rpmds unameP = NULL;
00912 static int oneshot = -1;
00913
00914 if (oneshot)
00915 oneshot = rpmdsUname(&unameP, NULL);
00916 if (unameP == NULL)
00917 goto unsatisfied;
00918
00919 if (rpmdsSearch(unameP, dep) >= 0) {
00920 rpmdsNotify(dep, _("(uname provides)"), rc);
00921 goto exit;
00922 }
00923 goto unsatisfied;
00924 }
00925
00926 if (NSType == RPMNS_TYPE_SONAME) {
00927 rpmds sonameP = NULL;
00928 rpmPRCO PRCO = rpmdsNewPRCO(NULL);
00929 char * fn = strcpy(alloca(strlen(Name)+1), Name);
00930 int flags = 0;
00931 rpmds ds;
00932
00933
00934 if (*fn != '/')
00935 goto unsatisfied;
00936 fn[strlen(fn)-1] = '\0';
00937
00938
00939 xx = rpmdsELF(fn, flags, rpmdsMergePRCO, PRCO);
00940 sonameP = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
00941 if (!(xx == 0 && sonameP != NULL))
00942 goto unsatisfied;
00943
00944
00945 ds = rpmdsSingle(rpmdsTagN(dep), rpmdsEVR(dep), "", Flags);
00946 xx = rpmdsSearch(sonameP, ds);
00947 ds = rpmdsFree(ds);
00948 PRCO = rpmdsFreePRCO(PRCO);
00949
00950
00951 if (xx >= 0) {
00952 rpmdsNotify(dep, _("(soname provides)"), rc);
00953 goto exit;
00954 }
00955 goto unsatisfied;
00956 }
00957
00958
00959 if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) {
00960
00961
00962
00963
00964 if (_rpmds_nopromote)
00965 _cacheThisRC = 0;
00966 goto exit;
00967 }
00968
00969
00970 if (rpmtsGetRdb(ts) != NULL) {
00971
00972 if (Name[0] == '/') {
00973
00974
00975 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
00976 (void) rpmdbPruneIterator(mi,
00977 ts->removedPackages, ts->numRemovedPackages, 1);
00978 while ((h = rpmdbNextIterator(mi)) != NULL) {
00979 rpmdsNotify(dep, _("(db files)"), rc);
00980 mi = rpmdbFreeIterator(mi);
00981 goto exit;
00982 }
00983 mi = rpmdbFreeIterator(mi);
00984 }
00985
00986
00987 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
00988 (void) rpmdbPruneIterator(mi,
00989 ts->removedPackages, ts->numRemovedPackages, 1);
00990 while ((h = rpmdbNextIterator(mi)) != NULL) {
00991 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) {
00992 rpmdsNotify(dep, _("(db provides)"), rc);
00993 mi = rpmdbFreeIterator(mi);
00994 goto exit;
00995 }
00996 }
00997 mi = rpmdbFreeIterator(mi);
00998
00999 }
01000
01001
01002
01003
01004
01005 if (adding == 1 && retries > 0 && !(rpmtsDFlags(ts) & RPMDEPS_FLAG_NOSUGGEST)) {
01006 if (ts->solve != NULL) {
01007 xx = (*ts->solve) (ts, dep, ts->solveData);
01008 if (xx == 0)
01009 goto exit;
01010 if (xx == -1) {
01011 retries--;
01012 rpmalMakeIndex(ts->addedPackages);
01013 goto retry;
01014 }
01015 }
01016 }
01017
01018
01019 unsatisfied:
01020 if (Flags & RPMSENSE_MISSINGOK) {
01021 rc = 0;
01022 rpmdsNotify(dep, _("(hint skipped)"), rc);
01023 } else {
01024 rc = 1;
01025 rpmdsNotify(dep, NULL, rc);
01026 }
01027
01028 exit:
01029
01030
01031
01032 if (_cacheDependsRC && _cacheThisRC) {
01033 dbiIndex dbi;
01034 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
01035 if (dbi == NULL) {
01036 _cacheDependsRC = 0;
01037 } else {
01038 const char * DNEVR;
01039 xx = 0;
01040
01041 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
01042 DBC * dbcursor = NULL;
01043 size_t DNEVRlen = strlen(DNEVR);
01044
01045 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, DB_WRITECURSOR);
01046
01047 memset(key, 0, sizeof(*key));
01048 key->data = (void *) DNEVR;
01049 key->size = DNEVRlen;
01050 memset(data, 0, sizeof(*data));
01051 data->data = &rc;
01052 data->size = sizeof(rc);
01053
01054
01055 xx = dbiPut(dbi, dbcursor, key, data, 0);
01056
01057 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
01058 }
01059
01060 if (xx)
01061 _cacheDependsRC = 0;
01062 }
01063 }
01064
01065 return rpmdsNegateRC(dep, rc);
01066 }
01067
01081 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA,
01082 rpmds requires,
01083 rpmds conflicts,
01084 rpmds dirnames,
01085 rpmds linktos,
01086 const char * depName, uint_32 tscolor, int adding)
01087
01088
01089
01090
01091 {
01092 rpmps ps = rpmtsProblems(ts);
01093 uint_32 dscolor;
01094 const char * Name;
01095 int rc;
01096 int ourrc = 0;
01097
01098 requires = rpmdsInit(requires);
01099 if (requires != NULL)
01100 while (!ourrc && rpmdsNext(requires) >= 0) {
01101
01102 if ((Name = rpmdsN(requires)) == NULL)
01103 continue;
01104
01105
01106 if (depName != NULL && strcmp(depName, Name))
01107 continue;
01108
01109
01110 dscolor = rpmdsColor(requires);
01111 if (tscolor && dscolor && !(tscolor & dscolor))
01112 continue;
01113
01114 rc = unsatisfiedDepend(ts, requires, adding);
01115
01116 switch (rc) {
01117 case 0:
01118 break;
01119 case 1:
01120 { fnpyKey * suggestedKeys = NULL;
01121
01122
01123 if (ts->availablePackages != NULL) {
01124 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
01125 requires, NULL);
01126 }
01127
01128
01129 rpmdsProblem(ps, pkgNEVRA, requires, suggestedKeys, adding);
01130
01131 }
01132 break;
01133 case 2:
01134 default:
01135 ourrc = 1;
01136 break;
01137 }
01138 }
01139
01140 conflicts = rpmdsInit(conflicts);
01141 if (conflicts != NULL)
01142 while (!ourrc && rpmdsNext(conflicts) >= 0) {
01143
01144 if ((Name = rpmdsN(conflicts)) == NULL)
01145 continue;
01146
01147
01148 if (depName != NULL && strcmp(depName, Name))
01149 continue;
01150
01151
01152 dscolor = rpmdsColor(conflicts);
01153 if (tscolor && dscolor && !(tscolor & dscolor))
01154 continue;
01155
01156 rc = unsatisfiedDepend(ts, conflicts, adding);
01157
01158
01159 switch (rc) {
01160 case 0:
01161 rpmdsProblem(ps, pkgNEVRA, conflicts, NULL, adding);
01162 break;
01163 case 1:
01164 break;
01165 case 2:
01166 default:
01167 ourrc = 1;
01168 break;
01169 }
01170 }
01171
01172 dirnames = rpmdsInit(dirnames);
01173 if (dirnames != NULL)
01174 while (!ourrc && rpmdsNext(dirnames) >= 0) {
01175
01176 if ((Name = rpmdsN(dirnames)) == NULL)
01177 continue;
01178
01179
01180 if (depName != NULL && strcmp(depName, Name))
01181 continue;
01182
01183
01184 dscolor = rpmdsColor(dirnames);
01185 if (tscolor && dscolor && !(tscolor & dscolor))
01186 continue;
01187
01188 rc = unsatisfiedDepend(ts, dirnames, adding);
01189
01190 switch (rc) {
01191 case 0:
01192 break;
01193 case 1:
01194 { fnpyKey * suggestedKeys = NULL;
01195
01196
01197 if (ts->availablePackages != NULL) {
01198 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
01199 dirnames, NULL);
01200 }
01201
01202
01203 rpmdsProblem(ps, pkgNEVRA, dirnames, suggestedKeys, adding);
01204
01205 }
01206 break;
01207 case 2:
01208 default:
01209 ourrc = 1;
01210 break;
01211 }
01212 }
01213
01214 linktos = rpmdsInit(linktos);
01215 if (linktos != NULL)
01216 while (!ourrc && rpmdsNext(linktos) >= 0) {
01217
01218 if ((Name = rpmdsN(linktos)) == NULL)
01219 continue;
01220 if (*Name == '\0')
01221 continue;
01222
01223
01224 if (depName != NULL && strcmp(depName, Name))
01225 continue;
01226
01227
01228 dscolor = rpmdsColor(linktos);
01229 if (tscolor && dscolor && !(tscolor & dscolor))
01230 continue;
01231
01232 rc = unsatisfiedDepend(ts, linktos, adding);
01233
01234 switch (rc) {
01235 case 0:
01236 break;
01237 case 1:
01238 { fnpyKey * suggestedKeys = NULL;
01239
01240
01241 if (ts->availablePackages != NULL) {
01242 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
01243 linktos, NULL);
01244 }
01245
01246
01247 rpmdsProblem(ps, pkgNEVRA, linktos, suggestedKeys, adding);
01248
01249 }
01250 break;
01251 case 2:
01252 default:
01253 ourrc = 1;
01254 break;
01255 }
01256 }
01257
01258 ps = rpmpsFree(ps);
01259 return ourrc;
01260 }
01261
01272 static int checkPackageSet(rpmts ts, const char * depName,
01273 rpmdbMatchIterator mi, int adding)
01274
01275
01276 {
01277 rpmdepFlags depFlags = rpmtsDFlags(ts);
01278 uint_32 tscolor = rpmtsColor(ts);
01279 int scareMem = 0;
01280 Header h;
01281 int ec = 0;
01282
01283 (void) rpmdbPruneIterator(mi,
01284 ts->removedPackages, ts->numRemovedPackages, 1);
01285 while ((h = rpmdbNextIterator(mi)) != NULL) {
01286 const char * pkgNEVRA;
01287 rpmds requires = NULL;
01288 rpmds conflicts = NULL;
01289 rpmds dirnames = NULL;
01290 rpmds linktos = NULL;
01291 int rc;
01292
01293 pkgNEVRA = hGetNEVRA(h, NULL);
01294 if (!(depFlags & RPMDEPS_FLAG_NOREQUIRES))
01295 requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
01296 if (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS))
01297 conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
01298 if (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS))
01299 dirnames = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem);
01300 if (!(depFlags & RPMDEPS_FLAG_NOLINKTOS))
01301 linktos = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem);
01302
01303 (void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
01304 (void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote);
01305 (void) rpmdsSetNoPromote(dirnames, _rpmds_nopromote);
01306 (void) rpmdsSetNoPromote(linktos, _rpmds_nopromote);
01307
01308 rc = checkPackageDeps(ts, pkgNEVRA,
01309 requires, conflicts, dirnames, linktos,
01310 depName, tscolor, adding);
01311
01312 linktos = rpmdsFree(linktos);
01313 dirnames = rpmdsFree(dirnames);
01314 conflicts = rpmdsFree(conflicts);
01315 requires = rpmdsFree(requires);
01316 pkgNEVRA = _free(pkgNEVRA);
01317
01318 if (rc) {
01319 ec = 1;
01320 break;
01321 }
01322 }
01323 mi = rpmdbFreeIterator(mi);
01324
01325 return ec;
01326 }
01327
01334 static int checkDependentPackages(rpmts ts, const char * depName)
01335
01336
01337 {
01338 int rc = 0;
01339
01340
01341 if (rpmtsGetRdb(ts) != NULL) {
01342 rpmdbMatchIterator mi;
01343 mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, depName, 0);
01344 rc = checkPackageSet(ts, depName, mi, 0);
01345 }
01346 return rc;
01347 }
01348
01355 static int checkDependentConflicts(rpmts ts, const char * depName)
01356
01357
01358 {
01359 int rc = 0;
01360
01361
01362 if (rpmtsGetRdb(ts) != NULL) {
01363 rpmdbMatchIterator mi;
01364 mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, depName, 0);
01365 rc = checkPackageSet(ts, depName, mi, 1);
01366 }
01367
01368 return rc;
01369 }
01370
01371 struct badDeps_s {
01372
01373 const char * pname;
01374
01375 const char * qname;
01376 };
01377
01378 #ifdef REFERENCE
01379 static struct badDeps_s {
01380 const char * pname;
01381 const char * qname;
01382 } badDeps[] = {
01383 { "libtermcap", "bash" },
01384 { "modutils", "vixie-cron" },
01385 { "ypbind", "yp-tools" },
01386 { "ghostscript-fonts", "ghostscript" },
01387
01388 { "libgnomeprint15", "gnome-print" },
01389 { "nautilus", "nautilus-mozilla" },
01390
01391 { "arts", "kdelibs-sound" },
01392
01393 { "pango-gtkbeta-devel", "pango-gtkbeta" },
01394 { "XFree86", "Mesa" },
01395 { "compat-glibc", "db2" },
01396 { "compat-glibc", "db1" },
01397 { "pam", "initscripts" },
01398 { "initscripts", "sysklogd" },
01399
01400 { "egcs-c++", "libstdc++" },
01401
01402 { "pilot-link-devel", "pilot-link" },
01403
01404 { "pam", "pamconfig" },
01405 { NULL, NULL }
01406 };
01407 #else
01408
01409 static int badDepsInitialized = 0;
01410
01411
01412 static struct badDeps_s * badDeps = NULL;
01413 #endif
01414
01417
01418 static void freeBadDeps(void)
01419
01420
01421 {
01422 if (badDeps) {
01423 struct badDeps_s * bdp;
01424 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++)
01425 bdp->pname = _free(bdp->pname);
01426 badDeps = _free(badDeps);
01427 }
01428 badDepsInitialized = 0;
01429 }
01430
01431
01440
01441 static int ignoreDep(const rpmts ts, const rpmte p, const rpmte q)
01442
01443
01444
01445
01446 {
01447 struct badDeps_s * bdp;
01448
01449 if (!badDepsInitialized) {
01450 char * s = rpmExpand("%{?_dependency_whiteout}", NULL);
01451 const char ** av = NULL;
01452 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA;
01453 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS))
01454 ? RPMMESS_WARNING : RPMMESS_DEBUG;
01455 int ac = 0;
01456 int i;
01457
01458 if (s != NULL && *s != '\0'
01459 && !(i = poptParseArgvString(s, &ac, (const char ***)&av))
01460 && ac > 0 && av != NULL)
01461 {
01462 bdp = badDeps = xcalloc(ac+1, sizeof(*badDeps));
01463 for (i = 0; i < ac; i++, bdp++) {
01464 char * pname, * qname;
01465
01466 if (av[i] == NULL)
01467 break;
01468 pname = xstrdup(av[i]);
01469 if ((qname = strchr(pname, '>')) != NULL)
01470 *qname++ = '\0';
01471 bdp->pname = pname;
01472
01473 bdp->qname = qname;
01474
01475 rpmMessage(msglvl,
01476 _("ignore package name relation(s) [%d]\t%s -> %s\n"),
01477 i, bdp->pname, (bdp->qname ? bdp->qname : "???"));
01478 }
01479 bdp->pname = NULL;
01480 bdp->qname = NULL;
01481 }
01482 av = _free(av);
01483 s = _free(s);
01484 badDepsInitialized++;
01485 }
01486
01487
01488 if (badDeps != NULL)
01489 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++) {
01490 if (!strcmp(rpmteN(p), bdp->pname) && !strcmp(rpmteN(q), bdp->qname))
01491 return 1;
01492 }
01493 return 0;
01494
01495 }
01496
01497
01503 static void markLoop( tsortInfo tsi, rpmte q)
01504
01505
01506
01507 {
01508 rpmte p;
01509
01510
01511 while (tsi != NULL && (p = tsi->tsi_suc) != NULL) {
01512 tsi = tsi->tsi_next;
01513 if (rpmteTSI(p)->tsi_chain != NULL)
01514 continue;
01515
01516 rpmteTSI(p)->tsi_chain = q;
01517
01518 if (rpmteTSI(p)->tsi_next != NULL)
01519 markLoop(rpmteTSI(p)->tsi_next, p);
01520 }
01521
01522 }
01523
01524
01525
01526
01527
01528
01529 static inline const char * identifyDepend(int_32 f)
01530
01531 {
01532 f = _notpre(f);
01533 if (f & RPMSENSE_SCRIPT_PRE)
01534 return "Requires(pre):";
01535 if (f & RPMSENSE_SCRIPT_POST)
01536 return "Requires(post):";
01537 if (f & RPMSENSE_SCRIPT_PREUN)
01538 return "Requires(preun):";
01539 if (f & RPMSENSE_SCRIPT_POSTUN)
01540 return "Requires(postun):";
01541 if (f & RPMSENSE_SCRIPT_VERIFY)
01542 return "Requires(verify):";
01543 if (f & RPMSENSE_MISSINGOK)
01544 return "Requires(hint):";
01545 if (f & RPMSENSE_FIND_REQUIRES)
01546 return "Requires(auto):";
01547 return "Requires:";
01548 }
01549
01562
01563
01564 static const char *
01565 zapRelation(rpmte q, rpmte p,
01566 int zap, int * nzaps, int msglvl)
01567
01568
01569 {
01570 rpmds requires;
01571 tsortInfo tsi_prev;
01572 tsortInfo tsi;
01573 const char *dp = NULL;
01574
01575 for (tsi_prev = rpmteTSI(q), tsi = rpmteTSI(q)->tsi_next;
01576 tsi != NULL;
01577
01578
01579 tsi_prev = tsi, tsi = tsi->tsi_next)
01580
01581 {
01582 int_32 Flags;
01583
01584
01585 if (tsi->tsi_suc != p)
01586 continue;
01587
01588
01589 requires = rpmteDS(p, tsi->tsi_tagn);
01590 if (requires == NULL) continue;
01591
01592 (void) rpmdsSetIx(requires, tsi->tsi_reqx);
01593
01594 Flags = rpmdsFlags(requires);
01595
01596 dp = rpmdsNewDNEVR( identifyDepend(Flags), requires);
01597
01598
01599
01600
01601
01602 if (zap) {
01603 rpmMessage(msglvl,
01604 _("removing %s \"%s\" from tsort relations.\n"),
01605 (rpmteNEVRA(p) ? rpmteNEVRA(p) : "???"), dp);
01606 rpmteTSI(p)->tsi_count--;
01607 if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next;
01608 tsi->tsi_next = NULL;
01609 tsi->tsi_suc = NULL;
01610 tsi = _free(tsi);
01611 if (nzaps)
01612 (*nzaps)++;
01613 if (zap)
01614 zap--;
01615 }
01616
01617
01618 break;
01619 }
01620 return dp;
01621 }
01622
01623
01624
01633
01634 static inline int addRelation(rpmts ts,
01635 rpmte p,
01636 unsigned char * selected,
01637 rpmds requires)
01638
01639
01640
01641 {
01642 rpmtsi qi; rpmte q;
01643 tsortInfo tsi;
01644 nsType NSType = rpmdsNSType(requires);
01645 fnpyKey key;
01646 int teType = rpmteType(p);
01647 alKey pkgKey;
01648 int i = 0;
01649 rpmal al = (teType == TR_ADDED ? ts->addedPackages : ts->erasedPackages);
01650
01651
01652 switch (NSType) {
01653 case RPMNS_TYPE_RPMLIB:
01654 case RPMNS_TYPE_CPUINFO:
01655 case RPMNS_TYPE_GETCONF:
01656 case RPMNS_TYPE_UNAME:
01657 case RPMNS_TYPE_SONAME:
01658 case RPMNS_TYPE_ACCESS:
01659 case RPMNS_TYPE_USER:
01660 case RPMNS_TYPE_GROUP:
01661 case RPMNS_TYPE_MOUNTED:
01662 case RPMNS_TYPE_DISKSPACE:
01663 case RPMNS_TYPE_DIGEST:
01664 case RPMNS_TYPE_GNUPG:
01665 case RPMNS_TYPE_MACRO:
01666 case RPMNS_TYPE_ENVVAR:
01667 case RPMNS_TYPE_RUNNING:
01668 return 0;
01669 break;
01670 default:
01671 break;
01672 }
01673
01674 { const char * Name = rpmdsN(requires);
01675
01676
01677 if (Name == NULL || !strncmp(Name, "config(", sizeof("config(")-1))
01678 return 0;
01679 }
01680
01681 pkgKey = RPMAL_NOMATCH;
01682 key = rpmalSatisfiesDepend(al, requires, &pkgKey);
01683
01684
01685 if (pkgKey == RPMAL_NOMATCH)
01686 return 0;
01687
01688
01689
01690 if (teType == TR_REMOVED)
01691 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages);
01692
01693 for (qi = rpmtsiInit(ts), i = 0; (q = rpmtsiNext(qi, 0)) != NULL; i++) {
01694 if (pkgKey == rpmteAddedKey(q))
01695 break;
01696 }
01697 qi = rpmtsiFree(qi);
01698 if (q == NULL || i >= ts->orderCount)
01699 return 0;
01700
01701
01702 if (teType == TR_ADDED && ignoreDep(ts, p, q))
01703 return 0;
01704
01705
01706
01707 if (selected[i] != 0)
01708 return 0;
01709
01710
01711 selected[i] = 1;
01712
01713
01714
01715 rpmteTSI(p)->tsi_count++;
01716
01717 if (rpmteDepth(p) <= rpmteDepth(q))
01718 (void) rpmteSetDepth(p, (rpmteDepth(q) + 1));
01719 if (rpmteDepth(p) > ts->maxDepth)
01720 ts->maxDepth = rpmteDepth(p);
01721
01722 tsi = xcalloc(1, sizeof(*tsi));
01723 tsi->tsi_suc = p;
01724
01725 tsi->tsi_tagn = rpmdsTagN(requires);
01726 tsi->tsi_reqx = rpmdsIx(requires);
01727
01728 tsi->tsi_next = rpmteTSI(q)->tsi_next;
01729 rpmteTSI(q)->tsi_next = tsi;
01730 rpmteTSI(q)->tsi_qcnt++;
01731 return 0;
01732 }
01733
01734
01741 static int orderListIndexCmp(const void * one, const void * two)
01742 {
01743
01744 long a = (long) ((const orderListIndex)one)->pkgKey;
01745 long b = (long) ((const orderListIndex)two)->pkgKey;
01746
01747 return (a - b);
01748 }
01749
01757
01758
01759 static void addQ( rpmte p,
01760 rpmte * qp,
01761 rpmte * rp,
01762 uint_32 prefcolor)
01763
01764 {
01765 rpmte q, qprev;
01766
01767
01768 rpmteTSI(p)->tsi_queued = 1;
01769
01770 if ((*rp) == NULL) {
01771
01772 (*rp) = (*qp) = p;
01773
01774 return;
01775 }
01776
01777
01778 for (qprev = NULL, q = (*qp);
01779 q != NULL;
01780 qprev = q, q = rpmteTSI(q)->tsi_suc)
01781 {
01782
01783 if (rpmteColor(p) != prefcolor && rpmteColor(p) != rpmteColor(q))
01784 continue;
01785
01786
01787 if (rpmteType(p) == TR_REMOVED && rpmteType(p) != rpmteType(q))
01788 continue;
01789 if (rpmteTSI(q)->tsi_qcnt <= rpmteTSI(p)->tsi_qcnt)
01790 break;
01791 }
01792
01793 if (qprev == NULL) {
01794 rpmteTSI(p)->tsi_suc = q;
01795
01796 (*qp) = p;
01797
01798 } else if (q == NULL) {
01799 rpmteTSI(qprev)->tsi_suc = p;
01800
01801 (*rp) = p;
01802
01803 } else {
01804 rpmteTSI(p)->tsi_suc = q;
01805 rpmteTSI(qprev)->tsi_suc = p;
01806 }
01807 }
01808
01809
01810
01811
01812 #ifdef NOTYET
01813 static uint32_t _autobits = _notpre(_ALL_REQUIRES_MASK);
01814 #define isAuto(_x) ((_x) & _autobits)
01815 #else
01816 static uint32_t _autobits = 0xffffffff;
01817 #define isAuto(_x) (1)
01818 #endif
01819
01820
01821 int rpmtsOrder(rpmts ts)
01822 {
01823 rpmds requires;
01824 int_32 Flags;
01825 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA;
01826 uint_32 prefcolor = rpmtsPrefColor(ts);
01827 rpmtsi pi; rpmte p;
01828 rpmtsi qi; rpmte q;
01829 rpmtsi ri; rpmte r;
01830 tsortInfo tsi;
01831 tsortInfo tsi_next;
01832 alKey * ordering;
01833 int orderingCount = 0;
01834 unsigned char * selected = alloca(sizeof(*selected) * (ts->orderCount + 1));
01835 int loopcheck;
01836 rpmte * newOrder;
01837 int newOrderCount = 0;
01838 orderListIndex orderList;
01839 int numOrderList;
01840 int npeer = 128;
01841 int * peer = memset(alloca(npeer*sizeof(*peer)), 0, (npeer*sizeof(*peer)));
01842 int nrescans = 10;
01843 int _printed = 0;
01844 char deptypechar;
01845 size_t tsbytes;
01846 int oType = 0;
01847 int treex;
01848 int depth;
01849 int breadth;
01850 int qlen;
01851 int i, j;
01852
01853 #ifdef DYING
01854 rpmalMakeIndex(ts->addedPackages);
01855 #endif
01856
01857
01858 pi = rpmtsiInit(ts);
01859 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
01860 alKey pkgKey;
01861 fnpyKey key;
01862 uint_32 tscolor = rpmtsColor(ts);
01863 pkgKey = RPMAL_NOMATCH;
01864
01865 key = (fnpyKey) p;
01866
01867 pkgKey = rpmalAdd(&ts->erasedPackages, pkgKey, key,
01868 rpmteDS(p, RPMTAG_PROVIDENAME),
01869 rpmteFI(p, RPMTAG_BASENAMES), tscolor);
01870
01871 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages);
01872 (void) rpmteSetAddedKey(p, pkgKey);
01873 }
01874 pi = rpmtsiFree(pi);
01875 rpmalMakeIndex(ts->erasedPackages);
01876
01877 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
01878
01879
01880 if (oType == 0)
01881 numOrderList = ts->orderCount;
01882 else {
01883 numOrderList = 0;
01884 if (oType & TR_ADDED)
01885 numOrderList += ts->numAddedPackages;
01886 if (oType & TR_REMOVED)
01887 numOrderList += ts->numRemovedPackages;
01888 }
01889 ordering = alloca(sizeof(*ordering) * (numOrderList + 1));
01890 loopcheck = numOrderList;
01891 tsbytes = 0;
01892
01893 pi = rpmtsiInit(ts);
01894 while ((p = rpmtsiNext(pi, oType)) != NULL)
01895 rpmteNewTSI(p);
01896 pi = rpmtsiFree(pi);
01897
01898
01899 rpmMessage(RPMMESS_DEBUG, _("========== recording tsort relations\n"));
01900 pi = rpmtsiInit(ts);
01901 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01902
01903 memset(selected, 0, sizeof(*selected) * ts->orderCount);
01904
01905 if ((requires = rpmteDS(p, RPMTAG_REQUIRENAME)) != NULL) {
01906
01907
01908 selected[rpmtsiOc(pi)] = 1;
01909
01910
01911
01912
01913 requires = rpmdsInit(requires);
01914 if (requires != NULL)
01915 while (rpmdsNext(requires) >= 0) {
01916
01917 Flags = rpmdsFlags(requires);
01918 if (!isAuto(Flags))
01919 continue;
01920
01921 switch (rpmteType(p)) {
01922 case TR_REMOVED:
01923
01924 if (!isErasePreReq(Flags))
01925 continue;
01926 break;
01927 case TR_ADDED:
01928
01929 if (!isInstallPreReq(Flags))
01930 continue;
01931 break;
01932 }
01933
01934
01935 (void) addRelation(ts, p, selected, requires);
01936
01937 }
01938
01939
01940 requires = rpmdsInit(requires);
01941 if (requires != NULL)
01942 while (rpmdsNext(requires) >= 0) {
01943
01944 Flags = rpmdsFlags(requires);
01945 if (!isAuto(Flags))
01946 continue;
01947
01948 switch (rpmteType(p)) {
01949 case TR_REMOVED:
01950
01951 if (isErasePreReq(Flags))
01952 continue;
01953 break;
01954 case TR_ADDED:
01955
01956 if (isInstallPreReq(Flags))
01957 continue;
01958 break;
01959 }
01960
01961
01962 (void) addRelation(ts, p, selected, requires);
01963
01964 }
01965 }
01966
01967 if (_autobits != 0xffffffff)
01968 {
01969
01970
01971 requires = rpmdsInit(rpmteDS(p, RPMTAG_DIRNAMES));
01972 if (requires != NULL)
01973 while (rpmdsNext(requires) >= 0) {
01974
01975
01976 (void) addRelation(ts, p, selected, requires);
01977
01978 }
01979
01980
01981 requires = rpmdsInit(rpmteDS(p, RPMTAG_FILELINKTOS));
01982 if (requires != NULL)
01983 while (rpmdsNext(requires) >= 0) {
01984
01985
01986 (void) addRelation(ts, p, selected, requires);
01987
01988 }
01989 }
01990
01991 }
01992 pi = rpmtsiFree(pi);
01993
01994
01995 treex = 0;
01996 pi = rpmtsiInit(ts);
01997 while ((p = rpmtsiNext(pi, oType)) != NULL) {
01998 int npreds;
01999
02000 npreds = rpmteTSI(p)->tsi_count;
02001
02002 (void) rpmteSetNpreds(p, npreds);
02003 (void) rpmteSetDepth(p, 0);
02004
02005 if (npreds == 0) {
02006 treex++;
02007 (void) rpmteSetTree(p, treex);
02008 (void) rpmteSetBreadth(p, treex);
02009 } else
02010 (void) rpmteSetTree(p, -1);
02011 #ifdef UNNECESSARY
02012 (void) rpmteSetParent(p, NULL);
02013 #endif
02014
02015 }
02016 pi = rpmtsiFree(pi);
02017 ts->ntrees = treex;
02018
02019
02020 rpmMessage(RPMMESS_DEBUG, _("========== tsorting packages (order, #predecessors, #succesors, tree, Ldepth, Rbreadth)\n"));
02021
02022 rescan:
02023 if (pi != NULL) pi = rpmtsiFree(pi);
02024 q = r = NULL;
02025 qlen = 0;
02026 pi = rpmtsiInit(ts);
02027 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02028
02029
02030 if (anaconda)
02031 rpmteTSI(p)->tsi_qcnt = (ts->orderCount - rpmtsiOc(pi));
02032
02033 if (rpmteTSI(p)->tsi_count != 0)
02034 continue;
02035 rpmteTSI(p)->tsi_suc = NULL;
02036 addQ(p, &q, &r, prefcolor);
02037 qlen++;
02038 }
02039 pi = rpmtsiFree(pi);
02040
02041
02042 for (; q != NULL; q = rpmteTSI(q)->tsi_suc) {
02043
02044
02045 rpmteTSI(q)->tsi_queued = 0;
02046
02047 if (oType != 0)
02048 switch (rpmteType(q)) {
02049 case TR_ADDED:
02050 if (!(oType & TR_ADDED))
02051 continue;
02052 break;
02053 case TR_REMOVED:
02054 if (!(oType & TR_REMOVED))
02055 continue;
02056 break;
02057 default:
02058 continue;
02059 break;
02060 }
02061 deptypechar = (rpmteType(q) == TR_REMOVED ? '-' : '+');
02062
02063 treex = rpmteTree(q);
02064 depth = rpmteDepth(q);
02065 breadth = ((depth < npeer) ? peer[depth]++ : 0);
02066 (void) rpmteSetBreadth(q, breadth);
02067
02068 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%5d%5d%5d %*s%c%s\n",
02069 orderingCount, rpmteNpreds(q),
02070 rpmteTSI(q)->tsi_qcnt,
02071 treex, depth, breadth,
02072 (2 * depth), "",
02073 deptypechar,
02074 (rpmteNEVRA(q) ? rpmteNEVRA(q) : "???"));
02075
02076 (void) rpmteSetDegree(q, 0);
02077 tsbytes += rpmtePkgFileSize(q);
02078
02079 ordering[orderingCount] = rpmteAddedKey(q);
02080 orderingCount++;
02081 qlen--;
02082 loopcheck--;
02083
02084
02085 tsi_next = rpmteTSI(q)->tsi_next;
02086 rpmteTSI(q)->tsi_next = NULL;
02087 while ((tsi = tsi_next) != NULL) {
02088 tsi_next = tsi->tsi_next;
02089 tsi->tsi_next = NULL;
02090 p = tsi->tsi_suc;
02091 if (p && (--rpmteTSI(p)->tsi_count) <= 0) {
02092
02093 (void) rpmteSetTree(p, treex);
02094 (void) rpmteSetDepth(p, depth+1);
02095 (void) rpmteSetParent(p, q);
02096 (void) rpmteSetDegree(q, rpmteDegree(q)+1);
02097
02098
02099 rpmteTSI(p)->tsi_suc = NULL;
02100
02101 addQ(p, &rpmteTSI(q)->tsi_suc, &r, prefcolor);
02102
02103 qlen++;
02104 }
02105 tsi = _free(tsi);
02106 }
02107 if (!_printed && loopcheck == qlen && rpmteTSI(q)->tsi_suc != NULL) {
02108 _printed++;
02109 (void) rpmtsUnorderedSuccessors(ts, orderingCount);
02110 rpmMessage(RPMMESS_DEBUG,
02111 _("========== successors only (%d bytes)\n"), (int)tsbytes);
02112
02113
02114 tsi = rpmteTSI(q);
02115 pi = rpmtsiInit(ts);
02116 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02117
02118 if (rpmteTSI(p)->tsi_queued == 0)
02119 continue;
02120 tsi->tsi_suc = p;
02121 tsi = rpmteTSI(p);
02122 }
02123 pi = rpmtsiFree(pi);
02124 tsi->tsi_suc = NULL;
02125 }
02126 }
02127
02128
02129 if (loopcheck != 0) {
02130 int nzaps;
02131
02132
02133 nzaps = 0;
02134 qi = rpmtsiInit(ts);
02135 while ((q = rpmtsiNext(qi, oType)) != NULL) {
02136 rpmteTSI(q)->tsi_chain = NULL;
02137 rpmteTSI(q)->tsi_queued = 0;
02138
02139 if (rpmteTSI(q)->tsi_count == 0)
02140 rpmteTSI(q)->tsi_count = -1;
02141 }
02142 qi = rpmtsiFree(qi);
02143
02144
02145 qi = rpmtsiInit(ts);
02146 while ((q = rpmtsiNext(qi, oType)) != NULL) {
02147 if ((tsi = rpmteTSI(q)->tsi_next) == NULL)
02148 continue;
02149 rpmteTSI(q)->tsi_next = NULL;
02150 markLoop(tsi, q);
02151 rpmteTSI(q)->tsi_next = tsi;
02152 }
02153 qi = rpmtsiFree(qi);
02154
02155
02156 ri = rpmtsiInit(ts);
02157 while ((r = rpmtsiNext(ri, oType)) != NULL)
02158 {
02159 int printed;
02160
02161 printed = 0;
02162
02163
02164 for (q = rpmteTSI(r)->tsi_chain; q != NULL;
02165 q = rpmteTSI(q)->tsi_chain)
02166 {
02167 if (rpmteTSI(q)->tsi_queued)
02168 break;
02169 rpmteTSI(q)->tsi_queued = 1;
02170 }
02171
02172
02173 while ((p = q) != NULL && (q = rpmteTSI(p)->tsi_chain) != NULL) {
02174 const char * dp;
02175 char buf[4096];
02176 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS))
02177 ? RPMMESS_WARNING : RPMMESS_DEBUG;
02178 ;
02179
02180
02181 rpmteTSI(p)->tsi_chain = NULL;
02182
02183 if (!printed) {
02184 rpmMessage(msglvl, _("LOOP:\n"));
02185 printed = 1;
02186 }
02187
02188
02189 dp = zapRelation(q, p, 1, &nzaps, msglvl);
02190
02191
02192 buf[0] = '\0';
02193 if (rpmteNEVRA(p) != NULL)
02194 (void) stpcpy(buf, rpmteNEVRA(p));
02195 rpmMessage(msglvl, " %-40s %s\n", buf,
02196 (dp ? dp : "not found!?!"));
02197
02198 dp = _free(dp);
02199 }
02200
02201
02202 for (p = r, q = rpmteTSI(r)->tsi_chain; q != NULL;
02203 p = q, q = rpmteTSI(q)->tsi_chain)
02204 {
02205
02206 rpmteTSI(p)->tsi_chain = NULL;
02207 rpmteTSI(p)->tsi_queued = 0;
02208 }
02209 }
02210 ri = rpmtsiFree(ri);
02211
02212
02213
02214 if (nzaps && nrescans-- > 0) {
02215 rpmMessage(RPMMESS_DEBUG, _("========== continuing tsort ...\n"));
02216 goto rescan;
02217 }
02218
02219
02220 rpmMessage(RPMMESS_ERROR, _("rpmtsOrder failed, %d elements remain\n"),
02221 loopcheck);
02222
02223 #ifdef NOTYET
02224
02225 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
02226 #endif
02227
02228 return loopcheck;
02229 }
02230
02231
02232 pi = rpmtsiInit(ts);
02233 while ((p = rpmtsiNext(pi, 0)) != NULL)
02234 rpmteFreeTSI(p);
02235 pi = rpmtsiFree(pi);
02236
02237
02238
02239
02240 orderList = xcalloc(numOrderList, sizeof(*orderList));
02241 j = 0;
02242 pi = rpmtsiInit(ts);
02243 while ((p = rpmtsiNext(pi, oType)) != NULL) {
02244
02245 orderList[j].pkgKey = rpmteAddedKey(p);
02246 orderList[j].orIndex = rpmtsiOc(pi);
02247 j++;
02248 }
02249 pi = rpmtsiFree(pi);
02250
02251 qsort(orderList, numOrderList, sizeof(*orderList), orderListIndexCmp);
02252
02253
02254 newOrder = xcalloc(ts->orderCount, sizeof(*newOrder));
02255
02256
02257 for (i = 0, newOrderCount = 0; i < orderingCount; i++)
02258 {
02259 struct orderListIndex_s key;
02260 orderListIndex needle;
02261
02262 key.pkgKey = ordering[i];
02263 needle = bsearch(&key, orderList, numOrderList,
02264 sizeof(key), orderListIndexCmp);
02265 if (needle == NULL)
02266 continue;
02267
02268 j = needle->orIndex;
02269 if ((q = ts->order[j]) == NULL || needle->pkgKey == RPMAL_NOMATCH)
02270 continue;
02271
02272 newOrder[newOrderCount++] = q;
02273 ts->order[j] = NULL;
02274 }
02275
02276
02277 assert(newOrderCount == ts->orderCount);
02278
02279
02280 ts->order = _free(ts->order);
02281
02282 ts->order = newOrder;
02283 ts->orderAlloced = ts->orderCount;
02284 orderList = _free(orderList);
02285
02286 #ifdef DYING
02287 rpmtsClean(ts);
02288 #endif
02289 freeBadDeps();
02290
02291 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
02292
02293 return 0;
02294 }
02295
02296
02297 int rpmtsCheck(rpmts ts)
02298 {
02299 const char * depName = NULL;;
02300 rpmdepFlags depFlags = rpmtsDFlags(ts);
02301 uint_32 tscolor = rpmtsColor(ts);
02302 rpmdbMatchIterator mi = NULL;
02303 rpmtsi pi = NULL; rpmte p;
02304 int closeatexit = 0;
02305 int xx;
02306 int rc;
02307
02308 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
02309
02310
02311 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
02312 if ((rc = rpmtsOpenDB(ts, ts->dbmode)) != 0)
02313 goto exit;
02314 closeatexit = 1;
02315 }
02316
02317 ts->probs = rpmpsFree(ts->probs);
02318 ts->probs = rpmpsCreate();
02319
02320 rpmalMakeIndex(ts->addedPackages);
02321
02322
02323
02324
02325
02326 pi = rpmtsiInit(ts);
02327 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
02328 rpmds provides, requires, conflicts, dirnames, linktos;
02329
02330
02331 rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s/%s 0x%x\n",
02332 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02333
02334 requires = (!(depFlags & RPMDEPS_FLAG_NOREQUIRES)
02335 ? rpmteDS(p, RPMTAG_REQUIRENAME) : NULL);
02336 conflicts = (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS)
02337 ? rpmteDS(p, RPMTAG_CONFLICTNAME) : NULL);
02338 dirnames = (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS)
02339 ? rpmteDS(p, RPMTAG_DIRNAMES) : NULL);
02340 linktos = (!(depFlags & RPMDEPS_FLAG_NOLINKTOS)
02341 ? rpmteDS(p, RPMTAG_FILELINKTOS) : NULL);
02342
02343 rc = checkPackageDeps(ts, rpmteNEVRA(p),
02344 requires, conflicts, dirnames, linktos,
02345 NULL, tscolor, 1);
02346 if (rc)
02347 goto exit;
02348
02349 rc = 0;
02350 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
02351 provides = rpmdsInit(provides);
02352 if (provides != NULL)
02353 while (rpmdsNext(provides) >= 0) {
02354 depName = _free(depName);
02355 depName = xstrdup(rpmdsN(provides));
02356
02357 #ifdef NOTYET
02358 if (rpmdsNSType(provides) == RPMNS_TYPE_ENVVAR) {
02359 const char * EVR = rpmdsEVR(provides);
02360 if (rpmdsNegateRC(provides, 0))
02361 EVR = NULL;
02362 rc = envPut(depName, EVR);
02363 if (!rc)
02364 continue;
02365 break;
02366 }
02367 #endif
02368
02369
02370 if (!checkDependentConflicts(ts, depName))
02371 continue;
02372 rc = 1;
02373 break;
02374 }
02375 if (rc)
02376 goto exit;
02377 }
02378 pi = rpmtsiFree(pi);
02379
02380
02381
02382
02383 pi = rpmtsiInit(ts);
02384 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
02385 rpmds provides;
02386 rpmfi fi;
02387
02388
02389 rpmMessage(RPMMESS_DEBUG, "========== --- %s %s/%s 0x%x\n",
02390 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02391
02392
02393 rc = 0;
02394 provides = rpmteDS(p, RPMTAG_PROVIDENAME);
02395 provides = rpmdsInit(provides);
02396 if (provides != NULL)
02397 while (rpmdsNext(provides) >= 0) {
02398 depName = _free(depName);
02399 depName = xstrdup(rpmdsN(provides));
02400
02401
02402 if (!checkDependentPackages(ts, depName))
02403 continue;
02404 rc = 1;
02405 break;
02406 }
02407 if (rc)
02408 goto exit;
02409
02410 rc = 0;
02411 fi = rpmteFI(p, RPMTAG_BASENAMES);
02412 fi = rpmfiInit(fi, 0);
02413 while (rpmfiNext(fi) >= 0) {
02414 depName = _free(depName);
02415 depName = xstrdup(rpmfiFN(fi));
02416
02417 if (!checkDependentPackages(ts, depName))
02418 continue;
02419 rc = 1;
02420 break;
02421 }
02422 if (rc)
02423 goto exit;
02424 }
02425 pi = rpmtsiFree(pi);
02426
02427
02428
02429
02430 { const char * tsNEVRA = "transaction dependencies";
02431 rpmds R = rpmdsFromPRCO(ts->PRCO, RPMTAG_REQUIRENAME);
02432 rpmds C = rpmdsFromPRCO(ts->PRCO, RPMTAG_CONFLICTNAME);
02433 rpmds D = NULL;
02434 rpmds L = NULL;
02435 const char * dep = NULL;
02436 int adding = 2;
02437 tscolor = 0;
02438 rc = checkPackageDeps(ts, tsNEVRA, R, C, D, L, dep, tscolor, adding);
02439 if (rc)
02440 goto exit;
02441 }
02442
02443 rc = 0;
02444
02445 exit:
02446 mi = rpmdbFreeIterator(mi);
02447 pi = rpmtsiFree(pi);
02448 depName = _free(depName);
02449
02450 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
02451
02452
02453 if (closeatexit)
02454 xx = rpmtsCloseDB(ts);
02455 else if (_cacheDependsRC)
02456 xx = rpmdbCloseDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS);
02457
02458
02459 #ifdef NOTYET
02460
02461 { rpmps ps = rpmtsProblems(ts);
02462 if (rc || rpmpsNumProblems(ps) > 0)
02463 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
02464 ps = rpmpsFree(ps);
02465 }
02466 #endif
02467
02468 return rc;
02469 }