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