rpmScript rpmScriptFromTriggerTag(Header h, rpmTagVal triggerTag, uint32_t ix) { rpmScript script = NULL; struct rpmtd_s tscripts, tprogs, tflags; headerGetFlags hgflags = HEADERGET_MINMEM; headerGet(h, RPMTAG_TRIGGERSCRIPTS, &tscripts, hgflags); headerGet(h, RPMTAG_TRIGGERSCRIPTPROG, &tprogs, hgflags); headerGet(h, RPMTAG_TRIGGERSCRIPTFLAGS, &tflags, hgflags); if (rpmtdSetIndex(&tscripts, ix) >= 0 && rpmtdSetIndex(&tprogs, ix) >= 0) { rpmscriptFlags sflags = 0; const char *prog = rpmtdGetString(&tprogs); if (rpmtdSetIndex(&tflags, ix) >= 0) sflags = rpmtdGetNumber(&tflags); script = rpmScriptNew(h, triggerTag, rpmtdGetString(&tscripts), sflags); /* hack up a hge-style NULL-terminated array */ script->args = xmalloc(2 * sizeof(*script->args) + strlen(prog) + 1); script->args[0] = (char *)(script->args + 2); script->args[1] = NULL; strcpy(script->args[0], prog); } rpmtdFreeData(&tscripts); rpmtdFreeData(&tprogs); rpmtdFreeData(&tflags); return script; }
static int isNewDep(rpmds *dsp, rpmds bds, Header h, rpmTagVal indextag, uint32_t index) { int isnew = 1; if (!indextag) { /* With normal deps, we can just merge and see if anything got added */ isnew = (rpmdsMerge(dsp, bds) > 0); } else { struct rpmtd_s idx; rpmds ads = *dsp; headerGet(h, indextag, &idx, HEADERGET_MINMEM); /* rpmdsFind/Merge() probably isn't realiable with triggers... */ rpmdsInit(ads); while (isnew && rpmdsNext(ads) >= 0) { if (!rstreq(rpmdsN(ads), rpmdsN(bds))) continue; if (!rstreq(rpmdsEVR(ads), rpmdsEVR(bds))) continue; if (rpmdsFlags(ads) != rpmdsFlags(bds)) continue; if (indextag && rpmtdSetIndex(&idx, rpmdsIx(ads)) >= 0 && rpmtdGetNumber(&idx) != index) continue; isnew = 0; } rpmtdFreeData(&idx); rpmdsMerge(dsp, bds); } return isnew; }
void rpmtriggersPrepPostUnTransFileTrigs(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) { char pfx[keylen + 1]; memcpy(pfx, key, keylen); pfx[keylen] = '\0'; /* Check if file trigger matches any file in this te */ rpmfi fi = rpmfilesFindPrefix(files, pfx); if (rpmfiFC(fi) > 0) { /* If yes then store it */ rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii), rpmdbIndexIteratorNumPkgs(ii)); } rpmfiFree(fi); } rpmdbIndexIteratorFree(ii); 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)) { struct rpmtd_s priorities; headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES, &priorities, HEADERGET_MINMEM); rpmtdSetIndex(&priorities, tix); rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi), tix, *rpmtdGetUint32(&priorities)); } rpmdsFree(rpmdsTrigger); tix++; } rpmdsFree(rpmdsTriggers); } } rpmdbFreeIterator(mi); }
rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, rpmscriptTriggerModes tm, int priorityClass) { int nerrors = 0; int triggersCount, i; Header trigH = rpmteHeader(te); struct rpmtd_s priorities; rpmTagVal priorityTag; rpmtriggers triggers; if (tm == RPMSCRIPT_FILETRIGGER) { priorityTag = RPMTAG_FILETRIGGERPRIORITIES; } else { priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES; } headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM); triggersCount = rpmtdCount(&priorities); triggers = rpmtriggersCreate(triggersCount); for (i = 0; i < triggersCount; i++) { rpmtdSetIndex(&priorities, i); /* Offset is not important, all triggers are from the same package */ rpmtriggersAdd(triggers, 0, i, *rpmtdGetUint32(&priorities)); } /* Sort triggers by priority, offset, trigger index */ rpmtriggersSortAndUniq(triggers); for (i = 0; i < triggersCount; i++) { if (priorityClass == 1) { if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND) continue; } else if (priorityClass == 2) { if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND) continue; } nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 2, triggers->triggerInfo[i].tix); } rpmtriggersFree(triggers); headerFree(trigH); return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL; }
static int haveLangTag(Header h, rpmTagVal tag, const char *lang) { int rc = 0; /* assume tag not present */ int langNum = -1; if (lang && *lang) { /* See if the language is in header i18n table */ struct rpmtd_s langtd; const char *s = NULL; headerGet(h, RPMTAG_HEADERI18NTABLE, &langtd, HEADERGET_MINMEM); while ((s = rpmtdNextString(&langtd)) != NULL) { if (rstreq(s, lang)) { langNum = rpmtdGetIndex(&langtd); break; } } rpmtdFreeData(&langtd); } else { /* C locale */ langNum = 0; } /* If locale is present, check the actual tag content */ if (langNum >= 0) { struct rpmtd_s td; headerGet(h, tag, &td, HEADERGET_MINMEM|HEADERGET_RAW); if (rpmtdSetIndex(&td, langNum) == langNum) { const char *s = rpmtdGetString(&td); /* non-empty string means a dupe */ if (s && *s) rc = 1; } rpmtdFreeData(&td); }; return rc; }
void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations, rpmfs fs, Header h) { char ** baseNames; char ** dirNames; uint32_t * dirIndexes; rpm_count_t fileCount, dirCount; int nrelocated = 0; int fileAlloced = 0; char * fn = NULL; int haveRelocatedBase = 0; size_t maxlen = 0; int i, j; struct rpmtd_s bnames, dnames, dindexes, fmodes; if (!addPrefixes(h, relocations, numRelocations)) return; if (rpmIsDebug()) { rpmlog(RPMLOG_DEBUG, "========== relocations\n"); for (i = 0; i < numRelocations; i++) { if (relocations[i].oldPath == NULL) continue; /* XXX can't happen */ if (relocations[i].newPath == NULL) rpmlog(RPMLOG_DEBUG, "%5d exclude %s\n", i, relocations[i].oldPath); else rpmlog(RPMLOG_DEBUG, "%5d relocate %s -> %s\n", i, relocations[i].oldPath, relocations[i].newPath); } } for (i = 0; i < numRelocations; i++) { if (relocations[i].newPath == NULL) continue; size_t len = strlen(relocations[i].newPath); if (len > maxlen) maxlen = len; } headerGet(h, RPMTAG_BASENAMES, &bnames, HEADERGET_MINMEM); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, HEADERGET_ALLOC); headerGet(h, RPMTAG_DIRNAMES, &dnames, HEADERGET_MINMEM); headerGet(h, RPMTAG_FILEMODES, &fmodes, HEADERGET_MINMEM); /* TODO XXX ugh.. use rpmtd iterators & friends instead */ baseNames = bnames.data; dirIndexes = dindexes.data; fileCount = rpmtdCount(&bnames); dirCount = rpmtdCount(&dnames); /* XXX TODO: use rpmtdDup() instead */ dirNames = dnames.data = duparray(dnames.data, dirCount); dnames.flags |= RPMTD_PTR_ALLOCED; /* * For all relocations, we go through sorted file/relocation lists * backwards so that /usr/local relocations take precedence over /usr * ones. */ /* Relocate individual paths. */ for (i = fileCount - 1; i >= 0; i--) { rpmFileTypes ft; int fnlen; size_t len = maxlen + strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1; if (len >= fileAlloced) { fileAlloced = len * 2; fn = xrealloc(fn, fileAlloced); } assert(fn != NULL); /* XXX can't happen */ *fn = '\0'; fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn; /* * See if this file path needs relocating. */ /* * XXX FIXME: Would a bsearch of the (already sorted) * relocation list be a good idea? */ for (j = numRelocations - 1; j >= 0; j--) { if (relocations[j].oldPath == NULL) /* XXX can't happen */ continue; len = !rstreq(relocations[j].oldPath, "/") ? strlen(relocations[j].oldPath) : 0; if (fnlen < len) continue; /* * Only subdirectories or complete file paths may be relocated. We * don't check for '\0' as our directory names all end in '/'. */ if (!(fn[len] == '/' || fnlen == len)) continue; if (!rstreqn(relocations[j].oldPath, fn, len)) continue; break; } if (j < 0) continue; rpmtdSetIndex(&fmodes, i); ft = rpmfiWhatis(rpmtdGetNumber(&fmodes)); /* On install, a relocate to NULL means skip the path. */ if (relocations[j].newPath == NULL) { if (ft == XDIR) { /* Start with the parent, looking for directory to exclude. */ for (j = dirIndexes[i]; j < dirCount; j++) { len = strlen(dirNames[j]) - 1; while (len > 0 && dirNames[j][len-1] == '/') len--; if (fnlen != len) continue; if (!rstreqn(fn, dirNames[j], fnlen)) continue; break; } } rpmfsSetAction(fs, i, FA_SKIPNSTATE); rpmlog(RPMLOG_DEBUG, "excluding %s %s\n", ftstring(ft), fn); continue; } /* Relocation on full paths only, please. */ if (fnlen != len) continue; rpmlog(RPMLOG_DEBUG, "relocating %s to %s\n", fn, relocations[j].newPath); nrelocated++; strcpy(fn, relocations[j].newPath); { char * te = strrchr(fn, '/'); if (te) { if (te > fn) te++; /* root is special */ fnlen = te - fn; } else te = fn + strlen(fn); if (!rstreq(baseNames[i], te)) { /* basename changed too? */ if (!haveRelocatedBase) { /* XXX TODO: use rpmtdDup() instead */ bnames.data = baseNames = duparray(baseNames, fileCount); bnames.flags |= RPMTD_PTR_ALLOCED; haveRelocatedBase = 1; } free(baseNames[i]); baseNames[i] = xstrdup(te); } *te = '\0'; /* terminate new directory name */ } /* Does this directory already exist in the directory list? */ for (j = 0; j < dirCount; j++) { if (fnlen != strlen(dirNames[j])) continue; if (!rstreqn(fn, dirNames[j], fnlen)) continue; break; } if (j < dirCount) { dirIndexes[i] = j; continue; } /* Creating new paths is a pita */ dirNames = dnames.data = xrealloc(dnames.data, sizeof(*dirNames) * (dirCount + 1)); dirNames[dirCount] = xstrdup(fn); dirIndexes[i] = dirCount; dirCount++; dnames.count++; } /* Finish off by relocating directories. */ for (i = dirCount - 1; i >= 0; i--) { for (j = numRelocations - 1; j >= 0; j--) { if (relocations[j].oldPath == NULL) /* XXX can't happen */ continue; size_t len = !rstreq(relocations[j].oldPath, "/") ? strlen(relocations[j].oldPath) : 0; if (len && !rstreqn(relocations[j].oldPath, dirNames[i], len)) continue; /* * Only subdirectories or complete file paths may be relocated. We * don't check for '\0' as our directory names all end in '/'. */ if (dirNames[i][len] != '/') continue; if (relocations[j].newPath) { /* Relocate the path */ char *t = NULL; rstrscat(&t, relocations[j].newPath, (dirNames[i] + len), NULL); /* Unfortunately rpmCleanPath strips the trailing slash.. */ (void) rpmCleanPath(t); rstrcat(&t, "/"); rpmlog(RPMLOG_DEBUG, "relocating directory %s to %s\n", dirNames[i], t); free(dirNames[i]); dirNames[i] = t; nrelocated++; } } } /* Save original filenames in header and replace (relocated) filenames. */ if (nrelocated) { saveOrig(h); headerMod(h, &bnames); headerMod(h, &dnames); headerMod(h, &dindexes); } rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); rpmtdFreeData(&fmodes); free(fn); }
/** * Adjust file states in database for files shared with this package: * currently either "replaced" or "wrong color". * @param psm package state machine data * @return 0 always */ static rpmRC markReplacedFiles(const rpmpsm psm) { const rpmts ts = psm->ts; rpmfs fs = rpmteGetFileStates(psm->te); sharedFileInfo replaced = rpmfsGetReplaced(fs); sharedFileInfo sfi; rpmdbMatchIterator mi; Header h; unsigned int * offsets; unsigned int prev; unsigned int num; if (!replaced) return RPMRC_OK; num = prev = 0; for (sfi = replaced; sfi; sfi=rpmfsNextReplaced(fs, sfi)) { if (prev && prev == sfi->otherPkg) continue; prev = sfi->otherPkg; num++; } if (num == 0) return RPMRC_OK; offsets = xmalloc(num * sizeof(*offsets)); offsets[0] = 0; num = prev = 0; for (sfi = replaced; sfi; sfi=rpmfsNextReplaced(fs, sfi)) { if (prev && prev == sfi->otherPkg) continue; prev = sfi->otherPkg; offsets[num++] = sfi->otherPkg; } mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0); rpmdbAppendIterator(mi, offsets, num); rpmdbSetIteratorRewrite(mi, 1); sfi = replaced; while ((h = rpmdbNextIterator(mi)) != NULL) { int modified; struct rpmtd_s secStates; modified = 0; if (!headerGet(h, RPMTAG_FILESTATES, &secStates, HEADERGET_MINMEM)) continue; prev = rpmdbGetIteratorOffset(mi); num = 0; while (sfi && sfi->otherPkg == prev) { int ix = rpmtdSetIndex(&secStates, sfi->otherFileNum); assert(ix != -1); char *state = rpmtdGetChar(&secStates); if (state && *state != sfi->rstate) { *state = sfi->rstate; if (modified == 0) { /* Modified header will be rewritten. */ modified = 1; rpmdbSetIteratorModified(mi, modified); } num++; } sfi=rpmfsNextReplaced(fs, sfi); } rpmtdFreeData(&secStates); } rpmdbFreeIterator(mi); free(offsets); return RPMRC_OK; }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, uint64_t fileCount, fingerPrintCache fpc) { tsMembers tsmem = rpmtsMembers(ts); rpmte p; rpmfiles fi; rpmfs fs; int j; unsigned int fileNum; rpmdbMatchIterator mi; Header h, newheader; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts, fileCount); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint *fpp = NULL; unsigned int installedPkg; int beingRemoved = 0; rpmfiles otherFi = NULL; rpmte *removedPkg = NULL; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); if (packageHashGetEntry(tsmem->removedPackages, installedPkg, &removedPkg, NULL, NULL)) { beingRemoved = 1; otherFi = rpmteFiles(removedPkg[0]); } h = headerLink(h); /* For packages being removed we can use its rpmfi to avoid all this */ if (!beingRemoved) { headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); } /* loop over all interesting files in that package */ do { int fpIx; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; /* lookup finger print for this file */ fileNum = rpmdbGetIteratorFileNum(mi); if (!beingRemoved) { rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); fpLookup(fpc, dirName, baseName, &fpp); fpIx = 0; } else { fpp = rpmfilesFps(otherFi); fpIx = fileNum; } /* search for files in the transaction with same finger print */ fpCacheGetByFp(fpc, fpp, fpIx, &recs, &numRecs); for (j = 0; j < numRecs; j++) { p = recs[j].p; fi = rpmteFiles(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { /* XXX What to do if this fails? */ otherFi = rpmfilesNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } handleInstInstalledFile(ts, p, fi, recs[j].fileno, h, otherFi, fileNum, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } rpmfilesFree(fi); } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfilesFree(otherFi); if (!beingRemoved) { rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); free(fpp); } headerFree(h); h = newheader; } rpmdbFreeIterator(mi); }
rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, rpmscriptTriggerModes tm, int priorityClass) { int nerrors = 0, i; rpmdbIndexIterator ii; const void *key; char *pfx; size_t keylen; Header trigH; int (*matchFunc)(rpmts, rpmte, const char*, rpmsenseFlags sense); rpmTagVal priorityTag; rpmtriggers triggers = rpmtriggersCreate(10); /* Decide if we match triggers against files in te or in whole ts */ if (tm == RPMSCRIPT_FILETRIGGER) { matchFunc = matchFilesInPkg; priorityTag = RPMTAG_FILETRIGGERPRIORITIES; } else { matchFunc = matchFilesInTran; priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES; } ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), triggerDsTag(tm)); /* 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)) { for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++) { struct rpmtd_s priorities; unsigned int priority; unsigned int offset = rpmdbIndexIteratorPkgOffset(ii, i); unsigned int tix = rpmdbIndexIteratorTagNum(ii, i); /* * 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 && (packageHashHasEntry(ts->members->removedPackages, offset) || packageHashHasEntry(ts->members->installedPackages, offset))) continue; /* Get priority of trigger from header */ trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offset); headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM); rpmtdSetIndex(&priorities, tix); priority = *rpmtdGetUint32(&priorities); headerFree(trigH); /* Store file trigger in array */ rpmtriggersAdd(triggers, offset, tix, priority); } } free(pfx); } rpmdbIndexIteratorFree(ii); /* Sort triggers by priority, offset, trigger index */ rpmtriggersSortAndUniq(triggers); if (rpmChrootIn() != 0) { rpmtriggersFree(triggers); return RPMRC_FAIL; } /* Handle stored triggers */ for (i = 0; i < triggers->count; i++) { if (priorityClass == 1) { if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND) continue; } else if (priorityClass == 2) { if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND) continue; } trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), triggers->triggerInfo[i].hdrNum); if (tm == RPMSCRIPT_FILETRIGGER) nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 0, triggers->triggerInfo[i].tix); else nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 1, triggers->triggerInfo[i].tix); headerFree(trigH); } rpmtriggersFree(triggers); /* XXX an error here would require a full abort */ (void) rpmChrootOut(); return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL; }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, fingerPrintCache fpc) { rpmps ps; rpmte p; rpmfi fi; rpmfs fs; rpmfi otherFi=NULL; int j; int xx; unsigned int fileNum; const char * oldDir; rpmdbMatchIterator mi; Header h, newheader; int beingRemoved; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } ps = rpmtsProblems(ts); /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint fp; unsigned int installedPkg; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); beingRemoved = 0; if (ts->removedPackages != NULL) for (j = 0; j < ts->numRemovedPackages; j++) { if (ts->removedPackages[j] != installedPkg) continue; beingRemoved = 1; break; } h = headerLink(h); headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); oldDir = NULL; /* loop over all interesting files in that package */ do { int gotRecs; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; fileNum = rpmdbGetIteratorFileNum(mi); rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); /* lookup finger print for this file */ if ( dirName == oldDir) { /* directory is the same as last round */ fp.baseName = baseName; } else { fp = fpLookup(fpc, dirName, baseName, 1); oldDir = dirName; } /* search for files in the transaction with same finger print */ gotRecs = rpmFpHashGetEntry(ts->ht, &fp, &recs, &numRecs, NULL); for (j=0; (j<numRecs)&&gotRecs; j++) { p = recs[j].p; fi = rpmteFI(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } rpmfiSetFX(fi, recs[j].fileno); rpmfiSetFX(otherFi, fileNum); xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { rpmfiSetFX(fi, recs[j].fileno); if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfiFree(otherFi); rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); headerFree(h); h = newheader; } mi = rpmdbFreeIterator(mi); }
/** * Execute triggers. * @todo Trigger on any provides, not just package NVR. * @param psm package state machine data * @param sourceH header of trigger source * @param trigH header of triggered package * @param arg2 * @param triggersAlreadyRun * @return */ static rpmRC handleOneTrigger(const rpmpsm psm, Header sourceH, Header trigH, int arg2, unsigned char * triggersAlreadyRun) { const rpmts ts = psm->ts; rpmds trigger = rpmdsInit(rpmdsNew(trigH, RPMTAG_TRIGGERNAME, 0)); struct rpmtd_s pfx; const char * sourceName = headerGetString(sourceH, RPMTAG_NAME); const char * triggerName = headerGetString(trigH, RPMTAG_NAME); rpmRC rc = RPMRC_OK; int i; if (trigger == NULL) return rc; headerGet(trigH, RPMTAG_INSTPREFIXES, &pfx, HEADERGET_ALLOC|HEADERGET_ARGV); (void) rpmdsSetNoPromote(trigger, 1); while ((i = rpmdsNext(trigger)) >= 0) { struct rpmtd_s tindexes; uint32_t tix; if (!(rpmdsFlags(trigger) & psm->sense)) continue; if (!rstreq(rpmdsN(trigger), sourceName)) continue; /* XXX Trigger on any provided dependency, not just the package NEVR */ if (!rpmdsAnyMatchesDep(sourceH, trigger, 1)) continue; if (!headerGet(trigH, RPMTAG_TRIGGERINDEX, &tindexes, HEADERGET_MINMEM)) continue; if (rpmtdSetIndex(&tindexes, i) < 0) { rpmtdFreeData(&tindexes); continue; } tix = rpmtdGetNumber(&tindexes); if (triggersAlreadyRun == NULL || triggersAlreadyRun[tix] == 0) { int arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName); if (arg1 < 0) { /* XXX W2DO? fails as "execution of script failed" */ rc = RPMRC_FAIL; } else { rpmScript script = rpmScriptFromTriggerTag(trigH, triggertag(psm->sense), tix); arg1 += psm->countCorrection; rc = runScript(psm, pfx.data, script, arg1, arg2); if (triggersAlreadyRun != NULL) triggersAlreadyRun[tix] = 1; rpmScriptFree(script); } } rpmtdFreeData(&tindexes); /* * Each target/source header pair can only result in a single * script being run. */ break; } rpmtdFreeData(&pfx); rpmdsFree(trigger); return rc; }