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