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

Generated on Tue Jun 12 17:56:13 2007 for rpm by doxygen 1.3.5