/* 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); }
static int dbiCursorDel(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) { int rc = EINVAL; int sane = (key->data != NULL && key->size > 0); if (dbc && sane) { DBC * cursor = dbc->cursor; int _printit; rpmdb rdb = dbc->dbi->dbi_rpmdb; rpmswEnter(&rdb->db_delops, 0); /* XXX TODO: insure that cursor is positioned with duplicates */ rc = cursor->c_get(cursor, key, data, DB_SET); /* XXX DB_NOTFOUND can be returned */ _printit = (rc == DB_NOTFOUND ? 0 : _debug); rc = cvtdberr(dbc->dbi, "dbcursor->c_get", rc, _printit); if (rc == 0) { rc = cursor->c_del(cursor, flags); rc = cvtdberr(dbc->dbi, "dbcursor->c_del", rc, _debug); } rpmswExit(&rdb->db_delops, data->size); } return rc; }
static int readFile(rpmtget tget) { int rc; int xx; xx = tgetInit(tget, 8 * BUFSIZ); xx = rpmswEnter(tget->gop, 0); if (S_ISDIR(tget->sb.st_mode)) { rc = tgetFill(tget); } else if (S_ISREG(tget->sb.st_mode)) { rc = tgetFill(tget); } else rc = -1; xx = rpmswExit(tget->gop, tget->nbuf); if (rc < 0) goto exit; rc = parseHTML(tget); exit: xx = tgetFini(tget); return rc; }
static rpmRC dbAdd(rpmts ts, rpmte te) { Header h = rpmteHeader(te); rpm_time_t installTime = (rpm_time_t) time(NULL); rpmfs fs = rpmteGetFileStates(te); rpm_count_t fc = rpmfsFC(fs); rpm_fstate_t * fileStates = rpmfsGetStates(fs); rpm_color_t tscolor = rpmtsColor(ts); rpm_tid_t tid = rpmtsGetTid(ts); rpmRC rc; if (fileStates != NULL && fc > 0) { headerPutChar(h, RPMTAG_FILESTATES, fileStates, fc); } headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1); headerPutUint32(h, RPMTAG_INSTALLTIME, &installTime, 1); headerPutUint32(h, RPMTAG_INSTALLCOLOR, &tscolor, 1); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0); rc = (rpmdbAdd(rpmtsGetRdb(ts), h) == 0) ? RPMRC_OK : RPMRC_FAIL; (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0); if (rc == RPMRC_OK) rpmteSetDBInstance(te, headerGetInstance(h)); headerFree(h); return rc; }
static int hBlobDigest(Header h, pgpDig dig, pgpHashAlgo hash_algo, DIGEST_CTX * ctxp) { HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); rpmop op = NULL; unsigned char * hmagic = NULL; size_t nmagic = 0; int xx; he->tag = RPMTAG_HEADERIMMUTABLE; xx = headerGet(h, he, 0); if (!xx) goto exit; (void) headerGetMagic(NULL, &hmagic, &nmagic); op = (rpmop) pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */ (void) rpmswEnter(op, 0); *ctxp = rpmDigestInit(hash_algo, RPMDIGEST_NONE); if (hmagic && nmagic > 0) { (void) rpmDigestUpdate(*ctxp, hmagic, nmagic); dig->nbytes += nmagic; } (void) rpmDigestUpdate(*ctxp, he->p.ptr, he->c); dig->nbytes += he->c; (void) rpmswExit(op, dig->nbytes); op->count--; /* XXX one too many */ exit: he->p.ptr = _free(he->p.ptr); return xx; }
static int dbiCursorGet(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) { int rc = EINVAL; int sane = ((flags == DB_NEXT) || (key->data != NULL && key->size > 0)); if (dbc && sane) { DBC * cursor = dbc->cursor; rpmdb rdb = dbc->dbi->dbi_rpmdb; int _printit; rpmswEnter(&rdb->db_getops, 0); /* XXX db4 does DB_FIRST on uninitialized cursor */ rc = cursor->c_get(cursor, key, data, flags); /* XXX DB_NOTFOUND can be returned */ _printit = (rc == DB_NOTFOUND ? 0 : _debug); rc = cvtdberr(dbc->dbi, "dbcursor->c_get", rc, _printit); /* Remember the last key fetched */ if (rc == 0) { dbc->key = key->data; dbc->keylen = key->size; } else { dbc->key = NULL; dbc->keylen = 0; } rpmswExit(&rdb->db_getops, data->size); } return rc; }
/* * 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 int dirWalk(const char * dn) { rpmop op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); int xx = rpmswEnter(op, 0); DIR * dir; struct dirent * dp; off_t d_off = -1; int nentries = 0; int rc = 1; if ((dir = Opendir(dn)) == NULL) goto exit; while ((dp = Readdir(dir)) != NULL) { if (nentries == 0) d_off = Telldir(dir); printDir(dp, Telldir(dir), nentries++); } #ifdef NOISY nentries = 0; Rewinddir(dir); while ((dp = Readdir(dir)) != NULL) printDir(dp, Telldir(dir), nentries++); Seekdir(dir, d_off); while ((dp = Readdir(dir)) != NULL) { printDir(dp, Telldir(dir), 0); break; } #endif rc = Closedir(dir); #ifdef REFERENCE { struct dirent ** dirents = NULL; int i; nentries = Scandir(dn, &dirents, NULL, Alphasort); for (i = 0; i < nentries; i++) { dp = dirents[i]; printDir(dp, dp->d_off, i); dirents[i] = _free(dirents[i]); } dirents = _free(dirents); } #endif exit: xx = rpmswExit(op, nentries); fprintf(stderr, "===== %s: %d entries\n", dn, nentries); if (_rpmsw_stats) rpmswPrint("opendir:", op, NULL); return rc; }
rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg) { rpmRC rc; rpmVSFlags vsflags = rpmtsVSFlags(ts); rpmKeyring keyring = rpmtsGetKeyring(ts, 1); rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); rc = headerVerify(keyring, vsflags, uh, uc, msg); rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), uc); rpmKeyringFree(keyring); return rc; }
static rpmRC dbRemove(rpmts ts, rpmte te) { rpmRC rc; (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0); rc = (rpmdbRemove(rpmtsGetRdb(ts), rpmteDBInstance(te)) == 0) ? RPMRC_OK : RPMRC_FAIL; (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0); if (rc == RPMRC_OK) rpmteSetDBInstance(te, 0); return rc; }
rpmRC rpmpsmRun(rpmts ts, rpmte te, pkgGoal goal) { rpmpsm psm = NULL; rpmRC rc = RPMRC_FAIL; /* Psm can't fail in test mode, just return early */ if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) return RPMRC_OK; psm = rpmpsmNew(ts, te); if (rpmChrootIn() == 0) { rpmtsOpX op; psm->goal = goal; psm->goalName = pkgGoalString(goal); switch (goal) { case PKG_INSTALL: case PKG_ERASE: /* Run pre transaction element hook for all plugins */ if (rpmpluginsCallPsmPre(ts->plugins, te) != RPMRC_FAIL) { op = (goal == PKG_INSTALL) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE; rpmswEnter(rpmtsOp(psm->ts, op), 0); rc = rpmpsmNext(psm, PSM_INIT); if (!rc) rc = rpmpsmNext(psm, PSM_PRE); if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS); if (!rc) rc = rpmpsmNext(psm, PSM_POST); (void) rpmpsmNext(psm, PSM_FINI); rpmswExit(rpmtsOp(psm->ts, op), 0); } /* Run post transaction element hook for all plugins */ rpmpluginsCallPsmPost(ts->plugins, te, rc); break; case PKG_PRETRANS: case PKG_POSTTRANS: case PKG_VERIFY: psm->scriptTag = goal; rc = rpmpsmStage(psm, PSM_SCRIPT); break; default: break; } /* XXX an error here would require a full abort */ (void) rpmChrootOut(); } rpmpsmFree(psm); return rc; }
static int dbiCursorPut(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) { int rc = EINVAL; int sane = (key->data != NULL && key->size > 0 && data->data != NULL && data->size > 0); if (dbc && sane) { DBC * cursor = dbc->cursor; rpmdb rdb = dbc->dbi->dbi_rpmdb; rpmswEnter(&rdb->db_putops, (ssize_t) 0); rc = cursor->c_put(cursor, key, data, DB_KEYLAST); rc = cvtdberr(dbc->dbi, "dbcursor->c_put", rc, _debug); rpmswExit(&rdb->db_putops, (ssize_t) data->size); } return rc; }
rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg) { rpmRC rc = RPMRC_FAIL; rpmVSFlags vsflags = rpmtsVSFlags(ts); rpmKeyring keyring = rpmtsGetKeyring(ts, 1); struct hdrblob_s blob; if (hdrblobInit(uh, uc, 0, 0, &blob, msg) == RPMRC_OK) { rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); rc = headerSigVerify(keyring, vsflags, &blob, msg); rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), uc); if (rc == RPMRC_NOTFOUND && msg != NULL && *msg == NULL) rasprintf(msg, "Header sanity check: OK"); } rpmKeyringFree(keyring); return rc; }
static int tgetInit(rpmtget tget, size_t nbuf) { int rc; int xx; if (_rpmsw_stats) { tget->sop = xcalloc(1, sizeof(*tget->sop)); tget->gop = xcalloc(1, sizeof(*tget->gop)); } fprintf(stderr, "===== %s\n", tget->uri); xx = rpmswEnter(tget->sop, 0); rc = Stat(tget->uri, &tget->sb); xx = rpmswExit(tget->sop, 1); if (rc < 0) goto exit; printStat(tget); if (nbuf == 0 && tget->sb.st_size > 0) nbuf = tget->sb.st_size; tget->fd = Fopen(tget->uri, "r.ufdio"); if (tget->fd == NULL || Ferror(tget->fd)) { rc = -1; goto exit; } tget->nbuf = nbuf; tget->buf = xmalloc(tget->nbuf + 2); tget->buf[0] = '\0'; tget->b = NULL; tget->nb = 0; rc = 0; exit: if (rc) (void) tgetFini(tget); return rc; }
static rpmRC rpmPackageErase(rpmts ts, rpmpsm psm) { rpmRC rc = RPMRC_OK; int once = 1; rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_ERASE), 0); while (once--) { if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) { /* Run triggers in this package other package(s) set off. */ rc = runImmedTriggers(psm, RPMSENSE_TRIGGERUN); if (rc) break; /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm, RPMSENSE_TRIGGERUN); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN)) rc = runInstScript(psm, RPMTAG_PREUN); rc = rpmpsmRemove(psm); if (rc) break; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) { rc = runInstScript(psm, RPMTAG_POSTUN); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) { /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm, RPMSENSE_TRIGGERPOSTUN); if (rc) break; } rc = dbRemove(ts, psm->te); } rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_ERASE), 0); return rc; }
/** * Run a scriptlet with args. * * Run a script with an interpreter. If the interpreter is not specified, * /bin/sh will be used. If the interpreter is /bin/sh, then the args from * the header will be ignored, passing instead arg1 and arg2. * * @param psm package state machine data * @param prefixes install prefixes * @param script scriptlet from header * @param arg1 no. instances of package installed after scriptlet exec * (-1 is no arg) * @param arg2 ditto, but for the target package * @return 0 on success */ static rpmRC runScript(rpmpsm psm, ARGV_const_t prefixes, rpmScript script, int arg1, int arg2) { rpmRC stoprc, rc = RPMRC_OK; rpmTagVal stag = rpmScriptTag(script); FD_t sfd = NULL; int warn_only = (stag != RPMTAG_PREIN && stag != RPMTAG_PREUN && stag != RPMTAG_PRETRANS && stag != RPMTAG_VERIFYSCRIPT); int selinux = !(rpmtsFlags(psm->ts) & RPMTRANS_FLAG_NOCONTEXTS); sfd = rpmtsNotify(psm->ts, psm->te, RPMCALLBACK_SCRIPT_START, stag, 0); if (sfd == NULL) sfd = rpmtsScriptFd(psm->ts); rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0); rc = rpmScriptRun(script, arg1, arg2, sfd, prefixes, warn_only, selinux, psm->ts->plugins); rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0); /* Map warn-only errors to "notfound" for script stop callback */ stoprc = (rc != RPMRC_OK && warn_only) ? RPMRC_NOTFOUND : rc; rpmtsNotify(psm->ts, psm->te, RPMCALLBACK_SCRIPT_STOP, stag, stoprc); /* * Notify callback for all errors. "total" abused for warning/error, * rc only reflects whether the condition prevented install/erase * (which is only happens with %prein and %preun scriptlets) or not. */ if (rc != RPMRC_OK) { if (warn_only) { rc = RPMRC_OK; } rpmtsNotify(psm->ts, psm->te, RPMCALLBACK_SCRIPT_ERROR, stag, rc); } return rc; }
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; }
static rpmRC rpmPackageInstall(rpmts ts, rpmpsm psm) { rpmRC rc = RPMRC_OK; int once = 1; rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_INSTALL), 0); while (once--) { /* HACK: replacepkgs abuses te instance to remove old header */ if (rpmtsFilterFlags(psm->ts) & RPMPROB_FILTER_REPLACEPKG) markReplacedInstance(ts, psm->te); if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) { /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm, RPMSENSE_TRIGGERPREIN); if (rc) break; /* Run triggers in this package other package(s) set off. */ rc = runImmedTriggers(psm, RPMSENSE_TRIGGERPREIN); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) { rc = runInstScript(psm, RPMTAG_PREIN); if (rc) break; } rc = rpmpsmUnpack(psm); if (rc) break; /* * If this package has already been installed, remove it from * the database before adding the new one. */ if (rpmteDBInstance(psm->te)) { rc = dbRemove(ts, psm->te); if (rc) break; } rc = dbAdd(ts, psm->te); if (rc) break; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) { rc = runInstScript(psm, RPMTAG_POSTIN); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) { /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm, RPMSENSE_TRIGGERIN); if (rc) break; /* Run triggers in this package other package(s) set off. */ rc = runImmedTriggers(psm, RPMSENSE_TRIGGERIN); if (rc) break; } rc = markReplacedFiles(psm); } rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_INSTALL), 0); return rc; }
rpmts rpmtsCreate(void) { rpmts ts; tsMembers tsmem; ts = xcalloc(1, sizeof(*ts)); memset(&ts->ops, 0, sizeof(ts->ops)); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1); ts->dsi = NULL; ts->solve = NULL; ts->solveData = NULL; ts->rdb = NULL; ts->dbmode = O_RDONLY; ts->scriptFd = NULL; ts->tid = (rpm_tid_t) time(NULL); ts->color = rpmExpandNumeric("%{?_transaction_color}"); ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}")?:2; ts->netsharedPaths = NULL; ts->installLangs = NULL; { char *tmp = rpmExpand("%{_netsharedpath}", NULL); if (tmp && *tmp != '%') { argvSplit(&ts->netsharedPaths, tmp, ":"); } free(tmp); tmp = rpmExpand("%{_install_langs}", NULL); if (tmp && *tmp != '%') { ARGV_t langs = NULL; argvSplit(&langs, tmp, ":"); /* If we'll be installing all languages anyway, don't bother */ for (ARGV_t l = langs; *l; l++) { if (rstreq(*l, "all")) { langs = argvFree(langs); break; } } ts->installLangs = langs; } free(tmp); } tsmem = xcalloc(1, sizeof(*ts->members)); tsmem->pool = NULL; tsmem->delta = 5; tsmem->addedPackages = NULL; tsmem->removedPackages = removedHashCreate(128, uintId, uintCmp, NULL, NULL); tsmem->orderAlloced = 0; tsmem->orderCount = 0; tsmem->order = NULL; ts->members = tsmem; ts->rootDir = NULL; ts->keyring = NULL; ts->nrefs = 0; ts->plugins = NULL; return rpmtsLink(ts); }
static void fdstat_enter(FD_t fd, fdOpX opx) { if (fd->stats != NULL) (void) rpmswEnter(fdOp(fd, opx), (ssize_t) 0); }
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 printGlob(const char * path) { rpmop op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); glob_t gl = { .gl_pathc = 0, .gl_pathv = NULL, .gl_offs = 0 }; int rc; int xx; fprintf(stderr, "===== %s\n", path); xx = rpmswEnter(op, 0); gl.gl_pathc = 0; gl.gl_pathv = NULL; gl.gl_offs = 0; rc = Glob(path, 0, my_Glob_error, &gl); if (rc != 0) { fprintf(stderr, "*** Glob rc %d\n", rc); } else if (rpmIsVerbose()) { int i; for (i = 0; i < (int)gl.gl_pathc; i++) fprintf(stderr, "%5d %s\n", i, gl.gl_pathv[i]); } Globfree(&gl); xx = rpmswExit(op, 0); if (_rpmsw_stats) rpmswPrint("glob:", op, NULL); return rc; } static struct poptOption optionsTable[] = { { "debug", 'd', POPT_ARG_VAL, &__debug, -1, NULL, NULL }, { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioAllPoptTable, 0, N_("Common options for all rpmio executables:"), NULL }, POPT_AUTOHELP POPT_TABLEEND }; int main(int argc, char *argv[]) { poptContext optCon = rpmioInit(argc, argv, optionsTable); ARGV_t av; int ac; const char * dn; int rc = 0; if (__debug) { _av_debug = -1; _dav_debug = -1; _ftp_debug = -1; _url_debug = -1; _rpmio_debug = -1; } av = poptGetArgs(optCon); ac = argvCount(av); if (ac < 1) { poptPrintUsage(optCon, stderr, 0); goto exit; } while (rc == 0 && (dn = *av++) != NULL) rc = printGlob(dn); exit: optCon = rpmioFini(optCon); return rc; }
static rpmRC rpmPackageErase(rpmts ts, rpmpsm psm) { rpmRC rc = RPMRC_OK; int once = 1; rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_ERASE), 0); while (once--) { /* Run file triggers in this package other package(s) set off. */ rc = runImmedFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERUN, RPMSCRIPT_FILETRIGGER, 1); if (rc) break; /* Run file triggers in other package(s) this package sets off. */ rc = runFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERUN, RPMSCRIPT_FILETRIGGER, 1); if (rc) break; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) { /* Run triggers in this package other package(s) set off. */ rc = runImmedTriggers(psm, RPMSENSE_TRIGGERUN); if (rc) break; /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm, RPMSENSE_TRIGGERUN); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN)) rc = runInstScript(psm, RPMTAG_PREUN); /* Run file triggers in this package other package(s) set off. */ rc = runImmedFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERUN, RPMSCRIPT_FILETRIGGER, 2); if (rc) break; /* Run file triggers in other package(s) this package sets off. */ rc = runFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERUN, RPMSCRIPT_FILETRIGGER, 2); if (rc) break; rc = rpmpsmRemove(psm); if (rc) break; /* Run file triggers in other package(s) this package sets off. */ rc = runFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERPOSTUN, RPMSCRIPT_FILETRIGGER, 1); if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) { rc = runInstScript(psm, RPMTAG_POSTUN); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) { /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm, RPMSENSE_TRIGGERPOSTUN); if (rc) break; } /* Run file triggers in other package(s) this package sets off. */ rc = runFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERPOSTUN, RPMSCRIPT_FILETRIGGER, 2); if (rc) break; /* Prepare post transaction uninstall triggers */ rpmtriggersPrepPostUnTransFileTrigs(psm->ts, psm->te); rc = dbRemove(ts, psm->te); } rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_ERASE), 0); return rc; }
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; }
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); }
/* * @todo Single use by %%doc in files.c prevents static. */ rpmRC doScript(Spec spec, int what, const char *name, rpmiob iob, int test) { const char * rootURL = spec->rootURL; const char * rootDir; const char * scriptName = NULL; const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", ""); const char * buildScript; const char * buildCmd = NULL; const char * buildTemplate = NULL; const char * buildPost = NULL; const char * mTemplate = NULL; const char * mCmd = NULL; const char * mPost = NULL; int argc = 0; const char **argv = NULL; FILE * fp = NULL; urlinfo u = NULL; rpmop op = NULL; int ix = -1; FD_t fd; FD_t xfd; int status; rpmRC rc; size_t i; switch (what) { case RPMBUILD_PREP: name = "%prep"; iob = spec->prep; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_PREP; mTemplate = "%{__spec_prep_template}"; mPost = "%{__spec_prep_post}"; mCmd = "%{__spec_prep_cmd}"; break; case RPMBUILD_BUILD: name = "%build"; iob = spec->build; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_BUILD; mTemplate = "%{__spec_build_template}"; mPost = "%{__spec_build_post}"; mCmd = "%{__spec_build_cmd}"; break; case RPMBUILD_INSTALL: name = "%install"; iob = spec->install; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_INSTALL; mTemplate = "%{__spec_install_template}"; mPost = "%{__spec_install_post}"; mCmd = "%{__spec_install_cmd}"; break; case RPMBUILD_CHECK: name = "%check"; iob = spec->check; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_CHECK; mTemplate = "%{__spec_check_template}"; mPost = "%{__spec_check_post}"; mCmd = "%{__spec_check_cmd}"; break; case RPMBUILD_CLEAN: name = "%clean"; iob = spec->clean; mTemplate = "%{__spec_clean_template}"; mPost = "%{__spec_clean_post}"; mCmd = "%{__spec_clean_cmd}"; break; case RPMBUILD_RMBUILD: name = "--clean"; mTemplate = "%{__spec_clean_template}"; mPost = "%{__spec_clean_post}"; mCmd = "%{__spec_clean_cmd}"; break; /* support "%track" script/section */ case RPMBUILD_TRACK: name = "%track"; iob = NULL; if (spec->foo) for (i = 0; i < spec->nfoo; i++) { if (spec->foo[i].str == NULL || spec->foo[i].iob == NULL) continue; if (xstrcasecmp(spec->foo[i].str, "track")) continue; iob = spec->foo[i].iob; /*@loopbreak@*/ break; } mTemplate = "%{__spec_track_template}"; mPost = "%{__spec_track_post}"; mCmd = "%{__spec_track_cmd}"; break; case RPMBUILD_STRINGBUF: default: mTemplate = "%{___build_template}"; mPost = "%{___build_post}"; mCmd = "%{___build_cmd}"; break; } assert(name != NULL); if ((what != RPMBUILD_RMBUILD) && iob == NULL) { rc = RPMRC_OK; goto exit; } if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) { rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n")); rc = RPMRC_FAIL; goto exit; } if (fdGetFp(fd) == NULL) xfd = Fdopen(fd, "w.fpio"); else xfd = fd; /*@-type@*/ /* FIX: cast? */ if ((fp = fdGetFp(xfd)) == NULL) { rc = RPMRC_FAIL; goto exit; } /*@=type@*/ (void) urlPath(rootURL, &rootDir); if (*rootDir == '\0') rootDir = "/"; (void) urlPath(scriptName, &buildScript); buildTemplate = rpmExpand(mTemplate, NULL); buildPost = rpmExpand(mPost, NULL); (void) fputs(buildTemplate, fp); /* support "%track" script/section */ if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir && what != RPMBUILD_TRACK) fprintf(fp, "cd '%s'\n", spec->buildSubdir); if (what == RPMBUILD_RMBUILD) { if (spec->buildSubdir) fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir); } else if (iob != NULL) fprintf(fp, "%s", rpmiobStr(iob)); (void) fputs(buildPost, fp); (void) Fclose(xfd); if (test) { rc = RPMRC_OK; goto exit; } if (buildDirURL && buildDirURL[0] != '/' && (urlSplit(buildDirURL, &u) != 0)) { rc = RPMRC_FAIL; goto exit; } switch (urlType(u)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC); addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC); if (strcmp(rootDir, "/")) addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC); break; case URL_IS_UNKNOWN: case URL_IS_DASH: case URL_IS_PATH: case URL_IS_HKP: default: break; } buildCmd = rpmExpand(mCmd, " ", buildScript, NULL); (void) poptParseArgvString(buildCmd, &argc, &argv); if (what != RPMBUILD_TRACK) /* support "%track" script/section */ rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd); /* Run the script with a stopwatch. */ if (op != NULL) (void) rpmswEnter(op, 0); status = rpmsqExecve(argv); if (ix >= 0 && ix < RPMSCRIPT_MAX) spec->sstates[ix] = (RPMSCRIPT_STATE_EXEC | RPMSCRIPT_STATE_REAPED) | (status & 0xffff); if (!WIFEXITED(status) || WEXITSTATUS(status)) { rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"), scriptName, name); rc = RPMRC_FAIL; } else rc = RPMRC_OK; if (op != NULL) { static unsigned int scale = 1000; (void) rpmswExit(op, 0); if (ix >= 0 && ix < RPMSCRIPT_MAX) spec->smetrics[ix] += op->usecs / scale; } exit: if (scriptName) { #if defined(RPM_VENDOR_OPENPKG) /* always-remove-tempfiles */ /* Unconditionally remove temporary files ("rpm-tmp.XXXXX") which were generated for the executed scripts. In OpenPKG we run the scripts in debug mode ("set -x") anyway, so we never need to see the whole generated script -- not even if it breaks. Instead we would just have temporary files staying around forever. */ #else if (rc == RPMRC_OK) #endif (void) Unlink(scriptName); scriptName = _free(scriptName); } switch (urlType(u)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: delMacro(spec->macros, "_remsh"); delMacro(spec->macros, "_remhost"); if (strcmp(rootDir, "/")) delMacro(spec->macros, "_remroot"); break; case URL_IS_UNKNOWN: case URL_IS_DASH: case URL_IS_PATH: case URL_IS_HKP: default: break; } argv = _free(argv); buildCmd = _free(buildCmd); buildTemplate = _free(buildTemplate); buildPost = _free(buildPost); buildDirURL = _free(buildDirURL); return rc; }
/*@-mods@*/ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) { HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); HE_t she = (HE_t) memset(alloca(sizeof(*she)), 0, sizeof(*she)); pgpDig dig = rpmtsDig(ts); char buf[8*BUFSIZ]; ssize_t count; Header sigh = NULL; rpmtsOpX opx; rpmop op = NULL; size_t nb; unsigned ix; Header h = NULL; const char * msg = NULL; rpmVSFlags vsflags; rpmRC rc = RPMRC_FAIL; /* assume failure */ rpmop opsave = (rpmop) memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave)); int xx; pgpPkt pp = (pgpPkt) alloca(sizeof(*pp)); if (hdrp) *hdrp = NULL; assert(dig != NULL); (void) fdSetDig(fd, dig); /* Snapshot current I/O counters (cached persistent I/O reuses counters) */ (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ)); { const char item[] = "Lead"; msg = NULL; rc = rpmpkgRead(item, fd, NULL, &msg); switch (rc) { default: rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg); /*@fallthrough@*/ case RPMRC_NOTFOUND: msg = _free(msg); goto exit; /*@notreached@*/ break; case RPMRC_OK: break; } msg = _free(msg); } { const char item[] = "Signature"; msg = NULL; rc = rpmpkgRead(item, fd, &sigh, &msg); switch (rc) { default: rpmlog(RPMLOG_ERR, "%s: %s: %s", fn, item, (msg && *msg ? msg : _("read failed\n"))); msg = _free(msg); goto exit; /*@notreached@*/ break; case RPMRC_OK: if (sigh == NULL) { rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn); rc = RPMRC_FAIL; goto exit; } break; } msg = _free(msg); } #define _chk(_mask) (she->tag == 0 && !(vsflags & (_mask))) /* * Figger the most effective available signature. * Prefer signatures over digests, then header-only over header+payload. * DSA will be preferred over RSA if both exist because tested first. * Note that NEEDPAYLOAD prevents header+payload signatures and digests. */ she->tag = (rpmTag)0; opx = (rpmtsOpX)0; vsflags = pgpDigVSFlags; if (_chk(RPMVSF_NOECDSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_ECDSA)) { she->tag = (rpmTag)RPMSIGTAG_ECDSA; } else if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_DSA)) { she->tag = (rpmTag)RPMSIGTAG_DSA; } else if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_RSA)) { she->tag = (rpmTag)RPMSIGTAG_RSA; } else if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_SHA1)) { she->tag = (rpmTag)RPMSIGTAG_SHA1; } else if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5)) { she->tag = (rpmTag)RPMSIGTAG_MD5; fdInitDigest(fd, PGPHASHALGO_MD5, 0); opx = RPMTS_OP_DIGEST; } /* Read the metadata, computing digest(s) on the fly. */ h = NULL; msg = NULL; /* XXX stats will include header i/o and setup overhead. */ /* XXX repackaged packages have appended tags, legacy dig/sig check fails */ if (opx > 0) { op = (rpmop) pgpStatsAccumulator(dig, opx); (void) rpmswEnter(op, 0); } /*@-type@*/ /* XXX arrow access of non-pointer (FDSTAT_t) */ nb = fd->stats->ops[FDSTAT_READ].bytes; { const char item[] = "Header"; msg = NULL; rc = rpmpkgRead(item, fd, &h, &msg); if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg); msg = _free(msg); goto exit; } msg = _free(msg); } nb = fd->stats->ops[FDSTAT_READ].bytes - nb; /*@=type@*/ if (opx > 0 && op != NULL) { (void) rpmswExit(op, nb); op = NULL; } /* Any digests or signatures to check? */ if (she->tag == 0) { rc = RPMRC_OK; goto exit; } dig->nbytes = 0; /* Fish out the autosign pubkey (if present). */ he->tag = RPMTAG_PUBKEYS; xx = headerGet(h, he, 0); if (xx && he->p.argv != NULL && he->c > 0) switch (he->t) { default: break; case RPM_STRING_ARRAY_TYPE: ix = he->c - 1; /* XXX FIXME: assumes last pubkey */ dig->pub = _free(dig->pub); dig->publen = 0; { rpmiob iob = rpmiobNew(0); iob = rpmiobAppend(iob, he->p.argv[ix], 0); xx = pgpArmorUnwrap(iob, (rpmuint8_t **)&dig->pub, &dig->publen); iob = rpmiobFree(iob); } if (xx != PGPARMOR_PUBKEY) { dig->pub = _free(dig->pub); dig->publen = 0; } break; } he->p.ptr = _free(he->p.ptr); /* Retrieve the tag parameters from the signature header. */ xx = headerGet(sigh, she, 0); if (she->p.ptr == NULL) { rc = RPMRC_FAIL; goto exit; } /*@-ownedtrans -noeffect@*/ xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c); /*@=ownedtrans =noeffect@*/ switch ((rpmSigTag)she->tag) { default: /* XXX keep gcc quiet. */ assert(0); /*@notreached@*/ break; case RPMSIGTAG_RSA: /* Parse the parameters from the OpenPGP packets that will be needed. */ xx = pgpPktLen(she->p.ui8p, she->c, pp); xx = rpmhkpLoadSignature(NULL, dig, pp); if (dig->signature.version != 3 && dig->signature.version != 4) { rpmlog(RPMLOG_ERR, _("skipping package %s with unverifiable V%u signature\n"), fn, dig->signature.version); rc = RPMRC_FAIL; goto exit; } xx = hBlobDigest(h, dig, dig->signature.hash_algo, &dig->hrsa); break; case RPMSIGTAG_DSA: /* Parse the parameters from the OpenPGP packets that will be needed. */ xx = pgpPktLen(she->p.ui8p, she->c, pp); xx = rpmhkpLoadSignature(NULL, dig, pp); if (dig->signature.version != 3 && dig->signature.version != 4) { rpmlog(RPMLOG_ERR, _("skipping package %s with unverifiable V%u signature\n"), fn, dig->signature.version); rc = RPMRC_FAIL; goto exit; } xx = hBlobDigest(h, dig, dig->signature.hash_algo, &dig->hdsa); break; case RPMSIGTAG_ECDSA: /* Parse the parameters from the OpenPGP packets that will be needed. */ xx = pgpPktLen(she->p.ui8p, she->c, pp); xx = rpmhkpLoadSignature(NULL, dig, pp); if (dig->signature.version != 3 && dig->signature.version != 4) { rpmlog(RPMLOG_ERR, _("skipping package %s with unverifiable V%u signature\n"), fn, dig->signature.version); rc = RPMRC_FAIL; goto exit; } xx = hBlobDigest(h, dig, dig->signature.hash_algo, &dig->hecdsa); break; case RPMSIGTAG_SHA1: /* XXX dig->hsha? */ xx = hBlobDigest(h, dig, PGPHASHALGO_SHA1, &dig->hdsa); break; case RPMSIGTAG_MD5: /* Legacy signatures need the compressed payload in the digest too. */ op = (rpmop) pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */ (void) rpmswEnter(op, 0); while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) dig->nbytes += count; (void) rpmswExit(op, dig->nbytes); op->count--; /* XXX one too many */ dig->nbytes += nb; /* XXX include size of header blob. */ if (count < 0) { rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd)); rc = RPMRC_FAIL; goto exit; } /* XXX Steal the digest-in-progress from the file handle. */ fdStealDigest(fd, dig); break; } /** @todo Implement disable/enable/warn/error/anal policy. */ buf[0] = '\0'; rc = rpmVerifySignature(dig, buf); switch (rc) { case RPMRC_OK: /* Signature is OK. */ rpmlog(RPMLOG_DEBUG, "%s: %s\n", fn, buf); break; case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */ case RPMRC_NOKEY: /* Public key is unavailable. */ #ifndef DYING /* XXX Print NOKEY/NOTTRUSTED warning only once. */ { int lvl = (pgpStashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING); rpmlog(lvl, "%s: %s\n", fn, buf); } break; case RPMRC_NOTFOUND: /* Signature is unknown type. */ rpmlog(RPMLOG_WARNING, "%s: %s\n", fn, buf); break; #else case RPMRC_NOTFOUND: /* Signature is unknown type. */ case RPMRC_NOSIG: /* Signature is unavailable. */ #endif default: case RPMRC_FAIL: /* Signature does not verify. */ rpmlog(RPMLOG_ERR, "%s: %s\n", fn, buf); break; } exit: if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) { /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sigh); /* Bump reference count for return. */ *hdrp = headerLink(h); } (void)headerFree(h); h = NULL; /* Accumulate time reading package header. */ (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR), fdstat_op(fd, FDSTAT_READ)); (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR), opsave); #ifdef NOTYET /* Return RPMRC_NOSIG for MANDATORY signature verification. */ { rpmSigTag sigtag = pgpGetSigtag(dig); switch (sigtag) { default: rc = RPMRC_NOSIG; /*@fallthrough@*/ case RPMSIGTAG_RSA: case RPMSIGTAG_DSA: case RPMSIGTAG_ECDSA: break; } } #endif rpmtsCleanDig(ts); (void)headerFree(sigh); sigh = NULL; return rc; }
static rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage) { const rpmts ts = psm->ts; rpmfi fi = psm->fi; rpmRC rc = RPMRC_OK; switch (stage) { case PSM_UNKNOWN: break; case PSM_INIT: rpmlog(RPMLOG_DEBUG, "%s: %s has %d files\n", psm->goalName, rpmteNEVR(psm->te), rpmfiFC(fi)); /* * When we run scripts, we pass an argument which is the number of * versions of this package that will be installed when we are * finished. */ psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te)); if (psm->npkgs_installed < 0) { rc = RPMRC_FAIL; break; } if (psm->goal == PKG_INSTALL) { Header h = rpmteHeader(psm->te); psm->scriptArg = psm->npkgs_installed + 1; psm->amount = 0; psm->total = headerGetNumber(h, RPMTAG_LONGARCHIVESIZE); /* fake up something for packages with no files */ if (psm->total == 0) psm->total = 100; /* HACK: reinstall abuses te instance to remove old header */ if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG) markReplacedInstance(ts, psm->te); if (rpmfiFC(fi) > 0) { struct rpmtd_s filenames; rpmTag ftag = RPMTAG_FILENAMES; if (headerIsEntry(h, RPMTAG_ORIGBASENAMES)) { ftag = RPMTAG_ORIGFILENAMES; } headerGet(h, ftag, &filenames, HEADERGET_EXT); fi->apath = filenames.data; /* Ick.. */ } headerFree(h); } if (psm->goal == PKG_ERASE) { psm->scriptArg = psm->npkgs_installed - 1; psm->amount = 0; psm->total = rpmfiFC(fi) ? rpmfiFC(fi) : 100; } break; case PSM_PRE: if (psm->goal == PKG_INSTALL) { psm->scriptTag = RPMTAG_PREIN; psm->sense = RPMSENSE_TRIGGERPREIN; psm->countCorrection = 0; /* XXX is this correct?!? */ if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) { /* Run triggers in other package(s) this package sets off. */ rc = rpmpsmNext(psm, PSM_TRIGGERS); if (rc) break; /* Run triggers in this package other package(s) set off. */ rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) { rc = rpmpsmNext(psm, PSM_SCRIPT); if (rc) break; } } if (psm->goal == PKG_ERASE) { psm->scriptTag = RPMTAG_PREUN; psm->sense = RPMSENSE_TRIGGERUN; psm->countCorrection = -1; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) { /* Run triggers in this package other package(s) set off. */ rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS); if (rc) break; /* Run triggers in other package(s) this package sets off. */ rc = rpmpsmNext(psm, PSM_TRIGGERS); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN)) rc = rpmpsmNext(psm, PSM_SCRIPT); } break; case PSM_PROCESS: if (psm->goal == PKG_INSTALL) { int fsmrc = 0; rpmpsmNotify(psm, RPMCALLBACK_INST_START, 0); /* make sure first progress call gets made */ rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, 0); if (rpmfiFC(fi) > 0 && !(rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)) { FD_t payload = rpmtePayload(psm->te); if (payload == NULL) { rc = RPMRC_FAIL; break; } fsmrc = rpmPackageFilesInstall(psm->ts, psm->te, psm->fi, payload, psm, &psm->failedFile); rpmswAdd(rpmtsOp(psm->ts, RPMTS_OP_UNCOMPRESS), fdOp(payload, FDSTAT_READ)); rpmswAdd(rpmtsOp(psm->ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST)); Fclose(payload); } /* XXX make sure progress reaches 100% */ rpmpsmNotify(psm, 0, psm->total); rpmpsmNotify(psm, RPMCALLBACK_INST_STOP, psm->total); if (fsmrc) { char *emsg = rpmcpioStrerror(fsmrc); rpmlog(RPMLOG_ERR, _("unpacking of archive failed%s%s: %s\n"), (psm->failedFile != NULL ? _(" on file ") : ""), (psm->failedFile != NULL ? psm->failedFile : ""), emsg); free(emsg); rc = RPMRC_FAIL; /* XXX notify callback on error. */ rpmtsNotify(ts, psm->te, RPMCALLBACK_UNPACK_ERROR, 0, 0); break; } } if (psm->goal == PKG_ERASE) { if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break; rpmpsmNotify(psm, RPMCALLBACK_UNINST_START, 0); /* make sure first progress call gets made */ rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, 0); /* XXX should't we log errors from here? */ if (rpmfiFC(fi) > 0 && !(rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)) { rc = rpmPackageFilesRemove(psm->ts, psm->te, psm->fi, psm, &psm->failedFile); } /* XXX make sure progress reaches 100% */ rpmpsmNotify(psm, 0, psm->total); rpmpsmNotify(psm, RPMCALLBACK_UNINST_STOP, psm->total); } break; case PSM_POST: if (psm->goal == PKG_INSTALL) { rpm_time_t installTime = (rpm_time_t) time(NULL); rpmfs fs = rpmteGetFileStates(psm->te); rpm_count_t fc = rpmfsFC(fs); rpm_fstate_t * fileStates = rpmfsGetStates(fs); Header h = rpmteHeader(psm->te); rpm_color_t tscolor = rpmtsColor(ts); if (fileStates != NULL && fc > 0) { headerPutChar(h, RPMTAG_FILESTATES, fileStates, fc); } headerPutUint32(h, RPMTAG_INSTALLTIME, &installTime, 1); headerPutUint32(h, RPMTAG_INSTALLCOLOR, &tscolor, 1); headerFree(h); /* * If this package has already been installed, remove it from * the database before adding the new one. */ if (rpmteDBInstance(psm->te)) { rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE); if (rc) break; } rc = rpmpsmNext(psm, PSM_RPMDB_ADD); if (rc) break; psm->scriptTag = RPMTAG_POSTIN; psm->sense = RPMSENSE_TRIGGERIN; psm->countCorrection = 0; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) { rc = rpmpsmNext(psm, PSM_SCRIPT); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) { /* Run triggers in other package(s) this package sets off. */ rc = rpmpsmNext(psm, PSM_TRIGGERS); if (rc) break; /* Run triggers in this package other package(s) set off. */ rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS); if (rc) break; } rc = markReplacedFiles(psm); } if (psm->goal == PKG_ERASE) { psm->scriptTag = RPMTAG_POSTUN; psm->sense = RPMSENSE_TRIGGERPOSTUN; psm->countCorrection = -1; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) { rc = rpmpsmNext(psm, PSM_SCRIPT); if (rc) break; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) { /* Run triggers in other package(s) this package sets off. */ rc = rpmpsmNext(psm, PSM_TRIGGERS); if (rc) break; } rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE); } break; case PSM_UNDO: break; case PSM_FINI: if (rc) { char *emsg = rpmcpioStrerror(rc); if (psm->failedFile) rpmlog(RPMLOG_ERR, _("%s failed on file %s: %s\n"), psm->goalName, psm->failedFile, emsg); else rpmlog(RPMLOG_ERR, _("%s failed: %s\n"), psm->goalName, emsg); free(emsg); /* XXX notify callback on error. */ rpmtsNotify(ts, psm->te, RPMCALLBACK_CPIO_ERROR, 0, 0); } psm->failedFile = _free(psm->failedFile); fi->apath = _free(fi->apath); break; case PSM_CREATE: break; case PSM_DESTROY: break; case PSM_SCRIPT: /* Run current package scriptlets. */ rc = runInstScript(psm); break; case PSM_TRIGGERS: /* Run triggers in other package(s) this package sets off. */ rc = runTriggers(psm); break; case PSM_IMMED_TRIGGERS: /* Run triggers in this package other package(s) set off. */ rc = runImmedTriggers(psm); break; case PSM_RPMDB_ADD: { Header h = rpmteHeader(psm->te); if (!headerIsEntry(h, RPMTAG_INSTALLTID)) { rpm_tid_t tid = rpmtsGetTid(ts); if (tid != 0 && tid != (rpm_tid_t)-1) headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1); } (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0); rc = (rpmdbAdd(rpmtsGetRdb(ts), h) == 0) ? RPMRC_OK : RPMRC_FAIL; (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0); if (rc == RPMRC_OK) rpmteSetDBInstance(psm->te, headerGetInstance(h)); headerFree(h); } break; case PSM_RPMDB_REMOVE: (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0); rc = (rpmdbRemove(rpmtsGetRdb(ts), rpmteDBInstance(psm->te)) == 0) ? RPMRC_OK : RPMRC_FAIL; (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0); if (rc == RPMRC_OK) rpmteSetDBInstance(psm->te, 0); break; default: break; } 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; }
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; }