• 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 <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 }

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