/** * Return exit code from running verify script from header. * @todo malloc/free/refcount handling is fishy here. * @param qva parsed query/verify options * @param ts transaction set * @param h header * @param scriptFd file handle to use for stderr (or NULL) * @return 0 on success */ static int rpmVerifyScript(QVA_t qva, rpmts ts, Header h, FD_t scriptFd) { rpmpsm psm = NULL; rpmte te = NULL; int rc = 0; /* fake up a erasure transaction element */ rc = rpmtsAddEraseElement(ts, h, -1); te = rpmtsElement(ts, 0); rpmteOpen(te, ts, 0); if (scriptFd != NULL) rpmtsSetScriptFd(ts, scriptFd); /* create psm to run the script */ psm = rpmpsmNew(ts, te); rpmpsmScriptStage(psm, RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG); rc = rpmpsmStage(psm, PSM_SCRIPT); psm = rpmpsmFree(psm); if (scriptFd != NULL) rpmtsSetScriptFd(ts, NULL); /* clean up our fake transaction bits */ rpmteClose(te, ts, 0); rpmtsEmpty(ts); 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; }
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 rpmRC rpmpsmNext(rpmpsm psm, pkgStage nstage) { psm->nstage = nstage; return rpmpsmStage(psm, psm->nstage); }
rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd, char ** specFilePtr, char ** cookie) { rpmfi fi = NULL; char * specFile = NULL; const char *rootdir = rpmtsRootDir(ts); Header h = NULL; rpmpsm psm = NULL; rpmte te = NULL; rpmRC rpmrc; int specix = -1; struct rpmtd_s filenames; rpmtdReset(&filenames); rpmrc = rpmReadPackageFile(ts, fd, NULL, &h); switch (rpmrc) { case RPMRC_NOTTRUSTED: case RPMRC_NOKEY: case RPMRC_OK: break; default: goto exit; break; } if (h == NULL) goto exit; rpmrc = RPMRC_FAIL; /* assume failure */ if (!headerIsSource(h)) { rpmlog(RPMLOG_ERR, _("source package expected, binary found\n")); goto exit; } /* src.rpm install can require specific rpmlib features, check them */ if (!rpmlibDeps(h)) goto exit; if (headerGet(h, RPMTAG_BASENAMES, &filenames, HEADERGET_ALLOC)) { struct rpmtd_s td; const char *str; const char *_cookie = headerGetString(h, RPMTAG_COOKIE); if (cookie && _cookie) *cookie = xstrdup(_cookie); /* Try to find spec by file flags */ if (_cookie && headerGet(h, RPMTAG_FILEFLAGS, &td, HEADERGET_MINMEM)) { rpmfileAttrs *flags; while (specix < 0 && (flags = rpmtdNextUint32(&td))) { if (*flags & RPMFILE_SPECFILE) specix = rpmtdGetIndex(&td); } } /* Still no spec? Look by filename. */ while (specix < 0 && (str = rpmtdNextString(&filenames))) { if (rpmFileHasSuffix(str, ".spec")) specix = rpmtdGetIndex(&filenames); } } if (rootdir && rstreq(rootdir, "/")) rootdir = NULL; /* Macros need to be added before trying to create directories */ rpmInstallLoadMacros(h); if (specix >= 0) { const char *bn; headerDel(h, RPMTAG_BASENAMES); headerDel(h, RPMTAG_DIRNAMES); headerDel(h, RPMTAG_DIRINDEXES); rpmtdInit(&filenames); for (int i = 0; (bn = rpmtdNextString(&filenames)); i++) { int spec = (i == specix); char *fn = rpmGenPath(rpmtsRootDir(ts), spec ? "%{_specdir}" : "%{_sourcedir}", bn); headerPutString(h, RPMTAG_OLDFILENAMES, fn); if (spec) specFile = xstrdup(fn); free(fn); } headerConvert(h, HEADERCONV_COMPRESSFILELIST); } else { rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n")); goto exit; }; if (rpmtsAddInstallElement(ts, h, NULL, 0, NULL)) { goto exit; } te = rpmtsElement(ts, 0); if (te == NULL) { /* XXX can't happen */ goto exit; } rpmteSetFd(te, fd); rpmteSetHeader(te, h); fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); h = headerFree(h); if (fi == NULL) { goto exit; } fi->apath = filenames.data; /* Ick */ rpmteSetFI(te, fi); fi = rpmfiFree(fi); if (rpmMkdirs(rpmtsRootDir(ts), "%{_topdir}:%{_sourcedir}:%{_specdir}")) { goto exit; } { /* set all files to be installed */ rpmfs fs = rpmteGetFileStates(te); int i; unsigned int fc = rpmfiFC(fi); for (i=0; i<fc; i++) rpmfsSetAction(fs, i, FA_CREATE); } psm = rpmpsmNew(ts, te); psm->goal = PKG_INSTALL; /* FIX: psm->fi->dnl should be owned. */ if (rpmpsmStage(psm, PSM_PROCESS) == RPMRC_OK) rpmrc = RPMRC_OK; (void) rpmpsmStage(psm, PSM_FINI); rpmpsmFree(psm); exit: if (specFilePtr && specFile && rpmrc == RPMRC_OK) *specFilePtr = specFile; else free(specFile); headerFree(h); rpmfiFree(fi); /* XXX nuke the added package(s). */ rpmtsClean(ts); return rpmrc; }