rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/rpmps.c
Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio.h>
    00008 #include <rpmiotypes.h>         /* XXX fnpyKey */
    00009 #include <rpmtypes.h>
    00010 #include <yarn.h>
    00011
    00012 #define _RPMPS_INTERNAL
    00013 #include "rpmps.h"
    00014
    00015 #include "debug.h"
    00016
    00017 /*@access fnpyKey @*/
    00018 /*@access rpmProblem @*/
    00019
    00020 /*@unchecked@*/
    00021 int _rpmps_debug = 0;
    00022
    00023 /*@unchecked@*/ /*@only@*/ /*@null@*/
    00024 rpmioPool _rpmpsPool;
    00025
    00026 static rpmps rpmpsGetPool(/*@null@*/ rpmioPool pool)
    00027         /*@globals _rpmpsPool, fileSystem, internalState @*/
    00028         /*@modifies pool, _rpmpsPool, fileSystem, internalState @*/
    00029 {
    00030     rpmps ps;
    00031
    00032     if (_rpmpsPool == NULL) {
    00033         _rpmpsPool = rpmioNewPool("ps", sizeof(*ps), -1, _rpmps_debug,
    00034                         NULL, NULL, NULL);
    00035         pool = _rpmpsPool;
    00036     }
    00037     return (rpmps) rpmioGetPool(pool, sizeof(*ps));
    00038 }
    00039
    00040 int rpmpsNumProblems(rpmps ps)
    00041 {
    00042     int numProblems = 0;
    00043     if (ps && ps->probs)
    00044         numProblems = ps->numProblems;
    00045     return numProblems;
    00046 }
    00047
    00048 rpmpsi rpmpsInitIterator(rpmps ps)
    00049 {
    00050     rpmpsi psi = NULL;
    00051     if (ps != NULL) {
    00052         psi = xcalloc(1, sizeof(*psi));
    00053 /*@-assignexpose -castexpose @*/
    00054         psi->ps = rpmpsLink(ps, "iter ref");
    00055 /*@=assignexpose =castexpose @*/
    00056         psi->ix = -1;
    00057     }
    00058     return psi;
    00059 }
    00060
    00061 rpmpsi rpmpsFreeIterator(rpmpsi psi)
    00062 {
    00063     if (psi != NULL) {
    00064         psi->ps = rpmpsUnlink(psi->ps, "iter unref");
    00065         psi = _free(psi);
    00066     }
    00067     return NULL;
    00068 }
    00069
    00070 int rpmpsNextIterator(rpmpsi psi)
    00071 {
    00072     int i = -1;
    00073
    00074     if (psi != NULL && ++psi->ix >= 0) {
    00075         if (psi->ix < rpmpsNumProblems(psi->ps)) {
    00076             i = psi->ix;
    00077         } else {
    00078             psi->ix = -1;
    00079         }
    00080     }
    00081     return i;
    00082 }
    00083
    00084 rpmProblem rpmpsProblem(rpmpsi psi)
    00085 {
    00086     rpmProblem p = NULL;
    00087     if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) {
    00088         p = psi->ps->probs + psi->ix;
    00089     }
    00090     return p;
    00091 }
    00092
    00093 rpmps rpmpsCreate(void)
    00094 {
    00095 #ifdef  BUGGY
    00096     rpmps ps = rpmpsGetPool(_rpmpsPool);
    00097 #else
    00098     rpmps ps = rpmpsGetPool(NULL);
    00099 #endif
    00100     return rpmpsLink(ps, "create");
    00101 }
    00102
    00103 rpmps rpmpsFree(rpmps ps)
    00104 {
    00105     if (ps == NULL) return NULL;
    00106     yarnPossess(ps->_item.use);
    00107 /*@-modfilesys@*/
    00108 if (_rpmps_debug)
    00109 fprintf(stderr, "--> ps %p -- %ld %s at %s:%u\n", ps, yarnPeekLock(ps->_item.use), "rpmpsFree", __FILE__, __LINE__);
    00110 /*@=modfilesys@*/
    00111     if (yarnPeekLock(ps->_item.use) <= 1L) {
    00112         if (ps->probs) {
    00113             int i;
    00114             for (i = 0; i < ps->numProblems; i++) {
    00115                 rpmProblem p = ps->probs + i;
    00116                 p->pkgNEVR = _free(p->pkgNEVR);
    00117                 p->altNEVR = _free(p->altNEVR);
    00118                 p->str1 = _free(p->str1);
    00119             }
    00120             ps->probs = _free(ps->probs);
    00121         }
    00122         ps = (rpmps) rpmioPutPool((rpmioItem)ps);
    00123     } else
    00124         yarnTwist(ps->_item.use, BY, -1);
    00125     return NULL;
    00126 }
    00127
    00128 void rpmpsAppend(rpmps ps, rpmProblemType type,
    00129                 const char * pkgNEVR, fnpyKey key,
    00130                 const char * dn, const char * bn,
    00131                 const char * altNEVR, rpmuint64_t ulong1)
    00132 {
    00133     rpmProblem p;
    00134     char *t;
    00135
    00136     if (ps == NULL) return;
    00137
    00138     if (ps->numProblems == ps->numProblemsAlloced) {
    00139         if (ps->numProblemsAlloced)
    00140             ps->numProblemsAlloced *= 2;
    00141         else
    00142             ps->numProblemsAlloced = 2;
    00143         ps->probs = xrealloc(ps->probs,
    00144                         ps->numProblemsAlloced * sizeof(*ps->probs));
    00145     }
    00146
    00147     p = ps->probs + ps->numProblems;
    00148     ps->numProblems++;
    00149     memset(p, 0, sizeof(*p));
    00150
    00151     p->type = type;
    00152     p->key = key;
    00153     p->ulong1 = ulong1;
    00154     p->ignoreProblem = 0;
    00155
    00156     p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
    00157     p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
    00158
    00159     p->str1 = NULL;
    00160     if (dn != NULL || bn != NULL) {
    00161         t = xcalloc(1,  (dn != NULL ? strlen(dn) : 0) +
    00162                         (bn != NULL ? strlen(bn) : 0) + 1);
    00163         p->str1 = t;
    00164         if (dn != NULL) t = stpcpy(t, dn);
    00165         if (bn != NULL) t = stpcpy(t, bn);
    00166     }
    00167 }
    00168
    00169 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
    00170
    00171 int rpmpsTrim(rpmps ps, rpmps filter)
    00172 {
    00173     rpmProblem t;
    00174     rpmProblem f;
    00175     int gotProblems = 0;
    00176
    00177     if (ps == NULL || ps->numProblems == 0)
    00178         return 0;
    00179
    00180     if (filter == NULL)
    00181         return (ps->numProblems == 0 ? 0 : 1);
    00182
    00183     t = ps->probs;
    00184     f = filter->probs;
    00185
    00186     while ((f - filter->probs) < filter->numProblems) {
    00187         if (!f->ignoreProblem) {
    00188             f++;
    00189             continue;
    00190         }
    00191         while ((t - ps->probs) < ps->numProblems) {
    00192             /*@-nullpass@*/     /* LCL: looks good to me <shrug> */
    00193             if (f->type == t->type && t->key == f->key &&
    00194                      XSTRCMP(f->str1, t->str1))
    00195                 /*@innerbreak@*/ break;
    00196             /*@=nullpass@*/
    00197             t++;
    00198             gotProblems = 1;
    00199         }
    00200
    00201         /* XXX This can't happen, but let's be sane in case it does. */
    00202         if ((t - ps->probs) == ps->numProblems)
    00203             break;
    00204
    00205         t->ignoreProblem = f->ignoreProblem;
    00206         t++, f++;
    00207     }
    00208
    00209     if ((t - ps->probs) < ps->numProblems)
    00210         gotProblems = 1;
    00211
    00212     return gotProblems;
    00213 }
    00214
    00215 #if !defined(HAVE_VSNPRINTF)
    00216 /*@-shadow -bufferoverflowhigh @*/
    00217 static inline int vsnprintf(/*@out@*/ char * buf, /*@unused@*/ int nb,
    00218         const char * fmt, va_list ap)
    00219 {
    00220     return vsprintf(buf, fmt, ap);
    00221 }
    00222 /*@=shadow =bufferoverflowhigh @*/
    00223 #endif
    00224 #if !defined(HAVE_SNPRINTF)
    00225 static inline int snprintf(/*@out@*/ char * buf, int nb, const char * fmt, ...)
    00226 {
    00227     va_list ap;
    00228     int rc;
    00229     va_start(ap, fmt);
    00230     rc = vsnprintf(buf, nb, fmt, ap);
    00231     va_end(ap);
    00232     return rc;
    00233 }
    00234 #endif
    00235
    00236 const char * rpmProblemString(const rpmProblem prob)
    00237 {
    00238 /*@observer@*/
    00239     const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
    00240 /*@observer@*/
    00241     const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
    00242 /*@observer@*/
    00243     const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
    00244     size_t nb = strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 1024;
    00245     char * buf = xmalloc(nb+1);
    00246     int rc;
    00247
    00248     switch (prob->type) {
    00249     case RPMPROB_BADPLATFORM:
    00250         rc = snprintf(buf, nb,
    00251                 _("package %s is intended for a %s platform"),
    00252                 pkgNEVR, str1);
    00253         break;
    00254     case RPMPROB_PKG_INSTALLED:
    00255         rc = snprintf(buf, nb,
    00256                 _("package %s is already installed"),
    00257                 pkgNEVR);
    00258         break;
    00259     case RPMPROB_NOREPACKAGE:
    00260         rc = snprintf(buf, nb,
    00261                 _("re-packaged package with %s: %s is missing"),
    00262                 str1, altNEVR);
    00263         break;
    00264     case RPMPROB_BADRELOCATE:
    00265         rc = snprintf(buf, nb,
    00266                 _("path %s in package %s is not relocatable"),
    00267                 str1, pkgNEVR);
    00268         break;
    00269     case RPMPROB_NEW_FILE_CONFLICT:
    00270         rc = snprintf(buf, nb,
    00271                 _("file %s conflicts between attempted installs of %s and %s"),
    00272                 str1, pkgNEVR, altNEVR);
    00273         break;
    00274     case RPMPROB_FILE_CONFLICT:
    00275         rc = snprintf(buf, nb,
    00276             _("file %s from install of %s conflicts with file from package %s"),
    00277                 str1, pkgNEVR, altNEVR);
    00278         break;
    00279     case RPMPROB_OLDPACKAGE:
    00280         rc = snprintf(buf, nb,
    00281                 _("package %s (which is newer than %s) is already installed"),
    00282                 altNEVR, pkgNEVR);
    00283         break;
    00284     case RPMPROB_DISKSPACE:
    00285         rc = snprintf(buf, nb,
    00286             _("installing package %s needs %lu%cB on the %s filesystem"),
    00287                 pkgNEVR,
    00288                 (unsigned long) (prob->ulong1 > (1024*1024)
    00289                     ? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
    00290                     : (prob->ulong1 + 1023) / 1024),
    00291                 prob->ulong1 > (1024*1024) ? 'M' : 'K',
    00292                 str1);
    00293         break;
    00294     case RPMPROB_DISKNODES:
    00295         rc = snprintf(buf, nb,
    00296             _("installing package %s needs %lu inodes on the %s filesystem"),
    00297                 pkgNEVR, (unsigned long)prob->ulong1, str1);
    00298         break;
    00299     case RPMPROB_BADPRETRANS:
    00300         rc = snprintf(buf, nb,
    00301                 _("package %s pre-transaction syscall(s): %s failed: %s"),
    00302                 pkgNEVR, str1, strerror((int)(prob->ulong1)));
    00303         break;
    00304     case RPMPROB_REQUIRES:
    00305         rc = snprintf(buf, nb, _("%s is needed by %s%s"),
    00306                 altNEVR+2,
    00307                 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
    00308         break;
    00309     case RPMPROB_CONFLICT:
    00310         rc = snprintf(buf, nb, _("%s conflicts with %s%s"),
    00311                 altNEVR+2,
    00312                 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
    00313         break;
    00314     case RPMPROB_RDONLY:
    00315         rc = snprintf(buf, nb,
    00316             _("installing package %s on %s rdonly filesystem"),
    00317                 pkgNEVR, str1);
    00318         break;
    00319     default:
    00320         rc = snprintf(buf, nb,
    00321                 _("unknown error %d encountered while manipulating package %s"),
    00322                 prob->type, pkgNEVR);
    00323         break;
    00324     }
    00325
    00326     buf[nb] = '\0';
    00327     return buf;
    00328 }
    00329
    00330 static int sameProblem(const rpmProblem ap, const rpmProblem bp)
    00331         /*@*/
    00332 {
    00333     if (ap->type != bp->type)
    00334         return 1;
    00335     if (ap->pkgNEVR)
    00336         if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR))
    00337             return 1;
    00338     if (ap->altNEVR)
    00339         if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR))
    00340             return 1;
    00341     if (ap->str1)
    00342         if (bp->str1 && strcmp(ap->str1, bp->str1))
    00343             return 1;
    00344
    00345     if (ap->ulong1 != bp->ulong1)
    00346         return 1;
    00347
    00348     return 0;
    00349 }
    00350
    00351 void rpmpsPrint(FILE *fp, rpmps ps)
    00352 {
    00353     const char * msg;
    00354     rpmpsi psi;
    00355     int i;
    00356
    00357     if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
    00358         return;
    00359
    00360     if (fp == NULL)
    00361         fp = stderr;
    00362
    00363     psi = rpmpsInitIterator(ps);
    00364     while ((i = rpmpsNextIterator(psi)) >= 0) {
    00365         rpmProblem p = rpmpsProblem(psi);
    00366         rpmpsi psif;
    00367         int j;
    00368
    00369         if (p->ignoreProblem)
    00370             continue;
    00371
    00372         /* Filter already displayed problems. */
    00373         psif = rpmpsInitIterator(ps);
    00374         while ((j = rpmpsNextIterator(psif)) < i) {
    00375             if (!sameProblem(p, rpmpsProblem(psif)))
    00376                 /*@innerbreak@*/ break;
    00377         }
    00378         psif = rpmpsFreeIterator(psif);
    00379
    00380         if (j < i)
    00381             continue;
    00382
    00383         msg = rpmProblemString(p);
    00384         fprintf(fp, "\t%s\n", msg);
    00385         msg = _free(msg);
    00386
    00387     }
    00388     psi = rpmpsFreeIterator(psi);
    00389 }
    00390
    00391 rpmProblem rpmpsGetProblem(rpmps ps, int num)
    00392 {
    00393     if (ps == NULL)
    00394         return(NULL);
    00395     /* XXX Retrieve last problem with negative index. */
    00396     if (num < 0)
    00397         num = ps->numProblems - 1;
    00398     if (num >= ps->numProblems)
    00399         return(NULL);
    00400     return (ps->probs + num);
    00401 }
    00402
    00403 char * rpmProblemGetPkgNEVR(rpmProblem prob)
    00404 {
    00405     return prob->pkgNEVR;
    00406 }
    00407
    00408 char * rpmProblemGetAltNEVR(rpmProblem prob)
    00409 {
    00410     return prob->altNEVR;
    00411 }
    00412
    00413 char * rpmProblemGetStr(rpmProblem prob)
    00414 {
    00415     return prob->str1;
    00416 }
    00417
    00418 rpmuint64_t rpmProblemGetDiskNeed(rpmProblem prob)
    00419 {
    00420     return prob->ulong1;
    00421 }
    00422
    00423 rpmProblemType rpmProblemGetType(rpmProblem prob)
    00424 {
    00425     return prob->type;
    00426 }
    00427
    00428 fnpyKey rpmProblemKey(rpmProblem prob)
    00429 {
    00430     return prob->key;
    00431 }