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