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

lib/rpmts.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include "rpmio_internal.h"     /* XXX for pgp and beecrypt */
00008 #include <rpmlib.h>
00009 #include <rpmmacro.h>           /* XXX rpmtsOpenDB() needs rpmGetPath */
00010 
00011 #include "rpmdb.h"              /* XXX stealing db->db_mode. */
00012 
00013 #include "rpmal.h"
00014 #include "rpmds.h"
00015 #include "rpmfi.h"
00016 
00017 #define _RPMTE_INTERNAL         /* XXX te->h */
00018 #include "rpmte.h"
00019 
00020 #define _RPMTS_INTERNAL
00021 #include "rpmts.h"
00022 
00023 /* XXX FIXME: merge with existing (broken?) tests in system.h */
00024 /* portability fiddles */
00025 #if STATFS_IN_SYS_STATVFS
00026 /*@-incondefs@*/
00027 #if defined(__LCLINT__)
00028 /*@-declundef -exportheader -protoparammatch @*/ /* LCL: missing annotation */
00029 extern int statvfs (const char * file, /*@out@*/ struct statvfs * buf)
00030         /*@globals fileSystem @*/
00031         /*@modifies *buf, fileSystem @*/;
00032 /*@=declundef =exportheader =protoparammatch @*/
00033 /*@=incondefs@*/
00034 #else
00035 # include <sys/statvfs.h>
00036 #endif
00037 #else
00038 # if STATFS_IN_SYS_VFS
00039 #  include <sys/vfs.h>
00040 # else
00041 #  if STATFS_IN_SYS_MOUNT
00042 #   include <sys/mount.h>
00043 #  else
00044 #   if STATFS_IN_SYS_STATFS
00045 #    include <sys/statfs.h>
00046 #   endif
00047 #  endif
00048 # endif
00049 #endif
00050 
00051 #include "debug.h"
00052 
00053 /*@access rpmdb @*/             /* XXX db->db_chrootDone, NULL */
00054 
00055 /*@access FD_t @*/              /* XXX compared with NULL */
00056 /*@access rpmps @*/
00057 /*@access rpmDiskSpaceInfo @*/
00058 /*@access rpmte @*/
00059 /*@access rpmtsi @*/
00060 /*@access rpmts @*/
00061 /*@access fnpyKey @*/
00062 /*@access pgpDig @*/
00063 /*@access pgpDigParams @*/
00064 
00065 /*@unchecked@*/
00066 int _rpmts_debug = 0;
00067 
00068 char * hGetNEVR(Header h, const char ** np)
00069 {
00070     const char * n, * v, * r;
00071     char * NVR, * t;
00072 
00073     (void) headerNVR(h, &n, &v, &r);
00074     NVR = t = xcalloc(1, strlen(n) + strlen(v) + strlen(r) + sizeof("--"));
00075 /*@-boundswrite@*/
00076     t = stpcpy(t, n);
00077     t = stpcpy(t, "-");
00078     t = stpcpy(t, v);
00079     t = stpcpy(t, "-");
00080     t = stpcpy(t, r);
00081     if (np)
00082         *np = n;
00083 /*@=boundswrite@*/
00084     return NVR;
00085 }
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         rc = rpmdbClose(ts->rdb);
00113         ts->rdb = NULL;
00114     }
00115     return rc;
00116 }
00117 
00118 int rpmtsOpenDB(rpmts ts, int dbmode)
00119 {
00120     int rc = 0;
00121 
00122     if (ts->rdb != NULL && ts->dbmode == dbmode)
00123         return 0;
00124 
00125     (void) rpmtsCloseDB(ts);
00126 
00127     /* XXX there's a potential db lock race here. */
00128 
00129     ts->dbmode = dbmode;
00130     rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
00131     if (rc) {
00132         const char * dn;
00133         dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00134         rpmMessage(RPMMESS_ERROR,
00135                         _("cannot open Packages database in %s\n"), dn);
00136         dn = _free(dn);
00137     }
00138     return rc;
00139 }
00140 
00141 int rpmtsInitDB(rpmts ts, int dbmode)
00142 {
00143     return rpmdbInit(ts->rootDir, dbmode);
00144 }
00145 
00146 int rpmtsRebuildDB(rpmts ts)
00147 {
00148     int rc;
00149     if (!(ts->vsflags & RPMVSF_NOHDRCHK))
00150         rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
00151     else
00152         rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
00153     return rc;
00154 }
00155 
00156 int rpmtsVerifyDB(rpmts ts)
00157 {
00158     return rpmdbVerify(ts->rootDir);
00159 }
00160 
00161 rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
00162                         const void * keyp, size_t keylen)
00163 {
00164     rpmdbMatchIterator mi;
00165     if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
00166         return NULL;
00167     mi = rpmdbInitIterator(ts->rdb, rpmtag, keyp, keylen);
00168     if (mi && !(ts->vsflags & RPMVSF_NOHDRCHK))
00169         (void) rpmdbSetHdrChk(mi, ts, headerCheck);
00170     return mi;
00171 }
00172 
00173 rpmRC rpmtsFindPubkey(rpmts ts)
00174 {
00175     const void * sig = rpmtsSig(ts);
00176     pgpDig dig = rpmtsDig(ts);
00177     pgpDigParams sigp = rpmtsSignature(ts);
00178     pgpDigParams pubp = rpmtsSignature(ts);
00179     rpmRC res;
00180     int xx;
00181 
00182     if (sig == NULL || dig == NULL || sigp == NULL || pubp == NULL) {
00183         res = RPMRC_NOKEY;
00184         goto exit;
00185     }
00186 
00187     if (ts->pkpkt == NULL
00188      || memcmp(sigp->signid, ts->pksignid, sizeof(ts->pksignid)))
00189     {
00190         int ix = -1;
00191         rpmdbMatchIterator mi;
00192         Header h;
00193 
00194         ts->pkpkt = _free(ts->pkpkt);
00195         ts->pkpktlen = 0;
00196         memset(ts->pksignid, 0, sizeof(ts->pksignid));
00197 
00198         /* Retrieve the pubkey that matches the signature. */
00199         mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
00200         while ((h = rpmdbNextIterator(mi)) != NULL) {
00201             const char ** pubkeys;
00202             int_32 pt, pc;
00203 
00204             if (!headerGetEntry(h, RPMTAG_PUBKEYS, &pt, (void **)&pubkeys, &pc))
00205                 continue;
00206             ix = rpmdbGetIteratorFileNum(mi);
00207 /*@-boundsread@*/
00208             if (ix >= pc
00209              || b64decode(pubkeys[ix], (void **) &ts->pkpkt, &ts->pkpktlen))
00210                 ix = -1;
00211 /*@=boundsread@*/
00212             pubkeys = headerFreeData(pubkeys, pt);
00213             break;
00214         }
00215         mi = rpmdbFreeIterator(mi);
00216 
00217         /* Was a matching pubkey found? */
00218         if (ix < 0 || ts->pkpkt == NULL) {
00219             res = RPMRC_NOKEY;
00220             goto exit;
00221         }
00222 
00223         /*
00224          * Can the pubkey packets be parsed?
00225          * Do the parameters match the signature?
00226          */
00227         if (pgpPrtPkts(ts->pkpkt, ts->pkpktlen, NULL, 0)
00228          && sigp->pubkey_algo == pubp->pubkey_algo
00229 #ifdef  NOTYET
00230          && sigp->hash_algo == pubp->hash_algo
00231 #endif
00232          && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)))
00233         {
00234             ts->pkpkt = _free(ts->pkpkt);
00235             ts->pkpktlen = 0;
00236             res = RPMRC_NOKEY;
00237             goto exit;
00238         }
00239 
00240         /* XXX Verify the pubkey signature. */
00241 
00242         /* Packet looks good, save the signer id. */
00243 /*@-boundsread@*/
00244         memcpy(ts->pksignid, sigp->signid, sizeof(ts->pksignid));
00245 /*@=boundsread@*/
00246 
00247         rpmMessage(RPMMESS_DEBUG, "========== %s pubkey id %s\n",
00248                 (sigp->pubkey_algo == PGPPUBKEYALGO_DSA ? "DSA" :
00249                 (sigp->pubkey_algo == PGPPUBKEYALGO_RSA ? "RSA" : "???")),
00250                 pgpHexStr(sigp->signid, sizeof(sigp->signid)));
00251 
00252     }
00253 
00254 #ifdef  NOTNOW
00255     {
00256         if (ts->pkpkt == NULL) {
00257             const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
00258             if (pgpReadPkts(pkfn, &ts->pkpkt, &ts->pkpktlen) != PGPARMOR_PUBKEY) {
00259                 pkfn = _free(pkfn);
00260                 res = RPMRC_NOKEY;
00261                 goto exit;
00262             }
00263             pkfn = _free(pkfn);
00264         }
00265     }
00266 #endif
00267 
00268     /* Retrieve parameters from pubkey packet(s). */
00269     xx = pgpPrtPkts(ts->pkpkt, ts->pkpktlen, dig, 0);
00270 
00271     /* Do the parameters match the signature? */
00272     if (sigp->pubkey_algo == pubp->pubkey_algo
00273 #ifdef  NOTYET
00274      && sigp->hash_algo == pubp->hash_algo
00275 #endif
00276      && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)) )
00277         res = RPMRC_OK;
00278     else
00279         res = RPMRC_NOKEY;
00280 
00281     /* XXX Verify the signature signature. */
00282 
00283 exit:
00284     return res;
00285 }
00286 
00287 int rpmtsCloseSDB(rpmts ts)
00288 {
00289     int rc = 0;
00290 
00291     if (ts->sdb != NULL) {
00292         rc = rpmdbClose(ts->sdb);
00293         ts->sdb = NULL;
00294     }
00295     return rc;
00296 }
00297 
00298 int rpmtsOpenSDB(rpmts ts, int dbmode)
00299 {
00300     static int has_sdbpath = -1;
00301     int rc = 0;
00302 
00303     if (ts->sdb != NULL && ts->sdbmode == dbmode)
00304         return 0;
00305 
00306     if (has_sdbpath < 0)
00307         has_sdbpath = rpmExpandNumeric("%{?_solve_dbpath:1}");
00308 
00309     /* If not configured, don't try to open. */
00310     if (has_sdbpath <= 0)
00311         return 1;
00312 
00313     addMacro(NULL, "_dbpath", NULL, "%{_solve_dbpath}", RMIL_DEFAULT);
00314 
00315     rc = rpmdbOpen(ts->rootDir, &ts->sdb, ts->sdbmode, 0644);
00316     if (rc) {
00317         const char * dn;
00318         dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00319         rpmMessage(RPMMESS_WARNING,
00320                         _("cannot open Solve database in %s\n"), dn);
00321         dn = _free(dn);
00322     }
00323     delMacro(NULL, "_dbpath");
00324 
00325     return rc;
00326 }
00327 
00334 static int sugcmp(const void * a, const void * b)
00335         /*@*/
00336 {
00337 /*@-boundsread@*/
00338     const char * astr = *(const char **)a;
00339     const char * bstr = *(const char **)b;
00340 /*@=boundsread@*/
00341     return strcmp(astr, bstr);
00342 }
00343 
00344 /*@-bounds@*/
00345 int rpmtsSolve(rpmts ts, rpmds ds, /*@unused@*/ const void * data)
00346 {
00347     const char * errstr;
00348     const char * str;
00349     const char * qfmt;
00350     rpmdbMatchIterator mi;
00351     Header bh;
00352     Header h;
00353     size_t bhnamelen;
00354     time_t bhtime;
00355     rpmTag rpmtag;
00356     const char * keyp;
00357     size_t keylen;
00358     int rc = 1; /* assume not found */
00359     int xx;
00360 
00361     /* Make suggestions only for install Requires: */
00362     if (ts->goal != TSM_INSTALL)
00363         return rc;
00364 
00365     if (rpmdsTagN(ds) != RPMTAG_REQUIRENAME)
00366         return rc;
00367 
00368     keyp = rpmdsN(ds);
00369     if (keyp == NULL)
00370         return rc;
00371 
00372     if (ts->sdb == NULL) {
00373         xx = rpmtsOpenSDB(ts, ts->sdbmode);
00374         if (xx) return rc;
00375     }
00376 
00377     /* Look for a matching Provides: in suggested universe. */
00378     rpmtag = (*keyp == '/' ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME);
00379     keylen = 0;
00380     mi = rpmdbInitIterator(ts->sdb, rpmtag, keyp, keylen);
00381     bhnamelen = 0;
00382     bhtime = 0;
00383     bh = NULL;
00384     while ((h = rpmdbNextIterator(mi)) != NULL) {
00385         const char * hname;
00386         size_t hnamelen;
00387         time_t htime;
00388         int_32 * ip;
00389 
00390         if (rpmtag == RPMTAG_PROVIDENAME && !rpmdsAnyMatchesDep(h, ds, 1))
00391             continue;
00392 
00393         /* XXX Prefer the shortest name if given alternatives. */
00394         hname = NULL;
00395         hnamelen = 0;
00396         if (headerGetEntry(h, RPMTAG_NAME, NULL, (void **)&hname, NULL)) {
00397             if (hname)
00398                 hnamelen = strlen(hname);
00399         }
00400         if (bhnamelen > 0 && hnamelen > bhnamelen)
00401             continue;
00402 
00403         /* XXX Prefer the newest build if given alternatives. */
00404         htime = 0;
00405         if (headerGetEntry(h, RPMTAG_BUILDTIME, NULL, (void **)&ip, NULL))
00406             htime = (time_t)*ip;
00407 
00408         if (htime <= bhtime)
00409             continue;
00410 
00411         bh = headerFree(bh);
00412         bh = headerLink(h);
00413         bhtime = htime;
00414         bhnamelen = hnamelen;
00415     }
00416     mi = rpmdbFreeIterator(mi);
00417 
00418     /* Is there a suggested resolution? */
00419     if (bh == NULL)
00420         goto exit;
00421 
00422     /* Format the suggestion. */
00423     qfmt = rpmExpand("%{?_solve_name_fmt}", NULL);
00424     if (qfmt == NULL || *qfmt == '\0')
00425         goto exit;
00426     str = headerSprintf(bh, qfmt, rpmTagTable, rpmHeaderFormats, &errstr);
00427     bh = headerFree(bh);
00428     qfmt = _free(qfmt);
00429     if (str == NULL) {
00430         rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr);
00431         goto exit;
00432     }
00433 
00434     if (ts->transFlags & RPMTRANS_FLAG_ADDINDEPS) {
00435         FD_t fd;
00436         rpmRC rpmrc;
00437 
00438         h = headerFree(h);
00439         fd = Fopen(str, "r.ufdio");
00440         if (fd == NULL || Ferror(fd)) {
00441             rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), str,
00442                         Fstrerror(fd));
00443             if (fd) {
00444                 xx = Fclose(fd);
00445                 fd = NULL;
00446             }
00447             str = _free(str);
00448             goto exit;
00449         }
00450         rpmrc = rpmReadPackageFile(ts, fd, str, &h);
00451         xx = Fclose(fd);
00452         switch (rpmrc) {
00453         default:
00454             str = _free(str);
00455             break;
00456         case RPMRC_NOTTRUSTED:
00457         case RPMRC_NOKEY:
00458         case RPMRC_OK:
00459             if (h != NULL &&
00460                 !rpmtsAddInstallElement(ts, h, (fnpyKey)str, 1, NULL))
00461             {
00462                 rpmMessage(RPMMESS_DEBUG, _("Adding: %s\n"), str);
00463                 rc = -1;
00464                 /* XXX str memory leak */
00465                 break;
00466             }
00467             str = _free(str);
00468             break;
00469         }
00470         h = headerFree(h);
00471         goto exit;
00472     }
00473 
00474     rpmMessage(RPMMESS_DEBUG, _("Suggesting: %s\n"), str);
00475     /* If suggestion is already present, don't bother. */
00476     if (ts->suggests != NULL && ts->nsuggests > 0) {
00477         if (bsearch(&str, ts->suggests, ts->nsuggests,
00478                         sizeof(*ts->suggests), sugcmp))
00479             goto exit;
00480     }
00481 
00482     /* Add a new (unique) suggestion. */
00483     ts->suggests = xrealloc(ts->suggests,
00484                         sizeof(*ts->suggests) * (ts->nsuggests + 2));
00485     ts->suggests[ts->nsuggests] = str;
00486     ts->nsuggests++;
00487     ts->suggests[ts->nsuggests] = NULL;
00488 
00489     if (ts->nsuggests > 1)
00490         qsort(ts->suggests, ts->nsuggests, sizeof(*ts->suggests), sugcmp);
00491 
00492 exit:
00493 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
00494     return rc;
00495 /*@=nullstate@*/
00496 }
00497 /*@=bounds@*/
00498 
00499 int rpmtsAvailable(rpmts ts, const rpmds ds)
00500 {
00501     fnpyKey * sugkey;
00502     int rc = 1; /* assume not found */
00503 
00504     if (ts->availablePackages == NULL)
00505         return rc;
00506     sugkey = rpmalAllSatisfiesDepend(ts->availablePackages, ds, NULL);
00507     if (sugkey == NULL)
00508         return rc;
00509 
00510     /* XXX no alternatives yet */
00511     if (sugkey[0] != NULL) {
00512         ts->suggests = xrealloc(ts->suggests,
00513                         sizeof(*ts->suggests) * (ts->nsuggests + 2));
00514         ts->suggests[ts->nsuggests] = sugkey[0];
00515         sugkey[0] = NULL;
00516         ts->nsuggests++;
00517         ts->suggests[ts->nsuggests] = NULL;
00518     }
00519     sugkey = _free(sugkey);
00520 /*@-nullstate@*/ /* FIX: ts->suggests[] may be NULL */
00521     return rc;
00522 /*@=nullstate@*/
00523 }
00524 
00525 int rpmtsSetSolveCallback(rpmts ts,
00526                 int (*solve) (rpmts ts, rpmds key, const void * data),
00527                 const void * solveData)
00528 {
00529     int rc = 0;
00530 
00531 /*@-branchstate@*/
00532     if (ts) {
00533 /*@-assignexpose -temptrans @*/
00534         ts->solve = solve;
00535         ts->solveData = solveData;
00536 /*@=assignexpose =temptrans @*/
00537     }
00538 /*@=branchstate@*/
00539     return rc;
00540 }
00541 
00542 rpmps rpmtsProblems(rpmts ts)
00543 {
00544     rpmps ps = NULL;
00545     if (ts) {
00546         if (ts->probs)
00547             ps = rpmpsLink(ts->probs, NULL);
00548     }
00549     return ps;
00550 }
00551 
00552 void rpmtsCleanDig(rpmts ts)
00553 {
00554     ts->sig = headerFreeData(ts->sig, ts->sigtype);
00555     ts->dig = pgpFreeDig(ts->dig);
00556 }
00557 
00558 void rpmtsClean(rpmts ts)
00559 {
00560     rpmtsi pi; rpmte p;
00561 
00562     if (ts == NULL)
00563         return;
00564 
00565     /* Clean up after dependency checks. */
00566     pi = rpmtsiInit(ts);
00567     while ((p = rpmtsiNext(pi, 0)) != NULL)
00568         rpmteCleanDS(p);
00569     pi = rpmtsiFree(pi);
00570 
00571     ts->addedPackages = rpmalFree(ts->addedPackages);
00572     ts->numAddedPackages = 0;
00573 
00574     ts->suggests = _free(ts->suggests);
00575     ts->nsuggests = 0;
00576 
00577     ts->probs = rpmpsFree(ts->probs);
00578 
00579     rpmtsCleanDig(ts);
00580 }
00581 
00582 void rpmtsEmpty(rpmts ts)
00583 {
00584     rpmtsi pi; rpmte p;
00585     int oc;
00586 
00587     if (ts == NULL)
00588         return;
00589 
00590 /*@-nullstate@*/        /* FIX: partial annotations */
00591     rpmtsClean(ts);
00592 /*@=nullstate@*/
00593 
00594     for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, 0)) != NULL; oc++) {
00595 /*@-type -unqualifiedtrans @*/
00596         ts->order[oc] = rpmteFree(ts->order[oc]);
00597 /*@=type =unqualifiedtrans @*/
00598     }
00599     pi = rpmtsiFree(pi);
00600 
00601     ts->orderCount = 0;
00602 
00603     ts->numRemovedPackages = 0;
00604 /*@-nullstate@*/        /* FIX: partial annotations */
00605     return;
00606 /*@=nullstate@*/
00607 }
00608 
00609 rpmts rpmtsFree(rpmts ts)
00610 {
00611     if (ts == NULL)
00612         return NULL;
00613 
00614     if (ts->nrefs > 1)
00615         return rpmtsUnlink(ts, "tsCreate");
00616 
00617 /*@-nullstate@*/        /* FIX: partial annotations */
00618     rpmtsEmpty(ts);
00619 /*@=nullstate@*/
00620 
00621     (void) rpmtsCloseDB(ts);
00622 
00623     (void) rpmtsCloseSDB(ts);
00624 
00625     ts->removedPackages = _free(ts->removedPackages);
00626 
00627     ts->availablePackages = rpmalFree(ts->availablePackages);
00628     ts->numAvailablePackages = 0;
00629 
00630     ts->dsi = _free(ts->dsi);
00631 
00632     if (ts->scriptFd != NULL) {
00633         ts->scriptFd = fdFree(ts->scriptFd, "rpmtsFree");
00634         ts->scriptFd = NULL;
00635     }
00636     ts->rootDir = _free(ts->rootDir);
00637     ts->currDir = _free(ts->currDir);
00638 
00639 /*@-type +voidabstract @*/      /* FIX: double indirection */
00640     ts->order = _free(ts->order);
00641 /*@=type =voidabstract @*/
00642     ts->orderAlloced = 0;
00643 
00644     if (ts->pkpkt != NULL)
00645         ts->pkpkt = _free(ts->pkpkt);
00646     ts->pkpktlen = 0;
00647     memset(ts->pksignid, 0, sizeof(ts->pksignid));
00648 
00649     (void) rpmtsUnlink(ts, "tsCreate");
00650 
00651     /*@-refcounttrans -usereleased @*/
00652     ts = _free(ts);
00653     /*@=refcounttrans =usereleased @*/
00654 
00655     return NULL;
00656 }
00657 
00658 rpmVSFlags rpmtsVSFlags(rpmts ts)
00659 {
00660     rpmVSFlags vsflags = 0;
00661     if (ts != NULL)
00662         vsflags = ts->vsflags;
00663     return vsflags;
00664 }
00665 
00666 rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
00667 {
00668     rpmVSFlags ovsflags = 0;
00669     if (ts != NULL) {
00670         ovsflags = ts->vsflags;
00671         ts->vsflags = vsflags;
00672     }
00673     return ovsflags;
00674 }
00675 
00676 int rpmtsUnorderedSuccessors(rpmts ts, int first)
00677 {
00678     int unorderedSuccessors = 0;
00679     if (ts != NULL) {
00680         unorderedSuccessors = ts->unorderedSuccessors;
00681         if (first >= 0)
00682             ts->unorderedSuccessors = first;
00683     }
00684     return unorderedSuccessors;
00685 }
00686 
00687 const char * rpmtsRootDir(rpmts ts)
00688 {
00689     return (ts != NULL ? ts->rootDir : NULL);
00690 }
00691 
00692 void rpmtsSetRootDir(rpmts ts, const char * rootDir)
00693 {
00694     if (ts != NULL) {
00695         size_t rootLen;
00696 
00697         ts->rootDir = _free(ts->rootDir);
00698 
00699         if (rootDir == NULL) {
00700 #ifndef DYING
00701             ts->rootDir = xstrdup("");
00702 #endif
00703             return;
00704         }
00705         rootLen = strlen(rootDir);
00706 
00707 /*@-branchstate@*/
00708         /* Make sure that rootDir has trailing / */
00709         if (!(rootLen && rootDir[rootLen - 1] == '/')) {
00710             char * t = alloca(rootLen + 2);
00711             *t = '\0';
00712             (void) stpcpy( stpcpy(t, rootDir), "/");
00713             rootDir = t;
00714         }
00715 /*@=branchstate@*/
00716         ts->rootDir = xstrdup(rootDir);
00717     }
00718 }
00719 
00720 const char * rpmtsCurrDir(rpmts ts)
00721 {
00722     const char * currDir = NULL;
00723     if (ts != NULL) {
00724         currDir = ts->currDir;
00725     }
00726     return currDir;
00727 }
00728 
00729 void rpmtsSetCurrDir(rpmts ts, const char * currDir)
00730 {
00731     if (ts != NULL) {
00732         ts->currDir = _free(ts->currDir);
00733         if (currDir)
00734             ts->currDir = xstrdup(currDir);
00735     }
00736 }
00737 
00738 FD_t rpmtsScriptFd(rpmts ts)
00739 {
00740     FD_t scriptFd = NULL;
00741     if (ts != NULL) {
00742         scriptFd = ts->scriptFd;
00743     }
00744 /*@-compdef -refcounttrans -usereleased@*/
00745     return scriptFd;
00746 /*@=compdef =refcounttrans =usereleased@*/
00747 }
00748 
00749 void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
00750 {
00751 
00752     if (ts != NULL) {
00753         if (ts->scriptFd != NULL) {
00754             ts->scriptFd = fdFree(ts->scriptFd, "rpmtsSetScriptFd");
00755             ts->scriptFd = NULL;
00756         }
00757         if (scriptFd != NULL)
00758             ts->scriptFd = fdLink(scriptFd, "rpmtsSetScriptFd");
00759     }
00760 }
00761 
00762 int rpmtsChrootDone(rpmts ts)
00763 {
00764     int chrootDone = 0;
00765     if (ts != NULL) {
00766         chrootDone = ts->chrootDone;
00767     }
00768     return chrootDone;
00769 }
00770 
00771 int rpmtsSetChrootDone(rpmts ts, int chrootDone)
00772 {
00773     int ochrootDone = 0;
00774     if (ts != NULL) {
00775         ochrootDone = ts->chrootDone;
00776         if (ts->rdb != NULL)
00777             ts->rdb->db_chrootDone = chrootDone;
00778         ts->chrootDone = chrootDone;
00779     }
00780     return ochrootDone;
00781 }
00782 
00783 int_32 rpmtsGetTid(rpmts ts)
00784 {
00785     int_32 tid = 0;
00786     if (ts != NULL) {
00787         tid = ts->tid;
00788     }
00789     return tid;
00790 }
00791 
00792 int_32 rpmtsSetTid(rpmts ts, int_32 tid)
00793 {
00794     int_32 otid = 0;
00795     if (ts != NULL) {
00796         otid = ts->tid;
00797         ts->tid = tid;
00798     }
00799     return otid;
00800 }
00801 
00802 int_32 rpmtsSigtag(const rpmts ts)
00803 {
00804     int_32 sigtag = 0;
00805     if (ts != NULL)
00806         sigtag = ts->sigtag;
00807     return sigtag;
00808 }
00809 
00810 int_32 rpmtsSigtype(const rpmts ts)
00811 {
00812     int_32 sigtag = 0;
00813     if (ts != NULL)
00814         sigtag = ts->sigtag;
00815     return sigtag;
00816 }
00817 
00818 const void * rpmtsSig(const rpmts ts)
00819 {
00820     const void * sig = NULL;
00821     if (ts != NULL)
00822         sig = ts->sig;
00823     return sig;
00824 }
00825 
00826 int_32 rpmtsSiglen(const rpmts ts)
00827 {
00828     int_32 siglen = 0;
00829     if (ts != NULL)
00830         siglen = ts->siglen;
00831     return siglen;
00832 }
00833 
00834 int rpmtsSetSig(rpmts ts,
00835                 int_32 sigtag, int_32 sigtype, const void * sig, int_32 siglen)
00836 {
00837     if (ts != NULL) {
00838         if (ts->sig && ts->sigtype)
00839             ts->sig = headerFreeData(ts->sig, ts->sigtype);
00840         ts->sigtag = sigtag;
00841         ts->sigtype = (sig ? sigtype : 0);
00842 /*@-assignexpose -kepttrans@*/
00843         ts->sig = sig;
00844 /*@=assignexpose =kepttrans@*/
00845         ts->siglen = siglen;
00846     }
00847     return 0;
00848 }
00849 
00850 pgpDig rpmtsDig(rpmts ts)
00851 {
00852 /*@-mods@*/ /* FIX: hide lazy malloc for now */
00853     if (ts->dig == NULL)
00854         ts->dig = pgpNewDig();
00855 /*@=mods@*/
00856     if (ts->dig == NULL)
00857         return NULL;
00858     return ts->dig;
00859 }
00860 
00861 pgpDigParams rpmtsSignature(const rpmts ts)
00862 {
00863     pgpDig dig = rpmtsDig(ts);
00864     if (dig == NULL) return NULL;
00865 /*@-immediatetrans@*/
00866     return &dig->signature;
00867 /*@=immediatetrans@*/
00868 }
00869 
00870 pgpDigParams rpmtsPubkey(const rpmts ts)
00871 {
00872     pgpDig dig = rpmtsDig(ts);
00873     if (dig == NULL) return NULL;
00874 /*@-immediatetrans@*/
00875     return &dig->pubkey;
00876 /*@=immediatetrans@*/
00877 }
00878 
00879 rpmdb rpmtsGetRdb(rpmts ts)
00880 {
00881     rpmdb rdb = NULL;
00882     if (ts != NULL) {
00883         rdb = ts->rdb;
00884     }
00885 /*@-compdef -refcounttrans -usereleased @*/
00886     return rdb;
00887 /*@=compdef =refcounttrans =usereleased @*/
00888 }
00889 
00890 int rpmtsInitDSI(const rpmts ts)
00891 {
00892     rpmDiskSpaceInfo dsi;
00893     struct stat sb;
00894     int rc;
00895     int i;
00896 
00897     if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
00898         return 0;
00899 
00900     rc = rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount);
00901     if (rc || ts->filesystems == NULL || ts->filesystemCount <= 0)
00902         return rc;
00903 
00904     /* Get available space on mounted file systems. */
00905 
00906     rpmMessage(RPMMESS_DEBUG, _("getting list of mounted filesystems\n"));
00907 
00908     ts->dsi = _free(ts->dsi);
00909     ts->dsi = xcalloc((ts->filesystemCount + 1), sizeof(*ts->dsi));
00910 
00911     dsi = ts->dsi;
00912 
00913     if (dsi != NULL)
00914     for (i = 0; (i < ts->filesystemCount) && dsi; i++, dsi++) {
00915 #if STATFS_IN_SYS_STATVFS
00916         struct statvfs sfb;
00917         memset(&sfb, 0, sizeof(sfb));
00918         rc = statvfs(ts->filesystems[i], &sfb);
00919 #else
00920         struct statfs sfb;
00921         memset(&sfb, 0, sizeof(sfb));
00922 #  if STAT_STATFS4
00923 /* This platform has the 4-argument version of the statfs call.  The last two
00924  * should be the size of struct statfs and 0, respectively.  The 0 is the
00925  * filesystem type, and is always 0 when statfs is called on a mounted
00926  * filesystem, as we're doing.
00927  */
00928         rc = statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0);
00929 #  else
00930         rc = statfs(ts->filesystems[i], &sfb);
00931 #  endif
00932 #endif
00933         if (rc)
00934             break;
00935 
00936         rc = stat(ts->filesystems[i], &sb);
00937         if (rc)
00938             break;
00939         dsi->dev = sb.st_dev;
00940 
00941         dsi->bsize = sfb.f_bsize;
00942         dsi->bneeded = 0;
00943         dsi->ineeded = 0;
00944 #ifdef STATFS_HAS_F_BAVAIL
00945         dsi->bavail = sfb.f_bavail;
00946 #else
00947 /* FIXME: the statfs struct doesn't have a member to tell how many blocks are
00948  * available for non-superusers.  f_blocks - f_bfree is probably too big, but
00949  * it's about all we can do.
00950  */
00951         dsi->bavail = sfb.f_blocks - sfb.f_bfree;
00952 #endif
00953         /* XXX Avoid FAT and other file systems that have not inodes. */
00954         dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
00955                                 ? sfb.f_ffree : -1;
00956     }
00957     return rc;
00958 }
00959 
00960 void rpmtsUpdateDSI(const rpmts ts, dev_t dev,
00961                 uint_32 fileSize, uint_32 prevSize, uint_32 fixupSize,
00962                 fileAction action)
00963 {
00964     rpmDiskSpaceInfo dsi;
00965     uint_32 bneeded;
00966 
00967     dsi = ts->dsi;
00968     if (dsi) {
00969         while (dsi->bsize && dsi->dev != dev)
00970             dsi++;
00971         if (dsi->bsize == 0)
00972             dsi = NULL;
00973     }
00974     if (dsi == NULL)
00975         return;
00976 
00977     bneeded = BLOCK_ROUND(fileSize, dsi->bsize);
00978 
00979     switch (action) {
00980     case FA_BACKUP:
00981     case FA_SAVE:
00982     case FA_ALTNAME:
00983         dsi->ineeded++;
00984         dsi->bneeded += bneeded;
00985         /*@switchbreak@*/ break;
00986 
00987     /*
00988      * FIXME: If two packages share a file (same md5sum), and
00989      * that file is being replaced on disk, will dsi->bneeded get
00990      * adjusted twice? Quite probably!
00991      */
00992     case FA_CREATE:
00993         dsi->bneeded += bneeded;
00994         dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->bsize);
00995         /*@switchbreak@*/ break;
00996 
00997     case FA_ERASE:
00998         dsi->ineeded--;
00999         dsi->bneeded -= bneeded;
01000         /*@switchbreak@*/ break;
01001 
01002     default:
01003         /*@switchbreak@*/ break;
01004     }
01005 
01006     if (fixupSize)
01007         dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->bsize);
01008 }
01009 
01010 void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
01011 {
01012     rpmDiskSpaceInfo dsi;
01013     rpmps ps;
01014     int fc;
01015     int i;
01016 
01017     if (ts->filesystems == NULL || ts->filesystemCount <= 0)
01018         return;
01019 
01020     dsi = ts->dsi;
01021     if (dsi == NULL)
01022         return;
01023     fc = rpmfiFC( rpmteFI(te, RPMTAG_BASENAMES) );
01024     if (fc <= 0)
01025         return;
01026 
01027     ps = rpmtsProblems(ts);
01028     for (i = 0; i < ts->filesystemCount; i++, dsi++) {
01029 
01030         if (dsi->bavail > 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
01031             rpmpsAppend(ps, RPMPROB_DISKSPACE,
01032                         rpmteNEVR(te), rpmteKey(te),
01033                         ts->filesystems[i], NULL, NULL,
01034            (adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
01035         }
01036 
01037         if (dsi->iavail > 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
01038             rpmpsAppend(ps, RPMPROB_DISKNODES,
01039                         rpmteNEVR(te), rpmteKey(te),
01040                         ts->filesystems[i], NULL, NULL,
01041             (adj_fs_blocks(dsi->ineeded) - dsi->iavail));
01042         }
01043     }
01044     ps = rpmpsFree(ps);
01045 }
01046 
01047 void * rpmtsNotify(rpmts ts, rpmte te,
01048                 rpmCallbackType what, unsigned long amount, unsigned long total)
01049 {
01050     void * ptr = NULL;
01051     if (ts && ts->notify && te) {
01052 assert(!(te->type == TR_ADDED && te->h == NULL));
01053         /*@-type@*/ /* FIX: cast? */
01054         /*@-noeffectuncon @*/ /* FIX: check rc */
01055         ptr = ts->notify(te->h, what, amount, total,
01056                         rpmteKey(te), ts->notifyData);
01057         /*@=noeffectuncon @*/
01058         /*@=type@*/
01059     }
01060     return ptr;
01061 }
01062 
01063 int rpmtsNElements(rpmts ts)
01064 {
01065     int nelements = 0;
01066     if (ts != NULL && ts->order != NULL) {
01067         nelements = ts->orderCount;
01068     }
01069     return nelements;
01070 }
01071 
01072 rpmte rpmtsElement(rpmts ts, int ix)
01073 {
01074     rpmte te = NULL;
01075     if (ts != NULL && ts->order != NULL) {
01076         if (ix >= 0 && ix < ts->orderCount)
01077             te = ts->order[ix];
01078     }
01079     /*@-compdef@*/
01080     return te;
01081     /*@=compdef@*/
01082 }
01083 
01084 rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
01085 {
01086     return (ts != NULL ? ts->ignoreSet : 0);
01087 }
01088 
01089 rpmtransFlags rpmtsFlags(rpmts ts)
01090 {
01091     return (ts != NULL ? ts->transFlags : 0);
01092 }
01093 
01094 rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
01095 {
01096     rpmtransFlags otransFlags = 0;
01097     if (ts != NULL) {
01098         otransFlags = ts->transFlags;
01099         ts->transFlags = transFlags;
01100     }
01101     return otransFlags;
01102 }
01103 
01104 int rpmtsSetNotifyCallback(rpmts ts,
01105                 rpmCallbackFunction notify, rpmCallbackData notifyData)
01106 {
01107     if (ts != NULL) {
01108         ts->notify = notify;
01109         ts->notifyData = notifyData;
01110     }
01111     return 0;
01112 }
01113 
01114 int rpmtsGetKeys(const rpmts ts, fnpyKey ** ep, int * nep)
01115 {
01116     int rc = 0;
01117 
01118     if (nep) *nep = ts->orderCount;
01119     if (ep) {
01120         rpmtsi pi;      rpmte p;
01121         fnpyKey * e;
01122 
01123         *ep = e = xmalloc(ts->orderCount * sizeof(*e));
01124         pi = rpmtsiInit(ts);
01125         while ((p = rpmtsiNext(pi, 0)) != NULL) {
01126             switch (rpmteType(p)) {
01127             case TR_ADDED:
01128                 /*@-dependenttrans@*/
01129                 *e = rpmteKey(p);
01130                 /*@=dependenttrans@*/
01131                 /*@switchbreak@*/ break;
01132             case TR_REMOVED:
01133             default:
01134                 *e = NULL;
01135                 /*@switchbreak@*/ break;
01136             }
01137             e++;
01138         }
01139         pi = rpmtsiFree(pi);
01140     }
01141     return rc;
01142 }
01143 
01144 rpmts rpmtsCreate(void)
01145 {
01146     rpmts ts;
01147 
01148     ts = xcalloc(1, sizeof(*ts));
01149     ts->goal = TSM_UNKNOWN;
01150     ts->filesystemCount = 0;
01151     ts->filesystems = NULL;
01152     ts->dsi = NULL;
01153 
01154     ts->solve = rpmtsSolve;
01155     ts->solveData = NULL;
01156     ts->nsuggests = 0;
01157     ts->suggests = NULL;
01158     ts->sdb = NULL;
01159     ts->sdbmode = O_RDONLY;
01160 
01161     ts->rdb = NULL;
01162     ts->dbmode = O_RDONLY;
01163 
01164     ts->scriptFd = NULL;
01165     ts->tid = (int_32) time(NULL);
01166     ts->delta = 5;
01167 
01168     ts->numRemovedPackages = 0;
01169     ts->allocedRemovedPackages = ts->delta;
01170     ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
01171                         sizeof(*ts->removedPackages));
01172 
01173     ts->rootDir = NULL;
01174     ts->currDir = NULL;
01175     ts->chrootDone = 0;
01176 
01177     ts->numAddedPackages = 0;
01178     ts->addedPackages = NULL;
01179 
01180     ts->numAvailablePackages = 0;
01181     ts->availablePackages = NULL;
01182 
01183     ts->orderAlloced = 0;
01184     ts->orderCount = 0;
01185     ts->order = NULL;
01186 
01187     ts->probs = NULL;
01188 
01189     ts->sig = NULL;
01190     ts->pkpkt = NULL;
01191     ts->pkpktlen = 0;
01192     memset(ts->pksignid, 0, sizeof(ts->pksignid));
01193     ts->dig = NULL;
01194 
01195     ts->nrefs = 0;
01196 
01197     return rpmtsLink(ts, "tsCreate");
01198 }

Generated on Tue Sep 17 15:59:52 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002