Esempio n. 1
0
File: verify.c Progetto: xrg/RPM
/**
 * Return exit code from running verify script from header.
 * @todo malloc/free/refcount handling is fishy here.
 * @param qva		parsed query/verify options
 * @param ts		transaction set
 * @param h		header
 * @param scriptFd      file handle to use for stderr (or NULL)
 * @return              0 on success
 */
static int rpmVerifyScript(QVA_t qva, rpmts ts, Header h, FD_t scriptFd)
{
    rpmpsm psm = NULL;
    rpmte te = NULL;
    int rc = 0;

    /* fake up a erasure transaction element */
    rc = rpmtsAddEraseElement(ts, h, -1);
    te = rpmtsElement(ts, 0);
    rpmteOpen(te, ts, 0);
    
    if (scriptFd != NULL)
	rpmtsSetScriptFd(ts, scriptFd);

    /* create psm to run the script */
    psm = rpmpsmNew(ts, te);
    rpmpsmScriptStage(psm, RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG);
    rc = rpmpsmStage(psm, PSM_SCRIPT);
    psm = rpmpsmFree(psm);

    if (scriptFd != NULL)
	rpmtsSetScriptFd(ts, NULL);

    /* clean up our fake transaction bits */
    rpmteClose(te, ts, 0);
    rpmtsEmpty(ts);

    return rc;
}
Esempio n. 2
0
int rpmErase(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_const_t argv)
{
    char * const * arg;
    char *qfmt = NULL;
    int numFailed = 0;
    int numPackages = 0;
    rpmVSFlags vsflags, ovsflags;

    if (argv == NULL) return 0;

    vsflags = setvsFlags(ia);
    ovsflags = rpmtsSetVSFlags(ts, vsflags);

    (void) rpmtsSetFlags(ts, ia->transFlags);

    setNotifyFlag(ia, ts);

    qfmt = rpmExpand("%{?_query_all_fmt}\n", NULL);
    for (arg = argv; *arg; arg++) {
	rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
	int matches = rpmdbGetIteratorCount(mi);
	int erasing = 1;

	if (! matches) {
	    rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg);
	    numFailed++;
	} else {
	    Header h;	/* XXX iterator owns the reference */

	    if (matches > 1 && 
		!(ia->installInterfaceFlags & UNINSTALL_ALLMATCHES)) {
		rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages:\n"),
			*arg);
		numFailed++;
		erasing = 0;
	    }

	    while ((h = rpmdbNextIterator(mi)) != NULL) {
		if (erasing) {
		    (void) rpmtsAddEraseElement(ts, h, -1);
		    numPackages++;
		} else {
		    char *nevra = headerFormat(h, qfmt, NULL);
		    rpmlog(RPMLOG_NOTICE, "  %s", nevra);
		    free(nevra);
		}
	    }
	}
	rpmdbFreeIterator(mi);
    }
    free(qfmt);

    if (numFailed) goto exit;
    numFailed = rpmcliTransaction(ts, ia, numPackages);
exit:
    rpmtsEmpty(ts);
    rpmtsSetVSFlags(ts, ovsflags);

    return numFailed;
}
Esempio n. 3
0
/*
 * Add a delete operation to the transaction
 * @param [String, Package, Dependency] pkg Package to delete
 */
VALUE
rpm_transaction_delete(VALUE trans, VALUE pkg)
{
	VALUE db;
	VALUE mi;

#if RPM_VERSION_CODE < RPM_VERSION(4,9,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0)
	db = rb_ivar_get(trans, id_db);

	if (TYPE(pkg) == T_STRING)
		mi = rpm_db_init_iterator(db, INT2NUM(RPMDBI_LABEL), pkg);
	else if (rb_obj_is_kind_of(pkg, rpm_cPackage) != Qfalse) {
		VALUE sigmd5 = rpm_package_aref(pkg,INT2NUM(RPMTAG_SIGMD5));
		if (sigmd5 != Qnil){
			mi = rpm_db_init_iterator(db, INT2NUM(RPMTAG_SIGMD5), sigmd5);
		}else{
			VALUE name = rpm_package_aref(pkg,INT2NUM(RPMDBI_LABEL));
			mi = rpm_db_init_iterator(db, INT2NUM(RPMDBI_LABEL), name);
		}
	} else if ( rb_obj_is_kind_of(pkg, rpm_cDependency) ==Qfalse &&
                    rb_respond_to(pkg,rb_intern("name")) && rb_respond_to(pkg,rb_intern("version"))){
		mi = rpm_db_init_iterator(db, INT2NUM(RPMDBI_LABEL),rb_funcall(pkg,rb_intern("name"),0));
		rpm_mi_set_iterator_version(mi,rb_funcall(pkg,rb_intern("version"),0));
	} else
		rb_raise(rb_eTypeError, "illegal argument type");
#else
	if (TYPE(pkg) == T_STRING)
		mi = rpm_transaction_init_iterator(trans, INT2NUM(RPMDBI_LABEL), pkg);
	else if (rb_obj_is_kind_of(pkg, rpm_cPackage) != Qfalse) {
		VALUE sigmd5 = rpm_package_aref(pkg,INT2NUM(RPMTAG_SIGMD5));
		if (sigmd5 != Qnil){
			mi = rpm_transaction_init_iterator(trans, INT2NUM(RPMTAG_SIGMD5), sigmd5);
		}else{
			VALUE name = rpm_package_aref(pkg,INT2NUM(RPMDBI_LABEL));
			mi = rpm_transaction_init_iterator(trans, INT2NUM(RPMDBI_LABEL), name);
		}
	} else if ( rb_obj_is_kind_of(pkg, rpm_cDependency) ==Qfalse &&
                    rb_respond_to(pkg,rb_intern("name")) && rb_respond_to(pkg,rb_intern("version"))){
		mi = rpm_transaction_init_iterator(trans, INT2NUM(RPMDBI_LABEL),rb_funcall(pkg,rb_intern("name"),0));
		rpm_mi_set_iterator_version(mi,rb_funcall(pkg,rb_intern("version"),0));
	} else
		rb_raise(rb_eTypeError, "illegal argument type");
#endif

	VALUE p;
	while (!NIL_P(p = rpm_mi_next_iterator(mi))) {
		VALUE off = rpm_mi_get_iterator_offset(mi);
		if (!NIL_P(off)){
#if RPM_VERSION_CODE < RPM_VERSION(4,1,0)
			rpmtransRemovePackage(RPM_TRANSACTION(trans), NUM2INT(off));
#else
			rpmtsAddEraseElement(RPM_TRANSACTION(trans), RPM_HEADER(p), NUM2INT(off));
#endif
		}
	}
	return Qnil;
}
Esempio n. 4
0
static PyObject *
rpmts_AddErase(rpmtsObject * s, PyObject * args)
{
    Header h;

    if (!PyArg_ParseTuple(args, "O&:AddErase", hdrFromPyObject, &h))
        return NULL;

    return PyBool_FromLong(rpmtsAddEraseElement(s->ts, h, -1) == 0);
}
Esempio n. 5
0
int add_for_erase(rpmts ts, char *name)
{
	Header hdr;
	rpmdbMatchIterator mi;
	int rc = 0;

	/* Locate the package and add for erasure */
	mi = rpmtsInitIterator(ts, (rpmTag)RPMDBI_LABEL, name, 0);
	while ((hdr = rpmdbNextIterator(mi)) != NULL) {
		int recOffset = rpmdbGetIteratorOffset(mi);
		if (recOffset) {
			rc = rpmtsAddEraseElement(ts, hdr, recOffset);
			if (rc) 
				printf("Error adding %s to transaction", name);

		}
	}
	mi = rpmdbFreeIterator(mi);
	return rc;	
}
int ssds_add_to_erase(rpmts ts, char *pkg){

	Header hdr;
	rpmdbMatchIterator mi;
	int rc = OK;

	/* Locate the package and add for erasure */
	mi = rpmtsInitIterator(ts, (rpmTag)RPMDBI_LABEL, pkg, 0);
	while ((hdr = rpmdbNextIterator(mi)) != NULL) {
		int recOffset = rpmdbGetIteratorOffset(mi);
		if (recOffset) {
			rc = rpmtsAddEraseElement(ts, hdr, recOffset);
			if (rc) 
				ssds_log(logERROR, "Error adding %s to transaction.\n", pkg);

		}
	}
	mi = rpmdbFreeIterator(mi);
	return rc;
}
Esempio n. 7
0
uint32_t
TDNFTransAddErasePkg(
    PTDNFRPMTS pTS,
    HyPackage hPkg
    )
{
    uint32_t dwError = 0;
    Header pRpmHeader = NULL;
    rpmdbMatchIterator pIterator = NULL;
    const char* pszName = NULL;
    unsigned int nOffset = 0;

    if(!pTS || !hPkg)
    {
        dwError = ERROR_TDNF_INVALID_PARAMETER;
        BAIL_ON_TDNF_ERROR(dwError);
    }

    pszName = hy_package_get_name(hPkg);

    pIterator = rpmtsInitIterator(pTS->pTS, (rpmTag)RPMDBI_LABEL, pszName, 0);
    while ((pRpmHeader = rpmdbNextIterator(pIterator)) != NULL)
    {
        nOffset = rpmdbGetIteratorOffset(pIterator);
        if(nOffset)
        {
            dwError = rpmtsAddEraseElement(pTS->pTS, pRpmHeader, nOffset);
            BAIL_ON_TDNF_ERROR(dwError);
        }
    }

cleanup:
    if(pIterator)
    {
        rpmdbFreeIterator(pIterator);
    }
    return dwError;

error:
    goto cleanup;
}
Esempio n. 8
0
/* --- Object methods */
static JSBool
rpmts_add(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    void * ptr = JS_GetInstancePrivate(cx, obj, &rpmtsClass, NULL);
    rpmts ts = ptr;
    char * pkgN = 0;
    JSBool ok = JS_FALSE;

_METHOD_DEBUG_ENTRY(_debug);

    if (!(ok = JS_ConvertArguments(cx, argc, argv, "s", &pkgN)))
        goto exit;

    if (pkgN != NULL) {
	rpmmi mi;
	Header h;
	int upgrade = 0;
	int xx;

	switch (*pkgN) {
	case '-':	pkgN++;		upgrade = -1;	break;
	case '+':	pkgN++;		upgrade = 1;	break;
	default:			upgrade = 1;	break;
	}
	mi = rpmtsInitIterator(ts, RPMTAG_NVRA, pkgN, 0);
	while ((h = rpmmiNext(mi)) != NULL) {
	    xx = (upgrade >= 0)
	        ? rpmtsAddInstallElement(ts, h, (fnpyKey)pkgN, upgrade, NULL)
		: rpmtsAddEraseElement(ts, h, rpmmiInstance(mi));
	    break;
	}
	mi = rpmmiFree(mi);
    }

    ok = JS_TRUE;
exit:
    *rval = BOOLEAN_TO_JSVAL(ok);	/* XXX return error */
    return ok;
}
Esempio n. 9
0
File: rpminstall.c Progetto: xrg/RPM
int rpmErase(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_const_t argv)
{
    char * const * arg;
    char *qfmt = NULL;
    int numFailed = 0;
    int stopUninstall = 0;
    int numPackages = 0;
    rpmVSFlags vsflags, ovsflags;
    rpmps ps;

    if (argv == NULL) return 0;

    vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
    if (ia->qva_flags & VERIFY_DIGEST)
	vsflags |= _RPMVSF_NODIGESTS;
    if (ia->qva_flags & VERIFY_SIGNATURE)
	vsflags |= _RPMVSF_NOSIGNATURES;
    if (ia->qva_flags & VERIFY_HDRCHK)
	vsflags |= RPMVSF_NOHDRCHK;
    ovsflags = rpmtsSetVSFlags(ts, vsflags);

    /* XXX suggest mechanism only meaningful when installing */
    ia->transFlags |= RPMTRANS_FLAG_NOSUGGEST;

    (void) rpmtsSetFlags(ts, ia->transFlags);

#ifdef	NOTYET	/* XXX no callbacks on erase yet */
    {	int notifyFlags, xx;
	notifyFlags = ia->eraseInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
	xx = rpmtsSetNotifyCallback(ts,
			rpmShowProgress, (void *) ((long)notifyFlags));
    }
#endif

    qfmt = rpmExpand("%{?_query_all_fmt}\n", NULL);
    for (arg = argv; *arg; arg++) {
	rpmdbMatchIterator mi;
	int matches = 0;
	int erasing = 1;

	/* Iterator count isn't reliable with labels, count manually... */
	mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
	while (rpmdbNextIterator(mi) != NULL) {
	    matches++;
	}
	rpmdbFreeIterator(mi);

	if (! matches) {
	    rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg);
	    numFailed++;
	} else {
	    Header h;	/* XXX iterator owns the reference */

	    if (matches > 1 && 
		!(ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES)) {
		rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages:\n"),
			*arg);
		numFailed++;
		erasing = 0;
	    }

	    mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
	    while ((h = rpmdbNextIterator(mi)) != NULL) {
		if (erasing) {
		    (void) rpmtsAddEraseElement(ts, h, -1);
		    numPackages++;
		} else {
		    char *nevra = headerFormat(h, qfmt, NULL);
		    rpmlog(RPMLOG_NOTICE, "  %s", nevra);
		    free(nevra);
		}
	    }
	    mi = rpmdbFreeIterator(mi);
	}
    }
    free(qfmt);

    if (numFailed) goto exit;

    if (!(ia->eraseInterfaceFlags & UNINSTALL_NODEPS)) {

	if (rpmtsCheck(ts)) {
	    numFailed = numPackages;
	    stopUninstall = 1;
	}

	ps = rpmtsProblems(ts);
	if (!stopUninstall && rpmpsNumProblems(ps) > 0) {
	    rpmlog(RPMLOG_ERR, _("Failed dependencies:\n"));
	    rpmpsPrint(NULL, ps);
	    numFailed += numPackages;
	    stopUninstall = 1;
	}
	ps = rpmpsFree(ps);
    }

    if (!stopUninstall && !(ia->installInterfaceFlags & INSTALL_NOORDER)) {
	if (rpmtsOrder(ts)) {
	    numFailed += numPackages;
	    stopUninstall = 1;
	}
    }

    if (numPackages && !stopUninstall) {
	(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_REVERSE));

	/* Drop added/available package indices and dependency sets. */
	rpmtsClean(ts);

	numPackages = rpmtsRun(ts, NULL, ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES));
	ps = rpmtsProblems(ts);
	if (rpmpsNumProblems(ps) > 0)
	    rpmpsPrint(NULL, ps);
	numFailed += numPackages;
	stopUninstall = 1;
	ps = rpmpsFree(ps);
    }

exit:
    rpmtsEmpty(ts);

    return numFailed;
}
Esempio n. 10
0
/**
 * Check installed package dependencies for problems.
 * @param qva		parsed query/verify options
 * @param ts		transaction set
 * @param h		header
 * @return		number of problems found (0 for no problems)
 */
static int verifyDependencies(/*@unused@*/ QVA_t qva, rpmts ts,
		Header h)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
{
#ifdef	NOTYET
    uint32_t hdrNum = headerGetInstance(h);
#endif
    rpmps ps;
    int rc = 0;		/* assume no problems */
    int xx;

    rpmtsEmpty(ts);

#ifdef	NOTYET
    if (hdrNum > 0)
	(void) rpmtsAddEraseElement(ts, h, hdrNum);
    else
#endif
	(void) rpmtsAddInstallElement(ts, h, headerGetOrigin(h), 0, NULL);

    xx = rpmtsCheck(ts);
    ps = rpmtsProblems(ts);

    if (rpmpsNumProblems(ps) > 0) {
	const char * altNEVR;
	const char * pkgNEVR = NULL;
	rpmpsi psi;
	rpmProblem prob;
	char * t, * te;
	int nb = 512;

	psi = rpmpsInitIterator(ps);
	while (rpmpsNextIterator(psi) >= 0) {
	    prob = rpmpsProblem(psi);
	    if (pkgNEVR == NULL)
		pkgNEVR = rpmProblemGetPkgNEVR(prob);

	    altNEVR = rpmProblemGetAltNEVR(prob);
assert(altNEVR != NULL);
	    if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
		nb += sizeof("\tRequires: ")-1;
	    if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
		nb += sizeof("\tConflicts: ")-1;
	    nb += strlen(altNEVR+2) + sizeof("\n") - 1;

	}
	psi = rpmpsFreeIterator(psi);

	te = t = alloca(nb);
	*te = '\0';
	sprintf(te, _("Unsatisfied dependencies for %s:\n"), pkgNEVR);
	te += strlen(te);

	psi = rpmpsInitIterator(ps);
	while (rpmpsNextIterator(psi) >= 0) {
	    prob = rpmpsProblem(psi);

	    if ((altNEVR = rpmProblemGetAltNEVR(prob)) == NULL)
		altNEVR = "? ?altNEVR?";
	    if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
		te = stpcpy(te, "\tRequires: ");
	    if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
		te = stpcpy(te, "\tConflicts: ");
	    te = stpcpy( stpcpy(te, altNEVR+2), "\n");

	    rc++;
	}
	psi = rpmpsFreeIterator(psi);

	if (te > t) {
	    *te++ = '\n';
	    *te = '\0';
	    rpmlog(RPMLOG_NOTICE, "%s", t);
	    te = t;
	    *t = '\0';
	}
    }

    ps = rpmpsFree(ps);

    rpmtsEmpty(ts);

    return rc;
}
Esempio n. 11
0
/*************************************************************************
* FUNCTION      :   RPMTransaction_Set::Install_or_remove                *
* ARGUMENTS     :   RPM headers to add                                   *
* RETURNS       :   TCL_OK or TCL_ERROR                                  *
* EXCEPTIONS    :   none                                                 *
* PURPOSE       :   Add an RPM to an install set                         *
*************************************************************************/
int RPMTransaction_Set::Install_or_remove(Tcl_Obj *name,Install_mode mode)
{
    // Is this a list? if so, recurse through it
    Tcl_ObjType *listtype = Tcl_GetObjType("list");
    if (name->typePtr == listtype)
    {
        // OK, go recursive on this
        int count = 0;
        if (Tcl_ListObjLength(_interp,name,&count) != TCL_OK)
            return TCL_ERROR;

        for (int i = 0; i < count; ++i)
        {
            Tcl_Obj *element = 0;
            if (Tcl_ListObjIndex(_interp,name,i,&element) != TCL_OK)
            {
                return TCL_ERROR;
            }
            if (Install_or_remove(element,mode) != TCL_OK)
                return TCL_ERROR;
        }
        return TCL_OK;
    }
    // OK, so not a list. Try to make it into an RPM header
    if (Tcl_ConvertToType(_interp,name,&RPMHeader_Obj::mytype) != TCL_OK)
        return TCL_ERROR;
    RPMHeader_Obj *header = ( RPMHeader_Obj *)(name->internalRep.otherValuePtr);
    \
    // Unfortunately, the transaction set API does not give us a way to know when
    // it has freed a fnpyKey key object. In order to clean these up, we will create
    // a TCL list object of all headers we use for this purpose, and clean it as needed.
    Tcl_Obj *hdr_copy = header->Get_obj();
    Tcl_IncrRefCount(hdr_copy);

    int error = 0;
    switch (mode)
    {
    case INSTALL:
        error = rpmtsAddInstallElement(transaction,*header,header,0,0);
        break;
    case UPGRADE:
        error = rpmtsAddInstallElement(transaction,*header,header,1,0);
        break;
    case REMOVE:
        error = rpmtsAddEraseElement(transaction,*header,header->DB_entry());
        break;
    }

    switch (error)
    {
    case 0:
        // Record that we have created an entry on the list
        header_list = Grow_list(header_list,hdr_copy);
        return TCL_OK;

    case 1:
        header->Dec_refcount();
        return Error("Error adding %s: %s\n",Tcl_GetStringFromObj(name,0),rpmErrorString());

    case 2:
        header->Dec_refcount();
        return Error("Error adding %s: needs capabilities %s\n",Tcl_GetStringFromObj(name,0),rpmErrorString());

    default:
        header->Dec_refcount();
        return Error("Unknown RPMlib error %d adding %s: needs capabilities %s\n",error,Tcl_GetStringFromObj(name,0),rpmErrorString());
    }
    return TCL_OK;
}
Esempio n. 12
0
rpmRC rpmgiNext(/*@null@*/ rpmgi gi)
{
    char hnum[32];
    rpmRC rpmrc = RPMRC_NOTFOUND;
    int xx;

    if (gi == NULL)
	return rpmrc;

if (_rpmgi_debug)
fprintf(stderr, "--> %s(%p) tag %s\n", __FUNCTION__, gi, tagName(gi->tag));

    /* Free header from previous iteration. */
    (void)headerFree(gi->h);
    gi->h = NULL;
    gi->hdrPath = _free(gi->hdrPath);
    hnum[0] = '\0';

    if (++gi->i >= 0)
    switch (gi->tag) {
    default:
	if (!gi->active) {
nextkey:
	    rpmrc = rpmgiLoadNextKey(gi);
	    if (rpmrc != RPMRC_OK)
		goto enditer;
	    rpmrc = rpmgiInitFilter(gi);
	    if (rpmrc != RPMRC_OK || gi->mi == NULL) {
		gi->mi = rpmmiFree(gi->mi);	/* XXX unnecessary */
		gi->i++;
		goto nextkey;
	    }
	    rpmrc = RPMRC_NOTFOUND;	/* XXX hack */
	    gi->active = 1;
	}
	if (gi->mi != NULL) {	/* XXX unnecessary */
	    Header h = rpmmiNext(gi->mi);
	    if (h != NULL) {
		if (!(gi->flags & RPMGI_NOHEADER))
		    gi->h = headerLink(h);
		/* XXX use h->origin instead. */
		sprintf(hnum, "%u", (unsigned)rpmmiInstance(gi->mi));
		gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
		rpmrc = RPMRC_OK;
		/* XXX header reference held by iterator, so no headerFree */
	    }
	}
	if (rpmrc != RPMRC_OK) {
	    gi->mi = rpmmiFree(gi->mi);
	    goto nextkey;
	}
	break;
    case RPMDBI_PACKAGES:
	if (!gi->active) {
	    rpmrc = rpmgiInitFilter(gi);
	    if (rpmrc != RPMRC_OK) {
		gi->mi = rpmmiFree(gi->mi);	/* XXX unnecessary */
		goto enditer;
	    }
	    rpmrc = RPMRC_NOTFOUND;	/* XXX hack */
	    gi->active = 1;
	}
	if (gi->mi != NULL) {	/* XXX unnecessary */
	    Header h = rpmmiNext(gi->mi);
	    if (h != NULL) {
		if (!(gi->flags & RPMGI_NOHEADER))
		    gi->h = headerLink(h);
		/* XXX use h->origin instead. */
		sprintf(hnum, "%u", (unsigned)rpmmiInstance(gi->mi));
		gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
		rpmrc = RPMRC_OK;
		/* XXX header reference held by iterator, so no headerFree */
	    }
	}
	if (rpmrc != RPMRC_OK) {
	    gi->mi = rpmmiFree(gi->mi);
	    goto enditer;
	}
	break;
    case RPMDBI_REMOVED:
    case RPMDBI_ADDED:
    {	rpmte p;
	int teType = 0;
	const char * teTypeString = NULL;

	if (!gi->active) {
	    gi->tsi = rpmtsiInit(gi->ts);
	    gi->active = 1;
	}
	if ((p = rpmtsiNext(gi->tsi, teType)) != NULL) {
	    Header h = rpmteHeader(p);
	    if (h != NULL)
		if (!(gi->flags & RPMGI_NOHEADER)) {
		    gi->h = headerLink(h);
		switch(rpmteType(p)) {
		case TR_ADDED:	teTypeString = "+++";	/*@switchbreak@*/break;
		case TR_REMOVED: teTypeString = "---";	/*@switchbreak@*/break;
		}
		sprintf(hnum, "%u", (unsigned)gi->i);
		gi->hdrPath = rpmExpand("%s h# ", teTypeString, hnum, NULL);
		rpmrc = RPMRC_OK;
		(void)headerFree(h);
		h = NULL;
	    }
	}
	if (rpmrc != RPMRC_OK) {
	    gi->tsi = rpmtsiFree(gi->tsi);
	    goto enditer;
	}
    }	break;
    case RPMDBI_HDLIST:
	if (!gi->active) {
	    const char * path = rpmExpand("%{?_query_hdlist_path}", NULL);
	    if (path == NULL || *path == '\0') {
		path = _free(path);
		path = rpmExpand(_query_hdlist_path, NULL);
	    }
	    gi->fd = rpmgiOpen(path, "rm%{?_rpmgio}");
	    gi->active = 1;
	    path = _free(path);
	}
	if (gi->fd != NULL) {
	    Header h = NULL;
	    const char item[] = "Header";
	    const char * msg = NULL;
/*@+voidabstract@*/
	    rpmrc = rpmpkgRead(item, gi->fd, &h, &msg);
/*@=voidabstract@*/
	    switch(rpmrc) {
		default:
		    rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg);
		case RPMRC_NOTFOUND:
		    h = NULL;
		case RPMRC_OK:
		    break;
	    }
	    msg = _free(msg);
	    if (h != NULL) {
		if (!(gi->flags & RPMGI_NOHEADER))
		    gi->h = headerLink(h);
		sprintf(hnum, "%u", (unsigned)gi->i);
		gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL);
		rpmrc = RPMRC_OK;
		(void)headerFree(h);
		h = NULL;
	    }
	}
	if (rpmrc != RPMRC_OK) {
	    if (gi->fd != NULL) (void) Fclose(gi->fd);
	    gi->fd = NULL;
	    goto enditer;
	}
	break;
    case RPMDBI_ARGLIST:
	/* XXX gi->active initialize? */
if (_rpmgi_debug  < 0)
fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
	/* Read next header, lazily expanding manifests as found. */
	rpmrc = rpmgiLoadReadHeader(gi);

	if (rpmrc != RPMRC_OK)	/* XXX check this */
	    goto enditer;

	gi->hdrPath = xstrdup(gi->argv[gi->i]);
	break;
    case RPMDBI_FTSWALK:
	if (gi->argv == NULL || gi->argv[0] == NULL)		/* HACK */
	    goto enditer;

	if (!gi->active) {
	    gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL);
	    /* XXX NULL with open(2)/malloc(3) errno set */
	    gi->active = 1;
	}

	/* Read next header, lazily walking file tree. */
	rpmrc = rpmgiWalkReadHeader(gi);

	if (rpmrc != RPMRC_OK) {
	    xx = Fts_close(gi->ftsp);
	    gi->ftsp = NULL;
	    goto enditer;
	}

	if (gi->fts != NULL)
	    gi->hdrPath = xstrdup(gi->fts->fts_path);
	break;
    }

    if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) {
	/* XXX rpmgi hack: Save header in transaction element. */
	if (gi->flags & RPMGI_ERASING) {
	    uint32_t hdrNum = headerGetInstance(gi->h);
	    xx = rpmtsAddEraseElement(gi->ts, gi->h, hdrNum);
	} else
	    xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL);
    }
    goto exit;

enditer:
    if (gi->flags & RPMGI_TSORDER) {
	rpmts ts = gi->ts;

	/* Block access to indices used for depsolving. */
	if (!(gi->flags & RPMGI_ERASING)) {
	    (void) rpmtsSetGoal(ts, TSM_INSTALL);
	    xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMDBI_DEPCACHE);
	    xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_BASENAMES);
	    xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_PROVIDENAME);
	} else {
	    (void) rpmtsSetGoal(ts, TSM_ERASE);
	}

	/* XXX query/verify will need the glop added to a buffer instead. */
	xx = rpmcliInstallCheck(ts);
	xx = rpmcliInstallSuggests(ts);

	/* Permit access to indices used for depsolving. */
	if (!(gi->flags & RPMGI_ERASING)) {
	    xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_PROVIDENAME);
	    xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_BASENAMES);
	    xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMDBI_DEPCACHE);
	}

	/* XXX Display dependency loops with rpm -qvT. */
	if (rpmIsVerbose())
	    (void) rpmtsSetDFlags(ts, (rpmtsDFlags(ts) | RPMDEPS_FLAG_DEPLOOPS));

	xx = (*gi->tsOrder) (ts);

	/* XXX hackery alert! */
	gi->tag = (!(gi->flags & RPMGI_ERASING) ? RPMDBI_ADDED : RPMDBI_REMOVED);
	gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER);

    }

    (void)headerFree(gi->h);
    gi->h = NULL;
    gi->hdrPath = _free(gi->hdrPath);
    gi->i = -1;
    gi->active = 0;

exit:
if (_rpmgi_debug)
fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, gi, rpmrc);
    return rpmrc;
}