csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
2ff057
/** \ingroup rpmdep
2ff057
 * \file lib/rpmte.c
2ff057
 * Routine(s) to handle an "rpmte"  transaction element.
2ff057
 */
2ff057
#include "system.h"
2ff057
2ff057
#include <rpm/rpmtypes.h>
2ff057
#include <rpm/rpmlib.h>		/* RPM_MACHTABLE_* */
2ff057
#include <rpm/rpmmacro.h>
2ff057
#include <rpm/rpmds.h>
2ff057
#include <rpm/rpmfi.h>
2ff057
#include <rpm/rpmts.h>
2ff057
#include <rpm/rpmdb.h>
2ff057
#include <rpm/rpmlog.h>
2ff057
2ff057
#include "lib/misc.h"
2ff057
#include "lib/rpmplugins.h"
2ff057
#include "lib/rpmte_internal.h"
2ff057
/* strpool-related interfaces */
2ff057
#include "lib/rpmfi_internal.h"
2ff057
#include "lib/rpmds_internal.h"
2ff057
#include "lib/rpmts_internal.h"
2ff057
2ff057
#include "debug.h"
2ff057
2ff057
/** \ingroup rpmte
2ff057
 * A single package instance to be installed/removed atomically.
2ff057
 */
2ff057
struct rpmte_s {
2ff057
    rpmElementType type;	/*!< Package disposition (installed/removed). */
2ff057
2ff057
    Header h;			/*!< Package header. */
2ff057
    char * NEVR;		/*!< Package name-version-release. */
2ff057
    char * NEVRA;		/*!< Package name-version-release.arch. */
2ff057
    char * name;		/*!< Name: */
2ff057
    char * epoch;
2ff057
    char * version;		/*!< Version: */
2ff057
    char * release;		/*!< Release: */
2ff057
    char * arch;		/*!< Architecture hint. */
2ff057
    char * os;			/*!< Operating system hint. */
2ff057
    int isSource;		/*!< (TR_ADDED) source rpm? */
2ff057
2ff057
    rpmte depends;              /*!< Package updated by this package (ERASE te) */
2ff057
    rpmte parent;		/*!< Parent transaction element. */
2ff057
    unsigned int db_instance;	/*!< Database instance (of removed pkgs) */
2ff057
    tsortInfo tsi;		/*!< Dependency ordering chains. */
2ff057
2ff057
    rpmds thisds;		/*!< This package's provided NEVR. */
2ff057
    rpmds provides;		/*!< Provides: dependencies. */
2ff057
    rpmds requires;		/*!< Requires: dependencies. */
2ff057
    rpmds conflicts;		/*!< Conflicts: dependencies. */
2ff057
    rpmds obsoletes;		/*!< Obsoletes: dependencies. */
2ff057
    rpmds order;		/*!< Order: dependencies. */
2ff057
    rpmds recommends;		/*!< Recommends: dependencies. */
2ff057
    rpmds suggests;		/*!< Suggests: dependencies. */
2ff057
    rpmds supplements;		/*!< Supplements: dependencies. */
2ff057
    rpmds enhances;		/*!< Enhances: dependencies. */
2ff057
    rpmfiles files;		/*!< File information. */
2ff057
    rpmfi fi;			/*!< File iterator (backwards compat) */
2ff057
    rpmps probs;		/*!< Problems (relocations) */
2ff057
    rpmts ts;			/*!< Parent transaction */
2ff057
2ff057
    rpm_color_t color;		/*!< Color bit(s) from package dependencies. */
2ff057
    rpm_loff_t pkgFileSize;	/*!< No. of bytes in package file (approx). */
2ff057
    unsigned int headerSize;	/*!< No. of bytes in package header */
2ff057
2ff057
    fnpyKey key;		/*!< (TR_ADDED) Retrieval key. */
2ff057
    rpmRelocation * relocs;	/*!< (TR_ADDED) Payload file relocations. */
2ff057
    int nrelocs;		/*!< (TR_ADDED) No. of relocations. */
2ff057
    uint8_t *badrelocs;		/*!< (TR_ADDED) Bad relocations (or NULL) */
2ff057
    FD_t fd;			/*!< (TR_ADDED) Payload file descriptor. */
Panu Matilainen d6b3d4
    int verified;		/*!< (TR_ADDED) Verification status */
2ff057
2ff057
#define RPMTE_HAVE_PRETRANS	(1 << 0)
2ff057
#define RPMTE_HAVE_POSTTRANS	(1 << 1)
2ff057
    int transscripts;		/*!< pre/posttrans script existence */
2ff057
    int failed;			/*!< (parent) install/erase failed */
2ff057
2ff057
    rpmfs fs;
2ff057
};
2ff057
2ff057
/* forward declarations */
2ff057
static void rpmteColorDS(rpmte te, rpmTag tag);
2ff057
static int rpmteClose(rpmte te, int reset_fi);
2ff057
2ff057
void rpmteCleanDS(rpmte te)
2ff057
{
2ff057
    te->thisds = rpmdsFree(te->thisds);
2ff057
    te->provides = rpmdsFree(te->provides);
2ff057
    te->requires = rpmdsFree(te->requires);
2ff057
    te->conflicts = rpmdsFree(te->conflicts);
2ff057
    te->obsoletes = rpmdsFree(te->obsoletes);
2ff057
    te->recommends = rpmdsFree(te->recommends);
2ff057
    te->suggests = rpmdsFree(te->suggests);
2ff057
    te->supplements = rpmdsFree(te->supplements);
2ff057
    te->enhances = rpmdsFree(te->enhances);
2ff057
    te->order = rpmdsFree(te->order);
2ff057
}
2ff057
2ff057
static rpmfiles getFiles(rpmte p, Header h)
2ff057
{
2ff057
    rpmfiFlags fiflags;
2ff057
    fiflags = (p->type == TR_ADDED) ? (RPMFI_NOHEADER | RPMFI_FLAGS_INSTALL) :
2ff057
				      (RPMFI_NOHEADER | RPMFI_FLAGS_ERASE);
2ff057
2ff057
    /* relocate stuff in header if necessary */
2ff057
    if (rpmteType(p) == TR_ADDED && rpmfsFC(p->fs) > 0) {
2ff057
	if (!headerIsEntry(h, RPMTAG_ORIGBASENAMES)) {
2ff057
	    if (rpmteIsSource(p)) {
2ff057
		/* Unlike binary packages, source relocation can fail */
2ff057
		if (rpmRelocateSrpmFileList(h, rpmtsRootDir(p->ts)) < 0) {
2ff057
		    return NULL;
2ff057
		}
2ff057
	    } else {
2ff057
		rpmRelocateFileList(p->relocs, p->nrelocs, p->fs, h);
2ff057
	    }
2ff057
	}
2ff057
    }
2ff057
    return rpmfilesNew(rpmtsPool(p->ts), h, RPMTAG_BASENAMES, fiflags);
2ff057
}
2ff057
2ff057
/**
2ff057
 * Initialize transaction element data from header.
2ff057
 * @param p		transaction element
2ff057
 * @param h		header
2ff057
 * @param key		(TR_ADDED) package retrieval key (e.g. file name)
2ff057
 * @param relocs	(TR_ADDED) package file relocations
2ff057
 */
2ff057
static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs)
2ff057
{
2ff057
    rpmstrPool tspool = rpmtsPool(p->ts);
2ff057
    struct rpmtd_s bnames;
2ff057
    int rc = 1; /* assume failure */
2ff057
2ff057
    p->name = headerGetAsString(h, RPMTAG_NAME);
2ff057
    p->version = headerGetAsString(h, RPMTAG_VERSION);
2ff057
    p->release = headerGetAsString(h, RPMTAG_RELEASE);
2ff057
2ff057
    /* name, version and release are required in all packages */
2ff057
    if (p->name == NULL || p->version == NULL || p->release == NULL)
2ff057
	goto exit;
2ff057
2ff057
    p->epoch = headerGetAsString(h, RPMTAG_EPOCH);
2ff057
2ff057
    p->arch = headerGetAsString(h, RPMTAG_ARCH);
2ff057
    p->os = headerGetAsString(h, RPMTAG_OS);
2ff057
2ff057
    /* gpg-pubkey's dont have os or arch (sigh), for others they are required */
2ff057
    if (!rstreq(p->name, "gpg-pubkey") && (p->arch == NULL || p->os == NULL))
2ff057
	goto exit;
2ff057
2ff057
    p->isSource = headerIsSource(h);
2ff057
    
2ff057
    p->NEVR = headerGetAsString(h, RPMTAG_NEVR);
2ff057
    p->NEVRA = headerGetAsString(h, RPMTAG_NEVRA);
2ff057
2ff057
    p->nrelocs = 0;
2ff057
    p->relocs = NULL;
2ff057
    p->badrelocs = NULL;
2ff057
    if (relocs != NULL)
2ff057
	rpmRelocationBuild(h, relocs, &p->nrelocs, &p->relocs, &p->badrelocs);
2ff057
2ff057
    p->db_instance = headerGetInstance(h);
2ff057
    p->key = key;
2ff057
    p->fd = NULL;
2ff057
2ff057
    p->pkgFileSize = 0;
2ff057
    p->headerSize = headerSizeof(h, HEADER_MAGIC_NO);
2ff057
2ff057
    p->thisds = rpmdsThisPool(tspool, h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
2ff057
    p->provides = rpmdsNewPool(tspool, h, RPMTAG_PROVIDENAME, 0);
2ff057
    p->requires = rpmdsNewPool(tspool, h, RPMTAG_REQUIRENAME, 0);
2ff057
    p->conflicts = rpmdsNewPool(tspool, h, RPMTAG_CONFLICTNAME, 0);
2ff057
    p->obsoletes = rpmdsNewPool(tspool, h, RPMTAG_OBSOLETENAME, 0);
2ff057
    p->order = rpmdsNewPool(tspool, h, RPMTAG_ORDERNAME, 0);
2ff057
    p->recommends = rpmdsNewPool(tspool, h, RPMTAG_RECOMMENDNAME, 0);
2ff057
    p->suggests = rpmdsNewPool(tspool, h, RPMTAG_SUGGESTNAME, 0);
2ff057
    p->supplements = rpmdsNewPool(tspool, h, RPMTAG_SUPPLEMENTNAME, 0);
2ff057
    p->enhances = rpmdsNewPool(tspool, h, RPMTAG_ENHANCENAME, 0);
2ff057
2ff057
    /* Relocation needs to know file count before rpmfiNew() */
2ff057
    headerGet(h, RPMTAG_BASENAMES, &bnames, HEADERGET_MINMEM);
2ff057
    p->fs = rpmfsNew(rpmtdCount(&bnames), (p->type == TR_ADDED));
2ff057
    rpmtdFreeData(&bnames);
2ff057
2ff057
    p->files = getFiles(p, h);
2ff057
2ff057
    /* Packages with no files return an empty file info set, NULL is an error */
2ff057
    if (p->files == NULL)
2ff057
	goto exit;
2ff057
2ff057
    /* See if we have pre/posttrans scripts. */
2ff057
    p->transscripts |= (headerIsEntry(h, RPMTAG_PRETRANS) ||
2ff057
			 headerIsEntry(h, RPMTAG_PRETRANSPROG)) ?
2ff057
			RPMTE_HAVE_PRETRANS : 0;
2ff057
    p->transscripts |= (headerIsEntry(h, RPMTAG_POSTTRANS) ||
2ff057
			 headerIsEntry(h, RPMTAG_POSTTRANSPROG)) ?
2ff057
			RPMTE_HAVE_POSTTRANS : 0;
2ff057
2ff057
    rpmteColorDS(p, RPMTAG_PROVIDENAME);
2ff057
    rpmteColorDS(p, RPMTAG_REQUIRENAME);
2ff057
2ff057
    if (p->type == TR_ADDED)
2ff057
	p->pkgFileSize = headerGetNumber(h, RPMTAG_LONGSIGSIZE) + 96 + 256;
2ff057
2ff057
    rc = 0;
2ff057
2ff057
exit:
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmte rpmteFree(rpmte te)
2ff057
{
2ff057
    if (te != NULL) {
2ff057
	if (te->relocs) {
2ff057
	    for (int i = 0; i < te->nrelocs; i++) {
2ff057
		free(te->relocs[i].oldPath);
2ff057
		free(te->relocs[i].newPath);
2ff057
	    }
2ff057
	    free(te->relocs);
2ff057
	    free(te->badrelocs);
2ff057
	}
2ff057
2ff057
	free(te->os);
2ff057
	free(te->arch);
2ff057
	free(te->epoch);
2ff057
	free(te->name);
2ff057
	free(te->version);
2ff057
	free(te->release);
2ff057
	free(te->NEVR);
2ff057
	free(te->NEVRA);
2ff057
2ff057
	fdFree(te->fd);
2ff057
	rpmfiFree(te->fi);
2ff057
	rpmfilesFree(te->files);
2ff057
	headerFree(te->h);
2ff057
	rpmfsFree(te->fs);
2ff057
	rpmpsFree(te->probs);
2ff057
	rpmteCleanDS(te);
2ff057
2ff057
	memset(te, 0, sizeof(*te));	/* XXX trash and burn */
2ff057
	free(te);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
rpmte rpmteNew(rpmts ts, Header h, rpmElementType type, fnpyKey key,
2ff057
	       rpmRelocation * relocs)
2ff057
{
2ff057
    rpmte p = xcalloc(1, sizeof(*p));
2ff057
    p->ts = ts;
2ff057
    p->type = type;
2ff057
2ff057
    if (addTE(p, h, key, relocs)) {
2ff057
	rpmteFree(p);
2ff057
	return NULL;
2ff057
    }
2ff057
2ff057
    return p;
2ff057
}
2ff057
2ff057
unsigned int rpmteDBInstance(rpmte te) 
2ff057
{
2ff057
    return (te != NULL ? te->db_instance : 0);
2ff057
}
2ff057
2ff057
void rpmteSetDBInstance(rpmte te, unsigned int instance) 
2ff057
{
2ff057
    if (te != NULL) 
2ff057
	te->db_instance = instance;
2ff057
}
2ff057
2ff057
Header rpmteHeader(rpmte te)
2ff057
{
2ff057
    return (te != NULL && te->h != NULL ? headerLink(te->h) : NULL);
2ff057
}
2ff057
2ff057
Header rpmteSetHeader(rpmte te, Header h)
2ff057
{
2ff057
    if (te != NULL)  {
2ff057
	te->h = headerFree(te->h);
2ff057
	if (h != NULL)
2ff057
	    te->h = headerLink(h);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
rpmElementType rpmteType(rpmte te)
2ff057
{
2ff057
    /* XXX returning negative for unsigned type */
2ff057
    return (te != NULL ? te->type : -1);
2ff057
}
2ff057
2ff057
const char * rpmteN(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->name : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteE(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->epoch : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteV(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->version : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteR(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->release : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteA(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->arch : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteO(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->os : NULL);
2ff057
}
2ff057
2ff057
int rpmteIsSource(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->isSource : 0);
2ff057
}
2ff057
2ff057
rpm_color_t rpmteColor(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->color : 0);
2ff057
}
2ff057
2ff057
rpm_color_t rpmteSetColor(rpmte te, rpm_color_t color)
2ff057
{
2ff057
    rpm_color_t ocolor = 0;
2ff057
    if (te != NULL) {
2ff057
	ocolor = te->color;
2ff057
	te->color = color;
2ff057
    }
2ff057
    return ocolor;
2ff057
}
2ff057
2ff057
rpm_loff_t rpmtePkgFileSize(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->pkgFileSize : 0);
2ff057
}
2ff057
2ff057
unsigned int rpmteHeaderSize(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->headerSize : 0);
2ff057
}
2ff057
2ff057
rpmte rpmteParent(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->parent : NULL);
2ff057
}
2ff057
2ff057
rpmte rpmteSetParent(rpmte te, rpmte pte)
2ff057
{
2ff057
    rpmte opte = NULL;
2ff057
    if (te != NULL) {
2ff057
	opte = te->parent;
2ff057
	te->parent = pte;
2ff057
    }
2ff057
    return opte;
2ff057
}
2ff057
2ff057
tsortInfo rpmteTSI(rpmte te)
2ff057
{
2ff057
    return te->tsi;
2ff057
}
2ff057
2ff057
void rpmteSetTSI(rpmte te, tsortInfo tsi)
2ff057
{
2ff057
    te->tsi = tsi;
2ff057
}
2ff057
2ff057
void rpmteSetDependsOn(rpmte te, rpmte depends)
2ff057
{
2ff057
    te->depends = depends;
2ff057
}
2ff057
2ff057
rpmte rpmteDependsOn(rpmte te)
2ff057
{
2ff057
    return te->depends;
2ff057
}
2ff057
2ff057
int rpmteDBOffset(rpmte te)
2ff057
{
2ff057
    return rpmteDBInstance(te);
2ff057
}
2ff057
2ff057
const char * rpmteEVR(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->NEVR + strlen(te->name) + 1 : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteNEVR(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->NEVR : NULL);
2ff057
}
2ff057
2ff057
const char * rpmteNEVRA(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->NEVRA : NULL);
2ff057
}
2ff057
2ff057
FD_t rpmteSetFd(rpmte te, FD_t fd)
2ff057
{
2ff057
    if (te != NULL)  {
2ff057
	if (te->fd != NULL)
2ff057
	    te->fd = fdFree(te->fd);
2ff057
	if (fd != NULL)
2ff057
	    te->fd = fdLink(fd);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
fnpyKey rpmteKey(rpmte te)
2ff057
{
2ff057
    return (te != NULL ? te->key : NULL);
2ff057
}
2ff057
2ff057
rpmds rpmteDS(rpmte te, rpmTagVal tag)
2ff057
{
2ff057
    if (te == NULL)
2ff057
	return NULL;
2ff057
2ff057
    switch (tag) {
2ff057
    case RPMTAG_NAME:		return te->thisds;
2ff057
    case RPMTAG_PROVIDENAME:	return te->provides;
2ff057
    case RPMTAG_REQUIRENAME:	return te->requires;
2ff057
    case RPMTAG_CONFLICTNAME:	return te->conflicts;
2ff057
    case RPMTAG_OBSOLETENAME:	return te->obsoletes;
2ff057
    case RPMTAG_ORDERNAME:	return te->order;
2ff057
    case RPMTAG_RECOMMENDNAME:	return te->recommends;
2ff057
    case RPMTAG_SUGGESTNAME:	return te->suggests;
2ff057
    case RPMTAG_SUPPLEMENTNAME:	return te->supplements;
2ff057
    case RPMTAG_ENHANCENAME:	return te->enhances;
2ff057
    default:			break;
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
void rpmteCleanFiles(rpmte te)
2ff057
{
2ff057
    if (te != NULL)  {
2ff057
	te->fi = rpmfiFree(te->fi);
2ff057
	te->files = rpmfilesFree(te->files);
2ff057
    }
2ff057
}
2ff057
2ff057
rpmfi rpmteFI(rpmte te)
2ff057
{
2ff057
    if (te == NULL)
2ff057
	return NULL;
2ff057
2ff057
    if (te->fi == NULL)
2ff057
	te->fi = rpmfilesIter(te->files, RPMFI_ITER_FWD);
2ff057
2ff057
    return te->fi; /* XXX take fi reference here? */
2ff057
}
2ff057
2ff057
rpmfiles rpmteFiles(rpmte te)
2ff057
{
2ff057
    return (te != NULL) ? rpmfilesLink(te->files) : NULL;
2ff057
}
2ff057
2ff057
static void rpmteColorDS(rpmte te, rpmTag tag)
2ff057
{
2ff057
    rpmfi fi;
2ff057
    rpmds ds = rpmteDS(te, tag);
2ff057
    char deptype = 'R';
2ff057
    char mydt;
2ff057
    const uint32_t * ddict;
2ff057
    rpm_color_t * colors;
2ff057
    rpm_color_t val;
2ff057
    int Count;
2ff057
    unsigned ix;
2ff057
    int ndx, i;
2ff057
2ff057
    if (!(te && (Count = rpmdsCount(ds)) > 0 && rpmfilesFC(te->files) > 0))
2ff057
	return;
2ff057
2ff057
    switch (tag) {
2ff057
    default:
2ff057
	return;
2ff057
	break;
2ff057
    case RPMTAG_PROVIDENAME:
2ff057
	deptype = 'P';
2ff057
	break;
2ff057
    case RPMTAG_REQUIRENAME:
2ff057
	deptype = 'R';
2ff057
	break;
2ff057
    }
2ff057
2ff057
    colors = xcalloc(Count, sizeof(*colors));
2ff057
2ff057
    /* Calculate dependency color. */
2ff057
    fi = rpmfilesIter(te->files, RPMFI_ITER_FWD);
2ff057
    while (rpmfiNext(fi) >= 0) {
2ff057
	val = rpmfiFColor(fi);
2ff057
	ddict = NULL;
2ff057
	ndx = rpmfiFDepends(fi, &ddict);
2ff057
	if (ddict != NULL)
2ff057
	while (ndx-- > 0) {
2ff057
	    ix = *ddict++;
2ff057
	    mydt = ((ix >> 24) & 0xff);
2ff057
	    if (mydt != deptype)
2ff057
		continue;
2ff057
	    ix &= 0x00ffffff;
2ff057
assert (ix < Count);
2ff057
	    colors[ix] |= val;
2ff057
	}
2ff057
    }
2ff057
2ff057
    /* Set color values in dependency set. */
2ff057
    ds = rpmdsInit(ds);
2ff057
    while ((i = rpmdsNext(ds)) >= 0) {
2ff057
	val = colors[i];
2ff057
	te->color |= val;
2ff057
	(void) rpmdsSetColor(ds, val);
2ff057
    }
2ff057
    free(colors);
2ff057
    rpmfiFree(fi);
2ff057
}
2ff057
2ff057
static Header rpmteDBHeader(rpmte te)
2ff057
{
2ff057
    Header h = NULL;
2ff057
    rpmdbMatchIterator mi;
2ff057
2ff057
    mi = rpmtsInitIterator(te->ts, RPMDBI_PACKAGES,
2ff057
			   &te->db_instance, sizeof(te->db_instance));
2ff057
    /* iterator returns weak refs, grab hold of header */
2ff057
    if ((h = rpmdbNextIterator(mi)))
2ff057
	h = headerLink(h);
2ff057
    rpmdbFreeIterator(mi);
2ff057
    return h;
2ff057
}
2ff057
2ff057
static Header rpmteFDHeader(rpmte te)
2ff057
{
2ff057
    Header h = NULL;
2ff057
    te->fd = rpmtsNotify(te->ts, te, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
2ff057
    if (te->fd != NULL) {
2ff057
	rpmVSFlags ovsflags;
2ff057
	rpmRC pkgrc;
2ff057
2ff057
	ovsflags = rpmtsSetVSFlags(te->ts,
2ff057
				   rpmtsVSFlags(te->ts) | RPMVSF_NEEDPAYLOAD);
2ff057
	pkgrc = rpmReadPackageFile(te->ts, te->fd, rpmteNEVRA(te), &h);
2ff057
	rpmtsSetVSFlags(te->ts, ovsflags);
2ff057
	switch (pkgrc) {
2ff057
	default:
2ff057
	    rpmteClose(te, 1);
2ff057
	    break;
2ff057
	case RPMRC_NOTTRUSTED:
2ff057
	case RPMRC_NOKEY:
2ff057
	case RPMRC_OK:
2ff057
	    break;
2ff057
	}
2ff057
    }
2ff057
    return h;
2ff057
}
2ff057
2ff057
static int rpmteOpen(rpmte te, int reload_fi)
2ff057
{
2ff057
    int rc = 0; /* assume failure */
2ff057
    Header h = NULL;
2ff057
    if (te == NULL || te->ts == NULL || rpmteFailed(te))
2ff057
	goto exit;
2ff057
2ff057
    rpmteSetHeader(te, NULL);
2ff057
2ff057
    switch (rpmteType(te)) {
2ff057
    case TR_ADDED:
2ff057
	h = rpmteDBInstance(te) ? rpmteDBHeader(te) : rpmteFDHeader(te);
2ff057
	break;
2ff057
    case TR_REMOVED:
2ff057
	h = rpmteDBHeader(te);
2ff057
    	break;
2ff057
    }
2ff057
    if (h != NULL) {
2ff057
	if (reload_fi) {
2ff057
	    /* This can fail if we get a different, bad header from callback */
2ff057
	    te->files = getFiles(te, h);
2ff057
	    rc = (te->files != NULL);
2ff057
	} else {
2ff057
	    rc = 1;
2ff057
	}
2ff057
	
2ff057
	rpmteSetHeader(te, h);
2ff057
	headerFree(h);
2ff057
    }
2ff057
2ff057
exit:
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static int rpmteClose(rpmte te, int reset_fi)
2ff057
{
2ff057
    if (te == NULL || te->ts == NULL)
2ff057
	return 0;
2ff057
2ff057
    switch (te->type) {
2ff057
    case TR_ADDED:
2ff057
	if (te->fd) {
2ff057
	    rpmtsNotify(te->ts, te, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
2ff057
	    te->fd = NULL;
2ff057
	}
2ff057
	break;
2ff057
    case TR_REMOVED:
2ff057
	/* eventually we'll want notifications for erase open too */
2ff057
	break;
2ff057
    }
2ff057
    rpmteSetHeader(te, NULL);
2ff057
    if (reset_fi) {
2ff057
	rpmteCleanFiles(te);
2ff057
    }
2ff057
    return 1;
2ff057
}
2ff057
2ff057
FD_t rpmtePayload(rpmte te)
2ff057
{
2ff057
    FD_t payload = NULL;
2ff057
    if (te->fd && te->h) {
2ff057
	const char *compr = headerGetString(te->h, RPMTAG_PAYLOADCOMPRESSOR);
2ff057
	char *ioflags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
2ff057
	payload = Fdopen(fdDup(Fileno(te->fd)), ioflags);
2ff057
	free(ioflags);
2ff057
    }
2ff057
    return payload;
2ff057
}
2ff057
2ff057
static int rpmteMarkFailed(rpmte te)
2ff057
{
2ff057
    rpmtsi pi = rpmtsiInit(te->ts);
2ff057
    rpmte p;
2ff057
2ff057
    te->failed++;
2ff057
    /* XXX we can do a much better here than this... */
2ff057
    while ((p = rpmtsiNext(pi, TR_REMOVED))) {
2ff057
	if (rpmteDependsOn(p) == te) {
2ff057
	    p->failed++;
2ff057
	}
2ff057
    }
2ff057
    rpmtsiFree(pi);
2ff057
    return te->failed;
2ff057
}
2ff057
2ff057
int rpmteFailed(rpmte te)
2ff057
{
2ff057
    return (te != NULL) ? te->failed : -1;
2ff057
}
2ff057
2ff057
int rpmteHaveTransScript(rpmte te, rpmTagVal tag)
2ff057
{
2ff057
    int rc = 0;
2ff057
    if (tag == RPMTAG_PRETRANS) {
2ff057
	rc = (te->transscripts & RPMTE_HAVE_PRETRANS);
2ff057
    } else if (tag == RPMTAG_POSTTRANS) {
2ff057
	rc = (te->transscripts & RPMTE_HAVE_POSTTRANS);
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmps rpmteProblems(rpmte te)
2ff057
{
2ff057
    return (te != NULL) ? rpmpsLink(te->probs) : NULL;
2ff057
}
2ff057
2ff057
void rpmteCleanProblems(rpmte te)
2ff057
{
2ff057
    if (te != NULL && te->probs != NULL) {
2ff057
	te->probs = rpmpsFree(te->probs);
2ff057
    }
2ff057
}
2ff057
2ff057
static void appendProblem(rpmte te, rpmProblemType type,
2ff057
		fnpyKey key, const char * altNEVR,
2ff057
		const char * str, uint64_t number)
2ff057
{
2ff057
    rpmProblem o;
2ff057
    rpmProblem p = rpmProblemCreate(type, te->NEVRA, key, altNEVR, str, number);
2ff057
    rpmpsi psi = rpmpsInitIterator(te->probs);
2ff057
2ff057
    /* Only add new, unique problems to the set */
2ff057
    while ((o = rpmpsiNext(psi))) {
2ff057
	if (rpmProblemCompare(p, o) == 0)
2ff057
	    break;
2ff057
    }
2ff057
    rpmpsFreeIterator(psi);
2ff057
2ff057
    if (o == NULL) {
2ff057
	if (te->probs == NULL)
2ff057
	    te->probs = rpmpsCreate();
2ff057
	rpmpsAppendProblem(te->probs, p);
Panu Matilainen ec599b
	rpmteMarkFailed(te);
2ff057
    }
2ff057
    rpmProblemFree(p);
2ff057
}
2ff057
2ff057
void rpmteAddProblem(rpmte te, rpmProblemType type,
2ff057
		     const char *altNEVR, const char *str, uint64_t number)
2ff057
{
2ff057
    if (te != NULL) {
2ff057
	appendProblem(te, type, rpmteKey(te), altNEVR, str, number);
2ff057
    }
2ff057
}
2ff057
2ff057
void rpmteAddDepProblem(rpmte te, const char * altNEVR, rpmds ds,
2ff057
		        fnpyKey * suggestedKeys)
2ff057
{
2ff057
    if (te != NULL) {
2ff057
	const char * DNEVR = rpmdsDNEVR(ds);
2ff057
	rpmProblemType type;
2ff057
	fnpyKey key = (suggestedKeys ? suggestedKeys[0] : NULL);
2ff057
2ff057
	switch ((unsigned)DNEVR[0]) {
2ff057
	case 'O':	type = RPMPROB_OBSOLETES;	break;
2ff057
	case 'C':	type = RPMPROB_CONFLICT;	break;
2ff057
	default:
2ff057
	case 'R':	type = RPMPROB_REQUIRES;	break;
2ff057
	}
2ff057
2ff057
	appendProblem(te, type, key, altNEVR, DNEVR+2, rpmdsInstance(ds));
2ff057
    }
2ff057
}
2ff057
2ff057
void rpmteAddRelocProblems(rpmte te)
2ff057
{
2ff057
    if (te && te->badrelocs) {
2ff057
	for (int i = 0; i < te->nrelocs; i++) {
2ff057
	    if (te->badrelocs[i]) {
2ff057
		rpmteAddProblem(te, RPMPROB_BADRELOCATE, NULL,
2ff057
				te->relocs[i].oldPath, 0);
2ff057
	    }
2ff057
	}
2ff057
    }
2ff057
}
2ff057
2ff057
const char * rpmteTypeString(rpmte te)
2ff057
{
2ff057
    switch (rpmteType(te)) {
2ff057
    case TR_ADDED:	return _("install");
2ff057
    case TR_REMOVED:	return _("erase");
2ff057
    default:		return "???";
2ff057
    }
2ff057
}
2ff057
2ff057
rpmfs rpmteGetFileStates(rpmte te)
2ff057
{
2ff057
    return te->fs;
2ff057
}
2ff057
Panu Matilainen d6b3d4
void rpmteSetVerified(rpmte te, int verified)
Panu Matilainen d6b3d4
{
Panu Matilainen d6b3d4
    te->verified = verified;
Panu Matilainen d6b3d4
}
Panu Matilainen d6b3d4
Panu Matilainen d6b3d4
int rpmteGetVerified(rpmte te)
Panu Matilainen d6b3d4
{
Panu Matilainen d6b3d4
    return te->verified;
Panu Matilainen d6b3d4
}
Panu Matilainen d6b3d4
2ff057
int rpmteProcess(rpmte te, pkgGoal goal, int num)
2ff057
{
2ff057
    /* Only install/erase resets pkg file info */
2ff057
    int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE);
2ff057
    int test = (rpmtsFlags(te->ts) & RPMTRANS_FLAG_TEST);
2ff057
    int reset_fi = (scriptstage == 0 && test == 0);
2ff057
    int failed = 1;
2ff057
2ff057
    /* Dont bother opening for elements without pre/posttrans scripts */
2ff057
    if (goal == PKG_PRETRANS || goal == PKG_POSTTRANS) {
2ff057
	if (!rpmteHaveTransScript(te, goal)) {
2ff057
	    return 0;
2ff057
	}
2ff057
    }
2ff057
2ff057
    if (rpmteOpen(te, reset_fi)) {
2ff057
	if (!scriptstage) {
2ff057
	    rpmtsNotify(te->ts, te, RPMCALLBACK_ELEM_PROGRESS, num,
2ff057
			rpmtsMembers(te->ts)->orderCount);
2ff057
	}
2ff057
2ff057
	failed = rpmpsmRun(te->ts, te, goal);
2ff057
	rpmteClose(te, reset_fi);
2ff057
    }
2ff057
    
2ff057
    if (failed) {
2ff057
	failed = rpmteMarkFailed(te);
2ff057
    }
2ff057
2ff057
    return failed;
2ff057
}