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

lib/transaction.c

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

Generated on Tue Dec 27 22:41:26 2016 for rpm by  doxygen 1.4.4