Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

lib/rpmds.c

Go to the documentation of this file.
00001 
00004 #include "system.h"
00005 
00006 #if HAVE_GELF_H
00007 #if LIBELF_H_LFS_CONFLICT
00008 /* Some implementations of libelf.h/gelf.h are incompatible with
00009  * the Large File API.
00010  */
00011 # undef _LARGEFILE64_SOURCE
00012 # undef _LARGEFILE_SOURCE
00013 # undef _FILE_OFFSET_BITS
00014 # define _FILE_OFFSET_BITS 32
00015 #endif
00016 
00017 #include <gelf.h>
00018 /*
00019  * On Solaris, gelf.h included libelf.h, which #undef'ed the gettext
00020  * convenience macro _().  Repair by repeating (from system.h) just
00021  * the bits that are needed for _() to function.
00022  */
00023 
00024 #if defined(__sun)
00025 #if ENABLE_NLS && !defined(__LCLINT__)
00026 # define _(Text) gettext (Text)
00027 #else
00028 # define _(Text) Text
00029 #endif /* gettext _() fixup */
00030 #endif
00031 #endif /* HAVE_GELF_H */
00032 
00033 #if HAVE_LIBELF && !HAVE_GELF_GETVERNAUX
00034 /* We have gelf.h and libelf, but we don't have some of the
00035  * helper functions gelf_getvernaux(), gelf_getverneed(), etc.
00036  * Provide our own simple versions here.
00037  */
00038 
00039 static GElf_Verdef *gelf_getverdef(Elf_Data *data, int offset,
00040                    GElf_Verdef *dst)
00041 {
00042         return (GElf_Verdef *) ((char *) data->d_buf + offset);
00043 }
00044 
00045 static GElf_Verdaux *gelf_getverdaux(Elf_Data *data, int offset,
00046                     GElf_Verdaux *dst)
00047 {
00048         return (GElf_Verdaux *) ((char *) data->d_buf + offset);
00049 }
00050 
00051 static GElf_Verneed *gelf_getverneed(Elf_Data *data, int offset,
00052                     GElf_Verneed *dst)
00053 {
00054         return (GElf_Verneed *) ((char *) data->d_buf + offset);
00055 }
00056 
00057 static GElf_Vernaux *gelf_getvernaux(Elf_Data *data, int offset,
00058                     GElf_Vernaux *dst)
00059 {
00060         return (GElf_Vernaux *) ((char *) data->d_buf + offset);
00061 }
00062 
00063 /* Most non-Linux systems won't have SHT_GNU_verdef or SHT_GNU_verneed,
00064  * but they might have something mostly-equivalent.  Solaris has
00065  * SHT_SUNW_{verdef,verneed}
00066  */
00067 #if !defined(SHT_GNU_verdef) && defined(__sun) && defined(SHT_SUNW_verdef)
00068 # define SHT_GNU_verdef SHT_SUNW_verdef
00069 # define SHT_GNU_verneed SHT_SUNW_verneed
00070 #endif
00071 
00072 #endif /* HAVE_LIBELF && !HAVE_GELF_GETVERNAUX */
00073 
00074 #if !defined(DT_GNU_HASH)
00075 #define DT_GNU_HASH     0x6ffffef5
00076 #endif
00077 
00078 #include <rpmio_internal.h>     /* XXX fdGetFILE */
00079 #include <rpmlib.h>
00080 #include <rpmmacro.h>
00081 
00082 #define _RPMDS_INTERNAL
00083 #define _RPMEVR_INTERNAL
00084 #define _RPMPRCO_INTERNAL
00085 #include <rpmds.h>
00086 
00087 #include <argv.h>
00088 
00089 #include "debug.h"
00090 
00091 /*@access rpmns @*/
00092 /*@access EVR_t @*/
00093 
00094 #define _isspace(_c)    \
00095         ((_c) == ' ' || (_c) == '\t' || (_c) == '\r' || (_c) == '\n')
00096 
00100 /*@unchecked@*/
00101 static int _noisy_range_comparison_debug_message = 0;
00102 
00103 /*@unchecked@*/
00104 int _rpmds_debug = 0;
00105 
00106 /*@unchecked@*/
00107 int _rpmds_nopromote = 1;
00108 
00109 /*@unchecked@*/
00110 /*@-exportheadervar@*/
00111 int _rpmds_unspecified_epoch_noise = 0;
00112 /*@=exportheadervar@*/
00113 
00114 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
00115 {
00116     if (ds == NULL) return NULL;
00117 /*@-modfilesys@*/
00118 if (_rpmds_debug && msg != NULL)
00119 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00120 /*@=modfilesys@*/
00121     ds->nrefs--;
00122     return NULL;
00123 }
00124 
00125 rpmds XrpmdsLink(rpmds ds, const char * msg, const char * fn, unsigned ln)
00126 {
00127     if (ds == NULL) return NULL;
00128     ds->nrefs++;
00129 
00130 /*@-modfilesys@*/
00131 if (_rpmds_debug && msg != NULL)
00132 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00133 /*@=modfilesys@*/
00134 
00135     /*@-refcounttrans@*/ return ds; /*@=refcounttrans@*/
00136 }
00137 
00138 rpmds rpmdsFree(rpmds ds)
00139 {
00140     HFD_t hfd = headerFreeData;
00141     rpmTag tagEVR, tagF;
00142 
00143     if (ds == NULL)
00144         return NULL;
00145 
00146     if (ds->nrefs > 1)
00147         return rpmdsUnlink(ds, ds->Type);
00148 
00149 /*@-modfilesys@*/
00150 if (_rpmds_debug < 0)
00151 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00152 /*@=modfilesys@*/
00153 
00154     if (ds->tagN == RPMTAG_PROVIDENAME) {
00155         tagEVR = RPMTAG_PROVIDEVERSION;
00156         tagF = RPMTAG_PROVIDEFLAGS;
00157     } else
00158     if (ds->tagN == RPMTAG_REQUIRENAME) {
00159         tagEVR = RPMTAG_REQUIREVERSION;
00160         tagF = RPMTAG_REQUIREFLAGS;
00161     } else
00162     if (ds->tagN == RPMTAG_CONFLICTNAME) {
00163         tagEVR = RPMTAG_CONFLICTVERSION;
00164         tagF = RPMTAG_CONFLICTFLAGS;
00165     } else
00166     if (ds->tagN == RPMTAG_OBSOLETENAME) {
00167         tagEVR = RPMTAG_OBSOLETEVERSION;
00168         tagF = RPMTAG_OBSOLETEFLAGS;
00169     } else
00170     if (ds->tagN == RPMTAG_TRIGGERNAME) {
00171         tagEVR = RPMTAG_TRIGGERVERSION;
00172         tagF = RPMTAG_TRIGGERFLAGS;
00173     } else
00174     if (ds->tagN == RPMTAG_DIRNAMES) {
00175         tagEVR = 0;
00176         tagF = 0;
00177     } else
00178     if (ds->tagN == RPMTAG_FILELINKTOS) {
00179         tagEVR = 0;
00180         tagF = 0;
00181     } else
00182         return NULL;
00183 
00184     /*@-branchstate@*/
00185     if (ds->Count > 0) {
00186         ds->N = hfd(ds->N, ds->Nt);
00187         ds->EVR = hfd(ds->EVR, ds->EVRt);
00188         /*@-evalorder@*/
00189         ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
00190         /*@=evalorder@*/
00191         ds->h = headerFree(ds->h);
00192     }
00193     /*@=branchstate@*/
00194 
00195     ds->DNEVR = _free(ds->DNEVR);
00196     ds->ns.str = _free(ds->ns.str);
00197     memset(&ds->ns, 0, sizeof(ds->ns));
00198     ds->A = _free(ds->A);
00199     ds->Color = _free(ds->Color);
00200     ds->Refs = _free(ds->Refs);
00201     ds->Result = _free(ds->Result);
00202 
00203     (void) rpmdsUnlink(ds, ds->Type);
00204     /*@-refcounttrans -usereleased@*/
00205 /*@-boundswrite@*/
00206     memset(ds, 0, sizeof(*ds));         /* XXX trash and burn */
00207 /*@=boundswrite@*/
00208     ds = _free(ds);
00209     /*@=refcounttrans =usereleased@*/
00210     return NULL;
00211 }
00212 
00213 /*@-bounds@*/
00214 static /*@null@*/
00215 const char ** rpmdsDupArgv(/*@null@*/ const char ** argv, int argc)
00216         /*@*/
00217 {
00218     const char ** av;
00219     size_t nb = 0;
00220     int ac = 0;
00221     char * t;
00222 
00223     if (argv == NULL)
00224         return NULL;
00225     for (ac = 0; ac < argc; ac++) {
00226 assert(argv[ac] != NULL);
00227         nb += strlen(argv[ac]) + 1;
00228     }
00229     nb += (ac + 1) * sizeof(*av);
00230 
00231     av = xmalloc(nb);
00232     t = (char *) (av + ac + 1);
00233     for (ac = 0; ac < argc; ac++) {
00234         av[ac] = t;
00235         t = stpcpy(t, argv[ac]) + 1;
00236     }
00237     av[ac] = NULL;
00238 /*@-nullret@*/
00239     return av;
00240 /*@=nullret@*/
00241 }
00242 /*@=bounds@*/
00243 
00244 rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
00245 {
00246     HFD_t hfd = headerFreeData;
00247     int scareMem = (flags & 0x1);
00248     HGE_t hge =
00249         (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry);
00250     rpmTag tagEVR, tagF;
00251     rpmds ds = NULL;
00252     const char * Type;
00253     const char ** N;
00254     rpmTagType Nt;
00255     int_32 Count;
00256 int rpmv3 = headerIsEntry(h, RPMTAG_OLDFILENAMES);
00257 
00258 assert(scareMem == 0);          /* XXX always allocate memory */
00259     if (tagN == RPMTAG_PROVIDENAME) {
00260         Type = "Provides";
00261         tagEVR = RPMTAG_PROVIDEVERSION;
00262         tagF = RPMTAG_PROVIDEFLAGS;
00263     } else
00264     if (tagN == RPMTAG_REQUIRENAME) {
00265         Type = "Requires";
00266         tagEVR = RPMTAG_REQUIREVERSION;
00267         tagF = RPMTAG_REQUIREFLAGS;
00268     } else
00269     if (tagN == RPMTAG_CONFLICTNAME) {
00270         Type = "Conflicts";
00271         tagEVR = RPMTAG_CONFLICTVERSION;
00272         tagF = RPMTAG_CONFLICTFLAGS;
00273     } else
00274     if (tagN == RPMTAG_OBSOLETENAME) {
00275         Type = "Obsoletes";
00276         tagEVR = RPMTAG_OBSOLETEVERSION;
00277         tagF = RPMTAG_OBSOLETEFLAGS;
00278     } else
00279     if (tagN == RPMTAG_TRIGGERNAME) {
00280         Type = "Triggers";
00281         tagEVR = RPMTAG_TRIGGERVERSION;
00282         tagF = RPMTAG_TRIGGERFLAGS;
00283     } else
00284     if (!rpmv3 && tagN == RPMTAG_DIRNAMES) {
00285         Type = "Dirnames";
00286         tagEVR = 0;
00287         tagF = 0;
00288     } else
00289     if (!rpmv3 && tagN == RPMTAG_FILELINKTOS) {
00290         Type = "Filelinktos";
00291         tagEVR = RPMTAG_DIRNAMES;
00292         tagF = RPMTAG_DIRINDEXES;
00293     } else
00294         goto exit;
00295 
00296     /*@-branchstate@*/
00297     if (hge(h, tagN, &Nt, &N, &Count)
00298      && N != NULL && Count > 0)
00299     {
00300         int xx;
00301         int_32 CountEVR, CountF;
00302 
00303         ds = xcalloc(1, sizeof(*ds));
00304         ds->Type = Type;
00305         ds->h = (scareMem ? headerLink(h) : NULL);
00306         ds->i = -1;
00307         ds->DNEVR = NULL;
00308         ds->tagN = tagN;
00309         ds->N = N;
00310         ds->Nt = Nt;
00311         ds->Count = Count;
00312         ds->nopromote = _rpmds_nopromote;
00313 
00314         if (tagEVR > 0)
00315             xx = hge(h, tagEVR, &ds->EVRt, &ds->EVR, &CountEVR);
00316         if (tagF > 0)
00317             xx = hge(h, tagF, &ds->Ft, &ds->Flags, &CountF);
00318 /*@-boundsread@*/
00319         if (!scareMem && ds->Flags != NULL)
00320             ds->Flags = memcpy(xmalloc(ds->Count * sizeof(*ds->Flags)),
00321                                 ds->Flags, ds->Count * sizeof(*ds->Flags));
00322         {   rpmTag tagA = RPMTAG_ARCH;
00323             rpmTagType At;
00324             const char * A = NULL;
00325             if (tagA > 0)
00326                 xx = hge(h, tagA, &At, &A, NULL);
00327             ds->A = (xx && A != NULL ? xstrdup(A) : NULL);
00328         }
00329         {   rpmTag tagBT = RPMTAG_BUILDTIME;
00330             rpmTagType BTt;
00331             int_32 * BTp = NULL;
00332             if (tagBT > 0)
00333                 xx = hge(h, tagBT, &BTt, &BTp, NULL);
00334             ds->BT = (xx && BTp != NULL && BTt == RPM_INT32_TYPE ? *BTp : 0);
00335         }
00336 /*@=boundsread@*/
00337 
00338         if (tagN == RPMTAG_DIRNAMES) {
00339             char * t;
00340             size_t len;
00341             int i;
00342             /* XXX Dirnames always have trailing '/', trim that here. */
00343             for (i = 0; i < Count; i++) {
00344                 (void) urlPath(N[i], (const char **)&t);
00345                 if (t > N[i])
00346                     N[i] = t;
00347                 t = (char *)N[i];
00348                 len = strlen(t);
00349                 /* XXX don't truncate if parent is / */
00350                 if (len > 1 && t[len-1] == '/')
00351                     t[len-1] = '\0';
00352             }
00353         } else
00354         if (tagN == RPMTAG_FILELINKTOS) {
00355             if (Count > CountF) Count = CountF;
00356 
00357             /* XXX Construct the absolute path of the target symlink(s). */
00358             const char ** av = xcalloc(Count+1, sizeof(*av));
00359             int i;
00360 
00361             for (i = 0; i < Count; i++) {
00362                 if (N[i] == NULL || *N[i] == '\0')
00363                     av[i] = xstrdup("");
00364                 else if (*N[i] == '/')
00365                     av[i] = xstrdup(N[i]);
00366                 else if (ds->EVR && ds->Flags && ds->Flags[i] >= 0 && ds->Flags[i] < CountEVR)
00367 /*@-nullderef@*/        /* XXX ds->Flags != NULL */
00368                     av[i] = rpmGenPath(NULL, ds->EVR[ds->Flags[i]], N[i]);
00369 /*@=nullderef@*/
00370                 else
00371                     av[i] = xstrdup("");
00372             }
00373             av[Count] = NULL;
00374 
00375             N = ds->N = hfd(ds->N, ds->Nt);
00376             ds->N = rpmdsDupArgv(av, Count);
00377             av = argvFree(av);
00378             ds->EVR = hfd(ds->EVR, ds->EVRt);
00379             /*@-evalorder@*/
00380             ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
00381             /*@=evalorder@*/
00382         }
00383 
00384 /*@-modfilesys@*/
00385 if (_rpmds_debug < 0)
00386 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00387 /*@=modfilesys@*/
00388 
00389     }
00390     /*@=branchstate@*/
00391 
00392 exit:
00393 /*@-compdef -usereleased@*/     /* FIX: ds->Flags may be NULL */
00394     /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
00395     ds = rpmdsLink(ds, (ds ? ds->Type : NULL));
00396     /*@=nullstate@*/
00397 
00398     return ds;
00399 /*@=compdef =usereleased@*/
00400 }
00401 
00402 /*@-mods@*/ /* FIX: correct annotations for ds->ns shadow */
00403 const char * rpmdsNewN(rpmds ds)
00404 {
00405     rpmns ns = &ds->ns;
00406     const char * Name = ds->N[ds->i];
00407     int xx;
00408 
00409     memset(ns, 0, sizeof(*ns));
00410     xx = rpmnsParse(Name, ns);
00411 
00412 /*@-usereleased -compdef@*/ /* FIX: correct annotations for ds->ns shadow */
00413     return ns->N;
00414 /*@-usereleased -compdef@*/
00415 }
00416 /*@=mods@*/
00417 
00418 char * rpmdsNewDNEVR(const char * dspfx, rpmds ds)
00419 {
00420     const char * N = rpmdsNewN(ds);
00421     const char * NS = ds->ns.NS;
00422     const char * A = ds->ns.A;
00423     int_32 dsFlags = 0;
00424     char * tbuf, * t;
00425     size_t nb = 0;
00426 
00427     if (dspfx)  nb += strlen(dspfx) + 1;
00428 /*@-boundsread@*/
00429     if (ds->ns.str[0] == '!')   nb++;
00430     if (NS)     nb += strlen(NS) + sizeof("()") - 1;
00431     if (N)      nb += strlen(N);
00432     if (A) {
00433         if (_rpmns_N_at_A && _rpmns_N_at_A[0])
00434             nb += sizeof(_rpmns_N_at_A[0]);
00435         nb += strlen(A);
00436     }
00437     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00438     if (ds->Flags != NULL
00439      && (dsFlags = (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)))
00440     {
00441         if (nb) nb++;
00442         if (dsFlags == RPMSENSE_NOTEQUAL)
00443             nb += 2;
00444         else {
00445             if (dsFlags & RPMSENSE_LESS)        nb++;
00446             if (dsFlags & RPMSENSE_GREATER)     nb++;
00447             if (dsFlags & RPMSENSE_EQUAL)       nb++;
00448         }
00449     }
00450 
00451     ds->ns.Flags = dsFlags;
00452 
00453     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00454     if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
00455         if (nb) nb++;
00456         nb += strlen(ds->EVR[ds->i]);
00457     }
00458 /*@=boundsread@*/
00459 
00460 /*@-boundswrite@*/
00461     t = tbuf = xmalloc(nb + 1);
00462     if (dspfx) {
00463         t = stpcpy(t, dspfx);
00464         *t++ = ' ';
00465     }
00466     if (ds->ns.str[0] == '!')
00467         *t++ = '!';
00468     if (NS)
00469         t = stpcpy( stpcpy(t, NS), "(");
00470     if (N)
00471         t = stpcpy(t, N);
00472     if (NS)
00473         t = stpcpy(t, ")");
00474     if (A) {
00475         if (_rpmns_N_at_A && _rpmns_N_at_A[0])
00476             *t++ = _rpmns_N_at_A[0];
00477         t = stpcpy(t, A);
00478     }
00479 
00480     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00481     if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
00482         if (t != tbuf)  *t++ = ' ';
00483         if (dsFlags == RPMSENSE_NOTEQUAL)
00484             t = stpcpy(t, "!=");
00485         else {
00486             if (dsFlags & RPMSENSE_LESS)        *t++ = '<';
00487             if (dsFlags & RPMSENSE_GREATER)     *t++ = '>';
00488             if (dsFlags & RPMSENSE_EQUAL)       *t++ = '=';
00489         }
00490     }
00491     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00492     if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
00493         if (t != tbuf)  *t++ = ' ';
00494         t = stpcpy(t, ds->EVR[ds->i]);
00495     }
00496     *t = '\0';
00497 /*@=boundswrite@*/
00498     return tbuf;
00499 }
00500 
00501 rpmds rpmdsThis(Header h, rpmTag tagN, int_32 Flags)
00502 {
00503     HGE_t hge = (HGE_t) headerGetEntryMinMemory;
00504     rpmds ds = NULL;
00505     const char * Type;
00506     const char * n, * v, * r;
00507     int_32 * ep;
00508     const char ** N, ** EVR;
00509     char * t;
00510     int xx;
00511 
00512     if (tagN == RPMTAG_PROVIDENAME) {
00513         Type = "Provides";
00514     } else
00515     if (tagN == RPMTAG_REQUIRENAME) {
00516         Type = "Requires";
00517     } else
00518     if (tagN == RPMTAG_CONFLICTNAME) {
00519         Type = "Conflicts";
00520     } else
00521     if (tagN == RPMTAG_OBSOLETENAME) {
00522         Type = "Obsoletes";
00523     } else
00524     if (tagN == RPMTAG_TRIGGERNAME) {
00525         Type = "Triggers";
00526     } else
00527     if (tagN == RPMTAG_DIRNAMES) {
00528         Type = "Dirnames";
00529     } else
00530     if (tagN == RPMTAG_FILELINKTOS) {
00531         Type = "Filelinktos";
00532     } else
00533         goto exit;
00534 
00535     xx = headerNVR(h, &n, &v, &r);
00536     ep = NULL;
00537     xx = hge(h, RPMTAG_EPOCH, NULL, &ep, NULL);
00538 
00539     t = xmalloc(sizeof(*N) + strlen(n) + 1);
00540 /*@-boundswrite@*/
00541     N = (const char **) t;
00542     t += sizeof(*N);
00543     *t = '\0';
00544     N[0] = t;
00545     t = stpcpy(t, n);
00546 
00547     t = xmalloc(sizeof(*EVR) +
00548                 (ep ? 20 : 0) + strlen(v) + strlen(r) + sizeof("-"));
00549     EVR = (const char **) t;
00550     t += sizeof(*EVR);
00551     *t = '\0';
00552     EVR[0] = t;
00553     if (ep) {
00554         sprintf(t, "%d:", *ep);
00555         t += strlen(t);
00556     }
00557     t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
00558 /*@=boundswrite@*/
00559 
00560     ds = xcalloc(1, sizeof(*ds));
00561     ds->Type = Type;
00562     ds->tagN = tagN;
00563     ds->Count = 1;
00564     ds->N = N;
00565     ds->Nt = -1;        /* XXX to insure that hfd will free */
00566     ds->EVR = EVR;
00567     ds->EVRt = -1;      /* XXX to insure that hfd will free */
00568 /*@-boundswrite@*/
00569     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
00570 /*@=boundswrite@*/
00571         {   rpmTag tagA = RPMTAG_ARCH;
00572             rpmTagType At;
00573             const char * A = NULL;
00574             if (tagA > 0)
00575                 xx = hge(h, tagA, &At, &A, NULL);
00576             ds->A = (xx && A != NULL ? xstrdup(A) : NULL);
00577         }
00578         {   rpmTag tagBT = RPMTAG_BUILDTIME;
00579             rpmTagType BTt;
00580             int_32 * BTp = NULL;
00581             if (tagBT > 0)
00582                 xx = hge(h, tagBT, &BTt, &BTp, NULL);
00583             ds->BT = (xx && BTp != NULL && BTt == RPM_INT32_TYPE ? *BTp : 0);
00584         }
00585     {   char pre[2];
00586 /*@-boundsread@*/
00587         pre[0] = ds->Type[0];
00588 /*@=boundsread@*/
00589         pre[1] = '\0';
00590         /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
00591 /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(pre, ds);
00592         /*@=nullstate@*/
00593     }
00594 
00595 exit:
00596     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00597 }
00598 
00599 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
00600 {
00601     rpmds ds = NULL;
00602     const char * Type;
00603 
00604     if (tagN == RPMTAG_PROVIDENAME) {
00605         Type = "Provides";
00606     } else
00607     if (tagN == RPMTAG_REQUIRENAME) {
00608         Type = "Requires";
00609     } else
00610     if (tagN == RPMTAG_CONFLICTNAME) {
00611         Type = "Conflicts";
00612     } else
00613     if (tagN == RPMTAG_OBSOLETENAME) {
00614         Type = "Obsoletes";
00615     } else
00616     if (tagN == RPMTAG_TRIGGERNAME) {
00617         Type = "Triggers";
00618     } else
00619     if (tagN == RPMTAG_DIRNAMES) {
00620         Type = "Dirnames";
00621     } else
00622     if (tagN == RPMTAG_FILELINKTOS) {
00623         Type = "Filelinktos";
00624     } else
00625         goto exit;
00626 
00627     ds = xcalloc(1, sizeof(*ds));
00628     ds->Type = Type;
00629     ds->tagN = tagN;
00630     ds->A = NULL;
00631     {   time_t now = time(NULL);
00632         ds->BT = now;
00633     }
00634     ds->Count = 1;
00635     /*@-assignexpose@*/
00636 /*@-boundswrite@*/
00637     ds->N = xmalloc(sizeof(*ds->N));            ds->N[0] = N;
00638     ds->Nt = -1;        /* XXX to insure that hfd will free */
00639     ds->EVR = xmalloc(sizeof(*ds->EVR));        ds->EVR[0] = EVR;
00640     ds->EVRt = -1;      /* XXX to insure that hfd will free */
00641     /*@=assignexpose@*/
00642     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
00643 /*@=boundswrite@*/
00644     {   char t[2];
00645 /*@-boundsread@*/
00646         t[0] = ds->Type[0];
00647 /*@=boundsread@*/
00648         t[1] = '\0';
00649 /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(t, ds);
00650     }
00651 
00652 exit:
00653     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00654 }
00655 
00656 int rpmdsCount(const rpmds ds)
00657 {
00658     return (ds != NULL ? ds->Count : 0);
00659 }
00660 
00661 int rpmdsIx(const rpmds ds)
00662 {
00663     return (ds != NULL ? ds->i : -1);
00664 }
00665 
00666 int rpmdsSetIx(rpmds ds, int ix)
00667 {
00668     int i = -1;
00669 
00670     if (ds != NULL) {
00671         i = ds->i;
00672         ds->i = ix;
00673     }
00674     return i;
00675 }
00676 
00677 const char * rpmdsDNEVR(const rpmds ds)
00678 {
00679     const char * DNEVR = NULL;
00680 
00681     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00682 /*@-boundsread@*/
00683         if (ds->DNEVR != NULL)
00684             DNEVR = ds->DNEVR;
00685 /*@=boundsread@*/
00686     }
00687     return DNEVR;
00688 }
00689 
00690 const char * rpmdsN(const rpmds ds)
00691 {
00692     const char * N = NULL;
00693 
00694     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00695 /*@-boundsread -globs -mods @*/ /* FIX: correct annotations for ds->ns shadow */
00696         N = (ds->ns.N ? ds->ns.N : rpmdsNewN(ds));
00697 /*@=boundsread =globs =mods @*/
00698     }
00699     return N;
00700 }
00701 
00702 const char * rpmdsEVR(const rpmds ds)
00703 {
00704     const char * EVR = NULL;
00705 
00706     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00707 /*@-boundsread@*/
00708         if (ds->EVR != NULL)
00709             EVR = ds->EVR[ds->i];
00710 /*@=boundsread@*/
00711     }
00712     return EVR;
00713 }
00714 
00715 int_32 rpmdsFlags(const rpmds ds)
00716 {
00717     int_32 Flags = 0;
00718 
00719     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00720 /*@-boundsread@*/
00721         if (ds->Flags != NULL)
00722             Flags = ds->Flags[ds->i];
00723 /*@=boundsread@*/
00724     }
00725     return Flags;
00726 }
00727 
00728 rpmTag rpmdsTagN(const rpmds ds)
00729 {
00730     rpmTag tagN = 0;
00731 
00732     if (ds != NULL)
00733         tagN = ds->tagN;
00734     return tagN;
00735 }
00736 
00737 const char * rpmdsA(const rpmds ds)
00738 {
00739     const char * A = NULL;
00740 
00741     if (ds != NULL)
00742         A = ds->A;
00743     return A;
00744 }
00745 
00746 time_t rpmdsBT(const rpmds ds)
00747 {
00748     time_t BT = 0;
00749     if (ds != NULL && ds->BT > 0)
00750         BT = ds->BT;
00751     return BT;
00752 }
00753 
00754 time_t rpmdsSetBT(const rpmds ds, time_t BT)
00755 {
00756     time_t oBT = 0;
00757     if (ds != NULL) {
00758         oBT = ds->BT;
00759         ds->BT = BT;
00760     }
00761     return oBT;
00762 }
00763 
00764 nsType rpmdsNSType(const rpmds ds)
00765 {
00766     nsType NSType = RPMNS_TYPE_UNKNOWN;
00767     if (ds != NULL)
00768         NSType = ds->ns.Type;
00769     return NSType;
00770 }
00771 
00772 int rpmdsNoPromote(const rpmds ds)
00773 {
00774     int nopromote = 0;
00775 
00776     if (ds != NULL)
00777         nopromote = ds->nopromote;
00778     return nopromote;
00779 }
00780 
00781 int rpmdsSetNoPromote(rpmds ds, int nopromote)
00782 {
00783     int onopromote = 0;
00784 
00785     if (ds != NULL) {
00786         onopromote = ds->nopromote;
00787         ds->nopromote = nopromote;
00788     }
00789     return onopromote;
00790 }
00791 
00792 void * rpmdsSetEVRparse(rpmds ds,
00793         int (*EVRparse)(const char *evrstr, EVR_t evr))
00794 {
00795     void * oEVRparse = NULL;
00796 
00797     if (ds != NULL) {
00798 /*@i@*/ oEVRparse = ds->EVRparse;
00799 /*@i@*/ ds->EVRparse = EVRparse;
00800     }
00801     return oEVRparse;
00802 }
00803 
00804 void * rpmdsSetEVRcmp(rpmds ds, int (*EVRcmp)(const char *a, const char *b))
00805 {
00806     void * oEVRcmp = NULL;
00807 
00808     if (ds != NULL) {
00809 /*@i@*/ oEVRcmp = ds->EVRcmp;
00810 /*@i@*/ ds->EVRcmp = EVRcmp;
00811     }
00812     return oEVRcmp;
00813 }
00814 
00815 uint_32 rpmdsColor(const rpmds ds)
00816 {
00817     uint_32 Color = 0;
00818 
00819     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00820 /*@-boundsread@*/
00821         if (ds->Color != NULL)
00822             Color = ds->Color[ds->i];
00823 /*@=boundsread@*/
00824     }
00825     return Color;
00826 }
00827 
00828 uint_32 rpmdsSetColor(const rpmds ds, uint_32 color)
00829 {
00830     uint_32 ocolor = 0;
00831 
00832     if (ds == NULL)
00833         return ocolor;
00834 
00835     if (ds->Color == NULL && ds->Count > 0)     /* XXX lazy malloc */
00836         ds->Color = xcalloc(ds->Count, sizeof(*ds->Color));
00837 
00838     if (ds->i >= 0 && ds->i < ds->Count) {
00839 /*@-bounds@*/
00840         if (ds->Color != NULL) {
00841             ocolor = ds->Color[ds->i];
00842             ds->Color[ds->i] = color;
00843         }
00844 /*@=bounds@*/
00845     }
00846     return ocolor;
00847 }
00848 
00849 int_32 rpmdsRefs(const rpmds ds)
00850 {
00851     int_32 Refs = 0;
00852 
00853     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00854 /*@-boundsread@*/
00855         if (ds->Refs != NULL)
00856             Refs = ds->Refs[ds->i];
00857 /*@=boundsread@*/
00858     }
00859     return Refs;
00860 }
00861 
00862 int_32 rpmdsSetRefs(const rpmds ds, int_32 refs)
00863 {
00864     int_32 orefs = 0;
00865 
00866     if (ds == NULL)
00867         return orefs;
00868 
00869     if (ds->Refs == NULL && ds->Count > 0)      /* XXX lazy malloc */
00870         ds->Refs = xcalloc(ds->Count, sizeof(*ds->Refs));
00871 
00872     if (ds->i >= 0 && ds->i < ds->Count) {
00873 /*@-bounds@*/
00874         if (ds->Refs != NULL) {
00875             orefs = ds->Refs[ds->i];
00876             ds->Refs[ds->i] = refs;
00877         }
00878 /*@=bounds@*/
00879     }
00880     return orefs;
00881 }
00882 
00883 int_32 rpmdsResult(const rpmds ds)
00884 {
00885     int_32 result = 0;
00886 
00887     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00888 /*@-boundsread@*/
00889         if (ds->Result != NULL)
00890             result = ds->Result[ds->i];
00891 /*@=boundsread@*/
00892     }
00893     return result;
00894 }
00895 
00896 int_32 rpmdsSetResult(const rpmds ds, int_32 result)
00897 {
00898     int_32 oresult = 0;
00899 
00900     if (ds == NULL)
00901         return oresult;
00902 
00903     if (ds->Result == NULL && ds->Count > 0)    /* XXX lazy malloc */
00904         ds->Result = xcalloc(ds->Count, sizeof(*ds->Result));
00905 
00906     if (ds->i >= 0 && ds->i < ds->Count) {
00907 /*@-bounds@*/
00908         if (ds->Result != NULL) {
00909             oresult = ds->Result[ds->i];
00910             ds->Result[ds->i] = result;
00911         }
00912 /*@=bounds@*/
00913     }
00914     return oresult;
00915 }
00916 
00917 void rpmdsNotify(rpmds ds, const char * where, int rc)
00918 {
00919     if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
00920         return;
00921     if (!(ds->Type != NULL && ds->DNEVR != NULL))
00922         return;
00923 
00924     rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
00925                 (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
00926                 (rc ? _("NO ") : _("YES")),
00927                 (where != NULL ? where : ""));
00928 }
00929 
00930 int rpmdsNext(/*@null@*/ rpmds ds)
00931         /*@modifies ds @*/
00932 {
00933     int i = -1;
00934 
00935     if (ds != NULL && ++ds->i >= 0) {
00936         if (ds->i < ds->Count) {
00937             char t[2];
00938             i = ds->i;
00939             ds->DNEVR = _free(ds->DNEVR);
00940             ds->ns.str = _free(ds->ns.str);
00941             memset(&ds->ns, 0, sizeof(ds->ns));
00942             t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
00943             t[1] = '\0';
00944             /*@-nullstate@*/
00945            /*@i@*/ ds->DNEVR = rpmdsNewDNEVR(t, ds);
00946             /*@=nullstate@*/
00947 
00948         } else
00949             ds->i = -1;
00950 
00951 /*@-modfilesys @*/
00952 if (_rpmds_debug  < 0 && i != -1)
00953 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
00954 /*@=modfilesys @*/
00955 
00956     }
00957 
00958     return i;
00959 }
00960 
00961 rpmds rpmdsInit(/*@null@*/ rpmds ds)
00962         /*@modifies ds @*/
00963 {
00964     if (ds != NULL)
00965         ds->i = -1;
00966     /*@-refcounttrans@*/
00967     return ds;
00968     /*@=refcounttrans@*/
00969 }
00970 
00971 /*@null@*/
00972 static rpmds rpmdsDup(const rpmds ods)
00973         /*@modifies ods @*/
00974 {
00975     rpmds ds = xcalloc(1, sizeof(*ds));
00976     size_t nb;
00977 
00978     ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
00979 /*@-assignexpose@*/
00980     ds->Type = ods->Type;
00981 /*@=assignexpose@*/
00982     ds->tagN = ods->tagN;
00983     ds->Count = ods->Count;
00984     ds->i = ods->i;
00985     ds->l = ods->l;
00986     ds->u = ods->u;
00987 
00988     nb = (ds->Count+1) * sizeof(*ds->N);
00989     ds->N = (ds->h != NULL
00990         ? memcpy(xmalloc(nb), ods->N, nb)
00991         : rpmdsDupArgv(ods->N, ods->Count) );
00992     ds->Nt = ods->Nt;
00993 
00994     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00995 assert(ods->EVR != NULL);
00996 assert(ods->Flags != NULL);
00997 
00998     nb = (ds->Count+1) * sizeof(*ds->EVR);
00999     ds->EVR = (ds->h != NULL
01000         ? memcpy(xmalloc(nb), ods->EVR, nb)
01001         : rpmdsDupArgv(ods->EVR, ods->Count) );
01002     ds->EVRt = ods->EVRt;
01003 
01004     nb = (ds->Count * sizeof(*ds->Flags));
01005     ds->Flags = (ds->h != NULL
01006         ? ods->Flags
01007         : memcpy(xmalloc(nb), ods->Flags, nb) );
01008     ds->Ft = ods->Ft;
01009     ds->nopromote = ods->nopromote;
01010 /*@-assignexpose@*/
01011     ds->EVRcmp = ods->EVRcmp;;
01012 /*@=assignexpose@*/
01013 
01014 /*@-compmempass@*/ /* FIX: ds->Flags is kept, not only */
01015     return rpmdsLink(ds, (ds ? ds->Type : NULL));
01016 /*@=compmempass@*/
01017 
01018 }
01019 
01020 int rpmdsFind(rpmds ds, const rpmds ods)
01021 {
01022     int comparison;
01023 
01024     if (ds == NULL || ods == NULL)
01025         return -1;
01026 
01027     ds->l = 0;
01028     ds->u = ds->Count;
01029     while (ds->l < ds->u) {
01030         ds->i = (ds->l + ds->u) / 2;
01031 
01032         comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
01033 
01034         /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
01035 /*@-nullderef@*/
01036         if (comparison == 0 && ods->EVR && ds->EVR)
01037             comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
01038         if (comparison == 0 && ods->Flags && ds->Flags)
01039             comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
01040 /*@=nullderef@*/
01041 
01042         if (comparison < 0)
01043             ds->u = ds->i;
01044         else if (comparison > 0)
01045             ds->l = ds->i + 1;
01046         else
01047             return ds->i;
01048     }
01049     return -1;
01050 }
01051 
01052 int rpmdsMerge(rpmds * dsp, rpmds ods)
01053 {
01054     rpmds ds;
01055     const char ** N;
01056     const char ** EVR;
01057     int_32 * Flags;
01058     int j;
01059 int save;
01060 
01061     if (dsp == NULL || ods == NULL)
01062         return -1;
01063 
01064     /* If not initialized yet, dup the 1st entry. */
01065 /*@-branchstate@*/
01066     if (*dsp == NULL) {
01067         save = ods->Count;
01068         ods->Count = 1;
01069         *dsp = rpmdsDup(ods);
01070         ods->Count = save;
01071     }
01072 /*@=branchstate@*/
01073     ds = *dsp;
01074     if (ds == NULL)
01075         return -1;
01076 
01077     /*
01078      * Add new entries.
01079      */
01080 save = ods->i;
01081     ods = rpmdsInit(ods);
01082     if (ods != NULL)
01083     while (rpmdsNext(ods) >= 0) {
01084         /*
01085          * If this entry is already present, don't bother.
01086          */
01087         if (rpmdsFind(ds, ods) >= 0)
01088             continue;
01089 
01090         /*
01091          * Insert new entry.
01092          */
01093         for (j = ds->Count; j > ds->u; j--)
01094             ds->N[j] = ds->N[j-1];
01095         ds->N[ds->u] = ods->N[ods->i];
01096         N = rpmdsDupArgv(ds->N, ds->Count+1);
01097         ds->N = _free(ds->N);
01098         ds->N = N;
01099         
01100         /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
01101 /*@-nullderef -nullpass -nullptrarith @*/
01102 assert(ods->EVR != NULL);
01103 assert(ods->Flags != NULL);
01104 
01105         for (j = ds->Count; j > ds->u; j--)
01106             ds->EVR[j] = ds->EVR[j-1];
01107         ds->EVR[ds->u] = ods->EVR[ods->i];
01108         EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
01109         ds->EVR = _free(ds->EVR);
01110         ds->EVR = EVR;
01111 
01112         Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
01113         if (ds->u > 0)
01114             memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
01115         if (ds->u < ds->Count)
01116             memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
01117         Flags[ds->u] = ods->Flags[ods->i];
01118         ds->Flags = _free(ds->Flags);
01119         ds->Flags = Flags;
01120 /*@=nullderef =nullpass =nullptrarith @*/
01121 
01122         ds->i = ds->Count;
01123         ds->Count++;
01124 
01125     }
01126 /*@-nullderef@*/
01127 ods->i = save;
01128 /*@=nullderef@*/
01129     return 0;
01130 }
01131 
01132 int rpmdsSearch(rpmds ds, rpmds ods)
01133 {
01134     int comparison;
01135     int i, l, u;
01136 
01137     if (ds == NULL || ods == NULL)
01138         return -1;
01139 
01140     /* Binary search to find the [l,u) subset that contains N */
01141     i = -1;
01142     l = 0;
01143     u = ds->Count;
01144     while (l < u) {
01145         i = (l + u) / 2;
01146 
01147         comparison = strcmp(ods->N[ods->i], ds->N[i]);
01148 
01149         if (comparison < 0)
01150             u = i;
01151         else if (comparison > 0)
01152             l = i + 1;
01153         else {
01154             /* Set l to 1st member of set that contains N. */
01155             if (strcmp(ods->N[ods->i], ds->N[l]))
01156                 l = i;
01157             while (l > 0 && !strcmp(ods->N[ods->i], ds->N[l-1]))
01158                 l--;
01159             /* Set u to 1st member of set that does not contain N. */
01160             if (u >= ds->Count || strcmp(ods->N[ods->i], ds->N[u]))
01161                 u = i;
01162             while (++u < ds->Count) {
01163                 if (strcmp(ods->N[ods->i], ds->N[u]))
01164                     /*@innerbreak@*/ break;
01165             }
01166             break;
01167         }
01168     }
01169 
01170     /* Check each member of [l,u) subset for ranges overlap. */
01171     i = -1;
01172     if (l < u) {
01173         int save = rpmdsSetIx(ds, l-1);
01174         while ((l = rpmdsNext(ds)) >= 0 && (l < u)) {
01175             if ((i = rpmdsCompare(ods, ds)) != 0)
01176                 break;
01177         }
01178         /* Return element index that overlaps, or -1. */
01179         if (i)
01180             i = rpmdsIx(ds);
01181         else {
01182             (void) rpmdsSetIx(ds, save);
01183             i = -1;
01184         }
01185         /* Save the return value. */
01186         if (ods->Result != NULL)
01187             (void) rpmdsSetResult(ods, (i != -1 ? 1 : 0));
01188     }
01189     return i;
01190 }
01191 
01192 struct cpuinfo_s {
01193 /*@observer@*/ /*@null@*/
01194     const char *name;
01195     int done;
01196     int flags;
01197 };
01198 
01199 /*@unchecked@*/
01200 static struct cpuinfo_s ctags[] = {
01201     { "processor",      0,  0 },
01202     { "vendor_id",      0,  0 },
01203     { "cpu_family",     0,  1 },
01204     { "model",          0,  1 },
01205     { "model_name",     0,  0 },
01206     { "stepping",       0,  1 },
01207     { "cpu_MHz",        0,  1 },
01208     { "cache_size",     0,  1 },
01209     { "physical_id",    0,  0 },
01210     { "siblings",       0,  0 },
01211     { "core_id",        0,  0 },
01212     { "cpu_cores",      0,  0 },
01213     { "fdiv_bug",       0,  3 },
01214     { "hlt_bug",        0,  3 },
01215     { "f00f_bug",       0,  3 },
01216     { "coma_bug",       0,  3 },
01217     { "fpu",            0,  0 },        /* XXX use flags attribute instead. */
01218     { "fpu_exception",  0,  3 },
01219     { "cpuid_level",    0,  0 },
01220     { "wp",             0,  3 },
01221     { "flags",          0,  4 },
01222     { "bogomips",       0,  1 },
01223     { NULL,             0, -1 }
01224 };
01225 
01231 static int rpmdsCpuinfoCtagFlags(const char * name)
01232         /*@globals ctags @*/
01233         /*@modifies ctags @*/
01234 {
01235     struct cpuinfo_s * ct;
01236     int flags = -1;
01237 
01238     for (ct = ctags; ct->name != NULL; ct++) {
01239         if (strcmp(ct->name, name))
01240             continue;
01241         if (ct->done)
01242             continue;
01243         ct->done = 1;           /* XXX insure single occurrence */
01244         flags = ct->flags;
01245         break;
01246     }
01247     return flags;
01248 }
01249 
01258 static void rpmdsNSAdd(/*@out@*/ rpmds *dsp, const char * NS,
01259                 const char *N, const char *EVR, int_32 Flags)
01260         /*@modifies *dsp @*/
01261 {
01262     char *t;
01263     rpmds ds;
01264     int xx;
01265 
01266     t = alloca(strlen(NS)+sizeof("()")+strlen(N));
01267     *t = '\0';
01268     (void) stpcpy( stpcpy( stpcpy( stpcpy(t, NS), "("), N), ")");
01269 
01270     ds = rpmdsSingle(RPMTAG_PROVIDENAME, t, EVR, Flags);
01271     xx = rpmdsMerge(dsp, ds);
01272     ds = rpmdsFree(ds);
01273 }
01274 
01275 #define _PROC_CPUINFO   "/proc/cpuinfo"
01276 
01278 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
01279 static const char * _cpuinfo_path = NULL;
01280 
01281 int rpmdsCpuinfo(rpmds *dsp, const char * fn)
01282         /*@globals _cpuinfo_path, ctags @*/
01283         /*@modifies _cpuinfo_path, ctags @*/
01284 {
01285     struct cpuinfo_s * ct;
01286     const char * NS = "cpuinfo";
01287     char buf[BUFSIZ];
01288     char * f, * fe;
01289     char * g, * ge;
01290     char * t;
01291     FD_t fd = NULL;
01292     FILE * fp;
01293     int rc = -1;
01294 
01295 /*@-modobserver@*/
01296     if (_cpuinfo_path == NULL) {
01297         _cpuinfo_path = rpmExpand("%{?_rpmds_cpuinfo_path}", NULL);
01298         /* XXX may need to validate path existence somewhen. */
01299         if (!(_cpuinfo_path != NULL && *_cpuinfo_path == '/')) {
01300 /*@-observertrans @*/
01301             _cpuinfo_path = _free(_cpuinfo_path);
01302 /*@=observertrans @*/
01303             _cpuinfo_path = xstrdup(_PROC_CPUINFO);
01304         }
01305     }
01306 /*@=modobserver@*/
01307 
01308 /*@-branchstate@*/
01309     if (fn == NULL)
01310         fn = _cpuinfo_path;
01311 /*@=branchstate@*/
01312 
01313     /* Reset done variables. */
01314     for (ct = ctags; ct->name != NULL; ct++)
01315         ct->done = 0;
01316 
01317     fd = Fopen(fn, "r.fpio");
01318     if (fd == NULL || Ferror(fd))
01319         goto exit;
01320     fp = fdGetFILE(fd);
01321 
01322     if (fp != NULL)
01323     while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
01324         /* rtrim on line. */
01325         ge = f + strlen(f);
01326         while (--ge > f && _isspace(*ge))
01327             *ge = '\0';
01328 
01329         /* ltrim on line. */
01330         while (*f && _isspace(*f))
01331             f++;
01332 
01333         /* split on ':' */
01334         fe = f;
01335         while (*fe && *fe != ':')
01336             fe++;
01337         if (*fe == '\0')
01338             continue;
01339         g = fe + 1;
01340 
01341         /* rtrim on field 1. */
01342         *fe = '\0';
01343         while (--fe > f && _isspace(*fe))
01344             *fe = '\0';
01345         if (*f == '\0')
01346             continue;
01347 
01348         /* ltrim on field 2. */
01349         while (*g && _isspace(*g))
01350             g++;
01351         if (*g == '\0')
01352             continue;
01353 
01354         for (t = f; *t != '\0'; t++) {
01355             if (_isspace(*t))
01356                 *t = '_';
01357         }
01358 
01359         switch (rpmdsCpuinfoCtagFlags(f)) {
01360         case -1:        /* not found */
01361         case 0:         /* ignore */
01362         default:
01363             continue;
01364             /*@notreached@*/ /*@switchbreak@*/ break;
01365         case 1:         /* Provides: cpuinfo(f) = g */
01366             for (t = g; *t != '\0'; t++) {
01367                 if (_isspace(*t) || *t == '(' || *t == ')')
01368                     *t = '_';
01369             }
01370             rpmdsNSAdd(dsp, NS, f, g, RPMSENSE_PROBE|RPMSENSE_EQUAL);
01371             /*@switchbreak@*/ break;
01372         case 2:         /* Provides: cpuinfo(g) */
01373             for (t = g; *t != '\0'; t++) {
01374                 if (_isspace(*t) || *t == '(' || *t == ')')
01375                     *t = '_';
01376             }
01377             rpmdsNSAdd(dsp, NS, g, "", RPMSENSE_PROBE);
01378             /*@switchbreak@*/ break;
01379         case 3:         /* if ("yes") Provides: cpuinfo(f) */
01380            if (!strcmp(g, "yes"))
01381                 rpmdsNSAdd(dsp, NS, f, "", RPMSENSE_PROBE);
01382             /*@switchbreak@*/ break;
01383         case 4:         /* Provides: cpuinfo(g[i]) */
01384         {   char ** av = NULL;
01385             int i = 0;
01386             rc = poptParseArgvString(g, NULL, (const char ***)&av);
01387             if (!rc && av != NULL)
01388             while ((t = av[i++]) != NULL)
01389                 rpmdsNSAdd(dsp, NS, t, "", RPMSENSE_PROBE);
01390             t = NULL;
01391             if (av != NULL)
01392                 free(av);
01393         }   /*@switchbreak@*/ break;
01394         }
01395     }
01396 
01397 exit:
01398 /*@-branchstate@*/
01399     if (fd != NULL) (void) Fclose(fd);
01400 /*@=branchstate@*/
01401     return rc;
01402 }
01403 
01404 struct rpmlibProvides_s {
01405 /*@observer@*/ /*@relnull@*/
01406     const char * featureName;
01407 /*@observer@*/ /*@relnull@*/
01408     const char * featureEVR;
01409     int featureFlags;
01410 /*@observer@*/ /*@relnull@*/
01411     const char * featureDescription;
01412 };
01413 
01414 /*@unchecked@*/ /*@observer@*/
01415 static struct rpmlibProvides_s rpmlibProvides[] = {
01416     { "rpmlib(VersionedDependencies)",  "3.0.3-1",
01417         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01418     N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
01419     { "rpmlib(CompressedFileNames)",    "3.0.4-1",
01420         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01421     N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
01422     { "rpmlib(PayloadIsBzip2)",         "3.0.5-1",
01423         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01424     N_("package payload can be compressed using bzip2.") },
01425     { "rpmlib(PayloadFilesHavePrefix)", "4.0-1",
01426         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01427     N_("package payload file(s) have \"./\" prefix.") },
01428     { "rpmlib(ExplicitPackageProvide)", "4.0-1",
01429         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01430     N_("package name-version-release is not implicitly provided.") },
01431     { "rpmlib(HeaderLoadSortsTags)",    "4.0.1-1",
01432         (                RPMSENSE_EQUAL),
01433     N_("header tags are always sorted after being loaded.") },
01434     { "rpmlib(ScriptletInterpreterArgs)",    "4.0.3-1",
01435         (                RPMSENSE_EQUAL),
01436     N_("the scriptlet interpreter can use arguments from header.") },
01437     { "rpmlib(PartialHardlinkSets)",    "4.0.4-1",
01438         (                RPMSENSE_EQUAL),
01439     N_("a hardlink file set may be installed without being complete.") },
01440     { "rpmlib(ConcurrentAccess)",    "4.1-1",
01441         (                RPMSENSE_EQUAL),
01442     N_("package scriptlets may access the rpm database while installing.") },
01443 #if defined(WITH_LUA)
01444     { "rpmlib(BuiltinLuaScripts)",    "4.2.2-1",
01445         (                RPMSENSE_EQUAL),
01446     N_("internal support for lua scripts.") },
01447 #endif
01448     { "rpmlib(HeaderTagTypeInt64)",    "4.4.3-1",
01449         (                RPMSENSE_EQUAL),
01450     N_("header tags can be type int_64.") },
01451     { "rpmlib(PayloadIsUstar)",         "4.4.4-1",
01452         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01453     N_("package payload can be in ustar tar archive format.") },
01454     { "rpmlib(PayloadIsLzma)",          "4.4.6-1",
01455         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01456     N_("package payload can be compressed using lzma.") },
01457     { "rpmlib(FileDigestParameterized)",    "4.4.6-1",
01458         (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
01459     N_("file digests can be other than MD5.") },
01460     { NULL,                             NULL, 0,        NULL }
01461 };
01462 
01469 int rpmdsRpmlib(rpmds * dsp, void * tblp)
01470 {
01471     const struct rpmlibProvides_s * rltblp = tblp;
01472     const struct rpmlibProvides_s * rlp;
01473     int xx;
01474 
01475     if (rltblp == NULL)
01476         rltblp = rpmlibProvides;
01477 
01478     for (rlp = rltblp; rlp->featureName != NULL; rlp++) {
01479         rpmds ds = rpmdsSingle(RPMTAG_PROVIDENAME, rlp->featureName,
01480                         rlp->featureEVR, rlp->featureFlags);
01481         xx = rpmdsMerge(dsp, ds);
01482         ds = rpmdsFree(ds);
01483     }
01484     return 0;
01485 }
01486 
01494 static int rpmdsSysinfoFile(rpmPRCO PRCO, const char * fn, int tagN)
01495         /*@globals h_errno, fileSystem, internalState @*/
01496         /*@modifies PRCO, fileSystem, internalState @*/
01497 {
01498     char buf[BUFSIZ];
01499     const char *N, *EVR;
01500     int_32 Flags;
01501     rpmds ds;
01502     char * f, * fe;
01503     char * g, * ge;
01504     FD_t fd = NULL;
01505     FILE * fp;
01506     int rc = -1;
01507     int ln;
01508     int xx;
01509 
01510     /* XXX for now, collect Dirnames/Filelinktos in Providename */
01511     if (tagN == RPMTAG_DIRNAMES || tagN == RPMTAG_FILELINKTOS)
01512         tagN = RPMTAG_PROVIDENAME;
01513 
01514 assert(fn != NULL);
01515     fd = Fopen(fn, "r.fpio");
01516     if (fd == NULL || Ferror(fd))
01517         goto exit;
01518     fp = fdGetFILE(fd);
01519 
01520     ln = 0;
01521     if (fp != NULL)
01522     while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
01523         ln++;
01524 
01525         /* insure a terminator. */
01526         buf[sizeof(buf)-1] = '\0';
01527 
01528         /* ltrim on line. */
01529         while (*f && _isspace(*f))
01530             f++;
01531 
01532         /* XXX skip YAML "- " markup */
01533         if (f[0] == '-' && _isspace(f[1])) {
01534             f += sizeof("- ")-1;
01535             while (*f && _isspace(*f))
01536                 f++;
01537         }
01538 
01539         /* skip empty lines and comments */
01540         if (*f == '\0' || *f == '#')
01541             continue;
01542 
01543         /* rtrim on line. */
01544         fe = f + strlen(f);
01545         while (--fe > f && _isspace(*fe))
01546             *fe = '\0';
01547 
01548         if (!(xisalnum(f[0]) || strchr("/_%!", f[0]) != NULL)) {
01549             fprintf(stderr, _("%s:%d \"%s\" has invalid name. Skipping ...\n"),
01550                     fn, ln, f);
01551             continue;
01552         }
01553 
01554         /* split on ' '  or comparison operator. */
01555         fe = f;
01556         if (*f == '!') fe++;
01557         while (*fe && !_isspace(*fe) && strchr("!<=>", *fe) == NULL)
01558             fe++;
01559         while (*fe && _isspace(*fe))
01560             *fe++ = '\0';
01561 
01562         N = f;
01563         EVR = NULL;
01564         Flags = 0;
01565 
01566         /* parse for non-path, versioned dependency. */
01567 /*@-branchstate@*/
01568         if (*f != '/' && *fe != '\0') {
01569             /* parse comparison operator */
01570             g = fe;
01571             Flags = rpmEVRflags(fe, (const char **)&g);
01572             if (Flags == 0) {
01573                 fprintf(stderr, _("%s:%d \"%s\" has no comparison operator. Skipping ...\n"),
01574                         fn, ln, fe);
01575                 continue;
01576             }
01577             *fe = '\0';
01578 
01579             /* ltrim on field 2. */
01580             while (*g && _isspace(*g))
01581                 g++;
01582             if (*g == '\0') {
01583                 /* XXX No EVR comparison value found. */
01584                 fprintf(stderr, _("%s:%d \"%s\" has no EVR string. Skipping ...\n"),
01585                         fn, ln, f);
01586                 continue;
01587             }
01588 
01589             ge = g + 1;
01590             while (*ge && !_isspace(*ge))
01591                 ge++;
01592 
01593             if (*ge != '\0')
01594                 *ge = '\0';     /* XXX can't happen, line rtrim'ed already. */
01595 
01596             EVR = g;
01597         }
01598 
01599         if (EVR == NULL)
01600             EVR = "";
01601         Flags |= RPMSENSE_PROBE;
01602 /*@=branchstate@*/
01603         ds = rpmdsSingle(tagN, N, EVR , Flags);
01604         if (ds) {       /* XXX can't happen */
01605             xx = rpmdsMergePRCO(PRCO, ds);
01606             ds = rpmdsFree(ds);
01607         }
01608     }
01609     rc = 0;
01610 
01611 exit:
01612 /*@-branchstate@*/
01613     if (fd != NULL) (void) Fclose(fd);
01614 /*@=branchstate@*/
01615     return rc;
01616 }
01617 
01618 #define _ETC_RPM_SYSINFO        "/etc/rpm/sysinfo"
01619 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
01620 static const char *_sysinfo_path = NULL;
01621 
01622 /*@unchecked@*/ /*@observer@*/ /*@relnull@*/
01623 static const char *_sysinfo_tags[] = {
01624     "Providename",
01625     "Requirename",
01626     "Conflictname",
01627     "Obsoletename",
01628     "Dirnames",
01629     "Filelinktos",
01630     NULL
01631 };
01632 
01633 int rpmdsSysinfo(rpmPRCO PRCO, const char * fn)
01634         /*@globals _sysinfo_path @*/
01635         /*@modifies _sysinfo_path @*/
01636 {
01637     struct stat * st = memset(alloca(sizeof(*st)), 0, sizeof(*st));
01638     int rc = -1;
01639     int xx;
01640 
01641 /*@-modobserver@*/
01642     if (_sysinfo_path == NULL) {
01643         _sysinfo_path = rpmExpand("%{?_rpmds_sysinfo_path}", NULL);
01644         /* XXX may need to validate path existence somewhen. */
01645         if (!(_sysinfo_path != NULL && *_sysinfo_path == '/')) {
01646 /*@-observertrans @*/
01647             _sysinfo_path = _free(_sysinfo_path);
01648 /*@=observertrans @*/
01649             _sysinfo_path = rpmGetPath(_ETC_RPM_SYSINFO, NULL);
01650         }
01651     }
01652 /*@=modobserver@*/
01653 
01654 /*@-branchstate@*/
01655     if (fn == NULL)
01656         fn = _sysinfo_path;
01657 /*@=branchstate@*/
01658 
01659     if (fn == NULL)
01660         goto exit;
01661 
01662     xx = Stat(fn, st);
01663     if (xx < 0)
01664         goto exit;
01665 
01666     if (S_ISDIR(st->st_mode)) {
01667         const char *dn = fn;
01668         const char **av;
01669         int tagN;
01670         rc = 0;         /* assume success */
01671 /*@-branchstate@*/
01672         for (av = _sysinfo_tags; av && *av; av++) {
01673             tagN = tagValue(*av);
01674             if (tagN < 0)
01675                 continue;
01676             fn = rpmGetPath(dn, "/", *av, NULL);
01677             st = memset(st, 0, sizeof(*st));
01678             xx = Stat(fn, st);
01679             if (xx == 0 && S_ISREG(st->st_mode))
01680                 rc = rpmdsSysinfoFile(PRCO, fn, tagN);
01681             fn = _free(fn);
01682             if (rc)
01683                 break;
01684         }
01685 /*@=branchstate@*/
01686     } else
01687     /* XXX for now, collect Dirnames/Filelinktos in Providename */
01688     if (S_ISREG(st->st_mode))
01689         rc = rpmdsSysinfoFile(PRCO, fn, RPMTAG_PROVIDENAME);
01690 
01691 exit:
01692     return rc;
01693 }
01694 
01695 struct conf {
01696 /*@observer@*/ /*@relnull@*/
01697     const char *name;
01698     const int call_name;
01699     const enum { SYSCONF, CONFSTR, PATHCONF } call;
01700 };
01701 
01702 /*@unchecked@*/ /*@observer@*/
01703 static const struct conf vars[] = {
01704 #ifdef _PC_LINK_MAX
01705     { "LINK_MAX", _PC_LINK_MAX, PATHCONF },
01706 #endif
01707 #ifdef _PC_LINK_MAX
01708     { "_POSIX_LINK_MAX", _PC_LINK_MAX, PATHCONF },
01709 #endif
01710 #ifdef _PC_MAX_CANON
01711     { "MAX_CANON", _PC_MAX_CANON, PATHCONF },
01712 #endif
01713 #ifdef _PC_MAX_CANON
01714     { "_POSIX_MAX_CANON", _PC_MAX_CANON, PATHCONF },
01715 #endif
01716 #ifdef _PC_MAX_INPUT
01717     { "MAX_INPUT", _PC_MAX_INPUT, PATHCONF },
01718 #endif
01719 #ifdef _PC_MAX_INPUT
01720     { "_POSIX_MAX_INPUT", _PC_MAX_INPUT, PATHCONF },
01721 #endif
01722 #ifdef _PC_NAME_MAX
01723     { "NAME_MAX", _PC_NAME_MAX, PATHCONF },
01724 #endif
01725 #ifdef _PC_NAME_MAX
01726     { "_POSIX_NAME_MAX", _PC_NAME_MAX, PATHCONF },
01727 #endif
01728 #ifdef _PC_PATH_MAX
01729     { "PATH_MAX", _PC_PATH_MAX, PATHCONF },
01730 #endif
01731 #ifdef _PC_PATH_MAX
01732     { "_POSIX_PATH_MAX", _PC_PATH_MAX, PATHCONF },
01733 #endif
01734 #ifdef _PC_PIPE_BUF
01735     { "PIPE_BUF", _PC_PIPE_BUF, PATHCONF },
01736 #endif
01737 #ifdef _PC_PIPE_BUF
01738     { "_POSIX_PIPE_BUF", _PC_PIPE_BUF, PATHCONF },
01739 #endif
01740 #ifdef _PC_SOCK_MAXBUF
01741     { "SOCK_MAXBUF", _PC_SOCK_MAXBUF, PATHCONF },
01742 #endif
01743 #ifdef _PC_ASYNC_IO
01744     { "_POSIX_ASYNC_IO", _PC_ASYNC_IO, PATHCONF },
01745 #endif
01746 #ifdef _PC_CHOWN_RESTRICTED
01747     { "_POSIX_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED, PATHCONF },
01748 #endif
01749 #ifdef _PC_NO_TRUNC
01750     { "_POSIX_NO_TRUNC", _PC_NO_TRUNC, PATHCONF },
01751 #endif
01752 #ifdef _PC_PRIO_IO
01753     { "_POSIX_PRIO_IO", _PC_PRIO_IO, PATHCONF },
01754 #endif
01755 #ifdef _PC_SYNC_IO
01756     { "_POSIX_SYNC_IO", _PC_SYNC_IO, PATHCONF },
01757 #endif
01758 #ifdef _PC_VDISABLE
01759     { "_POSIX_VDISABLE", _PC_VDISABLE, PATHCONF },
01760 #endif
01761 
01762 #ifdef _SC_ARG_MAX
01763     { "ARG_MAX", _SC_ARG_MAX, SYSCONF },
01764 #endif
01765 #ifdef _SC_ATEXIT_MAX
01766     { "ATEXIT_MAX", _SC_ATEXIT_MAX, SYSCONF },
01767 #endif
01768 #ifdef _SC_CHAR_BIT
01769     { "CHAR_BIT", _SC_CHAR_BIT, SYSCONF },
01770 #endif
01771 #ifdef _SC_CHAR_MAX
01772     { "CHAR_MAX", _SC_CHAR_MAX, SYSCONF },
01773 #endif
01774 #ifdef _SC_CHAR_MIN
01775     { "CHAR_MIN", _SC_CHAR_MIN, SYSCONF },
01776 #endif
01777 #ifdef _SC_CHILD_MAX
01778     { "CHILD_MAX", _SC_CHILD_MAX, SYSCONF },
01779 #endif
01780 #ifdef _SC_CLK_TCK
01781     { "CLK_TCK", _SC_CLK_TCK, SYSCONF },
01782 #endif
01783 #ifdef _SC_INT_MAX
01784     { "INT_MAX", _SC_INT_MAX, SYSCONF },
01785 #endif
01786 #ifdef _SC_INT_MIN
01787     { "INT_MIN", _SC_INT_MIN, SYSCONF },
01788 #endif
01789 #ifdef _SC_UIO_MAXIOV
01790     { "IOV_MAX", _SC_UIO_MAXIOV, SYSCONF },
01791 #endif
01792 #ifdef _SC_LOGIN_NAME_MAX
01793     { "LOGNAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF },
01794 #endif
01795 #ifdef _SC_LONG_BIT
01796     { "LONG_BIT", _SC_LONG_BIT, SYSCONF },
01797 #endif
01798 #ifdef _SC_MB_LEN_MAX
01799     { "MB_LEN_MAX", _SC_MB_LEN_MAX, SYSCONF },
01800 #endif
01801 #ifdef _SC_NGROUPS_MAX
01802     { "NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF },
01803 #endif
01804 #ifdef _SC_NL_ARGMAX
01805     { "NL_ARGMAX", _SC_NL_ARGMAX, SYSCONF },
01806 #endif
01807 #ifdef _SC_NL_LANGMAX
01808     { "NL_LANGMAX", _SC_NL_LANGMAX, SYSCONF },
01809 #endif
01810 #ifdef _SC_NL_MSGMAX
01811     { "NL_MSGMAX", _SC_NL_MSGMAX, SYSCONF },
01812 #endif
01813 #ifdef _SC_NL_NMAX
01814     { "NL_NMAX", _SC_NL_NMAX, SYSCONF },
01815 #endif
01816 #ifdef _SC_NL_SETMAX
01817     { "NL_SETMAX", _SC_NL_SETMAX, SYSCONF },
01818 #endif
01819 #ifdef _SC_NL_TEXTMAX
01820     { "NL_TEXTMAX", _SC_NL_TEXTMAX, SYSCONF },
01821 #endif
01822 #ifdef _SC_GETGR_R_SIZE_MAX
01823     { "NSS_BUFLEN_GROUP", _SC_GETGR_R_SIZE_MAX, SYSCONF },
01824 #endif
01825 #ifdef _SC_GETPW_R_SIZE_MAX
01826     { "NSS_BUFLEN_PASSWD", _SC_GETPW_R_SIZE_MAX, SYSCONF },
01827 #endif
01828 #ifdef _SC_NZERO
01829     { "NZERO", _SC_NZERO, SYSCONF },
01830 #endif
01831 #ifdef _SC_OPEN_MAX
01832     { "OPEN_MAX", _SC_OPEN_MAX, SYSCONF },
01833 #endif
01834 #ifdef _SC_PAGESIZE
01835     { "PAGESIZE", _SC_PAGESIZE, SYSCONF },
01836 #endif
01837 #ifdef _SC_PAGESIZE
01838     { "PAGE_SIZE", _SC_PAGESIZE, SYSCONF },
01839 #endif
01840 #ifdef _SC_PASS_MAX
01841     { "PASS_MAX", _SC_PASS_MAX, SYSCONF },
01842 #endif
01843 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
01844     { "PTHREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS, SYSCONF },
01845 #endif
01846 #ifdef _SC_THREAD_KEYS_MAX
01847     { "PTHREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX, SYSCONF },
01848 #endif
01849 #ifdef _SC_THREAD_STACK_MIN
01850     { "PTHREAD_STACK_MIN", _SC_THREAD_STACK_MIN, SYSCONF },
01851 #endif
01852 #ifdef _SC_THREAD_THREADS_MAX
01853     { "PTHREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX, SYSCONF },
01854 #endif
01855 #ifdef _SC_SCHAR_MAX
01856     { "SCHAR_MAX", _SC_SCHAR_MAX, SYSCONF },
01857 #endif
01858 #ifdef _SC_SCHAR_MIN
01859     { "SCHAR_MIN", _SC_SCHAR_MIN, SYSCONF },
01860 #endif
01861 #ifdef _SC_SHRT_MAX
01862     { "SHRT_MAX", _SC_SHRT_MAX, SYSCONF },
01863 #endif
01864 #ifdef _SC_SHRT_MIN
01865     { "SHRT_MIN", _SC_SHRT_MIN, SYSCONF },
01866 #endif
01867 #ifdef _SC_SSIZE_MAX
01868     { "SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF },
01869 #endif
01870 #ifdef _SC_TTY_NAME_MAX
01871     { "TTY_NAME_MAX", _SC_TTY_NAME_MAX, SYSCONF },
01872 #endif
01873 #ifdef _SC_TZNAME_MAX
01874     { "TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF },
01875 #endif
01876 #ifdef _SC_UCHAR_MAX
01877     { "UCHAR_MAX", _SC_UCHAR_MAX, SYSCONF },
01878 #endif
01879 #ifdef _SC_UINT_MAX
01880     { "UINT_MAX", _SC_UINT_MAX, SYSCONF },
01881 #endif
01882 #ifdef _SC_UIO_MAXIOV
01883     { "UIO_MAXIOV", _SC_UIO_MAXIOV, SYSCONF },
01884 #endif
01885 #ifdef _SC_ULONG_MAX
01886     { "ULONG_MAX", _SC_ULONG_MAX, SYSCONF },
01887 #endif
01888 #ifdef _SC_USHRT_MAX
01889     { "USHRT_MAX", _SC_USHRT_MAX, SYSCONF },
01890 #endif
01891 #ifdef _SC_WORD_BIT
01892     { "WORD_BIT", _SC_WORD_BIT, SYSCONF },
01893 #endif
01894 #ifdef _SC_AVPHYS_PAGES
01895     { "_AVPHYS_PAGES", _SC_AVPHYS_PAGES, SYSCONF },
01896 #endif
01897 #ifdef _SC_NPROCESSORS_CONF
01898     { "_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF, SYSCONF },
01899 #endif
01900 #ifdef _SC_NPROCESSORS_ONLN
01901     { "_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN, SYSCONF },
01902 #endif
01903 #ifdef _SC_PHYS_PAGES
01904     { "_PHYS_PAGES", _SC_PHYS_PAGES, SYSCONF },
01905 #endif
01906 #ifdef _SC_ARG_MAX
01907     { "_POSIX_ARG_MAX", _SC_ARG_MAX, SYSCONF },
01908 #endif
01909 #ifdef _SC_ASYNCHRONOUS_IO
01910     { "_POSIX_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO, SYSCONF },
01911 #endif
01912 #ifdef _SC_CHILD_MAX
01913     { "_POSIX_CHILD_MAX", _SC_CHILD_MAX, SYSCONF },
01914 #endif
01915 #ifdef _SC_FSYNC
01916     { "_POSIX_FSYNC", _SC_FSYNC, SYSCONF },
01917 #endif
01918 #ifdef _SC_JOB_CONTROL
01919     { "_POSIX_JOB_CONTROL", _SC_JOB_CONTROL, SYSCONF },
01920 #endif
01921 #ifdef _SC_MAPPED_FILES
01922     { "_POSIX_MAPPED_FILES", _SC_MAPPED_FILES, SYSCONF },
01923 #endif
01924 #ifdef _SC_MEMLOCK
01925     { "_POSIX_MEMLOCK", _SC_MEMLOCK, SYSCONF },
01926 #endif
01927 #ifdef _SC_MEMLOCK_RANGE
01928     { "_POSIX_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE, SYSCONF },
01929 #endif
01930 #ifdef _SC_MEMORY_PROTECTION
01931     { "_POSIX_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION, SYSCONF },
01932 #endif
01933 #ifdef _SC_MESSAGE_PASSING
01934     { "_POSIX_MESSAGE_PASSING", _SC_MESSAGE_PASSING, SYSCONF },
01935 #endif
01936 #ifdef _SC_NGROUPS_MAX
01937     { "_POSIX_NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF },
01938 #endif
01939 #ifdef _SC_OPEN_MAX
01940     { "_POSIX_OPEN_MAX", _SC_OPEN_MAX, SYSCONF },
01941 #endif
01942 #ifdef _SC_PII
01943     { "_POSIX_PII", _SC_PII, SYSCONF },
01944 #endif
01945 #ifdef _SC_PII_INTERNET
01946     { "_POSIX_PII_INTERNET", _SC_PII_INTERNET, SYSCONF },
01947 #endif
01948 #ifdef _SC_PII_INTERNET_DGRAM
01949     { "_POSIX_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM, SYSCONF },
01950 #endif
01951 #ifdef _SC_PII_INTERNET_STREAM
01952     { "_POSIX_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM, SYSCONF },
01953 #endif
01954 #ifdef _SC_PII_OSI
01955     { "_POSIX_PII_OSI", _SC_PII_OSI, SYSCONF },
01956 #endif
01957 #ifdef _SC_PII_OSI_CLTS
01958     { "_POSIX_PII_OSI_CLTS", _SC_PII_OSI_CLTS, SYSCONF },
01959 #endif
01960 #ifdef _SC_PII_OSI_COTS
01961     { "_POSIX_PII_OSI_COTS", _SC_PII_OSI_COTS, SYSCONF },
01962 #endif
01963 #ifdef _SC_PII_OSI_M
01964     { "_POSIX_PII_OSI_M", _SC_PII_OSI_M, SYSCONF },
01965 #endif
01966 #ifdef _SC_PII_SOCKET
01967     { "_POSIX_PII_SOCKET", _SC_PII_SOCKET, SYSCONF },
01968 #endif
01969 #ifdef _SC_PII_XTI
01970     { "_POSIX_PII_XTI", _SC_PII_XTI, SYSCONF },
01971 #endif
01972 #ifdef _SC_POLL
01973     { "_POSIX_POLL", _SC_POLL, SYSCONF },
01974 #endif
01975 #ifdef _SC_PRIORITIZED_IO
01976     { "_POSIX_PRIORITIZED_IO", _SC_PRIORITIZED_IO, SYSCONF },
01977 #endif
01978 #ifdef _SC_PRIORITY_SCHEDULING
01979     { "_POSIX_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING, SYSCONF },
01980 #endif
01981 #ifdef _SC_REALTIME_SIGNALS
01982     { "_POSIX_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS, SYSCONF },
01983 #endif
01984 #ifdef _SC_SAVED_IDS
01985     { "_POSIX_SAVED_IDS", _SC_SAVED_IDS, SYSCONF },
01986 #endif
01987 #ifdef _SC_SELECT
01988     { "_POSIX_SELECT", _SC_SELECT, SYSCONF },
01989 #endif
01990 #ifdef _SC_SEMAPHORES
01991     { "_POSIX_SEMAPHORES", _SC_SEMAPHORES, SYSCONF },
01992 #endif
01993 #ifdef _SC_SHARED_MEMORY_OBJECTS
01994     { "_POSIX_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS, SYSCONF },
01995 #endif
01996 #ifdef _SC_SSIZE_MAX
01997     { "_POSIX_SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF },
01998 #endif
01999 #ifdef _SC_STREAM_MAX
02000     { "_POSIX_STREAM_MAX", _SC_STREAM_MAX, SYSCONF },
02001 #endif
02002 #ifdef _SC_SYNCHRONIZED_IO
02003     { "_POSIX_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO, SYSCONF },
02004 #endif
02005 #ifdef _SC_THREADS
02006     { "_POSIX_THREADS", _SC_THREADS, SYSCONF },
02007 #endif
02008 #ifdef _SC_THREAD_ATTR_STACKADDR
02009     { "_POSIX_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR, SYSCONF },
02010 #endif
02011 #ifdef _SC_THREAD_ATTR_STACKSIZE
02012     { "_POSIX_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE, SYSCONF },
02013 #endif
02014 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
02015     { "_POSIX_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING, SYSCONF },
02016 #endif
02017 #ifdef _SC_THREAD_PRIO_INHERIT
02018     { "_POSIX_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT, SYSCONF },
02019 #endif
02020 #ifdef _SC_THREAD_PRIO_PROTECT
02021     { "_POSIX_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT, SYSCONF },
02022 #endif
02023 #ifdef _SC_THREAD_PROCESS_SHARED
02024     { "_POSIX_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED, SYSCONF },
02025 #endif
02026 #ifdef _SC_THREAD_SAFE_FUNCTIONS
02027     { "_POSIX_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS, SYSCONF },
02028 #endif
02029 #ifdef _SC_TIMERS
02030     { "_POSIX_TIMERS", _SC_TIMERS, SYSCONF },
02031 #endif
02032 #ifdef _SC_TIMER_MAX
02033     { "TIMER_MAX", _SC_TIMER_MAX, SYSCONF },
02034 #endif
02035 #ifdef _SC_TZNAME_MAX
02036     { "_POSIX_TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF },
02037 #endif
02038 #ifdef _SC_VERSION
02039     { "_POSIX_VERSION", _SC_VERSION, SYSCONF },
02040 #endif
02041 #ifdef _SC_T_IOV_MAX
02042     { "_T_IOV_MAX", _SC_T_IOV_MAX, SYSCONF },
02043 #endif
02044 #ifdef _SC_XOPEN_CRYPT
02045     { "_XOPEN_CRYPT", _SC_XOPEN_CRYPT, SYSCONF },
02046 #endif
02047 #ifdef _SC_XOPEN_ENH_I18N
02048     { "_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N, SYSCONF },
02049 #endif
02050 #ifdef _SC_XOPEN_LEGACY
02051     { "_XOPEN_LEGACY", _SC_XOPEN_LEGACY, SYSCONF },
02052 #endif
02053 #ifdef _SC_XOPEN_REALTIME
02054     { "_XOPEN_REALTIME", _SC_XOPEN_REALTIME, SYSCONF },
02055 #endif
02056 #ifdef _SC_XOPEN_REALTIME_THREADS
02057     { "_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS, SYSCONF },
02058 #endif
02059 #ifdef _SC_XOPEN_SHM
02060     { "_XOPEN_SHM", _SC_XOPEN_SHM, SYSCONF },
02061 #endif
02062 #ifdef _SC_XOPEN_UNIX
02063     { "_XOPEN_UNIX", _SC_XOPEN_UNIX, SYSCONF },
02064 #endif
02065 #ifdef _SC_XOPEN_VERSION
02066     { "_XOPEN_VERSION", _SC_XOPEN_VERSION, SYSCONF },
02067 #endif
02068 #ifdef _SC_XOPEN_XCU_VERSION
02069     { "_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION, SYSCONF },
02070 #endif
02071 #ifdef _SC_XOPEN_XPG2
02072     { "_XOPEN_XPG2", _SC_XOPEN_XPG2, SYSCONF },
02073 #endif
02074 #ifdef _SC_XOPEN_XPG3
02075     { "_XOPEN_XPG3", _SC_XOPEN_XPG3, SYSCONF },
02076 #endif
02077 #ifdef _SC_XOPEN_XPG4
02078     { "_XOPEN_XPG4", _SC_XOPEN_XPG4, SYSCONF },
02079 #endif
02080     /* POSIX.2  */
02081 #ifdef _SC_BC_BASE_MAX
02082     { "BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF },
02083 #endif
02084 #ifdef _SC_BC_DIM_MAX
02085     { "BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF },
02086 #endif
02087 #ifdef _SC_BC_SCALE_MAX
02088     { "BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF },
02089 #endif
02090 #ifdef _SC_BC_STRING_MAX
02091     { "BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF },
02092 #endif
02093 #ifdef _SC_CHARCLASS_NAME_MAX
02094     { "CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX, SYSCONF },
02095 #endif
02096 #ifdef _SC_COLL_WEIGHTS_MAX
02097     { "COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF },
02098 #endif
02099 #ifdef _SC_EQUIV_CLASS_MAX
02100     { "EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX, SYSCONF },
02101 #endif
02102 #ifdef _SC_EXPR_NEST_MAX
02103     { "EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF },
02104 #endif
02105 #ifdef _SC_LINE_MAX
02106     { "LINE_MAX", _SC_LINE_MAX, SYSCONF },
02107 #endif
02108 #ifdef _SC_BC_BASE_MAX
02109     { "POSIX2_BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF },
02110 #endif
02111 #ifdef _SC_BC_DIM_MAX
02112     { "POSIX2_BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF },
02113 #endif
02114 #ifdef _SC_BC_SCALE_MAX
02115     { "POSIX2_BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF },
02116 #endif
02117 #ifdef _SC_BC_STRING_MAX
02118     { "POSIX2_BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF },
02119 #endif
02120 #ifdef _SC_2_CHAR_TERM
02121     { "POSIX2_CHAR_TERM", _SC_2_CHAR_TERM, SYSCONF },
02122 #endif
02123 #ifdef _SC_COLL_WEIGHTS_MAX
02124     { "POSIX2_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF },
02125 #endif
02126 #ifdef _SC_2_C_BIND
02127     { "POSIX2_C_BIND", _SC_2_C_BIND, SYSCONF },
02128 #endif
02129 #ifdef _SC_2_C_DEV
02130     { "POSIX2_C_DEV", _SC_2_C_DEV, SYSCONF },
02131 #endif
02132 #ifdef _SC_2_C_VERSION
02133     { "POSIX2_C_VERSION", _SC_2_C_VERSION, SYSCONF },
02134 #endif
02135 #ifdef _SC_EXPR_NEST_MAX
02136     { "POSIX2_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF },
02137 #endif
02138 #ifdef _SC_2_FORT_DEV
02139     { "POSIX2_FORT_DEV", _SC_2_FORT_DEV, SYSCONF },
02140 #endif
02141 #ifdef _SC_2_FORT_RUN
02142     { "POSIX2_FORT_RUN", _SC_2_FORT_RUN, SYSCONF },
02143 #endif
02144 #ifdef _SC_LINE_MAX
02145     { "_POSIX2_LINE_MAX", _SC_LINE_MAX, SYSCONF },
02146 #endif
02147 #ifdef _SC_2_LOCALEDEF
02148     { "POSIX2_LOCALEDEF", _SC_2_LOCALEDEF, SYSCONF },
02149 #endif
02150 #ifdef _SC_RE_DUP_MAX
02151     { "POSIX2_RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF },
02152 #endif
02153 #ifdef _SC_2_SW_DEV
02154     { "POSIX2_SW_DEV", _SC_2_SW_DEV, SYSCONF },
02155 #endif
02156 #ifdef _SC_2_UPE
02157     { "POSIX2_UPE", _SC_2_UPE, SYSCONF },
02158 #endif
02159 #ifdef _SC_2_VERSION
02160     { "POSIX2_VERSION", _SC_2_VERSION, SYSCONF },
02161 #endif
02162 #ifdef _SC_RE_DUP_MAX
02163     { "RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF },
02164 #endif
02165 
02166 #ifdef _CS_PATH
02167     { "PATH", _CS_PATH, CONFSTR },
02168     { "CS_PATH", _CS_PATH, CONFSTR },
02169 #endif
02170 
02171     /* LFS */
02172 #ifdef _CS_LFS_CFLAGS
02173     { "LFS_CFLAGS", _CS_LFS_CFLAGS, CONFSTR },
02174 #endif
02175 #ifdef _CS_LFS_LDFLAGS
02176     { "LFS_LDFLAGS", _CS_LFS_LDFLAGS, CONFSTR },
02177 #endif
02178 #ifdef _CS_LFS_LIBS
02179     { "LFS_LIBS", _CS_LFS_LIBS, CONFSTR },
02180 #endif
02181 #ifdef _CS_LFS_LINTFLAGS
02182     { "LFS_LINTFLAGS", _CS_LFS_LINTFLAGS, CONFSTR },
02183 #endif
02184 #ifdef _CS_LFS64_CFLAGS
02185     { "LFS64_CFLAGS", _CS_LFS64_CFLAGS, CONFSTR },
02186 #endif
02187 #ifdef _CS_LFS64_LDFLAGS
02188     { "LFS64_LDFLAGS", _CS_LFS64_LDFLAGS, CONFSTR },
02189 #endif
02190 #ifdef _CS_LFS64_LIBS
02191     { "LFS64_LIBS", _CS_LFS64_LIBS, CONFSTR },
02192 #endif
02193 #ifdef _CS_LFS64_LINTFLAGS
02194     { "LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS, CONFSTR },
02195 #endif
02196 
02197     /* Programming environments.  */
02198 #ifdef _SC_XBS5_ILP32_OFF32
02199     { "_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32, SYSCONF },
02200 #endif
02201 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
02202     { "XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS, CONFSTR },
02203 #endif
02204 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
02205     { "XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS, CONFSTR },
02206 #endif
02207 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
02208     { "XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS, CONFSTR },
02209 #endif
02210 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
02211     { "XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS, CONFSTR },
02212 #endif
02213 
02214 #ifdef _SC_XBS5_ILP32_OFFBIG
02215     { "_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG, SYSCONF },
02216 #endif
02217 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
02218     { "XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS, CONFSTR },
02219 #endif
02220 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
02221     { "XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS, CONFSTR },
02222 #endif
02223 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
02224     { "XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS, CONFSTR },
02225 #endif
02226 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
02227     { "XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, CONFSTR },
02228 #endif
02229 
02230 #ifdef _SC_XBS5_LP64_OFF64
02231     { "_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64, SYSCONF },
02232 #endif
02233 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
02234     { "XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS, CONFSTR },
02235 #endif
02236 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
02237     { "XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS, CONFSTR },
02238 #endif
02239 #ifdef _CS_XBS5_LP64_OFF64_LIBS
02240     { "XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS, CONFSTR },
02241 #endif
02242 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
02243     { "XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS, CONFSTR },
02244 #endif
02245 
02246 #ifdef _SC_XBS5_LPBIG_OFFBIG
02247     { "_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG, SYSCONF },
02248 #endif
02249 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
02250     { "XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS, CONFSTR },
02251 #endif
02252 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
02253     { "XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, CONFSTR },
02254 #endif
02255 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
02256     { "XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS, CONFSTR },
02257 #endif
02258 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
02259     { "XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, CONFSTR },
02260 #endif
02261 
02262 #ifdef _SC_V6_ILP32_OFF32
02263     { "_POSIX_V6_ILP32_OFF32", _SC_V6_ILP32_OFF32, SYSCONF },
02264 #endif
02265 #ifdef _CS_POSIX_V6_ILP32_OFF32_CFLAGS
02266     { "POSIX_V6_ILP32_OFF32_CFLAGS", _CS_POSIX_V6_ILP32_OFF32_CFLAGS, CONFSTR },
02267 #endif
02268 #ifdef _CS_POSIX_V6_ILP32_OFF32_LDFLAGS
02269     { "POSIX_V6_ILP32_OFF32_LDFLAGS", _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, CONFSTR },
02270 #endif
02271 #ifdef _CS_POSIX_V6_ILP32_OFF32_LIBS
02272     { "POSIX_V6_ILP32_OFF32_LIBS", _CS_POSIX_V6_ILP32_OFF32_LIBS, CONFSTR },
02273 #endif
02274 #ifdef _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS
02275     { "POSIX_V6_ILP32_OFF32_LINTFLAGS", _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, CONFSTR },
02276 #endif
02277 
02278 #ifdef _CS_V6_WIDTH_RESTRICTED_ENVS
02279     { "_POSIX_V6_WIDTH_RESTRICTED_ENVS", _CS_V6_WIDTH_RESTRICTED_ENVS, CONFSTR },
02280 #endif
02281 
02282 #ifdef _SC_V6_ILP32_OFFBIG
02283     { "_POSIX_V6_ILP32_OFFBIG", _SC_V6_ILP32_OFFBIG, SYSCONF },
02284 #endif
02285 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
02286     { "POSIX_V6_ILP32_OFFBIG_CFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, CONFSTR },
02287 #endif
02288 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
02289     { "POSIX_V6_ILP32_OFFBIG_LDFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, CONFSTR },
02290 #endif
02291 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LIBS
02292     { "POSIX_V6_ILP32_OFFBIG_LIBS", _CS_POSIX_V6_ILP32_OFFBIG_LIBS, CONFSTR },
02293 #endif
02294 #ifdef _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS
02295     { "POSIX_V6_ILP32_OFFBIG_LINTFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, CONFSTR },
02296 #endif
02297 
02298 #ifdef _SC_V6_LP64_OFF64
02299     { "_POSIX_V6_LP64_OFF64", _SC_V6_LP64_OFF64, SYSCONF },
02300 #endif
02301 #ifdef _CS_POSIX_V6_LP64_OFF64_CFLAGS
02302     { "POSIX_V6_LP64_OFF64_CFLAGS", _CS_POSIX_V6_LP64_OFF64_CFLAGS, CONFSTR },
02303 #endif
02304 #ifdef _CS_POSIX_V6_LP64_OFF64_LDFLAGS
02305     { "POSIX_V6_LP64_OFF64_LDFLAGS", _CS_POSIX_V6_LP64_OFF64_LDFLAGS, CONFSTR },
02306 #endif
02307 #ifdef _CS_POSIX_V6_LP64_OFF64_LIBS
02308     { "POSIX_V6_LP64_OFF64_LIBS", _CS_POSIX_V6_LP64_OFF64_LIBS, CONFSTR },
02309 #endif
02310 #ifdef _CS_POSIX_V6_LP64_OFF64_LINTFLAGS
02311     { "POSIX_V6_LP64_OFF64_LINTFLAGS", _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, CONFSTR },
02312 #endif
02313 
02314 #ifdef _SC_V6_LPBIG_OFFBIG
02315     { "_POSIX_V6_LPBIG_OFFBIG", _SC_V6_LPBIG_OFFBIG, SYSCONF },
02316 #endif
02317 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
02318     { "POSIX_V6_LPBIG_OFFBIG_CFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, CONFSTR },
02319 #endif
02320 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
02321     { "POSIX_V6_LPBIG_OFFBIG_LDFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, CONFSTR },
02322 #endif
02323 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
02324     { "POSIX_V6_LPBIG_OFFBIG_LIBS", _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, CONFSTR },
02325 #endif
02326 #ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS
02327     { "POSIX_V6_LPBIG_OFFBIG_LINTFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, CONFSTR },
02328 #endif
02329 
02330 #ifdef _SC_ADVISORY_INFO
02331     { "_POSIX_ADVISORY_INFO", _SC_ADVISORY_INFO, SYSCONF },
02332 #endif
02333 #ifdef _SC_BARRIERS
02334     { "_POSIX_BARRIERS", _SC_BARRIERS, SYSCONF },
02335 #endif
02336 #ifdef _SC_BASE
02337     { "_POSIX_BASE", _SC_BASE, SYSCONF },
02338 #endif
02339 #ifdef _SC_C_LANG_SUPPORT
02340     { "_POSIX_C_LANG_SUPPORT", _SC_C_LANG_SUPPORT, SYSCONF },
02341 #endif
02342 #ifdef _SC_C_LANG_SUPPORT_R
02343     { "_POSIX_C_LANG_SUPPORT_R", _SC_C_LANG_SUPPORT_R, SYSCONF },
02344 #endif
02345 #ifdef _SC_CLOCK_SELECTION
02346     { "_POSIX_CLOCK_SELECTION", _SC_CLOCK_SELECTION, SYSCONF },
02347 #endif
02348 #ifdef _SC_CPUTIME
02349     { "_POSIX_CPUTIME", _SC_CPUTIME, SYSCONF },
02350 #endif
02351 #ifdef _SC_THREAD_CPUTIME
02352     { "_POSIX_THREAD_CPUTIME", _SC_THREAD_CPUTIME, SYSCONF },
02353 #endif
02354 #ifdef _SC_DEVICE_SPECIFIC
02355     { "_POSIX_DEVICE_SPECIFIC", _SC_DEVICE_SPECIFIC, SYSCONF },
02356 #endif
02357 #ifdef _SC_DEVICE_SPECIFIC_R
02358     { "_POSIX_DEVICE_SPECIFIC_R", _SC_DEVICE_SPECIFIC_R, SYSCONF },
02359 #endif
02360 #ifdef _SC_FD_MGMT
02361     { "_POSIX_FD_MGMT", _SC_FD_MGMT, SYSCONF },
02362 #endif
02363 #ifdef _SC_FIFO
02364     { "_POSIX_FIFO", _SC_FIFO, SYSCONF },
02365 #endif
02366 #ifdef _SC_PIPE
02367     { "_POSIX_PIPE", _SC_PIPE, SYSCONF },
02368 #endif
02369 #ifdef _SC_FILE_ATTRIBUTES
02370     { "_POSIX_FILE_ATTRIBUTES", _SC_FILE_ATTRIBUTES, SYSCONF },
02371 #endif
02372 #ifdef _SC_FILE_LOCKING
02373     { "_POSIX_FILE_LOCKING", _SC_FILE_LOCKING, SYSCONF },
02374 #endif
02375 #ifdef _SC_FILE_SYSTEM
02376     { "_POSIX_FILE_SYSTEM", _SC_FILE_SYSTEM, SYSCONF },
02377 #endif
02378 #ifdef _SC_MONOTONIC_CLOCK
02379     { "_POSIX_MONOTONIC_CLOCK", _SC_MONOTONIC_CLOCK, SYSCONF },
02380 #endif
02381 #ifdef _SC_MULTI_PROCESS
02382     { "_POSIX_MULTI_PROCESS", _SC_MULTI_PROCESS, SYSCONF },
02383 #endif
02384 #ifdef _SC_SINGLE_PROCESS
02385     { "_POSIX_SINGLE_PROCESS", _SC_SINGLE_PROCESS, SYSCONF },
02386 #endif
02387 #ifdef _SC_NETWORKING
02388     { "_POSIX_NETWORKING", _SC_NETWORKING, SYSCONF },
02389 #endif
02390 #ifdef _SC_READER_WRITER_LOCKS
02391     { "_POSIX_READER_WRITER_LOCKS", _SC_READER_WRITER_LOCKS, SYSCONF },
02392 #endif
02393 #ifdef _SC_SPIN_LOCKS
02394     { "_POSIX_SPIN_LOCKS", _SC_SPIN_LOCKS, SYSCONF },
02395 #endif
02396 #ifdef _SC_REGEXP
02397     { "_POSIX_REGEXP", _SC_REGEXP, SYSCONF },
02398 #endif
02399 #ifdef _SC_REGEX_VERSION
02400     { "_REGEX_VERSION", _SC_REGEX_VERSION, SYSCONF },
02401 #endif
02402 #ifdef _SC_SHELL
02403     { "_POSIX_SHELL", _SC_SHELL, SYSCONF },
02404 #endif
02405 #ifdef _SC_SIGNALS
02406     { "_POSIX_SIGNALS", _SC_SIGNALS, SYSCONF },
02407 #endif
02408 #ifdef _SC_SPAWN
02409     { "_POSIX_SPAWN", _SC_SPAWN, SYSCONF },
02410 #endif
02411 #ifdef _SC_SPORADIC_SERVER
02412     { "_POSIX_SPORADIC_SERVER", _SC_SPORADIC_SERVER, SYSCONF },
02413 #endif
02414 #ifdef _SC_THREAD_SPORADIC_SERVER
02415     { "_POSIX_THREAD_SPORADIC_SERVER", _SC_THREAD_SPORADIC_SERVER, SYSCONF },
02416 #endif
02417 #ifdef _SC_SYSTEM_DATABASE
02418     { "_POSIX_SYSTEM_DATABASE", _SC_SYSTEM_DATABASE, SYSCONF },
02419 #endif
02420 #ifdef _SC_SYSTEM_DATABASE_R
02421     { "_POSIX_SYSTEM_DATABASE_R", _SC_SYSTEM_DATABASE_R, SYSCONF },
02422 #endif
02423 #ifdef _SC_TIMEOUTS
02424     { "_POSIX_TIMEOUTS", _SC_TIMEOUTS, SYSCONF },
02425 #endif
02426 #ifdef _SC_TYPED_MEMORY_OBJECTS
02427     { "_POSIX_TYPED_MEMORY_OBJECTS", _SC_TYPED_MEMORY_OBJECTS, SYSCONF },
02428 #endif
02429 #ifdef _SC_USER_GROUPS
02430     { "_POSIX_USER_GROUPS", _SC_USER_GROUPS, SYSCONF },
02431 #endif
02432 #ifdef _SC_USER_GROUPS_R
02433     { "_POSIX_USER_GROUPS_R", _SC_USER_GROUPS_R, SYSCONF },
02434 #endif
02435 #ifdef _SC_2_PBS
02436     { "POSIX2_PBS", _SC_2_PBS, SYSCONF },
02437 #endif
02438 #ifdef _SC_2_PBS_ACCOUNTING
02439     { "POSIX2_PBS_ACCOUNTING", _SC_2_PBS_ACCOUNTING, SYSCONF },
02440 #endif
02441 #ifdef _SC_2_PBS_LOCATE
02442     { "POSIX2_PBS_LOCATE", _SC_2_PBS_LOCATE, SYSCONF },
02443 #endif
02444 #ifdef _SC_2_PBS_TRACK
02445     { "POSIX2_PBS_TRACK", _SC_2_PBS_TRACK, SYSCONF },
02446 #endif
02447 #ifdef _SC_2_PBS_MESSAGE
02448     { "POSIX2_PBS_MESSAGE", _SC_2_PBS_MESSAGE, SYSCONF },
02449 #endif
02450 #ifdef _SC_SYMLOOP_MAX
02451     { "SYMLOOP_MAX", _SC_SYMLOOP_MAX, SYSCONF },
02452 #endif
02453 #ifdef _SC_STREAM_MAX
02454     { "STREAM_MAX", _SC_STREAM_MAX, SYSCONF },
02455 #endif
02456 #ifdef _SC_AIO_LISTIO_MAX
02457     { "AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX, SYSCONF },
02458 #endif
02459 #ifdef _SC_AIO_MAX
02460     { "AIO_MAX", _SC_AIO_MAX, SYSCONF },
02461 #endif
02462 #ifdef _SC_AIO_PRIO_DELTA_MAX
02463     { "AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX, SYSCONF },
02464 #endif
02465 #ifdef _SC_DELAYTIMER_MAX
02466     { "DELAYTIMER_MAX", _SC_DELAYTIMER_MAX, SYSCONF },
02467 #endif
02468 #ifdef _SC_HOST_NAME_MAX
02469     { "HOST_NAME_MAX", _SC_HOST_NAME_MAX, SYSCONF },
02470 #endif
02471 #ifdef _SC_LOGIN_NAME_MAX
02472     { "LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF },
02473 #endif
02474 #ifdef _SC_MQ_OPEN_MAX
02475     { "MQ_OPEN_MAX", _SC_MQ_OPEN_MAX, SYSCONF },
02476 #endif
02477 #ifdef _SC_MQ_PRIO_MAX
02478     { "MQ_PRIO_MAX", _SC_MQ_PRIO_MAX, SYSCONF },
02479 #endif
02480 #ifdef _SC_DEVICE_IO
02481     { "_POSIX_DEVICE_IO", _SC_DEVICE_IO, SYSCONF },
02482 #endif
02483 #ifdef _SC_TRACE
02484     { "_POSIX_TRACE", _SC_TRACE, SYSCONF },
02485 #endif
02486 #ifdef _SC_TRACE_EVENT_FILTER
02487     { "_POSIX_TRACE_EVENT_FILTER", _SC_TRACE_EVENT_FILTER, SYSCONF },
02488 #endif
02489 #ifdef _SC_TRACE_INHERIT
02490     { "_POSIX_TRACE_INHERIT", _SC_TRACE_INHERIT, SYSCONF },
02491 #endif
02492 #ifdef _SC_TRACE_LOG
02493     { "_POSIX_TRACE_LOG", _SC_TRACE_LOG, SYSCONF },
02494 #endif
02495 #ifdef _SC_RTSIG_MAX
02496     { "RTSIG_MAX", _SC_RTSIG_MAX, SYSCONF },
02497 #endif
02498 #ifdef _SC_SEM_NSEMS_MAX
02499     { "SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX, SYSCONF },
02500 #endif
02501 #ifdef _SC_SEM_VALUE_MAX
02502     { "SEM_VALUE_MAX", _SC_SEM_VALUE_MAX, SYSCONF },
02503 #endif
02504 #ifdef _SC_SIGQUEUE_MAX
02505     { "SIGQUEUE_MAX", _SC_SIGQUEUE_MAX, SYSCONF },
02506 #endif
02507 #ifdef _PC_FILESIZEBITS
02508     { "FILESIZEBITS", _PC_FILESIZEBITS, PATHCONF },
02509 #endif
02510 #ifdef _PC_ALLOC_SIZE_MIN
02511     { "POSIX_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN, PATHCONF },
02512 #endif
02513 #ifdef _PC_REC_INCR_XFER_SIZE
02514     { "POSIX_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE, PATHCONF },
02515 #endif
02516 #ifdef _PC_REC_MAX_XFER_SIZE
02517     { "POSIX_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE, PATHCONF },
02518 #endif
02519 #ifdef _PC_REC_MIN_XFER_SIZE
02520     { "POSIX_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE, PATHCONF },
02521 #endif
02522 #ifdef _PC_REC_XFER_ALIGN
02523     { "POSIX_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN, PATHCONF },
02524 #endif
02525 #ifdef _PC_SYMLINK_MAX
02526     { "SYMLINK_MAX", _PC_SYMLINK_MAX, PATHCONF },
02527 #endif
02528 #ifdef _CS_GNU_LIBC_VERSION
02529     { "GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION, CONFSTR },
02530 #endif
02531 #ifdef _CS_GNU_LIBPTHREAD_VERSION
02532     { "GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION, CONFSTR },
02533 #endif
02534 #ifdef _PC_2_SYMLINKS
02535     { "POSIX2_SYMLINKS", _PC_2_SYMLINKS, PATHCONF },
02536 #endif
02537 
02538 #ifdef _SC_LEVEL1_ICACHE_SIZE
02539     { "LEVEL1_ICACHE_SIZE", _SC_LEVEL1_ICACHE_SIZE, SYSCONF },
02540 #endif
02541 #ifdef _SC_LEVEL1_ICACHE_ASSOC
02542     { "LEVEL1_ICACHE_ASSOC", _SC_LEVEL1_ICACHE_ASSOC, SYSCONF },
02543 #endif
02544 #ifdef _SC_LEVEL1_ICACHE_LINESIZE
02545     { "LEVEL1_ICACHE_LINESIZE", _SC_LEVEL1_ICACHE_LINESIZE, SYSCONF },
02546 #endif
02547 #ifdef _SC_LEVEL1_DCACHE_SIZE
02548     { "LEVEL1_DCACHE_SIZE", _SC_LEVEL1_DCACHE_SIZE, SYSCONF },
02549 #endif
02550 #ifdef _SC_LEVEL1_DCACHE_ASSOC
02551     { "LEVEL1_DCACHE_ASSOC", _SC_LEVEL1_DCACHE_ASSOC, SYSCONF },
02552 #endif
02553 #ifdef _SC_LEVEL1_DCACHE_LINESIZE
02554     { "LEVEL1_DCACHE_LINESIZE", _SC_LEVEL1_DCACHE_LINESIZE, SYSCONF },
02555 #endif
02556 #ifdef _SC_LEVEL2_CACHE_SIZE
02557     { "LEVEL2_CACHE_SIZE", _SC_LEVEL2_CACHE_SIZE, SYSCONF },
02558 #endif
02559 #ifdef _SC_LEVEL2_CACHE_ASSOC
02560     { "LEVEL2_CACHE_ASSOC", _SC_LEVEL2_CACHE_ASSOC, SYSCONF },
02561 #endif
02562 #ifdef _SC_LEVEL2_CACHE_LINESIZE
02563     { "LEVEL2_CACHE_LINESIZE", _SC_LEVEL2_CACHE_LINESIZE, SYSCONF },
02564 #endif
02565 #ifdef _SC_LEVEL3_CACHE_SIZE
02566     { "LEVEL3_CACHE_SIZE", _SC_LEVEL3_CACHE_SIZE, SYSCONF },
02567 #endif
02568 #ifdef _SC_LEVEL3_CACHE_ASSOC
02569     { "LEVEL3_CACHE_ASSOC", _SC_LEVEL3_CACHE_ASSOC, SYSCONF },
02570 #endif
02571 #ifdef _SC_LEVEL3_CACHE_LINESIZE
02572     { "LEVEL3_CACHE_LINESIZE", _SC_LEVEL3_CACHE_LINESIZE, SYSCONF },
02573 #endif
02574 #ifdef _SC_LEVEL4_CACHE_SIZE
02575     { "LEVEL4_CACHE_SIZE", _SC_LEVEL4_CACHE_SIZE, SYSCONF },
02576 #endif
02577 #ifdef _SC_LEVEL4_CACHE_ASSOC
02578     { "LEVEL4_CACHE_ASSOC", _SC_LEVEL4_CACHE_ASSOC, SYSCONF },
02579 #endif
02580 
02581 #ifdef _SC_IPV6
02582     { "IPV6", _SC_IPV6, SYSCONF },
02583 #endif
02584 #ifdef _SC_RAW_SOCKETS
02585     { "RAW_SOCKETS", _SC_RAW_SOCKETS, SYSCONF },
02586 #endif
02587 
02588     { NULL, 0, SYSCONF }
02589 };
02590 
02591 #define _GETCONF_PATH   "/"
02592 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
02593 static const char *_getconf_path = NULL;
02594 
02595 int
02596 rpmdsGetconf(rpmds * dsp, const char *path)
02597         /*@globals _getconf_path @*/
02598         /*@modifies _getconf_path @*/
02599 {
02600     const struct conf *c;
02601     size_t clen;
02602     long int value;
02603     const char * NS = "getconf";
02604     const char *N;
02605     char * EVR;
02606     char * t;
02607     int_32 Flags;
02608 
02609 /*@-modobserver@*/
02610     if (_getconf_path == NULL) {
02611         _getconf_path = rpmExpand("%{?_rpmds__getconf_path}", NULL);
02612         /* XXX may need to validate path existence somewhen. */
02613         if (!(_getconf_path != NULL && *_getconf_path == '/')) {
02614 /*@-observertrans @*/
02615             _getconf_path = _free(_getconf_path);
02616 /*@=observertrans @*/
02617             _getconf_path = xstrdup(_GETCONF_PATH);
02618         }
02619     }
02620 /*@=modobserver@*/
02621 
02622 /*@-branchstate@*/
02623     if (path == NULL)
02624         path = _getconf_path;
02625 
02626     for (c = vars; c->name != NULL; ++c) {
02627         N = c->name;
02628         EVR = NULL;
02629         switch (c->call) {
02630         case PATHCONF:
02631             value = pathconf(path, c->call_name);
02632             if (value != -1) {
02633                 EVR = xmalloc(32);
02634                 sprintf(EVR, "%ld", value);
02635             }
02636             /*@switchbreak@*/ break;
02637         case SYSCONF:
02638             value = sysconf(c->call_name);
02639             if (value == -1l) {
02640 #if defined(_SC_UINT_MAX) && defined(_SC_ULONG_MAX)
02641 /*@-unrecog@*/
02642                 if (c->call_name == _SC_UINT_MAX
02643                 || c->call_name == _SC_ULONG_MAX) {
02644                     EVR = xmalloc(32);
02645                     sprintf(EVR, "%lu", value);
02646                 }
02647 /*@=unrecog@*/
02648 #endif
02649             } else {
02650                 EVR = xmalloc(32);
02651                 sprintf(EVR, "%ld", value);
02652             }
02653             /*@switchbreak@*/ break;
02654         case CONFSTR:
02655             clen = confstr(c->call_name, (char *) NULL, 0);
02656             EVR = xmalloc(clen+1);
02657             *EVR = '\0';
02658             if (confstr (c->call_name, EVR, clen) != clen) {
02659                 fprintf(stderr, "confstr: %s\n", strerror(errno));
02660                 exit (EXIT_FAILURE);
02661             }
02662             EVR[clen] = '\0';
02663             /*@switchbreak@*/ break;
02664         }
02665         if (EVR == NULL)
02666             continue;
02667 
02668         for (t = EVR; *t; t++) {
02669             if (*t == '\n') *t = ' ';
02670         }
02671         if (!strcmp(N, "GNU_LIBC_VERSION")
02672          || !strcmp(N, "GNU_LIBPTHREAD_VERSION"))
02673         {
02674             for (t = EVR; *t; t++) {
02675                 if (*t == ' ') *t = '-';
02676             }
02677         }
02678 
02679         if (*EVR == '\0' || strchr(EVR, ' ') != NULL
02680          || (EVR[0] == '-' && strchr("0123456789", EVR[1]) == NULL))
02681         {
02682             EVR = _free(EVR);
02683             continue;
02684         }
02685 
02686         Flags = RPMSENSE_PROBE|RPMSENSE_EQUAL;
02687         rpmdsNSAdd(dsp, NS, N, EVR, Flags);
02688         EVR = _free(EVR);
02689     }
02690 /*@=branchstate@*/
02691     return 0;
02692 }
02693 
02694 int rpmdsMergePRCO(void * context, rpmds ds)
02695 {
02696     rpmPRCO PRCO = context;
02697     int rc = -1;
02698 
02699 /*@-modfilesys@*/
02700 if (_rpmds_debug < 0)
02701 fprintf(stderr, "*** %s(%p, %p) %s\n", __FUNCTION__, context, ds, tagName(rpmdsTagN(ds)));
02702 /*@=modfilesys@*/
02703     switch(rpmdsTagN(ds)) {
02704     default:
02705         break;
02706     case RPMTAG_PROVIDENAME:
02707         rc = rpmdsMerge(PRCO->Pdsp, ds);
02708         break;
02709     case RPMTAG_REQUIRENAME:
02710         rc = rpmdsMerge(PRCO->Rdsp, ds);
02711         break;
02712     case RPMTAG_CONFLICTNAME:
02713         rc = rpmdsMerge(PRCO->Cdsp, ds);
02714         break;
02715     case RPMTAG_OBSOLETENAME:
02716         rc = rpmdsMerge(PRCO->Odsp, ds);
02717         break;
02718     case RPMTAG_TRIGGERNAME:
02719         rc = rpmdsMerge(PRCO->Tdsp, ds);
02720         break;
02721     case RPMTAG_DIRNAMES:
02722         rc = rpmdsMerge(PRCO->Ddsp, ds);
02723         break;
02724     case RPMTAG_FILELINKTOS:
02725         rc = rpmdsMerge(PRCO->Ldsp, ds);
02726         break;
02727     }
02728     return rc;
02729 }
02730 
02731 rpmPRCO rpmdsFreePRCO(rpmPRCO PRCO)
02732 {
02733     if (PRCO) {
02734         PRCO->this = rpmdsFree(PRCO->this);
02735         PRCO->P = rpmdsFree(PRCO->P);
02736         PRCO->R = rpmdsFree(PRCO->R);
02737         PRCO->C = rpmdsFree(PRCO->C);
02738         PRCO->O = rpmdsFree(PRCO->O);
02739         PRCO->T = rpmdsFree(PRCO->T);
02740         PRCO->D = rpmdsFree(PRCO->D);
02741         PRCO->L = rpmdsFree(PRCO->L);
02742         PRCO->Pdsp = NULL;
02743         PRCO->Rdsp = NULL;
02744         PRCO->Cdsp = NULL;
02745         PRCO->Odsp = NULL;
02746         PRCO->Tdsp = NULL;
02747         PRCO->Ddsp = NULL;
02748         PRCO->Ldsp = NULL;
02749         PRCO = _free(PRCO);
02750     }
02751     return NULL;
02752 }
02753 
02754 rpmPRCO rpmdsNewPRCO(Header h)
02755 {
02756     rpmPRCO PRCO = xcalloc(1, sizeof(*PRCO));
02757 
02758     if (h != NULL) {
02759         int scareMem = 0;
02760         PRCO->this = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
02761         PRCO->P = rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem);
02762         PRCO->R = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
02763         PRCO->C = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
02764         PRCO->O = rpmdsNew(h, RPMTAG_OBSOLETENAME, scareMem);
02765         PRCO->T = rpmdsNew(h, RPMTAG_TRIGGERNAME, scareMem);
02766         PRCO->D = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem);
02767         PRCO->L = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem);
02768     }
02769     PRCO->Pdsp =  &PRCO->P;
02770     PRCO->Rdsp =  &PRCO->R;
02771     PRCO->Cdsp =  &PRCO->C;
02772     PRCO->Odsp =  &PRCO->O;
02773     PRCO->Tdsp =  &PRCO->T;
02774     PRCO->Ddsp =  &PRCO->D;
02775     PRCO->Ldsp =  &PRCO->L;
02776     return PRCO;
02777 }
02778 
02779 rpmds rpmdsFromPRCO(rpmPRCO PRCO, rpmTag tagN)
02780 {
02781     if (PRCO == NULL)
02782         return NULL;
02783     /*@-compdef -refcounttrans -retalias -retexpose -usereleased @*/
02784     if (tagN == RPMTAG_NAME)
02785         return PRCO->this;
02786     if (tagN == RPMTAG_PROVIDENAME)
02787         return *PRCO->Pdsp;
02788     if (tagN == RPMTAG_REQUIRENAME)
02789         return *PRCO->Rdsp;
02790     if (tagN == RPMTAG_CONFLICTNAME)
02791         return *PRCO->Cdsp;
02792     if (tagN == RPMTAG_OBSOLETENAME)
02793         return *PRCO->Odsp;
02794     if (tagN == RPMTAG_TRIGGERNAME)
02795         return *PRCO->Tdsp;
02796     if (tagN == RPMTAG_DIRNAMES)
02797         return *PRCO->Ddsp;
02798     if (tagN == RPMTAG_FILELINKTOS)
02799         return *PRCO->Ldsp;
02800     return NULL;
02801     /*@=compdef =refcounttrans =retalias =retexpose =usereleased @*/
02802 }
02803 
02810 static char * sonameDep(/*@returned@*/ char * t, const char * s, int isElf64)
02811         /*@modifies t @*/
02812 {
02813     *t = '\0';
02814 #if !defined(__alpha__) && !defined(__sun)
02815     if (isElf64) {
02816         if (s[strlen(s)-1] != ')')
02817         (void) stpcpy( stpcpy(t, s), "()(64bit)");
02818     else
02819             (void) stpcpy( stpcpy(t, s), "(64bit)");
02820     }else
02821 #endif
02822         (void) stpcpy(t, s);
02823     return t;
02824 }
02825 
02826 int rpmdsELF(const char * fn, int flags,
02827                 int (*add) (void * context, rpmds ds), void * context)
02828 {
02829 #if HAVE_GELF_H && HAVE_LIBELF
02830     Elf * elf;
02831     Elf_Scn * scn;
02832     Elf_Data * data;
02833     GElf_Ehdr ehdr_mem, * ehdr;
02834     GElf_Shdr shdr_mem, * shdr;
02835     GElf_Verdef def_mem, * def;
02836     GElf_Verneed need_mem, * need;
02837     GElf_Dyn dyn_mem, * dyn;
02838     unsigned int auxoffset;
02839     unsigned int offset;
02840     int fdno;
02841     int cnt2;
02842     int cnt;
02843     char buf[BUFSIZ];
02844     const char * s;
02845     int is_executable;
02846     const char * soname = NULL;
02847     rpmds ds;
02848     char * t;
02849     int xx;
02850     int isElf64;
02851     int isDSO;
02852     int gotSONAME = 0;
02853     int gotDEBUG = 0;
02854     int gotHASH = 0;
02855     int gotGNUHASH = 0;
02856     int skipP = (flags & RPMELF_FLAG_SKIPPROVIDES);
02857     int skipR = (flags & RPMELF_FLAG_SKIPREQUIRES);
02858     static int filter_GLIBC_PRIVATE = 0;
02859     static int oneshot = 0;
02860 
02861 /*@-castfcnptr@*/
02862 if (_rpmds_debug < 0)
02863 fprintf(stderr, "*** %s(%s, %d, %p, %p)\n", __FUNCTION__, fn, flags, (void *)add, context);
02864 /*@=castfcnptr@*/
02865     if (oneshot == 0) {
02866         oneshot = 1;
02867         filter_GLIBC_PRIVATE = rpmExpandNumeric("%{?_filter_GLIBC_PRIVATE}");
02868     }
02869 
02870     /* Extract dependencies only from files with executable bit set. */
02871     {   struct stat sb, * st = &sb;
02872         if (stat(fn, st) != 0)
02873             return -1;
02874         is_executable = (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
02875     }
02876 
02877     fdno = open(fn, O_RDONLY);
02878     if (fdno < 0)
02879         return fdno;
02880 
02881     (void) elf_version(EV_CURRENT);
02882 
02883 /*@-evalorder@*/
02884     elf = NULL;
02885     if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
02886      || elf_kind(elf) != ELF_K_ELF
02887      || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
02888      || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
02889         goto exit;
02890 /*@=evalorder@*/
02891 
02892     isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
02893     isDSO = ehdr->e_type == ET_DYN;
02894 
02895     /*@-branchstate -uniondef @*/
02896     scn = NULL;
02897     while ((scn = elf_nextscn(elf, scn)) != NULL) {
02898         shdr = gelf_getshdr(scn, &shdr_mem);
02899         if (shdr == NULL)
02900             break;
02901 
02902         soname = _free(soname);
02903         switch (shdr->sh_type) {
02904         default:
02905             continue;
02906             /*@notreached@*/ /*@switchbreak@*/ break;
02907         case SHT_GNU_verdef:
02908             data = NULL;
02909             if (!skipP)
02910             while ((data = elf_getdata (scn, data)) != NULL) {
02911                 offset = 0;
02912                 for (cnt = shdr->sh_info; --cnt >= 0; ) {
02913                 
02914                     def = gelf_getverdef (data, offset, &def_mem);
02915                     if (def == NULL)
02916                         /*@innerbreak@*/ break;
02917                     auxoffset = offset + def->vd_aux;
02918                     for (cnt2 = def->vd_cnt; --cnt2 >= 0; ) {
02919                         GElf_Verdaux aux_mem, * aux;
02920 
02921                         aux = gelf_getverdaux (data, auxoffset, &aux_mem);
02922                         if (aux == NULL)
02923                             /*@innerbreak@*/ break;
02924 
02925                         s = elf_strptr(elf, shdr->sh_link, aux->vda_name);
02926                         if (s == NULL)
02927                             /*@innerbreak@*/ break;
02928 
02929                         if (def->vd_flags & VER_FLG_BASE) {
02930                             soname = _free(soname);
02931                             soname = xstrdup(s);
02932                         } else
02933                         if (soname != NULL
02934                          && !(filter_GLIBC_PRIVATE != 0
02935                                 && !strcmp(s, "GLIBC_PRIVATE")))
02936                         {
02937                             buf[0] = '\0';
02938                             t = buf;
02939                             t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
02940 
02941                             t++;        /* XXX "foo(bar)" already in buf. */
02942 
02943                             /* Add next provide dependency. */
02944                             ds = rpmdsSingle(RPMTAG_PROVIDES,
02945                                         sonameDep(t, buf, isElf64),
02946                                         "", RPMSENSE_FIND_PROVIDES);
02947                             xx = add(context, ds);
02948                             ds = rpmdsFree(ds);
02949                         }
02950                         auxoffset += aux->vda_next;
02951                     }
02952                     offset += def->vd_next;
02953                 }
02954             }
02955             /*@switchbreak@*/ break;
02956         case SHT_GNU_verneed:
02957             data = NULL;
02958             /* Only from files with executable bit set. */
02959             if (!skipR && is_executable)
02960             while ((data = elf_getdata (scn, data)) != NULL) {
02961                 offset = 0;
02962                 for (cnt = shdr->sh_info; --cnt >= 0; ) {
02963                     need = gelf_getverneed (data, offset, &need_mem);
02964                     if (need == NULL)
02965                         /*@innerbreak@*/ break;
02966 
02967                     s = elf_strptr(elf, shdr->sh_link, need->vn_file);
02968                     if (s == NULL)
02969                         /*@innerbreak@*/ break;
02970                     soname = _free(soname);
02971                     soname = xstrdup(s);
02972                     auxoffset = offset + need->vn_aux;
02973                     for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) {
02974                         GElf_Vernaux aux_mem, * aux;
02975 
02976                         aux = gelf_getvernaux (data, auxoffset, &aux_mem);
02977                         if (aux == NULL)
02978                             /*@innerbreak@*/ break;
02979 
02980                         s = elf_strptr(elf, shdr->sh_link, aux->vna_name);
02981                         if (s == NULL)
02982                             /*@innerbreak@*/ break;
02983 
02984                         /* Filter dependencies that contain GLIBC_PRIVATE */
02985                         if (soname != NULL
02986                          && !(filter_GLIBC_PRIVATE != 0
02987                                 && !strcmp(s, "GLIBC_PRIVATE")))
02988                         {
02989                             buf[0] = '\0';
02990                             t = buf;
02991                             t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
02992 
02993                             t++;        /* XXX "foo(bar)" already in buf. */
02994 
02995                             /* Add next require dependency. */
02996                             ds = rpmdsSingle(RPMTAG_REQUIRENAME,
02997                                         sonameDep(t, buf, isElf64),
02998                                         "", RPMSENSE_FIND_REQUIRES);
02999                             xx = add(context, ds);
03000                             ds = rpmdsFree(ds);
03001                         }
03002                         auxoffset += aux->vna_next;
03003                     }
03004                     offset += need->vn_next;
03005                 }
03006             }
03007             /*@switchbreak@*/ break;
03008         case SHT_DYNAMIC:
03009             data = NULL;
03010             while ((data = elf_getdata (scn, data)) != NULL) {
03011 /*@-boundswrite@*/
03012                 for (cnt = 0; cnt < (shdr->sh_size / shdr->sh_entsize); ++cnt) {
03013                     dyn = gelf_getdyn (data, cnt, &dyn_mem);
03014                     if (dyn == NULL)
03015                         /*@innerbreak@*/ break;
03016                     s = NULL;
03017                     switch (dyn->d_tag) {
03018                     default:
03019                         /*@innercontinue@*/ continue;
03020                         /*@notreached@*/ /*@switchbreak@*/ break;
03021                     case DT_HASH:
03022                         gotHASH= 1;
03023                         /*@innercontinue@*/ continue;
03024                     case DT_GNU_HASH:
03025                         gotGNUHASH= 1;
03026                         /*@innercontinue@*/ continue;
03027                     case DT_DEBUG:    
03028                         gotDEBUG = 1;
03029                         /*@innercontinue@*/ continue;
03030                     case DT_NEEDED:
03031                         /* Only from files with executable bit set. */
03032                         if (skipR || !is_executable)
03033                             /*@innercontinue@*/ continue;
03034                         /* Add next require dependency. */
03035                         s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
03036 assert(s != NULL);
03037                         buf[0] = '\0';
03038                         ds = rpmdsSingle(RPMTAG_REQUIRENAME,
03039                                 sonameDep(buf, s, isElf64),
03040                                 "", RPMSENSE_FIND_REQUIRES);
03041                         xx = add(context, ds);
03042                         ds = rpmdsFree(ds);
03043                         /*@switchbreak@*/ break;
03044                     case DT_SONAME:
03045                         gotSONAME = 1;
03046                         if (skipP)
03047                             /*@innercontinue@*/ continue;
03048                         s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
03049 assert(s != NULL);
03050                         /* Add next provide dependency. */
03051                         buf[0] = '\0';
03052                         ds = rpmdsSingle(RPMTAG_PROVIDENAME,
03053                                 sonameDep(buf, s, isElf64),
03054                                 "", RPMSENSE_FIND_PROVIDES);
03055                         xx = add(context, ds);
03056                         ds = rpmdsFree(ds);
03057                         /*@switchbreak@*/ break;
03058                     }
03059                 }
03060 /*@=boundswrite@*/
03061             }
03062             /*@switchbreak@*/ break;
03063         }
03064     }
03065     /*@=branchstate =uniondef @*/
03066 
03067     /* For DSOs which use the .gnu_hash section and don't have a .hash
03068      * section, we need to ensure that we have a new enough glibc. */
03069     if (gotGNUHASH && !gotHASH) {
03070         ds = rpmdsSingle(RPMTAG_REQUIRENAME, "rtld(GNU_HASH)", "",
03071                         RPMSENSE_FIND_REQUIRES);
03072         xx = add(context, ds);
03073         ds = rpmdsFree(ds);
03074     }
03075 
03076     /* For DSO's, provide the basename of the file if DT_SONAME not found. */
03077     if (!skipP && isDSO && !gotDEBUG && !gotSONAME) {
03078         s = strrchr(fn, '/');
03079         if (s != NULL)
03080             s++;
03081         else
03082             s = fn;
03083 assert(s != NULL);
03084 
03085         /* Add next provide dependency. */
03086         buf[0] = '\0';
03087         ds = rpmdsSingle(RPMTAG_PROVIDENAME,
03088                 sonameDep(buf, s, isElf64), "", RPMSENSE_FIND_PROVIDES);
03089         xx = add(context, ds);
03090         ds = rpmdsFree(ds);
03091     }
03092 
03093 exit:
03094     soname = _free(soname);
03095     if (elf) (void) elf_end(elf);
03096     if (fdno > 0)
03097         xx = close(fdno);
03098     return 0;
03099 #else
03100     return -1;
03101 #endif
03102 }
03103 
03104 #define _SBIN_LDCONFIG_P        "/sbin/ldconfig -p"
03105 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
03106 static const char * _ldconfig_cmd = _SBIN_LDCONFIG_P;
03107 
03108 #define _LD_SO_CACHE    "/etc/ld.so.cache"
03109 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
03110 static const char * _ldconfig_cache = NULL;
03111 
03112 int rpmdsLdconfig(rpmPRCO PRCO, const char * fn)
03113         /*@globals _ldconfig_cmd, _ldconfig_cache @*/
03114         /*@modifies _ldconfig_cmd, _ldconfig_cache @*/
03115 {
03116     char buf[BUFSIZ];
03117     const char *DSOfn;
03118     const char *N, *EVR;
03119     int_32 Flags = 0;
03120     rpmds ds;
03121     char * f, * fe;
03122     char * g, * ge;
03123     char * t;
03124     FILE * fp = NULL;
03125     int rc = -1;
03126     int xx;
03127 
03128     if (PRCO == NULL)
03129         return -1;
03130 
03131 /*@-modobserver@*/
03132     if (_ldconfig_cmd == NULL) {
03133         _ldconfig_cmd = rpmExpand("%{?_rpmds_ldconfig_cmd}", NULL);
03134         if (!(_ldconfig_cmd != NULL && *_ldconfig_cmd == '/')) {
03135 /*@-observertrans @*/
03136             _ldconfig_cmd = _free(_ldconfig_cmd);
03137 /*@=observertrans @*/
03138             _ldconfig_cmd = xstrdup(_SBIN_LDCONFIG_P);
03139         }
03140     }
03141 
03142     if (_ldconfig_cache == NULL) {
03143         _ldconfig_cache = rpmExpand("%{?_rpmds_ldconfig_cache}", NULL);
03144         /* XXX may need to validate path existence somewhen. */
03145         if (!(_ldconfig_cache != NULL && *_ldconfig_cache == '/')) {
03146 /*@-observertrans @*/
03147             _ldconfig_cache = _free(_ldconfig_cache);
03148 /*@=observertrans @*/
03149             _ldconfig_cache = xstrdup(_LD_SO_CACHE);
03150         }
03151     }
03152 /*@=modobserver@*/
03153 
03154 /*@-branchstate@*/
03155     if (fn == NULL)
03156         fn = _ldconfig_cache;
03157 /*@=branchstate@*/
03158 
03159 if (_rpmds_debug < 0)
03160 fprintf(stderr, "*** %s(%p, %s) P %p R %p C %p O %p T %p D %p L %p\n", __FUNCTION__, PRCO, fn, PRCO->Pdsp, PRCO->Rdsp, PRCO->Cdsp, PRCO->Odsp, PRCO->Tdsp, PRCO->Ddsp, PRCO->Ldsp);
03161 
03162     fp = popen(_ldconfig_cmd, "r");
03163     if (fp == NULL)
03164         goto exit;
03165 
03166     while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
03167         EVR = NULL;
03168         /* rtrim on line. */
03169         ge = f + strlen(f);
03170         while (--ge > f && _isspace(*ge))
03171             *ge = '\0';
03172 
03173         /* ltrim on line. */
03174         while (*f && _isspace(*f))
03175             f++;
03176 
03177         /* split on '=>' */
03178         fe = f;
03179         while (*fe && !(fe[0] == '=' && fe[1] == '>'))
03180             fe++;
03181         if (*fe == '\0')
03182             continue;
03183 
03184         /* find the DSO file name. */
03185         DSOfn = fe + 2;
03186 
03187         /* ltrim on DSO file name. */
03188         while (*DSOfn && _isspace(*DSOfn))
03189             DSOfn++;
03190         if (*DSOfn == '\0')
03191             continue;
03192 
03193         /* rtrim from "=>" */
03194         if (fe > f && fe[-1] == ' ') fe[-1] = '\0';
03195         *fe++ = '\0';
03196         *fe++ = '\0';
03197         g = fe;
03198 
03199         /* ltrim on field 2. */
03200         while (*g && _isspace(*g))
03201             g++;
03202         if (*g == '\0')
03203             continue;
03204 
03205         /* split out flags */
03206         for (t = f; *t != '\0'; t++) {
03207             if (!_isspace(*t))
03208                 /*@innercontinue@*/ continue;
03209             *t++ = '\0';
03210             /*@innerbreak@*/ break;
03211         }
03212         /* XXX "libc4" "ELF" "libc5" "libc6" _("unknown") */
03213         /* XXX use flags to generate soname color */
03214         /* ",64bit" ",IA-64" ",x86-64", ",64bit" are color = 2 */
03215         /* ",N32" for mips64/libn32 */
03216 
03217         /* XXX use flags and LDASSUME_KERNEL to skip sonames? */
03218         /* "Linux" "Hurd" "Solaris" "FreeBSD" "kNetBSD" N_("Unknown OS") */
03219         /* ", OS ABI: %s %d.%d.%d" */
03220 
03221         N = f;
03222 /*@-branchstate@*/
03223         if (EVR == NULL)
03224             EVR = "";
03225 /*@=branchstate@*/
03226         Flags |= RPMSENSE_PROBE;
03227         ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
03228         xx = rpmdsMerge(PRCO->Pdsp, ds);
03229         ds = rpmdsFree(ds);
03230 
03231         xx = rpmdsELF(DSOfn, 0, rpmdsMergePRCO, PRCO);
03232     }
03233     rc = 0;
03234 
03235 exit:
03236     if (fp != NULL) (void) pclose(fp);
03237     return rc;
03238 }
03239 
03240 
03241 #if defined(__sun)
03242 #define _RLD_SEARCH_PATH        "/lib:/usr/lib"
03243 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
03244 static const char * _rld_search_path = NULL;
03245 
03246 /* search a colon-separated list of directories for shared objects */
03247 int rpmdsRldpath(rpmPRCO PRCO, const char * rldp)
03248         /*@globals _rld_search_path @*/
03249         /*@modifies _rld_search_path @*/
03250 {
03251     char buf[BUFSIZ];
03252     const char *N, *EVR;
03253     int_32 Flags = 0;
03254     rpmds ds;
03255     const char * f;
03256     const char * g;
03257     int rc = -1;
03258     int xx;
03259     glob_t  gl;
03260     char ** gp;
03261 
03262     if (PRCO == NULL)
03263         return -1;
03264 
03265 /*@-modobserver@*/
03266     if (_rld_search_path == NULL) {
03267         _rld_search_path = rpmExpand("%{?_rpmds_rld_search_path}", NULL);
03268         /* XXX may need to validate path existence somewhen. */
03269         if (!(_rld_search_path != NULL && *_rld_search_path == '/')) {
03270 /*@-observertrans @*/
03271             _rld_search_path = _free(_rld_search_path);
03272 /*@=observertrans @*/
03273             _rld_search_path = xstrdup(_RLD_SEARCH_PATH);
03274         }
03275     }
03276 /*@=modobserver@*/
03277 
03278 /*@-branchstate@*/
03279     if (rldp == NULL)
03280         rldp = _rld_search_path;
03281 /*@=branchstate@*/
03282 
03283 if (_rpmds_debug > 0)
03284 fprintf(stderr, "*** %s(%p, %s) P %p R %p C %p O %p\n", __FUNCTION__, PRCO, rldp, PRCO->Pdsp, PRCO->Rdsp, PRCO->Cdsp, PRCO->Odsp);
03285 
03286     f = rldp;
03287     /* move through the path, splitting on : */
03288     while (f) {
03289         EVR = NULL;
03290         g = strchr(f, ':');
03291         if (g == NULL) {
03292             strcpy(buf, f);
03293             /* this is the last element, no more :'s */
03294             f = NULL;
03295         } else {
03296             /* copy this chunk to buf */
03297             strncpy(buf, f, g - f + 1);
03298             buf[g-f] = '\0';
03299 
03300             /* get ready for next time through */
03301             f = g + 1;
03302         }
03303 
03304         if ( !(strlen(buf) > 0 && buf[0] == '/') )
03305             continue;
03306 
03307         /* XXX: danger, buffer len */
03308         /* XXX: *.so.* should be configurable via a macro */
03309         strcat(buf, "/*.so.*");
03310 
03311 if (_rpmds_debug > 0)
03312 fprintf(stderr, "*** %s(%p, %s) globbing %s\n", __FUNCTION__, PRCO, rldp, buf);
03313 
03314         xx = glob(buf, 0, NULL, &gl);
03315         if (xx)         /* glob error, probably GLOB_NOMATCH */
03316             continue;
03317 
03318 if (_rpmds_debug > 0)
03319 fprintf(stderr, "*** %s(%p, %s) glob matched %d files\n", __FUNCTION__, PRCO, rldp, gl.gl_pathc);
03320 
03321         gp = gl.gl_pathv;
03322         /* examine each match */
03323 /*@-branchstate@*/
03324         while (gp && *gp) {
03325             const char *DSOfn;
03326             /* XXX: should probably verify that we matched a file */
03327             DSOfn = *gp;
03328             gp++;
03329             if (EVR == NULL)
03330                 EVR = "";
03331 
03332             /* N needs to be basename of DSOfn */
03333             N = DSOfn + strlen(DSOfn);
03334             while (N > DSOfn && *N != '/')
03335                 --N;
03336 
03337             Flags |= RPMSENSE_PROBE;
03338             ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
03339             xx = rpmdsMerge(PRCO->Pdsp, ds);
03340             ds = rpmdsFree(ds);
03341 
03342             xx = rpmdsELF(DSOfn, 0, rpmdsMergePRCO, PRCO);
03343         }
03344 /*@=branchstate@*/
03345 /*@-immediatetrans@*/
03346         globfree(&gl);
03347 /*@=immediatetrans@*/
03348     }
03349     rc = 0;
03350 
03351     return rc;
03352 }
03353 
03354 #define _SOLARIS_CRLE   "/usr/sbin/crle"
03355 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
03356 static const char * _crle_cmd = NULL;
03357 
03358 int rpmdsCrle(rpmPRCO PRCO, /*@unused@*/ const char * fn)
03359         /*@globals _crle_cmd @*/
03360         /*@modifies _crle_cmd @*/
03361 {
03362     char buf[BUFSIZ];
03363     char * f;
03364     char * g, * ge;
03365     FILE * fp = NULL;
03366     int rc = -1;        /* assume failure */
03367     int xx;
03368     int found_dlp = 0;
03369 
03370     if (PRCO == NULL)
03371         return -1;
03372 
03373 /*@-modobserver@*/
03374     if (_crle_cmd == NULL) {
03375         _crle_cmd = rpmExpand("%{?_rpmds_crle_cmd}", NULL);
03376         if (!(_crle_cmd != NULL && *_crle_cmd == '/')) {
03377 /*@-observertrans @*/
03378             _crle_cmd = _free(_crle_cmd);
03379 /*@=observertrans @*/
03380             _crle_cmd = xstrdup(_SOLARIS_CRLE);
03381         }
03382     }
03383 
03384     /* XXX: we rely on _crle_cmd including the -64 arg, if ELF64 */
03385     fp = popen(_crle_cmd, "r");
03386     if (fp == NULL)
03387         return rc;
03388 
03389     /* 
03390      * we want the first line that contains "(ELF):"
03391      * we cannot search for "Default Library Path (ELF):" because that
03392      * changes in non-C locales.
03393      */
03394     while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
03395         if (found_dlp)  /* XXX read all data? */
03396             continue;
03397 
03398         g = strstr(f, "(ELF):");
03399         if (g == NULL)
03400             continue;
03401 
03402         found_dlp = 1;
03403         f = g + (sizeof("(ELF):")-1);
03404         while (_isspace(*f))
03405             f++;
03406 
03407         /* rtrim path */
03408         ge = f + strlen(f);
03409         while (--ge > f && _isspace(*ge))
03410             *ge = '\0';
03411     }
03412     xx = pclose(fp);
03413 
03414     /* we have the loader path, let rpmdsRldpath() do the work */
03415     if (found_dlp)
03416         rc = rpmdsRldpath(PRCO, f);
03417 
03418     return rc;
03419 }
03420 #endif
03421 
03422 int rpmdsUname(rpmds *dsp, const struct utsname * un)
03423 {
03424 /*@observer@*/
03425     static const char * NS = "uname";
03426     struct utsname myun;
03427     int rc = -1;
03428     int xx;
03429 
03430     if (un == NULL) {
03431         xx = uname(&myun);
03432         if (xx != 0)
03433             goto exit;
03434         un = &myun;
03435     }
03436 
03437 /*@-type@*/
03438     /* XXX values need to be checked for EVR (i.e. no '-' character.) */
03439     if (un->sysname != NULL)
03440         rpmdsNSAdd(dsp, NS, "sysname", un->sysname, RPMSENSE_EQUAL);
03441     if (un->nodename != NULL)
03442         rpmdsNSAdd(dsp, NS, "nodename", un->nodename, RPMSENSE_EQUAL);
03443     if (un->release != NULL)
03444         rpmdsNSAdd(dsp, NS, "release", un->release, RPMSENSE_EQUAL);
03445 #if 0   /* XXX has embedded spaces */
03446     if (un->version != NULL)
03447         rpmdsNSAdd(dsp, NS, "version", un->version, RPMSENSE_EQUAL);
03448 #endif
03449     if (un->machine != NULL)
03450         rpmdsNSAdd(dsp, NS, "machine", un->machine, RPMSENSE_EQUAL);
03451 #if defined(__linux__)
03452     if (un->domainname != NULL && strcmp(un->domainname, "(none)"))
03453         rpmdsNSAdd(dsp, NS, "domainname", un->domainname, RPMSENSE_EQUAL);
03454 #endif
03455 /*@=type@*/
03456     rc = 0;
03457 
03458 exit:
03459     return rc;
03460 }
03461 
03462 #define _PERL_PROVIDES  "/usr/bin/find /usr/lib/perl5 | /usr/lib/rpm/perl.prov"
03463 /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/
03464 static const char * _perldeps_cmd = NULL;
03465 
03466 int rpmdsPipe(rpmds * dsp, int_32 tagN, const char * cmd)
03467         /*@globals _perldeps_cmd @*/
03468         /*@modifies _perldeps_cmd @*/
03469 {
03470     char buf[BUFSIZ];
03471     const char *N, *EVR;
03472     int_32 Flags = 0;
03473     rpmds ds;
03474     char * f, * fe;
03475     char * g, * ge;
03476     FILE * fp = NULL;
03477     const char * fn = "pipe";
03478     int rc = -1;
03479     int cmdprinted;
03480     int ln;
03481     int xx;
03482 
03483 /*@-modobserver@*/
03484     if (_perldeps_cmd == NULL) {
03485         _perldeps_cmd = rpmExpand("%{?_rpmds_perldeps_cmd}", NULL);
03486         /* XXX may need to validate path existence somewhen. */
03487         if (!(_perldeps_cmd != NULL && *_perldeps_cmd == '/')) {
03488 /*@-observertrans @*/
03489             _perldeps_cmd = _free(_perldeps_cmd);
03490 /*@=observertrans @*/
03491             _perldeps_cmd = xstrdup(_PERL_PROVIDES);
03492         }
03493     }
03494 /*@=modobserver@*/
03495 
03496     if (tagN <= 0)
03497         tagN = RPMTAG_PROVIDENAME;
03498 /*@-branchstate@*/
03499     if (cmd == NULL)
03500         cmd = _perldeps_cmd;
03501 /*@=branchstate@*/
03502 
03503     fp = popen(cmd, "r");
03504     if (fp == NULL)
03505         goto exit;
03506 
03507     ln = 0;
03508     cmdprinted = 0;
03509     while((f = fgets(buf, sizeof(buf), fp)) != NULL) {
03510         ln++;
03511 
03512         /* insure a terminator. */
03513         buf[sizeof(buf)-1] = '\0';
03514 
03515         /* ltrim on line. */
03516         while (*f && _isspace(*f))
03517             f++;
03518 
03519         /* skip empty lines and comments */
03520         if (*f == '\0' || *f == '#')
03521             continue;
03522 
03523         /* rtrim on line. */
03524         fe = f + strlen(f);
03525         while (--fe > f && _isspace(*fe))
03526             *fe = '\0';
03527 
03528         /* split on ' '  or comparison operator. */
03529         fe = f;
03530         if (*f == '!') fe++;
03531         while (*fe && !_isspace(*fe) && strchr("!<=>", *fe) == NULL)
03532             fe++;
03533         while (*fe && _isspace(*fe))
03534             *fe++ = '\0';
03535 
03536         if (!(xisalnum(f[0]) || strchr("/_%!", f[0]) != NULL)) {
03537             if (!cmdprinted++)
03538                 fprintf(stderr, _("running \"%s\" pipe command\n"), cmd);
03539             fprintf(stderr, _("%s:%d \"%s\" has invalid name. Skipping ...\n"),
03540                         fn, ln, f);
03541             continue;
03542         }
03543 
03544         N = f;
03545         EVR = NULL;
03546         Flags = 0;
03547 
03548         /* parse for non-path, versioned dependency. */
03549 /*@-branchstate@*/
03550         if (*f != '/' && *fe != '\0') {
03551             /* parse comparison operator */
03552             g = fe;
03553             Flags = rpmEVRflags(fe, (const char **)&g);
03554             if (Flags == 0) {
03555                 if (!cmdprinted++)
03556                     fprintf(stderr, _("running \"%s\" pipe command\n"), cmd),
03557                 fprintf(stderr, _("%s:%d \"%s\" has no comparison operator. Skipping ...\n"),
03558                         fn, ln, fe);
03559                 continue;
03560             }
03561             *fe = '\0';
03562 
03563             /* ltrim on field 2. */
03564             while (*g && _isspace(*g))
03565                 g++;
03566             if (*g == '\0') {
03567                 if (!cmdprinted++)
03568                     fprintf(stderr, _("running \"%s\" pipe command\n"), cmd),
03569                 /* XXX No EVR comparison value found. */
03570                 fprintf(stderr, _("\tline %d: No EVR comparison value found.\n Skipping ..."),
03571                         ln);
03572                 fprintf(stderr, _("%s:%d \"%s\" has no EVR string. Skipping ...\n"),
03573                         fn, ln, f);
03574                 continue;
03575             }
03576 
03577             ge = g + 1;
03578             while (*ge && !_isspace(*ge))
03579                 ge++;
03580 
03581             if (*ge != '\0')
03582                 *ge = '\0';     /* XXX can't happen, line rtrim'ed already. */
03583 
03584             EVR = g;
03585         }
03586 
03587         if (EVR == NULL)
03588             EVR = "";
03589         Flags |= RPMSENSE_PROBE;
03590 /*@=branchstate@*/
03591         ds = rpmdsSingle(tagN, N, EVR, Flags);
03592         xx = rpmdsMerge(dsp, ds);
03593         ds = rpmdsFree(ds);
03594     }
03595     rc = 0;
03596 
03597 exit:
03598     if (fp != NULL) (void) pclose(fp);
03599     return rc;
03600 }
03601 
03602 static int rpmdsNAcmp(rpmds A, rpmds B)
03603         /*@*/
03604 {
03605     const char * AN = A->ns.N;
03606     const char * AA = A->ns.A;
03607     const char * BN = B->ns.N;
03608     const char * BA = B->ns.A;
03609     int rc;
03610 
03611     if (!AA && !BA) {
03612         rc = strcmp(AN, BN);
03613     } else if (AA && !BA) {
03614         rc = strncmp(AN, BN, (AA - AN)) || BN[AA - AN];
03615         if (!rc)
03616             rc = strcmp(AA, B->A);
03617     } else if (!AA && BA) {
03618         rc = strncmp(AN, BN, (BA - BN)) || AN[BA - BN];
03619         if (!rc)
03620             rc = strcmp(BA, A->A);
03621     } else {
03622         rc = strcmp(AN, BN);
03623     }
03624     return rc;
03625 }
03626 
03627 int rpmdsCompare(const rpmds A, const rpmds B)
03628 {
03629     const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
03630     const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
03631     EVR_t a = memset(alloca(sizeof(*a)), 0, sizeof(*a));
03632     EVR_t b = memset(alloca(sizeof(*a)), 0, sizeof(*a));
03633     int_32 aFlags = A->ns.Flags;
03634     int_32 bFlags = B->ns.Flags;
03635     int (*EVRcmp) (const char *a, const char *b);
03636     int result = 1;
03637     int sense;
03638     int xx;
03639 
03640 assert((rpmdsFlags(A) & RPMSENSE_SENSEMASK) == A->ns.Flags);
03641 assert((rpmdsFlags(B) & RPMSENSE_SENSEMASK) == B->ns.Flags);
03642 /*@-boundsread@*/
03643     /* Different names (and/or name.arch's) don't overlap. */
03644     if (rpmdsNAcmp(A, B)) {
03645         result = 0;
03646         goto exit;
03647     }
03648 
03649     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
03650 /*@-nullderef@*/
03651     if (!(A->EVR && A->Flags && B->EVR && B->Flags))
03652         goto exit;
03653 
03654     /* Same name. If either A or B is an existence test, always overlap. */
03655     if (!(aFlags && bFlags))
03656         goto exit;
03657 
03658     /* If either EVR is non-existent or empty, always overlap. */
03659     if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i]))
03660         goto exit;
03661 
03662     /* Both AEVR and BEVR exist. */
03663 /*@-boundswrite@*/
03664     xx = (A->EVRparse ? A->EVRparse : rpmEVRparse) (A->EVR[A->i], a);
03665     xx = (B->EVRparse ? B->EVRparse : rpmEVRparse) (B->EVR[B->i], b);
03666 /*@=boundswrite@*/
03667 
03668     /* If EVRcmp is identical, use that, otherwise use default. */
03669     EVRcmp = (A->EVRcmp && B->EVRcmp && A->EVRcmp == B->EVRcmp)
03670         ? A->EVRcmp : rpmvercmp;
03671 
03672     /* Compare {A,B} [epoch:]version[-release] */
03673     sense = 0;
03674     if (a->E && *a->E && b->E && *b->E)
03675 /*@i@*/ sense = EVRcmp(a->E, b->E);
03676     else if (a->E && *a->E && atol(a->E) > 0) {
03677         if (!B->nopromote) {
03678             int lvl = (_rpmds_unspecified_epoch_noise  ? RPMMESS_WARNING : RPMMESS_DEBUG);
03679             rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
03680                 aDepend, bDepend);
03681             sense = 0;
03682         } else
03683             sense = 1;
03684     } else if (b->E && *b->E && atol(b->E) > 0)
03685         sense = -1;
03686 
03687     if (sense == 0) {
03688 /*@i@*/ sense = EVRcmp(a->V, b->V);
03689         if (sense == 0 && a->R && *a->R && b->R && *b->R)
03690 /*@i@*/     sense = EVRcmp(a->R, b->R);
03691     }
03692 /*@=boundsread@*/
03693     a->str = _free(a->str);
03694     b->str = _free(b->str);
03695 
03696     /* Detect overlap of {A,B} range. */
03697     if (aFlags == RPMSENSE_NOTEQUAL || bFlags == RPMSENSE_NOTEQUAL) {
03698         result = (sense != 0);
03699     } else if (sense < 0 && ((aFlags & RPMSENSE_GREATER) || (bFlags & RPMSENSE_LESS))) {
03700         result = 1;
03701     } else if (sense > 0 && ((aFlags & RPMSENSE_LESS) || (bFlags & RPMSENSE_GREATER))) {
03702         result = 1;
03703     } else if (sense == 0 &&
03704         (((aFlags & RPMSENSE_EQUAL) && (bFlags & RPMSENSE_EQUAL)) ||
03705          ((aFlags & RPMSENSE_LESS) && (bFlags & RPMSENSE_LESS)) ||
03706          ((aFlags & RPMSENSE_GREATER) && (bFlags & RPMSENSE_GREATER)))) {
03707         result = 1;
03708     } else
03709         result = 0;
03710 /*@=nullderef@*/
03711 
03712 exit:
03713     if (_noisy_range_comparison_debug_message)
03714     rpmMessage(RPMMESS_DEBUG, D_("  %s    A %s\tB %s\n"),
03715         (result ? _("YES") : _("NO ")), aDepend, bDepend);
03716     aDepend = _free(aDepend);
03717     bDepend = _free(bDepend);
03718     return result;
03719 }
03720 
03721 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
03722         const fnpyKey * suggestedKeys, int adding)
03723 {
03724     const char * Name =  rpmdsN(ds);
03725     const char * DNEVR = rpmdsDNEVR(ds);
03726     const char * EVR = rpmdsEVR(ds);
03727     rpmProblemType type;
03728     fnpyKey key;
03729 
03730     if (ps == NULL) return;
03731 
03732     /*@-branchstate@*/
03733     if (Name == NULL) Name = "?N?";
03734     if (EVR == NULL) EVR = "?EVR?";
03735     if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
03736     /*@=branchstate@*/
03737 
03738     rpmMessage(RPMMESS_DEBUG, D_("package %s has unsatisfied %s: %s\n"),
03739             pkgNEVR, ds->Type, DNEVR+2);
03740 
03741     switch ((unsigned)DNEVR[0]) {
03742     case 'C':   type = RPMPROB_CONFLICT;        break;
03743     default:
03744     case 'R':   type = RPMPROB_REQUIRES;        break;
03745     }
03746 
03747     key = (suggestedKeys ? suggestedKeys[0] : NULL);
03748     rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
03749 }
03750 
03751 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
03752 {
03753     int scareMem = 0;
03754     rpmds provides = NULL;
03755     int_32 reqFlags = req->ns.Flags;
03756     int result = 1;
03757 
03758 assert((rpmdsFlags(req) & RPMSENSE_SENSEMASK) == req->ns.Flags);
03759     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
03760     if (req->EVR == NULL || req->Flags == NULL)
03761         goto exit;
03762 
03763     switch(req->ns.Type) {
03764     default:
03765 /*@-boundsread@*/
03766         /* Primary key retrieve satisfes an existence compare. */
03767         if (!reqFlags || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
03768             goto exit;
03769 /*@=boundsread@*/
03770         /*@fallthrough@*/
03771     case RPMNS_TYPE_ARCH:
03772         break;
03773     }
03774 
03775     /* Get provides information from header */
03776     provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
03777     if (provides == NULL) {
03778         result = 0;
03779         goto exit;      /* XXX should never happen */
03780     }
03781     if (nopromote)
03782         (void) rpmdsSetNoPromote(provides, nopromote);
03783 
03784     /*
03785      * Rpm prior to 3.0.3 did not have versioned provides.
03786      * If no provides version info is available, match any/all requires
03787      * with same name.
03788      */
03789     if (provides->EVR == NULL)
03790         goto exit;
03791 
03792     /* If any provide matches the require, we're done. */
03793     result = 0;
03794     if (provides != NULL)
03795     while (rpmdsNext(provides) >= 0)
03796         if ((result = rpmdsCompare(provides, req)))
03797             break;
03798 
03799 exit:
03800     provides = rpmdsFree(provides);
03801 
03802     return result;
03803 }
03804 
03805 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
03806 {
03807     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
03808     const char * pkgN, * V, * R;
03809     int_32 * epoch;
03810     const char * pkgEVR;
03811     char * t;
03812     int_32 reqFlags = req->ns.Flags;
03813     int_32 pkgFlags = RPMSENSE_EQUAL;
03814     int result = 1;
03815     rpmds pkg;
03816     size_t nb;
03817 
03818 assert((rpmdsFlags(req) & RPMSENSE_SENSEMASK) == req->ns.Flags);
03819     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
03820     if (req->EVR == NULL || req->Flags == NULL)
03821         goto exit;
03822 
03823 /*@-boundsread@*/
03824     if (!(reqFlags && req->EVR[req->i] && *req->EVR[req->i]))
03825         goto exit;
03826 /*@=boundsread@*/
03827 
03828     /* Get package information from header */
03829     (void) headerNVR(h, &pkgN, &V, &R);
03830 
03831     nb = 21 + 1 + 1;
03832     if (V) nb += strlen(V);
03833     if (R) nb += strlen(R);
03834 /*@-boundswrite@*/
03835     pkgEVR = t = alloca(nb);
03836     *t = '\0';
03837     if (hge(h, RPMTAG_EPOCH, NULL, &epoch, NULL)) {
03838         sprintf(t, "%d:", *epoch);
03839         t += strlen(t);
03840     }
03841     (void) stpcpy( stpcpy( stpcpy(t, V) , "-") , R);
03842 /*@=boundswrite@*/
03843 
03844     if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
03845         if (nopromote)
03846             (void) rpmdsSetNoPromote(pkg, nopromote);
03847         result = rpmdsCompare(pkg, req);
03848         pkg = rpmdsFree(pkg);
03849     }
03850 
03851 exit:
03852     return result;
03853 }
03854 
03855 int rpmdsNegateRC(const rpmds ds, int rc)
03856 {
03857     if (ds->ns.str[0] == '!')
03858         rc = (rc == 0);
03859     return rc;
03860 }

Generated on Sat Oct 1 16:48:18 2011 for rpm by  doxygen 1.4.4