diff --git a/CHANGES b/CHANGES index 6cdb71aad..f37c13af6 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,9 @@ - respect LINGUAS when install package files - added trigger support to build code - got rid of annoying mwftw() type warning + - fixed many command line options which got broke by changes + for non-gcc compilers + - added trigger support in install code 2.4.103 -> 2.4.104: - fixed popt/Makefile.in to use CPP from configure diff --git a/configure.in b/configure.in index 62e245fb1..07e570e61 100644 --- a/configure.in +++ b/configure.in @@ -557,6 +557,7 @@ AC_SUBST(MISCDIR) AC_SUBST(LIBMISC) AC_SUBST(MISCPATH) AC_SUBST(RPMCONFIGDIR) +AC_SUBST(MKDIR_P) if test -d newbuild ; then NBMAKEFILE=newbuild/Makefile diff --git a/lib/depends.c b/lib/depends.c index 161afeac1..993da7478 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -9,6 +9,7 @@ #include #include +#include "depends.h" #include "intl.h" #include "misc.h" #include "rpmlib.h" @@ -72,7 +73,6 @@ static int checkPackageDeps(rpmDependencies rpmdep, struct problemsSet * psp, Header h, const char * requirement); static int dbrecMatchesDepFlags(rpmDependencies rpmdep, int recOffset, char * reqVersion, int reqFlags); -static int headerMatchesDepFlags(Header h, char * reqVersion, int reqFlags); struct availablePackage * alSatisfiesDepend(struct availableList * al, char * reqName, char * reqVersion, int reqFlags); @@ -709,7 +709,7 @@ static int checkPackageDeps(rpmDependencies rpmdep, struct problemsSet * psp, return ourrc; } -static int headerMatchesDepFlags(Header h, char * reqInfo, int reqFlags) { +int headerMatchesDepFlags(Header h, char * reqInfo, int reqFlags) { char * name, * version, * release, * chptr; char * reqVersion = reqInfo; char * reqRelease = NULL; diff --git a/lib/formats.c b/lib/formats.c index 74ccd1837..2c7bc58aa 100644 --- a/lib/formats.c +++ b/lib/formats.c @@ -13,6 +13,8 @@ static char * permsFormat(int_32 type, const void * data, char * formatPrefix, int padding, int element); static char * depflagsFormat(int_32 type, const void * data, char * formatPrefix, int padding, int element); +static char * triggertypeFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element); static char * fflagsFormat(int_32 type, const void * data, char * formatPrefix, int padding, int element); static int fsnamesTag(Header h, int_32 * type, void ** data, int_32 * count, @@ -20,17 +22,24 @@ static int fsnamesTag(Header h, int_32 * type, void ** data, int_32 * count, static int fssizesTag(Header h, int_32 * type, void ** data, int_32 * count, int * freeData); static int instprefixTag(Header h, int_32 * type, void ** data, int_32 * count, - int * freeData); + int * freeData); +static int triggercondsTag(Header h, int_32 * type, void ** data, + int_32 * count, int * freeData); +static int triggertypeTag(Header h, int_32 * type, void ** data, + int_32 * count, int * freeData); static char * permsString(int mode); const struct headerSprintfExtension rpmHeaderFormats[] = { { HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } }, { HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } }, { HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } }, + { HEADER_EXT_TAG, "RPMTAG_TRIGGERCONDS", { triggercondsTag } }, + { HEADER_EXT_TAG, "RPMTAG_TRIGGERTYPE", { triggertypeTag } }, { HEADER_EXT_FORMAT, "depflags", { depflagsFormat } }, { HEADER_EXT_FORMAT, "fflags", { fflagsFormat } }, { HEADER_EXT_FORMAT, "perms", { permsFormat } }, { HEADER_EXT_FORMAT, "permissions", { permsFormat } }, + { HEADER_EXT_FORMAT, "triggertype", { triggertypeFormat } }, { HEADER_EXT_MORE, NULL, { (void *) headerDefaultFormats } } } ; @@ -85,6 +94,23 @@ static char * permsString(int mode) { return perms; } +static char * triggertypeFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element) { + const int_32 * item = data; + char * val; + + if (type != RPM_INT32_TYPE) { + val = malloc(20); + strcpy(val, _("(not a number)")); + } else if (*item & RPMSENSE_TRIGGERIN) { + val = strdup("in"); + } else { + val = strdup("un"); + } + + return val; +} + static char * permsFormat(int_32 type, const void * data, char * formatPrefix, int padding, int element) { char * val; @@ -140,7 +166,7 @@ static char * depflagsFormat(int_32 type, const void * data, char * formatPrefix, int padding, int element) { char * val; char buf[10]; - int anint = *((int_32 *) data); + int anint = *(((int_32 *) data) + element); if (type != RPM_INT32_TYPE) { val = malloc(20); @@ -223,3 +249,101 @@ static int fssizesTag(Header h, int_32 * type, void ** data, int_32 * count, return 0; } + +static int triggercondsTag(Header h, int_32 * type, void ** data, + int_32 * count, int * freeData) { + int_32 * indices, * flags; + char ** names, ** versions; + int numNames, numScripts; + char ** conds, ** s; + char * item, * flagsStr; + char * chptr; + int i, j; + char buf[5]; + + if (!headerGetEntry(h, RPMTAG_TRIGGERNAME, NULL, (void **) &names, + &numNames)) { + *freeData = 0; + return 0; + } + + headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, NULL); + headerGetEntry(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL); + headerGetEntry(h, RPMTAG_TRIGGERVERSION, NULL, (void **) &versions, NULL); + headerGetEntry(h, RPMTAG_TRIGGERSCRIPTS, NULL, (void **) &s, &numScripts); + free(s); + + *freeData = 1; + *data = conds = malloc(sizeof(char * ) * numScripts); + *count = numScripts; + *type = RPM_STRING_ARRAY_TYPE; + for (i = 0; i < numScripts; i++) { + chptr = malloc(1); + *chptr = '\0'; + + for (j = 0; j < numNames; j++) { + if (indices[j] != i) continue; + + item = malloc(strlen(names[j]) + strlen(versions[j]) + 20); + if (flags[j] & RPMSENSE_SENSEMASK) { + buf[0] = '%', buf[1] = '\0'; + flagsStr = depflagsFormat(RPM_INT32_TYPE, flags, buf, + 0, j); + sprintf(item, "%s %s %s", names[j], flagsStr, versions[j]); + free(flagsStr); + } else { + strcpy(item, names[j]); + } + + chptr = realloc(chptr, strlen(chptr) + strlen(item) + 5); + if (*chptr) strcat(chptr, ", "); + strcat(chptr, item); + free(item); + } + + conds[i] = chptr; + } + + free(names); + free(versions); + + return 0; +} + +static int triggertypeTag(Header h, int_32 * type, void ** data, + int_32 * count, int * freeData) { + int_32 * indices, * flags; + char ** conds, ** s; + int i, j; + char buf[5]; + int numScripts, numNames; + + if (!headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &indices, + &numNames)) { + *freeData = 0; + return 1; + } + + headerGetEntry(h, RPMTAG_TRIGGERFLAGS, NULL, (void **) &flags, NULL); + + headerGetEntry(h, RPMTAG_TRIGGERSCRIPTS, NULL, (void **) &s, &numScripts); + free(s); + + *freeData = 1; + *data = conds = malloc(sizeof(char * ) * numScripts); + *count = numScripts; + *type = RPM_STRING_ARRAY_TYPE; + for (i = 0; i < numScripts; i++) { + for (j = 0; j < numNames; j++) { + if (indices[j] != i) continue; + + if (flags[j] & RPMSENSE_TRIGGERIN) + conds[i] = strdup("in"); + else + conds[i] = strdup("un"); + break; + } + } + + return 0; +} diff --git a/lib/install.c b/lib/install.c index 4316cd0d7..b92cf9837 100644 --- a/lib/install.c +++ b/lib/install.c @@ -752,8 +752,8 @@ int rpmInstallPackage(char * rootdir, rpmdb db, int fd, } rpmMessage(RPMMESS_DEBUG, "running preinstall script (if any)\n"); - if (runScript("/", h, RPMTAG_PREIN, RPMTAG_PREINPROG, scriptArg, - flags & RPMINSTALL_NOSCRIPTS, 0)) { + if (runInstScript("/", h, RPMTAG_PREIN, RPMTAG_PREINPROG, scriptArg, + flags & RPMINSTALL_NOSCRIPTS, 0)) { if (replacedList) free(replacedList); if (freeFileMem) freeFileMemory(fileMem); @@ -914,8 +914,19 @@ int rpmInstallPackage(char * rootdir, rpmdb db, int fd, rpmMessage(RPMMESS_DEBUG, "running postinstall script (if any)\n"); - if (runScript(rootdir, h, RPMTAG_POSTIN, RPMTAG_POSTINPROG, scriptArg, - flags & RPMINSTALL_NOSCRIPTS, 0)) { + if (runInstScript(rootdir, h, RPMTAG_POSTIN, RPMTAG_POSTINPROG, scriptArg, + flags & RPMINSTALL_NOSCRIPTS, 0)) { + return 2; + } + + /* Run triggers this package sets off */ + if (runTriggers(rootdir, db, RPMSENSE_TRIGGERIN, h, 0)) { + return 2; + } + + /* Run triggers in this package which are set off by other things in + the database. */ + if (runImmedTriggers(rootdir, db, RPMSENSE_TRIGGERIN, h, 0)) { return 2; } diff --git a/lib/install.h b/lib/install.h index 453413dbb..689b0b9ac 100644 --- a/lib/install.h +++ b/lib/install.h @@ -12,7 +12,14 @@ struct sharedFile { int findSharedFiles(rpmdb db, int offset, char ** fileList, int fileCount, struct sharedFile ** listPtr, int * listCountPtr); -int runScript(char * prefix, Header h, int scriptTag, int progTag, - int arg, int norunScripts, int err); +int runInstScript(char * prefix, Header h, int scriptTag, int progTag, + int arg, int norunScripts, int err); +/* this looks for triggers in the database which h would set off */ +int runTriggers(char * root, rpmdb db, int sense, Header h, + int countCorrection); +/* while this looks for triggers in h which are set off by things in the db + database to calculate arguments to the trigger */ +int runImmedTriggers(char * root, rpmdb db, int sense, Header h, + int countCorrection); #endif diff --git a/lib/rpmdb.c b/lib/rpmdb.c index c57dc5c76..1184401eb 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -35,7 +35,7 @@ struct rpmdb_s { faFile pkgs; dbiIndex * nameIndex, * fileIndex, * groupIndex, * providesIndex; - dbiIndex * requiredbyIndex, * conflictsIndex; + dbiIndex * requiredbyIndex, * conflictsIndex, * triggerIndex; }; static void removeIndexEntry(dbiIndex * dbi, char * name, dbiIndexRecord rec, @@ -72,11 +72,32 @@ int rpmdbInit (char * prefix, int perms) { return openDatabase(prefix, dbpath, &db, O_CREAT | O_RDWR, perms, 1); } +static int openDbFile(char * prefix, char * dbpath, char * shortName, + int justCheck, int perms, dbiIndex ** db){ + char * filename = alloca(strlen(prefix) + strlen(dbpath) + + strlen(shortName) + 20); + + if (!prefix) prefix=""; + + strcpy(filename, prefix); + strcat(filename, dbpath); + strcat(filename, shortName); + + if (!justCheck || !exists(filename)) { + *db = dbiOpenIndex(filename, perms, 0644); + if (!*db) { + return 1; + } + } + + return 0; +} + int openDatabase(char * prefix, char * dbpath, rpmdb *rpmdbp, int mode, int perms, int justcheck) { char * filename; struct rpmdb_s db; - int i; + int i, rc; struct flock lockinfo; /* we should accept NULL as a valid prefix */ @@ -135,91 +156,37 @@ int openDatabase(char * prefix, char * dbpath, rpmdb *rpmdbp, int mode, } } - strcpy(filename, prefix); - strcat(filename, dbpath); - strcat(filename, "nameindex.rpm"); + rc = openDbFile(prefix, dbpath, "nameindex.rpm", justcheck, mode, + &db.nameIndex); + if (!rc) + rc = openDbFile(prefix, dbpath, "fileindex.rpm", justcheck, mode, + &db.fileIndex); + if (!rc) + rc = openDbFile(prefix, dbpath, "providesindex.rpm", justcheck, mode, + &db.providesIndex); + if (!rc) + rc = openDbFile(prefix, dbpath, "requiredby.rpm", justcheck, mode, + &db.requiredbyIndex); + if (!rc) + rc = openDbFile(prefix, dbpath, "conflictsindex.rpm", justcheck, mode, + &db.conflictsIndex); + if (!rc) + rc = openDbFile(prefix, dbpath, "groupindex.rpm", justcheck, mode, + &db.groupIndex); + if (!rc) + rc = openDbFile(prefix, dbpath, "triggerindex.rpm", justcheck, mode, + &db.triggerIndex); - if (!justcheck || !exists(filename)) { - db.nameIndex = dbiOpenIndex(filename, mode, 0644); - if (!db.nameIndex) { - faClose(db.pkgs); - return 1; - } - } - - strcpy(filename, prefix); - strcat(filename, dbpath); - strcat(filename, "fileindex.rpm"); - - if (!justcheck || !exists(filename)) { - db.fileIndex = dbiOpenIndex(filename, mode, 0644); - if (!db.fileIndex) { - faClose(db.pkgs); - dbiCloseIndex(db.nameIndex); - return 1; - } - } - - strcpy(filename, prefix); - strcat(filename, dbpath); - strcat(filename, "groupindex.rpm"); - - if (!justcheck || !exists(filename)) { - db.groupIndex = dbiOpenIndex(filename, mode, 0644); - if (!db.groupIndex) { - faClose(db.pkgs); - dbiCloseIndex(db.nameIndex); - dbiCloseIndex(db.fileIndex); - return 1; - } - } - - strcpy(filename, prefix); - strcat(filename, dbpath); - strcat(filename, "providesindex.rpm"); - - if (!justcheck || !exists(filename)) { - db.providesIndex = dbiOpenIndex(filename, mode, 0644); - if (!db.providesIndex) { - faClose(db.pkgs); - dbiCloseIndex(db.fileIndex); - dbiCloseIndex(db.nameIndex); - dbiCloseIndex(db.groupIndex); - return 1; - } - } - - strcpy(filename, prefix); - strcat(filename, dbpath); - strcat(filename, "requiredby.rpm"); - - if (!justcheck || !exists(filename)) { - db.requiredbyIndex = dbiOpenIndex(filename, mode, 0644); - if (!db.requiredbyIndex) { - faClose(db.pkgs); - dbiCloseIndex(db.fileIndex); - dbiCloseIndex(db.nameIndex); - dbiCloseIndex(db.groupIndex); - dbiCloseIndex(db.providesIndex); - return 1; - } - } - - strcpy(filename, prefix); - strcat(filename, dbpath); - strcat(filename, "conflictsindex.rpm"); - - if (!justcheck || !exists(filename)) { - db.conflictsIndex = dbiOpenIndex(filename, mode, 0644); - if (!db.conflictsIndex) { - faClose(db.pkgs); - dbiCloseIndex(db.fileIndex); - dbiCloseIndex(db.nameIndex); - dbiCloseIndex(db.groupIndex); - dbiCloseIndex(db.providesIndex); - dbiCloseIndex(db.requiredbyIndex); - return 1; - } + if (rc) { + faClose(db.pkgs); + if (db.nameIndex) dbiCloseIndex(db.nameIndex); + if (db.fileIndex) dbiCloseIndex(db.fileIndex); + if (db.providesIndex) dbiCloseIndex(db.providesIndex); + if (db.requiredbyIndex) dbiCloseIndex(db.requiredbyIndex); + if (db.conflictsIndex) dbiCloseIndex(db.conflictsIndex); + if (db.groupIndex) dbiCloseIndex(db.groupIndex); + if (db.triggerIndex) dbiCloseIndex(db.triggerIndex); + return 1; } *rpmdbp = malloc(sizeof(struct rpmdb_s)); @@ -240,6 +207,7 @@ void rpmdbClose (rpmdb db) { if (db->providesIndex) dbiCloseIndex(db->providesIndex); if (db->requiredbyIndex) dbiCloseIndex(db->requiredbyIndex); if (db->conflictsIndex) dbiCloseIndex(db->conflictsIndex); + if (db->triggerIndex) dbiCloseIndex(db->triggerIndex); free(db); } @@ -294,6 +262,10 @@ int rpmdbFindByConflicts(rpmdb db, char * filespec, dbiIndexSet * matches) { return dbiSearchIndex(db->conflictsIndex, filespec, matches); } +int rpmdbFindByTriggeredBy(rpmdb db, char * filespec, dbiIndexSet * matches) { + return dbiSearchIndex(db->triggerIndex, filespec, matches); +} + int rpmdbFindByGroup(rpmdb db, char * group, dbiIndexSet * matches) { return dbiSearchIndex(db->groupIndex, group, matches); } @@ -337,7 +309,7 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) { unsigned int count; dbiIndexRecord rec; char ** fileList, ** providesList, ** requiredbyList; - char ** conflictList; + char ** conflictList, ** triggerList; int i; rec.recOffset = offset; @@ -392,6 +364,18 @@ int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) { free(requiredbyList); } + if (headerGetEntry(h, RPMTAG_TRIGGERNAME, &type, (void **) &triggerList, + &count)) { + /* triggerList often contains duplicates */ + for (i = 0; i < count; i++) { + rpmMessage(RPMMESS_DEBUG, "removing trigger index for %s\n", + triggerList[i]); + removeIndexEntry(db->triggerIndex, triggerList[i], rec, + 1, "trigger index"); + } + free(triggerList); + } + if (headerGetEntry(h, RPMTAG_CONFLICTNAME, &type, (void **) &conflictList, &count)) { for (i = 0; i < count; i++) { @@ -453,13 +437,15 @@ static int addIndexEntry(dbiIndex * idx, char * index, unsigned int offset, int rpmdbAdd(rpmdb db, Header dbentry) { unsigned int dboffset; - unsigned int i; + unsigned int i, j; char ** fileList; char ** providesList; char ** requiredbyList; char ** conflictList; + char ** triggerList; char * name, * group; - int count, providesCount, requiredbyCount, conflictCount; + int count = 0, providesCount = 0, requiredbyCount = 0, conflictCount = 0; + int triggerCount = 0; int type; int rc = 0; @@ -468,25 +454,16 @@ int rpmdbAdd(rpmdb db, Header dbentry) { if (!group) group = "Unknown"; - if (!headerGetEntry(dbentry, RPMTAG_FILENAMES, &type, (void **) &fileList, - &count)) { - count = 0; - } - - if (!headerGetEntry(dbentry, RPMTAG_PROVIDES, &type, (void **) &providesList, - &providesCount)) { - providesCount = 0; - } - - if (!headerGetEntry(dbentry, RPMTAG_REQUIRENAME, &type, - (void **) &requiredbyList, &requiredbyCount)) { - requiredbyCount = 0; - } - - if (!headerGetEntry(dbentry, RPMTAG_CONFLICTNAME, &type, - (void **) &conflictList, &conflictCount)) { - conflictCount = 0; - } + headerGetEntry(dbentry, RPMTAG_FILENAMES, &type, (void **) &fileList, + &count); + headerGetEntry(dbentry, RPMTAG_PROVIDES, &type, (void **) &providesList, + &providesCount); + headerGetEntry(dbentry, RPMTAG_REQUIRENAME, &type, + (void **) &requiredbyList, &requiredbyCount); + headerGetEntry(dbentry, RPMTAG_CONFLICTNAME, &type, + (void **) &conflictList, &conflictCount); + headerGetEntry(dbentry, RPMTAG_TRIGGERNAME, &type, + (void **) &triggerList, &triggerCount); blockSignals(); @@ -496,6 +473,8 @@ int rpmdbAdd(rpmdb db, Header dbentry) { unblockSignals(); if (providesCount) free(providesList); if (requiredbyCount) free(requiredbyList); + if (conflictCount) free(conflictList); + if (triggerCount) free(triggerList); if (count) free(fileList); return 1; } @@ -509,36 +488,40 @@ int rpmdbAdd(rpmdb db, Header dbentry) { if (addIndexEntry(db->groupIndex, group, dboffset, 0)) rc = 1; - for (i = 0; i < conflictCount; i++) { - if (addIndexEntry(db->conflictsIndex, conflictList[i], dboffset, 0)) - rc = 1; + for (i = 0; i < triggerCount; i++) { + /* don't add duplicates */ + for (j = 0; j < i; j++) + if (!strcmp(triggerList[i], triggerList[j])) break; + if (j == i) + rc += addIndexEntry(db->triggerIndex, triggerList[i], dboffset, 0); } - for (i = 0; i < requiredbyCount; i++) { - if (addIndexEntry(db->requiredbyIndex, requiredbyList[i], dboffset, 0)) - rc = 1; - } + for (i = 0; i < conflictCount; i++) + rc += addIndexEntry(db->conflictsIndex, conflictList[i], dboffset, 0); - for (i = 0; i < providesCount; i++) { - if (addIndexEntry(db->providesIndex, providesList[i], dboffset, 0)) - rc = 1; - } + for (i = 0; i < requiredbyCount; i++) + rc += addIndexEntry(db->requiredbyIndex, requiredbyList[i], + dboffset, 0); - for (i = 0; i < count; i++) { - if (addIndexEntry(db->fileIndex, fileList[i], dboffset, i)) - rc = 1; - } + for (i = 0; i < providesCount; i++) + rc += addIndexEntry(db->providesIndex, providesList[i], dboffset, 0); + + for (i = 0; i < count; i++) + rc += addIndexEntry(db->fileIndex, fileList[i], dboffset, i); dbiSyncIndex(db->nameIndex); dbiSyncIndex(db->groupIndex); dbiSyncIndex(db->fileIndex); dbiSyncIndex(db->providesIndex); dbiSyncIndex(db->requiredbyIndex); + dbiSyncIndex(db->triggerIndex); unblockSignals(); if (requiredbyCount) free(requiredbyList); if (providesCount) free(providesList); + if (conflictCount) free(conflictList); + if (triggerCount) free(triggerList); if (count) free(fileList); return rc; diff --git a/lib/rpmlib.h b/lib/rpmlib.h index a7e9caad9..30c254bb6 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -112,7 +112,7 @@ extern const struct headerSprintfExtension rpmHeaderFormats[]; #define RPMTAG_BUILDARCHS 1089 #define RPMTAG_OBSOLETES 1090 #define RPMTAG_VERIFYSCRIPTPROG 1091 -#define RPMTAG_TRIGGERSCRIPTPROGS 1092 +#define RPMTAG_TRIGGERSCRIPTPROG 1092 #define RPMTAG_DOCDIR 1093 /* internal */ #define RPMTAG_COOKIE 1094 #define RPMTAG_FILEDEVICES 1095 @@ -120,9 +120,8 @@ extern const struct headerSprintfExtension rpmHeaderFormats[]; #define RPMTAG_FILELANGS 1097 #define RPMTAG_PREFIXES 1098 #define RPMTAG_INSTPREFIXES 1099 -#define RPMTAG_TRIGGERSCRIPTPROG 1100 -#define RPMTAG_TRIGGERIN 1101 /* internal */ -#define RPMTAG_TRIGGERUN 1102 /* internal */ +#define RPMTAG_TRIGGERIN 1100 /* internal */ +#define RPMTAG_TRIGGERUN 1101 /* internal */ #define RPMTAG_EXTERNAL_TAG 1000000 @@ -282,6 +281,7 @@ int rpmdbFindPackage(rpmdb db, char * name, dbiIndexSet * matches); int rpmdbFindByProvides(rpmdb db, char * provides, dbiIndexSet * matches); int rpmdbFindByRequiredBy(rpmdb db, char * requires, dbiIndexSet * matches); int rpmdbFindByConflicts(rpmdb db, char * conflicts, dbiIndexSet * matches); +int rpmdbFindByTriggeredBy(rpmdb db, char * package, dbiIndexSet * matches); /* these are just convience functions */ int rpmdbFindByLabel(rpmdb db, char * label, dbiIndexSet * matches); diff --git a/lib/uninstall.c b/lib/uninstall.c index 6a4a72e4b..e56bcc62a 100644 --- a/lib/uninstall.c +++ b/lib/uninstall.c @@ -16,6 +16,8 @@ #include #include +#include "dbindex.h" +#include "depends.h" #include "install.h" #include "intl.h" #include "messages.h" @@ -34,8 +36,10 @@ static int handleSharedFiles(rpmdb db, int offset, char ** fileList, char ** fileMd5List, int fileCount, enum fileActions * fileActions); static int removeFile(char * file, char state, unsigned int flags, char * md5, - short mode, enum fileActions action, char * rmmess, + short mode, enum fileActions action, int brokenMd5, int test); +static int runScript(Header h, char * root, int progArgc, char ** progArgv, + char * script, int arg1, int arg2, int errfd); static int sharedFileCmp(const void * one, const void * two) { if (((struct sharedFile *) one)->secRecOffset < @@ -200,7 +204,7 @@ int rpmRemovePackage(char * prefix, rpmdb db, unsigned int offset, int flags) { Header h; int i, j; int fileCount; - char * rmmess, * name, * version, * release; + char * name, * version, * release; char * fnbuffer = NULL; dbiIndexSet matches; int fnbuffersize = 0; @@ -237,23 +241,24 @@ int rpmRemovePackage(char * prefix, rpmdb db, unsigned int offset, int flags) { scriptArg = matches.count - 1; dbiFreeIndexRecord(matches); - if (flags & RPMUNINSTALL_TEST) { - rmmess = "would remove"; - } else { - rmmess = "removing"; + /* run triggers from this package which are keyed on installed packages */ + if (runImmedTriggers(prefix, db, RPMSENSE_TRIGGERUN, h, -1)) { + return 2; } - if (!(flags & RPMUNINSTALL_TEST)) { - rpmMessage(RPMMESS_DEBUG, "running preuninstall script (if any)\n"); + /* run triggers which are set off by the removal of this package */ + if (runTriggers(prefix, db, RPMSENSE_TRIGGERUN, h, -1)) + return 1; - if (runScript(prefix, h, RPMTAG_PREUN, RPMTAG_PREUNPROG, scriptArg, - flags & RPMUNINSTALL_NOSCRIPTS, 0)) { + if (!(flags & RPMUNINSTALL_TEST)) { + if (runInstScript(prefix, h, RPMTAG_PREUN, RPMTAG_PREUNPROG, scriptArg, + flags & RPMUNINSTALL_NOSCRIPTS, 0)) { headerFree(h); return 1; } } - rpmMessage(RPMMESS_DEBUG, "%s files test = %d\n", rmmess, + rpmMessage(RPMMESS_DEBUG, "will remove files test = %d\n", flags & RPMUNINSTALL_TEST); if (!(flags & RPMUNINSTALL_JUSTDB) && headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, @@ -321,7 +326,7 @@ int rpmRemovePackage(char * prefix, rpmdb db, unsigned int offset, int flags) { removeFile(fnbuffer, fileStatesList[i], fileFlagsList[i], fileMd5List[i], fileModesList[i], fileActions[i], - rmmess, !headerIsEntry(h, RPMTAG_RPMVERSION), + !headerIsEntry(h, RPMTAG_RPMVERSION), flags & RPMUNINSTALL_TEST); } @@ -331,68 +336,49 @@ int rpmRemovePackage(char * prefix, rpmdb db, unsigned int offset, int flags) { if (!(flags & RPMUNINSTALL_TEST)) { rpmMessage(RPMMESS_DEBUG, "running postuninstall script (if any)\n"); - runScript(prefix, h, RPMTAG_POSTUN, RPMTAG_POSTUNPROG, scriptArg, - flags & RPMUNINSTALL_NOSCRIPTS, 0); + runInstScript(prefix, h, RPMTAG_POSTUN, RPMTAG_POSTUNPROG, scriptArg, + flags & RPMUNINSTALL_NOSCRIPTS, 0); } headerFree(h); - rpmMessage(RPMMESS_DEBUG, "%s database entry\n", rmmess); + rpmMessage(RPMMESS_DEBUG, "removing database entry\n"); if (!(flags & RPMUNINSTALL_TEST)) rpmdbRemove(db, offset, 0); return 0; } -int runScript(char * root, Header h, int scriptTag, int progTag, - int arg, int norunScripts, int err) { - char * script; - char * fn; - int fd = -1; - int isdebug = rpmIsDebug(); - int child; - int status; - char upgradeArg[20]; +static int runScript(Header h, char * root, int progArgc, char ** progArgv, + char * script, int arg1, int arg2, int errfd) { + char ** argv; + int argc; char ** prefixes = NULL; int numPrefixes; char * oldPrefix; - char * program; - char ** programArgv; - char ** argv = NULL; - int programArgc; - int programType = 0; - int pipes[2]; - int out = 0; - int freePrefixes = 0; int maxPrefixLength; + int len; char * prefixBuf; + pid_t child; + int status; + char * fn; + int fd; int i; + int freePrefixes; + int pipes[2]; + int out = 1; - if (norunScripts) return 0; - - sprintf(upgradeArg, "%d", arg); - - /* headerGetEntry() sets the data pointer to NULL if the entry does - not exist */ - headerGetEntry(h, progTag, &programType, (void **) &programArgv, - &programArgc); - headerGetEntry(h, scriptTag, NULL, (void **) &script, NULL); - - if (!programArgv && !script) + if (!progArgv && !script) return 0; - else if (!programArgv) { - programArgv = malloc(4 * sizeof(char *)); - programArgv[0] = "/bin/sh"; - programArgc = 1; - } else if (programType == RPM_STRING_TYPE) { - program = (char *) programArgv; - programArgv = malloc(4 * sizeof(char *)); - programArgv[0] = program; - programArgc = 1; + else if (!progArgv) { + argv = alloca(5 * sizeof(char *)); + argv[0] = "/bin/sh"; + argc = 1; } else { - argv = programArgv; - programArgv = malloc((programArgc + 3) * sizeof(char *)); - memcpy(programArgv, argv, programArgc * sizeof(char *)); + argv = progArgv; + argv = alloca((progArgc + 4) * sizeof(char *)); + memcpy(argv, progArgv, progArgc * sizeof(char *)); + argc = progArgc; } if (headerGetEntry(h, RPMTAG_INSTPREFIXES, NULL, (void *) &prefixes, @@ -409,42 +395,45 @@ int runScript(char * root, Header h, int scriptTag, int progTag, maxPrefixLength = 0; for (i = 0; i < numPrefixes; i++) { - child = strlen(prefixes[i]); - if (child > maxPrefixLength) maxPrefixLength = child; + len = strlen(prefixes[i]); + if (len > maxPrefixLength) maxPrefixLength = len; } prefixBuf = alloca(maxPrefixLength + 50); - rpmMessage(RPMMESS_DEBUG, "running inst helper %s\n", programArgv[0]); - if (script) { if (makeTempFile(root, &fn, &fd)) { - free(programArgv); - if (argv) - free(argv); + free(argv); + if (freePrefixes) free(prefixes); return 1; } - if (isdebug && - (!strcmp(programArgv[0], "/bin/sh") || - !strcmp(programArgv[0], "/bin/bash"))) + if (rpmIsDebug() && + (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash"))) write(fd, "set -x\n", 7); write(fd, script, strlen(script)); close(fd); - programArgv[programArgc++] = fn + strlen(root); - programArgv[programArgc++] = upgradeArg; + argv[argc++] = fn + strlen(root); + if (arg1 >= 0) { + argv[argc] = alloca(20); + sprintf(argv[argc++], "%d", arg1); + } + if (arg2 >= 0) { + argv[argc] = alloca(20); + sprintf(argv[argc++], "%d", arg2); + } } - programArgv[programArgc] = NULL; + argv[argc] = NULL; - if (err) { + if (errfd) { if (rpmIsVerbose()) { - out = err; + out = errfd; } else { out = open("/dev/null", O_WRONLY); if (out < 0) { - out = err; + out = errfd; } } } @@ -456,12 +445,12 @@ int runScript(char * root, Header h, int scriptTag, int progTag, dup2(pipes[0], 0); close(pipes[0]); - if (err) { - if (err != 2) dup2(err, 2); + if (errfd) { + if (errfd != 2) dup2(errfd, 2); if (out != 1) dup2(out, 1); /* make sure we don't close stdin/stderr/stdout by mistake! */ - /* if (err > 2) close (err); - if (out > 2 && out != err) close (out); */ + if (errfd > 2) close (errfd); + if (out > 2 && out != errfd) close (out); } doputenv(SCRIPT_PATH); @@ -478,13 +467,12 @@ int runScript(char * root, Header h, int scriptTag, int progTag, } if (strcmp(root, "/")) { - rpmMessage(RPMMESS_DEBUG, "performing chroot(%s)\n", root); chroot(root); } chdir("/"); - execv(programArgv[0], programArgv); + execv(argv[0], argv); _exit(-1); } @@ -492,18 +480,13 @@ int runScript(char * root, Header h, int scriptTag, int progTag, if (freePrefixes) free(prefixes); - if (err) { + if (errfd) { if (out > 2) close(out); - if (err > 2) close(err); - if (!rpmIsVerbose()) close(out); + if (errfd > 2) close(errfd); } - free(programArgv); - if (argv) - free(argv); - if (script) { - if (!isdebug) unlink(fn); + if (!rpmIsDebug()) unlink(fn); free(fn); } @@ -515,8 +498,37 @@ int runScript(char * root, Header h, int scriptTag, int progTag, return 0; } +int runInstScript(char * root, Header h, int scriptTag, int progTag, + int arg, int norunScripts, int err) { + void ** programArgv; + int programArgc; + char ** argv; + int programType; + char * script; + int rc; + + if (norunScripts) return 0; + + /* headerGetEntry() sets the data pointer to NULL if the entry does + not exist */ + headerGetEntry(h, progTag, &programType, (void **) &programArgv, + &programArgc); + headerGetEntry(h, scriptTag, NULL, (void **) &script, NULL); + + if (programArgv && programType == RPM_STRING_TYPE) { + argv = alloca(sizeof(char *)); + *argv = (char *) programArgv; + } else { + argv = (char **) programArgv; + } + + rc = runScript(h, root, programArgc, argv, script, arg, -1, err); + if (programType == RPM_STRING_ARRAY_TYPE) free(programArgv); + return rc; +} + static int removeFile(char * file, char state, unsigned int flags, char * md5, - short mode, enum fileActions action, char * rmmess, + short mode, enum fileActions action, int brokenMd5, int test) { char currentMd5[40]; int rc = 0; @@ -571,7 +583,7 @@ static int removeFile(char * file, char state, unsigned int flags, char * md5, break; case REMOVE: - rpmMessage(RPMMESS_DEBUG, "%s - %s\n", file, rmmess); + rpmMessage(RPMMESS_DEBUG, "%s - removing\n", file); if (S_ISDIR(mode)) { if (!test) { if (rmdir(file)) { @@ -599,7 +611,151 @@ static int removeFile(char * file, char state, unsigned int flags, char * md5, } break; } - } + } - return 0; + return 0; +} + +static int handleOneTrigger(char * root, rpmdb db, int sense, Header sourceH, + Header triggeredH, int arg1correction, int arg2, + char * triggersAlreadyRun) { + char ** triggerNames, ** triggerVersions; + char ** triggerScripts, ** triggerProgs; + int_32 * triggerFlags, * triggerIndices; + char * triggerPackageName, * sourceName; + int numTriggers; + int rc = 0; + int i; + int index; + dbiIndexSet matches; + + if (!headerGetEntry(triggeredH, RPMTAG_TRIGGERNAME, NULL, + (void **) &triggerNames, &numTriggers)) { + headerFree(triggeredH); + return 0; + } + + headerGetEntry(sourceH, RPMTAG_NAME, NULL, (void **) &sourceName, NULL); + + headerGetEntry(triggeredH, RPMTAG_TRIGGERFLAGS, NULL, + (void **) &triggerFlags, NULL); + headerGetEntry(triggeredH, RPMTAG_TRIGGERVERSION, NULL, + (void **) &triggerVersions, NULL); + + for (i = 0; i < numTriggers; i++) { + if (!(triggerFlags[i] & sense)) continue; + if (strcmp(triggerNames[i], sourceName)) continue; + if (!headerMatchesDepFlags(sourceH, triggerVersions[i], + triggerFlags[i])) continue; + + headerGetEntry(triggeredH, RPMTAG_TRIGGERINDEX, NULL, + (void **) &triggerIndices, NULL); + headerGetEntry(triggeredH, RPMTAG_TRIGGERSCRIPTS, NULL, + (void **) &triggerScripts, NULL); + headerGetEntry(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, NULL, + (void **) &triggerProgs, NULL); + + headerGetEntry(triggeredH, RPMTAG_NAME, NULL, + (void **) &triggerPackageName, NULL); + rpmdbFindPackage(db, triggerPackageName, &matches); + dbiFreeIndexRecord(matches); + + index = triggerIndices[i]; + if (!triggersAlreadyRun || !triggersAlreadyRun[index]) { + rc = runScript(triggeredH, root, 1, triggerProgs + index, + triggerScripts[index], + matches.count + arg1correction, arg2, 0); + if (triggersAlreadyRun) triggersAlreadyRun[index] = 1; + } + + free(triggerScripts); + free(triggerProgs); + + /* each target/source header pair can only result in a single + script being run */ + break; + } + + free(triggerNames); + + return rc; +} + +int runTriggers(char * root, rpmdb db, int sense, Header h, + int countCorrection) { + char * packageName; + dbiIndexSet matches, otherMatches; + Header triggeredH; + int numPackage; + int rc; + int i, j; + + headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &packageName, NULL); + + if ((rc = rpmdbFindByTriggeredBy(db, packageName, &matches)) < 0) + return 1; + else if (rc) + return 0; + + rpmdbFindPackage(db, packageName, &otherMatches); + numPackage = otherMatches.count + countCorrection; + dbiFreeIndexRecord(otherMatches); + + rc = 0; + for (i = 0; i < matches.count; i++) { + if (!(triggeredH = rpmdbGetRecord(db, matches.recs[i].recOffset))) + return 1; + + rc |= handleOneTrigger(root, db, sense, h, triggeredH, 0, numPackage, + NULL); + + headerFree(triggeredH); + } + + dbiFreeIndexRecord(matches); + + return rc; + +} + +int runImmedTriggers(char * root, rpmdb db, int sense, Header h, + int countCorrection) { + int rc = 0; + dbiIndexSet matches; + char ** triggerNames; + int numTriggers; + int i, j; + int_32 * triggerIndices; + char * triggersRun; + Header sourceH; + + if (!headerGetEntry(h, RPMTAG_TRIGGERNAME, NULL, (void **) &triggerNames, + &numTriggers)) + return 0; + headerGetEntry(h, RPMTAG_TRIGGERINDEX, NULL, (void **) &triggerIndices, + &i); + triggersRun = alloca(sizeof(*triggersRun) * i); + memset(triggersRun, 0, sizeof(*triggersRun) * i); + + for (i = 0; i < numTriggers; i++) { + if (triggersRun[triggerIndices[i]]) continue; + + if ((j = rpmdbFindPackage(db, triggerNames[i], &matches))) { + if (j < 0) rc |= 1; + continue; + } + + for (j = 0; j < matches.count; j++) { + if (!(sourceH = rpmdbGetRecord(db, matches.recs[j].recOffset))) + return 1; + rc |= handleOneTrigger(root, db, sense, sourceH, h, + countCorrection, matches.count, triggersRun); + headerFree(sourceH); + if (triggersRun[triggerIndices[i]]) break; + } + + dbiFreeIndexRecord(matches); + } + + return rc; } diff --git a/lib/verify.c b/lib/verify.c index dd805a73f..5b5a8fa7d 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -210,6 +210,6 @@ int rpmVerifyFile(char * prefix, Header h, int filenum, int * result, } int rpmVerifyScript(char * root, Header h, int err) { - return runScript(root, h, RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, + return runInstScript(root, h, RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, 0, 0, err); } diff --git a/query.c b/query.c index ca668a2c3..3dfcd4efe 100644 --- a/query.c +++ b/query.c @@ -442,6 +442,16 @@ int doQuery(char * prefix, enum querysources source, int queryFlags, } break; + case QUERY_TRIGGEREDBY: + if (rpmdbFindByTriggeredBy(db, arg, &matches)) { + fprintf(stderr, _("no package triggers %s\n"), arg); + retcode = 1; + } else { + showMatches(db, matches, queryFlags, queryFormat); + dbiFreeIndexRecord(matches); + } + break; + case QUERY_WHATREQUIRES: if (rpmdbFindByRequiredBy(db, arg, &matches)) { fprintf(stderr, _("no package requires %s\n"), arg); diff --git a/query.h b/query.h index e87a19e76..744cdd9d7 100644 --- a/query.h +++ b/query.h @@ -5,7 +5,7 @@ enum querysources { QUERY_PATH, QUERY_PACKAGE, QUERY_ALL, QUERY_RPM, QUERY_GROUP, QUERY_WHATPROVIDES, QUERY_WHATREQUIRES, - QUERY_DBOFFSET }; + QUERY_DBOFFSET, QUERY_TRIGGEREDBY }; #define QUERY_FOR_LIST (1 << 1) #define QUERY_FOR_STATE (1 << 2) diff --git a/rpm.c b/rpm.c index fcf3833aa..6f8da9f39 100755 --- a/rpm.c +++ b/rpm.c @@ -45,6 +45,7 @@ #define GETOPT_INSTALL 1014 #define GETOPT_RMSOURCE 1015 #define GETOPT_RELOCATE 1016 +#define GETOPT_TRIGGEREDBY 1017 char * version = VERSION; @@ -158,6 +159,7 @@ static struct poptOption optionsTable[] = { { "tarball", 't', POPT_ARG_STRING, 0, 't' }, { "test", '\0', 0, &test, 0 }, { "timecheck", '\0', POPT_ARG_STRING, 0, GETOPT_TIMECHECK }, + { "triggeredby", '\0', 0, 0, GETOPT_TRIGGEREDBY }, { "upgrade", 'U', 0, 0, 'U' }, { "uninstall", 'u', 0, 0, 'u' }, { "verbose", 'v', 0, 0, 'v' }, @@ -503,10 +505,9 @@ int main(int argc, char ** argv) { int queryFor = 0; int installFlags = 0, uninstallFlags = 0, interfaceFlags = 0; int buildAmount = 0; - int shortCircuit = 0, queryTags = 0, excldocs = 0; int showrc = 0; int gotDbpath = 0, building = 0, verifyFlags; - int noMd5 = 0, allFiles = 0, justdb = 0, rmsource = 0; + int noMd5 = 0, rmsource = 0; int checksigFlags = 0; int timeCheck = 0; int addSign = NEW_SIGNATURE; @@ -532,44 +533,42 @@ int main(int argc, char ** argv) { struct rpmRelocation * relocations = NULL; int numRelocations = 0; - - /* set the defaults for the various command line options */ - allFiles = 0; - allMatches = 0; - badReloc = 0; - clean = 0; - dump = 0; - excldocs = 0; - force = 0; - ftpProxy = NULL; - ftpPort = NULL; - showHash = 0; - help = 0; - ignoreArch = 0; - ignoreOs = 0; - incldocs = 0; - initdb = 0; - justdb = 0; - noDeps = 0; - noOrder = 0; - noFiles = 0; - noMd5 = 0; - noPgp = 0; - noScripts = 0; - oldPackage = 0; - showPercents = 0; - pipeOutput = NULL; - prefix = NULL; - queryTags = 0; - quiet = 0; - replaceFiles = 0; - replacePackages = 0; - rootdir = "/"; - shortCircuit = 0; - signIt = 0; - test = 0; - rpm_version = 0; - + /* set the defaults for the various command line options */ + allFiles = 0; + allMatches = 0; + badReloc = 0; + clean = 0; + dump = 0; + excldocs = 0; + force = 0; + ftpProxy = NULL; + ftpPort = NULL; + showHash = 0; + help = 0; + ignoreArch = 0; + ignoreOs = 0; + incldocs = 0; + initdb = 0; + justdb = 0; + noDeps = 0; + noOrder = 0; + noFiles = 0; + noMd5 = 0; + noPgp = 0; + noScripts = 0; + oldPackage = 0; + showPercents = 0; + pipeOutput = NULL; + prefix = NULL; + queryTags = 0; + quiet = 0; + replaceFiles = 0; + replacePackages = 0; + rootdir = "/"; + shortCircuit = 0; + signIt = 0; + test = 0; + rpm_version = 0; /* set up the correct locale */ setlocale(LC_ALL, "" ); @@ -787,6 +786,14 @@ int main(int argc, char ** argv) { querySource = QUERY_WHATPROVIDES; break; + case GETOPT_TRIGGEREDBY: + if (querySource != QUERY_PACKAGE && + querySource != QUERY_TRIGGEREDBY) + argerror(_("one type of query/verify may be performed at a " + "time")); + querySource = QUERY_TRIGGEREDBY; + break; + case GETOPT_REBUILD: if (bigMode != MODE_UNKNOWN && bigMode != MODE_REBUILD) argerror(_("only one major mode may be specified")); diff --git a/rpmpopt b/rpmpopt index bc8b283b3..24495731e 100644 --- a/rpmpopt +++ b/rpmpopt @@ -40,7 +40,7 @@ rpm alias -R --requires rpm alias --info --qf 'Name : %-27{NAME} Distribution: %{DISTRIBUTION}\n\ Version : %-27{VERSION} Vendor: %{VENDOR}\n\ Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\ -Install date: %|INSTALLTIME?{%-27{INSTALLTIME:date}}:{(not installed) }| Build Host: %{BUILDHOST}\n\ +Install date: %|INSTALLTIME?{%-27{INSTALLTIME:date}}:{(not installed) }| Build Host: %{BUILDHOST}\n\ Group : %-27{GROUP} Source RPM: %{SOURCERPM}\n\ Size : %{SIZE}\n\ %|PACKAGER?{Packager : %{PACKAGER}\n}|\ @@ -49,3 +49,7 @@ Summary : %{SUMMARY}\n\ Description :\n%{DESCRIPTION}\n' rpm alias --changelog --qf '[* %{CHANGELOGTIME:day} %{CHANGELOGNAME}\n\n%{CHANGELOGTEXT}\n\n]' + +rpm alias --triggerscripts --qf '\ +[trigger%{TRIGGERTYPE} script (through %{TRIGGERSCRIPTPROG}) -- %{TRIGGERCONDS}\n\ +%{TRIGGERSCRIPTS}\n]'