diff options
Diffstat (limited to 'lib/rpmte.c')
-rw-r--r-- | lib/rpmte.c | 927 |
1 files changed, 927 insertions, 0 deletions
diff --git a/lib/rpmte.c b/lib/rpmte.c new file mode 100644 index 0000000..d13575a --- /dev/null +++ b/lib/rpmte.c @@ -0,0 +1,927 @@ +/** \ingroup rpmdep + * \file lib/rpmte.c + * Routine(s) to handle an "rpmte" transaction element. + */ +#include "system.h" + +#include <rpm/rpmtypes.h> +#include <rpm/rpmlib.h> /* RPM_MACHTABLE_* */ +#include <rpm/rpmmacro.h> +#include <rpm/rpmds.h> +#include <rpm/rpmfi.h> +#include <rpm/rpmts.h> +#include <rpm/rpmdb.h> +#include <rpm/rpmlog.h> + +#include "lib/rpmplugins.h" +#include "lib/rpmte_internal.h" + +#include "debug.h" + +/** \ingroup rpmte + * A single package instance to be installed/removed atomically. + */ +struct rpmte_s { + rpmElementType type; /*!< Package disposition (installed/removed). */ + + Header h; /*!< Package header. */ + char * NEVR; /*!< Package name-version-release. */ + char * NEVRA; /*!< Package name-version-release.arch. */ + char * name; /*!< Name: */ + char * epoch; + char * version; /*!< Version: */ + char * release; /*!< Release: */ + char * arch; /*!< Architecture hint. */ + char * os; /*!< Operating system hint. */ + int isSource; /*!< (TR_ADDED) source rpm? */ + + rpmte depends; /*!< Package updated by this package (ERASE te) */ + rpmte parent; /*!< Parent transaction element. */ + unsigned int db_instance; /*!< Database instance (of removed pkgs) */ + tsortInfo tsi; /*!< Dependency ordering chains. */ + + rpmds thisds; /*!< This package's provided NEVR. */ + rpmds provides; /*!< Provides: dependencies. */ + rpmds requires; /*!< Requires: dependencies. */ + rpmds conflicts; /*!< Conflicts: dependencies. */ + rpmds obsoletes; /*!< Obsoletes: dependencies. */ + rpmds order; /*!< Order: dependencies. */ + rpmfi fi; /*!< File information. */ + rpmps probs; /*!< Problems (relocations) */ + rpmts ts; /*!< Parent transaction */ + + rpm_color_t color; /*!< Color bit(s) from package dependencies. */ + rpm_loff_t pkgFileSize; /*!< No. of bytes in package file (approx). */ + unsigned int headerSize; /*!< No. of bytes in package header */ + + fnpyKey key; /*!< (TR_ADDED) Retrieval key. */ + rpmRelocation * relocs; /*!< (TR_ADDED) Payload file relocations. */ + int nrelocs; /*!< (TR_ADDED) No. of relocations. */ + FD_t fd; /*!< (TR_ADDED) Payload file descriptor. */ + +#define RPMTE_HAVE_PRETRANS (1 << 0) +#define RPMTE_HAVE_POSTTRANS (1 << 1) + int transscripts; /*!< pre/posttrans script existence */ + int failed; /*!< (parent) install/erase failed */ + + rpmfs fs; + + ARGV_t lastInCollectionsAny; /*!< list of collections this te is the last to be installed or removed */ + ARGV_t lastInCollectionsAdd; /*!< list of collections this te is the last to be only installed */ + ARGV_t firstInCollectionsRemove; /*!< list of collections this te is the first to be only removed */ + ARGV_t collections; /*!< list of collections */ +}; + +/* forward declarations */ +static void rpmteColorDS(rpmte te, rpmTag tag); +static int rpmteClose(rpmte te, int reset_fi); + +void rpmteCleanDS(rpmte te) +{ + te->thisds = rpmdsFree(te->thisds); + te->provides = rpmdsFree(te->provides); + te->requires = rpmdsFree(te->requires); + te->conflicts = rpmdsFree(te->conflicts); + te->obsoletes = rpmdsFree(te->obsoletes); + te->order = rpmdsFree(te->order); +} + +static rpmfi getFI(rpmte p, Header h) +{ + rpmfiFlags fiflags; + fiflags = (p->type == TR_ADDED) ? (RPMFI_NOHEADER | RPMFI_FLAGS_INSTALL) : + (RPMFI_NOHEADER | RPMFI_FLAGS_ERASE); + + /* relocate stuff in header if necessary */ + if (rpmteType(p) == TR_ADDED && rpmfsFC(p->fs) > 0) { + if (!headerIsSource(h) && !headerIsEntry(h, RPMTAG_ORIGBASENAMES)) { + rpmRelocateFileList(p->relocs, p->nrelocs, p->fs, h); + } + } + return rpmfiNew(NULL, h, RPMTAG_BASENAMES, fiflags); +} + +/* stupid bubble sort, but it's probably faster here */ +static void sortRelocs(rpmRelocation *relocations, int numRelocations) +{ + for (int i = 0; i < numRelocations; i++) { + int madeSwap = 0; + for (int j = 1; j < numRelocations; j++) { + rpmRelocation tmpReloc; + if (relocations[j - 1].oldPath == NULL || /* XXX can't happen */ + relocations[j ].oldPath == NULL || /* XXX can't happen */ + strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0) + continue; + tmpReloc = relocations[j - 1]; + relocations[j - 1] = relocations[j]; + relocations[j] = tmpReloc; + madeSwap = 1; + } + if (!madeSwap) break; + } +} + +static char * stripTrailingChar(char * s, char c) +{ + char * t; + for (t = s + strlen(s) - 1; *t == c && t >= s; t--) + *t = '\0'; + return s; +} + +static void buildRelocs(rpmte p, Header h, rpmRelocation *relocs) +{ + int i; + struct rpmtd_s validRelocs; + + for (rpmRelocation *r = relocs; r->oldPath || r->newPath; r++) + p->nrelocs++; + + headerGet(h, RPMTAG_PREFIXES, &validRelocs, HEADERGET_MINMEM); + p->relocs = xmalloc(sizeof(*p->relocs) * (p->nrelocs+1)); + + /* Build sorted relocation list from raw relocations. */ + for (i = 0; i < p->nrelocs; i++) { + char * t; + + /* + * Default relocations (oldPath == NULL) are handled in the UI, + * not rpmlib. + */ + if (relocs[i].oldPath == NULL) continue; /* XXX can't happen */ + + /* FIXME: Trailing /'s will confuse us greatly. Internal ones will + too, but those are more trouble to fix up. :-( */ + t = xstrdup(relocs[i].oldPath); + p->relocs[i].oldPath = (t[0] == '/' && t[1] == '\0') + ? t + : stripTrailingChar(t, '/'); + + /* An old path w/o a new path is valid, and indicates exclusion */ + if (relocs[i].newPath) { + int valid = 0; + const char *validprefix; + + t = xstrdup(relocs[i].newPath); + p->relocs[i].newPath = (t[0] == '/' && t[1] == '\0') + ? t + : stripTrailingChar(t, '/'); + + /* FIX: relocations[i].oldPath == NULL */ + /* Verify that the relocation's old path is in the header. */ + rpmtdInit(&validRelocs); + while ((validprefix = rpmtdNextString(&validRelocs))) { + if (rstreq(validprefix, p->relocs[i].oldPath)) { + valid = 1; + break; + } + } + + if (!valid) { + rpmteAddProblem(p, RPMPROB_BADRELOCATE, NULL, + p->relocs[i].oldPath, 0); + } + } else { + p->relocs[i].newPath = NULL; + } + } + p->relocs[i].oldPath = NULL; + p->relocs[i].newPath = NULL; + sortRelocs(p->relocs, p->nrelocs); + + rpmtdFreeData(&validRelocs); +} + +/** + * Initialize transaction element data from header. + * @param p transaction element + * @param h header + * @param key (TR_ADDED) package retrieval key (e.g. file name) + * @param relocs (TR_ADDED) package file relocations + */ +static void addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs) +{ + struct rpmtd_s colls; + + p->name = headerGetAsString(h, RPMTAG_NAME); + p->version = headerGetAsString(h, RPMTAG_VERSION); + p->release = headerGetAsString(h, RPMTAG_RELEASE); + + p->epoch = headerGetAsString(h, RPMTAG_EPOCH); + + p->arch = headerGetAsString(h, RPMTAG_ARCH); + p->os = headerGetAsString(h, RPMTAG_OS); + + p->isSource = headerIsSource(h); + + p->NEVR = headerGetAsString(h, RPMTAG_NEVR); + p->NEVRA = headerGetAsString(h, RPMTAG_NEVRA); + + p->nrelocs = 0; + p->relocs = NULL; + if (relocs != NULL) + buildRelocs(p, h, relocs); + + p->db_instance = headerGetInstance(h); + p->key = key; + p->fd = NULL; + + p->pkgFileSize = 0; + p->headerSize = headerSizeof(h, HEADER_MAGIC_NO); + + p->thisds = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL); + p->provides = rpmdsNew(h, RPMTAG_PROVIDENAME, 0); + p->requires = rpmdsNew(h, RPMTAG_REQUIRENAME, 0); + p->conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, 0); + p->obsoletes = rpmdsNew(h, RPMTAG_OBSOLETENAME, 0); + p->order = rpmdsNew(h, RPMTAG_ORDERNAME, 0); + + p->fs = rpmfsNew(h, p->type); + p->fi = getFI(p, h); + + /* See if we have pre/posttrans scripts. */ + p->transscripts |= (headerIsEntry(h, RPMTAG_PRETRANS) && + headerIsEntry(h, RPMTAG_PRETRANSPROG)) ? + RPMTE_HAVE_PRETRANS : 0; + p->transscripts |= (headerIsEntry(h, RPMTAG_POSTTRANS) && + headerIsEntry(h, RPMTAG_POSTTRANSPROG)) ? + RPMTE_HAVE_POSTTRANS : 0; + + p->lastInCollectionsAny = NULL; + p->lastInCollectionsAdd = NULL; + p->firstInCollectionsRemove = NULL; + p->collections = NULL; + if (headerGet(h, RPMTAG_COLLECTIONS, &colls, HEADERGET_MINMEM)) { + const char *collname; + while ((collname = rpmtdNextString(&colls))) { + argvAdd(&p->collections, collname); + } + argvSort(p->collections, NULL); + rpmtdFreeData(&colls); + } + + rpmteColorDS(p, RPMTAG_PROVIDENAME); + rpmteColorDS(p, RPMTAG_REQUIRENAME); + return; +} + +rpmte rpmteFree(rpmte te) +{ + if (te != NULL) { + if (te->relocs) { + for (int i = 0; i < te->nrelocs; i++) { + free(te->relocs[i].oldPath); + free(te->relocs[i].newPath); + } + free(te->relocs); + } + + free(te->os); + free(te->arch); + free(te->epoch); + free(te->name); + free(te->version); + free(te->release); + free(te->NEVR); + free(te->NEVRA); + + fdFree(te->fd); + rpmfiFree(te->fi); + headerFree(te->h); + rpmfsFree(te->fs); + rpmpsFree(te->probs); + rpmteCleanDS(te); + + argvFree(te->collections); + argvFree(te->lastInCollectionsAny); + argvFree(te->lastInCollectionsAdd); + argvFree(te->firstInCollectionsRemove); + + memset(te, 0, sizeof(*te)); /* XXX trash and burn */ + free(te); + } + return NULL; +} + +rpmte rpmteNew(rpmts ts, Header h, rpmElementType type, fnpyKey key, + rpmRelocation * relocs) +{ + rpmte p = xcalloc(1, sizeof(*p)); + p->ts = ts; + p->type = type; + addTE(p, h, key, relocs); + switch (type) { + case TR_ADDED: + p->pkgFileSize = headerGetNumber(h, RPMTAG_LONGSIGSIZE) + 96 + 256; + break; + case TR_REMOVED: + /* nothing to do */ + break; + } + + return p; +} + +unsigned int rpmteDBInstance(rpmte te) +{ + return (te != NULL ? te->db_instance : 0); +} + +void rpmteSetDBInstance(rpmte te, unsigned int instance) +{ + if (te != NULL) + te->db_instance = instance; +} + +Header rpmteHeader(rpmte te) +{ + return (te != NULL && te->h != NULL ? headerLink(te->h) : NULL); +} + +Header rpmteSetHeader(rpmte te, Header h) +{ + if (te != NULL) { + te->h = headerFree(te->h); + if (h != NULL) + te->h = headerLink(h); + } + return NULL; +} + +rpmElementType rpmteType(rpmte te) +{ + /* XXX returning negative for unsigned type */ + return (te != NULL ? te->type : -1); +} + +const char * rpmteN(rpmte te) +{ + return (te != NULL ? te->name : NULL); +} + +const char * rpmteE(rpmte te) +{ + return (te != NULL ? te->epoch : NULL); +} + +const char * rpmteV(rpmte te) +{ + return (te != NULL ? te->version : NULL); +} + +const char * rpmteR(rpmte te) +{ + return (te != NULL ? te->release : NULL); +} + +const char * rpmteA(rpmte te) +{ + return (te != NULL ? te->arch : NULL); +} + +const char * rpmteO(rpmte te) +{ + return (te != NULL ? te->os : NULL); +} + +int rpmteIsSource(rpmte te) +{ + return (te != NULL ? te->isSource : 0); +} + +rpm_color_t rpmteColor(rpmte te) +{ + return (te != NULL ? te->color : 0); +} + +rpm_color_t rpmteSetColor(rpmte te, rpm_color_t color) +{ + rpm_color_t ocolor = 0; + if (te != NULL) { + ocolor = te->color; + te->color = color; + } + return ocolor; +} + +ARGV_const_t rpmteCollections(rpmte te) +{ + return (te != NULL) ? te->collections : NULL; +} + +int rpmteHasCollection(rpmte te, const char *collname) +{ + return (argvSearch(rpmteCollections(te), collname, NULL) != NULL); +} + +int rpmteAddToLastInCollectionAdd(rpmte te, const char *collname) +{ + if (te != NULL) { + argvAdd(&te->lastInCollectionsAdd, collname); + argvSort(te->lastInCollectionsAdd, NULL); + return 0; + } + return -1; +} + +int rpmteAddToLastInCollectionAny(rpmte te, const char *collname) +{ + if (te != NULL) { + argvAdd(&te->lastInCollectionsAny, collname); + argvSort(te->lastInCollectionsAny, NULL); + return 0; + } + return -1; +} + +int rpmteAddToFirstInCollectionRemove(rpmte te, const char *collname) +{ + if (te != NULL) { + argvAdd(&te->firstInCollectionsRemove, collname); + argvSort(te->firstInCollectionsRemove, NULL); + return 0; + } + return -1; +} + +rpm_loff_t rpmtePkgFileSize(rpmte te) +{ + return (te != NULL ? te->pkgFileSize : 0); +} + +unsigned int rpmteHeaderSize(rpmte te) { + return (te != NULL ? te->headerSize : 0); +} + +rpmte rpmteParent(rpmte te) +{ + return (te != NULL ? te->parent : NULL); +} + +rpmte rpmteSetParent(rpmte te, rpmte pte) +{ + rpmte opte = NULL; + if (te != NULL) { + opte = te->parent; + te->parent = pte; + } + return opte; +} + +tsortInfo rpmteTSI(rpmte te) +{ + return te->tsi; +} + +void rpmteSetTSI(rpmte te, tsortInfo tsi) +{ + te->tsi = tsi; +} + +void rpmteSetDependsOn(rpmte te, rpmte depends) { + te->depends = depends; +} + +rpmte rpmteDependsOn(rpmte te) +{ + return te->depends; +} + +int rpmteDBOffset(rpmte te) +{ + return rpmteDBInstance(te); +} + +const char * rpmteEVR(rpmte te) +{ + return (te != NULL ? te->NEVR + strlen(te->name) + 1 : NULL); +} + +const char * rpmteNEVR(rpmte te) +{ + return (te != NULL ? te->NEVR : NULL); +} + +const char * rpmteNEVRA(rpmte te) +{ + return (te != NULL ? te->NEVRA : NULL); +} + +FD_t rpmteSetFd(rpmte te, FD_t fd) +{ + if (te != NULL) { + if (te->fd != NULL) + te->fd = fdFree(te->fd); + if (fd != NULL) + te->fd = fdLink(fd); + } + return NULL; +} + +fnpyKey rpmteKey(rpmte te) +{ + return (te != NULL ? te->key : NULL); +} + +rpmds rpmteDS(rpmte te, rpmTagVal tag) +{ + if (te == NULL) + return NULL; + + switch (tag) { + case RPMTAG_NAME: return te->thisds; + case RPMTAG_PROVIDENAME: return te->provides; + case RPMTAG_REQUIRENAME: return te->requires; + case RPMTAG_CONFLICTNAME: return te->conflicts; + case RPMTAG_OBSOLETENAME: return te->obsoletes; + case RPMTAG_ORDERNAME: return te->order; + default: break; + } + return NULL; +} + +rpmfi rpmteSetFI(rpmte te, rpmfi fi) +{ + if (te != NULL) { + te->fi = rpmfiFree(te->fi); + if (fi != NULL) + te->fi = rpmfiLink(fi); + } + return NULL; +} + +rpmfi rpmteFI(rpmte te) +{ + if (te == NULL) + return NULL; + + return te->fi; /* XXX take fi reference here? */ +} + +static void rpmteColorDS(rpmte te, rpmTag tag) +{ + rpmfi fi = rpmteFI(te); + rpmds ds = rpmteDS(te, tag); + char deptype = 'R'; + char mydt; + const uint32_t * ddict; + rpm_color_t * colors; + rpm_color_t val; + int Count; + unsigned ix; + int ndx, i; + + if (!(te && (Count = rpmdsCount(ds)) > 0 && rpmfiFC(fi) > 0)) + return; + + switch (tag) { + default: + return; + break; + case RPMTAG_PROVIDENAME: + deptype = 'P'; + break; + case RPMTAG_REQUIRENAME: + deptype = 'R'; + break; + } + + colors = xcalloc(Count, sizeof(*colors)); + + /* Calculate dependency color. */ + fi = rpmfiInit(fi, 0); + if (fi != NULL) + while (rpmfiNext(fi) >= 0) { + val = rpmfiFColor(fi); + ddict = NULL; + ndx = rpmfiFDepends(fi, &ddict); + if (ddict != NULL) + while (ndx-- > 0) { + ix = *ddict++; + mydt = ((ix >> 24) & 0xff); + if (mydt != deptype) + continue; + ix &= 0x00ffffff; +assert (ix < Count); + colors[ix] |= val; + } + } + + /* Set color values in dependency set. */ + ds = rpmdsInit(ds); + while ((i = rpmdsNext(ds)) >= 0) { + val = colors[i]; + te->color |= val; + (void) rpmdsSetColor(ds, val); + } + free(colors); +} + +static Header rpmteDBHeader(rpmte te) +{ + Header h = NULL; + rpmdbMatchIterator mi; + + mi = rpmtsInitIterator(te->ts, RPMDBI_PACKAGES, + &te->db_instance, sizeof(te->db_instance)); + /* iterator returns weak refs, grab hold of header */ + if ((h = rpmdbNextIterator(mi))) + h = headerLink(h); + mi = rpmdbFreeIterator(mi); + return h; +} + +static Header rpmteFDHeader(rpmte te) +{ + Header h = NULL; + te->fd = rpmtsNotify(te->ts, te, RPMCALLBACK_INST_OPEN_FILE, 0, 0); + if (te->fd != NULL) { + rpmVSFlags ovsflags; + rpmRC pkgrc; + + ovsflags = rpmtsSetVSFlags(te->ts, + rpmtsVSFlags(te->ts) | RPMVSF_NEEDPAYLOAD); + pkgrc = rpmReadPackageFile(te->ts, te->fd, rpmteNEVRA(te), &h); + rpmtsSetVSFlags(te->ts, ovsflags); + switch (pkgrc) { + default: + rpmteClose(te, 1); + break; + case RPMRC_NOTTRUSTED: + case RPMRC_NOKEY: + case RPMRC_OK: + break; + } + } + return h; +} + +static int rpmteOpen(rpmte te, int reload_fi) +{ + Header h = NULL; + if (te == NULL || te->ts == NULL || rpmteFailed(te)) + goto exit; + + rpmteSetHeader(te, NULL); + + switch (rpmteType(te)) { + case TR_ADDED: + h = rpmteDBInstance(te) ? rpmteDBHeader(te) : rpmteFDHeader(te); + break; + case TR_REMOVED: + h = rpmteDBHeader(te); + break; + } + if (h != NULL) { + if (reload_fi) { + te->fi = getFI(te, h); + } + + rpmteSetHeader(te, h); + headerFree(h); + } + +exit: + return (h != NULL); +} + +static int rpmteClose(rpmte te, int reset_fi) +{ + if (te == NULL || te->ts == NULL) + return 0; + + switch (te->type) { + case TR_ADDED: + if (te->fd) { + rpmtsNotify(te->ts, te, RPMCALLBACK_INST_CLOSE_FILE, 0, 0); + te->fd = NULL; + } + break; + case TR_REMOVED: + /* eventually we'll want notifications for erase open too */ + break; + } + rpmteSetHeader(te, NULL); + if (reset_fi) { + rpmteSetFI(te, NULL); + } + return 1; +} + +FD_t rpmtePayload(rpmte te) +{ + FD_t payload = NULL; + if (te->fd && te->h) { + const char *compr = headerGetString(te->h, RPMTAG_PAYLOADCOMPRESSOR); + char *ioflags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL); + payload = Fdopen(fdDup(Fileno(te->fd)), ioflags); + free(ioflags); + } + return payload; +} + +static int rpmteMarkFailed(rpmte te) +{ + rpmtsi pi = rpmtsiInit(te->ts); + rpmte p; + + te->failed++; + /* XXX we can do a much better here than this... */ + while ((p = rpmtsiNext(pi, TR_REMOVED))) { + if (rpmteDependsOn(p) == te) { + p->failed++; + } + } + rpmtsiFree(pi); + return te->failed; +} + +int rpmteFailed(rpmte te) +{ + return (te != NULL) ? te->failed : -1; +} + +static int rpmteHaveTransScript(rpmte te, rpmTagVal tag) +{ + int rc = 0; + if (tag == RPMTAG_PRETRANS) { + rc = (te->transscripts & RPMTE_HAVE_PRETRANS); + } else if (tag == RPMTAG_POSTTRANS) { + rc = (te->transscripts & RPMTE_HAVE_POSTTRANS); + } + return rc; +} + +rpmps rpmteProblems(rpmte te) +{ + return (te != NULL) ? rpmpsLink(te->probs) : NULL; +} + +void rpmteCleanProblems(rpmte te) +{ + if (te != NULL && te->probs != NULL) { + te->probs = rpmpsFree(te->probs); + } +} + +static void appendProblem(rpmte te, rpmProblemType type, + fnpyKey key, const char * altNEVR, + const char * str, uint64_t number) +{ + rpmProblem o; + rpmProblem p = rpmProblemCreate(type, te->NEVRA, key, altNEVR, str, number); + rpmpsi psi = rpmpsInitIterator(te->probs); + + /* Only add new, unique problems to the set */ + while ((o = rpmpsiNext(psi))) { + if (rpmProblemCompare(p, o) == 0) + break; + } + rpmpsFreeIterator(psi); + + if (o == NULL) { + if (te->probs == NULL) + te->probs = rpmpsCreate(); + rpmpsAppendProblem(te->probs, p); + } + rpmProblemFree(p); +} + +void rpmteAddProblem(rpmte te, rpmProblemType type, + const char *altNEVR, const char *str, uint64_t number) +{ + if (te != NULL) { + appendProblem(te, type, rpmteKey(te), altNEVR, str, number); + } +} + +void rpmteAddDepProblem(rpmte te, const char * altNEVR, rpmds ds, + fnpyKey * suggestedKeys) +{ + if (te != NULL) { + const char * DNEVR = rpmdsDNEVR(ds); + rpmProblemType type; + fnpyKey key = (suggestedKeys ? suggestedKeys[0] : NULL); + + switch ((unsigned)DNEVR[0]) { + case 'O': type = RPMPROB_OBSOLETES; break; + case 'C': type = RPMPROB_CONFLICT; break; + default: + case 'R': type = RPMPROB_REQUIRES; break; + } + + appendProblem(te, type, key, altNEVR, DNEVR+2, rpmdsInstance(ds)); + } +} + +const char * rpmteTypeString(rpmte te) +{ + switch(rpmteType(te)) { + case TR_ADDED: return _("install"); + case TR_REMOVED: return _("erase"); + default: return "???"; + } +} + +rpmfs rpmteGetFileStates(rpmte te) { + return te->fs; +} + +rpmRC rpmteSetupCollectionPlugins(rpmte te) +{ + ARGV_const_t colls = rpmteCollections(te); + rpmPlugins plugins = rpmtsPlugins(te->ts); + rpmRC rc = RPMRC_OK; + + if (!colls) { + return rc; + } + + rpmteOpen(te, 0); + for (; colls && *colls; colls++) { + if (!rpmpluginsPluginAdded(plugins, *colls)) { + rc = rpmpluginsAddCollectionPlugin(plugins, *colls); + if (rc != RPMRC_OK) { + break; + } + } + rc = rpmpluginsCallOpenTE(plugins, *colls, te); + if (rc != RPMRC_OK) { + break; + } + } + rpmteClose(te, 0); + + return rc; +} + +static rpmRC rpmteRunAllCollections(rpmte te, rpmPluginHook hook) +{ + ARGV_const_t colls; + rpmRC(*collHook) (rpmPlugins, const char *); + rpmRC rc = RPMRC_OK; + + if (rpmtsFlags(te->ts) & RPMTRANS_FLAG_NOCOLLECTIONS) { + goto exit; + } + + switch (hook) { + case PLUGINHOOK_COLL_POST_ADD: + colls = te->lastInCollectionsAdd; + collHook = rpmpluginsCallCollectionPostAdd; + break; + case PLUGINHOOK_COLL_POST_ANY: + colls = te->lastInCollectionsAny; + collHook = rpmpluginsCallCollectionPostAny; + break; + case PLUGINHOOK_COLL_PRE_REMOVE: + colls = te->firstInCollectionsRemove; + collHook = rpmpluginsCallCollectionPreRemove; + break; + default: + goto exit; + } + + for (; colls && *colls; colls++) { + rc = collHook(rpmtsPlugins(te->ts), *colls); + } + + exit: + return rc; +} + +int rpmteProcess(rpmte te, pkgGoal goal) +{ + /* Only install/erase resets pkg file info */ + int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE); + int reset_fi = (scriptstage == 0); + int failed = 1; + + /* Dont bother opening for elements without pre/posttrans scripts */ + if (goal == PKG_PRETRANS || goal == PKG_POSTTRANS) { + if (!rpmteHaveTransScript(te, goal)) { + return 0; + } + } + + if (!scriptstage) { + rpmteRunAllCollections(te, PLUGINHOOK_COLL_PRE_REMOVE); + } + + if (rpmteOpen(te, reset_fi)) { + failed = rpmpsmRun(te->ts, te, goal); + rpmteClose(te, reset_fi); + } + + if (!scriptstage) { + rpmteRunAllCollections(te, PLUGINHOOK_COLL_POST_ADD); + rpmteRunAllCollections(te, PLUGINHOOK_COLL_POST_ANY); + } + + /* XXX should %pretrans failure fail the package install? */ + if (failed && !scriptstage) { + failed = rpmteMarkFailed(te); + } + + return failed; +} |