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