コード例 #1
0
ファイル: rpmal.c プロジェクト: ereshetova/rpm
static void rpmalMakeIndex(rpmal al)
{
    availablePackage alp;
    int i;
    int providesCnt = 0;
    int fileCnt = 0;

    if (al == NULL || al->list == NULL) return;
    if (al->providesHash != NULL || al->fileHash != NULL)
	return;
    for (i = 0; i < al->size; i++) {
	alp = al->list + i;
	if (alp->provides != NULL)
	    providesCnt += rpmdsCount(alp->provides);
	if (alp->fi != NULL)
	    fileCnt += rpmfiFC(alp->fi);
    }

    al->providesHash = rpmalProvidesHashCreate(providesCnt/4+128, rstrhash,
					       strcmp, NULL, NULL);
    al->fileHash = rpmalFileHashCreate(fileCnt/4+128, fileHash, fileCompare,
				       NULL, NULL);

    for (i = 0; i < al->size; i++) {
	alp = al->list + i;
	rpmalAddProvides(al, i, alp->provides);
	rpmalAddFiles(al, i, alp->fi);
    }
}
コード例 #2
0
ファイル: transaction.c プロジェクト: akozumpl/rpm
static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
{
    rpmDiskSpaceInfo dsi = ts->dsi;

    if (dsi == NULL || !dsi->bsize)
	return;
    if (rpmfiFC(rpmteFI(te)) <= 0)
	return;

    for (; dsi->bsize; dsi++) {

	if (dsi->bavail >= 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
	    if (dsi->bneeded > dsi->obneeded) {
		rpmteAddProblem(te, RPMPROB_DISKSPACE, NULL, dsi->mntPoint,
		   (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
		dsi->obneeded = dsi->bneeded;
	    }
	}

	if (dsi->iavail >= 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
	    if (dsi->ineeded > dsi->oineeded) {
		rpmteAddProblem(te, RPMPROB_DISKNODES, NULL, dsi->mntPoint,
			(adj_fs_blocks(dsi->ineeded) - dsi->iavail));
		dsi->oineeded = dsi->ineeded;
	    }
	}
    }
}
コード例 #3
0
ファイル: transaction.c プロジェクト: akozumpl/rpm
/* Add fingerprint for each file not skipped. */
static void addFingerprints(rpmts ts, uint64_t fileCount, rpmFpHash ht, fingerPrintCache fpc)
{
    rpmtsi pi;
    rpmte p;
    rpmfi fi;
    int i;

    rpmFpHash symlinks = rpmFpHashCreate(fileCount/16+16, fpHashFunction, fpEqual, NULL, NULL);

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

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

	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
	rpmfiFpLookup(fi, fpc);
	/* collect symbolic links */
 	fi = rpmfiInit(fi, 0);
	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), rpmfiFC(fi));

    }
    rpmtsiFree(pi);

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

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

	fi = rpmfiInit(rpmteFI(p), 0);
	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
	while ((i = rpmfiNext(fi)) >= 0) {
	    if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i)))
		continue;
	    fpLookupSubdir(symlinks, ht, fpc, p, i);
	}
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
    }
    rpmtsiFree(pi);

    rpmFpHashFree(symlinks);
}
コード例 #4
0
ファイル: rpmfi-rb.c プロジェクト: hahnakane/junkcode
static VALUE
rpmfi_FC_get(VALUE s)
{
    rpmfi fi = rpmfi_ptr(s);
if (_debug)
fprintf(stderr, "==> %s(0x%lx) ptr %p\n", __FUNCTION__, s, fi);
    return INT2FIX(rpmfiFC(fi));
}
コード例 #5
0
ファイル: tagexts.c プロジェクト: Distrotech/rpm
static int filedepTag(Header h, rpmTag tagN, rpmtd td, headerGetFlags hgflags)
{
    rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    rpmds ds = NULL;
    char **fdeps = NULL;
    int numfiles;
    char deptype = 'R';
    int fileix;
    int rc = 0;

    numfiles = rpmfiFC(fi);
    if (numfiles <= 0) {
	goto exit;
    }

    if (tagN == RPMTAG_PROVIDENAME)
	deptype = 'P';
    else if (tagN == RPMTAG_REQUIRENAME)
	deptype = 'R';

    ds = rpmdsNew(h, tagN, 0);
    fdeps = xmalloc(numfiles * sizeof(*fdeps));

    while ((fileix = rpmfiNext(fi)) >= 0) {
	ARGV_t deps = NULL;
	const uint32_t * ddict = NULL;
	int ndx = rpmfiFDepends(fi, &ddict);
	if (ddict != NULL) {
	    while (ndx-- > 0) {
		const char * DNEVR;
		unsigned dix = *ddict++;
		char mydt = ((dix >> 24) & 0xff);
		if (mydt != deptype)
		    continue;
		dix &= 0x00ffffff;
		(void) rpmdsSetIx(ds, dix-1);
		if (rpmdsNext(ds) < 0)
		    continue;
		DNEVR = rpmdsDNEVR(ds);
		if (DNEVR != NULL) {
		    argvAdd(&deps, DNEVR + 2);
		}
	    }
	}
	fdeps[fileix] = deps ? argvJoin(deps, " ") : xstrdup("");
	argvFree(deps);
    }
    td->data = fdeps;
    td->count = numfiles;
    td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
    td->type = RPM_STRING_ARRAY_TYPE;
    rc = 1;

exit:
    rpmfiFree(fi);
    rpmdsFree(ds);
    return rc;
}
コード例 #6
0
ファイル: transaction.c プロジェクト: akozumpl/rpm
/* Calculate total number of files involved in transaction */
static uint64_t countFiles(rpmts ts)
{
    uint64_t fc = 0;
    rpmtsi pi = rpmtsiInit(ts);
    rpmte p;
    while ((p = rpmtsiNext(pi, 0)) != NULL)
	fc += rpmfiFC(rpmteFI(p));
    rpmtsiFree(pi);
    return fc;
}
コード例 #7
0
ファイル: transaction.c プロジェクト: xrg/RPM
/* Get a rpmdbMatchIterator containing all files in
 * the rpmdb that share the basename with one from
 * the transaction.
 * @param ts		transaction set
 * @return		rpmdbMatchIterator sorted
			by (package, fileNum)
 */
static
rpmdbMatchIterator rpmFindBaseNamesInDB(rpmts ts)
{
    rpmtsi pi;  rpmte p;
    rpmfi fi;
    int fc=0;
    rpmdbMatchIterator mi;
    int i, xx;
    const char * baseName;

    /* get number of files in transaction */
    // XXX move to ts
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	if ((fi = rpmteFI(p)) == NULL)
	    continue;   /* XXX can't happen */
	fc += rpmfiFC(fi);
    }
    pi = rpmtsiFree(pi);

    rpmStringSet baseNames = rpmStringSetCreate(fc, hashFunctionString, strcmp, NULL);

    mi = rpmdbInitIterator(rpmtsGetRdb(ts), RPMTAG_BASENAMES, NULL, 0);

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

	if ((fi = rpmteFI(p)) == NULL)
	    continue;   /* XXX can't happen */
	rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
		    ts->orderCount);

	/* Gather all installed headers with matching basename's. */
	fi = rpmfiInit(fi, 0);
	while ((i = rpmfiNext(fi)) >= 0) {
	    size_t keylen;
	    baseName = rpmfiBN(fi);
	    if (rpmStringSetHasEntry(baseNames, baseName))
		continue;

	    keylen = strlen(baseName);
	    if (keylen == 0)
		keylen++;	/* XXX "/" fixup. */
	    xx = rpmdbExtendIterator(mi, baseName, keylen);
	    rpmStringSetAddEntry(baseNames, baseName);
	 }
    }
    pi = rpmtsiFree(pi);
    rpmStringSetFree(baseNames);

    rpmdbSortIterator(mi);
    /* iterator is now sorted by (recnum, filenum) */
    return mi;
}
コード例 #8
0
ファイル: rpmtriggers.c プロジェクト: Conan-Kudo/rpm
void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
{
    rpmdbMatchIterator mi;
    rpmdbIndexIterator ii;
    Header trigH;
    const void *key;
    size_t keylen;
    rpmfiles files;
    rpmds rpmdsTriggers;
    rpmds rpmdsTrigger;
    int tix = 0;

    ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME);
    mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES);
    files = rpmteFiles(te);

    /* Iterate over file triggers in rpmdb */
    while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
	char pfx[keylen + 1];
	memcpy(pfx, key, keylen);
	pfx[keylen] = '\0';
	/* Check if file trigger matches any file in this te */
	rpmfi fi = rpmfilesFindPrefix(files, pfx);
	if (rpmfiFC(fi) > 0) {
	    /* If yes then store it */
	    rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii),
				rpmdbIndexIteratorNumPkgs(ii));
	}
	rpmfiFree(fi);
    }
    rpmdbIndexIteratorFree(ii);

    if (rpmdbGetIteratorCount(mi)) {
	/* Filter triggers and save only trans postun triggers into ts */
	while((trigH = rpmdbNextIterator(mi)) != NULL) {
	    rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0);
	    while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) {
		if ((rpmdsNext(rpmdsTrigger) >= 0) &&
		    (rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) {
		    struct rpmtd_s priorities;

		    headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
				&priorities, HEADERGET_MINMEM);
		    rpmtdSetIndex(&priorities, tix);
		    rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi),
				    tix, *rpmtdGetUint32(&priorities));
		}
		rpmdsFree(rpmdsTrigger);
		tix++;
	    }
	    rpmdsFree(rpmdsTriggers);
	}
    }
    rpmdbFreeIterator(mi);
}
コード例 #9
0
ファイル: tagexts.c プロジェクト: Distrotech/rpm
static int filenlinksTag(Header h, rpmtd td, headerGetFlags hgflags)
{
    rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    rpm_count_t fc = rpmfiFC(fi);

    if (fc > 0) {
	uint32_t *nlinks = xmalloc(fc * sizeof(*nlinks));
	int ix;
	while ((ix = rpmfiNext(fi)) >= 0) {
	    nlinks[ix] = rpmfiFNlink(fi);
	}
	td->data = nlinks;
	td->type = RPM_INT32_TYPE;
	td->count = fc;
	td->flags = RPMTD_ALLOCED;
    }

    rpmfiFree(fi);
    return (fc > 0);
}
コード例 #10
0
ファイル: tagexts.c プロジェクト: Distrotech/rpm
/**
 * Retrieve/generate file classes.
 * @param h		header
 * @retval td		tag data container
 * @param hgflags	header get flags
 * @return		1 on success
 */
static int fileclassTag(Header h, rpmtd td, headerGetFlags hgflags)
{
    rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    int numfiles = rpmfiFC(fi);

    if (numfiles > 0) {
	char **fclasses = xmalloc(numfiles * sizeof(*fclasses));
	int ix;

	rpmfiInit(fi, 0);
	while ((ix = rpmfiNext(fi)) >= 0) {
	    fclasses[ix] = makeFClass(fi);
	}

	td->data = fclasses;
	td->count = numfiles;
	td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
	td->type = RPM_STRING_ARRAY_TYPE;
    }

    rpmfiFree(fi);
    return (numfiles > 0); 
}
コード例 #11
0
ファイル: rpmfi-py.c プロジェクト: avokhmin/RPM5
static int
rpmfi_length(rpmfiObject * s)
	/*@*/
{
    return rpmfiFC(s->fi);
}
コード例 #12
0
ファイル: rpmfi-py.c プロジェクト: avokhmin/RPM5
/*@null@*/
static PyObject *
rpmfi_FC(rpmfiObject * s)
	/*@*/
{
    return Py_BuildValue("i", rpmfiFC(s->fi));
}
コード例 #13
0
ファイル: rpm_packages.cpp プロジェクト: Centurion89/osquery
void genRpmPackageFiles(RowYield& yield, QueryContext& context) {
  auto dropper = DropPrivileges::get();
  if (!dropper->dropTo("nobody") && isUserAdmin()) {
    LOG(WARNING) << "Cannot drop privileges for rpm_package_files";
    return;
  }

  // Isolate RPM/package inspection to the canonical: /usr/lib/rpm.
  RpmEnvironmentManager env_manager;

  if (rpmReadConfigFiles(nullptr, nullptr) != 0) {
    TLOG << "Cannot read RPM configuration files";
    return;
  }

  rpmts ts = rpmtsCreate();
  rpmdbMatchIterator matches;
  if (context.constraints["package"].exists(EQUALS)) {
    auto name = (*context.constraints["package"].getAll(EQUALS).begin());
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size());
  } else {
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
  }

  Header header;
  while ((header = rpmdbNextIterator(matches)) != nullptr) {
    rpmtd td = rpmtdNew();
    rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    std::string package_name = getRpmAttribute(header, RPMTAG_NAME, td);

    auto file_count = rpmfiFC(fi);
    if (file_count <= 0) {
      VLOG(1) << "RPM package " << package_name << " contains 0 files";
      rpmfiFree(fi);
      continue;
    } else if (file_count > MAX_RPM_FILES) {
      VLOG(1) << "RPM package " << package_name << " contains over "
              << MAX_RPM_FILES << " files";
      rpmfiFree(fi);
      continue;
    }

    // Iterate over every file in this package.
    for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) {
      Row r;
      auto path = rpmfiFN(fi);
      r["package"] = package_name;
      r["path"] = (path != nullptr) ? path : "";
      auto username = rpmfiFUser(fi);
      r["username"] = (username != nullptr) ? username : "";
      auto groupname = rpmfiFGroup(fi);
      r["groupname"] = (groupname != nullptr) ? groupname : "";
      r["mode"] = lsperms(rpmfiFMode(fi));
      r["size"] = BIGINT(rpmfiFSize(fi));

      int digest_algo;
      auto digest = rpmfiFDigestHex(fi, &digest_algo);
      if (digest_algo == PGPHASHALGO_SHA256) {
        r["sha256"] = (digest != nullptr) ? digest : "";
      }

      yield(r);
    }

    rpmfiFree(fi);
    rpmtdFree(td);
  }

  rpmdbFreeIterator(matches);
  rpmtsFree(ts);
  rpmFreeRpmrc();
}
コード例 #14
0
ファイル: rpmfi-py.c プロジェクト: OlegGirko/rpm
static PyObject *
rpmfi_FC(rpmfiObject * s, PyObject * unused)
{
    return Py_BuildValue("i", rpmfiFC(s->fi));
}
コード例 #15
0
ファイル: verify.c プロジェクト: avokhmin/RPM5
int showVerifyPackage(QVA_t qva, rpmts ts, Header h)
{
    static int scareMem = 0;
    rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
    int spew = (qva->qva_mode != 'v');	/* XXX no output w verify(...) probe. */
    int ec = 0;
    int i;
rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
uint32_t fc = rpmfiFC(fi);

  {
    /* Verify header digest/signature. */
    if (qva->qva_flags & (VERIFY_DIGEST | VERIFY_SIGNATURE))
    {
	const char * horigin = headerGetOrigin(h);
	const char * msg = NULL;
	size_t uhlen = 0;
	void * uh = headerUnload(h, &uhlen);
	int lvl = headerCheck(rpmtsDig(ts), uh, uhlen, &msg) == RPMRC_FAIL
		? RPMLOG_ERR : RPMLOG_DEBUG;
	rpmlog(lvl, "%s: %s\n",
		(horigin ? horigin : "verify"), (msg ? msg : ""));
	rpmtsCleanDig(ts);
	uh = _free(uh);
	msg = _free(msg);
    }

    /* Verify file digests. */
    if (fc > 0 && (qva->qva_flags & VERIFY_FILES))
#if defined(_OPENMP)
    #pragma omp parallel for private(i) reduction(+:ec)
#endif
    for (i = 0; i < (int)fc; i++) {
	int fflags = fi->fflags[i];
	rpmvf vf;
	int rc;

	/* If not querying %config, skip config files. */
	if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG))
	    continue;

	/* If not querying %doc, skip doc files. */
	if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC))
	    continue;

	/* If not verifying %ghost, skip ghost files. */
	/* XXX the broken!!! logic disables %ghost queries always. */
	if (!(qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST))
	    continue;

	/* Gather per-file data into a carrier. */
	vf = rpmvfNew(ts, fi, i, omitMask);

	/* Verify per-file metadata. */
	rc = rpmvfVerify(vf, spew);
	if (rc)
	    ec += rc;

	(void) rpmvfFree(vf);
	vf = NULL;
    }

    /* Run verify/sanity scripts (if any). */
    if (qva->qva_flags & VERIFY_SCRIPT)
    {
	int rc;

	if (headerIsEntry(h, RPMTAG_VERIFYSCRIPT) ||
	    headerIsEntry(h, RPMTAG_SANITYCHECK))
	{
	    FD_t fdo = fdDup(STDOUT_FILENO);

	    rc = rpmfiSetHeader(fi, h);
	    if ((rc = rpmVerifyScript(qva, ts, fi, fdo)) != 0)
		ec += rc;
	    if (fdo != NULL)
		rc = Fclose(fdo);
	    rc = rpmfiSetHeader(fi, NULL);
	}
    }

    /* Verify dependency assertions. */
    if (qva->qva_flags & VERIFY_DEPS)
    {
	int save_noise = _rpmds_unspecified_epoch_noise;
	int rc;

/*@-mods@*/
	if (rpmIsVerbose())
	    _rpmds_unspecified_epoch_noise = 1;
	if ((rc = verifyDependencies(qva, ts, h)) != 0)
	    ec += rc;
	_rpmds_unspecified_epoch_noise = save_noise;
/*@=mods@*/
    }
  }

    fi = rpmfiFree(fi);

    return ec;
}
コード例 #16
0
ファイル: transaction.c プロジェクト: xrg/RPM
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;
}
コード例 #17
0
ファイル: transaction.c プロジェクト: akozumpl/rpm
static int rpmtsPrepare(rpmts ts)
{
    tsMembers tsmem = rpmtsMembers(ts);
    rpmtsi pi;
    rpmte p;
    rpmfi fi;
    int rc = 0;
    uint64_t fileCount = countFiles(ts);

    fingerPrintCache fpc = fpCacheCreate(fileCount/2 + 10001);
    rpmFpHash ht = rpmFpHashCreate(fileCount/2+1, fpHashFunction, fpEqual,
			     NULL, NULL);
    rpmDiskSpaceInfo dsi;

    rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount);

    /* Skip netshared paths, not our i18n files, and excluded docs */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	if (rpmfiFC(rpmteFI(p)) == 0)
	    continue;
	if (rpmteType(p) == TR_ADDED) {
	    skipInstallFiles(ts, p);
	} else {
	    skipEraseFiles(ts, p);
	}
    }
    rpmtsiFree(pi);

    /* Open rpmdb & enter chroot for fingerprinting if necessary */
    if (rpmdbOpenAll(ts->rdb) || rpmChrootIn()) {
	rc = -1;
	goto exit;
    }
    
    rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, tsmem->orderCount);
    addFingerprints(ts, fileCount, ht, fpc);
    /* check against files in the rpmdb */
    checkInstalledFiles(ts, fileCount, ht, fpc);

    dsi = rpmtsDbDSI(ts);

    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, ht, p, fi);

	rpmtsUpdateDSIrpmDBSize(p, dsi);

	/* 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);
    }
    rpmtsiFree(pi);
    rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, tsmem->orderCount);

    /* return from chroot if done earlier */
    if (rpmChrootOut())
	rc = -1;

    /* File info sets, fp caches etc not needed beyond here, free 'em up. */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	rpmteSetFI(p, NULL);
    }
    rpmtsiFree(pi);

exit:
    rpmFpHashFree(ht);
    fpCacheFree(fpc);
    rpmtsFreeDSI(ts);
    return rc;
}
コード例 #18
0
ファイル: psm.c プロジェクト: pombredanne/rpm-3
rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd,
		char ** specFilePtr, char ** cookie)
{
    rpmfi fi = NULL;
    char * specFile = NULL;
    const char *rootdir = rpmtsRootDir(ts);
    Header h = NULL;
    rpmpsm psm = NULL;
    rpmte te = NULL;
    rpmRC rpmrc;
    int specix = -1;
    struct rpmtd_s filenames;

    rpmtdReset(&filenames);
    rpmrc = rpmReadPackageFile(ts, fd, NULL, &h);
    switch (rpmrc) {
    case RPMRC_NOTTRUSTED:
    case RPMRC_NOKEY:
    case RPMRC_OK:
	break;
    default:
	goto exit;
	break;
    }
    if (h == NULL)
	goto exit;

    rpmrc = RPMRC_FAIL; /* assume failure */

    if (!headerIsSource(h)) {
	rpmlog(RPMLOG_ERR, _("source package expected, binary found\n"));
	goto exit;
    }

    /* src.rpm install can require specific rpmlib features, check them */
    if (!rpmlibDeps(h))
	goto exit;

    if (headerGet(h, RPMTAG_BASENAMES, &filenames, HEADERGET_ALLOC)) {
	struct rpmtd_s td;
	const char *str;
	const char *_cookie = headerGetString(h, RPMTAG_COOKIE);
	if (cookie && _cookie) *cookie = xstrdup(_cookie);
	
	/* Try to find spec by file flags */
	if (_cookie && headerGet(h, RPMTAG_FILEFLAGS, &td, HEADERGET_MINMEM)) {
	    rpmfileAttrs *flags;
	    while (specix < 0 && (flags = rpmtdNextUint32(&td))) {
		if (*flags & RPMFILE_SPECFILE)
		    specix = rpmtdGetIndex(&td);
	    }
	}
	/* Still no spec? Look by filename. */
	while (specix < 0 && (str = rpmtdNextString(&filenames))) {
	    if (rpmFileHasSuffix(str, ".spec")) 
		specix = rpmtdGetIndex(&filenames);
	}
    }

    if (rootdir && rstreq(rootdir, "/"))
	rootdir = NULL;

    /* Macros need to be added before trying to create directories */
    rpmInstallLoadMacros(h);

    if (specix >= 0) {
	const char *bn;

	headerDel(h, RPMTAG_BASENAMES);
	headerDel(h, RPMTAG_DIRNAMES);
	headerDel(h, RPMTAG_DIRINDEXES);

	rpmtdInit(&filenames);
	for (int i = 0; (bn = rpmtdNextString(&filenames)); i++) {
	    int spec = (i == specix);
	    char *fn = rpmGenPath(rpmtsRootDir(ts),
				  spec ? "%{_specdir}" : "%{_sourcedir}", bn);
	    headerPutString(h, RPMTAG_OLDFILENAMES, fn);
	    if (spec) specFile = xstrdup(fn);
	    free(fn);
	}
	headerConvert(h, HEADERCONV_COMPRESSFILELIST);
    } else {
	rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n"));
	goto exit;
    };

    if (rpmtsAddInstallElement(ts, h, NULL, 0, NULL)) {
	goto exit;
    }

    te = rpmtsElement(ts, 0);
    if (te == NULL) {	/* XXX can't happen */
	goto exit;
    }
    rpmteSetFd(te, fd);

    rpmteSetHeader(te, h);
    fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);
    h = headerFree(h);

    if (fi == NULL) {
	goto exit;
    }
    fi->apath = filenames.data; /* Ick */
    rpmteSetFI(te, fi);
    fi = rpmfiFree(fi);

    if (rpmMkdirs(rpmtsRootDir(ts), "%{_topdir}:%{_sourcedir}:%{_specdir}")) {
	goto exit;
    }

    {
	/* set all files to be installed */
	rpmfs fs = rpmteGetFileStates(te);
	int i;
	unsigned int fc = rpmfiFC(fi);
	for (i=0; i<fc; i++) rpmfsSetAction(fs, i, FA_CREATE);
    }

    psm = rpmpsmNew(ts, te);
    psm->goal = PKG_INSTALL;

   	/* FIX: psm->fi->dnl should be owned. */
    if (rpmpsmStage(psm, PSM_PROCESS) == RPMRC_OK)
	rpmrc = RPMRC_OK;

    (void) rpmpsmStage(psm, PSM_FINI);
    rpmpsmFree(psm);

exit:
    if (specFilePtr && specFile && rpmrc == RPMRC_OK)
	*specFilePtr = specFile;
    else
	free(specFile);

    headerFree(h);
    rpmfiFree(fi);

    /* XXX nuke the added package(s). */
    rpmtsClean(ts);

    return rpmrc;
}
コード例 #19
0
ファイル: rpm_packages.cpp プロジェクト: imaxxs/osquery
QueryData genRpmPackageFiles(QueryContext& context) {
  QueryData results;
  if (rpmReadConfigFiles(nullptr, nullptr) != 0) {
    TLOG << "Cannot read RPM configuration files.";
    return results;
  }

  rpmts ts = rpmtsCreate();
  rpmdbMatchIterator matches;
  if (context.constraints["package"].exists()) {
    auto name = (*context.constraints["package"].getAll(EQUALS).begin());
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size());
  } else {
    matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0);
  }

  Header header;
  while ((header = rpmdbNextIterator(matches)) != nullptr) {
    rpmtd td = rpmtdNew();
    rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER);
    auto file_count = rpmfiFC(fi);
    if (file_count <= 0 || file_count > MAX_RPM_FILES) {
      // This package contains no or too many files.
      rpmfiFree(fi);
      continue;
    }

    // Iterate over every file in this package.
    for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) {
      Row r;
      r["package"] = getRpmAttribute(header, RPMTAG_NAME, td);
      auto path = rpmfiFN(fi);
      r["path"] = (path != nullptr) ? path : "";
      auto username = rpmfiFUser(fi);
      r["username"] = (username != nullptr) ? username : "";
      auto groupname = rpmfiFGroup(fi);
      r["groupname"] = (groupname != nullptr) ? groupname : "";
      r["mode"] = lsperms(rpmfiFMode(fi));
      r["size"] = BIGINT(rpmfiFSize(fi));

#ifdef CENTOS_CENTOS6
      // Older versions of rpmlib/rpmip use a hash algorithm enum.
      pgpHashAlgo digest_algo;
#else
      int digest_algo;
#endif
      auto digest = rpmfiFDigestHex(fi, &digest_algo);
      if (digest_algo == PGPHASHALGO_SHA256) {
        r["sha256"] = (digest != nullptr) ? digest : "";
      }

      results.push_back(r);
    }

    rpmfiFree(fi);
    rpmtdFree(td);
  }

  rpmdbFreeIterator(matches);
  rpmtsFree(ts);
  rpmFreeRpmrc();

  return results;
}
コード例 #20
0
ファイル: psm.c プロジェクト: pombredanne/rpm-3
static rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
{
    const rpmts ts = psm->ts;
    rpmfi fi = psm->fi;
    rpmRC rc = RPMRC_OK;

    switch (stage) {
    case PSM_UNKNOWN:
	break;
    case PSM_INIT:
	rpmlog(RPMLOG_DEBUG, "%s: %s has %d files\n",
		psm->goalName, rpmteNEVR(psm->te), rpmfiFC(fi));

	/*
	 * 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.
	 */
	psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
	if (psm->npkgs_installed < 0) {
	    rc = RPMRC_FAIL;
	    break;
	}

	if (psm->goal == PKG_INSTALL) {
	    Header h = rpmteHeader(psm->te);
	    psm->scriptArg = psm->npkgs_installed + 1;

	    psm->amount = 0;
	    psm->total = headerGetNumber(h, RPMTAG_LONGARCHIVESIZE);
	    /* fake up something for packages with no files */
	    if (psm->total == 0)
		psm->total = 100;

	    /* HACK: reinstall abuses te instance to remove old header */
	    if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)
		markReplacedInstance(ts, psm->te);

	    if (rpmfiFC(fi) > 0) {
		struct rpmtd_s filenames;
		rpmTag ftag = RPMTAG_FILENAMES;
	
		if (headerIsEntry(h, RPMTAG_ORIGBASENAMES)) {
		    ftag = RPMTAG_ORIGFILENAMES;
		}
		headerGet(h, ftag, &filenames, HEADERGET_EXT);
		fi->apath = filenames.data; /* Ick.. */
	    }
	    headerFree(h);
	}
	if (psm->goal == PKG_ERASE) {
	    psm->scriptArg = psm->npkgs_installed - 1;

	    psm->amount = 0;
	    psm->total = rpmfiFC(fi) ? rpmfiFC(fi) : 100;
	}
	break;
    case PSM_PRE:
	if (psm->goal == PKG_INSTALL) {
	    psm->scriptTag = RPMTAG_PREIN;
	    psm->sense = RPMSENSE_TRIGGERPREIN;
	    psm->countCorrection = 0;   /* XXX is this correct?!? */

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
		/* Run triggers in other package(s) this package sets off. */
		rc = rpmpsmNext(psm, PSM_TRIGGERS);
		if (rc) break;

		/* Run triggers in this package other package(s) set off. */
		rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
		if (rc) break;
	    }

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
		rc = rpmpsmNext(psm, PSM_SCRIPT);
		if (rc) break;
	    }
	}

	if (psm->goal == PKG_ERASE) {
	    psm->scriptTag = RPMTAG_PREUN;
	    psm->sense = RPMSENSE_TRIGGERUN;
	    psm->countCorrection = -1;

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
		/* Run triggers in this package other package(s) set off. */
		rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
		if (rc) break;

		/* Run triggers in other package(s) this package sets off. */
		rc = rpmpsmNext(psm, PSM_TRIGGERS);
		if (rc) break;
	    }

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
		rc = rpmpsmNext(psm, PSM_SCRIPT);
	}
	break;
    case PSM_PROCESS:
	if (psm->goal == PKG_INSTALL) {
	    int fsmrc = 0;

	    rpmpsmNotify(psm, RPMCALLBACK_INST_START, 0);
	    /* make sure first progress call gets made */
	    rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, 0);

	    if (rpmfiFC(fi) > 0 && !(rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)) {
		FD_t payload = rpmtePayload(psm->te);
		if (payload == NULL) {
		    rc = RPMRC_FAIL;
		    break;
		}

		fsmrc = rpmPackageFilesInstall(psm->ts, psm->te, psm->fi,
				  payload, psm, &psm->failedFile);

		rpmswAdd(rpmtsOp(psm->ts, RPMTS_OP_UNCOMPRESS),
			 fdOp(payload, FDSTAT_READ));
		rpmswAdd(rpmtsOp(psm->ts, RPMTS_OP_DIGEST),
			 fdOp(payload, FDSTAT_DIGEST));

		Fclose(payload);
	    }

	    /* XXX make sure progress reaches 100% */
	    rpmpsmNotify(psm, 0, psm->total);
	    rpmpsmNotify(psm, RPMCALLBACK_INST_STOP, psm->total);

	    if (fsmrc) {
		char *emsg = rpmcpioStrerror(fsmrc);
		rpmlog(RPMLOG_ERR,
			_("unpacking of archive failed%s%s: %s\n"),
			(psm->failedFile != NULL ? _(" on file ") : ""),
			(psm->failedFile != NULL ? psm->failedFile : ""),
			emsg);
		free(emsg);
		rc = RPMRC_FAIL;

		/* XXX notify callback on error. */
		rpmtsNotify(ts, psm->te, RPMCALLBACK_UNPACK_ERROR, 0, 0);
		break;
	    }
	}
	if (psm->goal == PKG_ERASE) {
	    if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)	break;

	    rpmpsmNotify(psm, RPMCALLBACK_UNINST_START, 0);
	    /* make sure first progress call gets made */
	    rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, 0);

	    /* XXX should't we log errors from here? */
	    if (rpmfiFC(fi) > 0 && !(rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)) {
		rc = rpmPackageFilesRemove(psm->ts, psm->te, psm->fi,
				  psm, &psm->failedFile);
	    }

	    /* XXX make sure progress reaches 100% */
	    rpmpsmNotify(psm, 0, psm->total);
	    rpmpsmNotify(psm, RPMCALLBACK_UNINST_STOP, psm->total);
	}
	break;
    case PSM_POST:
	if (psm->goal == PKG_INSTALL) {
	    rpm_time_t installTime = (rpm_time_t) time(NULL);
	    rpmfs fs = rpmteGetFileStates(psm->te);
	    rpm_count_t fc = rpmfsFC(fs);
	    rpm_fstate_t * fileStates = rpmfsGetStates(fs);
	    Header h = rpmteHeader(psm->te);
	    rpm_color_t tscolor = rpmtsColor(ts);

	    if (fileStates != NULL && fc > 0) {
		headerPutChar(h, RPMTAG_FILESTATES, fileStates, fc);
	    }

	    headerPutUint32(h, RPMTAG_INSTALLTIME, &installTime, 1);
	    headerPutUint32(h, RPMTAG_INSTALLCOLOR, &tscolor, 1);
	    headerFree(h);

	    /*
	     * If this package has already been installed, remove it from
	     * the database before adding the new one.
	     */
	    if (rpmteDBInstance(psm->te)) {
		rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
		if (rc) break;
	    }

	    rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
	    if (rc) break;

	    psm->scriptTag = RPMTAG_POSTIN;
	    psm->sense = RPMSENSE_TRIGGERIN;
	    psm->countCorrection = 0;

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
		rc = rpmpsmNext(psm, PSM_SCRIPT);
		if (rc) break;
	    }
	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
		/* Run triggers in other package(s) this package sets off. */
		rc = rpmpsmNext(psm, PSM_TRIGGERS);
		if (rc) break;

		/* Run triggers in this package other package(s) set off. */
		rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
		if (rc) break;
	    }

	    rc = markReplacedFiles(psm);

	}
	if (psm->goal == PKG_ERASE) {

	    psm->scriptTag = RPMTAG_POSTUN;
	    psm->sense = RPMSENSE_TRIGGERPOSTUN;
	    psm->countCorrection = -1;

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
		rc = rpmpsmNext(psm, PSM_SCRIPT);
		if (rc) break;
	    }

	    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
		/* Run triggers in other package(s) this package sets off. */
		rc = rpmpsmNext(psm, PSM_TRIGGERS);
		if (rc) break;
	    }

	    rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
	}
	break;
    case PSM_UNDO:
	break;
    case PSM_FINI:
	if (rc) {
	    char *emsg = rpmcpioStrerror(rc);
	    if (psm->failedFile)
		rpmlog(RPMLOG_ERR,
			_("%s failed on file %s: %s\n"),
			psm->goalName, psm->failedFile, emsg);
	    else
		rpmlog(RPMLOG_ERR, _("%s failed: %s\n"),
			psm->goalName, emsg);
	    free(emsg);

	    /* XXX notify callback on error. */
	    rpmtsNotify(ts, psm->te, RPMCALLBACK_CPIO_ERROR, 0, 0);
	}

	psm->failedFile = _free(psm->failedFile);

	fi->apath = _free(fi->apath);
	break;

    case PSM_CREATE:
	break;
    case PSM_DESTROY:
	break;
    case PSM_SCRIPT:	/* Run current package scriptlets. */
	rc = runInstScript(psm);
	break;
    case PSM_TRIGGERS:
	/* Run triggers in other package(s) this package sets off. */
	rc = runTriggers(psm);
	break;
    case PSM_IMMED_TRIGGERS:
	/* Run triggers in this package other package(s) set off. */
	rc = runImmedTriggers(psm);
	break;

    case PSM_RPMDB_ADD: {
	Header h = rpmteHeader(psm->te);

	if (!headerIsEntry(h, RPMTAG_INSTALLTID)) {
	    rpm_tid_t tid = rpmtsGetTid(ts);
	    if (tid != 0 && tid != (rpm_tid_t)-1)
		headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1);
	}
	
	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
	rc = (rpmdbAdd(rpmtsGetRdb(ts), h) == 0) ? RPMRC_OK : RPMRC_FAIL;
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);

	if (rc == RPMRC_OK)
	    rpmteSetDBInstance(psm->te, headerGetInstance(h));
	headerFree(h);
    }   break;

    case PSM_RPMDB_REMOVE:
	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
	rc = (rpmdbRemove(rpmtsGetRdb(ts), rpmteDBInstance(psm->te)) == 0) ?
						    RPMRC_OK : RPMRC_FAIL;
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
	if (rc == RPMRC_OK)
	    rpmteSetDBInstance(psm->te, 0);
	break;

    default:
	break;
   }

    return rc;
}