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