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

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

Generated on Sun Aug 21 21:56:40 2005 for rpm by  doxygen 1.3.9.1