Exemplo n.º 1
0
Arquivo: verify.c Projeto: nforro/rpm
/**
 * Check installed package dependencies for problems.
 * @param ts		transaction set
 * @param h		header
 * @return		number of problems found (0 for no problems)
 */
static int verifyDependencies(rpmts ts, Header h)
{
    rpmps ps;
    rpmte te;
    int rc;

    rpmtsEmpty(ts);
    (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);

    (void) rpmtsCheck(ts);
    te = rpmtsElement(ts, 0);
    ps = rpmteProblems(te);
    rc = rpmpsNumProblems(ps);

    if (rc > 0) {
	rpmlog(RPMLOG_NOTICE, _("Unsatisfied dependencies for %s:\n"),
	       rpmteNEVRA(te));
	rpmpsi psi = rpmpsInitIterator(ps);
	rpmProblem p;

	while ((p = rpmpsiNext(psi)) != NULL) {
	    char * ps = rpmProblemString(p);
	    rpmlog(RPMLOG_NOTICE, "\t%s\n", ps);
	    free(ps);
	}
	rpmpsFreeIterator(psi);
    }
    rpmpsFree(ps);
    rpmtsEmpty(ts);

    return rc;
}
Exemplo n.º 2
0
/**
 * Ensure that current package is newer than installed package.
 * @param ts		transaction set
 * @param p		current transaction element
 * @param h		installed header
 * @return		0 if not newer, 1 if okay
 */
static int ensureOlder(rpmts ts,
		const rpmte p, const Header h)
{
    rpmsenseFlags reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
    rpmds req;
    int rc;

    if (p == NULL || h == NULL)
	return 1;

    req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), rpmteEVR(p), reqFlags);
    rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
    req = rpmdsFree(req);

    if (rc == 0) {
	rpmps ps = rpmtsProblems(ts);
	char * altNEVR = headerGetNEVRA(h, NULL);
	rpmpsAppend(ps, RPMPROB_OLDPACKAGE,
		rpmteNEVRA(p), rpmteKey(p),
		NULL, NULL,
		altNEVR,
		0);
	altNEVR = _free(altNEVR);
	ps = rpmpsFree(ps);
	rc = 1;
    } else
	rc = 0;

    return rc;
}
Exemplo n.º 3
0
/*
 * Transaction main loop: install and remove packages
 */
static int rpmtsProcess(rpmts ts)
{
    rpmtsi pi;	rpmte p;
    int rc = 0;

    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	int failed = 1;
	rpmElementType tetype = rpmteType(p);
	rpmtsOpX op = (tetype == TR_ADDED) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE;

	rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	if (rpmteFailed(p)) {
	    /* XXX this should be a warning, need a better message though */
	    rpmlog(RPMLOG_DEBUG, "element %s marked as failed, skipping\n",
					rpmteNEVRA(p));
	    rc++;
	    continue;
	}
	
	if (rpmteOpen(p, ts, 1)) {
	    rpmpsm psm = NULL;
	    pkgStage stage = PSM_UNKNOWN;
	    int async = (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1)) ? 
			1 : 0;

	    switch (tetype) {
	    case TR_ADDED:
		stage = PSM_PKGINSTALL;
		break;
	    case TR_REMOVED:
		stage = PSM_PKGERASE;
		break;
	    }
	    psm = rpmpsmNew(ts, p);
	    rpmpsmSetAsync(psm, async);

	    (void) rpmswEnter(rpmtsOp(ts, op), 0);
	    failed = rpmpsmStage(psm, stage);
	    (void) rpmswExit(rpmtsOp(ts, op), 0);
	    psm = rpmpsmFree(psm);
	    rpmteClose(p, ts, 1);
	}
	if (failed) {
	    rpmteMarkFailed(p, ts);
	    rc++;
	}
	(void) rpmdbSync(rpmtsGetRdb(ts));
    }
    pi = rpmtsiFree(pi);
    return rc;
}
Exemplo n.º 4
0
Arquivo: psm.c Projeto: fingunter/rpm
static rpmpsm rpmpsmNew(rpmts ts, rpmte te, pkgGoal goal)
{
    rpmpsm psm = xcalloc(1, sizeof(*psm));
    psm->ts = rpmtsLink(ts);
    psm->files = rpmteFiles(te);
    psm->te = te; /* XXX rpmte not refcounted yet */
    if (!rpmteIsSource(te)) {
	/*
	 * When we run scripts, we pass an argument which is the number of
	 * versions of this package that will be installed when we are
	 * finished.
	 */
	int npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(te));
	switch (goal) {
	case PKG_INSTALL:
	case PKG_PRETRANS:
	    psm->scriptArg = npkgs_installed + 1;
	    psm->countCorrection = 0;
	    break;
	case PKG_ERASE:
	    psm->scriptArg = npkgs_installed - 1;
	    psm->countCorrection = -1;
	    break;
	case PKG_VERIFY:
	case PKG_POSTTRANS:
	    psm->scriptArg = npkgs_installed;
	    psm->countCorrection = 0;
	    break;
	default:
	    break;
	}
    }

    if (goal == PKG_INSTALL) {
	Header h = rpmteHeader(te);
	psm->total = headerGetNumber(h, RPMTAG_LONGARCHIVESIZE);
	headerFree(h);
    } else if (goal == PKG_ERASE) {
	psm->total = rpmfilesFC(psm->files);
    }
    /* Fake up something for packages with no files */
    if (psm->total == 0)
	psm->total = 100;

    rpmlog(RPMLOG_DEBUG, "%s: %s has %d files\n", pkgGoalString(goal),
	    rpmteNEVRA(psm->te), rpmfilesFC(psm->files));

    return psm;
}
Exemplo n.º 5
0
static rpmRC sepolAddTE(rpmte te)
{
    sepol *pol;
    sepol *polTail;

    if (!rpmteHasCollection(te, name)) {
	return RPMRC_OK;
    }

    pol = sepolNew(te);
    if (!pol) {
	/* something's wrong with the policy information, either missing or
	 * corrupt. abort */
	rpmlog(RPMLOG_ERR, _("Failed to extract policy from %s\n"),
	       rpmteNEVRA(te));
	return RPMRC_FAIL;
    }

    /* find the tail of pol */
    polTail = pol;
    while (polTail->next) {
	polTail = polTail->next;
    }

    /* add the new policy to the list */
    if (!policiesHead) {
	policiesHead = pol;
	policiesTail = polTail;
    } else {
	if (rpmteType(te) == TR_ADDED) {
	    /* add to the end of the list */
	    policiesTail->next = pol;
	    policiesTail = polTail;
	} else {
	    /* add to the beginning of the list */
	    polTail->next = policiesHead;
	    policiesHead = pol;
	}
    }

    return RPMRC_OK;
}
Exemplo n.º 6
0
/*
 * Transaction main loop: install and remove packages
 */
static int rpmtsProcess(rpmts ts)
{
    rpmtsi pi;	rpmte p;
    int rc = 0;

    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	int failed;

	rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	failed = rpmteProcess(p, rpmteType(p));
	if (failed) {
	    rpmlog(RPMLOG_ERR, "%s: %s %s\n", rpmteNEVRA(p),
		   rpmteTypeString(p), failed > 1 ? _("skipped") : _("failed"));
	    rc++;
	}
    }
    rpmtsiFree(pi);
    return rc;
}
Exemplo n.º 7
0
/* XXX only ts->{probs,di} modified */
static void handleOverlappedFiles(rpmts ts, fingerPrintCache fpc, rpmte p, rpmfiles fi)
{
    rpm_loff_t fixupSize = 0;
    int i, j;
    rpmfs fs = rpmteGetFileStates(p);
    rpmfs otherFs;
    rpm_count_t fc = rpmfilesFC(fi);
    int reportConflicts = !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
    fingerPrint * fpList = rpmfilesFps(fi);

    for (i = 0; i < fc; i++) {
	struct fingerPrint_s * fiFps;
	int otherPkgNum, otherFileNum;
	rpmfiles otherFi;
	rpmte otherTe;
	rpmfileAttrs FFlags;
	struct rpmffi_s * recs;
	int numRecs;

	if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
	    continue;

	FFlags = rpmfilesFFlags(fi, i);

	fixupSize = 0;

	/*
	 * Retrieve all records that apply to this file. Note that the
	 * file info records were built in the same order as the packages
	 * will be installed and removed so the records for an overlapped
	 * files will be sorted in exactly the same order.
	 */
	fiFps = fpCacheGetByFp(fpc, fpList, i, &recs, &numRecs);

	/*
	 * If this package is being added, look only at other packages
	 * being added -- removed packages dance to a different tune.
	 *
	 * If both this and the other package are being added, overlapped
	 * files must be identical (or marked as a conflict). The
	 * disposition of already installed config files leads to
	 * a small amount of extra complexity.
	 *
	 * If this package is being removed, then there are two cases that
	 * need to be worried about:
	 * If the other package is being added, then skip any overlapped files
	 * so that this package removal doesn't nuke the overlapped files
	 * that were just installed.
	 * If both this and the other package are being removed, then each
	 * file removal from preceding packages needs to be skipped so that
	 * the file removal occurs only on the last occurrence of an overlapped
	 * file in the transaction set.
	 *
	 */

	/*
	 * Locate this overlapped file in the set of added/removed packages,
	 * including the package owning it: a package can have self-conflicting
	 * files when directory symlinks are present. Don't compare a file
	 * with itself though...
	 */
	for (j = 0; j < numRecs && !(recs[j].p == p && recs[j].fileno == i); j++)
	    {};

	/* Find what the previous disposition of this file was. */
	otherFileNum = -1;			/* keep gcc quiet */
	otherFi = NULL;
	otherTe = NULL;
	otherFs = NULL;

	for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
	    otherTe = recs[otherPkgNum].p;
	    otherFileNum = recs[otherPkgNum].fileno;
	    otherFs = rpmteGetFileStates(otherTe);

	    /* Added packages need only look at other added packages. */
	    if (rpmteType(p) == TR_ADDED && rpmteType(otherTe) != TR_ADDED)
		continue;

	    /* XXX Happens iff fingerprint for incomplete package install. */
	    if (rpmfsGetAction(otherFs, otherFileNum) != FA_UNKNOWN) {
		otherFi = rpmteFiles(otherTe);
		break;
	    }
	}

	switch (rpmteType(p)) {
	case TR_ADDED:
	    if (otherPkgNum < 0) {
		/* XXX is this test still necessary? */
		rpmFileAction action;
		if (rpmfsGetAction(fs, i) != FA_UNKNOWN)
		    break;
		if (rpmfilesConfigConflict(fi, i)) {
		    /* Here is a non-overlapped pre-existing config file. */
		    action = (FFlags & RPMFILE_NOREPLACE) ?
			      FA_ALTNAME : FA_BACKUP;
		} else {
		    action = FA_CREATE;
		}
		rpmfsSetAction(fs, i, action);
		break;
	    }

assert(otherFi != NULL);
	    /* Mark added overlapped non-identical files as a conflict. */
	    if (rpmfilesCompare(otherFi, otherFileNum, fi, i)) {
		int rConflicts;

		/* If enabled, resolve colored conflicts to preferred type */
		rConflicts = handleColorConflict(ts, fs, fi, i,
						otherFs, otherFi, otherFileNum);

		if (rConflicts && reportConflicts) {
		    char *fn = rpmfilesFN(fi, i);
		    rpmteAddProblem(p, RPMPROB_NEW_FILE_CONFLICT,
				    rpmteNEVRA(otherTe), fn, 0);
		    free(fn);
		}
	    } else {
		/* Skip create on all but the first instance of a shared file */
		rpmFileAction oaction = rpmfsGetAction(otherFs, otherFileNum);
		if (oaction != FA_UNKNOWN && !XFA_SKIPPING(oaction)) {
		    rpmfileAttrs oflags;
		    /* ...but ghosts aren't really created so... */
		    oflags = rpmfilesFFlags(otherFi, otherFileNum);
		    if (!(oflags & RPMFILE_GHOST)) {
			rpmfsSetAction(fs, i, FA_SKIP);
		    }
		/* if the other file is color skipped then skip this file too */
		} else if (oaction == FA_SKIPCOLOR) {
		    rpmfsSetAction(fs, i, FA_SKIPCOLOR);
		}
	    }

	    /* Skipped files dont need fixup size or backups, %config or not */
	    if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
		break;

	    /* Try to get the disk accounting correct even if a conflict. */
	    fixupSize = rpmfilesFSize(otherFi, otherFileNum);

	    if (rpmfilesConfigConflict(fi, i)) {
		/* Here is an overlapped  pre-existing config file. */
		rpmFileAction action;
		action = (FFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SKIP;
		rpmfsSetAction(fs, i, action);
	    } else {
		/* If not decided yet, create it */
		if (rpmfsGetAction(fs, i) == FA_UNKNOWN)
		    rpmfsSetAction(fs, i, FA_CREATE);
	    }
	    break;

	case TR_REMOVED:
	    if (otherPkgNum >= 0) {
		assert(otherFi != NULL);
                /* Here is an overlapped added file we don't want to nuke. */
		if (rpmfsGetAction(otherFs, otherFileNum) != FA_ERASE) {
		    /* On updates, don't remove files. */
		    rpmfsSetAction(fs, i, FA_SKIP);
		    break;
		}
		/* Here is an overlapped removed file: skip in previous. */
		rpmfsSetAction(otherFs, otherFileNum, FA_SKIP);
	    }
	    if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
		break;
	    if (rpmfilesFState(fi, i) != RPMFILE_STATE_NORMAL)
		break;
		
	    /* Pre-existing modified config files need to be saved. */
	    if (rpmfilesConfigConflict(fi, i)) {
		rpmfsSetAction(fs, i, FA_SAVE);
		break;
	    }
	
	    /* Otherwise, we can just erase. */
	    rpmfsSetAction(fs, i, FA_ERASE);
	    break;
	}
	rpmfilesFree(otherFi);

	/* Update disk space info for a file. */
	rpmtsUpdateDSI(ts, fpEntryDev(fpc, fiFps), fpEntryDir(fpc, fiFps),
		       rpmfilesFSize(fi, i), rpmfilesFReplacedSize(fi, i),
		       fixupSize, rpmfsGetAction(fs, i));

    }
}
Exemplo n.º 8
0
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
{
    rpm_color_t tscolor = rpmtsColor(ts);
    int i;
    int rc = 0;
    int totalFileCount = 0;
    rpmfi fi;
    fingerPrintCache fpc;
    rpmps ps;
    rpmtsi pi;	rpmte p;
    int numAdded;
    int numRemoved;
    void * lock = NULL;
    int xx;

    /* XXX programmer error segfault avoidance. */
    if (rpmtsNElements(ts) <= 0)
	return -1;

    /* If we are in test mode, then there's no need for transaction lock. */
    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
	lock = rpmtsAcquireLock(ts);
	if (lock == NULL)
	    return -1;	/* XXX W2DO? */
    }

    if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
	(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
    if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
	(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));

    if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
	(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));

    /* if SELinux isn't enabled or init fails, don't bother... */
    if (!rpmtsSELinuxEnabled(ts)) {
        rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
    }

    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
	char *fn = rpmGetPath("%{?_install_file_context_path}", NULL);
	if (matchpathcon_init(fn) == -1) {
	    rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
	}
	free(fn);
    }

    ts->probs = rpmpsFree(ts->probs);
    ts->probs = rpmpsCreate();

    /* XXX Make sure the database is open RDWR for package install/erase. */
    {	int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
		? O_RDONLY : (O_RDWR|O_CREAT);

	/* Open database RDWR for installing packages. */
	if (rpmtsOpenDB(ts, dbmode)) {
	    rpmtsFreeLock(lock);
	    return -1;	/* XXX W2DO? */
	}
    }

    ts->ignoreSet = ignoreSet;
    {	char * currDir = rpmGetCwd();
	rpmtsSetCurrDir(ts, currDir);
	currDir = _free(currDir);
    }

    (void) rpmtsSetChrootDone(ts, 0);

    {	rpm_tid_t tid = (rpm_tid_t) time(NULL);
	(void) rpmtsSetTid(ts, tid);
    }

    /* Get available space on mounted file systems. */
    xx = rpmtsInitDSI(ts);

    /* ===============================================
     * For packages being installed:
     * - verify package arch/os.
     * - verify package epoch:version-release is newer.
     * - count files.
     * For packages being removed:
     * - count files.
     */

    rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts));
    ps = rpmtsProblems(ts);
    /* The ordering doesn't matter here */
    pi = rpmtsiInit(ts);
    /* XXX Only added packages need be checked. */
    while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
	rpmdbMatchIterator mi;
	int fc;

	if ((fi = rpmteFI(p)) == NULL)
	    continue;	/* XXX can't happen */
	fc = rpmfiFC(fi);

	if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH))
	    if (!archOkay(rpmteA(p)))
		rpmpsAppend(ps, RPMPROB_BADARCH,
			rpmteNEVRA(p), rpmteKey(p),
			rpmteA(p), NULL,
			NULL, 0);

	if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS))
	    if (!osOkay(rpmteO(p)))
		rpmpsAppend(ps, RPMPROB_BADOS,
			rpmteNEVRA(p), rpmteKey(p),
			rpmteO(p), NULL,
			NULL, 0);

	if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) {
	    Header h;
	    mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
	    while ((h = rpmdbNextIterator(mi)) != NULL)
		xx = ensureOlder(ts, p, h);
	    mi = rpmdbFreeIterator(mi);
	}

	if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
	    mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
	    xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
				rpmteE(p));
	    xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
				rpmteV(p));
	    xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
				rpmteR(p));
	    if (tscolor) {
		xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
				rpmteA(p));
		xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP,
				rpmteO(p));
	    }

	    while (rpmdbNextIterator(mi) != NULL) {
		rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
			rpmteNEVRA(p), rpmteKey(p),
			NULL, NULL,
			NULL, 0);
		break;
	    }
	    mi = rpmdbFreeIterator(mi);
	}

	/* Count no. of files (if any). */
	totalFileCount += fc;

    }
    pi = rpmtsiFree(pi);
    ps = rpmpsFree(ps);

    /* The ordering doesn't matter here */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
	int fc;

	if ((fi = rpmteFI(p)) == NULL)
	    continue;	/* XXX can't happen */
	fc = rpmfiFC(fi);

	totalFileCount += fc;
    }
    pi = rpmtsiFree(pi);


    /* Run pre-transaction scripts, but only if there are no known
     * problems up to this point and not disabled otherwise. */
    if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPRE))
     	  || (rpmpsNumProblems(ts->probs) &&
		(okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) {
	rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n");
	runTransScripts(ts, RPMTAG_PRETRANS);
    }

    /* ===============================================
     * Initialize transaction element file info for package:
     */

    /*
     * FIXME?: we'd be better off assembling one very large file list and
     * calling fpLookupList only once. I'm not sure that the speedup is
     * worth the trouble though.
     */
    rpmlog(RPMLOG_DEBUG, "computing %d file fingerprints\n", totalFileCount);

    numAdded = numRemoved = 0;
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	int fc;

	if ((fi = rpmteFI(p)) == NULL)
	    continue;	/* XXX can't happen */
	fc = rpmfiFC(fi);

	switch (rpmteType(p)) {
	case TR_ADDED:
	    numAdded++;
	    /* Skip netshared paths, not our i18n files, and excluded docs */
	    if (fc > 0)
		skipFiles(ts, p);
	    break;
	case TR_REMOVED:
	    numRemoved++;
	    break;
	}
    }
    pi = rpmtsiFree(pi);

    if (!rpmtsChrootDone(ts)) {
	const char * rootDir = rpmtsRootDir(ts);
	xx = chdir("/");
	if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
	    /* opening db before chroot not optimal, see rhbz#103852 c#3 */
	    xx = rpmdbOpenAll(ts->rdb);
	    if (chroot(rootDir) == -1) {
		rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n"));
		return -1;
	    }
	}
	(void) rpmtsSetChrootDone(ts, 1);
    }

    ts->ht = rpmFpHashCreate(totalFileCount/2+1, fpHashFunction, fpEqual,
			     NULL, NULL);
    rpmFpHash symlinks = rpmFpHashCreate(totalFileCount/16+16, fpHashFunction, fpEqual, NULL, NULL);
    fpc = fpCacheCreate(totalFileCount/2 + 10001);

    /* ===============================================
     * Add fingerprint for each file not skipped.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	int fc;

	(void) rpmdbCheckSignals();

	if ((fi = rpmteFI(p)) == NULL)
	    continue;	/* XXX can't happen */
	fc = rpmfiFC(fi);

	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
	rpmfiFpLookup(fi, fpc);
	/* collect symbolic links */
 	fi = rpmfiInit(fi, 0);
 	if (fi != NULL)		/* XXX lclint */
	while ((i = rpmfiNext(fi)) >= 0) {
	    struct rpmffi_s ffi;
	    char const *linktarget;
	    linktarget = rpmfiFLink(fi);
	    if (!(linktarget && *linktarget != '\0'))
		continue;
	    if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i)))
		continue;
	    ffi.p = p;
	    ffi.fileno = i;
	    rpmFpHashAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi);
	}
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);

    }
    pi = rpmtsiFree(pi);

    /* ===============================================
     * Check fingerprints if they contain symlinks
     * and add them to the ts->ht hash table
     */

    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	(void) rpmdbCheckSignals();

	if ((fi = rpmteFI(p)) == NULL)
	    continue;	/* XXX can't happen */
	fi = rpmfiInit(fi, 0);
	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
	if (fi != NULL)		/* XXX lclint */
	while ((i = rpmfiNext(fi)) >= 0) {
	    if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i)))
		continue;
	    fpLookupSubdir(symlinks, ts->ht, fpc, p, i);
	}
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
    }
    pi = rpmtsiFree(pi);

    rpmFpHashFree(symlinks);

    /* ===============================================
     * Compute file disposition for each package in transaction set.
     */
    rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount);

    /* check against files in the rpmdb */
    checkInstalledFiles(ts, fpc);

    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {

	if ((fi = rpmteFI(p)) == NULL)
	    continue;   /* XXX can't happen */

	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
	/* check files in ts against each other and update disk space
	   needs on each partition for this package. */
	handleOverlappedFiles(ts, p, fi);

	/* Check added package has sufficient space on each partition used. */
	if (rpmteType(p) == TR_ADDED) {
	    rpmtsCheckDSIProblems(ts, p);
	}
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
    }
    pi = rpmtsiFree(pi);

    if (rpmtsChrootDone(ts)) {
	const char * rootDir = rpmtsRootDir(ts);
	const char * currDir = rpmtsCurrDir(ts);
	if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
	    xx = chroot(".");
	(void) rpmtsSetChrootDone(ts, 0);
	if (currDir != NULL)
	    xx = chdir(currDir);
    }

    rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount);

    /* ===============================================
     * Free unused memory as soon as possible.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	rpmteSetFI(p, NULL);
    }
    pi = rpmtsiFree(pi);

    fpc = fpCacheFree(fpc);
    ts->ht = rpmFpHashFree(ts->ht);

    /* ===============================================
     * If unfiltered problems exist, free memory and return.
     */
    if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
     || (rpmpsNumProblems(ts->probs) &&
		(okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
       )
    {
	rpmtsFreeLock(lock);
	return ts->orderCount;
    }

    /* Actually install and remove packages */
    rc = rpmtsProcess(ts);

    if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPOST))) {
	rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n");
	runTransScripts(ts, RPMTAG_POSTTRANS);
    }

    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
	matchpathcon_fini();
    }

    rpmtsFreeLock(lock);

    /* FIX: ts->flList may be NULL */
    if (rc)
    	return -1;
    else
	return 0;
}
Exemplo n.º 9
0
/* XXX only ts->{probs,rpmdb} modified */
static int handleInstInstalledFile(const rpmts ts, rpmte p, rpmfi fi,
				   Header otherHeader, rpmfi otherFi,
				   int beingRemoved)
{
    rpm_color_t tscolor = rpmtsColor(ts);
    rpm_color_t prefcolor = rpmtsPrefColor(ts);
    rpm_color_t oFColor, FColor;
    char * altNEVR = NULL;
    rpmps ps;
    unsigned int fx = rpmfiFX(fi);
    rpmfs fs = rpmteGetFileStates(p);

    altNEVR = headerGetNEVRA(otherHeader, NULL);

    ps = rpmtsProblems(ts);
    int isCfgFile;

    oFColor = rpmfiFColor(otherFi);
    oFColor &= tscolor;

    FColor = rpmfiFColor(fi);
    FColor &= tscolor;

    isCfgFile = ((rpmfiFFlags(otherFi) | rpmfiFFlags(fi)) & RPMFILE_CONFIG);

    if (XFA_SKIPPING(rpmfsGetAction(fs, fx)))
	return 0;

    if (rpmfiCompare(otherFi, fi)) {
	int rConflicts;

	rConflicts = !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES));
	/* Resolve file conflicts to prefer Elf64 (if not forced). */
	if (tscolor != 0 && FColor != 0 && FColor != oFColor) {
	    if (oFColor & prefcolor) {
		rpmfsSetAction(fs, fx, FA_SKIPCOLOR);
		rConflicts = 0;
	    } else if (FColor & prefcolor) {
		rpmfsSetAction(fs, fx, FA_CREATE);
		rConflicts = 0;
	    }
	}

	if (rConflicts) {
	    rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
			rpmteNEVRA(p), rpmteKey(p),
			rpmfiDN(fi), rpmfiBN(fi),
			altNEVR,
			0);
	}

	/* Save file identifier to mark as state REPLACED. */
	if ( !(isCfgFile || XFA_SKIPPING(rpmfsGetAction(fs, fx))) ) {
	    if (!beingRemoved)
		rpmfsAddReplaced(rpmteGetFileStates(p), rpmfiFX(fi),
				 headerGetInstance(otherHeader),
				 rpmfiFX(otherFi));
	}
    }

    /* Determine config file dispostion, skipping missing files (if any). */
    if (isCfgFile) {
	int skipMissing =
	    ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
	rpmFileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
	rpmfsSetAction(fs, fx, action);
    }
    rpmfiSetFReplacedSize(fi, rpmfiFSize(otherFi));

    ps = rpmpsFree(ps);
    altNEVR = _free(altNEVR);
    return 0;
}
Exemplo n.º 10
0
/* XXX only ts->{probs,di} modified */
static void handleOverlappedFiles(const rpmts ts, const rpmte p, rpmfi fi)
{
    rpm_loff_t fixupSize = 0;
    rpmps ps;
    const char * fn;
    int i, j;
    rpm_color_t tscolor = rpmtsColor(ts);
    rpm_color_t prefcolor = rpmtsPrefColor(ts);
    rpmfs fs = rpmteGetFileStates(p);
    rpmfs otherFs;

    ps = rpmtsProblems(ts);
    fi = rpmfiInit(fi, 0);
    if (fi != NULL)
    while ((i = rpmfiNext(fi)) >= 0) {
	rpm_color_t oFColor, FColor;
	struct fingerPrint_s * fiFps;
	int otherPkgNum, otherFileNum;
	rpmfi otherFi;
	rpmte otherTe;
	rpmfileAttrs FFlags;
	rpm_mode_t FMode;
	struct rpmffi_s * recs;
	int numRecs;

	if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
	    continue;

	fn = rpmfiFN(fi);
	fiFps = rpmfiFpsIndex(fi, i);
	FFlags = rpmfiFFlags(fi);
	FMode = rpmfiFMode(fi);
	FColor = rpmfiFColor(fi);
	FColor &= tscolor;

	fixupSize = 0;

	/*
	 * Retrieve all records that apply to this file. Note that the
	 * file info records were built in the same order as the packages
	 * will be installed and removed so the records for an overlapped
	 * files will be sorted in exactly the same order.
	 */
	(void) rpmFpHashGetEntry(ts->ht, fiFps, &recs, &numRecs, NULL);

	/*
	 * If this package is being added, look only at other packages
	 * being added -- removed packages dance to a different tune.
	 *
	 * If both this and the other package are being added, overlapped
	 * files must be identical (or marked as a conflict). The
	 * disposition of already installed config files leads to
	 * a small amount of extra complexity.
	 *
	 * If this package is being removed, then there are two cases that
	 * need to be worried about:
	 * If the other package is being added, then skip any overlapped files
	 * so that this package removal doesn't nuke the overlapped files
	 * that were just installed.
	 * If both this and the other package are being removed, then each
	 * file removal from preceding packages needs to be skipped so that
	 * the file removal occurs only on the last occurence of an overlapped
	 * file in the transaction set.
	 *
	 */

	/* Locate this overlapped file in the set of added/removed packages. */
	for (j = 0; j < numRecs && recs[j].p != p; j++)
	    {};

	/* Find what the previous disposition of this file was. */
	otherFileNum = -1;			/* keep gcc quiet */
	otherFi = NULL;
	otherTe = NULL;
	otherFs = NULL;

	for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
	    otherTe = recs[otherPkgNum].p;
	    otherFi = rpmteFI(otherTe);
	    otherFileNum = recs[otherPkgNum].fileno;
	    otherFs = rpmteGetFileStates(otherTe);

	    /* Added packages need only look at other added packages. */
	    if (rpmteType(p) == TR_ADDED && rpmteType(otherTe) != TR_ADDED)
		continue;

	    (void) rpmfiSetFX(otherFi, otherFileNum);

	    /* XXX Happens iff fingerprint for incomplete package install. */
	    if (rpmfsGetAction(otherFs, otherFileNum) != FA_UNKNOWN);
		break;
	}

	oFColor = rpmfiFColor(otherFi);
	oFColor &= tscolor;

	switch (rpmteType(p)) {
	case TR_ADDED:
	  {
	    int reportConflicts =
		!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
	    int done = 0;

	    if (otherPkgNum < 0) {
		/* XXX is this test still necessary? */
		rpmFileAction action;
		if (rpmfsGetAction(fs, i) != FA_UNKNOWN)
		    break;
		if (rpmfiConfigConflict(fi)) {
		    /* Here is a non-overlapped pre-existing config file. */
		    action = (FFlags & RPMFILE_NOREPLACE) ?
			      FA_ALTNAME : FA_BACKUP;
		} else {
		    action = FA_CREATE;
		}
		rpmfsSetAction(fs, i, action);
		break;
	    }

assert(otherFi != NULL);
	    /* Mark added overlapped non-identical files as a conflict. */
	    if (rpmfiCompare(otherFi, fi)) {
		int rConflicts;

		rConflicts = reportConflicts;
		/* Resolve file conflicts to prefer Elf64 (if not forced) ... */
		if (tscolor != 0) {
		    if (FColor & prefcolor) {
			/* ... last file of preferred colour is installed ... */
			if (!XFA_SKIPPING(rpmfsGetAction(fs, i))) {
			    /* XXX static helpers are order dependent. Ick. */
			    if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade")
			     && strcmp(fn, "/usr/sbin/glibc_post_upgrade"))
				rpmfsSetAction(otherFs, otherFileNum, FA_SKIPCOLOR);
			}
			rpmfsSetAction(fs, i, FA_CREATE);
			rConflicts = 0;
		    } else
		    if (oFColor & prefcolor) {
			/* ... first file of preferred colour is installed ... */
			if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
			    rpmfsSetAction(otherFs, otherFileNum, FA_CREATE);
			rpmfsSetAction(fs, i, FA_SKIPCOLOR);
			rConflicts = 0;
		    }
		    done = 1;
		}
		if (rConflicts) {
		    rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
			rpmteNEVRA(p), rpmteKey(p),
			fn, NULL,
			rpmteNEVRA(otherTe),
			0);
		}
	    }

	    /* Try to get the disk accounting correct even if a conflict. */
	    fixupSize = rpmfiFSize(otherFi);

	    if (rpmfiConfigConflict(fi)) {
		/* Here is an overlapped  pre-existing config file. */
		rpmFileAction action;
		action = (FFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SKIP;
		rpmfsSetAction(fs, i, action);
	    } else {
		if (!done)
		    rpmfsSetAction(fs, i, FA_CREATE);
	    }
	  } break;

	case TR_REMOVED:
	    if (otherPkgNum >= 0) {
		assert(otherFi != NULL);
                /* Here is an overlapped added file we don't want to nuke. */
		if (rpmfsGetAction(otherFs, otherFileNum) != FA_ERASE) {
		    /* On updates, don't remove files. */
		    rpmfsSetAction(fs, i, FA_SKIP);
		    break;
		}
		/* Here is an overlapped removed file: skip in previous. */
		rpmfsSetAction(otherFs, otherFileNum, FA_SKIP);
	    }
	    if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
		break;
	    if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
		break;
	    if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG))) {
		rpmfsSetAction(fs, i, FA_ERASE);
		break;
	    }
		
	    /* Here is a pre-existing modified config file that needs saving. */
	    {	pgpHashAlgo algo = 0;
		size_t diglen = 0;
		const unsigned char *digest;
		if ((digest = rpmfiFDigest(fi, &algo, &diglen))) {
		    unsigned char fdigest[diglen];
		    if (!rpmDoDigest(algo, fn, 0, fdigest, NULL) &&
			memcmp(digest, fdigest, diglen)) {
			rpmfsSetAction(fs, i, FA_BACKUP);
			break;
		    }
		}
	    }
	    rpmfsSetAction(fs, i, FA_ERASE);
	    break;
	}

	/* Update disk space info for a file. */
	rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
		       rpmfiFReplacedSize(fi), fixupSize, rpmfsGetAction(fs, i));

    }
    ps = rpmpsFree(ps);
}
Exemplo n.º 11
0
int rpmtsCheck(rpmts ts)
{
    rpm_color_t tscolor = rpmtsColor(ts);
    rpmtsi pi = NULL; rpmte p;
    int closeatexit = 0;
    int rc = 0;
    depCache dcache = NULL;
    filedepHash confilehash = NULL;	/* file conflicts of installed packages */
    filedepHash connotfilehash = NULL;	/* file conflicts of installed packages */
    depexistsHash connothash = NULL;
    filedepHash reqfilehash = NULL;	/* file requires of installed packages */
    filedepHash reqnotfilehash = NULL;	/* file requires of installed packages */
    depexistsHash reqnothash = NULL;
    fingerPrintCache fpc = NULL;
    rpmdb rdb = NULL;
    
    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);

    /* Do lazy, readonly, open of rpm database. */
    rdb = rpmtsGetRdb(ts);
    if (rdb == NULL && rpmtsGetDBMode(ts) != -1) {
	if ((rc = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0)
	    goto exit;
	rdb = rpmtsGetRdb(ts);
	closeatexit = 1;
    }

    if (rdb)
	rpmdbCtrl(rdb, RPMDB_CTRL_LOCK_RO);

    /* XXX FIXME: figure some kind of heuristic for the cache size */
    dcache = depCacheCreate(5001, rstrhash, strcmp,
				     (depCacheFreeKey)rfree, NULL);

    /* build hashes of all confilict sdependencies */
    confilehash = filedepHashCreate(257, rstrhash, strcmp,
				    (filedepHashFreeKey)rfree,
				    (filedepHashFreeData)rfree);
    connothash = depexistsHashCreate(257, rstrhash, strcmp,
				    (filedepHashFreeKey)rfree);
    connotfilehash = filedepHashCreate(257, rstrhash, strcmp,
				    (filedepHashFreeKey)rfree,
				    (filedepHashFreeData)rfree);
    addIndexToDepHashes(ts, RPMTAG_CONFLICTNAME, NULL, confilehash, connothash, connotfilehash);
    if (!filedepHashNumKeys(confilehash))
	confilehash = filedepHashFree(confilehash);
    if (!depexistsHashNumKeys(connothash))
	connothash= depexistsHashFree(connothash);
    if (!filedepHashNumKeys(connotfilehash))
	connotfilehash = filedepHashFree(connotfilehash);

    /* build hashes of all requires dependencies */
    reqfilehash = filedepHashCreate(8191, rstrhash, strcmp,
				    (filedepHashFreeKey)rfree,
				    (filedepHashFreeData)rfree);
    reqnothash = depexistsHashCreate(257, rstrhash, strcmp,
				    (filedepHashFreeKey)rfree);
    reqnotfilehash = filedepHashCreate(257, rstrhash, strcmp,
				    (filedepHashFreeKey)rfree,
				    (filedepHashFreeData)rfree);
    addIndexToDepHashes(ts, RPMTAG_REQUIRENAME, NULL, reqfilehash, reqnothash, reqnotfilehash);
    if (!filedepHashNumKeys(reqfilehash))
	reqfilehash = filedepHashFree(reqfilehash);
    if (!depexistsHashNumKeys(reqnothash))
	reqnothash= depexistsHashFree(reqnothash);
    if (!filedepHashNumKeys(reqnotfilehash))
	reqnotfilehash = filedepHashFree(reqnotfilehash);

    /*
     * Look at all of the added packages and make sure their dependencies
     * are satisfied.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
	rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME));

	rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_REQUIRENAME),
		tscolor);
	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_CONFLICTNAME),
		tscolor);
	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_OBSOLETENAME),
		tscolor);

	/* Check provides against conflicts in installed packages. */
	while (rpmdsNext(provides) >= 0) {
	    const char *dep = rpmdsN(provides);
	    checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, dep);
	    if (reqnothash && depexistsHashHasEntry(reqnothash, dep))
		checkNotInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, dep);
	}

	/* Skip obsoletion checks for source packages (ie build) */
	if (rpmteIsSource(p))
	    continue;

	/* Check package name (not provides!) against installed obsoletes */
	checkInstDeps(ts, dcache, p, RPMTAG_OBSOLETENAME, rpmteN(p));

	/* Check filenames against installed conflicts */
        if (confilehash || reqnotfilehash) {
	    rpmfiles files = rpmteFiles(p);
	    rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD);
	    while (rpmfiNext(fi) >= 0) {
		if (confilehash)
		    checkInstFileDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fi, 0, confilehash, &fpc);
		if (reqnotfilehash)
		    checkInstFileDeps(ts, dcache, p, RPMTAG_REQUIRENAME, fi, 1, reqnotfilehash, &fpc);
	    }
	    rpmfiFree(fi);
	    rpmfilesFree(files);
	}
    }
    rpmtsiFree(pi);

    /*
     * Look at the removed packages and make sure they aren't critical.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
	rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME));

	rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	/* Check provides and filenames against installed dependencies. */
	while (rpmdsNext(provides) >= 0) {
	    const char *dep = rpmdsN(provides);
	    checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, dep);
	    if (connothash && depexistsHashHasEntry(connothash, dep))
		checkNotInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, dep);
	}

	if (reqfilehash || connotfilehash) {
	    rpmfiles files = rpmteFiles(p);
	    rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD);;
	    while (rpmfiNext(fi) >= 0) {
		if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) {
		    if (reqfilehash)
			checkInstFileDeps(ts, dcache, p, RPMTAG_REQUIRENAME, fi, 0, reqfilehash, &fpc);
		    if (connotfilehash)
			checkInstFileDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fi, 1, connotfilehash, &fpc);
		}
	    }
	    rpmfiFree(fi);
	    rpmfilesFree(files);
	}
    }
    rpmtsiFree(pi);

    if (rdb)
	rpmdbCtrl(rdb, RPMDB_CTRL_UNLOCK_RO);

exit:
    depCacheFree(dcache);
    filedepHashFree(confilehash);
    filedepHashFree(connotfilehash);
    depexistsHashFree(connothash);
    filedepHashFree(reqfilehash);
    filedepHashFree(reqnotfilehash);
    depexistsHashFree(reqnothash);
    fpCacheFree(fpc);

    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);

    if (closeatexit)
	(void) rpmtsCloseDB(ts);
    return rc;
}
Exemplo n.º 12
0
/*
 * Check for previously added versions and obsoletions.
 * Return index where to place this element, or -1 to skip.
 * XXX OBSOLETENAME is a bit of a hack, but gives us what
 * we want from rpmal: we're only interested in added package
 * names here, not their provides.
 */
static int findPos(rpmts ts, rpm_color_t tscolor, rpmte te, int upgrade)
{
    tsMembers tsmem = rpmtsMembers(ts);
    int oc = tsmem->orderCount;
    int skip = 0;
    const char * name = rpmteN(te);
    const char * evr = rpmteEVR(te);
    rpmte p;
    rpmstrPool tspool = rpmtsPool(ts);
    rpmds oldChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME,
				   name, evr, (RPMSENSE_LESS));
    rpmds newChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME,
				   name, evr, (RPMSENSE_GREATER));
    rpmds sameChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME,
				    name, evr, (RPMSENSE_EQUAL));
    rpmds obsChk = rpmteDS(te, RPMTAG_OBSOLETENAME);

    /* If obsoleting package has already been added, skip this. */
    if ((p = checkObsoleted(tsmem->addedPackages, rpmteDS(te, RPMTAG_NAME)))) {
	skip = 1;
	goto exit;
    }

    /* If obsoleted package has already been added, replace with this. */
    rpmdsInit(obsChk);
    while (rpmdsNext(obsChk) >= 0) {
	/* XXX Obsoletes are not colored */
	if ((p = checkAdded(tsmem->addedPackages, 0, te, obsChk))) {
	    goto exit;
	}
    }

    /* If same NEVR has already been added, skip this. */
    if ((p = checkAdded(tsmem->addedPackages, tscolor, te, sameChk))) {
	skip = 1;
	goto exit;
    }

    /* On upgrades... */
    if (upgrade) {
	/* ...if newer NEVR has already been added, skip this. */
	if ((p = checkAdded(tsmem->addedPackages, tscolor, te, newChk))) {
	    skip = 1;
	    goto exit;
	}

	/* ...if older NEVR has already been added, replace with this. */
	if ((p = checkAdded(tsmem->addedPackages, tscolor, te, oldChk))) {
	    goto exit;
	}
    }

exit:
    /* If we found a previous element we've something to say */
    if (p != NULL && rpmIsVerbose()) {
	const char *msg = skip ?
		    _("package %s was already added, skipping %s\n") :
		    _("package %s was already added, replacing with %s\n");
	rpmlog(RPMLOG_WARNING, msg, rpmteNEVRA(p), rpmteNEVRA(te));
    }

    /* If replacing a previous element, find out where it is. Pooh. */
    if (!skip && p != NULL) {
	for (oc = 0; oc < tsmem->orderCount; oc++) {
	    if (p == tsmem->order[oc])
		break;
	}
    }

    rpmdsFree(oldChk);
    rpmdsFree(newChk);
    rpmdsFree(sameChk);
    return (skip) ? -1 : oc;
}
Exemplo n.º 13
0
static JSBool
rpmte_getprop(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    void * ptr = JS_GetInstancePrivate(cx, obj, &rpmteClass, NULL);
    rpmte te = ptr;
    jsint tiny = JSVAL_TO_INT(id);

    /* XXX the class has ptr == NULL, instances have ptr != NULL. */
    if (ptr == NULL)
	return JS_TRUE;

    switch (tiny) {
    case _DEBUG:
	*vp = INT_TO_JSVAL(_debug);
	break;
    case _TYPE:
	*vp = INT_TO_JSVAL(rpmteType(te));	/* XXX should be string */
	break;
    case _N:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteN(te)));
	break;
    case _E:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteE(te)));
	break;
    case _V:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteV(te)));
	break;
    case _R:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteR(te)));
	break;
    case _A:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteA(te)));
	break;
    case _O:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteO(te)));
	break;
    case _NEVR:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteNEVR(te)));
	break;
    case _NEVRA:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteNEVRA(te)));
	break;
    case _PKGID:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmtePkgid(te)));
	break;
    case _HDRID:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteHdrid(te)));
	break;
    case _COLOR:
	*vp = INT_TO_JSVAL(rpmteColor(te));
	break;
    case _PKGFSIZE:
	*vp = INT_TO_JSVAL(rpmtePkgFileSize(te));
	break;
    case _BREADTH:
	*vp = INT_TO_JSVAL(rpmteBreadth(te));
	break;
    case _DEPTH:
	*vp = INT_TO_JSVAL(rpmteDepth(te));
	break;
    case _NPREDS:
	*vp = INT_TO_JSVAL(rpmteNpreds(te));
	break;
    case _DEGREE:
	*vp = INT_TO_JSVAL(rpmteDegree(te));
	break;
    case _PARENT:
#ifdef	DYING
	*vp = INT_TO_JSVAL(rpmteColor(te));
#else
	*vp = JSVAL_VOID;
#endif
	break;
    case _TREE:
	*vp = INT_TO_JSVAL(rpmteTree(te));
	break;
    case _ADDEDKEY:
	/* XXX FIXME */
	*vp = INT_TO_JSVAL((int)((long)rpmteAddedKey(te)));
	break;
    case _DBOFFSET:
	*vp = INT_TO_JSVAL(rpmteDBOffset(te));
	break;
#ifdef	NOTYET
    case _KEY:
	*vp = INT_TO_JSVAL(rpmteColor(te));
	break;
#endif
    case _SOURCERPM:
	*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, rpmteSourcerpm(te)));
	break;
    default:
	break;
    }

    return JS_TRUE;
}
Exemplo n.º 14
0
int rpmtsCheck(rpmts ts)
{
    rpm_color_t tscolor = rpmtsColor(ts);
    rpmtsi pi = NULL; rpmte p;
    int closeatexit = 0;
    int rc = 0;
    depCache dcache = NULL;
    conflictsCache confcache = NULL;
    
    (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);

    /* Do lazy, readonly, open of rpm database. */
    if (rpmtsGetRdb(ts) == NULL && rpmtsGetDBMode(ts) != -1) {
	if ((rc = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0)
	    goto exit;
	closeatexit = 1;
    }

    /* XXX FIXME: figure some kind of heuristic for the cache size */
    dcache = depCacheCreate(5001, rstrhash, strcmp,
				     (depCacheFreeKey)rfree, NULL);

    confcache = conflictsCacheCreate(257, rstrhash, strcmp,
				     (depCacheFreeKey)rfree);
    if (confcache) {
	rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMTAG_CONFLICTNAME);
	if (ii) {
	    char *key;
	    size_t keylen;
	    while ((rpmdbIndexIteratorNext(ii, (const void**)&key, &keylen)) == 0) {
		char *k;
		if (!key || keylen == 0 || key[0] != '/')
		    continue;
		k = rmalloc(keylen + 1);
		memcpy(k, key, keylen);
		k[keylen] = 0;
		conflictsCacheAddEntry(confcache, k);
	    }
	    rpmdbIndexIteratorFree(ii);
	}
    }

    
    /*
     * Look at all of the added packages and make sure their dependencies
     * are satisfied.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
	rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME));

	rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_REQUIRENAME),
		NULL, tscolor);
	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_CONFLICTNAME),
		NULL, tscolor);
	checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_OBSOLETENAME),
		NULL, tscolor);

	/* Check provides against conflicts in installed packages. */
	while (rpmdsNext(provides) >= 0) {
	    checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, rpmdsN(provides));
	}

	/* Skip obsoletion checks for source packages (ie build) */
	if (rpmteIsSource(p))
	    continue;

	/* Check package name (not provides!) against installed obsoletes */
	checkInstDeps(ts, dcache, p, RPMTAG_OBSOLETENAME, rpmteN(p));

	/* Check filenames against installed conflicts */
        if (conflictsCacheNumKeys(confcache)) {
	    rpmfi fi = rpmfiInit(rpmteFI(p), 0);
	    while (rpmfiNext(fi) >= 0) {
		const char *fn = rpmfiFN(fi);
		if (!conflictsCacheHasEntry(confcache, fn))
		    continue;
		checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fn);
	    }
	}
    }
    rpmtsiFree(pi);

    /*
     * Look at the removed packages and make sure they aren't critical.
     */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
	rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME));
	rpmfi fi = rpmfiInit(rpmteFI(p), 0);

	rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n",
		rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));

	/* Check provides and filenames against installed dependencies. */
	while (rpmdsNext(provides) >= 0) {
	    checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmdsN(provides));
	}

	while (rpmfiNext(fi) >= 0) {
	    if (RPMFILE_IS_INSTALLED(rpmfiFState(fi)))
		checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmfiFN(fi));
	}
    }
    rpmtsiFree(pi);

exit:
    depCacheFree(dcache);
    conflictsCacheFree(confcache);

    (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);

    if (closeatexit)
	(void) rpmtsCloseDB(ts);
    return rc;
}