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

Generated on Sat Oct 1 17:48:07 2011 for rpm by  doxygen 1.4.4