00001
00005 #include "system.h"
00006
00007 #include <rpmio.h>
00008 #include <rpmiotypes.h>
00009 #include <rpmtypes.h>
00010 #include <yarn.h>
00011
00012 #define _RPMPS_INTERNAL
00013 #include "rpmps.h"
00014
00015 #include "debug.h"
00016
00017
00018
00019
00020
00021 int _rpmps_debug = 0;
00022
00023
00024 rpmioPool _rpmpsPool;
00025
00026 static rpmps rpmpsGetPool( rpmioPool pool)
00027
00028
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
00054 psi->ps = rpmpsLink(ps, "iter ref");
00055
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
00108 if (_rpmps_debug)
00109 fprintf(stderr, "--> ps %p -- %ld %s at %s:%u\n", ps, yarnPeekLock(ps->_item.use), "rpmpsFree", __FILE__, __LINE__);
00110
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
00193 if (f->type == t->type && t->key == f->key &&
00194 XSTRCMP(f->str1, t->str1))
00195 break;
00196
00197 t++;
00198 gotProblems = 1;
00199 }
00200
00201
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
00217 static inline int vsnprintf( char * buf, int nb,
00218 const char * fmt, va_list ap)
00219 {
00220 return vsprintf(buf, fmt, ap);
00221 }
00222
00223 #endif
00224 #if !defined(HAVE_SNPRINTF)
00225 static inline int snprintf( 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
00239 const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
00240
00241 const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
00242
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
00373 psif = rpmpsInitIterator(ps);
00374 while ((j = rpmpsNextIterator(psif)) < i) {
00375 if (!sameProblem(p, rpmpsProblem(psif)))
00376 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
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 }