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 relocatable"),
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 }

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2