/* Check a given dependency against installed packages */ static void checkInstDeps(rpmts ts, depCache dcache, rpmte te, rpmTag depTag, const char *dep) { Header h; rpmdbMatchIterator mi = rpmtsPrunedIterator(ts, depTag, dep, 1); rpmstrPool pool = rpmtsPool(ts); /* require-problems are unsatisfied, others appear "satisfied" */ int is_problem = (depTag == RPMTAG_REQUIRENAME); while ((h = rpmdbNextIterator(mi)) != NULL) { char * pkgNEVRA; rpmds ds; /* Ignore self-obsoletes and self-conflicts */ if (depTag == RPMTAG_OBSOLETENAME || depTag == RPMTAG_CONFLICTNAME) { unsigned int instance = headerGetInstance(h); if (instance && instance == rpmteDBInstance(te)) continue; } pkgNEVRA = headerGetAsString(h, RPMTAG_NEVRA); ds = rpmdsNewPool(pool, h, depTag, 0); rpmdsSetIx(ds, rpmdbGetIteratorFileNum(mi)); if (unsatisfiedDepend(ts, dcache, ds) == is_problem) rpmteAddDepProblem(te, pkgNEVRA, ds, NULL); rpmdsFree(ds); free(pkgNEVRA); } rpmdbFreeIterator(mi); }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, uint64_t fileCount, fingerPrintCache fpc) { tsMembers tsmem = rpmtsMembers(ts); rpmte p; rpmfiles fi; rpmfs fs; int j; unsigned int fileNum; rpmdbMatchIterator mi; Header h, newheader; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts, fileCount); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint *fpp = NULL; unsigned int installedPkg; int beingRemoved = 0; rpmfiles otherFi = NULL; rpmte *removedPkg = NULL; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); if (packageHashGetEntry(tsmem->removedPackages, installedPkg, &removedPkg, NULL, NULL)) { beingRemoved = 1; otherFi = rpmteFiles(removedPkg[0]); } h = headerLink(h); /* For packages being removed we can use its rpmfi to avoid all this */ if (!beingRemoved) { headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); } /* loop over all interesting files in that package */ do { int fpIx; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; /* lookup finger print for this file */ fileNum = rpmdbGetIteratorFileNum(mi); if (!beingRemoved) { rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); fpLookup(fpc, dirName, baseName, &fpp); fpIx = 0; } else { fpp = rpmfilesFps(otherFi); fpIx = fileNum; } /* search for files in the transaction with same finger print */ fpCacheGetByFp(fpc, fpp, fpIx, &recs, &numRecs); for (j = 0; j < numRecs; j++) { p = recs[j].p; fi = rpmteFiles(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { /* XXX What to do if this fails? */ otherFi = rpmfilesNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } handleInstInstalledFile(ts, p, fi, recs[j].fileno, h, otherFi, fileNum, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } rpmfilesFree(fi); } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfilesFree(otherFi); if (!beingRemoved) { rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); free(fpp); } headerFree(h); h = newheader; } rpmdbFreeIterator(mi); }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, fingerPrintCache fpc) { rpmps ps; rpmte p; rpmfi fi; rpmfs fs; rpmfi otherFi=NULL; int j; int xx; unsigned int fileNum; const char * oldDir; rpmdbMatchIterator mi; Header h, newheader; int beingRemoved; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } ps = rpmtsProblems(ts); /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint fp; unsigned int installedPkg; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); beingRemoved = 0; if (ts->removedPackages != NULL) for (j = 0; j < ts->numRemovedPackages; j++) { if (ts->removedPackages[j] != installedPkg) continue; beingRemoved = 1; break; } h = headerLink(h); headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); oldDir = NULL; /* loop over all interesting files in that package */ do { int gotRecs; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; fileNum = rpmdbGetIteratorFileNum(mi); rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); /* lookup finger print for this file */ if ( dirName == oldDir) { /* directory is the same as last round */ fp.baseName = baseName; } else { fp = fpLookup(fpc, dirName, baseName, 1); oldDir = dirName; } /* search for files in the transaction with same finger print */ gotRecs = rpmFpHashGetEntry(ts->ht, &fp, &recs, &numRecs, NULL); for (j=0; (j<numRecs)&&gotRecs; j++) { p = recs[j].p; fi = rpmteFI(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } rpmfiSetFX(fi, recs[j].fileno); rpmfiSetFX(otherFi, fileNum); xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { rpmfiSetFX(fi, recs[j].fileno); if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfiFree(otherFi); rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); headerFree(h); h = newheader; } mi = rpmdbFreeIterator(mi); }
/* Cached rpmdb provide lookup, returns 0 if satisfied, 1 otherwise */ static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep) { const char * Name = rpmdsN(dep); const char * DNEVR = rpmdsDNEVR(dep); rpmTagVal deptag = rpmdsTagN(dep); int *cachedrc = NULL; rpmdbMatchIterator mi = NULL; Header h = NULL; int rc = 0; /* pretrans deps are provided by current packages, don't prune erasures */ int prune = (rpmdsFlags(dep) & RPMSENSE_PRETRANS) ? 0 : 1; unsigned int keyhash = 0; /* See if we already looked this up */ if (prune) { keyhash = depCacheKeyHash(dcache, DNEVR); if (depCacheGetHEntry(dcache, DNEVR, keyhash, &cachedrc, NULL, NULL)) { rc = *cachedrc; rpmdsNotify(dep, "(cached)", rc); return rc; } } /* * See if a filename dependency is a real file in some package, * taking file state into account: replaced, wrong colored and * not installed files can not satisfy a dependency. */ if (deptag != RPMTAG_OBSOLETENAME && Name[0] == '/') { mi = rpmtsPrunedIterator(ts, RPMDBI_INSTFILENAMES, Name, prune); while ((h = rpmdbNextIterator(mi)) != NULL) { /* Ignore self-conflicts */ if (deptag == RPMTAG_CONFLICTNAME) { unsigned int instance = headerGetInstance(h); if (instance && instance == rpmdsInstance(dep)) continue; } rpmdsNotify(dep, "(db files)", rc); break; } rpmdbFreeIterator(mi); } /* Otherwise look in provides no matter what the dependency looks like */ if (h == NULL) { rpmstrPool tspool = rpmtsPool(ts); /* Obsoletes use just name alone, everything else uses provides */ rpmTagVal dbtag = RPMDBI_PROVIDENAME; int selfevr = 0; if (deptag == RPMTAG_OBSOLETENAME) { dbtag = RPMDBI_NAME; selfevr = 1; } mi = rpmtsPrunedIterator(ts, dbtag, Name, prune); while ((h = rpmdbNextIterator(mi)) != NULL) { /* Provide-indexes can't be used with nevr-only matching */ int prix = (selfevr) ? -1 : rpmdbGetIteratorFileNum(mi); int match = rpmdsMatches(tspool, h, prix, dep, selfevr, _rpmds_nopromote); /* Ignore self-obsoletes and self-conflicts */ if (match && (deptag == RPMTAG_OBSOLETENAME || deptag == RPMTAG_CONFLICTNAME)) { unsigned int instance = headerGetInstance(h); if (instance && instance == rpmdsInstance(dep)) match = 0; } if (match) { rpmdsNotify(dep, "(db provides)", rc); break; } } rpmdbFreeIterator(mi); } rc = (h != NULL) ? 0 : 1; /* Cache the relatively expensive rpmdb lookup results */ /* Caching the oddball non-pruned case would mess up other results */ if (prune) depCacheAddHEntry(dcache, xstrdup(DNEVR), keyhash, rc); return rc; }