9 #include <rpm/rpmstring.h>
10 #include <rpm/rpmps.h>
30 int numProblems; /*!< Current probs array size. */
31 int numProblemsAlloced; /*!< Allocated probs array size. */
32 rpmProblem *probs; /*!< Array of pointers to specific problems. */
33 int nrefs; /*!< Reference count. */
44 rpmps rpmpsUnlink(rpmps ps, const char * msg)
52 rpmps rpmpsLink(rpmps ps, const char * msg)
60 int rpmpsNumProblems(rpmps ps)
64 numProblems = ps->numProblems;
68 rpmpsi rpmpsInitIterator(rpmps ps)
72 psi = xcalloc(1, sizeof(*psi));
73 psi->ps = rpmpsLink(ps, RPMDBG_M("rpmpsInitIterator"));
79 rpmpsi rpmpsFreeIterator(rpmpsi psi)
82 rpmpsUnlink(psi->ps, RPMDBG_M("rpmpsFreeIterator"));
89 int rpmpsNextIterator(rpmpsi psi)
93 if (psi != NULL && ++psi->ix >= 0) {
94 if (psi->ix < rpmpsNumProblems(psi->ps)) {
103 rpmProblem rpmpsGetProblem(rpmpsi psi)
105 rpmProblem *p = NULL;
106 if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) {
107 p = psi->ps->probs + psi->ix;
109 return p ? *p : NULL;
112 rpmps rpmpsCreate(void)
114 rpmps ps = xcalloc(1, sizeof(*ps));
115 return rpmpsLink(ps, RPMDBG_M("rpmpsCreate"));
118 rpmps rpmpsFree(rpmps ps)
120 if (ps == NULL) return NULL;
122 return rpmpsUnlink(ps, RPMDBG_M("rpmpsFree"));
126 rpmpsi psi = rpmpsInitIterator(ps);
127 while (rpmpsNextIterator(psi) >= 0) {
128 rpmProblemFree(rpmpsGetProblem(psi));
130 rpmpsFreeIterator(psi);
131 ps->probs = _free(ps->probs);
137 void rpmpsAppendProblem(rpmps ps, rpmProblem prob)
139 rpmProblem *p = NULL;
140 if (ps == NULL) return;
142 if (ps->numProblems == ps->numProblemsAlloced) {
143 if (ps->numProblemsAlloced)
144 ps->numProblemsAlloced *= 2;
146 ps->numProblemsAlloced = 2;
147 ps->probs = xrealloc(ps->probs,
148 ps->numProblemsAlloced * sizeof(ps->probs));
151 p = ps->probs + ps->numProblems;
153 *p = rpmProblemLink(prob);
156 void rpmpsAppend(rpmps ps, rpmProblemType type,
157 const char * pkgNEVR, fnpyKey key,
158 const char * dn, const char * bn,
159 const char * altNEVR, uint64_t number)
162 if (ps == NULL) return;
164 p = rpmProblemCreate(type, pkgNEVR, key, dn, bn, altNEVR, number);
165 rpmpsAppendProblem(ps, p);
169 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && rstreq((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 if ((*f)->type == (*t)->type && (*t)->key == (*f)->key &&
194 XSTRCMP((*f)->str1, (*t)->str1))
200 /* XXX This can't happen, but let's be sane in case it does. */
201 if ((t - ps->probs) == ps->numProblems)
204 (*t)->ignoreProblem = (*f)->ignoreProblem;
208 if ((t - ps->probs) < ps->numProblems)
214 rpmProblem rpmProblemCreate(rpmProblemType type,
215 const char * pkgNEVR,
217 const char * dn, const char * bn,
218 const char * altNEVR,
221 rpmProblem p = xcalloc(1, sizeof(*p));
227 p->ignoreProblem = 0;
229 p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
230 p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
233 if (dn != NULL || bn != NULL) {
234 t = xcalloc(1, (dn != NULL ? strlen(dn) : 0) +
235 (bn != NULL ? strlen(bn) : 0) + 1);
237 if (dn != NULL) t = stpcpy(t, dn);
238 if (bn != NULL) t = stpcpy(t, bn);
240 return rpmProblemLink(p);
243 rpmProblem rpmProblemFree(rpmProblem prob)
245 if (prob == NULL) return NULL;
247 if (prob->nrefs > 1) {
248 return rpmProblemUnlink(prob);
250 prob->pkgNEVR = _free(prob->pkgNEVR);
251 prob->altNEVR = _free(prob->altNEVR);
252 prob->str1 = _free(prob->str1);
257 rpmProblem rpmProblemLink(rpmProblem prob)
265 rpmProblem rpmProblemUnlink(rpmProblem prob)
273 const char * rpmProblemGetPkgNEVR(const rpmProblem p)
278 const char * rpmProblemGetAltNEVR(const rpmProblem p)
283 fnpyKey rpmProblemGetKey(const rpmProblem p)
288 rpmProblemType rpmProblemGetType(const rpmProblem p)
293 const char * rpmProblemGetStr(const rpmProblem p)
298 rpm_loff_t rpmProblemGetDiskNeed(const rpmProblem p)
303 char * rpmProblemString(const rpmProblem prob)
305 const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
306 const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
307 const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
311 switch (prob->type) {
312 case RPMPROB_BADARCH:
313 rc = rasprintf(&buf, _("package %s is intended for a %s architecture"),
318 _("package %s is intended for a %s operating system"),
321 case RPMPROB_PKG_INSTALLED:
322 rc = rasprintf(&buf, _("package %s is already installed"),
325 case RPMPROB_BADRELOCATE:
326 rc = rasprintf(&buf, _("path %s in package %s is not relocatable"),
329 case RPMPROB_NEW_FILE_CONFLICT:
331 _("file %s conflicts between attempted installs of %s and %s"),
332 str1, pkgNEVR, altNEVR);
334 case RPMPROB_FILE_CONFLICT:
336 _("file %s from install of %s conflicts with file from package %s"),
337 str1, pkgNEVR, altNEVR);
339 case RPMPROB_OLDPACKAGE:
341 _("package %s (which is newer than %s) is already installed"),
344 case RPMPROB_DISKSPACE:
346 _("installing package %s needs %" PRIu64 "%cB on the %s filesystem"),
348 prob->num1 > (1024*1024)
349 ? (prob->num1 + 1024 * 1024 - 1) / (1024 * 1024)
350 : (prob->num1 + 1023) / 1024,
351 prob->num1 > (1024*1024) ? 'M' : 'K',
354 case RPMPROB_DISKNODES:
356 _("installing package %s needs %" PRIu64 " inodes on the %s filesystem"),
357 pkgNEVR, prob->num1, str1);
359 case RPMPROB_REQUIRES:
360 rc = rasprintf(&buf, _("%s is needed by %s%s"),
362 (prob->num1 ? "" : _("(installed) ")), pkgNEVR);
364 case RPMPROB_CONFLICT:
365 rc = rasprintf(&buf, _("%s conflicts with %s%s"),
367 (prob->num1 ? "" : _("(installed) ")), pkgNEVR);
371 _("unknown error %d encountered while manipulating package %s"),
372 prob->type, pkgNEVR);
379 static int sameProblem(const rpmProblem ap, const rpmProblem bp)
381 if (ap->type != bp->type)
384 if (bp->pkgNEVR && !rstreq(ap->pkgNEVR, bp->pkgNEVR))
387 if (bp->altNEVR && !rstreq(ap->altNEVR, bp->altNEVR))
390 if (bp->str1 && !rstreq(ap->str1, bp->str1))
393 if (ap->num1 != bp->num1)
399 void rpmpsPrint(FILE *fp, rpmps ps)
405 if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
411 psi = rpmpsInitIterator(ps);
412 while ((i = rpmpsNextIterator(psi)) >= 0) {
414 rpmProblem p = rpmpsGetProblem(psi);
416 if (p->ignoreProblem)
419 rpmpsi psif = rpmpsInitIterator(ps);
420 /* Filter already displayed problems. */
421 while ((j = rpmpsNextIterator(psif)) < i) {
422 if (sameProblem(p, rpmpsGetProblem(psif)))
425 rpmpsFreeIterator(psif);
429 msg = rpmProblemString(p);
430 fprintf(fp, "\t%s\n", msg);
434 psi = rpmpsFreeIterator(psi);