Remove unimplemented, unused RPMPROB_BADPRETRANS
[platform/upstream/rpm.git] / lib / rpmps.c
1 /**
2  * \file lib/rpmps.c
3  */
4
5 #include "system.h"
6
7 #include <rpmlib.h>
8
9 #include "rpmps.h"
10
11 #include "misc.h"
12 #include "debug.h"
13
14
15 int _rpmps_debug = 0;
16
17 rpmps XrpmpsUnlink(rpmps ps, const char * msg,
18                 const char * fn, unsigned ln)
19 {
20 if (_rpmps_debug > 0 && msg != NULL)
21 fprintf(stderr, "--> ps %p -- %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
22     ps->nrefs--;
23     return ps;
24 }
25
26 rpmps XrpmpsLink(rpmps ps, const char * msg,
27                 const char * fn, unsigned ln)
28 {
29     ps->nrefs++;
30 if (_rpmps_debug > 0 && msg != NULL)
31 fprintf(stderr, "--> ps %p ++ %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
32     return ps;
33 }
34
35 int rpmpsNumProblems(rpmps ps)
36 {
37     int numProblems = 0;
38     if (ps && ps->probs)
39         numProblems = ps->numProblems;
40     return numProblems;
41 }
42
43 rpmps rpmpsCreate(void)
44 {
45     rpmps ps = xcalloc(1, sizeof(*ps));
46     return rpmpsLink(ps, "create");
47 }
48
49 rpmps rpmpsFree(rpmps ps)
50 {
51     if (ps == NULL) return NULL;
52     ps = rpmpsUnlink(ps, "dereference");
53     if (ps->nrefs > 0)
54         return NULL;
55         
56     if (ps->probs) {
57         int i;
58         for (i = 0; i < ps->numProblems; i++) {
59             rpmProblem p = ps->probs + i;
60             p->pkgNEVR = _free(p->pkgNEVR);
61             p->altNEVR = _free(p->altNEVR);
62             p->str1 = _free(p->str1);
63         }
64         ps->probs = _free(ps->probs);
65     }
66     ps = _free(ps);
67     return NULL;
68 }
69
70 void rpmpsAppend(rpmps ps, rpmProblemType type,
71                 const char * pkgNEVR, fnpyKey key,
72                 const char * dn, const char * bn,
73                 const char * altNEVR, unsigned long ulong1)
74 {
75     rpmProblem p;
76     char *t;
77
78     if (ps == NULL) return;
79
80     if (ps->numProblems == ps->numProblemsAlloced) {
81         if (ps->numProblemsAlloced)
82             ps->numProblemsAlloced *= 2;
83         else
84             ps->numProblemsAlloced = 2;
85         ps->probs = xrealloc(ps->probs,
86                         ps->numProblemsAlloced * sizeof(*ps->probs));
87     }
88
89     p = ps->probs + ps->numProblems;
90     ps->numProblems++;
91     memset(p, 0, sizeof(*p));
92
93     p->type = type;
94     p->key = key;
95     p->ulong1 = ulong1;
96     p->ignoreProblem = 0;
97
98     p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
99     p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
100
101     p->str1 = NULL;
102     if (dn != NULL || bn != NULL) {
103         t = xcalloc(1,  (dn != NULL ? strlen(dn) : 0) +
104                         (bn != NULL ? strlen(bn) : 0) + 1);
105         p->str1 = t;
106         if (dn != NULL) t = stpcpy(t, dn);
107         if (bn != NULL) t = stpcpy(t, bn);
108     }
109 }
110
111 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
112
113 int rpmpsTrim(rpmps ps, rpmps filter)
114 {
115     rpmProblem t;
116     rpmProblem f;
117     int gotProblems = 0;
118
119     if (ps == NULL || ps->numProblems == 0)
120         return 0;
121
122     if (filter == NULL)
123         return (ps->numProblems == 0 ? 0 : 1);
124
125     t = ps->probs;
126     f = filter->probs;
127
128     while ((f - filter->probs) < filter->numProblems) {
129         if (!f->ignoreProblem) {
130             f++;
131             continue;
132         }
133         while ((t - ps->probs) < ps->numProblems) {
134                 /* LCL: looks good to me <shrug> */
135             if (f->type == t->type && t->key == f->key &&
136                      XSTRCMP(f->str1, t->str1))
137                 break;
138             t++;
139             gotProblems = 1;
140         }
141
142         /* XXX This can't happen, but let's be sane in case it does. */
143         if ((t - ps->probs) == ps->numProblems)
144             break;
145
146         t->ignoreProblem = f->ignoreProblem;
147         t++, f++;
148     }
149
150     if ((t - ps->probs) < ps->numProblems)
151         gotProblems = 1;
152
153     return gotProblems;
154 }
155
156 #if !defined(HAVE_VSNPRINTF)
157 static inline int vsnprintf(char * buf, int nb,
158         const char * fmt, va_list ap)
159 {
160     return vsprintf(buf, fmt, ap);
161 }
162 #endif
163 #if !defined(HAVE_SNPRINTF)
164 static inline int snprintf(char * buf, int nb, const char * fmt, ...)
165 {
166     va_list ap;
167     int rc;
168     va_start(ap, fmt);
169     rc = vsnprintf(buf, nb, fmt, ap);
170     va_end(ap);
171     return rc;
172 }
173 #endif
174
175 const char * rpmProblemString(const rpmProblem prob)
176 {
177     const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
178     const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
179     const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
180     int nb =    strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 100;
181     char * buf = xmalloc(nb+1);
182     int rc;
183
184     switch (prob->type) {
185     case RPMPROB_BADARCH:
186         rc = snprintf(buf, nb,
187                 _("package %s is intended for a %s architecture"),
188                 pkgNEVR, str1);
189         break;
190     case RPMPROB_BADOS:
191         rc = snprintf(buf, nb,
192                 _("package %s is intended for a %s operating system"),
193                 pkgNEVR, str1);
194         break;
195     case RPMPROB_PKG_INSTALLED:
196         rc = snprintf(buf, nb,
197                 _("package %s is already installed"),
198                 pkgNEVR);
199         break;
200     case RPMPROB_BADRELOCATE:
201         rc = snprintf(buf, nb,
202                 _("path %s in package %s is not relocatable"),
203                 str1, pkgNEVR);
204         break;
205     case RPMPROB_NEW_FILE_CONFLICT:
206         rc = snprintf(buf, nb,
207                 _("file %s conflicts between attempted installs of %s and %s"),
208                 str1, pkgNEVR, altNEVR);
209         break;
210     case RPMPROB_FILE_CONFLICT:
211         rc = snprintf(buf, nb,
212             _("file %s from install of %s conflicts with file from package %s"),
213                 str1, pkgNEVR, altNEVR);
214         break;
215     case RPMPROB_OLDPACKAGE:
216         rc = snprintf(buf, nb,
217                 _("package %s (which is newer than %s) is already installed"),
218                 altNEVR, pkgNEVR);
219         break;
220     case RPMPROB_DISKSPACE:
221         rc = snprintf(buf, nb,
222             _("installing package %s needs %ld%cB on the %s filesystem"),
223                 pkgNEVR,
224                 prob->ulong1 > (1024*1024)
225                     ? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
226                     : (prob->ulong1 + 1023) / 1024,
227                 prob->ulong1 > (1024*1024) ? 'M' : 'K',
228                 str1);
229         break;
230     case RPMPROB_DISKNODES:
231         rc = snprintf(buf, nb,
232             _("installing package %s needs %ld inodes on the %s filesystem"),
233                 pkgNEVR, (long)prob->ulong1, str1);
234         break;
235     case RPMPROB_REQUIRES:
236         rc = snprintf(buf, nb, _("%s is needed by %s%s"),
237                 altNEVR+2,
238                 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
239         break;
240     case RPMPROB_CONFLICT:
241         rc = snprintf(buf, nb, _("%s conflicts with %s%s"),
242                 altNEVR+2,
243                 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
244         break;
245     default:
246         rc = snprintf(buf, nb,
247                 _("unknown error %d encountered while manipulating package %s"),
248                 prob->type, pkgNEVR);
249         break;
250     }
251
252     buf[nb] = '\0';
253     return buf;
254 }
255
256 static int sameProblem(const rpmProblem ap, const rpmProblem bp)
257 {
258     if (ap->type != bp->type)
259         return 1;
260     if (ap->pkgNEVR)
261         if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR))
262             return 1;
263     if (ap->altNEVR)
264         if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR))
265             return 1;
266     if (ap->str1)
267         if (bp->str1 && strcmp(ap->str1, bp->str1))
268             return 1;
269
270     if (ap->ulong1 != bp->ulong1)
271         return 1;
272
273     return 0;
274 }
275
276 void rpmpsPrint(FILE *fp, rpmps ps)
277 {
278     const char * msg;
279     int i;
280
281     if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
282         return;
283
284     if (fp == NULL)
285         fp = stderr;
286
287     for (i = 0; i < ps->numProblems; i++) {
288         rpmProblem p;
289         int j;
290
291         p = ps->probs + i;
292
293         if (p->ignoreProblem)
294             continue;
295
296         /* Filter already displayed problems. */
297         for (j = 0; j < i; j++) {
298             if (!sameProblem(p, ps->probs + j))
299                 break;
300         }
301         if (j < i)
302             continue;
303
304         msg = rpmProblemString(p);
305         fprintf(fp, "\t%s\n", msg);
306         msg = _free(msg);
307
308     }
309 }