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