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

- File List
- Globals

# lib/transaction.c

Go to the documentation of this file.

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