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

Generated on Fri Dec 3 2010 20:53:41 for rpm by  doxygen 1.7.2