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