rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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