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