rpm
4.5
|
00001 00005 #include "system.h" 00006 #include "rpmcli.h" /* IDTX prototypes */ 00007 #include <rpmlib.h> 00008 00009 #include <rpmmacro.h> /* XXX for rpmExpand */ 00010 00011 #include "fsm.h" 00012 #include "psm.h" 00013 00014 #define _RPMDB_INTERNAL /* XXX for dbiIndexFoo() */ 00015 #include "rpmdb.h" 00016 00017 #include "rpmds.h" 00018 00019 #include "rpmlock.h" 00020 00021 #define _RPMFI_INTERNAL 00022 #include "rpmfi.h" 00023 00024 #define _RPMTE_INTERNAL 00025 #include "rpmte.h" 00026 00027 #define _RPMTS_INTERNAL 00028 #include "rpmts.h" 00029 00030 #include "cpio.h" 00031 #include "fprint.h" 00032 #include "legacy.h" /* XXX dodigest */ 00033 #include "misc.h" /* XXX stripTrailingChar, splitString, currentDirectory */ 00034 00035 #include "debug.h" 00036 00037 /*@access Header @*/ /* XXX ts->notify arg1 is void ptr */ 00038 /*@access rpmps @*/ /* XXX need rpmProblemSetOK() */ 00039 /*@access dbiIndexSet @*/ 00040 00041 /*@access rpmpsm @*/ 00042 00043 /*@access alKey @*/ 00044 /*@access fnpyKey @*/ 00045 00046 /*@access rpmfi @*/ 00047 00048 /*@access rpmte @*/ 00049 /*@access rpmtsi @*/ 00050 /*@access rpmts @*/ 00051 00052 /*@access IDT @*/ 00053 /*@access IDTX @*/ 00054 /*@access FD_t @*/ 00055 00056 /* XXX: This is a hack. I needed a to setup a notify callback 00057 * for the rollback transaction, but I did not want to create 00058 * a header for rpminstall.c. 00059 */ 00060 extern void * rpmShowProgress(/*@null@*/ const void * arg, 00061 const rpmCallbackType what, 00062 const unsigned long long amount, 00063 const unsigned long long total, 00064 /*@null@*/ fnpyKey key, 00065 /*@null@*/ void * data) 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 00094 /*@-bounds@*/ 00095 static int handleInstInstalledFiles(const rpmts ts, 00096 rpmte p, rpmfi fi, 00097 sharedFileInfo shared, 00098 int sharedCount, int reportConflicts) 00099 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00100 /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/ 00101 { 00102 uint_32 tscolor = rpmtsColor(ts); 00103 uint_32 prefcolor = rpmtsPrefColor(ts); 00104 uint_32 otecolor, tecolor; 00105 uint_32 oFColor, FColor; 00106 uint_32 oFFlags, FFlags; 00107 const char * altNEVRA = NULL; 00108 rpmfi otherFi = NULL; 00109 int numReplaced = 0; 00110 rpmps ps; 00111 int i; 00112 00113 { rpmdbMatchIterator mi; 00114 Header h; 00115 int scareMem = 0; 00116 00117 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, 00118 &shared->otherPkg, sizeof(shared->otherPkg)); 00119 while ((h = rpmdbNextIterator(mi)) != NULL) { 00120 altNEVRA = hGetNEVRA(h, NULL); 00121 otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem); 00122 break; 00123 } 00124 mi = rpmdbFreeIterator(mi); 00125 } 00126 00127 /* Compute package color. */ 00128 tecolor = rpmteColor(p); 00129 tecolor &= tscolor; 00130 00131 /* Compute other pkg color. */ 00132 otecolor = 0; 00133 otherFi = rpmfiInit(otherFi, 0); 00134 if (otherFi != NULL) 00135 while (rpmfiNext(otherFi) >= 0) 00136 otecolor |= rpmfiFColor(otherFi); 00137 otecolor &= tscolor; 00138 00139 if (otherFi == NULL) 00140 return 1; 00141 00142 fi->replaced = xcalloc(sharedCount, sizeof(*fi->replaced)); 00143 00144 ps = rpmtsProblems(ts); 00145 for (i = 0; i < sharedCount; i++, shared++) { 00146 int otherFileNum, fileNum; 00147 00148 otherFileNum = shared->otherFileNum; 00149 (void) rpmfiSetFX(otherFi, otherFileNum); 00150 oFFlags = rpmfiFFlags(otherFi); 00151 oFColor = rpmfiFColor(otherFi); 00152 oFColor &= tscolor; 00153 00154 fileNum = shared->pkgFileNum; 00155 (void) rpmfiSetFX(fi, fileNum); 00156 FFlags = rpmfiFFlags(fi); 00157 FColor = rpmfiFColor(fi); 00158 FColor &= tscolor; 00159 00160 #ifdef DYING 00161 /* XXX another tedious segfault, assume file state normal. */ 00162 if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL) 00163 continue; 00164 #endif 00165 00166 if (XFA_SKIPPING(fi->actions[fileNum])) 00167 continue; 00168 00169 /* Remove setuid/setgid bits on other (possibly hardlinked) files. */ 00170 if (!(fi->mapflags & CPIO_SBIT_CHECK)) { 00171 int_16 omode = rpmfiFMode(otherFi); 00172 if (S_ISREG(omode) && (omode & 06000) != 0) 00173 fi->mapflags |= CPIO_SBIT_CHECK; 00174 } 00175 00176 if (((FFlags | oFFlags) & RPMFILE_GHOST)) 00177 continue; 00178 00179 if (rpmfiCompare(otherFi, fi)) { 00180 int rConflicts; 00181 00182 rConflicts = reportConflicts; 00183 /* Resolve file conflicts to prefer Elf64 (if not forced). */ 00184 if (tscolor != 0 && FColor != 0 && FColor != oFColor) 00185 { 00186 if (oFColor & prefcolor) { 00187 fi->actions[fileNum] = FA_SKIPCOLOR; 00188 rConflicts = 0; 00189 } else 00190 if (FColor & prefcolor) { 00191 fi->actions[fileNum] = FA_CREATE; 00192 rConflicts = 0; 00193 } 00194 } 00195 00196 if (rConflicts) { 00197 rpmpsAppend(ps, RPMPROB_FILE_CONFLICT, 00198 rpmteNEVRA(p), rpmteKey(p), 00199 rpmfiDN(fi), rpmfiBN(fi), 00200 altNEVRA, 00201 0); 00202 } 00203 00204 /* Save file identifier to mark as state REPLACED. */ 00205 if ( !(((FFlags | oFFlags) & RPMFILE_CONFIG) || XFA_SKIPPING(fi->actions[fileNum])) ) { 00206 /*@-assignexpose@*/ /* FIX: p->replaced, not fi */ 00207 if (!shared->isRemoved) 00208 fi->replaced[numReplaced++] = *shared; 00209 /*@=assignexpose@*/ 00210 } 00211 } 00212 00213 /* Determine config file dispostion, skipping missing files (if any). */ 00214 if (((FFlags | oFFlags) & RPMFILE_CONFIG)) { 00215 int skipMissing = 00216 ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1); 00217 fileAction action = rpmfiDecideFate(otherFi, fi, skipMissing); 00218 fi->actions[fileNum] = action; 00219 } 00220 fi->replacedSizes[fileNum] = rpmfiFSize(otherFi); 00221 } 00222 ps = rpmpsFree(ps); 00223 00224 altNEVRA = _free(altNEVRA); 00225 otherFi = rpmfiFree(otherFi); 00226 00227 fi->replaced = xrealloc(fi->replaced, /* XXX memory leak */ 00228 sizeof(*fi->replaced) * (numReplaced + 1)); 00229 fi->replaced[numReplaced].otherPkg = 0; 00230 00231 return 0; 00232 } 00233 /*@=bounds@*/ 00234 00237 /* XXX only ts->rpmdb modified */ 00238 static int handleRmvdInstalledFiles(const rpmts ts, rpmfi fi, 00239 sharedFileInfo shared, int sharedCount) 00240 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00241 /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/ 00242 { 00243 HGE_t hge = fi->hge; 00244 Header h; 00245 const char * otherStates; 00246 int i, xx; 00247 00248 rpmdbMatchIterator mi; 00249 00250 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, 00251 &shared->otherPkg, sizeof(shared->otherPkg)); 00252 h = rpmdbNextIterator(mi); 00253 if (h == NULL) { 00254 mi = rpmdbFreeIterator(mi); 00255 return 1; 00256 } 00257 00258 xx = hge(h, RPMTAG_FILESTATES, NULL, &otherStates, NULL); 00259 00260 /*@-boundswrite@*/ 00261 /* XXX there's an obscure segfault here w/o NULL check ... */ 00262 if (otherStates != NULL) 00263 for (i = 0; i < sharedCount; i++, shared++) { 00264 int otherFileNum, fileNum; 00265 otherFileNum = shared->otherFileNum; 00266 fileNum = shared->pkgFileNum; 00267 00268 if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL) 00269 continue; 00270 00271 fi->actions[fileNum] = FA_SKIP; 00272 } 00273 /*@=boundswrite@*/ 00274 00275 mi = rpmdbFreeIterator(mi); 00276 00277 return 0; 00278 } 00279 00280 #define ISROOT(_d) (((_d)[0] == '/' && (_d)[1] == '\0') ? "" : (_d)) 00281 00282 /*@unchecked@*/ 00283 int _fps_debug = 0; 00284 00285 static int fpsCompare (const void * one, const void * two) 00286 /*@*/ 00287 { 00288 const struct fingerPrint_s * a = (const struct fingerPrint_s *)one; 00289 const struct fingerPrint_s * b = (const struct fingerPrint_s *)two; 00290 int adnlen = strlen(a->entry->dirName); 00291 int asnlen = (a->subDir ? strlen(a->subDir) : 0); 00292 int abnlen = strlen(a->baseName); 00293 int bdnlen = strlen(b->entry->dirName); 00294 int bsnlen = (b->subDir ? strlen(b->subDir) : 0); 00295 int bbnlen = strlen(b->baseName); 00296 char * afn, * bfn, * t; 00297 int rc = 0; 00298 00299 if (adnlen == 1 && asnlen != 0) adnlen = 0; 00300 if (bdnlen == 1 && bsnlen != 0) bdnlen = 0; 00301 00302 /*@-boundswrite@*/ 00303 afn = t = alloca(adnlen+asnlen+abnlen+2); 00304 if (adnlen) t = stpcpy(t, a->entry->dirName); 00305 *t++ = '/'; 00306 if (a->subDir && asnlen) t = stpcpy(t, a->subDir); 00307 if (abnlen) t = stpcpy(t, a->baseName); 00308 if (afn[0] == '/' && afn[1] == '/') afn++; 00309 00310 bfn = t = alloca(bdnlen+bsnlen+bbnlen+2); 00311 if (bdnlen) t = stpcpy(t, b->entry->dirName); 00312 *t++ = '/'; 00313 if (b->subDir && bsnlen) t = stpcpy(t, b->subDir); 00314 if (bbnlen) t = stpcpy(t, b->baseName); 00315 if (bfn[0] == '/' && bfn[1] == '/') bfn++; 00316 /*@=boundswrite@*/ 00317 00318 rc = strcmp(afn, bfn); 00319 00320 return rc; 00321 } 00322 00323 /*@unchecked@*/ 00324 static int _linear_fps_search = 0; 00325 00326 static int findFps(const struct fingerPrint_s * fiFps, 00327 const struct fingerPrint_s * otherFps, 00328 int otherFc) 00329 /*@*/ 00330 { 00331 int otherFileNum; 00332 00333 if (_linear_fps_search) { 00334 00335 linear: 00336 for (otherFileNum = 0; otherFileNum < otherFc; otherFileNum++, otherFps++) { 00337 00338 /* If the addresses are the same, so are the values. */ 00339 if (fiFps == otherFps) 00340 break; 00341 00342 /* Otherwise, compare fingerprints by value. */ 00343 /*@-nullpass@*/ /* LCL: looks good to me */ 00344 if (FP_EQUAL((*fiFps), (*otherFps))) 00345 break; 00346 /*@=nullpass@*/ 00347 } 00348 00349 return otherFileNum; 00350 00351 } else { 00352 00353 const struct fingerPrint_s * bingoFps; 00354 00355 /*@-boundswrite@*/ 00356 bingoFps = bsearch(fiFps, otherFps, otherFc, sizeof(*otherFps), fpsCompare); 00357 /*@=boundswrite@*/ 00358 if (bingoFps == NULL) 00359 goto linear; 00360 00361 /* If the addresses are the same, so are the values. */ 00362 if (!(fiFps == bingoFps || FP_EQUAL((*fiFps), (*bingoFps)))) 00363 goto linear; 00364 00365 otherFileNum = (bingoFps != NULL ? (bingoFps - otherFps) : 0); 00366 00367 } 00368 00369 return otherFileNum; 00370 } 00371 00375 /* XXX only ts->{probs,di} modified */ 00376 static void handleOverlappedFiles(const rpmts ts, 00377 const rpmte p, rpmfi fi) 00378 /*@globals h_errno, fileSystem, internalState @*/ 00379 /*@modifies ts, fi, fileSystem, internalState @*/ 00380 { 00381 uint_32 fixupSize = 0; 00382 rpmps ps; 00383 const char * fn; 00384 int i, j; 00385 00386 ps = rpmtsProblems(ts); 00387 fi = rpmfiInit(fi, 0); 00388 if (fi != NULL) 00389 while ((i = rpmfiNext(fi)) >= 0) { 00390 uint_32 tscolor = rpmtsColor(ts); 00391 uint_32 prefcolor = rpmtsPrefColor(ts); 00392 uint_32 oFColor, FColor; 00393 struct fingerPrint_s * fiFps; 00394 int otherPkgNum, otherFileNum; 00395 rpmfi otherFi; 00396 int_32 FFlags; 00397 int_16 FMode; 00398 const rpmfi * recs; 00399 int numRecs; 00400 00401 if (XFA_SKIPPING(fi->actions[i])) 00402 continue; 00403 00404 fn = rpmfiFN(fi); 00405 fiFps = fi->fps + i; 00406 FFlags = rpmfiFFlags(fi); 00407 FMode = rpmfiFMode(fi); 00408 FColor = rpmfiFColor(fi); 00409 FColor &= tscolor; 00410 00411 fixupSize = 0; 00412 00413 /* 00414 * Retrieve all records that apply to this file. Note that the 00415 * file info records were built in the same order as the packages 00416 * will be installed and removed so the records for an overlapped 00417 * files will be sorted in exactly the same order. 00418 */ 00419 (void) htGetEntry(ts->ht, fiFps, 00420 (const void ***) &recs, &numRecs, NULL); 00421 00422 /* 00423 * If this package is being added, look only at other packages 00424 * being added -- removed packages dance to a different tune. 00425 * 00426 * If both this and the other package are being added, overlapped 00427 * files must be identical (or marked as a conflict). The 00428 * disposition of already installed config files leads to 00429 * a small amount of extra complexity. 00430 * 00431 * If this package is being removed, then there are two cases that 00432 * need to be worried about: 00433 * If the other package is being added, then skip any overlapped files 00434 * so that this package removal doesn't nuke the overlapped files 00435 * that were just installed. 00436 * If both this and the other package are being removed, then each 00437 * file removal from preceding packages needs to be skipped so that 00438 * the file removal occurs only on the last occurence of an overlapped 00439 * file in the transaction set. 00440 * 00441 */ 00442 00443 /* Locate this overlapped file in the set of added/removed packages. */ 00444 for (j = 0; j < numRecs && recs[j] != fi; j++) 00445 {}; 00446 00447 /* Find what the previous disposition of this file was. */ 00448 otherFileNum = -1; /* keep gcc quiet */ 00449 otherFi = NULL; 00450 for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) { 00451 struct fingerPrint_s * otherFps; 00452 int otherFc; 00453 00454 otherFi = recs[otherPkgNum]; 00455 00456 /* Added packages need only look at other added packages. */ 00457 if (rpmteType(p) == TR_ADDED && rpmteType(otherFi->te) != TR_ADDED) 00458 /*@innercontinue@*/ continue; 00459 00460 otherFps = otherFi->fps; 00461 otherFc = rpmfiFC(otherFi); 00462 00463 otherFileNum = findFps(fiFps, otherFps, otherFc); 00464 (void) rpmfiSetFX(otherFi, otherFileNum); 00465 00466 /* XXX Happens iff fingerprint for incomplete package install. */ 00467 if (otherFi->actions[otherFileNum] != FA_UNKNOWN) 00468 /*@innerbreak@*/ break; 00469 } 00470 00471 oFColor = rpmfiFColor(otherFi); 00472 oFColor &= tscolor; 00473 00474 /*@-boundswrite@*/ 00475 switch (rpmteType(p)) { 00476 case TR_ADDED: 00477 { int reportConflicts = 00478 !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES); 00479 int done = 0; 00480 00481 if (otherPkgNum < 0) { 00482 /* XXX is this test still necessary? */ 00483 if (fi->actions[i] != FA_UNKNOWN) 00484 /*@switchbreak@*/ break; 00485 if ((FFlags & RPMFILE_CONFIG) && (FFlags & RPMFILE_EXISTS)) { 00486 /* Here is a non-overlapped pre-existing config file. */ 00487 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE) 00488 ? FA_ALTNAME : FA_BACKUP; 00489 } else { 00490 fi->actions[i] = FA_CREATE; 00491 } 00492 /*@switchbreak@*/ break; 00493 } 00494 00495 assert(otherFi != NULL); 00496 /* Mark added overlapped non-identical files as a conflict. */ 00497 if (rpmfiCompare(otherFi, fi)) { 00498 int rConflicts; 00499 00500 rConflicts = reportConflicts; 00501 /* Resolve file conflicts to prefer Elf64 (if not forced) ... */ 00502 if (tscolor != 0) { 00503 if (FColor & prefcolor) { 00504 /* ... last file of preferred colour is installed ... */ 00505 if (!XFA_SKIPPING(fi->actions[i])) { 00506 /* XXX static helpers are order dependent. Ick. */ 00507 if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade") 00508 && strcmp(fn, "/usr/sbin/glibc_post_upgrade")) 00509 otherFi->actions[otherFileNum] = FA_SKIPCOLOR; 00510 } 00511 fi->actions[i] = FA_CREATE; 00512 rConflicts = 0; 00513 } else 00514 if (oFColor & prefcolor) { 00515 /* ... first file of preferred colour is installed ... */ 00516 if (XFA_SKIPPING(fi->actions[i])) 00517 otherFi->actions[otherFileNum] = FA_CREATE; 00518 fi->actions[i] = FA_SKIPCOLOR; 00519 rConflicts = 0; 00520 } else 00521 if (FColor == 0 && oFColor == 0) { 00522 /* ... otherwise, do both, last in wins. */ 00523 otherFi->actions[otherFileNum] = FA_CREATE; 00524 fi->actions[i] = FA_CREATE; 00525 rConflicts = 0; 00526 } 00527 done = 1; 00528 } 00529 00530 if (rConflicts) { 00531 rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT, 00532 rpmteNEVR(p), rpmteKey(p), 00533 fn, NULL, 00534 rpmteNEVR(otherFi->te), 00535 0); 00536 } 00537 } 00538 00539 /* Try to get the disk accounting correct even if a conflict. */ 00540 fixupSize = rpmfiFSize(otherFi); 00541 00542 if ((FFlags & RPMFILE_CONFIG) && (FFlags & RPMFILE_EXISTS)) { 00543 /* Here is an overlapped pre-existing config file. */ 00544 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE) 00545 ? FA_ALTNAME : FA_SKIP; 00546 } else { 00547 if (!done) 00548 fi->actions[i] = FA_CREATE; 00549 } 00550 } /*@switchbreak@*/ break; 00551 00552 case TR_REMOVED: 00553 if (otherPkgNum >= 0) { 00554 assert(otherFi != NULL); 00555 /* Here is an overlapped added file we don't want to nuke. */ 00556 if (otherFi->actions[otherFileNum] != FA_ERASE) { 00557 /* On updates, don't remove files. */ 00558 fi->actions[i] = FA_SKIP; 00559 /*@switchbreak@*/ break; 00560 } 00561 /* Here is an overlapped removed file: skip in previous. */ 00562 otherFi->actions[otherFileNum] = FA_SKIP; 00563 } 00564 if (XFA_SKIPPING(fi->actions[i])) 00565 /*@switchbreak@*/ break; 00566 if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL) 00567 /*@switchbreak@*/ break; 00568 00569 /* Disposition is assumed to be FA_ERASE. */ 00570 fi->actions[i] = FA_ERASE; 00571 if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG))) 00572 /*@switchbreak@*/ break; 00573 00574 /* Check for pre-existing modified config file that needs saving. */ 00575 if (!(FFlags & RPMFILE_SPARSE)) 00576 { int dalgo = 0; 00577 size_t dlen = 0; 00578 const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen); 00579 unsigned char * fdigest; 00580 assert(digest != NULL); 00581 00582 fdigest = xcalloc(1, dlen); 00583 /* Save (by renaming) locally modified config files. */ 00584 if (!dodigest(dalgo, fn, fdigest, 0, NULL) 00585 && memcmp(digest, fdigest, dlen)) 00586 fi->actions[i] = FA_BACKUP; 00587 fdigest = _free(fdigest); 00588 } 00589 /*@switchbreak@*/ break; 00590 } 00591 /*@=boundswrite@*/ 00592 00593 /* Update disk space info for a file. */ 00594 rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi), 00595 fi->replacedSizes[i], fixupSize, fi->actions[i]); 00596 00597 } 00598 ps = rpmpsFree(ps); 00599 } 00600 00608 /*@-nullpass@*/ 00609 static int ensureOlder(rpmts ts, 00610 const rpmte p, const Header h) 00611 /*@modifies ts @*/ 00612 { 00613 int_32 reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL); 00614 const char * reqEVR; 00615 rpmds req; 00616 char * t; 00617 int nb; 00618 int rc; 00619 00620 if (p == NULL || h == NULL) 00621 return 1; 00622 00623 /*@-boundswrite@*/ 00624 nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1; 00625 t = alloca(nb); 00626 *t = '\0'; 00627 reqEVR = t; 00628 if (rpmteE(p) != NULL) t = stpcpy( stpcpy(t, rpmteE(p)), ":"); 00629 if (rpmteV(p) != NULL) t = stpcpy(t, rpmteV(p)); 00630 *t++ = '-'; 00631 if (rpmteR(p) != NULL) t = stpcpy(t, rpmteR(p)); 00632 /*@=boundswrite@*/ 00633 00634 req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags); 00635 rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote); 00636 req = rpmdsFree(req); 00637 00638 if (rc == 0) { 00639 rpmps ps = rpmtsProblems(ts); 00640 const char * altNEVR = hGetNEVR(h, NULL); 00641 rpmpsAppend(ps, RPMPROB_OLDPACKAGE, 00642 rpmteNEVR(p), rpmteKey(p), 00643 NULL, NULL, 00644 altNEVR, 00645 0); 00646 altNEVR = _free(altNEVR); 00647 ps = rpmpsFree(ps); 00648 rc = 1; 00649 } else 00650 rc = 0; 00651 00652 return rc; 00653 } 00654 /*@=nullpass@*/ 00655 00661 /*@-mustmod@*/ /* FIX: fi->actions is modified. */ 00662 /*@-bounds@*/ 00663 /*@-nullpass@*/ 00664 static void skipFiles(const rpmts ts, rpmfi fi) 00665 /*@globals rpmGlobalMacroContext, h_errno @*/ 00666 /*@modifies fi, rpmGlobalMacroContext @*/ 00667 { 00668 uint_32 tscolor = rpmtsColor(ts); 00669 uint_32 FColor; 00670 int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS); 00671 int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS); 00672 char ** netsharedPaths = NULL; 00673 const char ** languages; 00674 const char * dn, * bn; 00675 int dnlen, bnlen, ix; 00676 const char * s; 00677 int * drc; 00678 char * dff; 00679 int dc; 00680 int i, j; 00681 00682 if (!noDocs) 00683 noDocs = rpmExpandNumeric("%{_excludedocs}"); 00684 00685 { const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL); 00686 /*@-branchstate@*/ 00687 if (tmpPath && *tmpPath != '%') 00688 netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':'); 00689 /*@=branchstate@*/ 00690 tmpPath = _free(tmpPath); 00691 } 00692 00693 s = rpmExpand("%{_install_langs}", NULL); 00694 /*@-branchstate@*/ 00695 if (!(s && *s != '%')) 00696 s = _free(s); 00697 if (s) { 00698 languages = (const char **) splitString(s, strlen(s), ':'); 00699 s = _free(s); 00700 } else 00701 languages = NULL; 00702 /*@=branchstate@*/ 00703 00704 /* Compute directory refcount, skip directory if now empty. */ 00705 dc = rpmfiDC(fi); 00706 drc = alloca(dc * sizeof(*drc)); 00707 memset(drc, 0, dc * sizeof(*drc)); 00708 dff = alloca(dc * sizeof(*dff)); 00709 memset(dff, 0, dc * sizeof(*dff)); 00710 00711 fi = rpmfiInit(fi, 0); 00712 if (fi != NULL) /* XXX lclint */ 00713 while ((i = rpmfiNext(fi)) >= 0) 00714 { 00715 char ** nsp; 00716 00717 bn = rpmfiBN(fi); 00718 bnlen = strlen(bn); 00719 ix = rpmfiDX(fi); 00720 dn = rpmfiDN(fi); 00721 if (dn == NULL) 00722 continue; /* XXX can't happen */ 00723 dnlen = strlen(dn); 00724 00725 drc[ix]++; 00726 00727 /* Don't bother with skipped files */ 00728 if (XFA_SKIPPING(fi->actions[i])) { 00729 drc[ix]--; dff[ix] = 1; 00730 continue; 00731 } 00732 00733 /* Ignore colored files not in our rainbow. */ 00734 FColor = rpmfiFColor(fi); 00735 if (tscolor && FColor && !(tscolor & FColor)) { 00736 drc[ix]--; dff[ix] = 1; 00737 fi->actions[i] = FA_SKIPCOLOR; 00738 continue; 00739 } 00740 00741 /* 00742 * Skip net shared paths. 00743 * Net shared paths are not relative to the current root (though 00744 * they do need to take package relocations into account). 00745 */ 00746 for (nsp = netsharedPaths; nsp && *nsp; nsp++) { 00747 int len; 00748 00749 len = strlen(*nsp); 00750 if (dnlen >= len) { 00751 if (strncmp(dn, *nsp, len)) 00752 /*@innercontinue@*/ continue; 00753 /* Only directories or complete file paths can be net shared */ 00754 if (!(dn[len] == '/' || dn[len] == '\0')) 00755 /*@innercontinue@*/ continue; 00756 } else { 00757 if (len < (dnlen + bnlen)) 00758 /*@innercontinue@*/ continue; 00759 if (strncmp(dn, *nsp, dnlen)) 00760 /*@innercontinue@*/ continue; 00761 /* Insure that only the netsharedpath basename is compared. */ 00762 if ((s = strchr((*nsp) + dnlen, '/')) != NULL && s[1] != '\0') 00763 /*@innercontinue@*/ continue; 00764 if (strncmp(bn, (*nsp) + dnlen, bnlen)) 00765 /*@innercontinue@*/ continue; 00766 len = dnlen + bnlen; 00767 /* Only directories or complete file paths can be net shared */ 00768 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0')) 00769 /*@innercontinue@*/ continue; 00770 } 00771 00772 /*@innerbreak@*/ break; 00773 } 00774 00775 if (nsp && *nsp) { 00776 drc[ix]--; dff[ix] = 1; 00777 fi->actions[i] = FA_SKIPNETSHARED; 00778 continue; 00779 } 00780 00781 /* 00782 * Skip i18n language specific files. 00783 */ 00784 if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) { 00785 const char **lang, *l, *le; 00786 for (lang = languages; *lang != NULL; lang++) { 00787 if (!strcmp(*lang, "all")) 00788 /*@innerbreak@*/ break; 00789 for (l = fi->flangs[i]; *l != '\0'; l = le) { 00790 for (le = l; *le != '\0' && *le != '|'; le++) 00791 {}; 00792 if ((le-l) > 0 && !strncmp(*lang, l, (le-l))) 00793 /*@innerbreak@*/ break; 00794 if (*le == '|') le++; /* skip over | */ 00795 } 00796 if (*l != '\0') 00797 /*@innerbreak@*/ break; 00798 } 00799 if (*lang == NULL) { 00800 drc[ix]--; dff[ix] = 1; 00801 fi->actions[i] = FA_SKIPNSTATE; 00802 continue; 00803 } 00804 } 00805 00806 /* 00807 * Skip config files if requested. 00808 */ 00809 if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) { 00810 drc[ix]--; dff[ix] = 1; 00811 fi->actions[i] = FA_SKIPNSTATE; 00812 continue; 00813 } 00814 00815 /* 00816 * Skip documentation if requested. 00817 */ 00818 if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) { 00819 drc[ix]--; dff[ix] = 1; 00820 fi->actions[i] = FA_SKIPNSTATE; 00821 continue; 00822 } 00823 } 00824 00825 /* Skip (now empty) directories that had skipped files. */ 00826 #ifndef NOTYET 00827 if (fi != NULL) /* XXX can't happen */ 00828 for (j = 0; j < dc; j++) 00829 #else 00830 if ((fi = rpmfiInitD(fi)) != NULL) 00831 while (j = rpmfiNextD(fi) >= 0) 00832 #endif 00833 { 00834 00835 if (drc[j]) continue; /* dir still has files. */ 00836 if (!dff[j]) continue; /* dir was not emptied here. */ 00837 00838 /* Find parent directory and basename. */ 00839 dn = fi->dnl[j]; dnlen = strlen(dn) - 1; 00840 bn = dn + dnlen; bnlen = 0; 00841 while (bn > dn && bn[-1] != '/') { 00842 bnlen++; 00843 dnlen--; 00844 bn--; 00845 } 00846 00847 /* If explicitly included in the package, skip the directory. */ 00848 fi = rpmfiInit(fi, 0); 00849 if (fi != NULL) /* XXX lclint */ 00850 while ((i = rpmfiNext(fi)) >= 0) { 00851 const char * fdn, * fbn; 00852 int_16 fFMode; 00853 00854 if (XFA_SKIPPING(fi->actions[i])) 00855 /*@innercontinue@*/ continue; 00856 00857 fFMode = rpmfiFMode(fi); 00858 00859 if (whatis(fFMode) != XDIR) 00860 /*@innercontinue@*/ continue; 00861 fdn = rpmfiDN(fi); 00862 if (strlen(fdn) != dnlen) 00863 /*@innercontinue@*/ continue; 00864 if (strncmp(fdn, dn, dnlen)) 00865 /*@innercontinue@*/ continue; 00866 fbn = rpmfiBN(fi); 00867 if (strlen(fbn) != bnlen) 00868 /*@innercontinue@*/ continue; 00869 if (strncmp(fbn, bn, bnlen)) 00870 /*@innercontinue@*/ continue; 00871 rpmMessage(RPMMESS_DEBUG, D_("excluding directory %s\n"), dn); 00872 fi->actions[i] = FA_SKIPNSTATE; 00873 /*@innerbreak@*/ break; 00874 } 00875 } 00876 00877 /*@-dependenttrans@*/ 00878 if (netsharedPaths) freeSplitString(netsharedPaths); 00879 if (languages) freeSplitString((char **)languages); 00880 /*@=dependenttrans@*/ 00881 } 00882 /*@=nullpass@*/ 00883 /*@=bounds@*/ 00884 /*@=mustmod@*/ 00885 00892 static /*@null@*/ 00893 rpmfi rpmtsiFi(const rpmtsi tsi) 00894 /*@*/ 00895 { 00896 rpmfi fi = NULL; 00897 00898 if (tsi != NULL && tsi->ocsave != -1) { 00899 /*@-type -abstract@*/ /* FIX: rpmte not opaque */ 00900 rpmte te = rpmtsElement(tsi->ts, tsi->ocsave); 00901 /*@-assignexpose@*/ 00902 if (te != NULL && (fi = te->fi) != NULL) 00903 fi->te = te; 00904 /*@=assignexpose@*/ 00905 /*@=type =abstract@*/ 00906 } 00907 /*@-compdef -refcounttrans -usereleased @*/ 00908 return fi; 00909 /*@=compdef =refcounttrans =usereleased @*/ 00910 } 00911 00918 /*@-nullpass@*/ 00919 static rpmRC _processFailedPackage(rpmts ts, rpmte p) 00920 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00921 /*@modifies ts, p, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00922 { 00923 int rc = RPMRC_OK; /* assume success */ 00924 00925 /* Handle failed packages. */ 00926 /* XXX TODO: Add header to rpmdb in PSM_INIT, not PSM_POST. */ 00927 if (p != NULL && rpmteType(p) == TR_ADDED && !p->installed) { 00928 /*@-compdef -usereleased@*/ /* p->fi->te undefined */ 00929 rpmpsm psm = rpmpsmNew(ts, p, p->fi); 00930 /*@=compdef =usereleased@*/ 00931 /* 00932 * If it died before the header was put in the rpmdb, we need 00933 * do to something wacky which is add the header to the DB anyway. 00934 * This will allow us to add the failed package as an erase 00935 * to the rollback transaction. This must be done because we 00936 * want the the erase scriptlets to run, and the only way that 00937 * is going is if the header is in the rpmdb. 00938 */ 00939 assert(psm != NULL); 00940 psm->stepName = "failed"; /* XXX W2DO? */ 00941 rc = rpmpsmStage(psm, PSM_RPMDB_ADD); 00942 psm = rpmpsmFree(psm); 00943 } 00944 return rc; 00945 } 00946 /*@=nullpass@*/ 00947 00948 /*@-nullpass@*/ 00949 rpmRC rpmtsRollback(rpmts rbts, rpmprobFilterFlags ignoreSet, int running, rpmte rbte) 00950 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00951 /*@modifies rbts, rpmGlobalMacroContext, fileSystem, internalState @*/ 00952 { 00953 const char * semfn = NULL; 00954 rpmRC rc = 0; 00955 uint_32 arbgoal = rpmtsARBGoal(rbts); 00956 QVA_t ia = memset(alloca(sizeof(*ia)), 0, sizeof(*ia)); 00957 time_t ttid; 00958 int xx; 00959 00960 /* Don't attempt rollback's of rollback transactions */ 00961 if ((rpmtsType(rbts) & RPMTRANS_TYPE_ROLLBACK) || 00962 (rpmtsType(rbts) & RPMTRANS_TYPE_AUTOROLLBACK)) 00963 return RPMRC_OK; 00964 00965 if (arbgoal == 0xffffffff) 00966 arbgoal = rpmtsGetTid(rbts); 00967 00968 /* Don't attempt rollbacks if no goal is set. */ 00969 if (!running && arbgoal == 0xffffffff) 00970 return RPMRC_OK; 00971 00972 /* We need to remove an headers that were going to be removed so 00973 * as to not foul up the regular rollback mechanism which will not 00974 * handle properly a file being in the repackaged package directory 00975 * and also its header still in the DB. 00976 */ 00977 { rpmtsi tsi; 00978 rpmte te; 00979 00980 /* XXX Insure an O_RDWR rpmdb. */ 00981 rpmtsOpenDB(rbts, O_RDWR); 00982 00983 tsi = rpmtsiInit(rbts); 00984 while((te = rpmtsiNext(tsi, TR_REMOVED)) != NULL) { 00985 if(!te->u.removed.dboffset) 00986 continue; 00987 rc = rpmdbRemove(rpmtsGetRdb(rbts), 00988 rpmtsGetTid(rbts), 00989 te->u.removed.dboffset, NULL, NULL); 00990 if (rc != RPMRC_OK) { 00991 rpmMessage(RPMMESS_ERROR, _("rpmdb erase failed. NEVRA: %s\n"), 00992 rpmteNEVRA(te)); 00993 break; 00994 } 00995 } 00996 tsi = rpmtsiFree(tsi); 00997 if (rc != RPMRC_OK) 00998 goto cleanup; 00999 } 01000 01001 /* Process the failed package */ 01002 rc = _processFailedPackage(rbts, rbte); 01003 if (rc != RPMRC_OK) 01004 goto cleanup; 01005 01006 rpmtsEmpty(rbts); 01007 01008 ttid = (time_t)arbgoal; 01009 rpmMessage(RPMMESS_NORMAL, _("Rollback to %-24.24s (0x%08x)\n"), 01010 ctime(&ttid), arbgoal); 01011 01012 /* Set the verify signature flags: 01013 * - can't verify signatures/digests on repackaged packages. 01014 * - header check are out. 01015 */ 01016 { 01017 rpmVSFlags vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); 01018 vsflags |= _RPMVSF_NODIGESTS; 01019 vsflags |= _RPMVSF_NOSIGNATURES; 01020 vsflags |= RPMVSF_NOHDRCHK; 01021 vsflags |= RPMVSF_NEEDPAYLOAD; 01022 xx = rpmtsSetVSFlags(rbts, vsflags); 01023 } 01024 01025 /* Set transaction flags to be the same as the running transaction */ 01026 { 01027 rpmtransFlags tsFlags = rpmtsFlags(rbts); 01028 tsFlags &= ~RPMTRANS_FLAG_DIRSTASH; /* No repackage of rollbacks */ 01029 tsFlags &= ~RPMTRANS_FLAG_REPACKAGE; /* No repackage of rollbacks */ 01030 tsFlags |= RPMTRANS_FLAG_NOFDIGESTS; /* Don't check file digests */ 01031 tsFlags = rpmtsSetFlags(rbts, tsFlags); 01032 } 01033 01034 /* Create install arguments structure */ 01035 ia->rbtid = arbgoal; 01036 /* transFlags/depFlags from rbts, (re-)set in rpmRollback(). */ 01037 ia->transFlags = rpmtsFlags(rbts); 01038 ia->depFlags = rpmtsDFlags(rbts); 01039 /* XXX probFilter is normally set in main(). */ 01040 ia->probFilter = ignoreSet; /* XXX RPMPROB_FILTER_NONE? */ 01041 /* XXX installInterfaceFlags is normally set in main(). */ 01042 ia->installInterfaceFlags = INSTALL_UPGRADE | INSTALL_HASH ; 01043 01044 /* rpmtsCheck and rpmtsOrder failures do not have links. */ 01045 ia->no_rollback_links = 1; 01046 01047 /* Create a file semaphore. */ 01048 semfn = rpmExpand("%{?semaphore_backout}", NULL); 01049 if (semfn && *semfn) { 01050 FD_t fd = Fopen(semfn, "w.fdio"); 01051 if (fd) 01052 xx = Fclose(fd); 01053 } 01054 01055 /*@-compmempass@*/ 01056 rc = rpmRollback(rbts, ia, NULL); 01057 /*@=compmempass@*/ 01058 01059 cleanup: 01060 /* Remove the file semaphore. */ 01061 if (semfn && *semfn) 01062 xx = Unlink(semfn); 01063 semfn = _free(semfn); 01064 01065 return rc; 01066 } 01067 /*@=nullpass@*/ 01068 01075 static int cmpArgvStr(/*@null@*/ const char ** AV, /*@null@*/ const char * B) 01076 /*@*/ 01077 { 01078 const char ** a; 01079 01080 if (AV != NULL && B != NULL) 01081 for (a = AV; *a != NULL; a++) { 01082 if (**a && *B && !strcmp(*a, B)) 01083 return 1; 01084 } 01085 return 0; 01086 } 01087 01088 01095 static int markLinkedFailed(rpmts ts, rpmte p) 01096 /*@globals fileSystem @*/ 01097 /*@modifies ts, p, fileSystem @*/ 01098 { 01099 rpmtsi qi; rpmte q; 01100 int bingo; 01101 01102 p->linkFailed = 1; 01103 01104 qi = rpmtsiInit(ts); 01105 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) { 01106 01107 if (q->done) 01108 continue; 01109 01110 /* 01111 * Either element may have missing data and can have multiple entries. 01112 * Try for hdrid, then pkgid, finally NEVRA, argv vs. argv compares. 01113 */ 01114 bingo = cmpArgvStr(q->flink.Hdrid, p->hdrid); 01115 if (!bingo) 01116 bingo = cmpArgvStr(q->flink.Pkgid, p->pkgid); 01117 if (!bingo) 01118 bingo = cmpArgvStr(q->flink.NEVRA, p->NEVRA); 01119 01120 if (!bingo) 01121 continue; 01122 01123 q->linkFailed = p->linkFailed; 01124 } 01125 qi = rpmtsiFree(qi); 01126 01127 return 0; 01128 } 01129 01130 #define NOTIFY(_ts, _al) /*@i@*/ if ((_ts)->notify) (void) (_ts)->notify _al 01131 01132 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) 01133 { 01134 uint_32 tscolor = rpmtsColor(ts); 01135 int i, j; 01136 int ourrc = 0; 01137 int totalFileCount = 0; 01138 rpmfi fi; 01139 sharedFileInfo shared, sharedList; 01140 int numShared; 01141 int nexti; 01142 fingerPrintCache fpc; 01143 rpmps ps; 01144 rpmpsm psm; 01145 rpmtsi pi; rpmte p; 01146 rpmtsi qi; rpmte q; 01147 int numAdded; 01148 int numRemoved; 01149 int rollbackFailures = 0; 01150 void * lock = NULL; 01151 int xx; 01152 01153 /* XXX programmer error segfault avoidance. */ 01154 if (rpmtsNElements(ts) <= 0) { 01155 rpmMessage(RPMMESS_ERROR, 01156 _("Invalid number of transaction elements.\n")); 01157 return -1; 01158 } 01159 01160 rollbackFailures = rpmExpandNumeric("%{?_rollback_transaction_on_failure}"); 01161 /* Don't rollback unless repackaging. */ 01162 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE)) 01163 rollbackFailures = 0; 01164 /* Don't rollback if testing. */ 01165 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) 01166 rollbackFailures = 0; 01167 01168 if (rpmtsType(ts) & (RPMTRANS_TYPE_ROLLBACK | RPMTRANS_TYPE_AUTOROLLBACK)) 01169 rollbackFailures = 0; 01170 01171 /* If we are in test mode, there is no need to rollback on 01172 * failure, nor acquire the transaction lock. 01173 */ 01174 /*@-branchstate@*/ 01175 /* Don't acquire the transaction lock if testing. */ 01176 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) 01177 lock = rpmtsAcquireLock(ts); 01178 /*@=branchstate@*/ 01179 01180 /* --noscripts implies no scripts or triggers, duh. */ 01181 if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS) 01182 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); 01183 /* --notriggers implies no triggers, duh. */ 01184 if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS) 01185 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers)); 01186 01187 /* --justdb implies no scripts or triggers, duh. */ 01188 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) 01189 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); 01190 01191 ts->probs = rpmpsFree(ts->probs); 01192 ts->probs = rpmpsCreate(); 01193 01194 /* XXX Make sure the database is open RDWR for package install/erase. */ 01195 { int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) 01196 ? O_RDONLY : (O_RDWR|O_CREAT); 01197 01198 /* Open database RDWR for installing packages. */ 01199 if (rpmtsOpenDB(ts, dbmode)) { 01200 lock = rpmtsFreeLock(lock); 01201 return -1; /* XXX W2DO? */ 01202 } 01203 } 01204 01205 ts->ignoreSet = ignoreSet; 01206 { const char * currDir = currentDirectory(); 01207 rpmtsSetCurrDir(ts, currDir); 01208 currDir = _free(currDir); 01209 } 01210 01211 (void) rpmtsSetChrootDone(ts, 0); 01212 01213 /* XXX rpmtsCreate() sets the transaction id, but apps may not honor. */ 01214 { int_32 tid = (int_32) time(NULL); 01215 (void) rpmtsSetTid(ts, tid); 01216 } 01217 01218 /* Get available space on mounted file systems. */ 01219 xx = rpmtsInitDSI(ts); 01220 01221 /* =============================================== 01222 * For packages being installed: 01223 * - verify package epoch:version-release is newer. 01224 * - count files. 01225 * For packages being removed: 01226 * - count files. 01227 */ 01228 01229 rpmMessage(RPMMESS_DEBUG, D_("sanity checking %d elements\n"), rpmtsNElements(ts)); 01230 ps = rpmtsProblems(ts); 01231 /* The ordering doesn't matter here */ 01232 pi = rpmtsiInit(ts); 01233 /* XXX Only added packages need be checked. */ 01234 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01235 rpmdbMatchIterator mi; 01236 int fc; 01237 01238 if ((fi = rpmtsiFi(pi)) == NULL) 01239 continue; /* XXX can't happen */ 01240 fc = rpmfiFC(fi); 01241 01242 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) { 01243 Header h; 01244 mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); 01245 while ((h = rpmdbNextIterator(mi)) != NULL) 01246 xx = ensureOlder(ts, p, h); 01247 mi = rpmdbFreeIterator(mi); 01248 } 01249 01250 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) { 01251 mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); 01252 xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, 01253 rpmteE(p)); 01254 xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, 01255 rpmteV(p)); 01256 xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, 01257 rpmteR(p)); 01258 if (tscolor) { 01259 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, 01260 rpmteA(p)); 01261 xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, 01262 rpmteO(p)); 01263 } 01264 01265 while (rpmdbNextIterator(mi) != NULL) { 01266 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED, 01267 rpmteNEVR(p), rpmteKey(p), 01268 NULL, NULL, 01269 NULL, 0); 01270 /*@innerbreak@*/ break; 01271 } 01272 mi = rpmdbFreeIterator(mi); 01273 } 01274 01275 /* Count no. of files (if any). */ 01276 totalFileCount += fc; 01277 01278 } 01279 pi = rpmtsiFree(pi); 01280 ps = rpmpsFree(ps); 01281 01282 /* The ordering doesn't matter here */ 01283 pi = rpmtsiInit(ts); 01284 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { 01285 int fc; 01286 01287 if ((fi = rpmtsiFi(pi)) == NULL) 01288 continue; /* XXX can't happen */ 01289 fc = rpmfiFC(fi); 01290 01291 totalFileCount += fc; 01292 } 01293 pi = rpmtsiFree(pi); 01294 01295 01296 /* Run pre-transaction scripts, but only if there are no known 01297 * problems up to this point. */ 01298 if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST)) 01299 || (rpmpsNumProblems(ts->probs) && 01300 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) 01301 { 01302 rpmMessage(RPMMESS_DEBUG, D_("running pre-transaction scripts\n")); 01303 pi = rpmtsiInit(ts); 01304 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01305 if ((fi = rpmtsiFi(pi)) == NULL) 01306 continue; /* XXX can't happen */ 01307 01308 /* If no pre-transaction script, then don't bother. */ 01309 if (fi->pretrans == NULL) 01310 continue; 01311 01312 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, 01313 rpmteKey(p), ts->notifyData); 01314 p->h = NULL; 01315 if (rpmteFd(p) != NULL) { 01316 rpmVSFlags ovsflags = rpmtsVSFlags(ts); 01317 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD; 01318 rpmRC rpmrc; 01319 ovsflags = rpmtsSetVSFlags(ts, vsflags); 01320 rpmrc = rpmReadPackageFile(ts, rpmteFd(p), 01321 rpmteNEVR(p), &p->h); 01322 vsflags = rpmtsSetVSFlags(ts, ovsflags); 01323 switch (rpmrc) { 01324 default: 01325 /*@-noeffectuncon@*/ /* FIX: notify annotations */ 01326 p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 01327 0, 0, 01328 rpmteKey(p), ts->notifyData); 01329 /*@=noeffectuncon@*/ 01330 p->fd = NULL; 01331 /*@switchbreak@*/ break; 01332 case RPMRC_NOTTRUSTED: 01333 case RPMRC_NOKEY: 01334 case RPMRC_OK: 01335 /*@switchbreak@*/ break; 01336 } 01337 } 01338 01339 /*@-branchstate@*/ 01340 if (rpmteFd(p) != NULL) { 01341 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1); 01342 if (fi != NULL) { /* XXX can't happen */ 01343 fi->te = p; 01344 p->fi = fi; 01345 } 01346 /*@-compdef -usereleased@*/ /* p->fi->te undefined */ 01347 psm = rpmpsmNew(ts, p, p->fi); 01348 /*@=compdef =usereleased@*/ 01349 assert(psm != NULL); 01350 psm->stepName = "pretrans"; 01351 psm->scriptTag = RPMTAG_PRETRANS; 01352 psm->progTag = RPMTAG_PRETRANSPROG; 01353 xx = rpmpsmStage(psm, PSM_SCRIPT); 01354 psm = rpmpsmFree(psm); 01355 01356 /*@-noeffectuncon -compdef -usereleased @*/ 01357 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, 01358 rpmteKey(p), ts->notifyData); 01359 /*@=noeffectuncon =compdef =usereleased @*/ 01360 p->fd = NULL; 01361 p->h = headerFree(p->h); 01362 } 01363 /*@=branchstate@*/ 01364 } 01365 pi = rpmtsiFree(pi); 01366 } 01367 01368 /* =============================================== 01369 * Initialize transaction element file info for package: 01370 */ 01371 01372 /* 01373 * FIXME?: we'd be better off assembling one very large file list and 01374 * calling fpLookupList only once. I'm not sure that the speedup is 01375 * worth the trouble though. 01376 */ 01377 rpmMessage(RPMMESS_DEBUG, D_("computing %d file fingerprints\n"), totalFileCount); 01378 01379 numAdded = numRemoved = 0; 01380 pi = rpmtsiInit(ts); 01381 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01382 int fc; 01383 01384 if ((fi = rpmtsiFi(pi)) == NULL) 01385 continue; /* XXX can't happen */ 01386 fc = rpmfiFC(fi); 01387 01388 /*@-branchstate@*/ 01389 switch (rpmteType(p)) { 01390 case TR_ADDED: 01391 numAdded++; 01392 fi->record = 0; 01393 /* Skip netshared paths, not our i18n files, and excluded docs */ 01394 if (fc > 0) 01395 skipFiles(ts, fi); 01396 /*@switchbreak@*/ break; 01397 case TR_REMOVED: 01398 numRemoved++; 01399 fi->record = rpmteDBOffset(p); 01400 /*@switchbreak@*/ break; 01401 } 01402 /*@=branchstate@*/ 01403 01404 fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL); 01405 } 01406 pi = rpmtsiFree(pi); 01407 01408 if (!rpmtsChrootDone(ts)) { 01409 const char * rootDir = rpmtsRootDir(ts); 01410 static int openall_before_chroot = -1; 01411 01412 if (openall_before_chroot < 0) 01413 openall_before_chroot = rpmExpandNumeric("%{?_openall_before_chroot}"); 01414 01415 xx = Chdir("/"); 01416 /*@-superuser -noeffect @*/ 01417 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { 01418 if (openall_before_chroot) 01419 xx = rpmdbOpenAll(rpmtsGetRdb(ts)); 01420 xx = Chroot(rootDir); 01421 } 01422 /*@=superuser =noeffect @*/ 01423 (void) rpmtsSetChrootDone(ts, 1); 01424 } 01425 01426 ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual); 01427 fpc = fpCacheCreate(totalFileCount); 01428 01429 /* =============================================== 01430 * Add fingerprint for each file not skipped. 01431 */ 01432 pi = rpmtsiInit(ts); 01433 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01434 int fc; 01435 01436 (void) rpmdbCheckSignals(); 01437 01438 if ((fi = rpmtsiFi(pi)) == NULL) 01439 continue; /* XXX can't happen */ 01440 fc = rpmfiFC(fi); 01441 01442 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); 01443 fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps); 01444 /*@-branchstate@*/ 01445 fi = rpmfiInit(fi, 0); 01446 if (fi != NULL) /* XXX lclint */ 01447 while ((i = rpmfiNext(fi)) >= 0) { 01448 if (XFA_SKIPPING(fi->actions[i])) 01449 /*@innercontinue@*/ continue; 01450 /*@-dependenttrans@*/ 01451 htAddEntry(ts->ht, fi->fps + i, (void *) fi); 01452 /*@=dependenttrans@*/ 01453 } 01454 /*@=branchstate@*/ 01455 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc); 01456 01457 } 01458 pi = rpmtsiFree(pi); 01459 01460 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount, 01461 NULL, ts->notifyData)); 01462 01463 /* =============================================== 01464 * Compute file disposition for each package in transaction set. 01465 */ 01466 rpmMessage(RPMMESS_DEBUG, D_("computing file dispositions\n")); 01467 ps = rpmtsProblems(ts); 01468 pi = rpmtsiInit(ts); 01469 /*@-nullpass@*/ 01470 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01471 dbiIndexSet * matches; 01472 unsigned int exclude; 01473 int knownBad; 01474 int fc; 01475 01476 (void) rpmdbCheckSignals(); 01477 01478 if ((fi = rpmtsiFi(pi)) == NULL) 01479 continue; /* XXX can't happen */ 01480 fc = rpmfiFC(fi); 01481 01482 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi), 01483 ts->orderCount, NULL, ts->notifyData)); 01484 01485 if (fc == 0) continue; 01486 01487 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); 01488 /* Extract file info for all files in this package from the database. */ 01489 matches = xcalloc(fc, sizeof(*matches)); 01490 exclude = (rpmteType(p) == TR_REMOVED ? fi->record : 0); 01491 if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc, exclude)) { 01492 ps = rpmpsFree(ps); 01493 lock = rpmtsFreeLock(lock); 01494 return 1; /* XXX WTFO? */ 01495 } 01496 01497 numShared = 0; 01498 fi = rpmfiInit(fi, 0); 01499 while ((i = rpmfiNext(fi)) >= 0) { 01500 struct stat sb, *st = &sb; 01501 uint_32 FFlags = rpmfiFFlags(fi); 01502 numShared += dbiIndexSetCount(matches[i]); 01503 if (!(FFlags & RPMFILE_CONFIG)) 01504 continue; 01505 if (!Lstat(rpmfiFN(fi), st)) { 01506 FFlags |= RPMFILE_EXISTS; 01507 if ((512 * st->st_blocks) < st->st_size) 01508 FFlags |= RPMFILE_SPARSE; 01509 (void) rpmfiSetFFlags(fi, FFlags); 01510 } 01511 } 01512 01513 /* Build sorted file info list for this package. */ 01514 shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList)); 01515 01516 fi = rpmfiInit(fi, 0); 01517 while ((i = rpmfiNext(fi)) >= 0) { 01518 /* 01519 * Take care not to mark files as replaced in packages that will 01520 * have been removed before we will get here. 01521 */ 01522 for (j = 0; j < dbiIndexSetCount(matches[i]); j++) { 01523 int ro; 01524 ro = dbiIndexRecordOffset(matches[i], j); 01525 knownBad = 0; 01526 qi = rpmtsiInit(ts); 01527 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) { 01528 if (ro == knownBad) 01529 /*@innerbreak@*/ break; 01530 if (rpmteDBOffset(q) == ro) 01531 knownBad = ro; 01532 } 01533 qi = rpmtsiFree(qi); 01534 01535 shared->pkgFileNum = i; 01536 shared->otherPkg = dbiIndexRecordOffset(matches[i], j); 01537 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j); 01538 shared->isRemoved = (knownBad == ro); 01539 shared++; 01540 } 01541 matches[i] = dbiFreeIndexSet(matches[i]); 01542 } 01543 numShared = shared - sharedList; 01544 shared->otherPkg = -1; 01545 matches = _free(matches); 01546 01547 /* Sort file info by other package index (otherPkg) */ 01548 qsort(sharedList, numShared, sizeof(*shared), sharedCmp); 01549 01550 /* For all files from this package that are in the database ... */ 01551 /*@-nullpass@*/ 01552 /*@-branchstate@*/ 01553 for (i = 0; i < numShared; i = nexti) { 01554 int beingRemoved; 01555 01556 shared = sharedList + i; 01557 01558 /* Find the end of the files in the other package. */ 01559 for (nexti = i + 1; nexti < numShared; nexti++) { 01560 if (sharedList[nexti].otherPkg != shared->otherPkg) 01561 /*@innerbreak@*/ break; 01562 } 01563 01564 /* Is this file from a package being removed? */ 01565 beingRemoved = 0; 01566 if (ts->removedPackages != NULL) 01567 for (j = 0; j < ts->numRemovedPackages; j++) { 01568 if (ts->removedPackages[j] != shared->otherPkg) 01569 /*@innercontinue@*/ continue; 01570 beingRemoved = 1; 01571 /*@innerbreak@*/ break; 01572 } 01573 01574 /* Determine the fate of each file. */ 01575 switch (rpmteType(p)) { 01576 case TR_ADDED: 01577 xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i, 01578 !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES))); 01579 /*@switchbreak@*/ break; 01580 case TR_REMOVED: 01581 if (!beingRemoved) 01582 xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i); 01583 /*@switchbreak@*/ break; 01584 } 01585 } 01586 /*@=branchstate@*/ 01587 /*@=nullpass@*/ 01588 01589 free(sharedList); 01590 01591 /* Update disk space needs on each partition for this package. */ 01592 /*@-nullpass@*/ 01593 handleOverlappedFiles(ts, p, fi); 01594 /*@=nullpass@*/ 01595 01596 /* Check added package has sufficient space on each partition used. */ 01597 switch (rpmteType(p)) { 01598 case TR_ADDED: 01599 rpmtsCheckDSIProblems(ts, p); 01600 /*@switchbreak@*/ break; 01601 case TR_REMOVED: 01602 /*@switchbreak@*/ break; 01603 } 01604 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc); 01605 } 01606 /*@=nullpass@*/ 01607 pi = rpmtsiFree(pi); 01608 ps = rpmpsFree(ps); 01609 01610 if (rpmtsChrootDone(ts)) { 01611 const char * rootDir = rpmtsRootDir(ts); 01612 const char * currDir = rpmtsCurrDir(ts); 01613 /*@-superuser -noeffect @*/ 01614 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') 01615 xx = Chroot("."); 01616 /*@=superuser =noeffect @*/ 01617 (void) rpmtsSetChrootDone(ts, 0); 01618 if (currDir != NULL) 01619 xx = Chdir(currDir); 01620 } 01621 01622 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount, 01623 NULL, ts->notifyData)); 01624 01625 /* =============================================== 01626 * Free unused memory as soon as possible. 01627 */ 01628 pi = rpmtsiInit(ts); 01629 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01630 if ((fi = rpmtsiFi(pi)) == NULL) 01631 continue; /* XXX can't happen */ 01632 if (rpmfiFC(fi) == 0) 01633 continue; 01634 fi->fps = _free(fi->fps); 01635 } 01636 pi = rpmtsiFree(pi); 01637 01638 fpc = fpCacheFree(fpc); 01639 ts->ht = htFree(ts->ht); 01640 01641 /* =============================================== 01642 * If unfiltered problems exist, free memory and return. 01643 */ 01644 if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) 01645 || (rpmpsNumProblems(ts->probs) && 01646 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))) 01647 ) 01648 { 01649 lock = rpmtsFreeLock(lock); 01650 return ts->orderCount; 01651 } 01652 01653 /* =============================================== 01654 * Save removed files before erasing. 01655 */ 01656 if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) { 01657 int progress; 01658 01659 progress = 0; 01660 pi = rpmtsiInit(ts); 01661 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01662 01663 (void) rpmdbCheckSignals(); 01664 01665 if ((fi = rpmtsiFi(pi)) == NULL) 01666 continue; /* XXX can't happen */ 01667 switch (rpmteType(p)) { 01668 case TR_ADDED: 01669 /*@switchbreak@*/ break; 01670 case TR_REMOVED: 01671 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE)) 01672 /*@switchbreak@*/ break; 01673 if (!progress) 01674 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_START, 01675 7, numRemoved, NULL, ts->notifyData)); 01676 01677 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_PROGRESS, progress, 01678 numRemoved, NULL, ts->notifyData)); 01679 progress++; 01680 01681 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0); 01682 01683 /* XXX TR_REMOVED needs CPIO_MAP_{ABSOLUTE,ADDDOT} CPIO_ALL_HARDLINKS */ 01684 fi->mapflags |= CPIO_MAP_ABSOLUTE; 01685 fi->mapflags |= CPIO_MAP_ADDDOT; 01686 fi->mapflags |= CPIO_ALL_HARDLINKS; 01687 psm = rpmpsmNew(ts, p, fi); 01688 assert(psm != NULL); 01689 xx = rpmpsmStage(psm, PSM_PKGSAVE); 01690 psm = rpmpsmFree(psm); 01691 fi->mapflags &= ~CPIO_MAP_ABSOLUTE; 01692 fi->mapflags &= ~CPIO_MAP_ADDDOT; 01693 fi->mapflags &= ~CPIO_ALL_HARDLINKS; 01694 01695 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0); 01696 01697 /*@switchbreak@*/ break; 01698 } 01699 } 01700 pi = rpmtsiFree(pi); 01701 if (progress) { 01702 NOTIFY(ts, (NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved, 01703 NULL, ts->notifyData)); 01704 } 01705 } 01706 01707 /* =============================================== 01708 * Install and remove packages. 01709 */ 01710 /*@-nullpass@*/ 01711 pi = rpmtsiInit(ts); 01712 /*@-branchstate@*/ /* FIX: fi reload needs work */ 01713 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01714 alKey pkgKey; 01715 int gotfd; 01716 01717 (void) rpmdbCheckSignals(); 01718 01719 gotfd = 0; 01720 if ((fi = rpmtsiFi(pi)) == NULL) 01721 continue; /* XXX can't happen */ 01722 01723 psm = rpmpsmNew(ts, p, fi); 01724 assert(psm != NULL); 01725 psm->unorderedSuccessor = 01726 (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1) ? 1 : 0); 01727 01728 switch (rpmteType(p)) { 01729 case TR_ADDED: 01730 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0); 01731 01732 pkgKey = rpmteAddedKey(p); 01733 01734 rpmMessage(RPMMESS_DEBUG, "========== +++ %s %s-%s 0x%x\n", 01735 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 01736 01737 p->h = NULL; 01738 /*@-type@*/ /* FIX: rpmte not opaque */ 01739 { 01740 /*@-noeffectuncon@*/ /* FIX: notify annotations */ 01741 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, 01742 rpmteKey(p), ts->notifyData); 01743 /*@=noeffectuncon@*/ 01744 if (rpmteFd(p) != NULL) { 01745 rpmVSFlags ovsflags = rpmtsVSFlags(ts); 01746 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD; 01747 rpmRC rpmrc; 01748 01749 ovsflags = rpmtsSetVSFlags(ts, vsflags); 01750 rpmrc = rpmReadPackageFile(ts, rpmteFd(p), 01751 rpmteNEVR(p), &p->h); 01752 vsflags = rpmtsSetVSFlags(ts, ovsflags); 01753 01754 switch (rpmrc) { 01755 default: 01756 /*@-noeffectuncon@*/ /* FIX: notify annotations */ 01757 p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 01758 0, 0, 01759 rpmteKey(p), ts->notifyData); 01760 /*@=noeffectuncon@*/ 01761 p->fd = NULL; 01762 ourrc++; 01763 /*@innerbreak@*/ break; 01764 case RPMRC_NOTTRUSTED: 01765 case RPMRC_NOKEY: 01766 case RPMRC_OK: 01767 /*@innerbreak@*/ break; 01768 } 01769 if (rpmteFd(p) != NULL) gotfd = 1; 01770 } else { 01771 ourrc++; 01772 xx = markLinkedFailed(ts, p); 01773 } 01774 } 01775 /*@=type@*/ 01776 01777 if (rpmteFd(p) != NULL) { 01778 /* 01779 * XXX Sludge necessary to tranfer existing fstates/actions 01780 * XXX around a recreated file info set. 01781 */ 01782 psm->fi = rpmfiFree(psm->fi); 01783 { 01784 char * fstates = fi->fstates; 01785 fileAction * actions = fi->actions; 01786 int mapflags = fi->mapflags; 01787 rpmte savep; 01788 int scareMem = 1; /* XXX rpmpsmStage needs fi->h */ 01789 01790 fi->fstates = NULL; 01791 fi->actions = NULL; 01792 /*@-nullstate@*/ /* FIX: fi->actions is NULL */ 01793 fi = rpmfiFree(fi); 01794 /*@=nullstate@*/ 01795 01796 savep = rpmtsSetRelocateElement(ts, p); 01797 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem); 01798 (void) rpmtsSetRelocateElement(ts, savep); 01799 01800 if (fi != NULL) { /* XXX can't happen */ 01801 fi->te = p; 01802 fi->fstates = _free(fi->fstates); 01803 fi->fstates = fstates; 01804 fi->actions = _free(fi->actions); 01805 fi->actions = actions; 01806 if (mapflags & CPIO_SBIT_CHECK) 01807 fi->mapflags |= CPIO_SBIT_CHECK; 01808 p->fi = fi; 01809 } 01810 } 01811 psm->fi = rpmfiLink(p->fi, NULL); 01812 01813 if ((xx = rpmpsmStage(psm, PSM_PKGINSTALL)) != 0) { 01814 ourrc++; 01815 xx = markLinkedFailed(ts, p); 01816 } else 01817 p->done = 1; 01818 01819 } else { 01820 ourrc++; 01821 } 01822 01823 if (gotfd) { 01824 /*@-noeffectuncon @*/ /* FIX: check rc */ 01825 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, 01826 rpmteKey(p), ts->notifyData); 01827 /*@=noeffectuncon @*/ 01828 /*@-type@*/ 01829 p->fd = NULL; 01830 /*@=type@*/ 01831 } 01832 01833 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0); 01834 01835 /*@switchbreak@*/ break; 01836 01837 case TR_REMOVED: 01838 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0); 01839 01840 rpmMessage(RPMMESS_DEBUG, "========== --- %s %s-%s 0x%x\n", 01841 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 01842 01843 /* If linked element install failed, then don't erase. */ 01844 if (p->linkFailed == 0) { 01845 if ((xx != rpmpsmStage(psm, PSM_PKGERASE)) != 0) { 01846 ourrc++; 01847 } else 01848 p->done = 1; 01849 } else 01850 ourrc++; 01851 01852 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0); 01853 01854 /*@switchbreak@*/ break; 01855 } 01856 01857 /* Would have freed header above in TR_ADD portion of switch 01858 * but needed the header to add it to the autorollback transaction. 01859 */ 01860 if (rpmteType(p) == TR_ADDED) 01861 p->h = headerFree(p->h); 01862 01863 xx = rpmdbSync(rpmtsGetRdb(ts)); 01864 01865 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */ 01866 psm = rpmpsmFree(psm); 01867 /*@=nullstate@*/ 01868 01869 /* If we received an error, lets break out and rollback, provided 01870 * autorollback is enabled. 01871 */ 01872 if (ourrc && rollbackFailures) { 01873 xx = rpmtsRollback(ts, ignoreSet, 1, p); 01874 break; 01875 } 01876 } 01877 /*@=nullpass@*/ 01878 /*@=branchstate@*/ 01879 pi = rpmtsiFree(pi); 01880 01881 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { 01882 rpmMessage(RPMMESS_DEBUG, D_("running post-transaction scripts\n")); 01883 pi = rpmtsiInit(ts); 01884 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01885 int haspostscript; 01886 01887 if ((fi = rpmtsiFi(pi)) == NULL) 01888 continue; /* XXX can't happen */ 01889 01890 haspostscript = (fi->posttrans != NULL ? 1 : 0); 01891 p->fi = rpmfiFree(p->fi); 01892 01893 /* If no post-transaction script, then don't bother. */ 01894 if (!haspostscript) 01895 continue; 01896 01897 p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, 01898 rpmteKey(p), ts->notifyData); 01899 p->h = NULL; 01900 if (rpmteFd(p) != NULL) { 01901 rpmVSFlags ovsflags = rpmtsVSFlags(ts); 01902 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD; 01903 rpmRC rpmrc; 01904 ovsflags = rpmtsSetVSFlags(ts, vsflags); 01905 rpmrc = rpmReadPackageFile(ts, rpmteFd(p), 01906 rpmteNEVR(p), &p->h); 01907 vsflags = rpmtsSetVSFlags(ts, ovsflags); 01908 switch (rpmrc) { 01909 default: 01910 p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 01911 0, 0, rpmteKey(p), ts->notifyData); 01912 p->fd = NULL; 01913 /*@switchbreak@*/ break; 01914 case RPMRC_NOTTRUSTED: 01915 case RPMRC_NOKEY: 01916 case RPMRC_OK: 01917 /*@switchbreak@*/ break; 01918 } 01919 } 01920 01921 /*@-nullpass@*/ 01922 if (rpmteFd(p) != NULL) { 01923 p->fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1); 01924 if (p->fi != NULL) /* XXX can't happen */ 01925 p->fi->te = p; 01926 /*@-compdef -usereleased@*/ /* p->fi->te undefined */ 01927 psm = rpmpsmNew(ts, p, p->fi); 01928 /*@=compdef =usereleased@*/ 01929 assert(psm != NULL); 01930 psm->stepName = "posttrans"; 01931 psm->scriptTag = RPMTAG_POSTTRANS; 01932 psm->progTag = RPMTAG_POSTTRANSPROG; 01933 xx = rpmpsmStage(psm, PSM_SCRIPT); 01934 psm = rpmpsmFree(psm); 01935 01936 /*@-noeffectuncon -compdef -usereleased @*/ 01937 (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, 01938 rpmteKey(p), ts->notifyData); 01939 /*@=noeffectuncon =compdef =usereleased @*/ 01940 p->fd = NULL; 01941 p->fi = rpmfiFree(p->fi); 01942 p->h = headerFree(p->h); 01943 } 01944 /*@=nullpass@*/ 01945 } 01946 pi = rpmtsiFree(pi); 01947 } 01948 01949 lock = rpmtsFreeLock(lock); 01950 01951 /*@-nullstate@*/ /* FIX: ts->flList may be NULL */ 01952 if (ourrc) 01953 return -1; 01954 else 01955 return 0; 01956 /*@=nullstate@*/ 01957 }