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

# lib/rpmps.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmlib.h>
    00008
    00009 #include "rpmps.h"
    00010
    00011 #include "misc.h"
    00012 #include "debug.h"
    00013
    00014 /*@access fnpyKey @*/
    00015 /*@access rpmProblem @*/
    00016
    00017 /*@unchecked@*/
    00018 int _rpmps_debug = 0;
    00019
    00020 rpmps XrpmpsUnlink(rpmps ps, const char * msg,
    00021                 const char * fn, unsigned ln)
    00022 {
    00023 /*@-modfilesys@*/
    00024 if (_rpmps_debug > 0 && msg != NULL)
    00025 fprintf(stderr, "--> ps %p -- %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
    00026 /*@=modfilesys@*/
    00027     ps->nrefs--;
    00028 /*@-refcounttrans@*/
    00029     return ps;
    00030 /*@=refcounttrans@*/
    00031 }
    00032
    00033 rpmps XrpmpsLink(rpmps ps, const char * msg,
    00034                 const char * fn, unsigned ln)
    00035 {
    00036     ps->nrefs++;
    00037 /*@-modfilesys@*/
    00038 if (_rpmps_debug > 0 && msg != NULL)
    00039 fprintf(stderr, "--> ps %p ++ %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
    00040 /*@=modfilesys@*/
    00041 /*@-refcounttrans@*/
    00042     return ps;
    00043 /*@=refcounttrans@*/
    00044 }
    00045
    00046 int rpmpsNumProblems(rpmps ps)
    00047 {
    00048     int numProblems = 0;
    00049     if (ps && ps->probs)
    00050         numProblems = ps->numProblems;
    00051     return numProblems;
    00052 }
    00053
    00054 rpmps rpmpsCreate(void)
    00055 {
    00056     rpmps ps = xcalloc(1, sizeof(*ps));
    00057     return rpmpsLink(ps, "create");
    00058 }
    00059
    00060 rpmps rpmpsFree(rpmps ps)
    00061 {
    00062     if (ps == NULL) return NULL;
    00063     ps = rpmpsUnlink(ps, "dereference");
    00064     if (ps->nrefs > 0)
    00065         return NULL;
    00066
    00067     if (ps->probs) {
    00068         int i;
    00069         for (i = 0; i < ps->numProblems; i++) {
    00070             rpmProblem p = ps->probs + i;
    00071             p->pkgNEVR = _free(p->pkgNEVR);
    00072             p->altNEVR = _free(p->altNEVR);
    00073             p->str1 = _free(p->str1);
    00074         }
    00075         ps->probs = _free(ps->probs);
    00076     }
    00077     ps = _free(ps);
    00078     return NULL;
    00079 }
    00080
    00081 void rpmpsAppend(rpmps ps, rpmProblemType type,
    00082                 const char * pkgNEVR, fnpyKey key,
    00083                 const char * dn, const char * bn,
    00084                 const char * altNEVR, unsigned long ulong1)
    00085 {
    00086     rpmProblem p;
    00087     char *t;
    00088
    00089     if (ps == NULL) return;
    00090
    00091     if (ps->numProblems == ps->numProblemsAlloced) {
    00092         if (ps->numProblemsAlloced)
    00093             ps->numProblemsAlloced *= 2;
    00094         else
    00095             ps->numProblemsAlloced = 2;
    00096         ps->probs = xrealloc(ps->probs,
    00097                         ps->numProblemsAlloced * sizeof(*ps->probs));
    00098     }
    00099
    00100     p = ps->probs + ps->numProblems;
    00101     ps->numProblems++;
    00102 /*@-boundswrite@*/
    00103     memset(p, 0, sizeof(*p));
    00104 /*@=boundswrite@*/
    00105
    00106     p->type = type;
    00107     p->key = key;
    00108     p->ulong1 = ulong1;
    00109     p->ignoreProblem = 0;
    00110
    00111     p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
    00112     p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
    00113
    00114     p->str1 = NULL;
    00115     if (dn != NULL || bn != NULL) {
    00116 /*@-boundswrite@*/
    00117         t = xcalloc(1,  (dn != NULL ? strlen(dn) : 0) +
    00118                         (bn != NULL ? strlen(bn) : 0) + 1);
    00119         p->str1 = t;
    00120         if (dn != NULL) t = stpcpy(t, dn);
    00121         if (bn != NULL) t = stpcpy(t, bn);
    00122 /*@=boundswrite@*/
    00123     }
    00124 }
    00125
    00126 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
    00127
    00128 int rpmpsTrim(rpmps ps, rpmps filter)
    00129 {
    00130     rpmProblem t;
    00131     rpmProblem f;
    00132     int gotProblems = 0;
    00133
    00134     if (ps == NULL || ps->numProblems == 0)
    00135         return 0;
    00136
    00137     if (filter == NULL)
    00138         return (ps->numProblems == 0 ? 0 : 1);
    00139
    00140     t = ps->probs;
    00141     f = filter->probs;
    00142
    00143     while ((f - filter->probs) < filter->numProblems) {
    00144         if (!f->ignoreProblem) {
    00145             f++;
    00146             continue;
    00147         }
    00148         while ((t - ps->probs) < ps->numProblems) {
    00149             /*@-nullpass@*/     /* LCL: looks good to me <shrug> */
    00150             if (f->type == t->type && t->key == f->key &&
    00151                      XSTRCMP(f->str1, t->str1))
    00152                 /*@innerbreak@*/ break;
    00153             /*@=nullpass@*/
    00154             t++;
    00155             gotProblems = 1;
    00156         }
    00157
    00158         /* XXX This can't happen, but let's be sane in case it does. */
    00159         if ((t - ps->probs) == ps->numProblems)
    00160             break;
    00161
    00162         t->ignoreProblem = f->ignoreProblem;
    00163         t++, f++;
    00164     }
    00165
    00166     if ((t - ps->probs) < ps->numProblems)
    00167         gotProblems = 1;
    00168
    00169     return gotProblems;
    00170 }
    00171
    00172 #if !defined(HAVE_VSNPRINTF)
    00173 /*@-shadow -bufferoverflowhigh @*/
    00174 static inline int vsnprintf(/*@out@*/ char * buf, /*@unused@*/ int nb,
    00175         const char * fmt, va_list ap)
    00176 {
    00177     return vsprintf(buf, fmt, ap);
    00178 }
    00179 /*@=shadow =bufferoverflowhigh @*/
    00180 #endif
    00181 #if !defined(HAVE_SNPRINTF)
    00182 static inline int snprintf(/*@out@*/ char * buf, int nb, const char * fmt, ...)
    00183 {
    00184     va_list ap;
    00185     int rc;
    00186     va_start(ap, fmt);
    00187     rc = vsnprintf(buf, nb, fmt, ap);
    00188     va_end(ap);
    00189     return rc;
    00190 }
    00191 #endif
    00192
    00193 const char * rpmProblemString(const rpmProblem prob)
    00194 {
    00195 /*@observer@*/
    00196     const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
    00197 /*@observer@*/
    00198     const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
    00199 /*@observer@*/
    00200     const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
    00201     int nb =    strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 100;
    00202     char * buf = xmalloc(nb+1);
    00203     int rc;
    00204
    00205     switch (prob->type) {
    00206     case RPMPROB_BADARCH:
    00207         rc = snprintf(buf, nb,
    00208                 _("package %s is intended for a %s architecture"),
    00209                 pkgNEVR, str1);
    00210         break;
    00211     case RPMPROB_BADOS:
    00212         rc = snprintf(buf, nb,
    00213                 _("package %s is intended for a %s operating system"),
    00214                 pkgNEVR, str1);
    00215         break;
    00216     case RPMPROB_PKG_INSTALLED:
    00217         rc = snprintf(buf, nb,
    00218                 _("package %s is already installed"),
    00219                 pkgNEVR);
    00220         break;
    00221     case RPMPROB_BADRELOCATE:
    00222         rc = snprintf(buf, nb,
    00223                 _("path %s in package %s is not relocateable"),
    00224                 str1, pkgNEVR);
    00225         break;
    00226     case RPMPROB_NEW_FILE_CONFLICT:
    00227         rc = snprintf(buf, nb,
    00228                 _("file %s conflicts between attempted installs of %s and %s"),
    00229                 str1, pkgNEVR, altNEVR);
    00230         break;
    00231     case RPMPROB_FILE_CONFLICT:
    00232         rc = snprintf(buf, nb,
    00233             _("file %s from install of %s conflicts with file from package %s"),
    00234                 str1, pkgNEVR, altNEVR);
    00235         break;
    00236     case RPMPROB_OLDPACKAGE:
    00237         rc = snprintf(buf, nb,
    00238                 _("package %s (which is newer than %s) is already installed"),
    00239                 altNEVR, pkgNEVR);
    00240         break;
    00241     case RPMPROB_DISKSPACE:
    00242         rc = snprintf(buf, nb,
    00243             _("installing package %s needs %ld%cB on the %s filesystem"),
    00244                 pkgNEVR,
    00245                 prob->ulong1 > (1024*1024)
    00246                     ? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
    00247                     : (prob->ulong1 + 1023) / 1024,
    00248                 prob->ulong1 > (1024*1024) ? 'M' : 'K',
    00249                 str1);
    00250         break;
    00251     case RPMPROB_DISKNODES:
    00252         rc = snprintf(buf, nb,
    00253             _("installing package %s needs %ld inodes on the %s filesystem"),
    00254                 pkgNEVR, (long)prob->ulong1, str1);
    00255         break;
    00256     case RPMPROB_BADPRETRANS:
    00257         rc = snprintf(buf, nb,
    00258                 _("package %s pre-transaction syscall(s): %s failed: %s"),
    00259                 pkgNEVR, str1, strerror(prob->ulong1));
    00260         break;
    00261     case RPMPROB_REQUIRES:
    00262         rc = snprintf(buf, nb, _("%s is needed by %s%s"),
    00263                 altNEVR+2,
    00264                 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
    00265         break;
    00266     case RPMPROB_CONFLICT:
    00267         rc = snprintf(buf, nb, _("%s conflicts with %s%s"),
    00268                 altNEVR+2,
    00269                 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
    00270         break;
    00271     default:
    00272         rc = snprintf(buf, nb,
    00273                 _("unknown error %d encountered while manipulating package %s"),
    00274                 prob->type, pkgNEVR);
    00275         break;
    00276     }
    00277
    00278     buf[nb] = '\0';
    00279     return buf;
    00280 }
    00281
    00282 static int sameProblem(const rpmProblem ap, const rpmProblem bp)
    00283         /*@*/
    00284 {
    00285     if (ap->type != bp->type)
    00286         return 1;
    00287     if (ap->pkgNEVR)
    00288         if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR))
    00289             return 1;
    00290     if (ap->altNEVR)
    00291         if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR))
    00292             return 1;
    00293     if (ap->str1)
    00294         if (bp->str1 && strcmp(ap->str1, bp->str1))
    00295             return 1;
    00296
    00297     if (ap->ulong1 != bp->ulong1)
    00298         return 1;
    00299
    00300     return 0;
    00301 }
    00302
    00303 void rpmpsPrint(FILE *fp, rpmps ps)
    00304 {
    00305     const char * msg;
    00306     int i;
    00307
    00308     if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
    00309         return;
    00310
    00311     if (fp == NULL)
    00312         fp = stderr;
    00313
    00314     for (i = 0; i < ps->numProblems; i++) {
    00315         rpmProblem p;
    00316         int j;
    00317
    00318         p = ps->probs + i;
    00319
    00320         if (p->ignoreProblem)
    00321             continue;
    00322
    00323         /* Filter already displayed problems. */
    00324         for (j = 0; j < i; j++) {
    00325             if (!sameProblem(p, ps->probs + j))
    00326                 /*@innerbreak@*/ break;
    00327         }
    00328         if (j < i)
    00329             continue;
    00330
    00331         msg = rpmProblemString(p);
    00332         fprintf(fp, "\t%s\n", msg);
    00333         msg = _free(msg);
    00334
    00335     }
    00336 }