rpm 5.2.1

lib/transaction.c

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