rpmts.c

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

Generated on Fri Feb 24 08:33:33 2006 for rpm by  doxygen 1.4.5