rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/rpmrollback.c
Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio.h>
    00008 #include <rpmiotypes.h>
    00009 #include <rpmcb.h>
    00010 #include <argv.h>
    00011
    00012 #include <rpmtypes.h>
    00013 #include <rpmtag.h>
    00014 #include <pkgio.h>
    00015 #include <rpmdb.h>
    00016
    00017 #include <rpmds.h>
    00018 #include "manifest.h"
    00019 #include "misc.h"               /* XXX rpmGlob() */
    00020
    00021 #define _RPMTE_INTERNAL         /* XXX findErases needs rpmte internals. */
    00022 #define _RPMTS_INTERNAL         /* XXX ts->teErase, ts->probs */
    00023 #define _RPMTS_PRINT
    00024 #include <rpmgi.h>              /* XXX rpmgiEscapeSpaces */
    00025
    00026 #include <rpmcli.h>
    00027 #define _RPMROLLBACK_INTERNAL
    00028 #include <rpmrollback.h>
    00029
    00030 #include "debug.h"
    00031
    00032 /*@access FD_t @*/      /* XXX void * arg */
    00033 /*@access rpmts @*/
    00034 /*@access rpmte @*/     /* XXX p->hdrid, p->pkgid, p->NEVRA */
    00035 /*@access IDTX @*/
    00036 /*@access IDT @*/
    00037
    00038 /*@unchecked@*/
    00039 static int reverse = -1;
    00040
    00043 static int IDTintcmp(const void * a, const void * b)
    00044         /*@*/
    00045 {
    00046     /*@-castexpose@*/
    00047     return ( reverse * (((IDT)a)->val.u32 - ((IDT)b)->val.u32) );
    00048     /*@=castexpose@*/
    00049 }
    00050
    00051 IDTX IDTXfree(IDTX idtx)
    00052 {
    00053     if (idtx) {
    00054         int i;
    00055         if (idtx->idt)
    00056         for (i = 0; i < idtx->nidt; i++) {
    00057             IDT idt = idtx->idt + i;
    00058             (void)headerFree(idt->h);
    00059             idt->h = NULL;
    00060             idt->key = _free(idt->key);
    00061         }
    00062         idtx->idt = _free(idtx->idt);
    00063         idtx = _free(idtx);
    00064     }
    00065     return NULL;
    00066 }
    00067
    00068 IDTX IDTXnew(void)
    00069 {
    00070     IDTX idtx = xcalloc(1, sizeof(*idtx));
    00071     idtx->delta = 10;
    00072     idtx->size = (int)sizeof(*((IDT)0));
    00073     return idtx;
    00074 }
    00075
    00076 IDTX IDTXgrow(IDTX idtx, int need)
    00077 {
    00078     if (need < 0) return NULL;
    00079     if (idtx == NULL)
    00080         idtx = IDTXnew();
    00081     if (need == 0) return idtx;
    00082
    00083     if ((idtx->nidt + need) > idtx->alloced) {
    00084         while (need > 0) {
    00085             idtx->alloced += idtx->delta;
    00086             need -= idtx->delta;
    00087         }
    00088         idtx->idt = xrealloc(idtx->idt, (idtx->alloced * idtx->size) );
    00089     }
    00090     return idtx;
    00091 }
    00092
    00093 IDTX IDTXsort(IDTX idtx)
    00094 {
    00095     if (idtx != NULL && idtx->idt != NULL && idtx->nidt > 0)
    00096         qsort(idtx->idt, idtx->nidt, idtx->size, IDTintcmp);
    00097     return idtx;
    00098 }
    00099
    00100 IDTX IDTXload(rpmts ts, rpmTag tag, rpmuint32_t rbtid)
    00101 {
    00102     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00103     IDTX idtx = NULL;
    00104     rpmmi mi;
    00105     Header h;
    00106     rpmuint32_t tid;
    00107     int xx;
    00108
    00109     mi = rpmtsInitIterator(ts, tag, NULL, 0);
    00110 #ifdef  NOTYET
    00111     (void) rpmmiAddPattern(mi, RPMTAG_NAME, RPMMIRE_DEFAULT, '!gpg-pubkey');
    00112 #endif
    00113     while ((h = rpmmiNext(mi)) != NULL) {
    00114         he->tag = tag;
    00115         xx = headerGet(h, he, 0);
    00116         if (!xx || he->p.ui32p == NULL)
    00117             continue;
    00118         tid = (he->p.ui32p ? he->p.ui32p[0] : 0);
    00119         he->p.ptr = _free(he->p.ptr);
    00120
    00121         if (tid == 0 || tid == 0xffffffff)
    00122             continue;
    00123
    00124         /* Don't bother with headers installed prior to the rollback goal. */
    00125         if (tid < rbtid)
    00126             continue;
    00127
    00128         idtx = IDTXgrow(idtx, 1);
    00129         if (idtx == NULL || idtx->idt == NULL)
    00130             continue;
    00131
    00132         {   IDT idt;
    00133             /*@-nullderef@*/
    00134             idt = idtx->idt + idtx->nidt;
    00135             /*@=nullderef@*/
    00136             idt->done = 0;
    00137             idt->h = headerLink(h);
    00138             idt->key = NULL;
    00139             idt->instance = rpmmiInstance(mi);
    00140             idt->val.u32 = tid;
    00141         }
    00142         idtx->nidt++;
    00143     }
    00144     mi = rpmmiFree(mi);
    00145
    00146     return IDTXsort(idtx);
    00147 }
    00148
    00149 IDTX IDTXglob(rpmts ts, const char * globstr, rpmTag tag, rpmuint32_t rbtid)
    00150 {
    00151     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00152     IDTX idtx = NULL;
    00153     Header h;
    00154     rpmuint32_t tid;
    00155     FD_t fd;
    00156     const char ** av = NULL;
    00157     const char * fn;
    00158     int ac = 0;
    00159     rpmRC rpmrc;
    00160     int xx;
    00161     int i;
    00162
    00163     av = NULL;  ac = 0;
    00164     fn = rpmgiEscapeSpaces(globstr);
    00165     xx = rpmGlob(fn, &ac, &av);
    00166     fn = _free(fn);
    00167
    00168     if (xx == 0)
    00169     for (i = 0; i < ac; i++) {
    00170         int isSource;
    00171
    00172         fd = Fopen(av[i], "r.fdio");
    00173         if (fd == NULL || Ferror(fd)) {
    00174             rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), av[i],
    00175                         Fstrerror(fd));
    00176             if (fd != NULL) (void) Fclose(fd);
    00177             continue;
    00178         }
    00179
    00180         rpmrc = rpmReadPackageFile(ts, fd, av[i], &h);
    00181         (void) Fclose(fd);
    00182         switch (rpmrc) {
    00183         default:
    00184             goto bottom;
    00185             /*@notreached@*/ /*@switchbreak@*/ break;
    00186         case RPMRC_NOTTRUSTED:
    00187         case RPMRC_NOKEY:
    00188         case RPMRC_OK:
    00189             isSource =
    00190                 (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
    00191                  headerIsEntry(h, RPMTAG_ARCH) != 0);
    00192             if (isSource)
    00193                 goto bottom;
    00194             /*@switchbreak@*/ break;
    00195         }
    00196
    00197 { const char * origin = headerGetOrigin(h);
    00198 assert(origin != NULL);
    00199 assert(!strcmp(av[i], origin));
    00200 }
    00201         he->tag = tag;
    00202         xx = headerGet(h, he, 0);
    00203         if (!xx || he->p.ui32p == NULL)
    00204             goto bottom;
    00205         tid = (he->p.ui32p ? he->p.ui32p[0] : 0);
    00206         he->p.ptr = _free(he->p.ptr);
    00207
    00208         /* Don't bother with headers installed prior to the rollback goal. */
    00209         if (tid < rbtid)
    00210             goto bottom;
    00211
    00212         idtx = IDTXgrow(idtx, 1);
    00213         if (idtx == NULL || idtx->idt == NULL)
    00214             goto bottom;
    00215
    00216         {   IDT idt;
    00217             idt = idtx->idt + idtx->nidt;
    00218             idt->done = 0;
    00219             idt->h = headerLink(h);
    00220             idt->key = av[i];
    00221             av[i] = NULL;
    00222             idt->instance = 0;
    00223             idt->val.u32 = tid;
    00224         }
    00225         idtx->nidt++;
    00226 bottom:
    00227         (void)headerFree(h);
    00228         h = NULL;
    00229     }
    00230
    00231     for (i = 0; i < ac; i++)
    00232         av[i] = _free(av[i]);
    00233     av = _free(av);     ac = 0;
    00234
    00235     return IDTXsort(idtx);
    00236 }
    00237
    00247 static int cmpArgvStr(rpmts ts, const char *lname, const char ** AV, int AC,
    00248                 /*@null@*/ const char * B)
    00249         /*@modifies ts @*/
    00250 {
    00251     const char * A;
    00252     int i;
    00253
    00254     if (AV != NULL && AC > 0 && B == NULL) {
    00255       if (!strcmp(lname, "NEVRA")) {
    00256         rpmps ps = rpmtsProblems(ts);
    00257         for (i = 0; i < AC && (A = AV[i]) != NULL; i++) {
    00258             rpmpsAppend(ps, RPMPROB_NOREPACKAGE,
    00259                         NULL, NULL,     /* NEVRA, key */
    00260                         lname, NULL,    /* dn, bn */
    00261                         A,              /* altNEVRA */
    00262                         0);
    00263         }
    00264         ps = rpmpsFree(ps);
    00265       }
    00266         return 0;
    00267     }
    00268
    00269     if (AV != NULL && B != NULL)
    00270     for (i = 0; i < AC && (A = AV[i]) != NULL; i++) {
    00271         if (*A && *B && !strcmp(A, B))
    00272             return 1;
    00273     }
    00274     return 0;
    00275 }
    00276
    00292 static int findErases(rpmts ts, /*@null@*/ rpmte p, unsigned thistid,
    00293                 /*@null@*/ IDT ip, int niids)
    00294         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00295         /*@modifies ts, p, ip, rpmGlobalMacroContext, fileSystem, internalState @*/
    00296 {
    00297     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00298     int rc = 0;
    00299     int xx;
    00300
    00301     /* Erase the previously installed packages for this transaction.
    00302      * Provided this transaction is not excluded from the rollback.
    00303      */
    00304     while (ip != NULL && ip->val.u32 == thistid) {
    00305
    00306         if (ip->done)
    00307             goto bottom;
    00308
    00309         {
    00310             const char ** flinkPkgid = NULL;
    00311             const char ** flinkHdrid = NULL;
    00312             const char ** flinkNEVRA = NULL;
    00313             rpmuint32_t pn, hn, nn;
    00314             int bingo;
    00315
    00316             he->tag = RPMTAG_BLINKPKGID;
    00317             xx = headerGet(ip->h, he, 0);
    00318             flinkPkgid = he->p.argv;
    00319             pn = he->c;
    00320
    00321             /* XXX Always erase packages at beginning of upgrade chain. */
    00322             if (pn == 1 && flinkPkgid[0] != NULL && !strcmp(flinkPkgid[0], RPMTE_CHAIN_END)) {
    00323                 flinkPkgid = _free(flinkPkgid);
    00324                 goto erase;
    00325             }
    00326
    00327             he->tag = RPMTAG_BLINKHDRID;
    00328             xx = headerGet(ip->h, he, 0);
    00329             flinkHdrid = he->p.argv;
    00330             hn = he->c;
    00331             he->tag = RPMTAG_BLINKNEVRA;
    00332             xx = headerGet(ip->h, he, 0);
    00333             flinkNEVRA = he->p.argv;
    00334             nn = he->c;
    00335
    00336             /*
    00337              * Link data may be missing and can have multiple entries.
    00338              */
    00339             /* XXX Until link tags are reliably populated, check in the order
    00340              *  NEVRA -> hdrid -> pkgid
    00341              * because NEVRA is easier to debug (hdrid/pkgid are more precise.)
    00342             */
    00343             bingo = 0;
    00344             if (!bingo)
    00345                 bingo = cmpArgvStr(ts, "NEVRA", flinkNEVRA, nn, (p ? p->NEVRA : NULL));
    00346             if (!bingo)
    00347                 bingo = cmpArgvStr(ts, "Hdrid", flinkHdrid, hn, (p ? p->hdrid : NULL));
    00348 /*@-nullstate@*/
    00349             if (!bingo)
    00350                 bingo = cmpArgvStr(ts, "Pkgid", flinkPkgid, pn, (p ? p->pkgid : NULL));
    00351 /*@=nullstate@*/
    00352             flinkPkgid = _free(flinkPkgid);
    00353             flinkHdrid = _free(flinkHdrid);
    00354             flinkNEVRA = _free(flinkNEVRA);
    00355
    00356             if (bingo < 0) {
    00357                 rc = -1;
    00358                 goto exit;
    00359             }
    00360
    00361             if (!bingo)
    00362                 goto bottom;
    00363         }
    00364
    00365 erase:
    00366         rpmlog(RPMLOG_DEBUG, D_("\t--- erase h#%u\n"), ip->instance);
    00367
    00368         rc = rpmtsAddEraseElement(ts, ip->h, ip->instance);
    00369         if (rc != 0)
    00370             goto exit;
    00371
    00372         /* Cross link the transaction elements to mimic --upgrade. */
    00373         if (p != NULL) {
    00374             rpmte q = ts->teErase;
    00375             xx = rpmteChain(p, q, ip->h, "Rollback");
    00376         }
    00377
    00378 #ifdef  NOTYET
    00379         ip->instance = 0;
    00380 #endif
    00381         ip->done = 1;
    00382
    00383 bottom:
    00384
    00385         /* Go to the next header in the rpmdb */
    00386         niids--;
    00387         if (niids > 0)
    00388             ip++;
    00389         else
    00390             ip = NULL;
    00391     }
    00392
    00393 exit:
    00394     return rc;
    00395 }
    00396
    00398 int rpmRollback(rpmts ts, QVA_t ia, const char ** argv)
    00399 {
    00400     int ifmask= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE);
    00401     unsigned thistid = 0xffffffff;
    00402     unsigned prevtid;
    00403     time_t tid;
    00404     IDTX itids = NULL;
    00405     IDTX rtids = NULL;
    00406     IDT rp;
    00407     int nrids = 0;
    00408     IDT ip;
    00409     int niids = 0;
    00410     int rc = 0;
    00411     int vsflags, ovsflags;
    00412     int numAdded;
    00413     int numRemoved;
    00414     unsigned int _unsafe_rollbacks = 0;
    00415     rpmtransFlags transFlags = ia->transFlags;
    00416     rpmdepFlags depFlags = ia->depFlags;
    00417     int xx;
    00418
    00419     if (argv != NULL && *argv != NULL) {
    00420         rc = -1;
    00421         goto exit;
    00422     }
    00423
    00424     _unsafe_rollbacks = rpmExpandNumeric("%{?_unsafe_rollbacks}");
    00425
    00426     vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
    00427     if (ia->qva_flags & VERIFY_DIGEST)
    00428         vsflags |= _RPMVSF_NODIGESTS;
    00429     if (ia->qva_flags & VERIFY_SIGNATURE)
    00430         vsflags |= _RPMVSF_NOSIGNATURES;
    00431     if (ia->qva_flags & VERIFY_HDRCHK)
    00432         vsflags |= RPMVSF_NOHDRCHK;
    00433     vsflags |= RPMVSF_NEEDPAYLOAD;      /* XXX no legacy signatures */
    00434     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00435
    00436     (void) rpmtsSetFlags(ts, transFlags);
    00437     (void) rpmtsSetDFlags(ts, depFlags);
    00438
    00439     /*  Make the transaction a rollback transaction.  In a rollback
    00440      *  a best effort is what we want
    00441      */
    00442     rpmtsSetType(ts, RPMTRANS_TYPE_ROLLBACK);
    00443
    00444     itids = IDTXload(ts, RPMTAG_INSTALLTID, ia->rbtid);
    00445     if (itids != NULL) {
    00446         ip = itids->idt;
    00447         niids = itids->nidt;
    00448     } else {
    00449         ip = NULL;
    00450         niids = 0;
    00451     }
    00452
    00453     {   const char * globstr = rpmExpand("%{_repackage_dir}/*/*.rpm", NULL);
    00454         if (globstr == NULL || *globstr == '%') {
    00455             globstr = _free(globstr);
    00456             rc = -1;
    00457             goto exit;
    00458         }
    00459         rtids = IDTXglob(ts, globstr, RPMTAG_REMOVETID, ia->rbtid);
    00460
    00461         if (rtids != NULL) {
    00462             rp = rtids->idt;
    00463             nrids = rtids->nidt;
    00464         } else {
    00465             rp = NULL;
    00466             nrids = 0;
    00467         }
    00468         globstr = _free(globstr);
    00469     }
    00470
    00471     {   int notifyFlags;
    00472         notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
    00473         xx = rpmtsSetNotifyCallback(ts,
    00474                         rpmShowProgress, (void *) ((long)notifyFlags));
    00475     }
    00476
    00477     /* Run transactions until rollback goal is achieved. */
    00478     do {
    00479         prevtid = thistid;
    00480         rc = 0;
    00481         rpmcliPackagesTotal = 0;
    00482         numAdded = 0;
    00483         numRemoved = 0;
    00484         ia->installInterfaceFlags &= ~ifmask;
    00485
    00486         /* Find larger of the remaining install/erase transaction id's. */
    00487         thistid = 0;
    00488         if (ip != NULL && ip->val.u32 > thistid)
    00489             thistid = ip->val.u32;
    00490         if (rp != NULL && rp->val.u32 > thistid)
    00491             thistid = rp->val.u32;
    00492
    00493         /* If we've achieved the rollback goal, then we're done. */
    00494         if (thistid == 0 || thistid < ia->rbtid)
    00495             break;
    00496
    00497         /* If we've reached the (configured) rollback goal, then we're done. */
    00498         if (_unsafe_rollbacks && thistid <= _unsafe_rollbacks)
    00499             break;
    00500
    00501         /* Is this transaction excluded from the rollback? */
    00502         if (ia->rbtidExcludes != NULL && ia->numrbtidExcludes > 0)
    00503         {
    00504             rpmuint32_t *excludedTID;
    00505             int excluded = 0;
    00506             for(excludedTID = ia->rbtidExcludes;
    00507                 excludedTID < ia->rbtidExcludes + ia->numrbtidExcludes;
    00508                 excludedTID++) {
    00509                 if (thistid == *excludedTID) {
    00510                     time_t ttid = (time_t)thistid;
    00511                     rpmlog(RPMLOG_NOTICE,
    00512                         _("Excluding TID from rollback: %-24.24s (0x%08x)\n"),
    00513                                 ctime(&ttid), thistid);
    00514                     excluded = 1;
    00515                     /*@innerbreak@*/ break;
    00516                 }
    00517             }
    00518             if (excluded) {
    00519                 /* Iterate over repackaged packages */
    00520                 while (rp != NULL && rp->val.u32 == thistid) {
    00521                     /* Go to the next repackaged package */
    00522                     nrids--;
    00523                     if (nrids > 0)
    00524                         rp++;
    00525                     else
    00526                         rp = NULL;
    00527                 }
    00528                 /* Iterate over installed packages */
    00529                 while (ip != NULL && ip->val.u32 == thistid) {
    00530                     /* Go to the next header in the rpmdb */
    00531                     niids--;
    00532                     if (niids > 0)
    00533                         ip++;
    00534                     else
    00535                         ip = NULL;
    00536                 }
    00537                 continue;               /* with next transaction */
    00538             }
    00539         }
    00540
    00541         rpmtsEmpty(ts);
    00542         (void) rpmtsSetFlags(ts, transFlags);
    00543         (void) rpmtsSetDFlags(ts, depFlags);
    00544         ts->probs = rpmpsFree(ts->probs);
    00545
    00546         /* Install the previously erased packages for this transaction.
    00547          */
    00548         while (rp != NULL && rp->val.u32 == thistid) {
    00549             if (!rp->done) {
    00550                 rpmlog(RPMLOG_DEBUG, D_("\t+++ install %s\n"),
    00551                         (rp->key ? rp->key : "???"));
    00552
    00553 /*@-abstract@*/
    00554                 rc = rpmtsAddInstallElement(ts, rp->h, (fnpyKey)rp->key,
    00555                                0, ia->relocations);
    00556 /*@=abstract@*/
    00557                 if (rc != 0)
    00558                     goto exit;
    00559
    00560                 numAdded++;
    00561                 rpmcliPackagesTotal++;
    00562                 if (!(ia->installInterfaceFlags & ifmask))
    00563                     ia->installInterfaceFlags |= INSTALL_UPGRADE;
    00564
    00565                 /* Re-add linked (i.e. from upgrade/obsoletes) erasures. */
    00566                 rc = findErases(ts, ts->teInstall, thistid, ip, niids);
    00567                 if (rc < 0)
    00568                     goto exit;
    00569 #ifdef  NOTYET
    00570                 (void)headerFree(rp->h);
    00571                 rpm->h = NULL;
    00572 #endif
    00573                 rp->done = 1;
    00574             }
    00575
    00576             /* Go to the next repackaged package */
    00577             nrids--;
    00578             if (nrids > 0)
    00579                 rp++;
    00580             else
    00581                 rp = NULL;
    00582         }
    00583
    00584         /* Re-add pure (i.e. not from upgrade/obsoletes) erasures. */
    00585         rc = findErases(ts, NULL, thistid, ip, niids);
    00586         if (rc < 0)
    00587             goto exit;
    00588
    00589         /* Check that all erasures have been re-added. */
    00590         while (ip != NULL && ip->val.u32 == thistid) {
    00591 #ifdef  NOTNOW
    00592 /* XXX Prevent incomplete rollback transactions. */
    00593 assert(ip->done || ia->no_rollback_links);
    00594 #endif
    00595             if (!(ip->done || ia->no_rollback_links)) {
    00596                 numRemoved++;
    00597
    00598                 if (_unsafe_rollbacks != 0)
    00599                     rpmcliPackagesTotal++;
    00600
    00601                 if (!(ia->installInterfaceFlags & ifmask))
    00602                     ia->installInterfaceFlags |= INSTALL_ERASE;
    00603             }
    00604
    00605             /* Go to the next header in the rpmdb */
    00606             niids--;
    00607             if (niids > 0)
    00608                 ip++;
    00609             else
    00610                 ip = NULL;
    00611         }
    00612
    00613         /* Print any rollback transaction problems */
    00614         xx = rpmcliInstallProblems(ts, _("Missing re-packaged package(s)"), 1);
    00615
    00616         /* Anything to do? */
    00617         if (rpmcliPackagesTotal <= 0)
    00618             break;
    00619
    00620         tid = (time_t)thistid;
    00621         rpmlog(RPMLOG_NOTICE,
    00622                 _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
    00623                         numAdded, numRemoved, ctime(&tid), thistid);
    00624
    00625         rc = (ia->rbCheck ? (*ia->rbCheck) (ts) : 0);
    00626         if (rc != 0)
    00627             goto exit;
    00628
    00629         rc = (ia->rbOrder ? (*ia->rbOrder) (ts) : 0);
    00630         if (rc != 0)
    00631             goto exit;
    00632
    00633         /* Drop added/available package indices and dependency sets. */
    00634         rpmtsClean(ts);
    00635
    00636         /* Print the transaction set. */
    00637         xx = rpmtsPrint(ts, stdout);
    00638
    00639         rc = (ia->rbRun
    00640             ? (*ia->rbRun)(ts, NULL, (ia->probFilter|RPMPROB_FILTER_OLDPACKAGE))
    00641             : 0);
    00642         if (rc != 0)
    00643             goto exit;
    00644
    00645         /* Remove repackaged packages after successful reinstall. */
    00646         if (rtids && !rpmIsDebug()) {
    00647             int i;
    00648             rpmlog(RPMLOG_NOTICE, _("Cleaning up repackaged packages:\n"));
    00649             if (rtids->idt)
    00650             for (i = 0; i < rtids->nidt; i++) {
    00651                 IDT rrp = rtids->idt + i;
    00652                 if (rrp->val.u32 != thistid)
    00653                     /*@innercontinue@*/ continue;
    00654                 if (rrp->key) { /* XXX can't happen */
    00655                     rpmlog(RPMLOG_NOTICE, _("\tRemoving %s:\n"), rrp->key);
    00656                     (void) unlink(rrp->key);    /* XXX: Should check rc??? */
    00657                 }
    00658             }
    00659         }
    00660
    00661         /* The rpmdb has changed, so reload installed package chains. */
    00662         itids = IDTXfree(itids);
    00663         itids = IDTXload(ts, RPMTAG_INSTALLTID, ia->rbtid);
    00664         if (itids != NULL) {
    00665             ip = itids->idt;
    00666             niids = itids->nidt;
    00667         } else {
    00668             ip = NULL;
    00669             niids = 0;
    00670         }
    00671
    00672         /* Re-position the iterator at the current install tid. */
    00673         while (ip != NULL && ip->val.u32 == thistid) {
    00674             /* Go to the next header in the rpmdb */
    00675             niids--;
    00676             if (niids > 0)
    00677                 ip++;
    00678             else
    00679                 ip = NULL;
    00680         }
    00681
    00682     } while (1);
    00683
    00684 exit:
    00685     rtids = IDTXfree(rtids);
    00686     itids = IDTXfree(itids);
    00687
    00688     rpmtsEmpty(ts);
    00689     (void) rpmtsSetFlags(ts, transFlags);
    00690     (void) rpmtsSetDFlags(ts, depFlags);
    00691
    00692     return rc;
    00693 }