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

lib/transaction.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include <rpmlib.h>
00007 
00008 #include <rpmmacro.h>   /* XXX for rpmExpand */
00009 
00010 #include "fsm.h"
00011 #include "psm.h"
00012 
00013 #include "rpmdb.h"
00014 
00015 #include "rpmds.h"
00016 
00017 #define _RPMFI_INTERNAL
00018 #include "rpmfi.h"
00019 
00020 #define _RPMTE_INTERNAL
00021 #include "rpmte.h"
00022 
00023 #define _RPMTS_INTERNAL
00024 #include "rpmts.h"
00025 
00026 #include "cpio.h"
00027 #include "fprint.h"
00028 #include "legacy.h"     /* XXX domd5 */
00029 #include "misc.h" /* XXX stripTrailingChar, splitString, currentDirectory */
00030 
00031 #include "debug.h"
00032 
00033 /*@access Header @*/            /* XXX ts->notify arg1 is void ptr */
00034 /*@access rpmps @*/     /* XXX need rpmProblemSetOK() */
00035 /*@access dbiIndexSet @*/
00036 
00037 /*@access rpmpsm @*/
00038 
00039 /*@access alKey @*/
00040 /*@access fnpyKey @*/
00041 
00042 /*@access rpmfi @*/
00043 
00044 /*@access rpmte @*/
00045 /*@access rpmtsi @*/
00046 /*@access rpmts @*/
00047 
00050 static int archOkay(/*@null@*/ const char * pkgArch)
00051         /*@*/
00052 {
00053     if (pkgArch == NULL) return 0;
00054     return (rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch) ? 1 : 0);
00055 }
00056 
00059 static int osOkay(/*@null@*/ const char * pkgOs)
00060         /*@*/
00061 {
00062     if (pkgOs == NULL) return 0;
00063     return (rpmMachineScore(RPM_MACHTABLE_INSTOS, pkgOs) ? 1 : 0);
00064 }
00065 
00068 static int sharedCmp(const void * one, const void * two)
00069         /*@*/
00070 {
00071     sharedFileInfo a = (sharedFileInfo) one;
00072     sharedFileInfo b = (sharedFileInfo) two;
00073 
00074     if (a->otherPkg < b->otherPkg)
00075         return -1;
00076     else if (a->otherPkg > b->otherPkg)
00077         return 1;
00078 
00079     return 0;
00080 }
00081 
00090 /* XXX only ts->{probs,rpmdb} modified */
00091 /*@-bounds@*/
00092 static int handleInstInstalledFiles(const rpmts ts,
00093                 rpmte p, rpmfi fi,
00094                 sharedFileInfo shared,
00095                 int sharedCount, int reportConflicts)
00096         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00097         /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
00098 {
00099     uint_32 tscolor = rpmtsColor(ts);
00100     uint_32 otecolor, tecolor;
00101     uint_32 oFColor, FColor;
00102     const char * altNEVR = NULL;
00103     rpmfi otherFi = NULL;
00104     int numReplaced = 0;
00105     rpmps ps;
00106     int i;
00107 
00108     {   rpmdbMatchIterator mi;
00109         Header h;
00110         int scareMem = 0;
00111 
00112         mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
00113                         &shared->otherPkg, sizeof(shared->otherPkg));
00114         while ((h = rpmdbNextIterator(mi)) != NULL) {
00115             altNEVR = hGetNEVR(h, NULL);
00116             otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00117             break;
00118         }
00119         mi = rpmdbFreeIterator(mi);
00120     }
00121 
00122     /* Compute package color. */
00123     tecolor = rpmteColor(p);
00124     tecolor &= tscolor;
00125 
00126     /* Compute other pkg color. */
00127     otecolor = 0;
00128     otherFi = rpmfiInit(otherFi, 0);
00129     if (otherFi != NULL)
00130     while (rpmfiNext(otherFi) >= 0)
00131         otecolor |= rpmfiFColor(otherFi);
00132     otecolor &= tscolor;
00133 
00134     if (otherFi == NULL)
00135         return 1;
00136 
00137     fi->replaced = xcalloc(sharedCount, sizeof(*fi->replaced));
00138 
00139     ps = rpmtsProblems(ts);
00140     for (i = 0; i < sharedCount; i++, shared++) {
00141         int otherFileNum, fileNum;
00142         int isCfgFile;
00143 
00144         otherFileNum = shared->otherFileNum;
00145         (void) rpmfiSetFX(otherFi, otherFileNum);
00146         oFColor = rpmfiFColor(otherFi);
00147         oFColor &= tscolor;
00148 
00149         fileNum = shared->pkgFileNum;
00150         (void) rpmfiSetFX(fi, fileNum);
00151         FColor = rpmfiFColor(fi);
00152         FColor &= tscolor;
00153 
00154         isCfgFile = ((rpmfiFFlags(otherFi) | rpmfiFFlags(fi)) & RPMFILE_CONFIG);
00155 
00156 #ifdef  DYING
00157         /* XXX another tedious segfault, assume file state normal. */
00158         if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00159             continue;
00160 #endif
00161 
00162         if (XFA_SKIPPING(fi->actions[fileNum]))
00163             continue;
00164 
00165         if (rpmfiCompare(otherFi, fi)) {
00166 
00167             /* Resolve file conflicts to prefer Elf64 (if not forced). */
00168             if (tscolor != 0 && FColor != 0 && FColor != oFColor
00169              && reportConflicts)
00170             {
00171                 if (oFColor & 0x2) {
00172                     fi->actions[fileNum] = FA_SKIP;
00173                     reportConflicts = 0;
00174                 } else
00175                 if (FColor & 0x2) {
00176                     fi->actions[fileNum] = FA_CREATE;
00177                     reportConflicts = 0;
00178                 }
00179             }
00180 
00181             if (reportConflicts) {
00182                 rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
00183                         rpmteNEVR(p), rpmteKey(p),
00184                         rpmfiDN(fi), rpmfiBN(fi),
00185                         altNEVR,
00186                         0);
00187             }
00188             /* Save file identifier to mark as state REPLACED. */
00189             if ( !(isCfgFile || XFA_SKIPPING(fi->actions[fileNum])) ) {
00190                 /*@-assignexpose@*/ /* FIX: p->replaced, not fi */
00191                 if (!shared->isRemoved)
00192                     fi->replaced[numReplaced++] = *shared;
00193                 /*@=assignexpose@*/
00194             }
00195         }
00196 
00197         /* Determine config file dispostion, skipping missing files (if any). */
00198         if (isCfgFile) {
00199             int skipMissing =
00200                 ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
00201             fileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
00202             fi->actions[fileNum] = action;
00203         }
00204         fi->replacedSizes[fileNum] = rpmfiFSize(otherFi);
00205     }
00206     ps = rpmpsFree(ps);
00207 
00208     altNEVR = _free(altNEVR);
00209     otherFi = rpmfiFree(otherFi);
00210 
00211     fi->replaced = xrealloc(fi->replaced,       /* XXX memory leak */
00212                            sizeof(*fi->replaced) * (numReplaced + 1));
00213     fi->replaced[numReplaced].otherPkg = 0;
00214 
00215     return 0;
00216 }
00217 /*@=bounds@*/
00218 
00221 /* XXX only ts->rpmdb modified */
00222 static int handleRmvdInstalledFiles(const rpmts ts, rpmfi fi,
00223                 sharedFileInfo shared, int sharedCount)
00224         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00225         /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
00226 {
00227     HGE_t hge = fi->hge;
00228     Header h;
00229     const char * otherStates;
00230     int i, xx;
00231    
00232     rpmdbMatchIterator mi;
00233 
00234     mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
00235                         &shared->otherPkg, sizeof(shared->otherPkg));
00236     h = rpmdbNextIterator(mi);
00237     if (h == NULL) {
00238         mi = rpmdbFreeIterator(mi);
00239         return 1;
00240     }
00241 
00242     xx = hge(h, RPMTAG_FILESTATES, NULL, (void **) &otherStates, NULL);
00243 
00244 /*@-boundswrite@*/
00245     for (i = 0; i < sharedCount; i++, shared++) {
00246         int otherFileNum, fileNum;
00247         otherFileNum = shared->otherFileNum;
00248         fileNum = shared->pkgFileNum;
00249 
00250         if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00251             continue;
00252 
00253         fi->actions[fileNum] = FA_SKIP;
00254     }
00255 /*@=boundswrite@*/
00256 
00257     mi = rpmdbFreeIterator(mi);
00258 
00259     return 0;
00260 }
00261 
00262 #define ISROOT(_d)      (((_d)[0] == '/' && (_d)[1] == '\0') ? "" : (_d))
00263 
00264 /*@unchecked@*/
00265 int _fps_debug = 0;
00266 
00267 static int fpsCompare (const void * one, const void * two)
00268         /*@*/
00269 {
00270     const struct fingerPrint_s * a = (const struct fingerPrint_s *)one;
00271     const struct fingerPrint_s * b = (const struct fingerPrint_s *)two;
00272     int adnlen = strlen(a->entry->dirName);
00273     int asnlen = (a->subDir ? strlen(a->subDir) : 0);
00274     int abnlen = strlen(a->baseName);
00275     int bdnlen = strlen(b->entry->dirName);
00276     int bsnlen = (b->subDir ? strlen(b->subDir) : 0);
00277     int bbnlen = strlen(b->baseName);
00278     char * afn, * bfn, * t;
00279     int rc = 0;
00280 
00281     if (adnlen == 1 && asnlen != 0) adnlen = 0;
00282     if (bdnlen == 1 && bsnlen != 0) bdnlen = 0;
00283 
00284 /*@-boundswrite@*/
00285     afn = t = alloca(adnlen+asnlen+abnlen+2);
00286     if (adnlen) t = stpcpy(t, a->entry->dirName);
00287     *t++ = '/';
00288     if (a->subDir && asnlen) t = stpcpy(t, a->subDir);
00289     if (abnlen) t = stpcpy(t, a->baseName);
00290     if (afn[0] == '/' && afn[1] == '/') afn++;
00291 
00292     bfn = t = alloca(bdnlen+bsnlen+bbnlen+2);
00293     if (bdnlen) t = stpcpy(t, b->entry->dirName);
00294     *t++ = '/';
00295     if (b->subDir && bsnlen) t = stpcpy(t, b->subDir);
00296     if (bbnlen) t = stpcpy(t, b->baseName);
00297     if (bfn[0] == '/' && bfn[1] == '/') bfn++;
00298 /*@=boundswrite@*/
00299 
00300     rc = strcmp(afn, bfn);
00301 /*@-modfilesys@*/
00302 if (_fps_debug)
00303 fprintf(stderr, "\trc(%d) = strcmp(\"%s\", \"%s\")\n", rc, afn, bfn);
00304 /*@=modfilesys@*/
00305 
00306 /*@-modfilesys@*/
00307 if (_fps_debug)
00308 fprintf(stderr, "\t%s/%s%s\trc %d\n",
00309 ISROOT(b->entry->dirName),
00310 (b->subDir ? b->subDir : ""),
00311 b->baseName,
00312 rc
00313 );
00314 /*@=modfilesys@*/
00315 
00316     return rc;
00317 }
00318 
00319 /*@unchecked@*/
00320 static int _linear_fps_search = 0;
00321 
00322 static int findFps(const struct fingerPrint_s * fiFps,
00323                 const struct fingerPrint_s * otherFps,
00324                 int otherFc)
00325         /*@*/
00326 {
00327     int otherFileNum;
00328 
00329 /*@-modfilesys@*/
00330 if (_fps_debug)
00331 fprintf(stderr, "==> %s/%s%s\n",
00332 ISROOT(fiFps->entry->dirName),
00333 (fiFps->subDir ? fiFps->subDir : ""),
00334 fiFps->baseName);
00335 /*@=modfilesys@*/
00336 
00337   if (_linear_fps_search) {
00338 
00339 linear:
00340     for (otherFileNum = 0; otherFileNum < otherFc; otherFileNum++, otherFps++) {
00341 
00342 /*@-modfilesys@*/
00343 if (_fps_debug)
00344 fprintf(stderr, "\t%4d %s/%s%s\n", otherFileNum,
00345 ISROOT(otherFps->entry->dirName),
00346 (otherFps->subDir ? otherFps->subDir : ""),
00347 otherFps->baseName);
00348 /*@=modfilesys@*/
00349 
00350         /* If the addresses are the same, so are the values. */
00351         if (fiFps == otherFps)
00352             break;
00353 
00354         /* Otherwise, compare fingerprints by value. */
00355         /*@-nullpass@*/ /* LCL: looks good to me */
00356         if (FP_EQUAL((*fiFps), (*otherFps)))
00357             break;
00358         /*@=nullpass@*/
00359     }
00360 
00361 if (otherFileNum == otherFc) {
00362 /*@-modfilesys@*/
00363 if (_fps_debug)
00364 fprintf(stderr, "*** FP_EQUAL NULL %s/%s%s\n",
00365 ISROOT(fiFps->entry->dirName),
00366 (fiFps->subDir ? fiFps->subDir : ""),
00367 fiFps->baseName);
00368 /*@=modfilesys@*/
00369 }
00370 
00371     return otherFileNum;
00372 
00373   } else {
00374 
00375     const struct fingerPrint_s * bingoFps;
00376 
00377 /*@-boundswrite@*/
00378     bingoFps = bsearch(fiFps, otherFps, otherFc, sizeof(*otherFps), fpsCompare);
00379 /*@=boundswrite@*/
00380     if (bingoFps == NULL) {
00381 /*@-modfilesys@*/
00382 if (_fps_debug)
00383 fprintf(stderr, "*** bingoFps NULL %s/%s%s\n",
00384 ISROOT(fiFps->entry->dirName),
00385 (fiFps->subDir ? fiFps->subDir : ""),
00386 fiFps->baseName);
00387 /*@=modfilesys@*/
00388         goto linear;
00389     }
00390 
00391     /* If the addresses are the same, so are the values. */
00392     /*@-nullpass@*/     /* LCL: looks good to me */
00393     if (!(fiFps == bingoFps || FP_EQUAL((*fiFps), (*bingoFps)))) {
00394 /*@-modfilesys@*/
00395 if (_fps_debug)
00396 fprintf(stderr, "***  BAD %s/%s%s\n",
00397 ISROOT(bingoFps->entry->dirName),
00398 (bingoFps->subDir ? bingoFps->subDir : ""),
00399 bingoFps->baseName);
00400 /*@=modfilesys@*/
00401         goto linear;
00402     }
00403 
00404     otherFileNum = (bingoFps != NULL ? (bingoFps - otherFps) : 0);
00405 
00406   }
00407 
00408     return otherFileNum;
00409 }
00410 
00414 /* XXX only ts->{probs,di} modified */
00415 static void handleOverlappedFiles(const rpmts ts,
00416                 const rpmte p, rpmfi fi)
00417         /*@globals h_errno, fileSystem, internalState @*/
00418         /*@modifies ts, fi, fileSystem, internalState @*/
00419 {
00420     uint_32 fixupSize = 0;
00421     rpmps ps;
00422     const char * fn;
00423     int i, j;
00424   
00425     ps = rpmtsProblems(ts);
00426     fi = rpmfiInit(fi, 0);
00427     if (fi != NULL)
00428     while ((i = rpmfiNext(fi)) >= 0) {
00429         uint_32 tscolor = rpmtsColor(ts);
00430         uint_32 oFColor, FColor;
00431         struct fingerPrint_s * fiFps;
00432         int otherPkgNum, otherFileNum;
00433         rpmfi otherFi;
00434         int_32 FFlags;
00435         int_16 FMode;
00436         const rpmfi * recs;
00437         int numRecs;
00438 
00439         if (XFA_SKIPPING(fi->actions[i]))
00440             continue;
00441 
00442         fn = rpmfiFN(fi);
00443         fiFps = fi->fps + i;
00444         FFlags = rpmfiFFlags(fi);
00445         FMode = rpmfiFMode(fi);
00446         FColor = rpmfiFColor(fi);
00447         FColor &= tscolor;
00448 
00449         fixupSize = 0;
00450 
00451         /*
00452          * Retrieve all records that apply to this file. Note that the
00453          * file info records were built in the same order as the packages
00454          * will be installed and removed so the records for an overlapped
00455          * files will be sorted in exactly the same order.
00456          */
00457         (void) htGetEntry(ts->ht, fiFps,
00458                         (const void ***) &recs, &numRecs, NULL);
00459 
00460         /*
00461          * If this package is being added, look only at other packages
00462          * being added -- removed packages dance to a different tune.
00463          *
00464          * If both this and the other package are being added, overlapped
00465          * files must be identical (or marked as a conflict). The
00466          * disposition of already installed config files leads to
00467          * a small amount of extra complexity.
00468          *
00469          * If this package is being removed, then there are two cases that
00470          * need to be worried about:
00471          * If the other package is being added, then skip any overlapped files
00472          * so that this package removal doesn't nuke the overlapped files
00473          * that were just installed.
00474          * If both this and the other package are being removed, then each
00475          * file removal from preceding packages needs to be skipped so that
00476          * the file removal occurs only on the last occurence of an overlapped
00477          * file in the transaction set.
00478          *
00479          */
00480 
00481         /* Locate this overlapped file in the set of added/removed packages. */
00482         for (j = 0; j < numRecs && recs[j] != fi; j++)
00483             {};
00484 
00485         /* Find what the previous disposition of this file was. */
00486         otherFileNum = -1;                      /* keep gcc quiet */
00487         otherFi = NULL;
00488         for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
00489             struct fingerPrint_s * otherFps;
00490             int otherFc;
00491 
00492             otherFi = recs[otherPkgNum];
00493 
00494             /* Added packages need only look at other added packages. */
00495             if (rpmteType(p) == TR_ADDED && rpmteType(otherFi->te) != TR_ADDED)
00496                 /*@innercontinue@*/ continue;
00497 
00498             otherFps = otherFi->fps;
00499             otherFc = rpmfiFC(otherFi);
00500 
00501             otherFileNum = findFps(fiFps, otherFps, otherFc);
00502             (void) rpmfiSetFX(otherFi, otherFileNum);
00503 
00504             /* XXX Happens iff fingerprint for incomplete package install. */
00505             if (otherFi->actions[otherFileNum] != FA_UNKNOWN)
00506                 /*@innerbreak@*/ break;
00507         }
00508 
00509         oFColor = rpmfiFColor(otherFi);
00510         oFColor &= tscolor;
00511 
00512 /*@-boundswrite@*/
00513         switch (rpmteType(p)) {
00514         case TR_ADDED:
00515           { struct stat sb;
00516             int reportConflicts =
00517                 !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
00518             int done = 0;
00519 
00520             if (otherPkgNum < 0) {
00521                 /* XXX is this test still necessary? */
00522                 if (fi->actions[i] != FA_UNKNOWN)
00523                     /*@switchbreak@*/ break;
00524                 if ((FFlags & RPMFILE_CONFIG) && !lstat(fn, &sb)) {
00525                     /* Here is a non-overlapped pre-existing config file. */
00526                     fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
00527                         ? FA_ALTNAME : FA_BACKUP;
00528                 } else {
00529                     fi->actions[i] = FA_CREATE;
00530                 }
00531                 /*@switchbreak@*/ break;
00532             }
00533 
00534 assert(otherFi != NULL);
00535             /* Mark added overlapped non-identical files as a conflict. */
00536             if (rpmfiCompare(otherFi, fi)) {
00537 
00538                 /* Resolve file conflicts to prefer Elf64 (if not forced) ... */
00539                 if (tscolor != 0 && reportConflicts) {
00540                     if (FColor & 0x2) {
00541                         /* ... last Elf64 file is installed ... */
00542                         if (!XFA_SKIPPING(fi->actions[i]))
00543                             otherFi->actions[otherFileNum] = FA_SKIP;
00544                         fi->actions[i] = FA_CREATE;
00545                         reportConflicts = 0;
00546                     } else
00547                     if (oFColor & 0x2) {
00548                         /* ... first Elf64 file is installed ... */
00549                         if (XFA_SKIPPING(fi->actions[i]))
00550                             otherFi->actions[otherFileNum] = FA_CREATE;
00551                         fi->actions[i] = FA_SKIP;
00552                         reportConflicts = 0;
00553                     } else
00554                     if (FColor == 0 && oFColor == 0) {
00555                         /* ... otherwise, do both, last in wins. */
00556                         otherFi->actions[otherFileNum] = FA_CREATE;
00557                         fi->actions[i] = FA_CREATE;
00558                         reportConflicts = 0;
00559                     }
00560                     done = 1;
00561                 }
00562 
00563                 if (reportConflicts) {
00564                     rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
00565                         rpmteNEVR(p), rpmteKey(p),
00566                         fn, NULL,
00567                         rpmteNEVR(otherFi->te),
00568                         0);
00569                 }
00570             }
00571 
00572             /* Try to get the disk accounting correct even if a conflict. */
00573             fixupSize = rpmfiFSize(otherFi);
00574 
00575             if ((FFlags & RPMFILE_CONFIG) && !lstat(fn, &sb)) {
00576                 /* Here is an overlapped  pre-existing config file. */
00577                 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
00578                         ? FA_ALTNAME : FA_SKIP;
00579             } else {
00580                 if (!done)
00581                     fi->actions[i] = FA_CREATE;
00582             }
00583           } /*@switchbreak@*/ break;
00584 
00585         case TR_REMOVED:
00586             if (otherPkgNum >= 0) {
00587 assert(otherFi != NULL);
00588                 /* Here is an overlapped added file we don't want to nuke. */
00589                 if (otherFi->actions[otherFileNum] != FA_ERASE) {
00590                     /* On updates, don't remove files. */
00591                     fi->actions[i] = FA_SKIP;
00592                     /*@switchbreak@*/ break;
00593                 }
00594                 /* Here is an overlapped removed file: skip in previous. */
00595                 otherFi->actions[otherFileNum] = FA_SKIP;
00596             }
00597             if (XFA_SKIPPING(fi->actions[i]))
00598                 /*@switchbreak@*/ break;
00599             if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
00600                 /*@switchbreak@*/ break;
00601             if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG))) {
00602                 fi->actions[i] = FA_ERASE;
00603                 /*@switchbreak@*/ break;
00604             }
00605                 
00606             /* Here is a pre-existing modified config file that needs saving. */
00607             {   char md5sum[50];
00608                 const unsigned char * MD5 = rpmfiMD5(fi);
00609                 if (!domd5(fn, md5sum, 0, NULL) && memcmp(MD5, md5sum, 16)) {
00610                     fi->actions[i] = FA_BACKUP;
00611                     /*@switchbreak@*/ break;
00612                 }
00613             }
00614             fi->actions[i] = FA_ERASE;
00615             /*@switchbreak@*/ break;
00616         }
00617 /*@=boundswrite@*/
00618 
00619         /* Update disk space info for a file. */
00620         rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
00621                 fi->replacedSizes[i], fixupSize, fi->actions[i]);
00622 
00623     }
00624     ps = rpmpsFree(ps);
00625 }
00626 
00634 static int ensureOlder(rpmts ts,
00635                 const rpmte p, const Header h)
00636         /*@modifies ts @*/
00637 {
00638     int_32 reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
00639     const char * reqEVR;
00640     rpmds req;
00641     char * t;
00642     int nb;
00643     int rc;
00644 
00645     if (p == NULL || h == NULL)
00646         return 1;
00647 
00648 /*@-boundswrite@*/
00649     nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1;
00650     t = alloca(nb);
00651     *t = '\0';
00652     reqEVR = t;
00653     if (rpmteE(p) != NULL)      t = stpcpy( stpcpy(t, rpmteE(p)), ":");
00654     if (rpmteV(p) != NULL)      t = stpcpy(t, rpmteV(p));
00655     *t++ = '-';
00656     if (rpmteR(p) != NULL)      t = stpcpy(t, rpmteR(p));
00657 /*@=boundswrite@*/
00658     
00659     req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
00660     rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
00661     req = rpmdsFree(req);
00662 
00663     if (rc == 0) {
00664         rpmps ps = rpmtsProblems(ts);
00665         const char * altNEVR = hGetNEVR(h, NULL);
00666         rpmpsAppend(ps, RPMPROB_OLDPACKAGE,
00667                 rpmteNEVR(p), rpmteKey(p),
00668                 NULL, NULL,
00669                 altNEVR,
00670                 0);
00671         altNEVR = _free(altNEVR);
00672         ps = rpmpsFree(ps);
00673         rc = 1;
00674     } else
00675         rc = 0;
00676 
00677     return rc;
00678 }
00679 
00685 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
00686 /*@-bounds@*/
00687 static void skipFiles(const rpmts ts, rpmfi fi)
00688         /*@globals rpmGlobalMacroContext, h_errno @*/
00689         /*@modifies fi, rpmGlobalMacroContext @*/
00690 {
00691     uint_32 tscolor = rpmtsColor(ts);
00692     uint_32 FColor;
00693     int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
00694     int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
00695     char ** netsharedPaths = NULL;
00696     const char ** languages;
00697     const char * dn, * bn;
00698     int dnlen, bnlen, ix;
00699     const char * s;
00700     int * drc;
00701     char * dff;
00702     int dc;
00703     int i, j;
00704 
00705     if (!noDocs)
00706         noDocs = rpmExpandNumeric("%{_excludedocs}");
00707 
00708     {   const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL);
00709         /*@-branchstate@*/
00710         if (tmpPath && *tmpPath != '%')
00711             netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
00712         /*@=branchstate@*/
00713         tmpPath = _free(tmpPath);
00714     }
00715 
00716     s = rpmExpand("%{_install_langs}", NULL);
00717     /*@-branchstate@*/
00718     if (!(s && *s != '%'))
00719         s = _free(s);
00720     if (s) {
00721         languages = (const char **) splitString(s, strlen(s), ':');
00722         s = _free(s);
00723     } else
00724         languages = NULL;
00725     /*@=branchstate@*/
00726 
00727     /* Compute directory refcount, skip directory if now empty. */
00728     dc = rpmfiDC(fi);
00729     drc = alloca(dc * sizeof(*drc));
00730     memset(drc, 0, dc * sizeof(*drc));
00731     dff = alloca(dc * sizeof(*dff));
00732     memset(dff, 0, dc * sizeof(*dff));
00733 
00734     fi = rpmfiInit(fi, 0);
00735     if (fi != NULL)     /* XXX lclint */
00736     while ((i = rpmfiNext(fi)) >= 0)
00737     {
00738         char ** nsp;
00739 
00740         bn = rpmfiBN(fi);
00741         bnlen = strlen(bn);
00742         ix = rpmfiDX(fi);
00743         dn = rpmfiDN(fi);
00744         dnlen = strlen(dn);
00745         if (dn == NULL)
00746             continue;   /* XXX can't happen */
00747 
00748         drc[ix]++;
00749 
00750         /* Don't bother with skipped files */
00751         if (XFA_SKIPPING(fi->actions[i])) {
00752             drc[ix]--; dff[ix] = 1;
00753             continue;
00754         }
00755 
00756         /* Ignore colored files not in our rainbow. */
00757         FColor = rpmfiFColor(fi);
00758         if (tscolor && FColor && !(tscolor & FColor)) {
00759             drc[ix]--;  dff[ix] = 1;
00760             fi->actions[i] = FA_SKIPCOLOR;
00761             continue;
00762         }
00763 
00764         /*
00765          * Skip net shared paths.
00766          * Net shared paths are not relative to the current root (though
00767          * they do need to take package relocations into account).
00768          */
00769         for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
00770             int len;
00771 
00772             len = strlen(*nsp);
00773             if (dnlen >= len) {
00774                 if (strncmp(dn, *nsp, len))
00775                     /*@innercontinue@*/ continue;
00776                 /* Only directories or complete file paths can be net shared */
00777                 if (!(dn[len] == '/' || dn[len] == '\0'))
00778                     /*@innercontinue@*/ continue;
00779             } else {
00780                 if (len < (dnlen + bnlen))
00781                     /*@innercontinue@*/ continue;
00782                 if (strncmp(dn, *nsp, dnlen))
00783                     /*@innercontinue@*/ continue;
00784                 if (strncmp(bn, (*nsp) + dnlen, bnlen))
00785                     /*@innercontinue@*/ continue;
00786                 len = dnlen + bnlen;
00787                 /* Only directories or complete file paths can be net shared */
00788                 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
00789                     /*@innercontinue@*/ continue;
00790             }
00791 
00792             /*@innerbreak@*/ break;
00793         }
00794 
00795         if (nsp && *nsp) {
00796             drc[ix]--;  dff[ix] = 1;
00797             fi->actions[i] = FA_SKIPNETSHARED;
00798             continue;
00799         }
00800 
00801         /*
00802          * Skip i18n language specific files.
00803          */
00804         if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
00805             const char **lang, *l, *le;
00806             for (lang = languages; *lang != NULL; lang++) {
00807                 if (!strcmp(*lang, "all"))
00808                     /*@innerbreak@*/ break;
00809                 for (l = fi->flangs[i]; *l != '\0'; l = le) {
00810                     for (le = l; *le != '\0' && *le != '|'; le++)
00811                         {};
00812                     if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
00813                         /*@innerbreak@*/ break;
00814                     if (*le == '|') le++;       /* skip over | */
00815                 }
00816                 if (*l != '\0')
00817                     /*@innerbreak@*/ break;
00818             }
00819             if (*lang == NULL) {
00820                 drc[ix]--;      dff[ix] = 1;
00821                 fi->actions[i] = FA_SKIPNSTATE;
00822                 continue;
00823             }
00824         }
00825 
00826         /*
00827          * Skip config files if requested.
00828          */
00829         if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
00830             drc[ix]--;  dff[ix] = 1;
00831             fi->actions[i] = FA_SKIPNSTATE;
00832             continue;
00833         }
00834 
00835         /*
00836          * Skip documentation if requested.
00837          */
00838         if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
00839             drc[ix]--;  dff[ix] = 1;
00840             fi->actions[i] = FA_SKIPNSTATE;
00841             continue;
00842         }
00843     }
00844 
00845     /* Skip (now empty) directories that had skipped files. */
00846 #ifndef NOTYET
00847     if (fi != NULL)     /* XXX can't happen */
00848     for (j = 0; j < dc; j++)
00849 #else
00850     if ((fi = rpmfiInitD(fi)) != NULL)
00851     while (j = rpmfiNextD(fi) >= 0)
00852 #endif
00853     {
00854 
00855         if (drc[j]) continue;   /* dir still has files. */
00856         if (!dff[j]) continue;  /* dir was not emptied here. */
00857         
00858         /* Find parent directory and basename. */
00859         dn = fi->dnl[j];        dnlen = strlen(dn) - 1;
00860         bn = dn + dnlen;        bnlen = 0;
00861         while (bn > dn && bn[-1] != '/') {
00862                 bnlen++;
00863                 dnlen--;
00864                 bn--;
00865         }
00866 
00867         /* If explicitly included in the package, skip the directory. */
00868         fi = rpmfiInit(fi, 0);
00869         if (fi != NULL)         /* XXX lclint */
00870         while ((i = rpmfiNext(fi)) >= 0) {
00871             const char * fdn, * fbn;
00872             int_16 fFMode;
00873 
00874             if (XFA_SKIPPING(fi->actions[i]))
00875                 /*@innercontinue@*/ continue;
00876 
00877             fFMode = rpmfiFMode(fi);
00878 
00879             if (whatis(fFMode) != XDIR)
00880                 /*@innercontinue@*/ continue;
00881             fdn = rpmfiDN(fi);
00882             if (strlen(fdn) != dnlen)
00883                 /*@innercontinue@*/ continue;
00884             if (strncmp(fdn, dn, dnlen))
00885                 /*@innercontinue@*/ continue;
00886             fbn = rpmfiBN(fi);
00887             if (strlen(fbn) != bnlen)
00888                 /*@innercontinue@*/ continue;
00889             if (strncmp(fbn, bn, bnlen))
00890                 /*@innercontinue@*/ continue;
00891             rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"), dn);
00892             fi->actions[i] = FA_SKIPNSTATE;
00893             /*@innerbreak@*/ break;
00894         }
00895     }
00896 
00897 /*@-dependenttrans@*/
00898     if (netsharedPaths) freeSplitString(netsharedPaths);
00899 #ifdef  DYING   /* XXX freeFi will deal with this later. */
00900     fi->flangs = _free(fi->flangs);
00901 #endif
00902     if (languages) freeSplitString((char **)languages);
00903 /*@=dependenttrans@*/
00904 }
00905 /*@=bounds@*/
00906 /*@=mustmod@*/
00907 
00914 static /*@null@*/
00915 rpmfi rpmtsiFi(const rpmtsi tsi)
00916         /*@*/
00917 {
00918     rpmfi fi = NULL;
00919 
00920     if (tsi != NULL && tsi->ocsave != -1) {
00921         /*@-type -abstract@*/ /* FIX: rpmte not opaque */
00922         rpmte te = rpmtsElement(tsi->ts, tsi->ocsave);
00923         /*@-assignexpose@*/
00924         if (te != NULL && (fi = te->fi) != NULL)
00925             fi->te = te;
00926         /*@=assignexpose@*/
00927         /*@=type =abstract@*/
00928     }
00929     /*@-compdef -refcounttrans -usereleased @*/
00930     return fi;
00931     /*@=compdef =refcounttrans =usereleased @*/
00932 }
00933 
00934 #define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al
00935 
00936 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
00937 {
00938     uint_32 tscolor = rpmtsColor(ts);
00939     int i, j;
00940     int ourrc = 0;
00941     int totalFileCount = 0;
00942     rpmfi fi;
00943     sharedFileInfo shared, sharedList;
00944     int numShared;
00945     int nexti;
00946     alKey lastFailKey;
00947     fingerPrintCache fpc;
00948     rpmps ps;
00949     rpmpsm psm;
00950     rpmtsi pi;  rpmte p;
00951     rpmtsi qi;  rpmte q;
00952     int numAdded;
00953     int numRemoved;
00954     int xx;
00955 
00956     /* XXX programmer error segfault avoidance. */
00957     if (rpmtsNElements(ts) <= 0)
00958         return -1;
00959 
00960     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
00961         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
00962     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
00963         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
00964 
00965     if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
00966         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
00967 
00968     ts->probs = rpmpsFree(ts->probs);
00969     ts->probs = rpmpsCreate();
00970 
00971     /* XXX Make sure the database is open RDWR for package install/erase. */
00972     {   int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
00973                 ? O_RDONLY : (O_RDWR|O_CREAT);
00974 
00975         /* Open database RDWR for installing packages. */
00976         if (rpmtsOpenDB(ts, dbmode))
00977             return -1;  /* XXX W2DO? */
00978     }
00979 
00980     ts->ignoreSet = ignoreSet;
00981     {   const char * currDir = currentDirectory();
00982         rpmtsSetCurrDir(ts, currDir);
00983         currDir = _free(currDir);
00984     }
00985 
00986     (void) rpmtsSetChrootDone(ts, 0);
00987 
00988     {   int_32 tid = (int_32) time(NULL);
00989         (void) rpmtsSetTid(ts, tid);
00990     }
00991 
00992     /* Get available space on mounted file systems. */
00993     xx = rpmtsInitDSI(ts);
00994 
00995     /* ===============================================
00996      * For packages being installed:
00997      * - verify package arch/os.
00998      * - verify package epoch:version-release is newer.
00999      * - count files.
01000      * For packages being removed:
01001      * - count files.
01002      */
01003 
01004 rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts));
01005     ps = rpmtsProblems(ts);
01006     /* The ordering doesn't matter here */
01007     pi = rpmtsiInit(ts);
01008     while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01009         rpmdbMatchIterator mi;
01010         int fc;
01011 
01012         if ((fi = rpmtsiFi(pi)) == NULL)
01013             continue;   /* XXX can't happen */
01014         fc = rpmfiFC(fi);
01015 
01016         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH) && !tscolor)
01017             if (!archOkay(rpmteA(p)))
01018                 rpmpsAppend(ps, RPMPROB_BADARCH,
01019                         rpmteNEVR(p), rpmteKey(p),
01020                         rpmteA(p), NULL,
01021                         NULL, 0);
01022 
01023         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS))
01024             if (!osOkay(rpmteO(p)))
01025                 rpmpsAppend(ps, RPMPROB_BADOS,
01026                         rpmteNEVR(p), rpmteKey(p),
01027                         rpmteO(p), NULL,
01028                         NULL, 0);
01029 
01030         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) {
01031             Header h;
01032             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01033             while ((h = rpmdbNextIterator(mi)) != NULL)
01034                 xx = ensureOlder(ts, p, h);
01035             mi = rpmdbFreeIterator(mi);
01036         }
01037 
01038         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
01039             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01040             xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_DEFAULT,
01041                                 rpmteE(p));
01042             xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_DEFAULT,
01043                                 rpmteV(p));
01044             xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT,
01045                                 rpmteR(p));
01046             if (tscolor) {
01047                 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT,
01048                                 rpmteA(p));
01049                 xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_DEFAULT,
01050                                 rpmteO(p));
01051             }
01052 
01053             while (rpmdbNextIterator(mi) != NULL) {
01054                 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
01055                         rpmteNEVR(p), rpmteKey(p),
01056                         NULL, NULL,
01057                         NULL, 0);
01058                 /*@innerbreak@*/ break;
01059             }
01060             mi = rpmdbFreeIterator(mi);
01061         }
01062 
01063         /* Count no. of files (if any). */
01064         totalFileCount += fc;
01065 
01066     }
01067     pi = rpmtsiFree(pi);
01068     ps = rpmpsFree(ps);
01069 
01070     /* The ordering doesn't matter here */
01071     pi = rpmtsiInit(ts);
01072     while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
01073         int fc;
01074 
01075         if ((fi = rpmtsiFi(pi)) == NULL)
01076             continue;   /* XXX can't happen */
01077         fc = rpmfiFC(fi);
01078 
01079         totalFileCount += fc;
01080     }
01081     pi = rpmtsiFree(pi);
01082 
01083     /* ===============================================
01084      * Initialize transaction element file info for package:
01085      */
01086 
01087     /*
01088      * FIXME?: we'd be better off assembling one very large file list and
01089      * calling fpLookupList only once. I'm not sure that the speedup is
01090      * worth the trouble though.
01091      */
01092 rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount);
01093 
01094     numAdded = numRemoved = 0;
01095     pi = rpmtsiInit(ts);
01096     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01097         int fc;
01098 
01099         if ((fi = rpmtsiFi(pi)) == NULL)
01100             continue;   /* XXX can't happen */
01101         fc = rpmfiFC(fi);
01102 
01103         /*@-branchstate@*/
01104         switch (rpmteType(p)) {
01105         case TR_ADDED:
01106             numAdded++;
01107             fi->record = 0;
01108             /* Skip netshared paths, not our i18n files, and excluded docs */
01109             if (fc > 0)
01110                 skipFiles(ts, fi);
01111             /*@switchbreak@*/ break;
01112         case TR_REMOVED:
01113             numRemoved++;
01114             fi->record = rpmteDBOffset(p);
01115             /*@switchbreak@*/ break;
01116         }
01117         /*@=branchstate@*/
01118 
01119         fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
01120     }
01121     pi = rpmtsiFree(pi);
01122 
01123     if (!rpmtsChrootDone(ts)) {
01124         const char * rootDir = rpmtsRootDir(ts);
01125         xx = chdir("/");
01126         /*@-superuser -noeffect @*/
01127         if (rootDir != NULL)
01128             xx = chroot(rootDir);
01129         /*@=superuser =noeffect @*/
01130         (void) rpmtsSetChrootDone(ts, 1);
01131     }
01132 
01133     ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
01134     fpc = fpCacheCreate(totalFileCount);
01135 
01136     /* ===============================================
01137      * Add fingerprint for each file not skipped.
01138      */
01139     pi = rpmtsiInit(ts);
01140     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01141         int fc;
01142 
01143         (void) rpmdbCheckSignals();
01144 
01145         if ((fi = rpmtsiFi(pi)) == NULL)
01146             continue;   /* XXX can't happen */
01147         fc = rpmfiFC(fi);
01148 
01149         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01150         fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
01151         /*@-branchstate@*/
01152         fi = rpmfiInit(fi, 0);
01153         if (fi != NULL)         /* XXX lclint */
01154         while ((i = rpmfiNext(fi)) >= 0) {
01155             if (XFA_SKIPPING(fi->actions[i]))
01156                 /*@innercontinue@*/ continue;
01157             /*@-dependenttrans@*/
01158             htAddEntry(ts->ht, fi->fps + i, (void *) fi);
01159             /*@=dependenttrans@*/
01160         }
01161         /*@=branchstate@*/
01162         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01163 
01164     }
01165     pi = rpmtsiFree(pi);
01166 
01167     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount,
01168         NULL, ts->notifyData));
01169 
01170     /* ===============================================
01171      * Compute file disposition for each package in transaction set.
01172      */
01173 rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
01174     ps = rpmtsProblems(ts);
01175     pi = rpmtsiInit(ts);
01176     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01177         dbiIndexSet * matches;
01178         int knownBad;
01179         int fc;
01180 
01181         (void) rpmdbCheckSignals();
01182 
01183         if ((fi = rpmtsiFi(pi)) == NULL)
01184             continue;   /* XXX can't happen */
01185         fc = rpmfiFC(fi);
01186 
01187         NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
01188                         ts->orderCount, NULL, ts->notifyData));
01189 
01190         if (fc == 0) continue;
01191 
01192         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01193         /* Extract file info for all files in this package from the database. */
01194         matches = xcalloc(fc, sizeof(*matches));
01195         if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
01196             ps = rpmpsFree(ps);
01197             return 1;   /* XXX WTFO? */
01198         }
01199 
01200         numShared = 0;
01201         fi = rpmfiInit(fi, 0);
01202         while ((i = rpmfiNext(fi)) >= 0)
01203             numShared += dbiIndexSetCount(matches[i]);
01204 
01205         /* Build sorted file info list for this package. */
01206         shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
01207 
01208         fi = rpmfiInit(fi, 0);
01209         while ((i = rpmfiNext(fi)) >= 0) {
01210             /*
01211              * Take care not to mark files as replaced in packages that will
01212              * have been removed before we will get here.
01213              */
01214             for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
01215                 int ro;
01216                 ro = dbiIndexRecordOffset(matches[i], j);
01217                 knownBad = 0;
01218                 qi = rpmtsiInit(ts);
01219                 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
01220                     if (ro == knownBad)
01221                         /*@innerbreak@*/ break;
01222                     if (rpmteDBOffset(q) == ro)
01223                         knownBad = ro;
01224                 }
01225                 qi = rpmtsiFree(qi);
01226 
01227                 shared->pkgFileNum = i;
01228                 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
01229                 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
01230                 shared->isRemoved = (knownBad == ro);
01231                 shared++;
01232             }
01233             matches[i] = dbiFreeIndexSet(matches[i]);
01234         }
01235         numShared = shared - sharedList;
01236         shared->otherPkg = -1;
01237         matches = _free(matches);
01238 
01239         /* Sort file info by other package index (otherPkg) */
01240         qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
01241 
01242         /* For all files from this package that are in the database ... */
01243         /*@-branchstate@*/
01244         for (i = 0; i < numShared; i = nexti) {
01245             int beingRemoved;
01246 
01247             shared = sharedList + i;
01248 
01249             /* Find the end of the files in the other package. */
01250             for (nexti = i + 1; nexti < numShared; nexti++) {
01251                 if (sharedList[nexti].otherPkg != shared->otherPkg)
01252                     /*@innerbreak@*/ break;
01253             }
01254 
01255             /* Is this file from a package being removed? */
01256             beingRemoved = 0;
01257             if (ts->removedPackages != NULL)
01258             for (j = 0; j < ts->numRemovedPackages; j++) {
01259                 if (ts->removedPackages[j] != shared->otherPkg)
01260                     /*@innercontinue@*/ continue;
01261                 beingRemoved = 1;
01262                 /*@innerbreak@*/ break;
01263             }
01264 
01265             /* Determine the fate of each file. */
01266             switch (rpmteType(p)) {
01267             case TR_ADDED:
01268                 xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
01269         !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
01270                 /*@switchbreak@*/ break;
01271             case TR_REMOVED:
01272                 if (!beingRemoved)
01273                     xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
01274                 /*@switchbreak@*/ break;
01275             }
01276         }
01277         /*@=branchstate@*/
01278 
01279         free(sharedList);
01280 
01281         /* Update disk space needs on each partition for this package. */
01282         handleOverlappedFiles(ts, p, fi);
01283 
01284         /* Check added package has sufficient space on each partition used. */
01285         switch (rpmteType(p)) {
01286         case TR_ADDED:
01287             rpmtsCheckDSIProblems(ts, p);
01288             /*@switchbreak@*/ break;
01289         case TR_REMOVED:
01290             /*@switchbreak@*/ break;
01291         }
01292         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01293     }
01294     pi = rpmtsiFree(pi);
01295     ps = rpmpsFree(ps);
01296 
01297     if (rpmtsChrootDone(ts)) {
01298         const char * currDir = rpmtsCurrDir(ts);
01299         /*@-superuser -noeffect @*/
01300         xx = chroot(".");
01301         /*@=superuser =noeffect @*/
01302         (void) rpmtsSetChrootDone(ts, 0);
01303         if (currDir != NULL)
01304             xx = chdir(currDir);
01305     }
01306 
01307     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount,
01308         NULL, ts->notifyData));
01309 
01310     /* ===============================================
01311      * Free unused memory as soon as possible.
01312      */
01313     pi = rpmtsiInit(ts);
01314     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01315         if ((fi = rpmtsiFi(pi)) == NULL)
01316             continue;   /* XXX can't happen */
01317         if (rpmfiFC(fi) == 0)
01318             continue;
01319         fi->fps = _free(fi->fps);
01320     }
01321     pi = rpmtsiFree(pi);
01322 
01323     fpc = fpCacheFree(fpc);
01324     ts->ht = htFree(ts->ht);
01325 
01326     /* ===============================================
01327      * If unfiltered problems exist, free memory and return.
01328      */
01329     if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
01330      || (ts->probs->numProblems &&
01331                 (okProbs != NULL || rpmpsTrim(ts->probs, okProbs)))
01332        )
01333     {
01334         return ts->orderCount;
01335     }
01336 
01337     /* ===============================================
01338      * Save removed files before erasing.
01339      */
01340     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
01341         int progress;
01342 
01343         progress = 0;
01344         pi = rpmtsiInit(ts);
01345         while ((p = rpmtsiNext(pi, 0)) != NULL) {
01346 
01347             (void) rpmdbCheckSignals();
01348 
01349             if ((fi = rpmtsiFi(pi)) == NULL)
01350                 continue;       /* XXX can't happen */
01351             switch (rpmteType(p)) {
01352             case TR_ADDED:
01353                 /*@switchbreak@*/ break;
01354             case TR_REMOVED:
01355                 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
01356                     /*@switchbreak@*/ break;
01357                 if (!progress)
01358                     NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START,
01359                                 7, numRemoved, NULL, ts->notifyData));
01360 
01361                 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
01362                         numRemoved, NULL, ts->notifyData));
01363                 progress++;
01364 
01365                 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
01366 
01367         /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
01368                 fi->mapflags |= CPIO_MAP_ABSOLUTE;
01369                 fi->mapflags |= CPIO_MAP_ADDDOT;
01370                 fi->mapflags |= CPIO_ALL_HARDLINKS;
01371                 psm = rpmpsmNew(ts, p, fi);
01372                 xx = rpmpsmStage(psm, PSM_PKGSAVE);
01373                 psm = rpmpsmFree(psm);
01374                 fi->mapflags &= ~CPIO_MAP_ABSOLUTE;
01375                 fi->mapflags &= ~CPIO_MAP_ADDDOT;
01376                 fi->mapflags &= ~CPIO_ALL_HARDLINKS;
01377 
01378                 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
01379 
01380                 /*@switchbreak@*/ break;
01381             }
01382         }
01383         pi = rpmtsiFree(pi);
01384         if (progress) {
01385             NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved,
01386                         NULL, ts->notifyData));
01387         }
01388     }
01389 
01390     /* ===============================================
01391      * Install and remove packages.
01392      */
01393     lastFailKey = (alKey)-2;    /* erased packages have -1 */
01394     pi = rpmtsiInit(ts);
01395     /*@-branchstate@*/ /* FIX: fi reload needs work */
01396     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01397         alKey pkgKey;
01398         int gotfd;
01399 
01400         (void) rpmdbCheckSignals();
01401 
01402         gotfd = 0;
01403         if ((fi = rpmtsiFi(pi)) == NULL)
01404             continue;   /* XXX can't happen */
01405         
01406         psm = rpmpsmNew(ts, p, fi);
01407 assert(psm != NULL);
01408         psm->unorderedSuccessor =
01409                 (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
01410 
01411         switch (rpmteType(p)) {
01412         case TR_ADDED:
01413             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
01414 
01415             pkgKey = rpmteAddedKey(p);
01416 
01417             rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s-%s 0x%x\n",
01418                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01419 
01420             p->h = NULL;
01421             /*@-type@*/ /* FIX: rpmte not opaque */
01422             {
01423                 /*@-noeffectuncon@*/ /* FIX: notify annotations */
01424                 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01425                                 rpmteKey(p), ts->notifyData);
01426                 /*@=noeffectuncon@*/
01427                 if (rpmteFd(p) != NULL) {
01428                     rpmVSFlags ovsflags = rpmtsVSFlags(ts);
01429                     rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
01430                     rpmRC rpmrc;
01431 
01432                     ovsflags = rpmtsSetVSFlags(ts, vsflags);
01433                     rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
01434                                 rpmteNEVR(p), &p->h);
01435                     vsflags = rpmtsSetVSFlags(ts, ovsflags);
01436 
01437                     switch (rpmrc) {
01438                     default:
01439                         /*@-noeffectuncon@*/ /* FIX: notify annotations */
01440                         p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
01441                                         0, 0,
01442                                         rpmteKey(p), ts->notifyData);
01443                         /*@=noeffectuncon@*/
01444                         p->fd = NULL;
01445                         ourrc++;
01446                         /*@innerbreak@*/ break;
01447                     case RPMRC_NOTTRUSTED:
01448                     case RPMRC_NOKEY:
01449                     case RPMRC_OK:
01450                         /*@innerbreak@*/ break;
01451                     }
01452                     if (rpmteFd(p) != NULL) gotfd = 1;
01453                 }
01454             }
01455             /*@=type@*/
01456 
01457             if (rpmteFd(p) != NULL) {
01458                 /*
01459                  * XXX Sludge necessary to tranfer existing fstates/actions
01460                  * XXX around a recreated file info set.
01461                  */
01462                 psm->fi = rpmfiFree(psm->fi);
01463                 {
01464                     char * fstates = fi->fstates;
01465                     fileAction * actions = fi->actions;
01466                     rpmte savep;
01467 
01468                     fi->fstates = NULL;
01469                     fi->actions = NULL;
01470 /*@-nullstate@*/ /* FIX: fi->actions is NULL */
01471                     fi = rpmfiFree(fi);
01472 /*@=nullstate@*/
01473 
01474                     savep = rpmtsSetRelocateElement(ts, p);
01475                     fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
01476                     (void) rpmtsSetRelocateElement(ts, savep);
01477 
01478                     if (fi != NULL) {   /* XXX can't happen */
01479                         fi->te = p;
01480                         fi->fstates = _free(fi->fstates);
01481                         fi->fstates = fstates;
01482                         fi->actions = _free(fi->actions);
01483                         fi->actions = actions;
01484                         p->fi = fi;
01485                     }
01486                 }
01487                 psm->fi = rpmfiLink(p->fi, NULL);
01488 
01489 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
01490                 if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
01491                     ourrc++;
01492                     lastFailKey = pkgKey;
01493                 }
01494 /*@=nullstate@*/
01495             } else {
01496                 ourrc++;
01497                 lastFailKey = pkgKey;
01498             }
01499 
01500             if (gotfd) {
01501                 /*@-noeffectuncon @*/ /* FIX: check rc */
01502                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01503                         rpmteKey(p), ts->notifyData);
01504                 /*@=noeffectuncon @*/
01505                 /*@-type@*/
01506                 p->fd = NULL;
01507                 /*@=type@*/
01508             }
01509 
01510             p->h = headerFree(p->h);
01511 
01512             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
01513 
01514             /*@switchbreak@*/ break;
01515 
01516         case TR_REMOVED:
01517             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
01518 
01519             rpmMessage(RPMMESS_DEBUG, "========== --- %s %s-%s 0x%x\n",
01520                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01521 
01522             /*
01523              * XXX This has always been a hack, now mostly broken.
01524              * If install failed, then we shouldn't erase.
01525              */
01526             if (rpmteDependsOnKey(p) != lastFailKey) {
01527                 if (rpmpsmStage(psm, PSM_PKGERASE))
01528                     ourrc++;
01529             }
01530 
01531             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
01532 
01533             /*@switchbreak@*/ break;
01534         }
01535         xx = rpmdbSync(rpmtsGetRdb(ts));
01536 
01537 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
01538         psm = rpmpsmFree(psm);
01539 /*@=nullstate@*/
01540 
01541 /*@-type@*/ /* FIX: p is almost opaque */
01542         p->fi = rpmfiFree(p->fi);
01543 /*@=type@*/
01544 
01545     }
01546     /*@=branchstate@*/
01547     pi = rpmtsiFree(pi);
01548 
01549     /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
01550     if (ourrc)
01551         return -1;
01552     else
01553         return 0;
01554     /*@=nullstate@*/
01555 }

Generated on Thu May 13 15:02:41 2004 for rpm by doxygen1.2.18