Add support for %transfiletriggerun.

This commit is contained in:
Lubos Kardos 2014-09-17 12:11:59 +02:00 committed by Lubos Kardos
parent ec78eea7fe
commit 30a5603159
6 changed files with 196 additions and 1 deletions

View File

@ -23,6 +23,7 @@
#include "lib/rpmte_internal.h" /* XXX internal apis */
#include "lib/rpmdb_internal.h" /* rpmdbAdd/Remove */
#include "lib/rpmts_internal.h" /* rpmtsPlugins() etc */
#include "lib/rpmds_internal.h" /* rpmdsFilterTi() */
#include "lib/rpmscript.h"
#include "lib/misc.h"
@ -712,6 +713,62 @@ static rpmRC rpmPackageInstall(rpmts ts, rpmpsm psm)
return rc;
}
/*
* Prepare post trans uninstall file triggers. After transcation uninstalled
* files are not saved anywhere. So we need during uninstalation of every
* package, in time when the files to uninstall are still available,
* to determine and store triggers that should be set off after transaction.
*/
static void prepPostUnTransFileTrigs(rpmts ts, rpmte te)
{
rpmdbMatchIterator mi;
rpmdbIndexIterator ii;
Header trigH;
const void *key;
size_t keylen;
rpmfiles files;
rpmds rpmdsTriggers;
rpmds rpmdsTrigger;
int tix = 0;
ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME);
mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES);
files = rpmteFiles(te);
/* Iterate over file triggers in rpmdb */
while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
/* Check if file trigger matches any file in this te */
rpmfi fi = rpmfilesFindPrefix(files, key);
if (rpmfiFC(fi) > 0) {
/* If yes then store it */
rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii),
rpmdbIndexIteratorNumPkgs(ii));
}
rpmfiFree(fi);
}
rpmdbIndexIteratorFree(ii);
rpmdbUniqIterator(mi);
if (rpmdbGetIteratorCount(mi)) {
/* Filter triggers and save only trans postun triggers into ts */
while((trigH = rpmdbNextIterator(mi)) != NULL) {
rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0);
while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) {
if ((rpmdsNext(rpmdsTrigger) >= 0) &&
(rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) {
rpmtsAddTrigger(ts, rpmdbGetIteratorOffset(mi) ,tix);
}
rpmdsFree(rpmdsTrigger);
tix++;
}
rpmdsFree(rpmdsTriggers);
}
}
rpmdbFreeIterator(mi);
}
static rpmRC rpmPackageErase(rpmts ts, rpmpsm psm)
{
rpmRC rc = RPMRC_OK;
@ -762,6 +819,9 @@ static rpmRC rpmPackageErase(rpmts ts, rpmpsm psm)
RPMSCRIPT_FILETRIGGER);
if (rc) break;
/* Prepare post transaction uninstall triggers */
prepPostUnTransFileTrigs(psm->ts, psm->te);
rc = dbRemove(ts, psm->te);
}

View File

@ -678,7 +678,7 @@ int rpmdbVerify(const char * prefix)
return rc;
}
static Header rpmdbGetHeaderAt(rpmdb db, unsigned int offset)
Header rpmdbGetHeaderAt(rpmdb db, unsigned int offset)
{
rpmdbMatchIterator mi = rpmdbInitIterator(db, RPMDBI_PACKAGES,
&offset, sizeof(offset));

View File

@ -200,6 +200,15 @@ void rpmdbSetIteratorIndex(rpmdbMatchIterator mi, unsigned int ix);
RPM_GNUC_INTERNAL
unsigned int rpmdbGetIteratorOffsetFor(rpmdbMatchIterator mi, unsigned int ix);
/** \ingroup rpmdb
* Return header located in rpmdb at given offset.
* @param db rpm database
* @param offset database offset
* @return header at given offset
*/
RPM_GNUC_INTERNAL
Header rpmdbGetHeaderAt(rpmdb db, unsigned int offset);
#ifdef __cplusplus
}
#endif

View File

@ -56,6 +56,72 @@ static rpmts rpmtsUnlink(rpmts ts)
return NULL;
}
/* Prepare space in memory for storing transaction triggers */
static void rpmtsInitTriggers(rpmts ts)
{
if (ts) {
ts->trigs2run.count = 0;
ts->trigs2run.alloced = 10;
ts->trigs2run.trigger = xmalloc(sizeof(*ts->trigs2run.trigger) *
ts->trigs2run.alloced);
}
}
static void rpmtsFreeTriggers(rpmts ts)
{
free(ts->trigs2run.trigger);
}
/* Add transaction trigger that should be set off after transaction */
void rpmtsAddTrigger(rpmts ts, unsigned int hdrNum, int index)
{
if (ts->trigs2run.alloced < ts->trigs2run.count + 1) {
ts->trigs2run.alloced <<= 1;
ts->trigs2run.trigger = xrealloc(ts->trigs2run.trigger,
sizeof(*ts->trigs2run.trigger) * ts->trigs2run.alloced);
}
ts->trigs2run.trigger[ts->trigs2run.count].hdrNum = hdrNum;
ts->trigs2run.trigger[ts->trigs2run.count].index = index;
ts->trigs2run.count++;
}
static int triggerCmp(const void *one, const void *two)
{
int rc;
const tsTrigger *a = one, *b = two;
rc = a->hdrNum - b->hdrNum;
if (rc == 0)
rc = a->index - b->index;
return rc;
}
void rpmtsUniqTriggers(rpmts ts)
{
unsigned int from;
unsigned int to = 0;
unsigned int count = ts->trigs2run.count;
if (ts->trigs2run.count > 1) {
qsort(ts->trigs2run.trigger, ts->trigs2run.count,
sizeof(*ts->trigs2run.trigger), triggerCmp);
}
for (from = 0; from < count; from++) {
if (from > 0 &&
!triggerCmp((const void *) &ts->trigs2run.trigger[from - 1],
(const void *) &ts->trigs2run.trigger[from])) {
ts->trigs2run.count--;
continue;
}
if (from != to)
ts->trigs2run.trigger[to] = ts->trigs2run.trigger[from];
to++;
}
}
rpmts rpmtsLink(rpmts ts)
{
if (ts)
@ -678,6 +744,8 @@ rpmts rpmtsFree(rpmts ts)
ts->plugins = rpmpluginsFree(ts->plugins);
rpmtsFreeTriggers(ts);
if (_rpmts_stats)
rpmtsPrintStats(ts);
@ -980,6 +1048,8 @@ rpmts rpmtsCreate(void)
ts->plugins = NULL;
rpmtsInitTriggers(ts);
return rpmtsLink(ts);
}

View File

@ -26,6 +26,17 @@ typedef struct tsMembers_s {
int delta; /*!< Delta for reallocation. */
} * tsMembers;
typedef struct tsTrigger_s {
unsigned int hdrNum;
int index;
} tsTrigger;
typedef struct tsTriggers_s {
tsTrigger *trigger;
int count;
int alloced;
} tsTriggers;
/** \ingroup rpmts
* The set of packages to be installed/removed atomically.
*/
@ -70,6 +81,8 @@ struct rpmts_s {
rpmPlugins plugins; /*!< Transaction plugins */
int nrefs; /*!< Reference count. */
tsTriggers trigs2run; /*!< Transaction file triggers */
};
#ifdef __cplusplus
@ -112,6 +125,12 @@ rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
RPM_GNUC_INTERNAL
rpmRC runScript(rpmts ts, rpmte te, ARGV_const_t prefixes,
rpmScript script, int arg1, int arg2);
RPM_GNUC_INTERNAL
void rpmtsAddTrigger(rpmts ts, unsigned int hdrNum, int index);
RPM_GNUC_INTERNAL
void rpmtsUniqTriggers(rpmts ts);
#ifdef __cplusplus
}

View File

@ -1819,6 +1819,42 @@ rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL;
}
/* Run triggers stored in ts */
static int runPostUnTransFileTrigs(rpmts ts)
{
int i;
Header trigH;
struct rpmtd_s installPrefixes;
rpmScript script;
int nerrors = 0;
rpmtsUniqTriggers(ts);
/* Iterate over stored triggers */
for (i = 0; i < ts->trigs2run.count; i++) {
/* Get header containing trigger script */
trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts),
ts->trigs2run.trigger[i].hdrNum);
/* Maybe package whith this trigger is already uninstalled */
if (trigH == NULL)
continue;
/* Prepare and run script */
script = rpmScriptFromTriggerTag(trigH, RPMSENSE_TRIGGERPOSTUN,
RPMSCRIPT_TRANSFILETRIGGER, ts->trigs2run.trigger[i].index);
headerGet(trigH, RPMTAG_INSTPREFIXES, &installPrefixes,
HEADERGET_ALLOC|HEADERGET_ARGV);
nerrors += runScript(ts, NULL, installPrefixes.data, script, 0, 0);
rpmtdFreeData(&installPrefixes);
rpmScriptFree(script);
headerFree(trigH);
}
return nerrors;
}
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
{
int rc = -1; /* assume failure */
@ -1911,6 +1947,7 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
/* Run file triggers in other package(s) this package sets off. */
runFileTriggers(ts, NULL, RPMSENSE_TRIGGERIN, RPMSCRIPT_TRANSFILETRIGGER);
runPostUnTransFileTrigs(ts);
/* Run file triggers in this package other package(s) set off. */
runTransScripts(ts, PKG_TRANSFILETRIGGERIN);