/* Add fingerprint for each file not skipped. */ static void addFingerprints(rpmts ts, uint64_t fileCount, rpmFpHash ht, fingerPrintCache fpc) { rpmtsi pi; rpmte p; rpmfi fi; int i; rpmFpHash symlinks = rpmFpHashCreate(fileCount/16+16, fpHashFunction, fpEqual, NULL, NULL); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfiFpLookup(fi, fpc); /* collect symbolic links */ fi = rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { struct rpmffi_s ffi; char const *linktarget; linktarget = rpmfiFLink(fi); if (!(linktarget && *linktarget != '\0')) continue; if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) continue; ffi.p = p; ffi.fileno = i; rpmFpHashAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), rpmfiFC(fi)); } rpmtsiFree(pi); /* =============================================== * Check fingerprints if they contain symlinks * and add them to the hash table */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); fi = rpmfiInit(rpmteFI(p), 0); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); while ((i = rpmfiNext(fi)) >= 0) { if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) continue; fpLookupSubdir(symlinks, ht, fpc, p, i); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } rpmtsiFree(pi); rpmFpHashFree(symlinks); }
/* Get a rpmdbMatchIterator containing all files in * the rpmdb that share the basename with one from * the transaction. * @param ts transaction set * @return rpmdbMatchIterator sorted by (package, fileNum) */ static rpmdbMatchIterator rpmFindBaseNamesInDB(rpmts ts) { rpmtsi pi; rpmte p; rpmfi fi; int fc=0; rpmdbMatchIterator mi; int i, xx; const char * baseName; /* get number of files in transaction */ // XXX move to ts pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc += rpmfiFC(fi); } pi = rpmtsiFree(pi); rpmStringSet baseNames = rpmStringSetCreate(fc, hashFunctionString, strcmp, NULL); mi = rpmdbInitIterator(rpmtsGetRdb(ts), RPMTAG_BASENAMES, NULL, 0); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi), ts->orderCount); /* Gather all installed headers with matching basename's. */ fi = rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { size_t keylen; baseName = rpmfiBN(fi); if (rpmStringSetHasEntry(baseNames, baseName)) continue; keylen = strlen(baseName); if (keylen == 0) keylen++; /* XXX "/" fixup. */ xx = rpmdbExtendIterator(mi, baseName, keylen); rpmStringSetAddEntry(baseNames, baseName); } } pi = rpmtsiFree(pi); rpmStringSetFree(baseNames); rpmdbSortIterator(mi); /* iterator is now sorted by (recnum, filenum) */ return mi; }
void rpmtsCleanProblems(rpmts ts) { rpmte p; rpmtsi pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) rpmteCleanProblems(p); rpmtsiFree(pi); }
/* * Run pre/post transaction scripts for transaction set * param ts Transaction set * param goal PKG_PRETRANS/PKG_POSTTRANS * return 0 on success */ static int runTransScripts(rpmts ts, pkgGoal goal) { rpmte p; rpmtsi pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rpmteProcess(p, goal); } pi = rpmtsiFree(pi); return 0; /* what to do about failures? */ }
/* Calculate total number of files involved in transaction */ static uint64_t countFiles(rpmts ts) { uint64_t fc = 0; rpmtsi pi = rpmtsiInit(ts); rpmte p; while ((p = rpmtsiNext(pi, 0)) != NULL) fc += rpmfiFC(rpmteFI(p)); rpmtsiFree(pi); return fc; }
/* * Transaction main loop: install and remove packages */ static int rpmtsProcess(rpmts ts) { rpmtsi pi; rpmte p; int rc = 0; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { int failed = 1; rpmElementType tetype = rpmteType(p); rpmtsOpX op = (tetype == TR_ADDED) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE; rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); if (rpmteFailed(p)) { /* XXX this should be a warning, need a better message though */ rpmlog(RPMLOG_DEBUG, "element %s marked as failed, skipping\n", rpmteNEVRA(p)); rc++; continue; } if (rpmteOpen(p, ts, 1)) { rpmpsm psm = NULL; pkgStage stage = PSM_UNKNOWN; int async = (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1)) ? 1 : 0; switch (tetype) { case TR_ADDED: stage = PSM_PKGINSTALL; break; case TR_REMOVED: stage = PSM_PKGERASE; break; } psm = rpmpsmNew(ts, p); rpmpsmSetAsync(psm, async); (void) rpmswEnter(rpmtsOp(ts, op), 0); failed = rpmpsmStage(psm, stage); (void) rpmswExit(rpmtsOp(ts, op), 0); psm = rpmpsmFree(psm); rpmteClose(p, ts, 1); } if (failed) { rpmteMarkFailed(p, ts); rc++; } (void) rpmdbSync(rpmtsGetRdb(ts)); } pi = rpmtsiFree(pi); return rc; }
static JSBool rpmts_enumerate(JSContext *cx, JSObject *obj, JSIterateOp op, jsval *statep, jsid *idp) { void * ptr = JS_GetInstancePrivate(cx, obj, &rpmtsClass, NULL); rpmts ts = ptr; rpmtsi tsi; JSObject *tsio = NULL; JSBool ok = JS_FALSE; _ENUMERATE_DEBUG_ENTRY(_debug); switch (op) { case JSENUMERATE_INIT: if ((tsio = JS_NewObject(cx, &rpmtsiClass, NULL, obj)) == NULL) goto exit; if ((tsi = rpmtsiInit(ts)) == NULL) goto exit; if (!JS_SetPrivate(cx, tsio, (void *)tsi)) { tsi = rpmtsiFree(tsi); goto exit; } *statep = OBJECT_TO_JSVAL(tsio); if (idp) *idp = JSVAL_ZERO; if (_debug) fprintf(stderr, "\tINIT tsio %p tsi %p\n", tsio, tsi); break; case JSENUMERATE_NEXT: tsio = (JSObject *) JSVAL_TO_OBJECT(*statep); tsi = JS_GetInstancePrivate(cx, tsio, &rpmtsiClass, NULL); if (rpmtsiNext(tsi, 0) != NULL) { int oc = rpmtsiOc(tsi); if (_debug) fprintf(stderr, "\tNEXT tsio %p tsi %p[%d]\n", tsio, tsi, oc); JS_ValueToId(cx, INT_TO_JSVAL(oc), idp); } else *idp = JSVAL_VOID; if (*idp != JSVAL_VOID) break; /*@fallthrough@*/ case JSENUMERATE_DESTROY: tsio = (JSObject *) JSVAL_TO_OBJECT(*statep); tsi = JS_GetInstancePrivate(cx, tsio, &rpmtsiClass, NULL); if (_debug) fprintf(stderr, "\tFINI tsio %p tsi %p\n", tsio, tsi); /* Allow our iterator object to be GC'd. */ *statep = JSVAL_NULL; break; } ok = JS_TRUE; exit: return ok; }
/* * Run pre/post transaction scripts for transaction set * param ts Transaction set * param goal PKG_PRETRANS/PKG_POSTTRANS * return 0 on success */ static int runTransScripts(rpmts ts, pkgGoal goal) { int rc = 0; rpmte p; rpmtsi pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rc += rpmteProcess(p, goal); } rpmtsiFree(pi); return rc; }
/* * For packages being installed: * - verify package arch/os. * - verify package epoch:version-release is newer. */ static rpmps checkProblems(rpmts ts) { rpm_color_t tscolor = rpmtsColor(ts); rpmprobFilterFlags probFilter = rpmtsFilterFlags(ts); rpmstrPool tspool = rpmtsPool(ts); rpmtsi pi = rpmtsiInit(ts); rpmte p; /* The ordering doesn't matter here */ /* XXX Only added packages need be checked. */ rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts)); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { if (!(probFilter & RPMPROB_FILTER_IGNOREARCH) && badArch(rpmteA(p))) rpmteAddProblem(p, RPMPROB_BADARCH, rpmteA(p), NULL, 0); if (!(probFilter & RPMPROB_FILTER_IGNOREOS) && badOs(rpmteO(p))) rpmteAddProblem(p, RPMPROB_BADOS, rpmteO(p), NULL, 0); if (!(probFilter & RPMPROB_FILTER_OLDPACKAGE)) { Header h; rpmdbMatchIterator mi; mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0); while ((h = rpmdbNextIterator(mi)) != NULL) ensureOlder(tspool, p, h); rpmdbFreeIterator(mi); } if (!(probFilter & RPMPROB_FILTER_REPLACEPKG)) { Header h; rpmdbMatchIterator mi; mi = rpmtsPrunedIterator(ts, RPMDBI_NAME, rpmteN(p), 1); rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(p)); rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(p)); rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(p)); if (tscolor) { rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, rpmteA(p)); rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(p)); } if ((h = rpmdbNextIterator(mi)) != NULL) { rpmteAddProblem(p, RPMPROB_PKG_INSTALLED, NULL, NULL, headerGetInstance(h)); } rpmdbFreeIterator(mi); } if (!(probFilter & RPMPROB_FILTER_FORCERELOCATE)) rpmteAddRelocProblems(p); } rpmtsiFree(pi); return rpmtsProblems(ts); }
/* Get a rpmdbMatchIterator containing all files in * the rpmdb that share the basename with one from * the transaction. * @param ts transaction set * @return rpmdbMatchIterator sorted by (package, fileNum) */ static rpmdbMatchIterator rpmFindBaseNamesInDB(rpmts ts, uint64_t fileCount) { tsMembers tsmem = rpmtsMembers(ts); rpmstrPool tspool = rpmtsPool(ts); rpmtsi pi; rpmte p; rpmfiles files; rpmfi fi; rpmdbMatchIterator mi; int oc = 0; const char * baseName; rpmsid baseNameId; rpmStringSet baseNames = rpmStringSetCreate(fileCount, sidHash, sidCmp, NULL); mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_BASENAMES); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, oc++, tsmem->orderCount); /* Gather all installed headers with matching basename's. */ files = rpmteFiles(p); fi = rpmfilesIter(files, RPMFI_ITER_FWD); while (rpmfiNext(fi) >= 0) { size_t keylen; baseNameId = rpmfiBNId(fi); if (rpmStringSetHasEntry(baseNames, baseNameId)) continue; keylen = rpmstrPoolStrlen(tspool, baseNameId); baseName = rpmstrPoolStr(tspool, baseNameId); if (keylen == 0) keylen++; /* XXX "/" fixup. */ rpmdbExtendIterator(mi, baseName, keylen); rpmStringSetAddEntry(baseNames, baseNameId); } rpmfiFree(fi); rpmfilesFree(files); } rpmtsiFree(pi); rpmStringSetFree(baseNames); rpmdbSortIterator(mi); /* iterator is now sorted by (recnum, filenum) */ return mi; }
/* Calculate total number of files involved in transaction */ static uint64_t countFiles(rpmts ts) { uint64_t fc = 0; rpmtsi pi = rpmtsiInit(ts); rpmte p; rpmfiles files; while ((p = rpmtsiNext(pi, 0)) != NULL) { files = rpmteFiles(p); fc += rpmfilesFC(files); rpmfilesFree(files); } rpmtsiFree(pi); return fc; }
/* * Run pre/post transaction scripts for transaction set * param ts Transaction set * param goal PKG_PRETRANS/PKG_POSTTRANS * return 0 on success */ static int runTransScripts(rpmts ts, pkgGoal goal) { int rc = 0; rpmte p; rpmtsi pi = rpmtsiInit(ts); rpmElementTypes types = TR_ADDED; if (goal == PKG_TRANSFILETRIGGERUN) types = TR_REMOVED; while ((p = rpmtsiNext(pi, types)) != NULL) { rc += rpmteProcess(p, goal); } rpmtsiFree(pi); return rc; }
rpmal rpmtsCreateAl(rpmts ts, rpmElementTypes types) { rpmal al = NULL; if (ts) { rpmte p; rpmtsi pi; rpmstrPool tspool = rpmtsPool(ts); al = rpmalCreate(tspool, (rpmtsNElements(ts) / 4) + 1, rpmtsFlags(ts), rpmtsColor(ts), rpmtsPrefColor(ts)); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, types))) rpmalAdd(al, p); rpmtsiFree(pi); } return al; }
/* Get a rpmdbMatchIterator containing all files in * the rpmdb that share the basename with one from * the transaction. * @param ts transaction set * @return rpmdbMatchIterator sorted by (package, fileNum) */ static rpmdbMatchIterator rpmFindBaseNamesInDB(rpmts ts, uint64_t fileCount) { tsMembers tsmem = rpmtsMembers(ts); rpmtsi pi; rpmte p; rpmfi fi; rpmdbMatchIterator mi; int xx; int oc = 0; const char * baseName; rpmStringSet baseNames = rpmStringSetCreate(fileCount, hashFunctionString, strcmp, NULL); mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_BASENAMES); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, oc++, tsmem->orderCount); /* Gather all installed headers with matching basename's. */ fi = rpmfiInit(rpmteFI(p), 0); while (rpmfiNext(fi) >= 0) { size_t keylen; baseName = rpmfiBN(fi); if (rpmStringSetHasEntry(baseNames, baseName)) continue; keylen = strlen(baseName); if (keylen == 0) keylen++; /* XXX "/" fixup. */ xx = rpmdbExtendIterator(mi, baseName, keylen); rpmStringSetAddEntry(baseNames, baseName); } } pi = rpmtsiFree(pi); rpmStringSetFree(baseNames); rpmdbSortIterator(mi); /* iterator is now sorted by (recnum, filenum) */ return mi; }
void rpmtsClean(rpmts ts) { rpmtsi pi; rpmte p; tsMembers tsmem = rpmtsMembers(ts); if (ts == NULL) return; /* Clean up after dependency checks. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) rpmteCleanDS(p); rpmtsiFree(pi); tsmem->addedPackages = rpmalFree(tsmem->addedPackages); tsmem->rpmlib = rpmdsFree(tsmem->rpmlib); rpmtsCleanProblems(ts); }
rpmps rpmtsProblems(rpmts ts) { rpmps ps = rpmpsCreate(); rpmtsi pi = rpmtsiInit(ts); rpmte p; while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmps teprobs = rpmteProblems(p); rpmpsMerge(ps, teprobs); rpmpsFree(teprobs); } rpmtsiFree(pi); /* Return NULL on no problems instead of an empty set */ if (rpmpsNumProblems(ps) == 0) { ps = rpmpsFree(ps); } return ps; }
static PyObject * rpmts_iternext(rpmtsObject * s) { PyObject * result = NULL; rpmte te; /* Reset iterator on 1st entry. */ if (s->tsi == NULL) { s->tsi = rpmtsiInit(s->ts); if (s->tsi == NULL) return NULL; } te = rpmtsiNext(s->tsi, 0); if (te != NULL) { result = rpmte_Wrap(&rpmte_Type, te); } else { s->tsi = rpmtsiFree(s->tsi); } return result; }
/* * Transaction main loop: install and remove packages */ static int rpmtsProcess(rpmts ts) { rpmtsi pi; rpmte p; int rc = 0; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { int failed; rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n", rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); failed = rpmteProcess(p, rpmteType(p)); if (failed) { rpmlog(RPMLOG_ERR, "%s: %s %s\n", rpmteNEVRA(p), rpmteTypeString(p), failed > 1 ? _("skipped") : _("failed")); rc++; } } rpmtsiFree(pi); return rc; }
/* * Run pre/post transaction scripts for transaction set * param ts Transaction set * param stag RPMTAG_PRETRANS or RPMTAG_POSTTRANS * return 0 on success, -1 on error (invalid script tag) */ static int runTransScripts(rpmts ts, rpmTag stag) { rpmtsi pi; rpmte p; rpmpsm psm; int xx; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rpmTag progtag = RPMTAG_NOT_FOUND; /* If no pre/post-transaction script, then don't bother. */ if (!rpmteHaveTransScript(p, stag)) continue; switch (stag) { case RPMTAG_PRETRANS: progtag = RPMTAG_PRETRANSPROG; break; case RPMTAG_POSTTRANS: progtag = RPMTAG_POSTTRANSPROG; break; default: assert(progtag != RPMTAG_NOT_FOUND); break; } if (rpmteOpen(p, ts, 0)) { psm = rpmpsmNew(ts, p); xx = rpmpsmScriptStage(psm, stag, progtag); psm = rpmpsmFree(psm); rpmteClose(p, ts, 0); } } pi = rpmtsiFree(pi); return 0; }
rpmRC rpmgiNext(/*@null@*/ rpmgi gi) { char hnum[32]; rpmRC rpmrc = RPMRC_NOTFOUND; int xx; if (gi == NULL) return rpmrc; if (_rpmgi_debug) fprintf(stderr, "--> %s(%p) tag %s\n", __FUNCTION__, gi, tagName(gi->tag)); /* Free header from previous iteration. */ (void)headerFree(gi->h); gi->h = NULL; gi->hdrPath = _free(gi->hdrPath); hnum[0] = '\0'; if (++gi->i >= 0) switch (gi->tag) { default: if (!gi->active) { nextkey: rpmrc = rpmgiLoadNextKey(gi); if (rpmrc != RPMRC_OK) goto enditer; rpmrc = rpmgiInitFilter(gi); if (rpmrc != RPMRC_OK || gi->mi == NULL) { gi->mi = rpmmiFree(gi->mi); /* XXX unnecessary */ gi->i++; goto nextkey; } rpmrc = RPMRC_NOTFOUND; /* XXX hack */ gi->active = 1; } if (gi->mi != NULL) { /* XXX unnecessary */ Header h = rpmmiNext(gi->mi); if (h != NULL) { if (!(gi->flags & RPMGI_NOHEADER)) gi->h = headerLink(h); /* XXX use h->origin instead. */ sprintf(hnum, "%u", (unsigned)rpmmiInstance(gi->mi)); gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL); rpmrc = RPMRC_OK; /* XXX header reference held by iterator, so no headerFree */ } } if (rpmrc != RPMRC_OK) { gi->mi = rpmmiFree(gi->mi); goto nextkey; } break; case RPMDBI_PACKAGES: if (!gi->active) { rpmrc = rpmgiInitFilter(gi); if (rpmrc != RPMRC_OK) { gi->mi = rpmmiFree(gi->mi); /* XXX unnecessary */ goto enditer; } rpmrc = RPMRC_NOTFOUND; /* XXX hack */ gi->active = 1; } if (gi->mi != NULL) { /* XXX unnecessary */ Header h = rpmmiNext(gi->mi); if (h != NULL) { if (!(gi->flags & RPMGI_NOHEADER)) gi->h = headerLink(h); /* XXX use h->origin instead. */ sprintf(hnum, "%u", (unsigned)rpmmiInstance(gi->mi)); gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL); rpmrc = RPMRC_OK; /* XXX header reference held by iterator, so no headerFree */ } } if (rpmrc != RPMRC_OK) { gi->mi = rpmmiFree(gi->mi); goto enditer; } break; case RPMDBI_REMOVED: case RPMDBI_ADDED: { rpmte p; int teType = 0; const char * teTypeString = NULL; if (!gi->active) { gi->tsi = rpmtsiInit(gi->ts); gi->active = 1; } if ((p = rpmtsiNext(gi->tsi, teType)) != NULL) { Header h = rpmteHeader(p); if (h != NULL) if (!(gi->flags & RPMGI_NOHEADER)) { gi->h = headerLink(h); switch(rpmteType(p)) { case TR_ADDED: teTypeString = "+++"; /*@switchbreak@*/break; case TR_REMOVED: teTypeString = "---"; /*@switchbreak@*/break; } sprintf(hnum, "%u", (unsigned)gi->i); gi->hdrPath = rpmExpand("%s h# ", teTypeString, hnum, NULL); rpmrc = RPMRC_OK; (void)headerFree(h); h = NULL; } } if (rpmrc != RPMRC_OK) { gi->tsi = rpmtsiFree(gi->tsi); goto enditer; } } break; case RPMDBI_HDLIST: if (!gi->active) { const char * path = rpmExpand("%{?_query_hdlist_path}", NULL); if (path == NULL || *path == '\0') { path = _free(path); path = rpmExpand(_query_hdlist_path, NULL); } gi->fd = rpmgiOpen(path, "rm%{?_rpmgio}"); gi->active = 1; path = _free(path); } if (gi->fd != NULL) { Header h = NULL; const char item[] = "Header"; const char * msg = NULL; /*@+voidabstract@*/ rpmrc = rpmpkgRead(item, gi->fd, &h, &msg); /*@=voidabstract@*/ switch(rpmrc) { default: rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg); case RPMRC_NOTFOUND: h = NULL; case RPMRC_OK: break; } msg = _free(msg); if (h != NULL) { if (!(gi->flags & RPMGI_NOHEADER)) gi->h = headerLink(h); sprintf(hnum, "%u", (unsigned)gi->i); gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL); rpmrc = RPMRC_OK; (void)headerFree(h); h = NULL; } } if (rpmrc != RPMRC_OK) { if (gi->fd != NULL) (void) Fclose(gi->fd); gi->fd = NULL; goto enditer; } break; case RPMDBI_ARGLIST: /* XXX gi->active initialize? */ if (_rpmgi_debug < 0) fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]); /* Read next header, lazily expanding manifests as found. */ rpmrc = rpmgiLoadReadHeader(gi); if (rpmrc != RPMRC_OK) /* XXX check this */ goto enditer; gi->hdrPath = xstrdup(gi->argv[gi->i]); break; case RPMDBI_FTSWALK: if (gi->argv == NULL || gi->argv[0] == NULL) /* HACK */ goto enditer; if (!gi->active) { gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL); /* XXX NULL with open(2)/malloc(3) errno set */ gi->active = 1; } /* Read next header, lazily walking file tree. */ rpmrc = rpmgiWalkReadHeader(gi); if (rpmrc != RPMRC_OK) { xx = Fts_close(gi->ftsp); gi->ftsp = NULL; goto enditer; } if (gi->fts != NULL) gi->hdrPath = xstrdup(gi->fts->fts_path); break; } if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) { /* XXX rpmgi hack: Save header in transaction element. */ if (gi->flags & RPMGI_ERASING) { uint32_t hdrNum = headerGetInstance(gi->h); xx = rpmtsAddEraseElement(gi->ts, gi->h, hdrNum); } else xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL); } goto exit; enditer: if (gi->flags & RPMGI_TSORDER) { rpmts ts = gi->ts; /* Block access to indices used for depsolving. */ if (!(gi->flags & RPMGI_ERASING)) { (void) rpmtsSetGoal(ts, TSM_INSTALL); xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMDBI_DEPCACHE); xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_BASENAMES); xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_PROVIDENAME); } else { (void) rpmtsSetGoal(ts, TSM_ERASE); } /* XXX query/verify will need the glop added to a buffer instead. */ xx = rpmcliInstallCheck(ts); xx = rpmcliInstallSuggests(ts); /* Permit access to indices used for depsolving. */ if (!(gi->flags & RPMGI_ERASING)) { xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_PROVIDENAME); xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_BASENAMES); xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMDBI_DEPCACHE); } /* XXX Display dependency loops with rpm -qvT. */ if (rpmIsVerbose()) (void) rpmtsSetDFlags(ts, (rpmtsDFlags(ts) | RPMDEPS_FLAG_DEPLOOPS)); xx = (*gi->tsOrder) (ts); /* XXX hackery alert! */ gi->tag = (!(gi->flags & RPMGI_ERASING) ? RPMDBI_ADDED : RPMDBI_REMOVED); gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER); } (void)headerFree(gi->h); gi->h = NULL; gi->hdrPath = _free(gi->hdrPath); gi->i = -1; gi->active = 0; exit: if (_rpmgi_debug) fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, gi, rpmrc); return rpmrc; }
static int rpmtsPrepare(rpmts ts) { tsMembers tsmem = rpmtsMembers(ts); rpmtsi pi; rpmte p; rpmfi fi; int rc = 0; uint64_t fileCount = countFiles(ts); fingerPrintCache fpc = fpCacheCreate(fileCount/2 + 10001); rpmFpHash ht = rpmFpHashCreate(fileCount/2+1, fpHashFunction, fpEqual, NULL, NULL); rpmDiskSpaceInfo dsi; rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount); /* Skip netshared paths, not our i18n files, and excluded docs */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { if (rpmfiFC(rpmteFI(p)) == 0) continue; if (rpmteType(p) == TR_ADDED) { skipInstallFiles(ts, p); } else { skipEraseFiles(ts, p); } } rpmtsiFree(pi); /* Open rpmdb & enter chroot for fingerprinting if necessary */ if (rpmdbOpenAll(ts->rdb) || rpmChrootIn()) { rc = -1; goto exit; } rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, tsmem->orderCount); addFingerprints(ts, fileCount, ht, fpc); /* check against files in the rpmdb */ checkInstalledFiles(ts, fileCount, ht, fpc); dsi = rpmtsDbDSI(ts); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); /* check files in ts against each other and update disk space needs on each partition for this package. */ handleOverlappedFiles(ts, ht, p, fi); rpmtsUpdateDSIrpmDBSize(p, dsi); /* Check added package has sufficient space on each partition used. */ if (rpmteType(p) == TR_ADDED) { rpmtsCheckDSIProblems(ts, p); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } rpmtsiFree(pi); rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, tsmem->orderCount); /* return from chroot if done earlier */ if (rpmChrootOut()) rc = -1; /* File info sets, fp caches etc not needed beyond here, free 'em up. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmteSetFI(p, NULL); } rpmtsiFree(pi); exit: rpmFpHashFree(ht); fpCacheFree(fpc); rpmtsFreeDSI(ts); 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; 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; }
static int rpmtsPrepare(rpmts ts) { tsMembers tsmem = rpmtsMembers(ts); rpmtsi pi; rpmte p; int rc = 0; uint64_t fileCount = countFiles(ts); const char *dbhome = NULL; struct stat dbstat; fingerPrintCache fpc = fpCacheCreate(fileCount/2 + 10001, rpmtsPool(ts)); rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount); /* Reset actions, set skip for netshared paths and excluded files */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmfiles files = rpmteFiles(p); if (rpmfilesFC(files) > 0) { rpmfs fs = rpmteGetFileStates(p); /* Ensure clean state, this could get called more than once. */ rpmfsResetActions(fs); if (rpmteType(p) == TR_ADDED) { skipInstallFiles(ts, files, fs); } else { skipEraseFiles(ts, files, fs); } } rpmfilesFree(files); } rpmtsiFree(pi); /* Open rpmdb & enter chroot for fingerprinting if necessary */ if (rpmdbOpenAll(ts->rdb) || rpmChrootIn()) { rc = -1; goto exit; } rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, tsmem->orderCount); /* Add fingerprint for each file not skipped. */ fpCachePopulate(fpc, ts, fileCount); /* check against files in the rpmdb */ checkInstalledFiles(ts, fileCount, fpc); dbhome = rpmdbHome(rpmtsGetRdb(ts)); /* If we can't stat, ignore db growth. Probably not right but... */ if (dbhome && stat(dbhome, &dbstat)) dbhome = NULL; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmfiles files = rpmteFiles(p);; if (files == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); /* check files in ts against each other and update disk space needs on each partition for this package. */ handleOverlappedFiles(ts, fpc, p, files); /* Check added package has sufficient space on each partition used. */ if (rpmteType(p) == TR_ADDED) { /* * Try to estimate space needed for rpmdb growth: guess that the * db grows 4 times the header size (indexes and all). */ if (dbhome) { int64_t hsize = rpmteHeaderSize(p) * 4; rpmtsUpdateDSI(ts, dbstat.st_dev, dbhome, hsize, 0, 0, FA_CREATE); } rpmtsCheckDSIProblems(ts, p); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfilesFree(files); } rpmtsiFree(pi); rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, tsmem->orderCount); /* return from chroot if done earlier */ if (rpmChrootOut()) rc = -1; /* On actual transaction, file info sets are not needed after this */ if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))) { pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmteCleanFiles(p); } rpmtsiFree(pi); } exit: fpCacheFree(fpc); rpmtsFreeDSI(ts); return rc; }
static int rpmtsSetupCollections(rpmts ts) { /* seenCollectionsPost and TEs are basically a key-value pair. each item in * seenCollectionsPost is a collection that has been seen from any package, * and the associated index in the TEs is the last transaction element * where that collection was seen. */ ARGV_t seenCollectionsPost = NULL; rpmte *TEs = NULL; int numSeenPost = 0; /* seenCollectionsPre is a list of collections that have been seen from * only removed packages */ ARGV_t seenCollectionsPre = NULL; int numSeenPre = 0; ARGV_const_t collname; int installing = 1; int i; rpmte p; rpmtsi pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { /* detect when we switch from installing to removing packages, and * update the lastInCollectionAdd lists */ if (installing && rpmteType(p) == TR_REMOVED) { installing = 0; for (i = 0; i < numSeenPost; i++) { rpmteAddToLastInCollectionAdd(TEs[i], seenCollectionsPost[i]); } } rpmteSetupCollectionPlugins(p); for (collname = rpmteCollections(p); collname && *collname; collname++) { /* figure out if we've seen this collection in post before */ for (i = 0; i < numSeenPost && strcmp(*collname, seenCollectionsPost[i]); i++) { } if (i < numSeenPost) { /* we've seen the collection, update the index */ TEs[i] = p; } else { /* haven't seen the collection yet, add it */ argvAdd(&seenCollectionsPost, *collname); TEs = xrealloc(TEs, sizeof(*TEs) * (numSeenPost + 1)); TEs[numSeenPost] = p; numSeenPost++; } /* figure out if we've seen this collection in pre remove before */ if (installing == 0) { for (i = 0; i < numSeenPre && strcmp(*collname, seenCollectionsPre[i]); i++) { } if (i >= numSeenPre) { /* haven't seen this collection, add it */ rpmteAddToFirstInCollectionRemove(p, *collname); argvAdd(&seenCollectionsPre, *collname); numSeenPre++; } } } } rpmtsiFree(pi); /* we've looked at all the rpmte's, update the lastInCollectionAny lists */ for (i = 0; i < numSeenPost; i++) { rpmteAddToLastInCollectionAny(TEs[i], seenCollectionsPost[i]); if (installing == 1) { /* lastInCollectionAdd is only updated above if packages were * removed. if nothing is removed in the transaction, we need to * update that list here */ rpmteAddToLastInCollectionAdd(TEs[i], seenCollectionsPost[i]); } } argvFree(seenCollectionsPost); argvFree(seenCollectionsPre); _free(TEs); return 0; }
/************************************************************************* * FUNCTION : RPMTransaction_Set::Show * * ARGUMENTS : Object to look for * * RETURNS : List of packages found * * EXCEPTIONS : none * * PURPOSE : Show the contents of a transaction set * *************************************************************************/ Tcl_Obj *RPMTransaction_Set::Show(Tcl_Obj *item) { Tcl_Obj *sub_obj = Tcl_NewObj(); Tcl_IncrRefCount(sub_obj); // Is this a list? if (item && item->typePtr == listtype) { // OK, go recursive on this int count = 0; if (Tcl_ListObjLength(_interp,item,&count) != TCL_OK) return sub_obj; for (int i = 0; i < count; ++i) { Tcl_Obj *element = 0; if (Tcl_ListObjIndex(_interp,item,i,&element) != TCL_OK) { return sub_obj; } Tcl_ListObjAppendElement(_interp,sub_obj,Show(element)); } return sub_obj; } // OK, not a list. were we given ANYTHING? if not, get everything. void *name = 0; if (item) { if (item->typePtr == &RPMHeader_Obj::mytype) { RPMHeader_Obj *header = ( RPMHeader_Obj *)(item->internalRep.otherValuePtr); int size = 0; int type = 0; if (!header->GetEntry(RPMTAG_NAME,type,name,size)) return sub_obj; } else // Not a header, interp as a string { name = (void *)Tcl_GetStringFromObj(item,0); } } rpmtsi matches = rpmtsiInit(transaction); if (!matches) return sub_obj; // OK, go over the list and create a list of items to return for(;;) { rpmte te = rpmtsiNext(matches,(rpmElementType)0); if (!te) break; Tcl_Obj *results[2]; switch (rpmteType(te)) { case TR_ADDED: { RPMHeader_Obj *hdr = (RPMHeader_Obj *)rpmteKey(te); results[0] = Tcl_NewStringObj("add",-1); results[1] = hdr->Get_obj();; } break; case TR_REMOVED: { results[0] = Tcl_NewStringObj("remove",-1); results[1] = Tcl_NewStringObj(rpmteN(te),-1); } break; } Tcl_Obj *list = Tcl_NewListObj(2,results); Tcl_IncrRefCount(list); Tcl_ListObjAppendElement(_interp,sub_obj,list); } rpmtsiFree(matches); return sub_obj; }
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) { rpm_color_t tscolor = rpmtsColor(ts); int i; int rc = 0; int totalFileCount = 0; rpmfi fi; fingerPrintCache fpc; rpmps ps; rpmtsi pi; rpmte p; int numAdded; int numRemoved; void * lock = NULL; int xx; /* XXX programmer error segfault avoidance. */ if (rpmtsNElements(ts) <= 0) return -1; /* If we are in test mode, then there's no need for transaction lock. */ if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { lock = rpmtsAcquireLock(ts); if (lock == NULL) return -1; /* XXX W2DO? */ } if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers)); if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); /* if SELinux isn't enabled or init fails, don't bother... */ if (!rpmtsSELinuxEnabled(ts)) { rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS)); } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) { char *fn = rpmGetPath("%{?_install_file_context_path}", NULL); if (matchpathcon_init(fn) == -1) { rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS)); } free(fn); } ts->probs = rpmpsFree(ts->probs); ts->probs = rpmpsCreate(); /* XXX Make sure the database is open RDWR for package install/erase. */ { int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) ? O_RDONLY : (O_RDWR|O_CREAT); /* Open database RDWR for installing packages. */ if (rpmtsOpenDB(ts, dbmode)) { rpmtsFreeLock(lock); return -1; /* XXX W2DO? */ } } ts->ignoreSet = ignoreSet; { char * currDir = rpmGetCwd(); rpmtsSetCurrDir(ts, currDir); currDir = _free(currDir); } (void) rpmtsSetChrootDone(ts, 0); { rpm_tid_t tid = (rpm_tid_t) time(NULL); (void) rpmtsSetTid(ts, tid); } /* Get available space on mounted file systems. */ xx = rpmtsInitDSI(ts); /* =============================================== * For packages being installed: * - verify package arch/os. * - verify package epoch:version-release is newer. * - count files. * For packages being removed: * - count files. */ rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts)); ps = rpmtsProblems(ts); /* The ordering doesn't matter here */ pi = rpmtsiInit(ts); /* XXX Only added packages need be checked. */ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rpmdbMatchIterator mi; int fc; if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH)) if (!archOkay(rpmteA(p))) rpmpsAppend(ps, RPMPROB_BADARCH, rpmteNEVRA(p), rpmteKey(p), rpmteA(p), NULL, NULL, 0); if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS)) if (!osOkay(rpmteO(p))) rpmpsAppend(ps, RPMPROB_BADOS, rpmteNEVRA(p), rpmteKey(p), rpmteO(p), NULL, NULL, 0); if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) { Header h; mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); while ((h = rpmdbNextIterator(mi)) != NULL) xx = ensureOlder(ts, p, h); mi = rpmdbFreeIterator(mi); } if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) { mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(p)); xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(p)); xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(p)); if (tscolor) { xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, rpmteA(p)); xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(p)); } while (rpmdbNextIterator(mi) != NULL) { rpmpsAppend(ps, RPMPROB_PKG_INSTALLED, rpmteNEVRA(p), rpmteKey(p), NULL, NULL, NULL, 0); break; } mi = rpmdbFreeIterator(mi); } /* Count no. of files (if any). */ totalFileCount += fc; } pi = rpmtsiFree(pi); ps = rpmpsFree(ps); /* The ordering doesn't matter here */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { int fc; if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); totalFileCount += fc; } pi = rpmtsiFree(pi); /* Run pre-transaction scripts, but only if there are no known * problems up to this point and not disabled otherwise. */ if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPRE)) || (rpmpsNumProblems(ts->probs) && (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) { rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n"); runTransScripts(ts, RPMTAG_PRETRANS); } /* =============================================== * Initialize transaction element file info for package: */ /* * FIXME?: we'd be better off assembling one very large file list and * calling fpLookupList only once. I'm not sure that the speedup is * worth the trouble though. */ rpmlog(RPMLOG_DEBUG, "computing %d file fingerprints\n", totalFileCount); numAdded = numRemoved = 0; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { int fc; if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); switch (rpmteType(p)) { case TR_ADDED: numAdded++; /* Skip netshared paths, not our i18n files, and excluded docs */ if (fc > 0) skipFiles(ts, p); break; case TR_REMOVED: numRemoved++; break; } } pi = rpmtsiFree(pi); if (!rpmtsChrootDone(ts)) { const char * rootDir = rpmtsRootDir(ts); xx = chdir("/"); if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { /* opening db before chroot not optimal, see rhbz#103852 c#3 */ xx = rpmdbOpenAll(ts->rdb); if (chroot(rootDir) == -1) { rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n")); return -1; } } (void) rpmtsSetChrootDone(ts, 1); } ts->ht = rpmFpHashCreate(totalFileCount/2+1, fpHashFunction, fpEqual, NULL, NULL); rpmFpHash symlinks = rpmFpHashCreate(totalFileCount/16+16, fpHashFunction, fpEqual, NULL, NULL); fpc = fpCacheCreate(totalFileCount/2 + 10001); /* =============================================== * Add fingerprint for each file not skipped. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { int fc; (void) rpmdbCheckSignals(); if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfiFpLookup(fi, fpc); /* collect symbolic links */ fi = rpmfiInit(fi, 0); if (fi != NULL) /* XXX lclint */ while ((i = rpmfiNext(fi)) >= 0) { struct rpmffi_s ffi; char const *linktarget; linktarget = rpmfiFLink(fi); if (!(linktarget && *linktarget != '\0')) continue; if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) continue; ffi.p = p; ffi.fileno = i; rpmFpHashAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc); } pi = rpmtsiFree(pi); /* =============================================== * Check fingerprints if they contain symlinks * and add them to the ts->ht hash table */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fi = rpmfiInit(fi, 0); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); if (fi != NULL) /* XXX lclint */ while ((i = rpmfiNext(fi)) >= 0) { if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) continue; fpLookupSubdir(symlinks, ts->ht, fpc, p, i); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } pi = rpmtsiFree(pi); rpmFpHashFree(symlinks); /* =============================================== * Compute file disposition for each package in transaction set. */ rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount); /* check against files in the rpmdb */ checkInstalledFiles(ts, fpc); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); /* check files in ts against each other and update disk space needs on each partition for this package. */ handleOverlappedFiles(ts, p, fi); /* Check added package has sufficient space on each partition used. */ if (rpmteType(p) == TR_ADDED) { rpmtsCheckDSIProblems(ts, p); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } pi = rpmtsiFree(pi); if (rpmtsChrootDone(ts)) { const char * rootDir = rpmtsRootDir(ts); const char * currDir = rpmtsCurrDir(ts); if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') xx = chroot("."); (void) rpmtsSetChrootDone(ts, 0); if (currDir != NULL) xx = chdir(currDir); } rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount); /* =============================================== * Free unused memory as soon as possible. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmteSetFI(p, NULL); } pi = rpmtsiFree(pi); fpc = fpCacheFree(fpc); ts->ht = rpmFpHashFree(ts->ht); /* =============================================== * If unfiltered problems exist, free memory and return. */ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (rpmpsNumProblems(ts->probs) && (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))) ) { rpmtsFreeLock(lock); return ts->orderCount; } /* Actually install and remove packages */ rc = rpmtsProcess(ts); if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPOST))) { rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n"); runTransScripts(ts, RPMTAG_POSTTRANS); } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) { matchpathcon_fini(); } rpmtsFreeLock(lock); /* FIX: ts->flList may be NULL */ if (rc) return -1; else return 0; }
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; }
void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount) { rpmtsi pi; rpmte p; rpmfs fs; rpmfiles fi; int i, fc; if (fpc->fp == NULL) fpc->fp = rpmFpHashCreate(fileCount/2 + 10001, fpHashFunction, fpEqual, NULL, NULL); rpmFpHash symlinks = rpmFpHashCreate(fileCount/16+16, fpHashFunction, fpEqual, NULL, NULL); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { fingerPrint *fpList; (void) rpmdbCheckSignals(); if ((fi = rpmteFiles(p)) == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfilesFpLookup(fi, fpc); fs = rpmteGetFileStates(p); fc = rpmfsFC(fs); fpList = rpmfilesFps(fi); /* collect symbolic links */ for (i = 0; i < fc; i++) { struct rpmffi_s ffi; char const *linktarget; if (XFA_SKIPPING(rpmfsGetAction(fs, i))) continue; linktarget = rpmfilesFLink(fi, i); if (!(linktarget && *linktarget != '\0')) continue; ffi.p = p; ffi.fileno = i; rpmFpHashAddEntry(symlinks, fpList + i, ffi); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc); rpmfilesFree(fi); } rpmtsiFree(pi); /* =============================================== * Check fingerprints if they contain symlinks * and add them to the hash table */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); fs = rpmteGetFileStates(p); fc = rpmfsFC(fs); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); for (i = 0; i < fc; i++) { if (XFA_SKIPPING(rpmfsGetAction(fs, i))) continue; fpLookupSubdir(symlinks, fpc, p, i); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } rpmtsiFree(pi); rpmFpHashFree(symlinks); }