removed support for repackaging and rollbacks (rpm.org)

This commit is contained in:
Alexey Tourbin 2011-04-02 11:13:11 +04:00
parent 1a3c5027f0
commit 9e15c26f3f
16 changed files with 13 additions and 836 deletions

View File

@ -11,7 +11,6 @@ EXTRA_DIST = \
multiplebuilds \
queryformat \
relocatable \
rollbacks \
signatures \
spec \
triggers \

View File

@ -1,49 +0,0 @@
The term "transaction rollback" is jargon for a method of maintaining
sets of packages that are applied to boxen sequentially. In a nutshell,
packages that are to be installed/removed are aggregated into something
called a "transaction set". Each transaction set is then assigned a unique
identifier so that the packages in the set can be distinguished, Finally,
since the transaction set identifier (TID) can be ordered, transaction sets
can be managed just like packages, since each TID will identify the sets
of packages to be installed/removed at each stage in a software life
maintenance cycle. The approach is very similar to what rpm already does
when encapsulating sets of files in packages which are then ordered
according to the package epoch, version and release.
The current release of rpm (rpm-4.0.2) has added TID's to every package
installed. In addition, an image of the header is preserved in the rpm
database that is identical to what was in the original package file.
This permits rpm to reconstruct the original package from the installed
components at any time.
The next version of rpm (rpm-4.0.3, now in a release cycle now) has added the
ability to repackage all the components to construct a copy of the original
package as part of a software upgrade. The reconstituted package as well
as the newly installed packages in the transaction set are all marked with
a TID that identifies the software upgrade uniquely. Thus software
replaced on a boxen is repackaged, and the packages can be archived
(or otherwise saved) as part of normal software management.
What remains to be done is to use the ordering property of TID's so that
transactions can be "rolled back" to any point in the past for which
the old packages are available. This will require a B-tree database
index for the currently installed transaction sets, and saving the names
of the packages that were removed. For the commonest case, a software
upgrade, each installed package can carry the names of replaced
(and repackaged) packages that were performed as a side effect of the
package upgrade. Other means will be needed to keep track of transaction
sets that only removed packages, however. Finally, a "transaction rollback"
loop still needs to be written that will walk backwards through the ordered
TID's, reconstructing the transaction set but reversing what packages
are removed and/or installed.
In addition to "transaction rollbacks", rpm will soon have the ability
to apply/commit/undo software transactions atomically. The next version of
rpm (rpm-4.0.3) already has the ability to apply/commit/undo file changes.
The term "apply" means that the file is installed with a temporary name
(currently just the original file name with the TID appended), "commit"
is the operation of renaming the file and setting it's mode and ownership,
while an "undo" is just a removal of the temporary file. The concepts
of apply/commit/undo are being extended to packages as a set of
file operations, and will need to be extended yet further to transaction
sets as well.

View File

@ -24,7 +24,7 @@ rpm \- RPM Package Manager
\fBrpm\fR {\fB-F|--freshen\fR} [\fBinstall-options\fR] \fB\fIPACKAGE_FILE\fB\fR\fI ...\fR
\fBrpm\fR {\fB-e|--erase\fR} [\fB--allmatches\fR] [\fB--nodeps\fR] [\fB--noscripts\fR] [\fB--notriggers\fR] [\fB--repackage\fR] [\fB--test\fR] \fB\fIPACKAGE_NAME\fB\fR\fI ...\fR
\fBrpm\fR {\fB-e|--erase\fR} [\fB--allmatches\fR] [\fB--nodeps\fR] [\fB--noscripts\fR] [\fB--notriggers\fR] [\fB--test\fR] \fB\fIPACKAGE_NAME\fB\fR\fI ...\fR
.SS "BUILDING PACKAGES:"
.PP
@ -64,7 +64,7 @@ rpm \- RPM Package Manager
[--ignoresize] [--ignorearch] [--ignoreos] [--includedocs] [--justdb]
[--nodeps] [--noorder] [--noscripts] [--notriggers]
[--oldpackage] [--percent] [--prefix \fINEWPATH\fB] [--relocate\ \fIOLDPATH\fB=\fINEWPATH\fB]
[--repackage] [--replacefiles] [--replacepkgs] [--test]\fR
[--replacefiles] [--replacepkgs] [--test]\fR
.SS "BUILD-OPTIONS"
.PP
@ -297,14 +297,6 @@ This option can be used repeatedly if several
\fIOLDPATH\fR's in the package are to
be relocated.
.TP
\fB--repackage\fR
Re-package the files before erasing. The previously installed
package will be named according to the macro
\fB%_repackage_name_fmt\fR
and will be created in the directory named by
the macro \fB%_repackage_dir\fR (default value
is \fI/var/tmp\fR).
.TP
\fB--replacefiles\fR
Install the packages even if they replace files from other,
already installed, packages.
@ -555,7 +547,7 @@ for details.
.PP
The general form of an rpm erase command is
.PP
\fBrpm\fR {\fB-e|--erase\fR} [\fB--allmatches\fR] [\fB--nodeps\fR] [\fB--noscripts\fR] [\fB--notriggers\fR] [\fB--repackage\fR] [\fB--test\fR] \fB\fIPACKAGE_NAME\fB\fR\fI ...\fR
\fBrpm\fR {\fB-e|--erase\fR} [\fB--allmatches\fR] [\fB--nodeps\fR] [\fB--noscripts\fR] [\fB--notriggers\fR] [\fB--test\fR] \fB\fIPACKAGE_NAME\fB\fR\fI ...\fR
.PP
The following options may also be used:
.TP
@ -601,14 +593,6 @@ and turns off execution of the corresponding
\fB%triggerpostun\fR
scriptlet(s).
.TP
\fB--repackage\fR
Re-package the files before erasing. The previously installed
package will be named according to the macro
\fB%_repackage_name_fmt\fR
and will be created in the directory named by
the macro \fB%_repackage_dir\fR (default value
is \fI/var/tmp\fR).
.TP
\fB--test\fR
Don't really uninstall anything, just go through the motions.
Useful in conjunction with the \fB-vv\fR option

View File

@ -698,7 +698,6 @@ static int expandRegular(/*@special@*/ FSM_t fsm)
if (rc)
goto exit;
/* XXX md5sum's will break on repackaging that includes modified files. */
fmd5sum = fsm->fmd5sum;
/* XXX This doesn't support brokenEndian checks. */

View File

@ -20,7 +20,6 @@ struct rpmInstallArguments_s rpmIArgs;
#define POPT_RELOCATE -1016
#define POPT_EXCLUDEPATH -1019
#define POPT_ROLLBACK -1024
/*@exits@*/ static void argerror(const char * desc)
/*@globals fileSystem @*/
@ -78,16 +77,6 @@ fprintf(stderr, "*** opt %s %c info 0x%x arg %p val 0x%x arg %p %s\n", opt->long
/*@=kepttrans@*/
ia->numRelocations++;
} break;
case POPT_ROLLBACK:
{ time_t tid;
if (arg == NULL)
argerror(_("rollback takes a time/date stamp argument"));
tid = get_date(arg, NULL);
if (tid == (time_t)-1 || tid == (time_t)0)
argerror(_("malformed rollback time/date stamp argument"));
ia->rbtid = tid;
} break;
default:
break;
}
@ -116,9 +105,6 @@ struct poptOption rpmInstallPoptTable[] = {
{ "badreloc", '\0', POPT_BIT_SET,
&rpmIArgs.probFilter, RPMPROB_FILTER_FORCERELOCATE,
N_("relocate files in non-relocatable package"), NULL},
{ "dirstash", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN,
&rpmIArgs.transFlags, RPMTRANS_FLAG_DIRSTASH,
N_("save erased package files by renaming into sub-directory"), NULL},
{ "erase", 'e', POPT_BIT_SET,
&rpmIArgs.installInterfaceFlags, INSTALL_ERASE,
N_("erase (uninstall) package"), N_("<package>+") },
@ -211,18 +197,12 @@ struct poptOption rpmInstallPoptTable[] = {
{ "relocate", '\0', POPT_ARG_STRING, 0, POPT_RELOCATE,
N_("relocate files from path <old> to <new>"),
N_("<old>=<new>") },
{ "repackage", '\0', POPT_BIT_SET,
&rpmIArgs.transFlags, RPMTRANS_FLAG_REPACKAGE,
N_("save erased package files by repackaging"), NULL},
{ "replacefiles", '\0', POPT_BIT_SET, &rpmIArgs.probFilter,
(RPMPROB_FILTER_REPLACEOLDFILES | RPMPROB_FILTER_REPLACENEWFILES),
N_("install even if the package replaces installed files"), NULL},
{ "replacepkgs", '\0', POPT_BIT_SET,
&rpmIArgs.probFilter, RPMPROB_FILTER_REPLACEPKG,
N_("reinstall if the package is already present"), NULL},
{ "rollback", '\0', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, 0, POPT_ROLLBACK,
N_("deinstall new, reinstall old, package(s), back to <date>"),
N_("<date>") },
{ "test", '\0', POPT_BIT_SET, &rpmIArgs.transFlags, RPMTRANS_FLAG_TEST,
N_("don't install, but tell if it would work or not"), NULL},
{ "upgrade", 'U', POPT_BIT_SET,

183
lib/psm.c
View File

@ -1192,7 +1192,6 @@ static int runImmedTriggers(PSM_t psm)
case PSM_PKGINSTALL: return " install";
case PSM_PKGERASE: return " erase";
case PSM_PKGCOMMIT: return " commit";
case PSM_PKGSAVE: return "repackage";
case PSM_INIT: return "init";
case PSM_PRE: return "pre";
@ -1274,9 +1273,8 @@ assert(psm->mi == NULL);
xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_SHA1HEADER,
RPMMIRE_DEFAULT, fi->digest);
while ((psm->oh = rpmdbNextIterator(psm->mi))) {
while (rpmdbNextIterator(psm->mi)) {
fi->record = rpmdbGetIteratorOffset(psm->mi);
psm->oh = NULL;
/*@loopbreak@*/ break;
}
psm->mi = rpmdbFreeIterator(psm->mi);
@ -1319,31 +1317,12 @@ assert(psm->mi == NULL);
fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
rc = RPMRC_OK;
}
if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
if (psm->goal == PSM_PKGERASE) {
psm->scriptArg = psm->npkgs_installed - 1;
/* Retrieve installed header. */
rc = psmStage(psm, PSM_RPMDB_LOAD);
}
if (psm->goal == PSM_PKGSAVE) {
/* Open output package for writing. */
{ const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
const char * pkgbn =
headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
bfmt = _free(bfmt);
psm->pkgURL = rpmGenPath("%{?_repackage_root}",
"%{?_repackage_dir}",
pkgbn);
pkgbn = _free(pkgbn);
(void) urlPath(psm->pkgURL, &psm->pkgfn);
psm->fd = Fopen(psm->pkgfn, "w.ufdio");
if (psm->fd == NULL || Ferror(psm->fd)) {
rc = RPMRC_FAIL;
break;
}
}
}
break;
case PSM_PRE:
if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
@ -1390,101 +1369,6 @@ assert(psm->mi == NULL);
if (!(ts->transFlags & RPMTRANS_FLAG_NOPREUN))
rc = psmStage(psm, PSM_SCRIPT);
}
if (psm->goal == PSM_PKGSAVE) {
/* Regenerate original header. */
{ void * uh = NULL;
int_32 uht, uhc;
if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
{
psm->oh = headerCopyLoad(uh);
uh = hfd(uh, uht);
} else
if (headerGetEntry(fi->h, RPMTAG_HEADERIMAGE, &uht, &uh, &uhc))
{
HeaderIterator hi;
int_32 tag, type, count;
hPTR_t ptr;
Header oh;
/* Load the original header from the blob. */
oh = headerCopyLoad(uh);
/* XXX this is headerCopy w/o headerReload() */
psm->oh = headerNew();
/*@-branchstate@*/
for (hi = headerInitIterator(oh);
headerNextIterator(hi, &tag, &type, &ptr, &count);
ptr = headerFreeData((void *)ptr, type))
{
if (ptr) (void) headerAddEntry(psm->oh, tag, type, ptr, count);
}
hi = headerFreeIterator(hi);
/*@=branchstate@*/
headerFree(oh);
uh = hfd(uh, uht);
} else {
break;
}
}
/* Retrieve type of payload compression. */
/*@-nullstate@*/ /* FIX: psm->oh may be NULL */
rc = psmStage(psm, PSM_RPMIO_FLAGS);
/*@=nullstate@*/
/* Write the lead section into the package. */
{ int archnum = -1;
int osnum = -1;
struct rpmlead lead;
#ifndef DYING
rpmGetArchInfo(NULL, &archnum);
rpmGetOsInfo(NULL, &osnum);
#endif
memset(&lead, 0, sizeof(lead));
lead.major = 3;
lead.minor = 0;
lead.type = RPMLEAD_BINARY;
lead.archnum = archnum;
lead.osnum = osnum;
lead.signature_type = RPMSIGTYPE_HEADERSIG;
{ char buf[256];
sprintf(buf, "%s-%s-%s", fi->name, fi->version, fi->release);
strncpy(lead.name, buf, sizeof(lead.name));
}
rc = writeLead(psm->fd, &lead);
if (rc) {
rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
Fstrerror(psm->fd));
rc = RPMRC_FAIL;
break;
}
}
/* Write the signature section into the package. */
{ Header sig = headerRegenSigHeader(fi->h);
rc = rpmWriteSignature(psm->fd, sig);
sig = rpmFreeSignature(sig);
if (rc) break;
}
/* Add remove transaction id to header. */
if (psm->oh)
{ int_32 tid = ts->id;
xx = headerAddEntry(psm->oh, RPMTAG_REMOVETID,
RPM_INT32_TYPE, &tid, 1);
}
/* Write the metadata section into the package. */
rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
if (rc) break;
}
break;
case PSM_PROCESS:
if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
@ -1601,40 +1485,6 @@ assert(psm->mi == NULL);
xx = psmStage(psm, PSM_NOTIFY);
}
if (psm->goal == PSM_PKGSAVE) {
fileAction * actions = fi->actions;
fileAction action = fi->action;
fi->action = FA_COPYOUT;
fi->actions = NULL;
if (psm->fd == NULL) { /* XXX can't happen */
rc = RPMRC_FAIL;
break;
}
/*@-nullpass@*/ /* LCL: psm->fd != NULL here. */
xx = Fflush(psm->fd);
psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
/*@=nullpass@*/
if (psm->cfd == NULL) { /* XXX can't happen */
rc = RPMRC_FAIL;
break;
}
rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
NULL, &psm->failedFile);
xx = fsmTeardown(fi->fsm);
saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
xx = Fclose(psm->cfd);
psm->cfd = NULL;
/*@-mods@*/
errno = saveerrno;
/*@=mods@*/
fi->action = action;
fi->actions = actions;
}
break;
case PSM_POST:
if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
@ -1705,8 +1555,6 @@ assert(psm->mi == NULL);
if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
rc = psmStage(psm, PSM_RPMDB_REMOVE);
}
if (psm->goal == PSM_PKGSAVE) {
}
/* Restore root directory if changed. */
xx = psmStage(psm, PSM_CHROOT_OUT);
@ -1717,22 +1565,6 @@ assert(psm->mi == NULL);
/* Restore root directory if changed. */
xx = psmStage(psm, PSM_CHROOT_OUT);
if (psm->fd) {
saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
xx = Fclose(psm->fd);
psm->fd = NULL;
/*@-mods@*/
errno = saveerrno;
/*@=mods@*/
}
if (psm->goal == PSM_PKGSAVE) {
if (!rc) {
rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
(psm->pkgURL ? psm->pkgURL : "???"));
}
}
if (rc) {
if (psm->failedFile)
rpmError(RPMERR_CPIO,
@ -1749,10 +1581,8 @@ assert(psm->mi == NULL);
xx = psmStage(psm, PSM_NOTIFY);
}
if (fi->h && (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE))
if (fi->h && psm->goal == PSM_PKGERASE)
fi->h = headerFree(fi->h);
psm->oh = headerFree(psm->oh);
psm->pkgURL = _free(psm->pkgURL);
psm->rpmio_flags = _free(psm->rpmio_flags);
psm->failedFile = _free(psm->failedFile);
@ -1766,7 +1596,6 @@ assert(psm->mi == NULL);
case PSM_PKGINSTALL:
case PSM_PKGERASE:
case PSM_PKGSAVE:
psm->goal = stage;
psm->rc = RPMRC_OK;
psm->stepName = pkgStageString(stage);
@ -1865,9 +1694,9 @@ assert(psm->mi == NULL);
if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
(void **) &payload_compressor, NULL))
payload_compressor = "gzip";
psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
psm->rpmio_flags = t = xmalloc(sizeof("r.gzdio"));
*t = '\0';
t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
t = stpcpy(t, "r");
if (!strcmp(payload_compressor, "gzip"))
t = stpcpy(t, ".gzdio");
if (!strcmp(payload_compressor, "bzip2"))
@ -1926,7 +1755,7 @@ fprintf(stderr, "*** PSM_RDB_LOAD: header #%u not found\n", fi->record);
}
/*@=branchstate@*/
/*@-nullstate@*/ /* FIX: psm->oh and psm->fi->h may be NULL. */
/*@-nullstate@*/ /* FIX: psm->fi->h may be NULL. */
return rc;
/*@=nullstate@*/
}

View File

@ -133,7 +133,6 @@ typedef enum pkgStage_e {
PSM_PKGINSTALL = 7,
PSM_PKGERASE = 8,
PSM_PKGCOMMIT = 10,
PSM_PKGSAVE = 12,
PSM_CREATE = 17,
PSM_NOTIFY = 22,
@ -165,8 +164,6 @@ struct psm_s {
/*@kept@*/
TFI_t fi; /*!< transaction element file info */
FD_t cfd; /*!< Payload file handle. */
FD_t fd; /*!< Repackage file handle. */
Header oh; /*!< Repackage header. */
/*@null@*/
rpmdbMatchIterator mi;
/*@observer@*/
@ -175,10 +172,7 @@ struct psm_s {
const char * rpmio_flags;
/*@only@*/ /*@null@*/
const char * failedFile;
/*@only@*/ /*@null@*/
const char * pkgURL; /*!< Repackage URL. */
/*@dependent@*/
const char * pkgfn; /*!< Repackage file name. */
int scriptTag; /*!< Scriptlet data tag. */
int progTag; /*!< Scriptlet interpreter tag. */
int npkgs_installed; /*!< No. of installed instances. */

View File

@ -335,88 +335,8 @@ struct rpmInstallArguments_s {
const char * prefix;
/*@observer@*/ /*@null@*/
const char * rootdir;
uint_32 rbtid; /*!< from --rollback */
};
/**
* A rollback transaction id element.
*/
typedef /*@abstract@*/ struct IDT_s {
unsigned int instance; /*!< installed package transaction id. */
/*@owned@*/ /*@null@*/
const char * key; /*! removed package file name. */
Header h; /*!< removed package header. */
const char * n; /*!< package name. */
const char * v; /*!< package version. */
const char * r; /*!< package release. */
union {
uint_32 u32; /*!< install/remove transaction id */
} val;
} * IDT;
/**
* A rollback transaction id index.
*/
typedef /*@abstract@*/ struct IDTindex_s {
int delta; /*!< no. elements to realloc as a chunk. */
int size; /*!< size of id index element. */
int alloced; /*!< current number of elements allocated. */
int nidt; /*!< current number of elements initialized. */
/*@only@*/ /*@null@*/
IDT idt; /*!< id index elements. */
} * IDTX;
/**
* Destroy id index.
* @param idtx id index
* @return NULL always
*/
/*@null@*/ IDTX IDTXfree(/*@only@*/ /*@null@*/ IDTX idtx)
/*@modifies idtx @*/;
/**
* Create id index.
* @return new id index
*/
/*@only@*/ IDTX IDTXnew(void)
/*@*/;
/**
* Insure that index has room for "need" elements.
* @param idtx id index
* @param need additional no. of elements needed
* @return id index (with room for "need" elements)
*/
/*@only@*/ /*@null@*/ IDTX IDTXgrow(/*@only@*/ /*@null@*/ IDTX idtx, int need)
/*@modifies idtx @*/;
/**
* Sort tag (instance,value) pairs.
* @param idtx id index
* @return id index
*/
/*@only@*/ /*@null@*/ IDTX IDTXsort(/*@only@*/ /*@null@*/ IDTX idtx)
/*@modifies idtx @*/;
/**
* Load tag (instance,value) pairs from rpm databse, and return sorted id index.
* @param db rpm database
* @param tag rpm tag
* @return id index
*/
/*@only@*/ /*@null@*/ IDTX IDTXload(rpmdb db, rpmTag tag)
/*@modifies db @*/;
/**
* Load tag (instance,value) pairs from packages, and return sorted id index.
* @param globstr glob expression
* @param tag rpm tag
* @return id index
*/
/*@only@*/ /*@null@*/ IDTX IDTXglob(const char * globstr, rpmTag tag)
/*@globals fileSystem @*/
/*@modifies fileSystem @*/;
/**
* The rpm CLI generic transaction callback.
@ -443,15 +363,6 @@ typedef /*@abstract@*/ struct IDTindex_s {
/*@unchecked@*/
extern int packagesTotal;
/** \ingroup rpmcli
* Rollback transactions, erasing new, reinstalling old, package(s).
* @return 0 on success
*/
int rpmRollback(struct rpmInstallArguments_s * ia,
/*@null@*/ const char ** argv)
/*@globals rpmGlobalMacroContext, fileSystem @*/
/*@modifies rpmGlobalMacroContext, fileSystem @*/;
/** \ingroup rpmcli
*/
/*@unchecked@*/

View File

@ -803,384 +803,3 @@ int rpmInstallSource(const char * rootdir, const char * arg,
return rc;
}
/*@unchecked@*/
static int reverse = -1;
/**
*/
static int IDTintcmp(const void * a, const void * b)
/*@*/
{
/*@-castexpose@*/
IDT ap = (IDT)a;
IDT bp = (IDT)b;
/*@=castexpose@*/
int rc = ((int)ap->val.u32 - (int)bp->val.u32);
if (rc)
return ( reverse * rc );
return ( strcmp(ap->n, bp->n) );
}
IDTX IDTXfree(IDTX idtx)
{
if (idtx) {
int i;
if (idtx->idt)
for (i = 0; i < idtx->nidt; i++) {
IDT idt = idtx->idt + i;
idt->h = headerFree(idt->h);
idt->key = _free(idt->key);
}
idtx->idt = _free(idtx->idt);
idtx = _free(idtx);
}
return NULL;
}
IDTX IDTXnew(void)
{
IDTX idtx = xcalloc(1, sizeof(*idtx));
idtx->delta = 10;
idtx->size = sizeof(*((IDT)0));
return idtx;
}
IDTX IDTXgrow(IDTX idtx, int need)
{
if (need < 0) return NULL;
if (idtx == NULL)
idtx = IDTXnew();
if (need == 0) return idtx;
if ((idtx->nidt + need) > idtx->alloced) {
while (need > 0) {
idtx->alloced += idtx->delta;
need -= idtx->delta;
}
idtx->idt = xrealloc(idtx->idt, (idtx->alloced * idtx->size) );
}
return idtx;
}
IDTX IDTXsort(IDTX idtx)
{
if (idtx != NULL && idtx->idt != NULL && idtx->nidt > 0)
qsort(idtx->idt, idtx->nidt, idtx->size, IDTintcmp);
return idtx;
}
IDTX IDTXload(rpmdb db, rpmTag tag)
{
IDTX idtx = NULL;
rpmdbMatchIterator mi;
HGE_t hge = (HGE_t) headerGetEntry;
Header h;
mi = rpmdbInitIterator(db, tag, NULL, 0);
/*@-branchstate@*/
while ((h = rpmdbNextIterator(mi)) != NULL) {
rpmTagType type = RPM_NULL_TYPE;
int_32 count = 0;
int_32 * tidp;
tidp = NULL;
if (!hge(h, tag, &type, (void **)&tidp, &count) || tidp == NULL)
continue;
if (type == RPM_INT32_TYPE && (*tidp == 0 || *tidp == -1))
continue;
idtx = IDTXgrow(idtx, 1);
if (idtx == NULL)
continue;
if (idtx->idt == NULL)
continue;
{ IDT idt;
/*@-nullderef@*/
idt = idtx->idt + idtx->nidt;
/*@=nullderef@*/
idt->h = headerLink(h);
(void) headerNVR(idt->h, &idt->n, &idt->v, &idt->r);
idt->key = NULL;
idt->instance = rpmdbGetIteratorOffset(mi);
idt->val.u32 = *tidp;
}
idtx->nidt++;
}
/*@=branchstate@*/
mi = rpmdbFreeIterator(mi);
return IDTXsort(idtx);
}
IDTX IDTXglob(const char * globstr, rpmTag tag)
{
IDTX idtx = NULL;
HGE_t hge = (HGE_t) headerGetEntry;
Header h;
int_32 * tidp;
FD_t fd;
const char ** av = NULL;
int ac = 0;
int rc;
int i;
av = NULL; ac = 0;
rc = rpmGlob(globstr, &ac, &av);
if (rc == 0)
for (i = 0; i < ac; i++) {
rpmTagType type;
int_32 count;
int isSource;
rpmRC rpmrc;
fd = Fopen(av[i], "r.ufdio");
if (fd == NULL || Ferror(fd)) {
rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), av[i],
Fstrerror(fd));
if (fd) (void) Fclose(fd);
continue;
}
/*@-mustmod@*/ /* LCL: segfault */
rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
/*@=mustmod@*/
if (rpmrc != RPMRC_OK || isSource) {
(void) Fclose(fd);
continue;
}
tidp = NULL;
/*@-branchstate@*/
if (hge(h, tag, &type, (void **) &tidp, &count) && tidp) {
idtx = IDTXgrow(idtx, 1);
if (idtx == NULL || idtx->idt == NULL) {
h = headerFree(h);
(void) Fclose(fd);
continue;
}
{ IDT idt;
idt = idtx->idt + idtx->nidt;
idt->h = headerLink(h);
(void) headerNVR(idt->h, &idt->n, &idt->v, &idt->r);
idt->key = xstrdup(av[i]);
idt->instance = 0;
idt->val.u32 = *tidp;
}
idtx->nidt++;
}
/*@=branchstate@*/
h = headerFree(h);
(void) Fclose(fd);
}
for (i = 0; i < ac; i++)
av[i] = _free(av[i]);
av = _free(av); ac = 0;
return IDTXsort(idtx);
}
int rpmRollback(struct rpmInstallArguments_s * ia, const char ** argv)
{
rpmdb db = NULL;
rpmTransactionSet ts = NULL;
rpmDependencyConflict conflicts = NULL;
int numConflicts = 0;
rpmProblemSet probs = NULL;
IDTX itids = NULL;
IDTX rtids = NULL;
unsigned thistid = 0xffffffff;
unsigned prevtid;
time_t tid;
IDT rp;
int nrids = 0;
IDT ip;
int niids = 0;
int packagesIn;
int packagesOut;
int rc;
int i;
int ifmask= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE);
if (argv != NULL && *argv != NULL) {
rc = -1;
goto exit;
}
rc = rpmdbOpen(ia->rootdir, &db, O_RDWR, 0644);
if (rc != 0)
goto exit;
itids = IDTXload(db, RPMTAG_INSTALLTID);
if (itids != NULL) {
ip = itids->idt;
niids = itids->nidt;
} else {
ip = NULL;
niids = 0;
}
{ const char * globstr = rpmExpand("%{?_repackage_dir}/*.rpm", NULL);
if (globstr == NULL || !strcmp(globstr, "/*.rpm")) {
globstr = _free(globstr);
rc = -1;
goto exit;
}
rtids = IDTXglob(globstr, RPMTAG_REMOVETID);
if (rtids != NULL) {
rp = rtids->idt;
nrids = rtids->nidt;
} else {
rp = NULL;
nrids = 0;
}
globstr = _free(globstr);
}
/* Run transactions until rollback goal is achieved. */
do {
prevtid = thistid;
rc = 0;
packagesTotal = 0;
packagesIn = 0;
packagesOut = 0;
ia->installInterfaceFlags &= ~ifmask;
/* Find larger of the remaining install/erase transaction id's. */
thistid = 0;
if (ip != NULL && ip->val.u32 > thistid)
thistid = ip->val.u32;
if (rp != NULL && rp->val.u32 > thistid)
thistid = rp->val.u32;
/* If we've achieved the rollback goal, then we're done. */
if (thistid == 0 || thistid < ia->rbtid)
break;
ts = rpmtransCreateSet(db, ia->rootdir);
/* Install the previously erased packages for this transaction. */
while (rp != NULL && rp->val.u32 == thistid) {
rpmMessage(RPMMESS_DEBUG, "\t+++ %s-%s-%s\t(from %s)\n", rp->n, rp->v, rp->r, basename(rp->key));
if (!(ia->installInterfaceFlags & ifmask))
ia->installInterfaceFlags |= INSTALL_INSTALL;
rc = rpmtransAddPackage(ts, rp->h, NULL, rp->key,
(ia->installInterfaceFlags & INSTALL_UPGRADE) != 0,
ia->relocations);
if (rc != 0)
goto exit;
packagesTotal++;
packagesIn++;
#ifdef NOTYET
rp->h = headerFree(rp->h);
#endif
nrids--;
if (nrids > 0)
rp++;
else
rp = NULL;
}
/*
* XXX OK, let's prevent disaster right here, as rollbacks will merrily
* XXX erase everything in order to achieve the desired goal.
*/
if (packagesIn == 0)
break;
/* Erase the previously installed packages for this transaction. */
while (ip != NULL && ip->val.u32 == thistid) {
rpmMessage(RPMMESS_DEBUG,
"\t--- %s-%s-%s\t(from rpmdb instance #%u)\n", ip->n, ip->v, ip->r, ip->instance);
if (!(ia->installInterfaceFlags & ifmask))
ia->installInterfaceFlags |= INSTALL_ERASE;
rc = rpmtransRemovePackage(ts, ip->instance);
if (rc != 0)
goto exit;
packagesTotal++;
packagesOut++;
#ifdef NOTYET
ip->instance = 0;
#endif
niids--;
if (niids > 0)
ip++;
else
ip = NULL;
}
/* Anything to do? */
if (packagesTotal <= 0)
break;
tid = (time_t)thistid;
rpmMessage(RPMMESS_DEBUG, _("rollback (+%d,-%d) packages to %s"),
packagesIn, packagesOut, ctime(&tid));
conflicts = NULL;
numConflicts = 0;
rc = rpmdepCheck(ts, &conflicts, &numConflicts);
if (rc != 0) {
rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
printDepProblems(stderr, conflicts, numConflicts);
conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
goto exit;
}
rc = rpmdepOrder(ts);
if (rc != 0)
goto exit;
probs = NULL;
rc = rpmRunTransactions(ts, rpmShowProgress,
(void *) ((long)ia->installInterfaceFlags),
NULL, &probs, ia->transFlags,
(ia->probFilter|RPMPROB_FILTER_OLDPACKAGE));
if (rc > 0) {
rpmProblemSetPrint(stderr, probs);
if (probs != NULL) rpmProblemSetFree(probs);
probs = NULL;
}
if (rc)
goto exit;
ts = rpmtransFree(ts);
/* Clean up after successful rollback. */
if (!rpmIsDebug())
for (i = 0; i < rtids->nidt; i++) {
IDT rrp = rtids->idt + i;
if (rrp->val.u32 != thistid)
continue;
(void) unlink(rrp->key);
}
} while (1);
exit:
ts = rpmtransFree(ts);
if (db != NULL) (void) rpmdbClose(db);
rtids = IDTXfree(rtids);
itids = IDTXfree(itids);
return rc;
}

View File

@ -1402,8 +1402,8 @@ typedef enum rpmtransFlags_e {
RPMTRANS_FLAG_KEEPOBSOLETE = (1 << 7), /*!< @todo Document. */
/*@=enummemuse@*/
RPMTRANS_FLAG_NOCONTEXTS = (1 << 8), /*!< from --nocontexts */
RPMTRANS_FLAG_DIRSTASH = (1 << 9), /*!< from --dirstash */
RPMTRANS_FLAG_REPACKAGE = (1 << 10), /*!< from --repackage */
R__TRANS_FLAG_DIRSTASH = (1 << 9), /*!< from --dirstash */
R__TRANS_FLAG_REPACKAGE = (1 << 10), /*!< from --repackage */
RPMTRANS_FLAG_PKGCOMMIT = (1 << 11),
/*@-enummemuse@*/

View File

@ -1943,25 +1943,6 @@ int rpmRunTransactions( rpmTransactionSet ts,
/*@=nullstate@*/
}
/* ===============================================
* Save removed files before erasing.
*/
if (ts->transFlags & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
tsi = tsInitIterator(ts);
while ((fi = tsNextIterator(tsi)) != NULL) {
psm->fi = fi;
switch (fi->type) {
case TR_ADDED:
break;
case TR_REMOVED:
if (ts->transFlags & RPMTRANS_FLAG_REPACKAGE)
(void) psmStage(psm, PSM_PKGSAVE);
break;
}
}
tsi = tsFreeIterator(tsi);
}
/* ===============================================
* Install and remove packages.
*/

View File

@ -516,17 +516,6 @@
# XXX Note: escaped %% for use in headerSprintf()
%_build_name_fmt %%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
# The output binary package file name template used when repackaging
# erased packages.
#
# XXX Note: escaped %% for use in headerSprintf()
%_repackage_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
# The directory in which erased packages will be saved when using
# the --repackage option.
%_repackage_dir /var/spool/repackage
%_repackage_root %{nil}
#==============================================================================
# ---- per-platform macros.
# Macros that are specific to an individual platform. The values here

View File

@ -2497,14 +2497,6 @@ msgid ""
"only packaging with major numbers <= 4 is supported by this version of RPM\n"
msgstr ""
#: lib/poptI.c:82
msgid "rollback takes a time/date stamp argument"
msgstr ""
#: lib/poptI.c:86
msgid "malformed rollback time/date stamp argument"
msgstr ""
#: lib/poptI.c:112 lib/poptI.c:166
msgid "do not execute package scriptlet(s)"
msgstr ""
@ -2589,10 +2581,6 @@ msgstr ""
msgid "<old>=<new>"
msgstr ""
#: lib/poptI.c:211
msgid "save erased package files by repackaging"
msgstr ""
#: lib/poptI.c:219
msgid "deinstall new, reinstall old, package(s), back to <date>"
msgstr ""
@ -3222,11 +3210,6 @@ msgstr ""
msgid "Installing %s\n"
msgstr ""
#: lib/rpminstall.c:1049
#, c-format
msgid "rollback (+%d,-%d) packages to %s"
msgstr ""
#: lib/rpmlead.c:50
#, c-format
msgid "read failed: %s (%d)\n"

View File

@ -1813,14 +1813,6 @@ msgstr "перемещения должны содержать ="
msgid "relocations must have a / following the ="
msgstr "перемещения должны иметь / после ="
#: lib/poptI.c:84
msgid "rollback takes a time/date stamp argument"
msgstr "для отката транзакции необходимо указать момент времени"
#: lib/poptI.c:88
msgid "malformed rollback time/date stamp argument"
msgstr "неправильный формат момента времени отката транзакции"
#: lib/poptI.c:104
msgid "install all files, even configurations which might otherwise be skipped"
msgstr ""
@ -1991,10 +1983,6 @@ msgstr "переместить файлы из пути <old> в <new>"
msgid "<old>=<new>"
msgstr "<old>=<new>"
#: lib/poptI.c:216
msgid "save erased package files by repackaging"
msgstr "сохранить подлежащие удалению файлы в новом пакете"
#: lib/poptI.c:219
msgid "install even if the package replaces installed files"
msgstr "устанавливать, даже если пакет перепишет уже установленные файлы"
@ -2667,11 +2655,6 @@ msgstr "невозможно открыть %s: %s\n"
msgid "Installing %s\n"
msgstr "Устанавливается %s\n"
#: lib/rpminstall.c:1117
#, c-format
msgid "rollback (+%d,-%d) packages to %s"
msgstr "откат транзакции (+%d,-%d) пакетов на %s"
#: lib/rpmlead.c:50
#, c-format
msgid "read failed: %s (%d)\n"

View File

@ -1810,14 +1810,6 @@ msgstr "переміщення мають містити ="
msgid "relocations must have a / following the ="
msgstr "переміщення потрібні мати / після ="
#: lib/poptI.c:84
msgid "rollback takes a time/date stamp argument"
msgstr "для відкочування транзакції потрібно вказати момент часу"
#: lib/poptI.c:88
msgid "malformed rollback time/date stamp argument"
msgstr "невірний формат моменту часу відкочування транзакції"
#: lib/poptI.c:104
msgid "install all files, even configurations which might otherwise be skipped"
msgstr ""
@ -1987,10 +1979,6 @@ msgstr "перемістити файли із шляху <old> у <new>"
msgid "<old>=<new>"
msgstr "<old>=<new>"
#: lib/poptI.c:216
msgid "save erased package files by repackaging"
msgstr "зберегти файли які підлягають видаленню у новому пакеті"
#: lib/poptI.c:219
msgid "install even if the package replaces installed files"
msgstr "встановлювати, навіть якщо пакет перепише вже встановлені файли"
@ -2663,11 +2651,6 @@ msgstr "неможливо відкрити %s: %s\n"
msgid "Installing %s\n"
msgstr "Встановлюється %s\n"
#: lib/rpminstall.c:1117
#, c-format
msgid "rollback (+%d,-%d) packages to %s"
msgstr "відкочування транзакції (+%d,-%d) пакетів на %s"
#: lib/rpmlead.c:50
#, c-format
msgid "read failed: %s (%d)\n"

12
rpmqv.c
View File

@ -1050,11 +1050,7 @@ int main(int argc, const char ** argv)
if (ia->noDeps) ia->eraseInterfaceFlags |= UNINSTALL_NODEPS;
if (!poptPeekArg(optCon)) {
if (ia->rbtid == 0)
argerror(_("no packages given for erase"));
ia->transFlags |= RPMTRANS_FLAG_NOMD5;
ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
ec += rpmRollback(ia, NULL);
argerror(_("no packages given for erase"));
} else {
ec += rpmErase(rootdir, (const char **)poptGetArgs(optCon),
ia->transFlags, ia->eraseInterfaceFlags);
@ -1088,11 +1084,7 @@ ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
}
if (!poptPeekArg(optCon)) {
if (ia->rbtid == 0)
argerror(_("no packages given for install"));
ia->transFlags |= RPMTRANS_FLAG_NOMD5;
ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
ec += rpmRollback(ia, NULL);
argerror(_("no packages given for install"));
} else {
/*@-compdef@*/ /* FIX: ia->relocations[0].newPath undefined */