rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

rpmps.c
Go to the documentation of this file.
1
5 #include "system.h"
6
7 #include <rpmio.h>
8 #include <rpmiotypes.h> /* XXX fnpyKey */
9 #include <rpmtypes.h>
10 #include <yarn.h>
11
12 #define _RPMPS_INTERNAL
13 #include "rpmps.h"
14
15 #include "debug.h"
16
17 /*@access fnpyKey @*/
18 /*@access rpmProblem @*/
19
20 /*@unchecked@*/
21 int _rpmps_debug = 0;
22
23 /*@unchecked@*/ /*@only@*/ /*@null@*/
24 rpmioPool _rpmpsPool;
25
26 static rpmps rpmpsGetPool(/*@null@*/ rpmioPool pool)
27 /*@globals _rpmpsPool, fileSystem, internalState @*/
28 /*@modifies pool, _rpmpsPool, fileSystem, internalState @*/
29 {
30 rpmps ps;
31
32 if (_rpmpsPool == NULL) {
33 _rpmpsPool = rpmioNewPool("ps", sizeof(*ps), -1, _rpmps_debug,
34 NULL, NULL, NULL);
35 pool = _rpmpsPool;
36 }
37 return (rpmps) rpmioGetPool(pool, sizeof(*ps));
38 }
39
40 int rpmpsNumProblems(rpmps ps)
41 {
42 int numProblems = 0;
43 if (ps && ps->probs)
44 numProblems = ps->numProblems;
45 return numProblems;
46 }
47
48 rpmpsi rpmpsInitIterator(rpmps ps)
49 {
50 rpmpsi psi = NULL;
51 if (ps != NULL) {
52 psi = xcalloc(1, sizeof(*psi));
53 /*@-assignexpose -castexpose @*/
54 psi->ps = rpmpsLink(ps, "iter ref");
55 /*@=assignexpose =castexpose @*/
56 psi->ix = -1;
57 }
58 return psi;
59 }
60
61 rpmpsi rpmpsFreeIterator(rpmpsi psi)
62 {
63 if (psi != NULL) {
64 psi->ps = rpmpsUnlink(psi->ps, "iter unref");
65 psi = _free(psi);
66 }
67 return NULL;
68 }
69
70 int rpmpsNextIterator(rpmpsi psi)
71 {
72 int i = -1;
73
74 if (psi != NULL && ++psi->ix >= 0) {
75 if (psi->ix < rpmpsNumProblems(psi->ps)) {
76 i = psi->ix;
77 } else {
78 psi->ix = -1;
79 }
80 }
81 return i;
82 }
83
84 rpmProblem rpmpsProblem(rpmpsi psi)
85 {
86 rpmProblem p = NULL;
87 if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) {
88 p = psi->ps->probs + psi->ix;
89 }
90 return p;
91 }
92
93 rpmps rpmpsCreate(void)
94 {
95 #ifdef BUGGY
96 rpmps ps = rpmpsGetPool(_rpmpsPool);
97 #else
98 rpmps ps = rpmpsGetPool(NULL);
99 #endif
100 return rpmpsLink(ps, "create");
101 }
102
103 rpmps rpmpsFree(rpmps ps)
104 {
105 if (ps == NULL) return NULL;
106 yarnPossess(ps->_item.use);
107 /*@-modfilesys@*/
108 if (_rpmps_debug)
109 fprintf(stderr, "--> ps %p -- %ld %s at %s:%u\n", ps, yarnPeekLock(ps->_item.use), "rpmpsFree", __FILE__, __LINE__);
110 /*@=modfilesys@*/
111 if (yarnPeekLock(ps->_item.use) <= 1L) {
112 if (ps->probs) {
113 int i;
114 for (i = 0; i < ps->numProblems; i++) {
115 rpmProblem p = ps->probs + i;
116 p->pkgNEVR = _free(p->pkgNEVR);
117 p->altNEVR = _free(p->altNEVR);
118 p->str1 = _free(p->str1);
119 }
120 ps->probs = _free(ps->probs);
121 }
122 ps = (rpmps) rpmioPutPool((rpmioItem)ps);
123 } else
124 yarnTwist(ps->_item.use, BY, -1);
125 return NULL;
126 }
127
128 void rpmpsAppend(rpmps ps, rpmProblemType type,
129 const char * pkgNEVR, fnpyKey key,
130 const char * dn, const char * bn,
131 const char * altNEVR, rpmuint64_t ulong1)
132 {
133 rpmProblem p;
134 char *t;
135
136 if (ps == NULL) return;
137
138 if (ps->numProblems == ps->numProblemsAlloced) {
139 if (ps->numProblemsAlloced)
140 ps->numProblemsAlloced *= 2;
141 else
142 ps->numProblemsAlloced = 2;
143 ps->probs = xrealloc(ps->probs,
144 ps->numProblemsAlloced * sizeof(*ps->probs));
145 }
146
147 p = ps->probs + ps->numProblems;
148 ps->numProblems++;
149 memset(p, 0, sizeof(*p));
150
151 p->type = type;
152 p->key = key;
153 p->ulong1 = ulong1;
154 p->ignoreProblem = 0;
155
156 p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
157 p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
158
159 p->str1 = NULL;
160 if (dn != NULL || bn != NULL) {
161 t = xcalloc(1, (dn != NULL ? strlen(dn) : 0) +
162 (bn != NULL ? strlen(bn) : 0) + 1);
163 p->str1 = t;
164 if (dn != NULL) t = stpcpy(t, dn);
165 if (bn != NULL) t = stpcpy(t, bn);
166 }
167 }
168
169 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
170
171 int rpmpsTrim(rpmps ps, rpmps filter)
172 {
173 rpmProblem t;
174 rpmProblem f;
175 int gotProblems = 0;
176
177 if (ps == NULL || ps->numProblems == 0)
178 return 0;
179
180 if (filter == NULL)
181 return (ps->numProblems == 0 ? 0 : 1);
182
183 t = ps->probs;
184 f = filter->probs;
185
186 while ((f - filter->probs) < filter->numProblems) {
187 if (!f->ignoreProblem) {
188 f++;
189 continue;
190 }
191 while ((t - ps->probs) < ps->numProblems) {
192 /*@-nullpass@*/ /* LCL: looks good to me <shrug> */
193 if (f->type == t->type && t->key == f->key &&
194 XSTRCMP(f->str1, t->str1))
195 /*@innerbreak@*/ break;
196 /*@=nullpass@*/
197 t++;
198 gotProblems = 1;
199 }
200
201 /* XXX This can't happen, but let's be sane in case it does. */
202 if ((t - ps->probs) == ps->numProblems)
203 break;
204
205 t->ignoreProblem = f->ignoreProblem;
206 t++, f++;
207 }
208
209 if ((t - ps->probs) < ps->numProblems)
210 gotProblems = 1;
211
212 return gotProblems;
213 }
214
215 #if !defined(HAVE_VSNPRINTF)
216 /*@-shadow -bufferoverflowhigh @*/
217 static inline int vsnprintf(/*@out@*/ char * buf, /*@unused@*/ int nb,
218 const char * fmt, va_list ap)
219 {
220 return vsprintf(buf, fmt, ap);
221 }
222 /*@=shadow =bufferoverflowhigh @*/
223 #endif
224 #if !defined(HAVE_SNPRINTF)
225 static inline int snprintf(/*@out@*/ char * buf, int nb, const char * fmt, ...)
226 {
227 va_list ap;
228 int rc;
229 va_start(ap, fmt);
230 rc = vsnprintf(buf, nb, fmt, ap);
231 va_end(ap);
232 return rc;
233 }
234 #endif
235
236 const char * rpmProblemString(const rpmProblem prob)
237 {
238 /*@observer@*/
239 const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
240 /*@observer@*/
241 const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
242 /*@observer@*/
243 const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
244 size_t nb = strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 1024;
245 char * buf = xmalloc(nb+1);
246 int rc;
247
248 switch (prob->type) {
249 case RPMPROB_BADPLATFORM:
250 rc = snprintf(buf, nb,
251 _("package %s is intended for a %s platform"),
252 pkgNEVR, str1);
253 break;
254 case RPMPROB_PKG_INSTALLED:
255 rc = snprintf(buf, nb,
256 _("package %s is already installed"),
257 pkgNEVR);
258 break;
259 case RPMPROB_NOREPACKAGE:
260 rc = snprintf(buf, nb,
261 _("re-packaged package with %s: %s is missing"),
262 str1, altNEVR);
263 break;
264 case RPMPROB_BADRELOCATE:
265 rc = snprintf(buf, nb,
266 _("path %s in package %s is not relocatable"),
267 str1, pkgNEVR);
268 break;
269 case RPMPROB_NEW_FILE_CONFLICT:
270 rc = snprintf(buf, nb,
271 _("file %s conflicts between attempted installs of %s and %s"),
272 str1, pkgNEVR, altNEVR);
273 break;
274 case RPMPROB_FILE_CONFLICT:
275 rc = snprintf(buf, nb,
276 _("file %s from install of %s conflicts with file from package %s"),
277 str1, pkgNEVR, altNEVR);
278 break;
279 case RPMPROB_OLDPACKAGE:
280 rc = snprintf(buf, nb,
281 _("package %s (which is newer than %s) is already installed"),
282 altNEVR, pkgNEVR);
283 break;
284 case RPMPROB_DISKSPACE:
285 rc = snprintf(buf, nb,
286 _("installing package %s needs %lu%cB on the %s filesystem"),
287 pkgNEVR,
288 (unsigned long) (prob->ulong1 > (1024*1024)
289 ? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
290 : (prob->ulong1 + 1023) / 1024),
291 prob->ulong1 > (1024*1024) ? 'M' : 'K',
292 str1);
293 break;
294 case RPMPROB_DISKNODES:
295 rc = snprintf(buf, nb,
296 _("installing package %s needs %lu inodes on the %s filesystem"),
297 pkgNEVR, (unsigned long)prob->ulong1, str1);
298 break;
299 case RPMPROB_BADPRETRANS:
300 rc = snprintf(buf, nb,
301 _("package %s pre-transaction syscall(s): %s failed: %s"),
302 pkgNEVR, str1, strerror((int)(prob->ulong1)));
303 break;
304 case RPMPROB_REQUIRES:
305 rc = snprintf(buf, nb, _("%s is needed by %s%s"),
306 altNEVR+2,
307 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
308 break;
309 case RPMPROB_CONFLICT:
310 rc = snprintf(buf, nb, _("%s conflicts with %s%s"),
311 altNEVR+2,
312 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
313 break;
314 case RPMPROB_RDONLY:
315 rc = snprintf(buf, nb,
316 _("installing package %s on %s rdonly filesystem"),
317 pkgNEVR, str1);
318 break;
319 default:
320 rc = snprintf(buf, nb,
321 _("unknown error %d encountered while manipulating package %s"),
322 prob->type, pkgNEVR);
323 break;
324 }
325
326 buf[nb] = '\0';
327 return buf;
328 }
329
330 static int sameProblem(const rpmProblem ap, const rpmProblem bp)
331 /*@*/
332 {
333 if (ap->type != bp->type)
334 return 1;
335 if (ap->pkgNEVR)
336 if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR))
337 return 1;
338 if (ap->altNEVR)
339 if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR))
340 return 1;
341 if (ap->str1)
342 if (bp->str1 && strcmp(ap->str1, bp->str1))
343 return 1;
344
345 if (ap->ulong1 != bp->ulong1)
346 return 1;
347
348 return 0;
349 }
350
351 void rpmpsPrint(FILE *fp, rpmps ps)
352 {
353 const char * msg;
354 rpmpsi psi;
355 int i;
356
357 if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
358 return;
359
360 if (fp == NULL)
361 fp = stderr;
362
363 psi = rpmpsInitIterator(ps);
364 while ((i = rpmpsNextIterator(psi)) >= 0) {
365 rpmProblem p = rpmpsProblem(psi);
366 rpmpsi psif;
367 int j;
368
369 if (p->ignoreProblem)
370 continue;
371
372 /* Filter already displayed problems. */
373 psif = rpmpsInitIterator(ps);
374 while ((j = rpmpsNextIterator(psif)) < i) {
375 if (!sameProblem(p, rpmpsProblem(psif)))
376 /*@innerbreak@*/ break;
377 }
378 psif = rpmpsFreeIterator(psif);
379
380 if (j < i)
381 continue;
382
383 msg = rpmProblemString(p);
384 fprintf(fp, "\t%s\n", msg);
385 msg = _free(msg);
386
387 }
388 psi = rpmpsFreeIterator(psi);
389 }
390
391 rpmProblem rpmpsGetProblem(rpmps ps, int num)
392 {
393 if (ps == NULL)
394 return(NULL);
395 /* XXX Retrieve last problem with negative index. */
396 if (num < 0)
397 num = ps->numProblems - 1;
398 if (num >= ps->numProblems)
399 return(NULL);
400 return (ps->probs + num);
401 }
402
403 char * rpmProblemGetPkgNEVR(rpmProblem prob)
404 {
405 return prob->pkgNEVR;
406 }
407
408 char * rpmProblemGetAltNEVR(rpmProblem prob)
409 {
410 return prob->altNEVR;
411 }
412
413 char * rpmProblemGetStr(rpmProblem prob)
414 {
415 return prob->str1;
416 }
417
418 rpmuint64_t rpmProblemGetDiskNeed(rpmProblem prob)
419 {
420 return prob->ulong1;
421 }
422
423 rpmProblemType rpmProblemGetType(rpmProblem prob)
424 {
425 return prob->type;
426 }
427
428 fnpyKey rpmProblemKey(rpmProblem prob)
429 {
430 return prob->key;
431 }