29 int numProblems; /*!< Current probs array size. */
30 int numProblemsAlloced; /*!< Allocated probs array size. */
31 rpmProblem *probs; /*!< Array of pointers to specific problems. */
32 int nrefs; /*!< Reference count. */
43 rpmps XrpmpsUnlink(rpmps ps, const char * msg,
44 const char * fn, unsigned ln)
46 if (_rpmps_debug > 0 && msg != NULL)
47 fprintf(stderr, "--> ps %p -- %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
52 rpmps XrpmpsLink(rpmps ps, const char * msg,
53 const char * fn, unsigned ln)
56 if (_rpmps_debug > 0 && msg != NULL)
57 fprintf(stderr, "--> ps %p ++ %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
61 int rpmpsNumProblems(rpmps ps)
65 numProblems = ps->numProblems;
69 rpmpsi rpmpsInitIterator(rpmps ps)
73 psi = xcalloc(1, sizeof(*psi));
74 psi->ps = rpmpsLink(ps, "iter ref");
80 rpmpsi rpmpsFreeIterator(rpmpsi psi)
83 rpmpsUnlink(psi->ps, "iter unref");
90 int rpmpsNextIterator(rpmpsi psi)
94 if (psi != NULL && ++psi->ix >= 0) {
95 if (psi->ix < rpmpsNumProblems(psi->ps)) {
104 rpmProblem rpmpsGetProblem(rpmpsi psi)
106 rpmProblem *p = NULL;
107 if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) {
108 p = psi->ps->probs + psi->ix;
113 rpmps rpmpsCreate(void)
115 rpmps ps = xcalloc(1, sizeof(*ps));
116 return rpmpsLink(ps, "create");
119 rpmps rpmpsFree(rpmps ps)
121 if (ps == NULL) return NULL;
122 ps = rpmpsUnlink(ps, "dereference");
127 rpmpsi psi = rpmpsInitIterator(ps);
128 while (rpmpsNextIterator(psi) >= 0) {
129 rpmProblemFree(rpmpsGetProblem(psi));
131 rpmpsFreeIterator(psi);
132 ps->probs = _free(ps->probs);
138 void rpmpsAppendProblem(rpmps ps, rpmProblem prob)
140 rpmProblem *p = NULL;
141 if (ps == NULL) return;
143 if (ps->numProblems == ps->numProblemsAlloced) {
144 if (ps->numProblemsAlloced)
145 ps->numProblemsAlloced *= 2;
147 ps->numProblemsAlloced = 2;
148 ps->probs = xrealloc(ps->probs,
149 ps->numProblemsAlloced * sizeof(ps->probs));
152 p = ps->probs + ps->numProblems;
157 void rpmpsAppend(rpmps ps, rpmProblemType type,
158 const char * pkgNEVR, fnpyKey key,
159 const char * dn, const char * bn,
160 const char * altNEVR, unsigned long ulong1)
163 if (ps == NULL) return;
165 p = rpmProblemCreate(type, pkgNEVR, key, dn, bn, altNEVR, ulong1);
166 rpmpsAppendProblem(ps, p);
169 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
171 /* XXX TODO: implement with iterators */
172 int rpmpsTrim(rpmps ps, rpmps filter)
178 if (ps == NULL || ps->numProblems == 0)
182 return (ps->numProblems == 0 ? 0 : 1);
187 while ((f - filter->probs) < filter->numProblems) {
188 if (!(*f)->ignoreProblem) {
192 while ((t - ps->probs) < ps->numProblems) {
193 /* LCL: looks good to me <shrug> */
194 if ((*f)->type == (*t)->type && (*t)->key == (*f)->key &&
195 XSTRCMP((*f)->str1, (*t)->str1))
201 /* XXX This can't happen, but let's be sane in case it does. */
202 if ((t - ps->probs) == ps->numProblems)
205 (*t)->ignoreProblem = (*f)->ignoreProblem;
209 if ((t - ps->probs) < ps->numProblems)
215 #if !defined(HAVE_VSNPRINTF)
216 static inline int vsnprintf(char * buf, int nb,
217 const char * fmt, va_list ap)
219 return vsprintf(buf, fmt, ap);
222 #if !defined(HAVE_SNPRINTF)
223 static inline int snprintf(char * buf, int nb, const char * fmt, ...)
228 rc = vsnprintf(buf, nb, fmt, ap);
234 rpmProblem rpmProblemCreate(rpmProblemType type,
235 const char * pkgNEVR,
237 const char * dn, const char * bn,
238 const char * altNEVR,
239 unsigned long ulong1)
241 rpmProblem p = xcalloc(1, sizeof(*p));
247 p->ignoreProblem = 0;
249 p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
250 p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
253 if (dn != NULL || bn != NULL) {
254 t = xcalloc(1, (dn != NULL ? strlen(dn) : 0) +
255 (bn != NULL ? strlen(bn) : 0) + 1);
257 if (dn != NULL) t = stpcpy(t, dn);
258 if (bn != NULL) t = stpcpy(t, bn);
263 rpmProblem rpmProblemFree(rpmProblem prob)
265 prob->pkgNEVR = _free(prob->pkgNEVR);
266 prob->altNEVR = _free(prob->altNEVR);
267 prob->str1 = _free(prob->str1);
272 const char * rpmProblemGetPkgNEVR(const rpmProblem p)
277 const char * rpmProblemGetAltNEVR(const rpmProblem p)
282 fnpyKey rpmProblemGetKey(const rpmProblem p)
287 rpmProblemType rpmProblemGetType(const rpmProblem p)
292 const char * rpmProblemGetStr(const rpmProblem p)
297 unsigned long rpmProblemGetLong(const rpmProblem p)
302 const char * rpmProblemString(const rpmProblem prob)
304 const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
305 const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
306 const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
307 int nb = strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 100;
308 char * buf = xmalloc(nb+1);
311 switch (prob->type) {
312 case RPMPROB_BADARCH:
313 rc = snprintf(buf, nb,
314 _("package %s is intended for a %s architecture"),
318 rc = snprintf(buf, nb,
319 _("package %s is intended for a %s operating system"),
322 case RPMPROB_PKG_INSTALLED:
323 rc = snprintf(buf, nb,
324 _("package %s is already installed"),
327 case RPMPROB_BADRELOCATE:
328 rc = snprintf(buf, nb,
329 _("path %s in package %s is not relocatable"),
332 case RPMPROB_NEW_FILE_CONFLICT:
333 rc = snprintf(buf, nb,
334 _("file %s conflicts between attempted installs of %s and %s"),
335 str1, pkgNEVR, altNEVR);
337 case RPMPROB_FILE_CONFLICT:
338 rc = snprintf(buf, nb,
339 _("file %s from install of %s conflicts with file from package %s"),
340 str1, pkgNEVR, altNEVR);
342 case RPMPROB_OLDPACKAGE:
343 rc = snprintf(buf, nb,
344 _("package %s (which is newer than %s) is already installed"),
347 case RPMPROB_DISKSPACE:
348 rc = snprintf(buf, nb,
349 _("installing package %s needs %ld%cB on the %s filesystem"),
351 prob->ulong1 > (1024*1024)
352 ? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
353 : (prob->ulong1 + 1023) / 1024,
354 prob->ulong1 > (1024*1024) ? 'M' : 'K',
357 case RPMPROB_DISKNODES:
358 rc = snprintf(buf, nb,
359 _("installing package %s needs %ld inodes on the %s filesystem"),
360 pkgNEVR, (long)prob->ulong1, str1);
362 case RPMPROB_REQUIRES:
363 rc = snprintf(buf, nb, _("%s is needed by %s%s"),
365 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
367 case RPMPROB_CONFLICT:
368 rc = snprintf(buf, nb, _("%s conflicts with %s%s"),
370 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
373 rc = snprintf(buf, nb,
374 _("unknown error %d encountered while manipulating package %s"),
375 prob->type, pkgNEVR);
383 static int sameProblem(const rpmProblem ap, const rpmProblem bp)
385 if (ap->type != bp->type)
388 if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR))
391 if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR))
394 if (bp->str1 && strcmp(ap->str1, bp->str1))
397 if (ap->ulong1 != bp->ulong1)
403 void rpmpsPrint(FILE *fp, rpmps ps)
409 if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
415 psi = rpmpsInitIterator(ps);
416 while ((i = rpmpsNextIterator(psi)) >= 0) {
418 rpmProblem p = rpmpsGetProblem(psi);
420 if (p->ignoreProblem)
423 rpmpsi psif = rpmpsInitIterator(ps);
424 /* Filter already displayed problems. */
425 while ((j = rpmpsNextIterator(psif)) < i) {
426 if (!sameProblem(p, rpmpsGetProblem(psif)))
429 rpmpsFreeIterator(psif);
433 msg = rpmProblemString(p);
434 fprintf(fp, "\t%s\n", msg);
438 psi = rpmpsFreeIterator(psi);