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 if (!(depFlags & RPMDEPS_FLAG_NOUPGRADE)) {
00396 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, rpmteN(p), 0);
00397 while((oh = rpmdbNextIterator(mi)) != NULL) {
00398 int lastx;
00399 rpmte q;
00400
00401
00402 ohcolor = hGetColor(oh);
00403 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
00404 continue;
00405
00406
00407 if (rpmHeadersIdentical(h, oh))
00408 continue;
00409
00410
00411 lastx = -1;
00412 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), &lastx, pkgKey);
00413 assert(lastx >= 0 && lastx < ts->orderCount);
00414 q = ts->order[lastx];
00415
00416
00417 xx = rpmteChain(p, q, oh, "Upgrades");
00418
00419
00420 rpmMessage(RPMMESS_DEBUG, _(" upgrade erases %s\n"), rpmteNEVRA(q));
00421
00422
00423 }
00424 mi = rpmdbFreeIterator(mi);
00425 }
00426
00427 if (!(depFlags & RPMDEPS_FLAG_NOOBSOLETES)) {
00428 obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME), "Obsoletes");
00429 obsoletes = rpmdsInit(obsoletes);
00430 if (obsoletes != NULL)
00431 while (rpmdsNext(obsoletes) >= 0) {
00432 const char * Name;
00433
00434 if ((Name = rpmdsN(obsoletes)) == NULL)
00435 continue;
00436
00437
00438 #if 0
00439 dscolor = rpmdsColor(obsoletes);
00440 #else
00441 dscolor = hcolor;
00442 #endif
00443
00444 if (tscolor && dscolor && !(tscolor & dscolor))
00445 continue;
00446
00447
00448 if (!strcmp(rpmteN(p), Name))
00449 continue;
00450
00451
00452 if (Name[0] == '/')
00453 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
00454 else
00455 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
00456
00457 xx = rpmdbPruneIterator(mi,
00458 ts->removedPackages, ts->numRemovedPackages, 1);
00459
00460 while((oh = rpmdbNextIterator(mi)) != NULL) {
00461 int lastx;
00462 rpmte q;
00463
00464
00465 ohcolor = hGetColor(oh);
00466
00467
00468
00469 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
00470 continue;
00471
00472
00473
00474
00475
00476 if (!(rpmdsEVR(obsoletes) == NULL
00477 || rpmdsAnyMatchesDep(oh, obsoletes, _rpmds_nopromote)))
00478 continue;
00479
00480
00481 lastx = -1;
00482 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), &lastx, pkgKey);
00483 assert(lastx >= 0 && lastx < ts->orderCount);
00484 q = ts->order[lastx];
00485
00486
00487 xx = rpmteChain(p, q, oh, "Obsoletes");
00488
00489
00490 rpmMessage(RPMMESS_DEBUG, _(" Obsoletes: %s\t\terases %s\n"),
00491 rpmdsDNEVR(obsoletes)+2, rpmteNEVRA(q));
00492
00493 }
00494 mi = rpmdbFreeIterator(mi);
00495 }
00496 obsoletes = rpmdsFree(obsoletes);
00497 }
00498
00499 ec = 0;
00500
00501 exit:
00502 pi = rpmtsiFree(pi);
00503 return ec;
00504 }
00505
00506 int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
00507 {
00508 int oc = -1;
00509 int rc = removePackage(ts, h, dboffset, &oc, RPMAL_NOMATCH);
00510 if (rc == 0 && oc >= 0 && oc < ts->orderCount)
00511 ts->teErase = ts->order[oc];
00512 else
00513 ts->teErase = NULL;
00514 return rc;
00515 }
00516
00524 static int unsatisfiedDepend(rpmts ts, rpmds dep, int adding)
00525
00526
00527
00528
00529 {
00530 DBT * key = alloca(sizeof(*key));
00531 DBT * data = alloca(sizeof(*data));
00532 rpmdbMatchIterator mi;
00533 nsType NSType;
00534 const char * Name;
00535 int_32 Flags;
00536 Header h;
00537 int _cacheThisRC = 1;
00538 int rc;
00539 int xx;
00540 int retries = 10;
00541
00542 if ((Name = rpmdsN(dep)) == NULL)
00543 return 0;
00544 Flags = rpmdsFlags(dep);
00545 NSType = rpmdsNSType(dep);
00546
00547
00548
00549
00550 if (_cacheDependsRC) {
00551 dbiIndex dbi;
00552 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
00553 if (dbi == NULL)
00554 _cacheDependsRC = 0;
00555 else {
00556 const char * DNEVR;
00557
00558 rc = -1;
00559
00560 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
00561 DBC * dbcursor = NULL;
00562 void * datap = NULL;
00563 size_t datalen = 0;
00564 size_t DNEVRlen = strlen(DNEVR);
00565
00566 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, 0);
00567
00568 memset(key, 0, sizeof(*key));
00569 key->data = (void *) DNEVR;
00570 key->size = DNEVRlen;
00571 memset(data, 0, sizeof(*data));
00572 data->data = datap;
00573 data->size = datalen;
00574
00575 xx = dbiGet(dbi, dbcursor, key, data, DB_SET);
00576
00577 DNEVR = key->data;
00578 DNEVRlen = key->size;
00579 datap = data->data;
00580 datalen = data->size;
00581
00582
00583 if (xx == 0 && datap && datalen == 4)
00584 memcpy(&rc, datap, datalen);
00585
00586 xx = dbiCclose(dbi, dbcursor, 0);
00587 }
00588
00589
00590 if (rc >= 0) {
00591 rpmdsNotify(dep, _("(cached)"), rc);
00592 return rpmdsNegateRC(dep, rc);
00593 }
00594 }
00595 }
00596
00597 retry:
00598 rc = 0;
00599
00600
00601 if (NSType == RPMNS_TYPE_FUNCTION) {
00602 xx = rpmExpandNumeric(Name);
00603 rc = (xx ? 0 : 1);
00604 if (Flags & RPMSENSE_MISSINGOK)
00605 goto unsatisfied;
00606 rpmdsNotify(dep, _("(function probe)"), rc);
00607 goto exit;
00608 }
00609
00610
00611 if (NSType == RPMNS_TYPE_USER) {
00612 const char *s;
00613 uid_t uid = 0;
00614 s = Name; while (*s && xisdigit(*s)) s++;
00615
00616 if (*s)
00617 xx = unameToUid(Name, &uid);
00618 else {
00619 uid = strtol(Name, NULL, 10);
00620 xx = (uidToUname(uid) ? 0 : -1);
00621 }
00622 rc = (xx >= 0 ? 0 : 1);
00623 if (Flags & RPMSENSE_MISSINGOK)
00624 goto unsatisfied;
00625 rpmdsNotify(dep, _("(user lookup)"), rc);
00626 goto exit;
00627 }
00628 if (NSType == RPMNS_TYPE_GROUP) {
00629 const char *s;
00630 gid_t gid = 0;
00631 s = Name; while (*s && xisdigit(*s)) s++;
00632
00633 if (*s)
00634 xx = gnameToGid(Name, &gid);
00635 else {
00636 gid = strtol(Name, NULL, 10);
00637 xx = (gidToGname(gid) ? 0 : -1);
00638 }
00639 rc = (xx >= 0 ? 0 : 1);
00640 if (Flags & RPMSENSE_MISSINGOK)
00641 goto unsatisfied;
00642 rpmdsNotify(dep, _("(group lookup)"), rc);
00643 goto exit;
00644 }
00645
00646
00647 if (NSType == RPMNS_TYPE_ACCESS) {
00648 rc = rpmioAccess(Name, NULL, X_OK);
00649 if (Flags & RPMSENSE_MISSINGOK)
00650 goto unsatisfied;
00651 rpmdsNotify(dep, _("(access probe)"), rc);
00652 goto exit;
00653 }
00654
00655
00656 if (NSType == RPMNS_TYPE_MOUNTED) {
00657 const char ** fs = NULL;
00658 int nfs = 0;
00659 int i = 0;
00660
00661 xx = rpmtsInitDSI(ts);
00662 fs = ts->filesystems;
00663 nfs = ts->filesystemCount;
00664
00665 if (fs != NULL)
00666 for (i = 0; i < nfs; i++) {
00667 if (!strcmp(fs[i], Name))
00668 break;
00669 }
00670 rc = (i < nfs ? 0 : 1);
00671 if (Flags & RPMSENSE_MISSINGOK)
00672 goto unsatisfied;
00673 rpmdsNotify(dep, _("(mtab probe)"), rc);
00674 goto exit;
00675 }
00676
00677 if (NSType == RPMNS_TYPE_DISKSPACE) {
00678 size_t nb = strlen(Name);
00679 rpmDiskSpaceInfo dsi = NULL;
00680 const char ** fs = NULL;
00681 size_t fslen = 0, longest = 0;
00682 int nfs = 0;
00683 int i = 0;
00684
00685 xx = rpmtsInitDSI(ts);
00686 fs = ts->filesystems;
00687 nfs = ts->filesystemCount;
00688
00689 if (fs != NULL)
00690 for (i = 0; i < nfs; i++) {
00691 fslen = strlen(fs[i]);
00692 if (fslen > nb)
00693 continue;
00694 if (strncmp(fs[i], Name, fslen))
00695 continue;
00696 if (fslen > 1 && Name[fslen] != '/' && Name[fslen] != '\0')
00697 continue;
00698 if (fslen < longest)
00699 continue;
00700 longest = fslen;
00701 dsi = ts->dsi + i;
00702 }
00703 if (dsi == NULL)
00704 rc = 1;
00705 else {
00706 char * end = NULL;
00707 long long needed = strtoll(rpmdsEVR(dep), &end, 0);
00708
00709 if (end && *end) {
00710 if (strchr("Gg", end[0]) && strchr("Bb", end[1]) && !end[2])
00711 needed *= 1024 * 1024 * 1024;
00712 if (strchr("Mm", end[0]) && strchr("Bb", end[1]) && !end[2])
00713 needed *= 1024 * 1024;
00714 if (strchr("Kk", end[0]) && strchr("Bb", end[1]) && !end[2])
00715 needed *= 1024;
00716 } else
00717 needed *= 1024 * 1024;
00718
00719 needed = BLOCK_ROUND(needed, dsi->f_bsize);
00720 xx = (dsi->f_bavail - needed);
00721 if ((Flags & RPMSENSE_LESS) && xx < 0) rc = 0;
00722 else if ((Flags & RPMSENSE_GREATER) && xx > 0) rc = 0;
00723 else if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0;
00724 else rc = 1;
00725 }
00726 if (Flags & RPMSENSE_MISSINGOK)
00727 goto unsatisfied;
00728 rpmdsNotify(dep, _("(diskspace probe)"), rc);
00729 goto exit;
00730 }
00731
00732 if (NSType == RPMNS_TYPE_DIGEST) {
00733 const char * EVR = rpmdsEVR(dep);
00734 FD_t fd = Fopen(Name, "r");
00735
00736 rc = 1;
00737 if (fd && !Ferror(fd)) {
00738 pgpHashAlgo digestHashAlgo = PGPHASHALGO_MD5;
00739 DIGEST_CTX ctx = rpmDigestInit(digestHashAlgo, RPMDIGEST_NONE);
00740 const char * digest = NULL;
00741 size_t digestlen = 0;
00742 int asAscii = 1;
00743 size_t nbuf = 8 * BUFSIZ;
00744 char * buf = alloca(nbuf);
00745 size_t nb;
00746
00747 while ((nb = Fread(buf, sizeof(buf[0]), nbuf, fd)) > 0)
00748 xx = rpmDigestUpdate(ctx, buf, nb);
00749 xx = Fclose(fd); fd = NULL;
00750 xx = rpmDigestFinal(ctx, (void **)&digest, &digestlen, asAscii);
00751
00752 xx = (EVR && *EVR && digest && *digest) ? strcmp(EVR, digest) : -1;
00753
00754 if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0;
00755 }
00756 if (Flags & RPMSENSE_MISSINGOK)
00757 goto unsatisfied;
00758 rpmdsNotify(dep, _("(digest probe)"), rc);
00759 goto exit;
00760 }
00761
00762 if (NSType == RPMNS_TYPE_GNUPG) {
00763 static const char gnupg_pre[] = "%(%{__gpg} -qv ";
00764 static const char gnupg_post[] = " 2>/dev/null; echo $?)";
00765 const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL);
00766
00767 rc = (t && t[0] == '0') ? 0 : 1;
00768 t = _free(t);
00769 if (Flags & RPMSENSE_MISSINGOK)
00770 goto unsatisfied;
00771 rpmdsNotify(dep, _("(gnupg probe)"), rc);
00772 goto exit;
00773 }
00774
00775 if (NSType == RPMNS_TYPE_MACRO) {
00776 static const char macro_pre[] = "%{?";
00777 static const char macro_post[] = ":0}";
00778 const char * a = rpmExpand(macro_pre, Name, macro_post, NULL);
00779
00780 rc = (a && a[0] == '0') ? 0 : 1;
00781 a = _free(a);
00782 if (Flags & RPMSENSE_MISSINGOK)
00783 goto unsatisfied;
00784 rpmdsNotify(dep, _("(macro probe)"), rc);
00785 goto exit;
00786 }
00787
00788 if (NSType == RPMNS_TYPE_ENVVAR) {
00789 const char * a = envGet(Name);
00790 const char * b = rpmdsEVR(dep);
00791
00792
00793 if (!(b && *b))
00794 rc = (!(a && *a));
00795 else {
00796 int sense = (a && *a) ? strcmp(a, b) : -1;
00797
00798 if ((Flags & RPMSENSE_SENSEMASK) == RPMSENSE_NOTEQUAL)
00799 rc = (sense == 0);
00800 else if (sense < 0 && (Flags & RPMSENSE_LESS))
00801 rc = 0;
00802 else if (sense > 0 && (Flags & RPMSENSE_GREATER))
00803 rc = 0;
00804 else if (sense == 0 && (Flags & RPMSENSE_EQUAL))
00805 rc = 0;
00806 else
00807 rc = (sense != 0);
00808 }
00809
00810 if (Flags & RPMSENSE_MISSINGOK)
00811 goto unsatisfied;
00812 rpmdsNotify(dep, _("(envvar probe)"), rc);
00813 goto exit;
00814 }
00815
00816 if (NSType == RPMNS_TYPE_RUNNING) {
00817 char *t = NULL;
00818 pid_t pid = strtol(Name, &t, 10);
00819
00820 if (t == NULL || *t != '\0') {
00821 const char * fn = rpmGetPath("%{_varrun}/", Name, ".pid", NULL);
00822 FD_t fd = NULL;
00823
00824 if (fn && *fn != '%' && (fd = Fopen(fn, "r")) && !Ferror(fd)) {
00825 char buf[32];
00826 size_t nb = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
00827
00828 if (nb > 0)
00829 pid = strtol(buf, &t, 10);
00830 } else
00831 pid = 0;
00832 if (fd != NULL)
00833 (void) Fclose(fd);
00834 fn = _free(fn);
00835 }
00836 rc = (pid > 0 ? (kill(pid, 0) < 0 && errno == ESRCH) : 1);
00837 if (Flags & RPMSENSE_MISSINGOK)
00838 goto unsatisfied;
00839 rpmdsNotify(dep, _("(running probe)"), rc);
00840 goto exit;
00841 }
00842
00843
00844 if (!rpmioAccess("/etc/rpm/sysinfo", NULL, R_OK)) {
00845 #ifdef NOTYET
00846 rpmTag tagN = (Name[0] == '/' ? RPMTAG_DIRNAMES : RPMTAG_PROVIDENAME);
00847 #else
00848 rpmTag tagN = RPMTAG_PROVIDENAME;
00849 #endif
00850 rpmds P = rpmdsFromPRCO(ts->PRCO, tagN);
00851 if (rpmdsSearch(P, dep) >= 0) {
00852 rpmdsNotify(dep, _("(sysinfo provides)"), rc);
00853 goto exit;
00854 }
00855 }
00856
00857
00858
00859
00860
00861
00862 if (NSType == RPMNS_TYPE_RPMLIB) {
00863 static rpmds rpmlibP = NULL;
00864 static int oneshot = -1;
00865
00866 if (oneshot)
00867 oneshot = rpmdsRpmlib(&rpmlibP, NULL);
00868 if (rpmlibP == NULL)
00869 goto unsatisfied;
00870
00871 if (rpmdsSearch(rpmlibP, dep) >= 0) {
00872 rpmdsNotify(dep, _("(rpmlib provides)"), rc);
00873 goto exit;
00874 }
00875 goto unsatisfied;
00876 }
00877
00878 if (NSType == RPMNS_TYPE_CPUINFO) {
00879 static rpmds cpuinfoP = NULL;
00880 static int oneshot = -1;
00881
00882 if (oneshot)
00883 oneshot = rpmdsCpuinfo(&cpuinfoP, NULL);
00884 if (cpuinfoP == NULL)
00885 goto unsatisfied;
00886
00887 if (rpmdsSearch(cpuinfoP, dep) >= 0) {
00888 rpmdsNotify(dep, _("(cpuinfo provides)"), rc);
00889 goto exit;
00890 }
00891 goto unsatisfied;
00892 }
00893
00894 if (NSType == RPMNS_TYPE_GETCONF) {
00895 static rpmds getconfP = NULL;
00896 static int oneshot = -1;
00897
00898 if (oneshot)
00899 oneshot = rpmdsGetconf(&getconfP, NULL);
00900 if (getconfP == NULL)
00901 goto unsatisfied;
00902
00903 if (rpmdsSearch(getconfP, dep) >= 0) {
00904 rpmdsNotify(dep, _("(getconf provides)"), rc);
00905 goto exit;
00906 }
00907 goto unsatisfied;
00908 }
00909
00910 if (NSType == RPMNS_TYPE_UNAME) {
00911 static rpmds unameP = NULL;
00912 static int oneshot = -1;
00913
00914 if (oneshot)
00915 oneshot = rpmdsUname(&unameP, NULL);
00916 if (unameP == NULL)
00917 goto unsatisfied;
00918
00919 if (rpmdsSearch(unameP, dep) >= 0) {
00920 rpmdsNotify(dep, _("(uname provides)"), rc);
00921 goto exit;
00922 }
00923 goto unsatisfied;
00924 }
00925
00926 if (NSType == RPMNS_TYPE_SONAME) {
00927 rpmds sonameP = NULL;
00928 rpmPRCO PRCO = rpmdsNewPRCO(NULL);
00929 char * fn = strcpy(alloca(strlen(Name)+1), Name);
00930 int flags = 0;
00931 rpmds ds;
00932
00933
00934 if (*fn != '/')
00935 goto unsatisfied;
00936 fn[strlen(fn)-1] = '\0';
00937
00938
00939 xx = rpmdsELF(fn, flags, rpmdsMergePRCO, PRCO);
00940 sonameP = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
00941 if (!(xx == 0 && sonameP != NULL))
00942 goto unsatisfied;
00943
00944
00945 ds = rpmdsSingle(rpmdsTagN(dep), rpmdsEVR(dep), "", Flags);
00946 xx = rpmdsSearch(sonameP, ds);
00947 ds = rpmdsFree(ds);
00948 PRCO = rpmdsFreePRCO(PRCO);
00949
00950
00951 if (xx >= 0) {
00952 rpmdsNotify(dep, _("(soname provides)"), rc);
00953 goto exit;
00954 }
00955 goto unsatisfied;
00956 }
00957
00958
00959 if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) {
00960
00961
00962
00963
00964 if (_rpmds_nopromote)
00965 _cacheThisRC = 0;
00966 goto exit;
00967 }
00968
00969
00970 if (rpmtsGetRdb(ts) != NULL) {
00971
00972 if (Name[0] == '/') {
00973
00974
00975 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
00976 (void) rpmdbPruneIterator(mi,
00977 ts->removedPackages, ts->numRemovedPackages, 1);
00978 while ((h = rpmdbNextIterator(mi)) != NULL) {
00979 rpmdsNotify(dep, _("(db files)"), rc);
00980 mi = rpmdbFreeIterator(mi);
00981 goto exit;
00982 }
00983 mi = rpmdbFreeIterator(mi);
00984 }
00985
00986
00987 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
00988 (void) rpmdbPruneIterator(mi,
00989 ts->removedPackages, ts->numRemovedPackages, 1);
00990 while ((h = rpmdbNextIterator(mi)) != NULL) {
00991 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) {
00992 rpmdsNotify(dep, _("(db provides)"), rc);
00993 mi = rpmdbFreeIterator(mi);
00994 goto exit;
00995 }
00996 }
00997 mi = rpmdbFreeIterator(mi);
00998
00999 }
01000
01001
01002
01003
01004
01005 if (adding == 1 && retries > 0 && !(rpmtsDFlags(ts) & RPMDEPS_FLAG_NOSUGGEST)) {
01006 if (ts->solve != NULL) {
01007 xx = (*ts->solve) (ts, dep, ts->solveData);
01008 if (xx == 0)
01009 goto exit;
01010 if (xx == -1) {
01011 retries--;
01012 rpmalMakeIndex(ts->addedPackages);
01013 goto retry;
01014 }
01015 }
01016 }
01017
01018
01019 unsatisfied:
01020 if (Flags & RPMSENSE_MISSINGOK) {
01021 rc = 0;
01022 rpmdsNotify(dep, _("(hint skipped)"), rc);
01023 } else {
01024 rc = 1;
01025 rpmdsNotify(dep, NULL, rc);
01026 }
01027
01028 exit:
01029
01030
01031
01032 if (_cacheDependsRC && _cacheThisRC) {
01033 dbiIndex dbi;
01034 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0);
01035 if (dbi == NULL) {
01036 _cacheDependsRC = 0;
01037 } else {
01038 const char * DNEVR;
01039 xx = 0;
01040
01041 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
01042 DBC * dbcursor = NULL;
01043 size_t DNEVRlen = strlen(DNEVR);
01044
01045 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, DB_WRITECURSOR);
01046
01047 memset(key, 0, sizeof(*key));
01048 key->data = (void *) DNEVR;
01049 key->size = DNEVRlen;
01050 memset(data, 0, sizeof(*data));
01051 data->data = &rc;
01052 data->size = sizeof(rc);
01053
01054
01055 xx = dbiPut(dbi, dbcursor, key, data, 0);
01056
01057 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
01058 }
01059
01060 if (xx)
01061 _cacheDependsRC = 0;
01062 }
01063 }
01064
01065 return rpmdsNegateRC(dep, rc);
01066 }
01067
01081 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA,
01082 rpmds requires,
01083 rpmds conflicts,
01084 rpmds dirnames,
01085 rpmds linktos,
01086 const char * depName, uint_32 tscolor, int adding)
01087
01088
01089
01090