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
00015
00016
00017
00018 int _rpmps_debug = 0;
00019
00020 rpmps XrpmpsUnlink(rpmps ps, const char * msg,
00021 const char * fn, unsigned ln)
00022 {
00023
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
00027 ps->nrefs--;
00028
00029 return ps;
00030
00031 }
00032
00033 rpmps XrpmpsLink(rpmps ps, const char * msg,
00034 const char * fn, unsigned ln)
00035 {
00036 ps->nrefs++;
00037
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
00041
00042 return ps;
00043
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
00103 memset(p, 0, sizeof(*p));
00104
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
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
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
00150 if (f->type == t->type && t->key == f->key &&
00151 XSTRCMP(f->str1, t->str1))
00152 break;
00153
00154 t++;
00155 gotProblems = 1;
00156 }
00157
00158
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
00174 static inline int vsnprintf( char * buf, int nb,
00175 const char * fmt, va_list ap)
00176 {
00177 return vsprintf(buf, fmt, ap);
00178 }
00179
00180 #endif
00181 #if !defined(HAVE_SNPRINTF)
00182 static inline int snprintf( 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
00196 const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
00197
00198 const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
00199
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
00324 for (j = 0; j < i; j++) {
00325 if (!sameProblem(p, ps->probs + j))
00326 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 }