rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/transaction.c
Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio.h>
    00008 #include <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 }