rpm 5.3.7
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> /* XXX fnpyKey */ 00009 #include <rpmcb.h> 00010 #include <rpmbf.h> 00011 #include <rpmmacro.h> /* XXX rpmExpand("%{_dependency_whiteout}" */ 00012 #include <envvar.h> 00013 #include <ugid.h> /* XXX user()/group() probes */ 00014 00015 #include <rpmtag.h> 00016 #define _RPMDB_INTERNAL /* XXX response cache needs dbiOpen et al. */ 00017 #include <rpmdb.h> 00018 00019 #define _RPMEVR_INTERNAL 00020 #include <rpmds.h> 00021 #include <rpmfi.h> 00022 00023 #define _RPMTE_INTERNAL 00024 #include <rpmte.h> 00025 #define _RPMTS_INTERNAL 00026 #include <rpmcli.h> /* XXX rpmcliPackagesTotal */ 00027 00028 #include "debug.h" 00029 00030 /*@access tsortInfo @*/ 00031 /*@access rpmte @*/ /* XXX for install <-> erase associate. */ 00032 /*@access rpmts @*/ 00033 /*@access rpmDiskSpaceInfo @*/ 00034 00035 #define CACHE_DEPENDENCY_RESULT 1 00036 #if defined(CACHE_DEPENDENCY_RESULT) 00037 /*@unchecked@*/ 00038 int _cacheDependsRC = CACHE_DEPENDENCY_RESULT; 00039 #endif 00040 00041 /*@observer@*/ /*@unchecked@*/ 00042 const char *rpmNAME = PACKAGE; 00043 00044 /*@observer@*/ /*@unchecked@*/ 00045 const char *rpmEVR = VERSION; 00046 00047 /*@unchecked@*/ 00048 int rpmFLAGS = RPMSENSE_EQUAL; 00049 00056 static int uintcmp(const void * a, const void * b) 00057 /*@requires maxRead(a) == 0 /\ maxRead(b) == 0 @*/ 00058 { 00059 const uint32_t * aptr = a; 00060 const uint32_t * bptr = b; 00061 int rc = (*aptr - *bptr); 00062 return rc; 00063 } 00064 00074 static int removePackage(rpmts ts, Header h, uint32_t hdrNum, 00075 /*@null@*/ int * indexp, 00076 /*@exposed@*/ /*@dependent@*/ /*@null@*/ alKey depends) 00077 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00078 /*@modifies ts, h, *indexp, rpmGlobalMacroContext, fileSystem, internalState @*/ 00079 { 00080 rpmte p; 00081 int xx; 00082 00083 /* Filter out duplicate erasures. */ 00084 if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) { 00085 uint32_t * needle = NULL; 00086 needle = bsearch(&hdrNum, ts->removedPackages, ts->numRemovedPackages, 00087 sizeof(*ts->removedPackages), uintcmp); 00088 if (needle != NULL) { 00089 /* XXX lastx should be per-call, not per-ts. */ 00090 if (indexp != NULL) 00091 *indexp = needle - ts->removedPackages; 00092 return 0; 00093 } 00094 } 00095 00096 if (ts->rbf == NULL) { 00097 static size_t nRemoves = 8192; /* XXX population estimate */ 00098 static double e = 1.0e-4; 00099 size_t m = 0; 00100 size_t k = 0; 00101 rpmbfParams(nRemoves, e, &m, &k); 00102 ts->rbf = rpmbfNew(m, k, 0); 00103 } 00104 00105 if (ts->numRemovedPackages == ts->allocedRemovedPackages) { 00106 ts->allocedRemovedPackages += ts->delta; 00107 ts->removedPackages = xrealloc(ts->removedPackages, 00108 sizeof(ts->removedPackages) * ts->allocedRemovedPackages); 00109 } 00110 00111 assert(ts->removedPackages != NULL); /* XXX can't happen. */ 00112 xx = rpmbfAdd(ts->rbf, &hdrNum, sizeof(hdrNum)); 00113 assert(xx == 0); 00114 ts->removedPackages[ts->numRemovedPackages] = hdrNum; 00115 ts->numRemovedPackages++; 00116 if (ts->numRemovedPackages > 1) 00117 qsort(ts->removedPackages, ts->numRemovedPackages, 00118 sizeof(*ts->removedPackages), uintcmp); 00119 00120 if (ts->orderCount >= ts->orderAlloced) { 00121 ts->orderAlloced += (ts->orderCount - ts->orderAlloced) + ts->delta; 00122 /*@-type +voidabstract @*/ 00123 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced); 00124 /*@=type =voidabstract @*/ 00125 } 00126 00127 p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, hdrNum, depends); 00128 ts->order[ts->orderCount] = p; 00129 ts->numErasedFiles += rpmfiFC(rpmteFI(p, RPMTAG_BASENAMES)); 00130 if (indexp != NULL) 00131 *indexp = ts->orderCount; 00132 ts->orderCount++; 00133 00134 /*@-nullstate@*/ /* XXX FIX: ts->order[] can be NULL. */ 00135 return 0; 00136 /*@=nullstate@*/ 00137 } 00138 00145 static int rpmHeadersIdentical(Header first, Header second) 00146 /*@globals internalState @*/ 00147 /*@modifies internalState @*/ 00148 { 00149 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00150 const char * one, * two; 00151 int rc = 0; 00152 int xx; 00153 00154 he->tag = RPMTAG_HDRID; 00155 xx = headerGet(first, he, 0); 00156 one = he->p.str; 00157 he->tag = RPMTAG_HDRID; 00158 xx = headerGet(second, he, 0); 00159 two = he->p.str; 00160 00161 if (one && two) 00162 rc = ((strcmp(one, two) == 0) ? 1 : 0); 00163 else if (one && !two) 00164 rc = 0; 00165 else if (!one && two) 00166 rc = 0; 00167 else { 00168 /* XXX Headers w/o digests case devolves to NEVR comparison. */ 00169 rpmds A = rpmdsThis(first, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); 00170 rpmds B = rpmdsThis(second, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); 00171 rc = rpmdsCompare(A, B); 00172 (void)rpmdsFree(A); 00173 A = NULL; 00174 (void)rpmdsFree(B); 00175 B = NULL; 00176 } 00177 one = _free(one); 00178 two = _free(two); 00179 return rc; 00180 } 00181 00182 /*@unchecked@*/ 00183 static rpmTag _upgrade_tag; 00184 /*@unchecked@*/ 00185 static rpmTag _debuginfo_tag; 00186 /*@unchecked@*/ 00187 static rpmTag _obsolete_tag; 00188 00197 static int rpmtsAddUpgrades(rpmts ts, rpmte p, rpmuint32_t hcolor, Header h) 00198 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00199 /*@modifies ts, p, rpmGlobalMacroContext, fileSystem, internalState @*/ 00200 { 00201 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00202 rpmuint32_t tscolor = rpmtsColor(ts); 00203 alKey pkgKey = rpmteAddedKey(p); 00204 rpmuint32_t ohcolor; 00205 rpmmi mi; 00206 Header oh; 00207 int xx; 00208 00209 if (_upgrade_tag == 0) { 00210 const char * t = rpmExpand("%{?_upgrade_tag}", NULL); 00211 /*@-mods@*/ 00212 _upgrade_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME); 00213 /*@=mods@*/ 00214 t = _free(t); 00215 } 00216 00217 mi = rpmtsInitIterator(ts, _upgrade_tag, rpmteN(p), 0); 00218 while((oh = rpmmiNext(mi)) != NULL) { 00219 int lastx; 00220 rpmte q; 00221 00222 /* Ignore colored packages not in our rainbow. */ 00223 ohcolor = hGetColor(oh); 00224 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor)) 00225 continue; 00226 00227 /* Snarf the original install tid & time from older package(s). */ 00228 he->tag = RPMTAG_ORIGINTID; 00229 xx = headerGet(oh, he, 0); 00230 if (xx && he->p.ui32p != NULL) { 00231 if (p->originTid[0] == 0 || p->originTid[0] > he->p.ui32p[0] 00232 || (he->c > 1 && p->originTid[0] == he->p.ui32p[0] && p->originTid[1] > he->p.ui32p[1])) 00233 { 00234 p->originTid[0] = he->p.ui32p[0]; 00235 p->originTid[1] = (he->c > 1 ? he->p.ui32p[1] : 0); 00236 } 00237 he->p.ptr = _free(he->p.ptr); 00238 } 00239 he->tag = RPMTAG_ORIGINTIME; 00240 xx = headerGet(oh, he, 0); 00241 if (xx && he->p.ui32p != NULL) { 00242 if (p->originTime[0] == 0 || p->originTime[0] > he->p.ui32p[0] 00243 || (he->c > 1 && p->originTime[0] == he->p.ui32p[0] && p->originTime[1] > he->p.ui32p[1])) 00244 { 00245 p->originTime[0] = he->p.ui32p[0]; 00246 p->originTime[1] = (he->c > 1 ? he->p.ui32p[1] : 0); 00247 } 00248 he->p.ptr = _free(he->p.ptr); 00249 } 00250 00251 #if defined(RPM_VENDOR_WINDRIVER) 00252 /* 00253 * If we're capable of installing multiple colors 00254 * but at least one of the packages are white (0), we 00255 * further verify the arch is the same (or compatible) to trigger an upgrade 00256 * we do have a special case to allow upgrades of noarch w/ a arch package 00257 */ 00258 if (tscolor && (!hcolor || !ohcolor)) { 00259 const char * arch; 00260 const char * oharch; 00261 he->tag = RPMTAG_ARCH; 00262 xx = headerGet(h, he, 0); 00263 arch = (xx && he->p.str != NULL ? he->p.str : NULL); 00264 he->tag = RPMTAG_ARCH; 00265 xx = headerGet(oh, he, 0); 00266 oharch = (xx && he->p.str != NULL ? he->p.str : NULL); 00267 if (arch != NULL && oharch != NULL) { 00268 if (strcmp("noarch", arch) || strcmp("noarch", oharch)) { 00269 if (!_isCompatibleArch(arch, oharch)) { 00270 arch = _free(arch); 00271 oharch = _free(oharch); 00272 continue; 00273 } 00274 } 00275 } 00276 arch = _free(arch); 00277 oharch = _free(oharch); 00278 } 00279 #endif 00280 00281 /* Skip identical packages. */ 00282 if (rpmHeadersIdentical(h, oh)) 00283 continue; 00284 00285 /* Create an erasure element. */ 00286 lastx = -1; 00287 xx = removePackage(ts, oh, rpmmiInstance(mi), &lastx, pkgKey); 00288 assert(lastx >= 0 && lastx < ts->orderCount); 00289 q = ts->order[lastx]; 00290 00291 /* Chain through upgrade flink. */ 00292 xx = rpmteChain(p, q, oh, "Upgrades"); 00293 00294 /*@-nullptrarith@*/ 00295 rpmlog(RPMLOG_DEBUG, D_(" upgrade erases %s\n"), rpmteNEVRA(q)); 00296 /*@=nullptrarith@*/ 00297 00298 } 00299 mi = rpmmiFree(mi); 00300 00301 return 0; 00302 } 00303 00310 static inline int chkSuffix(const char * fn, const char * suffix) 00311 /*@*/ 00312 { 00313 size_t flen = strlen(fn); 00314 size_t slen = strlen(suffix); 00315 return (flen > slen && !strcmp(fn + flen - slen, suffix)); 00316 } 00317 00326 static int rpmtsEraseDebuginfo(rpmts ts, rpmte p, Header h, 00327 /*@exposed@*/ /*@dependent@*/ /*@null@*/ alKey pkgKey) 00328 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00329 /*@modifies ts, p, rpmGlobalMacroContext, fileSystem, internalState @*/ 00330 { 00331 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00332 const void *keyval = NULL; 00333 size_t keylen = 0; 00334 size_t nrefs = 0; 00335 rpmuint32_t debuginfoInstance = 0; 00336 Header debuginfoHeader = NULL; 00337 rpmmi mi; 00338 Header oh; 00339 int xx; 00340 00341 /* XXX SOURCEPKGID is not populated reliably, do not use (yet). */ 00342 if (_debuginfo_tag == 0) { 00343 const char * t = rpmExpand("%{?_debuginfo_tag}", NULL); 00344 /*@-mods@*/ 00345 _debuginfo_tag = (*t != '\0' && !strcmp(t, "pkgid") 00346 ? RPMTAG_SOURCEPKGID : RPMTAG_SOURCERPM); 00347 /*@=mods@*/ 00348 t = _free(t); 00349 } 00350 00351 /* Grab the retrieval key. */ 00352 switch (_debuginfo_tag) { 00353 default: return 0; /*@notreached@*/ break; 00354 case RPMTAG_SOURCERPM: keyval = rpmteSourcerpm(p); break; 00355 } 00356 00357 /* Count remaining members in build set, excluding -debuginfo (if any). */ 00358 mi = rpmtsInitIterator(ts, _debuginfo_tag, keyval, keylen); 00359 xx = rpmmiPrune(mi, ts->removedPackages, ts->numRemovedPackages, 1); 00360 while((oh = rpmmiNext(mi)) != NULL) { 00361 /* Skip identical packages. */ 00362 if (rpmHeadersIdentical(h, oh)) 00363 continue; 00364 00365 he->tag = RPMTAG_NAME; 00366 xx = headerGet(oh, he, 0); 00367 if (!xx || he->p.str == NULL) 00368 continue; 00369 /* Save the -debuginfo member. */ 00370 if (chkSuffix(he->p.str, "-debuginfo")) { 00371 debuginfoInstance = rpmmiInstance(mi); 00372 debuginfoHeader = headerLink(oh); 00373 } else 00374 nrefs++; 00375 he->p.str = _free(he->p.str); 00376 } 00377 mi = rpmmiFree(mi); 00378 00379 /* Remove -debuginfo package when last build member is erased. */ 00380 if (nrefs == 0 && debuginfoInstance > 0 && debuginfoHeader != NULL) { 00381 int lastx = -1; 00382 rpmte q; 00383 00384 /* Create an erasure element. */ 00385 lastx = -1; 00386 xx = removePackage(ts, debuginfoHeader, debuginfoInstance, 00387 &lastx, pkgKey); 00388 assert(lastx >= 0 && lastx < ts->orderCount); 00389 q = ts->order[lastx]; 00390 00391 /* Chain through upgrade flink. */ 00392 /* XXX avoid assertion failure when erasing. */ 00393 if (pkgKey != RPMAL_NOMATCH) 00394 xx = rpmteChain(p, q, oh, "Upgrades"); 00395 00396 /*@-nullptrarith@*/ 00397 rpmlog(RPMLOG_DEBUG, D_(" lastref erases %s\n"), rpmteNEVRA(q)); 00398 /*@=nullptrarith@*/ 00399 00400 } 00401 (void)headerFree(debuginfoHeader); 00402 debuginfoHeader = NULL; 00403 00404 return (int)nrefs; 00405 } 00406 00414 static int rpmtsAddObsoletes(rpmts ts, rpmte p, rpmuint32_t hcolor) 00415 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00416 /*@modifies ts, p, rpmGlobalMacroContext, fileSystem, internalState @*/ 00417 { 00418 rpmuint32_t tscolor = rpmtsColor(ts); 00419 alKey pkgKey = rpmteAddedKey(p); 00420 rpmuint32_t ohcolor; 00421 rpmds obsoletes; 00422 rpmuint32_t dscolor; 00423 rpmmi mi; 00424 Header oh; 00425 int xx; 00426 00427 if (_obsolete_tag == 0) { 00428 const char *t = rpmExpand("%{?_obsolete_tag}", NULL); 00429 /*@-mods@*/ 00430 _obsolete_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME); 00431 /*@=mods@*/ 00432 t = _free(t); 00433 } 00434 00435 obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME), "Obsoletes"); 00436 obsoletes = rpmdsInit(obsoletes); 00437 if (obsoletes != NULL) 00438 while (rpmdsNext(obsoletes) >= 0) { 00439 const char * Name; 00440 00441 if ((Name = rpmdsN(obsoletes)) == NULL) 00442 continue; /* XXX can't happen */ 00443 00444 /* Ignore colored obsoletes not in our rainbow. */ 00445 #if 0 00446 /* XXX obsoletes are never colored, so this is for future devel. */ 00447 dscolor = rpmdsColor(obsoletes); 00448 #else 00449 dscolor = hcolor; 00450 #endif 00451 if (tscolor && dscolor && !(tscolor & dscolor)) 00452 continue; 00453 00454 /* XXX avoid self-obsoleting packages. */ 00455 if (!strcmp(rpmteN(p), Name)) 00456 continue; 00457 00458 /* Obsolete containing package if given a file, otherwise provide. */ 00459 if (Name[0] == '/') 00460 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0); 00461 else 00462 mi = rpmtsInitIterator(ts, _obsolete_tag, Name, 0); 00463 00464 xx = rpmmiPrune(mi, ts->removedPackages, ts->numRemovedPackages, 1); 00465 00466 while((oh = rpmmiNext(mi)) != NULL) { 00467 int lastx; 00468 rpmte q; 00469 00470 /* Ignore colored packages not in our rainbow. */ 00471 ohcolor = hGetColor(oh); 00472 00473 /* XXX provides *are* colored, effectively limiting Obsoletes: 00474 to matching only colored Provides: based on pkg coloring. */ 00475 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor)) 00476 /*@innercontinue@*/ continue; 00477 00478 /* 00479 * Rpm prior to 3.0.3 does not have versioned obsoletes. 00480 * If no obsoletes version info is available, match all names. 00481 */ 00482 if (!(rpmdsEVR(obsoletes) == NULL 00483 || rpmdsAnyMatchesDep(oh, obsoletes, _rpmds_nopromote))) 00484 /*@innercontinue@*/ continue; 00485 00486 /* Create an erasure element. */ 00487 lastx = -1; 00488 xx = removePackage(ts, oh, rpmmiInstance(mi), &lastx, pkgKey); 00489 assert(lastx >= 0 && lastx < ts->orderCount); 00490 q = ts->order[lastx]; 00491 00492 /* Chain through obsoletes flink. */ 00493 xx = rpmteChain(p, q, oh, "Obsoletes"); 00494 00495 /*@-nullptrarith@*/ 00496 rpmlog(RPMLOG_DEBUG, D_(" Obsoletes: %s\t\terases %s\n"), 00497 rpmdsDNEVR(obsoletes)+2, rpmteNEVRA(q)); 00498 /*@=nullptrarith@*/ 00499 } 00500 mi = rpmmiFree(mi); 00501 } 00502 (void)rpmdsFree(obsoletes); 00503 obsoletes = NULL; 00504 00505 return 0; 00506 } 00507 00508 #if defined(RPM_VENDOR_WINDRIVER) 00509 /* Is "compat" compatible w/ arch? */ 00510 int _isCompatibleArch(const char * arch, const char * compat) 00511 { 00512 const char * compatArch = rpmExpand(compat, " %{?_", compat, "_compat_arch}", NULL); 00513 const char * p, * pe, * t; 00514 int match = 0; 00515 00516 /* Hack to ensure iX86 being automatically compatible */ 00517 if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') { 00518 if ((arch[0] == compat[0]) && 00519 (arch[2] == compat[2]) && 00520 (arch[3] == compat[3])) 00521 match = 1; 00522 00523 if (!strcmp(compat, "x86_32")) 00524 match = 1; 00525 } 00526 00527 for ( p = pe = compatArch ; *pe && match == 0 ; ) { 00528 while (*p && xisspace(*p)) p++; 00529 pe = p ; while (*pe && !xisspace(*pe)) pe++; 00530 if (p == pe) 00531 break; 00532 t = strndup(p, (pe - p)); 00533 p = pe; /* Advance to next chunk */ 00534 rpmlog(RPMLOG_DEBUG, D_(" Comparing compat archs %s ? %s\n"), arch, t); 00535 if (!strcmp(arch, t)) 00536 match = 1; 00537 t = _free(t); 00538 } 00539 compatArch = _free(compatArch); 00540 return match; 00541 } 00542 #endif 00543 00544 int rpmtsAddInstallElement(rpmts ts, Header h, 00545 fnpyKey key, int upgrade, rpmRelocation relocs) 00546 { 00547 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00548 rpmdepFlags depFlags = rpmtsDFlags(ts); 00549 rpmuint32_t tscolor = rpmtsColor(ts); 00550 rpmuint32_t hcolor; 00551 int isSource; 00552 int duplicate = 0; 00553 rpmtsi pi = NULL; rpmte p; 00554 const char * arch = NULL; 00555 const char * os = NULL; 00556 rpmds oldChk, newChk; 00557 alKey pkgKey; /* addedPackages key */ 00558 int xx; 00559 int ec = 0; 00560 int rc; 00561 int oc; 00562 00563 hcolor = hGetColor(h); 00564 pkgKey = RPMAL_NOMATCH; 00565 00566 /* 00567 * Always add source headers. 00568 */ 00569 isSource = 00570 (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 && 00571 headerIsEntry(h, RPMTAG_ARCH) != 0); 00572 if (isSource) { 00573 oc = ts->orderCount; 00574 goto addheader; 00575 } 00576 00577 /* 00578 * Check platform affinity of binary packages. 00579 */ 00580 he->tag = RPMTAG_ARCH; 00581 xx = headerGet(h, he, 0); 00582 arch = he->p.str; 00583 he->tag = RPMTAG_OS; 00584 xx = headerGet(h, he, 0); 00585 os = he->p.str; 00586 if (nplatpat > 1) { 00587 const char * platform = NULL; 00588 00589 he->tag = RPMTAG_PLATFORM; 00590 xx = headerGet(h, he, 0); 00591 platform = he->p.str; 00592 if (!xx || platform == NULL) 00593 platform = rpmExpand(arch, "-unknown-", os, NULL); 00594 00595 rc = rpmPlatformScore(platform, platpat, nplatpat); 00596 #if defined(RPM_VENDOR_MANDRIVA) 00597 /* quick and dirty workaround for mdvbz#61746: 00598 * if no match on platform tag, we'll try again with arch tag 00599 * in case platform tag is inconsistent with it which is the case 00600 * with sub-packages of different arch 00601 */ 00602 if(xx && rc <= 0) { 00603 platform = _free(platform); 00604 platform = rpmExpand(arch, "-unknown-", os, NULL); 00605 rc = rpmPlatformScore(platform, platpat, nplatpat); 00606 } 00607 #endif 00608 if (rc <= 0) { 00609 rpmps ps = rpmtsProblems(ts); 00610 he->tag = RPMTAG_NVRA; 00611 xx = headerGet(h, he, 0); 00612 assert(he->p.str != NULL); 00613 00614 rpmpsAppend(ps, RPMPROB_BADPLATFORM, he->p.str, key, 00615 platform, NULL, NULL, 0); 00616 00617 /* XXX problem string should be printed by caller instead. */ 00618 if (rpmIsVerbose()) { 00619 const char * msg = rpmProblemString(rpmpsGetProblem(ps, -1)); 00620 rpmlog(RPMLOG_WARNING, "%s\n", msg); 00621 msg = _free(msg); 00622 } 00623 00624 ps = rpmpsFree(ps); 00625 he->p.ptr = _free(he->p.ptr); 00626 ec = 1; 00627 } 00628 platform = _free(platform); 00629 if (ec) 00630 goto exit; 00631 } 00632 00633 /* 00634 * Always install compatible binary packages. 00635 */ 00636 if (!upgrade) { 00637 oc = ts->orderCount; 00638 goto addheader; 00639 } 00640 00641 /* 00642 * Check that upgrade package is uniquely newer, replace older if necessary. 00643 */ 00644 oldChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_LESS)); 00645 newChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_EQUAL|RPMSENSE_GREATER)); 00646 /* XXX can't use rpmtsiNext() filter or oc will have wrong value. */ 00647 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) { 00648 rpmds this; 00649 00650 /* XXX Only added packages need be checked for dupes here. */ 00651 if (rpmteType(p) == TR_REMOVED) 00652 continue; 00653 00654 /* XXX Never check source header NEVRAO. */ 00655 if (rpmteIsSource(p)) 00656 continue; 00657 00658 if (tscolor) { 00659 const char * parch; 00660 const char * pos; 00661 00662 if (arch == NULL || (parch = rpmteA(p)) == NULL) 00663 continue; 00664 #if defined(RPM_VENDOR_WINDRIVER) 00665 /* XXX hackery for alias matching. */ 00666 if (!_isCompatibleArch(arch, parch)) 00667 continue; 00668 #else 00669 /* XXX hackery for i[3456]86 alias matching. */ 00670 if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') { 00671 if (arch[0] != parch[0]) continue; 00672 if (arch[2] != parch[2]) continue; 00673 if (arch[3] != parch[3]) continue; 00674 } 00675 #endif 00676 else if (strcmp(arch, parch)) 00677 continue; 00678 if (os == NULL || (pos = rpmteO(p)) == NULL) 00679 continue; 00680 00681 if (strcmp(os, pos)) 00682 continue; 00683 } 00684 00685 /* OK, binary rpm's with same arch and os. Check NEVR. */ 00686 if ((this = rpmteDS(p, RPMTAG_NAME)) == NULL) 00687 continue; /* XXX can't happen */ 00688 00689 /* If newer NEVRAO already added, then skip adding older. */ 00690 rc = rpmdsCompare(newChk, this); 00691 if (rc != 0) { 00692 const char * pkgNEVR = rpmdsDNEVR(this); 00693 const char * addNEVR = rpmdsDNEVR(oldChk); 00694 if (rpmIsVerbose()) 00695 rpmlog(RPMLOG_WARNING, 00696 _("package %s was already added, skipping %s\n"), 00697 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"), 00698 (addNEVR ? addNEVR + 2 : "?addNEVR?")); 00699 ec = 1; 00700 break; 00701 } 00702 00703 /* If older NEVRAO already added, then replace old with new. */ 00704 rc = rpmdsCompare(oldChk, this); 00705 if (rc != 0) { 00706 const char * pkgNEVR = rpmdsDNEVR(this); 00707 const char * addNEVR = rpmdsDNEVR(newChk); 00708 if (rpmIsVerbose()) 00709 rpmlog(RPMLOG_WARNING, 00710 _("package %s was already added, replacing with %s\n"), 00711 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"), 00712 (addNEVR ? addNEVR + 2 : "?addNEVR?")); 00713 duplicate = 1; 00714 pkgKey = rpmteAddedKey(p); 00715 break; 00716 } 00717 } 00718 pi = rpmtsiFree(pi); 00719 (void)rpmdsFree(oldChk); 00720 oldChk = NULL; 00721 (void)rpmdsFree(newChk); 00722 newChk = NULL; 00723 00724 /* If newer (or same) NEVRAO was already added, exit now. */ 00725 if (ec) 00726 goto exit; 00727 00728 addheader: 00729 if (oc >= ts->orderAlloced) { 00730 ts->orderAlloced += (oc - ts->orderAlloced) + ts->delta; 00731 /*@-type +voidabstract @*/ 00732 ts->order = xrealloc(ts->order, ts->orderAlloced * sizeof(*ts->order)); 00733 /*@=type =voidabstract @*/ 00734 } 00735 00736 p = rpmteNew(ts, h, TR_ADDED, key, relocs, -1, pkgKey); 00737 assert(p != NULL); 00738 00739 if (duplicate && oc < ts->orderCount) { 00740 ts->numAddedFiles -= rpmfiFC(rpmteFI(ts->order[oc], RPMTAG_BASENAMES)); 00741 /*@-type -unqualifiedtrans@*/ 00742 ts->order[oc] = rpmteFree(ts->order[oc]); 00743 /*@=type =unqualifiedtrans@*/ 00744 } 00745 00746 ts->order[oc] = p; 00747 ts->numAddedFiles += rpmfiFC(rpmteFI(p, RPMTAG_BASENAMES)); 00748 if (!duplicate) { 00749 ts->orderCount++; 00750 rpmcliPackagesTotal++; 00751 } 00752 00753 pkgKey = rpmalAdd(&ts->addedPackages, pkgKey, rpmteKey(p), 00754 rpmteDS(p, RPMTAG_PROVIDENAME), 00755 rpmteFI(p, RPMTAG_BASENAMES), tscolor); 00756 if (pkgKey == RPMAL_NOMATCH) { 00757 ts->order[oc] = rpmteFree(ts->order[oc]); 00758 ts->teInstall = NULL; 00759 ec = 1; 00760 goto exit; 00761 } 00762 (void) rpmteSetAddedKey(p, pkgKey); 00763 00764 if (!duplicate) { 00765 ts->numAddedPackages++; 00766 } 00767 00768 ts->teInstall = ts->order[oc]; 00769 00770 /* XXX rpmgi hack: Save header in transaction element if requested. */ 00771 if (upgrade & 0x2) 00772 (void) rpmteSetHeader(p, h); 00773 00774 /* If not upgrading, then we're done. */ 00775 if (!(upgrade & 0x1)) 00776 goto exit; 00777 00778 /* If source rpm, then we're done. */ 00779 if (isSource) 00780 goto exit; 00781 00782 /* Do lazy (readonly?) open of rpm database. */ 00783 if (rpmtsGetRdb(ts) == NULL && rpmtsDBMode(ts) != -1) { 00784 if ((ec = rpmtsOpenDB(ts, rpmtsDBMode(ts)) != 0)) 00785 goto exit; 00786 } 00787 00788 /* Add upgrades to the transaction (if not disabled). */ 00789 if (!(depFlags & RPMDEPS_FLAG_NOUPGRADE)) { 00790 /* 00791 * Don't upgrade -debuginfo until build set is empty. 00792 * 00793 * XXX Almost, but not quite, correct since the test depends on 00794 * added package arrival order. 00795 * I.e. -debuginfo additions must always follow all 00796 * other additions so that erasures of other members in the 00797 * same build set are seen if/when included in the same transaction. 00798 */ 00799 xx = rpmtsEraseDebuginfo(ts, p, h, pkgKey); 00800 if (!chkSuffix(rpmteN(p), "-debuginfo") || xx == 0) 00801 xx = rpmtsAddUpgrades(ts, p, hcolor, h); 00802 } 00803 00804 /* Add Obsoletes: to the transaction (if not disabled). */ 00805 if (!(depFlags & RPMDEPS_FLAG_NOOBSOLETES)) { 00806 xx = rpmtsAddObsoletes(ts, p, hcolor); 00807 } 00808 00809 ec = 0; 00810 00811 exit: 00812 arch = _free(arch); 00813 os = _free(os); 00814 pi = rpmtsiFree(pi); 00815 return ec; 00816 } 00817 00818 int rpmtsAddEraseElement(rpmts ts, Header h, uint32_t hdrNum) 00819 { 00820 int oc = -1; 00821 int rc = removePackage(ts, h, hdrNum, &oc, RPMAL_NOMATCH); 00822 if (rc == 0 && oc >= 0 && oc < ts->orderCount) { 00823 (void) rpmtsEraseDebuginfo(ts, ts->order[oc], h, RPMAL_NOMATCH); 00824 ts->teErase = ts->order[oc]; 00825 } else 00826 ts->teErase = NULL; 00827 return rc; 00828 } 00829 00830 /*@only@*/ /*@null@*/ /*@unchecked@*/ 00831 static char *sysinfo_path = NULL; 00832 00833 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/ 00834 static rpmds rpmlibP = NULL; 00835 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/ 00836 rpmds cpuinfoP = NULL; 00837 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/ 00838 static rpmds getconfP = NULL; 00839 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/ 00840 static rpmds unameP = NULL; 00841 00842 void rpmnsClean(void) 00843 /*@globals sysinfo_path, _sysinfo_path, rpmlibP, cpuinfoP, getconfP, unameP @*/ 00844 /*@modifies sysinfo_path, _sysinfo_path, rpmlibP, cpuinfoP, getconfP, unameP @*/ 00845 { 00846 (void)rpmdsFree(rpmlibP); 00847 rpmlibP = NULL; 00848 (void)rpmdsFree(cpuinfoP); 00849 cpuinfoP = NULL; 00850 (void)rpmdsFree(getconfP); 00851 getconfP = NULL; 00852 (void)rpmdsFree(unameP); 00853 unameP = NULL; 00854 /*@-observertrans@*/ 00855 _sysinfo_path = _free(_sysinfo_path); 00856 /*@=observertrans@*/ 00857 sysinfo_path = _free(sysinfo_path); 00858 } 00859 00867 static int unsatisfiedDepend(rpmts ts, rpmds dep, int adding) 00868 /*@globals _cacheDependsRC, rpmGlobalMacroContext, h_errno, 00869 sysinfo_path, fileSystem, internalState @*/ 00870 /*@modifies ts, dep, _cacheDependsRC, rpmGlobalMacroContext, 00871 sysinfo_path, fileSystem, internalState @*/ 00872 { 00873 DBT * key = alloca(sizeof(*key)); 00874 DBT * data = alloca(sizeof(*data)); 00875 rpmmi mi; 00876 nsType NSType; 00877 const char * Name; 00878 rpmuint32_t Flags; 00879 Header h; 00880 #if defined(CACHE_DEPENDENCY_RESULT) 00881 int _cacheThisRC = 1; 00882 #endif 00883 int rc; 00884 int xx; 00885 int retries = 20; 00886 00887 if ((Name = rpmdsN(dep)) == NULL) 00888 return 0; /* XXX can't happen */ 00889 Flags = rpmdsFlags(dep); 00890 NSType = rpmdsNSType(dep); 00891 00892 #if defined(CACHE_DEPENDENCY_RESULT) 00893 /* 00894 * Check if dbiOpen/dbiPut failed (e.g. permissions), we can't cache. 00895 */ 00896 if (_cacheDependsRC) { 00897 dbiIndex dbi; 00898 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0); 00899 if (dbi == NULL) 00900 _cacheDependsRC = 0; 00901 else { 00902 const char * DNEVR; 00903 00904 rc = -1; 00905 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) { 00906 DBC * dbcursor = NULL; 00907 void * datap = NULL; 00908 size_t datalen = 0; 00909 size_t DNEVRlen = strlen(DNEVR); 00910 00911 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, 0); 00912 00913 memset(key, 0, sizeof(*key)); 00914 /*@i@*/ key->data = (void *) DNEVR; 00915 key->size = DNEVRlen; 00916 memset(data, 0, sizeof(*data)); 00917 data->data = datap; 00918 data->size = datalen; 00919 /*@-nullstate@*/ /* FIX: data->data may be NULL */ 00920 xx = dbiGet(dbi, dbcursor, key, data, DB_SET); 00921 /*@=nullstate@*/ 00922 DNEVR = key->data; 00923 DNEVRlen = key->size; 00924 datap = data->data; 00925 datalen = data->size; 00926 00927 if (xx == 0 && datap && datalen == 4) 00928 memcpy(&rc, datap, datalen); 00929 xx = dbiCclose(dbi, dbcursor, 0); 00930 } 00931 00932 if (rc >= 0) { 00933 rpmdsNotify(dep, _("(cached)"), rc); 00934 return rpmdsNegateRC(dep, rc); 00935 } 00936 } 00937 } 00938 #endif 00939 00940 retry: 00941 rc = 0; /* assume dependency is satisfied */ 00942 00943 /* Expand macro probe dependencies. */ 00944 if (NSType == RPMNS_TYPE_FUNCTION) { 00945 xx = rpmExpandNumeric(Name); 00946 rc = (xx ? 0 : 1); 00947 if (Flags & RPMSENSE_MISSINGOK) 00948 goto unsatisfied; 00949 rpmdsNotify(dep, _("(function probe)"), rc); 00950 goto exit; 00951 } 00952 00953 /* Evaluate user/group lookup probes. */ 00954 if (NSType == RPMNS_TYPE_USER) { 00955 const char *s; 00956 uid_t uid = 0; 00957 s = Name; while (*s && xisdigit(*s)) s++; 00958 00959 if (*s) 00960 xx = unameToUid(Name, &uid); 00961 else { 00962 uid = strtol(Name, NULL, 10); 00963 xx = (uidToUname(uid) ? 0 : -1); 00964 } 00965 rc = (xx >= 0 ? 0 : 1); 00966 if (Flags & RPMSENSE_MISSINGOK) 00967 goto unsatisfied; 00968 rpmdsNotify(dep, _("(user lookup)"), rc); 00969 goto exit; 00970 } 00971 if (NSType == RPMNS_TYPE_GROUP) { 00972 const char *s; 00973 gid_t gid = 0; 00974 s = Name; while (*s && xisdigit(*s)) s++; 00975 00976 if (*s) 00977 xx = gnameToGid(Name, &gid); 00978 else { 00979 gid = strtol(Name, NULL, 10); 00980 xx = (gidToGname(gid) ? 0 : -1); 00981 } 00982 rc = (xx >= 0 ? 0 : 1); 00983 if (Flags & RPMSENSE_MISSINGOK) 00984 goto unsatisfied; 00985 rpmdsNotify(dep, _("(group lookup)"), rc); 00986 goto exit; 00987 } 00988 00989 /* Evaluate access(2) probe dependencies. */ 00990 if (NSType == RPMNS_TYPE_ACCESS) { 00991 rc = rpmioAccess(Name, NULL, X_OK); 00992 if (Flags & RPMSENSE_MISSINGOK) 00993 goto unsatisfied; 00994 rpmdsNotify(dep, _("(access probe)"), rc); 00995 goto exit; 00996 } 00997 00998 /* Evaluate mtab lookup and diskspace probe dependencies. */ 00999 if (NSType == RPMNS_TYPE_MOUNTED) { 01000 const char ** fs = NULL; 01001 int nfs = 0; 01002 int i = 0; 01003 01004 xx = rpmtsInitDSI(ts); 01005 fs = ts->filesystems; 01006 nfs = ts->filesystemCount; 01007 01008 if (fs != NULL) 01009 for (i = 0; i < nfs; i++) { 01010 if (!strcmp(fs[i], Name)) 01011 break; 01012 } 01013 rc = (i < nfs ? 0 : 1); 01014 if (Flags & RPMSENSE_MISSINGOK) 01015 goto unsatisfied; 01016 rpmdsNotify(dep, _("(mtab probe)"), rc); 01017 goto exit; 01018 } 01019 01020 if (NSType == RPMNS_TYPE_DISKSPACE) { 01021 size_t nb = strlen(Name); 01022 rpmDiskSpaceInfo dsi = NULL; 01023 const char ** fs = NULL; 01024 size_t fslen = 0, longest = 0; 01025 int nfs = 0; 01026 int i = 0; 01027 01028 xx = rpmtsInitDSI(ts); 01029 fs = ts->filesystems; 01030 nfs = ts->filesystemCount; 01031 01032 if (fs != NULL) 01033 for (i = 0; i < nfs; i++) { 01034 fslen = strlen(fs[i]); 01035 if (fslen > nb) 01036 continue; 01037 if (strncmp(fs[i], Name, fslen)) 01038 continue; 01039 if (fslen > 1 && Name[fslen] != '/' && Name[fslen] != '\0') 01040 continue; 01041 if (fslen < longest) 01042 continue; 01043 longest = fslen; 01044 dsi = ts->dsi + i; 01045 } 01046 if (dsi == NULL) 01047 rc = 1; /* no mounted paths !?! */ 01048 else { 01049 char * end = NULL; 01050 /*@-unrecog@*/ 01051 rpmuint64_t needed = strtoll(rpmdsEVR(dep), &end, 0); 01052 /*@=unrecog@*/ 01053 01054 if (end && *end) { 01055 if (strchr("Gg", end[0]) && strchr("Bb", end[1]) && !end[2]) 01056 needed *= 1024 * 1024 * 1024; 01057 if (strchr("Mm", end[0]) && strchr("Bb", end[1]) && !end[2]) 01058 needed *= 1024 * 1024; 01059 if (strchr("Kk", end[0]) && strchr("Bb", end[1]) && !end[2]) 01060 needed *= 1024; 01061 } else 01062 needed *= 1024 * 1024; /* XXX assume Mb if no units given */ 01063 01064 needed = BLOCK_ROUND(needed, dsi->f_bsize); 01065 xx = (dsi->f_bavail - needed); 01066 if ((Flags & RPMSENSE_LESS) && xx < 0) rc = 0; 01067 else if ((Flags & RPMSENSE_GREATER) && xx > 0) rc = 0; 01068 else if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0; 01069 else rc = 1; 01070 } 01071 if (Flags & RPMSENSE_MISSINGOK) 01072 goto unsatisfied; 01073 rpmdsNotify(dep, _("(diskspace probe)"), rc); 01074 goto exit; 01075 } 01076 01077 if (NSType == RPMNS_TYPE_DIGEST) { 01078 const char * EVR = rpmdsEVR(dep); 01079 const char *filename; 01080 pgpHashAlgo digestHashAlgo; 01081 FD_t fd; 01082 char *cp; 01083 int algo; 01084 01085 filename = Name; 01086 digestHashAlgo = PGPHASHALGO_MD5; 01087 if ((cp = strchr(filename, ':')) != NULL) { 01088 if ((algo = pgpHashAlgoStringToNumber(filename, cp-filename)) != PGPHASHALGO_ERROR) { 01089 digestHashAlgo = algo; 01090 filename = cp + 1; 01091 } 01092 } 01093 rc = 1; /* XXX assume failure */ 01094 fd = Fopen(filename, "r.fdio"); 01095 if (fd && !Ferror(fd)) { 01096 DIGEST_CTX ctx = rpmDigestInit(digestHashAlgo, RPMDIGEST_NONE); 01097 const char * digest = NULL; 01098 size_t digestlen = 0; 01099 int asAscii = 1; 01100 size_t nbuf = 8 * BUFSIZ; 01101 char * buf = alloca(nbuf); 01102 size_t nb; 01103 01104 while ((nb = Fread(buf, sizeof(buf[0]), nbuf, fd)) > 0) 01105 xx = rpmDigestUpdate(ctx, buf, nb); 01106 xx = Fclose(fd); fd = NULL; 01107 xx = rpmDigestFinal(ctx, &digest, &digestlen, asAscii); 01108 01109 xx = (EVR && *EVR && digest && *digest) ? strcasecmp(EVR, digest) : -1; 01110 /* XXX only equality makes sense for digest compares */ 01111 if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0; 01112 } 01113 if (Flags & RPMSENSE_MISSINGOK) 01114 goto unsatisfied; 01115 rpmdsNotify(dep, _("(digest probe)"), rc); 01116 goto exit; 01117 } 01118 01119 if (NSType == RPMNS_TYPE_SIGNATURE) { 01120 const char * EVR = rpmdsEVR(dep); 01121 ARGV_t avN = NULL; 01122 ARGV_t avEVR = NULL; 01123 rpmRC res; 01124 01125 /* Split /fn:/sig */ 01126 xx = argvSplit(&avN, Name, ":"); 01127 01128 /* Split /pub:id */ 01129 xx = (EVR && *EVR) ? argvSplit(&avEVR, EVR, ":") : argvAdd(&avEVR, ""); 01130 01131 res = rpmnsProbeSignature(ts, avN[0], avN[1], avEVR[0], avEVR[1], 0); 01132 rc = (res == RPMRC_OK ? 0 : 1); 01133 01134 avN = argvFree(avN); 01135 avEVR = argvFree(avEVR); 01136 01137 if (Flags & RPMSENSE_MISSINGOK) 01138 goto unsatisfied; 01139 rpmdsNotify(dep, _("(signature probe)"), rc); 01140 goto exit; 01141 } 01142 01143 if (NSType == RPMNS_TYPE_VERIFY) { 01144 QVA_t qva = memset(alloca(sizeof(*qva)), 0, sizeof(*qva)); 01145 01146 qva->qva_mode = 'v'; 01147 qva->qva_flags = (int)(VERIFY_ALL & ~(VERIFY_DEPS|VERIFY_SCRIPT)); 01148 rc = 0; /* assume success */ 01149 if (rpmtsGetRdb(ts) != NULL) { 01150 if (!strcmp(Name, "*")) /* -Va probe */ 01151 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0); 01152 else if (Name[0] == '/') /* -Vf probe */ 01153 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0); 01154 else /* -V probe */ 01155 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0); 01156 while ((h = rpmmiNext(mi)) != NULL) { 01157 if (!(Name[0] == '/' || !strcmp(Name, "*"))) 01158 if (!rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) 01159 continue; 01160 xx = (showVerifyPackage(qva, ts, h) ? 1 : 0); 01161 if (xx) 01162 rc = 1; 01163 } 01164 mi = rpmmiFree(mi); 01165 } 01166 01167 if (Flags & RPMSENSE_MISSINGOK) 01168 goto unsatisfied; 01169 rpmdsNotify(dep, _("(verify probe)"), rc); 01170 goto exit; 01171 } 01172 01173 if (NSType == RPMNS_TYPE_GNUPG) { 01174 const char * EVR = rpmdsEVR(dep); 01175 if (!(EVR && *EVR)) { 01176 static const char gnupg_pre[] = "%(%{__gpg} --batch --no-tty --quiet --verify "; 01177 static const char gnupg_post[] = " 2>/dev/null; echo $?)"; 01178 const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL); 01179 rc = (t && t[0] == '0') ? 0 : 1; 01180 t = _free(t); 01181 } 01182 else { 01183 static const char gnupg_pre[] = "%(%{__gpg} --batch --no-tty --quiet --verify "; 01184 static const char gnupg_post[] = " 2>&1 | grep '^Primary key fingerprint:' | sed -e 's;^.*: *;;' -e 's; *;;g')"; 01185 const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL); 01186 rc = ((Flags & RPMSENSE_EQUAL) && strcasecmp(EVR, t) == 0) ? 0 : 1; 01187 t = _free(t); 01188 } 01189 if (Flags & RPMSENSE_MISSINGOK) 01190 goto unsatisfied; 01191 rpmdsNotify(dep, _("(gnupg probe)"), rc); 01192 goto exit; 01193 } 01194 01195 if (NSType == RPMNS_TYPE_MACRO) { 01196 static const char macro_pre[] = "%{?"; 01197 static const char macro_post[] = ":0}"; 01198 const char * a = rpmExpand(macro_pre, Name, macro_post, NULL); 01199 01200 rc = (a && a[0] == '0') ? 0 : 1; 01201 a = _free(a); 01202 if (Flags & RPMSENSE_MISSINGOK) 01203 goto unsatisfied; 01204 rpmdsNotify(dep, _("(macro probe)"), rc); 01205 goto exit; 01206 } 01207 01208 if (NSType == RPMNS_TYPE_ENVVAR) { 01209 const char * a = envGet(Name); 01210 const char * b = rpmdsEVR(dep); 01211 01212 /* Existence test if EVR is missing/empty. */ 01213 if (!(b && *b)) 01214 rc = (!(a && *a)); 01215 else { 01216 int sense = (a && *a) ? strcmp(a, b) : -1; 01217 01218 if ((Flags & RPMSENSE_SENSEMASK) == RPMSENSE_NOTEQUAL) 01219 rc = (sense == 0); 01220 else if (sense < 0 && (Flags & RPMSENSE_LESS)) 01221 rc = 0; 01222 else if (sense > 0 && (Flags & RPMSENSE_GREATER)) 01223 rc = 0; 01224 else if (sense == 0 && (Flags & RPMSENSE_EQUAL)) 01225 rc = 0; 01226 else 01227 rc = (sense != 0); 01228 } 01229 01230 if (Flags & RPMSENSE_MISSINGOK) 01231 goto unsatisfied; 01232 rpmdsNotify(dep, _("(envvar probe)"), rc); 01233 goto exit; 01234 } 01235 01236 if (NSType == RPMNS_TYPE_RUNNING) { 01237 char *t = NULL; 01238 pid_t pid = strtol(Name, &t, 10); 01239 01240 if (t == NULL || *t != '\0') { 01241 const char * fn = rpmGetPath("%{_varrun}/", Name, ".pid", NULL); 01242 FD_t fd = NULL; 01243 01244 if (fn && *fn != '%' && (fd = Fopen(fn, "r.fdio")) && !Ferror(fd)) { 01245 char buf[32]; 01246 size_t nb = Fread(buf, sizeof(buf[0]), sizeof(buf), fd); 01247 01248 if (nb > 0) 01249 pid = strtol(buf, &t, 10); 01250 } else 01251 pid = 0; 01252 if (fd != NULL) 01253 (void) Fclose(fd); 01254 fn = _free(fn); 01255 } 01256 rc = (pid > 0 ? (kill(pid, 0) < 0 && errno == ESRCH) : 1); 01257 if (Flags & RPMSENSE_MISSINGOK) 01258 goto unsatisfied; 01259 rpmdsNotify(dep, _("(running probe)"), rc); 01260 goto exit; 01261 } 01262 01263 if (NSType == RPMNS_TYPE_SANITY) { 01264 /* XXX only the installer does not have the database open here. */ 01265 rc = 1; /* assume failure */ 01266 if (rpmtsGetRdb(ts) != NULL) { 01267 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0); 01268 while ((h = rpmmiNext(mi)) != NULL) { 01269 if (!rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) 01270 continue; 01271 rc = (headerIsEntry(h, RPMTAG_SANITYCHECK) == 0); 01272 if (rc == 0) { 01273 /* XXX FIXME: actually run the sanitycheck script. */ 01274 break; 01275 } 01276 } 01277 mi = rpmmiFree(mi); 01278 } 01279 if (Flags & RPMSENSE_MISSINGOK) 01280 goto unsatisfied; 01281 rpmdsNotify(dep, _("(sanity probe)"), rc); 01282 goto exit; 01283 } 01284 01285 if (NSType == RPMNS_TYPE_VCHECK) { 01286 rc = 1; /* assume failure */ 01287 if (rpmtsGetRdb(ts) != NULL) { 01288 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0); 01289 while ((h = rpmmiNext(mi)) != NULL) { 01290 if (!rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) 01291 continue; 01292 rc = (headerIsEntry(h, RPMTAG_TRACK) == 0); 01293 if (rc == 0) { 01294 /* XXX FIXME: actually run the vcheck script. */ 01295 break; 01296 } 01297 } 01298 mi = rpmmiFree(mi); 01299 } 01300 if (Flags & RPMSENSE_MISSINGOK) 01301 goto unsatisfied; 01302 rpmdsNotify(dep, _("(vcheck probe)"), rc); 01303 goto exit; 01304 } 01305 01306 /* Search system configured provides. */ 01307 if (sysinfo_path == NULL) { 01308 sysinfo_path = rpmExpand("%{?_rpmds_sysinfo_path}", NULL); 01309 if (!(sysinfo_path != NULL && *sysinfo_path == '/')) { 01310 sysinfo_path = _free(sysinfo_path); 01311 sysinfo_path = xstrdup(SYSCONFIGDIR "/sysinfo"); 01312 } 01313 } 01314 01315 if (!rpmioAccess(sysinfo_path, NULL, R_OK)) { 01316 #ifdef NOTYET /* XXX just sysinfo Provides: for now. */ 01317 rpmTag tagN = (Name[0] == '/' ? RPMTAG_DIRNAMES : RPMTAG_PROVIDENAME); 01318 #else 01319 rpmTag tagN = RPMTAG_PROVIDENAME; 01320 #endif 01321 rpmds P = rpmdsFromPRCO(rpmtsPRCO(ts), tagN); 01322 if (rpmdsSearch(P, dep) >= 0) { 01323 rpmdsNotify(dep, _("(sysinfo provides)"), rc); 01324 goto exit; 01325 } 01326 } 01327 01328 /* 01329 * New features in rpm packaging implicitly add versioned dependencies 01330 * on rpmlib provides. The dependencies look like "rpmlib(YaddaYadda)". 01331 * Check those dependencies now. 01332 */ 01333 if (NSType == RPMNS_TYPE_RPMLIB) { 01334 static int oneshot = -1; 01335 01336 if (oneshot) 01337 oneshot = rpmdsRpmlib(&rpmlibP, NULL); 01338 if (rpmlibP == NULL) 01339 goto unsatisfied; 01340 01341 if (rpmdsSearch(rpmlibP, dep) >= 0) { 01342 rpmdsNotify(dep, _("(rpmlib provides)"), rc); 01343 goto exit; 01344 } 01345 goto unsatisfied; 01346 } 01347 01348 if (NSType == RPMNS_TYPE_CPUINFO) { 01349 static int oneshot = -1; 01350 01351 if (oneshot && cpuinfoP == NULL) 01352 oneshot = rpmdsCpuinfo(&cpuinfoP, NULL); 01353 if (cpuinfoP == NULL) 01354 goto unsatisfied; 01355 01356 if (rpmdsSearch(cpuinfoP, dep) >= 0) { 01357 rpmdsNotify(dep, _("(cpuinfo provides)"), rc); 01358 goto exit; 01359 } 01360 goto unsatisfied; 01361 } 01362 01363 if (NSType == RPMNS_TYPE_GETCONF) { 01364 static int oneshot = -1; 01365 01366 if (oneshot) 01367 oneshot = rpmdsGetconf(&getconfP, NULL); 01368 if (getconfP == NULL) 01369 goto unsatisfied; 01370 01371 if (rpmdsSearch(getconfP, dep) >= 0) { 01372 rpmdsNotify(dep, _("(getconf provides)"), rc); 01373 goto exit; 01374 } 01375 goto unsatisfied; 01376 } 01377 01378 if (NSType == RPMNS_TYPE_UNAME) { 01379 static int oneshot = -1; 01380 01381 if (oneshot) 01382 oneshot = rpmdsUname(&unameP, NULL); 01383 if (unameP == NULL) 01384 goto unsatisfied; 01385 01386 if (rpmdsSearch(unameP, dep) >= 0) { 01387 rpmdsNotify(dep, _("(uname provides)"), rc); 01388 goto exit; 01389 } 01390 goto unsatisfied; 01391 } 01392 01393 if (NSType == RPMNS_TYPE_SONAME) { 01394 rpmds sonameP = NULL; 01395 rpmPRCO PRCO = rpmdsNewPRCO(NULL); 01396 char * fn = strcpy(alloca(strlen(Name)+1), Name); 01397 int flags = 0; /* XXX RPMELF_FLAG_SKIPREQUIRES? */ 01398 rpmds ds; 01399 01400 /* XXX Only absolute paths for now. */ 01401 if (*fn != '/') 01402 goto unsatisfied; 01403 fn[strlen(fn)-1] = '\0'; 01404 01405 /* Extract ELF Provides: from /path/to/DSO. */ 01406 xx = rpmdsELF(fn, flags, rpmdsMergePRCO, PRCO); 01407 sonameP = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME); 01408 if (!(xx == 0 && sonameP != NULL)) 01409 goto unsatisfied; 01410 01411 /* Search using the original {EVR,"",Flags} from the dep set. */ 01412 ds = rpmdsSingle(rpmdsTagN(dep), rpmdsEVR(dep), "", Flags); 01413 xx = rpmdsSearch(sonameP, ds); 01414 (void)rpmdsFree(ds); 01415 ds = NULL; 01416 PRCO = rpmdsFreePRCO(PRCO); 01417 01418 /* Was the dependency satisfied? */ 01419 if (xx >= 0) { 01420 rpmdsNotify(dep, _("(soname provides)"), rc); 01421 goto exit; 01422 } 01423 goto unsatisfied; 01424 } 01425 01426 /* Search added packages for the dependency. */ 01427 if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) { 01428 #if defined(CACHE_DEPENDENCY_RESULT) 01429 /* 01430 * XXX Ick, context sensitive answers from dependency cache. 01431 * XXX Always resolve added dependencies within context to disambiguate. 01432 */ 01433 if (_rpmds_nopromote) 01434 _cacheThisRC = 0; 01435 #endif 01436 goto exit; 01437 } 01438 01439 /* XXX only the installer does not have the database open here. */ 01440 if (rpmtsGetRdb(ts) != NULL) { 01441 /* XXX Always satisfy Requires: /, SuSE (others?) doesn't package "/" */ 01442 if (Name[0] == '/' && Name[1] == '\0') { 01443 rpmdsNotify(dep, _("(root files)"), rc); 01444 goto exit; 01445 } 01446 if (Name[0] == '/') { 01447 /* depFlags better be 0! */ 01448 01449 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0); 01450 (void) rpmmiPrune(mi, 01451 ts->removedPackages, ts->numRemovedPackages, 1); 01452 while ((h = rpmmiNext(mi)) != NULL) { 01453 rpmdsNotify(dep, _("(db files)"), rc); 01454 mi = rpmmiFree(mi); 01455 goto exit; 01456 } 01457 mi = rpmmiFree(mi); 01458 } 01459 01460 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0); 01461 (void) rpmmiPrune(mi, 01462 ts->removedPackages, ts->numRemovedPackages, 1); 01463 while ((h = rpmmiNext(mi)) != NULL) { 01464 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) { 01465 rpmdsNotify(dep, _("(db provides)"), rc); 01466 mi = rpmmiFree(mi); 01467 goto exit; 01468 } 01469 } 01470 mi = rpmmiFree(mi); 01471 } 01472 01473 /* 01474 * Search for an unsatisfied dependency. 01475 */ 01476 if (adding == 1 && retries > 0 && !(rpmtsDFlags(ts) & RPMDEPS_FLAG_NOSUGGEST)) { 01477 if (ts->solve != NULL) { 01478 xx = (*ts->solve) (ts, dep, ts->solveData); 01479 if (xx == 0) 01480 goto exit; 01481 if (xx == -1) { 01482 retries--; 01483 rpmalMakeIndex(ts->addedPackages); 01484 goto retry; 01485 } 01486 } 01487 } 01488 01489 unsatisfied: 01490 if (Flags & RPMSENSE_MISSINGOK) { 01491 rc = 0; /* dependency is unsatisfied, but just a hint. */ 01492 #if defined(CACHE_DEPENDENCY_RESULT) 01493 _cacheThisRC = 0; 01494 #endif 01495 rpmdsNotify(dep, _("(hint skipped)"), rc); 01496 } else { 01497 rc = 1; /* dependency is unsatisfied */ 01498 rpmdsNotify(dep, NULL, rc); 01499 } 01500 01501 exit: 01502 /* 01503 * If dbiOpen/dbiPut fails (e.g. permissions), we can't cache. 01504 */ 01505 #if defined(CACHE_DEPENDENCY_RESULT) 01506 if (_cacheDependsRC && _cacheThisRC) { 01507 dbiIndex dbi; 01508 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0); 01509 if (dbi == NULL) { 01510 _cacheDependsRC = 0; 01511 } else { 01512 const char * DNEVR; 01513 xx = 0; 01514 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) { 01515 DBC * dbcursor = NULL; 01516 size_t DNEVRlen = strlen(DNEVR); 01517 01518 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, DB_WRITECURSOR); 01519 01520 memset(key, 0, sizeof(*key)); 01521 /*@i@*/ key->data = (void *) DNEVR; 01522 key->size = DNEVRlen; 01523 memset(data, 0, sizeof(*data)); 01524 data->data = &rc; 01525 data->size = sizeof(rc); 01526 01527 /*@-compmempass@*/ 01528 xx = dbiPut(dbi, dbcursor, key, data, 0); 01529 /*@=compmempass@*/ 01530 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR); 01531 } 01532 if (xx) 01533 _cacheDependsRC = 0; 01534 } 01535 } 01536 #endif 01537 01538 return rpmdsNegateRC(dep, rc); 01539 } 01540 01554 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA, 01555 /*@null@*/ rpmds requires, 01556 /*@null@*/ rpmds conflicts, 01557 /*@null@*/ rpmds dirnames, 01558 /*@null@*/ rpmds linktos, 01559 /*@null@*/ const char * depName, 01560 rpmuint32_t tscolor, int adding) 01561 /*@globals rpmGlobalMacroContext, h_errno, 01562 fileSystem, internalState @*/ 01563 /*@modifies ts, requires, conflicts, dirnames, linktos, 01564 rpmGlobalMacroContext, fileSystem, internalState */ 01565 { 01566 rpmps ps = rpmtsProblems(ts); 01567 rpmuint32_t dscolor; 01568 const char * Name; 01569 int terminate = 2; /* XXX terminate if rc >= terminate */ 01570 int rc; 01571 int ourrc = 0; 01572 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* optional-dirname-and-symlink-deps */ 01573 int dirname_deps; 01574 int symlink_deps; 01575 #endif 01576 01577 requires = rpmdsInit(requires); 01578 if (requires != NULL) 01579 while (ourrc < terminate && rpmdsNext(requires) >= 0) { 01580 01581 if ((Name = rpmdsN(requires)) == NULL) 01582 continue; /* XXX can't happen */ 01583 01584 /* Filter out requires that came along for the ride. */ 01585 if (depName != NULL && strcmp(depName, Name)) 01586 continue; 01587 01588 /* Ignore colored requires not in our rainbow. */ 01589 dscolor = rpmdsColor(requires); 01590 if (tscolor && dscolor && !(tscolor & dscolor)) 01591 continue; 01592 01593 rc = unsatisfiedDepend(ts, requires, adding); 01594 01595 switch (rc) { 01596 case 0: /* requirements are satisfied. */ 01597 /*@switchbreak@*/ break; 01598 case 1: /* requirements are not satisfied. */ 01599 { fnpyKey * suggestedKeys = NULL; 01600 01601 if (ts->availablePackages != NULL) { 01602 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages, 01603 requires, NULL); 01604 } 01605 01606 rpmdsProblem(ps, pkgNEVRA, requires, suggestedKeys, adding); 01607 01608 } 01609 ourrc = 1; 01610 /*@switchbreak@*/ break; 01611 case 2: /* something went wrong! */ 01612 default: 01613 ourrc = 2; 01614 /*@switchbreak@*/ break; 01615 } 01616 } 01617 01618 conflicts = rpmdsInit(conflicts); 01619 if (conflicts != NULL) 01620 while (ourrc < terminate && rpmdsNext(conflicts) >= 0) { 01621 01622 if ((Name = rpmdsN(conflicts)) == NULL) 01623 continue; /* XXX can't happen */ 01624 01625 /* Filter out conflicts that came along for the ride. */ 01626 if (depName != NULL && strcmp(depName, Name)) 01627 continue; 01628 01629 /* Ignore colored conflicts not in our rainbow. */ 01630 dscolor = rpmdsColor(conflicts); 01631 if (tscolor && dscolor && !(tscolor & dscolor)) 01632 continue; 01633 01634 rc = unsatisfiedDepend(ts, conflicts, adding); 01635 01636 /* 1 == unsatisfied, 0 == satsisfied */ 01637 switch (rc) { 01638 case 0: /* conflicts exist. */ 01639 rpmdsProblem(ps, pkgNEVRA, conflicts, NULL, adding); 01640 ourrc = 1; 01641 /*@switchbreak@*/ break; 01642 case 1: /* conflicts don't exist. */ 01643 /*@switchbreak@*/ break; 01644 case 2: /* something went wrong! */ 01645 default: 01646 ourrc = 2; 01647 /*@switchbreak@*/ break; 01648 } 01649 } 01650 01651 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* optional-dirname-and-symlink-deps */ 01652 dirname_deps = rpmExpandNumeric("%{?_check_dirname_deps}%{?!_check_dirname_deps:1}"); 01653 if (dirname_deps) { 01654 #endif 01655 dirnames = rpmdsInit(dirnames); 01656 if (dirnames != NULL) 01657 while (ourrc < terminate && rpmdsNext(dirnames) >= 0) { 01658 01659 if ((Name = rpmdsN(dirnames)) == NULL) 01660 continue; /* XXX can't happen */ 01661 01662 /* Filter out dirnames that came along for the ride. */ 01663 if (depName != NULL && strcmp(depName, Name)) 01664 continue; 01665 01666 /* Ignore colored dirnames not in our rainbow. */ 01667 dscolor = rpmdsColor(dirnames); 01668 if (tscolor && dscolor && !(tscolor & dscolor)) 01669 continue; 01670 01671 rc = unsatisfiedDepend(ts, dirnames, adding); 01672 01673 switch (rc) { 01674 case 0: /* requirements are satisfied. */ 01675 /*@switchbreak@*/ break; 01676 case 1: /* requirements are not satisfied. */ 01677 { fnpyKey * suggestedKeys = NULL; 01678 01679 if (ts->availablePackages != NULL) { 01680 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages, 01681 dirnames, NULL); 01682 } 01683 01684 rpmdsProblem(ps, pkgNEVRA, dirnames, suggestedKeys, adding); 01685 01686 } 01687 ourrc = 1; 01688 /*@switchbreak@*/ break; 01689 case 2: /* something went wrong! */ 01690 default: 01691 ourrc = 2; 01692 /*@switchbreak@*/ break; 01693 } 01694 } 01695 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* optional-dirname-and-symlink-deps */ 01696 } 01697 01698 symlink_deps = rpmExpandNumeric("%{?_check_symlink_deps}%{?!_check_symlink_deps:1}"); 01699 if (symlink_deps) { 01700 #endif 01701 linktos = rpmdsInit(linktos); 01702 if (linktos != NULL) 01703 while (ourrc < terminate && rpmdsNext(linktos) >= 0) { 01704 01705 if ((Name = rpmdsN(linktos)) == NULL) 01706 continue; /* XXX can't happen */ 01707 if (*Name == '\0') /* XXX most linktos are empty */ 01708 continue; 01709 01710 /* Filter out linktos that came along for the ride. */ 01711 if (depName != NULL && strcmp(depName, Name)) 01712 continue; 01713 01714 /* Ignore colored linktos not in our rainbow. */ 01715 dscolor = rpmdsColor(linktos); 01716 if (tscolor && dscolor && !(tscolor & dscolor)) 01717 continue; 01718 01719 rc = unsatisfiedDepend(ts, linktos, adding); 01720 01721 switch (rc) { 01722 case 0: /* requirements are satisfied. */ 01723 /*@switchbreak@*/ break; 01724 case 1: /* requirements are not satisfied. */ 01725 { fnpyKey * suggestedKeys = NULL; 01726 01727 if (ts->availablePackages != NULL) { 01728 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages, 01729 linktos, NULL); 01730 } 01731 01732 rpmdsProblem(ps, pkgNEVRA, linktos, suggestedKeys, adding); 01733 01734 } 01735 ourrc = 1; 01736 /*@switchbreak@*/ break; 01737 case 2: /* something went wrong! */ 01738 default: 01739 ourrc = 2; 01740 /*@switchbreak@*/ break; 01741 } 01742 } 01743 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* optional-dirname-and-symlink-deps */ 01744 } 01745 #endif 01746 01747 ps = rpmpsFree(ps); 01748 return ourrc; 01749 } 01750 01761 static int checkPackageSet(rpmts ts, const char * depName, 01762 /*@only@*/ /*@null@*/ rpmmi mi, int adding) 01763 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01764 /*@modifies ts, mi, rpmGlobalMacroContext, fileSystem, internalState @*/ 01765 { 01766 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 01767 rpmdepFlags depFlags = rpmtsDFlags(ts); 01768 rpmuint32_t tscolor = rpmtsColor(ts); 01769 int scareMem = 0; 01770 Header h; 01771 int terminate = 2; /* XXX terminate if rc >= terminate */ 01772 int ourrc = 0; 01773 01774 (void) rpmmiPrune(mi, 01775 ts->removedPackages, ts->numRemovedPackages, 1); 01776 while (ourrc < terminate && (h = rpmmiNext(mi)) != NULL) { 01777 rpmds requires = NULL; 01778 rpmds conflicts = NULL; 01779 rpmds dirnames = NULL; 01780 rpmds linktos = NULL; 01781 int rc; 01782 01783 he->tag = RPMTAG_NVRA; 01784 rc = (headerGet(h, he, 0) ? 0 : 2); 01785 if (rc > ourrc) 01786 ourrc = rc; 01787 if (ourrc >= terminate) { 01788 he->p.str = _free(he->p.str); 01789 break; 01790 } 01791 01792 if (!(depFlags & RPMDEPS_FLAG_NOREQUIRES)) 01793 requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem); 01794 if (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS)) 01795 conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem); 01796 if (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS)) 01797 dirnames = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem); 01798 if (!(depFlags & RPMDEPS_FLAG_NOLINKTOS)) 01799 linktos = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem); 01800 01801 (void) rpmdsSetNoPromote(requires, _rpmds_nopromote); 01802 (void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote); 01803 (void) rpmdsSetNoPromote(dirnames, _rpmds_nopromote); 01804 (void) rpmdsSetNoPromote(linktos, _rpmds_nopromote); 01805 01806 rc = checkPackageDeps(ts, he->p.str, 01807 requires, conflicts, dirnames, linktos, 01808 depName, tscolor, adding); 01809 01810 (void)rpmdsFree(linktos); 01811 linktos = NULL; 01812 (void)rpmdsFree(dirnames); 01813 dirnames = NULL; 01814 (void)rpmdsFree(conflicts); 01815 conflicts = NULL; 01816 (void)rpmdsFree(requires); 01817 requires = NULL; 01818 he->p.str = _free(he->p.str); 01819 01820 if (rc > ourrc) 01821 ourrc = rc; 01822 } 01823 mi = rpmmiFree(mi); 01824 01825 return ourrc; 01826 } 01827 01834 static int checkDependentPackages(rpmts ts, const char * depName) 01835 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01836 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 01837 { 01838 int rc = 0; 01839 01840 /* XXX rpmdb can be closed here, avoid error msg. */ 01841 if (rpmtsGetRdb(ts) != NULL) { 01842 rpmmi mi; 01843 mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, depName, 0); 01844 rc = checkPackageSet(ts, depName, mi, 0); 01845 } 01846 return rc; 01847 } 01848 01855 static int checkDependentConflicts(rpmts ts, const char * depName) 01856 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01857 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 01858 { 01859 int rc = 0; 01860 01861 /* XXX rpmdb can be closed here, avoid error msg. */ 01862 if (rpmtsGetRdb(ts) != NULL) { 01863 rpmmi mi; 01864 mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, depName, 0); 01865 rc = checkPackageSet(ts, depName, mi, 1); 01866 } 01867 01868 return rc; 01869 } 01870 01871 int _rpmtsCheck(rpmts ts) 01872 { 01873 const char * depName = NULL; 01874 rpmdepFlags depFlags = rpmtsDFlags(ts); 01875 rpmuint32_t tscolor = rpmtsColor(ts); 01876 rpmmi mi = NULL; 01877 rpmtsi pi = NULL; rpmte p; 01878 int closeatexit = 0; 01879 int xx; 01880 int terminate = 2; /* XXX terminate if rc >= terminate */ 01881 int rc = 0; 01882 int ourrc = 0; 01883 01884 if (_rpmts_debug) 01885 fprintf(stderr, "--> %s(%p) tsFlags 0x%x\n", __FUNCTION__, ts, rpmtsFlags(ts)); 01886 01887 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0); 01888 01889 /* Do lazy, readonly, open of rpm database. */ 01890 if (rpmtsGetRdb(ts) == NULL && rpmtsDBMode(ts) != -1) { 01891 rc = (rpmtsOpenDB(ts, rpmtsDBMode(ts)) ? 2 : 0); 01892 closeatexit = (rc == 0); 01893 } 01894 if (rc && (ourrc = rc) >= terminate) 01895 goto exit; 01896 01897 ts->probs = rpmpsFree(ts->probs); 01898 01899 rpmalMakeIndex(ts->addedPackages); 01900 01901 /* 01902 * Look at all of the added packages and make sure their dependencies 01903 * are satisfied. 01904 */ 01905 pi = rpmtsiInit(ts); 01906 while (ourrc < terminate && (p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01907 rpmds provides, requires, conflicts, dirnames, linktos; 01908 rpmfi fi; 01909 01910 /*@-nullpass@*/ /* FIX: rpmts{A,O} can return null. */ 01911 rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n", 01912 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 01913 /*@=nullpass@*/ 01914 requires = (!(depFlags & RPMDEPS_FLAG_NOREQUIRES) 01915 ? rpmteDS(p, RPMTAG_REQUIRENAME) : NULL); 01916 conflicts = (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS) 01917 ? rpmteDS(p, RPMTAG_CONFLICTNAME) : NULL); 01918 /* XXX srpm's don't have directory paths. */ 01919 if (p->isSource) { 01920 dirnames = NULL; 01921 linktos = NULL; 01922 } else { 01923 dirnames = (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS) 01924 ? rpmteDS(p, RPMTAG_DIRNAMES) : NULL); 01925 linktos = (!(depFlags & RPMDEPS_FLAG_NOLINKTOS) 01926 ? rpmteDS(p, RPMTAG_FILELINKTOS) : NULL); 01927 } 01928 01929 rc = checkPackageDeps(ts, rpmteNEVRA(p), 01930 requires, conflicts, dirnames, linktos, 01931 NULL, tscolor, 1); 01932 if (rc && (ourrc = rc) >= terminate) 01933 break; 01934 01935 provides = rpmteDS(p, RPMTAG_PROVIDENAME); 01936 provides = rpmdsInit(provides); 01937 if (provides != NULL) 01938 while (ourrc < terminate && rpmdsNext(provides) >= 0) { 01939 depName = _free(depName); 01940 depName = xstrdup(rpmdsN(provides)); 01941 01942 #ifdef NOTYET 01943 if (rpmdsNSType(provides) == RPMNS_TYPE_ENVVAR) { 01944 const char * EVR = rpmdsEVR(provides); 01945 if (rpmdsNegateRC(provides, 0)) 01946 EVR = NULL; 01947 if (envPut(depName, EVR)); 01948 rc = 2; 01949 } else 01950 #endif 01951 01952 /* Adding: check provides key against conflicts matches. */ 01953 if (checkDependentConflicts(ts, depName)) 01954 rc = 1; 01955 } 01956 if (rc && (ourrc = rc) >= terminate) 01957 break; 01958 01959 fi = rpmteFI(p, RPMTAG_BASENAMES); 01960 fi = rpmfiInit(fi, 0); 01961 while (ourrc < terminate && rpmfiNext(fi) >= 0) { 01962 depName = _free(depName); 01963 depName = xstrdup(rpmfiFN(fi)); 01964 /* Adding: check filename against conflicts matches. */ 01965 if (checkDependentConflicts(ts, depName)) 01966 rc = 1; 01967 } 01968 if (rc && (ourrc = rc) >= terminate) 01969 break; 01970 } 01971 pi = rpmtsiFree(pi); 01972 if (rc && (ourrc = rc) >= terminate) 01973 goto exit; 01974 01975 /* 01976 * Look at the removed packages and make sure they aren't critical. 01977 */ 01978 pi = rpmtsiInit(ts); 01979 while (ourrc < terminate && (p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { 01980 rpmds provides; 01981 rpmfi fi; 01982 01983 /*@-nullpass@*/ /* FIX: rpmts{A,O} can return null. */ 01984 rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n", 01985 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 01986 /*@=nullpass@*/ 01987 01988 provides = rpmteDS(p, RPMTAG_PROVIDENAME); 01989 provides = rpmdsInit(provides); 01990 if (provides != NULL) 01991 while (ourrc < terminate && rpmdsNext(provides) >= 0) { 01992 depName = _free(depName); 01993 depName = xstrdup(rpmdsN(provides)); 01994 01995 /* Erasing: check provides against requiredby matches. */ 01996 if (checkDependentPackages(ts, depName)) 01997 rc = 1; 01998 } 01999 if (rc && (ourrc = rc) >= terminate) 02000 break; 02001 02002 fi = rpmteFI(p, RPMTAG_BASENAMES); 02003 fi = rpmfiInit(fi, 0); 02004 while (ourrc < terminate && rpmfiNext(fi) >= 0) { 02005 depName = _free(depName); 02006 depName = xstrdup(rpmfiFN(fi)); 02007 /* Erasing: check filename against requiredby matches. */ 02008 if (checkDependentPackages(ts, depName)) 02009 rc = 1; 02010 } 02011 if (rc && (ourrc = rc) >= terminate) 02012 break; 02013 } 02014 pi = rpmtsiFree(pi); 02015 if (rc && (ourrc = rc) >= terminate) 02016 goto exit; 02017 02018 /* 02019 * Make sure transaction dependencies are satisfied. 02020 */ 02021 { const char * tsNEVRA = "transaction dependencies"; 02022 rpmds R = rpmdsFromPRCO(rpmtsPRCO(ts), RPMTAG_REQUIRENAME); 02023 rpmds C = rpmdsFromPRCO(rpmtsPRCO(ts), RPMTAG_CONFLICTNAME); 02024 rpmds D = NULL; 02025 rpmds L = NULL; 02026 const char * dep = NULL; 02027 int adding = 2; 02028 tscolor = 0; /* XXX no coloring for transaction dependencies. */ 02029 rc = checkPackageDeps(ts, tsNEVRA, R, C, D, L, dep, tscolor, adding); 02030 } 02031 if (rc && (ourrc = rc) >= terminate) 02032 goto exit; 02033 02034 exit: 02035 mi = rpmmiFree(mi); 02036 pi = rpmtsiFree(pi); 02037 depName = _free(depName); 02038 02039 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0); 02040 02041 if (closeatexit) 02042 xx = rpmtsCloseDB(ts); 02043 #if defined(CACHE_DEPENDENCY_RESULT) 02044 else if (_cacheDependsRC) 02045 xx = rpmdbCloseDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS); 02046 #endif 02047 02048 #ifdef NOTYET 02049 /* On failed dependencies, perform the autorollback goal (if any). */ 02050 { rpmps ps = rpmtsProblems(ts); 02051 if (rc || rpmpsNumProblems(ps) > 0) 02052 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL); 02053 ps = rpmpsFree(ps); 02054 } 02055 #endif 02056 02057 return ourrc; 02058 } 02059 02060 int (*rpmtsCheck) (rpmts ts) 02061 = _rpmtsCheck;