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