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