diff options
author | Lubos Kardos <lkardos@lkardos.brq.redhat.com> | 2014-09-17 10:47:32 +0200 |
---|---|---|
committer | Lubos Kardos <lkardos@redhat.com> | 2015-02-05 08:08:12 +0100 |
commit | ec78eea7fe6a60bc10038ca3a7a4c5d85e2a9a16 (patch) | |
tree | 1278f3a860858998db3e92bfb9ebe979e6dcd66d /lib | |
parent | b04c4f559b25bf8b6774a445a0e537c8ce1d2c59 (diff) | |
download | rpm-ec78eea7fe6a60bc10038ca3a7a4c5d85e2a9a16.tar.gz |
Add support for executing file triggers.
Supported file triggers:
%filetriggerin
%filetriggerun
%filetriggerpostun
%transfiletriggerin
%transfiletriggerun
Diffstat (limited to 'lib')
-rw-r--r-- | lib/psm.c | 92 | ||||
-rw-r--r-- | lib/rpmfiles.h | 8 | ||||
-rw-r--r-- | lib/rpmte_internal.h | 2 | ||||
-rw-r--r-- | lib/rpmts_internal.h | 13 | ||||
-rw-r--r-- | lib/transaction.c | 452 |
5 files changed, 511 insertions, 56 deletions
@@ -238,61 +238,6 @@ exit: return rpmrc; } -/** - * 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 ts transaction set - * @param te transaction element - * @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(rpmts ts, rpmte te, 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); - - sfd = rpmtsNotify(ts, te, RPMCALLBACK_SCRIPT_START, stag, 0); - if (sfd == NULL) - sfd = rpmtsScriptFd(ts); - - rpmswEnter(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), 0); - rc = rpmScriptRun(script, arg1, arg2, sfd, - prefixes, warn_only, rpmtsPlugins(ts)); - rpmswExit(rpmtsOp(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(ts, 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(ts, te, RPMCALLBACK_SCRIPT_ERROR, stag, rc); - } - - return rc; -} - static rpmRC runInstScript(rpmpsm psm, rpmTagVal scriptTag) { rpmRC rc = RPMRC_OK; @@ -704,6 +649,7 @@ static rpmRC rpmPackageInstall(rpmts ts, rpmpsm psm) 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); @@ -748,8 +694,19 @@ static rpmRC rpmPackageInstall(rpmts ts, rpmpsm psm) if (rc) break; } + /* Run file triggers in other package(s) this package sets off. */ + rc = runFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERIN, + RPMSCRIPT_FILETRIGGER); + if (rc) break; + + /* Run file triggers in this package other package(s) set off. */ + rc = runImmedFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERIN, + RPMSCRIPT_FILETRIGGER); + if (rc) break; + rc = markReplacedFiles(psm); } + rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_INSTALL), 0); return rc; @@ -762,6 +719,17 @@ static rpmRC rpmPackageErase(rpmts ts, rpmpsm psm) 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); + if (rc) break; + + /* Run file triggers in other package(s) this package sets off. */ + rc = runFileTriggers(psm->ts, psm->te, RPMSENSE_TRIGGERUN, + RPMSCRIPT_FILETRIGGER); + if (rc) break; + if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) { /* Run triggers in this package other package(s) set off. */ rc = runImmedTriggers(psm, RPMSENSE_TRIGGERUN); @@ -789,8 +757,14 @@ static rpmRC rpmPackageErase(rpmts ts, rpmpsm 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); + if (rc) break; + rc = dbRemove(ts, psm->te); } + rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_ERASE), 0); return rc; @@ -835,6 +809,14 @@ rpmRC rpmpsmRun(rpmts ts, rpmte te, pkgGoal goal) case PKG_VERIFY: rc = runInstScript(psm, goal); break; + case PKG_TRANSFILETRIGGERIN: + rc = runImmedFileTriggers(ts, te, RPMSENSE_TRIGGERIN, + RPMSCRIPT_TRANSFILETRIGGER); + break; + case PKG_TRANSFILETRIGGERUN: + rc = runImmedFileTriggers(ts, te, RPMSENSE_TRIGGERUN, + RPMSCRIPT_TRANSFILETRIGGER); + break; default: break; } diff --git a/lib/rpmfiles.h b/lib/rpmfiles.h index 4f464c0ea..0c785d208 100644 --- a/lib/rpmfiles.h +++ b/lib/rpmfiles.h @@ -136,6 +136,14 @@ typedef rpmFlags rpmfiFlags; (RPMFI_NOFILECLASS | RPMFI_NOFILEDEPS | RPMFI_NOFILELANGS | \ RPMFI_NOFILECOLORS | RPMFI_NOFILEVERIFYFLAGS) +#define RPMFI_FLAGS_ONLY_FILENAMES \ + (RPMFI_NOFILECLASS | RPMFI_NOFILEDEPS | RPMFI_NOFILELANGS | \ + RPMFI_NOFILEUSER | RPMFI_NOFILEGROUP | RPMFI_NOFILEMODES | \ + RPMFI_NOFILESIZES | RPMFI_NOFILECAPS | RPMFI_NOFILELINKTOS | \ + RPMFI_NOFILEDIGESTS | RPMFI_NOFILEMTIMES | RPMFI_NOFILERDEVS | \ + RPMFI_NOFILEINODES | RPMFI_NOFILESTATES | RPMFI_NOFILECOLORS | \ + RPMFI_NOFILEVERIFYFLAGS | RPMFI_NOFILEFLAGS) + typedef enum rpmFileIter_e { RPMFI_ITER_FWD = 0, RPMFI_ITER_BACK = 1, diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h index af25c6269..464f47628 100644 --- a/lib/rpmte_internal.h +++ b/lib/rpmte_internal.h @@ -14,6 +14,8 @@ typedef enum pkgGoal_e { PKG_VERIFY = RPMTAG_VERIFYSCRIPT, PKG_PRETRANS = RPMTAG_PRETRANS, PKG_POSTTRANS = RPMTAG_POSTTRANS, + PKG_TRANSFILETRIGGERIN = RPMTAG_TRANSFILETRIGGERIN, + PKG_TRANSFILETRIGGERUN = RPMTAG_TRANSFILETRIGGERUN, } pkgGoal; /** \ingroup rpmte diff --git a/lib/rpmts_internal.h b/lib/rpmts_internal.h index b125ce6af..9f74e677a 100644 --- a/lib/rpmts_internal.h +++ b/lib/rpmts_internal.h @@ -8,6 +8,7 @@ #include "lib/fprint.h" #include "lib/rpmlock.h" #include "lib/rpmdb_internal.h" +#include "lib/rpmscript.h" typedef struct diskspaceInfo_s * rpmDiskSpaceInfo; @@ -100,6 +101,18 @@ int rpmtsSolve(rpmts ts, rpmds key); RPM_GNUC_INTERNAL rpmRC rpmtsSetupTransactionPlugins(rpmts ts); + +RPM_GNUC_INTERNAL +rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, + rpmscriptTriggerModes tm); + +RPM_GNUC_INTERNAL +rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, + rpmscriptTriggerModes tm); +RPM_GNUC_INTERNAL +rpmRC runScript(rpmts ts, rpmte te, ARGV_const_t prefixes, + rpmScript script, int arg1, int arg2); + #ifdef __cplusplus } #endif diff --git a/lib/transaction.c b/lib/transaction.c index b08b9d950..2bb690b96 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -1184,7 +1184,11 @@ static int runTransScripts(rpmts ts, pkgGoal goal) int rc = 0; rpmte p; rpmtsi pi = rpmtsiInit(ts); - while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { + rpmElementTypes types = TR_ADDED; + if (goal == PKG_TRANSFILETRIGGERUN) + types = TR_REMOVED; + + while ((p = rpmtsiNext(pi, types)) != NULL) { rc += rpmteProcess(p, goal); } rpmtsiFree(pi); @@ -1382,6 +1386,438 @@ rpmRC rpmtsSetupTransactionPlugins(rpmts ts) 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 ts transaction set + * @param te transaction element + * @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 + */ +rpmRC runScript(rpmts ts, rpmte te, 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); + + sfd = rpmtsNotify(ts, te, RPMCALLBACK_SCRIPT_START, stag, 0); + if (sfd == NULL) + sfd = rpmtsScriptFd(ts); + + rpmswEnter(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), 0); + rc = rpmScriptRun(script, arg1, arg2, sfd, + prefixes, warn_only, rpmtsPlugins(ts)); + rpmswExit(rpmtsOp(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(ts, 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(ts, te, RPMCALLBACK_SCRIPT_ERROR, stag, rc); + } + + return rc; +} + +/* + * Get files from next package from match iterator. If files are + * available in memory then don't read them from rpmdb. + */ +static rpmfiles rpmtsNextFiles(rpmts ts, rpmdbMatchIterator mi) +{ + Header h; + rpmte *te; + rpmfiles files = NULL; + rpmstrPool pool = ts->members->pool; + int ix; + unsigned int offset; + + ix = rpmdbGetIteratorIndex(mi); + if (ix < rpmdbGetIteratorCount(mi)) { + offset = rpmdbGetIteratorOffsetFor(mi, ix); + if (packageHashGetEntry(ts->members->removedPackages, offset, + &te, NULL, NULL)) { + /* Files are available in memory */ + files = rpmteFiles(te[0]); + } + + if (packageHashGetEntry(ts->members->installedPackages, offset, + &te, NULL, NULL)) { + /* Files are available in memory */ + files = rpmteFiles(te[0]); + } + } + + if (files) { + rpmdbSetIteratorIndex(mi, ix + 1); + } else { + /* Files are not available in memory. Read them from rpmdb */ + h = rpmdbNextIterator(mi); + if (h) { + files = rpmfilesNew(pool, h, RPMTAG_BASENAMES, + RPMFI_FLAGS_ONLY_FILENAMES); + } + } + + return files; +} + + +typedef struct matchFilesIter_s { + rpmts ts; + rpmds rpmdsTrigger; + rpmfiles files; + rpmfi fi; + const char *pfx; + rpmdbMatchIterator pi; + packageHash tranPkgs; +} *matchFilesIter; + +static matchFilesIter matchFilesIterator(rpmds trigger, rpmfiles files) +{ + matchFilesIter mfi = xcalloc(1, sizeof(*mfi)); + rpmdsInit(trigger); + mfi->rpmdsTrigger = trigger; + mfi->files = rpmfilesLink(files); + return mfi; +} + +static matchFilesIter matchDBFilesIterator(rpmds trigger, rpmts ts, + int inTransaction) +{ + matchFilesIter mfi = xcalloc(1, sizeof(*mfi)); + rpmsenseFlags sense; + + rpmdsSetIx(trigger, 0); + sense = rpmdsFlags(trigger); + rpmdsInit(trigger); + + mfi->rpmdsTrigger = trigger; + mfi->ts = ts; + + /* If inTransaction is set then filter out packages that aren't in transaction */ + if (inTransaction) { + if (sense & RPMSENSE_TRIGGERIN) + mfi->tranPkgs = ts->members->installedPackages; + else + mfi->tranPkgs = ts->members->removedPackages; + } + return mfi; +} + +static const char *matchFilesNext(matchFilesIter mfi) +{ + const char *matchFile = NULL; + int fx; + + /* Decide if we iterate over given files (mfi->files) */ + if (!mfi->ts) + do { + /* Get next file from mfi->fi */ + rpmfiNext(mfi->fi); + matchFile = rpmfiFN(mfi->fi); + if (strlen(matchFile)) + break; + matchFile = NULL; + + /* If we are done with current mfi->fi, create mfi->fi for next prefix */ + fx = rpmdsNext(mfi->rpmdsTrigger); + mfi->pfx = rpmdsN(mfi->rpmdsTrigger); + rpmfiFree(mfi->fi); + mfi->fi = rpmfilesFindPrefix(mfi->files, mfi->pfx); + + } while (fx >= 0); + /* or we iterate over files in rpmdb */ + else + do { + rpmfiNext(mfi->fi); + matchFile = rpmfiFN(mfi->fi); + if (strlen(matchFile)) + break; + matchFile = NULL; + + /* If we are done with current mfi->fi, create mfi->fi for next package */ + rpmfilesFree(mfi->files); + rpmfiFree(mfi->fi); + mfi->files = rpmtsNextFiles(mfi->ts, mfi->pi); + mfi->fi = rpmfilesFindPrefix(mfi->files, mfi->pfx); + if (mfi->files) + continue; + + /* If we are done with all packages, go through packages with new prefix */ + fx = rpmdsNext(mfi->rpmdsTrigger); + mfi->pfx = rpmdsN(mfi->rpmdsTrigger); + rpmdbFreeIterator(mfi->pi); + mfi->pi = rpmdbInitPrefixIterator(rpmtsGetRdb(mfi->ts), + RPMDBI_DIRNAMES, mfi->pfx, 0); + + rpmdbFilterIterator(mfi->pi, mfi->tranPkgs, 0); + rpmdbUniqIterator(mfi->pi); + + } while (fx >= 0); + + + return matchFile; +} + +static int matchFilesEmpty(matchFilesIter mfi) +{ + const char *matchFile; + + /* Try to get the first file */ + matchFile = matchFilesNext(mfi); + + /* Rewind back this file */ + rpmfiInit(mfi->fi, 0); + + if (matchFile) + /* We have at least one file so iterator is not empty */ + return 0; + else + /* No file in iterator */ + return 1; +} + +static matchFilesIter matchFilesIteratorFree(matchFilesIter mfi) +{ + rpmfiFree(mfi->fi); + rpmfilesFree(mfi->files); + rpmdbFreeIterator(mfi->pi); + free(mfi); + return NULL; +} + +/* + * Run all file triggers in header h + * @param searchMode 0 match trigger prefixes against files in te + * 1 match trigger prefixes against files in whole ts + * 2 match trigger prefixes against files in whole + * rpmdb + */ +static int runHandleTriggersInPkg(rpmts ts, rpmte te, Header h, + rpmsenseFlags sense, rpmscriptTriggerModes tm, + int searchMode) +{ + int nerrors = 0; + rpmds rpmdsTriggers, rpmdsTrigger; + int ti = 0; + rpmfiles files = NULL; + matchFilesIter mfi; + rpmScript script; + struct rpmtd_s installPrefixes; + char *(*inputFunc)(void *); + + rpmdsTriggers = rpmdsNew(h, triggerDsTag(tm), 0); + + /* Loop over triggers in pakage (in header h) */ + while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, ti))) { + /* + * Now rpmdsTrigger contains all dependencies belonging to one trigger + * with trigger index tix. Have a look at the first one to check flags. + */ + if ((rpmdsNext(rpmdsTrigger) >= 0) && + (rpmdsFlags(rpmdsTrigger) & sense)) { + + switch (searchMode) { + case 0: + /* Create iterator over files in te that this trigger matches */ + files = rpmteFiles(te); + mfi = matchFilesIterator(rpmdsTrigger, files); + break; + case 1: + /* Create iterator over files in ts that this trigger matches */ + mfi = matchDBFilesIterator(rpmdsTrigger, ts, 1); + break; + case 2: + /* Create iterator over files in whole rpmd that this trigger matches */ + mfi = matchDBFilesIterator(rpmdsTrigger, ts, 0); + break; + } + + /* If this trigger matches any file then run trigger script */ + if (!matchFilesEmpty(mfi)) { + script = rpmScriptFromTriggerTag(h, triggertag(sense), tm, ti); + + headerGet(h, RPMTAG_INSTPREFIXES, &installPrefixes, + HEADERGET_ALLOC|HEADERGET_ARGV); + + + /* + * As input function set function to get next file from + * matching file iterator. As parameter for this function + * set matching file iterator. Input function will be called + * during execution of trigger script in order to get data + * that will be passed as stdin to trigger script. To get + * these data from lua script function rpm.input() can be used. + */ + inputFunc = (char *(*)(void *)) matchFilesNext; + rpmScriptSetNextFileFunc(script, inputFunc, mfi); + + nerrors += runScript(ts, te, installPrefixes.data, + script, 0, 0); + rpmtdFreeData(&installPrefixes); + rpmScriptFree(script); + } + rpmfilesFree(files); + matchFilesIteratorFree(mfi); + } + rpmdsFree(rpmdsTrigger); + ti++; + } + rpmdsFree(rpmdsTriggers); + + return nerrors; +} + +/* Return true if any file in package (te) starts with pfx */ +static int matchFilesInPkg(rpmts ts, rpmte te, const char *pfx, + rpmsenseFlags sense) +{ + int rc; + rpmfiles files = rpmteFiles(te); + rpmfi fi = rpmfilesFindPrefix(files, pfx); + + rc = (fi != NULL); + rpmfilesFree(files); + rpmfiFree(fi); + return rc; +} + +/* Return true if any added/removed file in ts starts with pfx */ +static int matchFilesInTran(rpmts ts, rpmte te, const char *pfx, + rpmsenseFlags sense) +{ + int rc = 1; + rpmdbMatchIterator pi; + + /* Get all files from rpmdb starting with pfx */ + pi = rpmdbInitPrefixIterator(rpmtsGetRdb(ts), RPMDBI_DIRNAMES, pfx, 0); + + if (sense & RPMSENSE_TRIGGERIN) + /* Leave in pi only files installed in ts */ + rpmdbFilterIterator(pi, ts->members->installedPackages, 0); + else + /* Leave in pi only files removed in ts */ + rpmdbFilterIterator(pi, ts->members->removedPackages, 0); + + rc = rpmdbGetIteratorCount(pi); + rpmdbFreeIterator(pi); + + return rc; +} + +/* + * It runs file triggers in other package(s) this package/transaction sets off. + * If tm is RPMSCRIPT_FILETRIGGERSCRIPT then it runs file triggers that are + * fired by files in transaction entry. If tm is RPMSCRIPT_TRANSFILETRIGGERSCRIPT + * then it runs file triggers that are fired by all files in transaction set. + * In that case te can be NULL. + * + * @param ts transaction set + * @param te transaction entry + * @param sense defines which triggers should be set off (triggerin, + * triggerun, triggerpostun) + * @param tm trigger mode, (filetrigger/transfiletrigger) + */ +rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, + rpmscriptTriggerModes tm) +{ + int nerrors = 0; + rpmdbIndexIterator ii; + rpmdbMatchIterator mi; + const void *key; + char *pfx; + size_t keylen; + Header trigH; + int (*matchFunc)(rpmts, rpmte, const char*, rpmsenseFlags sense); + + /* Decide if we match triggers against files in te or in whole ts */ + if (tm == RPMSCRIPT_FILETRIGGER) + matchFunc = matchFilesInPkg; + else + matchFunc = matchFilesInTran; + + ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), triggerDsTag(tm)); + mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES); + + /* Loop over all file triggers in rpmdb */ + while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) { + pfx = xmalloc(keylen + 1); + memcpy(pfx, key, keylen); + pfx[keylen] = '\0'; + + /* Check if file trigger is fired by any file in ts/te */ + if (matchFunc(ts, te, pfx, sense)) + /* If yes then store it */ + rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii), + rpmdbIndexIteratorNumPkgs(ii)); + free(pfx); + } + rpmdbIndexIteratorFree(ii); + + rpmdbUniqIterator(mi); + /* + * Don't handle transaction triggers installed in current transaction + * to avoid executing the same script two times. These triggers are + * handled in runImmedFileTriggers(). + */ + if (tm == RPMSCRIPT_TRANSFILETRIGGER) { + rpmdbFilterIterator(mi, ts->members->removedPackages, 1); + rpmdbFilterIterator(mi, ts->members->installedPackages, 1); + } + + /* Handle stored triggers */ + if (rpmdbGetIteratorCount(mi)) { + while((trigH = rpmdbNextIterator(mi)) != NULL) { + + if (tm == RPMSCRIPT_FILETRIGGER) + nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 0); + else + nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 1); + } + } + rpmdbFreeIterator(mi); + + return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL; +} + +/* Run file triggers in this te other package(s) set off. + * @param ts transaction set + * @param te transaction entry + * @param sense defines which triggers should be set off (triggerin, + * triggerun, triggerpostun) + * @param tm trigger mode, (filetrigger/transfiletrigger) + */ +rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, + rpmscriptTriggerModes tm) +{ + int nerrors = 0; + + nerrors += runHandleTriggersInPkg(ts, te, rpmteHeader(te), sense, tm, 2); + return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL; +} int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) { @@ -1421,6 +1857,14 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) goto exit; } + if (!rpmpsNumProblems(tsprobs)) { + /* Run file triggers in this package other package(s) set off. */ + runFileTriggers(ts, NULL, RPMSENSE_TRIGGERUN, + RPMSCRIPT_TRANSFILETRIGGER); + /* Run file triggers in other package(s) this package sets off. */ + runTransScripts(ts, PKG_TRANSFILETRIGGERUN); + } + /* 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_NOPRETRANS)) @@ -1455,6 +1899,7 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))) tsmem->pool = rpmstrPoolFree(tsmem->pool); + /* Actually install and remove packages, get final exit code */ rc = rpmtsProcess(ts) ? -1 : 0; @@ -1464,6 +1909,11 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) runTransScripts(ts, PKG_POSTTRANS); } + /* Run file triggers in other package(s) this package sets off. */ + runFileTriggers(ts, NULL, RPMSENSE_TRIGGERIN, RPMSCRIPT_TRANSFILETRIGGER); + + /* Run file triggers in this package other package(s) set off. */ + runTransScripts(ts, PKG_TRANSFILETRIGGERIN); exit: /* Run post transaction hook for all plugins */ if (TsmPreDone) /* If TsmPre hook has been called, call the TsmPost hook */ |