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

lib/transaction.c

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

Generated on Fri Apr 16 16:36:53 2004 for rpm by doxygen 1.3.6