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

# lib/rpmps.c

Go to the documentation of this file.

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