lib/transaction.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include <rpmlib.h>
00007 
00008 #include <rpmmacro.h>   /* XXX for rpmExpand */
00009 
00010 #include "fsm.h"
00011 #include "psm.h"
00012 
00013 #include "rpmdb.h"
00014 
00015 #include "rpmds.h"
00016 
00017 #include "rpmlock.h"
00018 
00019 #define _RPMFI_INTERNAL
00020 #include "rpmfi.h"
00021 
00022 #define _RPMTE_INTERNAL
00023 #include "rpmte.h"
00024 
00025 #define _RPMTS_INTERNAL
00026 #include "rpmts.h"
00027 
00028 #include "cpio.h"
00029 #include "fprint.h"
00030 #include "legacy.h"     /* XXX domd5 */
00031 #include "misc.h" /* XXX stripTrailingChar, splitString, currentDirectory */
00032 
00033 #include "debug.h"
00034 
00035 /*
00036  * This is needed for the IDTX definitions.  I think probably those need
00037  * to be moved into a different source file (idtx.{c,h}), but that is up
00038  * to Jeff Johnson.
00039  */
00040 #include "rpmcli.h"
00041 
00042 /*@access Header @*/            /* XXX ts->notify arg1 is void ptr */
00043 /*@access rpmps @*/     /* XXX need rpmProblemSetOK() */
00044 /*@access dbiIndexSet @*/
00045 
00046 /*@access rpmpsm @*/
00047 
00048 /*@access alKey @*/
00049 /*@access fnpyKey @*/
00050 
00051 /*@access rpmfi @*/
00052 
00053 /*@access rpmte @*/
00054 /*@access rpmtsi @*/
00055 /*@access rpmts @*/
00056 
00057 /*@access IDT @*/
00058 /*@access IDTX @*/
00059 /*@access FD_t @*/
00060 
00061 /* XXX: This is a hack.  I needed a to setup a notify callback
00062  * for the rollback transaction, but I did not want to create
00063  * a header for rpminstall.c.
00064  */
00065 extern void * rpmShowProgress(/*@null@*/ const void * arg,
00066                         const rpmCallbackType what,
00067                         const unsigned long amount,
00068                         const unsigned long total,
00069                         /*@null@*/ fnpyKey key,
00070                         /*@null@*/ void * data)
00071         /*@*/;
00072 
00075 static int archOkay(/*@null@*/ const char * pkgArch)
00076         /*@*/
00077 {
00078     if (pkgArch == NULL) return 0;
00079     return (rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch) ? 1 : 0);
00080 }
00081 
00084 static int osOkay(/*@null@*/ const char * pkgOs)
00085         /*@*/
00086 {
00087     if (pkgOs == NULL) return 0;
00088     return (rpmMachineScore(RPM_MACHTABLE_INSTOS, pkgOs) ? 1 : 0);
00089 }
00090 
00093 static int sharedCmp(const void * one, const void * two)
00094         /*@*/
00095 {
00096     sharedFileInfo a = (sharedFileInfo) one;
00097     sharedFileInfo b = (sharedFileInfo) two;
00098 
00099     if (a->otherPkg < b->otherPkg)
00100         return -1;
00101     else if (a->otherPkg > b->otherPkg)
00102         return 1;
00103 
00104     return 0;
00105 }
00106 
00107 static int isDocFile(rpmfi fi)
00108 {
00109     const char *fn = rpmfiFN(fi);
00110     char *s = strstr(fn, "/usr/share/doc/");
00111     return (s == fn);
00112 }
00113 
00122 /* XXX only ts->{probs,rpmdb} modified */
00123 /*@-bounds@*/
00124 static int handleInstInstalledFiles(const rpmts ts,
00125                 rpmte p, rpmfi fi,
00126                 sharedFileInfo shared,
00127                 int sharedCount, int reportConflicts)
00128         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00129         /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
00130 {
00131     uint_32 tscolor = rpmtsColor(ts);
00132     uint_32 prefcolor = rpmtsPrefColor(ts);
00133     uint_32 otecolor, tecolor;
00134     uint_32 oFColor, FColor;
00135     const char * altNEVR = NULL;
00136     rpmfi otherFi = NULL;
00137     int numReplaced = 0;
00138     rpmps ps;
00139     int i;
00140 
00141     {   rpmdbMatchIterator mi;
00142         Header h;
00143         int scareMem = 0;
00144 
00145         mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
00146                         &shared->otherPkg, sizeof(shared->otherPkg));
00147         while ((h = rpmdbNextIterator(mi)) != NULL) {
00148             altNEVR = hGetNEVRA(h, NULL);
00149             otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00150             break;
00151         }
00152         mi = rpmdbFreeIterator(mi);
00153     }
00154 
00155     /* Compute package color. */
00156     tecolor = rpmteColor(p);
00157     tecolor &= tscolor;
00158 
00159     /* Compute other pkg color. */
00160     otecolor = 0;
00161     otherFi = rpmfiInit(otherFi, 0);
00162     if (otherFi != NULL)
00163     while (rpmfiNext(otherFi) >= 0)
00164         otecolor |= rpmfiFColor(otherFi);
00165     otecolor &= tscolor;
00166 
00167     if (otherFi == NULL)
00168         return 1;
00169 
00170     fi->replaced = xcalloc(sharedCount, sizeof(*fi->replaced));
00171 
00172     ps = rpmtsProblems(ts);
00173     for (i = 0; i < sharedCount; i++, shared++) {
00174         int otherFileNum, fileNum;
00175         int isCfgFile;
00176         int isGhostFile;
00177 
00178         otherFileNum = shared->otherFileNum;
00179         (void) rpmfiSetFX(otherFi, otherFileNum);
00180         oFColor = rpmfiFColor(otherFi);
00181         oFColor &= tscolor;
00182 
00183         fileNum = shared->pkgFileNum;
00184         (void) rpmfiSetFX(fi, fileNum);
00185         FColor = rpmfiFColor(fi);
00186         FColor &= tscolor;
00187 
00188         isCfgFile = ((rpmfiFFlags(otherFi) | rpmfiFFlags(fi)) & RPMFILE_CONFIG);
00189         isGhostFile = ((rpmfiFFlags(otherFi) & RPMFILE_GHOST) && (rpmfiFFlags(fi) & RPMFILE_GHOST));
00190 
00191 #ifdef  DYING
00192         /* XXX another tedious segfault, assume file state normal. */
00193         if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00194             continue;
00195 #endif
00196 
00197         if (XFA_SKIPPING(fi->actions[fileNum]))
00198             continue;
00199 
00200         if (!(fi->mapflags & CPIO_SBIT_CHECK)) {
00201             int_16 omode = rpmfiFMode(otherFi);
00202             if (S_ISREG(omode) && (omode & 06000) != 0) {
00203                 fi->mapflags |= CPIO_SBIT_CHECK;
00204             }
00205         }
00206 
00207         if (isGhostFile)
00208             continue;
00209 
00210         if (rpmfiCompare(otherFi, fi)) {
00211             int rConflicts;
00212 
00213             rConflicts = reportConflicts;
00214             /* Resolve file conflicts to prefer Elf64 (if not forced). */
00215             if (tscolor != 0 && FColor != 0 && FColor != oFColor)
00216             {
00217                 if (oFColor & prefcolor) {
00218                     fi->actions[fileNum] = FA_SKIPCOLOR;
00219                     rConflicts = 0;
00220                 } else
00221                 if (FColor & prefcolor) {
00222                     fi->actions[fileNum] = FA_CREATE;
00223                     rConflicts = 0;
00224                 }
00225             }
00226 
00227             /* XXX Temporary hack to permit documentation conflicts */
00228             if (rConflicts && isDocFile(fi)) {
00229                 fi->actions[i] = FA_CREATE;
00230                 rConflicts = 0;
00231             }
00232 
00233             if (rConflicts) {
00234                 rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
00235                         rpmteNEVRA(p), rpmteKey(p),
00236                         rpmfiDN(fi), rpmfiBN(fi),
00237                         altNEVR,
00238                         0);
00239             }
00240             /* Save file identifier to mark as state REPLACED. */
00241             if ( !(isCfgFile || XFA_SKIPPING(fi->actions[fileNum])) ) {
00242                 /*@-assignexpose@*/ /* FIX: p->replaced, not fi */
00243                 if (!shared->isRemoved)
00244                     fi->replaced[numReplaced++] = *shared;
00245                 /*@=assignexpose@*/
00246             }
00247         }
00248 
00249         /* Determine config file dispostion, skipping missing files (if any). */
00250         if (isCfgFile) {
00251             int skipMissing =
00252                 ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
00253             fileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
00254             fi->actions[fileNum] = action;
00255         }
00256         fi->replacedSizes[fileNum] = rpmfiFSize(otherFi);
00257     }
00258     ps = rpmpsFree(ps);
00259 
00260     altNEVR = _free(altNEVR);
00261     otherFi = rpmfiFree(otherFi);
00262 
00263     fi->replaced = xrealloc(fi->replaced,       /* XXX memory leak */
00264                            sizeof(*fi->replaced) * (numReplaced + 1));
00265     fi->replaced[numReplaced].otherPkg = 0;
00266 
00267     return 0;
00268 }
00269 /*@=bounds@*/
00270 
00273 /* XXX only ts->rpmdb modified */
00274 static int handleRmvdInstalledFiles(const rpmts ts, rpmfi fi,
00275                 sharedFileInfo shared, int sharedCount)
00276         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00277         /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
00278 {
00279     HGE_t hge = fi->hge;
00280     Header h;
00281     const char * otherStates;
00282     int i, xx;
00283 
00284     rpmdbMatchIterator mi;
00285 
00286     mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
00287                         &shared->otherPkg, sizeof(shared->otherPkg));
00288     h = rpmdbNextIterator(mi);
00289     if (h == NULL) {
00290         mi = rpmdbFreeIterator(mi);
00291         return 1;
00292     }
00293 
00294     xx = hge(h, RPMTAG_FILESTATES, NULL, (void **) &otherStates, NULL);
00295 
00296 /*@-boundswrite@*/
00297     for (i = 0; i < sharedCount; i++, shared++) {
00298         int otherFileNum, fileNum;
00299         otherFileNum = shared->otherFileNum;
00300         fileNum = shared->pkgFileNum;
00301 
00302         if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00303             continue;
00304 
00305         fi->actions[fileNum] = FA_SKIP;
00306     }
00307 /*@=boundswrite@*/
00308 
00309     mi = rpmdbFreeIterator(mi);
00310 
00311     return 0;
00312 }
00313 
00314 #define ISROOT(_d)      (((_d)[0] == '/' && (_d)[1] == '\0') ? "" : (_d))
00315 
00316 /*@unchecked@*/
00317 int _fps_debug = 0;
00318 
00319 static int fpsCompare (const void * one, const void * two)
00320         /*@*/
00321 {
00322     const struct fingerPrint_s * a = (const struct fingerPrint_s *)one;
00323     const struct fingerPrint_s * b = (const struct fingerPrint_s *)two;
00324     int adnlen = strlen(a->entry->dirName);
00325     int asnlen = (a->subDir ? strlen(a->subDir) : 0);
00326     int abnlen = strlen(a->baseName);
00327     int bdnlen = strlen(b->entry->dirName);
00328     int bsnlen = (b->subDir ? strlen(b->subDir) : 0);
00329     int bbnlen = strlen(b->baseName);
00330     char * afn, * bfn, * t;
00331     int rc = 0;
00332 
00333     if (adnlen == 1 && asnlen != 0) adnlen = 0;
00334     if (bdnlen == 1 && bsnlen != 0) bdnlen = 0;
00335 
00336 /*@-boundswrite@*/
00337     afn = t = alloca(adnlen+asnlen+abnlen+2);
00338     if (adnlen) t = stpcpy(t, a->entry->dirName);
00339     *t++ = '/';
00340     if (a->subDir && asnlen) t = stpcpy(t, a->subDir);
00341     if (abnlen) t = stpcpy(t, a->baseName);
00342     if (afn[0] == '/' && afn[1] == '/') afn++;
00343 
00344     bfn = t = alloca(bdnlen+bsnlen+bbnlen+2);
00345     if (bdnlen) t = stpcpy(t, b->entry->dirName);
00346     *t++ = '/';
00347     if (b->subDir && bsnlen) t = stpcpy(t, b->subDir);
00348     if (bbnlen) t = stpcpy(t, b->baseName);
00349     if (bfn[0] == '/' && bfn[1] == '/') bfn++;
00350 /*@=boundswrite@*/
00351 
00352     rc = strcmp(afn, bfn);
00353 /*@-modfilesys@*/
00354 if (_fps_debug)
00355 fprintf(stderr, "\trc(%d) = strcmp(\"%s\", \"%s\")\n", rc, afn, bfn);
00356 /*@=modfilesys@*/
00357 
00358 /*@-modfilesys@*/
00359 if (_fps_debug)
00360 fprintf(stderr, "\t%s/%s%s\trc %d\n",
00361 ISROOT(b->entry->dirName),
00362 (b->subDir ? b->subDir : ""),
00363 b->baseName,
00364 rc
00365 );
00366 /*@=modfilesys@*/
00367 
00368     return rc;
00369 }
00370 
00371 /*@unchecked@*/
00372 static int _linear_fps_search = 0;
00373 
00374 static int findFps(const struct fingerPrint_s * fiFps,
00375                 const struct fingerPrint_s * otherFps,
00376                 int otherFc)
00377         /*@*/
00378 {
00379     int otherFileNum;
00380 
00381 /*@-modfilesys@*/
00382 if (_fps_debug)
00383 fprintf(stderr, "==> %s/%s%s\n",
00384 ISROOT(fiFps->entry->dirName),
00385 (fiFps->subDir ? fiFps->subDir : ""),
00386 fiFps->baseName);
00387 /*@=modfilesys@*/
00388 
00389   if (_linear_fps_search) {
00390 
00391 linear:
00392     for (otherFileNum = 0; otherFileNum < otherFc; otherFileNum++, otherFps++) {
00393 
00394 /*@-modfilesys@*/
00395 if (_fps_debug)
00396 fprintf(stderr, "\t%4d %s/%s%s\n", otherFileNum,
00397 ISROOT(otherFps->entry->dirName),
00398 (otherFps->subDir ? otherFps->subDir : ""),
00399 otherFps->baseName);
00400 /*@=modfilesys@*/
00401 
00402         /* If the addresses are the same, so are the values. */
00403         if (fiFps == otherFps)
00404             break;
00405 
00406         /* Otherwise, compare fingerprints by value. */
00407         /*@-nullpass@*/ /* LCL: looks good to me */
00408         if (FP_EQUAL((*fiFps), (*otherFps)))
00409             break;
00410         /*@=nullpass@*/
00411     }
00412 
00413 if (otherFileNum == otherFc) {
00414 /*@-modfilesys@*/
00415 if (_fps_debug)
00416 fprintf(stderr, "*** FP_EQUAL NULL %s/%s%s\n",
00417 ISROOT(fiFps->entry->dirName),
00418 (fiFps->subDir ? fiFps->subDir : ""),
00419 fiFps->baseName);
00420 /*@=modfilesys@*/
00421 }
00422 
00423     return otherFileNum;
00424 
00425   } else {
00426 
00427     const struct fingerPrint_s * bingoFps;
00428 
00429 /*@-boundswrite@*/
00430     bingoFps = bsearch(fiFps, otherFps, otherFc, sizeof(*otherFps), fpsCompare);
00431 /*@=boundswrite@*/
00432     if (bingoFps == NULL) {
00433 /*@-modfilesys@*/
00434 if (_fps_debug)
00435 fprintf(stderr, "*** bingoFps NULL %s/%s%s\n",
00436 ISROOT(fiFps->entry->dirName),
00437 (fiFps->subDir ? fiFps->subDir : ""),
00438 fiFps->baseName);
00439 /*@=modfilesys@*/
00440         goto linear;
00441     }
00442 
00443     /* If the addresses are the same, so are the values. */
00444     /*@-nullpass@*/     /* LCL: looks good to me */
00445     if (!(fiFps == bingoFps || FP_EQUAL((*fiFps), (*bingoFps)))) {
00446 /*@-modfilesys@*/
00447 if (_fps_debug)
00448 fprintf(stderr, "***  BAD %s/%s%s\n",
00449 ISROOT(bingoFps->entry->dirName),
00450 (bingoFps->subDir ? bingoFps->subDir : ""),
00451 bingoFps->baseName);
00452 /*@=modfilesys@*/
00453         goto linear;
00454     }
00455 
00456     otherFileNum = (bingoFps != NULL ? (bingoFps - otherFps) : 0);
00457 
00458   }
00459 
00460     return otherFileNum;
00461 }
00462 
00466 /* XXX only ts->{probs,di} modified */
00467 static void handleOverlappedFiles(const rpmts ts,
00468                 const rpmte p, rpmfi fi)
00469         /*@globals h_errno, fileSystem, internalState @*/
00470         /*@modifies ts, fi, fileSystem, internalState @*/
00471 {
00472     uint_32 fixupSize = 0;
00473     rpmps ps;
00474     const char * fn;
00475     int i, j;
00476 
00477     ps = rpmtsProblems(ts);
00478     fi = rpmfiInit(fi, 0);
00479     if (fi != NULL)
00480     while ((i = rpmfiNext(fi)) >= 0) {
00481         uint_32 tscolor = rpmtsColor(ts);
00482         uint_32 prefcolor = rpmtsPrefColor(ts);
00483         uint_32 oFColor, FColor;
00484         struct fingerPrint_s * fiFps;
00485         int otherPkgNum, otherFileNum;
00486         rpmfi otherFi;
00487         int_32 FFlags;
00488         int_16 FMode;
00489         const rpmfi * recs;
00490         int numRecs;
00491 
00492         if (XFA_SKIPPING(fi->actions[i]))
00493             continue;
00494 
00495         fn = rpmfiFN(fi);
00496         fiFps = fi->fps + i;
00497         FFlags = rpmfiFFlags(fi);
00498         FMode = rpmfiFMode(fi);
00499         FColor = rpmfiFColor(fi);
00500         FColor &= tscolor;
00501 
00502         fixupSize = 0;
00503 
00504         /*
00505          * Retrieve all records that apply to this file. Note that the
00506          * file info records were built in the same order as the packages
00507          * will be installed and removed so the records for an overlapped
00508          * files will be sorted in exactly the same order.
00509          */
00510         (void) htGetEntry(ts->ht, fiFps,
00511                         (const void ***) &recs, &numRecs, NULL);
00512 
00513         /*
00514          * If this package is being added, look only at other packages
00515          * being added -- removed packages dance to a different tune.
00516          *
00517          * If both this and the other package are being added, overlapped
00518          * files must be identical (or marked as a conflict). The
00519          * disposition of already installed config files leads to
00520          * a small amount of extra complexity.
00521          *
00522          * If this package is being removed, then there are two cases that
00523          * need to be worried about:
00524          * If the other package is being added, then skip any overlapped files
00525          * so that this package removal doesn't nuke the overlapped files
00526          * that were just installed.
00527          * If both this and the other package are being removed, then each
00528          * file removal from preceding packages needs to be skipped so that
00529          * the file removal occurs only on the last occurence of an overlapped
00530          * file in the transaction set.
00531          *
00532          */
00533 
00534         /* Locate this overlapped file in the set of added/removed packages. */
00535         for (j = 0; j < numRecs && recs[j] != fi; j++)
00536             {};
00537 
00538         /* Find what the previous disposition of this file was. */
00539         otherFileNum = -1;                      /* keep gcc quiet */
00540         otherFi = NULL;
00541         for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
00542             struct fingerPrint_s * otherFps;
00543             int otherFc;
00544 
00545             otherFi = recs[otherPkgNum];
00546 
00547             /* Added packages need only look at other added packages. */
00548             if (rpmteType(p) == TR_ADDED && rpmteType(otherFi->te) != TR_ADDED)
00549                 /*@innercontinue@*/ continue;
00550 
00551             otherFps = otherFi->fps;
00552             otherFc = rpmfiFC(otherFi);
00553 
00554             otherFileNum = findFps(fiFps, otherFps, otherFc);
00555             (void) rpmfiSetFX(otherFi, otherFileNum);
00556 
00557             /* XXX Happens iff fingerprint for incomplete package install. */
00558             if (otherFi->actions[otherFileNum] != FA_UNKNOWN)
00559                 /*@innerbreak@*/ break;
00560         }
00561 
00562         oFColor = rpmfiFColor(otherFi);
00563         oFColor &= tscolor;
00564 
00565 /*@-boundswrite@*/
00566         switch (rpmteType(p)) {
00567         case TR_ADDED:
00568           {
00569             int reportConflicts =
00570                 !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
00571             int done = 0;
00572 
00573             if (otherPkgNum < 0) {
00574                 /* XXX is this test still necessary? */
00575                 if (fi->actions[i] != FA_UNKNOWN)
00576                     /*@switchbreak@*/ break;
00577                 if (rpmfiConfigConflict(fi)) {
00578                     /* Here is a non-overlapped pre-existing config file. */
00579                     fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
00580                         ? FA_ALTNAME : FA_BACKUP;
00581                 } else {
00582                     fi->actions[i] = FA_CREATE;
00583                 }
00584                 /*@switchbreak@*/ break;
00585             }
00586 
00587 assert(otherFi != NULL);
00588             /* Mark added overlapped non-identical files as a conflict. */
00589             if (rpmfiCompare(otherFi, fi)) {
00590                 int rConflicts;
00591 
00592                 rConflicts = reportConflicts;
00593                 /* Resolve file conflicts to prefer Elf64 (if not forced) ... */
00594                 if (tscolor != 0) {
00595                     if (FColor & prefcolor) {
00596                         /* ... last file of preferred colour is installed ... */
00597                         if (!XFA_SKIPPING(fi->actions[i])) {
00598                             /* XXX static helpers are order dependent. Ick. */
00599                             if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade")
00600                              && strcmp(fn, "/usr/sbin/glibc_post_upgrade"))
00601                                 otherFi->actions[otherFileNum] = FA_SKIPCOLOR;
00602                         }
00603                         fi->actions[i] = FA_CREATE;
00604                         rConflicts = 0;
00605                     } else
00606                     if (oFColor & prefcolor) {
00607                         /* ... first file of preferred colour is installed ... */
00608                         if (XFA_SKIPPING(fi->actions[i]))
00609                             otherFi->actions[otherFileNum] = FA_CREATE;
00610                         fi->actions[i] = FA_SKIPCOLOR;
00611                         rConflicts = 0;
00612                     } else
00613                     if (FColor == 0 && oFColor == 0) {
00614                         /* ... otherwise, do both, last in wins. */
00615                         otherFi->actions[otherFileNum] = FA_CREATE;
00616                         fi->actions[i] = FA_CREATE;
00617                         rConflicts = 0;
00618                     }
00619                     done = 1;
00620                 }
00621 
00622                 /* XXX Temporary hack to permit documentation conflicts */
00623                 if (rConflicts && isDocFile(fi)) {
00624                     fi->actions[i] = FA_CREATE;
00625                     rConflicts = 0;
00626                 }
00627 
00628                 if (rConflicts) {
00629                     rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
00630                         rpmteNEVRA(p), rpmteKey(p),
00631                         fn, NULL,
00632                         rpmteNEVRA(otherFi->te),
00633                         0);
00634                 }
00635             }
00636 
00637             /* Try to get the disk accounting correct even if a conflict. */
00638             fixupSize = rpmfiFSize(otherFi);
00639 
00640             if (rpmfiConfigConflict(fi)) {
00641                 /* Here is an overlapped  pre-existing config file. */
00642                 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
00643                         ? FA_ALTNAME : FA_SKIP;
00644             } else {
00645                 if (!done)
00646                     fi->actions[i] = FA_CREATE;
00647             }
00648           } /*@switchbreak@*/ break;
00649 
00650         case TR_REMOVED:
00651             if (otherPkgNum >= 0) {
00652 assert(otherFi != NULL);
00653                 /* Here is an overlapped added file we don't want to nuke. */
00654                 if (otherFi->actions[otherFileNum] != FA_ERASE) {
00655                     /* On updates, don't remove files. */
00656                     fi->actions[i] = FA_SKIP;
00657                     /*@switchbreak@*/ break;
00658                 }
00659                 /* Here is an overlapped removed file: skip in previous. */
00660                 otherFi->actions[otherFileNum] = FA_SKIP;
00661             }
00662             if (XFA_SKIPPING(fi->actions[i]))
00663                 /*@switchbreak@*/ break;
00664             if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
00665                 /*@switchbreak@*/ break;
00666             if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG))) {
00667                 fi->actions[i] = FA_ERASE;
00668                 /*@switchbreak@*/ break;
00669             }
00670                 
00671             /* Here is a pre-existing modified config file that needs saving. */
00672             {   char md5sum[50];
00673                 const unsigned char * MD5 = rpmfiMD5(fi);
00674                 if (!domd5(fn, md5sum, 0, NULL) && memcmp(MD5, md5sum, 16)) {
00675                     fi->actions[i] = FA_BACKUP;
00676                     /*@switchbreak@*/ break;
00677                 }
00678             }
00679             fi->actions[i] = FA_ERASE;
00680             /*@switchbreak@*/ break;
00681         }
00682 /*@=boundswrite@*/
00683 
00684         /* Update disk space info for a file. */
00685         rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
00686                 fi->replacedSizes[i], fixupSize, fi->actions[i]);
00687 
00688     }
00689     ps = rpmpsFree(ps);
00690 }
00691 
00699 static int ensureOlder(rpmts ts,
00700                 const rpmte p, const Header h)
00701         /*@modifies ts @*/
00702 {
00703     int_32 reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
00704     const char * reqEVR;
00705     rpmds req;
00706     char * t;
00707     int nb;
00708     int rc;
00709 
00710     if (p == NULL || h == NULL)
00711         return 1;
00712 
00713 /*@-boundswrite@*/
00714     nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1;
00715     t = alloca(nb);
00716     *t = '\0';
00717     reqEVR = t;
00718     if (rpmteE(p) != NULL)      t = stpcpy( stpcpy(t, rpmteE(p)), ":");
00719     if (rpmteV(p) != NULL)      t = stpcpy(t, rpmteV(p));
00720     *t++ = '-';
00721     if (rpmteR(p) != NULL)      t = stpcpy(t, rpmteR(p));
00722 /*@=boundswrite@*/
00723 
00724     req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
00725     rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
00726     req = rpmdsFree(req);
00727 
00728     if (rc == 0) {
00729         rpmps ps = rpmtsProblems(ts);
00730         const char * altNEVR = hGetNEVRA(h, NULL);
00731         rpmpsAppend(ps, RPMPROB_OLDPACKAGE,
00732                 rpmteNEVRA(p), rpmteKey(p),
00733                 NULL, NULL,
00734                 altNEVR,
00735                 0);
00736         altNEVR = _free(altNEVR);
00737         ps = rpmpsFree(ps);
00738         rc = 1;
00739     } else
00740         rc = 0;
00741 
00742     return rc;
00743 }
00744 
00750 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
00751 /*@-bounds@*/
00752 static void skipFiles(const rpmts ts, rpmfi fi)
00753         /*@globals rpmGlobalMacroContext, h_errno @*/
00754         /*@modifies fi, rpmGlobalMacroContext @*/
00755 {
00756     uint_32 tscolor = rpmtsColor(ts);
00757     uint_32 FColor;
00758     int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
00759     int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
00760     char ** netsharedPaths = NULL;
00761     const char ** languages;
00762     const char * dn, * bn;
00763     int dnlen, bnlen, ix;
00764     const char * s;
00765     int * drc;
00766     char * dff;
00767     int dc;
00768     int i, j;
00769 
00770     if (!noDocs)
00771         noDocs = rpmExpandNumeric("%{_excludedocs}");
00772 
00773     {   const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL);
00774         /*@-branchstate@*/
00775         if (tmpPath && *tmpPath != '%')
00776             netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
00777         /*@=branchstate@*/
00778         tmpPath = _free(tmpPath);
00779     }
00780 
00781     s = rpmExpand("%{_install_langs}", NULL);
00782     /*@-branchstate@*/
00783     if (!(s && *s != '%'))
00784         s = _free(s);
00785     if (s) {
00786         languages = (const char **) splitString(s, strlen(s), ':');
00787         s = _free(s);
00788     } else
00789         languages = NULL;
00790     /*@=branchstate@*/
00791 
00792     /* Compute directory refcount, skip directory if now empty. */
00793     dc = rpmfiDC(fi);
00794     drc = alloca(dc * sizeof(*drc));
00795     memset(drc, 0, dc * sizeof(*drc));
00796     dff = alloca(dc * sizeof(*dff));
00797     memset(dff, 0, dc * sizeof(*dff));
00798 
00799     fi = rpmfiInit(fi, 0);
00800     if (fi != NULL)     /* XXX lclint */
00801     while ((i = rpmfiNext(fi)) >= 0)
00802     {
00803         char ** nsp;
00804 
00805         bn = rpmfiBN(fi);
00806         bnlen = strlen(bn);
00807         ix = rpmfiDX(fi);
00808         dn = rpmfiDN(fi);
00809         dnlen = strlen(dn);
00810         if (dn == NULL)
00811             continue;   /* XXX can't happen */
00812 
00813         drc[ix]++;
00814 
00815         /* Don't bother with skipped files */
00816         if (XFA_SKIPPING(fi->actions[i])) {
00817             drc[ix]--; dff[ix] = 1;
00818             continue;
00819         }
00820 
00821         /* Ignore colored files not in our rainbow. */
00822         FColor = rpmfiFColor(fi);
00823         if (tscolor && FColor && !(tscolor & FColor)) {
00824             drc[ix]--;  dff[ix] = 1;
00825             fi->actions[i] = FA_SKIPCOLOR;
00826             continue;
00827         }
00828 
00829         /*
00830          * Skip net shared paths.
00831          * Net shared paths are not relative to the current root (though
00832          * they do need to take package relocations into account).
00833          */
00834         for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
00835             int len;
00836 
00837             len = strlen(*nsp);
00838             if (dnlen >= len) {
00839                 if (strncmp(dn, *nsp, len))
00840                     /*@innercontinue@*/ continue;
00841                 /* Only directories or complete file paths can be net shared */
00842                 if (!(dn[len] == '/' || dn[len] == '\0'))
00843                     /*@innercontinue@*/ continue;
00844             } else {
00845                 if (len < (dnlen + bnlen))
00846                     /*@innercontinue@*/ continue;
00847                 if (strncmp(dn, *nsp, dnlen))
00848                     /*@innercontinue@*/ continue;
00849                 /* Insure that only the netsharedpath basename is compared. */
00850                 if ((s = strchr((*nsp) + dnlen, '/')) != NULL && s[1] != '\0')
00851                     /*@innercontinue@*/ continue;
00852                 if (strncmp(bn, (*nsp) + dnlen, bnlen))
00853                     /*@innercontinue@*/ continue;
00854                 len = dnlen + bnlen;
00855                 /* Only directories or complete file paths can be net shared */
00856                 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
00857                     /*@innercontinue@*/ continue;
00858             }
00859 
00860             /*@innerbreak@*/ break;
00861         }
00862 
00863         if (nsp && *nsp) {
00864             drc[ix]--;  dff[ix] = 1;
00865             fi->actions[i] = FA_SKIPNETSHARED;
00866             continue;
00867         }
00868 
00869         /*
00870          * Skip i18n language specific files.
00871          */
00872         if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
00873             const char **lang, *l, *le;
00874             for (lang = languages; *lang != NULL; lang++) {
00875                 if (!strcmp(*lang, "all"))
00876                     /*@innerbreak@*/ break;
00877                 for (l = fi->flangs[i]; *l != '\0'; l = le) {
00878                     for (le = l; *le != '\0' && *le != '|'; le++)
00879                         {};
00880                     if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
00881                         /*@innerbreak@*/ break;
00882                     if (*le == '|') le++;       /* skip over | */
00883                 }
00884                 if (*l != '\0')
00885                     /*@innerbreak@*/ break;
00886             }
00887             if (*lang == NULL) {
00888                 drc[ix]--;      dff[ix] = 1;
00889                 fi->actions[i] = FA_SKIPNSTATE;
00890                 continue;
00891             }
00892         }
00893 
00894         /*
00895          * Skip config files if requested.
00896          */
00897         if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
00898             drc[ix]--;  dff[ix] = 1;
00899             fi->actions[i] = FA_SKIPNSTATE;
00900             continue;
00901         }
00902 
00903         /*
00904          * Skip documentation if requested.
00905          */
00906         if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
00907             drc[ix]--;  dff[ix] = 1;
00908             fi->actions[i] = FA_SKIPNSTATE;
00909             continue;
00910         }
00911     }
00912 
00913     /* Skip (now empty) directories that had skipped files. */
00914 #ifndef NOTYET
00915     if (fi != NULL)     /* XXX can't happen */
00916     for (j = 0; j < dc; j++)
00917 #else
00918     if ((fi = rpmfiInitD(fi)) != NULL)
00919     while (j = rpmfiNextD(fi) >= 0)
00920 #endif
00921     {
00922 
00923         if (drc[j]) continue;   /* dir still has files. */
00924         if (!dff[j]) continue;  /* dir was not emptied here. */
00925         
00926         /* Find parent directory and basename. */
00927         dn = fi->dnl[j];        dnlen = strlen(dn) - 1;
00928         bn = dn + dnlen;        bnlen = 0;
00929         while (bn > dn && bn[-1] != '/') {
00930                 bnlen++;
00931                 dnlen--;
00932                 bn--;
00933         }
00934 
00935         /* If explicitly included in the package, skip the directory. */
00936         fi = rpmfiInit(fi, 0);
00937         if (fi != NULL)         /* XXX lclint */
00938         while ((i = rpmfiNext(fi)) >= 0) {
00939             const char * fdn, * fbn;
00940             int_16 fFMode;
00941 
00942             if (XFA_SKIPPING(fi->actions[i]))
00943                 /*@innercontinue@*/ continue;
00944 
00945             fFMode = rpmfiFMode(fi);
00946 
00947             if (whatis(fFMode) != XDIR)
00948                 /*@innercontinue@*/ continue;
00949             fdn = rpmfiDN(fi);
00950             if (strlen(fdn) != dnlen)
00951                 /*@innercontinue@*/ continue;
00952             if (strncmp(fdn, dn, dnlen))
00953                 /*@innercontinue@*/ continue;
00954             fbn = rpmfiBN(fi);
00955             if (strlen(fbn) != bnlen)
00956                 /*@innercontinue@*/ continue;
00957             if (strncmp(fbn, bn, bnlen))
00958                 /*@innercontinue@*/ continue;
00959             rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"), dn);
00960             fi->actions[i] = FA_SKIPNSTATE;
00961             /*@innerbreak@*/ break;
00962         }
00963     }
00964 
00965 /*@-dependenttrans@*/
00966     if (netsharedPaths) freeSplitString(netsharedPaths);
00967 #ifdef  DYING   /* XXX freeFi will deal with this later. */
00968     fi->flangs = _free(fi->flangs);
00969 #endif
00970     if (languages) freeSplitString((char **)languages);
00971 /*@=dependenttrans@*/
00972 }
00973 /*@=bounds@*/
00974 /*@=mustmod@*/
00975 
00982 static /*@null@*/
00983 rpmfi rpmtsiFi(const rpmtsi tsi)
00984         /*@*/
00985 {
00986     rpmfi fi = NULL;
00987 
00988     if (tsi != NULL && tsi->ocsave != -1) {
00989         /*@-type -abstract@*/ /* FIX: rpmte not opaque */
00990         rpmte te = rpmtsElement(tsi->ts, tsi->ocsave);
00991         /*@-assignexpose@*/
00992         if (te != NULL && (fi = te->fi) != NULL)
00993             fi->te = te;
00994         /*@=assignexpose@*/
00995         /*@=type =abstract@*/
00996     }
00997     /*@-compdef -refcounttrans -usereleased @*/
00998     return fi;
00999     /*@=compdef =refcounttrans =usereleased @*/
01000 }
01001 
01009 static rpmRC _rpmtsRollback(rpmts rollbackTransaction)
01010         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
01011         /*@modifies rollbackTransaction,
01012                 rpmGlobalMacroContext, fileSystem, internalState @*/
01013 {
01014     int    rc         = 0;
01015     int    numAdded   = 0;
01016     int    numRemoved = 0;
01017     int_32 tid;
01018     rpmtsi tsi;
01019     rpmte  te;
01020     rpmps  ps;
01021 
01022     /*
01023      * Gather information about this rollback transaction for reporting.
01024      *    1) Get tid
01025      */
01026     tid = rpmtsGetTid(rollbackTransaction);
01027 
01028     /*
01029      *    2) Get number of install elments and erase elements
01030      */
01031     tsi = rpmtsiInit(rollbackTransaction);
01032     while((te = rpmtsiNext(tsi, 0)) != NULL) {
01033         switch (rpmteType(te)) {
01034         case TR_ADDED:
01035            numAdded++;
01036            /*@switchbreak@*/ break;
01037         case TR_REMOVED:
01038            numRemoved++;
01039            /*@switchbreak@*/ break;
01040         default:
01041            /*@switchbreak@*/ break;
01042         }       
01043     }
01044     tsi = rpmtsiFree(tsi);
01045 
01046     rpmMessage(RPMMESS_NORMAL, _("Transaction failed...rolling back\n"));
01047     rpmMessage(RPMMESS_NORMAL,
01048         _("Rollback packages (+%d/-%d) to %-24.24s (0x%08x):\n"),
01049                         numAdded, numRemoved, ctime(&tid), tid);
01050 
01051     /* Check the transaction to see if it is doable */
01052     rc = rpmtsCheck(rollbackTransaction);
01053     ps = rpmtsProblems(rollbackTransaction);
01054     if (rc != 0 && rpmpsNumProblems(ps) > 0) {
01055         rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
01056         rpmpsPrint(NULL, ps);
01057         ps = rpmpsFree(ps);
01058         return -1;
01059     }
01060     ps = rpmpsFree(ps);
01061 
01062     /* Order the transaction */
01063     rc = rpmtsOrder(rollbackTransaction);
01064     if (rc != 0) {
01065         rpmMessage(RPMMESS_ERROR,
01066             _("Could not order auto-rollback transaction!\n"));
01067        return -1;
01068     }
01069 
01070 
01071 
01072     /* Run the transaction and print any problems
01073      * We want to stay with the original transactions flags except
01074      * that we want to add what is essentially a force.
01075      * This handles two things in particular:
01076      *  
01077      *  1.  We we want to upgrade over a newer package.
01078      *  2.  If a header for the old package is there we
01079      *      we want to replace it.  No questions asked.
01080      */
01081     rc = rpmtsRun(rollbackTransaction, NULL,
01082           RPMPROB_FILTER_REPLACEPKG
01083         | RPMPROB_FILTER_REPLACEOLDFILES
01084         | RPMPROB_FILTER_REPLACENEWFILES
01085         | RPMPROB_FILTER_OLDPACKAGE
01086     );
01087     ps = rpmtsProblems(rollbackTransaction);
01088     if (rc > 0 && rpmpsNumProblems(ps) > 0)
01089         rpmpsPrint(stderr, ps);
01090     ps = rpmpsFree(ps);
01091 
01092     /*
01093      * After we have ran through the transaction we need to
01094      * remove any repackaged packages we just installed/upgraded
01095      * from the rp repository.
01096      */
01097     tsi = rpmtsiInit(rollbackTransaction);
01098     while((te = rpmtsiNext(tsi, 0)) != NULL) {
01099         rpmMessage(RPMMESS_NORMAL, _("Cleaning up repackaged packages:\n"));
01100         switch (rpmteType(te)) {
01101         /* The install elements are repackaged packages */
01102         case TR_ADDED:
01103             /* Make sure the filename is still there.  XXX: Can't happen */
01104             if(te->key) {
01105                 rpmMessage(RPMMESS_NORMAL, _("\tRemoving %s:\n"), te->key);
01106                 (void) unlink(te->key); /* XXX: Should check for an error? */
01107             }
01108             /*@switchbreak@*/ break;
01109                                                                                 
01110         /* Ignore erase elements...nothing to do */
01111         default:
01112             /*@switchbreak@*/ break;
01113         }
01114     }
01115     tsi = rpmtsiFree(tsi);
01116 
01117     /* Free the rollback transaction */
01118     rollbackTransaction = rpmtsFree(rollbackTransaction);
01119 
01120     return rc;
01121 }
01122 
01134 static rpmRC getRepackageHeaderFromTE(rpmts ts, rpmte te,
01135                 /*@out@*/ /*@null@*/ Header *hdrp,
01136                 /*@out@*/ /*@null@*/ const char **fnp)
01137         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
01138         /*@modifies ts, *hdrp, *fnp,
01139                 rpmGlobalMacroContext, fileSystem, internalState @*/
01140 {
01141     int_32 tid;
01142     const char * name;
01143     const char * rpname = NULL;
01144     const char * _repackage_dir = NULL;
01145     const char * globStr = "-*.rpm";
01146     char * rp = NULL;           /* Rollback package name */
01147     IDTX rtids = NULL;
01148     IDT rpIDT;
01149     int nrids = 0;
01150     int nb;                     /* Number of bytes */
01151     Header h = NULL;
01152     int rc   = RPMRC_NOTFOUND;  /* Assume we do not find it*/
01153     int xx;
01154 
01155     rpmMessage(RPMMESS_DEBUG,
01156         _("Getting repackaged header from transaction element\n"));
01157 
01158     /* Set header pointer to null if its not already */
01159     if (hdrp)
01160         *hdrp = NULL;
01161     if (fnp)
01162         *fnp = NULL;
01163 
01164     /* Get the TID of the current transaction */
01165     tid = rpmtsGetTid(ts);
01166     /* Need the repackage dir if the user want to
01167      * rollback on a failure.
01168      */
01169     _repackage_dir = rpmExpand("%{?_repackage_dir}", NULL);
01170     if (_repackage_dir == NULL) goto exit;
01171 
01172     /* Build the glob string to find the possible repackaged
01173      * packages for this package.
01174      */
01175     name = rpmteN(te);  
01176     nb = strlen(_repackage_dir) + strlen(name) + strlen(globStr) + 2;
01177     rp = memset((char *) malloc(nb), 0, nb);
01178     xx = snprintf(rp, nb, "%s/%s%s.rpm", _repackage_dir, name, globStr);
01179 
01180     /* Get the index of possible repackaged packages */
01181     rpmMessage(RPMMESS_DEBUG, _("\tLooking for %s...\n"), rp);
01182     rtids = IDTXglob(ts, rp, RPMTAG_REMOVETID);
01183     rp = _free(rp);
01184     if (rtids != NULL) {
01185         rpmMessage(RPMMESS_DEBUG, _("\tMatches found.\n"));
01186         rpIDT = rtids->idt;
01187         nrids = rtids->nidt;
01188     } else {
01189         rpmMessage(RPMMESS_DEBUG, _("\tNo matches found.\n"));
01190         goto exit;
01191     }
01192 
01193     /* Now walk through index until we find the package (or we have
01194      * exhausted the index.
01195      */
01196 /*@-branchstate@*/
01197     do {
01198         /* If index is null we have exhausted the list and need to
01199          * get out of here...the repackaged package was not found.
01200          */
01201         if (rpIDT == NULL) {
01202             rpmMessage(RPMMESS_DEBUG, _("\tRepackaged package not found!.\n"));
01203             break;
01204         }
01205 
01206         /* Is this the same tid.  If not decrement the list and continue */
01207         if (rpIDT->val.u32 != tid) {
01208             nrids--;
01209             if (nrids > 0)
01210                 rpIDT++;
01211             else
01212                 rpIDT = NULL;
01213             continue;
01214         }
01215 
01216         /* OK, the tid matches.  Now lets see if the name is the same.
01217          * If I could not get the name from the package, I will go onto
01218          * the next one.  Perhaps I should return an error at this
01219          * point, but if this was not the correct one, at least the correct one
01220          * would be found.
01221          * XXX:  Should Match NAC!
01222          */
01223         rpmMessage(RPMMESS_DEBUG, _("\tREMOVETID matched INSTALLTID.\n"));
01224         if (headerGetEntry(rpIDT->h, RPMTAG_NAME, NULL, (void **) &rpname, NULL)) {
01225             rpmMessage(RPMMESS_DEBUG, _("\t\tName:  %s.\n"), rpname);
01226             if (!strcmp(name,rpname)) {
01227                 /* It matched we have a canidate */
01228                 h  = headerLink(rpIDT->h);
01229                 nb = strlen(rpIDT->key) + 1;
01230                 rp = memset((char *) malloc(nb), 0, nb);
01231                 rp = strncat(rp, rpIDT->key, nb);
01232                 rc = RPMRC_OK;
01233                 break;
01234             }
01235         }
01236 
01237         /* Decrement list */    
01238         nrids--;
01239         if (nrids > 0)
01240             rpIDT++;
01241         else
01242             rpIDT = NULL;
01243     } while (1);
01244 /*@=branchstate@*/
01245 
01246 exit:
01247     if (rc != RPMRC_NOTFOUND && h != NULL && hdrp != NULL) {
01248         rpmMessage(RPMMESS_DEBUG, _("\tRepackaged Package was %s...\n"), rp);
01249         if (hdrp != NULL)
01250             *hdrp = headerLink(h);
01251 /*@-branchstate@*/
01252         if (fnp != NULL)
01253             *fnp = rp;
01254         else
01255             rp = _free(rp);
01256 /*@=branchstate@*/
01257     }
01258     if (h != NULL)
01259         h = headerFree(h);
01260     rtids = IDTXfree(rtids);
01261     return rc;  
01262 }
01263 
01273 static rpmRC _rpmtsAddRollbackElement(rpmts rollbackTransaction,
01274                 rpmts runningTransaction, rpmte te)
01275         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
01276         /*@modifies rollbackTransaction, runningTransaction,
01277                 rpmGlobalMacroContext, fileSystem, internalState @*/
01278 {
01279     Header h   = NULL;
01280     Header rph = NULL;
01281     char * rpn; 
01282     unsigned int db_instance = 0;
01283     rpmtsi pi;          
01284     rpmte p;
01285     int rc  = RPMRC_FAIL;       /* Assume Failure */
01286 
01287     switch(rpmteType(te)) {
01288     case TR_ADDED:
01289     {   rpmdbMatchIterator mi;
01290 
01291         rpmMessage(RPMMESS_DEBUG,
01292             _("Adding install element to auto-rollback transaction.\n"));
01293 
01294         /* Get the header for this package from the database
01295          * First get the database instance (the key).
01296          */
01297         db_instance = rpmteDBInstance(te);
01298         if (db_instance == 0) {
01299             /* Could not get the db instance: WTD! */
01300             rpmMessage(RPMMESS_FATALERROR,
01301                 _("Could not get install element database instance!\n"));
01302             break;
01303         }
01304 
01305         /* Now suck the header out of the database */
01306         mi = rpmtsInitIterator(rollbackTransaction,
01307             RPMDBI_PACKAGES, &db_instance, sizeof(db_instance));
01308         h = rpmdbNextIterator(mi);
01309         if (h != NULL) h = headerLink(h);
01310         mi = rpmdbFreeIterator(mi);
01311         if (h == NULL) {
01312             /* Header was not there??? */
01313             rpmMessage(RPMMESS_FATALERROR,
01314                 _("Could not get header for auto-rollback transaction!\n"));
01315             break;
01316         }
01317 
01318         /* Now see if there is a repackaged package for this */
01319         rc = getRepackageHeaderFromTE(runningTransaction, te, &rph, &rpn);
01320         switch(rc) {
01321         case RPMRC_OK:
01322             /* Add the install element, as we had a repackaged package */
01323             rpmMessage(RPMMESS_DEBUG,
01324                 _("\tAdded repackaged package header: %s.\n"), rpn);
01325             rpmMessage(RPMMESS_DEBUG,
01326                 _("\tAdded from install element %s.\n"), rpmteNEVRA(te));
01327             rc = rpmtsAddInstallElement(rollbackTransaction, headerLink(rph),
01328                 (fnpyKey) rpn, 1, te->relocs);
01329             /*@innerbreak@*/ break;
01330 
01331         case RPMRC_NOTFOUND:
01332             /* Add the header as an erase element, we did not
01333              * have a repackaged package
01334              */
01335             rpmMessage(RPMMESS_DEBUG, _("\tAdded erase element.\n"));
01336             rpmMessage(RPMMESS_DEBUG,
01337                 _("\tAdded from install element %s.\n"), rpmteNEVRA(te));
01338             rc = rpmtsAddEraseElement(rollbackTransaction, h, db_instance);
01339             /*@innerbreak@*/ break;
01340                         
01341         default:
01342             /* Not sure what to do on failure...just give up */
01343             rpmMessage(RPMMESS_FATALERROR,
01344                 _("Could not get repackaged header for auto-rollback transaction!\n"));
01345             /*@innerbreak@*/ break;
01346         }
01347     }   break;
01348 
01349    case TR_REMOVED:
01350         rpmMessage(RPMMESS_DEBUG,
01351             _("Add erase element to auto-rollback transaction.\n"));
01352         /* See if this element has already been added.
01353          * If so we want to do nothing.  Compare N's for match.
01354          * XXX:  Really should compare NAC's.
01355          */
01356         pi = rpmtsiInit(rollbackTransaction);
01357         while ((p = rpmtsiNext(pi, 0)) != NULL) {
01358             if (!strcmp(rpmteN(p), rpmteN(te))) {
01359                 rpmMessage(RPMMESS_DEBUG, _("\tFound existing upgrade element.\n"));
01360                 rpmMessage(RPMMESS_DEBUG, _("\tNot adding erase element for %s.\n"),
01361                         rpmteN(te));
01362                 rc = RPMRC_OK;  
01363                 pi = rpmtsiFree(pi);
01364                 goto cleanup;
01365             }
01366         }
01367         pi = rpmtsiFree(pi);
01368 
01369         /* Get the repackage header from the current transaction
01370         * element.
01371         */
01372         rc = getRepackageHeaderFromTE(runningTransaction, te, &rph, &rpn);
01373         switch(rc) {
01374         case RPMRC_OK:
01375             /* Add the install element */
01376             rpmMessage(RPMMESS_DEBUG,
01377                 _("\tAdded repackaged package %s.\n"), rpn);
01378             rpmMessage(RPMMESS_DEBUG,
01379                 _("\tAdded from erase element %s.\n"), rpmteNEVRA(te));
01380             rc = rpmtsAddInstallElement(rollbackTransaction, rph,
01381                 (fnpyKey) rpn, 1, te->relocs);
01382             if (rc != RPMRC_OK)
01383                 rpmMessage(RPMMESS_FATALERROR,
01384                     _("Could not add erase element to auto-rollback transaction.\n"));
01385             /*@innerbreak@*/ break;
01386 
01387         case RPMRC_NOTFOUND:
01388             /* Just did not have a repackaged package */
01389             rpmMessage(RPMMESS_DEBUG,
01390                 _("\tNo repackaged package...nothing to do.\n"));
01391             rc = RPMRC_OK;
01392             /*@innerbreak@*/ break;
01393 
01394         default:
01395             rpmMessage(RPMMESS_FATALERROR,
01396                 _("Failure reading repackaged package!\n"));
01397             /*@innerbreak@*/ break;
01398         }
01399         break;
01400 
01401     default:
01402         break;
01403     }
01404 
01405 /* XXX:  I want to free this, but if I do then the consumers of
01406  *       are hosed.  Just leaving you a little note Jeff, so you
01407  *       know that this does introduce a memory leak.  I wanted
01408  *       keep the patch as simple as possible so I am not fixxing
01409  *       the leak.
01410  *   if (rpn != NULL)
01411  *      free(rpn);
01412  */
01413 
01414 cleanup:
01415     /* Clean up */
01416     if (h != NULL)
01417         h = headerFree(h);
01418     if (rph != NULL)
01419         rph = headerFree(rph);
01420     return rc;
01421 }
01422 
01423 #define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al
01424 
01425 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
01426 {
01427     uint_32 tscolor = rpmtsColor(ts);
01428     int i, j;
01429     int ourrc = 0;
01430     int totalFileCount = 0;
01431     rpmfi fi;
01432     sharedFileInfo shared, sharedList;
01433     int numShared;
01434     int nexti;
01435     alKey lastFailKey;
01436     fingerPrintCache fpc;
01437     rpmps ps;
01438     rpmpsm psm;
01439     rpmtsi pi;  rpmte p;
01440     rpmtsi qi;  rpmte q;
01441     int numAdded;
01442     int numRemoved;
01443     rpmts rollbackTransaction = NULL;
01444     int rollbackOnFailure = 0;
01445     void * lock = NULL;
01446     int xx;
01447     mode_t oldmask;
01448 
01449     /* XXX programmer error segfault avoidance. */
01450     if (rpmtsNElements(ts) <= 0)
01451         return -1;
01452 
01453     /* Force default 022 umask during transaction for consistent results */
01454     oldmask = umask(022);
01455 
01456     /* See if we need to rollback on failure */
01457     rollbackOnFailure = rpmExpandNumeric(
01458         "%{?_rollback_transaction_on_failure}");
01459     if (rpmtsGetType(ts) & (RPMTRANS_TYPE_ROLLBACK
01460         | RPMTRANS_TYPE_AUTOROLLBACK)) {
01461         rollbackOnFailure = 0;
01462     }
01463     /* If we are in test mode, there is no need to rollback on
01464      * failure, nor acquire the transaction lock.
01465      */
01466 /*@-branchstate@*/
01467     /* If we are in test mode, then there's no need for transaction lock. */
01468     if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) {
01469         rollbackOnFailure = 0;
01470     } else {
01471         lock = rpmtsAcquireLock(ts);
01472         if (lock == NULL) {
01473             umask(oldmask);
01474             return -1;  /* XXX W2DO? */
01475         }
01476     }
01477 /*@=branchstate@*/
01478 
01479     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
01480         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
01481     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
01482         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
01483 
01484     if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
01485         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
01486 
01487     ts->probs = rpmpsFree(ts->probs);
01488     ts->probs = rpmpsCreate();
01489 
01490     /* XXX Make sure the database is open RDWR for package install/erase. */
01491     {   int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
01492                 ? O_RDONLY : (O_RDWR|O_CREAT);
01493 
01494         /* Open database RDWR for installing packages. */
01495         if (rpmtsOpenDB(ts, dbmode)) {
01496             rpmtsFreeLock(lock);
01497             umask(oldmask);
01498             return -1;  /* XXX W2DO? */
01499         }
01500     }
01501 
01502     ts->ignoreSet = ignoreSet;
01503     {   const char * currDir = currentDirectory();
01504         rpmtsSetCurrDir(ts, currDir);
01505         currDir = _free(currDir);
01506     }
01507 
01508     (void) rpmtsSetChrootDone(ts, 0);
01509 
01510     {   int_32 tid = (int_32) time(NULL);
01511         (void) rpmtsSetTid(ts, tid);
01512     }
01513 
01514     /* Get available space on mounted file systems. */
01515     xx = rpmtsInitDSI(ts);
01516 
01517     /* ===============================================
01518      * For packages being installed:
01519      * - verify package arch/os.
01520      * - verify package epoch:version-release is newer.
01521      * - count files.
01522      * For packages being removed:
01523      * - count files.
01524      */
01525 
01526 rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts));
01527     ps = rpmtsProblems(ts);
01528     /* The ordering doesn't matter here */
01529     pi = rpmtsiInit(ts);
01530     /* XXX Only added packages need be checked. */
01531     while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01532         rpmdbMatchIterator mi;
01533         int fc;
01534 
01535         if ((fi = rpmtsiFi(pi)) == NULL)
01536             continue;   /* XXX can't happen */
01537         fc = rpmfiFC(fi);
01538 
01539 /* ia64 emul autorelocation "works" by detecting incompatible arch, eww */
01540 #if !defined(__ia64__)
01541         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH))
01542             if (!archOkay(rpmteA(p)))
01543                 rpmpsAppend(ps, RPMPROB_BADARCH,
01544                         rpmteNEVRA(p), rpmteKey(p),
01545                         rpmteA(p), NULL,
01546                         NULL, 0);
01547 #endif
01548 
01549         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS))
01550             if (!osOkay(rpmteO(p)))
01551                 rpmpsAppend(ps, RPMPROB_BADOS,
01552                         rpmteNEVRA(p), rpmteKey(p),
01553                         rpmteO(p), NULL,
01554                         NULL, 0);
01555 
01556         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) {
01557             Header h;
01558             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01559             while ((h = rpmdbNextIterator(mi)) != NULL)
01560                 xx = ensureOlder(ts, p, h);
01561             mi = rpmdbFreeIterator(mi);
01562         }
01563 
01564         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
01565             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01566             xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
01567                                 rpmteE(p));
01568             xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
01569                                 rpmteV(p));
01570             xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
01571                                 rpmteR(p));
01572             if (tscolor) {
01573                 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
01574                                 rpmteA(p));
01575                 xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP,
01576                                 rpmteO(p));
01577             }
01578 
01579             while (rpmdbNextIterator(mi) != NULL) {
01580                 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
01581                         rpmteNEVRA(p), rpmteKey(p),
01582                         NULL, NULL,
01583                         NULL, 0);
01584                 /*@innerbreak@*/ break;
01585             }
01586             mi = rpmdbFreeIterator(mi);
01587         }
01588 
01589         /* Count no. of files (if any). */
01590         totalFileCount += fc;
01591 
01592     }
01593     pi = rpmtsiFree(pi);
01594     ps = rpmpsFree(ps);
01595 
01596     /* The ordering doesn't matter here */
01597     pi = rpmtsiInit(ts);
01598     while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
01599         int fc;
01600 
01601         if ((fi = rpmtsiFi(pi)) == NULL)
01602             continue;   /* XXX can't happen */
01603         fc = rpmfiFC(fi);
01604 
01605         totalFileCount += fc;
01606     }
01607     pi = rpmtsiFree(pi);
01608 
01609 
01610     /* Run pre-transaction scripts, but only if there are no known
01611      * problems up to this point. */
01612     if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPRE))
01613           || (ts->probs->numProblems &&
01614                 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) {
01615         rpmMessage(RPMMESS_DEBUG, _("running pre-transaction scripts\n"));
01616         pi = rpmtsiInit(ts);
01617         while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01618             if ((fi = rpmtsiFi(pi)) == NULL)
01619                 continue;       /* XXX can't happen */
01620 
01621             /* If no pre-transaction script, then don't bother. */
01622             if (fi->pretrans == NULL)
01623                 continue;
01624 
01625             p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01626                             rpmteKey(p), ts->notifyData);
01627             p->h = NULL;
01628             if (rpmteFd(p) != NULL) {
01629                 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
01630                 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
01631                 rpmRC rpmrc;
01632                 ovsflags = rpmtsSetVSFlags(ts, vsflags);
01633                 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
01634                             rpmteNEVR(p), &p->h);
01635                 vsflags = rpmtsSetVSFlags(ts, ovsflags);
01636                 switch (rpmrc) {
01637                 default:
01638                     /*@-noeffectuncon@*/ /* FIX: notify annotations */
01639                     p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
01640                                     0, 0,
01641                                     rpmteKey(p), ts->notifyData);
01642                     /*@=noeffectuncon@*/
01643                     p->fd = NULL;
01644                     /*@switchbreak@*/ break;
01645                 case RPMRC_NOTTRUSTED:
01646                 case RPMRC_NOKEY:
01647                 case RPMRC_OK:
01648                     /*@switchbreak@*/ break;
01649                 }
01650             }
01651 
01652 /*@-branchstate@*/
01653             if (rpmteFd(p) != NULL) {
01654                 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
01655                 if (fi != NULL) {       /* XXX can't happen */
01656                     fi->te = p;
01657                     p->fi = fi;
01658                 }
01659 /*@-compdef -usereleased@*/     /* p->fi->te undefined */
01660                 psm = rpmpsmNew(ts, p, p->fi);
01661 /*@=compdef =usereleased@*/
01662 assert(psm != NULL);
01663                 psm->scriptTag = RPMTAG_PRETRANS;
01664                 psm->progTag = RPMTAG_PRETRANSPROG;
01665                 xx = rpmpsmStage(psm, PSM_SCRIPT);
01666                 psm = rpmpsmFree(psm);
01667 
01668 /*@-noeffectuncon -compdef -usereleased @*/
01669                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01670                                   rpmteKey(p), ts->notifyData);
01671 /*@=noeffectuncon =compdef =usereleased @*/
01672                 p->fd = NULL;
01673                 p->h = headerFree(p->h);
01674             }
01675 /*@=branchstate@*/
01676         }
01677         pi = rpmtsiFree(pi);
01678     }
01679 
01680     /* ===============================================
01681      * Initialize transaction element file info for package:
01682      */
01683 
01684     /*
01685      * FIXME?: we'd be better off assembling one very large file list and
01686      * calling fpLookupList only once. I'm not sure that the speedup is
01687      * worth the trouble though.
01688      */
01689 rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount);
01690 
01691     numAdded = numRemoved = 0;
01692     pi = rpmtsiInit(ts);
01693     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01694         int fc;
01695 
01696         if ((fi = rpmtsiFi(pi)) == NULL)
01697             continue;   /* XXX can't happen */
01698         fc = rpmfiFC(fi);
01699 
01700         /*@-branchstate@*/
01701         switch (rpmteType(p)) {
01702         case TR_ADDED:
01703             numAdded++;
01704             fi->record = 0;
01705             /* Skip netshared paths, not our i18n files, and excluded docs */
01706             if (fc > 0)
01707                 skipFiles(ts, fi);
01708             /*@switchbreak@*/ break;
01709         case TR_REMOVED:
01710             numRemoved++;
01711             fi->record = rpmteDBOffset(p);
01712             /*@switchbreak@*/ break;
01713         }
01714         /*@=branchstate@*/
01715 
01716         fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
01717     }
01718     pi = rpmtsiFree(pi);
01719 
01720     if (!rpmtsChrootDone(ts)) {
01721         const char * rootDir = rpmtsRootDir(ts);
01722         xx = chdir("/");
01723         /*@-superuser -noeffect @*/
01724         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
01725             /* opening db before chroot not optimal, see rhbz#103852 c#3 */
01726             xx = rpmdbOpenAll(ts->rdb);
01727             xx = chroot(rootDir);
01728         }
01729         /*@=superuser =noeffect @*/
01730         (void) rpmtsSetChrootDone(ts, 1);
01731     }
01732 
01733     ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
01734     fpc = fpCacheCreate(totalFileCount);
01735 
01736     /* ===============================================
01737      * Add fingerprint for each file not skipped.
01738      */
01739     pi = rpmtsiInit(ts);
01740     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01741         int fc;
01742 
01743         (void) rpmdbCheckSignals();
01744 
01745         if ((fi = rpmtsiFi(pi)) == NULL)
01746             continue;   /* XXX can't happen */
01747         fc = rpmfiFC(fi);
01748 
01749         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01750         fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
01751         /*@-branchstate@*/
01752         fi = rpmfiInit(fi, 0);
01753         if (fi != NULL)         /* XXX lclint */
01754         while ((i = rpmfiNext(fi)) >= 0) {
01755             if (XFA_SKIPPING(fi->actions[i]))
01756                 /*@innercontinue@*/ continue;
01757             /*@-dependenttrans@*/
01758             htAddEntry(ts->ht, fi->fps + i, (void *) fi);
01759             /*@=dependenttrans@*/
01760         }
01761         /*@=branchstate@*/
01762         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01763 
01764     }
01765     pi = rpmtsiFree(pi);
01766 
01767     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount,
01768         NULL, ts->notifyData));
01769 
01770     /* ===============================================
01771      * Compute file disposition for each package in transaction set.
01772      */
01773 rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
01774     ps = rpmtsProblems(ts);
01775     pi = rpmtsiInit(ts);
01776     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01777         dbiIndexSet * matches;
01778         int knownBad;
01779         int fc;
01780 
01781         (void) rpmdbCheckSignals();
01782 
01783         if ((fi = rpmtsiFi(pi)) == NULL)
01784             continue;   /* XXX can't happen */
01785         fc = rpmfiFC(fi);
01786 
01787         NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
01788                         ts->orderCount, NULL, ts->notifyData));
01789 
01790         if (fc == 0) continue;
01791 
01792         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01793         /* Extract file info for all files in this package from the database. */
01794         matches = xcalloc(fc, sizeof(*matches));
01795         if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
01796             ps = rpmpsFree(ps);
01797             rpmtsFreeLock(lock);
01798             umask(oldmask);
01799             return 1;   /* XXX WTFO? */
01800         }
01801 
01802         numShared = 0;
01803         fi = rpmfiInit(fi, 0);
01804         while ((i = rpmfiNext(fi)) >= 0)
01805             numShared += dbiIndexSetCount(matches[i]);
01806 
01807         /* Build sorted file info list for this package. */
01808         shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
01809 
01810         fi = rpmfiInit(fi, 0);
01811         while ((i = rpmfiNext(fi)) >= 0) {
01812             /*
01813              * Take care not to mark files as replaced in packages that will
01814              * have been removed before we will get here.
01815              */
01816             for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
01817                 int ro;
01818                 ro = dbiIndexRecordOffset(matches[i], j);
01819                 knownBad = 0;
01820                 qi = rpmtsiInit(ts);
01821                 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
01822                     if (ro == knownBad)
01823                         /*@innerbreak@*/ break;
01824                     if (rpmteDBOffset(q) == ro)
01825                         knownBad = ro;
01826                 }
01827                 qi = rpmtsiFree(qi);
01828 
01829                 shared->pkgFileNum = i;
01830                 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
01831                 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
01832                 shared->isRemoved = (knownBad == ro);
01833                 shared++;
01834             }
01835             matches[i] = dbiFreeIndexSet(matches[i]);
01836         }
01837         numShared = shared - sharedList;
01838         shared->otherPkg = -1;
01839         matches = _free(matches);
01840 
01841         /* Sort file info by other package index (otherPkg) */
01842         qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
01843 
01844         /* For all files from this package that are in the database ... */
01845         /*@-branchstate@*/
01846         for (i = 0; i < numShared; i = nexti) {
01847             int beingRemoved;
01848 
01849             shared = sharedList + i;
01850 
01851             /* Find the end of the files in the other package. */
01852             for (nexti = i + 1; nexti < numShared; nexti++) {
01853                 if (sharedList[nexti].otherPkg != shared->otherPkg)
01854                     /*@innerbreak@*/ break;
01855             }
01856 
01857             /* Is this file from a package being removed? */
01858             beingRemoved = 0;
01859             if (ts->removedPackages != NULL)
01860             for (j = 0; j < ts->numRemovedPackages; j++) {
01861                 if (ts->removedPackages[j] != shared->otherPkg)
01862                     /*@innercontinue@*/ continue;
01863                 beingRemoved = 1;
01864                 /*@innerbreak@*/ break;
01865             }
01866 
01867             /* Determine the fate of each file. */
01868             switch (rpmteType(p)) {
01869             case TR_ADDED:
01870                 xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
01871         !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
01872                 /*@switchbreak@*/ break;
01873             case TR_REMOVED:
01874                 if (!beingRemoved)
01875                     xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
01876                 /*@switchbreak@*/ break;
01877             }
01878         }
01879         /*@=branchstate@*/
01880 
01881         free(sharedList);
01882 
01883         /* Update disk space needs on each partition for this package. */
01884         handleOverlappedFiles(ts, p, fi);
01885 
01886         /* Check added package has sufficient space on each partition used. */
01887         switch (rpmteType(p)) {
01888         case TR_ADDED:
01889             rpmtsCheckDSIProblems(ts, p);
01890             /*@switchbreak@*/ break;
01891         case TR_REMOVED:
01892             /*@switchbreak@*/ break;
01893         }
01894         /* check for s-bit files to be removed */
01895         if (rpmteType(p) == TR_REMOVED) {
01896             fi = rpmfiInit(fi, 0);
01897             while ((i = rpmfiNext(fi)) >= 0) {
01898                 int_16 mode;
01899                 if (XFA_SKIPPING(fi->actions[i]))
01900                     continue;
01901                 (void) rpmfiSetFX(fi, i);
01902                 mode = rpmfiFMode(fi);
01903                 if (S_ISREG(mode) && (mode & 06000) != 0) {
01904                     fi->mapflags |= CPIO_SBIT_CHECK;
01905                 }
01906             }
01907         }
01908         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01909     }
01910     pi = rpmtsiFree(pi);
01911     ps = rpmpsFree(ps);
01912 
01913     if (rpmtsChrootDone(ts)) {
01914         const char * rootDir = rpmtsRootDir(ts);
01915         const char * currDir = rpmtsCurrDir(ts);
01916         /*@-superuser -noeffect @*/
01917         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
01918             xx = chroot(".");
01919         /*@=superuser =noeffect @*/
01920         (void) rpmtsSetChrootDone(ts, 0);
01921         if (currDir != NULL)
01922             xx = chdir(currDir);
01923     }
01924 
01925     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount,
01926         NULL, ts->notifyData));
01927 
01928     /* ===============================================
01929      * Free unused memory as soon as possible.
01930      */
01931     pi = rpmtsiInit(ts);
01932     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01933         if ((fi = rpmtsiFi(pi)) == NULL)
01934             continue;   /* XXX can't happen */
01935         if (rpmfiFC(fi) == 0)
01936             continue;
01937         fi->fps = _free(fi->fps);
01938     }
01939     pi = rpmtsiFree(pi);
01940 
01941     fpc = fpCacheFree(fpc);
01942     ts->ht = htFree(ts->ht);
01943 
01944     /* ===============================================
01945      * If unfiltered problems exist, free memory and return.
01946      */
01947     if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
01948      || (ts->probs->numProblems &&
01949                 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
01950        )
01951     {
01952         rpmtsFreeLock(lock);
01953         umask(oldmask);
01954         return ts->orderCount;
01955     }
01956 
01957     /* ===============================================
01958      * If we were requested to rollback this transaction
01959      * if an error occurs, then we need to create a
01960      * a rollback transaction.
01961      */
01962      if (rollbackOnFailure) {
01963         rpmtransFlags tsFlags;
01964         rpmVSFlags ovsflags;
01965         rpmVSFlags vsflags;
01966 
01967         rpmMessage(RPMMESS_DEBUG,
01968             _("Creating auto-rollback transaction\n"));
01969 
01970         rollbackTransaction = rpmtsCreate();
01971 
01972         /* Set the verify signature flags:
01973          *      - can't verify digests on repackaged packages.  Other than
01974          *        they are wrong, this will cause segfaults down stream.
01975          *      - signatures are out too.
01976          *      - header check are out.
01977          */     
01978         vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
01979         vsflags |= _RPMVSF_NODIGESTS;
01980         vsflags |= _RPMVSF_NOSIGNATURES;
01981         vsflags |= RPMVSF_NOHDRCHK;
01982         vsflags |= RPMVSF_NEEDPAYLOAD;      /* XXX no legacy signatures */
01983         ovsflags = rpmtsSetVSFlags(ts, vsflags);
01984 
01985         /*
01986          *  If we run this thing its imperitive that it be known that it
01987          *  is an autorollback transaction.  This will affect the instance
01988          *  counts passed to the scriptlets in the psm.
01989          */
01990         rpmtsSetType(rollbackTransaction, RPMTRANS_TYPE_AUTOROLLBACK);
01991 
01992         /* Set transaction flags to be the same as the running transaction */
01993         tsFlags = rpmtsSetFlags(rollbackTransaction, rpmtsFlags(ts));
01994 
01995         /* Set root dir to be the same as the running transaction */
01996         rpmtsSetRootDir(rollbackTransaction, rpmtsRootDir(ts));
01997 
01998         /* Setup the notify of the call back to be the same as the running
01999          * transaction
02000          */
02001         xx = rpmtsSetNotifyCallback(rollbackTransaction, ts->notify, ts->notifyData);
02002 
02003         /* Create rpmtsScore for running transaction and rollback transaction */
02004         xx = rpmtsScoreInit(ts, rollbackTransaction);
02005      }
02006 
02007     /* ===============================================
02008      * Save removed files before erasing.
02009      */
02010     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
02011         int progress;
02012 
02013         progress = 0;
02014         pi = rpmtsiInit(ts);
02015         while ((p = rpmtsiNext(pi, 0)) != NULL) {
02016 
02017             if ((fi = rpmtsiFi(pi)) == NULL)
02018                 continue;       /* XXX can't happen */
02019             switch (rpmteType(p)) {
02020             case TR_ADDED:
02021                 /*@switchbreak@*/ break;
02022             case TR_REMOVED:
02023                 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
02024                     /*@switchbreak@*/ break;
02025                 if (!progress)
02026                     NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START,
02027                                 7, numRemoved, NULL, ts->notifyData));
02028 
02029                 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
02030                         numRemoved, NULL, ts->notifyData));
02031                 progress++;
02032 
02033                 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
02034 
02035         /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
02036                 fi->mapflags |= CPIO_MAP_ABSOLUTE;
02037                 fi->mapflags |= CPIO_MAP_ADDDOT;
02038                 fi->mapflags |= CPIO_ALL_HARDLINKS;
02039                 psm = rpmpsmNew(ts, p, fi);
02040 assert(psm != NULL);
02041                 xx = rpmpsmStage(psm, PSM_PKGSAVE);
02042                 psm = rpmpsmFree(psm);
02043                 fi->mapflags &= ~CPIO_MAP_ABSOLUTE;
02044                 fi->mapflags &= ~CPIO_MAP_ADDDOT;
02045                 fi->mapflags &= ~CPIO_ALL_HARDLINKS;
02046 
02047                 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
02048 
02049                 /*@switchbreak@*/ break;
02050             }
02051         }
02052         pi = rpmtsiFree(pi);
02053         if (progress) {
02054             NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved,
02055                         NULL, ts->notifyData));
02056         }
02057     }
02058 
02059     /* ===============================================
02060      * Install and remove packages.
02061      */
02062     lastFailKey = (alKey)-2;    /* erased packages have -1 */
02063     pi = rpmtsiInit(ts);
02064     /*@-branchstate@*/ /* FIX: fi reload needs work */
02065     while ((p = rpmtsiNext(pi, 0)) != NULL) {
02066         alKey pkgKey;
02067         int gotfd;
02068 
02069         gotfd = 0;
02070         if ((fi = rpmtsiFi(pi)) == NULL)
02071             continue;   /* XXX can't happen */
02072         
02073         psm = rpmpsmNew(ts, p, fi);
02074 assert(psm != NULL);
02075         psm->unorderedSuccessor =
02076                 (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
02077 
02078         switch (rpmteType(p)) {
02079         case TR_ADDED:
02080             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
02081 
02082             pkgKey = rpmteAddedKey(p);
02083 
02084             rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s-%s 0x%x\n",
02085                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02086 
02087             p->h = NULL;
02088             /*@-type@*/ /* FIX: rpmte not opaque */
02089             {
02090                 /*@-noeffectuncon@*/ /* FIX: notify annotations */
02091                 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
02092                                 rpmteKey(p), ts->notifyData);
02093                 /*@=noeffectuncon@*/
02094                 if (rpmteFd(p) != NULL) {
02095                     rpmVSFlags ovsflags = rpmtsVSFlags(ts);
02096                     rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
02097                     rpmRC rpmrc;
02098 
02099                     ovsflags = rpmtsSetVSFlags(ts, vsflags);
02100                     rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
02101                                 rpmteNEVR(p), &p->h);
02102                     vsflags = rpmtsSetVSFlags(ts, ovsflags);
02103 
02104                     switch (rpmrc) {
02105                     default:
02106                         /*@-noeffectuncon@*/ /* FIX: notify annotations */
02107                         p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
02108                                         0, 0,
02109                                         rpmteKey(p), ts->notifyData);
02110                         /*@=noeffectuncon@*/
02111                         p->fd = NULL;
02112                         ourrc++;
02113 
02114                         /* If we should rollback this transaction
02115                            on failure, lets do it.                 */
02116                         if (rollbackOnFailure) {
02117                             rpmMessage(RPMMESS_ERROR,
02118                                 _("Add failed.  Could not read package header.\n"));
02119                             /* Clean up the current transaction */
02120                             p->h = headerFree(p->h);
02121                             xx = rpmdbSync(rpmtsGetRdb(ts));
02122                             psm = rpmpsmFree(psm);
02123                             p->fi = rpmfiFree(p->fi);
02124                             pi = rpmtsiFree(pi);
02125 
02126                             /* Run the rollback transaction */
02127                             xx = _rpmtsRollback(rollbackTransaction);
02128                             umask(oldmask);
02129                             return -1;
02130                         }
02131                         /*@innerbreak@*/ break;
02132                     case RPMRC_NOTTRUSTED:
02133                     case RPMRC_NOKEY:
02134                     case RPMRC_OK:
02135                         /*@innerbreak@*/ break;
02136                     }
02137                     if (rpmteFd(p) != NULL) gotfd = 1;
02138                 }
02139             }
02140             /*@=type@*/
02141 
02142             if (rpmteFd(p) != NULL) {
02143                 /*
02144                  * XXX Sludge necessary to tranfer existing fstates/actions
02145                  * XXX around a recreated file info set.
02146                  */
02147                 psm->fi = rpmfiFree(psm->fi);
02148                 {
02149                     char * fstates = fi->fstates;
02150                     fileAction * actions = fi->actions;
02151                     sharedFileInfo replaced = fi->replaced;
02152                     int mapflags = fi->mapflags;
02153                     rpmte savep;
02154                     int numShared = 0;
02155 
02156                     if (replaced != NULL) {
02157                         for (replaced; replaced->otherPkg; replaced++) {
02158                             numShared++;
02159                         }
02160                         if (numShared > 0) {
02161                             replaced = xcalloc(numShared + 1, 
02162                                                sizeof(*fi->replaced));
02163                             memcpy(replaced, fi->replaced, 
02164                                    sizeof(*fi->replaced) * (numShared + 1));
02165                         }
02166                     }
02167 
02168                     fi->fstates = NULL;
02169                     fi->actions = NULL;
02170                     fi->replaced = NULL;
02171 /*@-nullstate@*/ /* FIX: fi->actions is NULL */
02172                     fi = rpmfiFree(fi);
02173 /*@=nullstate@*/
02174 
02175                     savep = rpmtsSetRelocateElement(ts, p);
02176                     fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
02177                     (void) rpmtsSetRelocateElement(ts, savep);
02178 
02179                     if (fi != NULL) {   /* XXX can't happen */
02180                         fi->te = p;
02181                         fi->fstates = _free(fi->fstates);
02182                         fi->fstates = fstates;
02183                         fi->actions = _free(fi->actions);
02184                         fi->actions = actions;
02185                         if (replaced != NULL)
02186                             fi->replaced = replaced;
02187                         if (mapflags & CPIO_SBIT_CHECK)
02188                             fi->mapflags |= CPIO_SBIT_CHECK;
02189                         p->fi = fi;
02190                     }
02191                 }
02192                 psm->fi = rpmfiLink(p->fi, NULL);
02193 
02194 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
02195                 if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
02196                     ourrc++;
02197                     lastFailKey = pkgKey;
02198 
02199                     /* If we should rollback this transaction
02200                        on failure, lets do it.                 */
02201                     if (rollbackOnFailure) {
02202                         rpmMessage(RPMMESS_ERROR,
02203                             _("Add failed in rpmpsmStage().\n"));
02204                         /* Clean up the current transaction */
02205                         p->h = headerFree(p->h);
02206                         xx = rpmdbSync(rpmtsGetRdb(ts));
02207                         psm = rpmpsmFree(psm);
02208                         p->fi = rpmfiFree(p->fi);
02209                         pi = rpmtsiFree(pi);
02210 
02211                         /* Run the rollback transaction */
02212                         xx = _rpmtsRollback(rollbackTransaction);
02213                         umask(oldmask);
02214                         return -1;
02215                     }
02216                 }
02217                 
02218                 /* If we should rollback on failure lets add
02219                  * this element to the rollback transaction
02220                  * as an erase element as it has installed succesfully.
02221                  */
02222                 if (rollbackOnFailure) {
02223                     int rc;
02224 
02225                     rc = _rpmtsAddRollbackElement(rollbackTransaction, ts, p);
02226                     if (rc != RPMRC_OK) {
02227                         /* Clean up the current transaction */
02228                         p->h = headerFree(p->h);
02229                         xx = rpmdbSync(rpmtsGetRdb(ts));
02230                         psm = rpmpsmFree(psm);
02231                         p->fi = rpmfiFree(p->fi);
02232                         pi = rpmtsiFree(pi);
02233                         
02234                         /* Clean up rollback transaction */
02235                         rollbackTransaction = rpmtsFree(rollbackTransaction);
02236                         umask(oldmask);
02237                         return -1;
02238                     }
02239                 }
02240 /*@=nullstate@*/
02241             } else {
02242                 ourrc++;
02243                 lastFailKey = pkgKey;
02244                 
02245                 /* If we should rollback this transaction
02246                  * on failure, lets do it.
02247                  */
02248                 if (rollbackOnFailure) {
02249                     rpmMessage(RPMMESS_ERROR, _("Add failed.  Could not get file list.\n"));
02250                     /* Clean up the current transaction */
02251                     p->h = headerFree(p->h);
02252                     xx = rpmdbSync(rpmtsGetRdb(ts));
02253                     psm = rpmpsmFree(psm);
02254                     p->fi = rpmfiFree(p->fi);
02255                     pi = rpmtsiFree(pi);
02256 
02257                     /* Run the rollback transaction */
02258                     xx = _rpmtsRollback(rollbackTransaction);
02259                     umask(oldmask);
02260                     return -1;
02261                 }
02262             }
02263 
02264             if (gotfd) {
02265                 /*@-noeffectuncon @*/ /* FIX: check rc */
02266                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
02267                         rpmteKey(p), ts->notifyData);
02268                 /*@=noeffectuncon @*/
02269                 /*@-type@*/
02270                 p->fd = NULL;
02271                 /*@=type@*/
02272             }
02273 
02274             p->h = headerFree(p->h);
02275 
02276             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
02277 
02278             /*@switchbreak@*/ break;
02279 
02280         case TR_REMOVED:
02281             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
02282 
02283             rpmMessage(RPMMESS_DEBUG, "========== --- %s %s-%s 0x%x\n",
02284                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
02285 
02286             /*
02287              * XXX This has always been a hack, now mostly broken.
02288              * If install failed, then we shouldn't erase.
02289              */
02290             if (rpmteDependsOnKey(p) != lastFailKey) {
02291                 if (rpmpsmStage(psm, PSM_PKGERASE)) {
02292                     ourrc++;
02293 
02294                     /* If we should rollback this transaction
02295                      * on failure, lets do it.
02296                      */
02297                     if (rollbackOnFailure) {
02298                         rpmMessage(RPMMESS_ERROR,
02299                             _("Erase failed failed in rpmpsmStage().\n"));
02300                         /* Clean up the current transaction */
02301                         xx = rpmdbSync(rpmtsGetRdb(ts));
02302                         psm = rpmpsmFree(psm);
02303                         p->fi = rpmfiFree(p->fi);
02304                         pi = rpmtsiFree(pi);
02305 
02306                         /* Run the rollback transaction */
02307                         xx = _rpmtsRollback(rollbackTransaction);
02308                         umask(oldmask);
02309                         return -1;
02310                     }
02311                 }
02312 
02313                 /* If we should rollback on failure lets add
02314                  * this element to the rollback transaction
02315                  * as an install element as it has erased succesfully.
02316                  */
02317                 if (rollbackOnFailure) {
02318                     int rc;
02319 
02320                     rc = _rpmtsAddRollbackElement(rollbackTransaction, ts, p);
02321 
02322                     if (rc != RPMRC_OK) {
02323                         /* Clean up the current transaction */
02324                         xx = rpmdbSync(rpmtsGetRdb(ts));
02325                         psm = rpmpsmFree(psm);
02326                         p->fi = rpmfiFree(p->fi);
02327                         pi = rpmtsiFree(pi);
02328                 
02329                         /* Clean up rollback transaction */
02330                         rollbackTransaction = rpmtsFree(rollbackTransaction);
02331                         umask(oldmask);
02332                         return -1;
02333                     }
02334                 }
02335             }
02336 
02337             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
02338 
02339             /*@switchbreak@*/ break;
02340         }
02341         xx = rpmdbSync(rpmtsGetRdb(ts));
02342 
02343 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
02344         psm = rpmpsmFree(psm);
02345 /*@=nullstate@*/
02346 
02347 #ifdef  DYING
02348 /*@-type@*/ /* FIX: p is almost opaque */
02349         p->fi = rpmfiFree(p->fi);
02350 /*@=type@*/
02351 #endif
02352 
02353     }
02354     /*@=branchstate@*/
02355     pi = rpmtsiFree(pi);
02356 
02357     /* If we created a rollback transaction lets get rid of it */
02358     if (rollbackOnFailure && rollbackTransaction != NULL)
02359         rollbackTransaction = rpmtsFree(rollbackTransaction);
02360 
02361     if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPOST))) {
02362         rpmMessage(RPMMESS_DEBUG, _("running post-transaction scripts\n"));
02363         pi = rpmtsiInit(ts);
02364         while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
02365             int haspostscript;
02366 
02367             if ((fi = rpmtsiFi(pi)) == NULL)
02368                 continue;       /* XXX can't happen */
02369 
02370             haspostscript = (fi->posttrans != NULL ? 1 : 0);
02371             p->fi = rpmfiFree(p->fi);
02372 
02373             /* If no post-transaction script, then don't bother. */
02374             if (!haspostscript)
02375                 continue;
02376 
02377             p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
02378                             rpmteKey(p), ts->notifyData);
02379             p->h = NULL;
02380             if (rpmteFd(p) != NULL) {
02381                 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
02382                 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
02383                 rpmRC rpmrc;
02384                 ovsflags = rpmtsSetVSFlags(ts, vsflags);
02385                 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
02386                             rpmteNEVR(p), &p->h);
02387                 vsflags = rpmtsSetVSFlags(ts, ovsflags);
02388                 switch (rpmrc) {
02389                 default:
02390                     p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
02391                                     0, 0, rpmteKey(p), ts->notifyData);
02392                     p->fd = NULL;
02393                     /*@switchbreak@*/ break;
02394                 case RPMRC_NOTTRUSTED:
02395                 case RPMRC_NOKEY:
02396                 case RPMRC_OK:
02397                     /*@switchbreak@*/ break;
02398                 }
02399             }
02400 
02401             if (rpmteFd(p) != NULL) {
02402                 p->fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
02403                 if (p->fi != NULL)      /* XXX can't happen */
02404                     p->fi->te = p;
02405 /*@-compdef -usereleased@*/     /* p->fi->te undefined */
02406                 psm = rpmpsmNew(ts, p, p->fi);
02407 /*@=compdef =usereleased@*/
02408 assert(psm != NULL);
02409                 psm->scriptTag = RPMTAG_POSTTRANS;
02410                 psm->progTag = RPMTAG_POSTTRANSPROG;
02411                 xx = rpmpsmStage(psm, PSM_SCRIPT);
02412                 psm = rpmpsmFree(psm);
02413 
02414 /*@-noeffectuncon -compdef -usereleased @*/
02415                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
02416                                   rpmteKey(p), ts->notifyData);
02417 /*@=noeffectuncon =compdef =usereleased @*/
02418                 p->fd = NULL;
02419                 p->fi = rpmfiFree(p->fi);
02420                 p->h = headerFree(p->h);
02421             }
02422         }
02423         pi = rpmtsiFree(pi);
02424     }
02425 
02426     rpmtsFreeLock(lock);
02427     umask(oldmask);
02428 
02429     /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
02430     if (ourrc)
02431         return -1;
02432     else
02433         return 0;
02434     /*@=nullstate@*/
02435 }

Generated on Tue Apr 3 13:50:32 2012 for rpm by  doxygen 1.4.7