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