csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
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
}