Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

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

Generated on Sun Oct 26 13:02:01 2003 for rpm by doxygen1.2.18