00001
00005 #include "system.h"
00006
00007 #include "rpmio_internal.h"
00008 #include <rpmlib.h>
00009 #include <rpmmacro.h>
00010
00011 #include "rpmdb.h"
00012
00013 #include "rpmal.h"
00014 #include "rpmds.h"
00015 #include "rpmfi.h"
00016 #include "rpmlock.h"
00017
00018 #define _RPMTE_INTERNAL
00019 #include "rpmte.h"
00020
00021 #define _RPMTS_INTERNAL
00022 #include "rpmts.h"
00023
00024
00025
00026 #if STATFS_IN_SYS_STATVFS
00027
00028 #if defined(__LCLINT__)
00029
00030 extern int statvfs (const char * file, struct statvfs * buf)
00031
00032 ;
00033
00034
00035 #else
00036 # include <sys/statvfs.h>
00037 #endif
00038 #else
00039 # if STATFS_IN_SYS_VFS
00040 # include <sys/vfs.h>
00041 # else
00042 # if STATFS_IN_SYS_MOUNT
00043 # include <sys/mount.h>
00044 # else
00045 # if STATFS_IN_SYS_STATFS
00046 # include <sys/statfs.h>
00047 # endif
00048 # endif
00049 # endif
00050 #endif
00051
00052 #include "debug.h"
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 int _rpmts_debug = 0;
00067
00068
00069 int _rpmts_stats = 0;
00070
00071 char * hGetNEVR(Header h, const char ** np)
00072 {
00073 const char * n, * v, * r;
00074 char * NVR, * t;
00075
00076 (void) headerNVR(h, &n, &v, &r);
00077 NVR = t = xcalloc(1, strlen(n) + strlen(v) + strlen(r) + sizeof("--"));
00078
00079 t = stpcpy(t, n);
00080 t = stpcpy(t, "-");
00081 t = stpcpy(t, v);
00082 t = stpcpy(t, "-");
00083 t = stpcpy(t, r);
00084 if (np)
00085 *np = n;
00086
00087 return NVR;
00088 }
00089
00090 uint_32 hGetColor(Header h)
00091 {
00092 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00093 uint_32 hcolor = 0;
00094 uint_32 * fcolors;
00095 int_32 ncolors;
00096 int i;
00097
00098 fcolors = NULL;
00099 ncolors = 0;
00100 if (hge(h, RPMTAG_FILECOLORS, NULL, (void **)&fcolors, &ncolors)
00101 && fcolors != NULL && ncolors > 0)
00102 {
00103
00104 for (i = 0; i < ncolors; i++)
00105 hcolor |= fcolors[i];
00106
00107 }
00108 hcolor &= 0x0f;
00109
00110 return hcolor;
00111 }
00112
00113 rpmts XrpmtsUnlink(rpmts ts, const char * msg, const char * fn, unsigned ln)
00114 {
00115
00116 if (_rpmts_debug)
00117 fprintf(stderr, "--> ts %p -- %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
00118
00119 ts->nrefs--;
00120 return NULL;
00121 }
00122
00123 rpmts XrpmtsLink(rpmts ts, const char * msg, const char * fn, unsigned ln)
00124 {
00125 ts->nrefs++;
00126
00127 if (_rpmts_debug)
00128 fprintf(stderr, "--> ts %p ++ %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
00129
00130 return ts;
00131 }
00132
00133 int rpmtsCloseDB(rpmts ts)
00134 {
00135 int rc = 0;
00136
00137 if (ts->rdb != NULL) {
00138 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->rdb->db_getops);
00139 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->rdb->db_putops);
00140 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->rdb->db_delops);
00141 rc = rpmdbClose(ts->rdb);
00142 ts->rdb = NULL;
00143 }
00144 return rc;
00145 }
00146
00147 int rpmtsOpenDB(rpmts ts, int dbmode)
00148 {
00149 int rc = 0;
00150
00151 if (ts->rdb != NULL && ts->dbmode == dbmode)
00152 return 0;
00153
00154 (void) rpmtsCloseDB(ts);
00155
00156
00157
00158 ts->dbmode = dbmode;
00159 rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
00160 if (rc) {
00161 const char * dn;
00162 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00163 rpmMessage(RPMMESS_ERROR,
00164 _("cannot open Packages database in %s\n"), dn);
00165 dn = _free(dn);
00166 }
00167 return rc;
00168 }
00169
00170 int rpmtsInitDB(rpmts ts, int dbmode)
00171 {
00172 void *lock = rpmtsAcquireLock(ts);
00173 int rc = -1;
00174 if (lock)
00175 rc = rpmdbInit(ts->rootDir, dbmode);
00176 rpmtsFreeLock(lock);
00177 return rc;
00178 }
00179
00180 int rpmtsRebuildDB(rpmts ts)
00181 {
00182 int rc;
00183 void *lock = rpmtsAcquireLock(ts);
00184 if (!lock) return -1;
00185 if (!(ts->vsflags & RPMVSF_NOHDRCHK))
00186 rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
00187 else
00188 rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
00189 rpmtsFreeLock(lock);
00190 return rc;
00191 }
00192
00193 int rpmtsVerifyDB(rpmts ts)
00194 {
00195 return rpmdbVerify(ts->rootDir);
00196 }
00197
00198
00199 static int isArch(const char * arch)
00200
00201 {
00202 const char ** av;
00203
00204
00205 static const char *arches[] = {
00206 "i386", "i486", "i586", "i686", "athlon", "x86_64", "amd64", "ia32e",
00207 "alpha", "alphaev5", "alphaev56", "alphapca56", "alphaev6", "alphaev67",
00208 "sparc", "sun4", "sun4m", "sun4c", "sun4d", "sparcv8", "sparcv9",
00209 "sparc64", "sun4u",
00210 "mips", "mipsel", "IP",
00211 "ppc", "ppciseries", "ppcpseries",
00212 "ppc64", "ppc64iseries", "ppc64pseries",
00213 "m68k",
00214 "rs6000",
00215 "ia64",
00216 "armv3l", "armv4b", "armv4l",
00217 "s390", "i370", "s390x",
00218 "sh", "xtensa",
00219 "noarch",
00220 NULL,
00221 };
00222
00223
00224 for (av = arches; *av != NULL; av++) {
00225 if (!strcmp(arch, *av))
00226 return 1;
00227 }
00228 return 0;
00229 }
00230
00231
00232
00233 rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
00234 const void * keyp, size_t keylen)
00235 {
00236 rpmdbMatchIterator mi;
00237 const char * arch = NULL;
00238 int xx;
00239
00240 if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
00241 return NULL;
00242
00243
00244
00245 if (rpmtag == RPMDBI_LABEL && keyp != NULL) {
00246 const char * s = keyp;
00247 const char *se;
00248 size_t slen = strlen(s);
00249 char *t = alloca(slen+1);
00250 int level = 0;
00251 int c;
00252
00253 keyp = t;
00254 while ((c = *s++) != '\0') {
00255 switch (c) {
00256 default:
00257 *t++ = c;
00258 break;
00259 case '(':
00260
00261 if (level++ != 0) {
00262 rpmError(RPMERR_QFMT, _("extra '(' in package label: %s\n"), keyp);
00263 return NULL;
00264 }
00265
00266 for (se = s; *se && xisdigit(*se); se++)
00267 {};
00268 if (*se == ':') {
00269
00270 *t++ = '-';
00271 s = se + 1;
00272 } else {
00273
00274 *t++ = '-';
00275 }
00276 break;
00277 case ')':
00278
00279 if (--level != 0) {
00280 rpmError(RPMERR_QFMT, _("missing '(' in package label: %s\n"), keyp);
00281 return NULL;
00282 }
00283
00284 break;
00285 }
00286 }
00287 if (level) {
00288 rpmError(RPMERR_QFMT, _("missing ')' in package label: %s\n"), keyp);
00289 return NULL;
00290 }
00291 *t = '\0';
00292 t = (char *) keyp;
00293 t = strrchr(t, '.');
00294
00295 if (t != NULL && isArch(t+1)) {
00296 *t++ = '\0';
00297 arch = t;
00298 }
00299 }
00300
00301
00302 mi = rpmdbInitIterator(ts->rdb, rpmtag, keyp, keylen);
00303
00304
00305 if (mi && !(ts->vsflags & RPMVSF_NOHDRCHK))
00306 (void) rpmdbSetHdrChk(mi, ts, headerCheck);
00307
00308
00309 if (arch != NULL)
00310 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT, arch);
00311 return mi;
00312 }
00313
00314
00315 rpmRC rpmtsFindPubkey(rpmts ts)
00316 {
00317 const void * sig = rpmtsSig(ts);
00318 pgpDig dig = rpmtsDig(ts);
00319 pgpDigParams sigp = rpmtsSignature(ts);
00320 pgpDigParams pubp = rpmtsSignature(ts);
00321 rpmRC res;
00322 int xx;
00323
00324 if (sig == NULL || dig == NULL || sigp == NULL || pubp == NULL) {
00325 res = RPMRC_NOKEY;
00326 goto exit;
00327 }
00328
00329 if (ts->pkpkt == NULL
00330 || memcmp(sigp->signid, ts->pksignid, sizeof(ts->pksignid)))
00331 {
00332 int ix = -1;
00333 rpmdbMatchIterator mi;
00334 Header h;
00335
00336 ts->pkpkt = _free(ts->pkpkt);
00337 ts->pkpktlen = 0;
00338 memset(ts->pksignid, 0, sizeof(ts->pksignid));
00339
00340
00341 mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
00342 while ((h = rpmdbNextIterator(mi)) != NULL) {
00343 const char ** pubkeys;
00344 int_32 pt, pc;
00345
00346 if (!headerGetEntry(h, RPMTAG_PUBKEYS, &pt, (void **)&pubkeys, &pc))
00347 continue;
00348 ix = rpmdbGetIteratorFileNum(mi);
00349
00350 if (ix >= pc
00351 || b64decode(pubkeys[ix], (void **) &ts->pkpkt, &ts->pkpktlen))
00352 ix = -1;
00353
00354 pubkeys = headerFreeData(pubkeys, pt);
00355 break;
00356 }
00357 mi = rpmdbFreeIterator(mi);
00358
00359
00360 if (ix < 0 || ts->pkpkt == NULL) {
00361 res = RPMRC_NOKEY;
00362 goto exit;
00363 }
00364
00365
00366
00367
00368
00369 if (pgpPrtPkts(ts->pkpkt, ts->pkpktlen, NULL, 0)
00370 && sigp->pubkey_algo == pubp->pubkey_algo
00371 #ifdef NOTYET
00372 && sigp->hash_algo == pubp->hash_algo
00373 #endif
00374 && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)))
00375 {
00376 ts->pkpkt = _free(ts->pkpkt);
00377 ts->pkpktlen = 0;
00378 res = RPMRC_NOKEY;
00379 goto exit;
00380 }
00381
00382
00383
00384
00385
00386 memcpy(ts->pksignid, sigp->signid, sizeof(ts->pksignid));
00387
00388
00389 rpmMessage(RPMMESS_DEBUG, "========== %s pubkey id %s\n",
00390 (sigp->pubkey_algo == PGPPUBKEYALGO_DSA ? "DSA" :
00391 (sigp->pubkey_algo == PGPPUBKEYALGO_RSA ? "RSA" : "???")),
00392 pgpHexStr(sigp->signid, sizeof(sigp->signid)));
00393
00394 }
00395
00396 #ifdef NOTNOW
00397 {
00398 if (ts->pkpkt == NULL) {
00399 const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
00400 if (pgpReadPkts(pkfn, &ts->pkpkt, &ts->pkpktlen) != PGPARMOR_PUBKEY) {
00401 pkfn = _free(pkfn);
00402 res = RPMRC_NOKEY;
00403 goto exit;
00404 }
00405 pkfn = _free(pkfn);
00406 }
00407 }
00408 #endif
00409
00410
00411 xx = pgpPrtPkts(ts->pkpkt, ts->pkpktlen, dig, 0);
00412
00413
00414 if (sigp->pubkey_algo == pubp->pubkey_algo
00415 #ifdef NOTYET
00416 && sigp->hash_algo == pubp->hash_algo
00417 #endif
00418 && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)) )
00419 res = RPMRC_OK;
00420 else
00421 res = RPMRC_NOKEY;
00422
00423
00424
00425 exit:
00426 return res;
00427 }
00428
00429 int rpmtsCloseSDB(rpmts ts)
00430 {
00431 int rc = 0;
00432
00433 if (ts->sdb != NULL) {
00434 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->sdb->db_getops);
00435 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->sdb->db_putops);
00436 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->sdb->db_delops);
00437 rc = rpmdbClose(ts->sdb);
00438 ts->sdb = NULL;
00439 }
00440 return rc;
00441 }
00442
00443 int rpmtsOpenSDB(rpmts ts, int dbmode)
00444 {
00445 static int has_sdbpath = -1;
00446 int rc = 0;
00447
00448 if (ts->sdb != NULL && ts->sdbmode == dbmode)
00449 return 0;
00450
00451 if (has_sdbpath < 0)
00452 has_sdbpath = rpmExpandNumeric("%{?_solve_dbpath:1}");
00453
00454
00455 if (has_sdbpath <= 0)
00456 return 1;
00457
00458 addMacro(NULL, "_dbpath", NULL, "%{_solve_dbpath}", RMIL_DEFAULT);
00459
00460 rc = rpmdbOpen(ts->rootDir, &ts->sdb, ts->sdbmode, 0644);
00461 if (rc) {
00462 const char * dn;
00463 dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00464 rpmMessage(RPMMESS_WARNING,
00465 _("cannot open Solve database in %s\n"), dn);
00466 dn = _free(dn);
00467 }
00468 delMacro(NULL, "_dbpath");
00469
00470 return rc;
00471 }
00472
00479 static int sugcmp(const void * a, const void * b)
00480
00481 {
00482
00483 const char * astr = *(const char **)a;
00484 const char * bstr = *(const char **)b;
00485
00486 return strcmp(astr, bstr);
00487 }
00488
00489
00490 int rpmtsSolve(rpmts ts, rpmds ds, const void * data)
00491 {
00492 const char * errstr;
00493 const char * str;
00494 const char * qfmt;
00495 rpmdbMatchIterator mi;
00496 Header bh;
00497 Header h;
00498 size_t bhnamelen;
00499 time_t bhtime;
00500 rpmTag rpmtag;
00501 const char * keyp;
00502 size_t keylen;
00503 int rc = 1;
00504 int xx;
00505
00506
00507 if (ts->goal != TSM_INSTALL)
00508 return rc;
00509
00510 if (rpmdsTagN(ds) != RPMTAG_REQUIRENAME)
00511 return rc;
00512
00513 keyp = rpmdsN(ds);
00514 if (keyp == NULL)
00515 return rc;
00516
00517 if (ts->sdb == NULL) {
00518 xx = rpmtsOpenSDB(ts, ts->sdbmode);
00519 if (xx) return rc;
00520 }
00521
00522
00523 rpmtag = (*keyp == '/' ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME);
00524 keylen = 0;
00525 mi = rpmdbInitIterator(ts->sdb, rpmtag, keyp, keylen);
00526 bhnamelen = 0;
00527 bhtime = 0;
00528 bh = NULL;
00529 while ((h = rpmdbNextIterator(mi)) != NULL) {
00530 const char * hname;
00531 size_t hnamelen;
00532 time_t htime;
00533 int_32 * ip;
00534
00535 if (rpmtag == RPMTAG_PROVIDENAME && !rpmdsAnyMatchesDep(h, ds, 1))
00536 continue;
00537
00538
00539 hname = NULL;
00540 hnamelen = 0;
00541 if (headerGetEntry(h, RPMTAG_NAME, NULL, (void **)&hname, NULL)) {
00542 if (hname)
00543 hnamelen = strlen(hname);
00544 }
00545 if (bhnamelen > 0 && hnamelen > bhnamelen)
00546 continue;
00547
00548
00549 htime = 0;
00550 if (headerGetEntry(h, RPMTAG_BUILDTIME, NULL, (void **)&ip, NULL))
00551 htime = (time_t)*ip;
00552
00553 if (htime <= bhtime)
00554 continue;
00555
00556 bh = headerFree(bh);
00557 bh = headerLink(h);
00558 bhtime = htime;
00559 bhnamelen = hnamelen;
00560 }
00561 mi = rpmdbFreeIterator(mi);
00562
00563
00564 if (bh == NULL)
00565 goto exit;
00566
00567
00568 qfmt = rpmExpand("%{?_solve_name_fmt}", NULL);
00569 if (qfmt == NULL || *qfmt == '\0')
00570 goto exit;
00571 str = headerSprintf(bh, qfmt, rpmTagTable, rpmHeaderFormats, &errstr);
00572 bh = headerFree(bh);
00573 qfmt = _free(qfmt);
00574 if (str == NULL) {
00575 rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr);
00576 goto exit;
00577 }
00578
00579 if (ts->transFlags & RPMTRANS_FLAG_ADDINDEPS) {
00580 FD_t fd;
00581 rpmRC rpmrc;
00582
00583 h = headerFree(h);
00584 fd = Fopen(str, "r.ufdio");
00585 if (fd == NULL || Ferror(fd)) {
00586 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), str,
00587 Fstrerror(fd));
00588 if (fd != NULL) {
00589 xx = Fclose(fd);
00590 fd = NULL;
00591 }
00592 str = _free(str);
00593 goto exit;
00594 }
00595 rpmrc = rpmReadPackageFile(ts, fd, str, &h);
00596 xx = Fclose(fd);
00597 switch (rpmrc) {
00598 default:
00599 str = _free(str);
00600 break;
00601 case RPMRC_NOTTRUSTED:
00602 case RPMRC_NOKEY:
00603 case RPMRC_OK:
00604 if (h != NULL &&
00605 !rpmtsAddInstallElement(ts, h, (fnpyKey)str, 1, NULL))
00606 {
00607 rpmMessage(RPMMESS_DEBUG, _("Adding: %s\n"), str);
00608 rc = -1;
00609
00610 break;
00611 }
00612 str = _free(str);
00613 break;
00614 }
00615 h = headerFree(h);
00616 goto exit;
00617 }
00618
00619 rpmMessage(RPMMESS_DEBUG, _("Suggesting: %s\n"), str);
00620
00621 if (ts->suggests != NULL && ts->nsuggests > 0) {
00622 if (bsearch(&str, ts->suggests, ts->nsuggests,
00623 sizeof(*ts->suggests), sugcmp))
00624 goto exit;
00625 }
00626
00627
00628 ts->suggests = xrealloc(ts->suggests,
00629 sizeof(*ts->suggests) * (ts->nsuggests + 2));
00630 ts->suggests[ts->nsuggests] = str;
00631 ts->nsuggests++;
00632 ts->suggests[ts->nsuggests] = NULL;
00633
00634 if (ts->nsuggests > 1)
00635 qsort(ts->suggests, ts->nsuggests, sizeof(*ts->suggests), sugcmp);
00636
00637 exit:
00638
00639 return rc;
00640
00641 }
00642
00643
00644 int rpmtsAvailable(rpmts ts, const rpmds ds)
00645 {
00646 fnpyKey * sugkey;
00647 int rc = 1;
00648
00649 if (ts->availablePackages == NULL)
00650 return rc;
00651 sugkey = rpmalAllSatisfiesDepend(ts->availablePackages, ds, NULL);
00652 if (sugkey == NULL)
00653 return rc;
00654
00655
00656 if (sugkey[0] != NULL) {
00657 ts->suggests = xrealloc(ts->suggests,
00658 sizeof(*ts->suggests) * (ts->nsuggests + 2));
00659 ts->suggests[ts->nsuggests] = sugkey[0];
00660 sugkey[0] = NULL;
00661 ts->nsuggests++;
00662 ts->suggests[ts->nsuggests] = NULL;
00663 }
00664 sugkey = _free(sugkey);
00665
00666 return rc;
00667
00668 }
00669
00670 int rpmtsSetSolveCallback(rpmts ts,
00671 int (*solve) (rpmts ts, rpmds key, const void * data),
00672 const void * solveData)
00673 {
00674 int rc = 0;
00675
00676
00677 if (ts) {
00678
00679 ts->solve = solve;
00680 ts->solveData = solveData;
00681
00682 }
00683
00684 return rc;
00685 }
00686
00687 rpmps rpmtsProblems(rpmts ts)
00688 {
00689 rpmps ps = NULL;
00690 if (ts) {
00691 if (ts->probs)
00692 ps = rpmpsLink(ts->probs, NULL);
00693 }
00694 return ps;
00695 }
00696
00697 void rpmtsCleanDig(rpmts ts)
00698 {
00699 ts->sig = headerFreeData(ts->sig, ts->sigtype);
00700 ts->dig = pgpFreeDig(ts->dig);
00701 }
00702
00703 void rpmtsClean(rpmts ts)
00704 {
00705 rpmtsi pi; rpmte p;
00706
00707 if (ts == NULL)
00708 return;
00709
00710
00711 pi = rpmtsiInit(ts);
00712 while ((p = rpmtsiNext(pi, 0)) != NULL)
00713 rpmteCleanDS(p);
00714 pi = rpmtsiFree(pi);
00715
00716 ts->addedPackages = rpmalFree(ts->addedPackages);
00717 ts->numAddedPackages = 0;
00718
00719 ts->suggests = _free(ts->suggests);
00720 ts->nsuggests = 0;
00721
00722 ts->probs = rpmpsFree(ts->probs);
00723
00724 rpmtsCleanDig(ts);
00725 }
00726
00727 void rpmtsEmpty(rpmts ts)
00728 {
00729 rpmtsi pi; rpmte p;
00730 int oc;
00731
00732 if (ts == NULL)
00733 return;
00734
00735
00736 rpmtsClean(ts);
00737
00738
00739 for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
00740
00741 ts->order[oc] = rpmteFree(ts->order[oc]);
00742
00743 }
00744 pi = rpmtsiFree(pi);
00745
00746 ts->orderCount = 0;
00747
00748 ts->numRemovedPackages = 0;
00749
00750 return;
00751
00752 }
00753
00754 static void rpmtsPrintStat(const char * name, struct rpmop_s * op)
00755
00756
00757 {
00758 static unsigned int scale = (1000 * 1000);
00759 if (op != NULL && op->count > 0)
00760 fprintf(stderr, " %s %6d %6lu.%06lu MB %6lu.%06lu secs\n",
00761 name, op->count,
00762 (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
00763 op->usecs/scale, op->usecs%scale);
00764 }
00765
00766 static void rpmtsPrintStats(rpmts ts)
00767
00768
00769 {
00770 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
00771
00772 rpmtsPrintStat("total: ", rpmtsOp(ts, RPMTS_OP_TOTAL));
00773 rpmtsPrintStat("check: ", rpmtsOp(ts, RPMTS_OP_CHECK));
00774 rpmtsPrintStat("order: ", rpmtsOp(ts, RPMTS_OP_ORDER));
00775 rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
00776 rpmtsPrintStat("repackage: ", rpmtsOp(ts, RPMTS_OP_REPACKAGE));
00777 rpmtsPrintStat("install: ", rpmtsOp(ts, RPMTS_OP_INSTALL));
00778 rpmtsPrintStat("erase: ", rpmtsOp(ts, RPMTS_OP_ERASE));
00779 rpmtsPrintStat("scriptlets: ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
00780 rpmtsPrintStat("compress: ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
00781 rpmtsPrintStat("uncompress: ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
00782 rpmtsPrintStat("digest: ", rpmtsOp(ts, RPMTS_OP_DIGEST));
00783 rpmtsPrintStat("signature: ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
00784 rpmtsPrintStat("dbadd: ", rpmtsOp(ts, RPMTS_OP_DBADD));
00785 rpmtsPrintStat("dbremove: ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
00786 rpmtsPrintStat("dbget: ", rpmtsOp(ts, RPMTS_OP_DBGET));
00787 rpmtsPrintStat("dbput: ", rpmtsOp(ts, RPMTS_OP_DBPUT));
00788 rpmtsPrintStat("dbdel: ", rpmtsOp(ts, RPMTS_OP_DBDEL));
00789 }
00790
00791 rpmts rpmtsFree(rpmts ts)
00792 {
00793 if (ts == NULL)
00794 return NULL;
00795
00796 if (ts->nrefs > 1)
00797 return rpmtsUnlink(ts, "tsCreate");
00798
00799
00800 rpmtsEmpty(ts);
00801
00802
00803 (void) rpmtsCloseDB(ts);
00804
00805 (void) rpmtsCloseSDB(ts);
00806
00807 ts->sx = rpmsxFree(ts->sx);
00808
00809 ts->removedPackages = _free(ts->removedPackages);
00810
00811 ts->availablePackages = rpmalFree(ts->availablePackages);
00812 ts->numAvailablePackages = 0;
00813
00814 ts->dsi = _free(ts->dsi);
00815
00816 if (ts->scriptFd != NULL) {
00817 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsFree");
00818 ts->scriptFd = NULL;
00819 }
00820 ts->rootDir = _free(ts->rootDir);
00821 ts->currDir = _free(ts->currDir);
00822
00823
00824 ts->order = _free(ts->order);
00825
00826 ts->orderAlloced = 0;
00827
00828 if (ts->pkpkt != NULL)
00829 ts->pkpkt = _free(ts->pkpkt);
00830 ts->pkpktlen = 0;
00831 memset(ts->pksignid, 0, sizeof(ts->pksignid));
00832
00833 if (_rpmts_stats)
00834 rpmtsPrintStats(ts);
00835
00836 (void) rpmtsUnlink(ts, "tsCreate");
00837
00838
00839 ts = _free(ts);
00840
00841
00842 return NULL;
00843 }
00844
00845 rpmVSFlags rpmtsVSFlags(rpmts ts)
00846 {
00847 rpmVSFlags vsflags = 0;
00848 if (ts != NULL)
00849 vsflags = ts->vsflags;
00850 return vsflags;
00851 }
00852
00853 rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
00854 {
00855 rpmVSFlags ovsflags = 0;
00856 if (ts != NULL) {
00857 ovsflags = ts->vsflags;
00858 ts->vsflags = vsflags;
00859 }
00860 return ovsflags;
00861 }
00862
00863 int rpmtsUnorderedSuccessors(rpmts ts, int first)
00864 {
00865 int unorderedSuccessors = 0;
00866 if (ts != NULL) {
00867 unorderedSuccessors = ts->unorderedSuccessors;
00868 if (first >= 0)
00869 ts->unorderedSuccessors = first;
00870 }
00871 return unorderedSuccessors;
00872 }
00873
00874 const char * rpmtsRootDir(rpmts ts)
00875 {
00876 return (ts != NULL ? ts->rootDir : NULL);
00877 }
00878
00879 void rpmtsSetRootDir(rpmts ts, const char * rootDir)
00880 {
00881 if (ts != NULL) {
00882 size_t rootLen;
00883
00884 ts->rootDir = _free(ts->rootDir);
00885
00886 if (rootDir == NULL) {
00887 #ifndef DYING
00888 ts->rootDir = xstrdup("");
00889 #endif
00890 return;
00891 }
00892 rootLen = strlen(rootDir);
00893
00894
00895
00896 if (!(rootLen && rootDir[rootLen - 1] == '/')) {
00897 char * t = alloca(rootLen + 2);
00898 *t = '\0';
00899 (void) stpcpy( stpcpy(t, rootDir), "/");
00900 rootDir = t;
00901 }
00902
00903 ts->rootDir = xstrdup(rootDir);
00904 }
00905 }
00906
00907 const char * rpmtsCurrDir(rpmts ts)
00908 {
00909 const char * currDir = NULL;
00910 if (ts != NULL) {
00911 currDir = ts->currDir;
00912 }
00913 return currDir;
00914 }
00915
00916 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
00917 {
00918 if (ts != NULL) {
00919 ts->currDir = _free(ts->currDir);
00920 if (currDir)
00921 ts->currDir = xstrdup(currDir);
00922 }
00923 }
00924
00925 FD_t rpmtsScriptFd(rpmts ts)
00926 {
00927 FD_t scriptFd = NULL;
00928 if (ts != NULL) {
00929 scriptFd = ts->scriptFd;
00930 }
00931
00932 return scriptFd;
00933
00934 }
00935
00936 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
00937 {
00938
00939 if (ts != NULL) {
00940 if (ts->scriptFd != NULL) {
00941 ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd");
00942 ts->scriptFd = NULL;
00943 }
00944
00945 if (scriptFd != NULL)
00946 ts->scriptFd = fdLink((void *)scriptFd, "rpmtsSetScriptFd");
00947
00948 }
00949 }
00950
00951 int rpmtsSELinuxEnabled(rpmts ts)
00952 {
00953 return (ts != NULL ? (ts->selinuxEnabled > 0) : 0);
00954 }
00955
00956 int rpmtsChrootDone(rpmts ts)
00957 {
00958 return (ts != NULL ? ts->chrootDone : 0);
00959 }
00960
00961 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
00962 {
00963 int ochrootDone = 0;
00964 if (ts != NULL) {
00965 ochrootDone = ts->chrootDone;
00966 if (ts->rdb != NULL)
00967 ts->rdb->db_chrootDone = chrootDone;
00968 ts->chrootDone = chrootDone;
00969 }
00970 return ochrootDone;
00971 }
00972
00973 rpmsx rpmtsREContext(rpmts ts)
00974 {
00975 return ( (ts && ts->sx ? rpmsxLink(ts->sx, __func__) : NULL) );
00976 }
00977
00978 int rpmtsSetREContext(rpmts ts, rpmsx sx)
00979 {
00980 int rc = -1;
00981 if (ts != NULL) {
00982 ts->sx = rpmsxFree(ts->sx);
00983 ts->sx = rpmsxLink(sx, __func__);
00984 if (ts->sx != NULL)
00985 rc = 0;
00986 }
00987 return rc;
00988 }
00989
00990 int_32 rpmtsGetTid(rpmts ts)
00991 {
00992 int_32 tid = 0;
00993 if (ts != NULL) {
00994 tid = ts->tid;
00995 }
00996 return tid;
00997 }
00998
00999 int_32 rpmtsSetTid(rpmts ts, int_32 tid)
01000 {
01001 int_32 otid = 0;
01002 if (ts != NULL) {
01003 otid = ts->tid;
01004 ts->tid = tid;
01005 }
01006 return otid;
01007 }
01008
01009 int_32 rpmtsSigtag(const rpmts ts)
01010 {
01011 int_32 sigtag = 0;
01012 if (ts != NULL)
01013 sigtag = ts->sigtag;
01014 return sigtag;
01015 }
01016
01017 int_32 rpmtsSigtype(const rpmts ts)
01018 {
01019 int_32 sigtype = 0;
01020 if (ts != NULL)
01021 sigtype = ts->sigtype;
01022 return sigtype;
01023 }
01024
01025 const void * rpmtsSig(const rpmts ts)
01026 {
01027 const void * sig = NULL;
01028 if (ts != NULL)
01029 sig = ts->sig;
01030 return sig;
01031 }
01032
01033 int_32 rpmtsSiglen(const rpmts ts)
01034 {
01035 int_32 siglen = 0;
01036 if (ts != NULL)
01037 siglen = ts->siglen;
01038 return siglen;
01039 }
01040
01041 int rpmtsSetSig(rpmts ts,
01042 int_32 sigtag, int_32 sigtype, const void * sig, int_32 siglen)
01043 {
01044 if (ts != NULL) {
01045 if (ts->sig && ts->sigtype)
01046 ts->sig = headerFreeData(ts->sig, ts->sigtype);
01047 ts->sigtag = sigtag;
01048 ts->sigtype = (sig ? sigtype : 0);
01049
01050 ts->sig = sig;
01051
01052 ts->siglen = siglen;
01053 }
01054 return 0;
01055 }
01056
01057 pgpDig rpmtsDig(rpmts ts)
01058 {
01059
01060 if (ts->dig == NULL)
01061 ts->dig = pgpNewDig();
01062
01063 if (ts->dig == NULL)
01064 return NULL;
01065 return ts->dig;
01066 }
01067
01068 pgpDigParams rpmtsSignature(const rpmts ts)
01069 {
01070 pgpDig dig = rpmtsDig(ts);
01071 if (dig == NULL) return NULL;
01072
01073 return &dig->signature;
01074
01075 }
01076
01077 pgpDigParams rpmtsPubkey(const rpmts ts)
01078 {
01079 pgpDig dig = rpmtsDig(ts);
01080 if (dig == NULL) return NULL;
01081
01082 return &dig->pubkey;
01083
01084 }
01085
01086 rpmdb rpmtsGetRdb(rpmts ts)
01087 {
01088 rpmdb rdb = NULL;
01089 if (ts != NULL) {
01090 rdb = ts->rdb;
01091 }
01092
01093 return rdb;
01094
01095 }
01096
01097 int rpmtsInitDSI(const rpmts ts)
01098 {
01099 rpmDiskSpaceInfo dsi;
01100 struct stat sb;
01101 int rc;
01102 int i;
01103
01104 if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
01105 return 0;
01106
01107 rpmMessage(RPMMESS_DEBUG, _("mounted filesystems:\n"));
01108 rpmMessage(RPMMESS_DEBUG,
01109 _(" i dev bsize bavail iavail mount point\n"));
01110
01111 rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
01112 if (rc || ts->filesystems == NULL || ts->filesystemCount <= 0)
01113 return rc;
01114
01115
01116
01117 ts->dsi = _free(ts->dsi);
01118 ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
01119
01120 dsi = ts->dsi;
01121
01122 if (dsi != NULL)
01123 for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
01124 #if STATFS_IN_SYS_STATVFS
01125 struct statvfs sfb;
01126 memset(&sfb, 0, sizeof(sfb));
01127 rc = statvfs(ts->filesystems[i], &sfb);
01128 #else
01129 struct statfs sfb;
01130 memset(&sfb, 0, sizeof(sfb));
01131 # if STAT_STATFS4
01132
01133
01134
01135
01136
01137 rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
01138 # else
01139 rc = statfs(ts->filesystems[i], &sfb);
01140 # endif
01141 #endif
01142 if (rc)
01143 break;
01144
01145 rc = stat(ts->filesystems[i], &sb);
01146 if (rc)
01147 break;
01148 dsi->dev = sb.st_dev;
01149
01150 dsi->bsize = sfb.f_bsize;
01151 dsi->bneeded = 0;
01152 dsi->ineeded = 0;
01153 #ifdef STATFS_HAS_F_BAVAIL
01154 dsi->bavail = sfb.f_bavail;
01155 #else
01156
01157
01158
01159
01160 dsi->bavail = sfb.f_blocks - sfb.f_bfree;
01161 #endif
01162
01163 dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
01164 ? sfb.f_ffree : -1;
01165 rpmMessage(RPMMESS_DEBUG, _("%5d 0x%04x %5u %12ld %12ld %s\n"),
01166 i, (unsigned) dsi->dev, (unsigned) dsi->bsize,
01167 (signed long) dsi->bavail, (signed long) dsi->iavail,
01168 ts->filesystems[i]);
01169 }
01170 return rc;
01171 }
01172
01173 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
01174 uint_32 fileSize, uint_32 prevSize, uint_32 fixupSize,
01175 fileAction action)
01176 {
01177 rpmDiskSpaceInfo dsi;
01178 uint_32 bneeded;
01179
01180 dsi = ts->dsi;
01181 if (dsi) {
01182 while (dsi->bsize && dsi->dev != dev)
01183 dsi++;
01184 if (dsi->bsize == 0)
01185 dsi = NULL;
01186 }
01187 if (dsi == NULL)
01188 return;
01189
01190 bneeded = BLOCK_ROUND(fileSize, dsi->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 break;
01199
01200
01201
01202
01203
01204
01205 case FA_CREATE:
01206 dsi->bneeded += bneeded;
01207 dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->bsize);
01208 break;
01209
01210 case FA_ERASE:
01211 dsi->ineeded--;
01212 dsi->bneeded -= bneeded;
01213 break;
01214
01215 default:
01216 break;
01217 }
01218
01219 if (fixupSize)
01220 dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->bsize);
01221 }
01222
01223 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
01224 {
01225 rpmDiskSpaceInfo dsi;
01226 rpmps ps;
01227 int fc;
01228 int 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->bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
01244 rpmpsAppend(ps, RPMPROB_DISKSPACE,
01245 rpmteNEVR(te), rpmteKey(te),
01246 ts->filesystems[i], NULL, NULL,
01247 (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
01248 }
01249
01250 if (dsi->iavail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
01251 rpmpsAppend(ps, RPMPROB_DISKNODES,
01252 rpmteNEVR(te), rpmteKey(te),
01253 ts->filesystems[i], NULL, NULL,
01254 (adj_fs_blocks(dsi->ineeded) - dsi->iavail));
01255 }
01256 }
01257 ps = rpmpsFree(ps);
01258 }
01259
01260 void * rpmtsNotify(rpmts ts, rpmte te,
01261 rpmCallbackType what, unsigned long amount, unsigned long total)
01262 {
01263 void * ptr = NULL;
01264 if (ts && ts->notify && te) {
01265 assert(!(te->type == TR_ADDED && te->h == NULL));
01266
01267
01268 ptr = ts->notify(te->h, what, amount, total,
01269 rpmteKey(te), ts->notifyData);
01270
01271
01272 }
01273 return ptr;
01274 }
01275
01276 int rpmtsNElements(rpmts ts)
01277 {
01278 int nelements = 0;
01279 if (ts != NULL && ts->order != NULL) {
01280 nelements = ts->orderCount;
01281 }
01282 return nelements;
01283 }
01284
01285 rpmte rpmtsElement(rpmts ts, int ix)
01286 {
01287 rpmte te = NULL;
01288 if (ts != NULL && ts->order != NULL) {
01289 if (ix >= 0 && ix < ts->orderCount)
01290 te = ts->order[ix];
01291 }
01292
01293 return te;
01294
01295 }
01296
01297 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
01298 {
01299 return (ts != NULL ? ts->ignoreSet : 0);
01300 }
01301
01302 rpmtransFlags rpmtsFlags(rpmts ts)
01303 {
01304 return (ts != NULL ? ts->transFlags : 0);
01305 }
01306
01307 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
01308 {
01309 rpmtransFlags otransFlags = 0;
01310 if (ts != NULL) {
01311 otransFlags = ts->transFlags;
01312 ts->transFlags = transFlags;
01313 }
01314 return otransFlags;
01315 }
01316
01317 Spec rpmtsSpec(rpmts ts)
01318 {
01319
01320 return ts->spec;
01321
01322 }
01323
01324 Spec rpmtsSetSpec(rpmts ts, Spec spec)
01325 {
01326 Spec ospec = ts->spec;
01327
01328 ts->spec = spec;
01329
01330 return ospec;
01331 }
01332
01333 rpmte rpmtsRelocateElement(rpmts ts)
01334 {
01335
01336 return ts->relocateElement;
01337
01338 }
01339
01340 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement)
01341 {
01342 rpmte orelocateElement = ts->relocateElement;
01343
01344 ts->relocateElement = relocateElement;
01345
01346 return orelocateElement;
01347 }
01348
01349 uint_32 rpmtsColor(rpmts ts)
01350 {
01351 return (ts != NULL ? ts->color : 0);
01352 }
01353
01354 uint_32 rpmtsSetColor(rpmts ts, uint_32 color)
01355 {
01356 uint_32 ocolor = 0;
01357 if (ts != NULL) {
01358 ocolor = ts->color;
01359 ts->color = color;
01360 }
01361 return ocolor;
01362 }
01363
01364 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
01365 {
01366 rpmop op = NULL;
01367
01368 if (ts != NULL && opx >= 0 && opx < RPMTS_OP_MAX)
01369 op = ts->ops + opx;
01370
01371 return op;
01372
01373 }
01374
01375 int rpmtsSetNotifyCallback(rpmts ts,
01376 rpmCallbackFunction notify, rpmCallbackData notifyData)
01377 {
01378 if (ts != NULL) {
01379 ts->notify = notify;
01380 ts->notifyData = notifyData;
01381 }
01382 return 0;
01383 }
01384
01385 int rpmtsGetKeys(const rpmts ts, fnpyKey ** ep, int * nep)
01386 {
01387 int rc = 0;
01388
01389 if (nep) *nep = ts->orderCount;
01390 if (ep) {
01391 rpmtsi pi; rpmte p;
01392 fnpyKey * e;
01393
01394 *ep = e = xmalloc(ts->orderCount * sizeof(*e));
01395 pi = rpmtsiInit(ts);
01396 while ((p = rpmtsiNext(pi, 0)) != NULL) {
01397 switch (rpmteType(p)) {
01398 case TR_ADDED:
01399
01400 *e = rpmteKey(p);
01401
01402 break;
01403 case TR_REMOVED:
01404 default:
01405 *e = NULL;
01406 break;
01407 }
01408 e++;
01409 }
01410 pi = rpmtsiFree(pi);
01411 }
01412 return rc;
01413 }
01414
01415 rpmts rpmtsCreate(void)
01416 {
01417 rpmts ts;
01418
01419 ts = xcalloc(1, sizeof(*ts));
01420 memset(&ts->ops, 0, sizeof(ts->ops));
01421 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
01422 ts->goal = TSM_UNKNOWN;
01423 ts->filesystemCount = 0;
01424 ts->filesystems = NULL;
01425 ts->dsi = NULL;
01426
01427 ts->solve = rpmtsSolve;
01428 ts->solveData = NULL;
01429 ts->nsuggests = 0;
01430 ts->suggests = NULL;
01431 ts->sdb = NULL;
01432 ts->sdbmode = O_RDONLY;
01433
01434 ts->rdb = NULL;
01435 ts->dbmode = O_RDONLY;
01436
01437 ts->scriptFd = NULL;
01438 ts->tid = (int_32) time(NULL);
01439 ts->delta = 5;
01440
01441 ts->color = rpmExpandNumeric("%{?_transaction_color}");
01442
01443 ts->numRemovedPackages = 0;
01444 ts->allocedRemovedPackages = ts->delta;
01445 ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
01446 sizeof(*ts->removedPackages));
01447
01448 ts->rootDir = NULL;
01449 ts->currDir = NULL;
01450 ts->chrootDone = 0;
01451
01452 ts->selinuxEnabled = is_selinux_enabled();
01453
01454 ts->numAddedPackages = 0;
01455 ts->addedPackages = NULL;
01456
01457 ts->numAvailablePackages = 0;
01458 ts->availablePackages = NULL;
01459
01460 ts->orderAlloced = 0;
01461 ts->orderCount = 0;
01462 ts->order = NULL;
01463
01464 ts->probs = NULL;
01465
01466 ts->sig = NULL;
01467 ts->pkpkt = NULL;
01468 ts->pkpktlen = 0;
01469 memset(ts->pksignid, 0, sizeof(ts->pksignid));
01470 ts->dig = NULL;
01471
01472 ts->nrefs = 0;
01473
01474 return rpmtsLink(ts, "tsCreate");
01475 }