void rpmalAdd(rpmal al, rpmte p) { rpmalNum pkgNum; availablePackage alp; if (al->size == al->alloced) { al->alloced += al->delta; al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced); } pkgNum = al->size++; alp = al->list + pkgNum; alp->p = p; alp->provides = rpmdsLink(rpmteDS(p, RPMTAG_PROVIDENAME)); alp->fi = rpmfiLink(rpmteFI(p)); if (al->providesHash != NULL) { // index is already created rpmalAddProvides(al, pkgNum, alp->provides); rpmalAddFiles(al, pkgNum, alp->fi); } assert(((rpmalNum)(alp - al->list)) == pkgNum); }
/* --- Object methods */ static JSBool rpmte_ds(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { void * ptr = JS_GetInstancePrivate(cx, obj, &rpmteClass, NULL); rpmte te = ptr; rpmTag tagN = RPMTAG_NAME; JSBool ok = JS_FALSE; _METHOD_DEBUG_ENTRY(_debug); if (!(ok = JS_ConvertArguments(cx, argc, argv, "/i", &tagN))) goto exit; { rpmds ds = NULL; JSObject *dso = NULL; if ((ds = rpmteDS(te, tagN)) == NULL) *rval = JSVAL_NULL; else if ((dso = JS_NewObject(cx, &rpmdsClass, NULL, NULL)) != NULL && JS_SetPrivate(cx, dso, rpmdsLink(ds, __FUNCTION__))) *rval = OBJECT_TO_JSVAL(dso); else { ds = rpmdsFree(ds); *rval = JSVAL_VOID; } } ok = JS_TRUE; exit: return ok; }
void rpmalAdd(rpmal al, rpmte p) { rpmalNum pkgNum; availablePackage alp; if (al->size == al->alloced) { al->alloced += al->delta; al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced); } pkgNum = al->size++; alp = al->list + pkgNum; alp->p = p; alp->provides = rpmdsLink(rpmteDS(p, RPMTAG_PROVIDENAME)); alp->obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME)); alp->fi = rpmteFiles(p); /* * Transition-time safe-guard to catch private-pool uses. * File sets with no files have NULL pool, that's fine. But WTF is up * with the provides: every single package should have at least its * own name as a provide, and thus never NULL, and normal use matches * this expectation. However the test-suite is tripping up on NULL * NULL pool from NULL alp->provides in numerous cases? */ { rpmstrPool fipool = rpmfilesPool(alp->fi); rpmstrPool dspool = rpmdsPool(alp->provides); assert(fipool == NULL || fipool == al->pool); assert(dspool == NULL || dspool == al->pool); } /* Try to be lazy as delayed hash creation is cheaper */ if (al->providesHash != NULL) rpmalAddProvides(al, pkgNum, alp->provides); if (al->obsoletesHash != NULL) rpmalAddObsoletes(al, pkgNum, alp->obsoletes); if (al->fileHash != NULL) rpmalAddFiles(al, pkgNum, alp->fi); assert(((rpmalNum)(alp - al->list)) == pkgNum); }
static rpmte * rpmalAllFileSatisfiesDepend(const rpmal al, const char *fileName, const rpmds filterds) { const char *slash; rpmte * ret = NULL; if (al == NULL || fileName == NULL || *fileName != '/') return NULL; /* Split path into dirname and basename components for lookup */ if ((slash = strrchr(fileName, '/')) != NULL) { availableIndexFileEntry result; int resultCnt = 0; size_t bnStart = (slash - fileName) + 1; rpmsid baseName; if (al->fileHash == NULL) rpmalMakeFileIndex(al); baseName = rpmstrPoolId(al->pool, fileName + bnStart, 0); if (!baseName) return NULL; /* no match possible */ rpmalFileHashGetEntry(al->fileHash, baseName, &result, &resultCnt, NULL); if (resultCnt > 0) { int i, found; ret = xmalloc((resultCnt+1) * sizeof(*ret)); fingerPrint * fp = NULL; rpmsid dirName = rpmstrPoolIdn(al->pool, fileName, bnStart, 1); if (!al->fpc) al->fpc = fpCacheCreate(1001, NULL); fpLookup(al->fpc, rpmstrPoolStr(al->pool, dirName), fileName + bnStart, &fp); for (found = i = 0; i < resultCnt; i++) { availablePackage alp = al->list + result[i].pkgNum; if (alp->p == NULL) /* deleted */ continue; /* ignore self-conflicts/obsoletes */ if (filterds && rpmteDS(alp->p, rpmdsTagN(filterds)) == filterds) continue; if (result[i].dirName != dirName && !fpLookupEquals(al->fpc, fp, rpmstrPoolStr(al->pool, result[i].dirName), fileName + bnStart)) continue; ret[found] = alp->p; found++; } _free(fp); ret[found] = NULL; } } return ret; }
/* Add erase elements for obsoleted packages of same color (if any). */ static int addObsoleteErasures(rpmts ts, rpm_color_t tscolor, rpmte p) { rpmstrPool tspool = rpmtsPool(ts); rpmds obsoletes = rpmdsInit(rpmteDS(p, RPMTAG_OBSOLETENAME)); Header oh; int rc = 0; while (rpmdsNext(obsoletes) >= 0 && rc == 0) { const char * Name; rpmdbMatchIterator mi = NULL; if ((Name = rpmdsN(obsoletes)) == NULL) continue; /* XXX can't happen */ mi = rpmtsPrunedIterator(ts, RPMDBI_NAME, Name, 1); while((oh = rpmdbNextIterator(mi)) != NULL) { const char *oarch = headerGetString(oh, RPMTAG_ARCH); int match; /* avoid self-obsoleting packages */ if (rstreq(rpmteN(p), Name) && rstreq(rpmteA(p), oarch)) { char * ohNEVRA = headerGetAsString(oh, RPMTAG_NEVRA); rpmlog(RPMLOG_DEBUG, " Not obsoleting: %s\n", ohNEVRA); free(ohNEVRA); continue; } /* * Rpm prior to 3.0.3 does not have versioned obsoletes. * If no obsoletes version info is available, match all names. */ match = (rpmdsEVR(obsoletes) == NULL); if (!match) match = rpmdsMatches(tspool, oh, -1, obsoletes, 1, _rpmds_nopromote); if (match) { char * ohNEVRA = headerGetAsString(oh, RPMTAG_NEVRA); rpmlog(RPMLOG_DEBUG, " Obsoletes: %s\t\terases %s\n", rpmdsDNEVR(obsoletes)+2, ohNEVRA); free(ohNEVRA); if (removePackage(ts, oh, p)) { rc = 1; break; } } } rpmdbFreeIterator(mi); } return rc; }
int rpmtsCheck(rpmts ts) { rpm_color_t tscolor = rpmtsColor(ts); rpmtsi pi = NULL; rpmte p; int closeatexit = 0; int rc = 0; depCache dcache = NULL; filedepHash confilehash = NULL; /* file conflicts of installed packages */ filedepHash connotfilehash = NULL; /* file conflicts of installed packages */ depexistsHash connothash = NULL; filedepHash reqfilehash = NULL; /* file requires of installed packages */ filedepHash reqnotfilehash = NULL; /* file requires of installed packages */ depexistsHash reqnothash = NULL; fingerPrintCache fpc = NULL; rpmdb rdb = NULL; (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0); /* Do lazy, readonly, open of rpm database. */ rdb = rpmtsGetRdb(ts); if (rdb == NULL && rpmtsGetDBMode(ts) != -1) { if ((rc = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0) goto exit; rdb = rpmtsGetRdb(ts); closeatexit = 1; } if (rdb) rpmdbCtrl(rdb, RPMDB_CTRL_LOCK_RO); /* XXX FIXME: figure some kind of heuristic for the cache size */ dcache = depCacheCreate(5001, rstrhash, strcmp, (depCacheFreeKey)rfree, NULL); /* build hashes of all confilict sdependencies */ confilehash = filedepHashCreate(257, rstrhash, strcmp, (filedepHashFreeKey)rfree, (filedepHashFreeData)rfree); connothash = depexistsHashCreate(257, rstrhash, strcmp, (filedepHashFreeKey)rfree); connotfilehash = filedepHashCreate(257, rstrhash, strcmp, (filedepHashFreeKey)rfree, (filedepHashFreeData)rfree); addIndexToDepHashes(ts, RPMTAG_CONFLICTNAME, NULL, confilehash, connothash, connotfilehash); if (!filedepHashNumKeys(confilehash)) confilehash = filedepHashFree(confilehash); if (!depexistsHashNumKeys(connothash)) connothash= depexistsHashFree(connothash); if (!filedepHashNumKeys(connotfilehash)) connotfilehash = filedepHashFree(connotfilehash); /* build hashes of all requires dependencies */ reqfilehash = filedepHashCreate(8191, rstrhash, strcmp, (filedepHashFreeKey)rfree, (filedepHashFreeData)rfree); reqnothash = depexistsHashCreate(257, rstrhash, strcmp, (filedepHashFreeKey)rfree); reqnotfilehash = filedepHashCreate(257, rstrhash, strcmp, (filedepHashFreeKey)rfree, (filedepHashFreeData)rfree); addIndexToDepHashes(ts, RPMTAG_REQUIRENAME, NULL, reqfilehash, reqnothash, reqnotfilehash); if (!filedepHashNumKeys(reqfilehash)) reqfilehash = filedepHashFree(reqfilehash); if (!depexistsHashNumKeys(reqnothash)) reqnothash= depexistsHashFree(reqnothash); if (!filedepHashNumKeys(reqnotfilehash)) reqnotfilehash = filedepHashFree(reqnotfilehash); /* * Look at all of the added packages and make sure their dependencies * are satisfied. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME)); rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_REQUIRENAME), tscolor); checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_CONFLICTNAME), tscolor); checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_OBSOLETENAME), tscolor); /* Check provides against conflicts in installed packages. */ while (rpmdsNext(provides) >= 0) { const char *dep = rpmdsN(provides); checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, dep); if (reqnothash && depexistsHashHasEntry(reqnothash, dep)) checkNotInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, dep); } /* Skip obsoletion checks for source packages (ie build) */ if (rpmteIsSource(p)) continue; /* Check package name (not provides!) against installed obsoletes */ checkInstDeps(ts, dcache, p, RPMTAG_OBSOLETENAME, rpmteN(p)); /* Check filenames against installed conflicts */ if (confilehash || reqnotfilehash) { rpmfiles files = rpmteFiles(p); rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD); while (rpmfiNext(fi) >= 0) { if (confilehash) checkInstFileDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fi, 0, confilehash, &fpc); if (reqnotfilehash) checkInstFileDeps(ts, dcache, p, RPMTAG_REQUIRENAME, fi, 1, reqnotfilehash, &fpc); } rpmfiFree(fi); rpmfilesFree(files); } } rpmtsiFree(pi); /* * Look at the removed packages and make sure they aren't critical. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME)); rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); /* Check provides and filenames against installed dependencies. */ while (rpmdsNext(provides) >= 0) { const char *dep = rpmdsN(provides); checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, dep); if (connothash && depexistsHashHasEntry(connothash, dep)) checkNotInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, dep); } if (reqfilehash || connotfilehash) { rpmfiles files = rpmteFiles(p); rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD);; while (rpmfiNext(fi) >= 0) { if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) { if (reqfilehash) checkInstFileDeps(ts, dcache, p, RPMTAG_REQUIRENAME, fi, 0, reqfilehash, &fpc); if (connotfilehash) checkInstFileDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fi, 1, connotfilehash, &fpc); } } rpmfiFree(fi); rpmfilesFree(files); } } rpmtsiFree(pi); if (rdb) rpmdbCtrl(rdb, RPMDB_CTRL_UNLOCK_RO); exit: depCacheFree(dcache); filedepHashFree(confilehash); filedepHashFree(connotfilehash); depexistsHashFree(connothash); filedepHashFree(reqfilehash); filedepHashFree(reqnotfilehash); depexistsHashFree(reqnothash); fpCacheFree(fpc); (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0); if (closeatexit) (void) rpmtsCloseDB(ts); return rc; }
/* * Check for previously added versions and obsoletions. * Return index where to place this element, or -1 to skip. * XXX OBSOLETENAME is a bit of a hack, but gives us what * we want from rpmal: we're only interested in added package * names here, not their provides. */ static int findPos(rpmts ts, rpm_color_t tscolor, rpmte te, int upgrade) { tsMembers tsmem = rpmtsMembers(ts); int oc = tsmem->orderCount; int skip = 0; const char * name = rpmteN(te); const char * evr = rpmteEVR(te); rpmte p; rpmstrPool tspool = rpmtsPool(ts); rpmds oldChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME, name, evr, (RPMSENSE_LESS)); rpmds newChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME, name, evr, (RPMSENSE_GREATER)); rpmds sameChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME, name, evr, (RPMSENSE_EQUAL)); rpmds obsChk = rpmteDS(te, RPMTAG_OBSOLETENAME); /* If obsoleting package has already been added, skip this. */ if ((p = checkObsoleted(tsmem->addedPackages, rpmteDS(te, RPMTAG_NAME)))) { skip = 1; goto exit; } /* If obsoleted package has already been added, replace with this. */ rpmdsInit(obsChk); while (rpmdsNext(obsChk) >= 0) { /* XXX Obsoletes are not colored */ if ((p = checkAdded(tsmem->addedPackages, 0, te, obsChk))) { goto exit; } } /* If same NEVR has already been added, skip this. */ if ((p = checkAdded(tsmem->addedPackages, tscolor, te, sameChk))) { skip = 1; goto exit; } /* On upgrades... */ if (upgrade) { /* ...if newer NEVR has already been added, skip this. */ if ((p = checkAdded(tsmem->addedPackages, tscolor, te, newChk))) { skip = 1; goto exit; } /* ...if older NEVR has already been added, replace with this. */ if ((p = checkAdded(tsmem->addedPackages, tscolor, te, oldChk))) { goto exit; } } exit: /* If we found a previous element we've something to say */ if (p != NULL && rpmIsVerbose()) { const char *msg = skip ? _("package %s was already added, skipping %s\n") : _("package %s was already added, replacing with %s\n"); rpmlog(RPMLOG_WARNING, msg, rpmteNEVRA(p), rpmteNEVRA(te)); } /* If replacing a previous element, find out where it is. Pooh. */ if (!skip && p != NULL) { for (oc = 0; oc < tsmem->orderCount; oc++) { if (p == tsmem->order[oc]) break; } } rpmdsFree(oldChk); rpmdsFree(newChk); rpmdsFree(sameChk); return (skip) ? -1 : oc; }
int rpmtsCheck(rpmts ts) { rpm_color_t tscolor = rpmtsColor(ts); rpmtsi pi = NULL; rpmte p; int closeatexit = 0; int rc = 0; depCache dcache = NULL; conflictsCache confcache = NULL; (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0); /* Do lazy, readonly, open of rpm database. */ if (rpmtsGetRdb(ts) == NULL && rpmtsGetDBMode(ts) != -1) { if ((rc = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0) goto exit; closeatexit = 1; } /* XXX FIXME: figure some kind of heuristic for the cache size */ dcache = depCacheCreate(5001, rstrhash, strcmp, (depCacheFreeKey)rfree, NULL); confcache = conflictsCacheCreate(257, rstrhash, strcmp, (depCacheFreeKey)rfree); if (confcache) { rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMTAG_CONFLICTNAME); if (ii) { char *key; size_t keylen; while ((rpmdbIndexIteratorNext(ii, (const void**)&key, &keylen)) == 0) { char *k; if (!key || keylen == 0 || key[0] != '/') continue; k = rmalloc(keylen + 1); memcpy(k, key, keylen); k[keylen] = 0; conflictsCacheAddEntry(confcache, k); } rpmdbIndexIteratorFree(ii); } } /* * Look at all of the added packages and make sure their dependencies * are satisfied. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME)); rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_REQUIRENAME), NULL, tscolor); checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_CONFLICTNAME), NULL, tscolor); checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_OBSOLETENAME), NULL, tscolor); /* Check provides against conflicts in installed packages. */ while (rpmdsNext(provides) >= 0) { checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, rpmdsN(provides)); } /* Skip obsoletion checks for source packages (ie build) */ if (rpmteIsSource(p)) continue; /* Check package name (not provides!) against installed obsoletes */ checkInstDeps(ts, dcache, p, RPMTAG_OBSOLETENAME, rpmteN(p)); /* Check filenames against installed conflicts */ if (conflictsCacheNumKeys(confcache)) { rpmfi fi = rpmfiInit(rpmteFI(p), 0); while (rpmfiNext(fi) >= 0) { const char *fn = rpmfiFN(fi); if (!conflictsCacheHasEntry(confcache, fn)) continue; checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fn); } } } rpmtsiFree(pi); /* * Look at the removed packages and make sure they aren't critical. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME)); rpmfi fi = rpmfiInit(rpmteFI(p), 0); rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); /* Check provides and filenames against installed dependencies. */ while (rpmdsNext(provides) >= 0) { checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmdsN(provides)); } while (rpmfiNext(fi) >= 0) { if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmfiFN(fi)); } } rpmtsiFree(pi); exit: depCacheFree(dcache); conflictsCacheFree(confcache); (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0); if (closeatexit) (void) rpmtsCloseDB(ts); return rc; }
/** * Check dep for an unsatisfied dependency. * @param ts transaction set * @param dep dependency * @return 0 if satisfied, 1 if not satisfied */ static int unsatisfiedDepend(rpmts ts, depCache dcache, rpmds dep) { tsMembers tsmem = rpmtsMembers(ts); int rc; int retrying = 0; int adding = (rpmdsInstance(dep) == 0); rpmsenseFlags dsflags = rpmdsFlags(dep); retry: rc = 0; /* assume dependency is satisfied */ /* * New features in rpm packaging implicitly add versioned dependencies * on rpmlib provides. The dependencies look like "rpmlib(YaddaYadda)". * Check those dependencies now. */ if (dsflags & RPMSENSE_RPMLIB) { if (tsmem->rpmlib == NULL) rpmdsRpmlibPool(rpmtsPool(ts), &(tsmem->rpmlib), NULL); if (tsmem->rpmlib != NULL && rpmdsSearch(tsmem->rpmlib, dep) >= 0) { rpmdsNotify(dep, "(rpmlib provides)", rc); goto exit; } goto unsatisfied; } /* Dont look at pre-requisites of already installed packages */ if (!adding && isInstallPreReq(dsflags) && !isErasePreReq(dsflags)) goto exit; /* Pretrans dependencies can't be satisfied by added packages. */ if (!(dsflags & RPMSENSE_PRETRANS)) { rpmte *matches = rpmalAllSatisfiesDepend(tsmem->addedPackages, dep); int match = 0; /* * Handle definitive matches within the added package set. * Self-obsoletes and -conflicts fall through here as we need to * check for possible other matches in the rpmdb. */ for (rpmte *m = matches; m && *m; m++) { rpmTagVal dtag = rpmdsTagN(dep); /* Requires match, look no further */ if (dtag == RPMTAG_REQUIRENAME) { match = 1; break; } /* Conflicts/obsoletes match on another package, look no further */ if (rpmteDS(*m, dtag) != dep) { match = 1; break; } } free(matches); if (match) goto exit; } /* See if the rpmdb provides it */ if (rpmdbProvides(ts, dcache, dep) == 0) goto exit; /* Search for an unsatisfied dependency. */ if (adding && !retrying && !(dsflags & RPMSENSE_PRETRANS)) { int xx = rpmtsSolve(ts, dep); if (xx == 0) goto exit; if (xx == -1) { retrying = 1; goto retry; } } unsatisfied: if (dsflags & RPMSENSE_MISSINGOK) { /* note the result, but missingok deps are never unsatisfied */ rpmdsNotify(dep, "(missingok)", 1); } else { /* dependency is unsatisfied */ rc = 1; rpmdsNotify(dep, NULL, rc); } exit: return rc; }
rpmte * rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds) { rpmte * ret = NULL; int i, ix, found; rpmsid nameId; const char *name; availableIndexEntry result; int resultCnt; int obsolete; rpmTagVal dtag; rpmds filterds = NULL; availablePackage alp; int rc; if (al == NULL || ds == NULL || (nameId = rpmdsNId(ds)) == 0) return ret; dtag = rpmdsTagN(ds); obsolete = (dtag == RPMTAG_OBSOLETENAME); if (dtag == RPMTAG_OBSOLETENAME || dtag == RPMTAG_CONFLICTNAME) filterds = ds; name = rpmstrPoolStr(al->pool, nameId); if (!obsolete && *name == '/') { /* First, look for files "contained" in package ... */ ret = rpmalAllFileSatisfiesDepend(al, name, filterds); if (ret != NULL && *ret != NULL) { rpmdsNotify(ds, "(added files)", 0); return ret; } /* ... then, look for files "provided" by package. */ ret = _free(ret); } if (al->providesHash == NULL) rpmalMakeProvidesIndex(al); rpmalDepHashGetEntry(al->providesHash, nameId, &result, &resultCnt, NULL); if (resultCnt==0) return NULL; ret = xmalloc((resultCnt+1) * sizeof(*ret)); for (found=i=0; i<resultCnt; i++) { alp = al->list + result[i].pkgNum; if (alp->p == NULL) /* deleted */ continue; /* ignore self-conflicts/obsoletes */ if (filterds && rpmteDS(alp->p, rpmdsTagN(filterds)) == filterds) continue; ix = result[i].entryIx; if (obsolete) { /* Obsoletes are on package NEVR only */ rpmds thisds; if (!rstreq(rpmdsNIndex(alp->provides, ix), rpmteN(alp->p))) continue; thisds = rpmteDS(alp->p, RPMTAG_NAME); rc = rpmdsCompareIndex(thisds, rpmdsIx(thisds), ds, rpmdsIx(ds)); } else { rc = rpmdsCompareIndex(alp->provides, ix, ds, rpmdsIx(ds)); } if (rc) ret[found++] = alp->p; } if (found) { rpmdsNotify(ds, "(added provide)", 0); ret[found] = NULL; } else { ret = _free(ret); } return ret; }