Always execute scriptlet callbacks with owning header (RhBug:1485389)

Triggers and file triggers can and do execute scriptlets from installed
packages which are not part of the current transaction and thus have no
associated transaction element, making the scriptlet callbacks
inconsistent and cumbersome for API users.

Create a fake transaction element for the poor orphan scriptlets lacking
one to make it consistent (of course, creating rpmte's with all their
associated data just to pass a header pointer along is ridiculously
expensive but *shrug*).

Regular triggers used to execute in the context of the triggering
transaction element, make them run with the owning trigger header too.
This commit is contained in:
Panu Matilainen 2017-09-04 17:39:16 +03:00
parent 61aef0f835
commit 6d610e9b9a
4 changed files with 17 additions and 8 deletions

View File

@ -249,7 +249,7 @@ static rpmRC runInstScript(rpmpsm psm, rpmTagVal scriptTag)
if (script) {
headerGet(h, RPMTAG_INSTPREFIXES, &pfx, HEADERGET_ALLOC|HEADERGET_ARGV);
rc = runScript(psm->ts, psm->te, pfx.data, script, psm->scriptArg, -1);
rc = runScript(psm->ts, psm->te, h, pfx.data, script, psm->scriptArg, -1);
rpmtdFreeData(&pfx);
}
@ -312,8 +312,7 @@ static rpmRC handleOneTrigger(rpmts ts, rpmte te, rpmsenseFlags sense,
rpmScript script = rpmScriptFromTriggerTag(trigH,
triggertag(sense), RPMSCRIPT_NORMALTRIGGER, tix);
arg1 += countCorrection;
rc = runScript(ts, te, pfx.data, script, arg1, arg2);
rc = runScript(ts, te, trigH, pfx.data, script, arg1, arg2);
if (triggersAlreadyRun != NULL)
triggersAlreadyRun[tix] = 1;
@ -361,7 +360,7 @@ static rpmRC runTriggers(rpmpsm psm, rpmsenseFlags sense)
mi = rpmtsInitIterator(ts, RPMDBI_TRIGGERNAME, N, 0);
while ((triggeredH = rpmdbNextIterator(mi)) != NULL) {
nerrors += handleOneTrigger(ts, psm->te, sense, h, triggeredH,
nerrors += handleOneTrigger(ts, NULL, sense, h, triggeredH,
0, numPackage, NULL);
}
rpmdbFreeIterator(mi);

View File

@ -183,7 +183,7 @@ int runPostUnTransFileTrigs(rpmts ts)
headerGet(trigH, RPMTAG_INSTPREFIXES, &installPrefixes,
HEADERGET_ALLOC|HEADERGET_ARGV);
nerrors += runScript(ts, NULL, installPrefixes.data, script, 0, 0);
nerrors += runScript(ts, NULL, trigH, installPrefixes.data, script, 0, 0);
rpmtdFreeData(&installPrefixes);
rpmScriptFree(script);
headerFree(trigH);
@ -424,7 +424,7 @@ static int runHandleTriggersInPkg(rpmts ts, rpmte te, Header h,
inputFunc = (char *(*)(void *)) matchFilesNext;
rpmScriptSetNextFileFunc(script, inputFunc, mfi);
nerrors += runScript(ts, te, installPrefixes.data,
nerrors += runScript(ts, te, h, installPrefixes.data,
script, 0, 0);
rpmtdFreeData(&installPrefixes);
rpmScriptFree(script);

View File

@ -119,7 +119,7 @@ RPM_GNUC_INTERNAL
rpmRC rpmtsSetupTransactionPlugins(rpmts ts);
RPM_GNUC_INTERNAL
rpmRC runScript(rpmts ts, rpmte te, ARGV_const_t prefixes,
rpmRC runScript(rpmts ts, rpmte te, Header h, ARGV_const_t prefixes,
rpmScript script, int arg1, int arg2);
#ifdef __cplusplus

View File

@ -1446,9 +1446,10 @@ rpmRC rpmtsSetupTransactionPlugins(rpmts ts)
* @param arg2 ditto, but for the target package
* @return 0 on success
*/
rpmRC runScript(rpmts ts, rpmte te, ARGV_const_t prefixes,
rpmRC runScript(rpmts ts, rpmte te, Header h, ARGV_const_t prefixes,
rpmScript script, int arg1, int arg2)
{
rpmte xte = te;
rpmRC stoprc, rc = RPMRC_OK;
rpmTagVal stag = rpmScriptTag(script);
FD_t sfd = NULL;
@ -1457,6 +1458,12 @@ rpmRC runScript(rpmts ts, rpmte te, ARGV_const_t prefixes,
stag != RPMTAG_PRETRANS &&
stag != RPMTAG_VERIFYSCRIPT);
/* Fake up a transaction element for triggers from rpmdb */
if (te == NULL) {
te = rpmteNew(ts, h, TR_REMOVED, NULL, NULL);
rpmteSetHeader(te, h);
}
sfd = rpmtsNotify(ts, te, RPMCALLBACK_SCRIPT_START, stag, 0);
if (sfd == NULL)
sfd = rpmtsScriptFd(ts);
@ -1482,6 +1489,9 @@ rpmRC runScript(rpmts ts, rpmte te, ARGV_const_t prefixes,
rpmtsNotify(ts, te, RPMCALLBACK_SCRIPT_ERROR, stag, rc);
}
if (te != xte)
rpmteFree(te);
return rc;
}