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