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             {   char md5sum[50];
00617                 const unsigned char * MD5 = rpmfiMD5(fi);
00618                 if (!domd5(fn, md5sum, 0, NULL) && memcmp(MD5, md5sum, 16)) {
00619                     fi->actions[i] = FA_BACKUP;
00620                     /*@switchbreak@*/ break;
00621                 }
00622             }
00623             fi->actions[i] = FA_ERASE;
00624             /*@switchbreak@*/ break;
00625         }
00626 /*@=boundswrite@*/
00627 
00628         /* Update disk space info for a file. */
00629         rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
00630                 fi->replacedSizes[i], fixupSize, fi->actions[i]);
00631 
00632     }
00633     ps = rpmpsFree(ps);
00634 }
00635 
00643 static int ensureOlder(rpmts ts,
00644                 const rpmte p, const Header h)
00645         /*@modifies ts @*/
00646 {
00647     int_32 reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
00648     const char * reqEVR;
00649     rpmds req;
00650     char * t;
00651     int nb;
00652     int rc;
00653 
00654     if (p == NULL || h == NULL)
00655         return 1;
00656 
00657 /*@-boundswrite@*/
00658     nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1;
00659     t = alloca(nb);
00660     *t = '\0';
00661     reqEVR = t;
00662     if (rpmteE(p) != NULL)      t = stpcpy( stpcpy(t, rpmteE(p)), ":");
00663     if (rpmteV(p) != NULL)      t = stpcpy(t, rpmteV(p));
00664     *t++ = '-';
00665     if (rpmteR(p) != NULL)      t = stpcpy(t, rpmteR(p));
00666 /*@=boundswrite@*/
00667     
00668     req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
00669     rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
00670     req = rpmdsFree(req);
00671 
00672     if (rc == 0) {
00673         rpmps ps = rpmtsProblems(ts);
00674         const char * altNEVR = hGetNEVR(h, NULL);
00675         rpmpsAppend(ps, RPMPROB_OLDPACKAGE,
00676                 rpmteNEVR(p), rpmteKey(p),
00677                 NULL, NULL,
00678                 altNEVR,
00679                 0);
00680         altNEVR = _free(altNEVR);
00681         ps = rpmpsFree(ps);
00682         rc = 1;
00683     } else
00684         rc = 0;
00685 
00686     return rc;
00687 }
00688 
00694 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
00695 /*@-bounds@*/
00696 static void skipFiles(const rpmts ts, rpmfi fi)
00697         /*@globals rpmGlobalMacroContext, h_errno @*/
00698         /*@modifies fi, rpmGlobalMacroContext @*/
00699 {
00700     uint_32 tscolor = rpmtsColor(ts);
00701     uint_32 FColor;
00702     int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
00703     int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
00704     char ** netsharedPaths = NULL;
00705     const char ** languages;
00706     const char * dn, * bn;
00707     int dnlen, bnlen, ix;
00708     const char * s;
00709     int * drc;
00710     char * dff;
00711     int dc;
00712     int i, j;
00713 
00714     if (!noDocs)
00715         noDocs = rpmExpandNumeric("%{_excludedocs}");
00716 
00717     {   const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL);
00718         /*@-branchstate@*/
00719         if (tmpPath && *tmpPath != '%')
00720             netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
00721         /*@=branchstate@*/
00722         tmpPath = _free(tmpPath);
00723     }
00724 
00725     s = rpmExpand("%{_install_langs}", NULL);
00726     /*@-branchstate@*/
00727     if (!(s && *s != '%'))
00728         s = _free(s);
00729     if (s) {
00730         languages = (const char **) splitString(s, strlen(s), ':');
00731         s = _free(s);
00732     } else
00733         languages = NULL;
00734     /*@=branchstate@*/
00735 
00736     /* Compute directory refcount, skip directory if now empty. */
00737     dc = rpmfiDC(fi);
00738     drc = alloca(dc * sizeof(*drc));
00739     memset(drc, 0, dc * sizeof(*drc));
00740     dff = alloca(dc * sizeof(*dff));
00741     memset(dff, 0, dc * sizeof(*dff));
00742 
00743     fi = rpmfiInit(fi, 0);
00744     if (fi != NULL)     /* XXX lclint */
00745     while ((i = rpmfiNext(fi)) >= 0)
00746     {
00747         char ** nsp;
00748 
00749         bn = rpmfiBN(fi);
00750         bnlen = strlen(bn);
00751         ix = rpmfiDX(fi);
00752         dn = rpmfiDN(fi);
00753         dnlen = strlen(dn);
00754         if (dn == NULL)
00755             continue;   /* XXX can't happen */
00756 
00757         drc[ix]++;
00758 
00759         /* Don't bother with skipped files */
00760         if (XFA_SKIPPING(fi->actions[i])) {
00761             drc[ix]--; dff[ix] = 1;
00762             continue;
00763         }
00764 
00765         /* Ignore colored files not in our rainbow. */
00766         FColor = rpmfiFColor(fi);
00767         if (tscolor && FColor && !(tscolor & FColor)) {
00768             drc[ix]--;  dff[ix] = 1;
00769             fi->actions[i] = FA_SKIPCOLOR;
00770             continue;
00771         }
00772 
00773         /*
00774          * Skip net shared paths.
00775          * Net shared paths are not relative to the current root (though
00776          * they do need to take package relocations into account).
00777          */
00778         for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
00779             int len;
00780 
00781             len = strlen(*nsp);
00782             if (dnlen >= len) {
00783                 if (strncmp(dn, *nsp, len))
00784                     /*@innercontinue@*/ continue;
00785                 /* Only directories or complete file paths can be net shared */
00786                 if (!(dn[len] == '/' || dn[len] == '\0'))
00787                     /*@innercontinue@*/ continue;
00788             } else {
00789                 if (len < (dnlen + bnlen))
00790                     /*@innercontinue@*/ continue;
00791                 if (strncmp(dn, *nsp, dnlen))
00792                     /*@innercontinue@*/ continue;
00793                 if (strncmp(bn, (*nsp) + dnlen, bnlen))
00794                     /*@innercontinue@*/ continue;
00795                 len = dnlen + bnlen;
00796                 /* Only directories or complete file paths can be net shared */
00797                 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
00798                     /*@innercontinue@*/ continue;
00799             }
00800 
00801             /*@innerbreak@*/ break;
00802         }
00803 
00804         if (nsp && *nsp) {
00805             drc[ix]--;  dff[ix] = 1;
00806             fi->actions[i] = FA_SKIPNETSHARED;
00807             continue;
00808         }
00809 
00810         /*
00811          * Skip i18n language specific files.
00812          */
00813         if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
00814             const char **lang, *l, *le;
00815             for (lang = languages; *lang != NULL; lang++) {
00816                 if (!strcmp(*lang, "all"))
00817                     /*@innerbreak@*/ break;
00818                 for (l = fi->flangs[i]; *l != '\0'; l = le) {
00819                     for (le = l; *le != '\0' && *le != '|'; le++)
00820                         {};
00821                     if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
00822                         /*@innerbreak@*/ break;
00823                     if (*le == '|') le++;       /* skip over | */
00824                 }
00825                 if (*l != '\0')
00826                     /*@innerbreak@*/ break;
00827             }
00828             if (*lang == NULL) {
00829                 drc[ix]--;      dff[ix] = 1;
00830                 fi->actions[i] = FA_SKIPNSTATE;
00831                 continue;
00832             }
00833         }
00834 
00835         /*
00836          * Skip config files if requested.
00837          */
00838         if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
00839             drc[ix]--;  dff[ix] = 1;
00840             fi->actions[i] = FA_SKIPNSTATE;
00841             continue;
00842         }
00843 
00844         /*
00845          * Skip documentation if requested.
00846          */
00847         if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
00848             drc[ix]--;  dff[ix] = 1;
00849             fi->actions[i] = FA_SKIPNSTATE;
00850             continue;
00851         }
00852     }
00853 
00854     /* Skip (now empty) directories that had skipped files. */
00855 #ifndef NOTYET
00856     if (fi != NULL)     /* XXX can't happen */
00857     for (j = 0; j < dc; j++)
00858 #else
00859     if ((fi = rpmfiInitD(fi)) != NULL)
00860     while (j = rpmfiNextD(fi) >= 0)
00861 #endif
00862     {
00863 
00864         if (drc[j]) continue;   /* dir still has files. */
00865         if (!dff[j]) continue;  /* dir was not emptied here. */
00866         
00867         /* Find parent directory and basename. */
00868         dn = fi->dnl[j];        dnlen = strlen(dn) - 1;
00869         bn = dn + dnlen;        bnlen = 0;
00870         while (bn > dn && bn[-1] != '/') {
00871                 bnlen++;
00872                 dnlen--;
00873                 bn--;
00874         }
00875 
00876         /* If explicitly included in the package, skip the directory. */
00877         fi = rpmfiInit(fi, 0);
00878         if (fi != NULL)         /* XXX lclint */
00879         while ((i = rpmfiNext(fi)) >= 0) {
00880             const char * fdn, * fbn;
00881             int_16 fFMode;
00882 
00883             if (XFA_SKIPPING(fi->actions[i]))
00884                 /*@innercontinue@*/ continue;
00885 
00886             fFMode = rpmfiFMode(fi);
00887 
00888             if (whatis(fFMode) != XDIR)
00889                 /*@innercontinue@*/ continue;
00890             fdn = rpmfiDN(fi);
00891             if (strlen(fdn) != dnlen)
00892                 /*@innercontinue@*/ continue;
00893             if (strncmp(fdn, dn, dnlen))
00894                 /*@innercontinue@*/ continue;
00895             fbn = rpmfiBN(fi);
00896             if (strlen(fbn) != bnlen)
00897                 /*@innercontinue@*/ continue;
00898             if (strncmp(fbn, bn, bnlen))
00899                 /*@innercontinue@*/ continue;
00900             rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"), dn);
00901             fi->actions[i] = FA_SKIPNSTATE;
00902             /*@innerbreak@*/ break;
00903         }
00904     }
00905 
00906 /*@-dependenttrans@*/
00907     if (netsharedPaths) freeSplitString(netsharedPaths);
00908 #ifdef  DYING   /* XXX freeFi will deal with this later. */
00909     fi->flangs = _free(fi->flangs);
00910 #endif
00911     if (languages) freeSplitString((char **)languages);
00912 /*@=dependenttrans@*/
00913 }
00914 /*@=bounds@*/
00915 /*@=mustmod@*/
00916 
00923 static /*@null@*/
00924 rpmfi rpmtsiFi(const rpmtsi tsi)
00925         /*@*/
00926 {
00927     rpmfi fi = NULL;
00928 
00929     if (tsi != NULL && tsi->ocsave != -1) {
00930         /*@-type -abstract@*/ /* FIX: rpmte not opaque */
00931         rpmte te = rpmtsElement(tsi->ts, tsi->ocsave);
00932         /*@-assignexpose@*/
00933         if (te != NULL && (fi = te->fi) != NULL)
00934             fi->te = te;
00935         /*@=assignexpose@*/
00936         /*@=type =abstract@*/
00937     }
00938     /*@-compdef -refcounttrans -usereleased @*/
00939     return fi;
00940     /*@=compdef =refcounttrans =usereleased @*/
00941 }
00942 
00943 #define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al
00944 
00945 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
00946 {
00947     uint_32 tscolor = rpmtsColor(ts);
00948     int i, j;
00949     int ourrc = 0;
00950     int totalFileCount = 0;
00951     rpmfi fi;
00952     sharedFileInfo shared, sharedList;
00953     int numShared;
00954     int nexti;
00955     alKey lastFailKey;
00956     fingerPrintCache fpc;
00957     rpmps ps;
00958     rpmpsm psm;
00959     rpmtsi pi;  rpmte p;
00960     rpmtsi qi;  rpmte q;
00961     int numAdded;
00962     int numRemoved;
00963     void * lock = NULL;
00964     int xx;
00965 
00966     /* XXX programmer error segfault avoidance. */
00967     if (rpmtsNElements(ts) <= 0)
00968         return -1;
00969 
00970     /* If we are in test mode, then there's no need for transaction lock. */
00971     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
00972         lock = rpmtsAcquireLock(ts);
00973         if (lock == NULL)
00974             return -1;
00975     }
00976 
00977     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
00978         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
00979     if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
00980         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
00981 
00982     if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
00983         (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
00984 
00985     ts->probs = rpmpsFree(ts->probs);
00986     ts->probs = rpmpsCreate();
00987 
00988     /* XXX Make sure the database is open RDWR for package install/erase. */
00989     {   int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
00990                 ? O_RDONLY : (O_RDWR|O_CREAT);
00991 
00992         /* Open database RDWR for installing packages. */
00993         if (rpmtsOpenDB(ts, dbmode)) {
00994             rpmtsFreeLock(lock);
00995             return -1;  /* XXX W2DO? */
00996     }
00997     }
00998 
00999     ts->ignoreSet = ignoreSet;
01000     {   const char * currDir = currentDirectory();
01001         rpmtsSetCurrDir(ts, currDir);
01002         currDir = _free(currDir);
01003     }
01004 
01005     (void) rpmtsSetChrootDone(ts, 0);
01006 
01007     {   int_32 tid = (int_32) time(NULL);
01008         (void) rpmtsSetTid(ts, tid);
01009     }
01010 
01011     /* Get available space on mounted file systems. */
01012     xx = rpmtsInitDSI(ts);
01013 
01014     /* ===============================================
01015      * For packages being installed:
01016      * - verify package arch/os.
01017      * - verify package epoch:version-release is newer.
01018      * - count files.
01019      * For packages being removed:
01020      * - count files.
01021      */
01022 
01023 rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts));
01024     ps = rpmtsProblems(ts);
01025     /* The ordering doesn't matter here */
01026     pi = rpmtsiInit(ts);
01027     while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
01028         rpmdbMatchIterator mi;
01029         int fc;
01030 
01031         if ((fi = rpmtsiFi(pi)) == NULL)
01032             continue;   /* XXX can't happen */
01033         fc = rpmfiFC(fi);
01034 
01035         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH) && !tscolor)
01036             if (!archOkay(rpmteA(p)))
01037                 rpmpsAppend(ps, RPMPROB_BADARCH,
01038                         rpmteNEVR(p), rpmteKey(p),
01039                         rpmteA(p), NULL,
01040                         NULL, 0);
01041 
01042         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS))
01043             if (!osOkay(rpmteO(p)))
01044                 rpmpsAppend(ps, RPMPROB_BADOS,
01045                         rpmteNEVR(p), rpmteKey(p),
01046                         rpmteO(p), NULL,
01047                         NULL, 0);
01048 
01049         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) {
01050             Header h;
01051             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01052             while ((h = rpmdbNextIterator(mi)) != NULL)
01053                 xx = ensureOlder(ts, p, h);
01054             mi = rpmdbFreeIterator(mi);
01055         }
01056 
01057         if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
01058             mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
01059             xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
01060                                 rpmteE(p));
01061             xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
01062                                 rpmteV(p));
01063             xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
01064                                 rpmteR(p));
01065             if (tscolor) {
01066                 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
01067                                 rpmteA(p));
01068                 xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP,
01069                                 rpmteO(p));
01070             }
01071 
01072             while (rpmdbNextIterator(mi) != NULL) {
01073                 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
01074                         rpmteNEVR(p), rpmteKey(p),
01075                         NULL, NULL,
01076                         NULL, 0);
01077                 /*@innerbreak@*/ break;
01078             }
01079             mi = rpmdbFreeIterator(mi);
01080         }
01081 
01082         /* Count no. of files (if any). */
01083         totalFileCount += fc;
01084 
01085     }
01086     pi = rpmtsiFree(pi);
01087     ps = rpmpsFree(ps);
01088 
01089     /* The ordering doesn't matter here */
01090     pi = rpmtsiInit(ts);
01091     while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
01092         int fc;
01093 
01094         if ((fi = rpmtsiFi(pi)) == NULL)
01095             continue;   /* XXX can't happen */
01096         fc = rpmfiFC(fi);
01097 
01098         totalFileCount += fc;
01099     }
01100     pi = rpmtsiFree(pi);
01101 
01102     /* ===============================================
01103      * Initialize transaction element file info for package:
01104      */
01105 
01106     /*
01107      * FIXME?: we'd be better off assembling one very large file list and
01108      * calling fpLookupList only once. I'm not sure that the speedup is
01109      * worth the trouble though.
01110      */
01111 rpmMessage(RPMMESS_DEBUG, _("computing %d file fingerprints\n"), totalFileCount);
01112 
01113     numAdded = numRemoved = 0;
01114     pi = rpmtsiInit(ts);
01115     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01116         int fc;
01117 
01118         if ((fi = rpmtsiFi(pi)) == NULL)
01119             continue;   /* XXX can't happen */
01120         fc = rpmfiFC(fi);
01121 
01122         /*@-branchstate@*/
01123         switch (rpmteType(p)) {
01124         case TR_ADDED:
01125             numAdded++;
01126             fi->record = 0;
01127             /* Skip netshared paths, not our i18n files, and excluded docs */
01128             if (fc > 0)
01129                 skipFiles(ts, fi);
01130             /*@switchbreak@*/ break;
01131         case TR_REMOVED:
01132             numRemoved++;
01133             fi->record = rpmteDBOffset(p);
01134             /*@switchbreak@*/ break;
01135         }
01136         /*@=branchstate@*/
01137 
01138         fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
01139     }
01140     pi = rpmtsiFree(pi);
01141 
01142     if (!rpmtsChrootDone(ts)) {
01143         const char * rootDir = rpmtsRootDir(ts);
01144         xx = chdir("/");
01145         /*@-superuser -noeffect @*/
01146         if (rootDir != NULL)
01147             xx = chroot(rootDir);
01148         /*@=superuser =noeffect @*/
01149         (void) rpmtsSetChrootDone(ts, 1);
01150     }
01151 
01152     ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
01153     fpc = fpCacheCreate(totalFileCount);
01154 
01155     /* ===============================================
01156      * Add fingerprint for each file not skipped.
01157      */
01158     pi = rpmtsiInit(ts);
01159     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01160         int fc;
01161 
01162         (void) rpmdbCheckSignals();
01163 
01164         if ((fi = rpmtsiFi(pi)) == NULL)
01165             continue;   /* XXX can't happen */
01166         fc = rpmfiFC(fi);
01167 
01168         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01169         fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
01170         /*@-branchstate@*/
01171         fi = rpmfiInit(fi, 0);
01172         if (fi != NULL)         /* XXX lclint */
01173         while ((i = rpmfiNext(fi)) >= 0) {
01174             if (XFA_SKIPPING(fi->actions[i]))
01175                 /*@innercontinue@*/ continue;
01176             /*@-dependenttrans@*/
01177             htAddEntry(ts->ht, fi->fps + i, (void *) fi);
01178             /*@=dependenttrans@*/
01179         }
01180         /*@=branchstate@*/
01181         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01182 
01183     }
01184     pi = rpmtsiFree(pi);
01185 
01186     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount,
01187         NULL, ts->notifyData));
01188 
01189     /* ===============================================
01190      * Compute file disposition for each package in transaction set.
01191      */
01192 rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n"));
01193     ps = rpmtsProblems(ts);
01194     pi = rpmtsiInit(ts);
01195     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01196         dbiIndexSet * matches;
01197         int knownBad;
01198         int fc;
01199 
01200         (void) rpmdbCheckSignals();
01201 
01202         if ((fi = rpmtsiFi(pi)) == NULL)
01203             continue;   /* XXX can't happen */
01204         fc = rpmfiFC(fi);
01205 
01206         NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
01207                         ts->orderCount, NULL, ts->notifyData));
01208 
01209         if (fc == 0) continue;
01210 
01211         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
01212         /* Extract file info for all files in this package from the database. */
01213         matches = xcalloc(fc, sizeof(*matches));
01214         if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
01215             ps = rpmpsFree(ps);
01216             rpmtsFreeLock(lock);
01217             return 1;   /* XXX WTFO? */
01218         }
01219 
01220         numShared = 0;
01221         fi = rpmfiInit(fi, 0);
01222         while ((i = rpmfiNext(fi)) >= 0)
01223             numShared += dbiIndexSetCount(matches[i]);
01224 
01225         /* Build sorted file info list for this package. */
01226         shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
01227 
01228         fi = rpmfiInit(fi, 0);
01229         while ((i = rpmfiNext(fi)) >= 0) {
01230             /*
01231              * Take care not to mark files as replaced in packages that will
01232              * have been removed before we will get here.
01233              */
01234             for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
01235                 int ro;
01236                 ro = dbiIndexRecordOffset(matches[i], j);
01237                 knownBad = 0;
01238                 qi = rpmtsiInit(ts);
01239                 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
01240                     if (ro == knownBad)
01241                         /*@innerbreak@*/ break;
01242                     if (rpmteDBOffset(q) == ro)
01243                         knownBad = ro;
01244                 }
01245                 qi = rpmtsiFree(qi);
01246 
01247                 shared->pkgFileNum = i;
01248                 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
01249                 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
01250                 shared->isRemoved = (knownBad == ro);
01251                 shared++;
01252             }
01253             matches[i] = dbiFreeIndexSet(matches[i]);
01254         }
01255         numShared = shared - sharedList;
01256         shared->otherPkg = -1;
01257         matches = _free(matches);
01258 
01259         /* Sort file info by other package index (otherPkg) */
01260         qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
01261 
01262         /* For all files from this package that are in the database ... */
01263         /*@-branchstate@*/
01264         for (i = 0; i < numShared; i = nexti) {
01265             int beingRemoved;
01266 
01267             shared = sharedList + i;
01268 
01269             /* Find the end of the files in the other package. */
01270             for (nexti = i + 1; nexti < numShared; nexti++) {
01271                 if (sharedList[nexti].otherPkg != shared->otherPkg)
01272                     /*@innerbreak@*/ break;
01273             }
01274 
01275             /* Is this file from a package being removed? */
01276             beingRemoved = 0;
01277             if (ts->removedPackages != NULL)
01278             for (j = 0; j < ts->numRemovedPackages; j++) {
01279                 if (ts->removedPackages[j] != shared->otherPkg)
01280                     /*@innercontinue@*/ continue;
01281                 beingRemoved = 1;
01282                 /*@innerbreak@*/ break;
01283             }
01284 
01285             /* Determine the fate of each file. */
01286             switch (rpmteType(p)) {
01287             case TR_ADDED:
01288                 xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
01289         !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
01290                 /*@switchbreak@*/ break;
01291             case TR_REMOVED:
01292                 if (!beingRemoved)
01293                     xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
01294                 /*@switchbreak@*/ break;
01295             }
01296         }
01297         /*@=branchstate@*/
01298 
01299         free(sharedList);
01300 
01301         /* Update disk space needs on each partition for this package. */
01302         handleOverlappedFiles(ts, p, fi);
01303 
01304         /* Check added package has sufficient space on each partition used. */
01305         switch (rpmteType(p)) {
01306         case TR_ADDED:
01307             rpmtsCheckDSIProblems(ts, p);
01308             /*@switchbreak@*/ break;
01309         case TR_REMOVED:
01310             /*@switchbreak@*/ break;
01311         }
01312         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
01313     }
01314     pi = rpmtsiFree(pi);
01315     ps = rpmpsFree(ps);
01316 
01317     if (rpmtsChrootDone(ts)) {
01318         const char * currDir = rpmtsCurrDir(ts);
01319         /*@-superuser -noeffect @*/
01320         xx = chroot(".");
01321         /*@=superuser =noeffect @*/
01322         (void) rpmtsSetChrootDone(ts, 0);
01323         if (currDir != NULL)
01324             xx = chdir(currDir);
01325     }
01326 
01327     NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount,
01328         NULL, ts->notifyData));
01329 
01330     /* ===============================================
01331      * Free unused memory as soon as possible.
01332      */
01333     pi = rpmtsiInit(ts);
01334     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01335         if ((fi = rpmtsiFi(pi)) == NULL)
01336             continue;   /* XXX can't happen */
01337         if (rpmfiFC(fi) == 0)
01338             continue;
01339         fi->fps = _free(fi->fps);
01340     }
01341     pi = rpmtsiFree(pi);
01342 
01343     fpc = fpCacheFree(fpc);
01344     ts->ht = htFree(ts->ht);
01345 
01346     /* ===============================================
01347      * If unfiltered problems exist, free memory and return.
01348      */
01349     if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
01350      || (ts->probs->numProblems &&
01351                 (okProbs != NULL || rpmpsTrim(ts->probs, okProbs)))
01352        )
01353     {
01354         rpmtsFreeLock(lock);
01355         return ts->orderCount;
01356     }
01357 
01358     /* ===============================================
01359      * Save removed files before erasing.
01360      */
01361     if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
01362         int progress;
01363 
01364         progress = 0;
01365         pi = rpmtsiInit(ts);
01366         while ((p = rpmtsiNext(pi, 0)) != NULL) {
01367 
01368             (void) rpmdbCheckSignals();
01369 
01370             if ((fi = rpmtsiFi(pi)) == NULL)
01371                 continue;       /* XXX can't happen */
01372             switch (rpmteType(p)) {
01373             case TR_ADDED:
01374                 /*@switchbreak@*/ break;
01375             case TR_REMOVED:
01376                 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
01377                     /*@switchbreak@*/ break;
01378                 if (!progress)
01379                     NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START,
01380                                 7, numRemoved, NULL, ts->notifyData));
01381 
01382                 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress,
01383                         numRemoved, NULL, ts->notifyData));
01384                 progress++;
01385 
01386                 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
01387 
01388         /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */
01389                 fi->mapflags |= CPIO_MAP_ABSOLUTE;
01390                 fi->mapflags |= CPIO_MAP_ADDDOT;
01391                 fi->mapflags |= CPIO_ALL_HARDLINKS;
01392                 psm = rpmpsmNew(ts, p, fi);
01393                 xx = rpmpsmStage(psm, PSM_PKGSAVE);
01394                 psm = rpmpsmFree(psm);
01395                 fi->mapflags &= ~CPIO_MAP_ABSOLUTE;
01396                 fi->mapflags &= ~CPIO_MAP_ADDDOT;
01397                 fi->mapflags &= ~CPIO_ALL_HARDLINKS;
01398 
01399                 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
01400 
01401                 /*@switchbreak@*/ break;
01402             }
01403         }
01404         pi = rpmtsiFree(pi);
01405         if (progress) {
01406             NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved,
01407                         NULL, ts->notifyData));
01408         }
01409     }
01410 
01411     /* ===============================================
01412      * Install and remove packages.
01413      */
01414     lastFailKey = (alKey)-2;    /* erased packages have -1 */
01415     pi = rpmtsiInit(ts);
01416     /*@-branchstate@*/ /* FIX: fi reload needs work */
01417     while ((p = rpmtsiNext(pi, 0)) != NULL) {
01418         alKey pkgKey;
01419         int gotfd;
01420 
01421         (void) rpmdbCheckSignals();
01422 
01423         gotfd = 0;
01424         if ((fi = rpmtsiFi(pi)) == NULL)
01425             continue;   /* XXX can't happen */
01426         
01427         psm = rpmpsmNew(ts, p, fi);
01428 assert(psm != NULL);
01429         psm->unorderedSuccessor =
01430                 (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0);
01431 
01432         switch (rpmteType(p)) {
01433         case TR_ADDED:
01434             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
01435 
01436             pkgKey = rpmteAddedKey(p);
01437 
01438             rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s-%s 0x%x\n",
01439                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01440 
01441             p->h = NULL;
01442             /*@-type@*/ /* FIX: rpmte not opaque */
01443             {
01444                 /*@-noeffectuncon@*/ /* FIX: notify annotations */
01445                 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01446                                 rpmteKey(p), ts->notifyData);
01447                 /*@=noeffectuncon@*/
01448                 if (rpmteFd(p) != NULL) {
01449                     rpmVSFlags ovsflags = rpmtsVSFlags(ts);
01450                     rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
01451                     rpmRC rpmrc;
01452 
01453                     ovsflags = rpmtsSetVSFlags(ts, vsflags);
01454                     rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
01455                                 rpmteNEVR(p), &p->h);
01456                     vsflags = rpmtsSetVSFlags(ts, ovsflags);
01457 
01458                     switch (rpmrc) {
01459                     default:
01460                         /*@-noeffectuncon@*/ /* FIX: notify annotations */
01461                         p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE,
01462                                         0, 0,
01463                                         rpmteKey(p), ts->notifyData);
01464                         /*@=noeffectuncon@*/
01465                         p->fd = NULL;
01466                         ourrc++;
01467                         /*@innerbreak@*/ break;
01468                     case RPMRC_NOTTRUSTED:
01469                     case RPMRC_NOKEY:
01470                     case RPMRC_OK:
01471                         /*@innerbreak@*/ break;
01472                     }
01473                     if (rpmteFd(p) != NULL) gotfd = 1;
01474                 }
01475             }
01476             /*@=type@*/
01477 
01478             if (rpmteFd(p) != NULL) {
01479                 /*
01480                  * XXX Sludge necessary to tranfer existing fstates/actions
01481                  * XXX around a recreated file info set.
01482                  */
01483                 psm->fi = rpmfiFree(psm->fi);
01484                 {
01485                     char * fstates = fi->fstates;
01486                     fileAction * actions = fi->actions;
01487                     rpmte savep;
01488 
01489                     fi->fstates = NULL;
01490                     fi->actions = NULL;
01491 /*@-nullstate@*/ /* FIX: fi->actions is NULL */
01492                     fi = rpmfiFree(fi);
01493 /*@=nullstate@*/
01494 
01495                     savep = rpmtsSetRelocateElement(ts, p);
01496                     fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1);
01497                     (void) rpmtsSetRelocateElement(ts, savep);
01498 
01499                     if (fi != NULL) {   /* XXX can't happen */
01500                         fi->te = p;
01501                         fi->fstates = _free(fi->fstates);
01502                         fi->fstates = fstates;
01503                         fi->actions = _free(fi->actions);
01504                         fi->actions = actions;
01505                         p->fi = fi;
01506                     }
01507                 }
01508                 psm->fi = rpmfiLink(p->fi, NULL);
01509 
01510 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
01511                 if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
01512                     ourrc++;
01513                     lastFailKey = pkgKey;
01514                 }
01515 /*@=nullstate@*/
01516             } else {
01517                 ourrc++;
01518                 lastFailKey = pkgKey;
01519             }
01520 
01521             if (gotfd) {
01522                 /*@-noeffectuncon @*/ /* FIX: check rc */
01523                 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01524                         rpmteKey(p), ts->notifyData);
01525                 /*@=noeffectuncon @*/
01526                 /*@-type@*/
01527                 p->fd = NULL;
01528                 /*@=type@*/
01529             }
01530 
01531             p->h = headerFree(p->h);
01532 
01533             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
01534 
01535             /*@switchbreak@*/ break;
01536 
01537         case TR_REMOVED:
01538             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
01539 
01540             rpmMessage(RPMMESS_DEBUG, "========== --- %s %s-%s 0x%x\n",
01541                 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
01542 
01543             /*
01544              * XXX This has always been a hack, now mostly broken.
01545              * If install failed, then we shouldn't erase.
01546              */
01547             if (rpmteDependsOnKey(p) != lastFailKey) {
01548                 if (rpmpsmStage(psm, PSM_PKGERASE))
01549                     ourrc++;
01550             }
01551 
01552             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
01553 
01554             /*@switchbreak@*/ break;
01555         }
01556         xx = rpmdbSync(rpmtsGetRdb(ts));
01557 
01558 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
01559         psm = rpmpsmFree(psm);
01560 /*@=nullstate@*/
01561 
01562 /*@-type@*/ /* FIX: p is almost opaque */
01563         p->fi = rpmfiFree(p->fi);
01564 /*@=type@*/
01565 
01566     }
01567     /*@=branchstate@*/
01568     pi = rpmtsiFree(pi);
01569 
01570     rpmtsFreeLock(lock);
01571 
01572     /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
01573     if (ourrc)
01574         return -1;
01575     else
01576         return 0;
01577     /*@=nullstate@*/
01578 }

Generated on Mon Nov 1 21:54:20 2004 for rpm by  doxygen 1.3.9.1