Main Page Modules Data Structures File List Data Fields Globals Related Pages

# lib/rpminstall.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmcli.h>
    00008
    00009 #include "rpmdb.h"
    00010 #include "rpmds.h"
    00011
    00012 #define _RPMTS_INTERNAL         /* ts->goal, ts->dbmode, ts->suggests */
    00013 #include "rpmts.h"
    00014
    00015 #include "manifest.h"
    00016 #include "misc.h"       /* XXX for rpmGlob() */
    00017 #include "debug.h"
    00018
    00019 /*@access rpmts @*/     /* XXX ts->goal, ts->dbmode */
    00020 /*@access rpmps @*/     /* XXX compared with NULL */
    00021 /*@access Header @*/            /* XXX compared with NULL */
    00022 /*@access rpmdb @*/             /* XXX compared with NULL */
    00023 /*@access FD_t @*/              /* XXX compared with NULL */
    00024 /*@access IDTX @*/
    00025 /*@access IDT @*/
    00026
    00027 /*@unchecked@*/
    00028 int rpmcliPackagesTotal = 0;
    00029 /*@unchecked@*/
    00030 int rpmcliHashesCurrent = 0;
    00031 /*@unchecked@*/
    00032 int rpmcliHashesTotal = 0;
    00033 /*@unchecked@*/
    00034 int rpmcliProgressCurrent = 0;
    00035 /*@unchecked@*/
    00036 int rpmcliProgressTotal = 0;
    00037
    00044 static void printHash(const unsigned long amount, const unsigned long total)
    00045         /*@globals rpmcliHashesCurrent, rpmcliHashesTotal,
    00046                 rpmcliProgressCurrent, fileSystem @*/
    00047         /*@modifies rpmcliHashesCurrent, rpmcliHashesTotal,
    00048                 rpmcliProgressCurrent, fileSystem @*/
    00049 {
    00050     int hashesNeeded;
    00051
    00052     rpmcliHashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50);
    00053
    00054     if (rpmcliHashesCurrent != rpmcliHashesTotal) {
    00055         float pct = (total ? (((float) amount) / total) : 1.0);
    00056         hashesNeeded = (rpmcliHashesTotal * pct) + 0.5;
    00057         while (hashesNeeded > rpmcliHashesCurrent) {
    00058             if (isatty (STDOUT_FILENO)) {
    00059                 int i;
    00060                 for (i = 0; i < rpmcliHashesCurrent; i++)
    00061                     (void) putchar ('#');
    00062                 for (; i < rpmcliHashesTotal; i++)
    00063                     (void) putchar (' ');
    00064                 fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5));
    00065                 for (i = 0; i < (rpmcliHashesTotal + 6); i++)
    00066                     (void) putchar ('\b');
    00067             } else
    00068                 fprintf(stdout, "#");
    00069
    00070             rpmcliHashesCurrent++;
    00071         }
    00072         (void) fflush(stdout);
    00073
    00074         if (rpmcliHashesCurrent == rpmcliHashesTotal) {
    00075             int i;
    00076             rpmcliProgressCurrent++;
    00077             if (isatty(STDOUT_FILENO)) {
    00078                 for (i = 1; i < rpmcliHashesCurrent; i++)
    00079                     (void) putchar ('#');
    00080                 pct = (rpmcliProgressTotal
    00081                     ? (((float) rpmcliProgressCurrent) / rpmcliProgressTotal)
    00082                     : 1);
    00083                 fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5));
    00084             }
    00085             fprintf(stdout, "\n");
    00086         }
    00087         (void) fflush(stdout);
    00088     }
    00089 }
    00090
    00091 void * rpmShowProgress(/*@null@*/ const void * arg,
    00092                         const rpmCallbackType what,
    00093                         const unsigned long amount,
    00094                         const unsigned long total,
    00095                         /*@null@*/ fnpyKey key,
    00096                         /*@null@*/ void * data)
    00097         /*@globals rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
    00098                 fileSystem @*/
    00099         /*@modifies rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
    00100                 fileSystem @*/
    00101 {
    00102     /*@-castexpose@*/
    00103     Header h = (Header) arg;
    00104     /*@=castexpose@*/
    00105     char * s;
    00106     int flags = (int) ((long)data);
    00107     void * rc = NULL;
    00108     /*@-assignexpose -abstract @*/
    00109     const char * filename = (const char *)key;
    00110     /*@=assignexpose =abstract @*/
    00111     static FD_t fd = NULL;
    00112     int xx;
    00113
    00114     switch (what) {
    00115     case RPMCALLBACK_INST_OPEN_FILE:
    00116 /*@-boundsread@*/
    00117         if (filename == NULL || filename[0] == '\0')
    00118             return NULL;
    00119 /*@=boundsread@*/
    00120         fd = Fopen(filename, "r.ufdio");
    00121         /*@-type@*/ /* FIX: still necessary? */
    00122         if (fd == NULL || Ferror(fd)) {
    00123             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), filename,
    00124                         Fstrerror(fd));
    00125             if (fd) {
    00126                 xx = Fclose(fd);
    00127                 fd = NULL;
    00128             }
    00129         } else
    00130             fd = fdLink(fd, "persist (showProgress)");
    00131         /*@=type@*/
    00132         return fd;
    00133         /*@notreached@*/ break;
    00134
    00135     case RPMCALLBACK_INST_CLOSE_FILE:
    00136         /*@-type@*/ /* FIX: still necessary? */
    00137         fd = fdFree(fd, "persist (showProgress)");
    00138         /*@=type@*/
    00139         if (fd) {
    00140             xx = Fclose(fd);
    00141             fd = NULL;
    00142         }
    00143         break;
    00144
    00145     case RPMCALLBACK_INST_START:
    00146         rpmcliHashesCurrent = 0;
    00147         if (h == NULL || !(flags & INSTALL_LABEL))
    00148             break;
    00149         /* @todo Remove headerSprintf() on a progress callback. */
    00150         if (flags & INSTALL_HASH) {
    00151             s = headerSprintf(h, "%{NAME}",
    00152                                 rpmTagTable, rpmHeaderFormats, NULL);
    00153             if (isatty (STDOUT_FILENO))
    00154                 fprintf(stdout, "%4d:%-23.23s", rpmcliProgressCurrent + 1, s);
    00155             else
    00156                 fprintf(stdout, "%-28.28s", s);
    00157             (void) fflush(stdout);
    00158             s = _free(s);
    00159         } else {
    00160             s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}",
    00161                                   rpmTagTable, rpmHeaderFormats, NULL);
    00162             fprintf(stdout, "%s\n", s);
    00163             (void) fflush(stdout);
    00164             s = _free(s);
    00165         }
    00166         break;
    00167
    00168     case RPMCALLBACK_TRANS_PROGRESS:
    00169     case RPMCALLBACK_INST_PROGRESS:
    00170         if (flags & INSTALL_PERCENT)
    00171             fprintf(stdout, "%%%% %f\n", (double) (total
    00172                                 ? ((((float) amount) / total) * 100)
    00173                                 : 100.0));
    00174         else if (flags & INSTALL_HASH)
    00175             printHash(amount, total);
    00176         (void) fflush(stdout);
    00177         break;
    00178
    00179     case RPMCALLBACK_TRANS_START:
    00180         rpmcliHashesCurrent = 0;
    00181         rpmcliProgressTotal = 1;
    00182         rpmcliProgressCurrent = 0;
    00183         if (!(flags & INSTALL_LABEL))
    00184             break;
    00185         if (flags & INSTALL_HASH)
    00186             fprintf(stdout, "%-28s", _("Preparing..."));
    00187         else
    00188             fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
    00189         (void) fflush(stdout);
    00190         break;
    00191
    00192     case RPMCALLBACK_TRANS_STOP:
    00193         if (flags & INSTALL_HASH)
    00194             printHash(1, 1);    /* Fixes "preparing..." progress bar */
    00195         rpmcliProgressTotal = rpmcliPackagesTotal;
    00196         rpmcliProgressCurrent = 0;
    00197         break;
    00198
    00199     case RPMCALLBACK_REPACKAGE_START:
    00200         rpmcliHashesCurrent = 0;
    00201         rpmcliProgressTotal = total;
    00202         rpmcliProgressCurrent = 0;
    00203         if (!(flags & INSTALL_LABEL))
    00204             break;
    00205         if (flags & INSTALL_HASH)
    00206             fprintf(stdout, "%-28s\n", _("Repackaging..."));
    00207         else
    00208             fprintf(stdout, "%s\n", _("Repackaging erased files..."));
    00209         (void) fflush(stdout);
    00210         break;
    00211
    00212     case RPMCALLBACK_REPACKAGE_PROGRESS:
    00213         if (amount && (flags & INSTALL_HASH))
    00214             printHash(1, 1);    /* Fixes "preparing..." progress bar */
    00215         break;
    00216
    00217     case RPMCALLBACK_REPACKAGE_STOP:
    00218         rpmcliProgressTotal = total;
    00219         rpmcliProgressCurrent = total;
    00220         if (flags & INSTALL_HASH)
    00221             printHash(1, 1);    /* Fixes "preparing..." progress bar */
    00222         rpmcliProgressTotal = rpmcliPackagesTotal;
    00223         rpmcliProgressCurrent = 0;
    00224         if (!(flags & INSTALL_LABEL))
    00225             break;
    00226         if (flags & INSTALL_HASH)
    00227             fprintf(stdout, "%-28s\n", _("Upgrading..."));
    00228         else
    00229             fprintf(stdout, "%s\n", _("Upgrading packages..."));
    00230         (void) fflush(stdout);
    00231         break;
    00232
    00233     case RPMCALLBACK_UNINST_PROGRESS:
    00234         break;
    00235     case RPMCALLBACK_UNINST_START:
    00236         break;
    00237     case RPMCALLBACK_UNINST_STOP:
    00238         break;
    00239     case RPMCALLBACK_UNPACK_ERROR:
    00240         break;
    00241     case RPMCALLBACK_CPIO_ERROR:
    00242         break;
    00243     case RPMCALLBACK_UNKNOWN:
    00244     default:
    00245         break;
    00246     }
    00247
    00248     return rc;
    00249 }
    00250
    00251 typedef /*@only@*/ /*@null@*/ const char * str_t;
    00252
    00253 struct rpmEIU {
    00254     Header h;
    00255     FD_t fd;
    00256     int numFailed;
    00257     int numPkgs;
    00258 /*@only@*/
    00259     str_t * pkgURL;
    00260 /*@dependent@*/ /*@null@*/
    00261     str_t * fnp;
    00262 /*@only@*/
    00263     char * pkgState;
    00264     int prevx;
    00265     int pkgx;
    00266     int numRPMS;
    00267     int numSRPMS;
    00268 /*@only@*/ /*@null@*/
    00269     str_t * sourceURL;
    00270     int isSource;
    00271     int argc;
    00272 /*@only@*/ /*@null@*/
    00273     str_t * argv;
    00274 /*@dependent@*/
    00275     rpmRelocation * relocations;
    00276     rpmRC rpmrc;
    00277 };
    00278
    00280 /*@-bounds@*/
    00281 int rpmInstall(rpmts ts,
    00282                 struct rpmInstallArguments_s * ia,
    00283                 const char ** fileArgv)
    00284 {
    00285     struct rpmEIU * eiu = memset(alloca(sizeof(*eiu)), 0, sizeof(*eiu));
    00286     rpmps ps;
    00287     rpmprobFilterFlags probFilter;
    00288     rpmRelocation * relocations;
    00289 /*@only@*/ /*@null@*/ const char * fileURL = NULL;
    00290     int stopInstall = 0;
    00291     const char ** av = NULL;
    00292     rpmVSFlags vsflags, ovsflags, tvsflags;
    00293     int ac = 0;
    00294     int rc;
    00295     int xx;
    00296     int i;
    00297
    00298     if (fileArgv == NULL) goto exit;
    00299
    00300     ts->goal = TSM_INSTALL;
    00301     rpmcliPackagesTotal = 0;
    00302
    00303     if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
    00304         ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
    00305
    00306     (void) rpmtsSetFlags(ts, ia->transFlags);
    00307     probFilter = ia->probFilter;
    00308     relocations = ia->relocations;
    00309
    00310     if (ia->installInterfaceFlags & INSTALL_UPGRADE)
    00311         vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
    00312     else
    00313         vsflags = rpmExpandNumeric("%{?_vsflags_install}");
    00314     if (ia->qva_flags & VERIFY_DIGEST)
    00315         vsflags |= _RPMVSF_NODIGESTS;
    00316     if (ia->qva_flags & VERIFY_SIGNATURE)
    00317         vsflags |= _RPMVSF_NOSIGNATURES;
    00318     if (ia->qva_flags & VERIFY_HDRCHK)
    00319         vsflags |= RPMVSF_NOHDRCHK;
    00320     ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD));
    00321
    00322     {   int notifyFlags;
    00323         notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
    00324         xx = rpmtsSetNotifyCallback(ts,
    00325                         rpmShowProgress, (void *) ((long)notifyFlags));
    00326     }
    00327
    00328     if ((eiu->relocations = relocations) != NULL) {
    00329         while (eiu->relocations->oldPath)
    00330             eiu->relocations++;
    00331         if (eiu->relocations->newPath == NULL)
    00332             eiu->relocations = NULL;
    00333     }
    00334
    00335     /* Build fully globbed list of arguments in argv[argc]. */
    00336     /*@-branchstate@*/
    00337     /*@-temptrans@*/
    00338     for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) {
    00339     /*@=temptrans@*/
    00340         av = _free(av); ac = 0;
    00341         rc = rpmGlob(*eiu->fnp, &ac, &av);
    00342         if (rc || ac == 0) continue;
    00343
    00344         eiu->argv = xrealloc(eiu->argv, (eiu->argc+ac+1) * sizeof(*eiu->argv));
    00345         memcpy(eiu->argv+eiu->argc, av, ac * sizeof(*av));
    00346         eiu->argc += ac;
    00347         eiu->argv[eiu->argc] = NULL;
    00348     }
    00349     /*@=branchstate@*/
    00350     av = _free(av);     ac = 0;
    00351
    00352 restart:
    00353     /* Allocate sufficient storage for next set of args. */
    00354     if (eiu->pkgx >= eiu->numPkgs) {
    00355         eiu->numPkgs = eiu->pkgx + eiu->argc;
    00356         eiu->pkgURL = xrealloc(eiu->pkgURL,
    00357                         (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL));
    00358         memset(eiu->pkgURL + eiu->pkgx, 0,
    00359                         ((eiu->argc + 1) * sizeof(*eiu->pkgURL)));
    00360         eiu->pkgState = xrealloc(eiu->pkgState,
    00361                         (eiu->numPkgs + 1) * sizeof(*eiu->pkgState));
    00362         memset(eiu->pkgState + eiu->pkgx, 0,
    00363                         ((eiu->argc + 1) * sizeof(*eiu->pkgState)));
    00364     }
    00365
    00366     /* Retrieve next set of args, cache on local storage. */
    00367     for (i = 0; i < eiu->argc; i++) {
    00368         fileURL = _free(fileURL);
    00369         fileURL = eiu->argv[i];
    00370         eiu->argv[i] = NULL;
    00371
    00372 #ifdef  NOTYET
    00373 if (fileURL[0] == '=') {
    00374     rpmds this = rpmdsSingle(RPMTAG_REQUIRENAME, fileURL+1, NULL, 0);
    00375
    00376     xx = rpmtsSolve(ts, this, NULL);
    00377     if (ts->suggests && ts->nsuggests > 0) {
    00378         fileURL = _free(fileURL);
    00379         fileURL = ts->suggests[0];
    00380         ts->suggests[0] = NULL;
    00381         while (ts->nsuggests-- > 0) {
    00382             if (ts->suggests[ts->nsuggests] == NULL)
    00383                 continue;
    00384             ts->suggests[ts->nsuggests] = _free(ts->suggests[ts->nsuggests]);
    00385         }
    00386         ts->suggests = _free(ts->suggests);
    00387         rpmMessage(RPMMESS_DEBUG, _("Adding goal: %s\n"), fileURL);
    00388         eiu->pkgURL[eiu->pkgx] = fileURL;
    00389         fileURL = NULL;
    00390         eiu->pkgx++;
    00391     }
    00392     this = rpmdsFree(this);
    00393 } else
    00394 #endif
    00395
    00396         switch (urlIsURL(fileURL)) {
    00397         case URL_IS_FTP:
    00398         case URL_IS_HTTP:
    00399         {   const char *tfn;
    00400
    00401             if (rpmIsVerbose())
    00402                 fprintf(stdout, _("Retrieving %s\n"), fileURL);
    00403
    00404             {   char tfnbuf[64];
    00405                 const char * rootDir = rpmtsRootDir(ts);
    00406                 if (!(rootDir && * rootDir))
    00407                     rootDir = "";
    00408                 strcpy(tfnbuf, "rpm-xfer.XXXXXX");
    00409                 (void) mktemp(tfnbuf);
    00410                 tfn = rpmGenPath(rootDir, "%{_tmppath}/", tfnbuf);
    00411             }
    00412
    00413             /* XXX undefined %{name}/%{version}/%{release} here */
    00414             /* XXX %{_tmpdir} does not exist */
    00415             rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
    00416             rc = urlGetFile(fileURL, tfn);
    00417             if (rc < 0) {
    00418                 rpmMessage(RPMMESS_ERROR,
    00419                         _("skipping %s - transfer failed - %s\n"),
    00420                         fileURL, ftpStrerror(rc));
    00421                 eiu->numFailed++;
    00422                 eiu->pkgURL[eiu->pkgx] = NULL;
    00423                 tfn = _free(tfn);
    00424                 /*@switchbreak@*/ break;
    00425             }
    00426             eiu->pkgState[eiu->pkgx] = 1;
    00427             eiu->pkgURL[eiu->pkgx] = tfn;
    00428             eiu->pkgx++;
    00429         }   /*@switchbreak@*/ break;
    00430         case URL_IS_PATH:
    00431         default:
    00432             eiu->pkgURL[eiu->pkgx] = fileURL;
    00433             fileURL = NULL;
    00434             eiu->pkgx++;
    00435             /*@switchbreak@*/ break;
    00436         }
    00437     }
    00438     fileURL = _free(fileURL);
    00439
    00440     if (eiu->numFailed) goto exit;
    00441
    00442     /* Continue processing file arguments, building transaction set. */
    00443     for (eiu->fnp = eiu->pkgURL+eiu->prevx;
    00444          *eiu->fnp != NULL;
    00445          eiu->fnp++, eiu->prevx++)
    00446     {
    00447         const char * fileName;
    00448
    00449         rpmMessage(RPMMESS_DEBUG, "============== %s\n", *eiu->fnp);
    00450         (void) urlPath(*eiu->fnp, &fileName);
    00451
    00452         /* Try to read the header from a package file. */
    00453         eiu->fd = Fopen(*eiu->fnp, "r.ufdio");
    00454         if (eiu->fd == NULL || Ferror(eiu->fd)) {
    00455             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
    00456                         Fstrerror(eiu->fd));
    00457             if (eiu->fd) {
    00458                 xx = Fclose(eiu->fd);
    00459                 eiu->fd = NULL;
    00460             }
    00461             eiu->numFailed++; *eiu->fnp = NULL;
    00462             continue;
    00463         }
    00464
    00465         /* Read the header, verifying signatures (if present). */
    00466         tvsflags = rpmtsSetVSFlags(ts, vsflags);
    00467         eiu->rpmrc = rpmReadPackageFile(ts, eiu->fd, *eiu->fnp, &eiu->h);
    00468         tvsflags = rpmtsSetVSFlags(ts, tvsflags);
    00469         xx = Fclose(eiu->fd);
    00470         eiu->fd = NULL;
    00471
    00472         switch (eiu->rpmrc) {
    00473         case RPMRC_FAIL:
    00474             rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *eiu->fnp);
    00475             eiu->numFailed++; *eiu->fnp = NULL;
    00476             continue;
    00477             /*@notreached@*/ /*@switchbreak@*/ break;
    00478         case RPMRC_NOTFOUND:
    00479             goto maybe_manifest;
    00480             /*@notreached@*/ /*@switchbreak@*/ break;
    00481         case RPMRC_NOTTRUSTED:
    00482         case RPMRC_NOKEY:
    00483         case RPMRC_OK:
    00484         default:
    00485             /*@switchbreak@*/ break;
    00486         }
    00487
    00488         eiu->isSource = headerIsEntry(eiu->h, RPMTAG_SOURCEPACKAGE);
    00489
    00490         if (eiu->isSource) {
    00491             rpmMessage(RPMMESS_DEBUG, "\tadded source package [%d]\n",
    00492                 eiu->numSRPMS);
    00493             eiu->sourceURL = xrealloc(eiu->sourceURL,
    00494                                 (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL));
    00495             eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp;
    00496             *eiu->fnp = NULL;
    00497             eiu->numSRPMS++;
    00498             eiu->sourceURL[eiu->numSRPMS] = NULL;
    00499             continue;
    00500         }
    00501
    00502         if (eiu->relocations) {
    00503             const char ** paths;
    00504             int pft;
    00505             int c;
    00506
    00507             if (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft,
    00508                                        (void **) &paths, &c) && (c == 1))
    00509             {
    00510                 eiu->relocations->oldPath = xstrdup(paths[0]);
    00511                 paths = headerFreeData(paths, pft);
    00512             } else {
    00513                 const char * name;
    00514                 xx = headerNVR(eiu->h, &name, NULL, NULL);
    00515                 rpmMessage(RPMMESS_ERROR,
    00516                                _("package %s is not relocateable\n"), name);
    00517                 eiu->numFailed++;
    00518                 goto exit;
    00519                 /*@notreached@*/
    00520             }
    00521         }
    00522
    00523         /* On --freshen, verify package is installed and newer */
    00524         if (ia->installInterfaceFlags & INSTALL_FRESHEN) {
    00525             rpmdbMatchIterator mi;
    00526             const char * name;
    00527             Header oldH;
    00528             int count;
    00529
    00530             xx = headerNVR(eiu->h, &name, NULL, NULL);
    00531             mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0);
    00532             count = rpmdbGetIteratorCount(mi);
    00533             while ((oldH = rpmdbNextIterator(mi)) != NULL) {
    00534                 if (rpmVersionCompare(oldH, eiu->h) < 0)
    00535                     /*@innercontinue@*/ continue;
    00536                 /* same or newer package already installed */
    00537                 count = 0;
    00538                 /*@innerbreak@*/ break;
    00539             }
    00540             mi = rpmdbFreeIterator(mi);
    00541             if (count == 0) {
    00542                 eiu->h = headerFree(eiu->h);
    00543                 continue;
    00544             }
    00545             /* Package is newer than those currently installed. */
    00546         }
    00547
    00548         /*@-abstract@*/
    00549         rc = rpmtsAddInstallElement(ts, eiu->h, (fnpyKey)fileName,
    00550                         (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0,
    00551                         relocations);
    00552         /*@=abstract@*/
    00553
    00554         /* XXX reference held by transaction set */
    00555         eiu->h = headerFree(eiu->h);
    00556         if (eiu->relocations)
    00557             eiu->relocations->oldPath = _free(eiu->relocations->oldPath);
    00558
    00559         switch(rc) {
    00560         case 0:
    00561             rpmMessage(RPMMESS_DEBUG, "\tadded binary package [%d]\n",
    00562                         eiu->numRPMS);
    00563             /*@switchbreak@*/ break;
    00564         case 1:
    00565             rpmMessage(RPMMESS_ERROR,
    00566                             _("error reading from file %s\n"), *eiu->fnp);
    00567             eiu->numFailed++;
    00568             goto exit;
    00569             /*@notreached@*/ /*@switchbreak@*/ break;
    00570         case 2:
    00571             rpmMessage(RPMMESS_ERROR,
    00572                             _("file %s requires a newer version of RPM\n"),
    00573                             *eiu->fnp);
    00574             eiu->numFailed++;
    00575             goto exit;
    00576             /*@notreached@*/ /*@switchbreak@*/ break;
    00577         }
    00578
    00579         eiu->numRPMS++;
    00580         continue;
    00581
    00582 maybe_manifest:
    00583         /* Try to read a package manifest. */
    00584         eiu->fd = Fopen(*eiu->fnp, "r.fpio");
    00585         if (eiu->fd == NULL || Ferror(eiu->fd)) {
    00586             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
    00587                         Fstrerror(eiu->fd));
    00588             if (eiu->fd) {
    00589                 xx = Fclose(eiu->fd);
    00590                 eiu->fd = NULL;
    00591             }
    00592             eiu->numFailed++; *eiu->fnp = NULL;
    00593             break;
    00594         }
    00595
    00596         /* Read list of packages from manifest. */
    00597         rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv);
    00598         if (rc != RPMRC_OK)
    00599             rpmError(RPMERR_MANIFEST, _("%s: not an rpm package (or package manifest): %s\n"),
    00600                         *eiu->fnp, Fstrerror(eiu->fd));
    00601         xx = Fclose(eiu->fd);
    00602         eiu->fd = NULL;
    00603
    00604         /* If successful, restart the query loop. */
    00605         if (rc == RPMRC_OK) {
    00606             eiu->prevx++;
    00607             goto restart;
    00608         }
    00609
    00610         eiu->numFailed++; *eiu->fnp = NULL;
    00611         break;
    00612     }
    00613
    00614     rpmMessage(RPMMESS_DEBUG, _("found %d source and %d binary packages\n"),
    00615                 eiu->numSRPMS, eiu->numRPMS);
    00616
    00617     if (eiu->numFailed) goto exit;
    00618
    00619     if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NODEPS)) {
    00620
    00621         if (rpmtsCheck(ts)) {
    00622             eiu->numFailed = eiu->numPkgs;
    00623             stopInstall = 1;
    00624         }
    00625
    00626         ps = rpmtsProblems(ts);
    00627         if (!stopInstall && rpmpsNumProblems(ps) > 0) {
    00628             rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
    00629             rpmpsPrint(NULL, ps);
    00630             eiu->numFailed = eiu->numPkgs;
    00631             stopInstall = 1;
    00632
    00633             /*@-branchstate@*/
    00634             if (ts->suggests != NULL && ts->nsuggests > 0) {
    00635                 rpmMessage(RPMMESS_NORMAL, _("    Suggested resolutions:\n"));
    00636                 for (i = 0; i < ts->nsuggests; i++) {
    00637                     const char * str = ts->suggests[i];
    00638
    00639                     if (str == NULL)
    00640                         break;
    00641
    00642                     rpmMessage(RPMMESS_NORMAL, "\t%s\n", str);
    00643
    00644                     ts->suggests[i] = NULL;
    00645                     str = _free(str);
    00646                 }
    00647                 ts->suggests = _free(ts->suggests);
    00648             }
    00649             /*@=branchstate@*/
    00650         }
    00651         ps = rpmpsFree(ps);
    00652     }
    00653
    00654     if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NOORDER)) {
    00655         if (rpmtsOrder(ts)) {
    00656             eiu->numFailed = eiu->numPkgs;
    00657             stopInstall = 1;
    00658         }
    00659     }
    00660
    00661     if (eiu->numRPMS && !stopInstall) {
    00662
    00663         rpmcliPackagesTotal += eiu->numSRPMS;
    00664
    00665         rpmMessage(RPMMESS_DEBUG, _("installing binary packages\n"));
    00666
    00667         /* Drop added/available package indices and dependency sets. */
    00668         rpmtsClean(ts);
    00669
    00670         rc = rpmtsRun(ts, NULL, probFilter);
    00671         ps = rpmtsProblems(ts);
    00672
    00673         if (rc < 0) {
    00674             eiu->numFailed += eiu->numRPMS;
    00675         } else if (rc > 0) {
    00676             eiu->numFailed += rc;
    00677             if (rpmpsNumProblems(ps) > 0)
    00678                 rpmpsPrint(stderr, ps);
    00679         }
    00680         ps = rpmpsFree(ps);
    00681     }
    00682
    00683     if (eiu->numSRPMS && !stopInstall) {
    00684         if (eiu->sourceURL != NULL)
    00685         for (i = 0; i < eiu->numSRPMS; i++) {
    00686             if (eiu->sourceURL[i] == NULL) continue;
    00687             eiu->fd = Fopen(eiu->sourceURL[i], "r.ufdio");
    00688             if (eiu->fd == NULL || Ferror(eiu->fd)) {
    00689                 rpmMessage(RPMMESS_ERROR, _("cannot open file %s: %s\n"),
    00690                            eiu->sourceURL[i], Fstrerror(eiu->fd));
    00691                 if (eiu->fd) {
    00692                     xx = Fclose(eiu->fd);
    00693                     eiu->fd = NULL;
    00694                 }
    00695                 continue;
    00696             }
    00697
    00698             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
    00699                 eiu->rpmrc = rpmInstallSourcePackage(ts, eiu->fd, NULL, NULL);
    00700                 if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++;
    00701             }
    00702
    00703             xx = Fclose(eiu->fd);
    00704             eiu->fd = NULL;
    00705         }
    00706     }
    00707
    00708 exit:
    00709     if (eiu->pkgURL != NULL)
    00710     for (i = 0; i < eiu->numPkgs; i++) {
    00711         if (eiu->pkgURL[i] == NULL) continue;
    00712         if (eiu->pkgState[i] == 1)
    00713             (void) Unlink(eiu->pkgURL[i]);
    00714         eiu->pkgURL[i] = _free(eiu->pkgURL[i]);
    00715     }
    00716     eiu->pkgState = _free(eiu->pkgState);
    00717     eiu->pkgURL = _free(eiu->pkgURL);
    00718     eiu->argv = _free(eiu->argv);
    00719
    00720     rpmtsEmpty(ts);
    00721
    00722     return eiu->numFailed;
    00723 }
    00724 /*@=bounds@*/
    00725
    00726 int rpmErase(rpmts ts,
    00727                 const struct rpmInstallArguments_s * ia,
    00728                 const char ** argv)
    00729 {
    00730     int count;
    00731     const char ** arg;
    00732     int numFailed = 0;
    00733     int stopUninstall = 0;
    00734     int numPackages = 0;
    00735     rpmVSFlags vsflags, ovsflags;
    00736     rpmps ps;
    00737
    00738     if (argv == NULL) return 0;
    00739
    00740     vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
    00741     if (ia->qva_flags & VERIFY_DIGEST)
    00742         vsflags |= _RPMVSF_NODIGESTS;
    00743     if (ia->qva_flags & VERIFY_SIGNATURE)
    00744         vsflags |= _RPMVSF_NOSIGNATURES;
    00745     if (ia->qva_flags & VERIFY_HDRCHK)
    00746         vsflags |= RPMVSF_NOHDRCHK;
    00747     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00748
    00749     if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
    00750         ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
    00751
    00752     (void) rpmtsSetFlags(ts, ia->transFlags);
    00753
    00754 #ifdef  NOTYET  /* XXX no callbacks on erase yet */
    00755     {   int notifyFlags;
    00756         notifyFlags = ia->eraseInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
    00757         xx = rpmtsSetNotifyCallback(ts,
    00758                         rpmShowProgress, (void *) ((long)notifyFlags)
    00759     }
    00760 #endif
    00761
    00762     ts->goal = TSM_ERASE;
    00763
    00764     for (arg = argv; *arg; arg++) {
    00765         rpmdbMatchIterator mi;
    00766
    00767         /* XXX HACK to get rpmdbFindByLabel out of the API */
    00768         mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
    00769         count = rpmdbGetIteratorCount(mi);
    00770         if (count <= 0) {
    00771             rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
    00772             numFailed++;
    00773         } else if (!(count == 1 || (ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES))) {
    00774             rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"),
    00775                         *arg);
    00776             numFailed++;
    00777         } else {
    00778             Header h;   /* XXX iterator owns the reference */
    00779             while ((h = rpmdbNextIterator(mi)) != NULL) {
    00780                 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
    00781                 if (recOffset) {
    00782                     (void) rpmtsAddEraseElement(ts, h, recOffset);
    00783                     numPackages++;
    00784                 }
    00785             }
    00786         }
    00787         mi = rpmdbFreeIterator(mi);
    00788     }
    00789
    00790     if (!(ia->eraseInterfaceFlags & UNINSTALL_NODEPS)) {
    00791
    00792         if (rpmtsCheck(ts)) {
    00793             numFailed = numPackages;
    00794             stopUninstall = 1;
    00795         }
    00796
    00797         ps = rpmtsProblems(ts);
    00798         if (!stopUninstall && rpmpsNumProblems(ps) > 0) {
    00799             rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
    00800             rpmpsPrint(NULL, ps);
    00801             numFailed += numPackages;
    00802             stopUninstall = 1;
    00803         }
    00804         ps = rpmpsFree(ps);
    00805     }
    00806
    00807     if (!stopUninstall) {
    00808         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_REVERSE));
    00809
    00810         /* Drop added/available package indices and dependency sets. */
    00811         rpmtsClean(ts);
    00812
    00813         numPackages = rpmtsRun(ts, NULL, 0);
    00814         ps = rpmtsProblems(ts);
    00815         if (rpmpsNumProblems(ps) > 0)
    00816             rpmpsPrint(NULL, ps);
    00817         numFailed += numPackages;
    00818         stopUninstall = 1;
    00819         ps = rpmpsFree(ps);
    00820     }
    00821
    00822     rpmtsEmpty(ts);
    00823
    00824     return numFailed;
    00825 }
    00826
    00827 int rpmInstallSource(rpmts ts, const char * arg,
    00828                 const char ** specFilePtr, const char ** cookie)
    00829 {
    00830     FD_t fd;
    00831     int rc;
    00832
    00833
    00834     fd = Fopen(arg, "r.ufdio");
    00835     if (fd == NULL || Ferror(fd)) {
    00836         rpmMessage(RPMMESS_ERROR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
    00837         if (fd) (void) Fclose(fd);
    00838         return 1;
    00839     }
    00840
    00841     if (rpmIsVerbose())
    00842         fprintf(stdout, _("Installing %s\n"), arg);
    00843
    00844     {
    00845         rpmVSFlags ovsflags =
    00846                 rpmtsSetVSFlags(ts, (rpmtsVSFlags(ts) | RPMVSF_NEEDPAYLOAD));
    00847         rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
    00848         rc = (rpmrc == RPMRC_OK ? 0 : 1);
    00849         ovsflags = rpmtsSetVSFlags(ts, ovsflags);
    00850     }
    00851     if (rc != 0) {
    00852         rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
    00853         /*@-unqualifiedtrans@*/
    00854         if (specFilePtr && *specFilePtr)
    00855             *specFilePtr = _free(*specFilePtr);
    00856         if (cookie && *cookie)
    00857             *cookie = _free(*cookie);
    00858         /*@=unqualifiedtrans@*/
    00859     }
    00860
    00861     (void) Fclose(fd);
    00862
    00863     return rc;
    00864 }
    00865
    00866 /*@unchecked@*/
    00867 static int reverse = -1;
    00868
    00871 static int IDTintcmp(const void * a, const void * b)
    00872         /*@*/
    00873 {
    00874     /*@-castexpose@*/
    00875     return ( reverse * (((IDT)a)->val.u32 - ((IDT)b)->val.u32) );
    00876     /*@=castexpose@*/
    00877 }
    00878
    00879 IDTX IDTXfree(IDTX idtx)
    00880 {
    00881     if (idtx) {
    00882         int i;
    00883         if (idtx->idt)
    00884         for (i = 0; i < idtx->nidt; i++) {
    00885             IDT idt = idtx->idt + i;
    00886             idt->h = headerFree(idt->h);
    00887             idt->key = _free(idt->key);
    00888         }
    00889         idtx->idt = _free(idtx->idt);
    00890         idtx = _free(idtx);
    00891     }
    00892     return NULL;
    00893 }
    00894
    00895 IDTX IDTXnew(void)
    00896 {
    00897     IDTX idtx = xcalloc(1, sizeof(*idtx));
    00898     idtx->delta = 10;
    00899     idtx->size = sizeof(*((IDT)0));
    00900     return idtx;
    00901 }
    00902
    00903 IDTX IDTXgrow(IDTX idtx, int need)
    00904 {
    00905     if (need < 0) return NULL;
    00906     if (idtx == NULL)
    00907         idtx = IDTXnew();
    00908     if (need == 0) return idtx;
    00909
    00910     if ((idtx->nidt + need) > idtx->alloced) {
    00911         while (need > 0) {
    00912             idtx->alloced += idtx->delta;
    00913             need -= idtx->delta;
    00914         }
    00915         idtx->idt = xrealloc(idtx->idt, (idtx->alloced * idtx->size) );
    00916     }
    00917     return idtx;
    00918 }
    00919
    00920 IDTX IDTXsort(IDTX idtx)
    00921 {
    00922     if (idtx != NULL && idtx->idt != NULL && idtx->nidt > 0)
    00923         qsort(idtx->idt, idtx->nidt, idtx->size, IDTintcmp);
    00924     return idtx;
    00925 }
    00926
    00927 IDTX IDTXload(rpmts ts, rpmTag tag)
    00928 {
    00929     IDTX idtx = NULL;
    00930     rpmdbMatchIterator mi;
    00931     HGE_t hge = (HGE_t) headerGetEntry;
    00932     Header h;
    00933
    00934     /*@-branchstate@*/
    00935     mi = rpmtsInitIterator(ts, tag, NULL, 0);
    00936     while ((h = rpmdbNextIterator(mi)) != NULL) {
    00937         rpmTagType type = RPM_NULL_TYPE;
    00938         int_32 count = 0;
    00939         int_32 * tidp;
    00940
    00941         tidp = NULL;
    00942         if (!hge(h, tag, &type, (void **)&tidp, &count) || tidp == NULL)
    00943             continue;
    00944
    00945         if (type == RPM_INT32_TYPE && (*tidp == 0 || *tidp == -1))
    00946             continue;
    00947
    00948         idtx = IDTXgrow(idtx, 1);
    00949         if (idtx == NULL)
    00950             continue;
    00951         if (idtx->idt == NULL)
    00952             continue;
    00953
    00954         {   IDT idt;
    00955             /*@-nullderef@*/
    00956             idt = idtx->idt + idtx->nidt;
    00957             /*@=nullderef@*/
    00958             idt->h = headerLink(h);
    00959             idt->key = NULL;
    00960             idt->instance = rpmdbGetIteratorOffset(mi);
    00961             idt->val.u32 = *tidp;
    00962         }
    00963         idtx->nidt++;
    00964     }
    00965     mi = rpmdbFreeIterator(mi);
    00966     /*@=branchstate@*/
    00967
    00968     return IDTXsort(idtx);
    00969 }
    00970
    00971 IDTX IDTXglob(rpmts ts, const char * globstr, rpmTag tag)
    00972 {
    00973     IDTX idtx = NULL;
    00974     HGE_t hge = (HGE_t) headerGetEntry;
    00975     Header h;
    00976     int_32 * tidp;
    00977     FD_t fd;
    00978     const char ** av = NULL;
    00979     int ac = 0;
    00980     rpmRC rpmrc;
    00981     int xx;
    00982     int i;
    00983
    00984     av = NULL;  ac = 0;
    00985     xx = rpmGlob(globstr, &ac, &av);
    00986
    00987     if (xx == 0)
    00988     for (i = 0; i < ac; i++) {
    00989         rpmTagType type;
    00990         int_32 count;
    00991         int isSource;
    00992
    00993         fd = Fopen(av[i], "r.ufdio");
    00994         if (fd == NULL || Ferror(fd)) {
    00995             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), av[i],
    00996                         Fstrerror(fd));
    00997             if (fd) (void) Fclose(fd);
    00998             continue;
    00999         }
    01000
    01001         rpmrc = rpmReadPackageFile(ts, fd, av[i], &h);
    01002         (void) Fclose(fd);
    01003         switch (rpmrc) {
    01004         default:
    01005             goto bottom;
    01006             /*@notreached@*/ /*@switchbreak@*/ break;
    01007         case RPMRC_NOTTRUSTED:
    01008         case RPMRC_NOKEY:
    01009         case RPMRC_OK:
    01010             isSource = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
    01011             if (isSource)
    01012                 goto bottom;
    01013             /*@switchbreak@*/ break;
    01014         }
    01015
    01016         tidp = NULL;
    01017         /*@-branchstate@*/
    01018         if (hge(h, tag, &type, (void **) &tidp, &count) && tidp) {
    01019
    01020             idtx = IDTXgrow(idtx, 1);
    01021             if (idtx == NULL || idtx->idt == NULL)
    01022                 goto bottom;
    01023
    01024             {   IDT idt;
    01025                 idt = idtx->idt + idtx->nidt;
    01026                 idt->h = headerLink(h);
    01027                 idt->key = av[i];
    01028                 av[i] = NULL;
    01029                 idt->instance = 0;
    01030                 idt->val.u32 = *tidp;
    01031             }
    01032             idtx->nidt++;
    01033         }
    01034         /*@=branchstate@*/
    01035 bottom:
    01036         h = headerFree(h);
    01037     }
    01038
    01039     for (i = 0; i < ac; i++)
    01040         av[i] = _free(av[i]);
    01041     av = _free(av);     ac = 0;
    01042
    01043     return idtx;
    01044 }
    01045
    01047 int rpmRollback(rpmts ts, struct rpmInstallArguments_s * ia, const char ** argv)
    01048 {
    01049     int ifmask= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE);
    01050     unsigned thistid = 0xffffffff;
    01051     unsigned prevtid;
    01052     time_t tid;
    01053     IDTX itids = NULL;
    01054     IDTX rtids = NULL;
    01055     IDT rp;
    01056     int nrids = 0;
    01057     IDT ip;
    01058     int niids = 0;
    01059     int rc = 0;
    01060     int vsflags, ovsflags;
    01061     int numAdded;
    01062     int numRemoved;
    01063     rpmps ps;
    01064     int _unsafe_rollbacks = 0;
    01065     rpmtransFlags transFlags = ia->transFlags;
    01066
    01067     if (argv != NULL && *argv != NULL) {
    01068         rc = -1;
    01069         goto exit;
    01070     }
    01071
    01072     _unsafe_rollbacks = rpmExpandNumeric("%{?_unsafe_rollbacks}");
    01073
    01074     vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
    01075     if (ia->qva_flags & VERIFY_DIGEST)
    01076         vsflags |= _RPMVSF_NODIGESTS;
    01077     if (ia->qva_flags & VERIFY_SIGNATURE)
    01078         vsflags |= _RPMVSF_NOSIGNATURES;
    01079     if (ia->qva_flags & VERIFY_HDRCHK)
    01080         vsflags |= RPMVSF_NOHDRCHK;
    01081     vsflags |= RPMVSF_NEEDPAYLOAD;      /* XXX no legacy signatures */
    01082     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    01083
    01084     (void) rpmtsSetFlags(ts, transFlags);
    01085
    01086     itids = IDTXload(ts, RPMTAG_INSTALLTID);
    01087     if (itids != NULL) {
    01088         ip = itids->idt;
    01089         niids = itids->nidt;
    01090     } else {
    01091         ip = NULL;
    01092         niids = 0;
    01093     }
    01094
    01095     {   const char * globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
    01096         if (globstr == NULL || *globstr == '%') {
    01097             globstr = _free(globstr);
    01098             rc = -1;
    01099             goto exit;
    01100         }
    01101         rtids = IDTXglob(ts, globstr, RPMTAG_REMOVETID);
    01102         if (rtids != NULL) {
    01103             rp = rtids->idt;
    01104             nrids = rtids->nidt;
    01105         } else {
    01106             rp = NULL;
    01107             nrids = 0;
    01108         }
    01109         globstr = _free(globstr);
    01110     }
    01111
    01112     {   int notifyFlags, xx;
    01113         notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
    01114         xx = rpmtsSetNotifyCallback(ts,
    01115                         rpmShowProgress, (void *) ((long)notifyFlags));
    01116     }
    01117
    01118     /* Run transactions until rollback goal is achieved. */
    01119     do {
    01120         prevtid = thistid;
    01121         rc = 0;
    01122         rpmcliPackagesTotal = 0;
    01123         numAdded = 0;
    01124         numRemoved = 0;
    01125         ia->installInterfaceFlags &= ~ifmask;
    01126
    01127         /* Find larger of the remaining install/erase transaction id's. */
    01128         thistid = 0;
    01129         if (ip != NULL && ip->val.u32 > thistid)
    01130             thistid = ip->val.u32;
    01131         if (rp != NULL && rp->val.u32 > thistid)
    01132             thistid = rp->val.u32;
    01133
    01134         /* If we've achieved the rollback goal, then we're done. */
    01135         if (thistid == 0 || thistid < ia->rbtid)
    01136             break;
    01137
    01138         /* If we've reached the (configured) rollback goal, then we're done. */
    01139         if (_unsafe_rollbacks && thistid <= _unsafe_rollbacks)
    01140             break;
    01141
    01142         rpmtsEmpty(ts);
    01143         (void) rpmtsSetFlags(ts, transFlags);
    01144
    01145         /* Install the previously erased packages for this transaction. */
    01146         while (rp != NULL && rp->val.u32 == thistid) {
    01147
    01148             rpmMessage(RPMMESS_DEBUG, "\t+++ install %s\n",
    01149                         (rp->key ? rp->key : "???"));
    01150
    01151 /*@-abstract@*/
    01152             rc = rpmtsAddInstallElement(ts, rp->h, (fnpyKey)rp->key,
    01153                                0, ia->relocations);
    01154 /*@=abstract@*/
    01155             if (rc != 0)
    01156                 goto exit;
    01157
    01158             numAdded++;
    01159             rpmcliPackagesTotal++;
    01160             if (!(ia->installInterfaceFlags & ifmask))
    01161                 ia->installInterfaceFlags |= INSTALL_UPGRADE;
    01162
    01163 #ifdef  NOTYET
    01164             rp->h = headerFree(rp->h);
    01165 #endif
    01166             nrids--;
    01167             if (nrids > 0)
    01168                 rp++;
    01169             else
    01170                 rp = NULL;
    01171         }
    01172
    01173         /* Erase the previously installed packages for this transaction. */
    01174         while (ip != NULL && ip->val.u32 == thistid) {
    01175
    01176             rpmMessage(RPMMESS_DEBUG,
    01177                         "\t--- erase h#%u\n", ip->instance);
    01178
    01179             rc = rpmtsAddEraseElement(ts, ip->h, ip->instance);
    01180             if (rc != 0)
    01181                 goto exit;
    01182
    01183             numRemoved++;
    01184
    01185             if (_unsafe_rollbacks)
    01186                 rpmcliPackagesTotal++;
    01187
    01188             if (!(ia->installInterfaceFlags & ifmask)) {
    01189                 ia->installInterfaceFlags |= INSTALL_ERASE;
    01190                 (void) rpmtsSetFlags(ts, (transFlags | RPMTRANS_FLAG_REVERSE));
    01191             }
    01192
    01193 #ifdef  NOTYET
    01194             ip->instance = 0;
    01195 #endif
    01196             niids--;
    01197             if (niids > 0)
    01198                 ip++;
    01199             else
    01200                 ip = NULL;
    01201         }
    01202
    01203         /* Anything to do? */
    01204         if (rpmcliPackagesTotal <= 0)
    01205             break;
    01206
    01207         tid = (time_t)thistid;
    01208         rpmMessage(RPMMESS_NORMAL,
    01209                 _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
    01210                         numAdded, numRemoved, ctime(&tid), tid);
    01211
    01212         rc = rpmtsCheck(ts);
    01213         ps = rpmtsProblems(ts);
    01214         if (rc != 0 && rpmpsNumProblems(ps) > 0) {
    01215             rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
    01216             rpmpsPrint(NULL, ps);
    01217             ps = rpmpsFree(ps);
    01218             goto exit;
    01219         }
    01220         ps = rpmpsFree(ps);
    01221
    01222         rc = rpmtsOrder(ts);
    01223         if (rc != 0)
    01224             goto exit;
    01225
    01226         /* Drop added/available package indices and dependency sets. */
    01227         rpmtsClean(ts);
    01228
    01229         rc = rpmtsRun(ts, NULL, (ia->probFilter|RPMPROB_FILTER_OLDPACKAGE));
    01230         ps = rpmtsProblems(ts);
    01231         if (rc > 0 && rpmpsNumProblems(ps) > 0)
    01232             rpmpsPrint(stderr, ps);
    01233         ps = rpmpsFree(ps);
    01234         if (rc)
    01235             goto exit;
    01236
    01237         /* Clean up after successful rollback. */
    01238         if (rtids && !rpmIsDebug()) {
    01239             int i;
    01240             if (rtids->idt)
    01241             for (i = 0; i < rtids->nidt; i++) {
    01242                 IDT rrp = rtids->idt + i;
    01243                 if (rrp->val.u32 != thistid)
    01244                     /*@innercontinue@*/ continue;
    01245                 if (rrp->key)   /* XXX can't happen */
    01246                     (void) unlink(rrp->key);
    01247             }
    01248         }
    01249
    01250
    01251     } while (1);
    01252
    01253 exit:
    01254     rtids = IDTXfree(rtids);
    01255     itids = IDTXfree(itids);
    01256
    01257     rpmtsEmpty(ts);
    01258     (void) rpmtsSetFlags(ts, transFlags);
    01259
    01260     return rc;
    01261 }