rpm  4.5
rpmds.c
Go to the documentation of this file.
1 
4 #include "system.h"
5 
6 #if HAVE_GELF_H
7 #if LIBELF_H_LFS_CONFLICT
8 /* Some implementations of libelf.h/gelf.h are incompatible with
9  * the Large File API.
10  */
11 # undef _LARGEFILE64_SOURCE
12 # undef _LARGEFILE_SOURCE
13 # undef _FILE_OFFSET_BITS
14 # define _FILE_OFFSET_BITS 32
15 #endif
16 
17 #include <gelf.h>
18 /*
19  * On Solaris, gelf.h included libelf.h, which #undef'ed the gettext
20  * convenience macro _(). Repair by repeating (from system.h) just
21  * the bits that are needed for _() to function.
22  */
23 
24 #if defined(__sun)
25 #if ENABLE_NLS && !defined(__LCLINT__)
26 # define _(Text) gettext (Text)
27 #else
28 # define _(Text) Text
29 #endif /* gettext _() fixup */
30 #endif
31 #endif /* HAVE_GELF_H */
32 
33 #if HAVE_LIBELF && !HAVE_GELF_GETVERNAUX
34 /* We have gelf.h and libelf, but we don't have some of the
35  * helper functions gelf_getvernaux(), gelf_getverneed(), etc.
36  * Provide our own simple versions here.
37  */
38 
39 static GElf_Verdef *gelf_getverdef(Elf_Data *data, int offset,
40  GElf_Verdef *dst)
41 {
42  return (GElf_Verdef *) ((char *) data->d_buf + offset);
43 }
44 
45 static GElf_Verdaux *gelf_getverdaux(Elf_Data *data, int offset,
46  GElf_Verdaux *dst)
47 {
48  return (GElf_Verdaux *) ((char *) data->d_buf + offset);
49 }
50 
51 static GElf_Verneed *gelf_getverneed(Elf_Data *data, int offset,
52  GElf_Verneed *dst)
53 {
54  return (GElf_Verneed *) ((char *) data->d_buf + offset);
55 }
56 
57 static GElf_Vernaux *gelf_getvernaux(Elf_Data *data, int offset,
58  GElf_Vernaux *dst)
59 {
60  return (GElf_Vernaux *) ((char *) data->d_buf + offset);
61 }
62 
63 /* Most non-Linux systems won't have SHT_GNU_verdef or SHT_GNU_verneed,
64  * but they might have something mostly-equivalent. Solaris has
65  * SHT_SUNW_{verdef,verneed}
66  */
67 #if !defined(SHT_GNU_verdef) && defined(__sun) && defined(SHT_SUNW_verdef)
68 # define SHT_GNU_verdef SHT_SUNW_verdef
69 # define SHT_GNU_verneed SHT_SUNW_verneed
70 #endif
71 
72 #endif /* HAVE_LIBELF && !HAVE_GELF_GETVERNAUX */
73 
74 #if !defined(DT_GNU_HASH)
75 #define DT_GNU_HASH 0x6ffffef5
76 #endif
77 
78 #include <rpmio_internal.h> /* XXX fdGetFILE */
79 #include <rpmlib.h>
80 #include <rpmmacro.h>
81 
82 #define _RPMDS_INTERNAL
83 #define _RPMEVR_INTERNAL
84 #define _RPMPRCO_INTERNAL
85 #include <rpmds.h>
86 
87 #include <argv.h>
88 
89 #include "debug.h"
90 
91 /*@access rpmns @*/
92 /*@access EVR_t @*/
93 
94 #define _isspace(_c) \
95  ((_c) == ' ' || (_c) == '\t' || (_c) == '\r' || (_c) == '\n')
96 
100 /*@unchecked@*/
102 
103 /*@unchecked@*/
104 int _rpmds_debug = 0;
105 
106 /*@unchecked@*/
108 
109 /*@unchecked@*/
110 /*@-exportheadervar@*/
112 /*@=exportheadervar@*/
113 
114 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
115 {
116  if (ds == NULL) return NULL;
117 /*@-modfilesys@*/
118 if (_rpmds_debug && msg != NULL)
119 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
120 /*@=modfilesys@*/
121  ds->nrefs--;
122  return NULL;
123 }
124 
125 rpmds XrpmdsLink(rpmds ds, const char * msg, const char * fn, unsigned ln)
126 {
127  if (ds == NULL) return NULL;
128  ds->nrefs++;
129 
130 /*@-modfilesys@*/
131 if (_rpmds_debug && msg != NULL)
132 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
133 /*@=modfilesys@*/
134 
135  /*@-refcounttrans@*/ return ds; /*@=refcounttrans@*/
136 }
137 
139 {
140  HFD_t hfd = headerFreeData;
141  rpmTag tagEVR, tagF;
142 
143  if (ds == NULL)
144  return NULL;
145 
146  if (ds->nrefs > 1)
147  return rpmdsUnlink(ds, ds->Type);
148 
149 /*@-modfilesys@*/
150 if (_rpmds_debug < 0)
151 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
152 /*@=modfilesys@*/
153 
154  if (ds->tagN == RPMTAG_PROVIDENAME) {
155  tagEVR = RPMTAG_PROVIDEVERSION;
156  tagF = RPMTAG_PROVIDEFLAGS;
157  } else
158  if (ds->tagN == RPMTAG_REQUIRENAME) {
159  tagEVR = RPMTAG_REQUIREVERSION;
160  tagF = RPMTAG_REQUIREFLAGS;
161  } else
162  if (ds->tagN == RPMTAG_CONFLICTNAME) {
163  tagEVR = RPMTAG_CONFLICTVERSION;
164  tagF = RPMTAG_CONFLICTFLAGS;
165  } else
166  if (ds->tagN == RPMTAG_OBSOLETENAME) {
167  tagEVR = RPMTAG_OBSOLETEVERSION;
168  tagF = RPMTAG_OBSOLETEFLAGS;
169  } else
170  if (ds->tagN == RPMTAG_TRIGGERNAME) {
171  tagEVR = RPMTAG_TRIGGERVERSION;
172  tagF = RPMTAG_TRIGGERFLAGS;
173  } else
174  if (ds->tagN == RPMTAG_DIRNAMES) {
175  tagEVR = 0;
176  tagF = 0;
177  } else
178  if (ds->tagN == RPMTAG_FILELINKTOS) {
179  tagEVR = 0;
180  tagF = 0;
181  } else
182  return NULL;
183 
184  /*@-branchstate@*/
185  if (ds->Count > 0) {
186  ds->N = hfd(ds->N, ds->Nt);
187  ds->EVR = hfd(ds->EVR, ds->EVRt);
188  /*@-evalorder@*/
189  ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
190  /*@=evalorder@*/
191  ds->h = headerFree(ds->h);
192  }
193  /*@=branchstate@*/
194 
195  ds->DNEVR = _free(ds->DNEVR);
196  ds->ns.str = _free(ds->ns.str);
197  memset(&ds->ns, 0, sizeof(ds->ns));
198  ds->A = _free(ds->A);
199  ds->Color = _free(ds->Color);
200  ds->Refs = _free(ds->Refs);
201  ds->Result = _free(ds->Result);
202 
203  (void) rpmdsUnlink(ds, ds->Type);
204  /*@-refcounttrans -usereleased@*/
205 /*@-boundswrite@*/
206  memset(ds, 0, sizeof(*ds)); /* XXX trash and burn */
207 /*@=boundswrite@*/
208  ds = _free(ds);
209  /*@=refcounttrans =usereleased@*/
210  return NULL;
211 }
212 
213 /*@-bounds@*/
214 static /*@null@*/
215 const char ** rpmdsDupArgv(/*@null@*/ const char ** argv, int argc)
216  /*@*/
217 {
218  const char ** av;
219  size_t nb = 0;
220  int ac = 0;
221  char * t;
222 
223  if (argv == NULL)
224  return NULL;
225  for (ac = 0; ac < argc; ac++) {
226 assert(argv[ac] != NULL);
227  nb += strlen(argv[ac]) + 1;
228  }
229  nb += (ac + 1) * sizeof(*av);
230 
231  av = xmalloc(nb);
232  t = (char *) (av + ac + 1);
233  for (ac = 0; ac < argc; ac++) {
234  av[ac] = t;
235  t = stpcpy(t, argv[ac]) + 1;
236  }
237  av[ac] = NULL;
238 /*@-nullret@*/
239  return av;
240 /*@=nullret@*/
241 }
242 /*@=bounds@*/
243 
244 rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
245 {
246  HFD_t hfd = headerFreeData;
247  int scareMem = (flags & 0x1);
248  HGE_t hge =
250  rpmTag tagEVR, tagF;
251  rpmds ds = NULL;
252  const char * Type;
253  const char ** N;
254  rpmTagType Nt;
255  int_32 Count;
256 int rpmv3 = headerIsEntry(h, RPMTAG_OLDFILENAMES);
257 
258 assert(scareMem == 0); /* XXX always allocate memory */
259  if (tagN == RPMTAG_PROVIDENAME) {
260  Type = "Provides";
261  tagEVR = RPMTAG_PROVIDEVERSION;
262  tagF = RPMTAG_PROVIDEFLAGS;
263  } else
264  if (tagN == RPMTAG_REQUIRENAME) {
265  Type = "Requires";
266  tagEVR = RPMTAG_REQUIREVERSION;
267  tagF = RPMTAG_REQUIREFLAGS;
268  } else
269  if (tagN == RPMTAG_CONFLICTNAME) {
270  Type = "Conflicts";
271  tagEVR = RPMTAG_CONFLICTVERSION;
272  tagF = RPMTAG_CONFLICTFLAGS;
273  } else
274  if (tagN == RPMTAG_OBSOLETENAME) {
275  Type = "Obsoletes";
276  tagEVR = RPMTAG_OBSOLETEVERSION;
277  tagF = RPMTAG_OBSOLETEFLAGS;
278  } else
279  if (tagN == RPMTAG_TRIGGERNAME) {
280  Type = "Triggers";
281  tagEVR = RPMTAG_TRIGGERVERSION;
282  tagF = RPMTAG_TRIGGERFLAGS;
283  } else
284  if (!rpmv3 && tagN == RPMTAG_DIRNAMES) {
285  Type = "Dirnames";
286  tagEVR = 0;
287  tagF = 0;
288  } else
289  if (!rpmv3 && tagN == RPMTAG_FILELINKTOS) {
290  Type = "Filelinktos";
291  tagEVR = RPMTAG_DIRNAMES;
292  tagF = RPMTAG_DIRINDEXES;
293  } else
294  goto exit;
295 
296  /*@-branchstate@*/
297  if (hge(h, tagN, &Nt, &N, &Count)
298  && N != NULL && Count > 0)
299  {
300  int xx;
301  int_32 CountEVR, CountF;
302 
303  ds = xcalloc(1, sizeof(*ds));
304  ds->Type = Type;
305  ds->h = (scareMem ? headerLink(h) : NULL);
306  ds->i = -1;
307  ds->DNEVR = NULL;
308  ds->tagN = tagN;
309  ds->N = N;
310  ds->Nt = Nt;
311  ds->Count = Count;
312  ds->nopromote = _rpmds_nopromote;
313 
314  if (tagEVR > 0)
315  xx = hge(h, tagEVR, &ds->EVRt, &ds->EVR, &CountEVR);
316  if (tagF > 0)
317  xx = hge(h, tagF, &ds->Ft, &ds->Flags, &CountF);
318 /*@-boundsread@*/
319  if (!scareMem && ds->Flags != NULL)
320  ds->Flags = memcpy(xmalloc(ds->Count * sizeof(*ds->Flags)),
321  ds->Flags, ds->Count * sizeof(*ds->Flags));
322  { rpmTag tagA = RPMTAG_ARCH;
323  rpmTagType At;
324  const char * A = NULL;
325  if (tagA > 0)
326  xx = hge(h, tagA, &At, &A, NULL);
327  ds->A = (xx && A != NULL ? xstrdup(A) : NULL);
328  }
329  { rpmTag tagBT = RPMTAG_BUILDTIME;
330  rpmTagType BTt;
331  int_32 * BTp = NULL;
332  if (tagBT > 0)
333  xx = hge(h, tagBT, &BTt, &BTp, NULL);
334  ds->BT = (xx && BTp != NULL && BTt == RPM_INT32_TYPE ? *BTp : 0);
335  }
336 /*@=boundsread@*/
337 
338  if (tagN == RPMTAG_DIRNAMES) {
339  char * t;
340  size_t len;
341  int i;
342  /* XXX Dirnames always have trailing '/', trim that here. */
343  for (i = 0; i < Count; i++) {
344  (void) urlPath(N[i], (const char **)&t);
345  if (t > N[i])
346  N[i] = t;
347  t = (char *)N[i];
348  len = strlen(t);
349  /* XXX don't truncate if parent is / */
350  if (len > 1 && t[len-1] == '/')
351  t[len-1] = '\0';
352  }
353  } else
354  if (tagN == RPMTAG_FILELINKTOS) {
355  if (Count > CountF) Count = CountF;
356 
357  /* XXX Construct the absolute path of the target symlink(s). */
358  const char ** av = xcalloc(Count+1, sizeof(*av));
359  int i;
360 
361  for (i = 0; i < Count; i++) {
362  if (N[i] == NULL || *N[i] == '\0')
363  av[i] = xstrdup("");
364  else if (*N[i] == '/')
365  av[i] = xstrdup(N[i]);
366  else if (ds->EVR && ds->Flags && ds->Flags[i] >= 0 && ds->Flags[i] < CountEVR)
367 /*@-nullderef@*/ /* XXX ds->Flags != NULL */
368  av[i] = rpmGenPath(NULL, ds->EVR[ds->Flags[i]], N[i]);
369 /*@=nullderef@*/
370  else
371  av[i] = xstrdup("");
372  }
373  av[Count] = NULL;
374 
375  N = ds->N = hfd(ds->N, ds->Nt);
376  ds->N = rpmdsDupArgv(av, Count);
377  av = argvFree(av);
378  ds->EVR = hfd(ds->EVR, ds->EVRt);
379  /*@-evalorder@*/
380  ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
381  /*@=evalorder@*/
382  }
383 
384 /*@-modfilesys@*/
385 if (_rpmds_debug < 0)
386 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
387 /*@=modfilesys@*/
388 
389  }
390  /*@=branchstate@*/
391 
392 exit:
393 /*@-compdef -usereleased@*/ /* FIX: ds->Flags may be NULL */
394  /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
395  ds = rpmdsLink(ds, (ds ? ds->Type : NULL));
396  /*@=nullstate@*/
397 
398  return ds;
399 /*@=compdef =usereleased@*/
400 }
401 
402 /*@-mods@*/ /* FIX: correct annotations for ds->ns shadow */
403 const char * rpmdsNewN(rpmds ds)
404 {
405  rpmns ns = &ds->ns;
406  const char * Name = ds->N[ds->i];
407  int xx;
408 
409  memset(ns, 0, sizeof(*ns));
410  xx = rpmnsParse(Name, ns);
411 
412 /*@-usereleased -compdef@*/ /* FIX: correct annotations for ds->ns shadow */
413  return ns->N;
414 /*@-usereleased -compdef@*/
415 }
416 /*@=mods@*/
417 
418 char * rpmdsNewDNEVR(const char * dspfx, rpmds ds)
419 {
420  const char * N = rpmdsNewN(ds);
421  const char * NS = ds->ns.NS;
422  const char * A = ds->ns.A;
423  int_32 dsFlags = 0;
424  char * tbuf, * t;
425  size_t nb = 0;
426 
427  if (dspfx) nb += strlen(dspfx) + 1;
428 /*@-boundsread@*/
429  if (ds->ns.str[0] == '!') nb++;
430  if (NS) nb += strlen(NS) + sizeof("()") - 1;
431  if (N) nb += strlen(N);
432  if (A) {
433  if (_rpmns_N_at_A && _rpmns_N_at_A[0])
434  nb += sizeof(_rpmns_N_at_A[0]);
435  nb += strlen(A);
436  }
437  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
438  if (ds->Flags != NULL
439  && (dsFlags = (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)))
440  {
441  if (nb) nb++;
442  if (dsFlags == RPMSENSE_NOTEQUAL)
443  nb += 2;
444  else {
445  if (dsFlags & RPMSENSE_LESS) nb++;
446  if (dsFlags & RPMSENSE_GREATER) nb++;
447  if (dsFlags & RPMSENSE_EQUAL) nb++;
448  }
449  }
450 
451  ds->ns.Flags = dsFlags;
452 
453  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
454  if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
455  if (nb) nb++;
456  nb += strlen(ds->EVR[ds->i]);
457  }
458 /*@=boundsread@*/
459 
460 /*@-boundswrite@*/
461  t = tbuf = xmalloc(nb + 1);
462  if (dspfx) {
463  t = stpcpy(t, dspfx);
464  *t++ = ' ';
465  }
466  if (ds->ns.str[0] == '!')
467  *t++ = '!';
468  if (NS)
469  t = stpcpy( stpcpy(t, NS), "(");
470  if (N)
471  t = stpcpy(t, N);
472  if (NS)
473  t = stpcpy(t, ")");
474  if (A) {
475  if (_rpmns_N_at_A && _rpmns_N_at_A[0])
476  *t++ = _rpmns_N_at_A[0];
477  t = stpcpy(t, A);
478  }
479 
480  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
481  if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
482  if (t != tbuf) *t++ = ' ';
483  if (dsFlags == RPMSENSE_NOTEQUAL)
484  t = stpcpy(t, "!=");
485  else {
486  if (dsFlags & RPMSENSE_LESS) *t++ = '<';
487  if (dsFlags & RPMSENSE_GREATER) *t++ = '>';
488  if (dsFlags & RPMSENSE_EQUAL) *t++ = '=';
489  }
490  }
491  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
492  if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
493  if (t != tbuf) *t++ = ' ';
494  t = stpcpy(t, ds->EVR[ds->i]);
495  }
496  *t = '\0';
497 /*@=boundswrite@*/
498  return tbuf;
499 }
500 
502 {
504  rpmds ds = NULL;
505  const char * Type;
506  const char * n, * v, * r;
507  int_32 * ep;
508  const char ** N, ** EVR;
509  char * t;
510  int xx;
511 
512  if (tagN == RPMTAG_PROVIDENAME) {
513  Type = "Provides";
514  } else
515  if (tagN == RPMTAG_REQUIRENAME) {
516  Type = "Requires";
517  } else
518  if (tagN == RPMTAG_CONFLICTNAME) {
519  Type = "Conflicts";
520  } else
521  if (tagN == RPMTAG_OBSOLETENAME) {
522  Type = "Obsoletes";
523  } else
524  if (tagN == RPMTAG_TRIGGERNAME) {
525  Type = "Triggers";
526  } else
527  if (tagN == RPMTAG_DIRNAMES) {
528  Type = "Dirnames";
529  } else
530  if (tagN == RPMTAG_FILELINKTOS) {
531  Type = "Filelinktos";
532  } else
533  goto exit;
534 
535  xx = headerNVR(h, &n, &v, &r);
536  ep = NULL;
537  xx = hge(h, RPMTAG_EPOCH, NULL, &ep, NULL);
538 
539  t = xmalloc(sizeof(*N) + strlen(n) + 1);
540 /*@-boundswrite@*/
541  N = (const char **) t;
542  t += sizeof(*N);
543  *t = '\0';
544  N[0] = t;
545  t = stpcpy(t, n);
546 
547  t = xmalloc(sizeof(*EVR) +
548  (ep ? 20 : 0) + strlen(v) + strlen(r) + sizeof("-"));
549  EVR = (const char **) t;
550  t += sizeof(*EVR);
551  *t = '\0';
552  EVR[0] = t;
553  if (ep) {
554  sprintf(t, "%d:", *ep);
555  t += strlen(t);
556  }
557  t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
558 /*@=boundswrite@*/
559 
560  ds = xcalloc(1, sizeof(*ds));
561  ds->Type = Type;
562  ds->tagN = tagN;
563  ds->Count = 1;
564  ds->N = N;
565  ds->Nt = -1; /* XXX to insure that hfd will free */
566  ds->EVR = EVR;
567  ds->EVRt = -1; /* XXX to insure that hfd will free */
568 /*@-boundswrite@*/
569  ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
570 /*@=boundswrite@*/
571  { rpmTag tagA = RPMTAG_ARCH;
572  rpmTagType At;
573  const char * A = NULL;
574  if (tagA > 0)
575  xx = hge(h, tagA, &At, &A, NULL);
576  ds->A = (xx && A != NULL ? xstrdup(A) : NULL);
577  }
578  { rpmTag tagBT = RPMTAG_BUILDTIME;
579  rpmTagType BTt;
580  int_32 * BTp = NULL;
581  if (tagBT > 0)
582  xx = hge(h, tagBT, &BTt, &BTp, NULL);
583  ds->BT = (xx && BTp != NULL && BTt == RPM_INT32_TYPE ? *BTp : 0);
584  }
585  { char pre[2];
586 /*@-boundsread@*/
587  pre[0] = ds->Type[0];
588 /*@=boundsread@*/
589  pre[1] = '\0';
590  /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
591 /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(pre, ds);
592  /*@=nullstate@*/
593  }
594 
595 exit:
596  return rpmdsLink(ds, (ds ? ds->Type : NULL));
597 }
598 
599 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
600 {
601  rpmds ds = NULL;
602  const char * Type;
603 
604  if (tagN == RPMTAG_PROVIDENAME) {
605  Type = "Provides";
606  } else
607  if (tagN == RPMTAG_REQUIRENAME) {
608  Type = "Requires";
609  } else
610  if (tagN == RPMTAG_CONFLICTNAME) {
611  Type = "Conflicts";
612  } else
613  if (tagN == RPMTAG_OBSOLETENAME) {
614  Type = "Obsoletes";
615  } else
616  if (tagN == RPMTAG_TRIGGERNAME) {
617  Type = "Triggers";
618  } else
619  if (tagN == RPMTAG_DIRNAMES) {
620  Type = "Dirnames";
621  } else
622  if (tagN == RPMTAG_FILELINKTOS) {
623  Type = "Filelinktos";
624  } else
625  goto exit;
626 
627  ds = xcalloc(1, sizeof(*ds));
628  ds->Type = Type;
629  ds->tagN = tagN;
630  ds->A = NULL;
631  { time_t now = time(NULL);
632  ds->BT = now;
633  }
634  ds->Count = 1;
635  /*@-assignexpose@*/
636 /*@-boundswrite@*/
637  ds->N = xmalloc(sizeof(*ds->N)); ds->N[0] = N;
638  ds->Nt = -1; /* XXX to insure that hfd will free */
639  ds->EVR = xmalloc(sizeof(*ds->EVR)); ds->EVR[0] = EVR;
640  ds->EVRt = -1; /* XXX to insure that hfd will free */
641  /*@=assignexpose@*/
642  ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
643 /*@=boundswrite@*/
644  { char t[2];
645 /*@-boundsread@*/
646  t[0] = ds->Type[0];
647 /*@=boundsread@*/
648  t[1] = '\0';
649 /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(t, ds);
650  }
651 
652 exit:
653  return rpmdsLink(ds, (ds ? ds->Type : NULL));
654 }
655 
656 int rpmdsCount(const rpmds ds)
657 {
658  return (ds != NULL ? ds->Count : 0);
659 }
660 
661 int rpmdsIx(const rpmds ds)
662 {
663  return (ds != NULL ? ds->i : -1);
664 }
665 
666 int rpmdsSetIx(rpmds ds, int ix)
667 {
668  int i = -1;
669 
670  if (ds != NULL) {
671  i = ds->i;
672  ds->i = ix;
673  }
674  return i;
675 }
676 
677 const char * rpmdsDNEVR(const rpmds ds)
678 {
679  const char * DNEVR = NULL;
680 
681  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
682 /*@-boundsread@*/
683  if (ds->DNEVR != NULL)
684  DNEVR = ds->DNEVR;
685 /*@=boundsread@*/
686  }
687  return DNEVR;
688 }
689 
690 const char * rpmdsN(const rpmds ds)
691 {
692  const char * N = NULL;
693 
694  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
695 /*@-boundsread -globs -mods @*/ /* FIX: correct annotations for ds->ns shadow */
696  N = (ds->ns.N ? ds->ns.N : rpmdsNewN(ds));
697 /*@=boundsread =globs =mods @*/
698  }
699  return N;
700 }
701 
702 const char * rpmdsEVR(const rpmds ds)
703 {
704  const char * EVR = NULL;
705 
706  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
707 /*@-boundsread@*/
708  if (ds->EVR != NULL)
709  EVR = ds->EVR[ds->i];
710 /*@=boundsread@*/
711  }
712  return EVR;
713 }
714 
716 {
717  int_32 Flags = 0;
718 
719  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
720 /*@-boundsread@*/
721  if (ds->Flags != NULL)
722  Flags = ds->Flags[ds->i];
723 /*@=boundsread@*/
724  }
725  return Flags;
726 }
727 
729 {
730  rpmTag tagN = 0;
731 
732  if (ds != NULL)
733  tagN = ds->tagN;
734  return tagN;
735 }
736 
737 const char * rpmdsA(const rpmds ds)
738 {
739  const char * A = NULL;
740 
741  if (ds != NULL)
742  A = ds->A;
743  return A;
744 }
745 
746 time_t rpmdsBT(const rpmds ds)
747 {
748  time_t BT = 0;
749  if (ds != NULL && ds->BT > 0)
750  BT = ds->BT;
751  return BT;
752 }
753 
754 time_t rpmdsSetBT(const rpmds ds, time_t BT)
755 {
756  time_t oBT = 0;
757  if (ds != NULL) {
758  oBT = ds->BT;
759  ds->BT = BT;
760  }
761  return oBT;
762 }
763 
765 {
766  nsType NSType = RPMNS_TYPE_UNKNOWN;
767  if (ds != NULL)
768  NSType = ds->ns.Type;
769  return NSType;
770 }
771 
772 int rpmdsNoPromote(const rpmds ds)
773 {
774  int nopromote = 0;
775 
776  if (ds != NULL)
777  nopromote = ds->nopromote;
778  return nopromote;
779 }
780 
781 int rpmdsSetNoPromote(rpmds ds, int nopromote)
782 {
783  int onopromote = 0;
784 
785  if (ds != NULL) {
786  onopromote = ds->nopromote;
787  ds->nopromote = nopromote;
788  }
789  return onopromote;
790 }
791 
793  int (*EVRparse)(const char *evrstr, EVR_t evr))
794 {
795  void * oEVRparse = NULL;
796 
797  if (ds != NULL) {
798 /*@i@*/ oEVRparse = ds->EVRparse;
799 /*@i@*/ ds->EVRparse = EVRparse;
800  }
801  return oEVRparse;
802 }
803 
804 void * rpmdsSetEVRcmp(rpmds ds, int (*EVRcmp)(const char *a, const char *b))
805 {
806  void * oEVRcmp = NULL;
807 
808  if (ds != NULL) {
809 /*@i@*/ oEVRcmp = ds->EVRcmp;
810 /*@i@*/ ds->EVRcmp = EVRcmp;
811  }
812  return oEVRcmp;
813 }
814 
816 {
817  uint_32 Color = 0;
818 
819  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
820 /*@-boundsread@*/
821  if (ds->Color != NULL)
822  Color = ds->Color[ds->i];
823 /*@=boundsread@*/
824  }
825  return Color;
826 }
827 
829 {
830  uint_32 ocolor = 0;
831 
832  if (ds == NULL)
833  return ocolor;
834 
835  if (ds->Color == NULL && ds->Count > 0) /* XXX lazy malloc */
836  ds->Color = xcalloc(ds->Count, sizeof(*ds->Color));
837 
838  if (ds->i >= 0 && ds->i < ds->Count) {
839 /*@-bounds@*/
840  if (ds->Color != NULL) {
841  ocolor = ds->Color[ds->i];
842  ds->Color[ds->i] = color;
843  }
844 /*@=bounds@*/
845  }
846  return ocolor;
847 }
848 
850 {
851  int_32 Refs = 0;
852 
853  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
854 /*@-boundsread@*/
855  if (ds->Refs != NULL)
856  Refs = ds->Refs[ds->i];
857 /*@=boundsread@*/
858  }
859  return Refs;
860 }
861 
863 {
864  int_32 orefs = 0;
865 
866  if (ds == NULL)
867  return orefs;
868 
869  if (ds->Refs == NULL && ds->Count > 0) /* XXX lazy malloc */
870  ds->Refs = xcalloc(ds->Count, sizeof(*ds->Refs));
871 
872  if (ds->i >= 0 && ds->i < ds->Count) {
873 /*@-bounds@*/
874  if (ds->Refs != NULL) {
875  orefs = ds->Refs[ds->i];
876  ds->Refs[ds->i] = refs;
877  }
878 /*@=bounds@*/
879  }
880  return orefs;
881 }
882 
884 {
885  int_32 result = 0;
886 
887  if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
888 /*@-boundsread@*/
889  if (ds->Result != NULL)
890  result = ds->Result[ds->i];
891 /*@=boundsread@*/
892  }
893  return result;
894 }
895 
897 {
898  int_32 oresult = 0;
899 
900  if (ds == NULL)
901  return oresult;
902 
903  if (ds->Result == NULL && ds->Count > 0) /* XXX lazy malloc */
904  ds->Result = xcalloc(ds->Count, sizeof(*ds->Result));
905 
906  if (ds->i >= 0 && ds->i < ds->Count) {
907 /*@-bounds@*/
908  if (ds->Result != NULL) {
909  oresult = ds->Result[ds->i];
910  ds->Result[ds->i] = result;
911  }
912 /*@=bounds@*/
913  }
914  return oresult;
915 }
916 
917 void rpmdsNotify(rpmds ds, const char * where, int rc)
918 {
919  if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
920  return;
921  if (!(ds->Type != NULL && ds->DNEVR != NULL))
922  return;
923 
924  rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
925  (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
926  (rc ? _("NO ") : _("YES")),
927  (where != NULL ? where : ""));
928 }
929 
930 int rpmdsNext(/*@null@*/ rpmds ds)
931  /*@modifies ds @*/
932 {
933  int i = -1;
934 
935  if (ds != NULL && ++ds->i >= 0) {
936  if (ds->i < ds->Count) {
937  char t[2];
938  i = ds->i;
939  ds->DNEVR = _free(ds->DNEVR);
940  ds->ns.str = _free(ds->ns.str);
941  memset(&ds->ns, 0, sizeof(ds->ns));
942  t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
943  t[1] = '\0';
944  /*@-nullstate@*/
945  /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(t, ds);
946  /*@=nullstate@*/
947 
948  } else
949  ds->i = -1;
950 
951 /*@-modfilesys @*/
952 if (_rpmds_debug < 0 && i != -1)
953 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
954 /*@=modfilesys @*/
955 
956  }
957 
958  return i;
959 }
960 
961 rpmds rpmdsInit(/*@null@*/ rpmds ds)
962  /*@modifies ds @*/
963 {
964  if (ds != NULL)
965  ds->i = -1;
966  /*@-refcounttrans@*/
967  return ds;
968  /*@=refcounttrans@*/
969 }
970 
971 /*@null@*/
972 static rpmds rpmdsDup(const rpmds ods)
973  /*@modifies ods @*/
974 {
975  rpmds ds = xcalloc(1, sizeof(*ds));
976  size_t nb;
977 
978  ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
979 /*@-assignexpose@*/
980  ds->Type = ods->Type;
981 /*@=assignexpose@*/
982  ds->tagN = ods->tagN;
983  ds->Count = ods->Count;
984  ds->i = ods->i;
985  ds->l = ods->l;
986  ds->u = ods->u;
987 
988  nb = (ds->Count+1) * sizeof(*ds->N);
989  ds->N = (ds->h != NULL
990  ? memcpy(xmalloc(nb), ods->N, nb)
991  : rpmdsDupArgv(ods->N, ods->Count) );
992  ds->Nt = ods->Nt;
993 
994  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
995 assert(ods->EVR != NULL);
996 assert(ods->Flags != NULL);
997 
998  nb = (ds->Count+1) * sizeof(*ds->EVR);
999  ds->EVR = (ds->h != NULL
1000  ? memcpy(xmalloc(nb), ods->EVR, nb)
1001  : rpmdsDupArgv(ods->EVR, ods->Count) );
1002  ds->EVRt = ods->EVRt;
1003 
1004  nb = (ds->Count * sizeof(*ds->Flags));
1005  ds->Flags = (ds->h != NULL
1006  ? ods->Flags
1007  : memcpy(xmalloc(nb), ods->Flags, nb) );
1008  ds->Ft = ods->Ft;
1009  ds->nopromote = ods->nopromote;
1010 /*@-assignexpose@*/
1011  ds->EVRcmp = ods->EVRcmp;;
1012 /*@=assignexpose@*/
1013 
1014 /*@-compmempass@*/ /* FIX: ds->Flags is kept, not only */
1015  return rpmdsLink(ds, (ds ? ds->Type : NULL));
1016 /*@=compmempass@*/
1017 
1018 }
1019 
1020 int rpmdsFind(rpmds ds, const rpmds ods)
1021 {
1022  int comparison;
1023 
1024  if (ds == NULL || ods == NULL)
1025  return -1;
1026 
1027  ds->l = 0;
1028  ds->u = ds->Count;
1029  while (ds->l < ds->u) {
1030  ds->i = (ds->l + ds->u) / 2;
1031 
1032  comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
1033 
1034  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
1035 /*@-nullderef@*/
1036  if (comparison == 0 && ods->EVR && ds->EVR)
1037  comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
1038  if (comparison == 0 && ods->Flags && ds->Flags)
1039  comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
1040 /*@=nullderef@*/
1041 
1042  if (comparison < 0)
1043  ds->u = ds->i;
1044  else if (comparison > 0)
1045  ds->l = ds->i + 1;
1046  else
1047  return ds->i;
1048  }
1049  return -1;
1050 }
1051 
1052 int rpmdsMerge(rpmds * dsp, rpmds ods)
1053 {
1054  rpmds ds;
1055  const char ** N;
1056  const char ** EVR;
1057  int_32 * Flags;
1058  int j;
1059 int save;
1060 
1061  if (dsp == NULL || ods == NULL)
1062  return -1;
1063 
1064  /* If not initialized yet, dup the 1st entry. */
1065 /*@-branchstate@*/
1066  if (*dsp == NULL) {
1067  save = ods->Count;
1068  ods->Count = 1;
1069  *dsp = rpmdsDup(ods);
1070  ods->Count = save;
1071  }
1072 /*@=branchstate@*/
1073  ds = *dsp;
1074  if (ds == NULL)
1075  return -1;
1076 
1077  /*
1078  * Add new entries.
1079  */
1080 save = ods->i;
1081  ods = rpmdsInit(ods);
1082  if (ods != NULL)
1083  while (rpmdsNext(ods) >= 0) {
1084  /*
1085  * If this entry is already present, don't bother.
1086  */
1087  if (rpmdsFind(ds, ods) >= 0)
1088  continue;
1089 
1090  /*
1091  * Insert new entry.
1092  */
1093  for (j = ds->Count; j > ds->u; j--)
1094  ds->N[j] = ds->N[j-1];
1095  ds->N[ds->u] = ods->N[ods->i];
1096  N = rpmdsDupArgv(ds->N, ds->Count+1);
1097  ds->N = _free(ds->N);
1098  ds->N = N;
1099 
1100  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
1101 /*@-nullderef -nullpass -nullptrarith @*/
1102 assert(ods->EVR != NULL);
1103 assert(ods->Flags != NULL);
1104 
1105  for (j = ds->Count; j > ds->u; j--)
1106  ds->EVR[j] = ds->EVR[j-1];
1107  ds->EVR[ds->u] = ods->EVR[ods->i];
1108  EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
1109  ds->EVR = _free(ds->EVR);
1110  ds->EVR = EVR;
1111 
1112  Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
1113  if (ds->u > 0)
1114  memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
1115  if (ds->u < ds->Count)
1116  memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
1117  Flags[ds->u] = ods->Flags[ods->i];
1118  ds->Flags = _free(ds->Flags);
1119  ds->Flags = Flags;
1120 /*@=nullderef =nullpass =nullptrarith @*/
1121 
1122  ds->i = ds->Count;
1123  ds->Count++;
1124 
1125  }
1126 /*@-nullderef@*/
1127 ods->i = save;
1128 /*@=nullderef@*/
1129  return 0;
1130 }
1131 
1133 {
1134  int comparison;
1135  int i, l, u;
1136 
1137  if (ds == NULL || ods == NULL)
1138  return -1;
1139 
1140  /* Binary search to find the [l,u) subset that contains N */
1141  i = -1;
1142  l = 0;
1143  u = ds->Count;
1144  while (l < u) {
1145  i = (l + u) / 2;
1146 
1147  comparison = strcmp(ods->N[ods->i], ds->N[i]);
1148 
1149  if (comparison < 0)
1150  u = i;
1151  else if (comparison > 0)
1152  l = i + 1;
1153  else {
1154  /* Set l to 1st member of set that contains N. */
1155  if (strcmp(ods->N[ods->i], ds->N[l]))
1156  l = i;
1157  while (l > 0 && !strcmp(ods->N[ods->i], ds->N[l-1]))
1158  l--;
1159  /* Set u to 1st member of set that does not contain N. */
1160  if (u >= ds->Count || strcmp(ods->N[ods->i], ds->N[u]))
1161  u = i;
1162  while (++u < ds->Count) {
1163  if (strcmp(ods->N[ods->i], ds->N[u]))
1164  /*@innerbreak@*/ break;
1165  }
1166  break;
1167  }
1168  }
1169 
1170  /* Check each member of [l,u) subset for ranges overlap. */
1171  i = -1;
1172  if (l < u) {
1173  int save = rpmdsSetIx(ds, l-1);
1174  while ((l = rpmdsNext(ds)) >= 0 && (l < u)) {
1175  if ((i = rpmdsCompare(ods, ds)) != 0)
1176  break;
1177  }
1178  /* Return element index that overlaps, or -1. */
1179  if (i)
1180  i = rpmdsIx(ds);
1181  else {
1182  (void) rpmdsSetIx(ds, save);
1183  i = -1;
1184  }
1185  /* Save the return value. */
1186  if (ods->Result != NULL)
1187  (void) rpmdsSetResult(ods, (i != -1 ? 1 : 0));
1188  }
1189  return i;
1190 }
1191 
1192 struct cpuinfo_s {
1193 /*@observer@*/ /*@null@*/
1194  const char *name;
1195  int done;
1196  int flags;
1197 };
1198 
1199 /*@unchecked@*/
1200 static struct cpuinfo_s ctags[] = {
1201  { "processor", 0, 0 },
1202  { "vendor_id", 0, 0 },
1203  { "cpu_family", 0, 1 },
1204  { "model", 0, 1 },
1205  { "model_name", 0, 0 },
1206  { "stepping", 0, 1 },
1207  { "cpu_MHz", 0, 1 },
1208  { "cache_size", 0, 1 },
1209  { "physical_id", 0, 0 },
1210  { "siblings", 0, 0 },
1211  { "core_id", 0, 0 },
1212  { "cpu_cores", 0, 0 },
1213  { "fdiv_bug", 0, 3 },
1214  { "hlt_bug", 0, 3 },
1215  { "f00f_bug", 0, 3 },
1216  { "coma_bug", 0, 3 },
1217  { "fpu", 0, 0 }, /* XXX use flags attribute instead. */
1218  { "fpu_exception", 0, 3 },
1219  { "cpuid_level", 0, 0 },
1220  { "wp", 0, 3 },
1221  { "flags", 0, 4 },
1222  { "bogomips", 0, 1 },
1223  { NULL, 0, -1 }
1224 };
1225 
1231 static int rpmdsCpuinfoCtagFlags(const char * name)
1232  /*@globals ctags @*/
1233  /*@modifies ctags @*/
1234 {
1235  struct cpuinfo_s * ct;
1236  int flags = -1;
1237 
1238  for (ct = ctags; ct->name != NULL; ct++) {
1239  if (strcmp(ct->name, name))
1240  continue;
1241  if (ct->done)
1242  continue;
1243  ct->done = 1; /* XXX insure single occurrence */
1244  flags = ct->flags;
1245  break;
1246  }
1247  return flags;
1248 }
1249 
1258 static void rpmdsNSAdd(/*@out@*/ rpmds *dsp, const char * NS,
1259  const char *N, const char *EVR, int_32 Flags)
1260  /*@modifies *dsp @*/
1261 {
1262  char *t;
1263  rpmds ds;
1264  int xx;
1265 
1266  t = alloca(strlen(NS)+sizeof("()")+strlen(N));
1267  *t = '\0';
1268  (void) stpcpy( stpcpy( stpcpy( stpcpy(t, NS), "("), N), ")");
1269 
1270  ds = rpmdsSingle(RPMTAG_PROVIDENAME, t, EVR, Flags);
1271  xx = rpmdsMerge(dsp, ds);
1272  ds = rpmdsFree(ds);
1273 }
1274 
1275 #define _PROC_CPUINFO "/proc/cpuinfo"
1276 
1278 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
1279 static const char * _cpuinfo_path = NULL;
1280 
1281 int rpmdsCpuinfo(rpmds *dsp, const char * fn)
1282  /*@globals _cpuinfo_path, ctags @*/
1283  /*@modifies _cpuinfo_path, ctags @*/
1284 {
1285  struct cpuinfo_s * ct;
1286  const char * NS = "cpuinfo";
1287  char buf[BUFSIZ];
1288  char * f, * fe;
1289  char * g, * ge;
1290  char * t;
1291  FD_t fd = NULL;
1292  FILE * fp;
1293  int rc = -1;
1294 
1295 /*@-modobserver@*/
1296  if (_cpuinfo_path == NULL) {
1297  _cpuinfo_path = rpmExpand("%{?_rpmds_cpuinfo_path}", NULL);
1298  /* XXX may need to validate path existence somewhen. */
1299  if (!(_cpuinfo_path != NULL && *_cpuinfo_path == '/')) {
1300 /*@-observertrans @*/
1301  _cpuinfo_path = _free(_cpuinfo_path);
1302 /*@=observertrans @*/
1303  _cpuinfo_path = xstrdup(_PROC_CPUINFO);
1304  }
1305  }
1306 /*@=modobserver@*/
1307 
1308 /*@-branchstate@*/
1309  if (fn == NULL)
1310  fn = _cpuinfo_path;
1311 /*@=branchstate@*/
1312 
1313  /* Reset done variables. */
1314  for (ct = ctags; ct->name != NULL; ct++)
1315  ct->done = 0;
1316 
1317  fd = Fopen(fn, "r.fpio");
1318  if (fd == NULL || Ferror(fd))
1319  goto exit;
1320  fp = fdGetFILE(fd);
1321 
1322  if (fp != NULL)
1323  while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
1324  /* rtrim on line. */
1325  ge = f + strlen(f);
1326  while (--ge > f && _isspace(*ge))
1327  *ge = '\0';
1328 
1329  /* ltrim on line. */
1330  while (*f && _isspace(*f))
1331  f++;
1332 
1333  /* split on ':' */
1334  fe = f;
1335  while (*fe && *fe != ':')
1336  fe++;
1337  if (*fe == '\0')
1338  continue;
1339  g = fe + 1;
1340 
1341  /* rtrim on field 1. */
1342  *fe = '\0';
1343  while (--fe > f && _isspace(*fe))
1344  *fe = '\0';
1345  if (*f == '\0')
1346  continue;
1347 
1348  /* ltrim on field 2. */
1349  while (*g && _isspace(*g))
1350  g++;
1351  if (*g == '\0')
1352  continue;
1353 
1354  for (t = f; *t != '\0'; t++) {
1355  if (_isspace(*t))
1356  *t = '_';
1357  }
1358 
1359  switch (rpmdsCpuinfoCtagFlags(f)) {
1360  case -1: /* not found */
1361  case 0: /* ignore */
1362  default:
1363  continue;
1364  /*@notreached@*/ /*@switchbreak@*/ break;
1365  case 1: /* Provides: cpuinfo(f) = g */
1366  for (t = g; *t != '\0'; t++) {
1367  if (_isspace(*t) || *t == '(' || *t == ')')
1368  *t = '_';
1369  }
1370  rpmdsNSAdd(dsp, NS, f, g, RPMSENSE_PROBE|RPMSENSE_EQUAL);
1371  /*@switchbreak@*/ break;
1372  case 2: /* Provides: cpuinfo(g) */
1373  for (t = g; *t != '\0'; t++) {
1374  if (_isspace(*t) || *t == '(' || *t == ')')
1375  *t = '_';
1376  }
1377  rpmdsNSAdd(dsp, NS, g, "", RPMSENSE_PROBE);
1378  /*@switchbreak@*/ break;
1379  case 3: /* if ("yes") Provides: cpuinfo(f) */
1380  if (!strcmp(g, "yes"))
1381  rpmdsNSAdd(dsp, NS, f, "", RPMSENSE_PROBE);
1382  /*@switchbreak@*/ break;
1383  case 4: /* Provides: cpuinfo(g[i]) */
1384  { char ** av = NULL;
1385  int i = 0;
1386  rc = poptParseArgvString(g, NULL, (const char ***)&av);
1387  if (!rc && av != NULL)
1388  while ((t = av[i++]) != NULL)
1389  rpmdsNSAdd(dsp, NS, t, "", RPMSENSE_PROBE);
1390  t = NULL;
1391  if (av != NULL)
1392  free(av);
1393  } /*@switchbreak@*/ break;
1394  }
1395  }
1396 
1397 exit:
1398 /*@-branchstate@*/
1399  if (fd != NULL) (void) Fclose(fd);
1400 /*@=branchstate@*/
1401  return rc;
1402 }
1403 
1405 /*@observer@*/ /*@relnull@*/
1406  const char * featureName;
1407 /*@observer@*/ /*@relnull@*/
1408  const char * featureEVR;
1410 /*@observer@*/ /*@relnull@*/
1411  const char * featureDescription;
1412 };
1413 
1414 /*@unchecked@*/ /*@observer@*/
1416  { "rpmlib(VersionedDependencies)", "3.0.3-1",
1417  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1418  N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
1419  { "rpmlib(CompressedFileNames)", "3.0.4-1",
1420  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1421  N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
1422  { "rpmlib(PayloadIsBzip2)", "3.0.5-1",
1423  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1424  N_("package payload can be compressed using bzip2.") },
1425  { "rpmlib(PayloadFilesHavePrefix)", "4.0-1",
1426  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1427  N_("package payload file(s) have \"./\" prefix.") },
1428  { "rpmlib(ExplicitPackageProvide)", "4.0-1",
1429  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1430  N_("package name-version-release is not implicitly provided.") },
1431  { "rpmlib(HeaderLoadSortsTags)", "4.0.1-1",
1432  ( RPMSENSE_EQUAL),
1433  N_("header tags are always sorted after being loaded.") },
1434  { "rpmlib(ScriptletInterpreterArgs)", "4.0.3-1",
1435  ( RPMSENSE_EQUAL),
1436  N_("the scriptlet interpreter can use arguments from header.") },
1437  { "rpmlib(PartialHardlinkSets)", "4.0.4-1",
1438  ( RPMSENSE_EQUAL),
1439  N_("a hardlink file set may be installed without being complete.") },
1440  { "rpmlib(ConcurrentAccess)", "4.1-1",
1441  ( RPMSENSE_EQUAL),
1442  N_("package scriptlets may access the rpm database while installing.") },
1443 #if defined(WITH_LUA)
1444  { "rpmlib(BuiltinLuaScripts)", "4.2.2-1",
1445  ( RPMSENSE_EQUAL),
1446  N_("internal support for lua scripts.") },
1447 #endif
1448  { "rpmlib(HeaderTagTypeInt64)", "4.4.3-1",
1449  ( RPMSENSE_EQUAL),
1450  N_("header tags can be type int_64.") },
1451  { "rpmlib(PayloadIsUstar)", "4.4.4-1",
1452  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1453  N_("package payload can be in ustar tar archive format.") },
1454  { "rpmlib(PayloadIsLzma)", "4.4.6-1",
1455  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1456  N_("package payload can be compressed using lzma.") },
1457  { "rpmlib(FileDigestParameterized)", "4.4.6-1",
1458  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1459  N_("file digests can be other than MD5.") },
1460  { NULL, NULL, 0, NULL }
1461 };
1462 
1469 int rpmdsRpmlib(rpmds * dsp, void * tblp)
1470 {
1471  const struct rpmlibProvides_s * rltblp = tblp;
1472  const struct rpmlibProvides_s * rlp;
1473  int xx;
1474 
1475  if (rltblp == NULL)
1476  rltblp = rpmlibProvides;
1477 
1478  for (rlp = rltblp; rlp->featureName != NULL; rlp++) {
1480  rlp->featureEVR, rlp->featureFlags);
1481  xx = rpmdsMerge(dsp, ds);
1482  ds = rpmdsFree(ds);
1483  }
1484  return 0;
1485 }
1486 
1494 static int rpmdsSysinfoFile(rpmPRCO PRCO, const char * fn, int tagN)
1495  /*@globals h_errno, fileSystem, internalState @*/
1496  /*@modifies PRCO, fileSystem, internalState @*/
1497 {
1498  char buf[BUFSIZ];
1499  const char *N, *EVR;
1500  int_32 Flags;
1501  rpmds ds;
1502  char * f, * fe;
1503  char * g, * ge;
1504  FD_t fd = NULL;
1505  FILE * fp;
1506  int rc = -1;
1507  int ln;
1508  int xx;
1509 
1510  /* XXX for now, collect Dirnames/Filelinktos in Providename */
1511  if (tagN == RPMTAG_DIRNAMES || tagN == RPMTAG_FILELINKTOS)
1512  tagN = RPMTAG_PROVIDENAME;
1513 
1514 assert(fn != NULL);
1515  fd = Fopen(fn, "r.fpio");
1516  if (fd == NULL || Ferror(fd))
1517  goto exit;
1518  fp = fdGetFILE(fd);
1519 
1520  ln = 0;
1521  if (fp != NULL)
1522  while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
1523  ln++;
1524 
1525  /* insure a terminator. */
1526  buf[sizeof(buf)-1] = '\0';
1527 
1528  /* ltrim on line. */
1529  while (*f && _isspace(*f))
1530  f++;
1531 
1532  /* XXX skip YAML "- " markup */
1533  if (f[0] == '-' && _isspace(f[1])) {
1534  f += sizeof("- ")-1;
1535  while (*f && _isspace(*f))
1536  f++;
1537  }
1538 
1539  /* skip empty lines and comments */
1540  if (*f == '\0' || *f == '#')
1541  continue;
1542 
1543  /* rtrim on line. */
1544  fe = f + strlen(f);
1545  while (--fe > f && _isspace(*fe))
1546  *fe = '\0';
1547 
1548  if (!(xisalnum(f[0]) || strchr("/_%!", f[0]) != NULL)) {
1549  fprintf(stderr, _("%s:%d \"%s\" has invalid name. Skipping ...\n"),
1550  fn, ln, f);
1551  continue;
1552  }
1553 
1554  /* split on ' ' or comparison operator. */
1555  fe = f;
1556  if (*f == '!') fe++;
1557  while (*fe && !_isspace(*fe) && strchr("!<=>", *fe) == NULL)
1558  fe++;
1559  while (*fe && _isspace(*fe))
1560  *fe++ = '\0';
1561 
1562  N = f;
1563  EVR = NULL;
1564  Flags = 0;
1565 
1566  /* parse for non-path, versioned dependency. */
1567 /*@-branchstate@*/
1568  if (*f != '/' && *fe != '\0') {
1569  /* parse comparison operator */
1570  g = fe;
1571  Flags = rpmEVRflags(fe, (const char **)&g);
1572  if (Flags == 0) {
1573  fprintf(stderr, _("%s:%d \"%s\" has no comparison operator. Skipping ...\n"),
1574  fn, ln, fe);
1575  continue;
1576  }
1577  *fe = '\0';
1578 
1579  /* ltrim on field 2. */
1580  while (*g && _isspace(*g))
1581  g++;
1582  if (*g == '\0') {
1583  /* XXX No EVR comparison value found. */
1584  fprintf(stderr, _("%s:%d \"%s\" has no EVR string. Skipping ...\n"),
1585  fn, ln, f);
1586  continue;
1587  }
1588 
1589  ge = g + 1;
1590  while (*ge && !_isspace(*ge))
1591  ge++;
1592 
1593  if (*ge != '\0')
1594  *ge = '\0'; /* XXX can't happen, line rtrim'ed already. */
1595 
1596  EVR = g;
1597  }
1598 
1599  if (EVR == NULL)
1600  EVR = "";
1601  Flags |= RPMSENSE_PROBE;
1602 /*@=branchstate@*/
1603  ds = rpmdsSingle(tagN, N, EVR , Flags);
1604  if (ds) { /* XXX can't happen */
1605  xx = rpmdsMergePRCO(PRCO, ds);
1606  ds = rpmdsFree(ds);
1607  }
1608  }
1609  rc = 0;
1610 
1611 exit:
1612 /*@-branchstate@*/
1613  if (fd != NULL) (void) Fclose(fd);
1614 /*@=branchstate@*/
1615  return rc;
1616 }
1617 
1618 #define _ETC_RPM_SYSINFO "/etc/rpm/sysinfo"
1619 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
1620 static const char *_sysinfo_path = NULL;
1621 
1622 /*@unchecked@*/ /*@observer@*/ /*@relnull@*/
1623 static const char *_sysinfo_tags[] = {
1624  "Providename",
1625  "Requirename",
1626  "Conflictname",
1627  "Obsoletename",
1628  "Dirnames",
1629  "Filelinktos",
1630  NULL
1631 };
1632 
1633 int rpmdsSysinfo(rpmPRCO PRCO, const char * fn)
1634  /*@globals _sysinfo_path @*/
1635  /*@modifies _sysinfo_path @*/
1636 {
1637  struct stat * st = memset(alloca(sizeof(*st)), 0, sizeof(*st));
1638  int rc = -1;
1639  int xx;
1640 
1641 /*@-modobserver@*/
1642  if (_sysinfo_path == NULL) {
1643  _sysinfo_path = rpmExpand("%{?_rpmds_sysinfo_path}", NULL);
1644  /* XXX may need to validate path existence somewhen. */
1645  if (!(_sysinfo_path != NULL && *_sysinfo_path == '/')) {
1646 /*@-observertrans @*/
1647  _sysinfo_path = _free(_sysinfo_path);
1648 /*@=observertrans @*/
1649  _sysinfo_path = rpmGetPath(_ETC_RPM_SYSINFO, NULL);
1650  }
1651  }
1652 /*@=modobserver@*/
1653 
1654 /*@-branchstate@*/
1655  if (fn == NULL)
1656  fn = _sysinfo_path;
1657 /*@=branchstate@*/
1658 
1659  if (fn == NULL)
1660  goto exit;
1661 
1662  xx = Stat(fn, st);
1663  if (xx < 0)
1664  goto exit;
1665 
1666  if (S_ISDIR(st->st_mode)) {
1667  const char *dn = fn;
1668  const char **av;
1669  int tagN;
1670  rc = 0; /* assume success */
1671 /*@-branchstate@*/
1672  for (av = _sysinfo_tags; av && *av; av++) {
1673  tagN = tagValue(*av);
1674  if (tagN < 0)
1675  continue;
1676  fn = rpmGetPath(dn, "/", *av, NULL);
1677  st = memset(st, 0, sizeof(*st));
1678  xx = Stat(fn, st);
1679  if (xx == 0 && S_ISREG(st->st_mode))
1680  rc = rpmdsSysinfoFile(PRCO, fn, tagN);
1681  fn = _free(fn);
1682  if (rc)
1683  break;
1684  }
1685 /*@=branchstate@*/
1686  } else
1687  /* XXX for now, collect Dirnames/Filelinktos in Providename */
1688  if (S_ISREG(st->st_mode))
1689  rc = rpmdsSysinfoFile(PRCO, fn, RPMTAG_PROVIDENAME);
1690 
1691 exit:
1692  return rc;
1693 }
1694 
1695 struct conf {
1696 /*@observer@*/ /*@relnull@*/
1697  const char *name;
1698  const int call_name;
1699  const enum { SYSCONF, CONFSTR, PATHCONF } call;
1700 };
1701 
1702 /*@unchecked@*/ /*@observer@*/
1703 static const struct conf vars[] = {
1704 #ifdef _PC_LINK_MAX
1705  { "LINK_MAX", _PC_LINK_MAX, PATHCONF },
1706 #endif
1707 #ifdef _PC_LINK_MAX
1708  { "_POSIX_LINK_MAX", _PC_LINK_MAX, PATHCONF },
1709 #endif
1710 #ifdef _PC_MAX_CANON
1711  { "MAX_CANON", _PC_MAX_CANON, PATHCONF },
1712 #endif
1713 #ifdef _PC_MAX_CANON
1714  { "_POSIX_MAX_CANON", _PC_MAX_CANON, PATHCONF },
1715 #endif
1716 #ifdef _PC_MAX_INPUT
1717  { "MAX_INPUT", _PC_MAX_INPUT, PATHCONF },
1718 #endif
1719 #ifdef _PC_MAX_INPUT
1720  { "_POSIX_MAX_INPUT", _PC_MAX_INPUT, PATHCONF },
1721 #endif
1722 #ifdef _PC_NAME_MAX
1723  { "NAME_MAX", _PC_NAME_MAX, PATHCONF },
1724 #endif
1725 #ifdef _PC_NAME_MAX
1726  { "_POSIX_NAME_MAX", _PC_NAME_MAX, PATHCONF },
1727 #endif
1728 #ifdef _PC_PATH_MAX
1729  { "PATH_MAX", _PC_PATH_MAX, PATHCONF },
1730 #endif
1731 #ifdef _PC_PATH_MAX
1732  { "_POSIX_PATH_MAX", _PC_PATH_MAX, PATHCONF },
1733 #endif
1734 #ifdef _PC_PIPE_BUF
1735  { "PIPE_BUF", _PC_PIPE_BUF, PATHCONF },
1736 #endif
1737 #ifdef _PC_PIPE_BUF
1738  { "_POSIX_PIPE_BUF", _PC_PIPE_BUF, PATHCONF },
1739 #endif
1740 #ifdef _PC_SOCK_MAXBUF
1741  { "SOCK_MAXBUF", _PC_SOCK_MAXBUF, PATHCONF },
1742 #endif
1743 #ifdef _PC_ASYNC_IO
1744  { "_POSIX_ASYNC_IO", _PC_ASYNC_IO, PATHCONF },
1745 #endif
1746 #ifdef _PC_CHOWN_RESTRICTED
1747  { "_POSIX_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED, PATHCONF },
1748 #endif
1749 #ifdef _PC_NO_TRUNC
1750  { "_POSIX_NO_TRUNC", _PC_NO_TRUNC, PATHCONF },
1751 #endif
1752 #ifdef _PC_PRIO_IO
1753  { "_POSIX_PRIO_IO", _PC_PRIO_IO, PATHCONF },
1754 #endif
1755 #ifdef _PC_SYNC_IO
1756  { "_POSIX_SYNC_IO", _PC_SYNC_IO, PATHCONF },
1757 #endif
1758 #ifdef _PC_VDISABLE
1759  { "_POSIX_VDISABLE", _PC_VDISABLE, PATHCONF },
1760 #endif
1761 
1762 #ifdef _SC_ARG_MAX
1763  { "ARG_MAX", _SC_ARG_MAX, SYSCONF },
1764 #endif
1765 #ifdef _SC_ATEXIT_MAX
1766  { "ATEXIT_MAX", _SC_ATEXIT_MAX, SYSCONF },
1767 #endif
1768 #ifdef _SC_CHAR_BIT
1769  { "CHAR_BIT", _SC_CHAR_BIT, SYSCONF },
1770 #endif
1771 #ifdef _SC_CHAR_MAX
1772  { "CHAR_MAX", _SC_CHAR_MAX, SYSCONF },
1773 #endif
1774 #ifdef _SC_CHAR_MIN
1775  { "CHAR_MIN", _SC_CHAR_MIN, SYSCONF },
1776 #endif
1777 #ifdef _SC_CHILD_MAX
1778  { "CHILD_MAX", _SC_CHILD_MAX, SYSCONF },
1779 #endif
1780 #ifdef _SC_CLK_TCK
1781  { "CLK_TCK", _SC_CLK_TCK, SYSCONF },
1782 #endif
1783 #ifdef _SC_INT_MAX
1784  { "INT_MAX", _SC_INT_MAX, SYSCONF },
1785 #endif
1786 #ifdef _SC_INT_MIN
1787  { "INT_MIN", _SC_INT_MIN, SYSCONF },
1788 #endif
1789 #ifdef _SC_UIO_MAXIOV
1790  { "IOV_MAX", _SC_UIO_MAXIOV, SYSCONF },
1791 #endif
1792 #ifdef _SC_LOGIN_NAME_MAX
1793  { "LOGNAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF },
1794 #endif
1795 #ifdef _SC_LONG_BIT
1796  { "LONG_BIT", _SC_LONG_BIT, SYSCONF },
1797 #endif
1798 #ifdef _SC_MB_LEN_MAX
1799  { "MB_LEN_MAX", _SC_MB_LEN_MAX, SYSCONF },
1800 #endif
1801 #ifdef _SC_NGROUPS_MAX
1802  { "NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF },
1803 #endif
1804 #ifdef _SC_NL_ARGMAX
1805  { "NL_ARGMAX", _SC_NL_ARGMAX, SYSCONF },
1806 #endif
1807 #ifdef _SC_NL_LANGMAX
1808  { "NL_LANGMAX", _SC_NL_LANGMAX, SYSCONF },
1809 #endif
1810 #ifdef _SC_NL_MSGMAX
1811  { "NL_MSGMAX", _SC_NL_MSGMAX, SYSCONF },
1812 #endif
1813 #ifdef _SC_NL_NMAX
1814  { "NL_NMAX", _SC_NL_NMAX, SYSCONF },
1815 #endif
1816 #ifdef _SC_NL_SETMAX
1817  { "NL_SETMAX", _SC_NL_SETMAX, SYSCONF },
1818 #endif
1819 #ifdef _SC_NL_TEXTMAX
1820  { "NL_TEXTMAX", _SC_NL_TEXTMAX, SYSCONF },
1821 #endif
1822 #ifdef _SC_GETGR_R_SIZE_MAX
1823  { "NSS_BUFLEN_GROUP", _SC_GETGR_R_SIZE_MAX, SYSCONF },
1824 #endif
1825 #ifdef _SC_GETPW_R_SIZE_MAX
1826  { "NSS_BUFLEN_PASSWD", _SC_GETPW_R_SIZE_MAX, SYSCONF },
1827 #endif
1828 #ifdef _SC_NZERO
1829  { "NZERO", _SC_NZERO, SYSCONF },
1830 #endif
1831 #ifdef _SC_OPEN_MAX
1832  { "OPEN_MAX", _SC_OPEN_MAX, SYSCONF },
1833 #endif
1834 #ifdef _SC_PAGESIZE
1835  { "PAGESIZE", _SC_PAGESIZE, SYSCONF },
1836 #endif
1837 #ifdef _SC_PAGESIZE
1838  { "PAGE_SIZE", _SC_PAGESIZE, SYSCONF },
1839 #endif
1840 #ifdef _SC_PASS_MAX
1841  { "PASS_MAX", _SC_PASS_MAX, SYSCONF },
1842 #endif
1843 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
1844  { "PTHREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS, SYSCONF },
1845 #endif
1846 #ifdef _SC_THREAD_KEYS_MAX
1847  { "PTHREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX, SYSCONF },
1848 #endif
1849 #ifdef _SC_THREAD_STACK_MIN
1850  { "PTHREAD_STACK_MIN", _SC_THREAD_STACK_MIN, SYSCONF },
1851 #endif
1852 #ifdef _SC_THREAD_THREADS_MAX
1853  { "PTHREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX, SYSCONF },
1854 #endif
1855 #ifdef _SC_SCHAR_MAX
1856  { "SCHAR_MAX", _SC_SCHAR_MAX, SYSCONF },
1857 #endif
1858 #ifdef _SC_SCHAR_MIN
1859  { "SCHAR_MIN", _SC_SCHAR_MIN, SYSCONF },
1860 #endif
1861 #ifdef _SC_SHRT_MAX
1862  { "SHRT_MAX", _SC_SHRT_MAX, SYSCONF },
1863 #endif
1864 #ifdef _SC_SHRT_MIN
1865  { "SHRT_MIN", _SC_SHRT_MIN, SYSCONF },
1866 #endif
1867 #ifdef _SC_SSIZE_MAX
1868  { "SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF },
1869 #endif
1870 #ifdef _SC_TTY_NAME_MAX
1871  { "TTY_NAME_MAX", _SC_TTY_NAME_MAX, SYSCONF },
1872 #endif
1873 #ifdef _SC_TZNAME_MAX
1874  { "TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF },
1875 #endif
1876 #ifdef _SC_UCHAR_MAX
1877  { "UCHAR_MAX", _SC_UCHAR_MAX, SYSCONF },
1878 #endif
1879 #ifdef _SC_UINT_MAX
1880  { "UINT_MAX", _SC_UINT_MAX, SYSCONF },
1881 #endif
1882 #ifdef _SC_UIO_MAXIOV
1883  { "UIO_MAXIOV", _SC_UIO_MAXIOV, SYSCONF },
1884 #endif
1885 #ifdef _SC_ULONG_MAX
1886  { "ULONG_MAX", _SC_ULONG_MAX, SYSCONF },
1887 #endif
1888 #ifdef _SC_USHRT_MAX
1889  { "USHRT_MAX", _SC_USHRT_MAX, SYSCONF },
1890 #endif
1891 #ifdef _SC_WORD_BIT
1892  { "WORD_BIT", _SC_WORD_BIT, SYSCONF },
1893 #endif
1894 #ifdef _SC_AVPHYS_PAGES
1895  { "_AVPHYS_PAGES", _SC_AVPHYS_PAGES, SYSCONF },
1896 #endif
1897 #ifdef _SC_NPROCESSORS_CONF
1898  { "_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF, SYSCONF },
1899 #endif
1900 #ifdef _SC_NPROCESSORS_ONLN
1901  { "_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN, SYSCONF },
1902 #endif
1903 #ifdef _SC_PHYS_PAGES
1904  { "_PHYS_PAGES", _SC_PHYS_PAGES, SYSCONF },
1905 #endif
1906 #ifdef _SC_ARG_MAX
1907  { "_POSIX_ARG_MAX", _SC_ARG_MAX, SYSCONF },
1908 #endif
1909 #ifdef _SC_ASYNCHRONOUS_IO
1910  { "_POSIX_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO, SYSCONF },
1911 #endif
1912 #ifdef _SC_CHILD_MAX
1913  { "_POSIX_CHILD_MAX", _SC_CHILD_MAX, SYSCONF },
1914 #endif
1915 #ifdef _SC_FSYNC
1916  { "_POSIX_FSYNC", _SC_FSYNC, SYSCONF },
1917 #endif
1918 #ifdef _SC_JOB_CONTROL
1919  { "_POSIX_JOB_CONTROL", _SC_JOB_CONTROL, SYSCONF },
1920 #endif
1921 #ifdef _SC_MAPPED_FILES
1922  { "_POSIX_MAPPED_FILES", _SC_MAPPED_FILES, SYSCONF },
1923 #endif
1924 #ifdef _SC_MEMLOCK
1925  { "_POSIX_MEMLOCK", _SC_MEMLOCK, SYSCONF },
1926 #endif
1927 #ifdef _SC_MEMLOCK_RANGE
1928  { "_POSIX_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE, SYSCONF },
1929 #endif
1930 #ifdef _SC_MEMORY_PROTECTION
1931  { "_POSIX_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION, SYSCONF },
1932 #endif
1933 #ifdef _SC_MESSAGE_PASSING
1934  { "_POSIX_MESSAGE_PASSING", _SC_MESSAGE_PASSING, SYSCONF },
1935 #endif
1936 #ifdef _SC_NGROUPS_MAX
1937  { "_POSIX_NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF },
1938 #endif
1939 #ifdef _SC_OPEN_MAX
1940  { "_POSIX_OPEN_MAX", _SC_OPEN_MAX, SYSCONF },
1941 #endif
1942 #ifdef _SC_PII
1943  { "_POSIX_PII", _SC_PII, SYSCONF },
1944 #endif
1945 #ifdef _SC_PII_INTERNET
1946  { "_POSIX_PII_INTERNET", _SC_PII_INTERNET, SYSCONF },
1947 #endif
1948 #ifdef _SC_PII_INTERNET_DGRAM
1949  { "_POSIX_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM, SYSCONF },
1950 #endif
1951 #ifdef _SC_PII_INTERNET_STREAM
1952  { "_POSIX_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM, SYSCONF },
1953 #endif
1954 #ifdef _SC_PII_OSI
1955  { "_POSIX_PII_OSI", _SC_PII_OSI, SYSCONF },
1956 #endif
1957 #ifdef _SC_PII_OSI_CLTS
1958  { "_POSIX_PII_OSI_CLTS", _SC_PII_OSI_CLTS, SYSCONF },
1959 #endif
1960 #ifdef _SC_PII_OSI_COTS
1961  { "_POSIX_PII_OSI_COTS", _SC_PII_OSI_COTS, SYSCONF },
1962 #endif
1963 #ifdef _SC_PII_OSI_M
1964  { "_POSIX_PII_OSI_M", _SC_PII_OSI_M, SYSCONF },
1965 #endif
1966 #ifdef _SC_PII_SOCKET
1967  { "_POSIX_PII_SOCKET", _SC_PII_SOCKET, SYSCONF },
1968 #endif
1969 #ifdef _SC_PII_XTI
1970  { "_POSIX_PII_XTI", _SC_PII_XTI, SYSCONF },
1971 #endif
1972 #ifdef _SC_POLL
1973  { "_POSIX_POLL", _SC_POLL, SYSCONF },
1974 #endif
1975 #ifdef _SC_PRIORITIZED_IO
1976  { "_POSIX_PRIORITIZED_IO", _SC_PRIORITIZED_IO, SYSCONF },
1977 #endif
1978 #ifdef _SC_PRIORITY_SCHEDULING
1979  { "_POSIX_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING, SYSCONF },
1980 #endif
1981 #ifdef _SC_REALTIME_SIGNALS
1982  { "_POSIX_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS, SYSCONF },
1983 #endif
1984 #ifdef _SC_SAVED_IDS
1985  { "_POSIX_SAVED_IDS", _SC_SAVED_IDS, SYSCONF },
1986 #endif
1987 #ifdef _SC_SELECT
1988  { "_POSIX_SELECT", _SC_SELECT, SYSCONF },
1989 #endif
1990 #ifdef _SC_SEMAPHORES
1991  { "_POSIX_SEMAPHORES", _SC_SEMAPHORES, SYSCONF },
1992 #endif
1993 #ifdef _SC_SHARED_MEMORY_OBJECTS
1994  { "_POSIX_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS, SYSCONF },
1995 #endif
1996 #ifdef _SC_SSIZE_MAX
1997  { "_POSIX_SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF },
1998 #endif
1999 #ifdef _SC_STREAM_MAX
2000  { "_POSIX_STREAM_MAX", _SC_STREAM_MAX, SYSCONF },
2001 #endif
2002 #ifdef _SC_SYNCHRONIZED_IO
2003  { "_POSIX_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO, SYSCONF },
2004 #endif
2005 #ifdef _SC_THREADS
2006  { "_POSIX_THREADS", _SC_THREADS, SYSCONF },
2007 #endif
2008 #ifdef _SC_THREAD_ATTR_STACKADDR
2009  { "_POSIX_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR, SYSCONF },
2010 #endif
2011 #ifdef _SC_THREAD_ATTR_STACKSIZE
2012  { "_POSIX_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE, SYSCONF },
2013 #endif
2014 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
2015  { "_POSIX_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING, SYSCONF },
2016 #endif
2017 #ifdef _SC_THREAD_PRIO_INHERIT
2018  { "_POSIX_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT, SYSCONF },
2019 #endif
2020 #ifdef _SC_THREAD_PRIO_PROTECT
2021  { "_POSIX_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT, SYSCONF },
2022 #endif
2023 #ifdef _SC_THREAD_PROCESS_SHARED
2024  { "_POSIX_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED, SYSCONF },
2025 #endif
2026 #ifdef _SC_THREAD_SAFE_FUNCTIONS
2027  { "_POSIX_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS, SYSCONF },
2028 #endif
2029 #ifdef _SC_TIMERS
2030  { "_POSIX_TIMERS", _SC_TIMERS, SYSCONF },
2031 #endif
2032 #ifdef _SC_TIMER_MAX
2033  { "TIMER_MAX", _SC_TIMER_MAX, SYSCONF },
2034 #endif
2035 #ifdef _SC_TZNAME_MAX
2036  { "_POSIX_TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF },
2037 #endif
2038 #ifdef _SC_VERSION
2039  { "_POSIX_VERSION", _SC_VERSION, SYSCONF },
2040 #endif
2041 #ifdef _SC_T_IOV_MAX
2042  { "_T_IOV_MAX", _SC_T_IOV_MAX, SYSCONF },
2043 #endif
2044 #ifdef _SC_XOPEN_CRYPT
2045  { "_XOPEN_CRYPT", _SC_XOPEN_CRYPT, SYSCONF },
2046 #endif
2047 #ifdef _SC_XOPEN_ENH_I18N
2048  { "_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N, SYSCONF },
2049 #endif
2050 #ifdef _SC_XOPEN_LEGACY
2051  { "_XOPEN_LEGACY", _SC_XOPEN_LEGACY, SYSCONF },
2052 #endif
2053 #ifdef _SC_XOPEN_REALTIME
2054  { "_XOPEN_REALTIME", _SC_XOPEN_REALTIME, SYSCONF },
2055 #endif
2056 #ifdef _SC_XOPEN_REALTIME_THREADS
2057  { "_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS, SYSCONF },
2058 #endif
2059 #ifdef _SC_XOPEN_SHM
2060  { "_XOPEN_SHM", _SC_XOPEN_SHM, SYSCONF },
2061 #endif
2062 #ifdef _SC_XOPEN_UNIX
2063  { "_XOPEN_UNIX", _SC_XOPEN_UNIX, SYSCONF },
2064 #endif
2065 #ifdef _SC_XOPEN_VERSION
2066  { "_XOPEN_VERSION", _SC_XOPEN_VERSION, SYSCONF },
2067 #endif
2068 #ifdef _SC_XOPEN_XCU_VERSION
2069  { "_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION, SYSCONF },
2070 #endif
2071 #ifdef _SC_XOPEN_XPG2
2072  { "_XOPEN_XPG2", _SC_XOPEN_XPG2, SYSCONF },
2073 #endif
2074 #ifdef _SC_XOPEN_XPG3
2075  { "_XOPEN_XPG3", _SC_XOPEN_XPG3, SYSCONF },
2076 #endif
2077 #ifdef _SC_XOPEN_XPG4
2078  { "_XOPEN_XPG4", _SC_XOPEN_XPG4, SYSCONF },
2079 #endif
2080  /* POSIX.2 */
2081 #ifdef _SC_BC_BASE_MAX
2082  { "BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF },
2083 #endif
2084 #ifdef _SC_BC_DIM_MAX
2085  { "BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF },
2086 #endif
2087 #ifdef _SC_BC_SCALE_MAX
2088  { "BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF },
2089 #endif
2090 #ifdef _SC_BC_STRING_MAX
2091  { "BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF },
2092 #endif
2093 #ifdef _SC_CHARCLASS_NAME_MAX
2094  { "CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX, SYSCONF },
2095 #endif
2096 #ifdef _SC_COLL_WEIGHTS_MAX
2097  { "COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF },
2098 #endif
2099 #ifdef _SC_EQUIV_CLASS_MAX
2100  { "EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX, SYSCONF },
2101 #endif
2102 #ifdef _SC_EXPR_NEST_MAX
2103  { "EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF },
2104 #endif
2105 #ifdef _SC_LINE_MAX
2106  { "LINE_MAX", _SC_LINE_MAX, SYSCONF },
2107 #endif
2108 #ifdef _SC_BC_BASE_MAX
2109  { "POSIX2_BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF },
2110 #endif
2111 #ifdef _SC_BC_DIM_MAX
2112  { "POSIX2_BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF },
2113 #endif
2114 #ifdef _SC_BC_SCALE_MAX
2115  { "POSIX2_BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF },
2116 #endif
2117 #ifdef _SC_BC_STRING_MAX
2118  { "POSIX2_BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF },
2119 #endif
2120 #ifdef _SC_2_CHAR_TERM
2121  { "POSIX2_CHAR_TERM", _SC_2_CHAR_TERM, SYSCONF },
2122 #endif
2123 #ifdef _SC_COLL_WEIGHTS_MAX
2124  { "POSIX2_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF },
2125 #endif
2126 #ifdef _SC_2_C_BIND
2127  { "POSIX2_C_BIND", _SC_2_C_BIND, SYSCONF },
2128 #endif
2129 #ifdef _SC_2_C_DEV
2130  { "POSIX2_C_DEV", _SC_2_C_DEV, SYSCONF },
2131 #endif
2132 #ifdef _SC_2_C_VERSION
2133  { "POSIX2_C_VERSION", _SC_2_C_VERSION, SYSCONF },
2134 #endif
2135 #ifdef _SC_EXPR_NEST_MAX
2136  { "POSIX2_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF },
2137 #endif
2138 #ifdef _SC_2_FORT_DEV
2139  { "POSIX2_FORT_DEV", _SC_2_FORT_DEV, SYSCONF },
2140 #endif
2141 #ifdef _SC_2_FORT_RUN
2142  { "POSIX2_FORT_RUN", _SC_2_FORT_RUN, SYSCONF },
2143 #endif
2144 #ifdef _SC_LINE_MAX
2145  { "_POSIX2_LINE_MAX", _SC_LINE_MAX, SYSCONF },
2146 #endif
2147 #ifdef _SC_2_LOCALEDEF
2148  { "POSIX2_LOCALEDEF", _SC_2_LOCALEDEF, SYSCONF },
2149 #endif
2150 #ifdef _SC_RE_DUP_MAX
2151  { "POSIX2_RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF },
2152 #endif
2153 #ifdef _SC_2_SW_DEV
2154  { "POSIX2_SW_DEV", _SC_2_SW_DEV, SYSCONF },
2155 #endif
2156 #ifdef _SC_2_UPE
2157  { "POSIX2_UPE", _SC_2_UPE, SYSCONF },
2158 #endif
2159 #ifdef _SC_2_VERSION
2160  { "POSIX2_VERSION", _SC_2_VERSION, SYSCONF },
2161 #endif
2162 #ifdef _SC_RE_DUP_MAX
2163  { "RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF },
2164 #endif
2165 
2166 #ifdef _CS_PATH
2167  { "PATH", _CS_PATH, CONFSTR },
2168  { "CS_PATH", _CS_PATH, CONFSTR },
2169 #endif
2170 
2171  /* LFS */
2172 #ifdef _CS_LFS_CFLAGS
2173  { "LFS_CFLAGS", _CS_LFS_CFLAGS, CONFSTR },
2174 #endif
2175 #ifdef _CS_LFS_LDFLAGS
2176  { "LFS_LDFLAGS", _CS_LFS_LDFLAGS, CONFSTR },
2177 #endif
2178 #ifdef _CS_LFS_LIBS
2179  { "LFS_LIBS", _CS_LFS_LIBS, CONFSTR },
2180 #endif
2181 #ifdef _CS_LFS_LINTFLAGS
2182  { "LFS_LINTFLAGS", _CS_LFS_LINTFLAGS, CONFSTR },
2183 #endif
2184 #ifdef _CS_LFS64_CFLAGS
2185  { "LFS64_CFLAGS", _CS_LFS64_CFLAGS, CONFSTR },
2186 #endif
2187 #ifdef _CS_LFS64_LDFLAGS
2188  { "LFS64_LDFLAGS", _CS_LFS64_LDFLAGS, CONFSTR },
2189 #endif
2190 #ifdef _CS_LFS64_LIBS
2191  { "LFS64_LIBS", _CS_LFS64_LIBS, CONFSTR },
2192 #endif
2193 #ifdef _CS_LFS64_LINTFLAGS
2194  { "LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS, CONFSTR },
2195 #endif
2196 
2197  /* Programming environments. */
2198 #ifdef _SC_XBS5_ILP32_OFF32
2199  { "_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32, SYSCONF },
2200 #endif
2201 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
2202  { "XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS, CONFSTR },
2203 #endif
2204 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
2205  { "XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS, CONFSTR },
2206 #endif
2207 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
2208  { "XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS, CONFSTR },
2209 #endif
2210 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
2211  { "XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS, CONFSTR },
2212 #endif
2213 
2214 #ifdef _SC_XBS5_ILP32_OFFBIG
2215  { "_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG, SYSCONF },
2216 #endif
2217 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
2218  { "XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS, CONFSTR },
2219 #endif
2220 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
2221  { "XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS, CONFSTR },
2222 #endif
2223 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
2224  { "XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS, CONFSTR },
2225 #endif
2226 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
2227  { "XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, CONFSTR },
2228 #endif
2229 
2230 #ifdef _SC_XBS5_LP64_OFF64
2231  { "_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64, SYSCONF },
2232 #endif
2233 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
2234  { "XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS, CONFSTR },
2235 #endif
2236 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
2237  { "XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS, CONFSTR },
2238 #endif
2239 #ifdef _CS_XBS5_LP64_OFF64_LIBS
2240  { "XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS, CONFSTR },
2241 #endif
2242 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
2243  { "XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS, CONFSTR },
2244 #endif
2245 
2246 #ifdef _SC_XBS5_LPBIG_OFFBIG
2247  { "_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG, SYSCONF },
2248 #endif
2249 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
2250  { "XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS, CONFSTR },
2251 #endif
2252 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
2253  { "XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, CONFSTR },
2254 #endif
2255 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
2256  { "XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS, CONFSTR },
2257 #endif
2258 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
2259  { "XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, CONFSTR },
2260 #endif
2261 
2262 #ifdef _SC_V6_ILP32_OFF32
2263  { "_POSIX_V6_ILP32_OFF32", _SC_V6_ILP32_OFF32, SYSCONF },
2264 #endif
2265 #ifdef _CS_POSIX_V6_ILP32_OFF32_CFLAGS
2266  { "POSIX_V6_ILP32_OFF32_CFLAGS", _CS_POSIX_V6_ILP32_OFF32_CFLAGS, CONFSTR },
2267 #endif
2268 #ifdef _CS_POSIX_V6_ILP32_OFF32_LDFLAGS
2269  { "POSIX_V6_ILP32_OFF32_LDFLAGS", _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, CONFSTR },
2270 #endif
2271 #ifdef _CS_POSIX_V6_ILP32_OFF32_LIBS
2272  { "POSIX_V6_ILP32_OFF32_LIBS", _CS_POSIX_V6_ILP32_OFF32_LIBS, CONFSTR },
2273 #endif
2274 #ifdef _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS
2275  { "POSIX_V6_ILP32_OFF32_LINTFLAGS", _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, CONFSTR },
2276 #endif
2277 
2278 #ifdef _CS_V6_WIDTH_RESTRICTED_ENVS
2279  { "_POSIX_V6_WIDTH_RESTRICTED_ENVS", _CS_V6_WIDTH_RESTRICTED_ENVS, CONFSTR },
2280 #endif
2281 
2282 #ifdef _SC_V6_ILP32_OFFBIG
2283  { "_POSIX_V6_ILP32_OFFBIG", _SC_V6_ILP32_OFFBIG, SYSCONF },
2284 #endif
2285 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
2286  { "POSIX_V6_ILP32_OFFBIG_CFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, CONFSTR },
2287 #endif
2288 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
2289  { "POSIX_V6_ILP32_OFFBIG_LDFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, CONFSTR },
2290 #endif
2291 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LIBS
2292  { "POSIX_V6_ILP32_OFFBIG_LIBS", _CS_POSIX_V6_ILP32_OFFBIG_LIBS, CONFSTR },
2293 #endif
2294 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS
2295  { "POSIX_V6_ILP32_OFFBIG_LINTFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, CONFSTR },
2296 #endif
2297 
2298 #ifdef _SC_V6_LP64_OFF64
2299  { "_POSIX_V6_LP64_OFF64", _SC_V6_LP64_OFF64, SYSCONF },
2300 #endif
2301 #ifdef _CS_POSIX_V6_LP64_OFF64_CFLAGS
2302  { "POSIX_V6_LP64_OFF64_CFLAGS", _CS_POSIX_V6_LP64_OFF64_CFLAGS, CONFSTR },
2303 #endif
2304 #ifdef _CS_POSIX_V6_LP64_OFF64_LDFLAGS
2305  { "POSIX_V6_LP64_OFF64_LDFLAGS", _CS_POSIX_V6_LP64_OFF64_LDFLAGS, CONFSTR },
2306 #endif
2307 #ifdef _CS_POSIX_V6_LP64_OFF64_LIBS
2308  { "POSIX_V6_LP64_OFF64_LIBS", _CS_POSIX_V6_LP64_OFF64_LIBS, CONFSTR },
2309 #endif
2310 #ifdef _CS_POSIX_V6_LP64_OFF64_LINTFLAGS
2311  { "POSIX_V6_LP64_OFF64_LINTFLAGS", _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, CONFSTR },
2312 #endif
2313 
2314 #ifdef _SC_V6_LPBIG_OFFBIG
2315  { "_POSIX_V6_LPBIG_OFFBIG", _SC_V6_LPBIG_OFFBIG, SYSCONF },
2316 #endif
2317 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
2318  { "POSIX_V6_LPBIG_OFFBIG_CFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, CONFSTR },
2319 #endif
2320 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
2321  { "POSIX_V6_LPBIG_OFFBIG_LDFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, CONFSTR },
2322 #endif
2323 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
2324  { "POSIX_V6_LPBIG_OFFBIG_LIBS", _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, CONFSTR },
2325 #endif
2326 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS
2327  { "POSIX_V6_LPBIG_OFFBIG_LINTFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, CONFSTR },
2328 #endif
2329 
2330 #ifdef _SC_ADVISORY_INFO
2331  { "_POSIX_ADVISORY_INFO", _SC_ADVISORY_INFO, SYSCONF },
2332 #endif
2333 #ifdef _SC_BARRIERS
2334  { "_POSIX_BARRIERS", _SC_BARRIERS, SYSCONF },
2335 #endif
2336 #ifdef _SC_BASE
2337  { "_POSIX_BASE", _SC_BASE, SYSCONF },
2338 #endif
2339 #ifdef _SC_C_LANG_SUPPORT
2340  { "_POSIX_C_LANG_SUPPORT", _SC_C_LANG_SUPPORT, SYSCONF },
2341 #endif
2342 #ifdef _SC_C_LANG_SUPPORT_R
2343  { "_POSIX_C_LANG_SUPPORT_R", _SC_C_LANG_SUPPORT_R, SYSCONF },
2344 #endif
2345 #ifdef _SC_CLOCK_SELECTION
2346  { "_POSIX_CLOCK_SELECTION", _SC_CLOCK_SELECTION, SYSCONF },
2347 #endif
2348 #ifdef _SC_CPUTIME
2349  { "_POSIX_CPUTIME", _SC_CPUTIME, SYSCONF },
2350 #endif
2351 #ifdef _SC_THREAD_CPUTIME
2352  { "_POSIX_THREAD_CPUTIME", _SC_THREAD_CPUTIME, SYSCONF },
2353 #endif
2354 #ifdef _SC_DEVICE_SPECIFIC
2355  { "_POSIX_DEVICE_SPECIFIC", _SC_DEVICE_SPECIFIC, SYSCONF },
2356 #endif
2357 #ifdef _SC_DEVICE_SPECIFIC_R
2358  { "_POSIX_DEVICE_SPECIFIC_R", _SC_DEVICE_SPECIFIC_R, SYSCONF },
2359 #endif
2360 #ifdef _SC_FD_MGMT
2361  { "_POSIX_FD_MGMT", _SC_FD_MGMT, SYSCONF },
2362 #endif
2363 #ifdef _SC_FIFO
2364  { "_POSIX_FIFO", _SC_FIFO, SYSCONF },
2365 #endif
2366 #ifdef _SC_PIPE
2367  { "_POSIX_PIPE", _SC_PIPE, SYSCONF },
2368 #endif
2369 #ifdef _SC_FILE_ATTRIBUTES
2370  { "_POSIX_FILE_ATTRIBUTES", _SC_FILE_ATTRIBUTES, SYSCONF },
2371 #endif
2372 #ifdef _SC_FILE_LOCKING
2373  { "_POSIX_FILE_LOCKING", _SC_FILE_LOCKING, SYSCONF },
2374 #endif
2375 #ifdef _SC_FILE_SYSTEM
2376  { "_POSIX_FILE_SYSTEM", _SC_FILE_SYSTEM, SYSCONF },
2377 #endif
2378 #ifdef _SC_MONOTONIC_CLOCK
2379  { "_POSIX_MONOTONIC_CLOCK", _SC_MONOTONIC_CLOCK, SYSCONF },
2380 #endif
2381 #ifdef _SC_MULTI_PROCESS
2382  { "_POSIX_MULTI_PROCESS", _SC_MULTI_PROCESS, SYSCONF },
2383 #endif
2384 #ifdef _SC_SINGLE_PROCESS
2385  { "_POSIX_SINGLE_PROCESS", _SC_SINGLE_PROCESS, SYSCONF },
2386 #endif
2387 #ifdef _SC_NETWORKING
2388  { "_POSIX_NETWORKING", _SC_NETWORKING, SYSCONF },
2389 #endif
2390 #ifdef _SC_READER_WRITER_LOCKS
2391  { "_POSIX_READER_WRITER_LOCKS", _SC_READER_WRITER_LOCKS, SYSCONF },
2392 #endif
2393 #ifdef _SC_SPIN_LOCKS
2394  { "_POSIX_SPIN_LOCKS", _SC_SPIN_LOCKS, SYSCONF },
2395 #endif
2396 #ifdef _SC_REGEXP
2397  { "_POSIX_REGEXP", _SC_REGEXP, SYSCONF },
2398 #endif
2399 #ifdef _SC_REGEX_VERSION
2400  { "_REGEX_VERSION", _SC_REGEX_VERSION, SYSCONF },
2401 #endif
2402 #ifdef _SC_SHELL
2403  { "_POSIX_SHELL", _SC_SHELL, SYSCONF },
2404 #endif
2405 #ifdef _SC_SIGNALS
2406  { "_POSIX_SIGNALS", _SC_SIGNALS, SYSCONF },
2407 #endif
2408 #ifdef _SC_SPAWN
2409  { "_POSIX_SPAWN", _SC_SPAWN, SYSCONF },
2410 #endif
2411 #ifdef _SC_SPORADIC_SERVER
2412  { "_POSIX_SPORADIC_SERVER", _SC_SPORADIC_SERVER, SYSCONF },
2413 #endif
2414 #ifdef _SC_THREAD_SPORADIC_SERVER
2415  { "_POSIX_THREAD_SPORADIC_SERVER", _SC_THREAD_SPORADIC_SERVER, SYSCONF },
2416 #endif
2417 #ifdef _SC_SYSTEM_DATABASE
2418  { "_POSIX_SYSTEM_DATABASE", _SC_SYSTEM_DATABASE, SYSCONF },
2419 #endif
2420 #ifdef _SC_SYSTEM_DATABASE_R
2421  { "_POSIX_SYSTEM_DATABASE_R", _SC_SYSTEM_DATABASE_R, SYSCONF },
2422 #endif
2423 #ifdef _SC_TIMEOUTS
2424  { "_POSIX_TIMEOUTS", _SC_TIMEOUTS, SYSCONF },
2425 #endif
2426 #ifdef _SC_TYPED_MEMORY_OBJECTS
2427  { "_POSIX_TYPED_MEMORY_OBJECTS", _SC_TYPED_MEMORY_OBJECTS, SYSCONF },
2428 #endif
2429 #ifdef _SC_USER_GROUPS
2430  { "_POSIX_USER_GROUPS", _SC_USER_GROUPS, SYSCONF },
2431 #endif
2432 #ifdef _SC_USER_GROUPS_R
2433  { "_POSIX_USER_GROUPS_R", _SC_USER_GROUPS_R, SYSCONF },
2434 #endif
2435 #ifdef _SC_2_PBS
2436  { "POSIX2_PBS", _SC_2_PBS, SYSCONF },
2437 #endif
2438 #ifdef _SC_2_PBS_ACCOUNTING
2439  { "POSIX2_PBS_ACCOUNTING", _SC_2_PBS_ACCOUNTING, SYSCONF },
2440 #endif
2441 #ifdef _SC_2_PBS_LOCATE
2442  { "POSIX2_PBS_LOCATE", _SC_2_PBS_LOCATE, SYSCONF },
2443 #endif
2444 #ifdef _SC_2_PBS_TRACK
2445  { "POSIX2_PBS_TRACK", _SC_2_PBS_TRACK, SYSCONF },
2446 #endif
2447 #ifdef _SC_2_PBS_MESSAGE
2448  { "POSIX2_PBS_MESSAGE", _SC_2_PBS_MESSAGE, SYSCONF },
2449 #endif
2450 #ifdef _SC_SYMLOOP_MAX
2451  { "SYMLOOP_MAX", _SC_SYMLOOP_MAX, SYSCONF },
2452 #endif
2453 #ifdef _SC_STREAM_MAX
2454  { "STREAM_MAX", _SC_STREAM_MAX, SYSCONF },
2455 #endif
2456 #ifdef _SC_AIO_LISTIO_MAX
2457  { "AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX, SYSCONF },
2458 #endif
2459 #ifdef _SC_AIO_MAX
2460  { "AIO_MAX", _SC_AIO_MAX, SYSCONF },
2461 #endif
2462 #ifdef _SC_AIO_PRIO_DELTA_MAX
2463  { "AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX, SYSCONF },
2464 #endif
2465 #ifdef _SC_DELAYTIMER_MAX
2466  { "DELAYTIMER_MAX", _SC_DELAYTIMER_MAX, SYSCONF },
2467 #endif
2468 #ifdef _SC_HOST_NAME_MAX
2469  { "HOST_NAME_MAX", _SC_HOST_NAME_MAX, SYSCONF },
2470 #endif
2471 #ifdef _SC_LOGIN_NAME_MAX
2472  { "LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF },
2473 #endif
2474 #ifdef _SC_MQ_OPEN_MAX
2475  { "MQ_OPEN_MAX", _SC_MQ_OPEN_MAX, SYSCONF },
2476 #endif
2477 #ifdef _SC_MQ_PRIO_MAX
2478  { "MQ_PRIO_MAX", _SC_MQ_PRIO_MAX, SYSCONF },
2479 #endif
2480 #ifdef _SC_DEVICE_IO
2481  { "_POSIX_DEVICE_IO", _SC_DEVICE_IO, SYSCONF },
2482 #endif
2483 #ifdef _SC_TRACE
2484  { "_POSIX_TRACE", _SC_TRACE, SYSCONF },
2485 #endif
2486 #ifdef _SC_TRACE_EVENT_FILTER
2487  { "_POSIX_TRACE_EVENT_FILTER", _SC_TRACE_EVENT_FILTER, SYSCONF },
2488 #endif
2489 #ifdef _SC_TRACE_INHERIT
2490  { "_POSIX_TRACE_INHERIT", _SC_TRACE_INHERIT, SYSCONF },
2491 #endif
2492 #ifdef _SC_TRACE_LOG
2493  { "_POSIX_TRACE_LOG", _SC_TRACE_LOG, SYSCONF },
2494 #endif
2495 #ifdef _SC_RTSIG_MAX
2496  { "RTSIG_MAX", _SC_RTSIG_MAX, SYSCONF },
2497 #endif
2498 #ifdef _SC_SEM_NSEMS_MAX
2499  { "SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX, SYSCONF },
2500 #endif
2501 #ifdef _SC_SEM_VALUE_MAX
2502  { "SEM_VALUE_MAX", _SC_SEM_VALUE_MAX, SYSCONF },
2503 #endif
2504 #ifdef _SC_SIGQUEUE_MAX
2505  { "SIGQUEUE_MAX", _SC_SIGQUEUE_MAX, SYSCONF },
2506 #endif
2507 #ifdef _PC_FILESIZEBITS
2508  { "FILESIZEBITS", _PC_FILESIZEBITS, PATHCONF },
2509 #endif
2510 #ifdef _PC_ALLOC_SIZE_MIN
2511  { "POSIX_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN, PATHCONF },
2512 #endif
2513 #ifdef _PC_REC_INCR_XFER_SIZE
2514  { "POSIX_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE, PATHCONF },
2515 #endif
2516 #ifdef _PC_REC_MAX_XFER_SIZE
2517  { "POSIX_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE, PATHCONF },
2518 #endif
2519 #ifdef _PC_REC_MIN_XFER_SIZE
2520  { "POSIX_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE, PATHCONF },
2521 #endif
2522 #ifdef _PC_REC_XFER_ALIGN
2523  { "POSIX_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN, PATHCONF },
2524 #endif
2525 #ifdef _PC_SYMLINK_MAX
2526  { "SYMLINK_MAX", _PC_SYMLINK_MAX, PATHCONF },
2527 #endif
2528 #ifdef _CS_GNU_LIBC_VERSION
2529  { "GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION, CONFSTR },
2530 #endif
2531 #ifdef _CS_GNU_LIBPTHREAD_VERSION
2532  { "GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION, CONFSTR },
2533 #endif
2534 #ifdef _PC_2_SYMLINKS
2535  { "POSIX2_SYMLINKS", _PC_2_SYMLINKS, PATHCONF },
2536 #endif
2537 
2538 #ifdef _SC_LEVEL1_ICACHE_SIZE
2539  { "LEVEL1_ICACHE_SIZE", _SC_LEVEL1_ICACHE_SIZE, SYSCONF },
2540 #endif
2541 #ifdef _SC_LEVEL1_ICACHE_ASSOC
2542  { "LEVEL1_ICACHE_ASSOC", _SC_LEVEL1_ICACHE_ASSOC, SYSCONF },
2543 #endif
2544 #ifdef _SC_LEVEL1_ICACHE_LINESIZE
2545  { "LEVEL1_ICACHE_LINESIZE", _SC_LEVEL1_ICACHE_LINESIZE, SYSCONF },
2546 #endif
2547 #ifdef _SC_LEVEL1_DCACHE_SIZE
2548  { "LEVEL1_DCACHE_SIZE", _SC_LEVEL1_DCACHE_SIZE, SYSCONF },
2549 #endif
2550 #ifdef _SC_LEVEL1_DCACHE_ASSOC
2551  { "LEVEL1_DCACHE_ASSOC", _SC_LEVEL1_DCACHE_ASSOC, SYSCONF },
2552 #endif
2553 #ifdef _SC_LEVEL1_DCACHE_LINESIZE
2554  { "LEVEL1_DCACHE_LINESIZE", _SC_LEVEL1_DCACHE_LINESIZE, SYSCONF },
2555 #endif
2556 #ifdef _SC_LEVEL2_CACHE_SIZE
2557  { "LEVEL2_CACHE_SIZE", _SC_LEVEL2_CACHE_SIZE, SYSCONF },
2558 #endif
2559 #ifdef _SC_LEVEL2_CACHE_ASSOC
2560  { "LEVEL2_CACHE_ASSOC", _SC_LEVEL2_CACHE_ASSOC, SYSCONF },
2561 #endif
2562 #ifdef _SC_LEVEL2_CACHE_LINESIZE
2563  { "LEVEL2_CACHE_LINESIZE", _SC_LEVEL2_CACHE_LINESIZE, SYSCONF },
2564 #endif
2565 #ifdef _SC_LEVEL3_CACHE_SIZE
2566  { "LEVEL3_CACHE_SIZE", _SC_LEVEL3_CACHE_SIZE, SYSCONF },
2567 #endif
2568 #ifdef _SC_LEVEL3_CACHE_ASSOC
2569  { "LEVEL3_CACHE_ASSOC", _SC_LEVEL3_CACHE_ASSOC, SYSCONF },
2570 #endif
2571 #ifdef _SC_LEVEL3_CACHE_LINESIZE
2572  { "LEVEL3_CACHE_LINESIZE", _SC_LEVEL3_CACHE_LINESIZE, SYSCONF },
2573 #endif
2574 #ifdef _SC_LEVEL4_CACHE_SIZE
2575  { "LEVEL4_CACHE_SIZE", _SC_LEVEL4_CACHE_SIZE, SYSCONF },
2576 #endif
2577 #ifdef _SC_LEVEL4_CACHE_ASSOC
2578  { "LEVEL4_CACHE_ASSOC", _SC_LEVEL4_CACHE_ASSOC, SYSCONF },
2579 #endif
2580 
2581 #ifdef _SC_IPV6
2582  { "IPV6", _SC_IPV6, SYSCONF },
2583 #endif
2584 #ifdef _SC_RAW_SOCKETS
2585  { "RAW_SOCKETS", _SC_RAW_SOCKETS, SYSCONF },
2586 #endif
2587 
2588  { NULL, 0, SYSCONF }
2589 };
2590 
2591 #define _GETCONF_PATH "/"
2592 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
2593 static const char *_getconf_path = NULL;
2594 
2595 int
2596 rpmdsGetconf(rpmds * dsp, const char *path)
2597  /*@globals _getconf_path @*/
2598  /*@modifies _getconf_path @*/
2599 {
2600  const struct conf *c;
2601  size_t clen;
2602  long int value;
2603  const char * NS = "getconf";
2604  const char *N;
2605  char * EVR;
2606  char * t;
2607  int_32 Flags;
2608 
2609 /*@-modobserver@*/
2610  if (_getconf_path == NULL) {
2611  _getconf_path = rpmExpand("%{?_rpmds__getconf_path}", NULL);
2612  /* XXX may need to validate path existence somewhen. */
2613  if (!(_getconf_path != NULL && *_getconf_path == '/')) {
2614 /*@-observertrans @*/
2615  _getconf_path = _free(_getconf_path);
2616 /*@=observertrans @*/
2617  _getconf_path = xstrdup(_GETCONF_PATH);
2618  }
2619  }
2620 /*@=modobserver@*/
2621 
2622 /*@-branchstate@*/
2623  if (path == NULL)
2624  path = _getconf_path;
2625 
2626  for (c = vars; c->name != NULL; ++c) {
2627  N = c->name;
2628  EVR = NULL;
2629  switch (c->call) {
2630  case PATHCONF:
2631  value = pathconf(path, c->call_name);
2632  if (value != -1) {
2633  EVR = xmalloc(32);
2634  sprintf(EVR, "%ld", value);
2635  }
2636  /*@switchbreak@*/ break;
2637  case SYSCONF:
2638  value = sysconf(c->call_name);
2639  if (value == -1l) {
2640 #if defined(_SC_UINT_MAX) && defined(_SC_ULONG_MAX)
2641 /*@-unrecog@*/
2642  if (c->call_name == _SC_UINT_MAX
2643  || c->call_name == _SC_ULONG_MAX) {
2644  EVR = xmalloc(32);
2645  sprintf(EVR, "%lu", value);
2646  }
2647 /*@=unrecog@*/
2648 #endif
2649  } else {
2650  EVR = xmalloc(32);
2651  sprintf(EVR, "%ld", value);
2652  }
2653  /*@switchbreak@*/ break;
2654  case CONFSTR:
2655  clen = confstr(c->call_name, (char *) NULL, 0);
2656  EVR = xmalloc(clen+1);
2657  *EVR = '\0';
2658  if (confstr (c->call_name, EVR, clen) != clen) {
2659  fprintf(stderr, "confstr: %s\n", strerror(errno));
2660  exit (EXIT_FAILURE);
2661  }
2662  EVR[clen] = '\0';
2663  /*@switchbreak@*/ break;
2664  }
2665  if (EVR == NULL)
2666  continue;
2667 
2668  for (t = EVR; *t; t++) {
2669  if (*t == '\n') *t = ' ';
2670  }
2671  if (!strcmp(N, "GNU_LIBC_VERSION")
2672  || !strcmp(N, "GNU_LIBPTHREAD_VERSION"))
2673  {
2674  for (t = EVR; *t; t++) {
2675  if (*t == ' ') *t = '-';
2676  }
2677  }
2678 
2679  if (*EVR == '\0' || strchr(EVR, ' ') != NULL
2680  || (EVR[0] == '-' && strchr("0123456789", EVR[1]) == NULL))
2681  {
2682  EVR = _free(EVR);
2683  continue;
2684  }
2685 
2686  Flags = RPMSENSE_PROBE|RPMSENSE_EQUAL;
2687  rpmdsNSAdd(dsp, NS, N, EVR, Flags);
2688  EVR = _free(EVR);
2689  }
2690 /*@=branchstate@*/
2691  return 0;
2692 }
2693 
2694 int rpmdsMergePRCO(void * context, rpmds ds)
2695 {
2696  rpmPRCO PRCO = context;
2697  int rc = -1;
2698 
2699 /*@-modfilesys@*/
2700 if (_rpmds_debug < 0)
2701 fprintf(stderr, "*** %s(%p, %p) %s\n", __FUNCTION__, context, ds, tagName(rpmdsTagN(ds)));
2702 /*@=modfilesys@*/
2703  switch(rpmdsTagN(ds)) {
2704  default:
2705  break;
2706  case RPMTAG_PROVIDENAME:
2707  rc = rpmdsMerge(PRCO->Pdsp, ds);
2708  break;
2709  case RPMTAG_REQUIRENAME:
2710  rc = rpmdsMerge(PRCO->Rdsp, ds);
2711  break;
2712  case RPMTAG_CONFLICTNAME:
2713  rc = rpmdsMerge(PRCO->Cdsp, ds);
2714  break;
2715  case RPMTAG_OBSOLETENAME:
2716  rc = rpmdsMerge(PRCO->Odsp, ds);
2717  break;
2718  case RPMTAG_TRIGGERNAME:
2719  rc = rpmdsMerge(PRCO->Tdsp, ds);
2720  break;
2721  case RPMTAG_DIRNAMES:
2722  rc = rpmdsMerge(PRCO->Ddsp, ds);
2723  break;
2724  case RPMTAG_FILELINKTOS:
2725  rc = rpmdsMerge(PRCO->Ldsp, ds);
2726  break;
2727  }
2728  return rc;
2729 }
2730 
2732 {
2733  if (PRCO) {
2734  PRCO->this = rpmdsFree(PRCO->this);
2735  PRCO->P = rpmdsFree(PRCO->P);
2736  PRCO->R = rpmdsFree(PRCO->R);
2737  PRCO->C = rpmdsFree(PRCO->C);
2738  PRCO->O = rpmdsFree(PRCO->O);
2739  PRCO->T = rpmdsFree(PRCO->T);
2740  PRCO->D = rpmdsFree(PRCO->D);
2741  PRCO->L = rpmdsFree(PRCO->L);
2742  PRCO->Pdsp = NULL;
2743  PRCO->Rdsp = NULL;
2744  PRCO->Cdsp = NULL;
2745  PRCO->Odsp = NULL;
2746  PRCO->Tdsp = NULL;
2747  PRCO->Ddsp = NULL;
2748  PRCO->Ldsp = NULL;
2749  PRCO = _free(PRCO);
2750  }
2751  return NULL;
2752 }
2753 
2755 {
2756  rpmPRCO PRCO = xcalloc(1, sizeof(*PRCO));
2757 
2758  if (h != NULL) {
2759  int scareMem = 0;
2760  PRCO->this = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
2761  PRCO->P = rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem);
2762  PRCO->R = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
2763  PRCO->C = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
2764  PRCO->O = rpmdsNew(h, RPMTAG_OBSOLETENAME, scareMem);
2765  PRCO->T = rpmdsNew(h, RPMTAG_TRIGGERNAME, scareMem);
2766  PRCO->D = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem);
2767  PRCO->L = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem);
2768  }
2769  PRCO->Pdsp = &PRCO->P;
2770  PRCO->Rdsp = &PRCO->R;
2771  PRCO->Cdsp = &PRCO->C;
2772  PRCO->Odsp = &PRCO->O;
2773  PRCO->Tdsp = &PRCO->T;
2774  PRCO->Ddsp = &PRCO->D;
2775  PRCO->Ldsp = &PRCO->L;
2776  return PRCO;
2777 }
2778 
2780 {
2781  if (PRCO == NULL)
2782  return NULL;
2783  /*@-compdef -refcounttrans -retalias -retexpose -usereleased @*/
2784  if (tagN == RPMTAG_NAME)
2785  return PRCO->this;
2786  if (tagN == RPMTAG_PROVIDENAME)
2787  return *PRCO->Pdsp;
2788  if (tagN == RPMTAG_REQUIRENAME)
2789  return *PRCO->Rdsp;
2790  if (tagN == RPMTAG_CONFLICTNAME)
2791  return *PRCO->Cdsp;
2792  if (tagN == RPMTAG_OBSOLETENAME)
2793  return *PRCO->Odsp;
2794  if (tagN == RPMTAG_TRIGGERNAME)
2795  return *PRCO->Tdsp;
2796  if (tagN == RPMTAG_DIRNAMES)
2797  return *PRCO->Ddsp;
2798  if (tagN == RPMTAG_FILELINKTOS)
2799  return *PRCO->Ldsp;
2800  return NULL;
2801  /*@=compdef =refcounttrans =retalias =retexpose =usereleased @*/
2802 }
2803 
2810 static char * sonameDep(/*@returned@*/ char * t, const char * s, int isElf64)
2811  /*@modifies t @*/
2812 {
2813  *t = '\0';
2814 #if !defined(__alpha__) && !defined(__sun)
2815  if (isElf64) {
2816  if (s[strlen(s)-1] != ')')
2817  (void) stpcpy( stpcpy(t, s), "()(64bit)");
2818  else
2819  (void) stpcpy( stpcpy(t, s), "(64bit)");
2820  }else
2821 #endif
2822  (void) stpcpy(t, s);
2823  return t;
2824 }
2825 
2826 int rpmdsELF(const char * fn, int flags,
2827  int (*add) (void * context, rpmds ds), void * context)
2828 {
2829 #if HAVE_GELF_H && HAVE_LIBELF
2830  Elf * elf;
2831  Elf_Scn * scn;
2832  Elf_Data * data;
2833  GElf_Ehdr ehdr_mem, * ehdr;
2834  GElf_Shdr shdr_mem, * shdr;
2835  GElf_Verdef def_mem, * def;
2836  GElf_Verneed need_mem, * need;
2837  GElf_Dyn dyn_mem, * dyn;
2838  unsigned int auxoffset;
2839  unsigned int offset;
2840  int fdno;
2841  int cnt2;
2842  int cnt;
2843  char buf[BUFSIZ];
2844  const char * s;
2845  int is_executable;
2846  const char * soname = NULL;
2847  rpmds ds;
2848  char * t;
2849  int xx;
2850  int isElf64;
2851  int isDSO;
2852  int gotSONAME = 0;
2853  int gotDEBUG = 0;
2854  int gotHASH = 0;
2855  int gotGNUHASH = 0;
2856  int skipP = (flags & RPMELF_FLAG_SKIPPROVIDES);
2857  int skipR = (flags & RPMELF_FLAG_SKIPREQUIRES);
2858  static int filter_GLIBC_PRIVATE = 0;
2859  static int oneshot = 0;
2860 
2861 /*@-castfcnptr@*/
2862 if (_rpmds_debug < 0)
2863 fprintf(stderr, "*** %s(%s, %d, %p, %p)\n", __FUNCTION__, fn, flags, (void *)add, context);
2864 /*@=castfcnptr@*/
2865  if (oneshot == 0) {
2866  oneshot = 1;
2867  filter_GLIBC_PRIVATE = rpmExpandNumeric("%{?_filter_GLIBC_PRIVATE}");
2868  }
2869 
2870  /* Extract dependencies only from files with executable bit set. */
2871  { struct stat sb, * st = &sb;
2872  if (stat(fn, st) != 0)
2873  return -1;
2874  is_executable = (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
2875  }
2876 
2877  fdno = open(fn, O_RDONLY);
2878  if (fdno < 0)
2879  return fdno;
2880 
2881  (void) elf_version(EV_CURRENT);
2882 
2883 /*@-evalorder@*/
2884  elf = NULL;
2885  if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
2886  || elf_kind(elf) != ELF_K_ELF
2887  || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
2888  || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
2889  goto exit;
2890 /*@=evalorder@*/
2891 
2892  isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
2893  isDSO = ehdr->e_type == ET_DYN;
2894 
2895  /*@-branchstate -uniondef @*/
2896  scn = NULL;
2897  while ((scn = elf_nextscn(elf, scn)) != NULL) {
2898  shdr = gelf_getshdr(scn, &shdr_mem);
2899  if (shdr == NULL)
2900  break;
2901 
2902  soname = _free(soname);
2903  switch (shdr->sh_type) {
2904  default:
2905  continue;
2906  /*@notreached@*/ /*@switchbreak@*/ break;
2907  case SHT_GNU_verdef:
2908  data = NULL;
2909  if (!skipP)
2910  while ((data = elf_getdata (scn, data)) != NULL) {
2911  offset = 0;
2912  for (cnt = shdr->sh_info; --cnt >= 0; ) {
2913 
2914  def = gelf_getverdef (data, offset, &def_mem);
2915  if (def == NULL)
2916  /*@innerbreak@*/ break;
2917  auxoffset = offset + def->vd_aux;
2918  for (cnt2 = def->vd_cnt; --cnt2 >= 0; ) {
2919  GElf_Verdaux aux_mem, * aux;
2920 
2921  aux = gelf_getverdaux (data, auxoffset, &aux_mem);
2922  if (aux == NULL)
2923  /*@innerbreak@*/ break;
2924 
2925  s = elf_strptr(elf, shdr->sh_link, aux->vda_name);
2926  if (s == NULL)
2927  /*@innerbreak@*/ break;
2928 
2929  if (def->vd_flags & VER_FLG_BASE) {
2930  soname = _free(soname);
2931  soname = xstrdup(s);
2932  } else
2933  if (soname != NULL
2934  && !(filter_GLIBC_PRIVATE != 0
2935  && !strcmp(s, "GLIBC_PRIVATE")))
2936  {
2937  buf[0] = '\0';
2938  t = buf;
2939  t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
2940 
2941  t++; /* XXX "foo(bar)" already in buf. */
2942 
2943  /* Add next provide dependency. */
2945  sonameDep(t, buf, isElf64),
2946  "", RPMSENSE_FIND_PROVIDES);
2947  xx = add(context, ds);
2948  ds = rpmdsFree(ds);
2949  }
2950  auxoffset += aux->vda_next;
2951  }
2952  offset += def->vd_next;
2953  }
2954  }
2955  /*@switchbreak@*/ break;
2956  case SHT_GNU_verneed:
2957  data = NULL;
2958  /* Only from files with executable bit set. */
2959  if (!skipR && is_executable)
2960  while ((data = elf_getdata (scn, data)) != NULL) {
2961  offset = 0;
2962  for (cnt = shdr->sh_info; --cnt >= 0; ) {
2963  need = gelf_getverneed (data, offset, &need_mem);
2964  if (need == NULL)
2965  /*@innerbreak@*/ break;
2966 
2967  s = elf_strptr(elf, shdr->sh_link, need->vn_file);
2968  if (s == NULL)
2969  /*@innerbreak@*/ break;
2970  soname = _free(soname);
2971  soname = xstrdup(s);
2972  auxoffset = offset + need->vn_aux;
2973  for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) {
2974  GElf_Vernaux aux_mem, * aux;
2975 
2976  aux = gelf_getvernaux (data, auxoffset, &aux_mem);
2977  if (aux == NULL)
2978  /*@innerbreak@*/ break;
2979 
2980  s = elf_strptr(elf, shdr->sh_link, aux->vna_name);
2981  if (s == NULL)
2982  /*@innerbreak@*/ break;
2983 
2984  /* Filter dependencies that contain GLIBC_PRIVATE */
2985  if (soname != NULL
2986  && !(filter_GLIBC_PRIVATE != 0
2987  && !strcmp(s, "GLIBC_PRIVATE")))
2988  {
2989  buf[0] = '\0';
2990  t = buf;
2991  t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
2992 
2993  t++; /* XXX "foo(bar)" already in buf. */
2994 
2995  /* Add next require dependency. */
2997  sonameDep(t, buf, isElf64),
2998  "", RPMSENSE_FIND_REQUIRES);
2999  xx = add(context, ds);
3000  ds = rpmdsFree(ds);
3001  }
3002  auxoffset += aux->vna_next;
3003  }
3004  offset += need->vn_next;
3005  }
3006  }
3007  /*@switchbreak@*/ break;
3008  case SHT_DYNAMIC:
3009  data = NULL;
3010  while ((data = elf_getdata (scn, data)) != NULL) {
3011 /*@-boundswrite@*/
3012  for (cnt = 0; cnt < (shdr->sh_size / shdr->sh_entsize); ++cnt) {
3013  dyn = gelf_getdyn (data, cnt, &dyn_mem);
3014  if (dyn == NULL)
3015  /*@innerbreak@*/ break;
3016  s = NULL;
3017  switch (dyn->d_tag) {
3018  default:
3019  /*@innercontinue@*/ continue;
3020  /*@notreached@*/ /*@switchbreak@*/ break;
3021  case DT_HASH:
3022  gotHASH= 1;
3023  /*@innercontinue@*/ continue;
3024  case DT_GNU_HASH:
3025  gotGNUHASH= 1;
3026  /*@innercontinue@*/ continue;
3027  case DT_DEBUG:
3028  gotDEBUG = 1;
3029  /*@innercontinue@*/ continue;
3030  case DT_NEEDED:
3031  /* Only from files with executable bit set. */
3032  if (skipR || !is_executable)
3033  /*@innercontinue@*/ continue;
3034  /* Add next require dependency. */
3035  s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
3036 assert(s != NULL);
3037  buf[0] = '\0';
3039  sonameDep(buf, s, isElf64),
3040  "", RPMSENSE_FIND_REQUIRES);
3041  xx = add(context, ds);
3042  ds = rpmdsFree(ds);
3043  /*@switchbreak@*/ break;
3044  case DT_SONAME:
3045  gotSONAME = 1;
3046  if (skipP)
3047  /*@innercontinue@*/ continue;
3048  s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
3049 assert(s != NULL);
3050  /* Add next provide dependency. */
3051  buf[0] = '\0';
3053  sonameDep(buf, s, isElf64),
3054  "", RPMSENSE_FIND_PROVIDES);
3055  xx = add(context, ds);
3056  ds = rpmdsFree(ds);
3057  /*@switchbreak@*/ break;
3058  }
3059  }
3060 /*@=boundswrite@*/
3061  }
3062  /*@switchbreak@*/ break;
3063  }
3064  }
3065  /*@=branchstate =uniondef @*/
3066 
3067  /* For DSOs which use the .gnu_hash section and don't have a .hash
3068  * section, we need to ensure that we have a new enough glibc. */
3069  if (gotGNUHASH && !gotHASH) {
3070  ds = rpmdsSingle(RPMTAG_REQUIRENAME, "rtld(GNU_HASH)", "",
3071  RPMSENSE_FIND_REQUIRES);
3072  xx = add(context, ds);
3073  ds = rpmdsFree(ds);
3074  }
3075 
3076  /* For DSO's, provide the basename of the file if DT_SONAME not found. */
3077  if (!skipP && isDSO && !gotDEBUG && !gotSONAME) {
3078  s = strrchr(fn, '/');
3079  if (s != NULL)
3080  s++;
3081  else
3082  s = fn;
3083 assert(s != NULL);
3084 
3085  /* Add next provide dependency. */
3086  buf[0] = '\0';
3088  sonameDep(buf, s, isElf64), "", RPMSENSE_FIND_PROVIDES);
3089  xx = add(context, ds);
3090  ds = rpmdsFree(ds);
3091  }
3092 
3093 exit:
3094  soname = _free(soname);
3095  if (elf) (void) elf_end(elf);
3096  if (fdno > 0)
3097  xx = close(fdno);
3098  return 0;
3099 #else
3100  return -1;
3101 #endif
3102 }
3103 
3104 #define _SBIN_LDCONFIG_P "/sbin/ldconfig -p"
3105 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3106 static const char * _ldconfig_cmd = _SBIN_LDCONFIG_P;
3107 
3108 #define _LD_SO_CACHE "/etc/ld.so.cache"
3109 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3110 static const char * _ldconfig_cache = NULL;
3111 
3112 int rpmdsLdconfig(rpmPRCO PRCO, const char * fn)
3113  /*@globals _ldconfig_cmd, _ldconfig_cache @*/
3114  /*@modifies _ldconfig_cmd, _ldconfig_cache @*/
3115 {
3116  char buf[BUFSIZ];
3117  const char *DSOfn;
3118  const char *N, *EVR;
3119  int_32 Flags = 0;
3120  rpmds ds;
3121  char * f, * fe;
3122  char * g, * ge;
3123  char * t;
3124  FILE * fp = NULL;
3125  int rc = -1;
3126  int xx;
3127 
3128  if (PRCO == NULL)
3129  return -1;
3130 
3131 /*@-modobserver@*/
3132  if (_ldconfig_cmd == NULL) {
3133  _ldconfig_cmd = rpmExpand("%{?_rpmds_ldconfig_cmd}", NULL);
3134  if (!(_ldconfig_cmd != NULL && *_ldconfig_cmd == '/')) {
3135 /*@-observertrans @*/
3136  _ldconfig_cmd = _free(_ldconfig_cmd);
3137 /*@=observertrans @*/
3138  _ldconfig_cmd = xstrdup(_SBIN_LDCONFIG_P);
3139  }
3140  }
3141 
3142  if (_ldconfig_cache == NULL) {
3143  _ldconfig_cache = rpmExpand("%{?_rpmds_ldconfig_cache}", NULL);
3144  /* XXX may need to validate path existence somewhen. */
3145  if (!(_ldconfig_cache != NULL && *_ldconfig_cache == '/')) {
3146 /*@-observertrans @*/
3147  _ldconfig_cache = _free(_ldconfig_cache);
3148 /*@=observertrans @*/
3149  _ldconfig_cache = xstrdup(_LD_SO_CACHE);
3150  }
3151  }
3152 /*@=modobserver@*/
3153 
3154 /*@-branchstate@*/
3155  if (fn == NULL)
3156  fn = _ldconfig_cache;
3157 /*@=branchstate@*/
3158 
3159 if (_rpmds_debug < 0)
3160 fprintf(stderr, "*** %s(%p, %s) P %p R %p C %p O %p T %p D %p L %p\n", __FUNCTION__, PRCO, fn, PRCO->Pdsp, PRCO->Rdsp, PRCO->Cdsp, PRCO->Odsp, PRCO->Tdsp, PRCO->Ddsp, PRCO->Ldsp);
3161 
3162  fp = popen(_ldconfig_cmd, "r");
3163  if (fp == NULL)
3164  goto exit;
3165 
3166  while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
3167  EVR = NULL;
3168  /* rtrim on line. */
3169  ge = f + strlen(f);
3170  while (--ge > f && _isspace(*ge))
3171  *ge = '\0';
3172 
3173  /* ltrim on line. */
3174  while (*f && _isspace(*f))
3175  f++;
3176 
3177  /* split on '=>' */
3178  fe = f;
3179  while (*fe && !(fe[0] == '=' && fe[1] == '>'))
3180  fe++;
3181  if (*fe == '\0')
3182  continue;
3183 
3184  /* find the DSO file name. */
3185  DSOfn = fe + 2;
3186 
3187  /* ltrim on DSO file name. */
3188  while (*DSOfn && _isspace(*DSOfn))
3189  DSOfn++;
3190  if (*DSOfn == '\0')
3191  continue;
3192 
3193  /* rtrim from "=>" */
3194  if (fe > f && fe[-1] == ' ') fe[-1] = '\0';
3195  *fe++ = '\0';
3196  *fe++ = '\0';
3197  g = fe;
3198 
3199  /* ltrim on field 2. */
3200  while (*g && _isspace(*g))
3201  g++;
3202  if (*g == '\0')
3203  continue;
3204 
3205  /* split out flags */
3206  for (t = f; *t != '\0'; t++) {
3207  if (!_isspace(*t))
3208  /*@innercontinue@*/ continue;
3209  *t++ = '\0';
3210  /*@innerbreak@*/ break;
3211  }
3212  /* XXX "libc4" "ELF" "libc5" "libc6" _("unknown") */
3213  /* XXX use flags to generate soname color */
3214  /* ",64bit" ",IA-64" ",x86-64", ",64bit" are color = 2 */
3215  /* ",N32" for mips64/libn32 */
3216 
3217  /* XXX use flags and LDASSUME_KERNEL to skip sonames? */
3218  /* "Linux" "Hurd" "Solaris" "FreeBSD" "kNetBSD" N_("Unknown OS") */
3219  /* ", OS ABI: %s %d.%d.%d" */
3220 
3221  N = f;
3222 /*@-branchstate@*/
3223  if (EVR == NULL)
3224  EVR = "";
3225 /*@=branchstate@*/
3226  Flags |= RPMSENSE_PROBE;
3227  ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
3228  xx = rpmdsMerge(PRCO->Pdsp, ds);
3229  ds = rpmdsFree(ds);
3230 
3231  xx = rpmdsELF(DSOfn, 0, rpmdsMergePRCO, PRCO);
3232  }
3233  rc = 0;
3234 
3235 exit:
3236  if (fp != NULL) (void) pclose(fp);
3237  return rc;
3238 }
3239 
3240 
3241 #if defined(__sun)
3242 #define _RLD_SEARCH_PATH "/lib:/usr/lib"
3243 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3244 static const char * _rld_search_path = NULL;
3245 
3246 /* search a colon-separated list of directories for shared objects */
3247 int rpmdsRldpath(rpmPRCO PRCO, const char * rldp)
3248  /*@globals _rld_search_path @*/
3249  /*@modifies _rld_search_path @*/
3250 {
3251  char buf[BUFSIZ];
3252  const char *N, *EVR;
3253  int_32 Flags = 0;
3254  rpmds ds;
3255  const char * f;
3256  const char * g;
3257  int rc = -1;
3258  int xx;
3259  glob_t gl;
3260  char ** gp;
3261 
3262  if (PRCO == NULL)
3263  return -1;
3264 
3265 /*@-modobserver@*/
3266  if (_rld_search_path == NULL) {
3267  _rld_search_path = rpmExpand("%{?_rpmds_rld_search_path}", NULL);
3268  /* XXX may need to validate path existence somewhen. */
3269  if (!(_rld_search_path != NULL && *_rld_search_path == '/')) {
3270 /*@-observertrans @*/
3271  _rld_search_path = _free(_rld_search_path);
3272 /*@=observertrans @*/
3273  _rld_search_path = xstrdup(_RLD_SEARCH_PATH);
3274  }
3275  }
3276 /*@=modobserver@*/
3277 
3278 /*@-branchstate@*/
3279  if (rldp == NULL)
3280  rldp = _rld_search_path;
3281 /*@=branchstate@*/
3282 
3283 if (_rpmds_debug > 0)
3284 fprintf(stderr, "*** %s(%p, %s) P %p R %p C %p O %p\n", __FUNCTION__, PRCO, rldp, PRCO->Pdsp, PRCO->Rdsp, PRCO->Cdsp, PRCO->Odsp);
3285 
3286  f = rldp;
3287  /* move through the path, splitting on : */
3288  while (f) {
3289  EVR = NULL;
3290  g = strchr(f, ':');
3291  if (g == NULL) {
3292  strcpy(buf, f);
3293  /* this is the last element, no more :'s */
3294  f = NULL;
3295  } else {
3296  /* copy this chunk to buf */
3297  strncpy(buf, f, g - f + 1);
3298  buf[g-f] = '\0';
3299 
3300  /* get ready for next time through */
3301  f = g + 1;
3302  }
3303 
3304  if ( !(strlen(buf) > 0 && buf[0] == '/') )
3305  continue;
3306 
3307  /* XXX: danger, buffer len */
3308  /* XXX: *.so.* should be configurable via a macro */
3309  strcat(buf, "/*.so.*");
3310 
3311 if (_rpmds_debug > 0)
3312 fprintf(stderr, "*** %s(%p, %s) globbing %s\n", __FUNCTION__, PRCO, rldp, buf);
3313 
3314  xx = glob(buf, 0, NULL, &gl);
3315  if (xx) /* glob error, probably GLOB_NOMATCH */
3316  continue;
3317 
3318 if (_rpmds_debug > 0)
3319 fprintf(stderr, "*** %s(%p, %s) glob matched %d files\n", __FUNCTION__, PRCO, rldp, gl.gl_pathc);
3320 
3321  gp = gl.gl_pathv;
3322  /* examine each match */
3323 /*@-branchstate@*/
3324  while (gp && *gp) {
3325  const char *DSOfn;
3326  /* XXX: should probably verify that we matched a file */
3327  DSOfn = *gp;
3328  gp++;
3329  if (EVR == NULL)
3330  EVR = "";
3331 
3332  /* N needs to be basename of DSOfn */
3333  N = DSOfn + strlen(DSOfn);
3334  while (N > DSOfn && *N != '/')
3335  --N;
3336 
3337  Flags |= RPMSENSE_PROBE;
3338  ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
3339  xx = rpmdsMerge(PRCO->Pdsp, ds);
3340  ds = rpmdsFree(ds);
3341 
3342  xx = rpmdsELF(DSOfn, 0, rpmdsMergePRCO, PRCO);
3343  }
3344 /*@=branchstate@*/
3345 /*@-immediatetrans@*/
3346  globfree(&gl);
3347 /*@=immediatetrans@*/
3348  }
3349  rc = 0;
3350 
3351  return rc;
3352 }
3353 
3354 #define _SOLARIS_CRLE "/usr/sbin/crle"
3355 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3356 static const char * _crle_cmd = NULL;
3357 
3358 int rpmdsCrle(rpmPRCO PRCO, /*@unused@*/ const char * fn)
3359  /*@globals _crle_cmd @*/
3360  /*@modifies _crle_cmd @*/
3361 {
3362  char buf[BUFSIZ];
3363  char * f;
3364  char * g, * ge;
3365  FILE * fp = NULL;
3366  int rc = -1; /* assume failure */
3367  int xx;
3368  int found_dlp = 0;
3369 
3370  if (PRCO == NULL)
3371  return -1;
3372 
3373 /*@-modobserver@*/
3374  if (_crle_cmd == NULL) {
3375  _crle_cmd = rpmExpand("%{?_rpmds_crle_cmd}", NULL);
3376  if (!(_crle_cmd != NULL && *_crle_cmd == '/')) {
3377 /*@-observertrans @*/
3378  _crle_cmd = _free(_crle_cmd);
3379 /*@=observertrans @*/
3380  _crle_cmd = xstrdup(_SOLARIS_CRLE);
3381  }
3382  }
3383 
3384  /* XXX: we rely on _crle_cmd including the -64 arg, if ELF64 */
3385  fp = popen(_crle_cmd, "r");
3386  if (fp == NULL)
3387  return rc;
3388 
3389  /*
3390  * we want the first line that contains "(ELF):"
3391  * we cannot search for "Default Library Path (ELF):" because that
3392  * changes in non-C locales.
3393  */
3394  while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
3395  if (found_dlp) /* XXX read all data? */
3396  continue;
3397 
3398  g = strstr(f, "(ELF):");
3399  if (g == NULL)
3400  continue;
3401 
3402  found_dlp = 1;
3403  f = g + (sizeof("(ELF):")-1);
3404  while (_isspace(*f))
3405  f++;
3406 
3407  /* rtrim path */
3408  ge = f + strlen(f);
3409  while (--ge > f && _isspace(*ge))
3410  *ge = '\0';
3411  }
3412  xx = pclose(fp);
3413 
3414  /* we have the loader path, let rpmdsRldpath() do the work */
3415  if (found_dlp)
3416  rc = rpmdsRldpath(PRCO, f);
3417 
3418  return rc;
3419 }
3420 #endif
3421 
3422 int rpmdsUname(rpmds *dsp, const struct utsname * un)
3423 {
3424 /*@observer@*/
3425  static const char * NS = "uname";
3426  struct utsname myun;
3427  int rc = -1;
3428  int xx;
3429 
3430  if (un == NULL) {
3431  xx = uname(&myun);
3432  if (xx != 0)
3433  goto exit;
3434  un = &myun;
3435  }
3436 
3437 /*@-type@*/
3438  /* XXX values need to be checked for EVR (i.e. no '-' character.) */
3439  if (un->sysname != NULL)
3440  rpmdsNSAdd(dsp, NS, "sysname", un->sysname, RPMSENSE_EQUAL);
3441  if (un->nodename != NULL)
3442  rpmdsNSAdd(dsp, NS, "nodename", un->nodename, RPMSENSE_EQUAL);
3443  if (un->release != NULL)
3444  rpmdsNSAdd(dsp, NS, "release", un->release, RPMSENSE_EQUAL);
3445 #if 0 /* XXX has embedded spaces */
3446  if (un->version != NULL)
3447  rpmdsNSAdd(dsp, NS, "version", un->version, RPMSENSE_EQUAL);
3448 #endif
3449  if (un->machine != NULL)
3450  rpmdsNSAdd(dsp, NS, "machine", un->machine, RPMSENSE_EQUAL);
3451 #if defined(__linux__)
3452  if (un->domainname != NULL && strcmp(un->domainname, "(none)"))
3453  rpmdsNSAdd(dsp, NS, "domainname", un->domainname, RPMSENSE_EQUAL);
3454 #endif
3455 /*@=type@*/
3456  rc = 0;
3457 
3458 exit:
3459  return rc;
3460 }
3461 
3462 #define _PERL_PROVIDES "/usr/bin/find /usr/lib/perl5 | /usr/lib/rpm/perl.prov"
3463 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3464 static const char * _perldeps_cmd = NULL;
3465 
3466 int rpmdsPipe(rpmds * dsp, int_32 tagN, const char * cmd)
3467  /*@globals _perldeps_cmd @*/
3468  /*@modifies _perldeps_cmd @*/
3469 {
3470  char buf[BUFSIZ];
3471  const char *N, *EVR;
3472  int_32 Flags = 0;
3473  rpmds ds;
3474  char * f, * fe;
3475  char * g, * ge;
3476  FILE * fp = NULL;
3477  const char * fn = "pipe";
3478  int rc = -1;
3479  int cmdprinted;
3480  int ln;
3481  int xx;
3482 
3483 /*@-modobserver@*/
3484  if (_perldeps_cmd == NULL) {
3485  _perldeps_cmd = rpmExpand("%{?_rpmds_perldeps_cmd}", NULL);
3486  /* XXX may need to validate path existence somewhen. */
3487  if (!(_perldeps_cmd != NULL && *_perldeps_cmd == '/')) {
3488 /*@-observertrans @*/
3489  _perldeps_cmd = _free(_perldeps_cmd);
3490 /*@=observertrans @*/
3491  _perldeps_cmd = xstrdup(_PERL_PROVIDES);
3492  }
3493  }
3494 /*@=modobserver@*/
3495 
3496  if (tagN <= 0)
3497  tagN = RPMTAG_PROVIDENAME;
3498 /*@-branchstate@*/
3499  if (cmd == NULL)
3500  cmd = _perldeps_cmd;
3501 /*@=branchstate@*/
3502 
3503  fp = popen(cmd, "r");
3504  if (fp == NULL)
3505  goto exit;
3506 
3507  ln = 0;
3508  cmdprinted = 0;
3509  while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
3510  ln++;
3511 
3512  /* insure a terminator. */
3513  buf[sizeof(buf)-1] = '\0';
3514 
3515  /* ltrim on line. */
3516  while (*f && _isspace(*f))
3517  f++;
3518 
3519  /* skip empty lines and comments */
3520  if (*f == '\0' || *f == '#')
3521  continue;
3522 
3523  /* rtrim on line. */
3524  fe = f + strlen(f);
3525  while (--fe > f && _isspace(*fe))
3526  *fe = '\0';
3527 
3528  /* split on ' ' or comparison operator. */
3529  fe = f;
3530  if (*f == '!') fe++;
3531  while (*fe && !_isspace(*fe) && strchr("!<=>", *fe) == NULL)
3532  fe++;
3533  while (*fe && _isspace(*fe))
3534  *fe++ = '\0';
3535 
3536  if (!(xisalnum(f[0]) || strchr("/_%!", f[0]) != NULL)) {
3537  if (!cmdprinted++)
3538  fprintf(stderr, _("running \"%s\" pipe command\n"), cmd);
3539  fprintf(stderr, _("%s:%d \"%s\" has invalid name. Skipping ...\n"),
3540  fn, ln, f);
3541  continue;
3542  }
3543 
3544  N = f;
3545  EVR = NULL;
3546  Flags = 0;
3547 
3548  /* parse for non-path, versioned dependency. */
3549 /*@-branchstate@*/
3550  if (*f != '/' && *fe != '\0') {
3551  /* parse comparison operator */
3552  g = fe;
3553  Flags = rpmEVRflags(fe, (const char **)&g);
3554  if (Flags == 0) {
3555  if (!cmdprinted++)
3556  fprintf(stderr, _("running \"%s\" pipe command\n"), cmd),
3557  fprintf(stderr, _("%s:%d \"%s\" has no comparison operator. Skipping ...\n"),
3558  fn, ln, fe);
3559  continue;
3560  }
3561  *fe = '\0';
3562 
3563  /* ltrim on field 2. */
3564  while (*g && _isspace(*g))
3565  g++;
3566  if (*g == '\0') {
3567  if (!cmdprinted++)
3568  fprintf(stderr, _("running \"%s\" pipe command\n"), cmd),
3569  /* XXX No EVR comparison value found. */
3570  fprintf(stderr, _("\tline %d: No EVR comparison value found.\n Skipping ..."),
3571  ln);
3572  fprintf(stderr, _("%s:%d \"%s\" has no EVR string. Skipping ...\n"),
3573  fn, ln, f);
3574  continue;
3575  }
3576 
3577  ge = g + 1;
3578  while (*ge && !_isspace(*ge))
3579  ge++;
3580 
3581  if (*ge != '\0')
3582  *ge = '\0'; /* XXX can't happen, line rtrim'ed already. */
3583 
3584  EVR = g;
3585  }
3586 
3587  if (EVR == NULL)
3588  EVR = "";
3589  Flags |= RPMSENSE_PROBE;
3590 /*@=branchstate@*/
3591  ds = rpmdsSingle(tagN, N, EVR, Flags);
3592  xx = rpmdsMerge(dsp, ds);
3593  ds = rpmdsFree(ds);
3594  }
3595  rc = 0;
3596 
3597 exit:
3598  if (fp != NULL) (void) pclose(fp);
3599  return rc;
3600 }
3601 
3602 static int rpmdsNAcmp(rpmds A, rpmds B)
3603  /*@*/
3604 {
3605  const char * AN = A->ns.N;
3606  const char * AA = A->ns.A;
3607  const char * BN = B->ns.N;
3608  const char * BA = B->ns.A;
3609  int rc;
3610 
3611  if (!AA && !BA) {
3612  rc = strcmp(AN, BN);
3613  } else if (AA && !BA) {
3614  rc = strncmp(AN, BN, (AA - AN)) || BN[AA - AN];
3615  if (!rc)
3616  rc = strcmp(AA, B->A);
3617  } else if (!AA && BA) {
3618  rc = strncmp(AN, BN, (BA - BN)) || AN[BA - BN];
3619  if (!rc)
3620  rc = strcmp(BA, A->A);
3621  } else {
3622  rc = strcmp(AN, BN);
3623  }
3624  return rc;
3625 }
3626 
3627 int rpmdsCompare(const rpmds A, const rpmds B)
3628 {
3629  const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
3630  const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
3631  EVR_t a = memset(alloca(sizeof(*a)), 0, sizeof(*a));
3632  EVR_t b = memset(alloca(sizeof(*a)), 0, sizeof(*a));
3633  int_32 aFlags = A->ns.Flags;
3634  int_32 bFlags = B->ns.Flags;
3635  int (*EVRcmp) (const char *a, const char *b);
3636  int result = 1;
3637  int sense;
3638  int xx;
3639 
3640 assert((rpmdsFlags(A) & RPMSENSE_SENSEMASK) == A->ns.Flags);
3641 assert((rpmdsFlags(B) & RPMSENSE_SENSEMASK) == B->ns.Flags);
3642 /*@-boundsread@*/
3643  /* Different names (and/or name.arch's) don't overlap. */
3644  if (rpmdsNAcmp(A, B)) {
3645  result = 0;
3646  goto exit;
3647  }
3648 
3649  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
3650 /*@-nullderef@*/
3651  if (!(A->EVR && A->Flags && B->EVR && B->Flags))
3652  goto exit;
3653 
3654  /* Same name. If either A or B is an existence test, always overlap. */
3655  if (!(aFlags && bFlags))
3656  goto exit;
3657 
3658  /* If either EVR is non-existent or empty, always overlap. */
3659  if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i]))
3660  goto exit;
3661 
3662  /* Both AEVR and BEVR exist. */
3663 /*@-boundswrite@*/
3664  xx = (A->EVRparse ? A->EVRparse : rpmEVRparse) (A->EVR[A->i], a);
3665  xx = (B->EVRparse ? B->EVRparse : rpmEVRparse) (B->EVR[B->i], b);
3666 /*@=boundswrite@*/
3667 
3668  /* If EVRcmp is identical, use that, otherwise use default. */
3669  EVRcmp = (A->EVRcmp && B->EVRcmp && A->EVRcmp == B->EVRcmp)
3670  ? A->EVRcmp : rpmvercmp;
3671 
3672  /* Compare {A,B} [epoch:]version[-release] */
3673  sense = 0;
3674  if (a->E && *a->E && b->E && *b->E)
3675 /*@i@*/ sense = EVRcmp(a->E, b->E);
3676  else if (a->E && *a->E && atol(a->E) > 0) {
3677  if (!B->nopromote) {
3678  int lvl = (_rpmds_unspecified_epoch_noise ? RPMMESS_WARNING : RPMMESS_DEBUG);
3679  rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
3680  aDepend, bDepend);
3681  sense = 0;
3682  } else
3683  sense = 1;
3684  } else if (b->E && *b->E && atol(b->E) > 0)
3685  sense = -1;
3686 
3687  if (sense == 0) {
3688 /*@i@*/ sense = EVRcmp(a->V, b->V);
3689  if (sense == 0 && a->R && *a->R && b->R && *b->R)
3690 /*@i@*/ sense = EVRcmp(a->R, b->R);
3691  }
3692 /*@=boundsread@*/
3693  a->str = _free(a->str);
3694  b->str = _free(b->str);
3695 
3696  /* Detect overlap of {A,B} range. */
3697  if (aFlags == RPMSENSE_NOTEQUAL || bFlags == RPMSENSE_NOTEQUAL) {
3698  result = (sense != 0);
3699  } else if (sense < 0 && ((aFlags & RPMSENSE_GREATER) || (bFlags & RPMSENSE_LESS))) {
3700  result = 1;
3701  } else if (sense > 0 && ((aFlags & RPMSENSE_LESS) || (bFlags & RPMSENSE_GREATER))) {
3702  result = 1;
3703  } else if (sense == 0 &&
3704  (((aFlags & RPMSENSE_EQUAL) && (bFlags & RPMSENSE_EQUAL)) ||
3705  ((aFlags & RPMSENSE_LESS) && (bFlags & RPMSENSE_LESS)) ||
3706  ((aFlags & RPMSENSE_GREATER) && (bFlags & RPMSENSE_GREATER)))) {
3707  result = 1;
3708  } else
3709  result = 0;
3710 /*@=nullderef@*/
3711 
3712 exit:
3713  if (_noisy_range_comparison_debug_message)
3714  rpmMessage(RPMMESS_DEBUG, D_(" %s A %s\tB %s\n"),
3715  (result ? _("YES") : _("NO ")), aDepend, bDepend);
3716  aDepend = _free(aDepend);
3717  bDepend = _free(bDepend);
3718  return result;
3719 }
3720 
3721 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
3722  const fnpyKey * suggestedKeys, int adding)
3723 {
3724  const char * Name = rpmdsN(ds);
3725  const char * DNEVR = rpmdsDNEVR(ds);
3726  const char * EVR = rpmdsEVR(ds);
3727  rpmProblemType type;
3728  fnpyKey key;
3729 
3730  if (ps == NULL) return;
3731 
3732  /*@-branchstate@*/
3733  if (Name == NULL) Name = "?N?";
3734  if (EVR == NULL) EVR = "?EVR?";
3735  if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
3736  /*@=branchstate@*/
3737 
3738  rpmMessage(RPMMESS_DEBUG, D_("package %s has unsatisfied %s: %s\n"),
3739  pkgNEVR, ds->Type, DNEVR+2);
3740 
3741  switch ((unsigned)DNEVR[0]) {
3742  case 'C': type = RPMPROB_CONFLICT; break;
3743  default:
3744  case 'R': type = RPMPROB_REQUIRES; break;
3745  }
3746 
3747  key = (suggestedKeys ? suggestedKeys[0] : NULL);
3748  rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
3749 }
3750 
3751 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
3752 {
3753  int scareMem = 0;
3754  rpmds provides = NULL;
3755  int_32 reqFlags = req->ns.Flags;
3756  int result = 1;
3757 
3758 assert((rpmdsFlags(req) & RPMSENSE_SENSEMASK) == req->ns.Flags);
3759  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
3760  if (req->EVR == NULL || req->Flags == NULL)
3761  goto exit;
3762 
3763  switch(req->ns.Type) {
3764  default:
3765 /*@-boundsread@*/
3766  /* Primary key retrieve satisfes an existence compare. */
3767  if (!reqFlags || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
3768  goto exit;
3769 /*@=boundsread@*/
3770  /*@fallthrough@*/
3771  case RPMNS_TYPE_ARCH:
3772  break;
3773  }
3774 
3775  /* Get provides information from header */
3776  provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
3777  if (provides == NULL) {
3778  result = 0;
3779  goto exit; /* XXX should never happen */
3780  }
3781  if (nopromote)
3782  (void) rpmdsSetNoPromote(provides, nopromote);
3783 
3784  /*
3785  * Rpm prior to 3.0.3 did not have versioned provides.
3786  * If no provides version info is available, match any/all requires
3787  * with same name.
3788  */
3789  if (provides->EVR == NULL)
3790  goto exit;
3791 
3792  /* If any provide matches the require, we're done. */
3793  result = 0;
3794  if (provides != NULL)
3795  while (rpmdsNext(provides) >= 0)
3796  if ((result = rpmdsCompare(provides, req)))
3797  break;
3798 
3799 exit:
3800  provides = rpmdsFree(provides);
3801 
3802  return result;
3803 }
3804 
3805 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
3806 {
3808  const char * pkgN, * V, * R;
3809  int_32 * epoch;
3810  const char * pkgEVR;
3811  char * t;
3812  int_32 reqFlags = req->ns.Flags;
3813  int_32 pkgFlags = RPMSENSE_EQUAL;
3814  int result = 1;
3815  rpmds pkg;
3816  size_t nb;
3817 
3818 assert((rpmdsFlags(req) & RPMSENSE_SENSEMASK) == req->ns.Flags);
3819  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
3820  if (req->EVR == NULL || req->Flags == NULL)
3821  goto exit;
3822 
3823 /*@-boundsread@*/
3824  if (!(reqFlags && req->EVR[req->i] && *req->EVR[req->i]))
3825  goto exit;
3826 /*@=boundsread@*/
3827 
3828  /* Get package information from header */
3829  (void) headerNVR(h, &pkgN, &V, &R);
3830 
3831  nb = 21 + 1 + 1;
3832  if (V) nb += strlen(V);
3833  if (R) nb += strlen(R);
3834 /*@-boundswrite@*/
3835  pkgEVR = t = alloca(nb);
3836  *t = '\0';
3837  if (hge(h, RPMTAG_EPOCH, NULL, &epoch, NULL)) {
3838  sprintf(t, "%d:", *epoch);
3839  t += strlen(t);
3840  }
3841  (void) stpcpy( stpcpy( stpcpy(t, V) , "-") , R);
3842 /*@=boundswrite@*/
3843 
3844  if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
3845  if (nopromote)
3846  (void) rpmdsSetNoPromote(pkg, nopromote);
3847  result = rpmdsCompare(pkg, req);
3848  pkg = rpmdsFree(pkg);
3849  }
3850 
3851 exit:
3852  return result;
3853 }
3854 
3855 int rpmdsNegateRC(const rpmds ds, int rc)
3856 {
3857  if (ds->ns.str[0] == '!')
3858  rc = (rc == 0);
3859  return rc;
3860 }