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