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

Generated on Tue Aug 4 11:05:49 2009 for rpm by  doxygen 1.5.1