• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

lib/transaction.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmio.h>
00008 #include <rpmmacro.h>   /* XXX for rpmExpand */
00009 #include <rpmtag.h>
00010 
00011 #define _RPMFI_INTERNAL
00012 #define _RPMTE_INTERNAL
00013 #define _RPMTS_INTERNAL
00014 #include "rpmcli.h"     /* IDTX prototypes */
00015 
00016 #include "fsm.h"
00017 #define _RPMSQ_INTERNAL
00018 #include "psm.h"
00019 
00020 #define _RPMDB_INTERNAL /* XXX for dbiIndexFoo() */
00021 #include "rpmdb.h"
00022 
00023 #include "rpmds.h"
00024 
00025 #include "rpmlock.h"
00026 
00027 #include "cpio.h"
00028 #include "fprint.h"
00029 #include "legacy.h"     /* XXX dodigest */
00030 #include "misc.h" /* XXX (free)splitString, currentDirectory */
00031 
00032 #include "debug.h"
00033 
00034 /*@access Header @*/            /* XXX ts->notify arg1 is void ptr */
00035 /*@access rpmps @*/     /* XXX need rpmProblemSetOK() */
00036 /*@access dbiIndexSet @*/
00037 
00038 /*@access rpmpsm @*/
00039 
00040 /*@access alKey @*/
00041 /*@access fnpyKey @*/
00042 
00043 /*@access rpmfi @*/
00044 
00045 /*@access rpmte @*/
00046 /*@access rpmtsi @*/
00047 /*@access rpmts @*/
00048 
00049 /*@access IDT @*/
00050 /*@access IDTX @*/
00051 /*@access FD_t @*/
00052 
00055 static int sharedCmp(const void * one, const void * two)
00056         /*@*/
00057 {
00058     sharedFileInfo a = (sharedFileInfo) one;
00059     sharedFileInfo b = (sharedFileInfo) two;
00060 
00061     if (a->otherPkg < b->otherPkg)
00062         return -1;
00063     else if (a->otherPkg > b->otherPkg)
00064         return 1;
00065 
00066     return 0;
00067 }
00068 
00079 static int handleInstInstalledFiles(const rpmts ts,
00080                 rpmte p, rpmfi fi,
00081                 sharedFileInfo shared,
00082                 int sharedCount, int reportConflicts)
00083         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00084         /*@modifies ts, p, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
00085 {
00086     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00087     const char * altNVRA = NULL;
00088     uint32_t tscolor = rpmtsColor(ts);
00089     uint32_t prefcolor = rpmtsPrefColor(ts);
00090     uint32_t otecolor, tecolor;
00091     uint32_t oFColor, FColor;
00092     uint32_t oFFlags, FFlags;
00093     rpmfi otherFi = NULL;
00094     rpmps ps;
00095     int xx;
00096     int i;
00097 
00098     {   rpmdbMatchIterator mi;
00099         Header h;
00100         int scareMem = 0;
00101 
00102         mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
00103                         &shared->otherPkg, sizeof(shared->otherPkg));
00104         while ((h = rpmdbNextIterator(mi)) != NULL) {
00105             he->tag = RPMTAG_NVRA;
00106             xx = headerGet(h, he, 0);
00107 assert(he->p.str != NULL);
00108             altNVRA = he->p.str;
00109             otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00110             break;
00111         }
00112         mi = rpmdbFreeIterator(mi);
00113     }
00114 
00115     /* Compute package color. */
00116     tecolor = rpmteColor(p);
00117     tecolor &= tscolor;
00118 
00119     /* Compute other pkg color. */
00120     otecolor = 0;
00121     otherFi = rpmfiInit(otherFi, 0);
00122     if (otherFi != NULL)
00123     while (rpmfiNext(otherFi) >= 0)
00124         otecolor |= rpmfiFColor(otherFi);
00125     otecolor &= tscolor;
00126 
00127     if (otherFi == NULL)
00128         return 1;
00129 
00130     p->replaced = xcalloc(sharedCount, sizeof(*p->replaced));
00131     p->nreplaced = 0;
00132 
00133     ps = rpmtsProblems(ts);
00134     for (i = 0; i < sharedCount; i++, shared++) {
00135         int otherFileNum, fileNum;
00136 
00137         otherFileNum = shared->otherFileNum;
00138         (void) rpmfiSetFX(otherFi, otherFileNum);
00139         oFFlags = rpmfiFFlags(otherFi);
00140         oFColor = rpmfiFColor(otherFi);
00141         oFColor &= tscolor;
00142 
00143         fileNum = shared->pkgFileNum;
00144         (void) rpmfiSetFX(fi, fileNum);
00145         FFlags = rpmfiFFlags(fi);
00146         FColor = rpmfiFColor(fi);
00147         FColor &= tscolor;
00148 
00149 #ifdef  DYING
00150         /* XXX another tedious segfault, assume file state normal. */
00151         if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00152             continue;
00153 #endif
00154 
00155         if (XFA_SKIPPING(fi->actions[fileNum]))
00156             continue;
00157 
00158         /* Remove setuid/setgid bits on other (possibly hardlinked) files. */
00159         if (!(fi->mapflags & CPIO_SBIT_CHECK)) {
00160             uint16_t omode = rpmfiFMode(otherFi);
00161             if (S_ISREG(omode) && (omode & 06000) != 0)
00162                 fi->mapflags |= CPIO_SBIT_CHECK;
00163         }
00164 
00165         if (((FFlags | oFFlags) & RPMFILE_GHOST))
00166             continue;
00167 
00168         if (rpmfiCompare(otherFi, fi)) {
00169             int rConflicts;
00170 
00171             rConflicts = reportConflicts;
00172             /* Resolve file conflicts to prefer Elf64 (if not forced). */
00173             if (tscolor != 0 && FColor != 0 && FColor != oFColor)
00174             {
00175                 if (oFColor & prefcolor) {
00176                     fi->actions[fileNum] = FA_SKIPCOLOR;
00177                     rConflicts = 0;
00178                 } else
00179                 if (FColor & prefcolor) {
00180                     fi->actions[fileNum] = FA_CREATE;
00181                     rConflicts = 0;
00182                 }
00183             }
00184 
00185             if (rConflicts) {
00186                 rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
00187                         rpmteNEVRA(p), rpmteKey(p),
00188                         rpmfiDN(fi), rpmfiBN(fi),
00189                         altNVRA,
00190                         0);
00191             }
00192 
00193             /* Save file identifier to mark as state REPLACED. */
00194             if ( !(((FFlags | oFFlags) & RPMFILE_CONFIG) || XFA_SKIPPING(fi->actions[fileNum])) ) {
00195                 /*@-assignexpose@*/
00196                 if (!shared->isRemoved)
00197                     p->replaced[p->nreplaced++] = *shared;
00198                 /*@=assignexpose@*/
00199             }
00200         }
00201 
00202         /* Determine config file dispostion, skipping missing files (if any). */
00203         if (((FFlags | oFFlags) & RPMFILE_CONFIG)) {
00204             int skipMissing =
00205                 ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
00206             fileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
00207             fi->actions[fileNum] = action;
00208         }
00209         fi->replacedSizes[fileNum] = rpmfiFSize(otherFi);
00210     }
00211     ps = rpmpsFree(ps);
00212 
00213     altNVRA = _free(altNVRA);
00214     otherFi = rpmfiFree(otherFi);
00215 
00216     p->replaced = xrealloc(p->replaced,
00217                            sizeof(*p->replaced) * (p->nreplaced + 1));
00218     memset(p->replaced + p->nreplaced, 0, sizeof(*p->replaced));
00219 
00220     return 0;
00221 }
00222 
00225 /* XXX only ts->rpmdb modified */
00226 static int handleRmvdInstalledFiles(const rpmts ts, rpmfi fi,
00227                 sharedFileInfo shared, int sharedCount)
00228         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00229         /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
00230 {
00231     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00232     Header h;
00233     const unsigned char * otherStates;
00234     int i, xx;
00235 
00236     rpmdbMatchIterator mi;
00237 
00238     mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
00239                         &shared->otherPkg, sizeof(shared->otherPkg));
00240     h = rpmdbNextIterator(mi);
00241     if (h == NULL) {
00242         mi = rpmdbFreeIterator(mi);
00243         return 1;
00244     }
00245 
00246     he->tag = RPMTAG_FILESTATES;
00247     xx = headerGet(h, he, 0);
00248     otherStates = he->p.ptr;
00249 
00250     /* XXX there's an obscure segfault here w/o NULL check ... */
00251     if (otherStates != NULL)
00252     for (i = 0; i < sharedCount; i++, shared++) {
00253         int otherFileNum, fileNum;
00254         otherFileNum = shared->otherFileNum;
00255         fileNum = shared->pkgFileNum;
00256 
00257         if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00258             continue;
00259 
00260         fi->actions[fileNum] = FA_SKIP;
00261     }
00262     he->p.ptr = _free(he->p.ptr);
00263     mi = rpmdbFreeIterator(mi);
00264 
00265     return 0;
00266 }
00267 
00268 #define ISROOT(_d)      (((_d)[0] == '/' && (_d)[1] == '\0') ? "" : (_d))
00269 
00270 /*@unchecked@*/
00271 int _fps_debug = 0;
00272 
00273 static int fpsCompare (const void * one, const void * two)
00274         /*@*/
00275 {
00276     const struct fingerPrint_s * a = (const struct fingerPrint_s *)one;
00277     const struct fingerPrint_s * b = (const struct fingerPrint_s *)two;
00278     size_t adnlen = strlen(a->entry->dirName);
00279     size_t asnlen = (a->subDir ? strlen(a->subDir) : 0);
00280     size_t abnlen = strlen(a->baseName);
00281     size_t bdnlen = strlen(b->entry->dirName);
00282     size_t bsnlen = (b->subDir ? strlen(b->subDir) : 0);
00283     size_t bbnlen = strlen(b->baseName);
00284     char * afn, * bfn, * t;
00285     int rc = 0;
00286 
00287     if (adnlen == 1 && asnlen != 0) adnlen = 0;
00288     if (bdnlen == 1 && bsnlen != 0) bdnlen = 0;
00289 
00290     afn = t = alloca(adnlen+asnlen+abnlen+2);
00291     if (adnlen) t = stpcpy(t, a->entry->dirName);
00292     *t++ = '/';
00293     if (a->subDir && asnlen) t = stpcpy(t, a->subDir);
00294     if (abnlen) t = stpcpy(t, a->baseName);
00295     if (afn[0] == '/' && afn[1] == '/') afn++;
00296 
00297     bfn = t = alloca(bdnlen+bsnlen+bbnlen+2);
00298     if (bdnlen) t = stpcpy(t, b->entry->dirName);
00299     *t++ = '/';
00300     if (b->subDir && bsnlen) t = stpcpy(t, b->subDir);
00301     if (bbnlen) t = stpcpy(t, b->baseName);
00302     if (bfn[0] == '/' && bfn[1] == '/') bfn++;
00303 
00304     rc = strcmp(afn, bfn);
00305 
00306     return rc;
00307 }
00308 
00309 /*@unchecked@*/
00310 static int _linear_fps_search = 0;
00311 
00312 static int findFps(const struct fingerPrint_s * fiFps,
00313                 const struct fingerPrint_s * otherFps,
00314                 int otherFc)
00315         /*@*/
00316 {
00317     int otherFileNum;
00318 
00319   if (_linear_fps_search) {
00320 
00321 linear:
00322     for (otherFileNum = 0; otherFileNum < otherFc; otherFileNum++, otherFps++) {
00323 
00324         /* If the addresses are the same, so are the values. */
00325         if (fiFps == otherFps)
00326             break;
00327 
00328         /* Otherwise, compare fingerprints by value. */
00329         /*@-nullpass@*/ /* LCL: looks good to me */
00330         if (FP_EQUAL((*fiFps), (*otherFps)))
00331             break;
00332         /*@=nullpass@*/
00333     }
00334 
00335     return otherFileNum;
00336 
00337   } else {
00338 
00339     const struct fingerPrint_s * bingoFps;
00340 
00341     bingoFps = bsearch(fiFps, otherFps, otherFc, sizeof(*otherFps), fpsCompare);
00342     if (bingoFps == NULL)
00343         goto linear;
00344 
00345     /* If the addresses are the same, so are the values. */
00346     if (!(fiFps == bingoFps || FP_EQUAL((*fiFps), (*bingoFps))))
00347         goto linear;
00348 
00349     otherFileNum = (bingoFps != NULL ? (bingoFps - otherFps) : 0);
00350 
00351   }
00352 
00353     return otherFileNum;
00354 }
00355 
00359 /* XXX only ts->{probs,di} modified */
00360 static void handleOverlappedFiles(const rpmts ts,
00361                 const rpmte p, rpmfi fi)
00362         /*@globals h_errno, fileSystem, internalState @*/
00363         /*@modifies ts, fi, fileSystem, internalState @*/
00364 {
00365     uint32_t fixupSize = 0;
00366     rpmps ps;
00367     const char * fn;
00368     int i, j;
00369 
00370     ps = rpmtsProblems(ts);
00371     fi = rpmfiInit(fi, 0);
00372     if (fi != NULL)
00373     while ((i = rpmfiNext(fi)) >= 0) {
00374         uint32_t tscolor = rpmtsColor(ts);
00375         uint32_t prefcolor = rpmtsPrefColor(ts);
00376         uint32_t oFColor, FColor;
00377         struct fingerPrint_s * fiFps;
00378         int otherPkgNum, otherFileNum;
00379         rpmfi otherFi;
00380         uint32_t FFlags;
00381         uint16_t FMode;
00382         const rpmfi * recs;
00383         int numRecs;
00384 
00385         if (XFA_SKIPPING(fi->actions[i]))
00386             continue;
00387 
00388         fn = rpmfiFN(fi);
00389         fiFps = fi->fps + i;
00390         FFlags = rpmfiFFlags(fi);
00391         FMode = rpmfiFMode(fi);
00392         FColor = rpmfiFColor(fi);
00393         FColor &= tscolor;
00394 
00395         fixupSize = 0;
00396 
00397         /*
00398          * Retrieve all records that apply to this file. Note that the
00399          * file info records were built in the same order as the packages
00400          * will be installed and removed so the records for an overlapped
00401          * files will be sorted in exactly the same order.
00402          */
00403         (void) htGetEntry(ts->ht, fiFps, &recs, &numRecs, NULL);
00404 
00405         /*
00406          * If this package is being added, look only at other packages
00407          * being added -- removed packages dance to a different tune.
00408          *
00409          * If both this and the other package are being added, overlapped
00410          * files must be identical (or marked as a conflict). The
00411          * disposition of already installed config files leads to
00412          * a small amount of extra complexity.
00413          *
00414          * If this package is being removed, then there are two cases that
00415          * need to be worried about:
00416          * If the other package is being added, then skip any overlapped files
00417          * so that this package removal doesn't nuke the overlapped files
00418          * that were just installed.
00419          * If both this and the other package are being removed, then each
00420          * file removal from preceding packages needs to be skipped so that
00421          * the file removal occurs only on the last occurence of an overlapped
00422          * file in the transaction set.
00423          *
00424          */
00425 
00426         /* Locate this overlapped file in the set of added/removed packages. */
00427         for (j = 0; j < numRecs && recs[j] != fi; j++)
00428             {};
00429 
00430         /* Find what the previous disposition of this file was. */
00431         otherFileNum = -1;                      /* keep gcc quiet */
00432         otherFi = NULL;
00433         for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
00434             struct fingerPrint_s * otherFps;
00435             int otherFc;
00436 
00437             otherFi = recs[otherPkgNum];
00438 
00439             /* Added packages need only look at other added packages. */
00440             if (rpmteType(p) == TR_ADDED && rpmteType(otherFi->te) != TR_ADDED)
00441                 /*@innercontinue@*/ continue;
00442 
00443             otherFps = otherFi->fps;
00444             otherFc = rpmfiFC(otherFi);
00445 
00446             otherFileNum = findFps(fiFps, otherFps, otherFc);
00447             (void) rpmfiSetFX(otherFi, otherFileNum);
00448 
00449             /* XXX Happens iff fingerprint for incomplete package install. */
00450             if (otherFi->actions[otherFileNum] != FA_UNKNOWN)
00451                 /*@innerbreak@*/ break;
00452         }
00453 
00454         oFColor = rpmfiFColor(otherFi);
00455         oFColor &= tscolor;
00456 
00457         switch (rpmteType(p)) {
00458         case TR_ADDED:
00459           { int reportConflicts =
00460                 !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
00461             int done = 0;
00462 
00463             if (otherPkgNum < 0) {
00464                 /* XXX is this test still necessary? */
00465                 if (fi->actions[i] != FA_UNKNOWN)
00466                     /*@switchbreak@*/ break;
00467                 if ((FFlags & RPMFILE_CONFIG) && (FFlags & RPMFILE_EXISTS)) {
00468                     /* Here is a non-overlapped pre-existing config file. */
00469                     fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
00470                         ? FA_ALTNAME : FA_BACKUP;
00471                 } else {
00472                     fi->actions[i] = FA_CREATE;
00473                 }
00474                 /*@switchbreak@*/ break;
00475             }
00476 
00477 assert(otherFi != NULL);
00478             /* Mark added overlapped non-identical files as a conflict. */
00479             if (rpmfiCompare(otherFi, fi)) {
00480                 int rConflicts;
00481 
00482                 rConflicts = reportConflicts;
00483                 /* Resolve file conflicts to prefer Elf64 (if not forced) ... */
00484                 if (tscolor != 0) {
00485                     if (FColor & prefcolor) {
00486                         /* ... last file of preferred colour is installed ... */
00487                         if (!XFA_SKIPPING(fi->actions[i])) {
00488                             /* XXX static helpers are order dependent. Ick. */
00489                             if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade")
00490                              && strcmp(fn, "/usr/sbin/glibc_post_upgrade"))
00491                                 otherFi->actions[otherFileNum] = FA_SKIPCOLOR;
00492                         }
00493                         fi->actions[i] = FA_CREATE;
00494                         rConflicts = 0;
00495                     } else
00496                     if (oFColor & prefcolor) {
00497                         /* ... first file of preferred colour is installed ... */
00498                         if (XFA_SKIPPING(fi->actions[i]))
00499                             otherFi->actions[otherFileNum] = FA_CREATE;
00500                         fi->actions[i] = FA_SKIPCOLOR;
00501                         rConflicts = 0;
00502                     } else
00503                     if (FColor == 0 && oFColor == 0) {
00504                         /* ... otherwise, do both, last in wins. */
00505                         otherFi->actions[otherFileNum] = FA_CREATE;
00506                         fi->actions[i] = FA_CREATE;
00507                         rConflicts = 0;
00508                     }
00509                     done = 1;
00510                 }
00511 
00512                 if (rConflicts) {
00513                     rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
00514                         rpmteNEVR(p), rpmteKey(p),
00515                         fn, NULL,
00516                         rpmteNEVR(otherFi->te),
00517                         0);
00518                 }
00519             }
00520 
00521             /* Try to get the disk accounting correct even if a conflict. */
00522             fixupSize = rpmfiFSize(otherFi);
00523 
00524             if ((FFlags & RPMFILE_CONFIG) && (FFlags & RPMFILE_EXISTS)) {
00525                 /* Here is an overlapped  pre-existing config file. */
00526                 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
00527                         ? FA_ALTNAME : FA_SKIP;
00528             } else {
00529                 if (!done)
00530                     fi->actions[i] = FA_CREATE;
00531             }
00532           } /*@switchbreak@*/ break;
00533 
00534         case TR_REMOVED:
00535             if (otherPkgNum >= 0) {
00536 assert(otherFi != NULL);
00537                 /* Here is an overlapped added file we don't want to nuke. */
00538                 if (otherFi->actions[otherFileNum] != FA_ERASE) {
00539                     /* On updates, don't remove files. */
00540                     fi->actions[i] = FA_SKIP;
00541                     /*@switchbreak@*/ break;
00542                 }
00543                 /* Here is an overlapped removed file: skip in previous. */
00544                 otherFi->actions[otherFileNum] = FA_SKIP;
00545             }
00546             if (XFA_SKIPPING(fi->actions[i]))
00547                 /*@switchbreak@*/ break;
00548             if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
00549                 /*@switchbreak@*/ break;
00550 
00551             /* Disposition is assumed to be FA_ERASE. */
00552             fi->actions[i] = FA_ERASE;
00553             if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG)))
00554                 /*@switchbreak@*/ break;
00555                 
00556             /* Check for pre-existing modified config file that needs saving. */
00557             if (!(FFlags & RPMFILE_SPARSE))
00558             {   int dalgo = 0;
00559                 size_t dlen = 0;
00560                 const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen);
00561                 unsigned char * fdigest;
00562 assert(digest != NULL);
00563                 
00564                 fdigest = xcalloc(1, dlen);
00565                 /* Save (by renaming) locally modified config files. */
00566                 if (!dodigest(dalgo, fn, fdigest, 0, NULL)
00567                  && memcmp(digest, fdigest, dlen))
00568                     fi->actions[i] = FA_BACKUP;
00569                 fdigest = _free(fdigest);
00570             }
00571             /*@switchbreak@*/ break;
00572         }
00573 
00574         /* Update disk space info for a file. */
00575         rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
00576                 fi->replacedSizes[i], fixupSize, fi->actions[i]);
00577 
00578     }
00579     ps = rpmpsFree(ps);
00580 }
00581 
00589 /*@-nullpass@*/
00590 static int ensureOlder(rpmts ts,
00591                 const rpmte p, const Header h)
00592         /*@modifies ts @*/
00593 {
00594     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00595     uint32_t reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
00596     const char * reqEVR;
00597     rpmds req;
00598     char * t;
00599     int nb;
00600     int rc;
00601 
00602     if (p == NULL || h == NULL)
00603         return 1;
00604 
00605     nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1;
00606     t = alloca(nb);
00607     *t = '\0';
00608     reqEVR = t;
00609     if (rpmteE(p) != NULL)      t = stpcpy( stpcpy(t, rpmteE(p)), ":");
00610     if (rpmteV(p) != NULL)      t = stpcpy(t, rpmteV(p));
00611     *t++ = '-';
00612     if (rpmteR(p) != NULL)      t = stpcpy(t, rpmteR(p));
00613 
00614     req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
00615     rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
00616     req = rpmdsFree(req);
00617 
00618     if (rc == 0) {
00619         rpmps ps = rpmtsProblems(ts);
00620         he->tag = RPMTAG_NVRA;
00621         rc = headerGet(h, he, 0);
00622 assert(he->p.str != NULL);
00623         rpmpsAppend(ps, RPMPROB_OLDPACKAGE,
00624                 rpmteNEVR(p), rpmteKey(p),
00625                 NULL, NULL,
00626                 he->p.str,
00627                 0);
00628         he->p.ptr = _free(he->p.ptr);
00629         ps = rpmpsFree(ps);
00630         rc = 1;
00631     } else
00632         rc = 0;
00633 
00634     return rc;
00635 }
00636 /*@=nullpass@*/
00637 
00643 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
00644 /*@-nullpass@*/
00645 static void skipFiles(const rpmts ts, rpmfi fi)
00646         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00647         /*@modifies fi, rpmGlobalMacroContext, internalState @*/
00648 {
00649     uint32_t tscolor = rpmtsColor(ts);
00650     uint32_t FColor;
00651     int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
00652     int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
00653     char ** netsharedPaths = NULL;
00654     const char ** languages;
00655     const char * dn, * bn;
00656     int dnlen, bnlen, ix;
00657     const char * s;
00658     int * drc;
00659     char * dff;
00660     int dc;
00661     int i, j;
00662 
00663 #if defined(RPM_VENDOR_OPENPKG) /* allow-excludedocs-default */
00664     /* The "%_excludedocs" macro is intended to set the _default_ if
00665        both --excludedocs and --includedocs are not specified and it
00666        is evaluated already before. So, do not override it here again,
00667        because it would not allow us to make "%_excludedocs 1" the
00668        default. */
00669 #else
00670     if (!noDocs)
00671         noDocs = rpmExpandNumeric("%{_excludedocs}");
00672 #endif
00673 
00674     {   const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL);
00675         if (tmpPath && *tmpPath != '%')
00676             netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
00677         tmpPath = _free(tmpPath);
00678     }
00679 
00680     s = rpmExpand("%{_install_langs}", NULL);
00681     if (!(s && *s != '%'))
00682         s = _free(s);
00683     if (s) {
00684         languages = (const char **) splitString(s, strlen(s), ':');
00685         s = _free(s);
00686     } else
00687         languages = NULL;
00688 
00689     /* Compute directory refcount, skip directory if now empty. */
00690     dc = rpmfiDC(fi);
00691     drc = alloca(dc * sizeof(*drc));
00692     memset(drc, 0, dc * sizeof(*drc));
00693     dff = alloca(dc * sizeof(*dff));
00694     memset(dff, 0, dc * sizeof(*dff));
00695 
00696     fi = rpmfiInit(fi, 0);
00697     if (fi != NULL)     /* XXX lclint */
00698     while ((i = rpmfiNext(fi)) >= 0)
00699     {
00700         char ** nsp;
00701 
00702         bn = rpmfiBN(fi);
00703         bnlen = strlen(bn);
00704         ix = rpmfiDX(fi);
00705         dn = rpmfiDN(fi);
00706         if (dn == NULL)
00707             continue;   /* XXX can't happen */
00708         dnlen = strlen(dn);
00709 
00710         drc[ix]++;
00711 
00712         /* Don't bother with skipped files */
00713         if (XFA_SKIPPING(fi->actions[i])) {
00714             drc[ix]--; dff[ix] = 1;
00715             continue;
00716         }
00717 
00718         /* Ignore colored files not in our rainbow. */
00719         FColor = rpmfiFColor(fi);
00720         if (tscolor && FColor && !(tscolor & FColor)) {
00721             drc[ix]--;  dff[ix] = 1;
00722             fi->actions[i] = FA_SKIPCOLOR;
00723             continue;
00724         }
00725 
00726         /*
00727          * Skip net shared paths.
00728          * Net shared paths are not relative to the current root (though
00729          * they do need to take package relocations into account).
00730          */
00731         for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
00732             int len;
00733 
00734             len = strlen(*nsp);
00735             if (dnlen >= len) {
00736                 if (strncmp(dn, *nsp, len))
00737                     /*@innercontinue@*/ continue;
00738                 /* Only directories or complete file paths can be net shared */
00739                 if (!(dn[len] == '/' || dn[len] == '\0'))
00740                     /*@innercontinue@*/ continue;
00741             } else {
00742                 if (len < (dnlen + bnlen))
00743                     /*@innercontinue@*/ continue;
00744                 if (strncmp(dn, *nsp, dnlen))
00745                     /*@innercontinue@*/ continue;
00746                 /* Insure that only the netsharedpath basename is compared. */
00747                 if ((s = strchr((*nsp) + dnlen, '/')) != NULL && s[1] != '\0')
00748                     /*@innercontinue@*/ continue;
00749                 if (strncmp(bn, (*nsp) + dnlen, bnlen))
00750                     /*@innercontinue@*/ continue;
00751                 len = dnlen + bnlen;
00752                 /* Only directories or complete file paths can be net shared */
00753                 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
00754                     /*@innercontinue@*/ continue;
00755             }
00756 
00757             /*@innerbreak@*/ break;
00758         }
00759 
00760         if (nsp && *nsp) {
00761             drc[ix]--;  dff[ix] = 1;
00762             fi->actions[i] = FA_SKIPNETSHARED;
00763             continue;
00764         }
00765 
00766         /*
00767          * Skip i18n language specific files.
00768          */
00769         if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
00770             const char **lang, *l, *le;
00771             for (lang = languages; *lang != NULL; lang++) {
00772                 if (!strcmp(*lang, "all"))
00773                     /*@innerbreak@*/ break;
00774                 for (l = fi->flangs[i]; *l != '\0'; l = le) {
00775                     for (le = l; *le != '\0' && *le != '|'; le++)
00776                         {};
00777                     if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
00778                         /*@innerbreak@*/ break;
00779                     if (*le == '|') le++;       /* skip over | */
00780                 }
00781                 if (*l != '\0')
00782                     /*@innerbreak@*/ break;
00783             }
00784             if (*lang == NULL) {
00785                 drc[ix]--;      dff[ix] = 1;
00786                 fi->actions[i] = FA_SKIPNSTATE;
00787                 continue;
00788             }
00789         }
00790 
00791         /*
00792          * Skip config files if requested.
00793          */
00794         if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
00795             drc[ix]--;  dff[ix] = 1;
00796             fi->actions[i] = FA_SKIPNSTATE;
00797             continue;
00798         }
00799 
00800         /*
00801          * Skip documentation if requested.
00802          */
00803         if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
00804             drc[ix]--;  dff[ix] = 1;
00805             fi->actions[i] = FA_SKIPNSTATE;
00806             continue;
00807         }
00808     }
00809 
00810     /* Skip (now empty) directories that had skipped files. */
00811 #ifndef NOTYET
00812     if (fi != NULL)     /* XXX can't happen */
00813     for (j = 0; j < dc; j++)
00814 #else
00815     if ((fi = rpmfiInitD(fi)) != NULL)
00816     while (j = rpmfiNextD(fi) >= 0)
00817 #endif
00818     {
00819 
00820         if (drc[j]) continue;   /* dir still has files. */
00821         if (!dff[j]) continue;  /* dir was not emptied here. */
00822         
00823         /* Find parent directory and basename. */
00824         dn = fi->dnl[j];        dnlen = strlen(dn) - 1;
00825         bn = dn + dnlen;        bnlen = 0;
00826         while (bn > dn && bn[-1] != '/') {
00827                 bnlen++;
00828                 dnlen--;
00829                 bn--;
00830         }
00831 
00832         /* If explicitly included in the package, skip the directory. */
00833         fi = rpmfiInit(fi, 0);
00834         if (fi != NULL)         /* XXX lclint */
00835         while ((i = rpmfiNext(fi)) >= 0) {
00836             const char * fdn, * fbn;
00837             uint16_t fFMode;
00838 
00839             if (XFA_SKIPPING(fi->actions[i]))
00840                 /*@innercontinue@*/ continue;
00841 
00842             fFMode = rpmfiFMode(fi);
00843 
00844             if (!S_ISDIR(fFMode))
00845                 /*@innercontinue@*/ continue;
00846             fdn = rpmfiDN(fi);
00847             if (strlen(fdn) != dnlen)
00848                 /*@innercontinue@*/ continue;
00849             if (strncmp(fdn, dn, dnlen))
00850                 /*@innercontinue@*/ continue;
00851             fbn = rpmfiBN(fi);
00852             if (strlen(fbn) != bnlen)
00853                 /*@innercontinue@*/ continue;
00854             if (strncmp(fbn, bn, bnlen))
00855                 /*@innercontinue@*/ continue;
00856             rpmlog(RPMLOG_DEBUG, D_("excluding directory %s\n"), dn);
00857             fi->actions[i] = FA_SKIPNSTATE;
00858             /*@innerbreak@*/ break;
00859         }
00860     }
00861 
00862 /*@-dependenttrans@*/
00863     if (netsharedPaths) freeSplitString(netsharedPaths);
00864     if (languages) freeSplitString((char **)languages);
00865 /*@=dependenttrans@*/
00866 }
00867 /*@=nullpass@*/
00868 /*@=mustmod@*/
00869 
00876 static /*@null@*/
00877 rpmfi rpmtsiFi(const rpmtsi tsi)
00878         /*@*/
00879 {
00880     rpmfi fi = NULL;
00881 
00882     if (tsi != NULL && tsi->ocsave != -1) {
00883         /*@-type -abstract@*/ /* FIX: rpmte not opaque */
00884         rpmte te = rpmtsElement(tsi->ts, tsi->ocsave);
00885         /*@-assignexpose@*/
00886         if (te != NULL && (fi = te->fi) != NULL)
00887             fi->te = te;
00888         /*@=assignexpose@*/
00889         /*@=type =abstract@*/
00890     }
00891     /*@-compdef -refcounttrans -usereleased @*/
00892     return fi;
00893     /*@=compdef =refcounttrans =usereleased @*/
00894 }
00895 
00902 /*@-nullpass@*/
00903 static rpmRC _processFailedPackage(rpmts ts, rpmte p)
00904         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00905         /*@modifies ts, p, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00906 {
00907     int rc  = RPMRC_OK; /* assume success */
00908 
00909     /* Handle failed packages. */
00910     /* XXX TODO: Add header to rpmdb in PSM_INIT, not PSM_POST. */
00911     if (p != NULL && rpmteType(p) == TR_ADDED && !p->installed) {
00912 /*@-compdef -usereleased@*/     /* p->fi->te undefined */
00913         rpmpsm psm = rpmpsmNew(ts, p, p->fi);
00914 /*@=compdef =usereleased@*/
00915         /*
00916          * If it died before the header was put in the rpmdb, we need
00917          * do to something wacky which is add the header to the DB anyway.
00918          * This will allow us to add the failed package as an erase
00919          * to the rollback transaction.  This must be done because we
00920          * want the the erase scriptlets to run, and the only way that
00921          * is going is if the header is in the rpmdb.
00922          */
00923 assert(psm != NULL);
00924         psm->stepName = "failed";       /* XXX W2DO? */
00925         rc = rpmpsmStage(psm, PSM_RPMDB_ADD);
00926         psm = rpmpsmFree(psm);
00927     }
00928     return rc;
00929 }
00930 /*@=nullpass@*/
00931 
00932 /*@-nullpass@*/
00933 rpmRC rpmtsRollback(rpmts rbts, rpmprobFilterFlags ignoreSet, int running, rpmte rbte)
00934         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00935         /*@modifies rbts, rpmGlobalMacroContext, fileSystem, internalState @*/
00936 {
00937     const char * semfn = NULL;
00938     rpmRC rc = 0;
00939     uint32_t arbgoal = rpmtsARBGoal(rbts);
00940     QVA_t ia = memset(alloca(sizeof(*ia)), 0, sizeof(*ia));
00941     time_t ttid;
00942     int xx;
00943 
00944     /* Don't attempt rollback's of rollback transactions */
00945     if ((rpmtsType(rbts) & RPMTRANS_TYPE_ROLLBACK) ||
00946         (rpmtsType(rbts) & RPMTRANS_TYPE_AUTOROLLBACK))
00947         return RPMRC_OK;
00948 
00949     if (arbgoal == 0xffffffff) 
00950         arbgoal = rpmtsGetTid(rbts);
00951 
00952     /* Don't attempt rollbacks if no goal is set. */
00953     if (!running && arbgoal == 0xffffffff)
00954         return RPMRC_OK;
00955 
00956     /* We need to remove an headers that were going to be removed so 
00957      * as to not foul up the regular rollback mechanism which will not 
00958      * handle properly a file being in the repackaged package directory
00959      * and also its header still in the DB.
00960      */
00961     {   rpmtsi tsi;
00962         rpmte te;
00963 
00964         /* XXX Insure an O_RDWR rpmdb. */
00965         xx = rpmtsOpenDB(rbts, O_RDWR);
00966 
00967         tsi = rpmtsiInit(rbts);
00968         while((te = rpmtsiNext(tsi, TR_REMOVED)) != NULL) {
00969             if (te->isSource) continue;
00970             if(!te->u.removed.dboffset)
00971                 continue;
00972             rc = rpmdbRemove(rpmtsGetRdb(rbts),
00973                         rpmtsGetTid(rbts),
00974                         te->u.removed.dboffset, NULL);
00975             if (rc != RPMRC_OK) {
00976                 rpmlog(RPMLOG_ERR, _("rpmdb erase failed. NEVRA: %s\n"),
00977                         rpmteNEVRA(te));
00978                 break;
00979             }
00980         }
00981         tsi = rpmtsiFree(tsi);
00982         if (rc != RPMRC_OK) 
00983             goto cleanup;
00984     }
00985 
00986     /* Process the failed package */
00987     rc = _processFailedPackage(rbts, rbte);
00988     if (rc != RPMRC_OK)
00989         goto cleanup;
00990 
00991     rpmtsEmpty(rbts);
00992 
00993     ttid = (time_t)arbgoal;
00994     rpmlog(RPMLOG_NOTICE, _("Rollback to %-24.24s (0x%08x)\n"),
00995         ctime(&ttid), arbgoal);
00996 
00997     /* Set the verify signature flags:
00998      *  - can't verify signatures/digests on repackaged packages.
00999      *  - header check are out.
01000      */
01001     {
01002         rpmVSFlags vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
01003         vsflags |= _RPMVSF_NODIGESTS;
01004         vsflags |= _RPMVSF_NOSIGNATURES;
01005         vsflags |= RPMVSF_NOHDRCHK;
01006         vsflags |= RPMVSF_NEEDPAYLOAD;      
01007         xx = rpmtsSetVSFlags(rbts, vsflags); 
01008     }
01009 
01010     /* Set transaction flags to be the same as the running transaction */
01011     {
01012         rpmtransFlags tsFlags = rpmtsFlags(rbts);
01013         tsFlags &= ~RPMTRANS_FLAG_DIRSTASH;     /* No repackage of rollbacks */
01014         tsFlags &= ~RPMTRANS_FLAG_REPACKAGE;    /* No repackage of rollbacks */
01015         tsFlags |= RPMTRANS_FLAG_NOFDIGESTS;    /* Don't check file digests */
01016         tsFlags = rpmtsSetFlags(rbts, tsFlags);
01017     }
01018 
01019     /* Create install arguments structure */    
01020     ia->rbtid = arbgoal;
01021     /* transFlags/depFlags from rbts, (re-)set in rpmRollback(). */
01022     ia->transFlags = rpmtsFlags(rbts);
01023     ia->depFlags = rpmtsDFlags(rbts);
01024     /* XXX probFilter is normally set in main(). */
01025     ia->probFilter = ignoreSet; /* XXX RPMPROB_FILTER_NONE? */
01026     /* XXX installInterfaceFlags is normally set in main(). */
01027     ia->installInterfaceFlags = INSTALL_UPGRADE | INSTALL_HASH ;
01028 
01029     /* rpmtsCheck and rpmtsOrder failures do not have links. */
01030     ia->no_rollback_links = 1;
01031 
01032     /* Create a file semaphore. */
01033     semfn = rpmExpand("%{?semaphore_backout}", NULL);
01034     if (semfn && *semfn) {
01035         FD_t fd = Fopen(semfn, "w.fdio");
01036         if (fd)
01037             xx = Fclose(fd);
01038     }
01039 
01040 /*@-compmempass@*/
01041     rc = rpmRollback(rbts, ia, NULL);
01042 /*@=compmempass@*/
01043 
01044 cleanup: 
01045     /* Remove the file semaphore. */
01046     if (semfn && *semfn)
01047         xx = Unlink(semfn);
01048     semfn = _free(semfn);
01049 
01050     return rc;
01051 }
01052 /*@=nullpass@*/
01053 
01060 static int cmpArgvStr(/*@null@*/ const char ** AV, /*@null@*/ const char * B)
01061         /*@*/
01062 {
01063     const char ** a;
01064 
01065     if (AV != NULL && B != NULL)
01066     for (a = AV; *a != NULL; a++) {
01067         if (**a && *B && !strcmp(*a, B))
01068             return 1;
01069     }
01070     return 0;
01071 }
01072 
01073 
01080 static int markLinkedFailed(rpmts ts, rpmte p)
01081         /*@globals fileSystem @*/
01082         /*@modifies ts, p, fileSystem @*/
01083 {
01084     rpmtsi qi; rpmte q;
01085     int bingo;
01086 
01087     p->linkFailed = 1;
01088 
01089     qi = rpmtsiInit(ts);
01090     while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
01091 
01092         if (q->done)
01093             continue;
01094 
01095         /*
01096          * Either element may have missing data and can have multiple entries.
01097          * Try for hdrid, then pkgid, finally NEVRA, argv vs. argv compares.
01098          */
01099         bingo = cmpArgvStr(q->flink.Hdrid, p->hdrid);
01100         if (!bingo)
01101                 bingo = cmpArgvStr(q->flink.Pkgid, p->pkgid);
01102         if (!bingo)
01103                 bingo = cmpArgvStr(q->flink.NEVRA, p->NEVRA);
01104 
01105         if (!bingo)
01106             continue;
01107 
01108         q->linkFailed = p->linkFailed;
01109     }
01110     qi = rpmtsiFree(qi);
01111 
01112     return 0;
01113 }
01114 
01115 #define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al
01116 
01117 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
01118 {
01119     uint32_t tscolor = rpmtsColor(ts);
01120     int i, j;
01121     int ourrc = 0;
01122     int totalFileCount = 0;
01123     rpmfi fi;
01124     sharedFileInfo shared, sharedList;
01125     int numShared;
01126     int nexti;
01127     fingerPrintCache fpc;
01128     rpmps ps;
01129     rpmpsm psm;
01130     rpmtsi pi;  rpmte p;
01131     rpmtsi qi;  rpmte q;
01132     int numAdded;
01133     int numRemoved;
01134     int rollbackFailures = 0;
01135     void * lock = NULL;
01136     int xx;
01137 
01138     /* XXX programmer error segfault avoidance. */
01139     if (rpmtsNElements(ts) <= 0) {
01140         rpmlog(RPMLOG_ERR,
01141             _("Invalid number of transaction elements.\n"));
01142         return -1;
01143     }
01144 
01145     rollbackFailures = rpmExpandNumeric("%{?_rollback_transaction_on_failure}");
01146     /* Don't rollback unless repackaging. */
01147     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
01148         rollbackFailures = 0;
01149     /* Don't rollback if testing. */
01150     if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
01151         rollbackFailures = 0;
01152 
01153     if (rpmtsType(ts) & (RPMTRANS_TYPE_ROLLBACK | RPMTRANS_TYPE_AUTOROLLBACK))
01154         rollbackFailures = 0;
01155 
01156     /* If we are in test mode, there is no need to rollback on
01157      * failure, nor acquire the transaction lock.
01158      */
01159     /* Don't acquire the transaction lock if testing. */
01160     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST))
01161         lock = rpmtsAcquireLock(ts);
01162 
01163     /* --noscripts implies no scripts or triggers, duh. */
01164     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
01165         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
01166     /* --notriggers implies no triggers, duh. */
01167     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
01168         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
01169 
01170     /* --justdb implies no scripts or triggers, duh. */
01171     if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
01172         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
01173 
01174     ts->probs = rpmpsFree(ts->probs);
01175     ts->probs = rpmpsCreate();
01176 
01177     /* XXX Make sure the database is open RDWR for package install/erase. */
01178     {   int dbmode = O_RDONLY;
01179 
01180         if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
01181             pi = rpmtsiInit(ts);
01182             while ((p = rpmtsiNext(pi, 0)) != NULL) {
01183                 if (p->isSource) continue;
01184                 dbmode = (O_RDWR|O_CREAT);
01185                 break;
01186             }
01187             pi = rpmtsiFree(pi);
01188         }
01189 
01190         /* Open database RDWR for installing packages. */
01191         if (rpmtsOpenDB(ts, dbmode)) {
01192             lock = rpmtsFreeLock(lock);
01193             return -1;  /* XXX W2DO? */
01194         }
01195     }
01196 
01197     ts->ignoreSet = ignoreSet;
01198     {   const char * currDir = currentDirectory();
01199         rpmtsSetCurrDir(ts, currDir);
01200         currDir = _free(currDir);
01201     }
01202 
01203     (void) rpmtsSetChrootDone(ts, 0);
01204 
01205     /* XXX rpmtsCreate() sets the transaction id, but apps may not honor. */
01206     {   uint32_t tid = (uint32_t) time(NULL);
01207         (void) rpmtsSetTid(ts, tid);
01208     }
01209 
01210     /* Get available space on mounted file systems. */
01211     xx = rpmtsInitDSI(ts);
01212 
01213     /* ===============================================
01214      * For packages being installed:
01215      * - verify package epoch:version-release is newer.
01216      * - count files.
01217      * For packages being removed:
01218      * - count files.
01219      */
01220 
01221 rpmlog(RPMLOG_DEBUG, D_("sanity checking %d elements\n"), rpmtsNElements(ts));
01222     ps = rpmtsProblems(ts);
01223     /* The ordering doesn't matter here */
01224     pi = rpmtsiInit(ts);
01225     /* XXX Only added packages need be checked. */
01226     while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01227         rpmdbMatchIterator mi;
01228         int fc;
01229 
01230         if (p->isSource) continue;
01231         if ((fi = rpmtsiFi(pi)) == NULL)
01232             continue;   /* XXX can't happen */
01233         fc = rpmfiFC(fi);
01234 
01235         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) {
01236             Header h;
01237             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01238             while ((h = rpmdbNextIterator(mi)) != NULL)
01239                 xx = ensureOlder(ts, p, h);
01240             mi = rpmdbFreeIterator(mi);
01241         }
01242 
01243         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
01244             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01245             xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
01246                                 rpmteE(p));
01247             xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
01248                                 rpmteV(p));
01249             xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
01250                                 rpmteR(p));
01251             if (tscolor) {
01252                 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
01253                                 rpmteA(p));
01254                 xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP,
01255                                 rpmteO(p));
01256             }
01257 
01258             while (rpmdbNextIterator(mi) != NULL) {
01259                 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
01260                         rpmteNEVR(p), rpmteKey(p),
01261                         NULL, NULL,
01262                         NULL, 0);
01263                 /*@innerbreak@*/ break;
01264             }
01265             mi = rpmdbFreeIterator(mi);
01266         }
01267 
01268         /* Count no. of files (if any). */
01269         totalFileCount += fc;
01270 
01271     }
01272     pi = rpmtsiFree(pi);
01273     ps = rpmpsFree(ps);
01274 
01275     /* The ordering doesn't matter here */
01276     pi = rpmtsiInit(ts);
01277     while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
01278         int fc;
01279 
01280         if (p->isSource) continue;
01281         if ((fi = rpmtsiFi(pi)) == NULL)
01282             continue;   /* XXX can't happen */
01283         fc = rpmfiFC(fi);
01284 
01285         totalFileCount += fc;
01286     }
01287     pi = rpmtsiFree(pi);
01288 
01289 
01290     /* Run pre-transaction scripts, but only if there are no known
01291      * problems up to this point. */
01292     if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST))
01293           || (rpmpsNumProblems(ts->probs) &&
01294                 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))))
01295     {
01296         rpmlog(RPMLOG_DEBUG, D_("running pre-transaction scripts\n"));
01297         pi = rpmtsiInit(ts);
01298         while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01299             if (p->isSource) continue;
01300             if ((fi = rpmtsiFi(pi)) == NULL)
01301                 continue;       /* XXX can't happen */
01302 
01303             /* If no pre-transaction script, then don't bother. */
01304             if (fi->pretrans == NULL)
01305                 continue;
01306 
01307             p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01308                             rpmteKey(p), ts->notifyData);
01309             p->h = NULL;
01310             if (rpmteFd(p) != NULL) {
01311                 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
01312                 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
01313                 rpmRC rpmrc;
01314                 ovsflags = rpmtsSetVSFlags(ts, vsflags);
01315                 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
01316                             rpmteNEVR(p), &p->h);
01317                 vsflags = rpmtsSetVSFlags(ts, ovsflags);
01318                 switch (rpmrc) {
01319                 default:
01320                     /*@-noeffectuncon@*/ /* FIX: notify annotations */
01321                     p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
01322                                     0, 0,
01323                                     rpmteKey(p), ts->notifyData);
01324                     /*@=noeffectuncon@*/
01325                     p->fd = NULL;
01326                     /*@switchbreak@*/ break;
01327                 case RPMRC_NOTTRUSTED:
01328                 case RPMRC_NOKEY:
01329                 case RPMRC_OK:
01330                     /*@switchbreak@*/ break;
01331                 }
01332             }
01333 
01334             if (rpmteFd(p) != NULL) {
01335                 int scareMem = 0;
01336                 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
01337                 if (fi != NULL) {       /* XXX can't happen */
01338                     fi->te = p;
01339                     p->fi = fi;
01340                 }
01341 /*@-compdef -usereleased@*/     /* p->fi->te undefined */
01342                 psm = rpmpsmNew(ts, p, p->fi);
01343 /*@=compdef =usereleased@*/
01344 assert(psm != NULL);
01345                 psm->stepName = "pretrans";
01346                 psm->scriptTag = RPMTAG_PRETRANS;
01347                 psm->progTag = RPMTAG_PRETRANSPROG;
01348                 xx = rpmpsmStage(psm, PSM_SCRIPT);
01349                 psm = rpmpsmFree(psm);
01350 
01351 /*@-noeffectuncon -compdef -usereleased @*/
01352                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01353                                   rpmteKey(p), ts->notifyData);
01354 /*@=noeffectuncon =compdef =usereleased @*/
01355                 p->fd = NULL;
01356                 p->h = headerFree(p->h);
01357             }
01358         }
01359         pi = rpmtsiFree(pi);
01360     }
01361 
01362     /* ===============================================
01363      * Initialize transaction element file info for package:
01364      */
01365 
01366     /*
01367      * FIXME?: we'd be better off assembling one very large file list and
01368      * calling fpLookupList only once. I'm not sure that the speedup is
01369      * worth the trouble though.
01370      */
01371 rpmlog(RPMLOG_DEBUG, D_("computing %d file fingerprints\n"), totalFileCount);
01372 
01373     numAdded = numRemoved = 0;
01374     pi = rpmtsiInit(ts);
01375     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01376         int fc;
01377 
01378         if (p->isSource) continue;
01379         if ((fi = rpmtsiFi(pi)) == NULL)
01380             continue;   /* XXX can't happen */
01381         fc = rpmfiFC(fi);
01382 
01383         switch (rpmteType(p)) {
01384         case TR_ADDED:
01385             numAdded++;
01386             fi->record = 0;
01387             /* Skip netshared paths, not our i18n files, and excluded docs */
01388             if (fc > 0)
01389                 skipFiles(ts, fi);
01390             /*@switchbreak@*/ break;
01391         case TR_REMOVED:
01392             numRemoved++;
01393             fi->record = rpmteDBOffset(p);
01394             /*@switchbreak@*/ break;
01395         }
01396 
01397         fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
01398     }
01399     pi = rpmtsiFree(pi);
01400 
01401     if (!rpmtsChrootDone(ts)) {
01402         const char * rootDir = rpmtsRootDir(ts);
01403         static int openall_before_chroot = -1;
01404 
01405         if (openall_before_chroot < 0)
01406             openall_before_chroot = rpmExpandNumeric("%{?_openall_before_chroot}");
01407 
01408         xx = Chdir("/");
01409         /*@-modobserver@*/
01410         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
01411             if (openall_before_chroot)
01412                 xx = rpmdbOpenAll(rpmtsGetRdb(ts));
01413             xx = Chroot(rootDir);
01414         }
01415         /*@=modobserver@*/
01416         (void) rpmtsSetChrootDone(ts, 1);
01417     }
01418 
01419     ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
01420     fpc = fpCacheCreate(totalFileCount);
01421 
01422     /* ===============================================
01423      * Add fingerprint for each file not skipped.
01424      */
01425     pi = rpmtsiInit(ts);
01426     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01427         int fc;
01428 
01429         (void) rpmdbCheckSignals();
01430 
01431         if (p->isSource) continue;
01432         if ((fi = rpmtsiFi(pi)) == NULL)
01433             continue;   /* XXX can't happen */
01434         fc = rpmfiFC(fi);
01435 
01436         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01437         fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
01438         fi = rpmfiInit(fi, 0);
01439         if (fi != NULL)         /* XXX lclint */
01440         while ((i = rpmfiNext(fi)) >= 0) {
01441             if (XFA_SKIPPING(fi->actions[i]))
01442                 /*@innercontinue@*/ continue;
01443             /*@-dependenttrans@*/
01444             htAddEntry(ts->ht, fi->fps + i, (void *) fi);
01445             /*@=dependenttrans@*/
01446         }
01447         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01448 
01449     }
01450     pi = rpmtsiFree(pi);
01451 
01452     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount,
01453         NULL, ts->notifyData));
01454 
01455     /* ===============================================
01456      * Compute file disposition for each package in transaction set.
01457      */
01458 rpmlog(RPMLOG_DEBUG, D_("computing file dispositions\n"));
01459     ps = rpmtsProblems(ts);
01460     pi = rpmtsiInit(ts);
01461 /*@-nullpass@*/
01462     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01463         dbiIndexSet * matches;
01464         unsigned int exclude;
01465         int knownBad;
01466         int fc;
01467 
01468         (void) rpmdbCheckSignals();
01469 
01470         if ((fi = rpmtsiFi(pi)) == NULL)
01471             continue;   /* XXX can't happen */
01472         fc = rpmfiFC(fi);
01473 
01474         NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
01475                         ts->orderCount, NULL, ts->notifyData));
01476 
01477         if (fc == 0) continue;
01478 
01479         /* All source files get installed. */
01480         if (p->isSource) {
01481             fi = rpmfiInit(fi, 0);
01482             if (fi != NULL)
01483             while ((i = rpmfiNext(fi)) >= 0)
01484                 fi->actions[i] = FA_CREATE;
01485             continue;
01486         }
01487 
01488         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01489         /* Extract file info for all files in this package from the database. */
01490         matches = xcalloc(fc, sizeof(*matches));
01491         exclude = (rpmteType(p) == TR_REMOVED ? fi->record : 0);
01492         if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc, exclude)) {
01493             ps = rpmpsFree(ps);
01494             lock = rpmtsFreeLock(lock);
01495             return 1;   /* XXX WTFO? */
01496         }
01497 
01498         numShared = 0;
01499         fi = rpmfiInit(fi, 0);
01500         while ((i = rpmfiNext(fi)) >= 0) {
01501             struct stat sb, *st = &sb;
01502             uint32_t FFlags = rpmfiFFlags(fi);
01503             numShared += dbiIndexSetCount(matches[i]);
01504             if (!(FFlags & RPMFILE_CONFIG))
01505                 /*@innercontinue@*/ continue;
01506             if (!Lstat(rpmfiFN(fi), st)) {
01507                 FFlags |= RPMFILE_EXISTS;
01508                 if ((512 * st->st_blocks) < st->st_size)
01509                      FFlags |= RPMFILE_SPARSE;
01510                 (void) rpmfiSetFFlags(fi, FFlags);
01511             }
01512         }
01513 
01514         /* Build sorted file info list for this package. */
01515         shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
01516 
01517         fi = rpmfiInit(fi, 0);
01518         while ((i = rpmfiNext(fi)) >= 0) {
01519             /*
01520              * Take care not to mark files as replaced in packages that will
01521              * have been removed before we will get here.
01522              */
01523             for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
01524                 int ro;
01525                 ro = dbiIndexRecordOffset(matches[i], j);
01526                 knownBad = 0;
01527                 qi = rpmtsiInit(ts);
01528                 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
01529                     if (ro == knownBad)
01530                         /*@innerbreak@*/ break;
01531                     if (rpmteDBOffset(q) == ro)
01532                         knownBad = ro;
01533                 }
01534                 qi = rpmtsiFree(qi);
01535 
01536                 shared->pkgFileNum = i;
01537                 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
01538                 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
01539                 shared->isRemoved = (knownBad == ro);
01540                 shared++;
01541             }
01542             matches[i] = dbiFreeIndexSet(matches[i]);
01543         }
01544         numShared = shared - sharedList;
01545         shared->otherPkg = -1;
01546         matches = _free(matches);
01547 
01548         /* Sort file info by other package index (otherPkg) */
01549         qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
01550 
01551         /* For all files from this package that are in the database ... */
01552 /*@-nullpass@*/
01553         for (i = 0; i < numShared; i = nexti) {
01554             int beingRemoved;
01555 
01556             shared = sharedList + i;
01557 
01558             /* Find the end of the files in the other package. */
01559             for (nexti = i + 1; nexti < numShared; nexti++) {
01560                 if (sharedList[nexti].otherPkg != shared->otherPkg)
01561                     /*@innerbreak@*/ break;
01562             }
01563 
01564             /* Is this file from a package being removed? */
01565             beingRemoved = 0;
01566             if (ts->removedPackages != NULL)
01567             for (j = 0; j < ts->numRemovedPackages; j++) {
01568                 if (ts->removedPackages[j] != shared->otherPkg)
01569                     /*@innercontinue@*/ continue;
01570                 beingRemoved = 1;
01571                 /*@innerbreak@*/ break;
01572             }
01573 
01574             /* Determine the fate of each file. */
01575             switch (rpmteType(p)) {
01576             case TR_ADDED:
01577                 xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
01578         !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
01579                 /*@switchbreak@*/ break;
01580             case TR_REMOVED:
01581                 if (!beingRemoved)
01582                     xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
01583                 /*@switchbreak@*/ break;
01584             }
01585         }
01586 /*@=nullpass@*/
01587 
01588         free(sharedList);
01589 
01590         /* Update disk space needs on each partition for this package. */
01591 /*@-nullpass@*/
01592         handleOverlappedFiles(ts, p, fi);
01593 /*@=nullpass@*/
01594 
01595         /* Check added package has sufficient space on each partition used. */
01596         switch (rpmteType(p)) {
01597         case TR_ADDED:
01598             rpmtsCheckDSIProblems(ts, p);
01599             /*@switchbreak@*/ break;
01600         case TR_REMOVED:
01601             /*@switchbreak@*/ break;
01602         }
01603         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01604     }
01605 /*@=nullpass@*/
01606     pi = rpmtsiFree(pi);
01607     ps = rpmpsFree(ps);
01608 
01609     if (rpmtsChrootDone(ts)) {
01610         const char * rootDir = rpmtsRootDir(ts);
01611         const char * currDir = rpmtsCurrDir(ts);
01612         /*@-modobserver@*/
01613         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
01614             xx = Chroot(".");
01615         /*@=modobserver@*/
01616         (void) rpmtsSetChrootDone(ts, 0);
01617         if (currDir != NULL)
01618             xx = Chdir(currDir);
01619     }
01620 
01621     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount,
01622         NULL, ts->notifyData));
01623 
01624     /* ===============================================
01625      * Free unused memory as soon as possible.
01626      */
01627     pi = rpmtsiInit(ts);
01628     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01629         if (p->isSource) continue;
01630         if ((fi = rpmtsiFi(pi)) == NULL)
01631             continue;   /* XXX can't happen */
01632         if (rpmfiFC(fi) == 0)
01633             continue;
01634         fi->fps = _free(fi->fps);
01635     }
01636     pi = rpmtsiFree(pi);
01637 
01638     fpc = fpCacheFree(fpc);
01639     ts->ht = htFree(ts->ht);
01640 
01641     /* ===============================================
01642      * If unfiltered problems exist, free memory and return.
01643      */
01644     if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
01645      || (rpmpsNumProblems(ts->probs) &&
01646                 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
01647        )
01648     {
01649         lock = rpmtsFreeLock(lock);
01650         return ts->orderCount;
01651     }
01652 
01653     /* ===============================================
01654      * Save removed files before erasing.
01655      */
01656     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
01657         int progress;
01658 
01659         progress = 0;
01660         pi = rpmtsiInit(ts);
01661         while ((p = rpmtsiNext(pi, 0)) != NULL) {
01662 
01663             (void) rpmdbCheckSignals();
01664 
01665             if (p->isSource) continue;
01666             if ((fi = rpmtsiFi(pi)) == NULL)
01667                 continue;       /* XXX can't happen */
01668             switch (rpmteType(p)) {
01669             case TR_ADDED:
01670                 /*@switchbreak@*/ break;
01671             case TR_REMOVED:
01672                 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
01673                     /*@switchbreak@*/ break;
01674                 if (!progress)
01675                     NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START,
01676                                 7, numRemoved, NULL, ts->notifyData));
01677 
01678                 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
01679                         numRemoved, NULL, ts->notifyData));
01680                 progress++;
01681 
01682                 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
01683 
01684         /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
01685                 fi->mapflags |= CPIO_MAP_ABSOLUTE;
01686                 fi->mapflags |= CPIO_MAP_ADDDOT;
01687                 fi->mapflags |= CPIO_ALL_HARDLINKS;
01688                 psm = rpmpsmNew(ts, p, fi);
01689 assert(psm != NULL);
01690                 xx = rpmpsmStage(psm, PSM_PKGSAVE);
01691                 psm = rpmpsmFree(psm);
01692                 fi->mapflags &= ~CPIO_MAP_ABSOLUTE;
01693                 fi->mapflags &= ~CPIO_MAP_ADDDOT;
01694                 fi->mapflags &= ~CPIO_ALL_HARDLINKS;
01695 
01696                 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
01697 
01698                 /*@switchbreak@*/ break;
01699             }
01700         }
01701         pi = rpmtsiFree(pi);
01702         if (progress) {
01703             NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved,
01704                         NULL, ts->notifyData));
01705         }
01706     }
01707 
01708     /* ===============================================
01709      * Install and remove packages.
01710      */
01711 /*@-nullpass@*/
01712     pi = rpmtsiInit(ts);
01713     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01714         alKey pkgKey;
01715         int gotfd;
01716 
01717         (void) rpmdbCheckSignals();
01718 
01719         gotfd = 0;
01720         if ((fi = rpmtsiFi(pi)) == NULL)
01721             continue;   /* XXX can't happen */
01722         
01723         psm = rpmpsmNew(ts, p, fi);
01724 assert(psm != NULL);
01725         psm->unorderedSuccessor =
01726                 (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
01727 
01728         switch (rpmteType(p)) {
01729         case TR_ADDED:
01730             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
01731 
01732             pkgKey = rpmteAddedKey(p);
01733 
01734             rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
01735                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01736 
01737             p->h = NULL;
01738             /*@-type@*/ /* FIX: rpmte not opaque */
01739             {
01740                 /*@-noeffectuncon@*/ /* FIX: notify annotations */
01741                 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01742                                 rpmteKey(p), ts->notifyData);
01743                 /*@=noeffectuncon@*/
01744                 if (rpmteFd(p) != NULL) {
01745                     rpmVSFlags ovsflags = rpmtsVSFlags(ts);
01746                     rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
01747                     rpmRC rpmrc;
01748 
01749                     ovsflags = rpmtsSetVSFlags(ts, vsflags);
01750                     rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
01751                                 rpmteNEVR(p), &p->h);
01752                     vsflags = rpmtsSetVSFlags(ts, ovsflags);
01753 
01754                     switch (rpmrc) {
01755                     default:
01756                         /*@-noeffectuncon@*/ /* FIX: notify annotations */
01757                         p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
01758                                         0, 0,
01759                                         rpmteKey(p), ts->notifyData);
01760                         /*@=noeffectuncon@*/
01761                         p->fd = NULL;
01762                         ourrc++;
01763                         /*@innerbreak@*/ break;
01764                     case RPMRC_NOTTRUSTED:
01765                     case RPMRC_NOKEY:
01766                     case RPMRC_OK:
01767                         /*@innerbreak@*/ break;
01768                     }
01769                     if (rpmteFd(p) != NULL) gotfd = 1;
01770                 }
01771             }
01772             /*@=type@*/
01773 
01774             if (rpmteFd(p) != NULL) {
01775                 /*
01776                  * XXX Sludge necessary to tranfer existing fstates/actions
01777                  * XXX around a recreated file info set.
01778                  */
01779                 psm->fi = rpmfiFree(psm->fi);
01780                 {
01781                     uint8_t * fstates = fi->fstates;
01782                     fileAction * actions = fi->actions;
01783                     int mapflags = fi->mapflags;
01784                     rpmte savep;
01785                     int scareMem = 0;
01786 
01787                     fi->fstates = NULL;
01788                     fi->actions = NULL;
01789 /*@-nullstate@*/ /* FIX: fi->actions is NULL */
01790                     fi = rpmfiFree(fi);
01791 /*@=nullstate@*/
01792 
01793                     savep = rpmtsSetRelocateElement(ts, p);
01794                     fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
01795                     (void) rpmtsSetRelocateElement(ts, savep);
01796 
01797                     if (fi != NULL) {   /* XXX can't happen */
01798                         fi->te = p;
01799                         fi->fstates = _free(fi->fstates);
01800                         fi->fstates = fstates;
01801                         fi->actions = _free(fi->actions);
01802                         fi->actions = actions;
01803                         if (mapflags & CPIO_SBIT_CHECK)
01804                             fi->mapflags |= CPIO_SBIT_CHECK;
01805                         p->fi = fi;
01806                     }
01807                 }
01808                 psm->fi = rpmfiLink(p->fi, NULL);
01809 
01810                 if ((xx = rpmpsmStage(psm, PSM_PKGINSTALL)) != 0) {
01811                     ourrc++;
01812                     xx = markLinkedFailed(ts, p);
01813                 } else
01814                     p->done = 1;
01815 
01816             } else {
01817                 ourrc++;
01818             }
01819 
01820             if (gotfd) {
01821                 /*@-noeffectuncon @*/ /* FIX: check rc */
01822                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01823                         rpmteKey(p), ts->notifyData);
01824                 /*@=noeffectuncon @*/
01825                 /*@-type@*/
01826                 p->fd = NULL;
01827                 /*@=type@*/
01828             }
01829 
01830             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
01831 
01832             /*@switchbreak@*/ break;
01833 
01834         case TR_REMOVED:
01835             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
01836 
01837             rpmlog(RPMLOG_DEBUG, "========== --- %s %s-%s 0x%x\n",
01838                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01839 
01840             /* If linked element install failed, then don't erase. */
01841             if (p->linkFailed == 0) {
01842                 if ((xx != rpmpsmStage(psm, PSM_PKGERASE)) != 0) {
01843                     ourrc++;
01844                 } else
01845                     p->done = 1;
01846             } else
01847                 ourrc++;
01848 
01849             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
01850 
01851             /*@switchbreak@*/ break;
01852         }
01853 
01854         /* Would have freed header above in TR_ADD portion of switch
01855          * but needed the header to add it to the autorollback transaction.
01856          */
01857         if (rpmteType(p) == TR_ADDED)
01858             p->h = headerFree(p->h);
01859 
01860         xx = rpmdbSync(rpmtsGetRdb(ts));
01861 
01862 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
01863         psm = rpmpsmFree(psm);
01864 /*@=nullstate@*/
01865 
01866         /* If we received an error, lets break out and rollback, provided
01867          * autorollback is enabled.
01868          */
01869         if (ourrc && rollbackFailures) {
01870             xx = rpmtsRollback(ts, ignoreSet, 1, p);
01871             break;
01872         }
01873     }
01874 /*@=nullpass@*/
01875     pi = rpmtsiFree(pi);
01876 
01877     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
01878         rpmlog(RPMLOG_DEBUG, D_("running post-transaction scripts\n"));
01879         pi = rpmtsiInit(ts);
01880         while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01881             int haspostscript;
01882 
01883             if ((fi = rpmtsiFi(pi)) == NULL)
01884                 continue;       /* XXX can't happen */
01885 
01886             haspostscript = (fi->posttrans != NULL ? 1 : 0);
01887             p->fi = rpmfiFree(p->fi);
01888 
01889             /* If no post-transaction script, then don't bother. */
01890             if (!haspostscript)
01891                 continue;
01892 
01893             p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01894                         rpmteKey(p), ts->notifyData);
01895             p->h = NULL;
01896             if (rpmteFd(p) != NULL) {
01897                 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
01898                 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
01899                 rpmRC rpmrc;
01900                 ovsflags = rpmtsSetVSFlags(ts, vsflags);
01901                 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
01902                         rpmteNEVR(p), &p->h);
01903                 vsflags = rpmtsSetVSFlags(ts, ovsflags);
01904                 switch (rpmrc) {
01905                 default:
01906                     p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
01907                                 0, 0, rpmteKey(p), ts->notifyData);
01908                     p->fd = NULL;
01909                     /*@switchbreak@*/ break;
01910                 case RPMRC_NOTTRUSTED:
01911                 case RPMRC_NOKEY:
01912                 case RPMRC_OK:
01913                     /*@switchbreak@*/ break;
01914                 }
01915             }
01916 
01917 /*@-nullpass@*/
01918             if (rpmteFd(p) != NULL) {
01919                 int scareMem = 0;
01920                 p->fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
01921                 if (p->fi != NULL)      /* XXX can't happen */
01922                     p->fi->te = p;
01923 /*@-compdef -usereleased@*/     /* p->fi->te undefined */
01924                 psm = rpmpsmNew(ts, p, p->fi);
01925 /*@=compdef =usereleased@*/
01926 assert(psm != NULL);
01927                 psm->stepName = "posttrans";
01928                 psm->scriptTag = RPMTAG_POSTTRANS;
01929                 psm->progTag = RPMTAG_POSTTRANSPROG;
01930                 xx = rpmpsmStage(psm, PSM_SCRIPT);
01931                 psm = rpmpsmFree(psm);
01932 
01933 /*@-noeffectuncon -compdef -usereleased @*/
01934                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01935                               rpmteKey(p), ts->notifyData);
01936 /*@=noeffectuncon =compdef =usereleased @*/
01937                 p->fd = NULL;
01938                 p->fi = rpmfiFree(p->fi);
01939                 p->h = headerFree(p->h);
01940             }
01941 /*@=nullpass@*/
01942         }
01943         pi = rpmtsiFree(pi);
01944     }
01945 
01946     lock = rpmtsFreeLock(lock);
01947 
01948     /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
01949     if (ourrc)
01950         return -1;
01951     else
01952         return 0;
01953     /*@=nullstate@*/
01954 }

Generated on Mon Nov 29 2010 05:18:45 for rpm by  doxygen 1.7.2