rpm  5.2.1
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@*/
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 
41 {
42  int numProblems = 0;
43  if (ps && ps->probs)
44  numProblems = ps->numProblems;
45  return numProblems;
46 }
47 
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 
62 {
63  if (psi != NULL) {
64  psi->ps = rpmpsUnlink(psi->ps, "iter unref");
65  psi = _free(psi);
66  }
67  return NULL;
68 }
69 
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 
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 
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 
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 
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;
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;
270  rc = snprintf(buf, nb,
271  _("file %s conflicts between attempted installs of %s and %s"),
272  str1, pkgNEVR, altNEVR);
273  break;
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 
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 
404 {
405  return prob->pkgNEVR;
406 }
407 
409 {
410  return prob->altNEVR;
411 }
412 
414 {
415  return prob->str1;
416 }
417 
419 {
420  return prob->ulong1;
421 }
422 
424 {
425  return prob->type;
426 }
427 
429 {
430  return prob->key;
431 }