|
rpm
5.4.4
|
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_DEPCACHE: 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_DASH: 00905 case URL_IS_HKP: 00906 case URL_IS_FTP: 00907 case URL_IS_HTTP: 00908 case URL_IS_HTTPS: 00909 case URL_IS_MONGO: /* XXX FIXME */ 00910 default: 00911 rootDir = "/"; 00912 break; 00913 } 00914 } 00915 return rootDir; 00916 } 00917 00918 void rpmtsSetRootDir(rpmts ts, const char * rootDir) 00919 { 00920 if (ts != NULL) { 00921 size_t rootLen; 00922 00923 ts->rootDir = _free(ts->rootDir); 00924 00925 if (rootDir == NULL) { 00926 #ifdef DYING 00927 ts->rootDir = xstrdup(""); 00928 #endif 00929 return; 00930 } 00931 rootLen = strlen(rootDir); 00932 00933 /* Make sure that rootDir has trailing / */ 00934 if (!(rootLen && rootDir[rootLen - 1] == '/')) { 00935 char * t = alloca(rootLen + 2); 00936 *t = '\0'; 00937 (void) stpcpy( stpcpy(t, rootDir), "/"); 00938 rootDir = t; 00939 } 00940 ts->rootDir = xstrdup(rootDir); 00941 } 00942 } 00943 00944 const char * rpmtsCurrDir(rpmts ts) 00945 { 00946 const char * currDir = NULL; 00947 if (ts != NULL) { 00948 currDir = ts->currDir; 00949 } 00950 return currDir; 00951 } 00952 00953 void rpmtsSetCurrDir(rpmts ts, const char * currDir) 00954 { 00955 if (ts != NULL) { 00956 ts->currDir = _free(ts->currDir); 00957 if (currDir) 00958 ts->currDir = xstrdup(currDir); 00959 } 00960 } 00961 00962 FD_t rpmtsScriptFd(rpmts ts) 00963 { 00964 FD_t scriptFd = NULL; 00965 if (ts != NULL) { 00966 scriptFd = ts->scriptFd; 00967 } 00968 /*@-compdef -refcounttrans -usereleased@*/ 00969 return scriptFd; 00970 /*@=compdef =refcounttrans =usereleased@*/ 00971 } 00972 00973 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd) 00974 { 00975 00976 if (ts != NULL) { 00977 if (ts->scriptFd != NULL) { 00978 /*@-assignexpose@*/ 00979 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd"); 00980 /*@=assignexpose@*/ 00981 ts->scriptFd = NULL; 00982 } 00983 /*@-assignexpose -castexpose @*/ 00984 if (scriptFd != NULL) 00985 ts->scriptFd = fdLink((void *)scriptFd, "rpmtsSetScriptFd"); 00986 /*@=assignexpose =castexpose @*/ 00987 } 00988 } 00989 00990 int rpmtsSELinuxEnabled(rpmts ts) 00991 { 00992 int selinuxEnabled = 0; 00993 if (ts) 00994 selinuxEnabled = (ts->selinuxEnabled > 0); 00995 return selinuxEnabled; 00996 } 00997 00998 int rpmtsChrootDone(rpmts ts) 00999 { 01000 return (ts != NULL ? ts->chrootDone : 0); 01001 } 01002 01003 int rpmtsSetChrootDone(rpmts ts, int chrootDone) 01004 { 01005 int ochrootDone = 0; 01006 if (ts != NULL) { 01007 ochrootDone = ts->chrootDone; 01008 if (ts->rdb != NULL) 01009 ts->rdb->db_chrootDone = chrootDone; 01010 ts->chrootDone = chrootDone; 01011 } 01012 return ochrootDone; 01013 } 01014 01015 rpmuint32_t rpmtsGetTid(rpmts ts) 01016 { 01017 rpmuint32_t tid = 0; /* XXX -1 is time(2) error return. */ 01018 if (ts != NULL) { 01019 tid = ts->tid[0]; 01020 } 01021 return tid; 01022 } 01023 01024 rpmuint32_t rpmtsSetTid(rpmts ts, rpmuint32_t tid) 01025 { 01026 rpmuint32_t otid = 0; /* XXX -1 is time(2) error return. */ 01027 if (ts != NULL) { 01028 otid = ts->tid[0]; 01029 ts->tid[0] = tid; 01030 ts->tid[1] = 0; 01031 } 01032 return otid; 01033 } 01034 01035 rpmPRCO rpmtsPRCO(rpmts ts) 01036 { 01037 rpmPRCO PRCO = NULL; 01038 01039 if (ts != NULL) { 01040 static int oneshot = 0; 01041 if (!oneshot) { 01042 const char * fn = rpmGetPath("%{?_rpmds_sysinfo_path}", NULL); 01043 int xx; 01044 01045 ts->PRCO = rpmdsNewPRCO(NULL); 01046 if (fn && *fn != '\0' && !rpmioAccess(fn, NULL, R_OK)) 01047 xx = rpmdsSysinfo(ts->PRCO, NULL); 01048 fn = _free(fn); 01049 oneshot++; 01050 } 01051 PRCO = ts->PRCO; 01052 } 01053 /*@-compdef -retexpose -usereleased @*/ 01054 return PRCO; 01055 /*@=compdef =retexpose =usereleased @*/ 01056 } 01057 01058 int rpmtsInitDSI(const rpmts ts) 01059 { 01060 rpmDiskSpaceInfo dsi; 01061 struct stat sb; 01062 int rc; 01063 size_t i; 01064 01065 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE) 01066 return 0; 01067 if (ts->filesystems != NULL) 01068 return 0; 01069 01070 rpmlog(RPMLOG_DEBUG, D_("mounted filesystems:\n")); 01071 rpmlog(RPMLOG_DEBUG, 01072 D_(" i dev bsize bavail iavail mount point\n")); 01073 01074 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount); 01075 if (rc || ts->filesystems == NULL || ts->filesystemCount == 0) 01076 return rc; 01077 01078 /* Get available space on mounted file systems. */ 01079 01080 ts->dsi = _free(ts->dsi); 01081 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi)); 01082 01083 dsi = ts->dsi; 01084 01085 if (dsi != NULL) 01086 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) { 01087 #if STATFS_IN_SYS_STATVFS 01088 struct statvfs sfb; 01089 memset(&sfb, 0, sizeof(sfb)); 01090 rc = statvfs(ts->filesystems[i], &sfb); 01091 #else 01092 struct statfs sfb; 01093 memset(&sfb, 0, sizeof(sfb)); 01094 # if STAT_STATFS4 01095 /* This platform has the 4-argument version of the statfs call. The last two 01096 * should be the size of struct statfs and 0, respectively. The 0 is the 01097 * filesystem type, and is always 0 when statfs is called on a mounted 01098 * filesystem, as we're doing. 01099 */ 01100 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0); 01101 # else 01102 rc = statfs(ts->filesystems[i], &sfb); 01103 # endif 01104 #endif 01105 if (rc) 01106 break; 01107 01108 rc = stat(ts->filesystems[i], &sb); 01109 if (rc) 01110 break; 01111 dsi->dev = sb.st_dev; 01112 /* XXX figger out how to get this info for non-statvfs systems. */ 01113 #if STATFS_IN_SYS_STATVFS 01114 dsi->f_frsize = sfb.f_frsize; 01115 #if defined(RPM_OS_AIX) 01116 dsi->f_fsid = 0; /* sfb.f_fsid is a structure on AIX */ 01117 #else 01118 dsi->f_fsid = sfb.f_fsid; 01119 #endif 01120 dsi->f_flag = sfb.f_flag; 01121 dsi->f_favail = (long long) sfb.f_favail; 01122 dsi->f_namemax = sfb.f_namemax; 01123 #elif defined(__APPLE__) && defined(__MACH__) && !defined(_SYS_STATVFS_H_) 01124 dsi->f_fsid = 0; /* "Not meaningful in this implementation." */ 01125 dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX); 01126 #elif defined(__OpenBSD__) 01127 dsi->f_fsid = 0; /* sfb.f_fsid is a structure on OpenBSD */ 01128 dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX); 01129 #else 01130 dsi->f_fsid = sfb.f_fsid; 01131 dsi->f_namemax = sfb.f_namelen; 01132 #endif 01133 01134 dsi->f_bsize = sfb.f_bsize; 01135 dsi->f_blocks = (unsigned long long)sfb.f_blocks; 01136 dsi->f_bfree = (unsigned long long)sfb.f_bfree; 01137 dsi->f_files = (unsigned long long)sfb.f_files; 01138 dsi->f_ffree = (unsigned long long)sfb.f_ffree; 01139 01140 dsi->bneeded = 0; 01141 dsi->ineeded = 0; 01142 #ifdef STATFS_HAS_F_BAVAIL 01143 dsi->f_bavail = (long long)(sfb.f_bavail ? sfb.f_bavail : 1); 01144 if (sfb.f_ffree > 0 && sfb.f_files > 0 && sfb.f_favail > 0) 01145 dsi->f_favail = (long long)sfb.f_favail; 01146 else /* XXX who knows what evil lurks here? */ 01147 dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0) 01148 ? (signed long long) sfb.f_ffree : -1; 01149 #else 01150 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are 01151 * available for non-superusers. f_blocks - f_bfree is probably too big, but 01152 * it's about all we can do. 01153 */ 01154 dsi->f_bavail = sfb.f_blocks - sfb.f_bfree; 01155 /* XXX Avoid FAT and other file systems that have not inodes. */ 01156 dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0) 01157 ? sfb.f_ffree : -1; 01158 #endif 01159 01160 #if !defined(ST_RDONLY) 01161 #define ST_RDONLY 1 01162 #endif 01163 rpmlog(RPMLOG_DEBUG, "%5u 0x%08x %8u %12ld %12ld %s %s\n", 01164 (unsigned)i, (unsigned) dsi->dev, (unsigned) dsi->f_bsize, 01165 (signed long) dsi->f_bavail, (signed long) dsi->f_favail, 01166 ((dsi->f_flag & ST_RDONLY) ? "ro" : "rw"), 01167 ts->filesystems[i]); 01168 } 01169 return rc; 01170 } 01171 01172 void rpmtsUpdateDSI(const rpmts ts, dev_t dev, 01173 rpmuint32_t fileSize, rpmuint32_t prevSize, rpmuint32_t fixupSize, 01174 int _action) 01175 { 01176 iosmFileAction action = _action; 01177 rpmDiskSpaceInfo dsi; 01178 rpmuint64_t bneeded; 01179 01180 dsi = ts->dsi; 01181 if (dsi) { 01182 while (dsi->f_bsize && dsi->dev != dev) 01183 dsi++; 01184 if (dsi->f_bsize == 0) 01185 dsi = NULL; 01186 } 01187 if (dsi == NULL) 01188 return; 01189 01190 bneeded = BLOCK_ROUND(fileSize, dsi->f_bsize); 01191 01192 switch (action) { 01193 case FA_BACKUP: 01194 case FA_SAVE: 01195 case FA_ALTNAME: 01196 dsi->ineeded++; 01197 dsi->bneeded += bneeded; 01198 /*@switchbreak@*/ break; 01199 01200 /* 01201 * FIXME: If two packages share a file (same md5sum), and 01202 * that file is being replaced on disk, will dsi->bneeded get 01203 * adjusted twice? Quite probably! 01204 */ 01205 case FA_CREATE: 01206 dsi->bneeded += bneeded; 01207 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->f_bsize); 01208 /*@switchbreak@*/ break; 01209 01210 case FA_ERASE: 01211 dsi->ineeded--; 01212 dsi->bneeded -= bneeded; 01213 /*@switchbreak@*/ break; 01214 01215 default: 01216 /*@switchbreak@*/ break; 01217 } 01218 01219 if (fixupSize) 01220 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->f_bsize); 01221 } 01222 01223 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te) 01224 { 01225 rpmDiskSpaceInfo dsi; 01226 rpmps ps; 01227 int fc; 01228 size_t i; 01229 01230 if (ts->filesystems == NULL || ts->filesystemCount == 0) 01231 return; 01232 01233 dsi = ts->dsi; 01234 if (dsi == NULL) 01235 return; 01236 fc = rpmfiFC( rpmteFI(te, RPMTAG_BASENAMES) ); 01237 if (fc <= 0) 01238 return; 01239 01240 ps = rpmtsProblems(ts); 01241 for (i = 0; i < ts->filesystemCount; i++, dsi++) { 01242 01243 if (dsi->f_bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->f_bavail) { 01244 if (dsi->bneeded != dsi->obneeded) { 01245 rpmpsAppend(ps, RPMPROB_DISKSPACE, 01246 rpmteNEVR(te), rpmteKey(te), 01247 ts->filesystems[i], NULL, NULL, 01248 (adj_fs_blocks(dsi->bneeded) - dsi->f_bavail) * dsi->f_bsize); 01249 dsi->obneeded = dsi->bneeded; 01250 } 01251 } 01252 01253 if (dsi->f_favail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->f_favail) { 01254 if (dsi->ineeded != dsi->oineeded) { 01255 rpmpsAppend(ps, RPMPROB_DISKNODES, 01256 rpmteNEVR(te), rpmteKey(te), 01257 ts->filesystems[i], NULL, NULL, 01258 (adj_fs_blocks(dsi->ineeded) - dsi->f_favail)); 01259 dsi->oineeded = dsi->ineeded; 01260 } 01261 } 01262 01263 if ((dsi->bneeded || dsi->ineeded) && (dsi->f_flag & ST_RDONLY)) { 01264 rpmpsAppend(ps, RPMPROB_RDONLY, 01265 rpmteNEVR(te), rpmteKey(te), 01266 ts->filesystems[i], NULL, NULL, 0); 01267 } 01268 } 01269 ps = rpmpsFree(ps); 01270 } 01271 01272 void * rpmtsNotify(rpmts ts, rpmte te, 01273 rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total) 01274 { 01275 void * ptr = NULL; 01276 if (ts && ts->notify) { 01277 Header h; 01278 fnpyKey cbkey; 01279 /*@-type@*/ /* FIX: cast? */ 01280 /*@-noeffectuncon @*/ /* FIX: check rc */ 01281 if (te) { 01282 /*@-castexpose -mods@*/ /* XXX noisy in transaction.c */ 01283 h = headerLink(te->h); 01284 /*@=castexpose =mods@*/ 01285 cbkey = rpmteKey(te); 01286 } else { 01287 h = NULL; 01288 cbkey = NULL; 01289 } 01290 ptr = ts->notify(h, what, amount, total, cbkey, ts->notifyData); 01291 (void)headerFree(h); 01292 h = NULL; 01293 /*@=noeffectuncon @*/ 01294 /*@=type@*/ 01295 } 01296 return ptr; 01297 } 01298 01299 int rpmtsNElements(rpmts ts) 01300 { 01301 int nelements = 0; 01302 if (ts != NULL && ts->order != NULL) { 01303 nelements = ts->orderCount; 01304 } 01305 return nelements; 01306 } 01307 01308 rpmte rpmtsElement(rpmts ts, int ix) 01309 { 01310 rpmte te = NULL; 01311 if (ts != NULL && ts->order != NULL) { 01312 if (ix >= 0 && ix < ts->orderCount) 01313 te = ts->order[ix]; 01314 } 01315 /*@-compdef@*/ 01316 return te; 01317 /*@=compdef@*/ 01318 } 01319 01320 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts) 01321 { 01322 return (ts != NULL ? ts->ignoreSet : 0); 01323 } 01324 01325 rpmtransFlags rpmtsFlags(rpmts ts) 01326 { 01327 rpmtransFlags transFlags = 0; 01328 if (ts != NULL) { 01329 transFlags = ts->transFlags; 01330 if (rpmtsSELinuxEnabled(ts) > 0) 01331 transFlags &= ~RPMTRANS_FLAG_NOCONTEXTS; 01332 else 01333 transFlags |= RPMTRANS_FLAG_NOCONTEXTS; 01334 } 01335 return transFlags; 01336 } 01337 01338 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags) 01339 { 01340 rpmtransFlags otransFlags = 0; 01341 if (ts != NULL) { 01342 otransFlags = ts->transFlags; 01343 if (rpmtsSELinuxEnabled(ts) > 0) 01344 transFlags &= ~RPMTRANS_FLAG_NOCONTEXTS; 01345 else 01346 transFlags |= RPMTRANS_FLAG_NOCONTEXTS; 01347 ts->transFlags = transFlags; 01348 } 01349 return otransFlags; 01350 } 01351 01352 rpmdepFlags rpmtsDFlags(rpmts ts) 01353 { 01354 return (ts != NULL ? ts->depFlags : 0); 01355 } 01356 01357 rpmdepFlags rpmtsSetDFlags(rpmts ts, rpmdepFlags depFlags) 01358 { 01359 rpmdepFlags odepFlags = 0; 01360 if (ts != NULL) { 01361 odepFlags = ts->depFlags; 01362 ts->depFlags = depFlags; 01363 } 01364 return odepFlags; 01365 } 01366 01367 Spec rpmtsSpec(rpmts ts) 01368 { 01369 /*@-compdef -retexpose -usereleased@*/ 01370 return ts->spec; 01371 /*@=compdef =retexpose =usereleased@*/ 01372 } 01373 01374 Spec rpmtsSetSpec(rpmts ts, Spec spec) 01375 { 01376 Spec ospec = ts->spec; 01377 /*@-assignexpose -temptrans@*/ 01378 ts->spec = spec; 01379 /*@=assignexpose =temptrans@*/ 01380 return ospec; 01381 } 01382 01383 rpmte rpmtsRelocateElement(rpmts ts) 01384 { 01385 /*@-compdef -retexpose -usereleased@*/ 01386 return ts->relocateElement; 01387 /*@=compdef =retexpose =usereleased@*/ 01388 } 01389 01390 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement) 01391 { 01392 rpmte orelocateElement = ts->relocateElement; 01393 /*@-assignexpose -temptrans@*/ 01394 ts->relocateElement = relocateElement; 01395 /*@=assignexpose =temptrans@*/ 01396 return orelocateElement; 01397 } 01398 01399 tsmStage rpmtsGoal(rpmts ts) 01400 { 01401 return (ts != NULL ? ts->goal : TSM_UNKNOWN); 01402 } 01403 01404 tsmStage rpmtsSetGoal(rpmts ts, tsmStage goal) 01405 { 01406 tsmStage ogoal = TSM_UNKNOWN; 01407 if (ts != NULL) { 01408 ogoal = ts->goal; 01409 ts->goal = goal; 01410 } 01411 return ogoal; 01412 } 01413 01414 int rpmtsDBMode(rpmts ts) 01415 { 01416 return (ts != NULL ? ts->dbmode : 0); 01417 } 01418 01419 int rpmtsSetDBMode(rpmts ts, int dbmode) 01420 { 01421 int odbmode = 0; 01422 if (ts != NULL) { 01423 odbmode = ts->dbmode; 01424 ts->dbmode = dbmode; 01425 } 01426 return odbmode; 01427 } 01428 01429 rpmuint32_t rpmtsColor(rpmts ts) 01430 { 01431 return (ts != NULL ? ts->color : 0); 01432 } 01433 01434 rpmuint32_t rpmtsSetColor(rpmts ts, rpmuint32_t color) 01435 { 01436 rpmuint32_t ocolor = 0; 01437 if (ts != NULL) { 01438 ocolor = ts->color; 01439 ts->color = color; 01440 } 01441 return ocolor; 01442 } 01443 01444 rpmuint32_t rpmtsPrefColor(rpmts ts) 01445 { 01446 return (ts != NULL ? ts->prefcolor : 0); 01447 } 01448 01449 int rpmtsSetNotifyCallback(rpmts ts, 01450 rpmCallbackFunction notify, rpmCallbackData notifyData) 01451 { 01452 if (ts != NULL) { 01453 ts->notify = notify; 01454 ts->notifyData = notifyData; 01455 } 01456 return 0; 01457 } 01458 01459 rpmts rpmtsCreate(void) 01460 { 01461 rpmts ts = rpmtsGetPool(_rpmtsPool); 01462 int xx; 01463 01464 memset(&ts->ops, 0, sizeof(ts->ops)); 01465 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1); 01466 ts->type = RPMTRANS_TYPE_NORMAL; 01467 ts->goal = TSM_UNKNOWN; 01468 ts->filesystemCount = 0; 01469 ts->filesystems = NULL; 01470 ts->dsi = NULL; 01471 01472 ts->solve = rpmtsSolve; 01473 ts->solveData = NULL; 01474 ts->nsuggests = 0; 01475 ts->suggests = NULL; 01476 01477 ts->PRCO = NULL; 01478 01479 ts->bag = NULL; 01480 01481 ts->rdb = NULL; 01482 ts->dbmode = O_RDONLY; 01483 ts->txn = NULL; 01484 01485 ts->scriptFd = NULL; 01486 { struct timeval tv; 01487 xx = gettimeofday(&tv, NULL); 01488 ts->tid[0] = (rpmuint32_t) tv.tv_sec; 01489 ts->tid[1] = (rpmuint32_t) tv.tv_usec; 01490 } 01491 ts->delta = 5; 01492 01493 ts->color = rpmExpandNumeric("%{?_transaction_color}"); 01494 ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}"); 01495 if (!ts->prefcolor) ts->prefcolor = 0x2; 01496 01497 ts->rbf = NULL; 01498 ts->numRemovedPackages = 0; 01499 ts->allocedRemovedPackages = ts->delta; 01500 ts->removedPackages = xcalloc(ts->allocedRemovedPackages, 01501 sizeof(*ts->removedPackages)); 01502 01503 ts->rootDir = NULL; 01504 ts->currDir = NULL; 01505 ts->chrootDone = 0; 01506 01507 ts->selinuxEnabled = rpmsxEnabled(NULL); 01508 01509 ts->numAddedPackages = 0; 01510 ts->addedPackages = NULL; 01511 01512 ts->numErasedPackages = 0; 01513 ts->erasedPackages = NULL; 01514 01515 ts->numAvailablePackages = 0; 01516 ts->availablePackages = NULL; 01517 01518 ts->orderAlloced = 0; 01519 ts->orderCount = 0; 01520 ts->order = NULL; 01521 ts->ntrees = 0; 01522 ts->maxDepth = 0; 01523 01524 ts->probs = NULL; 01525 01526 ts->keyring = NULL; 01527 ts->hkp = NULL; 01528 ts->dig = NULL; 01529 01530 /* Set autorollback goal to the end of time. */ 01531 ts->arbgoal = 0xffffffff; 01532 01533 return rpmtsLink(ts, "tsCreate"); 01534 }
1.7.5.1