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