|
|
2ff057 |
#include "system.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <rpm/rpmts.h>
|
|
|
2ff057 |
#include <rpm/rpmdb.h>
|
|
|
2ff057 |
#include <rpm/rpmds.h>
|
|
|
2ff057 |
#include <rpm/rpmfi.h>
|
|
|
2ff057 |
#include <stdlib.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "lib/rpmtriggers.h"
|
|
|
2ff057 |
#include "lib/rpmts_internal.h"
|
|
|
2ff057 |
#include "lib/rpmdb_internal.h"
|
|
|
2ff057 |
#include "lib/rpmds_internal.h"
|
|
|
2ff057 |
#include "lib/rpmfi_internal.h"
|
|
|
2ff057 |
#include "lib/rpmte_internal.h"
|
|
|
2ff057 |
#include "lib/rpmchroot.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#define TRIGGER_PRIORITY_BOUND 10000
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtriggers rpmtriggersCreate(unsigned int hint)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmtriggers triggers = xmalloc(sizeof(struct rpmtriggers_s));
|
|
|
2ff057 |
triggers->count = 0;
|
|
|
2ff057 |
triggers->alloced = hint;
|
|
|
2ff057 |
triggers->triggerInfo = xmalloc(sizeof(struct triggerInfo_s) *
|
|
|
2ff057 |
triggers->alloced);
|
|
|
2ff057 |
return triggers;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtriggers rpmtriggersFree(rpmtriggers triggers)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
_free(triggers->triggerInfo);
|
|
|
2ff057 |
_free(triggers);
|
|
|
2ff057 |
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static void rpmtriggersAdd(rpmtriggers trigs, unsigned int hdrNum,
|
|
|
2ff057 |
unsigned int tix, unsigned int priority)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (trigs->count == trigs->alloced) {
|
|
|
2ff057 |
trigs->alloced <<= 1;
|
|
|
2ff057 |
trigs->triggerInfo = xrealloc(trigs->triggerInfo,
|
|
|
2ff057 |
sizeof(struct triggerInfo_s) * trigs->alloced);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
trigs->triggerInfo[trigs->count].hdrNum = hdrNum;
|
|
|
2ff057 |
trigs->triggerInfo[trigs->count].tix = tix;
|
|
|
2ff057 |
trigs->triggerInfo[trigs->count].priority = priority;
|
|
|
2ff057 |
trigs->count++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static int trigCmp(const void *a, const void *b)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const struct triggerInfo_s *trigA = a, *trigB = b;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (trigA->priority < trigB->priority)
|
|
|
2ff057 |
return 1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (trigA->priority > trigB->priority)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (trigA->hdrNum < trigB->hdrNum)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (trigA->hdrNum > trigB->hdrNum)
|
|
|
2ff057 |
return 1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (trigA->tix < trigB->tix)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (trigA->tix > trigB->tix)
|
|
|
2ff057 |
return 1;
|
|
|
2ff057 |
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static void rpmtriggersSortAndUniq(rpmtriggers trigs)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
unsigned int from;
|
|
|
2ff057 |
unsigned int to = 0;
|
|
|
2ff057 |
unsigned int count = trigs->count;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (count > 1)
|
|
|
2ff057 |
qsort(trigs->triggerInfo, count, sizeof(struct triggerInfo_s), trigCmp);
|
|
|
2ff057 |
|
|
|
2ff057 |
for (from = 0; from < count; from++) {
|
|
|
2ff057 |
if (from > 0 &&
|
|
|
2ff057 |
!trigCmp((const void *) &trigs->triggerInfo[from - 1],
|
|
|
2ff057 |
(const void *) &trigs->triggerInfo[from])) {
|
|
|
2ff057 |
|
|
|
2ff057 |
trigs->count--;
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (from != to)
|
|
|
2ff057 |
trigs->triggerInfo[to] = trigs->triggerInfo[from];
|
|
|
2ff057 |
to++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmdbMatchIterator mi;
|
|
|
2ff057 |
rpmdbIndexIterator ii;
|
|
|
2ff057 |
Header trigH;
|
|
|
2ff057 |
const void *key;
|
|
|
2ff057 |
size_t keylen;
|
|
|
2ff057 |
rpmfiles files;
|
|
|
2ff057 |
rpmds rpmdsTriggers;
|
|
|
2ff057 |
rpmds rpmdsTrigger;
|
|
|
2ff057 |
|
|
|
2ff057 |
ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME);
|
|
|
2ff057 |
mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES);
|
|
|
2ff057 |
files = rpmteFiles(te);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Iterate over file triggers in rpmdb */
|
|
|
2ff057 |
while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
|
|
|
2ff057 |
char pfx[keylen + 1];
|
|
|
2ff057 |
memcpy(pfx, key, keylen);
|
|
|
2ff057 |
pfx[keylen] = '\0';
|
|
|
2ff057 |
/* Check if file trigger matches any installed file in this te */
|
|
|
2ff057 |
rpmfi fi = rpmfilesFindPrefix(files, pfx);
|
|
|
2ff057 |
while (rpmfiNext(fi) >= 0) {
|
|
|
2ff057 |
if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) {
|
|
|
2ff057 |
/* If yes then store it */
|
|
|
2ff057 |
rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii),
|
|
|
2ff057 |
rpmdbIndexIteratorNumPkgs(ii));
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmfiFree(fi);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdbIndexIteratorFree(ii);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmdbGetIteratorCount(mi)) {
|
|
|
2ff057 |
/* Filter triggers and save only trans postun triggers into ts */
|
|
|
2ff057 |
while ((trigH = rpmdbNextIterator(mi)) != NULL) {
|
|
|
2ff057 |
int tix = 0;
|
|
|
2ff057 |
rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0);
|
|
|
2ff057 |
while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) {
|
|
|
2ff057 |
if ((rpmdsNext(rpmdsTrigger) >= 0) &&
|
|
|
2ff057 |
(rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) {
|
|
|
2ff057 |
struct rpmtd_s priorities;
|
|
|
2ff057 |
|
|
|
2ff057 |
headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
|
|
|
2ff057 |
&priorities, HEADERGET_MINMEM);
|
|
|
2ff057 |
rpmtdSetIndex(&priorities, tix);
|
|
|
2ff057 |
rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi),
|
|
|
2ff057 |
tix, *rpmtdGetUint32(&priorities));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdsFree(rpmdsTrigger);
|
|
|
2ff057 |
tix++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdsFree(rpmdsTriggers);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdbFreeIterator(mi);
|
|
Panu Matilainen |
412d98 |
rpmfilesFree(files);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int runPostUnTransFileTrigs(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int i;
|
|
|
2ff057 |
Header trigH;
|
|
|
2ff057 |
struct rpmtd_s installPrefixes;
|
|
|
2ff057 |
rpmScript script;
|
|
|
2ff057 |
rpmtriggers trigs = ts->trigs2run;
|
|
|
2ff057 |
int nerrors = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmChrootIn() != 0)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtriggersSortAndUniq(trigs);
|
|
|
2ff057 |
/* Iterate over stored triggers */
|
|
|
2ff057 |
for (i = 0; i < trigs->count; i++) {
|
|
|
2ff057 |
/* Get header containing trigger script */
|
|
|
2ff057 |
trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts),
|
|
|
2ff057 |
trigs->triggerInfo[i].hdrNum);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Maybe package with this trigger is already uninstalled */
|
|
|
2ff057 |
if (trigH == NULL)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Prepare and run script */
|
|
|
2ff057 |
script = rpmScriptFromTriggerTag(trigH,
|
|
|
2ff057 |
triggertag(RPMSENSE_TRIGGERPOSTUN),
|
|
|
2ff057 |
RPMSCRIPT_TRANSFILETRIGGER, trigs->triggerInfo[i].tix);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerGet(trigH, RPMTAG_INSTPREFIXES, &installPrefixes,
|
|
|
2ff057 |
HEADERGET_ALLOC|HEADERGET_ARGV);
|
|
|
2ff057 |
|
|
|
2ff057 |
nerrors += runScript(ts, NULL, trigH, installPrefixes.data, script, 0, 0);
|
|
|
2ff057 |
rpmtdFreeData(&installPrefixes);
|
|
|
2ff057 |
rpmScriptFree(script);
|
|
|
2ff057 |
headerFree(trigH);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmChrootOut();
|
|
|
2ff057 |
|
|
|
2ff057 |
return nerrors;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Get files from next package from match iterator. If files are
|
|
|
2ff057 |
* available in memory then don't read them from rpmdb.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static rpmfiles rpmtsNextFiles(rpmts ts, rpmdbMatchIterator mi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
Header h;
|
|
|
2ff057 |
rpmte *te;
|
|
|
2ff057 |
rpmfiles files = NULL;
|
|
|
2ff057 |
rpmstrPool pool = ts->members->pool;
|
|
|
2ff057 |
int ix;
|
|
|
2ff057 |
unsigned int offset;
|
|
|
2ff057 |
|
|
|
2ff057 |
ix = rpmdbGetIteratorIndex(mi);
|
|
|
2ff057 |
if (ix < rpmdbGetIteratorCount(mi)) {
|
|
|
2ff057 |
offset = rpmdbGetIteratorOffsetFor(mi, ix);
|
|
|
2ff057 |
if (packageHashGetEntry(ts->members->removedPackages, offset,
|
|
|
2ff057 |
&te, NULL, NULL)) {
|
|
|
2ff057 |
/* Files are available in memory */
|
|
|
2ff057 |
files = rpmteFiles(te[0]);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (packageHashGetEntry(ts->members->installedPackages, offset,
|
|
|
2ff057 |
&te, NULL, NULL)) {
|
|
|
2ff057 |
/* Files are available in memory */
|
|
|
2ff057 |
files = rpmteFiles(te[0]);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (files) {
|
|
|
2ff057 |
rpmdbSetIteratorIndex(mi, ix + 1);
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
/* Files are not available in memory. Read them from rpmdb */
|
|
|
2ff057 |
h = rpmdbNextIterator(mi);
|
|
|
2ff057 |
if (h) {
|
|
|
2ff057 |
files = rpmfilesNew(pool, h, RPMTAG_BASENAMES,
|
|
|
2ff057 |
RPMFI_FLAGS_FILETRIGGER);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
return files;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
typedef struct matchFilesIter_s {
|
|
|
2ff057 |
rpmts ts;
|
|
|
2ff057 |
rpmds rpmdsTrigger;
|
|
|
2ff057 |
rpmfiles files;
|
|
|
2ff057 |
rpmfi fi;
|
|
|
2ff057 |
rpmfs fs;
|
|
|
2ff057 |
const char *pfx;
|
|
|
2ff057 |
rpmdbMatchIterator pi;
|
|
|
2ff057 |
packageHash tranPkgs;
|
|
|
2ff057 |
} *matchFilesIter;
|
|
|
2ff057 |
|
|
|
2ff057 |
static matchFilesIter matchFilesIterator(rpmds trigger, rpmfiles files, rpmte te)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
matchFilesIter mfi = xcalloc(1, sizeof(*mfi));
|
|
|
2ff057 |
rpmdsInit(trigger);
|
|
|
2ff057 |
mfi->rpmdsTrigger = trigger;
|
|
|
2ff057 |
mfi->files = rpmfilesLink(files);
|
|
|
2ff057 |
mfi->fs = rpmteGetFileStates(te);
|
|
|
2ff057 |
return mfi;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static matchFilesIter matchDBFilesIterator(rpmds trigger, rpmts ts,
|
|
|
2ff057 |
int inTransaction)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
matchFilesIter mfi = xcalloc(1, sizeof(*mfi));
|
|
|
2ff057 |
rpmsenseFlags sense;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmdsSetIx(trigger, 0);
|
|
|
2ff057 |
sense = rpmdsFlags(trigger);
|
|
|
2ff057 |
rpmdsInit(trigger);
|
|
|
2ff057 |
|
|
|
2ff057 |
mfi->rpmdsTrigger = trigger;
|
|
|
2ff057 |
mfi->ts = ts;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If inTransaction is set then filter out packages that aren't in transaction */
|
|
|
2ff057 |
if (inTransaction) {
|
|
|
2ff057 |
if (sense & RPMSENSE_TRIGGERIN)
|
|
|
2ff057 |
mfi->tranPkgs = ts->members->installedPackages;
|
|
|
2ff057 |
else
|
|
|
2ff057 |
mfi->tranPkgs = ts->members->removedPackages;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return mfi;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static const char *matchFilesNext(matchFilesIter mfi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *matchFile = NULL;
|
|
|
2ff057 |
int fx = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Decide if we iterate over given files (mfi->files) */
|
|
|
2ff057 |
if (!mfi->ts)
|
|
|
2ff057 |
do {
|
|
|
2ff057 |
/* Get next file from mfi->fi */
|
|
|
2ff057 |
matchFile = NULL;
|
|
|
2ff057 |
while (matchFile == NULL && rpmfiNext(mfi->fi) >= 0) {
|
|
|
2ff057 |
if (!XFA_SKIPPING(rpmfsGetAction(mfi->fs, rpmfiFX(mfi->fi))))
|
|
|
2ff057 |
matchFile = rpmfiFN(mfi->fi);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (matchFile)
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If we are done with current mfi->fi, create mfi->fi for next prefix */
|
|
|
2ff057 |
fx = rpmdsNext(mfi->rpmdsTrigger);
|
|
|
2ff057 |
mfi->pfx = rpmdsN(mfi->rpmdsTrigger);
|
|
|
2ff057 |
rpmfiFree(mfi->fi);
|
|
|
2ff057 |
mfi->fi = rpmfilesFindPrefix(mfi->files, mfi->pfx);
|
|
|
2ff057 |
|
|
|
2ff057 |
} while (fx >= 0);
|
|
|
2ff057 |
/* or we iterate over files in rpmdb */
|
|
|
2ff057 |
else
|
|
|
2ff057 |
do {
|
|
|
2ff057 |
matchFile = NULL;
|
|
|
2ff057 |
while (matchFile == NULL && rpmfiNext(mfi->fi) >= 0) {
|
|
|
2ff057 |
if (RPMFILE_IS_INSTALLED(rpmfiFState(mfi->fi)))
|
|
|
2ff057 |
matchFile = rpmfiFN(mfi->fi);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (matchFile)
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If we are done with current mfi->fi, create mfi->fi for next package */
|
|
|
2ff057 |
rpmfilesFree(mfi->files);
|
|
|
2ff057 |
rpmfiFree(mfi->fi);
|
|
|
2ff057 |
mfi->files = rpmtsNextFiles(mfi->ts, mfi->pi);
|
|
|
2ff057 |
mfi->fi = rpmfilesFindPrefix(mfi->files, mfi->pfx);
|
|
|
2ff057 |
if (mfi->files)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If we are done with all packages, go through packages with new prefix */
|
|
|
2ff057 |
fx = rpmdsNext(mfi->rpmdsTrigger);
|
|
|
2ff057 |
mfi->pfx = rpmdsN(mfi->rpmdsTrigger);
|
|
|
2ff057 |
rpmdbFreeIterator(mfi->pi);
|
|
|
2ff057 |
mfi->pi = rpmdbInitPrefixIterator(rpmtsGetRdb(mfi->ts),
|
|
|
2ff057 |
RPMDBI_DIRNAMES, mfi->pfx, 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmdbFilterIterator(mfi->pi, mfi->tranPkgs, 0);
|
|
|
2ff057 |
/* Only walk through each header with matches once */
|
|
|
2ff057 |
rpmdbUniqIterator(mfi->pi);
|
|
|
2ff057 |
|
|
|
2ff057 |
} while (fx >= 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
return matchFile;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static int matchFilesEmpty(matchFilesIter mfi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
const char *matchFile;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Try to get the first file */
|
|
|
2ff057 |
matchFile = matchFilesNext(mfi);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Rewind back this file */
|
|
|
2ff057 |
rpmfiInit(mfi->fi, 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (matchFile)
|
|
|
2ff057 |
/* We have at least one file so iterator is not empty */
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
else
|
|
|
2ff057 |
/* No file in iterator */
|
|
|
2ff057 |
return 1;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static matchFilesIter matchFilesIteratorFree(matchFilesIter mfi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmfiFree(mfi->fi);
|
|
|
2ff057 |
rpmfilesFree(mfi->files);
|
|
|
2ff057 |
rpmdbFreeIterator(mfi->pi);
|
|
|
2ff057 |
free(mfi);
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Run all file triggers in header h
|
|
|
2ff057 |
* @param searchMode 0 match trigger prefixes against files in te
|
|
|
2ff057 |
* 1 match trigger prefixes against files in whole ts
|
|
|
2ff057 |
* 2 match trigger prefixes against files in whole
|
|
|
2ff057 |
* rpmdb
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static int runHandleTriggersInPkg(rpmts ts, rpmte te, Header h,
|
|
|
2ff057 |
rpmsenseFlags sense, rpmscriptTriggerModes tm,
|
|
|
2ff057 |
int searchMode, int ti)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int nerrors = 0;
|
|
|
2ff057 |
rpmds rpmdsTriggers, rpmdsTrigger;
|
|
|
2ff057 |
rpmfiles files = NULL;
|
|
|
2ff057 |
matchFilesIter mfi = NULL;
|
|
|
2ff057 |
rpmScript script;
|
|
|
2ff057 |
struct rpmtd_s installPrefixes;
|
|
|
2ff057 |
char *(*inputFunc)(void *);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmdsTriggers = rpmdsNew(h, triggerDsTag(tm), 0);
|
|
|
2ff057 |
rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, ti);
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Now rpmdsTrigger contains all dependencies belonging to one trigger
|
|
|
2ff057 |
* with trigger index tix. Have a look at the first one to check flags.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
if ((rpmdsNext(rpmdsTrigger) >= 0) &&
|
|
|
2ff057 |
(rpmdsFlags(rpmdsTrigger) & sense)) {
|
|
|
2ff057 |
|
|
|
2ff057 |
switch (searchMode) {
|
|
|
2ff057 |
case 0:
|
|
|
2ff057 |
/* Create iterator over files in te that this trigger matches */
|
|
|
2ff057 |
files = rpmteFiles(te);
|
|
|
2ff057 |
mfi = matchFilesIterator(rpmdsTrigger, files, te);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 1:
|
|
|
2ff057 |
/* Create iterator over files in ts that this trigger matches */
|
|
|
2ff057 |
mfi = matchDBFilesIterator(rpmdsTrigger, ts, 1);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case 2:
|
|
|
2ff057 |
/* Create iterator over files in whole rpmd that this trigger matches */
|
|
|
2ff057 |
mfi = matchDBFilesIterator(rpmdsTrigger, ts, 0);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If this trigger matches any file then run trigger script */
|
|
|
2ff057 |
if (!matchFilesEmpty(mfi)) {
|
|
|
2ff057 |
script = rpmScriptFromTriggerTag(h, triggertag(sense), tm, ti);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerGet(h, RPMTAG_INSTPREFIXES, &installPrefixes,
|
|
|
2ff057 |
HEADERGET_ALLOC|HEADERGET_ARGV);
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* As input function set function to get next file from
|
|
|
2ff057 |
* matching file iterator. As parameter for this function
|
|
|
2ff057 |
* set matching file iterator. Input function will be called
|
|
|
2ff057 |
* during execution of trigger script in order to get data
|
|
|
2ff057 |
* that will be passed as stdin to trigger script. To get
|
|
|
2ff057 |
* these data from lua script function rpm.input() can be used.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
inputFunc = (char *(*)(void *)) matchFilesNext;
|
|
|
2ff057 |
rpmScriptSetNextFileFunc(script, inputFunc, mfi);
|
|
|
2ff057 |
|
|
|
2ff057 |
nerrors += runScript(ts, te, h, installPrefixes.data,
|
|
|
2ff057 |
script, 0, 0);
|
|
|
2ff057 |
rpmtdFreeData(&installPrefixes);
|
|
|
2ff057 |
rpmScriptFree(script);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmfilesFree(files);
|
|
|
2ff057 |
matchFilesIteratorFree(mfi);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdsFree(rpmdsTrigger);
|
|
|
2ff057 |
rpmdsFree(rpmdsTriggers);
|
|
|
2ff057 |
|
|
|
2ff057 |
return nerrors;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Return true if any file in package (te) starts with pfx */
|
|
|
2ff057 |
static int matchFilesInPkg(rpmts ts, rpmte te, const char *pfx,
|
|
|
2ff057 |
rpmsenseFlags sense)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc;
|
|
|
2ff057 |
rpmfiles files = rpmteFiles(te);
|
|
|
2ff057 |
rpmfi fi = rpmfilesFindPrefix(files, pfx);
|
|
|
2ff057 |
|
|
|
2ff057 |
rc = (fi != NULL);
|
|
|
2ff057 |
rpmfilesFree(files);
|
|
|
2ff057 |
rpmfiFree(fi);
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Return number of added/removed files starting with pfx in transaction */
|
|
|
2ff057 |
static int matchFilesInTran(rpmts ts, rpmte te, const char *pfx,
|
|
|
2ff057 |
rpmsenseFlags sense)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 1;
|
|
|
2ff057 |
rpmdbMatchIterator pi;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Get all files from rpmdb starting with pfx */
|
|
|
2ff057 |
pi = rpmdbInitPrefixIterator(rpmtsGetRdb(ts), RPMDBI_DIRNAMES, pfx, 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (sense & RPMSENSE_TRIGGERIN)
|
|
|
2ff057 |
/* Leave in pi only files installed in ts */
|
|
|
2ff057 |
rpmdbFilterIterator(pi, ts->members->installedPackages, 0);
|
|
|
2ff057 |
else
|
|
|
2ff057 |
/* Leave in pi only files removed in ts */
|
|
|
2ff057 |
rpmdbFilterIterator(pi, ts->members->removedPackages, 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
rc = rpmdbGetIteratorCount(pi);
|
|
|
2ff057 |
rpmdbFreeIterator(pi);
|
|
|
2ff057 |
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
|
|
|
2ff057 |
rpmscriptTriggerModes tm, int priorityClass)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int nerrors = 0, i;
|
|
|
2ff057 |
rpmdbIndexIterator ii;
|
|
|
2ff057 |
const void *key;
|
|
|
2ff057 |
char *pfx;
|
|
|
2ff057 |
size_t keylen;
|
|
|
2ff057 |
Header trigH;
|
|
|
2ff057 |
int (*matchFunc)(rpmts, rpmte, const char*, rpmsenseFlags sense);
|
|
|
2ff057 |
rpmTagVal priorityTag;
|
|
|
2ff057 |
rpmtriggers triggers = rpmtriggersCreate(10);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Decide if we match triggers against files in te or in whole ts */
|
|
|
2ff057 |
if (tm == RPMSCRIPT_FILETRIGGER) {
|
|
|
2ff057 |
matchFunc = matchFilesInPkg;
|
|
|
2ff057 |
priorityTag = RPMTAG_FILETRIGGERPRIORITIES;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
matchFunc = matchFilesInTran;
|
|
|
2ff057 |
priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), triggerDsTag(tm));
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Loop over all file triggers in rpmdb */
|
|
|
2ff057 |
while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
|
|
|
2ff057 |
pfx = xmalloc(keylen + 1);
|
|
|
2ff057 |
memcpy(pfx, key, keylen);
|
|
|
2ff057 |
pfx[keylen] = '\0';
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Check if file trigger is fired by any file in ts/te */
|
|
|
2ff057 |
if (matchFunc(ts, te, pfx, sense)) {
|
|
|
2ff057 |
for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++) {
|
|
|
2ff057 |
struct rpmtd_s priorities;
|
|
|
2ff057 |
unsigned int priority;
|
|
|
2ff057 |
unsigned int offset = rpmdbIndexIteratorPkgOffset(ii, i);
|
|
|
2ff057 |
unsigned int tix = rpmdbIndexIteratorTagNum(ii, i);
|
|
|
2ff057 |
|
|
|
2ff057 |
/*
|
|
|
2ff057 |
* Don't handle transaction triggers installed in current
|
|
|
2ff057 |
* transaction to avoid executing the same script two times.
|
|
|
2ff057 |
* These triggers are handled in runImmedFileTriggers().
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
if (tm == RPMSCRIPT_TRANSFILETRIGGER &&
|
|
|
2ff057 |
(packageHashHasEntry(ts->members->removedPackages, offset) ||
|
|
|
2ff057 |
packageHashHasEntry(ts->members->installedPackages, offset)))
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Get priority of trigger from header */
|
|
|
2ff057 |
trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offset);
|
|
|
2ff057 |
headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM);
|
|
|
2ff057 |
rpmtdSetIndex(&priorities, tix);
|
|
|
2ff057 |
priority = *rpmtdGetUint32(&priorities);
|
|
|
2ff057 |
headerFree(trigH);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Store file trigger in array */
|
|
|
2ff057 |
rpmtriggersAdd(triggers, offset, tix, priority);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(pfx);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdbIndexIteratorFree(ii);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Sort triggers by priority, offset, trigger index */
|
|
|
2ff057 |
rpmtriggersSortAndUniq(triggers);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmChrootIn() != 0) {
|
|
|
2ff057 |
rpmtriggersFree(triggers);
|
|
|
2ff057 |
return RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Handle stored triggers */
|
|
|
2ff057 |
for (i = 0; i < triggers->count; i++) {
|
|
|
2ff057 |
if (priorityClass == 1) {
|
|
|
2ff057 |
if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
} else if (priorityClass == 2) {
|
|
|
2ff057 |
if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), triggers->triggerInfo[i].hdrNum);
|
|
|
2ff057 |
if (tm == RPMSCRIPT_FILETRIGGER)
|
|
|
2ff057 |
nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 0,
|
|
|
2ff057 |
triggers->triggerInfo[i].tix);
|
|
|
2ff057 |
else
|
|
|
2ff057 |
nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 1,
|
|
|
2ff057 |
triggers->triggerInfo[i].tix);
|
|
|
2ff057 |
headerFree(trigH);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmtriggersFree(triggers);
|
|
|
2ff057 |
/* XXX an error here would require a full abort */
|
|
|
2ff057 |
(void) rpmChrootOut();
|
|
|
2ff057 |
|
|
|
2ff057 |
return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
|
|
|
2ff057 |
rpmscriptTriggerModes tm, int priorityClass)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int nerrors = 0;
|
|
|
2ff057 |
int triggersCount, i;
|
|
|
2ff057 |
Header trigH = rpmteHeader(te);
|
|
|
2ff057 |
struct rpmtd_s priorities;
|
|
|
2ff057 |
rpmTagVal priorityTag;
|
|
|
2ff057 |
rpmtriggers triggers;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (tm == RPMSCRIPT_FILETRIGGER) {
|
|
|
2ff057 |
priorityTag = RPMTAG_FILETRIGGERPRIORITIES;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM);
|
|
|
2ff057 |
|
|
|
2ff057 |
triggersCount = rpmtdCount(&priorities);
|
|
|
2ff057 |
triggers = rpmtriggersCreate(triggersCount);
|
|
|
2ff057 |
|
|
|
2ff057 |
for (i = 0; i < triggersCount; i++) {
|
|
|
2ff057 |
rpmtdSetIndex(&priorities, i);
|
|
|
2ff057 |
/* Offset is not important, all triggers are from the same package */
|
|
|
2ff057 |
rpmtriggersAdd(triggers, 0, i, *rpmtdGetUint32(&priorities));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Sort triggers by priority, offset, trigger index */
|
|
|
2ff057 |
rpmtriggersSortAndUniq(triggers);
|
|
|
2ff057 |
|
|
|
2ff057 |
for (i = 0; i < triggersCount; i++) {
|
|
|
2ff057 |
if (priorityClass == 1) {
|
|
|
2ff057 |
if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
} else if (priorityClass == 2) {
|
|
|
2ff057 |
if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND)
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 2,
|
|
|
2ff057 |
triggers->triggerInfo[i].tix);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmtriggersFree(triggers);
|
|
|
2ff057 |
headerFree(trigH);
|
|
|
2ff057 |
|
|
|
2ff057 |
return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL;
|
|
|
2ff057 |
}
|