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