|
rpm
5.4.4
|
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 * @param fileCount no. of files 00897 * @return rpmmi sorted by (package, fileNum) 00898 */ 00899 static 00900 rpmmi rpmtsFindBaseNamesInDB(rpmts ts, uint32_t fileCount) 00901 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00902 /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00903 { 00904 rpmtsi pi; rpmte p; 00905 rpmfi fi; 00906 rpmmi mi; 00907 int i, xx; 00908 const char * s; 00909 size_t ns; 00910 void * ptr; 00911 static rpmTag _tag = RPMTAG_BASENAMES; 00912 size_t n = (fileCount > 10 ? fileCount : 10); 00913 static double e = 1.0e-4; 00914 size_t m = 0; 00915 size_t k = 0; 00916 rpmbf bf; 00917 00918 FPSDEBUG(0, (stderr, "--> %s(%p,%u)\n", __FUNCTION__, ts, (unsigned)fileCount)); 00919 rpmbfParams(n, e, &m, &k); 00920 bf = rpmbfNew(m, k, 0); 00921 00922 mi = rpmmiInit(rpmtsGetRdb(ts), _tag, NULL, 0); 00923 00924 pi = rpmtsiInit(ts); 00925 while ((p = rpmtsiNext(pi, 0)) != NULL) { 00926 00927 (void) rpmdbCheckSignals(); 00928 00929 if ((fi = rpmteFI(p, _tag)) == NULL) 00930 continue; /* XXX can't happen */ 00931 00932 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi), 00933 ts->orderCount); 00934 00935 /* Gather all installed headers with matching basename's. */ 00936 fi = rpmfiInit(fi, 0); 00937 while ((i = rpmfiNext(fi)) >= 0) { 00938 s = rpmfiBN(fi); 00939 ns = strlen(s); 00940 00941 if (ns == 0) /* XXX "/" fixup */ 00942 /*@innercontinue@*/ continue; 00943 if (rpmbfChk(bf, s, ns)) 00944 /*@innercontinue@*/ continue; 00945 00946 xx = rpmmiGrowBasename(mi, s); 00947 00948 xx = rpmbfAdd(bf, s, ns); 00949 } 00950 } 00951 pi = rpmtsiFree(pi); 00952 bf = rpmbfFree(bf); 00953 00954 (void) rpmmiSort(mi); 00955 00956 return mi; 00957 } 00958 00959 /* Check files in the transactions against the rpmdb 00960 * Lookup all files with the same basename in the rpmdb 00961 * and then check for matching finger prints 00962 * @param ts transaction set 00963 * @param fpc global finger print cache 00964 */ 00965 static 00966 int rpmtsCheckInstalledFiles(rpmts ts, uint32_t fileCount, 00967 hashTable ht, fingerPrintCache fpc) 00968 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00969 /*@modifies ts, fpc, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00970 { 00971 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00972 rpmTagData BN = { .ptr = NULL }; 00973 rpmTagData DN = { .ptr = NULL }; 00974 rpmTagData DI = { .ptr = NULL }; 00975 rpmTagData FSTATES = { .ptr = NULL }; 00976 rpmuint32_t fc; 00977 00978 rpmte p; 00979 rpmmi mi; 00980 Header h; 00981 rpmfi fi; 00982 00983 const char * oldDir; 00984 int beingRemoved; 00985 rpmfi otherFi = NULL; 00986 unsigned int fileNum; 00987 int xx; 00988 int rc = 0; 00989 00990 FPSDEBUG(0, (stderr, "--> %s(%p,%u,%p,%p)\n", __FUNCTION__, ts, (unsigned)fileCount, ht, fpc)); 00991 00992 rpmlog(RPMLOG_DEBUG, D_("computing file dispositions\n")); 00993 00994 /* XXX fileCount == 0 installing src.rpm's */ 00995 if (fileCount == 0) 00996 return rc; 00997 00998 mi = rpmtsFindBaseNamesInDB(ts, fileCount); 00999 01000 /* Loop over all packages from the rpmdb */ 01001 while ((h = rpmmiNext(mi)) != NULL) { 01002 fingerPrint fp; 01003 uint32_t hdrNum = rpmmiInstance(mi); 01004 uint32_t tagNum = rpmmiBNTag(mi); 01005 int i; 01006 int j; 01007 01008 /* Is this package being removed? */ 01009 beingRemoved = 0; 01010 if (ts->removedPackages != NULL) 01011 for (j = 0; j < ts->numRemovedPackages; j++) { 01012 if (ts->removedPackages[j] != hdrNum) 01013 /*@innercontinue@*/ continue; 01014 beingRemoved = 1; 01015 /*@innerbreak@*/ break; 01016 } 01017 01018 he->tag = RPMTAG_BASENAMES; 01019 xx = headerGet(h, he, 0); 01020 BN.argv = (xx ? he->p.argv : NULL); 01021 fc = (xx ? he->c : 0); 01022 01023 he->tag = RPMTAG_DIRNAMES; 01024 xx = headerGet(h, he, 0); 01025 DN.argv = (xx ? he->p.argv : NULL); 01026 he->tag = RPMTAG_DIRINDEXES; 01027 xx = headerGet(h, he, 0); 01028 DI.ui32p = (xx ? he->p.ui32p : NULL); 01029 he->tag = RPMTAG_FILESTATES; 01030 xx = headerGet(h, he, 0); 01031 FSTATES.ui8p = (xx ? he->p.ui8p : NULL); 01032 01033 /* loop over all interesting files in that package */ 01034 oldDir = NULL; 01035 for (i = 0; i < (int)fc; i++) { 01036 const char * baseName = BN.argv[i]; 01037 rpmuint32_t baseKey = hashFunctionString(0, baseName, 0); 01038 int gotRecs; 01039 struct rpmffi_s ** recs; 01040 int numRecs; 01041 const char * dirName; 01042 01043 /* Skip uninteresting basenames. */ 01044 if (baseKey != tagNum) 01045 /*@innercontinue@*/ continue; 01046 fileNum = i; 01047 dirName = DN.argv[DI.ui32p[fileNum]]; 01048 01049 /* lookup finger print for this file */ 01050 if (dirName == oldDir) { 01051 /* directory is the same as last round */ 01052 fp.baseName = baseName; 01053 } else { 01054 fp = fpLookup(fpc, dirName, baseName, 1); 01055 oldDir = dirName; 01056 } 01057 01058 /* search for files in the transaction with same finger print */ 01059 recs = NULL; 01060 numRecs = 0; 01061 #ifdef REFERENCE 01062 gotRecs = rpmFpHashGetEntry(ht, &fp, &recs, &numRecs, NULL); 01063 #else /* REFERENCE */ 01064 gotRecs = (htGetEntry(ts->ht, &fp, &recs, &numRecs, NULL) == 0); 01065 #endif /* REFERENCE */ 01066 01067 for (j = 0; j < numRecs && gotRecs; j++) { 01068 p = recs[j]->p; 01069 fi = rpmteFI(p, RPMTAG_BASENAMES); 01070 01071 /* Determine the fate of each file. */ 01072 switch (rpmteType(p)) { 01073 case TR_ADDED: 01074 if (otherFi == NULL) { 01075 static int scareMem = 0; 01076 otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem); 01077 } 01078 (void) rpmfiSetFX(fi, recs[j]->fileno); 01079 (void) rpmfiSetFX(otherFi, fileNum); 01080 xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved); 01081 /*@switchbreak@*/ break; 01082 case TR_REMOVED: 01083 if (!beingRemoved) { 01084 (void) rpmfiSetFX(fi, recs[j]->fileno); 01085 #ifdef REFERENCE 01086 if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) { 01087 rpmfs fs = rpmteGetFileStates(p); 01088 rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); 01089 } 01090 #else 01091 if (FSTATES.ui8p[fileNum] == RPMFILE_STATE_NORMAL) 01092 fi->actions[recs[j]->fileno] = FA_SKIP; 01093 #endif 01094 } 01095 /*@switchbreak@*/ break; 01096 } 01097 } 01098 01099 } 01100 01101 otherFi = rpmfiFree(otherFi); 01102 FSTATES.ptr = _free(FSTATES.ptr); 01103 DI.ptr = _free(DI.ptr); 01104 DN.ptr = _free(DN.ptr); 01105 BN.ptr = _free(BN.ptr); 01106 } 01107 01108 mi = rpmmiFree(mi); 01109 01110 return rc; 01111 } 01112 01113 /* 01114 * For packages being installed: 01115 * - verify package arch/os. 01116 * - verify package epoch:version-release is newer. 01117 */ 01118 static rpmps rpmtsSanityCheck(rpmts ts, uint32_t * tfcp) 01119 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01120 /*@modifies ts, *tfcp, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01121 { 01122 rpmps ps; 01123 rpmtsi pi; 01124 rpmte p; 01125 rpmfi fi; 01126 uint32_t totalFileCount = 0; 01127 int fc; 01128 01129 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, tfcp)); 01130 rpmlog(RPMLOG_DEBUG, D_("sanity checking %d elements\n"), rpmtsNElements(ts)); 01131 ps = rpmtsProblems(ts); 01132 /* The ordering doesn't matter here */ 01133 pi = rpmtsiInit(ts); 01134 /* XXX Only added packages need be checked. */ 01135 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01136 int xx; 01137 01138 if (p->isSource) continue; 01139 if ((fi = rpmtsiFi(pi)) == NULL) 01140 continue; /* XXX can't happen */ 01141 fc = rpmfiFC(fi); 01142 01143 #ifdef REFERENCE 01144 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH)) 01145 if (!archOkay(rpmteA(p))) 01146 rpmpsAppend(ps, RPMPROB_BADARCH, 01147 rpmteNEVRA(p), rpmteKey(p), 01148 rpmteA(p), NULL, 01149 NULL, 0); 01150 01151 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS)) 01152 if (!osOkay(rpmteO(p))) 01153 rpmpsAppend(ps, RPMPROB_BADOS, 01154 rpmteNEVRA(p), rpmteKey(p), 01155 rpmteO(p), NULL, 01156 NULL, 0); 01157 #endif /* REFERENCE */ 01158 01159 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) { 01160 rpmmi mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); 01161 Header h; 01162 while ((h = rpmmiNext(mi)) != NULL) 01163 xx = ensureOlder(ts, p, h); 01164 mi = rpmmiFree(mi); 01165 } 01166 01167 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) { 01168 ARGV_t keys = NULL; 01169 int nkeys; 01170 xx = rpmdbMireApply(rpmtsGetRdb(ts), RPMTAG_NVRA, 01171 RPMMIRE_STRCMP, rpmteNEVRA(p), &keys); 01172 nkeys = argvCount(keys); 01173 01174 /* mdvbz: #63711 01175 * workaround for epoch & distepoch not being part of RPMTAG_NVRA, 01176 * leading to packages of same VRA but with different epoch or distepoch 01177 * being treated as the same package */ 01178 if (nkeys > 0) { 01179 int i, t; 01180 rpmTag tags[2] = { RPMTAG_EPOCH, RPMTAG_DISTEPOCH }; 01181 for (t = 0; t < 2; t++) { 01182 for (i = 0; i < nkeys; i++) { 01183 rpmmi mi = rpmtsInitIterator(ts, RPMTAG_NVRA, keys[i], 0); 01184 Header h; 01185 while ((h = rpmmiNext(mi)) != NULL) { 01186 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 01187 const char *val = NULL; 01188 he->tag = tags[t]; 01189 xx = headerGet(h, he, 0); 01190 if (he->tag == RPMTAG_EPOCH) 01191 val = rpmteE(p); 01192 else if (he->tag == RPMTAG_DISTEPOCH) 01193 val = rpmteD(p); 01194 if (strcmp(he->p.str ? he->p.str : "", val ? val : "")) 01195 nkeys--; 01196 he->p.ptr = _free(he->p.ptr); 01197 } 01198 mi = rpmmiFree(mi); 01199 } 01200 } 01201 } 01202 if (nkeys > 0) 01203 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED, 01204 rpmteNEVR(p), rpmteKey(p), 01205 NULL, NULL, 01206 NULL, 0); 01207 keys = argvFree(keys); 01208 } 01209 01210 #ifdef REFERENCE 01211 /* XXX rpmte problems can only be relocation problems atm */ 01212 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_FORCERELOCATE)) { 01213 rpmpsi psi = rpmpsInitIterator(rpmteProblems(p)); 01214 while (rpmpsNextIterator(psi) >= 0) { 01215 rpmpsAppendProblem(ps, rpmpsGetProblem(psi)); 01216 } 01217 rpmpsFreeIterator(psi); 01218 } 01219 #endif /* REFERENCE */ 01220 01221 /* Count no. of files (if any). */ 01222 totalFileCount += fc; 01223 01224 } 01225 pi = rpmtsiFree(pi); 01226 01227 /* The ordering doesn't matter here */ 01228 pi = rpmtsiInit(ts); 01229 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { 01230 01231 if (p->isSource) continue; 01232 if ((fi = rpmtsiFi(pi)) == NULL) 01233 continue; /* XXX can't happen */ 01234 fc = rpmfiFC(fi); 01235 01236 totalFileCount += fc; 01237 } 01238 pi = rpmtsiFree(pi); 01239 01240 if (tfcp) 01241 *tfcp = totalFileCount; 01242 01243 return ps; 01244 } 01245 01246 /* 01247 * Run pre/post transaction script. 01248 * param ts transaction set 01249 * param stag RPMTAG_PRETRANS or RPMTAG_POSTTRANS 01250 * return 0 on success 01251 */ 01252 static int rpmtsRunScript(rpmts ts, rpmTag stag) 01253 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01254 /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01255 { 01256 rpmtsi pi; 01257 rpmte p; 01258 rpmfi fi; 01259 rpmpsm psm; 01260 int xx; 01261 rpmTag ptag; 01262 01263 FPSDEBUG(0, (stderr, "--> %s(%p,%s(%u))\n", __FUNCTION__, ts, tagName(stag), (unsigned)stag)); 01264 switch (stag) { 01265 default: 01266 assert(0); 01267 /*@notreached@*/ break; 01268 case RPMTAG_PRETRANS: ptag = RPMTAG_PRETRANSPROG; break; 01269 case RPMTAG_POSTTRANS: ptag = RPMTAG_POSTTRANSPROG; break; 01270 } 01271 01272 pi = rpmtsiInit(ts); 01273 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01274 if (p->isSource) continue; 01275 if ((fi = rpmtsiFi(pi)) == NULL) 01276 continue; /* XXX can't happen */ 01277 01278 /* If no prre/post transaction script, then don't bother. */ 01279 if (!rpmteHaveTransScript(p, stag)) 01280 continue; 01281 01282 if (rpmteOpen(p, ts, 0)) { 01283 if (p->fi != NULL) /* XXX can't happen */ 01284 p->fi->te = p; 01285 #ifdef REFERENCE 01286 psm = rpmpsmNew(ts, p); 01287 #else /* REFERENCE */ 01288 psm = rpmpsmNew(ts, p, p->fi); 01289 #endif /* REFERENCE */ 01290 xx = rpmpsmScriptStage(psm, stag, ptag); 01291 psm = rpmpsmFree(psm, __FUNCTION__); 01292 xx = rpmteClose(p, ts, 0); 01293 } 01294 } 01295 pi = rpmtsiFree(pi); 01296 01297 return 0; 01298 } 01299 01300 /* Add fingerprint for each file not skipped. */ 01301 static void rpmtsAddFingerprints(rpmts ts, uint32_t fileCount, hashTable ht, 01302 fingerPrintCache fpc) 01303 /*@modifies ts, fpc @*/ 01304 { 01305 rpmtsi pi; 01306 rpmte p; 01307 rpmfi fi; 01308 int i; 01309 01310 hashTable symlinks = htCreate(fileCount/16+16, 0, 0, fpHashFunction, fpEqual); 01311 01312 FPSDEBUG(0, (stderr, "--> %s(%p,%u,%p,%p)\n", __FUNCTION__, ts, (unsigned)fileCount, ht, fpc)); 01313 pi = rpmtsiInit(ts); 01314 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01315 (void) rpmdbCheckSignals(); 01316 01317 if (p->isSource) continue; 01318 if ((fi = rpmtsiFi(pi)) == NULL) 01319 continue; /* XXX can't happen */ 01320 01321 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); 01322 01323 rpmfiFpLookup(fi, fpc); 01324 01325 /* Collect symlinks. */ 01326 fi = rpmfiInit(fi, 0); 01327 if (fi != NULL) /* XXX lclint */ 01328 while ((i = rpmfiNext(fi)) >= 0) { 01329 char const *linktarget; 01330 linktarget = rpmfiFLink(fi); 01331 if (!(linktarget && *linktarget != '\0')) 01332 /*@innercontinue@*/ continue; 01333 if (iosmFileActionSkipped(fi->actions[i])) 01334 /*@innercontinue@*/ continue; 01335 #ifdef REFERENCE 01336 { struct rpmffi_s ffi; 01337 ffi.p = p; 01338 ffi.fileno = i; 01339 htAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi); 01340 } 01341 #else 01342 { struct rpmffi_s *ffip = alloca(sizeof(*ffip)); 01343 /*@-dependenttrans@*/ 01344 ffip->p = p; 01345 /*@=dependenttrans@*/ 01346 ffip->fileno = i; 01347 htAddEntry(symlinks, fi->fps + i, (void *) ffip); 01348 } 01349 #endif 01350 } 01351 01352 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), rpmfiFC(fi)); 01353 01354 } 01355 pi = rpmtsiFree(pi); 01356 01357 /* =============================================== 01358 * Check fingerprints if they contain symlinks 01359 * and add them to the hash table 01360 */ 01361 01362 pi = rpmtsiInit(ts); 01363 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01364 (void) rpmdbCheckSignals(); 01365 01366 if (p->isSource) continue; 01367 if ((fi = rpmteFI(p, RPMTAG_BASENAMES)) == NULL) 01368 continue; /* XXX can't happen */ 01369 fi = rpmfiInit(fi, 0); 01370 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); 01371 while ((i = rpmfiNext(fi)) >= 0) { 01372 #ifdef REFERENCE 01373 if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) 01374 continue; 01375 #else 01376 if (iosmFileActionSkipped(fi->actions[i])) 01377 /*@innercontinue@*/ continue; 01378 #endif 01379 fpLookupSubdir(symlinks, ht, fpc, p, i); 01380 } 01381 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); 01382 } 01383 pi = rpmtsiFree(pi); 01384 01385 symlinks = htFree(symlinks); 01386 01387 } 01388 01389 static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet, rpmsx * sxp) 01390 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01391 /*@modifies ts, *sxp, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01392 { 01393 int xx; 01394 01395 /*@+voidabstract@*/ 01396 FPSDEBUG(0, (stderr, "--> %s(%p,0x%x,%p)\n", __FUNCTION__, ts, ignoreSet, (void *)sxp)); 01397 /*@=voidabstract@*/ 01398 /* --noscripts implies no scripts or triggers, duh. */ 01399 if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS) 01400 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); 01401 /* --notriggers implies no triggers, duh. */ 01402 if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS) 01403 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers)); 01404 01405 /* --justdb implies no scripts or triggers, duh. */ 01406 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) 01407 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); 01408 01409 /* if SELinux isn't enabled or init fails, don't bother... */ 01410 if (!rpmtsSELinuxEnabled(ts)) 01411 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | (RPMTRANS_FLAG_NOCONTEXTS|RPMTRANS_FLAG_NOPOLICY))); 01412 01413 if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOCONTEXTS|RPMTRANS_FLAG_NOPOLICY))) { 01414 *sxp = rpmsxNew("%{?_install_file_context_path}", 0); 01415 if (*sxp == NULL) 01416 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | (RPMTRANS_FLAG_NOCONTEXTS|RPMTRANS_FLAG_NOPOLICY))); 01417 } else 01418 *sxp = NULL; 01419 01420 /* XXX Make sure the database is open RDWR for package install/erase. */ 01421 { int dbmode = O_RDONLY; 01422 01423 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { 01424 rpmtsi pi; 01425 rpmte p; 01426 pi = rpmtsiInit(ts); 01427 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01428 if (p->isSource) continue; 01429 dbmode = (O_RDWR|O_CREAT); 01430 break; 01431 } 01432 pi = rpmtsiFree(pi); 01433 } 01434 01435 /* Open database RDWR for installing packages. */ 01436 if (rpmtsOpenDB(ts, dbmode)) 01437 return -1; /* XXX W2DO? */ 01438 01439 } 01440 01441 ts->ignoreSet = ignoreSet; 01442 ts->probs = rpmpsFree(ts->probs); 01443 01444 { const char * currDir = currentDirectory(); 01445 rpmtsSetCurrDir(ts, currDir); 01446 currDir = _free(currDir); 01447 } 01448 01449 (void) rpmtsSetChrootDone(ts, 0); 01450 01451 /* XXX rpmtsCreate() sets the transaction id, but apps may not honor. */ 01452 { rpmuint32_t tid = (rpmuint32_t) time(NULL); 01453 (void) rpmtsSetTid(ts, tid); 01454 } 01455 01456 /* Get available space on mounted file systems. */ 01457 xx = rpmtsInitDSI(ts); 01458 01459 return 0; 01460 } 01461 01462 static int rpmtsFinish(rpmts ts, /*@only@*/ rpmsx sx) 01463 /*@modifies sx @*/ 01464 { 01465 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, sx)); 01466 #ifdef REFERENCE 01467 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) { 01468 matchpathcon_fini(); 01469 } 01470 #else /* REFERENCE */ 01471 if (sx != NULL) sx = rpmsxFree(sx); 01472 #endif /* REFERENCE */ 01473 return 0; 01474 } 01475 01476 static int rpmtsPrepare(rpmts ts, rpmsx sx, uint32_t fileCount, 01477 uint32_t * nrmvdp) 01478 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01479 /*@modifies ts, *nrmvdp, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01480 { 01481 rpmtsi pi; 01482 rpmte p; 01483 fingerPrintCache fpc; 01484 rpmfi fi; 01485 int xx; 01486 int rc = 0; 01487 01488 #ifdef REFERENCE 01489 uint64_t fileCount = countFiles(ts); 01490 const char * rootDir = rpmtsRootDir(ts); 01491 int dochroot = (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/'); 01492 01493 rpmFpHash ht = rpmFpHashCreate(fileCount/2+1, fpHashFunction, fpEqual, 01494 NULL, NULL); 01495 01496 fpc = fpCacheCreate(fileCount/2 + 10001); 01497 01498 rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount); 01499 01500 /* Skip netshared paths, not our i18n files, and excluded docs */ 01501 pi = rpmtsiInit(ts); 01502 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { 01503 if ((fi = rpmteFI(p)) == NULL) 01504 continue; /* XXX can't happen */ 01505 01506 if (rpmfiFC(fi) > 0) 01507 rpmtsSkipFiles(ts, p); 01508 } 01509 pi = rpmtsiFree(pi); 01510 01511 /* Enter chroot for fingerprinting if necessary */ 01512 if (!rpmtsChrootDone(ts)) { 01513 xx = chdir("/"); 01514 if (dochroot) { 01515 /* opening db before chroot not optimal, see rhbz#103852 c#3 */ 01516 xx = rpmdbOpenAll(ts->rdb); 01517 if (chroot(rootDir) == -1) { 01518 rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n")); 01519 rc = -1; 01520 goto exit; 01521 } 01522 } 01523 (void) rpmtsSetChrootDone(ts, 1); 01524 } 01525 01526 #else /* REFERENCE */ 01527 01528 void * ptr; 01529 uint32_t numAdded = 0; 01530 uint32_t numRemoved = 0; 01531 01532 FPSDEBUG(0, (stderr, "--> %s(%p,%p,%u,%p)\n", __FUNCTION__, ts, sx, (unsigned)fileCount, nrmvdp)); 01533 rpmlog(RPMLOG_DEBUG, D_("computing %u file fingerprints\n"), (unsigned)fileCount); 01534 01535 pi = rpmtsiInit(ts); 01536 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01537 int fc; 01538 01539 if (p->isSource) continue; 01540 if ((fi = rpmtsiFi(pi)) == NULL) 01541 continue; /* XXX can't happen */ 01542 fc = rpmfiFC(fi); 01543 01544 switch (rpmteType(p)) { 01545 case TR_ADDED: 01546 numAdded++; 01547 fi->record = 0; 01548 /* Skip netshared paths, not our i18n files, and excluded docs */ 01549 if (fc > 0) 01550 rpmtsSkipFiles(ts, fi); 01551 /*@switchbreak@*/ break; 01552 case TR_REMOVED: 01553 numRemoved++; 01554 fi->record = rpmteDBOffset(p); 01555 /*@switchbreak@*/ break; 01556 } 01557 01558 fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL); 01559 } 01560 pi = rpmtsiFree(pi); 01561 01562 if (nrmvdp) 01563 *nrmvdp = numRemoved; 01564 01565 if (!rpmtsChrootDone(ts)) { 01566 const char * rootDir = rpmtsRootDir(ts); 01567 static int openall_before_chroot = -1; 01568 01569 if (openall_before_chroot < 0) 01570 openall_before_chroot = rpmExpandNumeric("%{?_openall_before_chroot}"); 01571 01572 xx = Chdir("/"); 01573 /*@-modobserver@*/ 01574 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { 01575 if (openall_before_chroot) 01576 xx = rpmdbOpenAll(rpmtsGetRdb(ts)); 01577 xx = Chroot(rootDir); 01578 } 01579 /*@=modobserver@*/ 01580 (void) rpmtsSetChrootDone(ts, 1); 01581 } 01582 01583 ts->ht = htCreate(fileCount/2 + 1, 0, 1, fpHashFunction, fpEqual); 01584 fpc = fpCacheCreate(fileCount/2 + 10001); 01585 01586 #endif /* REFERENCE */ 01587 01588 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount); 01589 01590 /* =============================================== 01591 * Add fingerprint for each file not skipped. 01592 */ 01593 #ifdef REFERENCE 01594 rpmtsAddFingerprints(ts, fileCount, ht, fpc); 01595 #else /* REFERENCE */ 01596 rpmtsAddFingerprints(ts, fileCount, ts->ht, fpc); 01597 #endif /* REFERENCE */ 01598 01599 /* =============================================== 01600 * Compute file disposition for each package in transaction set. 01601 */ 01602 #ifdef REFERENCE 01603 rpmtsCheckInstalledFiles(ts, fileCount, ht, fpc); 01604 #else /* REFERENCE */ 01605 rc = rpmtsCheckInstalledFiles(ts, fileCount, ts->ht, fpc); 01606 if (rc) 01607 goto exit; 01608 #endif /* REFERENCE */ 01609 01610 pi = rpmtsiInit(ts); 01611 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01612 if ((fi = rpmteFI(p, RPMTAG_BASENAMES)) == NULL) 01613 continue; /* XXX can't happen */ 01614 /* XXX Set all SRPM files to FA_CREATE. */ 01615 if (p->isSource) { 01616 int i; 01617 fi = rpmfiInit(fi, 0); 01618 if (fi != NULL) 01619 while ((i = rpmfiNext(fi)) >= 0) 01620 fi->actions[i] = FA_CREATE; 01621 continue; 01622 } 01623 01624 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); 01625 01626 /* Update disk space needs on each partition for this package. */ 01627 /*@-nullpass@*/ 01628 #ifdef REFERENCE 01629 handleOverlappedFiles(ts, ht, p, fi); 01630 #else /* REFERENCE */ 01631 handleOverlappedFiles(ts, p, fi); 01632 #endif /* REFERENCE */ 01633 /*@=nullpass@*/ 01634 01635 /* Check added package has sufficient space on each partition used. */ 01636 switch (rpmteType(p)) { 01637 case TR_ADDED: 01638 rpmtsCheckDSIProblems(ts, p); 01639 /*@switchbreak@*/ break; 01640 case TR_REMOVED: 01641 /*@switchbreak@*/ break; 01642 } 01643 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), rpmfiFC(fi)); 01644 } 01645 pi = rpmtsiFree(pi); 01646 01647 if (rpmtsChrootDone(ts)) { 01648 const char * rootDir = rpmtsRootDir(ts); 01649 const char * currDir = rpmtsCurrDir(ts); 01650 /*@-modobserver@*/ 01651 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') 01652 xx = Chroot("."); 01653 /*@=modobserver@*/ 01654 (void) rpmtsSetChrootDone(ts, 0); 01655 if (currDir != NULL) 01656 xx = Chdir(currDir); 01657 } 01658 01659 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount); 01660 01661 /* =============================================== 01662 * Free unused memory as soon as possible. 01663 */ 01664 #ifdef REFERENCE 01665 pi = rpmtsiInit(ts); 01666 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01667 rpmteSetFI(p, NULL); 01668 } 01669 pi = rpmtsiFree(pi); 01670 #else /* REFERENCE */ 01671 pi = rpmtsiInit(ts); 01672 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01673 if (p->isSource) continue; 01674 if ((fi = rpmtsiFi(pi)) == NULL) 01675 continue; /* XXX can't happen */ 01676 if (rpmfiFC(fi) == 0) 01677 continue; 01678 fi->fps = _free(fi->fps); 01679 } 01680 pi = rpmtsiFree(pi); 01681 #endif /* REFERENCE */ 01682 01683 exit: 01684 #ifdef REFERENCE 01685 ht = rpmFpHashFree(ht); 01686 #else /* REFERENCE */ 01687 ts->ht = htFree(ts->ht); 01688 #endif /* REFERENCE */ 01689 fpc = fpCacheFree(fpc); 01690 01691 return rc; 01692 } 01693 01694 /* 01695 * Transaction main loop: install and remove packages 01696 */ 01697 static int rpmtsProcess(rpmts ts, rpmprobFilterFlags ignoreSet, 01698 int rollbackFailures) 01699 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01700 /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01701 { 01702 rpmtsi pi; 01703 rpmte p; 01704 int rc = 0; 01705 01706 FPSDEBUG(0, (stderr, "--> %s(%p,0x%x,%d)\n", __FUNCTION__, ts, ignoreSet, rollbackFailures)); 01707 pi = rpmtsiInit(ts); 01708 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01709 rpmfi fi; 01710 rpmop sw; 01711 rpmpsm psm = NULL; 01712 pkgStage stage = PSM_UNKNOWN; 01713 int failed; 01714 int gotfd; 01715 int xx; 01716 01717 #ifdef REFERENCE 01718 rpmElementType tetype = rpmteType(p); 01719 rpmtsOpX op = (tetype == TR_ADDED) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE; 01720 #endif /* REFERENCE */ 01721 01722 (void) rpmdbCheckSignals(); 01723 01724 failed = 1; 01725 gotfd = 0; 01726 if ((fi = rpmtsiFi(pi)) == NULL) 01727 continue; /* XXX can't happen */ 01728 01729 if (rpmteFailed(p)) { 01730 /* XXX this should be a warning, need a better message though */ 01731 rpmlog(RPMLOG_DEBUG, D_("element %s marked as failed, skipping\n"), 01732 rpmteNEVRA(p)); 01733 rc++; 01734 continue; 01735 } 01736 01737 psm = rpmpsmNew(ts, p, fi); 01738 { int async = (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1)) ? 01739 1 : 0; 01740 rpmpsmSetAsync(psm, async); 01741 } 01742 01743 switch (rpmteType(p)) { 01744 case TR_ADDED: 01745 rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n", 01746 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 01747 stage = PSM_PKGINSTALL; 01748 sw = rpmtsOp(ts, RPMTS_OP_INSTALL); 01749 #ifdef REFERENCE 01750 if (rpmteOpen(p, ts, 1)) { 01751 (void) rpmswEnter(rpmtsOp(ts, op), 0); 01752 failed = rpmpsmStage(psm, stage); 01753 (void) rpmswExit(rpmtsOp(ts, op), 0); 01754 rpmteClose(p, ts, 1); 01755 } 01756 #else /* REFERENCE */ 01757 if ((p->h = rpmteFDHeader(ts, p)) != NULL) 01758 gotfd = 1; 01759 01760 if (gotfd && rpmteFd(p) != NULL) { 01761 /* 01762 * XXX Sludge necessary to transfer existing fstates/actions 01763 * XXX around a recreated file info set. 01764 */ 01765 rpmuint8_t * fstates = fi->fstates; 01766 iosmFileAction * actions = (iosmFileAction *) fi->actions; 01767 int mapflags = fi->mapflags; 01768 rpmte savep; 01769 int scareMem = 0; 01770 01771 psm->fi = rpmfiFree(psm->fi); 01772 01773 fi->fstates = NULL; 01774 fi->actions = NULL; 01775 /*@-nullstate@*/ /* FIX: fi->actions is NULL */ 01776 fi = rpmfiFree(fi); 01777 /*@=nullstate@*/ 01778 01779 savep = rpmtsSetRelocateElement(ts, p); 01780 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem); 01781 (void) rpmtsSetRelocateElement(ts, savep); 01782 01783 if (fi != NULL) { /* XXX can't happen */ 01784 fi->te = p; 01785 fi->fstates = _free(fi->fstates); 01786 fi->fstates = fstates; 01787 fi->actions = _free(fi->actions); 01788 fi->actions = (int *) actions; 01789 if (mapflags & IOSM_SBIT_CHECK) 01790 fi->mapflags |= IOSM_SBIT_CHECK; 01791 p->fi = fi; 01792 } 01793 01794 psm->fi = rpmfiLink(p->fi, __FUNCTION__); 01795 01796 (void) rpmswEnter(sw, 0); 01797 failed = (rpmpsmStage(psm, stage) != RPMRC_OK); 01798 (void) rpmswExit(sw, 0); 01799 01800 xx = rpmteClose(p, ts, 0); 01801 gotfd = 0; 01802 } 01803 01804 #endif /* REFERENCE */ 01805 /*@switchbreak@*/ break; 01806 01807 case TR_REMOVED: 01808 rpmlog(RPMLOG_DEBUG, "========== --- %s %s-%s 0x%x\n", 01809 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); 01810 stage = PSM_PKGERASE; 01811 sw = rpmtsOp(ts, RPMTS_OP_ERASE); 01812 #ifdef REFERENCE 01813 if (rpmteOpen(p, ts, 1)) { 01814 (void) rpmswEnter(rpmtsOp(ts, op), 0); 01815 failed = rpmpsmStage(psm, stage); 01816 (void) rpmswExit(rpmtsOp(ts, op), 0); 01817 rpmteClose(p, ts, 1); 01818 } 01819 #else /* REFERENCE */ 01820 (void) rpmswEnter(sw, 0); 01821 failed = (rpmpsmStage(psm, stage) != RPMRC_OK); 01822 (void) rpmswExit(sw, 0); 01823 #endif /* REFERENCE */ 01824 /*@switchbreak@*/ break; 01825 } 01826 01827 #if defined(RPM_VENDOR_MANDRIVA) 01828 if (!failed && !(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { 01829 if(!rpmteIsSource(p)) 01830 xx = mayAddToFilesAwaitingFiletriggers(rpmtsRootDir(ts), 01831 fi, (rpmteType(p) == TR_ADDED ? 1 : 0)); 01832 p->done = 1; 01833 } 01834 #endif 01835 01836 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */ 01837 psm = rpmpsmFree(psm, __FUNCTION__); 01838 /*@=nullstate@*/ 01839 01840 if (failed) { 01841 rc++; 01842 #ifdef REFERENCE 01843 rpmteMarkFailed(p, ts); 01844 #else /* REFERENCE */ 01845 xx = rpmtsMarkLinkedFailed(ts, p); 01846 /* If we received an error, lets break out and rollback, provided 01847 * autorollback is enabled. 01848 */ 01849 if (rollbackFailures) { 01850 xx = rpmtsRollback(ts, ignoreSet, 1, p); 01851 break; 01852 } 01853 #endif /* REFERENCE */ 01854 } 01855 01856 if (p->h != NULL) { 01857 (void) headerFree(p->h); 01858 p->h = NULL; 01859 } 01860 01861 #ifdef REFERENCE 01862 (void) rpmdbSync(rpmtsGetRdb(ts)); 01863 #endif /* REFERENCE */ 01864 01865 } 01866 pi = rpmtsiFree(pi); 01867 return rc; 01868 } 01869 01870 /* ================================================================= */ 01871 static int rpmtsRepackage(rpmts ts, uint32_t numRemoved) 01872 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01873 /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01874 { 01875 rpmpsm psm; 01876 rpmfi fi; 01877 rpmtsi pi; 01878 rpmte p; 01879 void * ptr; 01880 int progress = 0; 01881 int rc = 0; 01882 int xx; 01883 01884 FPSDEBUG(0, (stderr, "--> %s(%p,%u)\n", __FUNCTION__, ts, (unsigned)numRemoved)); 01885 pi = rpmtsiInit(ts); 01886 while ((p = rpmtsiNext(pi, 0)) != NULL) { 01887 01888 (void) rpmdbCheckSignals(); 01889 01890 if (p->isSource) continue; 01891 if ((fi = rpmtsiFi(pi)) == NULL) 01892 continue; /* XXX can't happen */ 01893 switch (rpmteType(p)) { 01894 case TR_ADDED: 01895 /*@switchbreak@*/ break; 01896 case TR_REMOVED: 01897 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE)) 01898 /*@switchbreak@*/ break; 01899 if (!progress) 01900 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_START, 01901 7, numRemoved); 01902 01903 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_PROGRESS, 01904 progress, numRemoved); 01905 progress++; 01906 01907 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0); 01908 01909 /* XXX TR_REMOVED needs IOSM_MAP_{ABSOLUTE,ADDDOT} IOSM_ALL_HARDLINKS */ 01910 fi->mapflags |= IOSM_MAP_ABSOLUTE; 01911 fi->mapflags |= IOSM_MAP_ADDDOT; 01912 fi->mapflags |= IOSM_ALL_HARDLINKS; 01913 psm = rpmpsmNew(ts, p, fi); 01914 assert(psm != NULL); 01915 xx = rpmpsmStage(psm, PSM_PKGSAVE); 01916 psm = rpmpsmFree(psm, __FUNCTION__); 01917 fi->mapflags &= ~IOSM_MAP_ABSOLUTE; 01918 fi->mapflags &= ~IOSM_MAP_ADDDOT; 01919 fi->mapflags &= ~IOSM_ALL_HARDLINKS; 01920 01921 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0); 01922 01923 /*@switchbreak@*/ break; 01924 } 01925 } 01926 pi = rpmtsiFree(pi); 01927 if (progress) 01928 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved); 01929 01930 return rc; 01931 } 01932 01939 /*@-nullpass@*/ 01940 static rpmRC _processFailedPackage(rpmts ts, rpmte p) 01941 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01942 /*@modifies ts, p, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01943 { 01944 int rc = RPMRC_OK; /* assume success */ 01945 01946 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, p)); 01947 /* Handle failed packages. */ 01948 /* XXX TODO: Add header to rpmdb in PSM_INIT, not PSM_POST. */ 01949 if (p != NULL && rpmteType(p) == TR_ADDED && !p->installed) { 01950 /*@-compdef -usereleased@*/ /* p->fi->te undefined */ 01951 rpmpsm psm = rpmpsmNew(ts, p, p->fi); 01952 /*@=compdef =usereleased@*/ 01953 /* 01954 * If it died before the header was put in the rpmdb, we need 01955 * do to something wacky which is add the header to the DB anyway. 01956 * This will allow us to add the failed package as an erase 01957 * to the rollback transaction. This must be done because we 01958 * want the the erase scriptlets to run, and the only way that 01959 * is going is if the header is in the rpmdb. 01960 */ 01961 assert(psm != NULL); 01962 psm->stepName = "failed"; /* XXX W2DO? */ 01963 rc = rpmpsmStage(psm, PSM_RPMDB_ADD); 01964 psm = rpmpsmFree(psm, __FUNCTION__); 01965 } 01966 return rc; 01967 } 01968 /*@=nullpass@*/ 01969 01970 /*@-nullpass@*/ 01971 rpmRC rpmtsRollback(rpmts rbts, rpmprobFilterFlags ignoreSet, int running, rpmte rbte) 01972 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 01973 /*@modifies rbts, rpmGlobalMacroContext, fileSystem, internalState @*/ 01974 { 01975 const char * semfn = NULL; 01976 rpmRC rc = 0; 01977 rpmuint32_t arbgoal = rpmtsARBGoal(rbts); 01978 QVA_t ia = memset(alloca(sizeof(*ia)), 0, sizeof(*ia)); 01979 time_t ttid; 01980 int xx; 01981 01982 FPSDEBUG(0, (stderr, "--> %s(%p,0x%x,%d,%p)\n", __FUNCTION__, rbts, ignoreSet, running, rbte)); 01983 /* Don't attempt rollback's of rollback transactions */ 01984 if ((rpmtsType(rbts) & RPMTRANS_TYPE_ROLLBACK) || 01985 (rpmtsType(rbts) & RPMTRANS_TYPE_AUTOROLLBACK)) 01986 return RPMRC_OK; 01987 01988 if (arbgoal == 0xffffffff) 01989 arbgoal = rpmtsGetTid(rbts); 01990 01991 /* Don't attempt rollbacks if no goal is set. */ 01992 if (!running && arbgoal == 0xffffffff) 01993 return RPMRC_OK; 01994 01995 /* We need to remove an headers that were going to be removed so 01996 * as to not foul up the regular rollback mechanism which will not 01997 * handle properly a file being in the repackaged package directory 01998 * and also its header still in the DB. 01999 */ 02000 { rpmtsi tsi; 02001 rpmte te; 02002 02003 /* XXX Insure an O_RDWR rpmdb. */ 02004 xx = rpmtsOpenDB(rbts, O_RDWR); 02005 02006 tsi = rpmtsiInit(rbts); 02007 while((te = rpmtsiNext(tsi, TR_REMOVED)) != NULL) { 02008 if (te->isSource) continue; 02009 if(!te->u.removed.dboffset) 02010 continue; 02011 rc = rpmdbRemove(rpmtsGetRdb(rbts), 02012 rpmtsGetTid(rbts), 02013 te->u.removed.dboffset, NULL); 02014 if (rc != RPMRC_OK) { 02015 rpmlog(RPMLOG_ERR, _("rpmdb erase failed. NEVRA: %s\n"), 02016 rpmteNEVRA(te)); 02017 break; 02018 } 02019 } 02020 tsi = rpmtsiFree(tsi); 02021 if (rc != RPMRC_OK) 02022 goto cleanup; 02023 } 02024 02025 /* Process the failed package */ 02026 rc = _processFailedPackage(rbts, rbte); 02027 if (rc != RPMRC_OK) 02028 goto cleanup; 02029 02030 rpmtsEmpty(rbts); 02031 02032 ttid = (time_t)arbgoal; 02033 rpmlog(RPMLOG_NOTICE, _("Rollback to %-24.24s (0x%08x)\n"), 02034 ctime(&ttid), arbgoal); 02035 02036 /* Set the verify signature flags: 02037 * - can't verify signatures/digests on repackaged packages. 02038 * - header check are out. 02039 */ 02040 { 02041 rpmVSFlags vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); 02042 vsflags |= _RPMVSF_NODIGESTS; 02043 vsflags |= _RPMVSF_NOSIGNATURES; 02044 vsflags |= RPMVSF_NOHDRCHK; 02045 vsflags |= RPMVSF_NEEDPAYLOAD; 02046 xx = rpmtsSetVSFlags(rbts, vsflags); 02047 } 02048 02049 /* Set transaction flags to be the same as the running transaction */ 02050 { 02051 rpmtransFlags tsFlags = rpmtsFlags(rbts); 02052 tsFlags &= ~RPMTRANS_FLAG_DIRSTASH; /* No repackage of rollbacks */ 02053 tsFlags &= ~RPMTRANS_FLAG_REPACKAGE; /* No repackage of rollbacks */ 02054 tsFlags |= RPMTRANS_FLAG_NOFDIGESTS; /* Don't check file digests */ 02055 tsFlags = rpmtsSetFlags(rbts, tsFlags); 02056 } 02057 02058 /* Create install arguments structure */ 02059 ia->rbtid = arbgoal; 02060 /* transFlags/depFlags from rbts, (re-)set in rpmRollback(). */ 02061 ia->transFlags = rpmtsFlags(rbts); 02062 ia->depFlags = rpmtsDFlags(rbts); 02063 /* XXX probFilter is normally set in main(). */ 02064 ia->probFilter = ignoreSet; /* XXX RPMPROB_FILTER_NONE? */ 02065 /* XXX installInterfaceFlags is normally set in main(). */ 02066 ia->installInterfaceFlags = INSTALL_UPGRADE | INSTALL_HASH ; 02067 02068 /* rpmtsCheck and rpmtsOrder failures do not have links. */ 02069 ia->no_rollback_links = 1; 02070 02071 /* Create a file semaphore. */ 02072 semfn = rpmExpand("%{?semaphore_backout}", NULL); 02073 if (semfn && *semfn) { 02074 FD_t fd = Fopen(semfn, "w.fdio"); 02075 if (fd) 02076 xx = Fclose(fd); 02077 } 02078 02079 /*@-compmempass@*/ 02080 rc = rpmRollback(rbts, ia, NULL); 02081 /*@=compmempass@*/ 02082 02083 cleanup: 02084 /* Remove the file semaphore. */ 02085 if (semfn && *semfn) 02086 xx = Unlink(semfn); 02087 semfn = _free(semfn); 02088 02089 return rc; 02090 } 02091 /*@=nullpass@*/ 02092 02093 int _rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) 02094 { 02095 int ourrc = -1; /* assume failure */ 02096 uint32_t totalFileCount = 0; 02097 rpmps ps; 02098 rpmsx sx = NULL; 02099 uint32_t numRemoved; 02100 int rollbackFailures = 0; 02101 void * lock = NULL; 02102 int xx; 02103 02104 FPSDEBUG(0, (stderr, "--> %s(%p,%p,0x%x)\n", __FUNCTION__, ts, okProbs, ignoreSet)); 02105 if (_rpmts_debug) 02106 fprintf(stderr, "--> %s(%p,%p,0x%x) tsFlags 0x%x\n", __FUNCTION__, ts, okProbs, (unsigned) ignoreSet, rpmtsFlags(ts)); 02107 02108 /* XXX programmer error segfault avoidance. */ 02109 if (rpmtsNElements(ts) <= 0) { 02110 rpmlog(RPMLOG_ERR, 02111 _("Invalid number of transaction elements.\n")); 02112 return -1; 02113 } 02114 02115 /* Don't acquire the transaction lock if testing. */ 02116 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) 02117 lock = rpmtsAcquireLock(ts); 02118 02119 rollbackFailures = rpmExpandNumeric("%{?_rollback_transaction_on_failure}"); 02120 /* Don't rollback unless repackaging. */ 02121 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE)) 02122 rollbackFailures = 0; 02123 /* Don't rollback if testing. */ 02124 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) 02125 rollbackFailures = 0; 02126 02127 if (rpmtsType(ts) & (RPMTRANS_TYPE_ROLLBACK | RPMTRANS_TYPE_AUTOROLLBACK)) 02128 rollbackFailures = 0; 02129 02130 /* =============================================== 02131 * Setup flags and such, open the rpmdb in O_RDWR mode. 02132 */ 02133 sx = NULL; 02134 if (rpmtsSetup(ts, ignoreSet, &sx)) 02135 goto exit; 02136 02137 /* =============================================== 02138 * For packages being installed: 02139 * - verify package epoch:version-release is newer. 02140 * - count files. 02141 * For packages being removed: 02142 * - count files. 02143 */ 02144 02145 totalFileCount = 0; 02146 ps = rpmtsSanityCheck(ts, &totalFileCount); 02147 ps = rpmpsFree(ps); 02148 02149 /* =============================================== 02150 * Run pre-transaction scripts, but only if no known problems exist. 02151 */ 02152 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRETRANS) && 02153 (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST)) 02154 || (rpmpsNumProblems(ts->probs) && 02155 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))))) 02156 { 02157 rpmlog(RPMLOG_DEBUG, D_("running pre-transaction scripts\n")); 02158 xx = rpmtsRunScript(ts, RPMTAG_PRETRANS); 02159 } 02160 02161 /* =============================================== 02162 * Compute file disposition for each package in transaction set. 02163 */ 02164 numRemoved = 0; 02165 if (rpmtsPrepare(ts, sx, totalFileCount, &numRemoved)) 02166 goto exit; 02167 02168 /* =============================================== 02169 * If unfiltered problems exist, free memory and return. 02170 */ 02171 if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) 02172 || (rpmpsNumProblems(ts->probs) && 02173 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))) 02174 ) 02175 { 02176 lock = rpmtsFreeLock(lock); 02177 if (sx != NULL) sx = rpmsxFree(sx); 02178 return ts->orderCount; 02179 } 02180 02181 /* =============================================== 02182 * Save removed files before erasing. 02183 */ 02184 if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) { 02185 xx = rpmtsRepackage(ts, numRemoved); 02186 } 02187 02188 #ifdef NOTYET 02189 xx = rpmtxnBegin(rpmtsGetRdb(ts), NULL, &ts->txn); 02190 #endif 02191 02192 /* =============================================== 02193 * Install and remove packages. 02194 */ 02195 ourrc = rpmtsProcess(ts, ignoreSet, rollbackFailures); 02196 02197 /* =============================================== 02198 * Run post-transaction scripts unless disabled. 02199 */ 02200 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTTRANS) && 02201 !(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) 02202 { 02203 02204 #if defined(RPM_VENDOR_MANDRIVA) 02205 if ((rpmtsFlags(ts) & _noTransTriggers) != _noTransTriggers) 02206 rpmRunFileTriggers(rpmtsRootDir(ts)); 02207 #endif 02208 02209 rpmlog(RPMLOG_DEBUG, D_("running post-transaction scripts\n")); 02210 xx = rpmtsRunScript(ts, RPMTAG_POSTTRANS); 02211 } 02212 02213 exit: 02214 xx = rpmtsFinish(ts, sx); 02215 02216 lock = rpmtsFreeLock(lock); 02217 02218 /*@-nullstate@*/ /* FIX: ts->flList may be NULL */ 02219 if (ourrc) { 02220 if (ts->txn != NULL) 02221 xx = rpmtxnAbort(ts->txn); 02222 ts->txn = NULL; 02223 return -1; 02224 } else { 02225 if (ts->txn != NULL) 02226 xx = rpmtxnCommit(ts->txn); 02227 ts->txn = NULL; 02228 xx = rpmtxnCheckpoint(rpmtsGetRdb(ts)); 02229 return 0; 02230 } 02231 /*@=nullstate@*/ 02232 } 02233 02234 int (*rpmtsRun) (rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) 02235 = _rpmtsRun;
1.7.5.1