• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

lib/rpmts.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmio_internal.h>
00008 #include <rpmbc.h>              /* XXX beecrypt base64 */
00009 #include <rpmio.h>
00010 #include <rpmurl.h>
00011 #include <rpmpgp.h>
00012 #include <rpmcb.h>              /* XXX fnpyKey */
00013 #include <rpmmacro.h>           /* XXX rpmtsOpenDB() needs rpmGetPath */
00014 #include <rpmlib.h>
00015 
00016 #define _RPMDB_INTERNAL         /* XXX almost opaque sigh */
00017 #include "rpmdb.h"              /* XXX stealing db->db_mode. */
00018 
00019 #define _RPMEVR_INTERNAL        /* XXX RPMSENSE_KEYRING */
00020 #include "rpmevr.h"
00021 
00022 #include "rpmal.h"
00023 #include "rpmds.h"
00024 #include "rpmfi.h"
00025 #include "rpmlock.h"
00026 #include "rpmns.h"
00027 
00028 #define _RPMTE_INTERNAL         /* XXX te->h */
00029 #include "rpmte.h"
00030 
00031 #define _RPMTS_INTERNAL
00032 #include "rpmts.h"
00033 
00034 #include "fs.h"
00035 
00036 /* XXX FIXME: merge with existing (broken?) tests in system.h */
00037 /* portability fiddles */
00038 #if STATFS_IN_SYS_STATVFS
00039 /*@-incondefs@*/
00040 #if defined(__LCLINT__)
00041 /*@-declundef -exportheader -protoparammatch @*/ /* LCL: missing annotation */
00042 extern int statvfs (const char * file, /*@out@*/ struct statvfs * buf)
00043         /*@globals fileSystem @*/
00044         /*@modifies *buf, fileSystem @*/;
00045 /*@=declundef =exportheader =protoparammatch @*/
00046 /*@=incondefs@*/
00047 #else
00048 # include <sys/statvfs.h>
00049 #endif
00050 #else
00051 # if STATFS_IN_SYS_VFS
00052 #  include <sys/vfs.h>
00053 # else
00054 #  if STATFS_IN_SYS_MOUNT
00055 #   include <sys/mount.h>
00056 #  else
00057 #   if STATFS_IN_SYS_STATFS
00058 #    include <sys/statfs.h>
00059 #   endif
00060 #  endif
00061 # endif
00062 #endif
00063 
00064 #include "debug.h"
00065 
00066 /*@access FD_t @*/              /* XXX void * arg */
00067 /*@access rpmdb @*/             /* XXX db->db_chrootDone, NULL */
00068 
00069 /*@access rpmps @*/
00070 /*@access rpmDiskSpaceInfo @*/
00071 /*@access rpmsx @*/
00072 /*@access rpmte @*/
00073 /*@access rpmtsi @*/
00074 /*@access fnpyKey @*/
00075 /*@access pgpDig @*/
00076 /*@access pgpDigParams @*/
00077 
00078 /*@unchecked@*/
00079 int _rpmts_debug = 0;
00080 
00081 /*@unchecked@*/
00082 int _rpmts_stats = 0;
00083 
00084 /*@unchecked@*/
00085 int _rpmts_macros = 0;
00086 
00087 rpmts XrpmtsUnlink(rpmts ts, const char * msg, const char * fn, unsigned ln)
00088 {
00089 /*@-modfilesys@*/
00090 if (_rpmts_debug)
00091 fprintf(stderr, "--> ts %p -- %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
00092 /*@=modfilesys@*/
00093     ts->nrefs--;
00094     return NULL;
00095 }
00096 
00097 rpmts XrpmtsLink(rpmts ts, const char * msg, const char * fn, unsigned ln)
00098 {
00099     ts->nrefs++;
00100 /*@-modfilesys@*/
00101 if (_rpmts_debug)
00102 fprintf(stderr, "--> ts %p ++ %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
00103 /*@=modfilesys@*/
00104     /*@-refcounttrans@*/ return ts; /*@=refcounttrans@*/
00105 }
00106 
00107 int rpmtsCloseDB(rpmts ts)
00108 {
00109     int rc = 0;
00110 
00111     if (ts->rdb != NULL) {
00112         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->rdb->db_getops);
00113         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->rdb->db_putops);
00114         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->rdb->db_delops);
00115         rc = rpmdbClose(ts->rdb);
00116         ts->rdb = NULL;
00117     }
00118     return rc;
00119 }
00120 
00121 int rpmtsOpenDB(rpmts ts, int dbmode)
00122 {
00123     int rc = 0;
00124 
00125     if (ts->rdb != NULL && ts->dbmode == dbmode)
00126         return 0;
00127 
00128     (void) rpmtsCloseDB(ts);
00129 
00130     /* XXX there's a db lock race here that is the callers responsibility. */
00131 
00132     ts->dbmode = dbmode;
00133     rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
00134     if (rc) {
00135         const char * dn;
00136         dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00137         rpmlog(RPMLOG_ERR,
00138                         _("cannot open Packages database in %s\n"), dn);
00139         dn = _free(dn);
00140     }
00141     return rc;
00142 }
00143 
00144 int rpmtsInitDB(rpmts ts, int dbmode)
00145 {
00146 #if defined(SUPPORT_INITDB)
00147     void *lock = rpmtsAcquireLock(ts);
00148     int rc = rpmdbInit(ts->rootDir, dbmode);
00149     lock = rpmtsFreeLock(lock);
00150     return rc;
00151 #else
00152     return -1;
00153 #endif
00154 }
00155 
00156 int rpmtsRebuildDB(rpmts ts)
00157 {
00158     void * lock = rpmtsAcquireLock(ts);
00159     int rc = rpmtsOpenDB(ts, ts->dbmode);
00160 
00161     if (rc == 0)
00162         rc = rpmdbRebuild(ts->rootDir,
00163                 (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK) ? ts : NULL));
00164     lock = rpmtsFreeLock(lock);
00165     return rc;
00166 }
00167 
00168 int rpmtsVerifyDB(rpmts ts)
00169 {
00170 #if defined(SUPPORT_VERIFYDB)
00171     return rpmdbVerify(ts->rootDir);
00172 #else
00173     return -1;
00174 #endif
00175 }
00176 
00177 /*@-compdef@*/ /* keyp might not be defined. */
00178 rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
00179                         const void * keyp, size_t keylen)
00180 {
00181     rpmdbMatchIterator mi;
00182     const char * arch = NULL;
00183     int xx;
00184 
00185     if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
00186         return NULL;
00187 
00188     /* Parse out "N(EVR).A" tokens from a label key. */
00189     if (rpmtag == RPMDBI_LABEL && keyp != NULL) {
00190         const char * s = keyp;
00191         const char *se;
00192         size_t slen = strlen(s);
00193         char *t = alloca(slen+1);
00194         int level = 0;
00195         int c;
00196 
00197         keyp = t;
00198         while ((c = *s++) != '\0') {
00199             switch (c) {
00200             default:
00201                 *t++ = c;
00202                 /*@switchbreak@*/ break;
00203             case '(':
00204                 /* XXX Fail if nested parens. */
00205                 if (level++ != 0) {
00206                     rpmlog(RPMLOG_ERR, _("extra '(' in package label: %s\n"), keyp);
00207                     return NULL;
00208                 }
00209                 /* Parse explicit epoch. */
00210                 for (se = s; *se && xisdigit(*se); se++)
00211                     {};
00212                 if (*se == ':') {
00213                     /* XXX skip explicit epoch's (for now) */
00214                     *t++ = '-';
00215                     s = se + 1;
00216                 } else {
00217                     /* No Epoch: found. Convert '(' to '-' and chug. */
00218                     *t++ = '-';
00219                 }
00220                 /*@switchbreak@*/ break;
00221             case ')':
00222                 /* XXX Fail if nested parens. */
00223                 if (--level != 0) {
00224                     rpmlog(RPMLOG_ERR, _("missing '(' in package label: %s\n"), keyp);
00225                     return NULL;
00226                 }
00227                 /* Don't copy trailing ')' */
00228                 /*@switchbreak@*/ break;
00229             }
00230         }
00231         if (level) {
00232             rpmlog(RPMLOG_ERR, _("missing ')' in package label: %s\n"), keyp);
00233             return NULL;
00234         }
00235         *t = '\0';
00236         t = (char *) keyp;
00237         t = strrchr(t, '.');
00238         /* Is this a valid ".arch" suffix? */
00239         if (t != NULL && rpmnsArch(t+1)) {
00240            *t++ = '\0';
00241            arch = t;
00242         }
00243     }
00244 
00245     mi = rpmdbInitIterator(ts->rdb, rpmtag, keyp, keylen);
00246 
00247     /* Verify header signature/digest during retrieve (if not disabled). */
00248     if (mi && !(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
00249         (void) rpmdbSetHdrChk(mi, ts);
00250 
00251     /* Select specified arch only. */
00252     if (arch != NULL)
00253         xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT, arch);
00254     return mi;
00255 }
00256 /*@=compdef@*/
00257 
00258 rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, ssize_t pktlen)
00259 {
00260     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00261     static unsigned char zeros[] =
00262         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00263     const char * afmt = "%{pubkeys:armor}";
00264     const char * group = "Public Keys";
00265     const char * license = "pubkey";
00266     const char * buildhost = "localhost";
00267     uint32_t pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
00268     uint32_t zero = 0;
00269     pgpDig dig = NULL;
00270     pgpDigParams pubp = NULL;
00271     const char * d = NULL;
00272     const char * enc = NULL;
00273     const char * n = NULL;
00274     const char * u = NULL;
00275     const char * v = NULL;
00276     const char * r = NULL;
00277     const char * evr = NULL;
00278     Header h = NULL;
00279     rpmRC rc = RPMRC_FAIL;              /* assume failure */
00280     char * t;
00281     int xx;
00282 
00283     if (pkt == NULL || pktlen <= 0)
00284         return RPMRC_FAIL;
00285     if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
00286         return RPMRC_FAIL;
00287 
00288 /*@-moduncon@*/
00289     if ((enc = b64encode(pkt, pktlen)) == NULL)
00290         goto exit;
00291 /*@=moduncon@*/
00292 
00293     dig = pgpDigNew(0);
00294 
00295     /* Build header elements. */
00296     (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00297     pubp = pgpGetPubkey(dig);
00298 
00299     if (!memcmp(pubp->signid, zeros, sizeof(pubp->signid))
00300      || !memcmp(pubp->time, zeros, sizeof(pubp->time))
00301      || pubp->userid == NULL)
00302         goto exit;
00303 
00304     v = t = xmalloc(16+1);
00305     t = stpcpy(t, pgpHexStr(pubp->signid, sizeof(pubp->signid)));
00306 
00307     r = t = xmalloc(8+1);
00308     t = stpcpy(t, pgpHexStr(pubp->time, sizeof(pubp->time)));
00309 
00310     n = t = xmalloc(sizeof("gpg()")+8);
00311     t = stpcpy( stpcpy( stpcpy(t, "gpg("), v+8), ")");
00312 
00313     /*@-nullpass@*/ /* FIX: pubp->userid may be NULL */
00314     u = t = xmalloc(sizeof("gpg()")+strlen(pubp->userid));
00315     t = stpcpy( stpcpy( stpcpy(t, "gpg("), pubp->userid), ")");
00316     /*@=nullpass@*/
00317 
00318     evr = t = xmalloc(sizeof("4X:-")+strlen(v)+strlen(r));
00319     t = stpcpy(t, (pubp->version == 4 ? "4:" : "3:"));
00320     t = stpcpy( stpcpy( stpcpy(t, v), "-"), r);
00321 
00322     /* Check for pre-existing header. */
00323 
00324     /* Build pubkey header. */
00325     h = headerNew();
00326 
00327     he->append = 1;
00328 
00329     he->tag = RPMTAG_PUBKEYS;
00330     he->t = RPM_STRING_ARRAY_TYPE;
00331     he->p.argv = &enc;
00332     he->c = 1;
00333     xx = headerPut(h, he, 0);
00334 
00335     he->append = 0;
00336 
00337     d = headerSprintf(h, afmt, NULL, rpmHeaderFormats, NULL);
00338     if (d == NULL)
00339         goto exit;
00340 
00341     he->t = RPM_STRING_TYPE;
00342     he->c = 1;
00343     he->tag = RPMTAG_NAME;
00344     he->p.str = "gpg-pubkey";
00345     xx = headerPut(h, he, 0);
00346     he->tag = RPMTAG_VERSION;
00347     he->p.str = v+8;
00348     xx = headerPut(h, he, 0);
00349     he->tag = RPMTAG_RELEASE;
00350     he->p.str = r;
00351     xx = headerPut(h, he, 0);
00352 
00353     /* Add Summary/Description/Group. */
00354     he->tag = RPMTAG_DESCRIPTION;
00355     he->p.str = d;
00356 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00357     xx = headerAddI18NString(h, he->tag, he->p.ptr, "C");
00358 #else
00359     xx = headerPut(h, he, 0);
00360 #endif
00361     he->tag = RPMTAG_GROUP;
00362     he->p.str = group;
00363 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00364     xx = headerAddI18NString(h, he->tag, he->p.ptr, "C");
00365 #else
00366     xx = headerPut(h, he, 0);
00367 #endif
00368     he->tag = RPMTAG_SUMMARY;
00369     he->p.str = u;
00370 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00371     xx = headerAddI18NString(h, he->tag, he->p.ptr, "C");
00372 #else
00373     xx = headerPut(h, he, 0);
00374 #endif
00375 
00376 #ifdef  NOTYET  /* XXX can't erase pubkeys with "pubkey" arch. */
00377     /* Add a "pubkey" arch/os to avoid missing value NULL ptrs. */
00378     he->tag = RPMTAG_ARCH;
00379     he->p.str = "pubkey";
00380     xx = headerPut(h, he, 0);
00381     he->tag = RPMTAG_OS;
00382     he->p.str = "pubkey";
00383     xx = headerPut(h, he, 0);
00384 #endif
00385 
00386     he->tag = RPMTAG_LICENSE;
00387     he->p.str = license;
00388     xx = headerPut(h, he, 0);
00389 
00390     he->tag = RPMTAG_SIZE;
00391     he->t = RPM_UINT32_TYPE;
00392     he->p.ui32p = &zero;
00393     he->c = 1;
00394     xx = headerPut(h, he, 0);
00395 
00396     he->append = 1;
00397 
00398     he->tag = RPMTAG_PROVIDENAME;
00399     he->t = RPM_STRING_ARRAY_TYPE;
00400     he->p.argv = &u;
00401     he->c = 1;
00402     xx = headerPut(h, he, 0);
00403     he->tag = RPMTAG_PROVIDEVERSION;
00404     he->t = RPM_STRING_ARRAY_TYPE;
00405     he->p.argv = &evr;
00406     he->c = 1;
00407     xx = headerPut(h, he, 0);
00408     he->tag = RPMTAG_PROVIDEFLAGS;
00409     he->t = RPM_UINT32_TYPE;
00410     he->p.ui32p = &pflags;
00411     he->c = 1;
00412     xx = headerPut(h, he, 0);
00413 
00414     he->tag = RPMTAG_PROVIDENAME;
00415     he->t = RPM_STRING_ARRAY_TYPE;
00416     he->p.argv = &n;
00417     he->c = 1;
00418     xx = headerPut(h, he, 0);
00419     he->tag = RPMTAG_PROVIDEVERSION;
00420     he->t = RPM_STRING_ARRAY_TYPE;
00421     he->p.argv = &evr;
00422     he->c = 1;
00423     xx = headerPut(h, he, 0);
00424     he->tag = RPMTAG_PROVIDEFLAGS;
00425     he->t = RPM_UINT32_TYPE;
00426     he->p.ui32p = &pflags;
00427     he->c = 1;
00428     xx = headerPut(h, he, 0);
00429 
00430     he->append = 0;
00431 
00432     he->tag = RPMTAG_RPMVERSION;
00433     he->t = RPM_STRING_TYPE;
00434     he->p.str = RPMVERSION;
00435     he->c = 1;
00436     xx = headerPut(h, he, 0);
00437 
00438     /* XXX W2DO: tag value inheirited from parent? */
00439     he->tag = RPMTAG_BUILDHOST;
00440     he->t = RPM_STRING_TYPE;
00441     he->p.str = buildhost;
00442     he->c = 1;
00443     xx = headerPut(h, he, 0);
00444     {   uint32_t tid = rpmtsGetTid(ts);
00445         he->tag = RPMTAG_INSTALLTIME;
00446         he->t = RPM_UINT32_TYPE;
00447         he->p.ui32p = &tid;
00448         he->c = 1;
00449         xx = headerPut(h, he, 0);
00450         /* XXX W2DO: tag value inheirited from parent? */
00451         he->tag = RPMTAG_BUILDTIME;
00452         he->t = RPM_UINT32_TYPE;
00453         he->p.ui32p = &tid;
00454         he->c = 1;
00455         xx = headerPut(h, he, 0);
00456     }
00457 
00458 #ifdef  NOTYET
00459     /* XXX W2DO: tag value inheirited from parent? */
00460     he->tag = RPMTAG_SOURCERPM;
00461     he->t = RPM_STRING_TYPE;
00462     he->p.str = fn;
00463     he->c = 1;
00464     xx = headerPut(h, he, 0);
00465 #endif
00466 
00467     /* Add header to database. */
00468     xx = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL);
00469     if (xx != 0)
00470         goto exit;
00471     rc = RPMRC_OK;
00472 
00473 exit:
00474     /* Clean up. */
00475     h = headerFree(h);
00476     dig = pgpDigFree(dig);
00477     n = _free(n);
00478     u = _free(u);
00479     v = _free(v);
00480     r = _free(r);
00481     evr = _free(evr);
00482     enc = _free(enc);
00483     d = _free(d);
00484     
00485     return rc;
00486 }
00487 
00488 int rpmtsCloseSDB(rpmts ts)
00489 {
00490     int rc = 0;
00491 
00492     if (ts->sdb != NULL) {
00493         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET), &ts->sdb->db_getops);
00494         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT), &ts->sdb->db_putops);
00495         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL), &ts->sdb->db_delops);
00496         rc = rpmdbClose(ts->sdb);
00497         ts->sdb = NULL;
00498     }
00499     return rc;
00500 }
00501 
00502 int rpmtsOpenSDB(rpmts ts, int dbmode)
00503 {
00504     static int has_sdbpath = -1;
00505     int rc = 0;
00506 
00507     if (ts->sdb != NULL && ts->sdbmode == dbmode)
00508         return 0;
00509 
00510     if (has_sdbpath < 0)
00511         has_sdbpath = rpmExpandNumeric("%{?_solve_dbpath:1}");
00512 
00513     /* If not configured, don't try to open. */
00514     if (has_sdbpath <= 0)
00515         return 1;
00516 
00517     addMacro(NULL, "_dbpath", NULL, "%{_solve_dbpath}", RMIL_DEFAULT);
00518 
00519     rc = rpmdbOpen(ts->rootDir, &ts->sdb, ts->sdbmode, 0644);
00520     if (rc) {
00521         const char * dn;
00522         dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00523         rpmlog(RPMLOG_WARNING,
00524                         _("cannot open Solve database in %s\n"), dn);
00525         dn = _free(dn);
00526         /* XXX only try to open the solvedb once. */
00527         has_sdbpath = 0;
00528     }
00529     delMacro(NULL, "_dbpath");
00530 
00531     return rc;
00532 }
00533 
00540 static int sugcmp(const void * a, const void * b)
00541         /*@*/
00542 {
00543     const char * astr = *(const char **)a;
00544     const char * bstr = *(const char **)b;
00545     return strcmp(astr, bstr);
00546 }
00547 
00548 int rpmtsSolve(rpmts ts, rpmds ds, /*@unused@*/ const void * data)
00549 {
00550     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00551     const char * errstr;
00552     const char * str = NULL;
00553     const char * qfmt;
00554     rpmdbMatchIterator mi;
00555     Header bh = NULL;
00556     Header h = NULL;
00557     size_t bhnamelen = 0;
00558     time_t bhtime = 0;
00559     rpmTag rpmtag;
00560     const char * keyp;
00561     size_t keylen = 0;
00562     int rc = 1; /* assume not found */
00563     int xx;
00564 
00565     /* Make suggestions only for installing Requires: */
00566     if (ts->goal != TSM_INSTALL)
00567         return rc;
00568 
00569     switch (rpmdsTagN(ds)) {
00570     case RPMTAG_CONFLICTNAME:
00571     default:
00572         return rc;
00573         /*@notreached@*/ break;
00574     case RPMTAG_DIRNAMES:       /* XXX perhaps too many wrong answers */
00575     case RPMTAG_REQUIRENAME:
00576     case RPMTAG_FILELINKTOS:
00577         break;
00578     }
00579 
00580     keyp = rpmdsN(ds);
00581     if (keyp == NULL)
00582         return rc;
00583 
00584     if (ts->sdb == NULL) {
00585         xx = rpmtsOpenSDB(ts, ts->sdbmode);
00586         if (xx) return rc;
00587     }
00588 
00589     /* Look for a matching Provides: in suggested universe. */
00590     rpmtag = (*keyp == '/' ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME);
00591     mi = rpmdbInitIterator(ts->sdb, rpmtag, keyp, keylen);
00592     while ((h = rpmdbNextIterator(mi)) != NULL) {
00593         size_t hnamelen;
00594         time_t htime;
00595 
00596         if (rpmtag == RPMTAG_PROVIDENAME && !rpmdsAnyMatchesDep(h, ds, 1))
00597             continue;
00598 
00599         he->tag = RPMTAG_NAME;
00600         xx = headerGet(h, he, 0);
00601         hnamelen = ((xx && he->p.str) ? strlen(he->p.str) : 0);
00602         he->p.ptr = _free(he->p.ptr);
00603 
00604         /* XXX Prefer the shortest pkg N for basenames/provides resp. */
00605         if (bhnamelen > 0 && hnamelen > bhnamelen)
00606             continue;
00607 
00608         /* XXX Prefer the newest build if given alternatives. */
00609         he->tag = RPMTAG_BUILDTIME;
00610         xx = headerGet(h, he, 0);
00611         htime = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
00612         he->p.ptr = _free(he->p.ptr);
00613 
00614         if (htime <= bhtime)
00615             continue;
00616 
00617         /* Save new "best" candidate. */
00618         bh = headerFree(bh);
00619         bh = headerLink(h);
00620         bhtime = htime;
00621         bhnamelen = hnamelen;
00622     }
00623     mi = rpmdbFreeIterator(mi);
00624 
00625     /* Is there a suggested resolution? */
00626     if (bh == NULL)
00627         goto exit;
00628 
00629     /* Format the suggested resolution path. */
00630     qfmt = rpmExpand("%{?_solve_name_fmt}", NULL);
00631     if (qfmt == NULL || *qfmt == '\0')
00632         goto exit;
00633     str = headerSprintf(bh, qfmt, NULL, rpmHeaderFormats, &errstr);
00634     bh = headerFree(bh);
00635     qfmt = _free(qfmt);
00636     if (str == NULL) {
00637         rpmlog(RPMLOG_ERR, _("incorrect solve path format: %s\n"), errstr);
00638         goto exit;
00639     }
00640 
00641     if (ts->depFlags & RPMDEPS_FLAG_ADDINDEPS) {
00642         FD_t fd;
00643         rpmRC rpmrc;
00644 
00645         fd = Fopen(str, "r.fdio");
00646         if (fd == NULL || Ferror(fd)) {
00647             rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), str,
00648                         Fstrerror(fd));
00649             if (fd != NULL) {
00650                 xx = Fclose(fd);
00651                 fd = NULL;
00652             }
00653             str = _free(str);
00654             goto exit;
00655         }
00656         rpmrc = rpmReadPackageFile(ts, fd, str, &h);
00657         xx = Fclose(fd);
00658         switch (rpmrc) {
00659         default:
00660             break;
00661         case RPMRC_NOTTRUSTED:
00662         case RPMRC_NOKEY:
00663         case RPMRC_OK:
00664             if (h != NULL &&
00665                 !rpmtsAddInstallElement(ts, h, (fnpyKey)str, 1, NULL))
00666             {
00667                 rpmlog(RPMLOG_DEBUG, D_("Adding: %s\n"), str);
00668                 rc = -1;        /* XXX restart unsatisfiedDepends() */
00669                 break;
00670             }
00671             break;
00672         }
00673         str = _free(str);
00674         h = headerFree(h);
00675         goto exit;
00676     }
00677 
00678     rpmlog(RPMLOG_DEBUG, D_("Suggesting: %s\n"), str);
00679     /* If suggestion is already present, don't bother. */
00680     if (ts->suggests != NULL && ts->nsuggests > 0) {
00681         if (bsearch(&str, ts->suggests, ts->nsuggests,
00682                         sizeof(*ts->suggests), sugcmp))
00683         {
00684             str = _free(str);
00685             goto exit;
00686         }
00687     }
00688 
00689     /* Add a new (unique) suggestion. */
00690     ts->suggests = xrealloc(ts->suggests,
00691                         sizeof(*ts->suggests) * (ts->nsuggests + 2));
00692     ts->suggests[ts->nsuggests] = str;
00693     ts->nsuggests++;
00694     ts->suggests[ts->nsuggests] = NULL;
00695 
00696     if (ts->nsuggests > 1)
00697         qsort(ts->suggests, ts->nsuggests, sizeof(*ts->suggests), sugcmp);
00698 
00699 exit:
00700 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
00701     return rc;
00702 /*@=nullstate@*/
00703 }
00704 
00705 int rpmtsAvailable(rpmts ts, const rpmds ds)
00706 {
00707     fnpyKey * sugkey;
00708     int rc = 1; /* assume not found */
00709 
00710     if (ts->availablePackages == NULL)
00711         return rc;
00712     sugkey = rpmalAllSatisfiesDepend(ts->availablePackages, ds, NULL);
00713     if (sugkey == NULL)
00714         return rc;
00715 
00716     /* XXX no alternatives yet */
00717     if (sugkey[0] != NULL) {
00718         ts->suggests = xrealloc(ts->suggests,
00719                         sizeof(*ts->suggests) * (ts->nsuggests + 2));
00720         ts->suggests[ts->nsuggests] = sugkey[0];
00721         sugkey[0] = NULL;
00722         ts->nsuggests++;
00723         ts->suggests[ts->nsuggests] = NULL;
00724     }
00725     sugkey = _free(sugkey);
00726 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
00727     return rc;
00728 /*@=nullstate@*/
00729 }
00730 
00731 int rpmtsSetSolveCallback(rpmts ts,
00732                 int (*solve) (rpmts ts, rpmds key, const void * data),
00733                 const void * solveData)
00734 {
00735     int rc = 0;
00736 
00737     if (ts) {
00738 /*@-assignexpose -temptrans @*/
00739         ts->solve = solve;
00740         ts->solveData = solveData;
00741 /*@=assignexpose =temptrans @*/
00742     }
00743     return rc;
00744 }
00745 
00746 rpmps rpmtsProblems(rpmts ts)
00747 {
00748     rpmps ps = NULL;
00749     if (ts) {
00750         if (ts->probs)
00751             ps = rpmpsLink(ts->probs, "rpmtsProblems");
00752     }
00753     return ps;
00754 }
00755 
00756 void rpmtsClean(rpmts ts)
00757 {
00758     rpmtsi pi; rpmte p;
00759 
00760     if (ts == NULL)
00761         return;
00762 
00763     /* Clean up after dependency checks. */
00764     pi = rpmtsiInit(ts);
00765     while ((p = rpmtsiNext(pi, 0)) != NULL)
00766         rpmteCleanDS(p);
00767     pi = rpmtsiFree(pi);
00768 
00769     ts->addedPackages = rpmalFree(ts->addedPackages);
00770     ts->numAddedPackages = 0;
00771 
00772     ts->erasedPackages = rpmalFree(ts->erasedPackages);
00773     ts->numErasedPackages = 0;
00774 
00775     ts->suggests = _free(ts->suggests);
00776     ts->nsuggests = 0;
00777 
00778     ts->probs = rpmpsFree(ts->probs);
00779 
00780     rpmtsCleanDig(ts);
00781 }
00782 
00783 void rpmtsEmpty(rpmts ts)
00784 {
00785     rpmtsi pi; rpmte p;
00786     int oc;
00787 
00788     if (ts == NULL)
00789         return;
00790 
00791 /*@-nullstate@*/        /* FIX: partial annotations */
00792     rpmtsClean(ts);
00793 /*@=nullstate@*/
00794 
00795     for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
00796 /*@-type -unqualifiedtrans @*/
00797         ts->order[oc] = rpmteFree(ts->order[oc]);
00798 /*@=type =unqualifiedtrans @*/
00799     }
00800     pi = rpmtsiFree(pi);
00801 
00802     ts->orderCount = 0;
00803     ts->ntrees = 0;
00804     ts->maxDepth = 0;
00805 
00806     ts->numRemovedPackages = 0;
00807 /*@-nullstate@*/        /* FIX: partial annotations */
00808     return;
00809 /*@=nullstate@*/
00810 }
00811 
00812 static void rpmtsPrintStat(const char * name, /*@null@*/ struct rpmop_s * op)
00813         /*@globals fileSystem @*/
00814         /*@modifies fileSystem @*/
00815 {
00816     static unsigned int scale = (1000 * 1000);
00817     if (op != NULL && op->count > 0)
00818         fprintf(stderr, "   %s %8d %6lu.%06lu MB %6lu.%06lu secs\n",
00819                 name, op->count,
00820                 (unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
00821                 op->usecs/scale, op->usecs%scale);
00822 }
00823 
00824 /*@unchecked@*/ /*@relnull@*/
00825 extern rpmop _hdr_loadops;
00826 /*@unchecked@*/ /*@relnull@*/
00827 extern rpmop _hdr_getops;
00828 
00829 static void rpmtsPrintStats(rpmts ts)
00830         /*@globals fileSystem, internalState @*/
00831         /*@modifies fileSystem, internalState @*/
00832 {
00833     (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
00834 
00835     if (_hdr_loadops)
00836         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_HDRLOAD), _hdr_loadops);
00837     if (_hdr_getops)
00838         (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_HDRGET), _hdr_getops);
00839 
00840     rpmtsPrintStat("total:       ", rpmtsOp(ts, RPMTS_OP_TOTAL));
00841     rpmtsPrintStat("check:       ", rpmtsOp(ts, RPMTS_OP_CHECK));
00842     rpmtsPrintStat("order:       ", rpmtsOp(ts, RPMTS_OP_ORDER));
00843     rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
00844     rpmtsPrintStat("repackage:   ", rpmtsOp(ts, RPMTS_OP_REPACKAGE));
00845     rpmtsPrintStat("install:     ", rpmtsOp(ts, RPMTS_OP_INSTALL));
00846     rpmtsPrintStat("erase:       ", rpmtsOp(ts, RPMTS_OP_ERASE));
00847     rpmtsPrintStat("scriptlets:  ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
00848     rpmtsPrintStat("compress:    ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
00849     rpmtsPrintStat("uncompress:  ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
00850     rpmtsPrintStat("digest:      ", rpmtsOp(ts, RPMTS_OP_DIGEST));
00851     rpmtsPrintStat("signature:   ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
00852     rpmtsPrintStat("dbadd:       ", rpmtsOp(ts, RPMTS_OP_DBADD));
00853     rpmtsPrintStat("dbremove:    ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
00854     rpmtsPrintStat("dbget:       ", rpmtsOp(ts, RPMTS_OP_DBGET));
00855     rpmtsPrintStat("dbput:       ", rpmtsOp(ts, RPMTS_OP_DBPUT));
00856     rpmtsPrintStat("dbdel:       ", rpmtsOp(ts, RPMTS_OP_DBDEL));
00857     rpmtsPrintStat("readhdr:     ", rpmtsOp(ts, RPMTS_OP_READHDR));
00858     rpmtsPrintStat("hdrload:     ", rpmtsOp(ts, RPMTS_OP_HDRLOAD));
00859     rpmtsPrintStat("hdrget:      ", rpmtsOp(ts, RPMTS_OP_HDRGET));
00860 /*@-globstate@*/
00861     return;
00862 /*@=globstate@*/
00863 }
00864 
00865 rpmts rpmtsFree(rpmts ts)
00866 {
00867     if (ts == NULL)
00868         return NULL;
00869 
00870     if (ts->nrefs > 1)
00871         return rpmtsUnlink(ts, "tsCreate");
00872 
00873 /*@-nullstate@*/        /* FIX: partial annotations */
00874     rpmtsEmpty(ts);
00875 /*@=nullstate@*/
00876 
00877     ts->PRCO = rpmdsFreePRCO(ts->PRCO);
00878 
00879     (void) rpmtsCloseDB(ts);
00880 
00881     (void) rpmtsCloseSDB(ts);
00882 
00883     ts->sx = rpmsxFree(ts->sx);
00884 
00885     ts->removedPackages = _free(ts->removedPackages);
00886 
00887     ts->availablePackages = rpmalFree(ts->availablePackages);
00888     ts->numAvailablePackages = 0;
00889 
00890     ts->dsi = _free(ts->dsi);
00891 
00892     if (ts->scriptFd != NULL) {
00893         ts->scriptFd = fdFree(ts->scriptFd, "rpmtsFree");
00894         ts->scriptFd = NULL;
00895     }
00896     ts->rootDir = _free(ts->rootDir);
00897     ts->currDir = _free(ts->currDir);
00898 
00899 /*@-type +voidabstract @*/      /* FIX: double indirection */
00900     ts->order = _free(ts->order);
00901 /*@=type =voidabstract @*/
00902     ts->orderAlloced = 0;
00903 
00904     ts->pkpkt = _free(ts->pkpkt);
00905     ts->pkpktlen = 0;
00906     memset(ts->pksignid, 0, sizeof(ts->pksignid));
00907 
00908     if (_rpmts_stats)
00909         rpmtsPrintStats(ts);
00910 
00911     if (_rpmts_macros) {
00912         const char ** av = NULL;
00913         (void)rpmGetMacroEntries(NULL, NULL, 1, &av);
00914         argvPrint("macros used", av, NULL);
00915         av = argvFree(av);
00916     }
00917 
00918     (void) rpmtsUnlink(ts, "tsCreate");
00919 
00920     /*@-refcounttrans -usereleased @*/
00921     ts = _free(ts);
00922     /*@=refcounttrans =usereleased @*/
00923 
00924     return NULL;
00925 }
00926 
00927 rpmVSFlags rpmtsVSFlags(/*@unused@*/rpmts ts)
00928 {
00929     return pgpDigVSFlags;
00930 }
00931 
00932 rpmVSFlags rpmtsSetVSFlags(/*@unused@*/rpmts ts, rpmVSFlags vsflags)
00933 {
00934     rpmVSFlags ovsflags;
00935     ovsflags = pgpDigVSFlags;
00936     pgpDigVSFlags = vsflags;
00937     return ovsflags;
00938 }
00939 
00940 /*
00941  * This allows us to mark transactions as being of a certain type.
00942  * The three types are:
00943  *
00944  *     RPM_TRANS_NORMAL         
00945  *     RPM_TRANS_ROLLBACK
00946  *     RPM_TRANS_AUTOROLLBACK
00947  *
00948  * ROLLBACK and AUTOROLLBACK transactions should always be ran as
00949  * a best effort.  In particular this is important to the autorollback
00950  * feature to avoid rolling back a rollback (otherwise known as
00951  * dueling rollbacks (-;).  AUTOROLLBACK's additionally need instance
00952  * counts passed to scriptlets to be altered.
00953  */
00954 /* Let them know what type of transaction we are */
00955 rpmTSType rpmtsType(rpmts ts)
00956 {
00957     return ((ts != NULL) ? ts->type : 0);
00958 }
00959 
00960 void rpmtsSetType(rpmts ts, rpmTSType type)
00961 {
00962     if (ts != NULL)
00963         ts->type = type;
00964 }
00965 
00966 uint32_t rpmtsARBGoal(rpmts ts)
00967 {
00968     return ((ts != NULL) ?  ts->arbgoal : 0);
00969 }
00970 
00971 void rpmtsSetARBGoal(rpmts ts, uint32_t goal)
00972 {
00973     if (ts != NULL)
00974         ts->arbgoal = goal;
00975 }
00976 
00977 int rpmtsUnorderedSuccessors(rpmts ts, int first)
00978 {
00979     int unorderedSuccessors = 0;
00980     if (ts != NULL) {
00981         unorderedSuccessors = ts->unorderedSuccessors;
00982         if (first >= 0)
00983             ts->unorderedSuccessors = first;
00984     }
00985     return unorderedSuccessors;
00986 }
00987 
00988 const char * rpmtsRootDir(rpmts ts)
00989 {
00990     const char * rootDir = NULL;
00991 
00992     if (ts != NULL && ts->rootDir != NULL) {
00993         urltype ut = urlPath(ts->rootDir, &rootDir);
00994         switch (ut) {
00995         case URL_IS_UNKNOWN:
00996         case URL_IS_PATH:
00997             break;
00998         case URL_IS_HTTPS:
00999         case URL_IS_HTTP:
01000         case URL_IS_HKP:
01001         case URL_IS_FTP:
01002         case URL_IS_DASH:
01003         default:
01004             rootDir = "/";
01005             break;
01006         }
01007     }
01008     return rootDir;
01009 }
01010 
01011 void rpmtsSetRootDir(rpmts ts, const char * rootDir)
01012 {
01013     if (ts != NULL) {
01014         size_t rootLen;
01015 
01016         ts->rootDir = _free(ts->rootDir);
01017 
01018         if (rootDir == NULL) {
01019 #ifndef DYING
01020             ts->rootDir = xstrdup("");
01021 #endif
01022             return;
01023         }
01024         rootLen = strlen(rootDir);
01025 
01026         /* Make sure that rootDir has trailing / */
01027         if (!(rootLen && rootDir[rootLen - 1] == '/')) {
01028             char * t = alloca(rootLen + 2);
01029             *t = '\0';
01030             (void) stpcpy( stpcpy(t, rootDir), "/");
01031             rootDir = t;
01032         }
01033         ts->rootDir = xstrdup(rootDir);
01034     }
01035 }
01036 
01037 const char * rpmtsCurrDir(rpmts ts)
01038 {
01039     const char * currDir = NULL;
01040     if (ts != NULL) {
01041         currDir = ts->currDir;
01042     }
01043     return currDir;
01044 }
01045 
01046 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
01047 {
01048     if (ts != NULL) {
01049         ts->currDir = _free(ts->currDir);
01050         if (currDir)
01051             ts->currDir = xstrdup(currDir);
01052     }
01053 }
01054 
01055 FD_t rpmtsScriptFd(rpmts ts)
01056 {
01057     FD_t scriptFd = NULL;
01058     if (ts != NULL) {
01059         scriptFd = ts->scriptFd;
01060     }
01061 /*@-compdef -refcounttrans -usereleased@*/
01062     return scriptFd;
01063 /*@=compdef =refcounttrans =usereleased@*/
01064 }
01065 
01066 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
01067 {
01068 
01069     if (ts != NULL) {
01070         if (ts->scriptFd != NULL) {
01071             ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd");
01072             ts->scriptFd = NULL;
01073         }
01074 /*@+voidabstract@*/
01075         if (scriptFd != NULL)
01076             ts->scriptFd = fdLink((void *)scriptFd, "rpmtsSetScriptFd");
01077 /*@=voidabstract@*/
01078     }
01079 }
01080 
01081 int rpmtsSELinuxEnabled(rpmts ts)
01082 {
01083     return (ts != NULL ? (ts->selinuxEnabled > 0) : 0);
01084 }
01085 
01086 int rpmtsChrootDone(rpmts ts)
01087 {
01088     return (ts != NULL ? ts->chrootDone : 0);
01089 }
01090 
01091 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
01092 {
01093     int ochrootDone = 0;
01094     if (ts != NULL) {
01095         ochrootDone = ts->chrootDone;
01096         if (ts->rdb != NULL)
01097             ts->rdb->db_chrootDone = chrootDone;
01098         ts->chrootDone = chrootDone;
01099     }
01100     return ochrootDone;
01101 }
01102 
01103 rpmsx rpmtsREContext(rpmts ts)
01104 {
01105     return ( (ts && ts->sx ? rpmsxLink(ts->sx, __func__) : NULL) );
01106 }
01107 
01108 int rpmtsSetREContext(rpmts ts, rpmsx sx)
01109 {
01110     int rc = -1;
01111     if (ts != NULL) {
01112         ts->sx = rpmsxFree(ts->sx);
01113         ts->sx = rpmsxLink(sx, __func__);
01114         if (ts->sx != NULL)
01115             rc = 0;
01116     }
01117     return rc;
01118 }
01119 
01120 uint32_t rpmtsGetTid(rpmts ts)
01121 {
01122     uint32_t tid = 0;   /* XXX -1 is time(2) error return. */
01123     if (ts != NULL) {
01124         tid = ts->tid;
01125     }
01126     return tid;
01127 }
01128 
01129 uint32_t rpmtsSetTid(rpmts ts, uint32_t tid)
01130 {
01131     uint32_t otid = 0;  /* XXX -1 is time(2) error return. */
01132     if (ts != NULL) {
01133         otid = ts->tid;
01134         ts->tid = tid;
01135     }
01136     return otid;
01137 }
01138 
01139 rpmPRCO rpmtsPRCO(rpmts ts)
01140 {
01141 /*@-compdef -retexpose -usereleased @*/
01142     return (ts != NULL ? ts->PRCO : NULL);
01143 /*@=compdef =retexpose =usereleased @*/
01144 }
01145 
01146 int rpmtsInitDSI(const rpmts ts)
01147 {
01148     rpmDiskSpaceInfo dsi;
01149     struct stat sb;
01150     int rc;
01151     int i;
01152 
01153     if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
01154         return 0;
01155     if (ts->filesystems != NULL)
01156         return 0;
01157 
01158     rpmlog(RPMLOG_DEBUG, D_("mounted filesystems:\n"));
01159     rpmlog(RPMLOG_DEBUG,
01160         D_("    i        dev    bsize       bavail       iavail mount point\n"));
01161 
01162     rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
01163     if (rc || ts->filesystems == NULL || ts->filesystemCount == 0)
01164         return rc;
01165 
01166     /* Get available space on mounted file systems. */
01167 
01168     ts->dsi = _free(ts->dsi);
01169     ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
01170 
01171     dsi = ts->dsi;
01172 
01173     if (dsi != NULL)
01174     for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
01175 #if STATFS_IN_SYS_STATVFS
01176         struct statvfs sfb;
01177         memset(&sfb, 0, sizeof(sfb));
01178         rc = statvfs(ts->filesystems[i], &sfb);
01179 #else
01180         struct statfs sfb;
01181         memset(&sfb, 0, sizeof(sfb));
01182 #  if STAT_STATFS4
01183 /* This platform has the 4-argument version of the statfs call.  The last two
01184  * should be the size of struct statfs and 0, respectively.  The 0 is the
01185  * filesystem type, and is always 0 when statfs is called on a mounted
01186  * filesystem, as we're doing.
01187  */
01188         rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
01189 #  else
01190         rc = statfs(ts->filesystems[i], &sfb);
01191 #  endif
01192 #endif
01193         if (rc)
01194             break;
01195 
01196         rc = stat(ts->filesystems[i], &sb);
01197         if (rc)
01198             break;
01199         dsi->dev = sb.st_dev;
01200 /* XXX figger out how to get this info for non-statvfs systems. */
01201 #if STATFS_IN_SYS_STATVFS
01202         dsi->f_frsize = sfb.f_frsize;
01203 #if defined(RPM_OS_AIX)
01204         dsi->f_fsid = 0; /* sfb.f_fsid is a structure on AIX */
01205 #else
01206         dsi->f_fsid = sfb.f_fsid;
01207 #endif
01208         dsi->f_flag = sfb.f_flag;
01209         dsi->f_favail = sfb.f_favail;
01210         dsi->f_namemax = sfb.f_namemax;
01211 #elif defined(__APPLE__) && defined(__MACH__) && !defined(_SYS_STATVFS_H_)
01212         dsi->f_fsid = 0; /* "Not meaningful in this implementation." */
01213         dsi->f_namemax = pathconf(ts->filesystems[i], _PC_NAME_MAX);
01214 #else
01215         dsi->f_fsid = sfb.f_fsid;
01216         dsi->f_namemax = sfb.f_namelen;
01217 #endif
01218 
01219         dsi->f_bsize = sfb.f_bsize;
01220         dsi->f_blocks = sfb.f_blocks;
01221         dsi->f_bfree = sfb.f_bfree;
01222         dsi->f_files = sfb.f_files;
01223         dsi->f_ffree = sfb.f_ffree;
01224 
01225         dsi->bneeded = 0;
01226         dsi->ineeded = 0;
01227 #ifdef STATFS_HAS_F_BAVAIL
01228         dsi->f_bavail = sfb.f_bavail ? sfb.f_bavail : 1;
01229         if (sfb.f_ffree > 0 && sfb.f_files > 0 && sfb.f_favail > 0)
01230             dsi->f_favail = sfb.f_favail;
01231         else    /* XXX who knows what evil lurks here? */
01232             dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
01233                                 ? sfb.f_ffree : -1;
01234 #else
01235 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are
01236  * available for non-superusers.  f_blocks - f_bfree is probably too big, but
01237  * it's about all we can do.
01238  */
01239         dsi->f_bavail = sfb.f_blocks - sfb.f_bfree;
01240         /* XXX Avoid FAT and other file systems that have not inodes. */
01241         dsi->f_favail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
01242                                 ? sfb.f_ffree : -1;
01243 #endif
01244 
01245 #if !defined(ST_RDONLY)
01246 #define ST_RDONLY       1
01247 #endif
01248         rpmlog(RPMLOG_DEBUG, "%5d 0x%08x %8u %12ld %12ld %s %s\n",
01249                 i, (unsigned) dsi->dev, (unsigned) dsi->f_bsize,
01250                 (signed long) dsi->f_bavail, (signed long) dsi->f_favail,
01251                 ((dsi->f_flag & ST_RDONLY) ? "ro" : "rw"),
01252                 ts->filesystems[i]);
01253     }
01254     return rc;
01255 }
01256 
01257 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
01258                 uint32_t fileSize, uint32_t prevSize, uint32_t fixupSize,
01259                 fileAction action)
01260 {
01261     rpmDiskSpaceInfo dsi;
01262     uint64_t bneeded;
01263 
01264     dsi = ts->dsi;
01265     if (dsi) {
01266         while (dsi->f_bsize && dsi->dev != dev)
01267             dsi++;
01268         if (dsi->f_bsize == 0)
01269             dsi = NULL;
01270     }
01271     if (dsi == NULL)
01272         return;
01273 
01274     bneeded = BLOCK_ROUND(fileSize, dsi->f_bsize);
01275 
01276     switch (action) {
01277     case FA_BACKUP:
01278     case FA_SAVE:
01279     case FA_ALTNAME:
01280         dsi->ineeded++;
01281         dsi->bneeded += bneeded;
01282         /*@switchbreak@*/ break;
01283 
01284     /*
01285      * FIXME: If two packages share a file (same md5sum), and
01286      * that file is being replaced on disk, will dsi->bneeded get
01287      * adjusted twice? Quite probably!
01288      */
01289     case FA_CREATE:
01290         dsi->bneeded += bneeded;
01291         dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->f_bsize);
01292         /*@switchbreak@*/ break;
01293 
01294     case FA_ERASE:
01295         dsi->ineeded--;
01296         dsi->bneeded -= bneeded;
01297         /*@switchbreak@*/ break;
01298 
01299     default:
01300         /*@switchbreak@*/ break;
01301     }
01302 
01303     if (fixupSize)
01304         dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->f_bsize);
01305 }
01306 
01307 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
01308 {
01309     rpmDiskSpaceInfo dsi;
01310     rpmps ps;
01311     int fc;
01312     int i;
01313 
01314     if (ts->filesystems == NULL || ts->filesystemCount == 0)
01315         return;
01316 
01317     dsi = ts->dsi;
01318     if (dsi == NULL)
01319         return;
01320     fc = rpmfiFC( rpmteFI(te, RPMTAG_BASENAMES) );
01321     if (fc <= 0)
01322         return;
01323 
01324     ps = rpmtsProblems(ts);
01325     for (i = 0; i < ts->filesystemCount; i++, dsi++) {
01326 
01327         if (dsi->f_bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->f_bavail) {
01328             rpmpsAppend(ps, RPMPROB_DISKSPACE,
01329                         rpmteNEVR(te), rpmteKey(te),
01330                         ts->filesystems[i], NULL, NULL,
01331            (adj_fs_blocks(dsi->bneeded) - dsi->f_bavail) * dsi->f_bsize);
01332         }
01333 
01334         if (dsi->f_favail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->f_favail) {
01335             rpmpsAppend(ps, RPMPROB_DISKNODES,
01336                         rpmteNEVR(te), rpmteKey(te),
01337                         ts->filesystems[i], NULL, NULL,
01338             (adj_fs_blocks(dsi->ineeded) - dsi->f_favail));
01339         }
01340 
01341         if ((dsi->bneeded || dsi->ineeded) && (dsi->f_flag & ST_RDONLY)) {
01342             rpmpsAppend(ps, RPMPROB_RDONLY,
01343                         rpmteNEVR(te), rpmteKey(te),
01344                         ts->filesystems[i], NULL, NULL, 0);
01345         }
01346     }
01347     ps = rpmpsFree(ps);
01348 }
01349 
01350 void * rpmtsNotify(rpmts ts, rpmte te,
01351                 rpmCallbackType what, uint64_t amount, uint64_t total)
01352 {
01353     void * ptr = NULL;
01354     if (ts && ts->notify && te) {
01355 assert(!(te->type == TR_ADDED && te->h == NULL));
01356         /*@-type@*/ /* FIX: cast? */
01357         /*@-noeffectuncon @*/ /* FIX: check rc */
01358         ptr = ts->notify(te->h, what, amount, total,
01359                         rpmteKey(te), ts->notifyData);
01360         /*@=noeffectuncon @*/
01361         /*@=type@*/
01362     }
01363     return ptr;
01364 }
01365 
01366 int rpmtsNElements(rpmts ts)
01367 {
01368     int nelements = 0;
01369     if (ts != NULL && ts->order != NULL) {
01370         nelements = ts->orderCount;
01371     }
01372     return nelements;
01373 }
01374 
01375 rpmte rpmtsElement(rpmts ts, int ix)
01376 {
01377     rpmte te = NULL;
01378     if (ts != NULL && ts->order != NULL) {
01379         if (ix >= 0 && ix < ts->orderCount)
01380             te = ts->order[ix];
01381     }
01382     /*@-compdef@*/
01383     return te;
01384     /*@=compdef@*/
01385 }
01386 
01387 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
01388 {
01389     return (ts != NULL ? ts->ignoreSet : 0);
01390 }
01391 
01392 rpmtransFlags rpmtsFlags(rpmts ts)
01393 {
01394     return (ts != NULL ? ts->transFlags : 0);
01395 }
01396 
01397 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
01398 {
01399     rpmtransFlags otransFlags = 0;
01400     if (ts != NULL) {
01401         otransFlags = ts->transFlags;
01402         ts->transFlags = transFlags;
01403     }
01404     return otransFlags;
01405 }
01406 
01407 rpmdepFlags rpmtsDFlags(rpmts ts)
01408 {
01409     return (ts != NULL ? ts->depFlags : 0);
01410 }
01411 
01412 rpmdepFlags rpmtsSetDFlags(rpmts ts, rpmdepFlags depFlags)
01413 {
01414     rpmdepFlags odepFlags = 0;
01415     if (ts != NULL) {
01416         odepFlags = ts->depFlags;
01417         ts->depFlags = depFlags;
01418     }
01419     return odepFlags;
01420 }
01421 
01422 Spec rpmtsSpec(rpmts ts)
01423 {
01424 /*@-compdef -retexpose -usereleased@*/
01425     return ts->spec;
01426 /*@=compdef =retexpose =usereleased@*/
01427 }
01428 
01429 Spec rpmtsSetSpec(rpmts ts, Spec spec)
01430 {
01431     Spec ospec = ts->spec;
01432 /*@-assignexpose -temptrans@*/
01433     ts->spec = spec;
01434 /*@=assignexpose =temptrans@*/
01435     return ospec;
01436 }
01437 
01438 rpmte rpmtsRelocateElement(rpmts ts)
01439 {
01440 /*@-compdef -retexpose -usereleased@*/
01441     return ts->relocateElement;
01442 /*@=compdef =retexpose =usereleased@*/
01443 }
01444 
01445 rpmte rpmtsSetRelocateElement(rpmts ts, rpmte relocateElement)
01446 {
01447     rpmte orelocateElement = ts->relocateElement;
01448 /*@-assignexpose -temptrans@*/
01449     ts->relocateElement = relocateElement;
01450 /*@=assignexpose =temptrans@*/
01451     return orelocateElement;
01452 }
01453 
01454 tsmStage rpmtsGoal(rpmts ts)
01455 {
01456     return (ts != NULL ? ts->goal : TSM_UNKNOWN);
01457 }
01458 
01459 tsmStage rpmtsSetGoal(rpmts ts, tsmStage goal)
01460 {
01461     tsmStage ogoal = TSM_UNKNOWN;
01462     if (ts != NULL) {
01463         ogoal = ts->goal;
01464         ts->goal = goal;
01465     }
01466     return ogoal;
01467 }
01468 
01469 int rpmtsDBMode(rpmts ts)
01470 {
01471     return (ts != NULL ? ts->dbmode : 0);
01472 }
01473 
01474 int rpmtsSetDBMode(rpmts ts, int dbmode)
01475 {
01476     int odbmode = 0;
01477     if (ts != NULL) {
01478         odbmode = ts->dbmode;
01479         ts->dbmode = dbmode;
01480     }
01481     return odbmode;
01482 }
01483 
01484 uint32_t rpmtsColor(rpmts ts)
01485 {
01486     return (ts != NULL ? ts->color : 0);
01487 }
01488 
01489 uint32_t rpmtsSetColor(rpmts ts, uint32_t color)
01490 {
01491     uint32_t ocolor = 0;
01492     if (ts != NULL) {
01493         ocolor = ts->color;
01494         ts->color = color;
01495     }
01496     return ocolor;
01497 }
01498 
01499 uint32_t rpmtsPrefColor(rpmts ts)
01500 {
01501     return (ts != NULL ? ts->prefcolor : 0);
01502 }
01503 
01504 int rpmtsSetNotifyCallback(rpmts ts,
01505                 rpmCallbackFunction notify, rpmCallbackData notifyData)
01506 {
01507     if (ts != NULL) {
01508         ts->notify = notify;
01509         ts->notifyData = notifyData;
01510     }
01511     return 0;
01512 }
01513 
01514 rpmts rpmtsCreate(void)
01515 {
01516     rpmts ts;
01517     int xx;
01518 
01519     ts = xcalloc(1, sizeof(*ts));
01520     memset(&ts->ops, 0, sizeof(ts->ops));
01521     (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
01522     ts->type = RPMTRANS_TYPE_NORMAL;
01523     ts->goal = TSM_UNKNOWN;
01524     ts->filesystemCount = 0;
01525     ts->filesystems = NULL;
01526     ts->dsi = NULL;
01527 
01528     ts->solve = rpmtsSolve;
01529     ts->solveData = NULL;
01530     ts->nsuggests = 0;
01531     ts->suggests = NULL;
01532 
01533     ts->PRCO = rpmdsNewPRCO(NULL);
01534     {   const char * fn = rpmGetPath("%{?_rpmds_sysinfo_path}", NULL);
01535         if (fn && *fn != '\0' && !rpmioAccess(fn, NULL, R_OK))
01536            xx = rpmdsSysinfo(ts->PRCO, NULL);
01537         fn = _free(fn);
01538     }
01539 
01540     ts->sdb = NULL;
01541     ts->sdbmode = O_RDONLY;
01542 
01543     ts->rdb = NULL;
01544     ts->dbmode = O_RDONLY;
01545 
01546     ts->scriptFd = NULL;
01547     ts->tid = (uint32_t) time(NULL);
01548     ts->delta = 5;
01549 
01550     ts->color = rpmExpandNumeric("%{?_transaction_color}");
01551     ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}");
01552     if (!ts->prefcolor) ts->prefcolor = 0x2;
01553 
01554     ts->numRemovedPackages = 0;
01555     ts->allocedRemovedPackages = ts->delta;
01556     ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
01557                         sizeof(*ts->removedPackages));
01558 
01559     ts->rootDir = NULL;
01560     ts->currDir = NULL;
01561     ts->chrootDone = 0;
01562 
01563     ts->selinuxEnabled = is_selinux_enabled();
01564 
01565     ts->numAddedPackages = 0;
01566     ts->addedPackages = NULL;
01567 
01568     ts->numErasedPackages = 0;
01569     ts->erasedPackages = NULL;
01570 
01571     ts->numAvailablePackages = 0;
01572     ts->availablePackages = NULL;
01573 
01574     ts->orderAlloced = 0;
01575     ts->orderCount = 0;
01576     ts->order = NULL;
01577     ts->ntrees = 0;
01578     ts->maxDepth = 0;
01579 
01580     ts->probs = NULL;
01581 
01582     ts->pkpkt = NULL;
01583     ts->pkpktlen = 0;
01584     memset(ts->pksignid, 0, sizeof(ts->pksignid));
01585     ts->dig = NULL;
01586 
01587     /* Set autorollback goal to the end of time. */
01588     ts->arbgoal = 0xffffffff;
01589 
01590     ts->nrefs = 0;
01591 
01592     return rpmtsLink(ts, "tsCreate");
01593 }

Generated on Mon Nov 29 2010 05:18:44 for rpm by  doxygen 1.7.2