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

# lib/rpmds.c

Go to the documentation of this file.

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