• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

lib/rpmds.c

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

Generated on Mon Nov 29 2010 05:18:44 for rpm by  doxygen 1.7.2