rpm 5.2.1
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> /* XXX fnpyKey */ 00009 #include <rpmlog.h> 00010 #include <iosm.h> /* XXX iosmFileAction */ 00011 #include <rpmurl.h> 00012 #include <rpmpgp.h> 00013 #include <rpmmacro.h> /* XXX rpmtsOpenDB() needs rpmGetPath */ 00014 #include <rpmkeyring.h> 00015 00016 #include <rpmtypes.h> 00017 #include <rpmtag.h> 00018 #include <pkgio.h> 00019 00020 #define _RPMDB_INTERNAL /* XXX almost opaque sigh */ 00021 #include "rpmdb.h" /* XXX stealing db->db_mode. */ 00022 00023 #include "rpmal.h" 00024 #include "rpmds.h" 00025 #include "rpmfi.h" 00026 #include "rpmlock.h" 00027 #include "rpmns.h" 00028 00029 #define _RPMTE_INTERNAL /* XXX te->h */ 00030 #include "rpmte.h" 00031 00032 #define _RPMTS_INTERNAL 00033 #include "rpmts.h" 00034 00035 #include <rpmcli.h> 00036 00037 #include "fs.h" 00038 00039 /* XXX FIXME: merge with existing (broken?) tests in system.h */ 00040 /* portability fiddles */ 00041 #if STATFS_IN_SYS_STATVFS 00042 /*@-incondefs@*/ 00043 #if defined(__LCLINT__) 00044 /*@-declundef -exportheader -protoparammatch @*/ /* LCL: missing annotation */ 00045 extern int statvfs (const char * file, /*@out@*/ struct statvfs * buf) 00046 /*@globals fileSystem @*/ 00047 /*@modifies *buf, fileSystem @*/; 00048 /*@=declundef =exportheader =protoparammatch @*/ 00049 /*@=incondefs@*/ 00050 #else 00051 # include <sys/statvfs.h> 00052 #endif 00053 #else 00054 # if STATFS_IN_SYS_VFS 00055 # include <sys/vfs.h> 00056 # else 00057 # if STATFS_IN_SYS_MOUNT 00058 # include <sys/mount.h> 00059 # else 00060 # if STATFS_IN_SYS_STATFS 00061 # include <sys/statfs.h> 00062 # endif 00063 # endif 00064 # endif 00065 #endif 00066 00067 #include "debug.h" 00068 00069 /*@access FD_t @*/ /* XXX void * arg */ 00070 /*@access rpmdb @*/ /* XXX db->db_chrootDone, NULL */ 00071 00072 /*@access rpmDiskSpaceInfo @*/ 00073 /*@access rpmKeyring @*/ 00074 /*@access rpmps @*/ 00075 /*@access rpmsx @*/ 00076 /*@access rpmte @*/ 00077 /*@access rpmtsi @*/ 00078 /*@access fnpyKey @*/ 00079 /*@access pgpDig @*/ 00080 /*@access pgpDigParams @*/ 00081 00082 /*@unchecked@*/ 00083 int _rpmts_debug = 0; 00084 00085 /*@unchecked@*/ 00086 int _rpmts_stats = 0; 00087 00088 /*@unchecked@*/ 00089 int _rpmts_macros = 0; 00090 00091 int rpmtsCloseDB(rpmts ts) 00092 { 00093 int rc = 0; 00094 00095 if (ts->rdb != NULL) { 00096 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->rdb->db_getops); 00097 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->rdb->db_putops); 00098 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->rdb->db_delops); 00099 rc = rpmdbClose(ts->rdb); 00100 ts->rdb = NULL; 00101 } 00102 return rc; 00103 } 00104 00105 int rpmtsOpenDB(rpmts ts, int dbmode) 00106 { 00107 int rc = 0; 00108 00109 if (ts->rdb != NULL && ts->dbmode == dbmode) 00110 return 0; 00111 00112 (void) rpmtsCloseDB(ts); 00113 00114 /* XXX there's a db lock race here that is the callers responsibility. */ 00115 00116 ts->dbmode = dbmode; 00117 rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644); 00118 if (rc) { 00119 const char * dn; 00120 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL); 00121 rpmlog(RPMLOG_ERR, 00122 _("cannot open Packages database in %s\n"), dn); 00123 dn = _free(dn); 00124 } 00125 return rc; 00126 } 00127 00128 int rpmtsInitDB(rpmts ts, int dbmode) 00129 { 00130 #if defined(SUPPORT_INITDB) 00131 void *lock = rpmtsAcquireLock(ts); 00132 int rc = rpmdbInit(ts->rootDir, dbmode); 00133 lock = rpmtsFreeLock(lock); 00134 return rc; 00135 #else 00136 return -1; 00137 #endif 00138 } 00139 00140 int rpmtsRebuildDB(rpmts ts) 00141 { 00142 void * lock = rpmtsAcquireLock(ts); 00143 int rc = rpmtsOpenDB(ts, ts->dbmode); 00144 00145 if (rc == 0) 00146 rc = rpmdbRebuild(ts->rootDir, 00147 (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK) ? ts : NULL)); 00148 lock = rpmtsFreeLock(lock); 00149 return rc; 00150 } 00151 00152 int rpmtsVerifyDB(rpmts ts) 00153 { 00154 #if defined(SUPPORT_VERIFYDB) 00155 return rpmdbVerify(ts->rootDir); 00156 #else 00157 return -1; 00158 #endif 00159 } 00160 00161 /*@-compdef@*/ /* keyp might not be defined. */ 00162 rpmmi rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, 00163 const void * keyp, size_t keylen) 00164 { 00165 rpmmi mi; 00166 const char * arch = NULL; 00167 int xx; 00168 00169 if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode)) 00170 return NULL; 00171 00172 /* Parse out "N(EVR).A" tokens from a label key. */ 00173 if (rpmtag == RPMDBI_LABEL && keyp != NULL) { 00174 const char * s = keyp; 00175 const char *se; 00176 size_t slen = strlen(s); 00177 char *t = alloca(slen+1); 00178 int level = 0; 00179 int c; 00180 00181 keyp = t; 00182 while ((c = *s++) != '\0') { 00183 switch (c) { 00184 default: 00185 *t++ = (char)c; 00186 /*@switchbreak@*/ break; 00187 case '(': 00188 /* XXX Fail if nested parens. */ 00189 if (level++ != 0) { 00190 rpmlog(RPMLOG_ERR, _("extra '(' in package label: %s\n"), (char *)keyp); 00191 return NULL; 00192 } 00193 /* Parse explicit epoch. */ 00194 for (se = s; *se && xisdigit(*se); se++) 00195 {}; 00196 if (*se == ':') { 00197 /* XXX skip explicit epoch's (for now) */ 00198 *t++ = '-'; 00199 s = se + 1; 00200 } else { 00201 /* No Epoch: found. Convert '(' to '-' and chug. */ 00202 *t++ = '-'; 00203 } 00204 /*@switchbreak@*/ break; 00205 case ')': 00206 /* XXX Fail if nested parens. */ 00207 if (--level != 0) { 00208 rpmlog(RPMLOG_ERR, _("missing '(' in package label: %s\n"), (char *)keyp); 00209 return NULL; 00210 } 00211 /* Don't copy trailing ')' */ 00212 /*@switchbreak@*/ break; 00213 } 00214 } 00215 if (level) { 00216 rpmlog(RPMLOG_ERR, _("missing ')' in package label: %s\n"), (char *)keyp); 00217 return NULL; 00218 } 00219 *t = '\0'; 00220 t = (char *) keyp; 00221 t = strrchr(t, '.'); 00222 /* Is this a valid ".arch" suffix? */ 00223 if (t != NULL && rpmnsArch(t+1)) { 00224 *t++ = '\0'; 00225 arch = t; 00226 } 00227 } 00228 00229 mi = rpmmiInit(ts->rdb, rpmtag, keyp, keylen); 00230 00231 /* Verify header signature/digest during retrieve (if not disabled). */ 00232 if (mi && !(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK)) 00233 (void) rpmmiSetHdrChk(mi, ts); 00234 00235 /* Select specified arch only. */ 00236 if (arch != NULL) 00237 xx = rpmmiAddPattern(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT, arch); 00238 return mi; 00239 } 00240 /*@=compdef@*/ 00241 00242 int rpmtsCloseSDB(rpmts ts) 00243 { 00244 int rc = 0; 00245 00246 if (ts->sdb != NULL) { 00247 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->sdb->db_getops); 00248 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->sdb->db_putops); 00249 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->sdb->db_delops); 00250 rc = rpmdbClose(ts->sdb); 00251 ts->sdb = NULL; 00252 } 00253 return rc; 00254 } 00255 00256 int rpmtsOpenSDB(rpmts ts, int dbmode) 00257 { 00258 static int has_sdbpath = -1; 00259 int rc = 0; 00260 00261 if (ts->sdb != NULL && ts->sdbmode == dbmode) 00262 return 0; 00263 00264 if (has_sdbpath < 0) 00265 has_sdbpath = rpmExpandNumeric("%{?_solve_dbpath:1}"); 00266 00267 /* If not configured, don't try to open. */ 00268 if (has_sdbpath <= 0) 00269 return 1; 00270 00271 addMacro(NULL, "_dbpath", NULL, "%{_solve_dbpath}", RMIL_DEFAULT); 00272 00273 rc = rpmdbOpen(ts->rootDir, &ts->sdb, ts->sdbmode, 0644); 00274 if (rc) { 00275 const char * dn; 00276 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL); 00277 rpmlog(RPMLOG_WARNING, 00278 _("cannot open Solve database in %s\n"), dn); 00279 dn = _free(dn); 00280 /* XXX only try to open the solvedb once. */ 00281 has_sdbpath = 0; 00282 } 00283 delMacro(NULL, "_dbpath"); 00284 00285 return rc; 00286 } 00287 00294 static int sugcmp(const void * a, const void * b) 00295 /*@*/ 00296 { 00297 const char * astr = *(const char **)a; 00298 const char * bstr = *(const char **)b; 00299 return strcmp(astr, bstr); 00300 } 00301 00302 int rpmtsSolve(rpmts ts, rpmds ds, /*@unused@*/ const void * data) 00303 { 00304 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00305 const char * errstr; 00306 const char * str = NULL; 00307 const char * qfmt; 00308 rpmmi mi; 00309 Header bh = NULL; 00310 Header h = NULL; 00311 size_t bhnamelen = 0; 00312 time_t bhtime = 0; 00313 rpmTag rpmtag; 00314 const char * keyp; 00315 size_t keylen = 0; 00316 int rc = 1; /* assume not found */ 00317 int xx; 00318 00319 /* Make suggestions only for installing Requires: */ 00320 if (ts->goal != TSM_INSTALL) 00321 return rc; 00322 00323 switch (rpmdsTagN(ds)) { 00324 case RPMTAG_CONFLICTNAME: 00325 default: 00326 return rc; 00327 /*@notreached@*/ break; 00328 case RPMTAG_DIRNAMES: /* XXX perhaps too many wrong answers */ 00329 case RPMTAG_REQUIRENAME: 00330 case RPMTAG_FILELINKTOS: 00331 break; 00332 } 00333 00334 keyp = rpmdsN(ds); 00335 if (keyp == NULL) 00336 return rc; 00337 00338 if (ts->sdb == NULL) { 00339 xx = rpmtsOpenSDB(ts, ts->sdbmode); 00340 if (xx) return rc; 00341 } 00342 00343 /* Look for a matching Provides: in suggested universe. */ 00344 rpmtag = (*keyp == '/' ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME); 00345 mi = rpmmiInit(ts->sdb, rpmtag, keyp, keylen); 00346 while ((h = rpmmiNext(mi)) != NULL) { 00347 size_t hnamelen; 00348 time_t htime; 00349 00350 if (rpmtag == RPMTAG_PROVIDENAME && !rpmdsAnyMatchesDep(h, ds, 1)) 00351 continue; 00352 00353 he->tag = RPMTAG_NAME; 00354 xx = headerGet(h, he, 0); 00355 hnamelen = ((xx && he->p.str) ? strlen(he->p.str) : 0); 00356 he->p.ptr = _free(he->p.ptr); 00357 00358 /* XXX Prefer the shortest pkg N for basenames/provides resp. */ 00359 if (bhnamelen > 0 && hnamelen > bhnamelen) 00360 continue; 00361 00362 /* XXX Prefer the newest build if given alternatives. */ 00363 he->tag = RPMTAG_BUILDTIME; 00364 xx = headerGet(h, he, 0); 00365 htime = (xx && he->p.ui32p ? he->p.ui32p[0] : 0); 00366 he->p.ptr = _free(he->p.ptr); 00367 00368 if (htime <= bhtime) 00369 continue; 00370 00371 /* Save new "best" candidate. */ 00372 (void)headerFree(bh); 00373 bh = NULL; 00374 bh = headerLink(h); 00375 bhtime = htime; 00376 bhnamelen = hnamelen; 00377 } 00378 mi = rpmmiFree(mi); 00379 00380 /* Is there a suggested resolution? */ 00381 if (bh == NULL) 00382 goto exit; 00383 00384 /* Format the suggested resolution path. */ 00385 qfmt = rpmExpand("%{?_solve_name_fmt}", NULL); 00386 if (qfmt == NULL || *qfmt == '\0') 00387 goto exit; 00388 str = headerSprintf(bh, qfmt, NULL, rpmHeaderFormats, &errstr); 00389 (void)headerFree(bh); 00390 bh = NULL; 00391 qfmt = _free(qfmt); 00392 if (str == NULL) { 00393 rpmlog(RPMLOG_ERR, _("incorrect solve path format: %s\n"), errstr); 00394 goto exit; 00395 } 00396 00397 if (ts->depFlags & RPMDEPS_FLAG_ADDINDEPS) { 00398 FD_t fd; 00399 rpmRC rpmrc; 00400 00401 fd = Fopen(str, "r.fdio"); 00402 if (fd == NULL || Ferror(fd)) { 00403 rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), str, 00404 Fstrerror(fd)); 00405 if (fd != NULL) { 00406 xx = Fclose(fd); 00407 fd = NULL; 00408 } 00409 str = _free(str); 00410 goto exit; 00411 } 00412 rpmrc = rpmReadPackageFile(ts, fd, str, &h); 00413 xx = Fclose(fd); 00414 switch (rpmrc) { 00415 default: 00416 break; 00417 case RPMRC_NOTTRUSTED: 00418 case RPMRC_NOKEY: 00419 case RPMRC_OK: 00420 if (h != NULL && 00421 !rpmtsAddInstallElement(ts, h, (fnpyKey)str, 1, NULL)) 00422 { 00423 rpmlog(RPMLOG_DEBUG, D_("Adding: %s\n"), str); 00424 rc = -1; /* XXX restart unsatisfiedDepends() */ 00425 break; 00426 } 00427 break; 00428 } 00429 str = _free(str); 00430 (void)headerFree(h); 00431 h = NULL; 00432 goto exit; 00433 } 00434 00435 rpmlog(RPMLOG_DEBUG, D_("Suggesting: %s\n"), str); 00436 /* If suggestion is already present, don't bother. */ 00437 if (ts->suggests != NULL && ts->nsuggests > 0) { 00438 if (bsearch(&str, ts->suggests, ts->nsuggests, 00439 sizeof(*ts->suggests), sugcmp)) 00440 { 00441 str = _free(str); 00442 goto exit; 00443 } 00444 } 00445 00446 /* Add a new (unique) suggestion. */ 00447 ts->suggests = xrealloc(ts->suggests, 00448 sizeof(*ts->suggests) * (ts->nsuggests + 2)); 00449 ts->suggests[ts->nsuggests] = str; 00450 ts->nsuggests++; 00451 ts->suggests[ts->nsuggests] = NULL; 00452 00453 if (ts->nsuggests > 1) 00454 qsort(ts->suggests, ts->nsuggests, sizeof(*ts->suggests), sugcmp); 00455 00456 exit: 00457 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */ 00458 return rc; 00459 /*@=nullstate@*/ 00460 } 00461 00462 int rpmtsAvailable(rpmts ts, const rpmds ds) 00463 { 00464 fnpyKey * sugkey; 00465 int rc = 1; /* assume not found */ 00466 00467 if (ts->availablePackages == NULL) 00468 return rc; 00469 sugkey = rpmalAllSatisfiesDepend(ts->availablePackages, ds, NULL); 00470 if (sugkey == NULL) 00471 return rc; 00472 00473 /* XXX no alternatives yet */ 00474 if (sugkey[0] != NULL) { 00475 ts->suggests = xrealloc(ts->suggests, 00476 sizeof(*ts->suggests) * (ts->nsuggests + 2)); 00477 ts->suggests[ts->nsuggests] = sugkey[0]; 00478 sugkey[0] = NULL; 00479 ts->nsuggests++; 00480 ts->suggests[ts->nsuggests] = NULL; 00481 } 00482 sugkey = _free(sugkey); 00483 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */ 00484 return rc; 00485 /*@=nullstate@*/ 00486 } 00487 00488 int rpmtsSetSolveCallback(rpmts ts, 00489 int (*solve) (rpmts ts, rpmds key, const void * data), 00490 const void * solveData) 00491 { 00492 int rc = 0; 00493 00494 if (ts) { 00495 /*@-assignexpose -temptrans @*/ 00496 ts->solve = solve; 00497 ts->solveData = solveData; 00498 /*@=assignexpose =temptrans @*/ 00499 } 00500 return rc; 00501 } 00502 00503 rpmps rpmtsProblems(rpmts ts) 00504 { 00505 static const char msg[] = "rpmtsProblems"; 00506 rpmps ps = NULL; 00507 if (ts) { 00508 if (ts->probs == NULL) 00509 ts->probs = rpmpsCreate(); 00510 /*@-castexpose@*/ 00511 ps = rpmpsLink(ts->probs, msg); 00512 /*@=castexpose@*/ 00513 } 00514 return ps; 00515 } 00516 00517 void rpmtsClean(rpmts ts) 00518 { 00519 rpmtsi pi; rpmte p; 00520 00521 if (ts == NULL) 00522 return; 00523 00524 /* Clean up after dependency checks. */ 00525 pi = rpmtsiInit(ts); 00526 while ((p = rpmtsiNext(pi, 0)) != NULL) 00527 rpmteCleanDS(p); 00528 pi = rpmtsiFree(pi); 00529 00530 ts->addedPackages = rpmalFree(ts->addedPackages); 00531 ts->numAddedPackages = 0; 00532 00533 ts->erasedPackages = rpmalFree(ts->erasedPackages); 00534 ts->numErasedPackages = 0; 00535 00536 ts->suggests = _free(ts->suggests); 00537 ts->nsuggests = 0; 00538 00539 ts->probs = rpmpsFree(ts->probs); 00540 00541 rpmtsCleanDig(ts); 00542 } 00543 00544 void rpmtsEmpty(rpmts ts) 00545 { 00546 rpmtsi pi; rpmte p; 00547 int oc; 00548 00549 if (ts == NULL) 00550 return; 00551 00552 /*@-nullstate@*/ /* FIX: partial annotations */ 00553 rpmtsClean(ts); 00554 /*@=nullstate@*/ 00555 00556 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) { 00557 /*@-type -unqualifiedtrans @*/ 00558 ts->order[oc] = rpmteFree(ts->order[oc]); 00559 /*@=type =unqualifiedtrans @*/ 00560 } 00561 pi = rpmtsiFree(pi); 00562 00563 ts->orderCount = 0; 00564 ts->ntrees = 0; 00565 ts->maxDepth = 0; 00566 00567 ts->numRemovedPackages = 0; 00568 /*@-nullstate@*/ /* FIX: partial annotations */ 00569 return; 00570 /*@=nullstate@*/ 00571 } 00572 00573 static void rpmtsPrintStat(const char * name, /*@null@*/ struct rpmop_s * op) 00574 /*@globals fileSystem @*/ 00575 /*@modifies fileSystem @*/ 00576 { 00577 static unsigned int scale = (1000 * 1000); 00578 if (op != NULL && op->count > 0) 00579 fprintf(stderr, " %s %8d %6lu.%06lu MB %6lu.%06lu secs\n", 00580 name, op->count, 00581 (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale, 00582 op->usecs/scale, op->usecs%scale); 00583 } 00584 00585 /*@unchecked@*/ /*@relnull@*/ 00586 extern rpmop _hdr_loadops; 00587 /*@unchecked@*/ /*@relnull@*/ 00588 extern rpmop _hdr_getops; 00589 00590 static void rpmtsPrintStats(rpmts ts) 00591 /*@globals fileSystem, internalState @*/ 00592 /*@modifies fileSystem, internalState @*/ 00593 { 00594 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0); 00595 00596 if (_hdr_loadops) 00597 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_HDRLOAD), _hdr_loadops); 00598 if (_hdr_getops) 00599 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_HDRGET), _hdr_getops); 00600 00601 rpmtsPrintStat("total: ", rpmtsOp(ts, RPMTS_OP_TOTAL)); 00602 rpmtsPrintStat("check: ", rpmtsOp(ts, RPMTS_OP_CHECK)); 00603 rpmtsPrintStat("order: ", rpmtsOp(ts, RPMTS_OP_ORDER)); 00604 rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT)); 00605 rpmtsPrintStat("repackage: ", rpmtsOp(ts, RPMTS_OP_REPACKAGE)); 00606 rpmtsPrintStat("install: ", rpmtsOp(ts, RPMTS_OP_INSTALL)); 00607 rpmtsPrintStat("erase: ", rpmtsOp(ts, RPMTS_OP_ERASE)); 00608 rpmtsPrintStat("scriptlets: ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS)); 00609 rpmtsPrintStat("compress: ", rpmtsOp(ts, RPMTS_OP_COMPRESS)); 00610 rpmtsPrintStat("uncompress: ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS)); 00611 rpmtsPrintStat("digest: ", rpmtsOp(ts, RPMTS_OP_DIGEST)); 00612 rpmtsPrintStat("signature: ", rpmtsOp(ts, RPMTS_OP_SIGNATURE)); 00613 rpmtsPrintStat("dbadd: ", rpmtsOp(ts, RPMTS_OP_DBADD)); 00614 rpmtsPrintStat("dbremove: ", rpmtsOp(ts, RPMTS_OP_DBREMOVE)); 00615 rpmtsPrintStat("dbget: ", rpmtsOp(ts, RPMTS_OP_DBGET)); 00616 rpmtsPrintStat("dbput: ", rpmtsOp(ts, RPMTS_OP_DBPUT)); 00617 rpmtsPrintStat("dbdel: ", rpmtsOp(ts, RPMTS_OP_DBDEL)); 00618 rpmtsPrintStat("readhdr: ", rpmtsOp(ts, RPMTS_OP_READHDR)); 00619 rpmtsPrintStat("hdrload: ", rpmtsOp(ts, RPMTS_OP_HDRLOAD)); 00620 rpmtsPrintStat("hdrget: ", rpmtsOp(ts, RPMTS_OP_HDRGET)); 00621 /*@-globstate@*/ 00622 return; 00623 /*@=globstate@*/ 00624 } 00625 00626 static void rpmtsFini(void * _ts) 00627 /*@modifies _ts @*/ 00628 { 00629 rpmts ts = _ts; 00630 00631 /*@-nullstate@*/ /* FIX: partial annotations */ 00632 /* XXX there's a recursion here ... release and reacquire the lock */ 00633 #ifndef BUGGY 00634 yarnRelease(ts->_item.use); /* XXX hack-o-round */ 00635 #endif 00636 rpmtsEmpty(ts); 00637 #ifndef BUGGY 00638 yarnPossess(ts->_item.use); /* XXX hack-o-round */ 00639 #endif 00640 /*@=nullstate@*/ 00641 00642 ts->PRCO = rpmdsFreePRCO(ts->PRCO); 00643 00644 (void) rpmtsCloseDB(ts); 00645 00646 (void) rpmtsCloseSDB(ts); 00647 00648 ts->sx = rpmsxFree(ts->sx); 00649 00650 ts->removedPackages = _free(ts->removedPackages); 00651 00652 ts->availablePackages = rpmalFree(ts->availablePackages); 00653 ts->numAvailablePackages = 0; 00654 00655 ts->dsi = _free(ts->dsi); 00656 00657 if (ts->scriptFd != NULL) { 00658 /*@-refcounttrans@*/ /* FIX: XfdFree annotation */ 00659 ts->scriptFd = fdFree(ts->scriptFd, __FUNCTION__); 00660 /*@=refcounttrans@*/ 00661 ts->scriptFd = NULL; 00662 } 00663 ts->rootDir = _free(ts->rootDir); 00664 ts->currDir = _free(ts->currDir); 00665 00666 /*@-type +voidabstract @*/ /* FIX: double indirection */ 00667 ts->order = _free(ts->order); 00668 /*@=type =voidabstract @*/ 00669 ts->orderAlloced = 0; 00670 00671 ts->keyring = rpmKeyringFree(ts->keyring); 00672 ts->pkpkt = _free(ts->pkpkt); 00673 ts->pkpktlen = 0; 00674 memset(ts->pksignid, 0, sizeof(ts->pksignid)); 00675 00676 if (_rpmts_stats) 00677 rpmtsPrintStats(ts); 00678 00679 if (_rpmts_macros) { 00680 const char ** av = NULL; 00681 /*@-globs@*/ /* Avoid rpmGlobalMcroContext et al. */ 00682 (void)rpmGetMacroEntries(NULL, NULL, 1, &av); 00683 /*@=globs@*/ 00684 argvPrint("macros used", av, NULL); 00685 av = argvFree(av); 00686 } 00687 } 00688 00689 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00690 rpmioPool _rpmtsPool; 00691 00692 static rpmts rpmtsGetPool(/*@null@*/ rpmioPool pool) 00693 /*@globals _rpmtsPool, fileSystem, internalState @*/ 00694 /*@modifies pool, _rpmtsPool, fileSystem, internalState @*/ 00695 { 00696 rpmts ts; 00697 00698 if (_rpmtsPool == NULL) { 00699 _rpmtsPool = rpmioNewPool("ts", sizeof(*ts), -1, _rpmts_debug, 00700 NULL, NULL, rpmtsFini); 00701 pool = _rpmtsPool; 00702 } 00703 return (rpmts) rpmioGetPool(pool, sizeof(*ts)); 00704 } 00705 00706 void * rpmtsGetKeyring(rpmts ts, /*@unused@*/ int autoload) 00707 { 00708 rpmKeyring keyring = NULL; 00709 if (ts) { 00710 #ifdef NOTYET 00711 if (ts->keyring == NULL && autoload) 00712 loadKeyring(ts); 00713 keyring = rpmKeyringLink(ts->keyring); 00714 #else 00715 keyring = ts->keyring; 00716 #endif 00717 } 00718 /*@-refcounttrans@*/ 00719 return (void *)keyring; 00720 /*@=refcounttrans@*/ 00721 } 00722 00723 int rpmtsSetKeyring(rpmts ts, void * _keyring) 00724 { 00725 rpmKeyring keyring = _keyring; 00726 00727 if (ts == NULL) 00728 return -1; 00729 00730 #ifdef NOTYET 00731 /* 00732 * Should we permit switching keyring on the fly? For now, require 00733 * rpmdb isn't open yet (fairly arbitrary limitation)... 00734 */ 00735 if (rpmtsGetRdb(ts) != NULL) 00736 return -1; 00737 #endif 00738 00739 /*@-modnomods@*/ 00740 ts->keyring = rpmKeyringFree(ts->keyring); 00741 /*@=modnomods@*/ 00742 00743 #ifdef NOTYET 00744 ts->keyring = rpmKeyringLink(keyring); 00745 #else 00746 /*@-assignexpose -newreftrans @*/ 00747 /*@i@*/ ts->keyring = keyring; 00748 /*@=assignexpose =newreftrans @*/ 00749 #endif 00750 00751 return 0; 00752 } 00753 00754 rpmVSFlags rpmtsVSFlags(/*@unused@*/ rpmts ts) 00755 { 00756 return pgpDigVSFlags; 00757 } 00758 00759 rpmVSFlags rpmtsSetVSFlags(/*@unused@*/ rpmts ts, rpmVSFlags vsflags) 00760 /*@globals pgpDigVSFlags @*/ 00761 /*@modifies pgpDigVSFlags @*/ 00762 { 00763 rpmVSFlags ovsflags; 00764 ovsflags = pgpDigVSFlags; 00765 pgpDigVSFlags = vsflags; 00766 return ovsflags; 00767 } 00768 00769 /* 00770 * This allows us to mark transactions as being of a certain type. 00771 * The three types are: 00772 * 00773 * RPM_TRANS_NORMAL 00774 * RPM_TRANS_ROLLBACK 00775 * RPM_TRANS_AUTOROLLBACK 00776 * 00777 * ROLLBACK and AUTOROLLBACK transactions should always be ran as 00778 * a best effort. In particular this is important to the autorollback 00779 * feature to avoid rolling back a rollback (otherwise known as 00780 * dueling rollbacks (-;). AUTOROLLBACK's additionally need instance 00781 * counts passed to scriptlets to be altered. 00782 */ 00783 /* Let them know what type of transaction we are */ 00784 rpmTSType rpmtsType(rpmts ts) 00785 { 00786 return ((ts != NULL) ? ts->type : 0); 00787 } 00788 00789 void rpmtsSetType(rpmts ts, rpmTSType type) 00790 { 00791 if (ts != NULL) 00792 ts->type = type; 00793 } 00794 00795 rpmuint32_t rpmtsARBGoal(rpmts ts) 00796 { 00797 return ((ts != NULL) ? ts->arbgoal : 0); 00798 } 00799 00800 void rpmtsSetARBGoal(rpmts ts, rpmuint32_t goal) 00801 { 00802 if (ts != NULL) 00803 ts->arbgoal = goal; 00804 } 00805 00806 int rpmtsUnorderedSuccessors(rpmts ts, int first) 00807 { 00808 int unorderedSuccessors = 0; 00809 if (ts != NULL) { 00810 unorderedSuccessors = ts->unorderedSuccessors; 00811 if (first >= 0) 00812 ts->unorderedSuccessors = first; 00813 } 00814 return unorderedSuccessors; 00815 } 00816 00817 const char * rpmtsRootDir(rpmts ts) 00818 { 00819 const char * rootDir = NULL; 00820 00821 if (ts != NULL && ts->rootDir != NULL) { 00822 urltype ut = urlPath(ts->rootDir, &rootDir); 00823 switch (ut) { 00824 case URL_IS_UNKNOWN: 00825 case URL_IS_PATH: 00826 break; 00827 case URL_IS_HTTPS: 00828 case URL_IS_HTTP: 00829 case URL_IS_HKP: 00830 case URL_IS_FTP: 00831 case URL_IS_DASH: 00832 default: 00833 rootDir = "/"; 00834 break; 00835 } 00836 } 00837 return rootDir; 00838 } 00839 00840 void rpmtsSetRootDir(rpmts ts, const char * rootDir) 00841 { 00842 if (ts != NULL) { 00843 size_t rootLen; 00844 00845 ts->rootDir = _free(ts->rootDir); 00846 00847 if (rootDir == NULL) { 00848 #ifndef DYING 00849 ts->rootDir = xstrdup(""); 00850 #endif 00851 return; 00852 } 00853 rootLen = strlen(rootDir); 00854 00855 /* Make sure that rootDir has trailing / */ 00856 if (!(rootLen && rootDir[rootLen - 1] == '/')) { 00857 char * t = alloca(rootLen + 2); 00858 *t = '\0'; 00859 (void) stpcpy( stpcpy(t, rootDir), "/"); 00860 rootDir = t; 00861 } 00862 ts->rootDir = xstrdup(rootDir); 00863 } 00864 } 00865 00866 const char * rpmtsCurrDir(rpmts ts) 00867 { 00868 const char * currDir = NULL; 00869 if (ts != NULL) { 00870 currDir = ts->currDir; 00871 } 00872 return currDir; 00873 } 00874 00875 void rpmtsSetCurrDir(rpmts ts, const char * currDir) 00876 { 00877 if (ts != NULL) { 00878 ts->currDir = _free(ts->currDir); 00879 if (currDir) 00880 ts->currDir = xstrdup(currDir); 00881 } 00882 } 00883 00884 FD_t rpmtsScriptFd(rpmts ts) 00885 { 00886 FD_t scriptFd = NULL; 00887 if (ts != NULL) { 00888 scriptFd = ts->scriptFd; 00889 } 00890 /*@-compdef -refcounttrans -usereleased@*/ 00891 return scriptFd; 00892 /*@=compdef =refcounttrans =usereleased@*/ 00893 } 00894 00895 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd) 00896 { 00897 00898 if (ts != NULL) { 00899 if (ts->scriptFd != NULL) { 00900 /*@-assignexpose@*/ 00901 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd"); 00902 /*@=assignexpose@*/ 00903 ts->scriptFd = NULL; 00904 } 00905 /*@-assignexpose -castexpose @*/ 00906 if (scriptFd != NULL) 00907 ts->scriptFd = fdLink((void *)scriptFd, "rpmtsSetScriptFd"); 00908 /*@=assignexpose =castexpose @*/ 00909 } 00910 } 00911 00912 int rpmtsSELinuxEnabled(rpmts ts) 00913 { 00914 int selinuxEnabled = 0; 00915 if (ts) 00916 selinuxEnabled = (ts->selinuxEnabled > 0); 00917 return selinuxEnabled; 00918 } 00919 00920 int rpmtsChrootDone(rpmts ts) 00921 { 00922 return (ts != NULL ? ts->chrootDone : 0); 00923 } 00924 00925 int rpmtsSetChrootDone(rpmts ts, int chrootDone) 00926 { 00927 int ochrootDone = 0; 00928 if (ts != NULL) { 00929 ochrootDone = ts->chrootDone; 00930 if (ts->rdb != NULL) 00931 ts->rdb->db_chrootDone = chrootDone; 00932 ts->chrootDone = chrootDone; 00933 } 00934 return ochrootDone; 00935 } 00936 00937 rpmuint32_t rpmtsGetTid(rpmts ts) 00938 { 00939 rpmuint32_t tid = 0; /* XXX -1 is time(2) error return. */ 00940 if (ts != NULL) { 00941 tid = ts->tid[0]; 00942 } 00943 return tid; 00944 } 00945 00946 rpmuint32_t rpmtsSetTid(rpmts ts, rpmuint32_t tid) 00947 { 00948 rpmuint32_t otid = 0; /* XXX -1 is time(2) error return. */ 00949 if (ts != NULL) { 00950 otid = ts->tid[0]; 00951 ts->tid[0] = tid; 00952 ts->tid[1] = 0; 00953 } 00954 return otid; 00955 } 00956 00957 rpmPRCO rpmtsPRCO(rpmts ts) 00958 { 00959 rpmPRCO PRCO = NULL; 00960 00961 if (ts != NULL) { 00962 static int oneshot = 0; 00963 if (!oneshot) { 00964 const char * fn = rpmGetPath("%{?_rpmds_sysinfo_path}", NULL); 00965 int xx; 00966 00967 ts->PRCO = rpmdsNewPRCO(NULL); 00968 if (fn && *fn != '\0' && !rpmioAccess(fn, NULL, R_OK)) 00969 xx = rpmdsSysinfo(ts->PRCO, NULL); 00970 fn = _free(fn); 00971 oneshot++; 00972 } 00973 PRCO = ts->PRCO; 00974 } 00975 /*@-compdef -retexpose -usereleased @*/ 00976 return PRCO; 00977 /*@=compdef =retexpose =usereleased @*/ 00978 } 00979 00980 int rpmtsInitDSI(const rpmts ts) 00981 { 00982 rpmDiskSpaceInfo dsi; 00983 struct stat sb; 00984 int rc; 00985 size_t i; 00986 00987 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE) 00988 return 0; 00989 if (ts->filesystems != NULL) 00990 return 0; 00991 00992 rpmlog(RPMLOG_DEBUG, D_("mounted filesystems:\n")); 00993 rpmlog(RPMLOG_DEBUG, 00994 D_(" i dev bsize bavail iavail mount point\n")); 00995 00996 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount); 00997 if (rc || ts->filesystems == NULL || ts->filesystemCount == 0) 00998 return rc; 00999 01000 /* Get available space on mounted file systems. */ 01001 01002 ts->dsi = _free(ts->dsi); 01003 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi)); 01004 01005 dsi = ts->dsi; 01006 01007 if (dsi != NULL) 01008 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) { 01009 #if STATFS_IN_SYS_STATVFS 01010 struct statvfs sfb; 01011 memset(&sfb, 0, sizeof(sfb)); 01012 rc = statvfs(ts->filesystems[i], &sfb); 01013 #else 01014 struct statfs sfb; 01015 memset(&sfb, 0, sizeof(sfb)); 01016 # if STAT_STATFS4 01017 /* This platform has the 4-argument version of the statfs call. The last two 01018 * should be the size of struct statfs and 0, respectively. The 0 is the 01019 * filesystem type, and is always 0 when statfs is called on a mounted 01020 * filesystem, as we're doing. 01021 */ 01022 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0); 01023 # else 01024 rc = statfs(ts->filesystems[i], &sfb); 01025 # endif 01026 #endif 01027 if (rc) 01028 break; 01029 01030 rc = stat(ts->filesystems[i], &sb); 01031 if (rc) 01032 break; 01033 dsi->dev = sb.st_dev; 01034 /* XXX figger out how to get this info for non-statvfs systems. */ 01035 #if STATFS_IN_SYS_STATVFS 01036 dsi->f_frsize = sfb.f_frsize; 01037 #if defined(RPM_OS_AIX) 01038 dsi->f_fsid = 0; /* sfb.f_fsid is a structure on AIX */ 01039 #else 01040 dsi->f_fsid = sfb.f_fsid; 01041 #endif 01042 dsi->f_flag = sfb.f_flag; 01043 dsi->f_favail = (long long) sfb.f_favail; 01044 dsi->f_namemax = sfb.f_namemax; 01045 #elif defined(__APPLE__) && defined(__MACH__) && !defined(_SYS_STATVFS_H_) 01046 dsi->f_fsid = 0; /* "Not meaningful in this implementation." */ 01047 dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX); 01048 #elif defined(__OpenBSD__) 01049 dsi->f_fsid = 0; /* sfb.f_fsid is a structure on OpenBSD */ 01050 dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX); 01051 #else 01052 dsi->f_fsid = sfb.f_fsid; 01053 dsi->f_namemax = sfb.f_namelen; 01054 #endif 01055 01056 dsi->f_bsize = sfb.f_bsize; 01057 dsi->f_blocks = (unsigned long long)sfb.f_blocks; 01058 dsi->f_bfree = (unsigned long long)sfb.f_bfree; 01059 dsi->f_files = (unsigned long long)sfb.f_files; 01060 dsi->f_ffree = (unsigned long long)sfb.f_ffree; 01061 01062 dsi->bneeded = 0; 01063 dsi->ineeded = 0; 01064 #ifdef STATFS_HAS_F_BAVAIL 01065 dsi->f_bavail = (long long)(sfb.f_bavail ? sfb.f_bavail : 1); 01066 if (sfb.f_ffree > 0 && sfb.f_files > 0 && sfb.f_favail > 0) 01067 dsi->f_favail = (long long)sfb.f_favail; 01068 else /* XXX who knows what evil lurks here? */ 01069 dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0) 01070 ? (signed long long) sfb.f_ffree : -1; 01071 #else 01072 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are 01073 * available for non-superusers. f_blocks - f_bfree is probably too big, but 01074 * it's about all we can do. 01075 */ 01076 dsi->f_bavail = sfb.f_blocks - sfb.f_bfree; 01077 /* XXX Avoid FAT and other file systems that have not inodes. */ 01078 dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0) 01079 ? sfb.f_ffree : -1; 01080 #endif 01081 01082 #if !defined(ST_RDONLY) 01083 #define ST_RDONLY 1 01084 #endif 01085 rpmlog(RPMLOG_DEBUG, "%5u 0x%08x %8u %12ld %12ld %s %s\n", 01086 (unsigned)i, (unsigned) dsi->dev, (unsigned) dsi->f_bsize, 01087 (signed long) dsi->f_bavail, (signed long) dsi->f_favail, 01088 ((dsi->f_flag & ST_RDONLY) ? "ro" : "rw"), 01089 ts->filesystems[i]); 01090 } 01091 return rc; 01092 } 01093 01094 void rpmtsUpdateDSI(const rpmts ts, dev_t dev, 01095 rpmuint32_t fileSize, rpmuint32_t prevSize, rpmuint32_t fixupSize, 01096 int _action) 01097 { 01098 iosmFileAction action = _action; 01099 rpmDiskSpaceInfo dsi; 01100 rpmuint64_t bneeded; 01101 01102 dsi = ts->dsi; 01103 if (dsi) { 01104 while (dsi->f_bsize && dsi->dev != dev) 01105 dsi++; 01106 if (dsi->f_bsize == 0) 01107 dsi = NULL; 01108 } 01109 if (dsi == NULL) 01110 return; 01111 01112 bneeded = BLOCK_ROUND(fileSize, dsi->f_bsize); 01113 01114 switch (action) { 01115 case FA_BACKUP: 01116 case FA_SAVE: 01117 case FA_ALTNAME: 01118 dsi->ineeded++; 01119 dsi->bneeded += bneeded; 01120 /*@switchbreak@*/ break; 01121 01122 /* 01123 * FIXME: If two packages share a file (same md5sum), and 01124 * that file is being replaced on disk, will dsi->bneeded get 01125 * adjusted twice? Quite probably! 01126 */ 01127 case FA_CREATE: 01128 dsi->bneeded += bneeded; 01129 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->f_bsize); 01130 /*@switchbreak@*/ break; 01131 01132 case FA_ERASE: 01133 dsi->ineeded--; 01134 dsi->bneeded -= bneeded; 01135 /*@switchbreak@*/ break; 01136 01137 default: 01138 /*@switchbreak@*/ break; 01139 } 01140 01141 if (fixupSize) 01142 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->f_bsize); 01143 } 01144 01145 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te) 01146 { 01147 rpmDiskSpaceInfo dsi; 01148 rpmps ps; 01149 int fc; 01150 size_t i; 01151 01152 if (ts->filesystems == NULL || ts->filesystemCount == 0) 01153 return; 01154 01155 dsi = ts->dsi; 01156 if (dsi == NULL) 01157 return; 01158 fc = rpmfiFC( rpmteFI(te, RPMTAG_BASENAMES) ); 01159 if (fc <= 0) 01160 return; 01161 01162 ps = rpmtsProblems(ts); 01163 for (i = 0; i < ts->filesystemCount; i++, dsi++) { 01164 01165 if (dsi->f_bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->f_bavail) { 01166 rpmpsAppend(ps, RPMPROB_DISKSPACE, 01167 rpmteNEVR(te), rpmteKey(te), 01168 ts->filesystems[i], NULL, NULL, 01169 (adj_fs_blocks(dsi->bneeded) - dsi->f_bavail) * dsi->f_bsize); 01170 } 01171 01172 if (dsi->f_favail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->f_favail) { 01173 rpmpsAppend(ps, RPMPROB_DISKNODES, 01174 rpmteNEVR(te), rpmteKey(te), 01175 ts->filesystems[i], NULL, NULL, 01176 (adj_fs_blocks(dsi->ineeded) - dsi->f_favail)); 01177 } 01178 01179 if ((dsi->bneeded || dsi->ineeded) && (dsi->f_flag & ST_RDONLY)) { 01180 rpmpsAppend(ps, RPMPROB_RDONLY, 01181 rpmteNEVR(te), rpmteKey(te), 01182 ts->filesystems[i], NULL, NULL, 0); 01183 } 01184 } 01185 ps = rpmpsFree(ps); 01186 } 01187 01188 void * rpmtsNotify(rpmts ts, rpmte te, 01189 rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total) 01190 { 01191 void * ptr = NULL; 01192 if (ts && ts->notify) { 01193 Header h; 01194 fnpyKey cbkey; 01195 /*@-type@*/ /* FIX: cast? */ 01196 /*@-noeffectuncon @*/ /* FIX: check rc */ 01197 if (te) { 01198 /*@-castexpose -mods@*/ /* XXX noisy in transaction.c */ 01199 h = headerLink(te->h); 01200 /*@=castexpose =mods@*/ 01201 cbkey = rpmteKey(te); 01202 } else { 01203 h = NULL; 01204 cbkey = NULL; 01205 } 01206 ptr = ts->notify(h, what, amount, total, cbkey, ts->notifyData); 01207 (void)headerFree(h); 01208 h = NULL; 01209 /*@=noeffectuncon @*/ 01210 /*@=type@*/ 01211 } 01212 return ptr; 01213 } 01214 01215 int rpmtsNElements(rpmts ts) 01216 { 01217 int nelements = 0; 01218 if (ts != NULL && ts->order != NULL) { 01219 nelements = ts->orderCount; 01220 } 01221 return nelements; 01222 } 01223 01224 rpmte rpmtsElement(rpmts ts, int ix) 01225 { 01226 rpmte te = NULL; 01227 if (ts != NULL && ts->order != NULL) { 01228 if (ix >= 0 && ix < ts->orderCount) 01229 te = ts->order[ix]; 01230 } 01231 /*@-compdef@*/ 01232 return te; 01233 /*@=compdef@*/ 01234 } 01235 01236 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts) 01237 { 01238 return (ts != NULL ? ts->ignoreSet : 0); 01239 } 01240 01241 rpmtransFlags rpmtsFlags(rpmts ts) 01242 { 01243 rpmtransFlags transFlags = 0; 01244 if (ts != NULL) { 01245 transFlags = ts->transFlags; 01246 if (rpmtsSELinuxEnabled(ts) > 0) 01247 transFlags &= ~RPMTRANS_FLAG_NOCONTEXTS; 01248 else 01249 transFlags |= RPMTRANS_FLAG_NOCONTEXTS; 01250 } 01251 return transFlags; 01252 } 01253 01254 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags) 01255 { 01256 rpmtransFlags otransFlags = 0; 01257 if (ts != NULL) { 01258 otransFlags = ts->transFlags; 01259 if (rpmtsSELinuxEnabled(ts) > 0) 01260 transFlags &= ~RPMTRANS_FLAG_NOCONTEXTS; 01261 else 01262 transFlags |= RPMTRANS_FLAG_NOCONTEXTS; 01263 ts->transFlags = transFlags; 01264 } 01265 return otransFlags; 01266 } 01267 01268 rpmdepFlags rpmtsDFlags(rpmts ts) 01269 { 01270 return (ts != NULL ? ts->depFlags : 0); 01271 } 01272 01273 rpmdepFlags rpmtsSetDFlags(rpmts ts, rpmdepFlags depFlags) 01274 { 01275 rpmdepFlags odepFlags = 0; 01276 if (ts != NULL) { 01277 odepFlags = ts->depFlags; 01278 ts->depFlags = depFlags; 01279 } 01280 return odepFlags; 01281 } 01282 01283 Spec rpmtsSpec(rpmts ts) 01284 { 01285 /*@-compdef -retexpose -usereleased@*/ 01286 return ts->spec; 01287 /*@=compdef =retexpose =usereleased@*/ 01288 } 01289 01290 Spec rpmtsSetSpec(rpmts ts, Spec spec) 01291 { 01292 Spec ospec = ts->spec; 01293 /*@-assignexpose -temptrans@*/ 01294 ts->spec = spec; 01295 /*@=assignexpose =temptrans@*/ 01296 return ospec; 01297 } 01298 01299 rpmte rpmtsRelocateElement(rpmts ts) 01300 { 01301 /*@-compdef -retexpose -usereleased@*/ 01302 return ts->relocateElement; 01303 /*@=compdef =retexpose =usereleased@*/ 01304 } 01305 01306 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement) 01307 { 01308 rpmte orelocateElement = ts->relocateElement; 01309 /*@-assignexpose -temptrans@*/ 01310 ts->relocateElement = relocateElement; 01311 /*@=assignexpose =temptrans@*/ 01312 return orelocateElement; 01313 } 01314 01315 tsmStage rpmtsGoal(rpmts ts) 01316 { 01317 return (ts != NULL ? ts->goal : TSM_UNKNOWN); 01318 } 01319 01320 tsmStage rpmtsSetGoal(rpmts ts, tsmStage goal) 01321 { 01322 tsmStage ogoal = TSM_UNKNOWN; 01323 if (ts != NULL) { 01324 ogoal = ts->goal; 01325 ts->goal = goal; 01326 } 01327 return ogoal; 01328 } 01329 01330 int rpmtsDBMode(rpmts ts) 01331 { 01332 return (ts != NULL ? ts->dbmode : 0); 01333 } 01334 01335 int rpmtsSetDBMode(rpmts ts, int dbmode) 01336 { 01337 int odbmode = 0; 01338 if (ts != NULL) { 01339 odbmode = ts->dbmode; 01340 ts->dbmode = dbmode; 01341 } 01342 return odbmode; 01343 } 01344 01345 rpmuint32_t rpmtsColor(rpmts ts) 01346 { 01347 return (ts != NULL ? ts->color : 0); 01348 } 01349 01350 rpmuint32_t rpmtsSetColor(rpmts ts, rpmuint32_t color) 01351 { 01352 rpmuint32_t ocolor = 0; 01353 if (ts != NULL) { 01354 ocolor = ts->color; 01355 ts->color = color; 01356 } 01357 return ocolor; 01358 } 01359 01360 rpmuint32_t rpmtsPrefColor(rpmts ts) 01361 { 01362 return (ts != NULL ? ts->prefcolor : 0); 01363 } 01364 01365 int rpmtsSetNotifyCallback(rpmts ts, 01366 rpmCallbackFunction notify, rpmCallbackData notifyData) 01367 { 01368 if (ts != NULL) { 01369 ts->notify = notify; 01370 ts->notifyData = notifyData; 01371 } 01372 return 0; 01373 } 01374 01375 rpmts rpmtsCreate(void) 01376 { 01377 rpmts ts = rpmtsGetPool(_rpmtsPool); 01378 int xx; 01379 01380 memset(&ts->ops, 0, sizeof(ts->ops)); 01381 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1); 01382 ts->type = RPMTRANS_TYPE_NORMAL; 01383 ts->goal = TSM_UNKNOWN; 01384 ts->filesystemCount = 0; 01385 ts->filesystems = NULL; 01386 ts->dsi = NULL; 01387 01388 ts->solve = rpmtsSolve; 01389 ts->solveData = NULL; 01390 ts->nsuggests = 0; 01391 ts->suggests = NULL; 01392 01393 ts->PRCO = NULL; 01394 01395 ts->sdb = NULL; 01396 ts->sdbmode = O_RDONLY; 01397 01398 ts->rdb = NULL; 01399 ts->dbmode = O_RDONLY; 01400 01401 ts->scriptFd = NULL; 01402 { struct timeval tv; 01403 xx = gettimeofday(&tv, NULL); 01404 ts->tid[0] = (rpmuint32_t) tv.tv_sec; 01405 ts->tid[1] = (rpmuint32_t) tv.tv_usec; 01406 } 01407 ts->delta = 5; 01408 01409 ts->color = rpmExpandNumeric("%{?_transaction_color}"); 01410 ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}"); 01411 if (!ts->prefcolor) ts->prefcolor = 0x2; 01412 01413 ts->numRemovedPackages = 0; 01414 ts->allocedRemovedPackages = ts->delta; 01415 ts->removedPackages = xcalloc(ts->allocedRemovedPackages, 01416 sizeof(*ts->removedPackages)); 01417 01418 ts->rootDir = NULL; 01419 ts->currDir = NULL; 01420 ts->chrootDone = 0; 01421 01422 ts->selinuxEnabled = is_selinux_enabled(); 01423 01424 ts->numAddedPackages = 0; 01425 ts->addedPackages = NULL; 01426 01427 ts->numErasedPackages = 0; 01428 ts->erasedPackages = NULL; 01429 01430 ts->numAvailablePackages = 0; 01431 ts->availablePackages = NULL; 01432 01433 ts->orderAlloced = 0; 01434 ts->orderCount = 0; 01435 ts->order = NULL; 01436 ts->ntrees = 0; 01437 ts->maxDepth = 0; 01438 01439 ts->probs = NULL; 01440 01441 ts->keyring = NULL; 01442 ts->pkpkt = NULL; 01443 ts->pkpktlen = 0; 01444 memset(ts->pksignid, 0, sizeof(ts->pksignid)); 01445 ts->dig = NULL; 01446 01447 /* Set autorollback goal to the end of time. */ 01448 ts->arbgoal = 0xffffffff; 01449 01450 return rpmtsLink(ts, "tsCreate"); 01451 }