rpm  5.4.10
rpmds.c
Go to the documentation of this file.
1 
4 #include "system.h"
5 
6 #if defined(WITH_CPUINFO)
7 #include <cpuinfo.h>
8 #endif
9 
10 #if defined(HAVE_GELF_H) && !defined(__FreeBSD__)
11 #if LIBELF_H_LFS_CONFLICT
12 /* Some implementations of libelf.h/gelf.h are incompatible with
13  * the Large File API.
14  */
15 # undef _LARGEFILE64_SOURCE
16 # undef _LARGEFILE_SOURCE
17 # undef _FILE_OFFSET_BITS
18 # define _FILE_OFFSET_BITS 32
19 #endif
20 
21 #if defined(__LCLINT__)
22 typedef long long loff_t;
23 #endif
24 #include <gelf.h>
25 /*
26  * On Solaris, gelf.h included libelf.h, which #undef'ed the gettext
27  * convenience macro _(). Repair by repeating (from system.h) just
28  * the bits that are needed for _() to function.
29  */
30 
31 #if defined(__sun)
32 #if defined(ENABLE_NLS) && !defined(__LCLINT__)
33 # define _(Text) gettext (Text)
34 #else
35 # define _(Text) Text
36 #endif /* gettext _() fixup */
37 #endif
38 #endif /* HAVE_GELF_H */
39 
40 #if defined(HAVE_LIBELF) && !defined(HAVE_GELF_GETVERNAUX) && !defined(__FreeBSD__)
41 /* We have gelf.h and libelf, but we don't have some of the
42  * helper functions gelf_getvernaux(), gelf_getverneed(), etc.
43  * Provide our own simple versions here.
44  */
45 
46 static GElf_Verdef *gelf_getverdef(Elf_Data *data, int offset,
47  GElf_Verdef *dst)
48 {
49  return (GElf_Verdef *) ((char *) data->d_buf + offset);
50 }
51 
52 static GElf_Verdaux *gelf_getverdaux(Elf_Data *data, int offset,
53  GElf_Verdaux *dst)
54 {
55  return (GElf_Verdaux *) ((char *) data->d_buf + offset);
56 }
57 
58 static GElf_Verneed *gelf_getverneed(Elf_Data *data, int offset,
59  GElf_Verneed *dst)
60 {
61  return (GElf_Verneed *) ((char *) data->d_buf + offset);
62 }
63 
64 static GElf_Vernaux *gelf_getvernaux(Elf_Data *data, int offset,
65  GElf_Vernaux *dst)
66 {
67  return (GElf_Vernaux *) ((char *) data->d_buf + offset);
68 }
69 
70 /* Most non-Linux systems won't have SHT_GNU_verdef or SHT_GNU_verneed,
71  * but they might have something mostly-equivalent. Solaris has
72  * SHT_SUNW_{verdef,verneed}
73  */
74 #if !defined(SHT_GNU_verdef) && defined(__sun) && defined(SHT_SUNW_verdef)
75 # define SHT_GNU_verdef SHT_SUNW_verdef
76 # define SHT_GNU_verneed SHT_SUNW_verneed
77 #endif
78 
79 #endif /* HAVE_LIBELF && !HAVE_GELF_GETVERNAUX */
80 
81 #if !defined(DT_GNU_HASH)
82 #define DT_GNU_HASH 0x6ffffef5
83 #endif
84 
85 #define _RPMIOB_INTERNAL
86 #include <rpmiotypes.h>
87 #include <rpmio_internal.h> /* XXX fdGetFILE */
88 #include <rpmcb.h> /* XXX fnpyKey */
89 #include <rpmmacro.h>
90 #include <argv.h>
91 #include <set.h>
92 
93 #include <rpmtypes.h>
94 #include <rpmtag.h>
95 
96 #define _RPMDS_INTERNAL
97 #define _RPMEVR_INTERNAL
98 #define _RPMPRCO_INTERNAL
99 #include <rpmds.h>
100 
101 #include "debug.h"
102 
103 /*@access rpmns @*/
104 /*@access EVR_t @*/
105 
106 #ifdef __cplusplus
107 GENfree(evrFlags *)
108 GENfree(rpmuint32_t *)
109 GENfree(rpmint32_t *)
110 GENfree(rpmPRCO)
111 #endif /* __cplusplus */
112 
113 #define _isspace(_c) \
114  ((_c) == ' ' || (_c) == '\t' || (_c) == '\r' || (_c) == '\n')
115 
119 /*@unchecked@*/
121 
122 /*@unchecked@*/
123 int _rpmds_debug = 0;
124 
125 /*@unchecked@*/
127 
128 /*@unchecked@*/
129 /*@-exportheadervar@*/
131 /*@=exportheadervar@*/
132 
138 /*@observer@*/
139 static const char * rpmdsTagName(rpmTag tagN)
140  /*@*/
141 {
142  const char * Type;
143 
144  /* XXX Preserve existing names in debugging messages. */
145  switch (tagN) {
146  default: Type = tagName(tagN); break;
147  case RPMTAG_PROVIDENAME: Type = "Provides"; break;
148  case RPMTAG_REQUIRENAME: Type = "Requires"; break;
149  case RPMTAG_CONFLICTNAME: Type = "Conflicts"; break;
150  case RPMTAG_OBSOLETENAME: Type = "Obsoletes"; break;
151  case RPMTAG_TRIGGERNAME: Type = "Triggers"; break;
152  case RPMTAG_SUGGESTSNAME: Type = "Suggests"; break;
153  case RPMTAG_ENHANCESNAME: Type = "Enhances"; break;
154  case RPMTAG_DIRNAMES: Type = "Dirs"; break;
155  case RPMTAG_BASENAMES: Type = "Files"; break;
156  case RPMTAG_FILELINKTOS: Type = "Linktos"; break;
157  case 0: Type = "Unknown"; break;
158  }
159  return Type;
160 }
161 
162 const char * rpmdsType(const rpmds ds)
163 {
164  return rpmdsTagName(rpmdsTagN(ds));
165 }
166 
167 static void rpmdsFini(void * _ds)
168 {
169  rpmds ds = (rpmds) _ds;
170 
171  if (ds->Count > 0) {
172  ds->N = _free(ds->N);
173  ds->EVR = _free(ds->EVR);
174  ds->Flags = _free(ds->Flags);
175  (void)headerFree(ds->h);
176  ds->h = NULL;
177  }
178 
179  ds->DNEVR = _free(ds->DNEVR);
180  ds->ns.str = _free(ds->ns.str);
181  memset(&ds->ns, 0, sizeof(ds->ns));
182  ds->A = _free(ds->A);
183  ds->Color = _free(ds->Color);
184  ds->Refs = _free(ds->Refs);
185  ds->Result = _free(ds->Result);
186  ds->exclude = (miRE) mireFreeAll(ds->exclude, ds->nexclude);
187  ds->include = (miRE) mireFreeAll(ds->include, ds->ninclude);
188 }
189 
190 /*@unchecked@*/ /*@only@*/ /*@null@*/
192 
193 static rpmds rpmdsGetPool(/*@null@*/ rpmioPool pool)
194  /*@globals _rpmdsPool, fileSystem, internalState @*/
195  /*@modifies pool, _rpmdsPool, fileSystem, internalState @*/
196 {
197  rpmds ds;
198 
199  if (_rpmdsPool == NULL) {
200  _rpmdsPool = rpmioNewPool("ds", sizeof(*ds), -1, _rpmds_debug,
201  NULL, NULL, rpmdsFini);
202  pool = _rpmdsPool;
203  }
204  ds = (rpmds) rpmioGetPool(pool, sizeof(*ds));
205  memset(((char *)ds)+sizeof(ds->_item), 0, sizeof(*ds)-sizeof(ds->_item));
206  return ds;
207 }
208 
209 static /*@null@*/
210 const char ** rpmdsDupArgv(/*@null@*/ const char ** argv, int argc)
211  /*@*/
212 {
213  const char ** av;
214  size_t nb = 0;
215  int ac = 0;
216  char * t;
217 
218  if (argv == NULL)
219  return NULL;
220  for (ac = 0; ac < argc; ac++) {
221 assert(argv[ac] != NULL);
222  nb += strlen(argv[ac]) + 1;
223  }
224  nb += (ac + 1) * sizeof(*av);
225 
226  av = (const char **) xmalloc(nb);
227  t = (char *) (av + ac + 1);
228  for (ac = 0; ac < argc; ac++) {
229  av[ac] = t;
230  t = stpcpy(t, argv[ac]) + 1;
231  }
232  av[ac] = NULL;
233 /*@-nullret@*/
234  return av;
235 /*@=nullret@*/
236 }
237 
238 rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
239 {
240  int scareMem = (flags & 0x1);
241  int delslash = 1;
242  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
243  rpmTag tagEVR, tagF;
244  rpmds ds = NULL;
245  const char * Type = NULL;
246  const char ** N;
247  rpmuint32_t Count;
248  int xx;
249 
250 assert(scareMem == 0); /* XXX always allocate memory */
251 
252  if (tagN == RPMTAG_NAME)
253  return rpmdsThis(h, tagN, RPMSENSE_EQUAL);
254 
255  switch (tagN) {
256  default:
257  goto exit;
258  /*@notreached@*/ break;
259  case RPMTAG_PROVIDENAME:
260  tagEVR = RPMTAG_PROVIDEVERSION;
261  tagF = RPMTAG_PROVIDEFLAGS;
262  break;
263  case RPMTAG_REQUIRENAME:
264  tagEVR = RPMTAG_REQUIREVERSION;
265  tagF = RPMTAG_REQUIREFLAGS;
266  break;
267  case RPMTAG_CONFLICTNAME:
268  tagEVR = RPMTAG_CONFLICTVERSION;
269  tagF = RPMTAG_CONFLICTFLAGS;
270  break;
271  case RPMTAG_OBSOLETENAME:
272  tagEVR = RPMTAG_OBSOLETEVERSION;
273  tagF = RPMTAG_OBSOLETEFLAGS;
274  break;
275  case RPMTAG_TRIGGERNAME:
276  tagEVR = RPMTAG_TRIGGERVERSION;
277  tagF = RPMTAG_TRIGGERFLAGS;
278  break;
279  case RPMTAG_SUGGESTSNAME:
280  tagEVR = RPMTAG_SUGGESTSVERSION;
281  tagF = RPMTAG_SUGGESTSFLAGS;
282  break;
283  case RPMTAG_ENHANCESNAME:
284  tagEVR = RPMTAG_ENHANCESVERSION;
285  tagF = RPMTAG_ENHANCESFLAGS;
286  break;
287  case RPMTAG_DIRNAMES:
288  tagEVR = (rpmTag) 0;
289  tagF = (rpmTag) 0;
290  delslash = (flags & 0x2) ? 0 : 1;
291  break;
292  case RPMTAG_BASENAMES:
293  tagEVR = RPMTAG_DIRNAMES;
294  tagF = RPMTAG_DIRINDEXES;
295  break;
296  case RPMTAG_FILELINKTOS:
297  tagEVR = RPMTAG_DIRNAMES;
298  tagF = RPMTAG_DIRINDEXES;
299  break;
300  }
301 
302  if (Type == NULL)
303  Type = rpmdsTagName(tagN);
304 
305  he->tag = tagN;
306  xx = headerGet(h, he, 0);
307  N = he->p.argv;
308  Count = he->c;
309  if (xx && N != NULL && Count > 0) {
310  ds = rpmdsGetPool(_rpmdsPool);
311  ds->Type = Type;
312  ds->h = NULL;
313  ds->i = -1;
314  ds->DNEVR = NULL;
315  ds->tagN = tagN;
316  ds->N = N;
317  ds->Count = Count;
318  ds->nopromote = _rpmds_nopromote;
319 
320  if (tagEVR > 0) {
321  he->tag = tagEVR;
322  xx = headerGet(h, he, 0);
323  ds->EVR = he->p.argv;
324  }
325  if (tagF > 0) {
326  he->tag = tagF;
327  xx = headerGet(h, he, 0);
328  ds->Flags = (evrFlags * ) he->p.ui32p;
329  }
330  {
331  he->tag = RPMTAG_ARCH;
332  xx = headerGet(h, he, 0);
333  ds->A = he->p.str;
334  }
335  {
336  he->tag = RPMTAG_BUILDTIME;
337  xx = headerGet(h, he, 0);
338  ds->BT = (he->p.ui32p ? he->p.ui32p[0] : 0);
339  he->p.ptr = _free(he->p.ptr);
340  }
341 
342  if (tagN == RPMTAG_DIRNAMES) {
343  char * dn;
344  size_t len;
345  unsigned i;
346  /* XXX Dirnames always have trailing '/', trim that here. */
347  if (delslash)
348  for (i = 0; i < Count; i++) {
349  (void) urlPath(N[i], (const char **)&dn);
350  if (dn > N[i])
351  N[i] = dn;
352  dn = (char *)N[i];
353  len = strlen(dn);
354  /* XXX don't truncate if parent is / */
355  if (len > 1 && dn[len-1] == '/')
356  dn[len-1] = '\0';
357  }
358  } else
359  if (tagN == RPMTAG_BASENAMES) {
360  const char ** av = (const char **) xcalloc(Count+1, sizeof(*av));
361  char * dn;
362  unsigned i;
363 
364  for (i = 0; i < Count; i++) {
365  (void) urlPath(ds->EVR[ds->Flags[i]], (const char **)&dn);
366  av[i] = rpmGenPath(NULL, dn, N[i]);
367  }
368  av[Count] = NULL;
369 
370 /*@-unqualifiedtrans@*/
371  N = ds->N = _free(ds->N);
372 /*@=unqualifiedtrans@*/
373  N = ds->N = rpmdsDupArgv(av, Count);
374  av = argvFree(av);
375  ds->EVR = _free(ds->EVR);
376  ds->Flags = _free(ds->Flags);
377  } else
378  if (tagN == RPMTAG_FILELINKTOS) {
379  /* XXX Construct the absolute path of the target symlink(s). */
380  const char ** av = (const char **) xcalloc(Count+1, sizeof(*av));
381  unsigned i;
382 
383  for (i = 0; i < Count; i++) {
384  if (N[i] == NULL || *N[i] == '\0')
385  av[i] = xstrdup("");
386  else if (*N[i] == '/')
387  av[i] = xstrdup(N[i]);
388  else if (ds->EVR != NULL && ds->Flags != NULL)
389  av[i] = rpmGenPath(NULL, ds->EVR[ds->Flags[i]], N[i]);
390  else
391  av[i] = xstrdup("");
392  }
393  av[Count] = NULL;
394 
395 /*@-unqualifiedtrans@*/
396  N = ds->N = _free(ds->N);
397 /*@=unqualifiedtrans@*/
398  N = ds->N = rpmdsDupArgv(av, Count);
399  av = argvFree(av);
400  ds->EVR = _free(ds->EVR);
401  ds->Flags = _free(ds->Flags);
402  }
403 
404 /*@-modfilesys@*/
405 if (_rpmds_debug < 0)
406 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
407 /*@=modfilesys@*/
408 
409  }
410 
411 exit:
412 /*@-compdef -usereleased@*/ /* FIX: ds->Flags may be NULL */
413  /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
414  ds = rpmdsLink(ds, (ds ? ds->Type : NULL));
415  /*@=nullstate@*/
416 
417  return ds;
418 /*@=compdef =usereleased@*/
419 }
420 
421 const char * rpmdsNewN(rpmds ds)
422 {
423  rpmns ns = &ds->ns;
424  const char * Name = ds->N[ds->i];
425  int xx;
426 
427  xx = rpmnsParse(Name, ns);
428 
429 /*@-compdef -usereleased@*/ /* FIX: correct annotations for ds->ns shadow */
430  return ns->N;
431 /*@=compdef =usereleased@*/
432 }
433 
434 char * rpmdsNewDNEVR(const char * dspfx, rpmds ds)
435 {
436  const char * N = rpmdsNewN(ds);
437  const char * NS = ds->ns.NS;
438  const char * A = ds->ns.A;
439  evrFlags dsFlags = (evrFlags) 0;
440  char * tbuf, * t;
441  size_t nb = 0;
442 
443  if (dspfx) nb += strlen(dspfx) + 1;
444  if (ds->ns.str[0] == '!') nb++;
445  if (NS) nb += strlen(NS) + sizeof("()") - 1;
446  if (N) nb += strlen(N);
447  if (A) {
448  if (_rpmns_N_at_A && _rpmns_N_at_A[0])
449  nb += sizeof(_rpmns_N_at_A[0]);
450  nb += strlen(A);
451  }
452  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
453  if (ds->Flags != NULL
454  && (dsFlags = (evrFlags) (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)))
455  {
456  if (nb) nb++;
457  if (dsFlags == RPMSENSE_NOTEQUAL)
458  nb += 2;
459  else {
460  if (dsFlags & RPMSENSE_LESS) nb++;
461  if (dsFlags & RPMSENSE_GREATER) nb++;
462  if (dsFlags & RPMSENSE_EQUAL) nb++;
463  }
464  }
465 
466  ds->ns.Flags = dsFlags;
467 
468  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
469  if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
470  if (nb) nb++;
471  nb += strlen(ds->EVR[ds->i]);
472  }
473 
474  t = tbuf = (char *) xmalloc(nb + 1);
475  if (dspfx) {
476  t = stpcpy(t, dspfx);
477  *t++ = ' ';
478  }
479  if (ds->ns.str[0] == '!')
480  *t++ = '!';
481  if (NS)
482  t = stpcpy( stpcpy(t, NS), "(");
483  if (N)
484  t = stpcpy(t, N);
485  if (NS)
486  t = stpcpy(t, ")");
487  if (A) {
488  if (_rpmns_N_at_A && _rpmns_N_at_A[0])
489  *t++ = _rpmns_N_at_A[0];
490  t = stpcpy(t, A);
491  }
492 
493  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
494  if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
495  if (t != tbuf) *t++ = ' ';
496  if (dsFlags == RPMSENSE_NOTEQUAL)
497  t = stpcpy(t, "!=");
498  else {
499  if (dsFlags & RPMSENSE_LESS) *t++ = '<';
500  if (dsFlags & RPMSENSE_GREATER) *t++ = '>';
501  if (dsFlags & RPMSENSE_EQUAL) *t++ = '=';
502  }
503  }
504  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
505  if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
506  if (t != tbuf) *t++ = ' ';
507  t = stpcpy(t, ds->EVR[ds->i]);
508  }
509  *t = '\0';
510  return tbuf;
511 }
512 
514 {
515  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
516  rpmds ds = NULL;
517  const char * Type;
518  const char * Name, * V, * R;
519 #ifdef RPM_VENDOR_MANDRIVA
520  const char * D = NULL;
521 #endif
522  rpmuint32_t E;
523  const char ** N, ** EVR;
524  char * t;
525  size_t nb;
526  int xx;
527 
528  if (tagN == RPMTAG_NAME)
529  tagN = RPMTAG_PROVIDENAME;
530 
531  Type = rpmdsTagName(tagN);
532 
533  he->tag = RPMTAG_EPOCH;
534  xx = headerGet(h, he, 0);
535  E = (he->p.ui32p ? he->p.ui32p[0] : 0);
536  he->p.ptr = _free(he->p.ptr);
537 
538 #if defined(RPM_VENDOR_MANDRIVA)
539  he->tag = RPMTAG_DISTEPOCH;
540  xx = headerGet(h, he, 0);
541  D = (he->p.str ? he->p.str : NULL);
542 #endif
543 /*@-mods@*/
544  xx = headerNEVRA(h, &Name, NULL, &V, &R, NULL);
545 /*@=mods@*/
546  /* XXX segfault avoidance */
547  if (Name == NULL) Name = xstrdup("N");
548  if (V == NULL) V = xstrdup("V");
549  if (R == NULL) R = xstrdup("R");
550 
551  t = (char *) xmalloc(sizeof(*N) + strlen(Name) + 1);
552  N = (const char **) t;
553  t += sizeof(*N);
554  *t = '\0';
555  N[0] = t;
556  t = stpcpy(t, Name);
557  Name = _free(Name);
558 
559  nb = sizeof(*EVR) + 20 + strlen(V) + strlen(R) + sizeof("-");
560 #if defined(RPM_VENDOR_MANDRIVA)
561  nb += (D ? strlen(D) + sizeof(":") : 0);
562 #endif
563  t = (char *) xmalloc(nb);
564  EVR = (const char **) t;
565  t += sizeof(*EVR);
566  *t = '\0';
567  EVR[0] = t;
568  sprintf(t, "%d:", E);
569  t += strlen(t);
570  t = stpcpy( stpcpy( stpcpy( t, V), "-"), R);
571 #if defined(RPM_VENDOR_MANDRIVA)
572  if (D != NULL) {
573  t = stpcpy( stpcpy( t, ":"), D);
574  D = _free(D);
575  }
576 #endif
577  V = _free(V);
578  R = _free(R);
579 
580  ds = rpmdsGetPool(_rpmdsPool);
581  ds->Type = Type;
582  ds->tagN = tagN;
583  ds->Count = 1;
584  ds->N = N;
585  ds->EVR = EVR;
586  ds->Flags = (evrFlags *) xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
587 
588  he->tag = RPMTAG_ARCH;
589  xx = headerGet(h, he, 0);
590  ds->A = he->p.str;
591 
592  he->tag = RPMTAG_BUILDTIME;
593  xx = headerGet(h, he, 0);
594  ds->BT = (he->p.ui32p ? he->p.ui32p[0] : 0);
595  he->p.ptr = _free(he->p.ptr);
596 
597  { char pre[2];
598  pre[0] = ds->Type[0];
599  pre[1] = '\0';
600  /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
601  ds->i = 0; /* XXX rpmdsNewN() needs ds->i = 0, not -1 */
602 /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(pre, ds);
603  /*@=nullstate@*/
604  }
605 
606  return rpmdsLink(ds, (ds ? ds->Type : NULL));
607 }
608 
609 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, evrFlags Flags)
610 {
611  rpmds ds = rpmdsGetPool(_rpmdsPool);
612  const char * Type = rpmdsTagName(tagN);
613 
614  ds->Type = Type;
615  ds->tagN = tagN;
616  ds->A = NULL;
617  { time_t now = time(NULL);
618  ds->BT = (rpmuint32_t)now;
619  }
620  ds->Count = 1;
621  /*@-assignexpose@*/
622  ds->N = (const char **) xcalloc(2, sizeof(*ds->N)); ds->N[0] = N;
623  ds->EVR = (const char **) xcalloc(2, sizeof(*ds->EVR)); ds->EVR[0] = EVR;
624  /*@=assignexpose@*/
625  ds->Flags = (evrFlags *) xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
626  { char t[2];
627  t[0] = ds->Type[0];
628  t[1] = '\0';
629  ds->i = 0; /* XXX rpmdsNewN() needs ds->i = 0, not -1 */
630 /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(t, ds);
631  }
632 
633  return rpmdsLink(ds, (ds ? ds->Type : NULL));
634 }
635 
636 int rpmdsCount(const rpmds ds)
637 {
638  return (ds != NULL ? ds->Count : 0);
639 }
640 
641 int rpmdsIx(const rpmds ds)
642 {
643  return (ds != NULL ? ds->i : -1);
644 }
645 
646 int rpmdsSetIx(rpmds ds, int ix)
647 {
648  int i = -1;
649 
650  if (ds != NULL) {
651  i = ds->i;
652  ds->i = ix;
653  }
654  return i;
655 }
656 
657 const char * rpmdsDNEVR(const rpmds ds)
658 {
659  const char * DNEVR = NULL;
660 
661  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
662  if (ds->DNEVR != NULL)
663  DNEVR = ds->DNEVR;
664  }
665  return DNEVR;
666 }
667 
668 const char * rpmdsN(const rpmds ds)
669 {
670  const char * N = NULL;
671 
672  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
673 /*@-globs -mods @*/ /* FIX: correct annotations for ds->ns shadow */
674  N = (ds->ns.N ? ds->ns.N : rpmdsNewN(ds));
675 /*@=globs =mods @*/
676  }
677  return N;
678 }
679 
680 const char * rpmdsEVR(const rpmds ds)
681 {
682  const char * EVR = NULL;
683 
684  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
685  if (ds->EVR != NULL)
686  EVR = ds->EVR[ds->i];
687  }
688  return EVR;
689 }
690 
692 {
693  evrFlags Flags = (evrFlags) 0;
694 
695  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
696  if (ds->Flags != NULL)
697  Flags = ds->Flags[ds->i];
698  }
699  return Flags;
700 }
701 
703 {
704  rpmTag tagN = (rpmTag) 0;
705 
706  if (ds != NULL)
707  tagN = ds->tagN;
708  return tagN;
709 }
710 
711 const char * rpmdsA(const rpmds ds)
712 {
713  const char * A = NULL;
714 
715  if (ds != NULL)
716  A = ds->A;
717  return A;
718 }
719 
720 time_t rpmdsBT(const rpmds ds)
721 {
722  time_t BT = 0;
723  if (ds != NULL && ds->BT > 0)
724  BT = ds->BT;
725  return BT;
726 }
727 
728 time_t rpmdsSetBT(const rpmds ds, time_t BT)
729 {
730  time_t oBT = 0;
731  if (ds != NULL) {
732  oBT = (time_t)ds->BT;
733  ds->BT = (rpmuint32_t)BT;
734  }
735  return oBT;
736 }
737 
739 {
740  nsType NSType = RPMNS_TYPE_UNKNOWN;
741  if (ds != NULL)
742  NSType = ds->ns.Type;
743  return NSType;
744 }
745 
746 int rpmdsNoPromote(const rpmds ds)
747 {
748  int nopromote = 0;
749 
750  if (ds != NULL)
751  nopromote = ds->nopromote;
752  return nopromote;
753 }
754 
755 int rpmdsSetNoPromote(rpmds ds, int nopromote)
756 {
757  int onopromote = 0;
758 
759  if (ds != NULL) {
760  onopromote = ds->nopromote;
761  ds->nopromote = nopromote;
762  }
763  return onopromote;
764 }
765 
767  int (*EVRparse)(const char *evrstr, EVR_t evr))
768 {
769  void * oEVRparse = NULL;
770 
771  if (ds != NULL) {
772 /*@i@*/ oEVRparse = (void *) ds->EVRparse;
773 /*@i@*/ ds->EVRparse = EVRparse;
774  }
775  return oEVRparse;
776 }
777 
778 void * rpmdsSetEVRcmp(rpmds ds, int (*EVRcmp)(const char *a, const char *b))
779 {
780  void * oEVRcmp = NULL;
781 
782  if (ds != NULL) {
783 /*@i@*/ oEVRcmp = (void *) ds->EVRcmp;
784 /*@i@*/ ds->EVRcmp = EVRcmp;
785  }
786  return oEVRcmp;
787 }
788 
790 {
791  rpmuint32_t Color = 0;
792 
793  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
794  if (ds->Color != NULL)
795  Color = ds->Color[ds->i];
796  }
797  return Color;
798 }
799 
801 {
802  rpmuint32_t ocolor = 0;
803 
804  if (ds == NULL)
805  return ocolor;
806 
807  if (ds->Color == NULL && ds->Count > 0) /* XXX lazy malloc */
808  ds->Color = (rpmuint32_t *) xcalloc(ds->Count, sizeof(*ds->Color));
809 
810  if (ds->i >= 0 && ds->i < (int)ds->Count) {
811  if (ds->Color != NULL) {
812  ocolor = ds->Color[ds->i];
813  ds->Color[ds->i] = color;
814  }
815  }
816  return ocolor;
817 }
818 
819 void * rpmdsExclude(const rpmds ds)
820 {
821  return (ds != NULL ? ds->exclude : NULL);
822 }
823 
824 int rpmdsNExclude(const rpmds ds)
825 {
826  return (ds != NULL ? ds->nexclude : 0);
827 }
828 
829 void * rpmdsInclude(const rpmds ds)
830 {
831  return (ds != NULL ? ds->include : NULL);
832 }
833 
834 int rpmdsNInclude(const rpmds ds)
835 {
836  return (ds != NULL ? ds->ninclude : 0);
837 }
838 
840 {
841  rpmuint32_t Refs = 0;
842 
843  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
844  if (ds->Refs != NULL)
845  Refs = ds->Refs[ds->i];
846  }
847  return Refs;
848 }
849 
851 {
852  rpmuint32_t orefs = 0;
853 
854  if (ds == NULL)
855  return orefs;
856 
857  if (ds->Refs == NULL && ds->Count > 0) /* XXX lazy malloc */
858  ds->Refs = (rpmuint32_t *) xcalloc(ds->Count, sizeof(*ds->Refs));
859 
860  if (ds->i >= 0 && ds->i < (int)ds->Count) {
861  if (ds->Refs != NULL) {
862  orefs = ds->Refs[ds->i];
863  ds->Refs[ds->i] = refs;
864  }
865  }
866  return orefs;
867 }
868 
870 {
871  rpmint32_t result = 0;
872 
873  if (ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count) {
874  if (ds->Result != NULL)
875  result = ds->Result[ds->i];
876  }
877  return result;
878 }
879 
881 {
882  rpmint32_t oresult = 0;
883 
884  if (ds == NULL)
885  return oresult;
886 
887  if (ds->Result == NULL && ds->Count > 0) /* XXX lazy malloc */
888  ds->Result = (rpmint32_t *) xcalloc(ds->Count, sizeof(*ds->Result));
889 
890  if (ds->i >= 0 && ds->i < (int)ds->Count) {
891  if (ds->Result != NULL) {
892  oresult = ds->Result[ds->i];
893  ds->Result[ds->i] = result;
894  }
895  }
896  return oresult;
897 }
898 
899 void rpmdsNotify(rpmds ds, const char * where, int rc)
900 {
901  if (!(ds != NULL && ds->i >= 0 && ds->i < (int)ds->Count))
902  return;
903  if (ds->DNEVR == NULL)
904  return;
905 
906  rpmlog(RPMLOG_DEBUG, "%9s: %-45s %-s %s\n", rpmdsTagName(ds->tagN),
907  (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
908  (rc ? _("NO ") : _("YES")),
909  (where != NULL ? where : ""));
910 }
911 
912 int rpmdsNext(/*@null@*/ rpmds ds)
913  /*@modifies ds @*/
914 {
915  int i = -1;
916 
917  if (ds != NULL && ++ds->i >= 0) {
918  if (ds->i < (int)ds->Count) {
919  char t[2];
920  i = ds->i;
921  ds->DNEVR = _free(ds->DNEVR);
922  ds->ns.str = _free(ds->ns.str);
923  memset(&ds->ns, 0, sizeof(ds->ns));
924  t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
925  t[1] = '\0';
926  /*@-nullstate@*/
927  /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(t, ds);
928  /*@=nullstate@*/
929 
930  } else
931  ds->i = -1;
932 
933 /*@-modfilesys @*/
934 if (_rpmds_debug < 0 && i != -1 && ds->DNEVR[2] != '\0')
935 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
936 /*@=modfilesys @*/
937 
938  }
939 
940  return i;
941 }
942 
943 rpmds rpmdsInit(/*@null@*/ rpmds ds)
944  /*@modifies ds @*/
945 {
946  if (ds != NULL)
947  ds->i = -1;
948  /*@-refcounttrans@*/
949  return ds;
950  /*@=refcounttrans@*/
951 }
952 
953 /*@null@*/
954 static rpmds rpmdsDup(const rpmds ods)
955  /*@modifies ods @*/
956 {
957  rpmds ds = rpmdsGetPool(_rpmdsPool);
958  size_t nb;
959 
960 /*@-assignexpose -castexpose @*/
961  ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
962  ds->Type = ods->Type;
963 /*@=assignexpose =castexpose @*/
964  ds->tagN = ods->tagN;
965  ds->Count = ods->Count;
966  ds->i = ods->i;
967  ds->l = ods->l;
968  ds->u = ods->u;
969 
970  nb = (ds->Count+1) * sizeof(*ds->N);
971  ds->N = (const char **) (ds->h != NULL
972  ? memcpy(xmalloc(nb), ods->N, nb)
973  : rpmdsDupArgv(ods->N, ods->Count) );
974 
975  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
976  if (ods->tagN != RPMTAG_BASENAMES &&
977  ods->tagN != RPMTAG_DIRNAMES &&
978  ods->tagN != RPMTAG_FILEPATHS) {
979 assert(ods->EVR != NULL);
980 assert(ods->Flags != NULL);
981  nb = (ds->Count+1) * sizeof(*ds->EVR);
982  ds->EVR = (ds->h != NULL
983  ? memcpy(xmalloc(nb), ods->EVR, nb)
984  : rpmdsDupArgv(ods->EVR, ods->Count) );
985 
986  nb = (ds->Count * sizeof(*ds->Flags));
987  ds->Flags = (ds->h != NULL
988  ? ods->Flags
989  : memcpy(xmalloc(nb), ods->Flags, nb) );
990  ds->nopromote = ods->nopromote;
991  /*@-assignexpose@*/
992  ds->EVRcmp = ods->EVRcmp;
993  }
994 /*@=assignexpose@*/
995 
996 /*@-compmempass@*/ /* FIX: ds->Flags is kept, not only */
997  return rpmdsLink(ds, (ds ? ds->Type : NULL));
998 /*@=compmempass@*/
999 }
1000 
1001 int rpmdsFind(rpmds ds, const rpmds ods)
1002 {
1003  int comparison;
1004 
1005  if (ds == NULL || ods == NULL)
1006  return -1;
1007 
1008  ds->l = 0;
1009  ds->u = ds->Count;
1010  while (ds->l < ds->u) {
1011  ds->i = (ds->l + ds->u) / 2;
1012 
1013  comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
1014 
1015  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
1016 /*@-nullderef@*/
1017  if (comparison == 0 && ods->EVR && ds->EVR)
1018  comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
1019  if (comparison == 0 && ods->Flags && ds->Flags)
1020  comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
1021 /*@=nullderef@*/
1022 
1023  if (comparison < 0)
1024  ds->u = ds->i;
1025  else if (comparison > 0)
1026  ds->l = ds->i + 1;
1027  else
1028  return ds->i;
1029  }
1030  return -1;
1031 }
1032 
1033 int rpmdsMerge(rpmds * dsp, rpmds ods)
1034 {
1035  rpmds ds;
1036  const char ** N;
1037  const char ** EVR;
1038  evrFlags * Flags;
1039  int j;
1040 int save;
1041 
1042  if (dsp == NULL || ods == NULL)
1043  return -1;
1044 
1045  /* If not initialized yet, dup the 1st entry. */
1046  if (*dsp == NULL) {
1047  save = ods->Count;
1048  ods->Count = 1;
1049  *dsp = rpmdsDup(ods);
1050  ods->Count = save;
1051  }
1052  ds = *dsp;
1053  if (ds == NULL)
1054  return -1;
1055 
1056  /*
1057  * Add new entries.
1058  */
1059 save = ods->i;
1060  ods = rpmdsInit(ods);
1061  if (ods != NULL)
1062  while (rpmdsNext(ods) >= 0) {
1063  /*
1064  * If this entry is already present, don't bother.
1065  */
1066  if (rpmdsFind(ds, ods) >= 0)
1067  continue;
1068 
1069  /*
1070  * Insert new entry.
1071  */
1072  for (j = ds->Count; j > (int)ds->u; j--)
1073  ds->N[j] = ds->N[j-1];
1074  ds->N[ds->u] = ods->N[ods->i];
1075  N = rpmdsDupArgv(ds->N, ds->Count+1);
1076  ds->N = _free(ds->N);
1077  ds->N = N;
1078 
1079  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
1080 /*@-nullderef -nullpass -nullptrarith @*/
1081  if (ds->tagN != RPMTAG_BASENAMES &&
1082  ds->tagN != RPMTAG_DIRNAMES &&
1083  ds->tagN != RPMTAG_FILEPATHS) {
1084 assert(ods->EVR != NULL);
1085 assert(ods->Flags != NULL);
1086 
1087  for (j = ds->Count; j > (int)ds->u; j--)
1088  ds->EVR[j] = ds->EVR[j-1];
1089  ds->EVR[ds->u] = ods->EVR[ods->i];
1090  EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
1091  ds->EVR = _free(ds->EVR);
1092  ds->EVR = EVR;
1093 
1094  Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
1095  if (ds->u > 0)
1096  memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
1097  if (ds->u < ds->Count)
1098  memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
1099  Flags[ds->u] = ods->Flags[ods->i];
1100  ds->Flags = _free(ds->Flags);
1101  ds->Flags = Flags;
1102  }
1103 /*@=nullderef =nullpass =nullptrarith @*/
1104 
1105  ds->i = -1;
1106  ds->Count++;
1107 
1108  }
1109 /*@-nullderef@*/
1110 ods->i = save;
1111 /*@=nullderef@*/
1112  return 0;
1113 }
1114 
1116 {
1117  int comparison;
1118  int i, l, u;
1119 
1120  if (ds == NULL || ods == NULL)
1121  return -1;
1122 
1123  /* Binary search to find the [l,u) subset that contains N */
1124  i = -1;
1125  l = 0;
1126  u = ds->Count;
1127  while (l < u) {
1128  i = (l + u) / 2;
1129 
1130  comparison = strcmp(ods->N[ods->i], ds->N[i]);
1131 
1132  if (comparison < 0)
1133  u = i;
1134  else if (comparison > 0)
1135  l = i + 1;
1136  else {
1137  /* Set l to 1st member of set that contains N. */
1138  if (strcmp(ods->N[ods->i], ds->N[l]))
1139  l = i;
1140  while (l > 0 && !strcmp(ods->N[ods->i], ds->N[l-1]))
1141  l--;
1142  /* Set u to 1st member of set that does not contain N. */
1143  if (u >= (int)ds->Count || strcmp(ods->N[ods->i], ds->N[u]))
1144  u = i;
1145  while (++u < (int)ds->Count) {
1146  if (strcmp(ods->N[ods->i], ds->N[u]))
1147  /*@innerbreak@*/ break;
1148  }
1149  break;
1150  }
1151  }
1152 
1153  /* Check each member of [l,u) subset for ranges overlap. */
1154  i = -1;
1155  if (l < u) {
1156  int save = rpmdsSetIx(ds, l-1);
1157  while ((l = rpmdsNext(ds)) >= 0 && (l < u)) {
1158  if ((i = rpmdsCompare(ods, ds)) != 0)
1159  break;
1160  }
1161  /* Return element index that overlaps, or -1. */
1162  if (i)
1163  i = rpmdsIx(ds);
1164  else {
1165  (void) rpmdsSetIx(ds, save);
1166  i = -1;
1167  }
1168  /* Save the return value. */
1169  if (ods->Result != NULL)
1170  (void) rpmdsSetResult(ods, (i != -1 ? 1 : 0));
1171  }
1172  return i;
1173 }
1174 
1183 static void rpmdsNSAdd(/*@out@*/ rpmds *dsp, const char * NS,
1184  const char *N, const char *EVR, evrFlags Flags)
1185  /*@modifies *dsp @*/
1186 {
1187  char *t;
1188  rpmds ds;
1189  int xx;
1190 
1191  t = (char *) alloca(strlen(NS)+sizeof("()")+strlen(N));
1192  *t = '\0';
1193  (void) stpcpy( stpcpy( stpcpy( stpcpy(t, NS), "("), N), ")");
1194 
1195  ds = rpmdsSingle(RPMTAG_PROVIDENAME, t, EVR, Flags);
1196  xx = rpmdsMerge(dsp, ds);
1197  (void)rpmdsFree(ds);
1198  ds = NULL;
1199 }
1200 
1201 #if defined(WITH_CPUINFO)
1202 int rpmdsCpuinfo(rpmds *dsp, const char * fn)
1203 {
1204  const char * NS = "cpuinfo";
1205  struct cpuinfo *cip = cpuinfo_new();
1206  cpuinfo_feature_t feature;
1207  char tmp[20];
1208  union _dbswap {
1209  rpmuint32_t ui;
1210  unsigned char uc[4];
1211  };
1212  static union _dbswap orderedbytes = { .ui = 0x11223344 };
1213  const char * endian = NULL;
1214 
1215  snprintf(tmp, 19, "%d", cpuinfo_get_frequency(cip));
1216  tmp[19] = '\0';
1217  rpmdsNSAdd(dsp, NS, "cpu_MHz", tmp, RPMSENSE_PROBE|RPMSENSE_EQUAL);
1218  snprintf(tmp, 19, "%d", cpuinfo_get_cores(cip));
1219  rpmdsNSAdd(dsp, NS, "cpu_cores", tmp, RPMSENSE_PROBE|RPMSENSE_EQUAL);
1220  snprintf(tmp, 19, "%d", cpuinfo_get_threads(cip));
1221  rpmdsNSAdd(dsp, NS, "cpu_threads", tmp, RPMSENSE_PROBE|RPMSENSE_EQUAL);
1222 
1223  if(orderedbytes.uc[0] == 0x44)
1224  endian = "little";
1225  else if(orderedbytes.uc[0] == 0x11)
1226  endian = "big";
1227  else if(orderedbytes.uc[0] == 0x22)
1228  endian = "pdp";
1229  rpmdsNSAdd(dsp, NS, "endian", endian, RPMSENSE_PROBE|RPMSENSE_EQUAL);
1230 
1231  for (feature = cpuinfo_feature_common; feature != cpuinfo_feature_architecture_max; feature++) {
1232  if(feature == cpuinfo_feature_common_max)
1233  feature = cpuinfo_feature_architecture;
1234  if (cpuinfo_has_feature(cip, feature)) {
1235  const char *name = cpuinfo_string_of_feature(feature);
1236  if (name)
1237  rpmdsNSAdd(dsp, NS, name, "", RPMSENSE_PROBE);
1238  }
1239  }
1240  cpuinfo_destroy(cip);
1241 
1242  return RPMRC_OK;
1243 }
1244 
1245 #else
1246 
1247 struct cpuinfo_s {
1248 /*@observer@*/ /*@null@*/
1249  const char *name;
1250  int done;
1251  int flags;
1252 };
1253 
1254 /*@unchecked@*/
1255 static struct cpuinfo_s ctags[] = {
1256  { "processor", 0, 0 },
1257  { "Processor", 0, 1 }, /* XXX armv5 */
1258  { "vendor_id", 0, 0 },
1259  { "cpu_family", 0, 1 },
1260  { "model", 0, 1 },
1261  { "model_name", 0, 0 },
1262  { "stepping", 0, 1 },
1263  { "cpu_MHz", 0, 1 },
1264  { "CPU_implementer",0, 1 }, /* XXX armv5 */
1265  { "CPU_architecture",0, 1 }, /* XXX armv5 */
1266  { "CPU_variant", 0, 1 }, /* XXX armv5 */
1267  { "CPU_part", 0, 1 }, /* XXX armv5 */
1268  { "CPU_revision", 0, 1 }, /* XXX armv5 */
1269  { "Hardware", 0, 2 }, /* XXX armv5 */
1270  { "Revision", 0, 1 }, /* XXX armv5 */
1271  { "Serial", 0, 1 }, /* XXX armv5 */
1272  { "cache_size", 0, 1 },
1273  { "physical_id", 0, 0 },
1274  { "siblings", 0, 0 },
1275  { "core_id", 0, 0 },
1276  { "cpu_cores", 0, 0 },
1277  { "fdiv_bug", 0, 3 },
1278  { "hlt_bug", 0, 3 },
1279  { "f00f_bug", 0, 3 },
1280  { "coma_bug", 0, 3 },
1281  { "fpu", 0, 0 }, /* XXX use flags attribute instead. */
1282  { "fpu_exception", 0, 3 },
1283  { "cpuid_level", 0, 0 },
1284  { "wp", 0, 3 },
1285  { "flags", 0, 4 },
1286  { "Features", 0, 4 }, /* XXX armv5 */
1287  { "bogomips", 0, 1 },
1288  { "BogoMIPS", 0, 1 }, /* XXX armv5 */
1289  { "clflush_size", 0, 1 },
1290  { NULL, 0, -1 }
1291 };
1292 
1298 static int rpmdsCpuinfoCtagFlags(const char * name)
1299  /*@globals ctags @*/
1300  /*@modifies ctags @*/
1301 {
1302  struct cpuinfo_s * ct;
1303  int flags = -1;
1304 
1305  for (ct = ctags; ct->name != NULL; ct++) {
1306  if (strcmp(ct->name, name))
1307  continue;
1308  if (ct->done)
1309  continue;
1310  ct->done = 1; /* XXX insure single occurrence */
1311  flags = ct->flags;
1312  break;
1313  }
1314  return flags;
1315 }
1316 
1317 #define _PROC_CPUINFO "/proc/cpuinfo"
1318 
1320 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
1321 const char * _cpuinfo_path = NULL;
1322 
1323 int rpmdsCpuinfo(rpmds *dsp, const char * fn)
1324  /*@globals _cpuinfo_path, ctags @*/
1325  /*@modifies _cpuinfo_path, ctags @*/
1326 {
1327  struct cpuinfo_s * ct;
1328  const char * NS = "cpuinfo";
1329  rpmiob iob = NULL;
1330  char * f, * fe, * fend;
1331  char * g, * ge;
1332  char * t;
1333  int rc = -1;
1334  int xx;
1335 
1336 /*@-modobserver@*/
1337  if (_cpuinfo_path == NULL) {
1338  _cpuinfo_path = rpmExpand("%{?_rpmds_cpuinfo_path}", NULL);
1339  /* XXX may need to validate path existence somewhen. */
1340  if (!(_cpuinfo_path != NULL && *_cpuinfo_path == '/')) {
1341 /*@-observertrans @*/
1342  _cpuinfo_path = _free(_cpuinfo_path);
1343 /*@=observertrans @*/
1344  _cpuinfo_path = xstrdup(_PROC_CPUINFO);
1345  }
1346  }
1347 /*@=modobserver@*/
1348 
1349  if (fn == NULL)
1350  fn = _cpuinfo_path;
1351 
1352  /* Reset done variables. */
1353  for (ct = ctags; ct->name != NULL; ct++)
1354  ct->done = 0;
1355 
1356  xx = rpmiobSlurp(fn, &iob);
1357  if (!(xx == 0 && iob != NULL))
1358  goto exit;
1359 
1360  for (f = (char *)iob->b; *f != '\0'; f = fend) {
1361  /* find EOL */
1362  fe = f;
1363  while (*fe != '\0' && !(*fe == '\n' || *fe == '\r'))
1364  fe++;
1365  ge = fe;
1366  while (*fe != '\0' && (*fe == '\n' || *fe == '\r'))
1367  *fe++ = '\0';
1368  fend = fe;
1369 
1370  /* rtrim on line. */
1371  while (--ge > f && _isspace(*ge))
1372  *ge = '\0';
1373 
1374  /* ltrim on line. */
1375  while (*f && _isspace(*f))
1376  f++;
1377 
1378  /* split on ':' */
1379  fe = f;
1380  while (*fe && *fe != ':')
1381  fe++;
1382  if (*fe == '\0')
1383  continue;
1384  g = fe + 1;
1385 
1386  /* rtrim on field 1. */
1387  *fe = '\0';
1388  while (--fe > f && _isspace(*fe))
1389  *fe = '\0';
1390  if (*f == '\0')
1391  continue;
1392 
1393  /* ltrim on field 2. */
1394  while (*g && _isspace(*g))
1395  g++;
1396  if (*g == '\0')
1397  continue;
1398 
1399  for (t = f; *t != '\0'; t++) {
1400  if (_isspace(*t))
1401  *t = '_';
1402  }
1403 
1404  switch (rpmdsCpuinfoCtagFlags(f)) {
1405  case -1: /* not found */
1406  case 0: /* ignore */
1407  default:
1408  continue;
1409  /*@notreached@*/ /*@switchbreak@*/ break;
1410  case 1: /* Provides: cpuinfo(f) = g */
1411  for (t = g; *t != '\0'; t++) {
1412  if (_isspace(*t) || *t == '(' || *t == ')')
1413  *t = '_';
1414  }
1415  rpmdsNSAdd(dsp, NS, f, g, (evrFlags)(RPMSENSE_PROBE|RPMSENSE_EQUAL));
1416  /*@switchbreak@*/ break;
1417  case 2: /* Provides: cpuinfo(g) */
1418  for (t = g; *t != '\0'; t++) {
1419  if (_isspace(*t) || *t == '(' || *t == ')')
1420  *t = '_';
1421  }
1422  rpmdsNSAdd(dsp, NS, g, "", RPMSENSE_PROBE);
1423  /*@switchbreak@*/ break;
1424  case 3: /* if ("yes") Provides: cpuinfo(f) */
1425  if (!strcmp(g, "yes"))
1426  rpmdsNSAdd(dsp, NS, f, "", RPMSENSE_PROBE);
1427  /*@switchbreak@*/ break;
1428  case 4: /* Provides: cpuinfo(g[i]) */
1429  { char ** av = NULL;
1430  int i = 0;
1431  rc = poptParseArgvString(g, NULL, (const char ***)&av);
1432  if (!rc && av != NULL)
1433  while ((t = av[i++]) != NULL)
1434  rpmdsNSAdd(dsp, NS, t, "", RPMSENSE_PROBE);
1435  t = NULL;
1436  if (av != NULL)
1437  free(av);
1438  } /*@switchbreak@*/ break;
1439  }
1440  }
1441 
1442 exit:
1443  iob = rpmiobFree(iob);
1444  return rc;
1445 }
1446 #endif
1447 
1449 /*@observer@*/ /*@relnull@*/
1450  const char * featureName;
1451 /*@observer@*/ /*@relnull@*/
1452  const char * featureEVR;
1454 /*@observer@*/ /*@relnull@*/
1455  const char * featureDescription;
1456 };
1457 
1458 /*@unchecked@*/ /*@observer@*/
1460  { "rpmlib(VersionedDependencies)", "3.0.3-1",
1461  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1462  N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
1463  { "rpmlib(CompressedFileNames)", "3.0.4-1",
1464  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1465  N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
1466 #if defined(WITH_BZIP2)
1467  { "rpmlib(PayloadIsBzip2)", "3.0.5-1",
1468  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1469  N_("package payload can be compressed using bzip2.") },
1470 #endif
1471  { "rpmlib(PayloadFilesHavePrefix)", "4.0-1",
1472  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1473  N_("package payload file(s) have \"./\" prefix.") },
1474  { "rpmlib(ExplicitPackageProvide)", "4.0-1",
1475  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1476  N_("package name-version-release is not implicitly provided.") },
1477  { "rpmlib(HeaderLoadSortsTags)", "4.0.1-1",
1478  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1479  N_("header tags are always sorted after being loaded.") },
1480  { "rpmlib(ScriptletInterpreterArgs)", "4.0.3-1",
1481  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1482  N_("the scriptlet interpreter can use arguments from header.") },
1483  { "rpmlib(PartialHardlinkSets)", "4.0.4-1",
1484  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1485  N_("a hardlink file set may be installed without being complete.") },
1486  { "rpmlib(ConcurrentAccess)", "4.1-1",
1487  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1488  N_("package scriptlets may access the rpm database while installing.") },
1489 #if defined(WITH_LUA)
1490  { "rpmlib(BuiltinLuaScripts)", "4.2.2-1",
1491  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1492  N_("internal embedded lua scripts.") },
1493 #endif
1494 #if defined(WITH_AUGEAS)
1495  { "rpmlib(BuiltinAugeasScripts)", "5.3-1",
1496  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1497  N_("internal embedded Augeas.") },
1498 #endif
1499 #if defined(WITH_FICL)
1500  { "rpmlib(BuiltinFiclScripts)", "5.2-1",
1501  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1502  N_("internal embedded FICL.") },
1503 #endif
1504 #if defined(WITH_GPSEE)
1505  { "rpmlib(BuiltinJavaScript)", "5.2-1",
1506  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1507  N_("internal embedded JavaScript.") },
1508 #endif
1509 #if defined(WITH_PERLEMBED)
1510  { "rpmlib(BuiltinPerlScripts)", "5.2-1",
1511  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1512  N_("internal embedded perl scripts.") },
1513 #endif
1514 #if defined(WITH_PYTHONEMBED)
1515  { "rpmlib(BuiltinPythonScripts)", "5.2-1",
1516  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1517  N_("internal embedded python scripts.") },
1518 #endif
1519 #if defined(WITH_RUBYEMBED)
1520  { "rpmlib(BuiltinRubyScripts)", "5.2-1",
1521  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1522  N_("internal embedded ruby scripts.") },
1523 #endif
1524 #if defined(WITH_SEMANAGE)
1525  { "rpmlib(BuiltinSpookScripts)", "5.3-1",
1526  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1527  N_("internal embedded Spook scripts.") },
1528 #endif
1529 #if defined(WITH_SQLITE)
1530  { "rpmlib(BuiltinSqlScripts)", "5.3-1",
1531  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1532  N_("internal embedded sqlite3 scripts.") },
1533 #endif
1534 #if defined(WITH_SQUIRREL)
1535  { "rpmlib(BuiltinSquirrelScripts)", "5.2-1",
1536  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1537  N_("internal embedded squirrel scripts.") },
1538 #endif
1539 #if defined(WITH_TCL)
1540  { "rpmlib(BuiltinTclScripts)", "5.2-1",
1541  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1542  N_("internal embedded tcl scripts.") },
1543 #endif
1544  { "rpmlib(HeaderTagTypeInt64)", "4.4.3-1",
1545  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1546  N_("header tag data can be of type uint64_t.") },
1547  { "rpmlib(PayloadIsUstar)", "4.4.4-1",
1548  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1549  N_("package payload can be in ustar tar archive format.") },
1550 #if defined(WITH_XZ) /* XXX should be 4.4.6, but use SuSE's 4.4.2 instead */
1551  { "rpmlib(PayloadIsLzma)", "4.4.2-1",
1552  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1553  N_("package payload can be compressed using lzma.") },
1554 #endif
1555  { "rpmlib(FileDigestParameterized)", "4.4.6-1",
1556  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1557  N_("file digests can be other than MD5.") },
1558  { "rpmlib(FileDigests)", "4.6.0-1",
1559  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1560  N_("file digests can be other than MD5.") },
1561 #if defined(SUPPORT_AR_PAYLOADS)
1562  { "rpmlib(PayloadIsAr)", "5.1-1",
1563  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1564  N_("package payload can be in ar archive format.") },
1565 #endif
1566 #if defined(WITH_XZ)
1567  { "rpmlib(PayloadIsXz)", "5.2-1",
1568  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1569  N_("package payload can be compressed using xz.") },
1570 #endif
1571  /* XXX FIXME: Alt should _NOT_ have added a tracking dependency. */
1572  { "rpmlib(SetVersions)", "4.0.4-alt98",
1573  (evrFlags)(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1574  N_("dependencies support set/subset versions.") },
1575 #if defined(RPM_VENDOR_MANDRIVA)
1576  { "rpmlib(DistEpoch)", "5.4.7-1",
1577  (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
1578  N_("package has distepoch.") },
1579 #endif
1580  { NULL, NULL, (evrFlags)0, NULL }
1581 };
1582 
1589 int rpmdsRpmlib(rpmds * dsp, void * tblp)
1590 {
1591  const struct rpmlibProvides_s * rltblp = (struct rpmlibProvides_s *) tblp;
1592  const struct rpmlibProvides_s * rlp;
1593  int xx;
1594 
1595  if (rltblp == NULL)
1596  rltblp = rpmlibProvides;
1597 
1598  for (rlp = rltblp; rlp->featureName != NULL; rlp++) {
1600  rlp->featureEVR, rlp->featureFlags);
1601  xx = rpmdsMerge(dsp, ds);
1602  (void)rpmdsFree(ds);
1603  ds = NULL;
1604  }
1605  return 0;
1606 }
1607 
1615 static int rpmdsSysinfoFile(rpmPRCO PRCO, const char * fn, rpmTag tagN)
1616  /*@globals h_errno, fileSystem, internalState @*/
1617  /*@modifies PRCO, fileSystem, internalState @*/
1618 {
1619  char buf[BUFSIZ];
1620  const char *N, *EVR;
1621  evrFlags Flags;
1622  rpmds ds;
1623  char * f, * fe;
1624  char * g, * ge;
1625  FD_t fd = NULL;
1626  FILE * fp;
1627  int rc = -1;
1628  int ln;
1629  int xx;
1630 
1631  /* XXX for now, collect Dirnames/Filelinktos in Providename */
1632  if (tagN == RPMTAG_DIRNAMES || tagN == RPMTAG_FILELINKTOS)
1633  tagN = RPMTAG_PROVIDENAME;
1634 
1635 assert(fn != NULL);
1636  fd = Fopen(fn, "r.fpio");
1637  if (fd == NULL || Ferror(fd))
1638  goto exit;
1639  fp = fdGetFILE(fd);
1640 
1641  ln = 0;
1642  if (fp != NULL)
1643  while((f = fgets(buf, (int)sizeof(buf), fp)) != NULL) {
1644  ln++;
1645 
1646  /* insure a terminator. */
1647  buf[sizeof(buf)-1] = '\0';
1648 
1649  /* ltrim on line. */
1650  while (*f && _isspace(*f))
1651  f++;
1652 
1653  /* XXX skip YAML "- " markup */
1654  if (f[0] == '-' && _isspace(f[1])) {
1655  f += sizeof("- ")-1;
1656  while (*f && _isspace(*f))
1657  f++;
1658  }
1659 
1660  /* skip empty lines and comments */
1661  if (*f == '\0' || *f == '#')
1662  continue;
1663 
1664  /* rtrim on line. */
1665  fe = f + strlen(f);
1666  while (--fe > f && _isspace(*fe))
1667  *fe = '\0';
1668 
1669  if (!(xisalnum(f[0]) || strchr("/_%!", f[0]) != NULL)) {
1670  fprintf(stderr, _("%s:%d \"%s\" has invalid name. Skipping ...\n"),
1671  fn, ln, f);
1672  continue;
1673  }
1674 
1675  /* split on ' ' or comparison operator. */
1676  fe = f;
1677  if (*f == '!') fe++;
1678  while (*fe && !_isspace(*fe) && strchr("!<=>", *fe) == NULL)
1679  fe++;
1680  while (*fe && _isspace(*fe))
1681  *fe++ = '\0';
1682 
1683  N = f;
1684  EVR = NULL;
1685  Flags = (evrFlags) 0;
1686 
1687  /* parse for non-path, versioned dependency. */
1688  if (*f != '/' && *fe != '\0') {
1689  /* parse comparison operator */
1690  g = fe;
1691  Flags = rpmEVRflags(fe, (const char **)&g);
1692  if (Flags == 0) {
1693  fprintf(stderr, _("%s:%d \"%s\" has no comparison operator. Skipping ...\n"),
1694  fn, ln, fe);
1695  continue;
1696  }
1697  *fe = '\0';
1698 
1699  /* ltrim on field 2. */
1700  while (*g && _isspace(*g))
1701  g++;
1702  if (*g == '\0') {
1703  /* XXX No EVR comparison value found. */
1704  fprintf(stderr, _("%s:%d \"%s\" has no EVR string. Skipping ...\n"),
1705  fn, ln, f);
1706  continue;
1707  }
1708 
1709  ge = g + 1;
1710  while (*ge && !_isspace(*ge))
1711  ge++;
1712 
1713  if (*ge != '\0')
1714  *ge = '\0'; /* XXX can't happen, line rtrim'ed already. */
1715 
1716  EVR = g;
1717  }
1718 
1719  if (EVR == NULL)
1720  EVR = "";
1721  Flags = (evrFlags) (Flags | RPMSENSE_PROBE);
1722  ds = rpmdsSingle(tagN, N, EVR , Flags);
1723  if (ds) { /* XXX can't happen */
1724  xx = rpmdsMergePRCO(PRCO, ds);
1725  (void)rpmdsFree(ds);
1726  ds = NULL;
1727  }
1728  }
1729  rc = 0;
1730 
1731 exit:
1732  if (fd != NULL) (void) Fclose(fd);
1733  return rc;
1734 }
1735 
1736 #if defined(RPM_VENDOR_WINDRIVER)
1737 #define _ETC_RPM_SYSINFO "%{_etcrpm}/sysinfo"
1738 #else
1739 #define _ETC_RPM_SYSINFO SYSCONFIGDIR "/sysinfo"
1740 #endif
1741 
1742 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
1743 const char *_sysinfo_path = NULL;
1744 
1745 /*@-nullassign@*/
1746 /*@unchecked@*/ /*@observer@*/ /*@relnull@*/
1747 static const char *_sysinfo_tags[] = {
1748  "Providename",
1749  "Requirename",
1750  "Conflictname",
1751  "Obsoletename",
1752  "Dirnames",
1753  "Filelinktos",
1754  NULL
1755 };
1756 /*@=nullassign@*/
1757 
1758 int rpmdsSysinfo(rpmPRCO PRCO, const char * fn)
1759  /*@globals _sysinfo_path @*/
1760  /*@modifies _sysinfo_path @*/
1761 {
1762  struct stat * st = (struct stat *) memset(alloca(sizeof(*st)), 0, sizeof(*st));
1763  int rc = -1;
1764  int xx;
1765 
1766 /*@-modobserver@*/
1767  if (_sysinfo_path == NULL) {
1768  _sysinfo_path = rpmExpand("%{?_rpmds_sysinfo_path}", NULL);
1769  /* XXX may need to validate path existence somewhen. */
1770  if (!(_sysinfo_path != NULL && *_sysinfo_path == '/')) {
1771 /*@-observertrans @*/
1772  _sysinfo_path = _free(_sysinfo_path);
1773 /*@=observertrans @*/
1774  _sysinfo_path = xstrdup(_ETC_RPM_SYSINFO);
1775  }
1776  }
1777 /*@=modobserver@*/
1778 
1779  if (fn == NULL)
1780  fn = _sysinfo_path;
1781 
1782  if (fn == NULL)
1783  goto exit;
1784 
1785  xx = Stat(fn, st);
1786  if (xx < 0)
1787  goto exit;
1788 
1789  if (S_ISDIR(st->st_mode)) {
1790  const char *dn = fn;
1791  const char **av;
1792  rpmTag tagN;
1793  rc = 0; /* assume success */
1794  for (av = _sysinfo_tags; av && *av; av++) {
1795  tagN = tagValue(*av);
1796  if ((int)tagN < 0) /* XXX FIXME: all tags are valid now */
1797  continue;
1798  fn = rpmGetPath(dn, "/", *av, NULL);
1799  st = (struct stat *) memset(st, 0, sizeof(*st));
1800  xx = Stat(fn, st);
1801  if (xx == 0 && S_ISREG(st->st_mode))
1802  rc = rpmdsSysinfoFile(PRCO, fn, tagN);
1803  fn = _free(fn);
1804  if (rc)
1805  break;
1806  }
1807  } else
1808  /* XXX for now, collect Dirnames/Filelinktos in Providename */
1809  if (S_ISREG(st->st_mode))
1810  rc = rpmdsSysinfoFile(PRCO, fn, RPMTAG_PROVIDENAME);
1811 
1812 exit:
1813  return rc;
1814 }
1815 
1816 typedef enum { SYSCONF, CONFSTR, PATHCONF } _conf_e;
1817 struct _conf_s {
1818 /*@observer@*/ /*@relnull@*/
1819  const char *name;
1820  const int call_name;
1821  const _conf_e call;
1822 };
1823 
1824 /*@unchecked@*/ /*@observer@*/
1825 static const struct _conf_s vars[] = {
1826 #ifdef _PC_LINK_MAX
1827  { "LINK_MAX", _PC_LINK_MAX, PATHCONF },
1828 #endif
1829 #ifdef _PC_LINK_MAX
1830  { "_POSIX_LINK_MAX", _PC_LINK_MAX, PATHCONF },
1831 #endif
1832 #ifdef _PC_MAX_CANON
1833  { "MAX_CANON", _PC_MAX_CANON, PATHCONF },
1834 #endif
1835 #ifdef _PC_MAX_CANON
1836  { "_POSIX_MAX_CANON", _PC_MAX_CANON, PATHCONF },
1837 #endif
1838 #ifdef _PC_MAX_INPUT
1839  { "MAX_INPUT", _PC_MAX_INPUT, PATHCONF },
1840 #endif
1841 #ifdef _PC_MAX_INPUT
1842  { "_POSIX_MAX_INPUT", _PC_MAX_INPUT, PATHCONF },
1843 #endif
1844 #ifdef _PC_NAME_MAX
1845  { "NAME_MAX", _PC_NAME_MAX, PATHCONF },
1846 #endif
1847 #ifdef _PC_NAME_MAX
1848  { "_POSIX_NAME_MAX", _PC_NAME_MAX, PATHCONF },
1849 #endif
1850 #ifdef _PC_PATH_MAX
1851  { "PATH_MAX", _PC_PATH_MAX, PATHCONF },
1852 #endif
1853 #ifdef _PC_PATH_MAX
1854  { "_POSIX_PATH_MAX", _PC_PATH_MAX, PATHCONF },
1855 #endif
1856 #ifdef _PC_PIPE_BUF
1857  { "PIPE_BUF", _PC_PIPE_BUF, PATHCONF },
1858 #endif
1859 #ifdef _PC_PIPE_BUF
1860  { "_POSIX_PIPE_BUF", _PC_PIPE_BUF, PATHCONF },
1861 #endif
1862 #ifdef _PC_SOCK_MAXBUF
1863  { "SOCK_MAXBUF", _PC_SOCK_MAXBUF, PATHCONF },
1864 #endif
1865 #ifdef _PC_ASYNC_IO
1866  { "_POSIX_ASYNC_IO", _PC_ASYNC_IO, PATHCONF },
1867 #endif
1868 #ifdef _PC_CHOWN_RESTRICTED
1869  { "_POSIX_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED, PATHCONF },
1870 #endif
1871 #ifdef _PC_NO_TRUNC
1872  { "_POSIX_NO_TRUNC", _PC_NO_TRUNC, PATHCONF },
1873 #endif
1874 #ifdef _PC_PRIO_IO
1875  { "_POSIX_PRIO_IO", _PC_PRIO_IO, PATHCONF },
1876 #endif
1877 #ifdef _PC_SYNC_IO
1878  { "_POSIX_SYNC_IO", _PC_SYNC_IO, PATHCONF },
1879 #endif
1880 #ifdef _PC_VDISABLE
1881  { "_POSIX_VDISABLE", _PC_VDISABLE, PATHCONF },
1882 #endif
1883 
1884 #ifdef _SC_ARG_MAX
1885  { "ARG_MAX", _SC_ARG_MAX, SYSCONF },
1886 #endif
1887 #ifdef _SC_ATEXIT_MAX
1888  { "ATEXIT_MAX", _SC_ATEXIT_MAX, SYSCONF },
1889 #endif
1890 #ifdef _SC_CHAR_BIT
1891  { "CHAR_BIT", _SC_CHAR_BIT, SYSCONF },
1892 #endif
1893 #ifdef _SC_CHAR_MAX
1894  { "CHAR_MAX", _SC_CHAR_MAX, SYSCONF },
1895 #endif
1896 #ifdef _SC_CHAR_MIN
1897  { "CHAR_MIN", _SC_CHAR_MIN, SYSCONF },
1898 #endif
1899 #ifdef _SC_CHILD_MAX
1900  { "CHILD_MAX", _SC_CHILD_MAX, SYSCONF },
1901 #endif
1902 #ifdef _SC_CLK_TCK
1903  { "CLK_TCK", _SC_CLK_TCK, SYSCONF },
1904 #endif
1905 #ifdef _SC_INT_MAX
1906  { "INT_MAX", _SC_INT_MAX, SYSCONF },
1907 #endif
1908 #ifdef _SC_INT_MIN
1909  { "INT_MIN", _SC_INT_MIN, SYSCONF },
1910 #endif
1911 #ifdef _SC_UIO_MAXIOV
1912  { "IOV_MAX", _SC_UIO_MAXIOV, SYSCONF },
1913 #endif
1914 #ifdef _SC_LOGIN_NAME_MAX
1915  { "LOGNAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF },
1916 #endif
1917 #ifdef _SC_LONG_BIT
1918  { "LONG_BIT", _SC_LONG_BIT, SYSCONF },
1919 #endif
1920 #ifdef _SC_MB_LEN_MAX
1921  { "MB_LEN_MAX", _SC_MB_LEN_MAX, SYSCONF },
1922 #endif
1923 #ifdef _SC_NGROUPS_MAX
1924  { "NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF },
1925 #endif
1926 #ifdef _SC_NL_ARGMAX
1927  { "NL_ARGMAX", _SC_NL_ARGMAX, SYSCONF },
1928 #endif
1929 #ifdef _SC_NL_LANGMAX
1930  { "NL_LANGMAX", _SC_NL_LANGMAX, SYSCONF },
1931 #endif
1932 #ifdef _SC_NL_MSGMAX
1933  { "NL_MSGMAX", _SC_NL_MSGMAX, SYSCONF },
1934 #endif
1935 #ifdef _SC_NL_NMAX
1936  { "NL_NMAX", _SC_NL_NMAX, SYSCONF },
1937 #endif
1938 #ifdef _SC_NL_SETMAX
1939  { "NL_SETMAX", _SC_NL_SETMAX, SYSCONF },
1940 #endif
1941 #ifdef _SC_NL_TEXTMAX
1942  { "NL_TEXTMAX", _SC_NL_TEXTMAX, SYSCONF },
1943 #endif
1944 #ifdef _SC_GETGR_R_SIZE_MAX
1945  { "NSS_BUFLEN_GROUP", _SC_GETGR_R_SIZE_MAX, SYSCONF },
1946 #endif
1947 #ifdef _SC_GETPW_R_SIZE_MAX
1948  { "NSS_BUFLEN_PASSWD", _SC_GETPW_R_SIZE_MAX, SYSCONF },
1949 #endif
1950 #ifdef _SC_NZERO
1951  { "NZERO", _SC_NZERO, SYSCONF },
1952 #endif
1953 #ifdef _SC_OPEN_MAX
1954  { "OPEN_MAX", _SC_OPEN_MAX, SYSCONF },
1955 #endif
1956 #ifdef _SC_PAGESIZE
1957  { "PAGESIZE", _SC_PAGESIZE, SYSCONF },
1958 #endif
1959 #ifdef _SC_PAGESIZE
1960  { "PAGE_SIZE", _SC_PAGESIZE, SYSCONF },
1961 #endif
1962 #ifdef _SC_PASS_MAX
1963  { "PASS_MAX", _SC_PASS_MAX, SYSCONF },
1964 #endif
1965 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
1966  { "PTHREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS, SYSCONF },
1967 #endif
1968 #ifdef _SC_THREAD_KEYS_MAX
1969  { "PTHREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX, SYSCONF },
1970 #endif
1971 #ifdef _SC_THREAD_STACK_MIN
1972  { "PTHREAD_STACK_MIN", _SC_THREAD_STACK_MIN, SYSCONF },
1973 #endif
1974 #ifdef _SC_THREAD_THREADS_MAX
1975  { "PTHREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX, SYSCONF },
1976 #endif
1977 #ifdef _SC_SCHAR_MAX
1978  { "SCHAR_MAX", _SC_SCHAR_MAX, SYSCONF },
1979 #endif
1980 #ifdef _SC_SCHAR_MIN
1981  { "SCHAR_MIN", _SC_SCHAR_MIN, SYSCONF },
1982 #endif
1983 #ifdef _SC_SHRT_MAX
1984  { "SHRT_MAX", _SC_SHRT_MAX, SYSCONF },
1985 #endif
1986 #ifdef _SC_SHRT_MIN
1987  { "SHRT_MIN", _SC_SHRT_MIN, SYSCONF },
1988 #endif
1989 #ifdef _SC_SSIZE_MAX
1990  { "SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF },
1991 #endif
1992 #ifdef _SC_TTY_NAME_MAX
1993  { "TTY_NAME_MAX", _SC_TTY_NAME_MAX, SYSCONF },
1994 #endif
1995 #ifdef _SC_TZNAME_MAX
1996  { "TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF },
1997 #endif
1998 #ifdef _SC_UCHAR_MAX
1999  { "UCHAR_MAX", _SC_UCHAR_MAX, SYSCONF },
2000 #endif
2001 #ifdef _SC_UINT_MAX
2002  { "UINT_MAX", _SC_UINT_MAX, SYSCONF },
2003 #endif
2004 #ifdef _SC_UIO_MAXIOV
2005  { "UIO_MAXIOV", _SC_UIO_MAXIOV, SYSCONF },
2006 #endif
2007 #ifdef _SC_ULONG_MAX
2008  { "ULONG_MAX", _SC_ULONG_MAX, SYSCONF },
2009 #endif
2010 #ifdef _SC_USHRT_MAX
2011  { "USHRT_MAX", _SC_USHRT_MAX, SYSCONF },
2012 #endif
2013 #ifdef _SC_WORD_BIT
2014  { "WORD_BIT", _SC_WORD_BIT, SYSCONF },
2015 #endif
2016 #ifdef _SC_AVPHYS_PAGES
2017  { "_AVPHYS_PAGES", _SC_AVPHYS_PAGES, SYSCONF },
2018 #endif
2019 #ifdef _SC_NPROCESSORS_CONF
2020  { "_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF, SYSCONF },
2021 #endif
2022 #ifdef _SC_NPROCESSORS_ONLN
2023  { "_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN, SYSCONF },
2024 #endif
2025 #ifdef _SC_PHYS_PAGES
2026  { "_PHYS_PAGES", _SC_PHYS_PAGES, SYSCONF },
2027 #endif
2028 #ifdef _SC_ARG_MAX
2029  { "_POSIX_ARG_MAX", _SC_ARG_MAX, SYSCONF },
2030 #endif
2031 #ifdef _SC_ASYNCHRONOUS_IO
2032  { "_POSIX_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO, SYSCONF },
2033 #endif
2034 #ifdef _SC_CHILD_MAX
2035  { "_POSIX_CHILD_MAX", _SC_CHILD_MAX, SYSCONF },
2036 #endif
2037 #ifdef _SC_FSYNC
2038  { "_POSIX_FSYNC", _SC_FSYNC, SYSCONF },
2039 #endif
2040 #ifdef _SC_JOB_CONTROL
2041  { "_POSIX_JOB_CONTROL", _SC_JOB_CONTROL, SYSCONF },
2042 #endif
2043 #ifdef _SC_MAPPED_FILES
2044  { "_POSIX_MAPPED_FILES", _SC_MAPPED_FILES, SYSCONF },
2045 #endif
2046 #ifdef _SC_MEMLOCK
2047  { "_POSIX_MEMLOCK", _SC_MEMLOCK, SYSCONF },
2048 #endif
2049 #ifdef _SC_MEMLOCK_RANGE
2050  { "_POSIX_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE, SYSCONF },
2051 #endif
2052 #ifdef _SC_MEMORY_PROTECTION
2053  { "_POSIX_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION, SYSCONF },
2054 #endif
2055 #ifdef _SC_MESSAGE_PASSING
2056  { "_POSIX_MESSAGE_PASSING", _SC_MESSAGE_PASSING, SYSCONF },
2057 #endif
2058 #ifdef _SC_NGROUPS_MAX
2059  { "_POSIX_NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF },
2060 #endif
2061 #ifdef _SC_OPEN_MAX
2062  { "_POSIX_OPEN_MAX", _SC_OPEN_MAX, SYSCONF },
2063 #endif
2064 #ifdef _SC_PII
2065  { "_POSIX_PII", _SC_PII, SYSCONF },
2066 #endif
2067 #ifdef _SC_PII_INTERNET
2068  { "_POSIX_PII_INTERNET", _SC_PII_INTERNET, SYSCONF },
2069 #endif
2070 #ifdef _SC_PII_INTERNET_DGRAM
2071  { "_POSIX_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM, SYSCONF },
2072 #endif
2073 #ifdef _SC_PII_INTERNET_STREAM
2074  { "_POSIX_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM, SYSCONF },
2075 #endif
2076 #ifdef _SC_PII_OSI
2077  { "_POSIX_PII_OSI", _SC_PII_OSI, SYSCONF },
2078 #endif
2079 #ifdef _SC_PII_OSI_CLTS
2080  { "_POSIX_PII_OSI_CLTS", _SC_PII_OSI_CLTS, SYSCONF },
2081 #endif
2082 #ifdef _SC_PII_OSI_COTS
2083  { "_POSIX_PII_OSI_COTS", _SC_PII_OSI_COTS, SYSCONF },
2084 #endif
2085 #ifdef _SC_PII_OSI_M
2086  { "_POSIX_PII_OSI_M", _SC_PII_OSI_M, SYSCONF },
2087 #endif
2088 #ifdef _SC_PII_SOCKET
2089  { "_POSIX_PII_SOCKET", _SC_PII_SOCKET, SYSCONF },
2090 #endif
2091 #ifdef _SC_PII_XTI
2092  { "_POSIX_PII_XTI", _SC_PII_XTI, SYSCONF },
2093 #endif
2094 #ifdef _SC_POLL
2095  { "_POSIX_POLL", _SC_POLL, SYSCONF },
2096 #endif
2097 #ifdef _SC_PRIORITIZED_IO
2098  { "_POSIX_PRIORITIZED_IO", _SC_PRIORITIZED_IO, SYSCONF },
2099 #endif
2100 #ifdef _SC_PRIORITY_SCHEDULING
2101  { "_POSIX_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING, SYSCONF },
2102 #endif
2103 #ifdef _SC_REALTIME_SIGNALS
2104  { "_POSIX_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS, SYSCONF },
2105 #endif
2106 #ifdef _SC_SAVED_IDS
2107  { "_POSIX_SAVED_IDS", _SC_SAVED_IDS, SYSCONF },
2108 #endif
2109 #ifdef _SC_SELECT
2110  { "_POSIX_SELECT", _SC_SELECT, SYSCONF },
2111 #endif
2112 #ifdef _SC_SEMAPHORES
2113  { "_POSIX_SEMAPHORES", _SC_SEMAPHORES, SYSCONF },
2114 #endif
2115 #ifdef _SC_SHARED_MEMORY_OBJECTS
2116  { "_POSIX_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS, SYSCONF },
2117 #endif
2118 #ifdef _SC_SSIZE_MAX
2119  { "_POSIX_SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF },
2120 #endif
2121 #ifdef _SC_STREAM_MAX
2122  { "_POSIX_STREAM_MAX", _SC_STREAM_MAX, SYSCONF },
2123 #endif
2124 #ifdef _SC_SYNCHRONIZED_IO
2125  { "_POSIX_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO, SYSCONF },
2126 #endif
2127 #ifdef _SC_THREADS
2128  { "_POSIX_THREADS", _SC_THREADS, SYSCONF },
2129 #endif
2130 #ifdef _SC_THREAD_ATTR_STACKADDR
2131  { "_POSIX_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR, SYSCONF },
2132 #endif
2133 #ifdef _SC_THREAD_ATTR_STACKSIZE
2134  { "_POSIX_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE, SYSCONF },
2135 #endif
2136 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
2137  { "_POSIX_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING, SYSCONF },
2138 #endif
2139 #ifdef _SC_THREAD_PRIO_INHERIT
2140  { "_POSIX_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT, SYSCONF },
2141 #endif
2142 #ifdef _SC_THREAD_PRIO_PROTECT
2143  { "_POSIX_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT, SYSCONF },
2144 #endif
2145 #ifdef _SC_THREAD_PROCESS_SHARED
2146  { "_POSIX_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED, SYSCONF },
2147 #endif
2148 #ifdef _SC_THREAD_SAFE_FUNCTIONS
2149  { "_POSIX_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS, SYSCONF },
2150 #endif
2151 #ifdef _SC_TIMERS
2152  { "_POSIX_TIMERS", _SC_TIMERS, SYSCONF },
2153 #endif
2154 #ifdef _SC_TIMER_MAX
2155  { "TIMER_MAX", _SC_TIMER_MAX, SYSCONF },
2156 #endif
2157 #ifdef _SC_TZNAME_MAX
2158  { "_POSIX_TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF },
2159 #endif
2160 #ifdef _SC_VERSION
2161  { "_POSIX_VERSION", _SC_VERSION, SYSCONF },
2162 #endif
2163 #ifdef _SC_T_IOV_MAX
2164  { "_T_IOV_MAX", _SC_T_IOV_MAX, SYSCONF },
2165 #endif
2166 #ifdef _SC_XOPEN_CRYPT
2167  { "_XOPEN_CRYPT", _SC_XOPEN_CRYPT, SYSCONF },
2168 #endif
2169 #ifdef _SC_XOPEN_ENH_I18N
2170  { "_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N, SYSCONF },
2171 #endif
2172 #ifdef _SC_XOPEN_LEGACY
2173  { "_XOPEN_LEGACY", _SC_XOPEN_LEGACY, SYSCONF },
2174 #endif
2175 #ifdef _SC_XOPEN_REALTIME
2176  { "_XOPEN_REALTIME", _SC_XOPEN_REALTIME, SYSCONF },
2177 #endif
2178 #ifdef _SC_XOPEN_REALTIME_THREADS
2179  { "_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS, SYSCONF },
2180 #endif
2181 #ifdef _SC_XOPEN_SHM
2182  { "_XOPEN_SHM", _SC_XOPEN_SHM, SYSCONF },
2183 #endif
2184 #ifdef _SC_XOPEN_UNIX
2185  { "_XOPEN_UNIX", _SC_XOPEN_UNIX, SYSCONF },
2186 #endif
2187 #ifdef _SC_XOPEN_VERSION
2188  { "_XOPEN_VERSION", _SC_XOPEN_VERSION, SYSCONF },
2189 #endif
2190 #ifdef _SC_XOPEN_XCU_VERSION
2191  { "_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION, SYSCONF },
2192 #endif
2193 #ifdef _SC_XOPEN_XPG2
2194  { "_XOPEN_XPG2", _SC_XOPEN_XPG2, SYSCONF },
2195 #endif
2196 #ifdef _SC_XOPEN_XPG3
2197  { "_XOPEN_XPG3", _SC_XOPEN_XPG3, SYSCONF },
2198 #endif
2199 #ifdef _SC_XOPEN_XPG4
2200  { "_XOPEN_XPG4", _SC_XOPEN_XPG4, SYSCONF },
2201 #endif
2202  /* POSIX.2 */
2203 #ifdef _SC_BC_BASE_MAX
2204  { "BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF },
2205 #endif
2206 #ifdef _SC_BC_DIM_MAX
2207  { "BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF },
2208 #endif
2209 #ifdef _SC_BC_SCALE_MAX
2210  { "BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF },
2211 #endif
2212 #ifdef _SC_BC_STRING_MAX
2213  { "BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF },
2214 #endif
2215 #ifdef _SC_CHARCLASS_NAME_MAX
2216  { "CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX, SYSCONF },
2217 #endif
2218 #ifdef _SC_COLL_WEIGHTS_MAX
2219  { "COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF },
2220 #endif
2221 #ifdef _SC_EQUIV_CLASS_MAX
2222  { "EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX, SYSCONF },
2223 #endif
2224 #ifdef _SC_EXPR_NEST_MAX
2225  { "EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF },
2226 #endif
2227 #ifdef _SC_LINE_MAX
2228  { "LINE_MAX", _SC_LINE_MAX, SYSCONF },
2229 #endif
2230 #ifdef _SC_BC_BASE_MAX
2231  { "POSIX2_BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF },
2232 #endif
2233 #ifdef _SC_BC_DIM_MAX
2234  { "POSIX2_BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF },
2235 #endif
2236 #ifdef _SC_BC_SCALE_MAX
2237  { "POSIX2_BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF },
2238 #endif
2239 #ifdef _SC_BC_STRING_MAX
2240  { "POSIX2_BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF },
2241 #endif
2242 #ifdef _SC_2_CHAR_TERM
2243  { "POSIX2_CHAR_TERM", _SC_2_CHAR_TERM, SYSCONF },
2244 #endif
2245 #ifdef _SC_COLL_WEIGHTS_MAX
2246  { "POSIX2_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF },
2247 #endif
2248 #ifdef _SC_2_C_BIND
2249  { "POSIX2_C_BIND", _SC_2_C_BIND, SYSCONF },
2250 #endif
2251 #ifdef _SC_2_C_DEV
2252  { "POSIX2_C_DEV", _SC_2_C_DEV, SYSCONF },
2253 #endif
2254 #ifdef _SC_2_C_VERSION
2255  { "POSIX2_C_VERSION", _SC_2_C_VERSION, SYSCONF },
2256 #endif
2257 #ifdef _SC_EXPR_NEST_MAX
2258  { "POSIX2_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF },
2259 #endif
2260 #ifdef _SC_2_FORT_DEV
2261  { "POSIX2_FORT_DEV", _SC_2_FORT_DEV, SYSCONF },
2262 #endif
2263 #ifdef _SC_2_FORT_RUN
2264  { "POSIX2_FORT_RUN", _SC_2_FORT_RUN, SYSCONF },
2265 #endif
2266 #ifdef _SC_LINE_MAX
2267  { "_POSIX2_LINE_MAX", _SC_LINE_MAX, SYSCONF },
2268 #endif
2269 #ifdef _SC_2_LOCALEDEF
2270  { "POSIX2_LOCALEDEF", _SC_2_LOCALEDEF, SYSCONF },
2271 #endif
2272 #ifdef _SC_RE_DUP_MAX
2273  { "POSIX2_RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF },
2274 #endif
2275 #ifdef _SC_2_SW_DEV
2276  { "POSIX2_SW_DEV", _SC_2_SW_DEV, SYSCONF },
2277 #endif
2278 #ifdef _SC_2_UPE
2279  { "POSIX2_UPE", _SC_2_UPE, SYSCONF },
2280 #endif
2281 #ifdef _SC_2_VERSION
2282  { "POSIX2_VERSION", _SC_2_VERSION, SYSCONF },
2283 #endif
2284 #ifdef _SC_RE_DUP_MAX
2285  { "RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF },
2286 #endif
2287 
2288 #ifdef _CS_PATH
2289  { "PATH", _CS_PATH, CONFSTR },
2290  { "CS_PATH", _CS_PATH, CONFSTR },
2291 #endif
2292 
2293  /* LFS */
2294 #ifdef _CS_LFS_CFLAGS
2295  { "LFS_CFLAGS", _CS_LFS_CFLAGS, CONFSTR },
2296 #endif
2297 #ifdef _CS_LFS_LDFLAGS
2298  { "LFS_LDFLAGS", _CS_LFS_LDFLAGS, CONFSTR },
2299 #endif
2300 #ifdef _CS_LFS_LIBS
2301  { "LFS_LIBS", _CS_LFS_LIBS, CONFSTR },
2302 #endif
2303 #ifdef _CS_LFS_LINTFLAGS
2304  { "LFS_LINTFLAGS", _CS_LFS_LINTFLAGS, CONFSTR },
2305 #endif
2306 #ifdef _CS_LFS64_CFLAGS
2307  { "LFS64_CFLAGS", _CS_LFS64_CFLAGS, CONFSTR },
2308 #endif
2309 #ifdef _CS_LFS64_LDFLAGS
2310  { "LFS64_LDFLAGS", _CS_LFS64_LDFLAGS, CONFSTR },
2311 #endif
2312 #ifdef _CS_LFS64_LIBS
2313  { "LFS64_LIBS", _CS_LFS64_LIBS, CONFSTR },
2314 #endif
2315 #ifdef _CS_LFS64_LINTFLAGS
2316  { "LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS, CONFSTR },
2317 #endif
2318 
2319  /* Programming environments. */
2320 #ifdef _SC_XBS5_ILP32_OFF32
2321  { "_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32, SYSCONF },
2322 #endif
2323 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
2324  { "XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS, CONFSTR },
2325 #endif
2326 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
2327  { "XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS, CONFSTR },
2328 #endif
2329 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
2330  { "XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS, CONFSTR },
2331 #endif
2332 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
2333  { "XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS, CONFSTR },
2334 #endif
2335 
2336 #ifdef _SC_XBS5_ILP32_OFFBIG
2337  { "_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG, SYSCONF },
2338 #endif
2339 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
2340  { "XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS, CONFSTR },
2341 #endif
2342 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
2343  { "XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS, CONFSTR },
2344 #endif
2345 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
2346  { "XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS, CONFSTR },
2347 #endif
2348 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
2349  { "XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, CONFSTR },
2350 #endif
2351 
2352 #ifdef _SC_XBS5_LP64_OFF64
2353  { "_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64, SYSCONF },
2354 #endif
2355 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
2356  { "XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS, CONFSTR },
2357 #endif
2358 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
2359  { "XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS, CONFSTR },
2360 #endif
2361 #ifdef _CS_XBS5_LP64_OFF64_LIBS
2362  { "XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS, CONFSTR },
2363 #endif
2364 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
2365  { "XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS, CONFSTR },
2366 #endif
2367 
2368 #ifdef _SC_XBS5_LPBIG_OFFBIG
2369  { "_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG, SYSCONF },
2370 #endif
2371 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
2372  { "XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS, CONFSTR },
2373 #endif
2374 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
2375  { "XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, CONFSTR },
2376 #endif
2377 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
2378  { "XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS, CONFSTR },
2379 #endif
2380 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
2381  { "XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, CONFSTR },
2382 #endif
2383 
2384 #ifdef _SC_V6_ILP32_OFF32
2385  { "_POSIX_V6_ILP32_OFF32", _SC_V6_ILP32_OFF32, SYSCONF },
2386 #endif
2387 #ifdef _CS_POSIX_V6_ILP32_OFF32_CFLAGS
2388  { "POSIX_V6_ILP32_OFF32_CFLAGS", _CS_POSIX_V6_ILP32_OFF32_CFLAGS, CONFSTR },
2389 #endif
2390 #ifdef _CS_POSIX_V6_ILP32_OFF32_LDFLAGS
2391  { "POSIX_V6_ILP32_OFF32_LDFLAGS", _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, CONFSTR },
2392 #endif
2393 #ifdef _CS_POSIX_V6_ILP32_OFF32_LIBS
2394  { "POSIX_V6_ILP32_OFF32_LIBS", _CS_POSIX_V6_ILP32_OFF32_LIBS, CONFSTR },
2395 #endif
2396 #ifdef _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS
2397  { "POSIX_V6_ILP32_OFF32_LINTFLAGS", _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, CONFSTR },
2398 #endif
2399 
2400 #ifdef _CS_V6_WIDTH_RESTRICTED_ENVS
2401  { "_POSIX_V6_WIDTH_RESTRICTED_ENVS", _CS_V6_WIDTH_RESTRICTED_ENVS, CONFSTR },
2402 #endif
2403 
2404 #ifdef _SC_V6_ILP32_OFFBIG
2405  { "_POSIX_V6_ILP32_OFFBIG", _SC_V6_ILP32_OFFBIG, SYSCONF },
2406 #endif
2407 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
2408  { "POSIX_V6_ILP32_OFFBIG_CFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, CONFSTR },
2409 #endif
2410 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
2411  { "POSIX_V6_ILP32_OFFBIG_LDFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, CONFSTR },
2412 #endif
2413 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LIBS
2414  { "POSIX_V6_ILP32_OFFBIG_LIBS", _CS_POSIX_V6_ILP32_OFFBIG_LIBS, CONFSTR },
2415 #endif
2416 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS
2417  { "POSIX_V6_ILP32_OFFBIG_LINTFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, CONFSTR },
2418 #endif
2419 
2420 #ifdef _SC_V6_LP64_OFF64
2421  { "_POSIX_V6_LP64_OFF64", _SC_V6_LP64_OFF64, SYSCONF },
2422 #endif
2423 #ifdef _CS_POSIX_V6_LP64_OFF64_CFLAGS
2424  { "POSIX_V6_LP64_OFF64_CFLAGS", _CS_POSIX_V6_LP64_OFF64_CFLAGS, CONFSTR },
2425 #endif
2426 #ifdef _CS_POSIX_V6_LP64_OFF64_LDFLAGS
2427  { "POSIX_V6_LP64_OFF64_LDFLAGS", _CS_POSIX_V6_LP64_OFF64_LDFLAGS, CONFSTR },
2428 #endif
2429 #ifdef _CS_POSIX_V6_LP64_OFF64_LIBS
2430  { "POSIX_V6_LP64_OFF64_LIBS", _CS_POSIX_V6_LP64_OFF64_LIBS, CONFSTR },
2431 #endif
2432 #ifdef _CS_POSIX_V6_LP64_OFF64_LINTFLAGS
2433  { "POSIX_V6_LP64_OFF64_LINTFLAGS", _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, CONFSTR },
2434 #endif
2435 
2436 #ifdef _SC_V6_LPBIG_OFFBIG
2437  { "_POSIX_V6_LPBIG_OFFBIG", _SC_V6_LPBIG_OFFBIG, SYSCONF },
2438 #endif
2439 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
2440  { "POSIX_V6_LPBIG_OFFBIG_CFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, CONFSTR },
2441 #endif
2442 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
2443  { "POSIX_V6_LPBIG_OFFBIG_LDFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, CONFSTR },
2444 #endif
2445 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
2446  { "POSIX_V6_LPBIG_OFFBIG_LIBS", _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, CONFSTR },
2447 #endif
2448 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS
2449  { "POSIX_V6_LPBIG_OFFBIG_LINTFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, CONFSTR },
2450 #endif
2451 
2452 #ifdef _SC_ADVISORY_INFO
2453  { "_POSIX_ADVISORY_INFO", _SC_ADVISORY_INFO, SYSCONF },
2454 #endif
2455 #ifdef _SC_BARRIERS
2456  { "_POSIX_BARRIERS", _SC_BARRIERS, SYSCONF },
2457 #endif
2458 #ifdef _SC_BASE
2459  { "_POSIX_BASE", _SC_BASE, SYSCONF },
2460 #endif
2461 #ifdef _SC_C_LANG_SUPPORT
2462  { "_POSIX_C_LANG_SUPPORT", _SC_C_LANG_SUPPORT, SYSCONF },
2463 #endif
2464 #ifdef _SC_C_LANG_SUPPORT_R
2465  { "_POSIX_C_LANG_SUPPORT_R", _SC_C_LANG_SUPPORT_R, SYSCONF },
2466 #endif
2467 #ifdef _SC_CLOCK_SELECTION
2468  { "_POSIX_CLOCK_SELECTION", _SC_CLOCK_SELECTION, SYSCONF },
2469 #endif
2470 #ifdef _SC_CPUTIME
2471  { "_POSIX_CPUTIME", _SC_CPUTIME, SYSCONF },
2472 #endif
2473 #ifdef _SC_THREAD_CPUTIME
2474  { "_POSIX_THREAD_CPUTIME", _SC_THREAD_CPUTIME, SYSCONF },
2475 #endif
2476 #ifdef _SC_DEVICE_SPECIFIC
2477  { "_POSIX_DEVICE_SPECIFIC", _SC_DEVICE_SPECIFIC, SYSCONF },
2478 #endif
2479 #ifdef _SC_DEVICE_SPECIFIC_R
2480  { "_POSIX_DEVICE_SPECIFIC_R", _SC_DEVICE_SPECIFIC_R, SYSCONF },
2481 #endif
2482 #ifdef _SC_FD_MGMT
2483  { "_POSIX_FD_MGMT", _SC_FD_MGMT, SYSCONF },
2484 #endif
2485 #ifdef _SC_FIFO
2486  { "_POSIX_FIFO", _SC_FIFO, SYSCONF },
2487 #endif
2488 #ifdef _SC_PIPE
2489  { "_POSIX_PIPE", _SC_PIPE, SYSCONF },
2490 #endif
2491 #ifdef _SC_FILE_ATTRIBUTES
2492  { "_POSIX_FILE_ATTRIBUTES", _SC_FILE_ATTRIBUTES, SYSCONF },
2493 #endif
2494 #ifdef _SC_FILE_LOCKING
2495  { "_POSIX_FILE_LOCKING", _SC_FILE_LOCKING, SYSCONF },
2496 #endif
2497 #ifdef _SC_FILE_SYSTEM
2498  { "_POSIX_FILE_SYSTEM", _SC_FILE_SYSTEM, SYSCONF },
2499 #endif
2500 #ifdef _SC_MONOTONIC_CLOCK
2501  { "_POSIX_MONOTONIC_CLOCK", _SC_MONOTONIC_CLOCK, SYSCONF },
2502 #endif
2503 #ifdef _SC_MULTI_PROCESS
2504  { "_POSIX_MULTI_PROCESS", _SC_MULTI_PROCESS, SYSCONF },
2505 #endif
2506 #ifdef _SC_SINGLE_PROCESS
2507  { "_POSIX_SINGLE_PROCESS", _SC_SINGLE_PROCESS, SYSCONF },
2508 #endif
2509 #ifdef _SC_NETWORKING
2510  { "_POSIX_NETWORKING", _SC_NETWORKING, SYSCONF },
2511 #endif
2512 #ifdef _SC_READER_WRITER_LOCKS
2513  { "_POSIX_READER_WRITER_LOCKS", _SC_READER_WRITER_LOCKS, SYSCONF },
2514 #endif
2515 #ifdef _SC_SPIN_LOCKS
2516  { "_POSIX_SPIN_LOCKS", _SC_SPIN_LOCKS, SYSCONF },
2517 #endif
2518 #ifdef _SC_REGEXP
2519  { "_POSIX_REGEXP", _SC_REGEXP, SYSCONF },
2520 #endif
2521 #ifdef _SC_REGEX_VERSION
2522  { "_REGEX_VERSION", _SC_REGEX_VERSION, SYSCONF },
2523 #endif
2524 #ifdef _SC_SHELL
2525  { "_POSIX_SHELL", _SC_SHELL, SYSCONF },
2526 #endif
2527 #ifdef _SC_SIGNALS
2528  { "_POSIX_SIGNALS", _SC_SIGNALS, SYSCONF },
2529 #endif
2530 #ifdef _SC_SPAWN
2531  { "_POSIX_SPAWN", _SC_SPAWN, SYSCONF },
2532 #endif
2533 #ifdef _SC_SPORADIC_SERVER
2534  { "_POSIX_SPORADIC_SERVER", _SC_SPORADIC_SERVER, SYSCONF },
2535 #endif
2536 #ifdef _SC_THREAD_SPORADIC_SERVER
2537  { "_POSIX_THREAD_SPORADIC_SERVER", _SC_THREAD_SPORADIC_SERVER, SYSCONF },
2538 #endif
2539 #ifdef _SC_SYSTEM_DATABASE
2540  { "_POSIX_SYSTEM_DATABASE", _SC_SYSTEM_DATABASE, SYSCONF },
2541 #endif
2542 #ifdef _SC_SYSTEM_DATABASE_R
2543  { "_POSIX_SYSTEM_DATABASE_R", _SC_SYSTEM_DATABASE_R, SYSCONF },
2544 #endif
2545 #ifdef _SC_TIMEOUTS
2546  { "_POSIX_TIMEOUTS", _SC_TIMEOUTS, SYSCONF },
2547 #endif
2548 #ifdef _SC_TYPED_MEMORY_OBJECTS
2549  { "_POSIX_TYPED_MEMORY_OBJECTS", _SC_TYPED_MEMORY_OBJECTS, SYSCONF },
2550 #endif
2551 #ifdef _SC_USER_GROUPS
2552  { "_POSIX_USER_GROUPS", _SC_USER_GROUPS, SYSCONF },
2553 #endif
2554 #ifdef _SC_USER_GROUPS_R
2555  { "_POSIX_USER_GROUPS_R", _SC_USER_GROUPS_R, SYSCONF },
2556 #endif
2557 #ifdef _SC_2_PBS
2558  { "POSIX2_PBS", _SC_2_PBS, SYSCONF },
2559 #endif
2560 #ifdef _SC_2_PBS_ACCOUNTING
2561  { "POSIX2_PBS_ACCOUNTING", _SC_2_PBS_ACCOUNTING, SYSCONF },
2562 #endif
2563 #ifdef _SC_2_PBS_LOCATE
2564  { "POSIX2_PBS_LOCATE", _SC_2_PBS_LOCATE, SYSCONF },
2565 #endif
2566 #ifdef _SC_2_PBS_TRACK
2567  { "POSIX2_PBS_TRACK", _SC_2_PBS_TRACK, SYSCONF },
2568 #endif
2569 #ifdef _SC_2_PBS_MESSAGE
2570  { "POSIX2_PBS_MESSAGE", _SC_2_PBS_MESSAGE, SYSCONF },
2571 #endif
2572 #ifdef _SC_SYMLOOP_MAX
2573  { "SYMLOOP_MAX", _SC_SYMLOOP_MAX, SYSCONF },
2574 #endif
2575 #ifdef _SC_STREAM_MAX
2576  { "STREAM_MAX", _SC_STREAM_MAX, SYSCONF },
2577 #endif
2578 #ifdef _SC_AIO_LISTIO_MAX
2579  { "AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX, SYSCONF },
2580 #endif
2581 #ifdef _SC_AIO_MAX
2582  { "AIO_MAX", _SC_AIO_MAX, SYSCONF },
2583 #endif
2584 #ifdef _SC_AIO_PRIO_DELTA_MAX
2585  { "AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX, SYSCONF },
2586 #endif
2587 #ifdef _SC_DELAYTIMER_MAX
2588  { "DELAYTIMER_MAX", _SC_DELAYTIMER_MAX, SYSCONF },
2589 #endif
2590 #ifdef _SC_HOST_NAME_MAX
2591  { "HOST_NAME_MAX", _SC_HOST_NAME_MAX, SYSCONF },
2592 #endif
2593 #ifdef _SC_LOGIN_NAME_MAX
2594  { "LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF },
2595 #endif
2596 #ifdef _SC_MQ_OPEN_MAX
2597  { "MQ_OPEN_MAX", _SC_MQ_OPEN_MAX, SYSCONF },
2598 #endif
2599 #ifdef _SC_MQ_PRIO_MAX
2600  { "MQ_PRIO_MAX", _SC_MQ_PRIO_MAX, SYSCONF },
2601 #endif
2602 #ifdef _SC_DEVICE_IO
2603  { "_POSIX_DEVICE_IO", _SC_DEVICE_IO, SYSCONF },
2604 #endif
2605 #ifdef _SC_TRACE
2606  { "_POSIX_TRACE", _SC_TRACE, SYSCONF },
2607 #endif
2608 #ifdef _SC_TRACE_EVENT_FILTER
2609  { "_POSIX_TRACE_EVENT_FILTER", _SC_TRACE_EVENT_FILTER, SYSCONF },
2610 #endif
2611 #ifdef _SC_TRACE_INHERIT
2612  { "_POSIX_TRACE_INHERIT", _SC_TRACE_INHERIT, SYSCONF },
2613 #endif
2614 #ifdef _SC_TRACE_LOG
2615  { "_POSIX_TRACE_LOG", _SC_TRACE_LOG, SYSCONF },
2616 #endif
2617 #ifdef _SC_RTSIG_MAX
2618  { "RTSIG_MAX", _SC_RTSIG_MAX, SYSCONF },
2619 #endif
2620 #ifdef _SC_SEM_NSEMS_MAX
2621  { "SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX, SYSCONF },
2622 #endif
2623 #ifdef _SC_SEM_VALUE_MAX
2624  { "SEM_VALUE_MAX", _SC_SEM_VALUE_MAX, SYSCONF },
2625 #endif
2626 #ifdef _SC_SIGQUEUE_MAX
2627  { "SIGQUEUE_MAX", _SC_SIGQUEUE_MAX, SYSCONF },
2628 #endif
2629 #ifdef _PC_FILESIZEBITS
2630  { "FILESIZEBITS", _PC_FILESIZEBITS, PATHCONF },
2631 #endif
2632 #ifdef _PC_ALLOC_SIZE_MIN
2633  { "POSIX_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN, PATHCONF },
2634 #endif
2635 #ifdef _PC_REC_INCR_XFER_SIZE
2636  { "POSIX_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE, PATHCONF },
2637 #endif
2638 #ifdef _PC_REC_MAX_XFER_SIZE
2639  { "POSIX_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE, PATHCONF },
2640 #endif
2641 #ifdef _PC_REC_MIN_XFER_SIZE
2642  { "POSIX_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE, PATHCONF },
2643 #endif
2644 #ifdef _PC_REC_XFER_ALIGN
2645  { "POSIX_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN, PATHCONF },
2646 #endif
2647 #ifdef _PC_SYMLINK_MAX
2648  { "SYMLINK_MAX", _PC_SYMLINK_MAX, PATHCONF },
2649 #endif
2650 #ifdef _CS_GNU_LIBC_VERSION
2651  { "GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION, CONFSTR },
2652 #endif
2653 #ifdef _CS_GNU_LIBPTHREAD_VERSION
2654  { "GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION, CONFSTR },
2655 #endif
2656 #ifdef _PC_2_SYMLINKS
2657  { "POSIX2_SYMLINKS", _PC_2_SYMLINKS, PATHCONF },
2658 #endif
2659 
2660 #ifdef _SC_LEVEL1_ICACHE_SIZE
2661  { "LEVEL1_ICACHE_SIZE", _SC_LEVEL1_ICACHE_SIZE, SYSCONF },
2662 #endif
2663 #ifdef _SC_LEVEL1_ICACHE_ASSOC
2664  { "LEVEL1_ICACHE_ASSOC", _SC_LEVEL1_ICACHE_ASSOC, SYSCONF },
2665 #endif
2666 #ifdef _SC_LEVEL1_ICACHE_LINESIZE
2667  { "LEVEL1_ICACHE_LINESIZE", _SC_LEVEL1_ICACHE_LINESIZE, SYSCONF },
2668 #endif
2669 #ifdef _SC_LEVEL1_DCACHE_SIZE
2670  { "LEVEL1_DCACHE_SIZE", _SC_LEVEL1_DCACHE_SIZE, SYSCONF },
2671 #endif
2672 #ifdef _SC_LEVEL1_DCACHE_ASSOC
2673  { "LEVEL1_DCACHE_ASSOC", _SC_LEVEL1_DCACHE_ASSOC, SYSCONF },
2674 #endif
2675 #ifdef _SC_LEVEL1_DCACHE_LINESIZE
2676  { "LEVEL1_DCACHE_LINESIZE", _SC_LEVEL1_DCACHE_LINESIZE, SYSCONF },
2677 #endif
2678 #ifdef _SC_LEVEL2_CACHE_SIZE
2679  { "LEVEL2_CACHE_SIZE", _SC_LEVEL2_CACHE_SIZE, SYSCONF },
2680 #endif
2681 #ifdef _SC_LEVEL2_CACHE_ASSOC
2682  { "LEVEL2_CACHE_ASSOC", _SC_LEVEL2_CACHE_ASSOC, SYSCONF },
2683 #endif
2684 #ifdef _SC_LEVEL2_CACHE_LINESIZE
2685  { "LEVEL2_CACHE_LINESIZE", _SC_LEVEL2_CACHE_LINESIZE, SYSCONF },
2686 #endif
2687 #ifdef _SC_LEVEL3_CACHE_SIZE
2688  { "LEVEL3_CACHE_SIZE", _SC_LEVEL3_CACHE_SIZE, SYSCONF },
2689 #endif
2690 #ifdef _SC_LEVEL3_CACHE_ASSOC
2691  { "LEVEL3_CACHE_ASSOC", _SC_LEVEL3_CACHE_ASSOC, SYSCONF },
2692 #endif
2693 #ifdef _SC_LEVEL3_CACHE_LINESIZE
2694  { "LEVEL3_CACHE_LINESIZE", _SC_LEVEL3_CACHE_LINESIZE, SYSCONF },
2695 #endif
2696 #ifdef _SC_LEVEL4_CACHE_SIZE
2697  { "LEVEL4_CACHE_SIZE", _SC_LEVEL4_CACHE_SIZE, SYSCONF },
2698 #endif
2699 #ifdef _SC_LEVEL4_CACHE_ASSOC
2700  { "LEVEL4_CACHE_ASSOC", _SC_LEVEL4_CACHE_ASSOC, SYSCONF },
2701 #endif
2702 
2703 #ifdef _SC_IPV6
2704  { "IPV6", _SC_IPV6, SYSCONF },
2705 #endif
2706 #ifdef _SC_RAW_SOCKETS
2707  { "RAW_SOCKETS", _SC_RAW_SOCKETS, SYSCONF },
2708 #endif
2709 
2710  { NULL, 0, SYSCONF }
2711 };
2712 
2713 #define _GETCONF_PATH "/"
2714 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
2715 static const char *_getconf_path = NULL;
2716 
2717 int
2718 rpmdsGetconf(rpmds * dsp, const char *path)
2719  /*@globals _getconf_path @*/
2720  /*@modifies _getconf_path @*/
2721 {
2722  const struct _conf_s *c;
2723  size_t clen;
2724  long int value;
2725  const char * NS = "getconf";
2726  const char *N;
2727  char * EVR;
2728  char * t;
2729  evrFlags Flags;
2730 
2731 /*@-modobserver@*/
2732  if (_getconf_path == NULL) {
2733  _getconf_path = rpmExpand("%{?_rpmds__getconf_path}", NULL);
2734  /* XXX may need to validate path existence somewhen. */
2735  if (!(_getconf_path != NULL && *_getconf_path == '/')) {
2736 /*@-observertrans @*/
2737  _getconf_path = _free(_getconf_path);
2738 /*@=observertrans @*/
2739  _getconf_path = xstrdup(_GETCONF_PATH);
2740  }
2741  }
2742 /*@=modobserver@*/
2743 
2744  if (path == NULL)
2745  path = _getconf_path;
2746 
2747  for (c = vars; c->name != NULL; ++c) {
2748  N = c->name;
2749  EVR = NULL;
2750  switch (c->call) {
2751  case PATHCONF:
2752  value = pathconf(path, c->call_name);
2753  if (value != -1) {
2754  EVR = (char *) xmalloc(32);
2755  sprintf(EVR, "%ld", value);
2756  }
2757  /*@switchbreak@*/ break;
2758  case SYSCONF:
2759  value = sysconf(c->call_name);
2760  if (value == -1l) {
2761 #if defined(_SC_UINT_MAX) && defined(_SC_ULONG_MAX)
2762 /*@-unrecog@*/
2763  if (c->call_name == _SC_UINT_MAX
2764  || c->call_name == _SC_ULONG_MAX) {
2765  EVR = (char *) xmalloc(32);
2766  sprintf(EVR, "%lu", value);
2767  }
2768 /*@=unrecog@*/
2769 #endif
2770  } else {
2771  EVR = (char *) xmalloc(32);
2772  sprintf(EVR, "%ld", value);
2773  }
2774  /*@switchbreak@*/ break;
2775  case CONFSTR:
2776 #ifndef __CYGWIN__
2777  clen = confstr(c->call_name, (char *) NULL, 0);
2778  EVR = (char *) xmalloc(clen+1);
2779  *EVR = '\0';
2780  if (confstr (c->call_name, EVR, clen) != clen) {
2781  fprintf(stderr, "confstr: %s\n", strerror(errno));
2782  exit (EXIT_FAILURE);
2783  }
2784  EVR[clen] = '\0';
2785 #endif
2786  /*@switchbreak@*/ break;
2787  }
2788  if (EVR == NULL)
2789  continue;
2790 
2791  for (t = EVR; *t; t++) {
2792  if (*t == '\n') *t = ' ';
2793  }
2794  if (!strcmp(N, "GNU_LIBC_VERSION")
2795  || !strcmp(N, "GNU_LIBPTHREAD_VERSION"))
2796  {
2797  for (t = EVR; *t; t++) {
2798  if (*t == ' ') *t = '-';
2799  }
2800  }
2801 
2802  if (*EVR == '\0' || strchr(EVR, ' ') != NULL
2803  || (EVR[0] == '-' && strchr("0123456789", EVR[1]) == NULL))
2804  {
2805  EVR = _free(EVR);
2806  continue;
2807  }
2808 
2809  Flags = (evrFlags) (RPMSENSE_PROBE|RPMSENSE_EQUAL);
2810  rpmdsNSAdd(dsp, NS, N, EVR, Flags);
2811  EVR = _free(EVR);
2812  }
2813  return 0;
2814 }
2815 
2816 int rpmdsMergePRCO(void * context, rpmds ds)
2817 {
2818  rpmPRCO PRCO = (rpmPRCO) context;
2819  int rc = -1;
2820 
2821 /*@-modfilesys@*/
2822 if (_rpmds_debug < 0)
2823 fprintf(stderr, "*** rpmdsMergePRCO(%p, %p) %s\n", context, ds, rpmdsTagName(rpmdsTagN(ds)));
2824 /*@=modfilesys@*/
2825  switch(rpmdsTagN(ds)) {
2826  default:
2827  break;
2828  case RPMTAG_PROVIDENAME:
2829  rc = rpmdsMerge(PRCO->Pdsp, ds);
2830  break;
2831  case RPMTAG_REQUIRENAME:
2832  rc = rpmdsMerge(PRCO->Rdsp, ds);
2833  break;
2834  case RPMTAG_CONFLICTNAME:
2835  rc = rpmdsMerge(PRCO->Cdsp, ds);
2836  break;
2837  case RPMTAG_OBSOLETENAME:
2838  rc = rpmdsMerge(PRCO->Odsp, ds);
2839  break;
2840  case RPMTAG_TRIGGERNAME:
2841  rc = rpmdsMerge(PRCO->Tdsp, ds);
2842  break;
2843  case RPMTAG_DIRNAMES:
2844  rc = rpmdsMerge(PRCO->Ddsp, ds);
2845  break;
2846  case RPMTAG_FILELINKTOS:
2847  rc = rpmdsMerge(PRCO->Ldsp, ds);
2848  break;
2849  }
2850  return rc;
2851 }
2852 
2854 {
2855  if (PRCO) {
2856  (void)rpmdsFree(PRCO->my);
2857  PRCO->my = NULL;
2858  (void)rpmdsFree(PRCO->P);
2859  PRCO->P = NULL;
2860  (void)rpmdsFree(PRCO->R);
2861  PRCO->R = NULL;
2862  (void)rpmdsFree(PRCO->C);
2863  PRCO->C = NULL;
2864  (void)rpmdsFree(PRCO->O);
2865  PRCO->O = NULL;
2866  (void)rpmdsFree(PRCO->T);
2867  PRCO->T = NULL;
2868  (void)rpmdsFree(PRCO->D);
2869  PRCO->D = NULL;
2870  (void)rpmdsFree(PRCO->L);
2871  PRCO->L = NULL;
2872  memset(PRCO, 0, sizeof(*PRCO));
2873  PRCO = _free(PRCO);
2874  }
2875  return NULL;
2876 }
2877 
2879 {
2880  rpmPRCO PRCO = (rpmPRCO) xcalloc(1, sizeof(*PRCO));
2881 
2882  if (h != NULL) {
2883  static int scareMem = 0;
2884  PRCO->my = rpmdsNew(h, RPMTAG_NAME, scareMem);
2885  PRCO->P = rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem);
2886  PRCO->R = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
2887  PRCO->C = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
2888  PRCO->O = rpmdsNew(h, RPMTAG_OBSOLETENAME, scareMem);
2889  PRCO->T = rpmdsNew(h, RPMTAG_TRIGGERNAME, scareMem);
2890  PRCO->D = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem);
2891  PRCO->L = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem);
2892  }
2893  PRCO->Pdsp = &PRCO->P;
2894  PRCO->Rdsp = &PRCO->R;
2895  PRCO->Cdsp = &PRCO->C;
2896  PRCO->Odsp = &PRCO->O;
2897  PRCO->Tdsp = &PRCO->T;
2898  PRCO->Ddsp = &PRCO->D;
2899  PRCO->Ldsp = &PRCO->L;
2900  return PRCO;
2901 }
2902 
2904 {
2905  /*@-compdef -refcounttrans -retalias -retexpose -usereleased @*/
2906  if (PRCO != NULL)
2907  switch (tagN) {
2908  default: break;
2909  case RPMTAG_NAME: return PRCO->my; /*@notreached@*/ break;
2910  case RPMTAG_PROVIDENAME: return *PRCO->Pdsp; /*@notreached@*/ break;
2911  case RPMTAG_REQUIRENAME: return *PRCO->Rdsp; /*@notreached@*/ break;
2912  case RPMTAG_CONFLICTNAME: return *PRCO->Cdsp; /*@notreached@*/ break;
2913  case RPMTAG_OBSOLETENAME: return *PRCO->Odsp; /*@notreached@*/ break;
2914  case RPMTAG_TRIGGERNAME: return *PRCO->Tdsp; /*@notreached@*/ break;
2915  case RPMTAG_DIRNAMES: return *PRCO->Ddsp; /*@notreached@*/ break;
2916  case RPMTAG_FILELINKTOS: return *PRCO->Ldsp; /*@notreached@*/ break;
2917  }
2918  return NULL;
2919  /*@=compdef =refcounttrans =retalias =retexpose =usereleased @*/
2920 }
2921 
2928 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF) && !defined(__FreeBSD__)
2929 #if defined(RPM_VENDOR_MANDRIVA)
2930 static char * sonameDep(/*@returned@*/ char * t, const char * s, int isElf64, int devel, int uClibc)
2931  /*@modifies t @*/
2932 {
2933  char *tmp = t;
2934  *t = '\0';
2935  if (uClibc)
2936  tmp = stpcpy(tmp, "uClibc(");
2937  if (devel) {
2938  tmp = stpcpy(tmp, "devel(");
2939  }
2940 #if !defined(__alpha__) && !defined(__sun)
2941  if (isElf64) {
2942  /* XXX: eehhk, would've been nice with consistency, mandriva legacy... :| */
2943  if (!devel && s[strlen(s)-1] != ')')
2944  tmp = stpcpy( stpcpy(tmp, s), "()(64bit)");
2945  else {
2946  tmp = stpcpy(tmp, s);
2947  if (devel)
2948  tmp = strstr(t, ".so");
2949  tmp = stpcpy(tmp, "(64bit)");
2950  }
2951  }else
2952 #endif
2953  tmp = stpcpy(tmp, s);
2954  if (devel) {
2955  char *suffix = strstr(t, ".so");
2956  if (suffix)
2957  tmp = suffix;
2958  tmp = stpcpy(tmp, ")");
2959  }
2960  if (uClibc)
2961  tmp = stpcpy(tmp, ")");
2962 
2963  return t;
2964 }
2965 
2966 static char *find_elf_interpreter(GElf_Ehdr *ehdr, Elf *elf, char *filename, char *prev)
2967 {
2968  FILE *fp = NULL;
2969  struct stat statbuf;
2970  GElf_Ehdr ehdr_mem;
2971  GElf_Shdr shdr_mem, *shdr;
2972  GElf_Phdr phdr_mem, *phdr;
2973  GElf_Dyn dyn_mem, *dyn;
2974  Elf_Data * data;
2975  Elf_Scn *scn = NULL;
2976  int fdno;
2977  char *interp_name = NULL;
2978  char *libpath = NULL;
2979  int cnt;
2980  int class;
2981  size_t shstrndx;
2982 
2983  if (filename) {
2984  if (!*filename)
2985  return NULL;
2986  if (!(fp = fopen(filename, "r"))) {
2987  perror(filename);
2988  return NULL;
2989  }
2990  if (fstat((fdno = fileno(fp)), &statbuf) < 0) {
2991  perror(filename);
2992  goto end;
2993  }
2994  if ((size_t) statbuf.st_size < sizeof(Elf64_Ehdr) || !S_ISREG(statbuf.st_mode))
2995  goto foo;
2996 
2997  (void) elf_version(EV_CURRENT);
2998  elf = NULL;
2999  if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
3000  || elf_kind(elf) != ELF_K_ELF
3001  || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
3002  || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
3003  goto end;
3004  }
3005 foo:
3006 
3007  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
3008  fprintf(stderr, "%s: not a dynamic executable\n", filename);
3009  goto end;
3010  }
3011  class = gelf_getclass(elf);
3012 
3013  for (cnt = 0; cnt < ehdr->e_phnum; cnt++) {
3014  phdr = gelf_getphdr (elf, cnt, &phdr_mem);
3015  if (phdr->p_type == PT_INTERP)
3016  break;
3017  phdr = NULL;
3018  }
3019  if (phdr) {
3020  Elf_Data *data = NULL;
3021 
3022  scn = gelf_offscn (elf, phdr->p_offset);
3023  shdr = gelf_getshdr(scn, &shdr_mem);
3024  data = elf_getdata (scn, data);
3025  if (data && data->d_buf) {
3026  interp_name = strdup(data->d_buf);
3027  goto end;
3028  }
3029  /* no 'data' most likely implies that this is an elf interpreter itself */
3030  }
3031 
3032  if (elf_getshdrstrndx (elf, &shstrndx) >= 0)
3033  while ((scn = elf_nextscn(elf, scn)) != NULL) {
3034  shdr = gelf_getshdr(scn, &shdr_mem);
3035  if (shdr->sh_type == SHT_DYNAMIC) {
3036  char *rpath = NULL;
3037  for (cnt = 0; cnt < ehdr->e_phnum; cnt++) {
3038  phdr = gelf_getphdr (elf, cnt, &phdr_mem);
3039  if (phdr->p_type == PT_LOAD)
3040  break;
3041  }
3042 
3043  data = NULL;
3044  while ((data = elf_getdata (scn, data)) != NULL) {
3045  int dynsize = (int)(shdr->sh_size / shdr->sh_entsize)-1;
3046  for (cnt = dynsize; cnt >= 0; --cnt) {
3047  dyn = gelf_getdyn (data, cnt, &dyn_mem);
3048 
3049  if (dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH) {
3050  rpath = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
3051  break;
3052  }
3053  }
3054  for (cnt = 0; cnt <= dynsize; ++cnt) {
3055  dyn = gelf_getdyn (data, cnt, &dyn_mem);
3056 
3057  /* if this an elf interpeter, the only thing we want is to find SONAME
3058  * and return it
3059  */
3060  if (phdr && dyn->d_tag == DT_SONAME) {
3061  interp_name = strdup(elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val));
3062  goto end;
3063  }
3064  if (dyn->d_tag == DT_NEEDED) {
3065  char *tmp, *tmp2;
3066  /* XXX: we multiply by 4 to make sure to have room for several paths */
3067  char buf[4*MAXPATHLEN] = "";
3068  char path[4*MAXPATHLEN];
3069  char *buildroot;
3070 
3071  libpath = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
3072  if (prev && *prev && libpath && !strcmp(basename(prev), libpath))
3073  libpath = NULL;
3074 
3075  if (!libpath || !strlen(libpath))
3076  continue;
3077 
3078  tmp = libpath;
3079  while (*tmp) {
3080  if (*tmp == '/')
3081  libpath = tmp + 1;
3082  tmp++;
3083  }
3084 
3085  /* If this is a fully resolved name, we don't need to modify the path */
3086  if (stat(libpath, &statbuf) == 0)
3087  continue;
3088 
3089  tmp2 = buf;
3090  if (rpath && *rpath) {
3091  tmp2 = stpcpy(buf, rpath);
3092  }
3093  tmp = getenv("LD_LIBRARY_PATH");
3094  if (tmp)
3095  tmp2 = stpcpy(tmp2, tmp);
3096  if ((rpath && *rpath) || tmp)
3097  tmp2 = stpcpy(tmp2, ":");
3098  /* XXX: do better check to ensure libraries are all of the same class */
3099  tmp2 = stpcpy(tmp2, (class == ELFCLASS64) ? "/lib64:/usr/lib64" : "/lib:/usr/lib");
3100  /* we need to search through library paths within buildroot as well */
3101  buildroot = rpmExpand("%{buildroot}", NULL);
3102  if (stat(buildroot, &statbuf) == 0) {
3103  char *tmp3;
3104  for (tmp2 = buf, tmp = path;
3105  tmp2 != NULL;
3106  tmp2 = tmp3) {
3107  tmp = stpcpy(tmp, buildroot);
3108  tmp3 = strchr(tmp2, ':');
3109  if (tmp3)
3110  *tmp3 = '\0';
3111  tmp = stpcpy(tmp, tmp2);
3112  tmp = stpcpy(tmp, ":");
3113  if (tmp3) {
3114  *tmp3 = ':';
3115  tmp3++;
3116  }
3117  }
3118  } else
3119  tmp = path;
3120  _free(buildroot);
3121  stpcpy(tmp, buf);
3122  tmp = buf;
3123  {
3124  int i, count = 1;
3125  char *path_n;
3126 
3127  /* Eliminate all double //s */
3128  path_n = path;
3129  while ((path_n = strstr(path_n, "//"))) {
3130  i = strlen(path_n);
3131  memmove(path_n, path_n + 1, i - 1);
3132  *(path_n + i - 1) = '\0';
3133  }
3134 
3135  /* Replace colons with zeros in path_list and count them */
3136  for (i = strlen(path); i > 0; i--) {
3137  if (path[i] == ':') {
3138  path[i] = 0;
3139  count++;
3140  }
3141  }
3142  path_n = path;
3143  for (i = 0; i < count; i++) {
3144  strcpy(tmp, path_n);
3145  strcat(tmp, "/");
3146  strcat(tmp, libpath);
3147 
3148  if (stat(tmp, &statbuf) == 0 && statbuf.st_mode & S_IRUSR) {
3149  path[0] = '\0';
3150  break;
3151  }
3152  path_n += (strlen(path_n) + 1);
3153  }
3154  if(path[0])
3155  *tmp = '\0';
3156  }
3157  libpath = buf;
3158  break;
3159  }
3160  }
3161  }
3162  }
3163  }
3164 
3165 end:
3166  if (fp) {
3167  if (elf) (void) elf_end(elf);
3168  fclose(fp);
3169  }
3170  if (!interp_name && libpath)
3171  return find_elf_interpreter(NULL, NULL, libpath, filename);
3172  return interp_name;
3173 }
3174 
3175 static int checkuClibc(GElf_Ehdr *ehdr, Elf *elf) {
3176  int ret = 0;
3177  char *interp = find_elf_interpreter(ehdr, elf, NULL, NULL);
3178 
3179  if (interp) {
3180  char *tmp = basename(interp);
3181  if (tmp[0] == 'l' && tmp[1] == 'd') {
3182  tmp += ((tmp[2] == '3' && tmp[3] == '2') ||
3183  (tmp[2] == '6' && tmp[3] == '4')) ?
3184  5 : 3;
3185  if (!strncasecmp(tmp, "uClibc.so", sizeof("uClibc.so")-1))
3186  ret = 1;
3187  }
3188  free(interp);
3189  }
3190  return ret;
3191 }
3192 #else
3193 static char * sonameDep(/*@returned@*/ char * t, const char * s, int isElf64, int devel, int uClibc)
3194  /*@modifies t @*/
3195 {
3196  *t = '\0';
3197 #if !defined(__alpha__) && !defined(__sun)
3198  if (isElf64) {
3199  if (s[strlen(s)-1] != ')')
3200  (void) stpcpy( stpcpy(t, s), "()(64bit)");
3201  else
3202  (void) stpcpy( stpcpy(t, s), "(64bit)");
3203  }else
3204 #endif
3205  (void) stpcpy(t, s);
3206  return t;
3207 }
3208 #endif
3209 #endif
3210 
3211 /*@-moduncon -noeffectuncon @*/
3212 int rpmdsELF(const char * fn, int flags,
3213  int (*add) (void * context, rpmds ds), void * context)
3214 {
3215 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF) && !defined(__FreeBSD__)
3216  Elf * elf;
3217  Elf_Scn * scn;
3218  Elf_Data * data;
3219  GElf_Ehdr ehdr_mem, * ehdr;
3220  GElf_Shdr shdr_mem, * shdr;
3221  GElf_Verdef def_mem, * def;
3222  GElf_Verneed need_mem, * need;
3223  GElf_Dyn dyn_mem, * dyn;
3224  unsigned int auxoffset;
3225  unsigned int offset;
3226  int fdno;
3227  int cnt2;
3228  int cnt;
3229  char buf[BUFSIZ];
3230  const char * s;
3231  int is_executable;
3232  const char * soname = NULL;
3233  rpmds ds;
3234  char * t;
3235  int xx;
3236  int isElf64;
3237  int isDSO;
3238  int isuClibc;
3239  int gotSONAME = 0;
3240  int gotDEBUG = 0;
3241  int gotHASH = 0;
3242  int gotGNUHASH = 0;
3243  int skipP = (flags & RPMELF_FLAG_SKIPPROVIDES);
3244  int skipR = (flags & RPMELF_FLAG_SKIPREQUIRES);
3245  static int filter_GLIBC_PRIVATE = 0;
3246  static int oneshot = 0;
3247 
3248 /*@-castfcnptr@*/
3249 if (_rpmds_debug < 0)
3250 fprintf(stderr, "*** rpmdsELF(%s, %d, %p, %p)\n", fn, flags, (void *)add, context);
3251 /*@=castfcnptr@*/
3252  if (oneshot == 0) {
3253  oneshot = 1;
3254  filter_GLIBC_PRIVATE = rpmExpandNumeric("%{?_filter_GLIBC_PRIVATE}");
3255  }
3256 
3257  /* Extract dependencies only from files with executable bit set. */
3258  { struct stat sb, * st = &sb;
3259  if (stat(fn, st) != 0)
3260  return -1;
3261  is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
3262  }
3263 
3264  fdno = open(fn, O_RDONLY);
3265  if (fdno < 0)
3266  return fdno;
3267 
3268  (void) elf_version(EV_CURRENT);
3269 
3270 /*@-evalorder@*/
3271  elf = NULL;
3272  if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
3273  || elf_kind(elf) != ELF_K_ELF
3274  || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
3275  || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
3276  goto exit;
3277 /*@=evalorder@*/
3278 
3279  isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
3280  isDSO = ehdr->e_type == ET_DYN;
3281 #if defined(RPM_VENDOR_MANDRIVA)
3282  isuClibc = checkuClibc(ehdr, elf);
3283 #else
3284  isuClibc = 0;
3285 #endif
3286 
3287  /*@-uniondef @*/
3288  scn = NULL;
3289  while ((scn = elf_nextscn(elf, scn)) != NULL) {
3290  shdr = gelf_getshdr(scn, &shdr_mem);
3291  if (shdr == NULL)
3292  break;
3293 
3294  soname = _free(soname);
3295  switch (shdr->sh_type) {
3296  default:
3297  continue;
3298  /*@notreached@*/ /*@switchbreak@*/ break;
3299  case SHT_NOTE:
3300 #if defined(HAVE_GELF_GETNOTE) /* XXX OpenIndiana & older elfutils haven't. */
3301  if (!(shdr->sh_flags & SHF_ALLOC))
3302  continue;
3303  data = NULL;
3304  while ((data = elf_getdata(scn, data)) != NULL) {
3305  GElf_Nhdr nhdr;
3306  size_t name_offset;
3307  size_t desc_offset;
3308  offset = 0;
3309  while (offset < data->d_size
3310  && (offset = gelf_getnote(data, offset,
3311  &nhdr, &name_offset, &desc_offset)) > 0)
3312  {
3313  const char *name = ((char *)data->d_buf) + name_offset;
3314  const char *desc = ((char *)data->d_buf) + desc_offset;
3315  if (memchr(name, '\0', nhdr.n_namesz) == NULL)
3316  /*@innercontinue@*/ continue;
3317  switch (nhdr.n_type) {
3318  default: /*@innercontinue@*/ continue;
3319 #if !defined(NT_GNU_BUILD_ID)
3320 #define NT_GNU_BUILD_ID 3
3321 #endif
3322  case NT_GNU_BUILD_ID:
3323  if (strcmp(name, "GNU") == 0 && nhdr.n_descsz > 0) {
3324  static const char hex[] = "0123456789abcdef";
3325  static evrFlags _Flags = (evrFlags)
3326  (RPMSENSE_EQUAL|RPMSENSE_FIND_PROVIDES);
3327  size_t i;
3328  buf[0] = '\0';
3329  t = buf;
3330  for (i = 0; i < nhdr.n_descsz; ++i) {
3331  *t++ = hex[ (((unsigned)desc[i] >> 4) & 0x0f) ];
3332  *t++ = hex[ (((unsigned)desc[i] ) & 0x0f) ];
3333  }
3334  *t = '\0';
3335  /* Add next buildid. */
3336  ds = rpmdsSingle(RPMTAG_PROVIDES, "elf(buildid)",
3337  buf, _Flags);
3338  xx = add(context, ds);
3339  (void)rpmdsFree(ds);
3340  ds = NULL;
3341  }
3342  /*@switchbreak@*/ break;
3343  }
3344  }
3345  }
3346 #endif /* defined(HAVE_GELF_GETNOTE) */
3347  /*@switchbreak@*/ break;
3348  case SHT_GNU_verdef:
3349  data = NULL;
3350  if (!skipP)
3351  while ((data = elf_getdata (scn, data)) != NULL) {
3352  offset = 0;
3353  for (cnt = (int)shdr->sh_info; --cnt >= 0; ) {
3354 
3355  def = gelf_getverdef (data, offset, &def_mem);
3356  if (def == NULL)
3357  /*@innerbreak@*/ break;
3358  auxoffset = (unsigned)(offset + def->vd_aux);
3359  for (cnt2 = (int)def->vd_cnt; --cnt2 >= 0; ) {
3360  GElf_Verdaux aux_mem, * aux;
3361 
3362  aux = gelf_getverdaux (data, auxoffset, &aux_mem);
3363  if (aux == NULL)
3364  /*@innerbreak@*/ break;
3365 
3366  s = elf_strptr(elf, shdr->sh_link, aux->vda_name);
3367  if (s == NULL)
3368  /*@innerbreak@*/ break;
3369 
3370  if (def->vd_flags & VER_FLG_BASE) {
3371  soname = _free(soname);
3372  soname = xstrdup(s);
3373  } else
3374  if (soname != NULL
3375  && !(filter_GLIBC_PRIVATE != 0
3376  && !strcmp(s, "GLIBC_PRIVATE")))
3377  {
3378  buf[0] = '\0';
3379  t = buf;
3380  t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
3381 
3382  t++; /* XXX "foo(bar)" already in buf. */
3383 
3384  /* Add next provide dependency. */
3386  sonameDep(t, buf, isElf64, 0, isuClibc),
3387  "", RPMSENSE_FIND_PROVIDES);
3388  xx = add(context, ds);
3389  (void)rpmdsFree(ds);
3390  ds = NULL;
3391  }
3392  auxoffset += aux->vda_next;
3393  }
3394  offset += def->vd_next;
3395  }
3396  }
3397  /*@switchbreak@*/ break;
3398  case SHT_GNU_verneed:
3399  data = NULL;
3400  /* Only from files with executable bit set. */
3401  if (!skipR && is_executable)
3402  while ((data = elf_getdata (scn, data)) != NULL) {
3403  offset = 0;
3404  for (cnt = (int)shdr->sh_info; --cnt >= 0; ) {
3405  need = gelf_getverneed (data, offset, &need_mem);
3406  if (need == NULL)
3407  /*@innerbreak@*/ break;
3408 
3409  s = elf_strptr(elf, shdr->sh_link, need->vn_file);
3410  if (s == NULL)
3411  /*@innerbreak@*/ break;
3412  soname = _free(soname);
3413  soname = xstrdup(s);
3414  auxoffset = (unsigned)(offset + need->vn_aux);
3415  for (cnt2 = (int)need->vn_cnt; --cnt2 >= 0; ) {
3416  GElf_Vernaux aux_mem, * aux;
3417 
3418  aux = gelf_getvernaux (data, auxoffset, &aux_mem);
3419  if (aux == NULL)
3420  /*@innerbreak@*/ break;
3421 
3422  s = elf_strptr(elf, shdr->sh_link, aux->vna_name);
3423  if (s == NULL)
3424  /*@innerbreak@*/ break;
3425 
3426  /* Filter dependencies that contain GLIBC_PRIVATE */
3427  if (soname != NULL
3428  && !(filter_GLIBC_PRIVATE != 0
3429  && !strcmp(s, "GLIBC_PRIVATE")))
3430  {
3431  buf[0] = '\0';
3432  t = buf;
3433  t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
3434 
3435  t++; /* XXX "foo(bar)" already in buf. */
3436 
3437  /* Add next require dependency. */
3439  sonameDep(t, buf, isElf64, 0, isuClibc),
3440  "", RPMSENSE_FIND_REQUIRES);
3441  xx = add(context, ds);
3442  (void)rpmdsFree(ds);
3443  ds = NULL;
3444  }
3445  auxoffset += aux->vna_next;
3446  }
3447  offset += need->vn_next;
3448  }
3449  }
3450  /*@switchbreak@*/ break;
3451  case SHT_DYNAMIC:
3452  data = NULL;
3453  while ((data = elf_getdata (scn, data)) != NULL) {
3454  for (cnt = 0; cnt < (int)(shdr->sh_size / shdr->sh_entsize); ++cnt) {
3455  dyn = gelf_getdyn (data, cnt, &dyn_mem);
3456  if (dyn == NULL)
3457  /*@innerbreak@*/ break;
3458  s = NULL;
3459  switch (dyn->d_tag) {
3460  default:
3461  /*@innercontinue@*/ continue;
3462  /*@notreached@*/ /*@switchbreak@*/ break;
3463  case DT_HASH:
3464  gotHASH= 1;
3465  /*@innercontinue@*/ continue;
3466  case DT_GNU_HASH:
3467  gotGNUHASH= 1;
3468  /*@innercontinue@*/ continue;
3469  case DT_DEBUG:
3470  gotDEBUG = 1;
3471  /*@innercontinue@*/ continue;
3472  case DT_NEEDED:
3473  /* Only from files with executable bit set. */
3474  if (skipR || !is_executable)
3475  /*@innercontinue@*/ continue;
3476  /* Add next require dependency. */
3477  s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
3478 assert(s != NULL);
3479  buf[0] = '\0';
3481  sonameDep(buf, s, isElf64, 0, isuClibc),
3482  "", RPMSENSE_FIND_REQUIRES);
3483  xx = add(context, ds);
3484  (void)rpmdsFree(ds);
3485  ds = NULL;
3486  /*@switchbreak@*/ break;
3487  case DT_SONAME:
3488  gotSONAME = 1;
3489  if (skipP)
3490  /*@innercontinue@*/ continue;
3491  s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
3492 assert(s != NULL);
3493  /* Add next provide dependency. */
3494  buf[0] = '\0';
3496  sonameDep(buf, s, isElf64, 0, isuClibc),
3497  "", RPMSENSE_FIND_PROVIDES);
3498  xx = add(context, ds);
3499  (void)rpmdsFree(ds);
3500  ds = NULL;
3501  /*@switchbreak@*/ break;
3502  }
3503  }
3504  }
3505  /*@switchbreak@*/ break;
3506  }
3507  }
3508  /*@=uniondef @*/
3509 
3510 #if !defined(RPM_VENDOR_MANDRIVA)
3511  /* For DSOs which use the .gnu_hash section and don't have a .hash
3512  * section, we need to ensure that we have a new enough glibc. */
3513  if (gotGNUHASH && !gotHASH) {
3514  ds = rpmdsSingle(RPMTAG_REQUIRENAME, "rtld(GNU_HASH)", "",
3515  RPMSENSE_FIND_REQUIRES);
3516  xx = add(context, ds);
3517  (void)rpmdsFree(ds);
3518  ds = NULL;
3519  }
3520 #endif
3521 
3522  /* For DSO's, provide the basename of the file if DT_SONAME not found. */
3523  if (!skipP && isDSO && !gotDEBUG && !gotSONAME) {
3524  s = strrchr(fn, '/');
3525  if (s != NULL)
3526  s++;
3527  else
3528  s = fn;
3529 assert(s != NULL);
3530 
3531  /* Add next provide dependency. */
3532  buf[0] = '\0';
3534  sonameDep(buf, s, isElf64, 0, isuClibc), "", RPMSENSE_FIND_PROVIDES);
3535  xx = add(context, ds);
3536  (void)rpmdsFree(ds);
3537  ds = NULL;
3538  }
3539 
3540 exit:
3541  soname = _free(soname);
3542  if (elf) (void) elf_end(elf);
3543  if (fdno > 0)
3544  xx = close(fdno);
3545  return 0;
3546 #else
3547  return -1;
3548 #endif
3549 }
3550 /*@=moduncon =noeffectuncon @*/
3551 
3552 
3553 #if defined(RPM_VENDOR_MANDRIVA)
3554 
3563 int rpmdsSymlink(const char * fn, int flags,
3564  int (*add) (void * context, rpmds ds), void * context)
3565  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
3566  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/;
3567 int rpmdsSymlink(const char * fn, int flags,
3568  int (*add) (void * context, rpmds ds), void * context)
3569 {
3570 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF) && !defined(__FreeBSD__)
3571  Elf * elf;
3572  Elf_Scn * scn;
3573  Elf_Data * data;
3574  GElf_Ehdr ehdr_mem, * ehdr;
3575  GElf_Shdr shdr_mem, * shdr;
3576  GElf_Dyn dyn_mem, * dyn;
3577  int fdno;
3578  int cnt;
3579  int i;
3580  char buf[BUFSIZ];
3581  const char * s, * bn;
3582  int is_executable;
3583  int is_symlink;
3584  const char * soname = NULL;
3585  rpmds ds;
3586  int xx = -1;
3587  int isElf64;
3588  int isuClibc;
3589  int gotSONAME = 0;
3590  int skipP = (flags & RPMELF_FLAG_SKIPPROVIDES);
3591  int skipR = (flags & RPMELF_FLAG_SKIPREQUIRES);
3592  int lnklen;
3593  char path[MAXPATHLEN];
3594  /*
3595  * We filter out these as they come with glibc, making dependencies on
3596  * them rather redundant.
3597  */
3598  const char *filterRequires[] = {"ld-linux", "ld64-linux" "libBrokenLocale.so",
3599  "libanl.so", "libc.so", "libcidn.so", "libcrypt.so", "libdl.so", "libm.so",
3600  "libnsl.so", "libnss_compat.so", "libnss_dns.so", "libnss_files.so",
3601  "libnss_hesiod.so", "libnss_nis.so", "libnss_nisplus.so", "libpthread.so",
3602  "libresolv.so", "librt.so", "libutil.so", "libthread_db.so"};
3603  ARGV_t deps = NULL;
3604  miRE mire;
3605 
3606  bn = basename((char*)fn);
3608  if (!mireRegcomp(mire, "^lib.*\\.so$"))
3609  xx = mireRegexec(mire, bn, (size_t) 0);
3610  mire = mireFree(mire);
3611  if (xx < 0)
3612  return 0;
3613 
3615  /* Filename must end with ".so" to be devel(...) dependency. */
3616  if (!mireRegcomp(mire, "^.*/(usr/)?lib(64)?/lib.*\\.so$"))
3617  xx = mireRegexec(mire, fn, (size_t) 0);
3618  mire = mireFree(mire);
3619  /* if outside of standard library dirs, we refuse to generate requires */
3620  if (xx < 0)
3621  skipR = 1;
3622 
3623 /*@-castfcnptr@*/
3624 if (_rpmds_debug < 0)
3625 fprintf(stderr, "*** rpmdsELF(%s, %d, %p, %p)\n", fn, flags, (void *)add, context);
3626 /*@=castfcnptr@*/
3627 
3628  /* Extract dependencies only from files with executable bit set. */
3629  { struct stat sb, * st = &sb;
3630  if (lstat(fn, st) != 0)
3631  return -1;
3632  is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
3633  is_symlink = S_ISLNK(st->st_mode);
3634  }
3635 
3636  if (is_symlink) {
3637  const char *bn;
3638  if ((lnklen = readlink(fn, path, MAXPATHLEN - 1)) == -1) {
3639  warn("%s", fn);
3640  return -1;
3641  }
3642  /* XXX: unused, path should expand to absolute path... */
3643  path[lnklen] = '\0';
3644 
3645  /* if filename of library linked to isn't consistent with symlink
3646  * filename, then we skip it
3647  */
3648  bn = basename((char*)fn);
3649  if (strncmp(bn, basename(path), (size_t)(strstr(bn, ".so") - bn)))
3650  return 0;
3651  } else {
3652  FILE *fp = fopen(fn, "r");
3653  char buf[BUFSIZ];
3654  char *in;
3655  stpcpy(path, fn);
3656  fn = NULL;
3657  if (fp == NULL || ferror(fp)) {
3658  if (fp) (void) fclose(fp);
3659  return -1;
3660  }
3661  /* try resolve ld scripts
3662  * certainly *not* state of the art, but should in practice work
3663  * everywhere where relevant...
3664  */
3665  while ((in = fgets(buf, sizeof(buf) - 1, fp))) {
3666  in[sizeof(buf)-1] = '\0';
3667  if ((in = strstr(in, "GROUP")) &&
3668  (in = strchr(in, '(')) &&
3669  (fn = strchr(in, '/')) &&
3670  (in = strchr(fn, ' '))) {
3671  *in = '\0';
3672  break;
3673  }
3674  if (ferror(fp) || feof(fp))
3675  break;
3676  }
3677  fclose(fp);
3678  if (!fn)
3679  return -1;
3680  else {
3681  /* XXX: try determine relative root */
3682  struct stat sb, * st = &sb;
3683 
3684  while((in = strrchr(path, '/'))) {
3685  stpcpy(in, fn);
3686  if (stat(path, st) == 0) {
3687  fn = path;
3688  break;
3689  }
3690  *in = 0;
3691  }
3692  if (!fn)
3693  return -1;
3694  }
3695  }
3696 
3697  fdno = open(fn, O_RDONLY);
3698  if (fdno < 0)
3699  return fdno;
3700 
3701  (void) elf_version(EV_CURRENT);
3702 
3703 /*@-evalorder@*/
3704  elf = NULL;
3705  if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
3706  || elf_kind(elf) != ELF_K_ELF
3707  || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
3708  || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
3709  goto exit;
3710 /*@=evalorder@*/
3711 
3712  isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
3713 #if defined(RPM_VENDOR_MANDRIVA)
3714  isuClibc = checkuClibc(ehdr, elf);
3715 #else
3716  isuClibc = 0;
3717 #endif
3718 
3719  /*@-uniondef @*/
3720  scn = NULL;
3721  while ((scn = elf_nextscn(elf, scn)) != NULL) {
3722  shdr = gelf_getshdr(scn, &shdr_mem);
3723  if (shdr == NULL)
3724  break;
3725 
3726  soname = _free(soname);
3727  switch (shdr->sh_type) {
3728  default:
3729  continue;
3730  /*@notreached@*/ /*@switchbreak@*/ break;
3731  case SHT_DYNAMIC:
3732  data = NULL;
3733  while ((data = elf_getdata (scn, data)) != NULL) {
3734  for (cnt = 0; cnt < (int)(shdr->sh_size / shdr->sh_entsize); ++cnt) {
3735  dyn = gelf_getdyn (data, cnt, &dyn_mem);
3736  if (dyn == NULL)
3737  /*@innerbreak@*/ break;
3738  s = NULL;
3739  switch (dyn->d_tag) {
3740  default:
3741  /*@innercontinue@*/ continue;
3742  /*@notreached@*/ /*@switchbreak@*/ break;
3743  case DT_NEEDED:
3744  /* Only from files with executable bit set. */
3745  if (skipR || !is_executable)
3746  /*@innercontinue@*/ continue;
3747  /* Add next require dependency. */
3748  s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
3749 assert(s != NULL);
3750  buf[0] = '\0';
3751 
3752  for (i = 0; i < (int)(sizeof(filterRequires)/sizeof(filterRequires[0])); i++)
3753  if (!strncmp(s, filterRequires[i], strlen(filterRequires[i])) && !isuClibc)
3754  break;
3755 
3756  if (sizeof(filterRequires)/sizeof(filterRequires[0]) == i)
3757  argvAdd(&deps, s);
3758  /*@switchbreak@*/ break;
3759  case DT_SONAME:
3760  gotSONAME = 1;
3761  s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
3762 assert(s != NULL);
3763  /* Add next provide dependency. */
3764  buf[0] = '\0';
3765 
3766  if (!skipP) {
3768  sonameDep(buf, s, isElf64, 1, isuClibc),
3769  "", RPMSENSE_FIND_PROVIDES);
3770  xx = add(context, ds);
3771  (void)rpmdsFree(ds);
3772  ds = NULL;
3773  }
3774  /*@switchbreak@*/ break;
3775  }
3776  }
3777  }
3778  /*@switchbreak@*/ break;
3779  }
3780  }
3781  /*@=uniondef @*/
3782 
3783 exit:
3784  if (gotSONAME && !skipR) {
3785  for (i = 0, cnt = argvCount(deps); i < cnt; i++) {
3786  if (deps[i][0] == 'l' && deps[i][1] == 'd')
3787  continue;
3789  sonameDep(buf, deps[i], isElf64, 1, isuClibc),
3790  "", RPMSENSE_FIND_REQUIRES);
3791  xx = add(context, ds);
3792  (void)rpmdsFree(ds);
3793  ds = NULL;
3794  }
3795  }
3796 
3797  deps = argvFree(deps);
3798  if (elf) (void) elf_end(elf);
3799  if (fdno > 0)
3800  xx = close(fdno);
3801  return 0;
3802 #else
3803  return -1;
3804 #endif
3805 }
3806 #endif /* RPM_VENDOR_MANDRIVA */
3807 
3808 #define _SBIN_LDCONFIG_P "/sbin/ldconfig -p"
3809 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3810 static const char * _ldconfig_cmd = _SBIN_LDCONFIG_P;
3811 
3812 #define _LD_SO_CACHE "/etc/ld.so.cache"
3813 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3814 static const char * _ldconfig_cache = NULL;
3815 
3816 int rpmdsLdconfig(rpmPRCO PRCO, const char * fn)
3817  /*@globals _ldconfig_cmd, _ldconfig_cache @*/
3818  /*@modifies _ldconfig_cmd, _ldconfig_cache @*/
3819 {
3820  char buf[BUFSIZ];
3821  const char *DSOfn;
3822  const char *N, *EVR;
3823  evrFlags Flags = (evrFlags) 0;
3824  rpmds ds;
3825  char * f, * fe;
3826  char * g, * ge;
3827  char * t;
3828  FILE * fp = NULL;
3829  int rc = -1;
3830  int xx;
3831 
3832  if (PRCO == NULL)
3833  return -1;
3834 
3835 /*@-modobserver@*/
3836  if (_ldconfig_cmd == NULL) {
3837  _ldconfig_cmd = rpmExpand("%{?_rpmds_ldconfig_cmd}", NULL);
3838  if (!(_ldconfig_cmd != NULL && *_ldconfig_cmd == '/')) {
3839 /*@-observertrans @*/
3840  _ldconfig_cmd = _free(_ldconfig_cmd);
3841 /*@=observertrans @*/
3842  _ldconfig_cmd = xstrdup(_SBIN_LDCONFIG_P);
3843  }
3844  }
3845 
3846  if (_ldconfig_cache == NULL) {
3847  _ldconfig_cache = rpmExpand("%{?_rpmds_ldconfig_cache}", NULL);
3848  /* XXX may need to validate path existence somewhen. */
3849  if (!(_ldconfig_cache != NULL && *_ldconfig_cache == '/')) {
3850 /*@-observertrans @*/
3851  _ldconfig_cache = _free(_ldconfig_cache);
3852 /*@=observertrans @*/
3853  _ldconfig_cache = xstrdup(_LD_SO_CACHE);
3854  }
3855  }
3856 /*@=modobserver@*/
3857 
3858  if (fn == NULL)
3859  fn = _ldconfig_cache;
3860 
3861 if (_rpmds_debug < 0)
3862 fprintf(stderr, "*** rpmdsLdconfig(%p, %s) P %p R %p C %p O %p T %p D %p L %p\n", PRCO, fn, PRCO->Pdsp, PRCO->Rdsp, PRCO->Cdsp, PRCO->Odsp, PRCO->Tdsp, PRCO->Ddsp, PRCO->Ldsp);
3863 
3864  fp = popen(_ldconfig_cmd, "r");
3865  if (fp == NULL)
3866  goto exit;
3867 
3868  while((f = fgets(buf, (int)sizeof(buf), fp)) != NULL) {
3869  EVR = NULL;
3870  /* rtrim on line. */
3871  ge = f + strlen(f);
3872  while (--ge > f && _isspace(*ge))
3873  *ge = '\0';
3874 
3875  /* ltrim on line. */
3876  while (*f && _isspace(*f))
3877  f++;
3878 
3879  /* split on '=>' */
3880  fe = f;
3881  while (*fe && !(fe[0] == '=' && fe[1] == '>'))
3882  fe++;
3883  if (*fe == '\0')
3884  continue;
3885 
3886  /* find the DSO file name. */
3887  DSOfn = fe + 2;
3888 
3889  /* ltrim on DSO file name. */
3890  while (*DSOfn && _isspace(*DSOfn))
3891  DSOfn++;
3892  if (*DSOfn == '\0')
3893  continue;
3894 
3895  /* rtrim from "=>" */
3896  if (fe > f && fe[-1] == ' ') fe[-1] = '\0';
3897  *fe++ = '\0';
3898  *fe++ = '\0';
3899  g = fe;
3900 
3901  /* ltrim on field 2. */
3902  while (*g && _isspace(*g))
3903  g++;
3904  if (*g == '\0')
3905  continue;
3906 
3907  /* split out flags */
3908  for (t = f; *t != '\0'; t++) {
3909  if (!_isspace(*t))
3910  /*@innercontinue@*/ continue;
3911  *t++ = '\0';
3912  /*@innerbreak@*/ break;
3913  }
3914  /* XXX "libc4" "ELF" "libc5" "libc6" _("unknown") */
3915  /* XXX use flags to generate soname color */
3916  /* ",64bit" ",IA-64" ",x86-64", ",64bit" are color = 2 */
3917  /* ",N32" for mips64/libn32 */
3918 
3919  /* XXX use flags and LDASSUME_KERNEL to skip sonames? */
3920  /* "Linux" "Hurd" "Solaris" "FreeBSD" "kNetBSD" N_("Unknown OS") */
3921  /* ", OS ABI: %s %d.%d.%d" */
3922 
3923  N = f;
3924  if (EVR == NULL)
3925  EVR = "";
3926  Flags = (evrFlags) (Flags | RPMSENSE_PROBE);
3927  ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
3928  xx = rpmdsMerge(PRCO->Pdsp, ds);
3929  (void)rpmdsFree(ds);
3930  ds = NULL;
3931 
3932  xx = rpmdsELF(DSOfn, 0, rpmdsMergePRCO, PRCO);
3933  }
3934  rc = 0;
3935 
3936 exit:
3937  if (fp != NULL) (void) pclose(fp);
3938  return rc;
3939 }
3940 
3941 
3942 #if defined(__sun)
3943 #define _RLD_SEARCH_PATH "/lib:/usr/lib"
3944 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
3945 static const char * _rld_search_path = NULL;
3946 
3947 /* search a colon-separated list of directories for shared objects */
3948 int rpmdsRldpath(rpmPRCO PRCO, const char * rldp)
3949  /*@globals _rld_search_path @*/
3950  /*@modifies _rld_search_path @*/
3951 {
3952  char buf[BUFSIZ];
3953  const char *N, *EVR;
3954  evrFlags Flags = 0;
3955  rpmds ds;
3956  const char * f;
3957  const char * g;
3958  int rc = -1;
3959  int xx;
3960  glob_t gl;
3961  char ** gp;
3962 
3963  if (PRCO == NULL)
3964  return -1;
3965 
3966 /*@-modobserver@*/
3967  if (_rld_search_path == NULL) {
3968  _rld_search_path = rpmExpand("%{?_rpmds_rld_search_path}", NULL);
3969  /* XXX may need to validate path existence somewhen. */
3970  if (!(_rld_search_path != NULL && *_rld_search_path == '/')) {
3971 /*@-observertrans @*/
3972  _rld_search_path = _free(_rld_search_path);
3973 /*@=observertrans @*/
3974  _rld_search_path = xstrdup(_RLD_SEARCH_PATH);
3975  }
3976  }
3977 /*@=modobserver@*/
3978 
3979  if (rldp == NULL)
3980  rldp = _rld_search_path;
3981 
3982 if (_rpmds_debug > 0)
3983 fprintf(stderr, "*** rpmdsRldpath(%p, %s) P %p R %p C %p O %p\n", PRCO, rldp, PRCO->Pdsp, PRCO->Rdsp, PRCO->Cdsp, PRCO->Odsp);
3984 
3985  f = rldp;
3986  /* move through the path, splitting on : */
3987  while (f) {
3988  EVR = NULL;
3989  g = strchr(f, ':');
3990  if (g == NULL) {
3991  strcpy(buf, f);
3992  /* this is the last element, no more :'s */
3993  f = NULL;
3994  } else {
3995  /* copy this chunk to buf */
3996  strncpy(buf, f, g - f + 1);
3997  buf[g-f] = '\0';
3998 
3999  /* get ready for next time through */
4000  f = g + 1;
4001  }
4002 
4003  if ( !(strlen(buf) > 0 && buf[0] == '/') )
4004  continue;
4005 
4006  /* XXX: danger, buffer len */
4007  /* XXX: *.so.* should be configurable via a macro */
4008  strcat(buf, "/*.so.*");
4009 
4010 if (_rpmds_debug > 0)
4011 fprintf(stderr, "*** rpmdsRldpath(%p, %s) globbing %s\n", PRCO, rldp, buf);
4012 
4013  xx = Glob(buf, 0, NULL, &gl);
4014  if (xx) /* glob error, probably GLOB_NOMATCH */
4015  continue;
4016 
4017 if (_rpmds_debug > 0)
4018 fprintf(stderr, "*** rpmdsRldpath(%p, %s) glob matched %d files\n", PRCO, rldp, gl.gl_pathc);
4019 
4020  gp = gl.gl_pathv;
4021  /* examine each match */
4022  while (gp && *gp) {
4023  const char *DSOfn;
4024  /* XXX: should probably verify that we matched a file */
4025  DSOfn = *gp;
4026  gp++;
4027  if (EVR == NULL)
4028  EVR = "";
4029 
4030  /* N needs to be basename of DSOfn */
4031  N = DSOfn + strlen(DSOfn);
4032  while (N > DSOfn && *N != '/')
4033  --N;
4034 
4035  Flags |= RPMSENSE_PROBE;
4036  ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
4037  xx = rpmdsMerge(PRCO->Pdsp, ds);
4038  (void)rpmdsFree(ds);
4039  ds = NULL;
4040 
4041  xx = rpmdsELF(DSOfn, 0, rpmdsMergePRCO, PRCO);
4042  }
4043 /*@-immediatetrans@*/
4044  Globfree(&gl);
4045 /*@=immediatetrans@*/
4046  }
4047  rc = 0;
4048 
4049  return rc;
4050 }
4051 
4052 #define _SOLARIS_CRLE "/usr/sbin/crle"
4053 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
4054 static const char * _crle_cmd = NULL;
4055 
4056 int rpmdsCrle(rpmPRCO PRCO, /*@unused@*/ const char * fn)
4057  /*@globals _crle_cmd @*/
4058  /*@modifies _crle_cmd @*/
4059 {
4060  char buf[BUFSIZ];
4061  char * f;
4062  char * g, * ge;
4063  FILE * fp = NULL;
4064  int rc = -1; /* assume failure */
4065  int xx;
4066  int found_dlp = 0;
4067 
4068  if (PRCO == NULL)
4069  return -1;
4070 
4071 /*@-modobserver@*/
4072  if (_crle_cmd == NULL) {
4073  _crle_cmd = rpmExpand("%{?_rpmds_crle_cmd}", NULL);
4074  if (!(_crle_cmd != NULL && *_crle_cmd == '/')) {
4075 /*@-observertrans @*/
4076  _crle_cmd = _free(_crle_cmd);
4077 /*@=observertrans @*/
4078  _crle_cmd = xstrdup(_SOLARIS_CRLE);
4079  }
4080  }
4081 
4082  /* XXX: we rely on _crle_cmd including the -64 arg, if ELF64 */
4083  fp = popen(_crle_cmd, "r");
4084  if (fp == NULL)
4085  return rc;
4086 
4087  /*
4088  * we want the first line that contains "(ELF):"
4089  * we cannot search for "Default Library Path (ELF):" because that
4090  * changes in non-C locales.
4091  */
4092  while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
4093  if (found_dlp) /* XXX read all data? */
4094  continue;
4095 
4096  g = strstr(f, "(ELF):");
4097  if (g == NULL)
4098  continue;
4099 
4100  found_dlp = 1;
4101  f = g + (sizeof("(ELF):")-1);
4102  while (_isspace(*f))
4103  f++;
4104 
4105  /* rtrim path */
4106  ge = f + strlen(f);
4107  while (--ge > f && _isspace(*ge))
4108  *ge = '\0';
4109  }
4110  xx = pclose(fp);
4111 
4112  /* we have the loader path, let rpmdsRldpath() do the work */
4113  if (found_dlp)
4114  rc = rpmdsRldpath(PRCO, f);
4115 
4116  return rc;
4117 }
4118 #endif
4119 
4120 int rpmdsUname(rpmds *dsp, const struct utsname * un)
4121 {
4122 /*@observer@*/
4123  static const char * NS = "uname";
4124  struct utsname myun;
4125  int rc = -1;
4126  int xx;
4127 
4128  if (un == NULL) {
4129  xx = uname(&myun);
4130  if (xx != 0)
4131  goto exit;
4132  un = &myun;
4133  }
4134 
4135 /*@-type@*/
4136  /* XXX values need to be checked for EVR (i.e. no '-' character.) */
4137  if (un->sysname != NULL)
4138  rpmdsNSAdd(dsp, NS, "sysname", un->sysname, RPMSENSE_EQUAL);
4139  if (un->nodename != NULL)
4140  rpmdsNSAdd(dsp, NS, "nodename", un->nodename, RPMSENSE_EQUAL);
4141  if (un->release != NULL)
4142  rpmdsNSAdd(dsp, NS, "release", un->release, RPMSENSE_EQUAL);
4143 #if 0 /* XXX has embedded spaces */
4144  if (un->version != NULL)
4145  rpmdsNSAdd(dsp, NS, "version", un->version, RPMSENSE_EQUAL);
4146 #endif
4147  if (un->machine != NULL)
4148  rpmdsNSAdd(dsp, NS, "machine", un->machine, RPMSENSE_EQUAL);
4149 #if defined(__linux__)
4150  if (un->domainname != NULL && strcmp(un->domainname, "(none)"))
4151  rpmdsNSAdd(dsp, NS, "domainname", un->domainname, RPMSENSE_EQUAL);
4152 #endif
4153 /*@=type@*/
4154  rc = 0;
4155 
4156 exit:
4157  return rc;
4158 }
4159 
4160 #define _PERL_PROVIDES "/usr/bin/find /usr/lib/perl5 | /usr/lib/rpm/perl.prov"
4161 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
4162 static const char * _perldeps_cmd = NULL;
4163 
4164 int rpmdsPipe(rpmds * dsp, rpmTag tagN, const char * cmd)
4165  /*@globals _perldeps_cmd @*/
4166  /*@modifies _perldeps_cmd @*/
4167 {
4168  char buf[BUFSIZ];
4169  const char *N, *EVR;
4170  evrFlags Flags = (evrFlags) 0;
4171  rpmds ds;
4172  char * f, * fe;
4173  char * g, * ge;
4174  FILE * fp = NULL;
4175  const char * fn = "pipe";
4176  int rc = -1;
4177  int cmdprinted;
4178  int ln;
4179  int xx;
4180 
4181 /*@-modobserver@*/
4182  if (_perldeps_cmd == NULL) {
4183  _perldeps_cmd = rpmExpand("%{?_rpmds_perldeps_cmd}", NULL);
4184  /* XXX may need to validate path existence somewhen. */
4185  if (!(_perldeps_cmd != NULL && *_perldeps_cmd == '/')) {
4186 /*@-observertrans @*/
4187  _perldeps_cmd = _free(_perldeps_cmd);
4188 /*@=observertrans @*/
4189  _perldeps_cmd = xstrdup(_PERL_PROVIDES);
4190  }
4191  }
4192 /*@=modobserver@*/
4193 
4194  if (tagN <= 0)
4195  tagN = RPMTAG_PROVIDENAME;
4196  if (cmd == NULL)
4197  cmd = _perldeps_cmd;
4198 
4199  fp = popen(cmd, "r");
4200  if (fp == NULL)
4201  goto exit;
4202 
4203  ln = 0;
4204  cmdprinted = 0;
4205  while((f = fgets(buf, (int)sizeof(buf), fp)) != NULL) {
4206  ln++;
4207 
4208  /* insure a terminator. */
4209  buf[sizeof(buf)-1] = '\0';
4210 
4211  /* ltrim on line. */
4212  while (*f && _isspace(*f))
4213  f++;
4214 
4215  /* skip empty lines and comments */
4216  if (*f == '\0' || *f == '#')
4217  continue;
4218 
4219  /* rtrim on line. */
4220  fe = f + strlen(f);
4221  while (--fe > f && _isspace(*fe))
4222  *fe = '\0';
4223 
4224  /* split on ' ' or comparison operator. */
4225  fe = f;
4226  if (*f == '!') fe++;
4227  while (*fe && !_isspace(*fe) && strchr("!<=>", *fe) == NULL)
4228  fe++;
4229  while (*fe && _isspace(*fe))
4230  *fe++ = '\0';
4231 
4232  if (!(xisalnum(f[0]) || strchr("/_%!", f[0]) != NULL)) {
4233  if (!cmdprinted++)
4234  fprintf(stderr, _("running \"%s\" pipe command\n"), cmd);
4235  fprintf(stderr, _("%s:%d \"%s\" has invalid name. Skipping ...\n"),
4236  fn, ln, f);
4237  continue;
4238  }
4239 
4240  N = f;
4241  EVR = NULL;
4242  Flags = (evrFlags) 0;
4243 
4244  /* parse for non-path, versioned dependency. */
4245  if (*f != '/' && *fe != '\0') {
4246  /* parse comparison operator */
4247  g = fe;
4248  Flags = rpmEVRflags(fe, (const char **)&g);
4249  if (Flags == 0) {
4250  if (!cmdprinted++)
4251  fprintf(stderr, _("running \"%s\" pipe command\n"), cmd),
4252  fprintf(stderr, _("%s:%d \"%s\" has no comparison operator. Skipping ...\n"),
4253  fn, ln, fe);
4254  continue;
4255  }
4256  *fe = '\0';
4257 
4258  /* ltrim on field 2. */
4259  while (*g && _isspace(*g))
4260  g++;
4261  if (*g == '\0') {
4262  if (!cmdprinted++)
4263  fprintf(stderr, _("running \"%s\" pipe command\n"), cmd),
4264  /* XXX No EVR comparison value found. */
4265  fprintf(stderr, _("\tline %d: No EVR comparison value found.\n Skipping ..."),
4266  ln);
4267  fprintf(stderr, _("%s:%d \"%s\" has no EVR string. Skipping ...\n"),
4268  fn, ln, f);
4269  continue;
4270  }
4271 
4272  ge = g + 1;
4273  while (*ge && !_isspace(*ge))
4274  ge++;
4275 
4276  if (*ge != '\0')
4277  *ge = '\0'; /* XXX can't happen, line rtrim'ed already. */
4278 
4279  EVR = g;
4280  }
4281 
4282  if (EVR == NULL)
4283  EVR = "";
4284  Flags = (evrFlags) (Flags | RPMSENSE_PROBE);
4285  ds = rpmdsSingle(tagN, N, EVR, Flags);
4286  xx = rpmdsMerge(dsp, ds);
4287  (void)rpmdsFree(ds);
4288  ds = NULL;
4289  }
4290  rc = 0;
4291 
4292 exit:
4293  if (fp != NULL) (void) pclose(fp);
4294  return rc;
4295 }
4296 
4297 static int rpmdsNAcmp(rpmds A, rpmds B)
4298  /*@*/
4299 {
4300  const char * AN = A->ns.N;
4301  const char * AA = A->ns.A;
4302  const char * BN = B->ns.N;
4303  const char * BA = B->ns.A;
4304  int rc;
4305 
4306  if (!AA && !BA) {
4307  rc = strcmp(AN, BN);
4308  } else if (AA && !BA) {
4309  rc = strncmp(AN, BN, (AA - AN)) || BN[AA - AN];
4310  if (!rc)
4311  rc = strcmp(AA, B->A);
4312  } else if (!AA && BA) {
4313  rc = strncmp(AN, BN, (BA - BN)) || AN[BA - BN];
4314  if (!rc)
4315  rc = strcmp(BA, A->A);
4316  } else {
4317  rc = strcmp(AN, BN);
4318  }
4319  return rc;
4320 }
4321 
4322 /*@unchecked@*/ /*@only@*/ /*@null@*/
4323 const char * evr_tuple_order = NULL;
4324 
4329 /*@observer@*/
4330 static const char * rpmdsEVRorder(void)
4331  /*@globals evr_tuple_order @*/
4332  /*@modifies evr_tuple_order @*/
4333 {
4334  if (evr_tuple_order == NULL) {
4335 /*@-mods@*/
4336  evr_tuple_order = rpmExpand("%{?evr_tuple_order}", NULL);
4337 /*@=mods@*/
4338  if (evr_tuple_order == NULL || evr_tuple_order[0] == '\0')
4339  evr_tuple_order = xstrdup("EVR");
4340  }
4341 assert(evr_tuple_order != NULL && evr_tuple_order[0] != '\0');
4342 /*@-freshtrans@*/
4343  return evr_tuple_order;
4344 /*@=freshtrans@*/
4345 }
4346 
4347 int rpmdsCompare(const rpmds A, const rpmds B)
4348 {
4349  const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
4350  const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
4351  EVR_t a = (EVR_t) memset(alloca(sizeof(*a)), 0, sizeof(*a));
4352  EVR_t b = (EVR_t) memset(alloca(sizeof(*a)), 0, sizeof(*a));
4353  evrFlags aFlags = A->ns.Flags;
4354  evrFlags bFlags = B->ns.Flags;
4355  int (*EVRcmp) (const char *a, const char *b);
4356  int result = 1;
4357  const char * s;
4358  int set_version = 0;
4359  int sense;
4360  int xx;
4361 
4362 assert((rpmdsFlags(A) & RPMSENSE_SENSEMASK) == A->ns.Flags);
4363 assert((rpmdsFlags(B) & RPMSENSE_SENSEMASK) == B->ns.Flags);
4364  /* Different names (and/or name.arch's) don't overlap. */
4365  if (rpmdsNAcmp(A, B)) {
4366  result = 0;
4367  goto exit;
4368  }
4369 
4370  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
4371 /*@-nullderef@*/
4372  if (!(A->EVR && A->Flags && B->EVR && B->Flags))
4373  goto exit;
4374 
4375  /* Same name. If either A or B is an existence test, always overlap. */
4376  if (!(aFlags && bFlags))
4377  goto exit;
4378 
4379  /* If either EVR is non-existent or empty, always overlap. */
4380  if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i]))
4381  goto exit;
4382 
4383  /* Both AEVR and BEVR exist. */
4384  xx = (A->EVRparse ? A->EVRparse : rpmEVRparse) (A->EVR[A->i], a);
4385  xx = (B->EVRparse ? B->EVRparse : rpmEVRparse) (B->EVR[B->i], b);
4386 
4387  /* If EVRcmp is identical, use that, otherwise use default. */
4388  EVRcmp = (A->EVRcmp && B->EVRcmp && A->EVRcmp == B->EVRcmp)
4389  ? A->EVRcmp : rpmvercmp;
4390 
4391  /* Compare {A,B} [epoch:]version[-release][:distepoch] */
4392  sense = 0;
4393  for (s = rpmdsEVRorder(); *s; s++) {
4394  int ix;
4395  switch ((int)*s) {
4396  default: continue; /*@notreached@*//*@switchbreak@*/ break;
4397  case 'E':
4398  ix = RPMEVR_E;
4399  if (a->F[ix] && *a->F[ix] && b->F[ix] && *b->F[ix]) {
4400  /* XXX ALT version-set comparison */
4401  if (!strcmp(a->F[ix], "set") && !strcmp(b->F[ix], "set"))
4402  set_version = 1;
4403  /*@switchbreak@*/ break;
4404  }
4405 
4406  /* XXX Special handling for missing Epoch: tags hysteria */
4407  if (a->F[ix] && *a->F[ix] && atol(a->F[ix]) > 0) {
4408  if (!B->nopromote) {
4409  int lvl = (_rpmds_unspecified_epoch_noise
4411  rpmlog(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
4412  aDepend, bDepend);
4413  sense = 0;
4414  } else
4415  sense = 1;
4416  } else
4417  if (b->F[ix] && *b->F[ix] && atol(b->F[ix]) > 0)
4418  sense = -1;
4419  /*@switchbreak@*/ break;
4420  case 'V': ix = RPMEVR_V; /*@switchbreak@*/break;
4421  case 'T': ix = RPMEVR_T; /*@switchbreak@*/break;
4422  case 'R': ix = RPMEVR_R; /*@switchbreak@*/break;
4423  case 'D': ix = RPMEVR_D; /*@switchbreak@*/break;
4424  }
4425 #if defined(RPM_VENDOR_MANDRIVA) /* mdvbz#55810 */
4426  if(ix >= RPMEVR_R && (bFlags & (~RPMSENSE_GREATER & RPMSENSE_EQUAL))
4427  && !(ix == RPMEVR_D && (bFlags & RPMSENSE_LESS))
4428  && *(b->F[ix]) == '\0')
4429  break;
4430  if (a->F[ix] && b->F[ix])
4431 #else
4432  if (a->F[ix] && *a->F[ix] && b->F[ix] && *b->F[ix])
4433 #endif
4434  {
4435  /* XXX ALT version-set comparison */
4436  if (ix == RPMEVR_V && set_version) {
4437  set_version = 0;
4438  sense = rpmsetCmp(a->F[ix], b->F[ix]);
4439  if (sense < -1) {
4440  if (sense == -3)
4441  rpmlog(RPMLOG_WARNING, _("failed to decode %s\n"), a->F[ix]);
4442  if (sense == -4)
4443  rpmlog(RPMLOG_WARNING, _("failed to decode %s\n"), b->F[ix]);
4444  /* neither is subset of each other */
4445  sense = 0;
4446  }
4447  } else
4448  if (ix == RPMEVR_T) /* XXX twiddle-in-version "negative" compare */
4449  sense = -EVRcmp(a->F[ix], b->F[ix]);
4450  else
4451 /*@i@*/ sense = EVRcmp(a->F[ix], b->F[ix]);
4452  }
4453  if (sense)
4454  break;
4455  }
4456 
4457  a->str = _free(a->str);
4458  b->str = _free(b->str);
4459 
4460  /* Detect overlap of {A,B} range. */
4461  if (aFlags == RPMSENSE_NOTEQUAL || bFlags == RPMSENSE_NOTEQUAL) {
4462  result = (sense != 0);
4463  } else if (sense < 0 && ((aFlags & RPMSENSE_GREATER) || (bFlags & RPMSENSE_LESS))) {
4464  result = 1;
4465  } else if (sense > 0 && ((aFlags & RPMSENSE_LESS) || (bFlags & RPMSENSE_GREATER))) {
4466  result = 1;
4467  } else if (sense == 0 &&
4468  (((aFlags & RPMSENSE_EQUAL) && (bFlags & RPMSENSE_EQUAL)) ||
4469  ((aFlags & RPMSENSE_LESS) && (bFlags & RPMSENSE_LESS)) ||
4470  ((aFlags & RPMSENSE_GREATER) && (bFlags & RPMSENSE_GREATER)))) {
4471  result = 1;
4472  } else
4473  result = 0;
4474 /*@=nullderef@*/
4475 
4476 exit:
4477  if (_noisy_range_comparison_debug_message)
4478  rpmlog(RPMLOG_DEBUG, D_(" %s A %s\tB %s\n"),
4479  (result ? _("YES") : _("NO ")), aDepend, bDepend);
4480  aDepend = _free(aDepend);
4481  bDepend = _free(bDepend);
4482  return result;
4483 }
4484 
4485 int rpmdsMatch(const rpmds A, rpmds B)
4486 {
4487  int result = 0;
4488 
4489  /* If A dependency matches any in B, we're done. */
4490  if ((B = rpmdsInit(B)) != NULL)
4491  while (rpmdsNext(B) >= 0)
4492  if ((result = rpmdsCompare(A, B)))
4493  break;
4494  return result;
4495 }
4496 
4497 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
4498  const fnpyKey * suggestedKeys, int adding)
4499 {
4500  const char * Name = rpmdsN(ds);
4501  const char * DNEVR = rpmdsDNEVR(ds);
4502  const char * EVR = rpmdsEVR(ds);
4503  rpmProblemType type;
4504  fnpyKey key;
4505 
4506  if (ps == NULL) return;
4507 
4508  if (Name == NULL) Name = "?N?";
4509  if (EVR == NULL) EVR = "?EVR?";
4510  if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
4511 
4512  rpmlog(RPMLOG_DEBUG, D_("package %s has unsatisfied %s: %s\n"),
4513  pkgNEVR, ds->Type, DNEVR+2);
4514 
4515  switch ((unsigned)DNEVR[0]) {
4516  case 'C': type = RPMPROB_CONFLICT; break;
4517  default:
4518  case 'R': type = RPMPROB_REQUIRES; break;
4519  }
4520 
4521  key = (suggestedKeys ? suggestedKeys[0] : NULL);
4522  rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
4523 }
4524 
4525 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
4526 {
4527  int scareMem = 0;
4528  rpmds provides = NULL;
4529  evrFlags reqFlags = req->ns.Flags;
4530  int result = 1;
4531 
4532 assert((rpmdsFlags(req) & RPMSENSE_SENSEMASK) == req->ns.Flags);
4533  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
4534  if (req->EVR == NULL || req->Flags == NULL)
4535  goto exit;
4536 
4537  switch(req->ns.Type) {
4538  default:
4539  /* Primary key retrieve satisfes an existence compare. */
4540  if (!reqFlags || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
4541  goto exit;
4542  /*@fallthrough@*/
4543  case RPMNS_TYPE_ARCH:
4544  break;
4545  }
4546 
4547  /* Get provides information from header */
4548  provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
4549  if (provides == NULL) {
4550  result = 0;
4551  goto exit; /* XXX should never happen */
4552  }
4553  if (nopromote)
4554  (void) rpmdsSetNoPromote(provides, nopromote);
4555 
4556  /*
4557  * Rpm prior to 3.0.3 did not have versioned provides.
4558  * If no provides version info is available, match any/all requires
4559  * with same name.
4560  */
4561  if (provides->EVR == NULL)
4562  goto exit;
4563 
4564  /* If any provide matches the require, we're done. */
4565  result = 0;
4566  if (provides != NULL)
4567  while (rpmdsNext(provides) >= 0)
4568  if ((result = rpmdsCompare(provides, req)))
4569  break;
4570 
4571 exit:
4572  (void)rpmdsFree(provides);
4573  provides = NULL;
4574 
4575  return result;
4576 }
4577 
4578 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
4579 {
4580  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
4581  const char * pkgN, * V, * R;
4582 #ifdef RPM_VENDOR_MANDRIVA
4583  const char * D;
4584  int gotD = 0;
4585 #endif
4586  rpmuint32_t E;
4587  int gotE = 0;
4588  const char * pkgEVR;
4589  char * t;
4590  evrFlags reqFlags = req->ns.Flags;
4591  evrFlags pkgFlags = RPMSENSE_EQUAL;
4592  int result = 1;
4593  rpmds pkg;
4594  size_t nb;
4595 
4596 assert((rpmdsFlags(req) & RPMSENSE_SENSEMASK) == req->ns.Flags);
4597  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
4598  if (req->EVR == NULL || req->Flags == NULL)
4599  goto exit;
4600 
4601  if (!(reqFlags && req->EVR[req->i] && *req->EVR[req->i]))
4602  goto exit;
4603 
4604  /* Get package information from header */
4605 /*@-mods@*/
4606  (void) headerNEVRA(h, &pkgN, NULL, &V, &R, NULL);
4607 /*@=mods@*/
4608  /* XXX segfault avoidance */
4609  if (pkgN == NULL) pkgN = xstrdup("N");
4610  if (V == NULL) V = xstrdup("V");
4611  if (R == NULL) R = xstrdup("R");
4612  he->tag = RPMTAG_EPOCH;
4613  gotE = headerGet(h, he, 0);
4614  E = (he->p.ui32p ? he->p.ui32p[0] : 0);
4615  he->p.ptr = _free(he->p.ptr);
4616 
4617 #if defined(RPM_VENDOR_MANDRIVA)
4618  he->tag = RPMTAG_DISTEPOCH;
4619  gotD = headerGet(h, he, 0);
4620  D = (he->p.str ? he->p.str : NULL);
4621 #endif
4622 
4623  nb = 21 + 1 + 1;
4624  if (V) nb += strlen(V);
4625  if (R) nb += strlen(R);
4626 #if defined(RPM_VENDOR_MANDRIVA)
4627  if (gotD) nb += strlen(D) + 1;
4628 #endif
4629  pkgEVR = t = (char *) alloca(nb);
4630  *t = '\0';
4631  if (gotE) {
4632  sprintf(t, "%d:", E);
4633  t += strlen(t);
4634  }
4635  t = stpcpy( stpcpy( stpcpy(t, V) , "-") , R);
4636 #if defined(RPM_VENDOR_MANDRIVA)
4637  if (gotD) {
4638  t = stpcpy( stpcpy( t, ":"), D);
4639  D = _free(D);
4640  }
4641 #endif
4642  V = _free(V);
4643  R = _free(R);
4644 
4645  if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
4646  if (nopromote)
4647  (void) rpmdsSetNoPromote(pkg, nopromote);
4648  result = rpmdsCompare(pkg, req);
4649  (void)rpmdsFree(pkg);
4650  pkg = NULL;
4651  }
4652  pkgN = _free(pkgN);
4653 
4654 exit:
4655  return result;
4656 }
4657 
4658 int rpmdsNegateRC(const rpmds ds, int rc)
4659 {
4660  if (ds->ns.str[0] == '!')
4661  rc = (rc == 0);
4662  return rc;
4663 }