lib/rpmds.c

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

Generated on Fri Aug 31 11:16:07 2007 for rpm by  doxygen 1.4.6