/*@access rpmtsi @*/
/*@access rpmts @*/
-/* Internal function to rollback a transaction
- * This is not declared in the header because we not
- * want others calling this directly (or at all).
- */
-rpmRC _rpmtsRollback(rpmts rollbackTransaction);
-
-/* Internal function to add an element to a rollback transaction
- * This is not declared in the header because we not want others
- * calling this directly (or at all).
- */
-rpmRC _rpmtsAddRollbackElement(rpmts rollbackTransaction, rpmts runningTransaction, rpmte te);
+/*@access IDT @*/
+/*@access IDTX @*/
+/*@access FD_t @*/
-/* You might want to move this into the header Jeff (or even
- * to a different file altogether (i.e. the prototype and the
- * the function).
- */
-rpmRC getRepackageHeaderFromTE(rpmte te, rpmts ts, Header *hdrp, char **fn);
-
/* XXX: This is a hack. I needed a to setup a notify callback
* for the rollback transaction, but I did not want to create
* a header for rpminstall.c.
const unsigned long amount,
const unsigned long total,
/*@null@*/ fnpyKey key,
- /*@null@*/ void * data);
+ /*@null@*/ void * data)
+ /*@*/;
/**
*/
Header h;
const char * otherStates;
int i, xx;
-
+
rpmdbMatchIterator mi;
mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
rpmps ps;
const char * fn;
int i, j;
-
+
ps = rpmtsProblems(ts);
fi = rpmfiInit(fi, 0);
if (fi != NULL)
*t++ = '-';
if (rpmteR(p) != NULL) t = stpcpy(t, rpmteR(p));
/*@=boundswrite@*/
-
+
req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
req = rpmdsFree(req);
/*@=compdef =refcounttrans =usereleased @*/
}
-#define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al
-
-int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
+/**
+ * This is not a generalized function to be called from outside
+ * librpm. It is called internally by rpmtsRun() to rollback
+ * a failed transaction.
+ * @param rollbackTransaction rollback transaction
+ * @return RPMRC_OK, or RPMRC_FAIL
+ */
+static rpmRC _rpmtsRollback(rpmts rollbackTransaction)
+ /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
+ /*@modifies rollbackTransaction,
+ rpmGlobalMacroContext, fileSystem, internalState @*/
{
- uint_32 tscolor = rpmtsColor(ts);
- int i, j;
- int ourrc = 0;
- int totalFileCount = 0;
- rpmfi fi;
- sharedFileInfo shared, sharedList;
- int numShared;
- int nexti;
- alKey lastFailKey;
- fingerPrintCache fpc;
- rpmps ps;
- rpmpsm psm;
- rpmtsi pi; rpmte p;
- rpmtsi qi; rpmte q;
- int numAdded;
- int numRemoved;
- rpmts rollbackTransaction = NULL;
- int rollbackOnFailure = 0;
- void * lock;
- int xx;
-
-
- /* XXX programmer error segfault avoidance. */
- if (rpmtsNElements(ts) <= 0)
- return -1;
+ int rc = 0;
+ int numAdded = 0;
+ int numRemoved = 0;
+ int_32 tid;
+ rpmtsi tsi;
+ rpmte te;
+ rpmps ps;
- /* See if we need to rollback on failure */
- rollbackOnFailure = rpmExpandNumeric(
- "%{?_rollback_transaction_on_failure}");
- if(rpmtsGetType(ts) & (RPMTRANS_TYPE_ROLLBACK
- | RPMTRANS_TYPE_AUTOROLLBACK)) {
- rollbackOnFailure = 0;
- }
- /* If we are in test mode, there is no need to rollback on
- * failure (-;
+ /*
+ * Gather information about this rollback transaction for reporting.
+ * 1) Get tid
*/
- if(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) rollbackOnFailure = 0;
-
- 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));
+ tid = rpmtsGetTid(rollbackTransaction);
- ts->probs = rpmpsFree(ts->probs);
- ts->probs = rpmpsCreate();
+ /*
+ * 2) Get number of install elments and erase elements
+ */
+ tsi = rpmtsiInit(rollbackTransaction);
+ while((te = rpmtsiNext(tsi, 0)) != NULL) {
+ switch (rpmteType(te)) {
+ case TR_ADDED:
+ numAdded++;
+ /*@switchbreak@*/ break;
+ case TR_REMOVED:
+ numRemoved++;
+ /*@switchbreak@*/ break;
+ default:
+ /*@switchbreak@*/ break;
+ }
+ }
+ tsi = rpmtsiFree(tsi);
- /* 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);
+ rpmMessage(RPMMESS_NORMAL, _("Transaction failed...rolling back\n"));
+ rpmMessage(RPMMESS_NORMAL,
+ _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
+ numAdded, numRemoved, ctime(&tid), tid);
- /* Open database RDWR for installing packages. */
- if (rpmtsOpenDB(ts, dbmode)) {
- rpmtsFreeLock(lock);
- return -1; /* XXX W2DO? */
- }
+ /* Check the transaction to see if it is doable */
+ rc = rpmtsCheck(rollbackTransaction);
+ ps = rpmtsProblems(rollbackTransaction);
+ if (rc != 0 && rpmpsNumProblems(ps) > 0) {
+ rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
+ rpmpsPrint(NULL, ps);
+ ps = rpmpsFree(ps);
+ return -1;
}
+ ps = rpmpsFree(ps);
- ts->ignoreSet = ignoreSet;
- { const char * currDir = currentDirectory();
- rpmtsSetCurrDir(ts, currDir);
- currDir = _free(currDir);
+ /* Order the transaction */
+ rc = rpmtsOrder(rollbackTransaction);
+ if (rc != 0) {
+ rpmMessage(RPMMESS_ERROR,
+ _("Could not order auto-rollback transaction!\n"));
+ return -1;
}
- (void) rpmtsSetChrootDone(ts, 0);
-
- { int_32 tid = (int_32) 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.
+ /* Run the transaction and print any problems
+ * We want to stay with the original transactions flags except
+ * that we want to add what is essentially a force.
+ * This handles two things in particular:
+ *
+ * 1. We we want to upgrade over a newer package.
+ * 2. If a header for the old package is there we
+ * we want to replace it. No questions asked.
*/
+ rc = rpmtsRun(rollbackTransaction, NULL,
+ RPMPROB_FILTER_REPLACEPKG
+ | RPMPROB_FILTER_REPLACEOLDFILES
+ | RPMPROB_FILTER_REPLACENEWFILES
+ | RPMPROB_FILTER_OLDPACKAGE
+ );
+ ps = rpmtsProblems(rollbackTransaction);
+ if (rc > 0 && rpmpsNumProblems(ps) > 0)
+ rpmpsPrint(stderr, ps);
+ ps = rpmpsFree(ps);
+ rollbackTransaction = rpmtsFree(rollbackTransaction);
-rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts));
- ps = rpmtsProblems(ts);
- /* The ordering doesn't matter here */
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
- rpmdbMatchIterator mi;
- int fc;
-
- if ((fi = rpmtsiFi(pi)) == NULL)
- continue; /* XXX can't happen */
- fc = rpmfiFC(fi);
-
- if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH) && !tscolor)
- if (!archOkay(rpmteA(p)))
- rpmpsAppend(ps, RPMPROB_BADARCH,
- rpmteNEVR(p), rpmteKey(p),
- rpmteA(p), NULL,
- NULL, 0);
+ return rc;
+}
- if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS))
- if (!osOkay(rpmteO(p)))
- rpmpsAppend(ps, RPMPROB_BADOS,
- rpmteNEVR(p), rpmteKey(p),
- rpmteO(p), NULL,
- NULL, 0);
+/**
+ * Get the repackaged header and filename from the repackage directory.
+ * @todo Find a suitable home for this function.
+ * @todo This function creates an IDTX everytime it is called. Needs to
+ * be made more efficient (only create on per running transaction).
+ * @param ts rpm transaction
+ * @param te transaction element
+ * @return hdrp Repackaged header
+ * @return fn Repackaged package's path (transaction key)
+ * @return RPMRC_NOTFOUND or RPMRC_OK
+ */
+static rpmRC getRepackageHeaderFromTE(rpmts ts, rpmte te,
+ /*@out@*/ /*@null@*/ Header *hdrp,
+ /*@out@*/ /*@null@*/ const char **fn)
+ /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
+ /*@modifies ts, *hdrp, *fn,
+ rpmGlobalMacroContext, fileSystem, internalState @*/
+{
+ int_32 tid;
+ const char * name;
+ const char * rpname = NULL;
+ const char * _repackage_dir = NULL;
+ const char * globStr = "-*.rpm";
+ char * rp = NULL; /* Rollback package name */
+ IDTX rtids = NULL;
+ IDT rpIDT;
+ int nrids = 0;
+ int nb; /* Number of bytes */
+ Header h = NULL;
+ int rc = RPMRC_NOTFOUND; /* Assume we do not find it*/
+ int xx;
- 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);
- }
+ rpmMessage(RPMMESS_DEBUG,
+ _("Getting repackaged header from transaction element\n"));
- 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));
- }
+ /* Set header pointer to null if its not already */
+ if (hdrp)
+ *hdrp = NULL;
+ if (fn)
+ *fn = NULL;
- while (rpmdbNextIterator(mi) != NULL) {
- rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
- rpmteNEVR(p), rpmteKey(p),
- NULL, NULL,
- NULL, 0);
- /*@innerbreak@*/ break;
- }
- mi = rpmdbFreeIterator(mi);
- }
+ /* Get the TID of the current transaction */
+ tid = rpmtsGetTid(ts);
+ /* Need the repackage dir if the user want to
+ * rollback on a failure.
+ */
+ _repackage_dir = rpmExpand("%{?_repackage_dir}", NULL);
+ if (_repackage_dir == NULL) goto exit;
- /* Count no. of files (if any). */
- totalFileCount += fc;
+ /* Build the glob string to find the possible repackaged
+ * packages for this package.
+ */
+ name = rpmteN(te);
+ nb = strlen(_repackage_dir) + strlen(name) + strlen(globStr) + 2;
+ rp = memset((char *) malloc(nb), 0, nb);
+ xx = snprintf(rp, nb, "%s/%s%s.rpm", _repackage_dir, name, globStr);
+ /* Get the index of possible repackaged packages */
+ rpmMessage(RPMMESS_DEBUG, _("\tLooking for %s...\n"), rp);
+ rtids = IDTXglob(ts, rp, RPMTAG_REMOVETID);
+ rp = _free(rp);
+ if (rtids != NULL) {
+ rpmMessage(RPMMESS_DEBUG, _("\tMatches found.\n"));
+ rpIDT = rtids->idt;
+ nrids = rtids->nidt;
+ } else {
+ rpmMessage(RPMMESS_DEBUG, _("\tNo matches found.\n"));
+ goto exit;
}
- pi = rpmtsiFree(pi);
- ps = rpmpsFree(ps);
- /* The ordering doesn't matter here */
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
- int fc;
+ /* Now walk through index until we find the package (or we have
+ * exhausted the index.
+ */
+/*@-branchstate@*/
+ do {
+ /* If index is null we have exhausted the list and need to
+ * get out of here...the repackaged package was not found.
+ */
+ if (rpIDT == NULL) {
+ rpmMessage(RPMMESS_DEBUG, _("\tRepackaged package not found!.\n"));
+ break;
+ }
- if ((fi = rpmtsiFi(pi)) == NULL)
- continue; /* XXX can't happen */
- fc = rpmfiFC(fi);
+ /* Is this the same tid. If not decrement the list and continue */
+ if (rpIDT->val.u32 != tid) {
+ nrids--;
+ if (nrids > 0)
+ rpIDT++;
+ else
+ rpIDT = NULL;
+ continue;
+ }
- totalFileCount += fc;
+ /* OK, the tid matches. Now lets see if the name is the same.
+ * If I could not get the name from the package, I will go onto
+ * the next one. Perhaps I should return an error at this
+ * point, but if this was not the correct one, at least the correct one
+ * would be found.
+ * XXX: Should I be matching name and arch?
+ */
+ rpmMessage(RPMMESS_DEBUG, _("\tREMOVETID matched INSTALLTID.\n"));
+ if (headerGetEntry(rpIDT->h, RPMTAG_NAME, NULL, (void **) &rpname, NULL)) {
+ rpmMessage(RPMMESS_DEBUG, _("\t\tName: %s.\n"), rpname);
+ if (!strcmp(name,rpname)) {
+ /* It matched we have a canidate */
+ h = headerLink(rpIDT->h);
+ nb = strlen(rpIDT->key) + 1;
+ rp = memset((char *) malloc(nb), 0, nb);
+ rp = strncat(rp, rpIDT->key, nb);
+ rc = RPMRC_OK;
+ break;
+ }
+ }
+
+ /* Decrement list */
+ nrids--;
+ if (nrids > 0)
+ rpIDT++;
+ else
+ rpIDT = NULL;
+ } while (1);
+/*@=branchstate@*/
+
+exit:
+ if (rc != RPMRC_NOTFOUND && h != NULL && hdrp != NULL) {
+ rpmMessage(RPMMESS_DEBUG, _("\tRepackaged Package was %s...\n"), rp);
+ if (hdrp != NULL)
+ *hdrp = headerLink(h);
+/*@-branchstate@*/
+ if (fn != NULL)
+ *fn = rp;
+ else
+ rp = _free(rp);
+/*@=branchstate@*/
}
- pi = rpmtsiFree(pi);
+ if (h != NULL)
+ h = headerFree(h);
+ rtids = IDTXfree(rtids);
+ return rc;
+}
+/**
+ * This is not a generalized function to be called from outside
+ * librpm. It is called internally by rpmtsRun() to add elements
+ * to its rollback transaction.
+ * @param rollbackTransaction rollback transaction
+ * @param runningTransaction running transaction (the one you want to rollback)
+ * @param te Transaction element.
+ * @return RPMRC_OK, or RPMRC_FAIL
+ */
+static rpmRC _rpmtsAddRollbackElement(rpmts rollbackTransaction,
+ rpmts runningTransaction, rpmte te)
+ /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
+ /*@modifies rollbackTransaction, runningTransaction,
+ rpmGlobalMacroContext, fileSystem, internalState @*/
+{
+ Header h = NULL;
+ Header rph = NULL;
+ char * rpn;
+ unsigned int db_instance = 0;
+ rpmtsi pi;
+ rpmte p;
+ int rc = RPMRC_FAIL; /* Assume Failure */
- /* Run pre-transaction scripts, but only if there are no known
- * problems up to this point. */
- if (!((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
- || (ts->probs->numProblems &&
- (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) {
- rpmMessage(RPMMESS_DEBUG, _("running pre-transaction scripts\n"));
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
- if ((fi = rpmtsiFi(pi)) == NULL)
- continue; /* XXX can't happen */
+ switch(rpmteType(te)) {
+ case TR_ADDED:
+ { rpmdbMatchIterator mi;
- p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
- rpmteKey(p), ts->notifyData);
- p->h = NULL;
- if (rpmteFd(p) != NULL) {
- rpmVSFlags ovsflags = rpmtsVSFlags(ts);
- rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
- rpmRC rpmrc;
- ovsflags = rpmtsSetVSFlags(ts, vsflags);
- rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
- rpmteNEVR(p), &p->h);
- vsflags = rpmtsSetVSFlags(ts, ovsflags);
- switch (rpmrc) {
- default:
- /*@-noeffectuncon@*/ /* FIX: notify annotations */
- p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
- 0, 0,
- rpmteKey(p), ts->notifyData);
- /*@=noeffectuncon@*/
- p->fd = NULL;
- /*@innerbreak@*/ break;
- case RPMRC_NOTTRUSTED:
- case RPMRC_NOKEY:
- case RPMRC_OK:
- /*@innerbreak@*/ break;
- }
- }
+ rpmMessage(RPMMESS_DEBUG,
+ _("Adding install element to auto-rollback transaction.\n"));
- if (rpmteFd(p) != NULL) {
- fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
- if (fi != NULL) { /* XXX can't happen */
- fi->te = p;
- p->fi = fi;
- }
- psm = rpmpsmNew(ts, p, p->fi);
- psm->scriptTag = RPMTAG_PRETRANS;
- psm->progTag = RPMTAG_PRETRANSPROG;
- xx = rpmpsmStage(psm, PSM_SCRIPT);
- psm = rpmpsmFree(psm);
+ /* Get the header for this package from the database
+ * First get the database instance (the key).
+ */
+ db_instance = rpmteDBInstance(te);
+ if (db_instance == 0) {
+ /* Could not get the db instance: WTD! */
+ rpmMessage(RPMMESS_FATALERROR,
+ _("Could not get install element database instance!\n"));
+ break;
+ }
- (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
- rpmteKey(p), ts->notifyData);
- p->fd = NULL;
- p->h = headerFree(p->h);
+ /* Now suck the header out of the database */
+ mi = rpmtsInitIterator(rollbackTransaction,
+ RPMDBI_PACKAGES, &db_instance, sizeof(db_instance));
+ h = rpmdbNextIterator(mi);
+ if (h != NULL) h = headerLink(h);
+ mi = rpmdbFreeIterator(mi);
+ if (h == NULL) {
+ /* Header was not there??? */
+ rpmMessage(RPMMESS_FATALERROR,
+ _("Could not get header for auto-rollback transaction!\n"));
+ break;
+ }
+
+ /* Now see if there is a repackaged package for this */
+ rc = getRepackageHeaderFromTE(runningTransaction, te, &rph, &rpn);
+ switch(rc) {
+ case RPMRC_OK:
+ /* Add the install element, as we had a repackaged package */
+ rpmMessage(RPMMESS_DEBUG,
+ _("\tAdded repackaged package header: %s.\n"), rpn);
+ rc = rpmtsAddInstallElement(rollbackTransaction, headerLink(rph),
+ (fnpyKey) rpn, 1, te->relocs);
+ /*@innerbreak@*/ break;
+
+ case RPMRC_NOTFOUND:
+ /* Add the header as an erase element, we did not
+ * have a repackaged package
+ */
+ rpmMessage(RPMMESS_DEBUG, _("\tAdded erase element.\n"));
+ rc = rpmtsAddEraseElement(rollbackTransaction, h, db_instance);
+ /*@innerbreak@*/ break;
+
+ default:
+ /* Not sure what to do on failure...just give up */
+ rpmMessage(RPMMESS_FATALERROR,
+ _("Could not get repackaged header for auto-rollback transaction!\n"));
+ /*@innerbreak@*/ break;
+ }
+ } break;
+
+ case TR_REMOVED:
+ rpmMessage(RPMMESS_DEBUG,
+ _("Add erase element to auto-rollback transaction.\n"));
+
+ /* See if this element has already been added as an upgrade.
+ * If so we want to do nothing.
+ */
+ pi = rpmtsiInit(rollbackTransaction);
+ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
+ if (rpmteType(p) == TR_ADDED) continue;
+ if (!strcmp(rpmteN(p), rpmteN(te))) {
+ rpmMessage(RPMMESS_DEBUG, _("\tFound existing upgrade element.\n"));
+ rpmMessage(RPMMESS_DEBUG, _("\tNot adding erase element for %s.\n"),
+ rpmteN(te));
+ rc = RPMRC_OK;
+ pi = rpmtsiFree(pi);
+ /*@loopbreak@*/ break;
}
}
pi = rpmtsiFree(pi);
- }
-
- /* ===============================================
- * 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.
- */
-rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount);
- numAdded = numRemoved = 0;
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, 0)) != NULL) {
- int fc;
+ /* Get the repackage header from the current transaction
+ * element.
+ */
+ rc = getRepackageHeaderFromTE(runningTransaction, te, &rph, &rpn);
+ switch(rc) {
+ case RPMRC_OK:
+ /* Add the install element */
+ rpmMessage(RPMMESS_DEBUG,
+ _("\tAdded repackaged package %s.\n"), rpn);
+ rc = rpmtsAddInstallElement(rollbackTransaction, rph,
+ (fnpyKey) rpn, 1, te->relocs);
+ if (rc != RPMRC_OK)
+ rpmMessage(RPMMESS_FATALERROR,
+ _("Could not add erase element to auto-rollback transaction.\n"));
+ /*@innerbreak@*/ break;
- if ((fi = rpmtsiFi(pi)) == NULL)
- continue; /* XXX can't happen */
- fc = rpmfiFC(fi);
+ case RPMRC_NOTFOUND:
+ /* Just did not have a repackaged package */
+ rpmMessage(RPMMESS_DEBUG,
+ _("\tNo repackaged package...nothing to do.\n"));
+ rc = RPMRC_OK;
+ /*@innerbreak@*/ break;
- /*@-branchstate@*/
- switch (rpmteType(p)) {
- case TR_ADDED:
- numAdded++;
- fi->record = 0;
- /* Skip netshared paths, not our i18n files, and excluded docs */
- if (fc > 0)
- skipFiles(ts, fi);
- /*@switchbreak@*/ break;
- case TR_REMOVED:
- numRemoved++;
- fi->record = rpmteDBOffset(p);
- /*@switchbreak@*/ break;
+ default:
+ rpmMessage(RPMMESS_FATALERROR,
+ _("Failure reading repackaged package!\n"));
+ /*@innerbreak@*/ break;
}
- /*@=branchstate@*/
+ break;
- fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
+ default:
+ break;
}
- pi = rpmtsiFree(pi);
- if (!rpmtsChrootDone(ts)) {
- const char * rootDir = rpmtsRootDir(ts);
- xx = chdir("/");
- /*@-superuser -noeffect @*/
- if (rootDir != NULL)
- xx = chroot(rootDir);
- /*@=superuser =noeffect @*/
- (void) rpmtsSetChrootDone(ts, 1);
- }
+/* XXX: I want to free this, but if I do then the consumers of
+ * are hosed. Just leaving you a little note Jeff, so you
+ * know that this does introduce a memory leak. I wanted
+ * keep the patch as simple as possible so I am not fixxing
+ * the leak.
+ * if (rpn != NULL)
+ * free(rpn);
+ */
- ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
- fpc = fpCacheCreate(totalFileCount);
+ /* Clean up */
+ if (h != NULL)
+ h = headerFree(h);
+ if (rph != NULL)
+ rph = headerFree(rph);
+ return rc;
+}
+#define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al
- /* ===============================================
- * Add fingerprint for each file not skipped.
- */
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, 0)) != NULL) {
- int fc;
+int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
+{
+ uint_32 tscolor = rpmtsColor(ts);
+ int i, j;
+ int ourrc = 0;
+ int totalFileCount = 0;
+ rpmfi fi;
+ sharedFileInfo shared, sharedList;
+ int numShared;
+ int nexti;
+ alKey lastFailKey;
+ fingerPrintCache fpc;
+ rpmps ps;
+ rpmpsm psm;
+ rpmtsi pi; rpmte p;
+ rpmtsi qi; rpmte q;
+ int numAdded;
+ int numRemoved;
+ rpmts rollbackTransaction = NULL;
+ int rollbackOnFailure = 0;
+ void * lock;
+ int xx;
- (void) rpmdbCheckSignals();
- if ((fi = rpmtsiFi(pi)) == NULL)
- continue; /* XXX can't happen */
- fc = rpmfiFC(fi);
+ /* XXX programmer error segfault avoidance. */
+ if (rpmtsNElements(ts) <= 0)
+ return -1;
- (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
- fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
- /*@-branchstate@*/
- fi = rpmfiInit(fi, 0);
- if (fi != NULL) /* XXX lclint */
- while ((i = rpmfiNext(fi)) >= 0) {
- if (XFA_SKIPPING(fi->actions[i]))
- /*@innercontinue@*/ continue;
- /*@-dependenttrans@*/
- htAddEntry(ts->ht, fi->fps + i, (void *) fi);
- /*@=dependenttrans@*/
+ /* See if we need to rollback on failure */
+ rollbackOnFailure = rpmExpandNumeric(
+ "%{?_rollback_transaction_on_failure}");
+ if (rpmtsGetType(ts) & (RPMTRANS_TYPE_ROLLBACK
+ | RPMTRANS_TYPE_AUTOROLLBACK)) {
+ rollbackOnFailure = 0;
+ }
+ /* If we are in test mode, there is no need to rollback on
+ * failure (-;
+ */
+ if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) rollbackOnFailure = 0;
+
+ 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));
+
+ 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? */
}
- /*@=branchstate@*/
- (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
+ }
+
+ ts->ignoreSet = ignoreSet;
+ { const char * currDir = currentDirectory();
+ rpmtsSetCurrDir(ts, currDir);
+ currDir = _free(currDir);
+ }
+
+ (void) rpmtsSetChrootDone(ts, 0);
+ { int_32 tid = (int_32) time(NULL);
+ (void) rpmtsSetTid(ts, tid);
}
- pi = rpmtsiFree(pi);
- NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount,
- NULL, ts->notifyData));
+ /* Get available space on mounted file systems. */
+ xx = rpmtsInitDSI(ts);
/* ===============================================
- * Compute file disposition for each package in transaction set.
+ * For packages being installed:
+ * - verify package arch/os.
+ * - verify package epoch:version-release is newer.
+ * - count files.
+ * For packages being removed:
+ * - count files.
*/
-rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
+
+rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts));
ps = rpmtsProblems(ts);
+ /* The ordering doesn't matter here */
pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, 0)) != NULL) {
- dbiIndexSet * matches;
- int knownBad;
+ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
+ rpmdbMatchIterator mi;
int fc;
- (void) rpmdbCheckSignals();
-
if ((fi = rpmtsiFi(pi)) == NULL)
continue; /* XXX can't happen */
fc = rpmfiFC(fi);
- NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
- ts->orderCount, NULL, ts->notifyData));
-
- if (fc == 0) continue;
-
- (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
- /* Extract file info for all files in this package from the database. */
- matches = xcalloc(fc, sizeof(*matches));
- if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
- ps = rpmpsFree(ps);
- rpmtsFreeLock(lock);
- return 1; /* XXX WTFO? */
- }
-
- numShared = 0;
- fi = rpmfiInit(fi, 0);
- while ((i = rpmfiNext(fi)) >= 0)
- numShared += dbiIndexSetCount(matches[i]);
-
- /* Build sorted file info list for this package. */
- shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
+ if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH) && !tscolor)
+ if (!archOkay(rpmteA(p)))
+ rpmpsAppend(ps, RPMPROB_BADARCH,
+ rpmteNEVR(p), rpmteKey(p),
+ rpmteA(p), NULL,
+ NULL, 0);
- fi = rpmfiInit(fi, 0);
- while ((i = rpmfiNext(fi)) >= 0) {
- /*
- * Take care not to mark files as replaced in packages that will
- * have been removed before we will get here.
- */
- for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
- int ro;
- ro = dbiIndexRecordOffset(matches[i], j);
- knownBad = 0;
- qi = rpmtsiInit(ts);
- while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
- if (ro == knownBad)
- /*@innerbreak@*/ break;
- if (rpmteDBOffset(q) == ro)
- knownBad = ro;
- }
- qi = rpmtsiFree(qi);
+ if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS))
+ if (!osOkay(rpmteO(p)))
+ rpmpsAppend(ps, RPMPROB_BADOS,
+ rpmteNEVR(p), rpmteKey(p),
+ rpmteO(p), NULL,
+ NULL, 0);
- shared->pkgFileNum = i;
- shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
- shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
- shared->isRemoved = (knownBad == ro);
- shared++;
- }
- matches[i] = dbiFreeIndexSet(matches[i]);
+ 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);
}
- numShared = shared - sharedList;
- shared->otherPkg = -1;
- matches = _free(matches);
-
- /* Sort file info by other package index (otherPkg) */
- qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
-
- /* For all files from this package that are in the database ... */
- /*@-branchstate@*/
- for (i = 0; i < numShared; i = nexti) {
- int beingRemoved;
-
- shared = sharedList + i;
- /* Find the end of the files in the other package. */
- for (nexti = i + 1; nexti < numShared; nexti++) {
- if (sharedList[nexti].otherPkg != shared->otherPkg)
- /*@innerbreak@*/ break;
+ 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));
}
- /* Is this file from a package being removed? */
- beingRemoved = 0;
- if (ts->removedPackages != NULL)
- for (j = 0; j < ts->numRemovedPackages; j++) {
- if (ts->removedPackages[j] != shared->otherPkg)
- /*@innercontinue@*/ continue;
- beingRemoved = 1;
+ while (rpmdbNextIterator(mi) != NULL) {
+ rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
+ rpmteNEVR(p), rpmteKey(p),
+ NULL, NULL,
+ NULL, 0);
/*@innerbreak@*/ break;
}
-
- /* Determine the fate of each file. */
- switch (rpmteType(p)) {
- case TR_ADDED:
- xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
- !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
- /*@switchbreak@*/ break;
- case TR_REMOVED:
- if (!beingRemoved)
- xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
- /*@switchbreak@*/ break;
- }
+ mi = rpmdbFreeIterator(mi);
}
- /*@=branchstate@*/
-
- free(sharedList);
- /* Update disk space needs on each partition for this package. */
- handleOverlappedFiles(ts, p, fi);
+ /* Count no. of files (if any). */
+ totalFileCount += fc;
- /* Check added package has sufficient space on each partition used. */
- switch (rpmteType(p)) {
- case TR_ADDED:
- rpmtsCheckDSIProblems(ts, p);
- /*@switchbreak@*/ break;
- case TR_REMOVED:
- /*@switchbreak@*/ break;
- }
- (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
}
pi = rpmtsiFree(pi);
ps = rpmpsFree(ps);
- if (rpmtsChrootDone(ts)) {
- const char * currDir = rpmtsCurrDir(ts);
- /*@-superuser -noeffect @*/
- xx = chroot(".");
- /*@=superuser =noeffect @*/
- (void) rpmtsSetChrootDone(ts, 0);
- if (currDir != NULL)
- xx = chdir(currDir);
- }
-
- NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount,
- NULL, ts->notifyData));
-
- /* ===============================================
- * Free unused memory as soon as possible.
- */
+ /* The ordering doesn't matter here */
pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
+ int fc;
+
if ((fi = rpmtsiFi(pi)) == NULL)
continue; /* XXX can't happen */
- if (rpmfiFC(fi) == 0)
- continue;
- fi->fps = _free(fi->fps);
+ fc = rpmfiFC(fi);
+
+ totalFileCount += fc;
}
pi = rpmtsiFree(pi);
- fpc = fpCacheFree(fpc);
- ts->ht = htFree(ts->ht);
- /* ===============================================
- * If unfiltered problems exist, free memory and return.
- */
- if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
- || (ts->probs->numProblems &&
- (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
- )
- {
- rpmtsFreeLock(lock);
- return ts->orderCount;
+ /* Run pre-transaction scripts, but only if there are no known
+ * problems up to this point. */
+ if (!((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
+ || (ts->probs->numProblems &&
+ (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) {
+ rpmMessage(RPMMESS_DEBUG, _("running pre-transaction scripts\n"));
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
+ if ((fi = rpmtsiFi(pi)) == NULL)
+ continue; /* XXX can't happen */
+
+ p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
+ rpmteKey(p), ts->notifyData);
+ p->h = NULL;
+ if (rpmteFd(p) != NULL) {
+ rpmVSFlags ovsflags = rpmtsVSFlags(ts);
+ rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
+ rpmRC rpmrc;
+ ovsflags = rpmtsSetVSFlags(ts, vsflags);
+ rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
+ rpmteNEVR(p), &p->h);
+ vsflags = rpmtsSetVSFlags(ts, ovsflags);
+ switch (rpmrc) {
+ default:
+ /*@-noeffectuncon@*/ /* FIX: notify annotations */
+ p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
+ 0, 0,
+ rpmteKey(p), ts->notifyData);
+ /*@=noeffectuncon@*/
+ p->fd = NULL;
+ /*@switchbreak@*/ break;
+ case RPMRC_NOTTRUSTED:
+ case RPMRC_NOKEY:
+ case RPMRC_OK:
+ /*@switchbreak@*/ break;
+ }
+ }
+
+/*@-branchstate@*/
+ if (rpmteFd(p) != NULL) {
+ fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
+ if (fi != NULL) { /* XXX can't happen */
+ fi->te = p;
+ p->fi = fi;
+ }
+/*@-compdef -usereleased@*/ /* p->fi->te undefined */
+ psm = rpmpsmNew(ts, p, p->fi);
+/*@=compdef =usereleased@*/
+assert(psm != NULL);
+ psm->scriptTag = RPMTAG_PRETRANS;
+ psm->progTag = RPMTAG_PRETRANSPROG;
+ xx = rpmpsmStage(psm, PSM_SCRIPT);
+ psm = rpmpsmFree(psm);
+
+/*@-noeffectuncon -compdef -usereleased @*/
+ (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
+ rpmteKey(p), ts->notifyData);
+/*@=noeffectuncon =compdef =usereleased @*/
+ p->fd = NULL;
+ p->h = headerFree(p->h);
+ }
+/*@=branchstate@*/
+ }
+ pi = rpmtsiFree(pi);
}
/* ===============================================
- * If we were requested to rollback this transaction
- * if an error occurs, then we need to create a
- * a rollback transaction.
+ * Initialize transaction element file info for package:
*/
- if(rollbackOnFailure) {
- rpmtransFlags xx;
- rpmVSFlags ovsflags;
- rpmVSFlags vsflags;
- rpmMessage(RPMMESS_DEBUG,
- _("Creating auto-rollback transaction\n"));
+ /*
+ * 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.
+ */
+rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount);
- rollbackTransaction = rpmtsCreate();
+ numAdded = numRemoved = 0;
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ int fc;
- /* Set the verify signature flags:
- * - can't verify digests on repackaged packages. Other than
- * they are wrong, this will cause segfaults down stream.
- * - signatures are out too.
- * - header check are out.
- */
- vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
- vsflags |= _RPMVSF_NODIGESTS;
- vsflags |= _RPMVSF_NOSIGNATURES;
- vsflags |= RPMVSF_NOHDRCHK;
- vsflags |= RPMVSF_NEEDPAYLOAD; /* XXX no legacy signatures */
- ovsflags = rpmtsSetVSFlags(ts, vsflags);
+ if ((fi = rpmtsiFi(pi)) == NULL)
+ continue; /* XXX can't happen */
+ fc = rpmfiFC(fi);
- /*
- * If we run this thing its imperitive that it be known that it
- * is an autorollback transaction. This will affect the instance
- * counts passed to the scriptlets in the psm.
- */
- rpmtsSetType(rollbackTransaction, RPMTRANS_TYPE_AUTOROLLBACK);
+ /*@-branchstate@*/
+ switch (rpmteType(p)) {
+ case TR_ADDED:
+ numAdded++;
+ fi->record = 0;
+ /* Skip netshared paths, not our i18n files, and excluded docs */
+ if (fc > 0)
+ skipFiles(ts, fi);
+ /*@switchbreak@*/ break;
+ case TR_REMOVED:
+ numRemoved++;
+ fi->record = rpmteDBOffset(p);
+ /*@switchbreak@*/ break;
+ }
+ /*@=branchstate@*/
- /* Set transaction flags to be the same as the running transaction */
- xx = rpmtsSetFlags(rollbackTransaction, rpmtsFlags(ts));
+ fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
+ }
+ pi = rpmtsiFree(pi);
- /* Set root dir to be the same as the running transaction */
- rpmtsSetRootDir(rollbackTransaction, rpmtsRootDir(ts));
-
- /* Setup the notify of the call back to be the same as the running
- * transaction
- */
- xx = rpmtsSetNotifyCallback(rollbackTransaction, ts->notify, ts->notifyData);
+ if (!rpmtsChrootDone(ts)) {
+ const char * rootDir = rpmtsRootDir(ts);
+ xx = chdir("/");
+ /*@-superuser -noeffect @*/
+ if (rootDir != NULL)
+ xx = chroot(rootDir);
+ /*@=superuser =noeffect @*/
+ (void) rpmtsSetChrootDone(ts, 1);
+ }
- /* Create rpmtsScore for running transaction and rollback transaction */
- xx = rpmtsScoreInit(ts, rollbackTransaction);
- }
+ ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
+ fpc = fpCacheCreate(totalFileCount);
/* ===============================================
- * Save removed files before erasing.
+ * Add fingerprint for each file not skipped.
*/
- if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
- int progress;
-
- progress = 0;
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, 0)) != NULL) {
-
- (void) rpmdbCheckSignals();
-
- if ((fi = rpmtsiFi(pi)) == NULL)
- continue; /* XXX can't happen */
- switch (rpmteType(p)) {
- case TR_ADDED:
- /*@switchbreak@*/ break;
- case TR_REMOVED:
- if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
- /*@switchbreak@*/ break;
- if (!progress)
- NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START,
- 7, numRemoved, NULL, ts->notifyData));
-
- NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
- numRemoved, NULL, ts->notifyData));
- progress++;
-
- (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ int fc;
- /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
- fi->mapflags |= CPIO_MAP_ABSOLUTE;
- fi->mapflags |= CPIO_MAP_ADDDOT;
- fi->mapflags |= CPIO_ALL_HARDLINKS;
- psm = rpmpsmNew(ts, p, fi);
- xx = rpmpsmStage(psm, PSM_PKGSAVE);
- psm = rpmpsmFree(psm);
- fi->mapflags &= ~CPIO_MAP_ABSOLUTE;
- fi->mapflags &= ~CPIO_MAP_ADDDOT;
- fi->mapflags &= ~CPIO_ALL_HARDLINKS;
+ (void) rpmdbCheckSignals();
- (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
+ if ((fi = rpmtsiFi(pi)) == NULL)
+ continue; /* XXX can't happen */
+ fc = rpmfiFC(fi);
- /*@switchbreak@*/ break;
- }
- }
- pi = rpmtsiFree(pi);
- if (progress) {
- NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved,
- NULL, ts->notifyData));
+ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
+ fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
+ /*@-branchstate@*/
+ fi = rpmfiInit(fi, 0);
+ if (fi != NULL) /* XXX lclint */
+ while ((i = rpmfiNext(fi)) >= 0) {
+ if (XFA_SKIPPING(fi->actions[i]))
+ /*@innercontinue@*/ continue;
+ /*@-dependenttrans@*/
+ htAddEntry(ts->ht, fi->fps + i, (void *) fi);
+ /*@=dependenttrans@*/
}
+ /*@=branchstate@*/
+ (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
+
}
+ pi = rpmtsiFree(pi);
+
+ NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount,
+ NULL, ts->notifyData));
/* ===============================================
- * Install and remove packages.
+ * Compute file disposition for each package in transaction set.
*/
- lastFailKey = (alKey)-2; /* erased packages have -1 */
+rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
+ ps = rpmtsProblems(ts);
pi = rpmtsiInit(ts);
- /*@-branchstate@*/ /* FIX: fi reload needs work */
while ((p = rpmtsiNext(pi, 0)) != NULL) {
- alKey pkgKey;
- int gotfd;
+ dbiIndexSet * matches;
+ int knownBad;
+ int fc;
(void) rpmdbCheckSignals();
- gotfd = 0;
if ((fi = rpmtsiFi(pi)) == NULL)
continue; /* XXX can't happen */
-
- psm = rpmpsmNew(ts, p, fi);
-assert(psm != NULL);
- psm->unorderedSuccessor =
- (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
+ fc = rpmfiFC(fi);
- switch (rpmteType(p)) {
- case TR_ADDED:
- (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
+ NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
+ ts->orderCount, NULL, ts->notifyData));
- pkgKey = rpmteAddedKey(p);
+ if (fc == 0) continue;
- rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s-%s 0x%x\n",
- rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
-
- p->h = NULL;
- /*@-type@*/ /* FIX: rpmte not opaque */
- {
- /*@-noeffectuncon@*/ /* FIX: notify annotations */
- p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
- rpmteKey(p), ts->notifyData);
- /*@=noeffectuncon@*/
- if (rpmteFd(p) != NULL) {
- rpmVSFlags ovsflags = rpmtsVSFlags(ts);
- rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
- rpmRC rpmrc;
-
- ovsflags = rpmtsSetVSFlags(ts, vsflags);
- rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
- rpmteNEVR(p), &p->h);
- vsflags = rpmtsSetVSFlags(ts, ovsflags);
+ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
+ /* Extract file info for all files in this package from the database. */
+ matches = xcalloc(fc, sizeof(*matches));
+ if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
+ ps = rpmpsFree(ps);
+ rpmtsFreeLock(lock);
+ return 1; /* XXX WTFO? */
+ }
- switch (rpmrc) {
- default:
- /*@-noeffectuncon@*/ /* FIX: notify annotations */
- p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
- 0, 0,
- rpmteKey(p), ts->notifyData);
- /*@=noeffectuncon@*/
- p->fd = NULL;
- ourrc++;
+ numShared = 0;
+ fi = rpmfiInit(fi, 0);
+ while ((i = rpmfiNext(fi)) >= 0)
+ numShared += dbiIndexSetCount(matches[i]);
- /* If we should rollback this transaction
- on failure, lets do it. */
- if(rollbackOnFailure) {
- rpmMessage(RPMMESS_ERROR,
- _("Add failed. Could not read package header.\n"));
- /* Clean up the current transaction */
- p->h = headerFree(p->h);
- xx = rpmdbSync(rpmtsGetRdb(ts));
- psm = rpmpsmFree(psm);
- p->fi = rpmfiFree(p->fi);
- pi = rpmtsiFree(pi);
+ /* Build sorted file info list for this package. */
+ shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
- /* Run the rollback transaction */
- xx = _rpmtsRollback(rollbackTransaction);
- return -1;
- }
- /*@innerbreak@*/ break;
- case RPMRC_NOTTRUSTED:
- case RPMRC_NOKEY:
- case RPMRC_OK:
+ fi = rpmfiInit(fi, 0);
+ while ((i = rpmfiNext(fi)) >= 0) {
+ /*
+ * Take care not to mark files as replaced in packages that will
+ * have been removed before we will get here.
+ */
+ for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
+ int ro;
+ ro = dbiIndexRecordOffset(matches[i], j);
+ knownBad = 0;
+ qi = rpmtsiInit(ts);
+ while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
+ if (ro == knownBad)
/*@innerbreak@*/ break;
- }
- if (rpmteFd(p) != NULL) gotfd = 1;
+ if (rpmteDBOffset(q) == ro)
+ knownBad = ro;
}
- }
- /*@=type@*/
-
- if (rpmteFd(p) != NULL) {
- /*
- * XXX Sludge necessary to tranfer existing fstates/actions
- * XXX around a recreated file info set.
- */
- psm->fi = rpmfiFree(psm->fi);
- {
- char * fstates = fi->fstates;
- fileAction * actions = fi->actions;
- rpmte savep;
+ qi = rpmtsiFree(qi);
- fi->fstates = NULL;
- fi->actions = NULL;
-/*@-nullstate@*/ /* FIX: fi->actions is NULL */
- fi = rpmfiFree(fi);
-/*@=nullstate@*/
+ shared->pkgFileNum = i;
+ shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
+ shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
+ shared->isRemoved = (knownBad == ro);
+ shared++;
+ }
+ matches[i] = dbiFreeIndexSet(matches[i]);
+ }
+ numShared = shared - sharedList;
+ shared->otherPkg = -1;
+ matches = _free(matches);
- savep = rpmtsSetRelocateElement(ts, p);
- fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
- (void) rpmtsSetRelocateElement(ts, savep);
+ /* Sort file info by other package index (otherPkg) */
+ qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
- if (fi != NULL) { /* XXX can't happen */
- fi->te = p;
- fi->fstates = _free(fi->fstates);
- fi->fstates = fstates;
- fi->actions = _free(fi->actions);
- fi->actions = actions;
- p->fi = fi;
- }
- }
- psm->fi = rpmfiLink(p->fi, NULL);
+ /* For all files from this package that are in the database ... */
+ /*@-branchstate@*/
+ for (i = 0; i < numShared; i = nexti) {
+ int beingRemoved;
-/*@-nullstate@*/ /* FIX: psm->fi may be NULL */
- if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
- ourrc++;
- lastFailKey = pkgKey;
-
- /* If we should rollback this transaction
- on failure, lets do it. */
- if(rollbackOnFailure) {
- rpmMessage(RPMMESS_ERROR,
- _("Add failed in rpmpsmStage().\n"));
- /* Clean up the current transaction */
- p->h = headerFree(p->h);
- xx = rpmdbSync(rpmtsGetRdb(ts));
- psm = rpmpsmFree(psm);
- p->fi = rpmfiFree(p->fi);
- pi = rpmtsiFree(pi);
+ shared = sharedList + i;
- /* Run the rollback transaction */
- xx = _rpmtsRollback(rollbackTransaction);
- return -1;
- }
- }
-
- /* If we should rollback on failure lets add
- * this element to the rollback transaction
- * as an erase element as it has installed succesfully.
- */
- if(rollbackOnFailure) {
- int rc;
-
- rc = _rpmtsAddRollbackElement(rollbackTransaction, ts, p);
- if(rc != RPMRC_OK) {
- /* Clean up the current transaction */
- p->h = headerFree(p->h);
- xx = rpmdbSync(rpmtsGetRdb(ts));
- psm = rpmpsmFree(psm);
- p->fi = rpmfiFree(p->fi);
- pi = rpmtsiFree(pi);
-
- /* Clean up rollback transaction */
- rpmtsFree(rollbackTransaction);
- return -1;
- }
- }
-/*@=nullstate@*/
- } else {
- ourrc++;
- lastFailKey = pkgKey;
-
- /* If we should rollback this transaction
- * on failure, lets do it.
- */
- if(rollbackOnFailure) {
- rpmMessage(RPMMESS_ERROR, _("Add failed. Could not get file list.\n"));
- /* Clean up the current transaction */
- p->h = headerFree(p->h);
- xx = rpmdbSync(rpmtsGetRdb(ts));
- psm = rpmpsmFree(psm);
- p->fi = rpmfiFree(p->fi);
- pi = rpmtsiFree(pi);
+ /* Find the end of the files in the other package. */
+ for (nexti = i + 1; nexti < numShared; nexti++) {
+ if (sharedList[nexti].otherPkg != shared->otherPkg)
+ /*@innerbreak@*/ break;
+ }
- /* Run the rollback transaction */
- xx = _rpmtsRollback(rollbackTransaction);
- return -1;
- }
+ /* Is this file from a package being removed? */
+ beingRemoved = 0;
+ if (ts->removedPackages != NULL)
+ for (j = 0; j < ts->numRemovedPackages; j++) {
+ if (ts->removedPackages[j] != shared->otherPkg)
+ /*@innercontinue@*/ continue;
+ beingRemoved = 1;
+ /*@innerbreak@*/ break;
}
- if (gotfd) {
- /*@-noeffectuncon @*/ /* FIX: check rc */
- (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
- rpmteKey(p), ts->notifyData);
- /*@=noeffectuncon @*/
- /*@-type@*/
- p->fd = NULL;
- /*@=type@*/
+ /* Determine the fate of each file. */
+ switch (rpmteType(p)) {
+ case TR_ADDED:
+ xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
+ !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
+ /*@switchbreak@*/ break;
+ case TR_REMOVED:
+ if (!beingRemoved)
+ xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
+ /*@switchbreak@*/ break;
}
+ }
+ /*@=branchstate@*/
- p->h = headerFree(p->h);
+ free(sharedList);
- (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
+ /* Update disk space needs on each partition for this package. */
+ handleOverlappedFiles(ts, p, fi);
+ /* Check added package has sufficient space on each partition used. */
+ switch (rpmteType(p)) {
+ case TR_ADDED:
+ rpmtsCheckDSIProblems(ts, p);
/*@switchbreak@*/ break;
-
case TR_REMOVED:
- (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
+ /*@switchbreak@*/ break;
+ }
+ (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
+ }
+ pi = rpmtsiFree(pi);
+ ps = rpmpsFree(ps);
- rpmMessage(RPMMESS_DEBUG, "========== --- %s %s-%s 0x%x\n",
- rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
+ if (rpmtsChrootDone(ts)) {
+ const char * currDir = rpmtsCurrDir(ts);
+ /*@-superuser -noeffect @*/
+ xx = chroot(".");
+ /*@=superuser =noeffect @*/
+ (void) rpmtsSetChrootDone(ts, 0);
+ if (currDir != NULL)
+ xx = chdir(currDir);
+ }
- /*
- * XXX This has always been a hack, now mostly broken.
- * If install failed, then we shouldn't erase.
- */
- if (rpmteDependsOnKey(p) != lastFailKey) {
- if (rpmpsmStage(psm, PSM_PKGERASE)) {
- ourrc++;
-
- /* If we should rollback this transaction
- * on failure, lets do it.
- */
- if(rollbackOnFailure) {
- rpmMessage(RPMMESS_ERROR,
- _("Erase failed failed in rpmpsmStage().\n"));
- /* Clean up the current transaction */
- xx = rpmdbSync(rpmtsGetRdb(ts));
- psm = rpmpsmFree(psm);
- p->fi = rpmfiFree(p->fi);
- pi = rpmtsiFree(pi);
+ NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount,
+ NULL, ts->notifyData));
- /* Run the rollback transaction */
- xx = _rpmtsRollback(rollbackTransaction);
- return -1;
- }
- }
+ /* ===============================================
+ * Free unused memory as soon as possible.
+ */
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ if ((fi = rpmtsiFi(pi)) == NULL)
+ continue; /* XXX can't happen */
+ if (rpmfiFC(fi) == 0)
+ continue;
+ fi->fps = _free(fi->fps);
+ }
+ pi = rpmtsiFree(pi);
- /* If we should rollback on failure lets add
- * this element to the rollback transaction
- * as an install element as it has erased succesfully.
- */
- if(rollbackOnFailure) {
- int rc;
+ fpc = fpCacheFree(fpc);
+ ts->ht = htFree(ts->ht);
- rc = _rpmtsAddRollbackElement(rollbackTransaction, ts, p);
+ /* ===============================================
+ * If unfiltered problems exist, free memory and return.
+ */
+ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
+ || (ts->probs->numProblems &&
+ (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
+ )
+ {
+ rpmtsFreeLock(lock);
+ return ts->orderCount;
+ }
- if(rc != RPMRC_OK) {
- /* Clean up the current transaction */
- xx = rpmdbSync(rpmtsGetRdb(ts));
- psm = rpmpsmFree(psm);
- p->fi = rpmfiFree(p->fi);
- pi = rpmtsiFree(pi);
-
- /* Clean up rollback transaction */
- rpmtsFree(rollbackTransaction);
- return -1;
- }
- }
- }
+ /* ===============================================
+ * If we were requested to rollback this transaction
+ * if an error occurs, then we need to create a
+ * a rollback transaction.
+ */
+ if (rollbackOnFailure) {
+ rpmtransFlags tsFlags;
+ rpmVSFlags ovsflags;
+ rpmVSFlags vsflags;
- (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
+ rpmMessage(RPMMESS_DEBUG,
+ _("Creating auto-rollback transaction\n"));
- /*@switchbreak@*/ break;
- }
- xx = rpmdbSync(rpmtsGetRdb(ts));
+ rollbackTransaction = rpmtsCreate();
-/*@-nullstate@*/ /* FIX: psm->fi may be NULL */
- psm = rpmpsmFree(psm);
-/*@=nullstate@*/
+ /* Set the verify signature flags:
+ * - can't verify digests on repackaged packages. Other than
+ * they are wrong, this will cause segfaults down stream.
+ * - signatures are out too.
+ * - header check are out.
+ */
+ vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
+ vsflags |= _RPMVSF_NODIGESTS;
+ vsflags |= _RPMVSF_NOSIGNATURES;
+ vsflags |= RPMVSF_NOHDRCHK;
+ vsflags |= RPMVSF_NEEDPAYLOAD; /* XXX no legacy signatures */
+ ovsflags = rpmtsSetVSFlags(ts, vsflags);
-/*@-type@*/ /* FIX: p is almost opaque */
- p->fi = rpmfiFree(p->fi);
-/*@=type@*/
+ /*
+ * If we run this thing its imperitive that it be known that it
+ * is an autorollback transaction. This will affect the instance
+ * counts passed to the scriptlets in the psm.
+ */
+ rpmtsSetType(rollbackTransaction, RPMTRANS_TYPE_AUTOROLLBACK);
- }
- /*@=branchstate@*/
- pi = rpmtsiFree(pi);
+ /* Set transaction flags to be the same as the running transaction */
+ tsFlags = rpmtsSetFlags(rollbackTransaction, rpmtsFlags(ts));
- /* If we created a rollback transaction lets get rid of it */
- if(rollbackOnFailure && rollbackTransaction != NULL) {
- rpmtsFree(rollbackTransaction);
- }
+ /* Set root dir to be the same as the running transaction */
+ rpmtsSetRootDir(rollbackTransaction, rpmtsRootDir(ts));
- rpmMessage(RPMMESS_DEBUG, _("running post-transaction scripts\n"));
- pi = rpmtsiInit(ts);
- while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
- p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
- rpmteKey(p), ts->notifyData);
- p->h = NULL;
- if (rpmteFd(p) != NULL) {
- rpmVSFlags ovsflags = rpmtsVSFlags(ts);
- rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
- rpmRC rpmrc;
- ovsflags = rpmtsSetVSFlags(ts, vsflags);
- rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
- rpmteNEVR(p), &p->h);
- vsflags = rpmtsSetVSFlags(ts, ovsflags);
- switch (rpmrc) {
- default:
- p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
- 0, 0, rpmteKey(p), ts->notifyData);
- p->fd = NULL;
- break;
- case RPMRC_NOTTRUSTED:
- case RPMRC_NOKEY:
- case RPMRC_OK:
- break;
- }
- }
+ /* Setup the notify of the call back to be the same as the running
+ * transaction
+ */
+ xx = rpmtsSetNotifyCallback(rollbackTransaction, ts->notify, ts->notifyData);
- if (rpmteFd(p) != NULL) {
- fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
- if (fi != NULL) { /* XXX can't happen */
- fi->te = p;
- p->fi = fi;
- }
- psm = rpmpsmNew(ts, p, p->fi);
- psm->scriptTag = RPMTAG_POSTTRANS;
- psm->progTag = RPMTAG_POSTTRANSPROG;
- xx = rpmpsmStage(psm, PSM_SCRIPT);
- psm = rpmpsmFree(psm);
+ /* Create rpmtsScore for running transaction and rollback transaction */
+ xx = rpmtsScoreInit(ts, rollbackTransaction);
+ }
- (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
- rpmteKey(p), ts->notifyData);
- p->fd = NULL;
- p->h = headerFree(p->h);
- }
- }
- pi = rpmtsiFree(pi);
+ /* ===============================================
+ * Save removed files before erasing.
+ */
+ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
+ int progress;
- rpmtsFreeLock(lock);
+ progress = 0;
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
- /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
- if (ourrc)
- return -1;
- else
- return 0;
- /*@=nullstate@*/
-}
+ (void) rpmdbCheckSignals();
-/**
- * Get the repackaged header and filename from the repackage directory.
- * @todo Find a suitable home for this function.
- * @todo This function creates an IDTX everytime it is called. Needs to
- * be made more efficient (only create on per running transaction).
- * @param te transaction element
- * @param rpmts rpm transaction
- * @return hdrp Repackaged header
- * @return fn Repackaged package's path (transaction key)
- * @return RPMRC_NOTFOUND or RPMRC_OK
- */
-rpmRC getRepackageHeaderFromTE(rpmte te, rpmts ts, Header *hdrp, char **fn)
-{
- int_32 tid;
- const char * name;
- const char * rpname = NULL;
- const char * _repackage_dir = NULL;
- const char * globStr = "-*.rpm";
- char * rp = NULL; /* Rollback package name */
- IDTX rtids = NULL;
- IDT rpIDT;
- int nrids = 0;
- int nb; /* Number of bytes */
- Header h = NULL;
- int rc = RPMRC_NOTFOUND; /* Assume we do not find it*/
-
- rpmMessage(RPMMESS_DEBUG,
- _("Getting repackaged header from transaction element\n"));
+ if ((fi = rpmtsiFi(pi)) == NULL)
+ continue; /* XXX can't happen */
+ switch (rpmteType(p)) {
+ case TR_ADDED:
+ /*@switchbreak@*/ break;
+ case TR_REMOVED:
+ if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
+ /*@switchbreak@*/ break;
+ if (!progress)
+ NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START,
+ 7, numRemoved, NULL, ts->notifyData));
- /* Set header pointer to null if its not already */
- if(hdrp)
- *hdrp = NULL;
- if(fn)
- *fn = NULL;
+ NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
+ numRemoved, NULL, ts->notifyData));
+ progress++;
- /* Get the TID of the current transaction */
- tid = rpmtsGetTid(ts);
- /* Need the repackage dir if the user want to
- * rollback on a failure.
- */
- _repackage_dir = rpmExpand("%{?_repackage_dir}", NULL);
- if(_repackage_dir == NULL) goto exit;
+ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
- /* Build the glob string to find the possible repackaged
- * packages for this package.
- */
- name = rpmteN(te);
- nb = strlen(_repackage_dir) + strlen(name) + strlen(globStr) + 2;
- rp = memset((char *) malloc(nb), 0, nb);
- snprintf(rp, nb, "%s/%s%s.rpm", _repackage_dir, name, globStr);
+ /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
+ fi->mapflags |= CPIO_MAP_ABSOLUTE;
+ fi->mapflags |= CPIO_MAP_ADDDOT;
+ fi->mapflags |= CPIO_ALL_HARDLINKS;
+ psm = rpmpsmNew(ts, p, fi);
+assert(psm != NULL);
+ xx = rpmpsmStage(psm, PSM_PKGSAVE);
+ psm = rpmpsmFree(psm);
+ fi->mapflags &= ~CPIO_MAP_ABSOLUTE;
+ fi->mapflags &= ~CPIO_MAP_ADDDOT;
+ fi->mapflags &= ~CPIO_ALL_HARDLINKS;
- /* Get the index of possible repackaged packages */
- rpmMessage(RPMMESS_DEBUG, _("\tLooking for %s...\n"), rp);
- rtids = IDTXglob(ts, rp, RPMTAG_REMOVETID);
- rp = _free(rp);
- if (rtids != NULL) {
- rpmMessage(RPMMESS_DEBUG, _("\tMatches found.\n"));
- rpIDT = rtids->idt;
- nrids = rtids->nidt;
- } else {
- rpmMessage(RPMMESS_DEBUG, _("\tNo matches found.\n"));
- goto exit;
- }
+ (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
- /* Now walk through index until we find the package (or we have
- * exhausted the index.
- */
- do {
- /* If index is null we have exhausted the list and need to
- * get out of here...the repackaged package was not found.
- */
- if(rpIDT == NULL) {
- rpmMessage(RPMMESS_DEBUG, _("\tRepackaged package not found!.\n"));
- break;
+ /*@switchbreak@*/ break;
+ }
}
-
- /* Is this the same tid. If not decrement the list and continue */
- if(rpIDT->val.u32 != tid) {
- nrids--;
- if(nrids > 0)
- rpIDT++;
- else
- rpIDT = NULL;
- continue;
+ pi = rpmtsiFree(pi);
+ if (progress) {
+ NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved,
+ NULL, ts->notifyData));
}
+ }
- /* OK, the tid matches. Now lets see if the name is the same.
- * If I could not get the name from the package, I will go onto
- * the next one. Perhaps I should return an error at this
- * point, but if this was not the correct one, at least the correct one
- * would be found.
- * XXX: Should I be matching name and arch?
- */
- rpmMessage(RPMMESS_DEBUG, _("\tREMOVETID matched INSTALLTID.\n"));
- if(headerGetEntry(rpIDT->h, RPMTAG_NAME, NULL, (void **) &rpname, NULL)) {
- rpmMessage(RPMMESS_DEBUG, _("\t\tName: %s.\n"), rpname);
- if(!strcmp(name,rpname)) {
- /* It matched we have a canidate */
- h = headerLink(rpIDT->h);
- nb = strlen(rpIDT->key) + 1;
- rp = memset((char *) malloc(nb), 0, nb);
- rp = strncat(rp, rpIDT->key, nb);
- rc = RPMRC_OK;
- break;
+ /* ===============================================
+ * Install and remove packages.
+ */
+ lastFailKey = (alKey)-2; /* erased packages have -1 */
+ pi = rpmtsiInit(ts);
+ /*@-branchstate@*/ /* FIX: fi reload needs work */
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ alKey pkgKey;
+ int gotfd;
+
+ (void) rpmdbCheckSignals();
+
+ gotfd = 0;
+ if ((fi = rpmtsiFi(pi)) == NULL)
+ continue; /* XXX can't happen */
+
+ psm = rpmpsmNew(ts, p, fi);
+assert(psm != NULL);
+ psm->unorderedSuccessor =
+ (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
+
+ switch (rpmteType(p)) {
+ case TR_ADDED:
+ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
+
+ pkgKey = rpmteAddedKey(p);
+
+ rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s-%s 0x%x\n",
+ rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
+
+ p->h = NULL;
+ /*@-type@*/ /* FIX: rpmte not opaque */
+ {
+ /*@-noeffectuncon@*/ /* FIX: notify annotations */
+ p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
+ rpmteKey(p), ts->notifyData);
+ /*@=noeffectuncon@*/
+ if (rpmteFd(p) != NULL) {
+ rpmVSFlags ovsflags = rpmtsVSFlags(ts);
+ rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
+ rpmRC rpmrc;
+
+ ovsflags = rpmtsSetVSFlags(ts, vsflags);
+ rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
+ rpmteNEVR(p), &p->h);
+ vsflags = rpmtsSetVSFlags(ts, ovsflags);
+
+ switch (rpmrc) {
+ default:
+ /*@-noeffectuncon@*/ /* FIX: notify annotations */
+ p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
+ 0, 0,
+ rpmteKey(p), ts->notifyData);
+ /*@=noeffectuncon@*/
+ p->fd = NULL;
+ ourrc++;
+
+ /* If we should rollback this transaction
+ on failure, lets do it. */
+ if (rollbackOnFailure) {
+ rpmMessage(RPMMESS_ERROR,
+ _("Add failed. Could not read package header.\n"));
+ /* Clean up the current transaction */
+ p->h = headerFree(p->h);
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+ psm = rpmpsmFree(psm);
+ p->fi = rpmfiFree(p->fi);
+ pi = rpmtsiFree(pi);
+
+ /* Run the rollback transaction */
+ xx = _rpmtsRollback(rollbackTransaction);
+ return -1;
+ }
+ /*@innerbreak@*/ break;
+ case RPMRC_NOTTRUSTED:
+ case RPMRC_NOKEY:
+ case RPMRC_OK:
+ /*@innerbreak@*/ break;
+ }
+ if (rpmteFd(p) != NULL) gotfd = 1;
+ }
}
- }
+ /*@=type@*/
- /* Decrement list */
- nrids--;
- if(nrids > 0)
- rpIDT++;
- else
- rpIDT = NULL;
- } while(1);
-
-exit:
- if(rc != RPMRC_NOTFOUND && h != NULL && hdrp != NULL) {
- rpmMessage(RPMMESS_DEBUG, _("\tRepackaged Package was %s...\n"), rp);
- *hdrp = headerLink(h);
- *fn = rp;
- }
- if(h != NULL) {
- h = headerFree(h);
- }
- rtids = IDTXfree(rtids);
- return rc;
-}
+ if (rpmteFd(p) != NULL) {
+ /*
+ * XXX Sludge necessary to tranfer existing fstates/actions
+ * XXX around a recreated file info set.
+ */
+ psm->fi = rpmfiFree(psm->fi);
+ {
+ char * fstates = fi->fstates;
+ fileAction * actions = fi->actions;
+ rpmte savep;
-/**
- * This is not a generalized function to be called from outside
- * librpm. It is called internally by rpmtsRun() to add elements
- * to its rollback transaction.
- * @param rollbackTransaction rollback transaction
- * @param runningTransaction running transaction (the one you want to rollback)
- * @param te Transaction element.
- * @return RPMRC_OK, or RPMRC_FAIL
- */
-rpmRC _rpmtsAddRollbackElement(rpmts rollbackTransaction, rpmts runningTransaction, rpmte te)
-{
- Header h = NULL;
- Header rph = NULL;
- char * rpn;
- unsigned int db_instance = 0;
- rpmtsi pi;
- rpmte p;
- int rc = RPMRC_FAIL; /* Assume Failure */
-
- switch(rpmteType(te)) {
- case TR_ADDED:
- rpmMessage(RPMMESS_DEBUG,
- _("Adding install element to auto-rollback transaction.\n"));
-
- /* Get the header for this package from the database
- * First get the database instance (the key).
- */
- db_instance = rpmteDBInstance(te);
- if(db_instance <= 0) {
- /* Could not get the db instance: WTD! */
- rpmMessage(RPMMESS_FATALERROR,
- _("Could not get install element database instance!\n"));
- break;
- }
+ fi->fstates = NULL;
+ fi->actions = NULL;
+/*@-nullstate@*/ /* FIX: fi->actions is NULL */
+ fi = rpmfiFree(fi);
+/*@=nullstate@*/
- /* Now suck the header out of the database */
- rpmdbMatchIterator mi = rpmtsInitIterator(rollbackTransaction,
- RPMDBI_PACKAGES, &db_instance, sizeof(db_instance));
- h = rpmdbNextIterator(mi);
- if(h != NULL) h = headerLink(h);
- mi = rpmdbFreeIterator(mi);
- if(h == NULL) {
- /* Header was not there??? */
- rpmMessage(RPMMESS_FATALERROR,
- _("Could not get header for auto-rollback transaction!\n"));
- break;
- }
-
- /* Now see if there is a repackaged package for this */
- rc = getRepackageHeaderFromTE(te, runningTransaction, &rph, &rpn);
- switch(rc) {
- case RPMRC_OK:
- /* Add the install element, as we had a repackaged package */
- rpmMessage(RPMMESS_DEBUG,
- _("\tAdded repackaged package header: %s.\n"), rpn);
- rc = rpmtsAddInstallElement(rollbackTransaction, headerLink(rph),
- (fnpyKey) rpn, 1, te->relocs);
- break;
+ savep = rpmtsSetRelocateElement(ts, p);
+ fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
+ (void) rpmtsSetRelocateElement(ts, savep);
- case RPMRC_NOTFOUND:
- /* Add the header as an erase element, we did not
- * have a repackaged package
- */
- rpmMessage(RPMMESS_DEBUG, _("\tAdded erase element.\n"));
- rc = rpmtsAddEraseElement(rollbackTransaction, h, db_instance);
- break;
+ if (fi != NULL) { /* XXX can't happen */
+ fi->te = p;
+ fi->fstates = _free(fi->fstates);
+ fi->fstates = fstates;
+ fi->actions = _free(fi->actions);
+ fi->actions = actions;
+ p->fi = fi;
+ }
+ }
+ psm->fi = rpmfiLink(p->fi, NULL);
+
+/*@-nullstate@*/ /* FIX: psm->fi may be NULL */
+ if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
+ ourrc++;
+ lastFailKey = pkgKey;
+
+ /* If we should rollback this transaction
+ on failure, lets do it. */
+ if (rollbackOnFailure) {
+ rpmMessage(RPMMESS_ERROR,
+ _("Add failed in rpmpsmStage().\n"));
+ /* Clean up the current transaction */
+ p->h = headerFree(p->h);
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+ psm = rpmpsmFree(psm);
+ p->fi = rpmfiFree(p->fi);
+ pi = rpmtsiFree(pi);
+
+ /* Run the rollback transaction */
+ xx = _rpmtsRollback(rollbackTransaction);
+ return -1;
+ }
+ }
+
+ /* If we should rollback on failure lets add
+ * this element to the rollback transaction
+ * as an erase element as it has installed succesfully.
+ */
+ if (rollbackOnFailure) {
+ int rc;
+
+ rc = _rpmtsAddRollbackElement(rollbackTransaction, ts, p);
+ if (rc != RPMRC_OK) {
+ /* Clean up the current transaction */
+ p->h = headerFree(p->h);
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+ psm = rpmpsmFree(psm);
+ p->fi = rpmfiFree(p->fi);
+ pi = rpmtsiFree(pi);
- default:
- /* Not sure what to do on failure...just give up */
- rpmMessage(RPMMESS_FATALERROR,
- _("Could not get repackaged header for auto-rollback transaction!\n"));
- break;
- }
- break;
+ /* Clean up rollback transaction */
+ rollbackTransaction = rpmtsFree(rollbackTransaction);
+ return -1;
+ }
+ }
+/*@=nullstate@*/
+ } else {
+ ourrc++;
+ lastFailKey = pkgKey;
+
+ /* If we should rollback this transaction
+ * on failure, lets do it.
+ */
+ if (rollbackOnFailure) {
+ rpmMessage(RPMMESS_ERROR, _("Add failed. Could not get file list.\n"));
+ /* Clean up the current transaction */
+ p->h = headerFree(p->h);
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+ psm = rpmpsmFree(psm);
+ p->fi = rpmfiFree(p->fi);
+ pi = rpmtsiFree(pi);
- case TR_REMOVED:
- rpmMessage(RPMMESS_DEBUG,
- _("Add erase element to auto-rollback transaction.\n"));
+ /* Run the rollback transaction */
+ xx = _rpmtsRollback(rollbackTransaction);
+ return -1;
+ }
+ }
- /* See if this element has already been added as an upgrade.
- * If so we want to do nothing.
- */
- pi = rpmtsiInit(rollbackTransaction);
- while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
- if(rpmteType(p) == TR_ADDED) continue;
- if(!strcmp(rpmteN(p), rpmteN(te))) {
- rpmMessage(RPMMESS_DEBUG, _("\tFound existing upgrade element.\n"));
- rpmMessage(RPMMESS_DEBUG, _("\tNot adding erase element for %s.\n"),
- rpmteN(te));
- rc = RPMRC_OK;
- pi = rpmtsiFree(pi);
- break;
+ if (gotfd) {
+ /*@-noeffectuncon @*/ /* FIX: check rc */
+ (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
+ rpmteKey(p), ts->notifyData);
+ /*@=noeffectuncon @*/
+ /*@-type@*/
+ p->fd = NULL;
+ /*@=type@*/
}
- }
- pi = rpmtsiFree(pi);
+ p->h = headerFree(p->h);
- /* Get the repackage header from the current transaction
- * element.
- */
- rc = getRepackageHeaderFromTE(te, runningTransaction, &rph, &rpn);
- switch(rc) {
- case RPMRC_OK:
- /* Add the install element */
- rpmMessage(RPMMESS_DEBUG,
- _("\tAdded repackaged package %s.\n"), rpn);
- rc = rpmtsAddInstallElement(rollbackTransaction, rph,
- (fnpyKey) rpn, 1, te->relocs);
- if(rc != RPMRC_OK)
- rpmMessage(RPMMESS_FATALERROR,
- _("Could not add erase element to auto-rollback transaction.\n"));
- break;
+ (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
- case RPMRC_NOTFOUND:
- /* Just did not have a repackaged package */
- rpmMessage(RPMMESS_DEBUG,
- _("\tNo repackaged package...nothing to do.\n"));
- rc = RPMRC_OK;
- break;
+ /*@switchbreak@*/ break;
- default:
- rpmMessage(RPMMESS_FATALERROR,
- _("Failure reading repackaged package!\n"));
- break;
- }
- break;
+ case TR_REMOVED:
+ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
- default:
- break;
- }
+ rpmMessage(RPMMESS_DEBUG, "========== --- %s %s-%s 0x%x\n",
+ rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
-/* XXX: I want to free this, but if I do then the consumers of
- * are hosed. Just leaving you a little note Jeff, so you
- * know that this does introduce a memory leak. I wanted
- * keep the patch as simple as possible so I am not fixxing
- * the leak.
- * if(rpn != NULL)
- * free(rpn);
- */
+ /*
+ * XXX This has always been a hack, now mostly broken.
+ * If install failed, then we shouldn't erase.
+ */
+ if (rpmteDependsOnKey(p) != lastFailKey) {
+ if (rpmpsmStage(psm, PSM_PKGERASE)) {
+ ourrc++;
- /* Clean up */
- if(h != NULL)
- h = headerFree(h);
- if(rph != NULL)
- rph = headerFree(rph);
- return rc;
-}
+ /* If we should rollback this transaction
+ * on failure, lets do it.
+ */
+ if (rollbackOnFailure) {
+ rpmMessage(RPMMESS_ERROR,
+ _("Erase failed failed in rpmpsmStage().\n"));
+ /* Clean up the current transaction */
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+ psm = rpmpsmFree(psm);
+ p->fi = rpmfiFree(p->fi);
+ pi = rpmtsiFree(pi);
-/**
- * This is not a generalized function to be called from outside
- * librpm. It is called internally by rpmtsRun() to rollback
- * a failed transaction.
- * @param rollbackTransaction rollback transaction
- * @return RPMRC_OK, or RPMRC_FAIL
- */
-rpmRC _rpmtsRollback(rpmts rollbackTransaction)
-{
- int rc = 0;
- int numAdded = 0;
- int numRemoved = 0;
- int_32 tid;
- rpmtsi tsi;
- rpmte te;
- rpmps ps;
+ /* Run the rollback transaction */
+ xx = _rpmtsRollback(rollbackTransaction);
+ return -1;
+ }
+ }
- /*
- * Gather information about this rollback transaction for reporting.
- * 1) Get tid
- */
- tid = rpmtsGetTid(rollbackTransaction);
- /*
- * 2) Get number of install elments and erase elements
- */
- tsi = rpmtsiInit(rollbackTransaction);
- while((te = rpmtsiNext(tsi, 0)) != NULL) {
- switch (rpmteType(te)) {
- case TR_ADDED:
- numAdded++;
- break;
- case TR_REMOVED:
- numRemoved++;
- break;
- default:
- break;
- }
- }
- tsi = rpmtsiFree(tsi);
+ /* If we should rollback on failure lets add
+ * this element to the rollback transaction
+ * as an install element as it has erased succesfully.
+ */
+ if (rollbackOnFailure) {
+ int rc;
- rpmMessage(RPMMESS_NORMAL, _("Transaction failed...rolling back\n"));
- rpmMessage(RPMMESS_NORMAL,
- _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
- numAdded, numRemoved, ctime(&tid), tid);
+ rc = _rpmtsAddRollbackElement(rollbackTransaction, ts, p);
- /* Check the transaction to see if it is doable */
- rc = rpmtsCheck(rollbackTransaction);
- ps = rpmtsProblems(rollbackTransaction);
- if (rc != 0 && rpmpsNumProblems(ps) > 0) {
- rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
- rpmpsPrint(NULL, ps);
- ps = rpmpsFree(ps);
- return -1;
- }
- ps = rpmpsFree(ps);
+ if (rc != RPMRC_OK) {
+ /* Clean up the current transaction */
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+ psm = rpmpsmFree(psm);
+ p->fi = rpmfiFree(p->fi);
+ pi = rpmtsiFree(pi);
+
+ /* Clean up rollback transaction */
+ rollbackTransaction = rpmtsFree(rollbackTransaction);
+ return -1;
+ }
+ }
+ }
+
+ (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
+
+ /*@switchbreak@*/ break;
+ }
+ xx = rpmdbSync(rpmtsGetRdb(ts));
+
+/*@-nullstate@*/ /* FIX: psm->fi may be NULL */
+ psm = rpmpsmFree(psm);
+/*@=nullstate@*/
+
+/*@-type@*/ /* FIX: p is almost opaque */
+ p->fi = rpmfiFree(p->fi);
+/*@=type@*/
- /* Order the transaction */
- rc = rpmtsOrder(rollbackTransaction);
- if (rc != 0) {
- rpmMessage(RPMMESS_ERROR,
- _("Could not order auto-rollback transaction!\n"));
- return -1;
}
+ /*@=branchstate@*/
+ pi = rpmtsiFree(pi);
-
+ /* If we created a rollback transaction lets get rid of it */
+ if (rollbackOnFailure && rollbackTransaction != NULL)
+ rollbackTransaction = rpmtsFree(rollbackTransaction);
- /* Run the transaction and print any problems
- * We want to stay with the original transactions flags except
- * that we want to add what is essentially a force.
- * This handles two things in particular:
- *
- * 1. We we want to upgrade over a newer package.
- * 2. If a header for the old package is there we
- * we want to replace it. No questions asked.
- */
- rc = rpmtsRun(rollbackTransaction, NULL,
- RPMPROB_FILTER_REPLACEPKG
- | RPMPROB_FILTER_REPLACEOLDFILES
- | RPMPROB_FILTER_REPLACENEWFILES
- | RPMPROB_FILTER_OLDPACKAGE
- );
- ps = rpmtsProblems(rollbackTransaction);
- if (rc > 0 && rpmpsNumProblems(ps) > 0)
- rpmpsPrint(stderr, ps);
- ps = rpmpsFree(ps);
- rollbackTransaction = rpmtsFree(rollbackTransaction);
+ rpmMessage(RPMMESS_DEBUG, _("running post-transaction scripts\n"));
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
+ p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
+ rpmteKey(p), ts->notifyData);
+ p->h = NULL;
+ if (rpmteFd(p) != NULL) {
+ rpmVSFlags ovsflags = rpmtsVSFlags(ts);
+ rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
+ rpmRC rpmrc;
+ ovsflags = rpmtsSetVSFlags(ts, vsflags);
+ rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
+ rpmteNEVR(p), &p->h);
+ vsflags = rpmtsSetVSFlags(ts, ovsflags);
+ switch (rpmrc) {
+ default:
+ p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
+ 0, 0, rpmteKey(p), ts->notifyData);
+ p->fd = NULL;
+ /*@switchbreak@*/ break;
+ case RPMRC_NOTTRUSTED:
+ case RPMRC_NOKEY:
+ case RPMRC_OK:
+ /*@switchbreak@*/ break;
+ }
+ }
- return rc;
+ if (rpmteFd(p) != NULL) {
+ fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
+ if (fi != NULL) { /* XXX can't happen */
+ fi->te = p;
+ p->fi = fi;
+ }
+/*@-compdef -usereleased@*/ /* p->fi->te undefined */
+ psm = rpmpsmNew(ts, p, p->fi);
+/*@=compdef =usereleased@*/
+assert(psm != NULL);
+ psm->scriptTag = RPMTAG_POSTTRANS;
+ psm->progTag = RPMTAG_POSTTRANSPROG;
+ xx = rpmpsmStage(psm, PSM_SCRIPT);
+ psm = rpmpsmFree(psm);
+
+/*@-noeffectuncon -compdef -usereleased @*/
+ (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
+ rpmteKey(p), ts->notifyData);
+/*@=noeffectuncon =compdef =usereleased @*/
+ p->fd = NULL;
+ p->h = headerFree(p->h);
+ }
+ }
+ pi = rpmtsiFree(pi);
+
+ rpmtsFreeLock(lock);
+
+ /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
+ if (ourrc)
+ return -1;
+ else
+ return 0;
+ /*@=nullstate@*/
}