rpm
4.5
|
00001 00005 #include "system.h" 00006 00007 #include "rpmio_internal.h" /* XXX PGPHASHALGO_MD5 */ 00008 #include <rpmcli.h> /* XXX rpmcliPackagesTotal */ 00009 00010 #include <rpmmacro.h> /* XXX rpmExpand("%{_dependency_whiteout}" */ 00011 #include <envvar.h> 00012 #include <ugid.h> /* XXX user()/group() probes */ 00013 00014 /* XXX CACHE_DEPENDENCY_RESULT deprecated, functionality being reimplemented */ 00015 #define CACHE_DEPENDENCY_RESULT 1 00016 #if defined(CACHE_DEPENDENCY_RESULT) 00017 #define _RPMDB_INTERNAL /* XXX response cache needs dbiOpen et al. */ 00018 #endif 00019 #include "rpmdb.h" 00020 00021 #define _RPMEVR_INTERNAL 00022 #include "rpmds.h" 00023 #include "rpmfi.h" 00024 00025 #define _RPMTE_INTERNAL 00026 #include "rpmte.h" 00027 00028 #define _RPMTS_INTERNAL 00029 #include "rpmts.h" 00030 00031 #include "debug.h" 00032 00033 /*@access tsortInfo @*/ 00034 /*@access rpmte @*/ /* XXX for install <-> erase associate. */ 00035 /*@access rpmts @*/ 00036 /*@access rpmDiskSpaceInfo @*/ 00037 00038 /*@access alKey @*/ /* XXX for reordering and RPMAL_NOMATCH assign */ 00039 00042 typedef /*@abstract@*/ struct orderListIndex_s * orderListIndex; 00043 /*@access orderListIndex@*/ 00044 00047 struct orderListIndex_s { 00048 /*@dependent@*/ 00049 alKey pkgKey; 00050 int orIndex; 00051 }; 00052 00053 /*@unchecked@*/ 00054 #if defined(CACHE_DEPENDENCY_RESULT) 00055 int _cacheDependsRC = CACHE_DEPENDENCY_RESULT; 00056 #endif 00057 00058 /*@observer@*/ /*@unchecked@*/ 00059 const char *rpmNAME = PACKAGE; 00060 00061 /*@observer@*/ /*@unchecked@*/ 00062 const char *rpmEVR = VERSION; 00063 00064 /*@unchecked@*/ 00065 int rpmFLAGS = RPMSENSE_EQUAL; 00066 00073 static int intcmp(const void * a, const void * b) 00074 /*@requires maxRead(a) == 0 /\ maxRead(b) == 0 @*/ 00075 { 00076 const int * aptr = a; 00077 const int * bptr = b; 00078 int rc = (*aptr - *bptr); 00079 return rc; 00080 } 00081 00091 static int removePackage(rpmts ts, Header h, int dboffset, 00092 /*@null@*/ int * indexp, 00093 /*@exposed@*/ /*@dependent@*/ /*@null@*/ alKey depends) 00094 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00095 /*@modifies ts, h, *indexp, rpmGlobalMacroContext, fileSystem, internalState @*/ 00096 { 00097 rpmte p; 00098 00099 /* Filter out duplicate erasures. */ 00100 if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) { 00101 int * needle = NULL; 00102 /*@-boundswrite@*/ 00103 needle = bsearch(&dboffset, ts->removedPackages, ts->numRemovedPackages, 00104 sizeof(*ts->removedPackages), intcmp); 00105 if (needle != NULL) { 00106 /* XXX lastx should be per-call, not per-ts. */ 00107 if (indexp != NULL) 00108 *indexp = needle - ts->removedPackages; 00109 return 0; 00110 } 00111 /*@=boundswrite@*/ 00112 } 00113 00114 if (ts->numRemovedPackages == ts->allocedRemovedPackages) { 00115 ts->allocedRemovedPackages += ts->delta; 00116 ts->removedPackages = xrealloc(ts->removedPackages, 00117 sizeof(ts->removedPackages) * ts->allocedRemovedPackages); 00118 } 00119 00120 if (ts->removedPackages != NULL) { /* XXX can't happen. */ 00121 /*@-boundswrite@*/ 00122 ts->removedPackages[ts->numRemovedPackages] = dboffset; 00123 ts->numRemovedPackages++; 00124 /*@=boundswrite@*/ 00125 if (ts->numRemovedPackages > 1) 00126 qsort(ts->removedPackages, ts->numRemovedPackages, 00127 sizeof(*ts->removedPackages), intcmp); 00128 } 00129 00130 if (ts->orderCount >= ts->orderAlloced) { 00131 ts->orderAlloced += (ts->orderCount - ts->orderAlloced) + ts->delta; 00132 /*@-type +voidabstract @*/ 00133 ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced); 00134 /*@=type =voidabstract @*/ 00135 } 00136 00137 p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, dboffset, depends); 00138 /*@-boundswrite@*/ 00139 ts->order[ts->orderCount] = p; 00140 if (indexp != NULL) 00141 *indexp = ts->orderCount; 00142 ts->orderCount++; 00143 /*@=boundswrite@*/ 00144 00145 /*@-nullstate@*/ /* XXX FIX: ts->order[] can be NULL. */ 00146 return 0; 00147 /*@=nullstate@*/ 00148 } 00149 00156 static int rpmHeadersIdentical(Header first, Header second) 00157 /*@*/ 00158 { 00159 const char * one, * two; 00160 rpmds A, B; 00161 int rc; 00162 00163 if (!headerGetEntry(first, RPMTAG_HDRID, NULL, &one, NULL)) 00164 one = NULL; 00165 if (!headerGetEntry(second, RPMTAG_HDRID, NULL, &two, NULL)) 00166 two = NULL; 00167 00168 if (one && two) 00169 return ((strcmp(one, two) == 0) ? 1 : 0); 00170 if (one && !two) 00171 return 0; 00172 if (!one && two) 00173 return 0; 00174 /* XXX Headers w/o digests case devolves to NEVR comparison. */ 00175 A = rpmdsThis(first, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); 00176 B = rpmdsThis(second, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); 00177 rc = rpmdsCompare(A, B); 00178 A = rpmdsFree(A); 00179 B = rpmdsFree(B); 00180 return rc; 00181 } 00182 00183 00184 /*@unchecked@*/ 00185 static rpmTag _upgrade_tag; 00186 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL) 00187 /*@unchecked@*/ 00188 static rpmTag _debuginfo_tag; 00189 #endif /* SUPPORT_DEBUGINFO_UPGRADE_MODEL */ 00190 /*@unchecked@*/ 00191 static rpmTag _obsolete_tag; 00192 00201 static int rpmtsAddUpgrades(rpmts ts, rpmte p, uint32_t hcolor, Header h) 00202 { 00203 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00204 uint32_t tscolor = rpmtsColor(ts); 00205 alKey pkgKey = rpmteAddedKey(p); 00206 uint32_t ohcolor; 00207 rpmdbMatchIterator mi; 00208 Header oh; 00209 int xx; 00210 00211 if (_upgrade_tag == 0) { 00212 const char * t = rpmExpand("%{?_upgrade_tag}", NULL); 00213 /*@-mods@*/ 00214 _upgrade_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME); 00215 /*@=mods@*/ 00216 t = _free(t); 00217 } 00218 00219 mi = rpmtsInitIterator(ts, _upgrade_tag, rpmteN(p), 0); 00220 while((oh = rpmdbNextIterator(mi)) != NULL) { 00221 int lastx; 00222 rpmte q; 00223 00224 /* Ignore colored packages not in our rainbow. */ 00225 ohcolor = hGetColor(oh); 00226 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor)) 00227 continue; 00228 00229 #if defined(SUPPORT_ORIGINTID) 00230 /* Snarf the original install tid & time from older package(s). */ 00231 he->tag = RPMTAG_ORIGINTID; 00232 xx = headerGet(oh, he, 0); 00233 if (xx && he->p.ui32p != NULL) { 00234 if (p->originTid[0] == 0 || p->originTid[0] > he->p.ui32p[0] 00235 || (he->c > 1 && p->originTid[0] == he->p.ui32p[0] && p->originTid[1] > he->p.ui32p[1])) 00236 { 00237 p->originTid[0] = he->p.ui32p[0]; 00238 p->originTid[1] = (he->c > 1 ? he->p.ui32p[1] : 0); 00239 } 00240 he->p.ptr = _free(he->p.ptr); 00241 } 00242 he->tag = RPMTAG_ORIGINTIME; 00243 xx = headerGet(oh, he, 0); 00244 if (xx && he->p.ui32p != NULL) { 00245 if (p->originTime[0] == 0 || p->originTime[0] > he->p.ui32p[0] 00246 || (he->c > 1 && p->originTime[0] == he->p.ui32p[0] && p->originTime[1] > he->p.ui32p[1])) 00247 { 00248 p->originTime[0] = he->p.ui32p[0]; 00249 p->originTime[1] = (he->c > 1 ? he->p.ui32p[1] : 0); 00250 } 00251 he->p.ptr = _free(he->p.ptr); 00252 } 00253 #endif /* SUPPORT_ORIGINTID */ 00254 00255 /* Skip identical packages. */ 00256 if (rpmHeadersIdentical(h, oh)) 00257 continue; 00258 00259 /* Create an erasure element. */ 00260 lastx = -1; 00261 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), &lastx, pkgKey); 00262 assert(lastx >= 0 && lastx < ts->orderCount); 00263 q = ts->order[lastx]; 00264 00265 /* Chain through upgrade flink. */ 00266 xx = rpmteChain(p, q, oh, "Upgrades"); 00267 00268 /*@-nullptrarith@*/ 00269 rpmlog(RPMLOG_DEBUG, D_(" upgrade erases %s\n"), rpmteNEVRA(q)); 00270 /*@=nullptrarith@*/ 00271 00272 } 00273 mi = rpmdbFreeIterator(mi); 00274 00275 return 0; 00276 } 00277 00278 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL) 00279 00285 static inline int chkSuffix(const char * fn, const char * suffix) 00286 /*@*/ 00287 { 00288 size_t flen = strlen(fn); 00289 size_t slen = strlen(suffix); 00290 return (flen > slen && !strcmp(fn + flen - slen, suffix)); 00291 } 00292 00301 static int rpmtsEraseDebuginfo(rpmts ts, rpmte p, Header h, alKey pkgKey) 00302 { 00303 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00304 const void *keyval = NULL; 00305 size_t keylen = 0; 00306 size_t nrefs = 0; 00307 uint32_t debuginfoInstance = 0; 00308 Header debuginfoHeader = NULL; 00309 rpmdbMatchIterator mi; 00310 Header oh; 00311 int xx; 00312 00313 /* XXX SOURCEPKGID is not populated reliably, do not use (yet). */ 00314 if (_debuginfo_tag == 0) { 00315 const char * t = rpmExpand("%{?_debuginfo_tag}", NULL); 00316 /*@-mods@*/ 00317 _debuginfo_tag = (*t != '\0' && !strcmp(t, "pkgid") 00318 ? RPMTAG_SOURCEPKGID : RPMTAG_SOURCERPM); 00319 /*@=mods@*/ 00320 t = _free(t); 00321 } 00322 00323 /* Grab the retrieval key. */ 00324 switch (_debuginfo_tag) { 00325 default: return 0; /*@notreached@*/ break; 00326 case RPMTAG_SOURCERPM: keyval = rpmteSourcerpm(p); break; 00327 } 00328 00329 /* Count remaining members in build set, excluding -debuginfo (if any). */ 00330 mi = rpmtsInitIterator(ts, _debuginfo_tag, keyval, keylen); 00331 xx = rpmdbPruneIterator(mi, ts->removedPackages, ts->numRemovedPackages, 1); 00332 while((oh = rpmdbNextIterator(mi)) != NULL) { 00333 /* Skip identical packages. */ 00334 if (rpmHeadersIdentical(h, oh)) 00335 continue; 00336 00337 he->tag = RPMTAG_NAME; 00338 xx = headerGet(oh, he, 0); 00339 if (!xx || he->p.str == NULL) 00340 continue; 00341 /* Save the -debuginfo member. */ 00342 if (chkSuffix(he->p.str, "-debuginfo")) { 00343 debuginfoInstance = rpmdbGetIteratorOffset(mi); 00344 debuginfoHeader = headerLink(oh); 00345 } else 00346 nrefs++; 00347 he->p.str = _free(he->p.str); 00348 } 00349 mi = rpmdbFreeIterator(mi); 00350 00351 /* Remove -debuginfo package when last build member is erased. */ 00352 if (nrefs == 0 && debuginfoInstance > 0 && debuginfoHeader != NULL) { 00353 int lastx = -1; 00354 rpmte q; 00355 00356 /* Create an erasure element. */ 00357 lastx = -1; 00358 xx = removePackage(ts, debuginfoHeader, debuginfoInstance, 00359 &lastx, pkgKey); 00360 assert(lastx >= 0 && lastx < ts->orderCount); 00361 q = ts->order[lastx]; 00362 00363 /* Chain through upgrade flink. */ 00364 /* XXX avoid assertion failure when erasing. */ 00365 if (pkgKey != RPMAL_NOMATCH) 00366 xx = rpmteChain(p, q, oh, "Upgrades"); 00367 00368 /*@-nullptrarith@*/ 00369 rpmlog(RPMLOG_DEBUG, D_(" lastref erases %s\n"), rpmteNEVRA(q)); 00370 /*@=nullptrarith@*/ 00371 00372 } 00373 debuginfoHeader = headerFree(debuginfoHeader); 00374 00375 return nrefs; 00376 } 00377 #endif /* SUPPORT_DEBUGINFO_UPGRADE_MODEL */ 00378 00386 static int rpmtsAddObsoletes(rpmts ts, rpmte p, uint32_t hcolor) 00387 { 00388 uint32_t tscolor = rpmtsColor(ts); 00389 alKey pkgKey = rpmteAddedKey(p); 00390 uint32_t ohcolor; 00391 rpmds obsoletes; 00392 uint32_t dscolor; 00393 rpmdbMatchIterator mi; 00394 Header oh; 00395 int xx; 00396 00397 if (_obsolete_tag == 0) { 00398 const char *t = rpmExpand("%{?_obsolete_tag}", NULL); 00399 /*@-mods@*/ 00400 _obsolete_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME); 00401 /*@=mods@*/ 00402 t = _free(t); 00403 } 00404 00405 obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME), "Obsoletes"); 00406 obsoletes = rpmdsInit(obsoletes); 00407 if (obsoletes != NULL) 00408 while (rpmdsNext(obsoletes) >= 0) { 00409 const char * Name; 00410 00411 if ((Name = rpmdsN(obsoletes)) == NULL) 00412 continue; /* XXX can't happen */ 00413 00414 /* Ignore colored obsoletes not in our rainbow. */ 00415 #if 0 00416 /* XXX obsoletes are never colored, so this is for future devel. */ 00417 dscolor = rpmdsColor(obsoletes); 00418 #else 00419 dscolor = hcolor; 00420 #endif 00421 if (tscolor && dscolor && !(tscolor & dscolor)) 00422 continue; 00423 00424 /* XXX avoid self-obsoleting packages. */ 00425 if (!strcmp(rpmteN(p), Name)) 00426 continue; 00427 00428 /* Obsolete containing package if given a file, otherwise provide. */ 00429 if (Name[0] == '/') 00430 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0); 00431 else 00432 mi = rpmtsInitIterator(ts, _obsolete_tag, Name, 0); 00433 00434 xx = rpmdbPruneIterator(mi, 00435 ts->removedPackages, ts->numRemovedPackages, 1); 00436 00437 while((oh = rpmdbNextIterator(mi)) != NULL) { 00438 int lastx; 00439 rpmte q; 00440 00441 /* Ignore colored packages not in our rainbow. */ 00442 ohcolor = hGetColor(oh); 00443 00444 /* XXX provides *are* colored, effectively limiting Obsoletes: 00445 to matching only colored Provides: based on pkg coloring. */ 00446 if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor)) 00447 /*@innercontinue@*/ continue; 00448 00449 /* 00450 * Rpm prior to 3.0.3 does not have versioned obsoletes. 00451 * If no obsoletes version info is available, match all names. 00452 */ 00453 if (!(rpmdsEVR(obsoletes) == NULL 00454 || rpmdsAnyMatchesDep(oh, obsoletes, _rpmds_nopromote))) 00455 /*@innercontinue@*/ continue; 00456 00457 /* Create an erasure element. */ 00458 lastx = -1; 00459 xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), &lastx, pkgKey); 00460 assert(lastx >= 0 && lastx < ts->orderCount); 00461 q = ts->order[lastx]; 00462 00463 /* Chain through obsoletes flink. */ 00464 xx = rpmteChain(p, q, oh, "Obsoletes"); 00465 00466 /*@-nullptrarith@*/ 00467 rpmlog(RPMLOG_DEBUG, D_(" Obsoletes: %s\t\terases %s\n"), 00468 rpmdsDNEVR(obsoletes)+2, rpmteNEVRA(q)); 00469 /*@=nullptrarith@*/ 00470 } 00471 mi = rpmdbFreeIterator(mi); 00472 } 00473 obsoletes = rpmdsFree(obsoletes); 00474 00475 return 0; 00476 } 00477 00478 00479 int rpmtsAddInstallElement(rpmts ts, Header h, 00480 fnpyKey key, int upgrade, rpmRelocation relocs) 00481 { 00482 rpmdepFlags depFlags = rpmtsDFlags(ts); 00483 uint_32 tscolor = rpmtsColor(ts); 00484 uint_32 hcolor; 00485 int isSource; 00486 int duplicate = 0; 00487 rpmtsi pi = NULL; rpmte p; 00488 HGE_t hge = (HGE_t)headerGetEntryMinMemory; 00489 const char * arch; 00490 const char * os; 00491 rpmds oldChk, newChk; 00492 alKey pkgKey; /* addedPackages key */ 00493 int xx; 00494 int ec = 0; 00495 int rc; 00496 int oc; 00497 00498 hcolor = hGetColor(h); 00499 pkgKey = RPMAL_NOMATCH; 00500 00501 /* 00502 * Always add source headers. 00503 */ 00504 isSource = (headerIsEntry(h, RPMTAG_SOURCERPM) == 0) ; 00505 if (isSource) { 00506 oc = ts->orderCount; 00507 goto addheader; 00508 } 00509 00510 /* 00511 * Check platform affinity of binary packages. 00512 */ 00513 arch = NULL; 00514 xx = hge(h, RPMTAG_ARCH, NULL, &arch, NULL); 00515 os = NULL; 00516 xx = hge(h, RPMTAG_OS, NULL, &os, NULL); 00517 if (nplatpat > 1) { 00518 const char * platform = NULL; 00519 00520 if (hge(h, RPMTAG_PLATFORM, NULL, &platform, NULL)) 00521 platform = xstrdup(platform); 00522 else 00523 platform = rpmExpand(arch, "-unknown-", os, NULL); 00524 00525 rc = rpmPlatformScore(platform, platpat, nplatpat); 00526 if (rc <= 0) { 00527 const char * pkgNEVR = hGetNEVRA(h, NULL); 00528 rpmps ps = rpmtsProblems(ts); 00529 rpmpsAppend(ps, RPMPROB_BADPLATFORM, pkgNEVR, key, 00530 platform, NULL, NULL, 0); 00531 ps = rpmpsFree(ps); 00532 pkgNEVR = _free(pkgNEVR); 00533 ec = 1; 00534 } 00535 platform = _free(platform); 00536 if (ec) 00537 goto exit; 00538 } 00539 00540 /* 00541 * Always install compatible binary packages. 00542 */ 00543 if (!upgrade) { 00544 oc = ts->orderCount; 00545 goto addheader; 00546 } 00547 00548 /* 00549 * Check that upgrade package is uniquely newer, replace older if necessary. 00550 */ 00551 oldChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_LESS)); 00552 newChk = rpmdsThis(h, RPMTAG_REQUIRENAME, (RPMSENSE_EQUAL|RPMSENSE_GREATER)); 00553 /* XXX can't use rpmtsiNext() filter or oc will have wrong value. */ 00554 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) { 00555 rpmds this; 00556 00557 /* XXX Only added packages need be checked for dupes here. */ 00558 if (rpmteType(p) == TR_REMOVED) 00559 continue; 00560 00561 /* XXX Never check source header NEVRAO. */ 00562 if (rpmteIsSource(p)) 00563 continue; 00564 00565 if (tscolor) { 00566 const char * parch; 00567 const char * pos; 00568 00569 if (arch == NULL || (parch = rpmteA(p)) == NULL) 00570 continue; 00571 /* XXX hackery for i[3456]86 alias matching. */ 00572 if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') { 00573 if (arch[0] != parch[0]) continue; 00574 if (arch[2] != parch[2]) continue; 00575 if (arch[3] != parch[3]) continue; 00576 } else if (strcmp(arch, parch)) 00577 continue; 00578 if (os == NULL || (pos = rpmteO(p)) == NULL) 00579 continue; 00580 00581 if (strcmp(os, pos)) 00582 continue; 00583 } 00584 00585 /* OK, binary rpm's with same arch and os. Check NEVR. */ 00586 if ((this = rpmteDS(p, RPMTAG_NAME)) == NULL) 00587 continue; /* XXX can't happen */ 00588 00589 /* If newer NEVRAO already added, then skip adding older. */ 00590 rc = rpmdsCompare(newChk, this); 00591 if (rc != 0) { 00592 const char * pkgNEVR = rpmdsDNEVR(this); 00593 const char * addNEVR = rpmdsDNEVR(oldChk); 00594 if (rpmIsVerbose()) 00595 rpmMessage(RPMMESS_WARNING, 00596 _("package %s was already added, skipping %s\n"), 00597 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"), 00598 (addNEVR ? addNEVR + 2 : "?addNEVR?")); 00599 ec = 1; 00600 break; 00601 } 00602 00603 /* If older NEVRAO already added, then replace old with new. */ 00604 rc = rpmdsCompare(oldChk, this); 00605 if (rc != 0) { 00606 const char * pkgNEVR = rpmdsDNEVR(this); 00607 const char * addNEVR = rpmdsDNEVR(newChk); 00608 if (rpmIsVerbose()) 00609 rpmMessage(RPMMESS_WARNING, 00610 _("package %s was already added, replacing with %s\n"), 00611 (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"), 00612 (addNEVR ? addNEVR + 2 : "?addNEVR?")); 00613 duplicate = 1; 00614 pkgKey = rpmteAddedKey(p); 00615 break; 00616 } 00617 } 00618 pi = rpmtsiFree(pi); 00619 oldChk = rpmdsFree(oldChk); 00620 newChk = rpmdsFree(newChk); 00621 00622 /* If newer (or same) NEVRAO was already added, exit now. */ 00623 if (ec) 00624 goto exit; 00625 00626 addheader: 00627 if (oc >= ts->orderAlloced) { 00628 ts->orderAlloced += (oc - ts->orderAlloced) + ts->delta; 00629 /*@-type +voidabstract @*/ 00630 ts->order = xrealloc(ts->order, ts->orderAlloced * sizeof(*ts->order)); 00631 /*@=type =voidabstract @*/ 00632 } 00633 00634 p = rpmteNew(ts, h, TR_ADDED, key, relocs, -1, pkgKey); 00635 assert(p != NULL); 00636 00637 if (duplicate && oc < ts->orderCount) { 00638 /*@-type -unqualifiedtrans@*/ 00639 /*@-boundswrite@*/ 00640 ts->order[oc] = rpmteFree(ts->order[oc]); 00641 /*@=boundswrite@*/ 00642 /*@=type =unqualifiedtrans@*/ 00643 } 00644 00645 /*@-boundswrite@*/ 00646 ts->order[oc] = p; 00647 /*@=boundswrite@*/ 00648 if (!duplicate) { 00649 ts->orderCount++; 00650 rpmcliPackagesTotal++; 00651 } 00652 00653 pkgKey = rpmalAdd(&ts->addedPackages, pkgKey, rpmteKey(p), 00654 rpmteDS(p, RPMTAG_PROVIDENAME), 00655 rpmteFI(p, RPMTAG_BASENAMES), tscolor); 00656 if (pkgKey == RPMAL_NOMATCH) { 00657 /*@-boundswrite@*/ 00658 ts->order[oc] = rpmteFree(ts->order[oc]); 00659 /*@=boundswrite@*/ 00660 ts->teInstall = NULL; 00661 ec = 1; 00662 goto exit; 00663 } 00664 (void) rpmteSetAddedKey(p, pkgKey); 00665 00666 if (!duplicate) { 00667 ts->numAddedPackages++; 00668 } 00669 00670 ts->teInstall = ts->order[oc]; 00671 00672 /* XXX rpmgi hack: Save header in transaction element if requested. */ 00673 if (upgrade & 0x2) 00674 (void) rpmteSetHeader(p, h); 00675 00676 /* If not upgrading, then we're done. */ 00677 if (!(upgrade & 0x1)) 00678 goto exit; 00679 00680 /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */ 00681 /* If source rpm, then we're done. */ 00682 if (isSource) 00683 goto exit; 00684 00685 /* Do lazy (readonly?) open of rpm database. */ 00686 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) { 00687 if ((ec = rpmtsOpenDB(ts, ts->dbmode)) != 0) 00688 goto exit; 00689 } 00690 00691 /* Add upgrades to the transaction (if not disabled). */ 00692 if (!(depFlags & RPMDEPS_FLAG_NOUPGRADE)) { 00693 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL) 00694 /* 00695 * Don't upgrade -debuginfo until build set is empty. 00696 * 00697 * XXX Almost, but not quite, correct since the test depends on 00698 * added package arrival order. 00699 * I.e. -debuginfo additions must always follow all 00700 * other additions so that erasures of other members in the 00701 * same build set are seen if/when included in the same transaction. 00702 */ 00703 xx = rpmtsEraseDebuginfo(ts, p, h, pkgKey); 00704 if (!chkSuffix(rpmteN(p), "-debuginfo") || xx == 0) 00705 #endif /* SUPPORT_DEBUGINFO_UPGRADE_MODEL */ 00706 xx = rpmtsAddUpgrades(ts, p, hcolor, h); 00707 } 00708 00709 /* Add Obsoletes: to the transaction (if not disabled). */ 00710 if (!(depFlags & RPMDEPS_FLAG_NOOBSOLETES)) { 00711 xx = rpmtsAddObsoletes(ts, p, hcolor); 00712 } 00713 ec = 0; 00714 00715 exit: 00716 pi = rpmtsiFree(pi); 00717 return ec; 00718 } 00719 00720 int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset) 00721 { 00722 int oc = -1; 00723 int rc = removePackage(ts, h, dboffset, &oc, RPMAL_NOMATCH); 00724 if (rc == 0 && oc >= 0 && oc < ts->orderCount) { 00725 #if defined(SUPPORT_DEBUGINFO_UPGRADE_MODEL) 00726 (void) rpmtsEraseDebuginfo(ts, ts->order[oc], h, RPMAL_NOMATCH); 00727 #endif /* SUPPORT_DEBUGINFO_UPGRADE_MODEL */ 00728 ts->teErase = ts->order[oc]; 00729 } else 00730 ts->teErase = NULL; 00731 return rc; 00732 } 00733 00741 static int unsatisfiedDepend(rpmts ts, rpmds dep, int adding) 00742 /*@globals _cacheDependsRC, rpmGlobalMacroContext, h_errno, 00743 fileSystem, internalState @*/ 00744 /*@modifies ts, dep, _cacheDependsRC, rpmGlobalMacroContext, 00745 fileSystem, internalState @*/ 00746 { 00747 DBT * key = alloca(sizeof(*key)); 00748 DBT * data = alloca(sizeof(*data)); 00749 rpmdbMatchIterator mi; 00750 nsType NSType; 00751 const char * Name; 00752 int_32 Flags; 00753 Header h; 00754 #if defined(CACHE_DEPENDENCY_RESULT) 00755 int _cacheThisRC = 1; 00756 #endif 00757 int rc; 00758 int xx; 00759 int retries = 10; 00760 00761 if ((Name = rpmdsN(dep)) == NULL) 00762 return 0; /* XXX can't happen */ 00763 Flags = rpmdsFlags(dep); 00764 NSType = rpmdsNSType(dep); 00765 00766 /* 00767 * Check if dbiOpen/dbiPut failed (e.g. permissions), we can't cache. 00768 */ 00769 #if defined(CACHE_DEPENDENCY_RESULT) 00770 if (_cacheDependsRC) { 00771 dbiIndex dbi; 00772 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0); 00773 if (dbi == NULL) 00774 _cacheDependsRC = 0; 00775 else { 00776 const char * DNEVR; 00777 00778 rc = -1; 00779 /*@-branchstate@*/ 00780 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) { 00781 DBC * dbcursor = NULL; 00782 void * datap = NULL; 00783 size_t datalen = 0; 00784 size_t DNEVRlen = strlen(DNEVR); 00785 00786 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, 0); 00787 00788 memset(key, 0, sizeof(*key)); 00789 /*@i@*/ key->data = (void *) DNEVR; 00790 key->size = DNEVRlen; 00791 memset(data, 0, sizeof(*data)); 00792 data->data = datap; 00793 data->size = datalen; 00794 /*@-nullstate@*/ /* FIX: data->data may be NULL */ 00795 xx = dbiGet(dbi, dbcursor, key, data, DB_SET); 00796 /*@=nullstate@*/ 00797 DNEVR = key->data; 00798 DNEVRlen = key->size; 00799 datap = data->data; 00800 datalen = data->size; 00801 00802 /*@-boundswrite@*/ 00803 if (xx == 0 && datap && datalen == 4) 00804 memcpy(&rc, datap, datalen); 00805 /*@=boundswrite@*/ 00806 xx = dbiCclose(dbi, dbcursor, 0); 00807 } 00808 /*@=branchstate@*/ 00809 00810 if (rc >= 0) { 00811 rpmdsNotify(dep, _("(cached)"), rc); 00812 return rpmdsNegateRC(dep, rc); 00813 } 00814 } 00815 } 00816 #endif 00817 00818 retry: 00819 rc = 0; /* assume dependency is satisfied */ 00820 00821 /* Expand macro probe dependencies. */ 00822 if (NSType == RPMNS_TYPE_FUNCTION) { 00823 xx = rpmExpandNumeric(Name); 00824 rc = (xx ? 0 : 1); 00825 if (Flags & RPMSENSE_MISSINGOK) 00826 goto unsatisfied; 00827 rpmdsNotify(dep, _("(function probe)"), rc); 00828 goto exit; 00829 } 00830 00831 #if 0 00832 /* Evaluate user/group lookup probes. */ 00833 if (NSType == RPMNS_TYPE_USER) { 00834 const char *s; 00835 uid_t uid = 0; 00836 s = Name; while (*s && xisdigit(*s)) s++; 00837 00838 if (*s) 00839 xx = unameToUid(Name, &uid); 00840 else { 00841 uid = strtol(Name, NULL, 10); 00842 xx = (uidToUname(uid) ? 0 : -1); 00843 } 00844 rc = (xx >= 0 ? 0 : 1); 00845 if (Flags & RPMSENSE_MISSINGOK) 00846 goto unsatisfied; 00847 rpmdsNotify(dep, _("(user lookup)"), rc); 00848 goto exit; 00849 } 00850 if (NSType == RPMNS_TYPE_GROUP) { 00851 const char *s; 00852 gid_t gid = 0; 00853 s = Name; while (*s && xisdigit(*s)) s++; 00854 00855 if (*s) 00856 xx = gnameToGid(Name, &gid); 00857 else { 00858 gid = strtol(Name, NULL, 10); 00859 xx = (gidToGname(gid) ? 0 : -1); 00860 } 00861 rc = (xx >= 0 ? 0 : 1); 00862 if (Flags & RPMSENSE_MISSINGOK) 00863 goto unsatisfied; 00864 rpmdsNotify(dep, _("(group lookup)"), rc); 00865 goto exit; 00866 } 00867 #endif 00868 00869 /* Evaluate access(2) probe dependencies. */ 00870 if (NSType == RPMNS_TYPE_ACCESS) { 00871 rc = rpmioAccess(Name, NULL, X_OK); 00872 if (Flags & RPMSENSE_MISSINGOK) 00873 goto unsatisfied; 00874 rpmdsNotify(dep, _("(access probe)"), rc); 00875 goto exit; 00876 } 00877 00878 /* Evaluate mtab lookup and diskspace probe dependencies. */ 00879 if (NSType == RPMNS_TYPE_MOUNTED) { 00880 const char ** fs = NULL; 00881 int nfs = 0; 00882 int i = 0; 00883 00884 xx = rpmtsInitDSI(ts); 00885 fs = ts->filesystems; 00886 nfs = ts->filesystemCount; 00887 00888 if (fs != NULL) 00889 for (i = 0; i < nfs; i++) { 00890 if (!strcmp(fs[i], Name)) 00891 break; 00892 } 00893 rc = (i < nfs ? 0 : 1); 00894 if (Flags & RPMSENSE_MISSINGOK) 00895 goto unsatisfied; 00896 rpmdsNotify(dep, _("(mtab probe)"), rc); 00897 goto exit; 00898 } 00899 00900 if (NSType == RPMNS_TYPE_DISKSPACE) { 00901 size_t nb = strlen(Name); 00902 rpmDiskSpaceInfo dsi = NULL; 00903 const char ** fs = NULL; 00904 size_t fslen = 0, longest = 0; 00905 int nfs = 0; 00906 int i = 0; 00907 00908 xx = rpmtsInitDSI(ts); 00909 fs = ts->filesystems; 00910 nfs = ts->filesystemCount; 00911 00912 if (fs != NULL) 00913 for (i = 0; i < nfs; i++) { 00914 fslen = strlen(fs[i]); 00915 if (fslen > nb) 00916 continue; 00917 if (strncmp(fs[i], Name, fslen)) 00918 continue; 00919 if (fslen > 1 && Name[fslen] != '/' && Name[fslen] != '\0') 00920 continue; 00921 if (fslen < longest) 00922 continue; 00923 longest = fslen; 00924 dsi = ts->dsi + i; 00925 } 00926 if (dsi == NULL) 00927 rc = 1; /* no mounted paths !?! */ 00928 else { 00929 char * end = NULL; 00930 long long needed = strtoll(rpmdsEVR(dep), &end, 0); 00931 00932 if (end && *end) { 00933 if (strchr("Gg", end[0]) && strchr("Bb", end[1]) && !end[2]) 00934 needed *= 1024 * 1024 * 1024; 00935 if (strchr("Mm", end[0]) && strchr("Bb", end[1]) && !end[2]) 00936 needed *= 1024 * 1024; 00937 if (strchr("Kk", end[0]) && strchr("Bb", end[1]) && !end[2]) 00938 needed *= 1024; 00939 } else 00940 needed *= 1024 * 1024; /* XXX assume Mb if no units given */ 00941 00942 needed = BLOCK_ROUND(needed, dsi->f_bsize); 00943 xx = (dsi->f_bavail - needed); 00944 if ((Flags & RPMSENSE_LESS) && xx < 0) rc = 0; 00945 else if ((Flags & RPMSENSE_GREATER) && xx > 0) rc = 0; 00946 else if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0; 00947 else rc = 1; 00948 } 00949 if (Flags & RPMSENSE_MISSINGOK) 00950 goto unsatisfied; 00951 rpmdsNotify(dep, _("(diskspace probe)"), rc); 00952 goto exit; 00953 } 00954 00955 if (NSType == RPMNS_TYPE_DIGEST) { 00956 const char * EVR = rpmdsEVR(dep); 00957 FD_t fd = Fopen(Name, "r"); 00958 00959 rc = 1; /* XXX assume failure */ 00960 if (fd && !Ferror(fd)) { 00961 pgpHashAlgo digestHashAlgo = PGPHASHALGO_MD5; 00962 DIGEST_CTX ctx = rpmDigestInit(digestHashAlgo, RPMDIGEST_NONE); 00963 const char * digest = NULL; 00964 size_t digestlen = 0; 00965 int asAscii = 1; 00966 size_t nbuf = 8 * BUFSIZ; 00967 char * buf = alloca(nbuf); 00968 size_t nb; 00969 00970 while ((nb = Fread(buf, sizeof(buf[0]), nbuf, fd)) > 0) 00971 xx = rpmDigestUpdate(ctx, buf, nb); 00972 xx = Fclose(fd); fd = NULL; 00973 xx = rpmDigestFinal(ctx, &digest, &digestlen, asAscii); 00974 00975 xx = (EVR && *EVR && digest && *digest) ? strcmp(EVR, digest) : -1; 00976 /* XXX only equality makes sense for digest compares */ 00977 if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0; 00978 } 00979 if (Flags & RPMSENSE_MISSINGOK) 00980 goto unsatisfied; 00981 rpmdsNotify(dep, _("(digest probe)"), rc); 00982 goto exit; 00983 } 00984 00985 if (NSType == RPMNS_TYPE_GNUPG) { 00986 static const char gnupg_pre[] = "%(%{__gpg} -qv "; 00987 static const char gnupg_post[] = " 2>/dev/null; echo $?)"; 00988 const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL); 00989 00990 rc = (t && t[0] == '0') ? 0 : 1; 00991 t = _free(t); 00992 if (Flags & RPMSENSE_MISSINGOK) 00993 goto unsatisfied; 00994 rpmdsNotify(dep, _("(gnupg probe)"), rc); 00995 goto exit; 00996 } 00997 00998 if (NSType == RPMNS_TYPE_MACRO) { 00999 static const char macro_pre[] = "%{?"; 01000 static const char macro_post[] = ":0}"; 01001 const char * a = rpmExpand(macro_pre, Name, macro_post, NULL); 01002 01003 rc = (a && a[0] == '0') ? 0 : 1; 01004 a = _free(a); 01005 if (Flags & RPMSENSE_MISSINGOK) 01006 goto unsatisfied; 01007 rpmdsNotify(dep, _("(macro probe)"), rc); 01008 goto exit; 01009 } 01010 01011 if (NSType == RPMNS_TYPE_ENVVAR) { 01012 const char * a = envGet(Name); 01013 const char * b = rpmdsEVR(dep); 01014 01015 /* Existence test if EVR is missing/empty. */ 01016 if (!(b && *b)) 01017 rc = (!(a && *a)); 01018 else { 01019 int sense = (a && *a) ? strcmp(a, b) : -1; 01020 01021 if ((Flags & RPMSENSE_SENSEMASK) == RPMSENSE_NOTEQUAL) 01022 rc = (sense == 0); 01023 else if (sense < 0 && (Flags & RPMSENSE_LESS)) 01024 rc = 0; 01025 else if (sense > 0 && (Flags & RPMSENSE_GREATER)) 01026 rc = 0; 01027 else if (sense == 0 && (Flags & RPMSENSE_EQUAL)) 01028 rc = 0; 01029 else 01030 rc = (sense != 0); 01031 } 01032 01033 if (Flags & RPMSENSE_MISSINGOK) 01034 goto unsatisfied; 01035 rpmdsNotify(dep, _("(envvar probe)"), rc); 01036 goto exit; 01037 } 01038 01039 if (NSType == RPMNS_TYPE_RUNNING) { 01040 char *t = NULL; 01041 pid_t pid = strtol(Name, &t, 10); 01042 01043 if (t == NULL || *t != '\0') { 01044 const char * fn = rpmGetPath("%{_varrun}/", Name, ".pid", NULL); 01045 FD_t fd = NULL; 01046 01047 if (fn && *fn != '%' && (fd = Fopen(fn, "r")) && !Ferror(fd)) { 01048 char buf[32]; 01049 size_t nb = Fread(buf, sizeof(buf[0]), sizeof(buf), fd); 01050 01051 if (nb > 0) 01052 pid = strtol(buf, &t, 10); 01053 } else 01054 pid = 0; 01055 if (fd != NULL) 01056 (void) Fclose(fd); 01057 fn = _free(fn); 01058 } 01059 rc = (pid > 0 ? (kill(pid, 0) < 0 && errno == ESRCH) : 1); 01060 if (Flags & RPMSENSE_MISSINGOK) 01061 goto unsatisfied; 01062 rpmdsNotify(dep, _("(running probe)"), rc); 01063 goto exit; 01064 } 01065 01066 /* Search system configured provides. */ 01067 01068 if (!rpmioAccess("/etc/rpm/sysinfo", NULL, R_OK)) { 01069 #ifdef NOTYET /* XXX just sysinfo Provides: for now. */ 01070 rpmTag tagN = (Name[0] == '/' ? RPMTAG_DIRNAMES : RPMTAG_PROVIDENAME); 01071 #else 01072 rpmTag tagN = RPMTAG_PROVIDENAME; 01073 #endif 01074 rpmds P = rpmdsFromPRCO(ts->PRCO, tagN); 01075 if (rpmdsSearch(P, dep) >= 0) { 01076 rpmdsNotify(dep, _("(sysinfo provides)"), rc); 01077 goto exit; 01078 } 01079 } 01080 01081 /* 01082 * New features in rpm packaging implicitly add versioned dependencies 01083 * on rpmlib provides. The dependencies look like "rpmlib(YaddaYadda)". 01084 * Check those dependencies now. 01085 */ 01086 if (NSType == RPMNS_TYPE_RPMLIB) { 01087 static rpmds rpmlibP = NULL; 01088 static int oneshot = -1; 01089 01090 if (oneshot) 01091 oneshot = rpmdsRpmlib(&rpmlibP, NULL); 01092 if (rpmlibP == NULL) 01093 goto unsatisfied; 01094 01095 if (rpmdsSearch(rpmlibP, dep) >= 0) { 01096 rpmdsNotify(dep, _("(rpmlib provides)"), rc); 01097 goto exit; 01098 } 01099 goto unsatisfied; 01100 } 01101 01102 if (NSType == RPMNS_TYPE_CPUINFO) { 01103 static rpmds cpuinfoP = NULL; 01104 static int oneshot = -1; 01105 01106 if (oneshot) 01107 oneshot = rpmdsCpuinfo(&cpuinfoP, NULL); 01108 if (cpuinfoP == NULL) 01109 goto unsatisfied; 01110 01111 if (rpmdsSearch(cpuinfoP, dep) >= 0) { 01112 rpmdsNotify(dep, _("(cpuinfo provides)"), rc); 01113 goto exit; 01114 } 01115 goto unsatisfied; 01116 } 01117 01118 if (NSType == RPMNS_TYPE_GETCONF) { 01119 static rpmds getconfP = NULL; 01120 static int oneshot = -1; 01121 01122 if (oneshot) 01123 oneshot = rpmdsGetconf(&getconfP, NULL); 01124 if (getconfP == NULL) 01125 goto unsatisfied; 01126 01127 if (rpmdsSearch(getconfP, dep) >= 0) { 01128 rpmdsNotify(dep, _("(getconf provides)"), rc); 01129 goto exit; 01130 } 01131 goto unsatisfied; 01132 } 01133 01134 if (NSType == RPMNS_TYPE_UNAME) { 01135 static rpmds unameP = NULL; 01136 static int oneshot = -1; 01137 01138 if (oneshot) 01139 oneshot = rpmdsUname(&unameP, NULL); 01140 if (unameP == NULL) 01141 goto unsatisfied; 01142 01143 if (rpmdsSearch(unameP, dep) >= 0) { 01144 rpmdsNotify(dep, _("(uname provides)"), rc); 01145 goto exit; 01146 } 01147 goto unsatisfied; 01148 } 01149 01150 if (NSType == RPMNS_TYPE_SONAME) { 01151 rpmds sonameP = NULL; 01152 rpmPRCO PRCO = rpmdsNewPRCO(NULL); 01153 char * fn = strcpy(alloca(strlen(Name)+1), Name); 01154 int flags = 0; /* XXX RPMELF_FLAG_SKIPREQUIRES? */ 01155 rpmds ds; 01156 01157 /* XXX Only absolute paths for now. */ 01158 if (*fn != '/') 01159 goto unsatisfied; 01160 fn[strlen(fn)-1] = '\0'; 01161 01162 /* Extract ELF Provides: from /path/to/DSO. */ 01163 xx = rpmdsELF(fn, flags, rpmdsMergePRCO, PRCO); 01164 sonameP = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME); 01165 if (!(xx == 0 && sonameP != NULL)) 01166 goto unsatisfied; 01167 01168 /* Search using the original {EVR,"",Flags} from the dep set. */ 01169 ds = rpmdsSingle(rpmdsTagN(dep), rpmdsEVR(dep), "", Flags); 01170 xx = rpmdsSearch(sonameP, ds); 01171 ds = rpmdsFree(ds); 01172 PRCO = rpmdsFreePRCO(PRCO); 01173 01174 /* Was the dependency satisfied? */ 01175 if (xx >= 0) { 01176 rpmdsNotify(dep, _("(soname provides)"), rc); 01177 goto exit; 01178 } 01179 goto unsatisfied; 01180 } 01181 01182 /* Search added packages for the dependency. */ 01183 if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) { 01184 #if defined(CACHE_DEPENDENCY_RESULT) 01185 /* 01186 * XXX Ick, context sensitive answers from dependency cache. 01187 * XXX Always resolve added dependencies within context to disambiguate. 01188 */ 01189 if (_rpmds_nopromote) 01190 _cacheThisRC = 0; 01191 #endif 01192 goto exit; 01193 } 01194 01195 /* XXX only the installer does not have the database open here. */ 01196 if (rpmtsGetRdb(ts) != NULL) { 01197 /*@-boundsread@*/ 01198 if (Name[0] == '/') { 01199 /* depFlags better be 0! */ 01200 01201 mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0); 01202 (void) rpmdbPruneIterator(mi, 01203 ts->removedPackages, ts->numRemovedPackages, 1); 01204 while ((h = rpmdbNextIterator(mi)) != NULL) { 01205 rpmdsNotify(dep, _("(db files)"), rc); 01206 mi = rpmdbFreeIterator(mi); 01207 goto exit; 01208 } 01209 mi = rpmdbFreeIterator(mi); 01210 } 01211 /*@=boundsread@*/ 01212 01213 mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0); 01214 (void) rpmdbPruneIterator(mi, 01215 ts->removedPackages, ts->numRemovedPackages, 1); 01216 while ((h = rpmdbNextIterator(mi)) != NULL) { 01217 if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) { 01218 rpmdsNotify(dep, _("(db provides)"), rc); 01219 mi = rpmdbFreeIterator(mi); 01220 goto exit; 01221 } 01222 } 01223 mi = rpmdbFreeIterator(mi); 01224 01225 } 01226 01227 /* 01228 * Search for an unsatisfied dependency. 01229 */ 01230 /*@-boundsread@*/ 01231 if (adding == 1 && retries > 0 && !(rpmtsDFlags(ts) & RPMDEPS_FLAG_NOSUGGEST)) { 01232 if (ts->solve != NULL) { 01233 xx = (*ts->solve) (ts, dep, ts->solveData); 01234 if (xx == 0) 01235 goto exit; 01236 if (xx == -1) { 01237 retries--; 01238 rpmalMakeIndex(ts->addedPackages); 01239 goto retry; 01240 } 01241 } 01242 } 01243 /*@=boundsread@*/ 01244 01245 unsatisfied: 01246 if (Flags & RPMSENSE_MISSINGOK) { 01247 rc = 0; /* dependency is unsatisfied, but just a hint. */ 01248 _cacheThisRC = 0; 01249 rpmdsNotify(dep, _("(hint skipped)"), rc); 01250 } else { 01251 rc = 1; /* dependency is unsatisfied */ 01252 rpmdsNotify(dep, NULL, rc); 01253 } 01254 01255 exit: 01256 /* 01257 * If dbiOpen/dbiPut fails (e.g. permissions), we can't cache. 01258 */ 01259 #if defined(CACHE_DEPENDENCY_RESULT) 01260 if (_cacheDependsRC && _cacheThisRC) { 01261 dbiIndex dbi; 01262 dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPENDS, 0); 01263 if (dbi == NULL) { 01264 _cacheDependsRC = 0; 01265 } else { 01266 const char * DNEVR; 01267 xx = 0; 01268 /*@-branchstate@*/ 01269 if ((DNEVR = rpmdsDNEVR(dep)) != NULL) { 01270 DBC * dbcursor = NULL; 01271 size_t DNEVRlen = strlen(DNEVR); 01272 01273 xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, DB_WRITECURSOR); 01274 01275 memset(key, 0, sizeof(*key)); 01276 /*@i@*/ key->data = (void *) DNEVR; 01277 key->size = DNEVRlen; 01278 memset(data, 0, sizeof(*data)); 01279 data->data = &rc; 01280 data->size = sizeof(rc); 01281 01282 /*@-compmempass@*/ 01283 xx = dbiPut(dbi, dbcursor, key, data, 0); 01284 /*@=compmempass@*/ 01285 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR); 01286 } 01287 /*@=branchstate@*/ 01288 if (xx) 01289 _cacheDependsRC = 0; 01290 } 01291 } 01292 #endif 01293 01294 return rpmdsNegateRC(dep, rc); 01295 } 01296 01310 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA, 01311 /*@null@*/ rpmds requires, 01312 /*@null@*/ rpmds conflicts, 01313 /*@null@*/ rpmds dirnames, 01314 /*@null@*/ rpmds linktos, 01315 /*@null@*/ const char * depName, uint_32 tscolor, int adding) 01316 /*@globals rpmGlobalMacroContext, h_errno, 01317 fileSystem, internalState @*/ 01318 /*@modifies ts, requires, conflicts, dirnames, linktos, 01319 rpmGlobalMacroContext, fileSystem, internalState */ 01320 { 01321 rpmps ps = rpmtsProblems(ts); 01322 uint_32 dscolor; 01323 const char * Name; 01324 int rc; 01325 int ourrc = 0; 01326 int dirname_deps; 01327 int symlink_deps; 01328 01329 requires = rpmdsInit(requires); 01330 if (requires != NULL) 01331 while (!ourrc && rpmdsNext(requires) >= 0) { 01332 01333 if ((Name = rpmdsN(requires)) == NULL) 01334 continue; /* XXX can't happen */ 01335 01336 /* Filter out requires that came along for the ride. */ 01337 if (depName != NULL && strcmp(depName, Name)) 01338 continue; 01339 01340 /* Ignore colored requires not in our rainbow. */ 01341 dscolor = rpmdsColor(requires); 01342 if (tscolor && dscolor && !(tscolor & dscolor)) 01343 continue; 01344 01345 rc = unsatisfiedDepend(ts, requires, adding); 01346 01347 switch (rc) { 01348 case 0: /* requirements are satisfied. */ 01349 /*@switchbreak@*/ break; 01350 case 1: /* requirements are not satisfied. */ 01351 { fnpyKey * suggestedKeys = NULL; 01352 01353 /*@-branchstate@*/ 01354 if (ts->availablePackages != NULL) { 01355 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages, 01356 requires, NULL); 01357 } 01358 /*@=branchstate@*/ 01359 01360 rpmdsProblem(ps, pkgNEVRA, requires, suggestedKeys, adding); 01361 01362 } 01363 /*@switchbreak@*/ break; 01364 case 2: /* something went wrong! */ 01365 default: 01366 ourrc = 1; 01367 /*@switchbreak@*/ break; 01368 } 01369 } 01370 01371 conflicts = rpmdsInit(conflicts); 01372 if (conflicts != NULL) 01373 while (!ourrc && rpmdsNext(conflicts) >= 0) { 01374 01375 if ((Name = rpmdsN(conflicts)) == NULL) 01376 continue; /* XXX can't happen */ 01377 01378 /* Filter out conflicts that came along for the ride. */ 01379 if (depName != NULL && strcmp(depName, Name)) 01380 continue; 01381 01382 /* Ignore colored conflicts not in our rainbow. */ 01383 dscolor = rpmdsColor(conflicts); 01384 if (tscolor && dscolor && !(tscolor & dscolor)) 01385 continue; 01386 01387 rc = unsatisfiedDepend(ts, conflicts, adding); 01388 01389 /* 1 == unsatisfied, 0 == satsisfied */ 01390 switch (rc) { 01391 case 0: /* conflicts exist. */ 01392 rpmdsProblem(ps, pkgNEVRA, conflicts, NULL, adding); 01393 /*@switchbreak@*/ break; 01394 case 1: /* conflicts don't exist. */ 01395 /*@switchbreak@*/ break; 01396 case 2: /* something went wrong! */ 01397 default: 01398 ourrc = 1; 01399 /*@switchbreak@*/ break; 01400 } 01401 } 01402 01403 dirname_deps = rpmExpandNumeric("%{?_check_dirname_deps}%{?!_check_dirname_deps:1}"); 01404 if (dirname_deps) { 01405 dirnames = rpmdsInit(dirnames); 01406 if (dirnames != NULL) 01407 while (!ourrc && rpmdsNext(dirnames) >= 0) { 01408 01409 if ((Name = rpmdsN(dirnames)) == NULL) 01410 continue; /* XXX can't happen */ 01411 01412 /* Filter out dirnames that came along for the ride. */ 01413 if (depName != NULL && strcmp(depName, Name)) 01414 continue; 01415 01416 /* Ignore colored dirnames not in our rainbow. */ 01417 dscolor = rpmdsColor(dirnames); 01418 if (tscolor && dscolor && !(tscolor & dscolor)) 01419 continue; 01420 01421 rc = unsatisfiedDepend(ts, dirnames, adding); 01422 01423 switch (rc) { 01424 case 0: /* requirements are satisfied. */ 01425 /*@switchbreak@*/ break; 01426 case 1: /* requirements are not satisfied. */ 01427 { fnpyKey * suggestedKeys = NULL; 01428 01429 /*@-branchstate@*/ 01430 if (ts->availablePackages != NULL) { 01431 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages, 01432 dirnames, NULL); 01433 } 01434 /*@=branchstate@*/ 01435 01436 rpmdsProblem(ps, pkgNEVRA, dirnames, suggestedKeys, adding); 01437 01438 } 01439 /*@switchbreak@*/ break; 01440 case 2: /* something went wrong! */ 01441 default: 01442 ourrc = 1; 01443 /*@switchbreak@*/ break; 01444 } 01445 } 01446 } 01447 01448 symlink_deps = rpmExpandNumeric("%{?_check_symlink_deps}%{?!_check_symlink_deps:1}"); 01449 if (symlink_deps) { 01450 linktos = rpmdsInit(linktos); 01451 if (linktos != NULL) 01452 while (!ourrc && rpmdsNext(linktos) >= 0) { 01453 01454 if ((Name = rpmdsN(linktos)) == NULL) 01455 continue; /* XXX can't happen */ 01456 if (*Name == '\0') /* XXX most linktos are empty */ 01457 continue; 01458 01459 /* Filter out linktos that came along for the ride. */ 01460 if (depName != NULL && strcmp(depName, Name)) 01461 continue; 01462 01463 /* Ignore colored linktos not in our rainbow. */ 01464 dscolor = rpmdsColor(linktos); 01465 if (tscolor && dscolor && !(tscolor & dscolor)) 01466 continue; 01467 } 01468 01469 rc = unsatisfiedDepend(ts, linktos, adding); 01470 01471 switch (rc) { 01472 case 0: /* requirements are satisfied. */ 01473 /*@switchbreak@*/ break; 01474 case 1: /* requirements are not satisfied. */ 01475 { fnpyKey * suggestedKeys = NULL; 01476 01477 /*@-branchstate@*/ 01478 if (ts->availablePackages != NULL) { 01479 suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages, 01480 linktos, NULL); 01481 } 01482 /*@=branchstate@*/ 01483 01484 rpmdsProblem(ps, pkgNEVRA, linktos, suggestedKeys, adding); 01485 01486 } 01487 /*@switchbreak@*/ break; 01488 case 2: /* something went wrong! */ 01489 default: 01490 ourrc = 1; 01491 /*@switchbreak@*/ break; 01492 } 01493 } 01494 01495 ps = rpmpsFree(ps); 01496 return ourrc; 01497 } 01498 01509 static int checkPackageSet(rpmts ts, const char * depName, 01510 /*@only@*/ /*@null@*/ rpmdbMatchIterator mi, int adding) 01511 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01512 /*@modifies ts, mi, rpmGlobalMacroContext, fileSystem, internalState @*/ 01513 { 01514 rpmdepFlags depFlags = rpmtsDFlags(ts); 01515 uint_32 tscolor = rpmtsColor(ts); 01516 int scareMem = 0; 01517 Header h; 01518 int ec = 0; 01519 01520 (void) rpmdbPruneIterator(mi, 01521 ts->removedPackages, ts->numRemovedPackages, 1); 01522 while ((h = rpmdbNextIterator(mi)) != NULL) { 01523 const char * pkgNEVRA; 01524 rpmds requires = NULL; 01525 rpmds conflicts = NULL; 01526 rpmds dirnames = NULL; 01527 rpmds linktos = NULL; 01528 int rc; 01529 01530 pkgNEVRA = hGetNEVRA(h, NULL); 01531 if (!(depFlags & RPMDEPS_FLAG_NOREQUIRES)) 01532 requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem); 01533 if (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS)) 01534 conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem); 01535 if (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS)) 01536 dirnames = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem); 01537 if (!(depFlags & RPMDEPS_FLAG_NOLINKTOS)) 01538 linktos = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem); 01539 01540 (void) rpmdsSetNoPromote(requires, _rpmds_nopromote); 01541 (void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote); 01542 (void) rpmdsSetNoPromote(dirnames, _rpmds_nopromote); 01543 (void) rpmdsSetNoPromote(linktos, _rpmds_nopromote); 01544 01545 rc = checkPackageDeps(ts, pkgNEVRA, 01546 requires, conflicts, dirnames, linktos, 01547 depName, tscolor, adding); 01548 01549 linktos = rpmdsFree(linktos); 01550 dirnames = rpmdsFree(dirnames); 01551 conflicts = rpmdsFree(conflicts); 01552 requires = rpmdsFree(requires); 01553 pkgNEVRA = _free(pkgNEVRA); 01554 01555 if (rc) { 01556 ec = 1; 01557 break; 01558 } 01559 } 01560 mi = rpmdbFreeIterator(mi); 01561 01562 return ec; 01563 } 01564 01571 static int checkDependentPackages(rpmts ts, const char * depName) 01572 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01573 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 01574 { 01575 int rc = 0; 01576 01577 /* XXX rpmdb can be closed here, avoid error msg. */ 01578 if (rpmtsGetRdb(ts) != NULL) { 01579 rpmdbMatchIterator mi; 01580 mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, depName, 0); 01581 rc = checkPackageSet(ts, depName, mi, 0); 01582 } 01583 return rc; 01584 } 01585 01592 static int checkDependentConflicts(rpmts ts, const char * depName) 01593 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01594 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 01595 { 01596 int rc = 0; 01597 01598 /* XXX rpmdb can be closed here, avoid error msg. */ 01599 if (rpmtsGetRdb(ts) != NULL) { 01600 rpmdbMatchIterator mi; 01601 mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, depName, 0); 01602 rc = checkPackageSet(ts, depName, mi, 1); 01603 } 01604 01605 return rc; 01606 } 01607 01608 struct badDeps_s { 01609 /*@observer@*/ /*@owned@*/ /*@null@*/ 01610 const char * pname; 01611 /*@observer@*/ /*@dependent@*/ /*@null@*/ 01612 const char * qname; 01613 }; 01614 01615 #ifdef REFERENCE 01616 static struct badDeps_s { 01617 /*@observer@*/ /*@null@*/ const char * pname; 01618 /*@observer@*/ /*@null@*/ const char * qname; 01619 } badDeps[] = { 01620 { "libtermcap", "bash" }, 01621 { "modutils", "vixie-cron" }, 01622 { "ypbind", "yp-tools" }, 01623 { "ghostscript-fonts", "ghostscript" }, 01624 /* 7.2 only */ 01625 { "libgnomeprint15", "gnome-print" }, 01626 { "nautilus", "nautilus-mozilla" }, 01627 /* 7.1 only */ 01628 { "arts", "kdelibs-sound" }, 01629 /* 7.0 only */ 01630 { "pango-gtkbeta-devel", "pango-gtkbeta" }, 01631 { "XFree86", "Mesa" }, 01632 { "compat-glibc", "db2" }, 01633 { "compat-glibc", "db1" }, 01634 { "pam", "initscripts" }, 01635 { "initscripts", "sysklogd" }, 01636 /* 6.2 */ 01637 { "egcs-c++", "libstdc++" }, 01638 /* 6.1 */ 01639 { "pilot-link-devel", "pilot-link" }, 01640 /* 5.2 */ 01641 { "pam", "pamconfig" }, 01642 { NULL, NULL } 01643 }; 01644 #else 01645 /*@unchecked@*/ 01646 static int badDepsInitialized = 0; 01647 01648 /*@unchecked@*/ /*@only@*/ /*@null@*/ 01649 static struct badDeps_s * badDeps = NULL; 01650 #endif 01651 01654 /*@-modobserver -observertrans @*/ 01655 static void freeBadDeps(void) 01656 /*@globals badDeps, badDepsInitialized @*/ 01657 /*@modifies badDeps, badDepsInitialized @*/ 01658 { 01659 if (badDeps) { 01660 struct badDeps_s * bdp; 01661 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++) 01662 bdp->pname = _free(bdp->pname); 01663 badDeps = _free(badDeps); 01664 } 01665 badDepsInitialized = 0; 01666 } 01667 /*@=modobserver =observertrans @*/ 01668 01677 /*@-boundsread@*/ 01678 static int ignoreDep(const rpmts ts, const rpmte p, const rpmte q) 01679 /*@globals badDeps, badDepsInitialized, 01680 rpmGlobalMacroContext, h_errno @*/ 01681 /*@modifies badDeps, badDepsInitialized, 01682 rpmGlobalMacroContext @*/ 01683 { 01684 struct badDeps_s * bdp; 01685 01686 if (!badDepsInitialized) { 01687 char * s = rpmExpand("%{?_dependency_whiteout}", NULL); 01688 const char ** av = NULL; 01689 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA; 01690 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS)) 01691 ? RPMMESS_WARNING : RPMMESS_DEBUG; 01692 int ac = 0; 01693 int i; 01694 01695 if (s != NULL && *s != '\0' 01696 && !(i = poptParseArgvString(s, &ac, (const char ***)&av)) 01697 && ac > 0 && av != NULL) 01698 { 01699 bdp = badDeps = xcalloc(ac+1, sizeof(*badDeps)); 01700 for (i = 0; i < ac; i++, bdp++) { 01701 char * pname, * qname; 01702 01703 if (av[i] == NULL) 01704 break; 01705 pname = xstrdup(av[i]); 01706 if ((qname = strchr(pname, '>')) != NULL) 01707 *qname++ = '\0'; 01708 bdp->pname = pname; 01709 /*@-usereleased@*/ 01710 bdp->qname = qname; 01711 /*@=usereleased@*/ 01712 rpmMessage(msglvl, 01713 _("ignore package name relation(s) [%d]\t%s -> %s\n"), 01714 i, bdp->pname, (bdp->qname ? bdp->qname : "???")); 01715 } 01716 bdp->pname = NULL; 01717 bdp->qname = NULL; 01718 } 01719 av = _free(av); 01720 s = _free(s); 01721 badDepsInitialized++; 01722 } 01723 01724 /*@-compdef@*/ 01725 if (badDeps != NULL) 01726 for (bdp = badDeps; bdp->pname != NULL && bdp->qname != NULL; bdp++) { 01727 if (!strcmp(rpmteN(p), bdp->pname) && !strcmp(rpmteN(q), bdp->qname)) 01728 return 1; 01729 } 01730 return 0; 01731 /*@=compdef@*/ 01732 } 01733 /*@=boundsread@*/ 01734 01740 static void markLoop(/*@special@*/ tsortInfo tsi, rpmte q) 01741 /*@globals internalState @*/ 01742 /*@uses tsi @*/ 01743 /*@modifies internalState @*/ 01744 { 01745 rpmte p; 01746 01747 /*@-branchstate@*/ /* FIX: q is kept */ 01748 while (tsi != NULL && (p = tsi->tsi_suc) != NULL) { 01749 tsi = tsi->tsi_next; 01750 if (rpmteTSI(p)->tsi_chain != NULL) 01751 continue; 01752 /*@-assignexpose -temptrans@*/ 01753 rpmteTSI(p)->tsi_chain = q; 01754 /*@=assignexpose =temptrans@*/ 01755 if (rpmteTSI(p)->tsi_next != NULL) 01756 markLoop(rpmteTSI(p)->tsi_next, p); 01757 } 01758 /*@=branchstate@*/ 01759 } 01760 01761 /* 01762 * Return display string a dependency, adding contextual flags marker. 01763 * @param f dependency flags 01764 * @return display string 01765 */ 01766 static inline /*@observer@*/ const char * identifyDepend(int_32 f) 01767 /*@*/ 01768 { 01769 f = _notpre(f); 01770 if (f & RPMSENSE_SCRIPT_PRE) 01771 return "Requires(pre):"; 01772 if (f & RPMSENSE_SCRIPT_POST) 01773 return "Requires(post):"; 01774 if (f & RPMSENSE_SCRIPT_PREUN) 01775 return "Requires(preun):"; 01776 if (f & RPMSENSE_SCRIPT_POSTUN) 01777 return "Requires(postun):"; 01778 if (f & RPMSENSE_SCRIPT_VERIFY) 01779 return "Requires(verify):"; 01780 if (f & RPMSENSE_MISSINGOK) 01781 return "Requires(hint):"; 01782 if (f & RPMSENSE_FIND_REQUIRES) 01783 return "Requires(auto):"; 01784 return "Requires:"; 01785 } 01786 01799 /*@-boundswrite@*/ 01800 /*@-mustmod@*/ /* FIX: hack modifies, but -type disables */ 01801 static /*@owned@*/ /*@null@*/ const char * 01802 zapRelation(rpmte q, rpmte p, 01803 int zap, /*@in@*/ /*@out@*/ int * nzaps, int msglvl) 01804 /*@globals rpmGlobalMacroContext, h_errno @*/ 01805 /*@modifies q, p, *nzaps, rpmGlobalMacroContext @*/ 01806 { 01807 rpmds requires; 01808 tsortInfo tsi_prev; 01809 tsortInfo tsi; 01810 const char *dp = NULL; 01811 01812 for (tsi_prev = rpmteTSI(q), tsi = rpmteTSI(q)->tsi_next; 01813 tsi != NULL; 01814 /* XXX Note: the loop traverses "not found", break on "found". */ 01815 /*@-nullderef@*/ 01816 tsi_prev = tsi, tsi = tsi->tsi_next) 01817 /*@=nullderef@*/ 01818 { 01819 int_32 Flags; 01820 01821 /*@-abstractcompare@*/ 01822 if (tsi->tsi_suc != p) 01823 continue; 01824 /*@=abstractcompare@*/ 01825 01826 requires = rpmteDS((rpmteType(p) == TR_REMOVED ? q : p), tsi->tsi_tagn); 01827 if (requires == NULL) continue; /* XXX can't happen */ 01828 01829 (void) rpmdsSetIx(requires, tsi->tsi_reqx); 01830 01831 Flags = rpmdsFlags(requires); 01832 01833 dp = rpmdsNewDNEVR( identifyDepend(Flags), requires); 01834 01835 /* 01836 * Attempt to unravel a dependency loop by eliminating Requires's. 01837 */ 01838 /*@-branchstate@*/ 01839 if (zap) { 01840 rpmMessage(msglvl, 01841 _("removing %s \"%s\" from tsort relations.\n"), 01842 (rpmteNEVRA(p) ? rpmteNEVRA(p) : "???"), dp); 01843 rpmteTSI(p)->tsi_count--; 01844 if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next; 01845 tsi->tsi_next = NULL; 01846 tsi->tsi_suc = NULL; 01847 tsi = _free(tsi); 01848 if (nzaps) 01849 (*nzaps)++; 01850 if (zap) 01851 zap--; 01852 } 01853 /*@=branchstate@*/ 01854 /* XXX Note: the loop traverses "not found", get out now! */ 01855 break; 01856 } 01857 return dp; 01858 } 01859 /*@=mustmod@*/ 01860 /*@=boundswrite@*/ 01861 01870 /*@-mustmod@*/ 01871 static inline int addRelation(rpmts ts, 01872 /*@dependent@*/ rpmte p, 01873 unsigned char * selected, 01874 rpmds requires) 01875 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01876 /*@modifies ts, p, *selected, rpmGlobalMacroContext, 01877 fileSystem, internalState @*/ 01878 { 01879 rpmtsi qi; rpmte q; 01880 tsortInfo tsi; 01881 nsType NSType = rpmdsNSType(requires); 01882 fnpyKey key; 01883 int teType = rpmteType(p); 01884 alKey pkgKey; 01885 int i = 0; 01886 rpmal al = (teType == TR_ADDED ? ts->addedPackages : ts->erasedPackages); 01887 01888 /* Avoid certain NS dependencies. */ 01889 switch (NSType) { 01890 case RPMNS_TYPE_RPMLIB: 01891 case RPMNS_TYPE_CPUINFO: 01892 case RPMNS_TYPE_GETCONF: 01893 case RPMNS_TYPE_UNAME: 01894 case RPMNS_TYPE_SONAME: 01895 case RPMNS_TYPE_ACCESS: 01896 case RPMNS_TYPE_USER: 01897 case RPMNS_TYPE_GROUP: 01898 case RPMNS_TYPE_MOUNTED: 01899 case RPMNS_TYPE_DISKSPACE: 01900 case RPMNS_TYPE_DIGEST: 01901 case RPMNS_TYPE_GNUPG: 01902 case RPMNS_TYPE_MACRO: 01903 case RPMNS_TYPE_ENVVAR: 01904 case RPMNS_TYPE_RUNNING: 01905 return 0; 01906 /*@notreached@*/ break; 01907 default: 01908 break; 01909 } 01910 01911 { const char * Name = rpmdsN(requires); 01912 01913 /* Avoid package config dependencies. */ 01914 if (Name == NULL || !strncmp(Name, "config(", sizeof("config(")-1)) 01915 return 0; 01916 } 01917 01918 pkgKey = RPMAL_NOMATCH; 01919 key = rpmalSatisfiesDepend(al, requires, &pkgKey); 01920 01921 /* Ordering depends only on added/erased package relations. */ 01922 if (pkgKey == RPMAL_NOMATCH) 01923 return 0; 01924 01925 /* XXX Set q to the added/removed package that was found. */ 01926 /* XXX pretend erasedPackages are just appended to addedPackages. */ 01927 if (teType == TR_REMOVED) 01928 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages); 01929 01930 for (qi = rpmtsiInit(ts), i = 0; (q = rpmtsiNext(qi, 0)) != NULL; i++) { 01931 if (pkgKey == rpmteAddedKey(q)) 01932 break; 01933 } 01934 qi = rpmtsiFree(qi); 01935 if (q == NULL || i >= ts->orderCount) 01936 return 0; 01937 01938 /* Avoid certain dependency relations. */ 01939 if (ignoreDep(ts, p, q)) 01940 return 0; 01941 01942 /* Avoid redundant relations. */ 01943 /*@-boundsread@*/ 01944 if (selected[i] != 0) 01945 return 0; 01946 /*@=boundsread@*/ 01947 /*@-boundswrite@*/ 01948 selected[i] = 1; 01949 /*@=boundswrite@*/ 01950 01951 /* Erasures are reversed installs. */ 01952 if (teType == TR_REMOVED) { 01953 rpmte r = p; 01954 p = q; 01955 q = r; 01956 } 01957 01958 /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ 01959 rpmteTSI(p)->tsi_count++; /* bump p predecessor count */ 01960 01961 if (rpmteDepth(p) <= rpmteDepth(q)) /* Save max. depth in dependency tree */ 01962 (void) rpmteSetDepth(p, (rpmteDepth(q) + 1)); 01963 if (rpmteDepth(p) > ts->maxDepth) 01964 ts->maxDepth = rpmteDepth(p); 01965 01966 tsi = xcalloc(1, sizeof(*tsi)); 01967 tsi->tsi_suc = p; 01968 01969 tsi->tsi_tagn = rpmdsTagN(requires); 01970 tsi->tsi_reqx = rpmdsIx(requires); 01971 01972 tsi->tsi_next = rpmteTSI(q)->tsi_next; 01973 rpmteTSI(q)->tsi_next = tsi; 01974 rpmteTSI(q)->tsi_qcnt++; /* bump q successor count */ 01975 01976 return 0; 01977 } 01978 /*@=mustmod@*/ 01979 01986 static int orderListIndexCmp(const void * one, const void * two) /*@*/ 01987 { 01988 /*@-castexpose@*/ 01989 long a = (long) ((const orderListIndex)one)->pkgKey; 01990 long b = (long) ((const orderListIndex)two)->pkgKey; 01991 /*@=castexpose@*/ 01992 return (a - b); 01993 } 01994 02002 /*@-boundswrite@*/ 02003 /*@-mustmod@*/ 02004 static void addQ(/*@dependent@*/ rpmte p, 02005 /*@in@*/ /*@out@*/ rpmte * qp, 02006 /*@in@*/ /*@out@*/ rpmte * rp, 02007 uint_32 prefcolor) 02008 /*@modifies p, *qp, *rp @*/ 02009 { 02010 rpmte q, qprev; 02011 02012 /* Mark the package as queued. */ 02013 rpmteTSI(p)->tsi_queued = 1; 02014 02015 if ((*rp) == NULL) { /* 1st element */ 02016 /*@-dependenttrans@*/ /* FIX: double indirection */ 02017 (*rp) = (*qp) = p; 02018 /*@=dependenttrans@*/ 02019 return; 02020 } 02021 02022 /* Find location in queue using metric tsi_qcnt. */ 02023 for (qprev = NULL, q = (*qp); 02024 q != NULL; 02025 qprev = q, q = rpmteTSI(q)->tsi_suc) 02026 { 02027 /* XXX Insure preferred color first. */ 02028 if (rpmteColor(p) != prefcolor && rpmteColor(p) != rpmteColor(q)) 02029 continue; 02030 02031 /* XXX Insure removed after added. */ 02032 if (rpmteType(p) == TR_REMOVED && rpmteType(p) != rpmteType(q)) 02033 continue; 02034 if (rpmteTSI(q)->tsi_qcnt <= rpmteTSI(p)->tsi_qcnt) 02035 break; 02036 } 02037 02038 if (qprev == NULL) { /* insert at beginning of list */ 02039 rpmteTSI(p)->tsi_suc = q; 02040 /*@-dependenttrans@*/ 02041 (*qp) = p; /* new head */ 02042 /*@=dependenttrans@*/ 02043 } else if (q == NULL) { /* insert at end of list */ 02044 rpmteTSI(qprev)->tsi_suc = p; 02045 /*@-dependenttrans@*/ 02046 (*rp) = p; /* new tail */ 02047 /*@=dependenttrans@*/ 02048 } else { /* insert between qprev and q */ 02049 rpmteTSI(p)->tsi_suc = q; 02050 rpmteTSI(qprev)->tsi_suc = p; 02051 } 02052 } 02053 /*@=mustmod@*/ 02054 /*@=boundswrite@*/ 02055 02056 /*@unchecked@*/ 02057 #ifdef NOTYET 02058 static uint32_t _autobits = _notpre(_ALL_REQUIRES_MASK); 02059 #define isAuto(_x) ((_x) & _autobits) 02060 #else 02061 static uint32_t _autobits = 0xffffffff; 02062 #define isAuto(_x) (1) 02063 #endif 02064 02065 /*@-bounds@*/ 02066 int rpmtsOrder(rpmts ts) 02067 { 02068 rpmds requires; 02069 int_32 Flags; 02070 int anaconda = rpmtsDFlags(ts) & RPMDEPS_FLAG_ANACONDA; 02071 uint_32 prefcolor = rpmtsPrefColor(ts); 02072 rpmtsi pi; rpmte p; 02073 rpmtsi qi; rpmte q; 02074 rpmtsi ri; rpmte r; 02075 tsortInfo tsi; 02076 tsortInfo tsi_next; 02077 alKey * ordering; 02078 int orderingCount = 0; 02079 unsigned char * selected = alloca(sizeof(*selected) * (ts->orderCount + 1)); 02080 int loopcheck; 02081 rpmte * newOrder; 02082 int newOrderCount = 0; 02083 orderListIndex orderList; 02084 int numOrderList; 02085 int npeer = 128; /* XXX more than deep enough for now. */ 02086 int * peer = memset(alloca(npeer*sizeof(*peer)), 0, (npeer*sizeof(*peer))); 02087 int nrescans = 10; 02088 int _printed = 0; 02089 char deptypechar; 02090 size_t tsbytes; 02091 int oType = 0; 02092 int treex; 02093 int depth; 02094 int breadth; 02095 int qlen; 02096 int i, j; 02097 02098 #ifdef DYING 02099 rpmalMakeIndex(ts->addedPackages); 02100 #endif 02101 02102 /* Create erased package index. */ 02103 pi = rpmtsiInit(ts); 02104 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { 02105 alKey pkgKey; 02106 fnpyKey key; 02107 uint_32 tscolor = rpmtsColor(ts); 02108 pkgKey = RPMAL_NOMATCH; 02109 /*@-abstract@*/ 02110 key = (fnpyKey) p; 02111 /*@=abstract@*/ 02112 pkgKey = rpmalAdd(&ts->erasedPackages, pkgKey, key, 02113 rpmteDS(p, RPMTAG_PROVIDENAME), 02114 rpmteFI(p, RPMTAG_BASENAMES), tscolor); 02115 /* XXX pretend erasedPackages are just appended to addedPackages. */ 02116 pkgKey = (alKey)(((long)pkgKey) + ts->numAddedPackages); 02117 (void) rpmteSetAddedKey(p, pkgKey); 02118 } 02119 pi = rpmtsiFree(pi); 02120 rpmalMakeIndex(ts->erasedPackages); 02121 02122 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0); 02123 02124 /* T1. Initialize. */ 02125 if (oType == 0) 02126 numOrderList = ts->orderCount; 02127 else { 02128 numOrderList = 0; 02129 if (oType & TR_ADDED) 02130 numOrderList += ts->numAddedPackages; 02131 if (oType & TR_REMOVED) 02132 numOrderList += ts->numRemovedPackages; 02133 } 02134 ordering = alloca(sizeof(*ordering) * (numOrderList + 1)); 02135 loopcheck = numOrderList; 02136 tsbytes = 0; 02137 02138 pi = rpmtsiInit(ts); 02139 while ((p = rpmtsiNext(pi, oType)) != NULL) 02140 rpmteNewTSI(p); 02141 pi = rpmtsiFree(pi); 02142 02143 /* Record all relations. */ 02144 rpmMessage(RPMMESS_DEBUG, D_("========== recording tsort relations\n")); 02145 pi = rpmtsiInit(ts); 02146 while ((p = rpmtsiNext(pi, oType)) != NULL) { 02147 02148 memset(selected, 0, sizeof(*selected) * ts->orderCount); 02149 02150 if ((requires = rpmteDS(p, RPMTAG_REQUIRENAME)) != NULL) { 02151 02152 /* Avoid narcisstic relations. */ 02153 selected[rpmtsiOc(pi)] = 1; 02154 02155 /* T2. Next "q <- p" relation. */ 02156 02157 /* First, do pre-requisites. */ 02158 requires = rpmdsInit(requires); 02159 if (requires != NULL) 02160 while (rpmdsNext(requires) >= 0) { 02161 02162 Flags = rpmdsFlags(requires); 02163 if (!isAuto(Flags)) 02164 /*@innercontinue@*/ continue; 02165 02166 switch (rpmteType(p)) { 02167 case TR_REMOVED: 02168 /* Skip if not %preun/%postun requires. */ 02169 if (!isErasePreReq(Flags)) 02170 /*@innercontinue@*/ continue; 02171 /*@switchbreak@*/ break; 02172 case TR_ADDED: 02173 /* Skip if not %pre/%post requires. */ 02174 if (!isInstallPreReq(Flags)) 02175 /*@innercontinue@*/ continue; 02176 /*@switchbreak@*/ break; 02177 } 02178 02179 /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ 02180 (void) addRelation(ts, p, selected, requires); 02181 02182 } 02183 02184 /* Then do co-requisites. */ 02185 requires = rpmdsInit(requires); 02186 if (requires != NULL) 02187 while (rpmdsNext(requires) >= 0) { 02188 02189 Flags = rpmdsFlags(requires); 02190 if (!isAuto(Flags)) 02191 /*@innercontinue@*/ continue; 02192 02193 switch (rpmteType(p)) { 02194 case TR_REMOVED: 02195 /* Skip if %preun/%postun requires. */ 02196 if (isErasePreReq(Flags)) 02197 /*@innercontinue@*/ continue; 02198 /*@switchbreak@*/ break; 02199 case TR_ADDED: 02200 /* Skip if %pre/%post requires. */ 02201 if (isInstallPreReq(Flags)) 02202 /*@innercontinue@*/ continue; 02203 /*@switchbreak@*/ break; 02204 } 02205 02206 /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ 02207 (void) addRelation(ts, p, selected, requires); 02208 02209 } 02210 } 02211 02212 02213 /* Ensure that erasures follow installs during upgrades. */ 02214 if (rpmteType(p) == TR_REMOVED && p->flink.Pkgid && p->flink.Pkgid[0]) { 02215 02216 qi = rpmtsiInit(ts); 02217 while ((q = rpmtsiNext(qi, TR_ADDED)) != NULL) { 02218 if (strcmp(q->pkgid, p->flink.Pkgid[0])) 02219 continue; 02220 requires = rpmdsFromPRCO(q->PRCO, RPMTAG_NAME); 02221 if (requires != NULL) { 02222 /* XXX disable erased arrow reversal. */ 02223 p->type = TR_ADDED; 02224 (void) addRelation(ts, p, selected, requires); 02225 p->type = TR_REMOVED; 02226 } 02227 } 02228 qi = rpmtsiFree(qi); 02229 } 02230 02231 if (_autobits != 0xffffffff) 02232 { 02233 02234 /* Order by requiring parent directories pre-requsites. */ 02235 requires = rpmdsInit(rpmteDS(p, RPMTAG_DIRNAMES)); 02236 if (requires != NULL) 02237 while (rpmdsNext(requires) >= 0) { 02238 02239 /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ 02240 (void) addRelation(ts, p, selected, requires); 02241 02242 } 02243 02244 /* Order by requiring no dangling symlinks. */ 02245 requires = rpmdsInit(rpmteDS(p, RPMTAG_FILELINKTOS)); 02246 if (requires != NULL) 02247 while (rpmdsNext(requires) >= 0) { 02248 02249 /* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */ 02250 (void) addRelation(ts, p, selected, requires); 02251 02252 } 02253 } 02254 02255 } 02256 pi = rpmtsiFree(pi); 02257 02258 /* Save predecessor count and mark tree roots. */ 02259 treex = 0; 02260 pi = rpmtsiInit(ts); 02261 while ((p = rpmtsiNext(pi, oType)) != NULL) { 02262 int npreds; 02263 02264 npreds = rpmteTSI(p)->tsi_count; 02265 02266 (void) rpmteSetNpreds(p, npreds); 02267 (void) rpmteSetDepth(p, 0); 02268 02269 if (npreds == 0) { 02270 treex++; 02271 (void) rpmteSetTree(p, treex); 02272 (void) rpmteSetBreadth(p, treex); 02273 } else 02274 (void) rpmteSetTree(p, -1); 02275 #ifdef UNNECESSARY 02276 (void) rpmteSetParent(p, NULL); 02277 #endif 02278 02279 } 02280 pi = rpmtsiFree(pi); 02281 ts->ntrees = treex; 02282 02283 /* T4. Scan for zeroes. */ 02284 rpmMessage(RPMMESS_DEBUG, D_("========== tsorting packages (order, #predecessors, #succesors, tree, Ldepth, Rbreadth)\n")); 02285 02286 rescan: 02287 if (pi != NULL) pi = rpmtsiFree(pi); 02288 q = r = NULL; 02289 qlen = 0; 02290 pi = rpmtsiInit(ts); 02291 while ((p = rpmtsiNext(pi, oType)) != NULL) { 02292 02293 /* Prefer packages in chainsaw or anaconda presentation order. */ 02294 if (anaconda) 02295 rpmteTSI(p)->tsi_qcnt = (ts->orderCount - rpmtsiOc(pi)); 02296 02297 if (rpmteTSI(p)->tsi_count != 0) 02298 continue; 02299 rpmteTSI(p)->tsi_suc = NULL; 02300 addQ(p, &q, &r, prefcolor); 02301 qlen++; 02302 } 02303 pi = rpmtsiFree(pi); 02304 02305 /* T5. Output front of queue (T7. Remove from queue.) */ 02306 for (; q != NULL; q = rpmteTSI(q)->tsi_suc) { 02307 02308 /* Mark the package as unqueued. */ 02309 rpmteTSI(q)->tsi_queued = 0; 02310 02311 if (oType != 0) 02312 switch (rpmteType(q)) { 02313 case TR_ADDED: 02314 if (!(oType & TR_ADDED)) 02315 continue; 02316 /*@switchbreak@*/ break; 02317 case TR_REMOVED: 02318 if (!(oType & TR_REMOVED)) 02319 continue; 02320 /*@switchbreak@*/ break; 02321 default: 02322 continue; 02323 /*@notreached@*/ /*@switchbreak@*/ break; 02324 } 02325 deptypechar = (rpmteType(q) == TR_REMOVED ? '-' : '+'); 02326 02327 treex = rpmteTree(q); 02328 depth = rpmteDepth(q); 02329 breadth = ((depth < npeer) ? peer[depth]++ : 0); 02330 (void) rpmteSetBreadth(q, breadth); 02331 02332 rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%5d%5d%5d %*s%c%s\n", 02333 orderingCount, rpmteNpreds(q), 02334 rpmteTSI(q)->tsi_qcnt, 02335 treex, depth, breadth, 02336 (2 * depth), "", 02337 deptypechar, 02338 (rpmteNEVRA(q) ? rpmteNEVRA(q) : "???")); 02339 02340 (void) rpmteSetDegree(q, 0); 02341 tsbytes += rpmtePkgFileSize(q); 02342 02343 ordering[orderingCount] = rpmteAddedKey(q); 02344 orderingCount++; 02345 qlen--; 02346 loopcheck--; 02347 02348 /* T6. Erase relations. */ 02349 tsi_next = rpmteTSI(q)->tsi_next; 02350 rpmteTSI(q)->tsi_next = NULL; 02351 while ((tsi = tsi_next) != NULL) { 02352 tsi_next = tsi->tsi_next; 02353 tsi->tsi_next = NULL; 02354 p = tsi->tsi_suc; 02355 if (p && (--rpmteTSI(p)->tsi_count) <= 0) { 02356 02357 (void) rpmteSetTree(p, treex); 02358 (void) rpmteSetDepth(p, depth+1); 02359 (void) rpmteSetParent(p, q); 02360 (void) rpmteSetDegree(q, rpmteDegree(q)+1); 02361 02362 /* XXX TODO: add control bit. */ 02363 rpmteTSI(p)->tsi_suc = NULL; 02364 /*@-nullstate@*/ /* XXX FIX: rpmteTSI(q)->tsi_suc can be NULL. */ 02365 addQ(p, &rpmteTSI(q)->tsi_suc, &r, prefcolor); 02366 /*@=nullstate@*/ 02367 qlen++; 02368 } 02369 tsi = _free(tsi); 02370 } 02371 if (!_printed && loopcheck == qlen && rpmteTSI(q)->tsi_suc != NULL) { 02372 _printed++; 02373 (void) rpmtsUnorderedSuccessors(ts, orderingCount); 02374 rpmMessage(RPMMESS_DEBUG, 02375 D_("========== successors only (%d bytes)\n"), (int)tsbytes); 02376 02377 /* Relink the queue in presentation order. */ 02378 tsi = rpmteTSI(q); 02379 pi = rpmtsiInit(ts); 02380 while ((p = rpmtsiNext(pi, oType)) != NULL) { 02381 /* Is this element in the queue? */ 02382 if (rpmteTSI(p)->tsi_queued == 0) 02383 /*@innercontinue@*/ continue; 02384 tsi->tsi_suc = p; 02385 tsi = rpmteTSI(p); 02386 } 02387 pi = rpmtsiFree(pi); 02388 tsi->tsi_suc = NULL; 02389 } 02390 } 02391 02392 /* T8. End of process. Check for loops. */ 02393 if (loopcheck != 0) { 02394 int nzaps; 02395 02396 /* T9. Initialize predecessor chain. */ 02397 nzaps = 0; 02398 qi = rpmtsiInit(ts); 02399 while ((q = rpmtsiNext(qi, oType)) != NULL) { 02400 rpmteTSI(q)->tsi_chain = NULL; 02401 rpmteTSI(q)->tsi_queued = 0; 02402 /* Mark packages already sorted. */ 02403 if (rpmteTSI(q)->tsi_count == 0) 02404 rpmteTSI(q)->tsi_count = -1; 02405 } 02406 qi = rpmtsiFree(qi); 02407 02408 /* T10. Mark all packages with their predecessors. */ 02409 qi = rpmtsiInit(ts); 02410 while ((q = rpmtsiNext(qi, oType)) != NULL) { 02411 if ((tsi = rpmteTSI(q)->tsi_next) == NULL) 02412 continue; 02413 rpmteTSI(q)->tsi_next = NULL; 02414 markLoop(tsi, q); 02415 rpmteTSI(q)->tsi_next = tsi; 02416 } 02417 qi = rpmtsiFree(qi); 02418 02419 /* T11. Print all dependency loops. */ 02420 ri = rpmtsiInit(ts); 02421 while ((r = rpmtsiNext(ri, oType)) != NULL) 02422 { 02423 int printed; 02424 02425 printed = 0; 02426 02427 /* T12. Mark predecessor chain, looking for start of loop. */ 02428 for (q = rpmteTSI(r)->tsi_chain; q != NULL; 02429 q = rpmteTSI(q)->tsi_chain) 02430 { 02431 if (rpmteTSI(q)->tsi_queued) 02432 /*@innerbreak@*/ break; 02433 rpmteTSI(q)->tsi_queued = 1; 02434 } 02435 02436 /* T13. Print predecessor chain from start of loop. */ 02437 while ((p = q) != NULL && (q = rpmteTSI(p)->tsi_chain) != NULL) { 02438 const char * dp; 02439 char buf[4096]; 02440 int msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS)) 02441 ? RPMMESS_WARNING : RPMMESS_ERROR; 02442 ; 02443 02444 /* Unchain predecessor loop. */ 02445 rpmteTSI(p)->tsi_chain = NULL; 02446 02447 if (!printed) { 02448 rpmMessage(msglvl, _("LOOP:\n")); 02449 printed = 1; 02450 } 02451 02452 /* Find (and destroy if co-requisite) "q <- p" relation. */ 02453 dp = zapRelation(q, p, 1, &nzaps, msglvl); 02454 02455 /* Print next member of loop. */ 02456 buf[0] = '\0'; 02457 if (rpmteNEVRA(p) != NULL) 02458 (void) stpcpy(buf, rpmteNEVRA(p)); 02459 rpmMessage(msglvl, " %-40s %s\n", buf, 02460 (dp ? dp : "not found!?!")); 02461 02462 dp = _free(dp); 02463 } 02464 02465 /* Walk (and erase) linear part of predecessor chain as well. */ 02466 for (p = r, q = rpmteTSI(r)->tsi_chain; q != NULL; 02467 p = q, q = rpmteTSI(q)->tsi_chain) 02468 { 02469 /* Unchain linear part of predecessor loop. */ 02470 rpmteTSI(p)->tsi_chain = NULL; 02471 rpmteTSI(p)->tsi_queued = 0; 02472 } 02473 } 02474 ri = rpmtsiFree(ri); 02475 02476 /* If a relation was eliminated, then continue sorting. */ 02477 /* XXX TODO: add control bit. */ 02478 if (nzaps && nrescans-- > 0) { 02479 rpmMessage(RPMMESS_DEBUG, D_("========== continuing tsort ...\n")); 02480 goto rescan; 02481 } 02482 02483 /* Return no. of packages that could not be ordered. */ 02484 rpmMessage(RPMMESS_ERROR, _("rpmtsOrder failed, %d elements remain\n"), 02485 loopcheck); 02486 02487 #ifdef NOTYET 02488 /* Do autorollback goal since we could not sort this transaction properly. */ 02489 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL); 02490 #endif 02491 02492 return loopcheck; 02493 } 02494 02495 /* Clean up tsort remnants (if any). */ 02496 pi = rpmtsiInit(ts); 02497 while ((p = rpmtsiNext(pi, 0)) != NULL) 02498 rpmteFreeTSI(p); 02499 pi = rpmtsiFree(pi); 02500 02501 /* 02502 * The order ends up as installed packages followed by removed packages. 02503 */ 02504 orderList = xcalloc(numOrderList, sizeof(*orderList)); 02505 j = 0; 02506 pi = rpmtsiInit(ts); 02507 while ((p = rpmtsiNext(pi, oType)) != NULL) { 02508 /* Prepare added/erased package ordering permutation. */ 02509 orderList[j].pkgKey = rpmteAddedKey(p); 02510 orderList[j].orIndex = rpmtsiOc(pi); 02511 j++; 02512 } 02513 pi = rpmtsiFree(pi); 02514 02515 qsort(orderList, numOrderList, sizeof(*orderList), orderListIndexCmp); 02516 02517 /*@-type@*/ 02518 newOrder = xcalloc(ts->orderCount, sizeof(*newOrder)); 02519 /*@=type@*/ 02520 /*@-branchstate@*/ 02521 for (i = 0, newOrderCount = 0; i < orderingCount; i++) 02522 { 02523 struct orderListIndex_s key; 02524 orderListIndex needle; 02525 02526 key.pkgKey = ordering[i]; 02527 needle = bsearch(&key, orderList, numOrderList, 02528 sizeof(key), orderListIndexCmp); 02529 if (needle == NULL) /* XXX can't happen */ 02530 continue; 02531 02532 j = needle->orIndex; 02533 if ((q = ts->order[j]) == NULL || needle->pkgKey == RPMAL_NOMATCH) 02534 continue; 02535 02536 newOrder[newOrderCount++] = q; 02537 ts->order[j] = NULL; 02538 } 02539 /*@=branchstate@*/ 02540 02541 assert(newOrderCount == ts->orderCount); 02542 02543 /*@+voidabstract@*/ 02544 ts->order = _free(ts->order); 02545 /*@=voidabstract@*/ 02546 ts->order = newOrder; 02547 ts->orderAlloced = ts->orderCount; 02548 orderList = _free(orderList); 02549 02550 #ifdef DYING /* XXX now done at the CLI level just before rpmtsRun(). */ 02551 rpmtsClean(ts); 02552 #endif 02553 freeBadDeps(); 02554 02555 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ORDER), 0); 02556 02557 return 0; 02558 } 02559 /*@=bounds@*/ 02560 02561 int rpmtsCheck(rpmts ts) 02562 { 02563 const char * depName = NULL;; 02564 rpmdepFlags depFlags = rpmtsDFlags(ts); 02565 uint_32 tscolor = rpmtsColor(ts); 02566 rpmdbMatchIterator mi = NULL; 02567 rpmtsi pi = NULL; rpmte p; 02568 int closeatexit = 0; 02569 int xx; 02570 int rc; 02571 02572 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0); 02573 02574 /* Do lazy, readonly, open of rpm database. */ 02575 if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) { 02576 if ((rc = rpmtsOpenDB(ts, ts->dbmode)) != 0) 02577 goto exit; 02578 closeatexit = 1; 02579 } 02580 02581 ts->probs = rpmpsFree(ts->probs); 02582 ts->probs = rpmpsCreate(); 02583 02584 rpmalMakeIndex(ts->addedPackages); 02585 02586 /* 02587 * Look at all of the added packages and make sure their dependencies 02588 * are satisfied. 02589 */ 02590 pi = rpmtsiInit(ts); 02591 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 02592 rpmds provides, requires, conflicts, dirnames, linktos; 02593 02594 /*@-nullpass@*/ /* FIX: rpmts{A,O} can return null. */ 02595 rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s/%s 0x%x\n", 02596 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 02597 /*@=nullpass@*/ 02598 requires = (!(depFlags & RPMDEPS_FLAG_NOREQUIRES) 02599 ? rpmteDS(p, RPMTAG_REQUIRENAME) : NULL); 02600 conflicts = (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS) 02601 ? rpmteDS(p, RPMTAG_CONFLICTNAME) : NULL); 02602 dirnames = (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS) 02603 ? rpmteDS(p, RPMTAG_DIRNAMES) : NULL); 02604 linktos = (!(depFlags & RPMDEPS_FLAG_NOLINKTOS) 02605 ? rpmteDS(p, RPMTAG_FILELINKTOS) : NULL); 02606 02607 rc = checkPackageDeps(ts, rpmteNEVRA(p), 02608 requires, conflicts, dirnames, linktos, 02609 NULL, tscolor, 1); 02610 if (rc) 02611 goto exit; 02612 02613 rc = 0; 02614 provides = rpmteDS(p, RPMTAG_PROVIDENAME); 02615 provides = rpmdsInit(provides); 02616 if (provides != NULL) 02617 while (rpmdsNext(provides) >= 0) { 02618 depName = _free(depName); 02619 depName = xstrdup(rpmdsN(provides)); 02620 02621 #ifdef NOTYET 02622 if (rpmdsNSType(provides) == RPMNS_TYPE_ENVVAR) { 02623 const char * EVR = rpmdsEVR(provides); 02624 if (rpmdsNegateRC(provides, 0)) 02625 EVR = NULL; 02626 rc = envPut(depName, EVR); 02627 if (!rc) 02628 /*@innercontinue@*/ continue; 02629 /*@innerbreak@*/ break; 02630 } 02631 #endif 02632 02633 /* Adding: check provides key against conflicts matches. */ 02634 if (!checkDependentConflicts(ts, depName)) 02635 /*@innercontinue@*/ continue; 02636 rc = 1; 02637 /*@innerbreak@*/ break; 02638 } 02639 if (rc) 02640 goto exit; 02641 } 02642 pi = rpmtsiFree(pi); 02643 02644 /* 02645 * Look at the removed packages and make sure they aren't critical. 02646 */ 02647 pi = rpmtsiInit(ts); 02648 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { 02649 rpmds provides; 02650 rpmfi fi; 02651 02652 /*@-nullpass@*/ /* FIX: rpmts{A,O} can return null. */ 02653 rpmMessage(RPMMESS_DEBUG, "========== --- %s %s/%s 0x%x\n", 02654 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 02655 /*@=nullpass@*/ 02656 02657 rc = 0; 02658 provides = rpmteDS(p, RPMTAG_PROVIDENAME); 02659 provides = rpmdsInit(provides); 02660 if (provides != NULL) 02661 while (rpmdsNext(provides) >= 0) { 02662 depName = _free(depName); 02663 depName = xstrdup(rpmdsN(provides)); 02664 02665 /* Erasing: check provides against requiredby matches. */ 02666 if (!checkDependentPackages(ts, depName)) 02667 /*@innercontinue@*/ continue; 02668 rc = 1; 02669 /*@innerbreak@*/ break; 02670 } 02671 if (rc) 02672 goto exit; 02673 02674 rc = 0; 02675 fi = rpmteFI(p, RPMTAG_BASENAMES); 02676 fi = rpmfiInit(fi, 0); 02677 while (rpmfiNext(fi) >= 0) { 02678 depName = _free(depName); 02679 depName = xstrdup(rpmfiFN(fi)); 02680 /* Erasing: check filename against requiredby matches. */ 02681 if (!checkDependentPackages(ts, depName)) 02682 /*@innercontinue@*/ continue; 02683 rc = 1; 02684 /*@innerbreak@*/ break; 02685 } 02686 if (rc) 02687 goto exit; 02688 } 02689 pi = rpmtsiFree(pi); 02690 02691 /* 02692 * Make sure transaction dependencies are satisfied. 02693 */ 02694 { const char * tsNEVRA = "transaction dependencies"; 02695 rpmds R = rpmdsFromPRCO(ts->PRCO, RPMTAG_REQUIRENAME); 02696 rpmds C = rpmdsFromPRCO(ts->PRCO, RPMTAG_CONFLICTNAME); 02697 rpmds D = NULL; 02698 rpmds L = NULL; 02699 const char * dep = NULL; 02700 int adding = 2; 02701 tscolor = 0; /* XXX no coloring for transaction dependencies. */ 02702 rc = checkPackageDeps(ts, tsNEVRA, R, C, D, L, dep, tscolor, adding); 02703 if (rc) 02704 goto exit; 02705 } 02706 02707 rc = 0; 02708 02709 exit: 02710 mi = rpmdbFreeIterator(mi); 02711 pi = rpmtsiFree(pi); 02712 depName = _free(depName); 02713 02714 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0); 02715 02716 /*@-branchstate@*/ 02717 if (closeatexit) 02718 xx = rpmtsCloseDB(ts); 02719 #if defined(CACHE_DEPENDENCY_RESULT) 02720 else if (_cacheDependsRC) 02721 xx = rpmdbCloseDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS); 02722 #endif 02723 /*@=branchstate@*/ 02724 02725 #ifdef NOTYET 02726 /* On failed dependencies, perform the autorollback goal (if any). */ 02727 { rpmps ps = rpmtsProblems(ts); 02728 if (rc || rpmpsNumProblems(ps) > 0) 02729 (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL); 02730 ps = rpmpsFree(ps); 02731 } 02732 #endif 02733 02734 return rc; 02735 }