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

# rpmdb/tagname.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio_internal.h>     /* XXX DIGEST_CTX, xtolower, xstrcasecmp */
    00008 #include <rpmmacro.h>
    00009 #include <argv.h>
    00010 #define _RPMTAG_INTERNAL
    00011 #include <rpmtag.h>
    00012 #include "debug.h"
    00013
    00014 /*@access headerTagTableEntry @*/
    00015 /*@access headerTagIndices @*/
    00016
    00022 static int tagLoadATags(/*@null@*/ ARGV_t * argvp,
    00023                 int (*cmp) (const void * avp, const void * bvp))
    00024         /*@globals rpmGlobalMacroContext, h_errno @*/
    00025         /*@modifies *argvp, rpmGlobalMacroContext @*/
    00026 {
    00027     ARGV_t aTags = NULL;
    00028     char * s = rpmExpand("%{?_arbitrary_tags}", NULL);
    00029
    00030     if (s && *s)
    00031         (void) argvSplit(&aTags, s, ":");
    00032     else
    00033         aTags = xcalloc(1, sizeof(*aTags));
    00034     if (aTags && aTags[0] && aTags[1])
    00035         (void) argvSort(aTags, cmp);
    00036     s = _free(s);
    00037
    00038     if (argvp)
    00039         *argvp = aTags;
    00040     else
    00041         aTags = argvFree(aTags);
    00042 /*@-nullstate@*/        /* *argvp may be NULL */
    00043     return 0;
    00044 /*@=nullstate@*/
    00045 }
    00046
    00053 static int tagCmpName(const void * avp, const void * bvp)
    00054         /*@*/
    00055 {
    00056     headerTagTableEntry a = *(headerTagTableEntry *) avp;
    00057     headerTagTableEntry b = *(headerTagTableEntry *) bvp;
    00058     return strcmp(a->name, b->name);
    00059 }
    00060
    00067 static int tagCmpValue(const void * avp, const void * bvp)
    00068         /*@*/
    00069 {
    00070     headerTagTableEntry a = *(headerTagTableEntry *) avp;
    00071     headerTagTableEntry b = *(headerTagTableEntry *) bvp;
    00072     int ret = ((int)a->val - (int)b->val);
    00073     /* Make sure that sort is stable, longest name first. */
    00074     if (ret == 0)
    00075         ret = ((int)strlen(b->name) - (int)strlen(a->name));
    00076     return ret;
    00077 }
    00078
    00086 static int tagLoadIndex(headerTagTableEntry ** ipp, size_t * np,
    00087                 int (*cmp) (const void * avp, const void * bvp))
    00088         /*@modifies *ipp, *np @*/
    00089 {
    00090     headerTagTableEntry tte, *ip;
    00091     size_t n = 0;
    00092
    00093     ip = xcalloc(rpmTagTableSize, sizeof(*ip));
    00094     n = 0;
    00095 /*@-dependenttrans@*/ /*@-observertrans@*/ /*@-castexpose@*/ /*@-mods@*/ /*@-modobserver@*/
    00096     for (tte = rpmTagTable; tte->name != NULL; tte++) {
    00097         ip[n] = tte;
    00098         n++;
    00099     }
    00100 assert(n == rpmTagTableSize);
    00101 /*@=dependenttrans@*/ /*@=observertrans@*/ /*@=castexpose@*/ /*@=mods@*/ /*@=modobserver@*/
    00102
    00103     if (n > 1)
    00104         qsort(ip, n, sizeof(*ip), cmp);
    00105     *ipp = ip;
    00106     *np = n;
    00107     return 0;
    00108 }
    00109
    00110 static char * _tagCanonicalize(const char * s)
    00111         /*@*/
    00112 {
    00113     const char * se;
    00114     size_t nb = 0;
    00115     char * te;
    00116     char * t;
    00117     int c;
    00118
    00119     if (!strncasecmp(s, "RPMTAG_", sizeof("RPMTAG_")-1))
    00120         s += sizeof("RPMTAG_") - 1;
    00121     se = s;
    00122     while ((c = (int)*se++) && xisalnum(c))
    00123         nb++;
    00124
    00125     te = t = xmalloc(nb+1);
    00126     if (*s != '\0' && nb > 0) {
    00127         *te++ = (char) xtoupper((int)*s++);
    00128         nb--;
    00129     }
    00130     while (nb--)
    00131         *te++ = (char) xtolower((int)*s++);
    00132     *te = '\0';
    00133
    00134     return t;
    00135 }
    00136
    00137 static rpmTag _tagGenerate(const char *s)
    00138         /*@*/
    00139 {
    00140     DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
    00141     const char * digest = NULL;
    00142     size_t digestlen = 0;
    00143     size_t nb = strlen(s);
    00144     rpmTag tag = 0;
    00145     int xx;
    00146
    00147     xx = rpmDigestUpdate(ctx, s, nb);
    00148     xx = rpmDigestFinal(ctx, &digest, &digestlen, 0);
    00149     if (digest && digestlen > 4) {
    00150         memcpy(&tag, digest + (digestlen - 4), 4);
    00151         tag &= 0x3fffffff;
    00152         tag |= 0x40000000;
    00153     }
    00154     digest = _free(digest);
    00155     return tag;
    00156 }
    00157
    00158 /* forward refs */
    00159 static const char * _tagName(rpmTag tag)
    00160         /*@globals rpmGlobalMacroContext, h_errno @*/
    00161         /*@modifies rpmGlobalMacroContext @*/;
    00162 static unsigned int _tagType(rpmTag tag)
    00163         /*@globals rpmGlobalMacroContext, h_errno @*/
    00164         /*@modifies rpmGlobalMacroContext @*/;
    00165 static rpmTag _tagValue(const char * tagstr)
    00166         /*@globals rpmGlobalMacroContext, h_errno @*/
    00167         /*@modifies rpmGlobalMacroContext @*/;
    00168
    00169 /*@unchecked@*/
    00170 static struct headerTagIndices_s _rpmTags = {
    00171     tagLoadIndex,
    00172     NULL, 0, tagCmpName, _tagValue,
    00173     NULL, 0, tagCmpValue, _tagName, _tagType,
    00174     256, NULL, NULL, _tagCanonicalize, _tagGenerate
    00175 };
    00176
    00177 /*@-compmempass@*/
    00178 /*@unchecked@*/
    00179 headerTagIndices rpmTags = &_rpmTags;
    00180 /*@=compmempass@*/
    00181
    00182 /*@-mods@*/
    00183 static const char * _tagName(rpmTag tag)
    00184 {
    00185     char * nameBuf;
    00186     size_t nameBufLen = 0;
    00187     headerTagTableEntry t;
    00188     size_t i, l, u;
    00189     int comparison;
    00190     int xx;
    00191     char *s;
    00192
    00193     if (_rpmTags.aTags == NULL)
    00194         xx = tagLoadATags(&_rpmTags.aTags, NULL);
    00195     if (_rpmTags.byValue == NULL)
    00196         xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize,
    00197                 tagCmpValue);
    00198     if (_rpmTags.nameBufLen == 0)
    00199         _rpmTags.nameBufLen = 256;
    00200     if (_rpmTags.nameBuf == NULL)
    00201         _rpmTags.nameBuf = xcalloc(1, _rpmTags.nameBufLen);
    00202     nameBuf = _rpmTags.nameBuf;
    00203     nameBuf[0] = nameBuf[1] = '\0';
    00204     nameBufLen = _rpmTags.nameBufLen;
    00205
    00206     switch (tag) {
    00207     case RPMDBI_PACKAGES:
    00208         strncpy(nameBuf, "Packages", nameBufLen);
    00209         break;
    00210     case RPMDBI_DEPENDS:
    00211         strncpy(nameBuf, "Depends", nameBufLen);
    00212         break;
    00213     case RPMDBI_ADDED:
    00214         strncpy(nameBuf, "Added", nameBufLen);
    00215         break;
    00216     case RPMDBI_REMOVED:
    00217         strncpy(nameBuf, "Removed", nameBufLen);
    00218         break;
    00219     case RPMDBI_AVAILABLE:
    00220         strncpy(nameBuf, "Available", nameBufLen);
    00221         break;
    00222     case RPMDBI_HDLIST:
    00223         strncpy(nameBuf, "Hdlist", nameBufLen);
    00224         break;
    00225     case RPMDBI_ARGLIST:
    00226         strncpy(nameBuf, "Arglist", nameBufLen);
    00227         break;
    00228     case RPMDBI_FTSWALK:
    00229         strncpy(nameBuf, "Ftswalk", nameBufLen);
    00230         break;
    00231
    00232     /* XXX make sure rpmdb indices are identically named. */
    00233     case RPMTAG_CONFLICTS:
    00234         strncpy(nameBuf, "Conflictname", nameBufLen);
    00235         break;
    00236     case RPMTAG_HDRID:
    00237         strncpy(nameBuf, "Sha1header", nameBufLen);
    00238         break;
    00239
    00240     default:
    00241         if (_rpmTags.byValue == NULL)
    00242             break;
    00243         l = 0;
    00244         u = _rpmTags.byValueSize;
    00245         while (l < u) {
    00246             i = (l + u) / 2;
    00247             t = _rpmTags.byValue[i];
    00248
    00249             comparison = ((int)tag - (int)t->val);
    00250
    00251             if (comparison < 0)
    00252                 u = i;
    00253             else if (comparison > 0)
    00254                 l = i + 1;
    00255             else {
    00256                 /* Make sure that the bsearch retrieve is stable. */
    00257                 while (i > 0 && tag == _rpmTags.byValue[i-1]->val) {
    00258                     i--;
    00259                     t--;
    00260                 }
    00261                 t = _rpmTags.byValue[i];
    00262                 s = (*_rpmTags.tagCanonicalize) (t->name);
    00263                 strncpy(nameBuf, s, nameBufLen);
    00264                 s = _free(s);
    00265                 /*@loopbreak@*/ break;
    00266             }
    00267         }
    00268         break;
    00269     }
    00270     if (nameBuf[0] == '\0')
    00271         xx = snprintf(nameBuf, nameBufLen, "Tag_0x%08x", (unsigned) tag);
    00272     nameBuf[nameBufLen-1] = '\0';
    00273 /*@-globstate@*/        /* _rpmTags.nameBuf reachable. */
    00274     return nameBuf;
    00275 /*@=globstate@*/
    00276 }
    00277 /*@=mods@*/
    00278
    00279 static unsigned int _tagType(rpmTag tag)
    00280 {
    00281     headerTagTableEntry t;
    00282     size_t i, l, u;
    00283     int comparison;
    00284     int xx;
    00285
    00286     if (_rpmTags.aTags == NULL)
    00287         xx = tagLoadATags(&_rpmTags.aTags, NULL);
    00288     if (_rpmTags.byValue == NULL)
    00289         xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
    00290
    00291     switch (tag) {
    00292     case RPMDBI_PACKAGES:
    00293     case RPMDBI_DEPENDS:
    00294     case RPMDBI_ADDED:
    00295     case RPMDBI_REMOVED:
    00296     case RPMDBI_AVAILABLE:
    00297     case RPMDBI_HDLIST:
    00298     case RPMDBI_ARGLIST:
    00299     case RPMDBI_FTSWALK:
    00300         break;
    00301     default:
    00302         if (_rpmTags.byValue == NULL)
    00303             break;
    00304         l = 0;
    00305         u = _rpmTags.byValueSize;
    00306         while (l < u) {
    00307             i = (l + u) / 2;
    00308             t = _rpmTags.byValue[i];
    00309
    00310             comparison = ((int)tag - (int)t->val);
    00311
    00312             if (comparison < 0)
    00313                 u = i;
    00314             else if (comparison > 0)
    00315                 l = i + 1;
    00316             else {
    00317                 /* Make sure that the bsearch retrieve is stable. */
    00318                 while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) {
    00319                     i--;
    00320                     t--;
    00321                 }
    00322                 return t->type;
    00323             }
    00324         }
    00325         break;
    00326     }
    00327     return 0;
    00328 }
    00329
    00330 static rpmTag _tagValue(const char * tagstr)
    00331 {
    00332     headerTagTableEntry t;
    00333     int comparison;
    00334     size_t i, l, u;
    00335     const char * s;
    00336     rpmTag tag;
    00337     int xx;
    00338
    00339     /* XXX headerSprintf looks up by "RPMTAG_FOO", not "FOO". */
    00340     if (!strncasecmp(tagstr, "RPMTAG_", sizeof("RPMTAG_")-1))
    00341         tagstr += sizeof("RPMTAG_") - 1;
    00342
    00343     if (!xstrcasecmp(tagstr, "Packages"))
    00344         return RPMDBI_PACKAGES;
    00345     if (!xstrcasecmp(tagstr, "Depends"))
    00346         return RPMDBI_DEPENDS;
    00347     if (!xstrcasecmp(tagstr, "Added"))
    00348         return RPMDBI_ADDED;
    00349     if (!xstrcasecmp(tagstr, "Removed"))
    00350         return RPMDBI_REMOVED;
    00351     if (!xstrcasecmp(tagstr, "Available"))
    00352         return RPMDBI_AVAILABLE;
    00353     if (!xstrcasecmp(tagstr, "Hdlist"))
    00354         return RPMDBI_HDLIST;
    00355     if (!xstrcasecmp(tagstr, "Arglist"))
    00356         return RPMDBI_ARGLIST;
    00357     if (!xstrcasecmp(tagstr, "Ftswalk"))
    00358         return RPMDBI_FTSWALK;
    00359
    00360     if (_rpmTags.aTags == NULL)
    00361         xx = tagLoadATags(&_rpmTags.aTags, NULL);
    00362     if (_rpmTags.byName == NULL)
    00363         xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
    00364     if (_rpmTags.byName == NULL)
    00365         goto exit;
    00366
    00367     l = 0;
    00368     u = _rpmTags.byNameSize;
    00369     while (l < u) {
    00370         i = (l + u) / 2;
    00371         t = _rpmTags.byName[i];
    00372
    00373         comparison = xstrcasecmp(tagstr, t->name + (sizeof("RPMTAG_")-1));
    00374
    00375         if (comparison < 0)
    00376             u = i;
    00377         else if (comparison > 0)
    00378             l = i + 1;
    00379         else
    00380             return t->val;
    00381     }
    00382
    00383 exit:
    00384     /* Generate an arbitrary tag string. */
    00385     s = _tagCanonicalize(tagstr);
    00386     tag = _tagGenerate(s);
    00387     s = _free(s);
    00388     return tag;
    00389 }
    00390
    00391 const char * tagName(rpmTag tag)
    00392 {
    00393     return ((*rpmTags->tagName)(tag));
    00394 }
    00395
    00396 unsigned int tagType(rpmTag tag)
    00397 {
    00398     return ((*rpmTags->tagType)(tag));
    00399 }
    00400
    00401 rpmTag tagValue(const char * tagstr)
    00402 {
    00403     return ((*rpmTags->tagValue)(tagstr));
    00404 }
    00405
    00406 char * tagCanonicalize(const char * s)
    00407 {
    00408     return ((*rpmTags->tagCanonicalize)(s));
    00409 }
    00410
    00411 rpmTag tagGenerate(const char * s)
    00412 {
    00413     return ((*rpmTags->tagGenerate)(s));
    00414 }
    00415
    00416 void tagClean(headerTagIndices _rpmTags)
    00417 {
    00418     if (_rpmTags == NULL)
    00419         _rpmTags = rpmTags;
    00420    if (_rpmTags) {
    00421         _rpmTags->nameBuf = _free(_rpmTags->nameBuf);
    00422         _rpmTags->byName = _free(_rpmTags->byName);
    00423         _rpmTags->byValue = _free(_rpmTags->byValue);
    00424         _rpmTags->aTags = argvFree(_rpmTags->aTags);
    00425     }
    00426 }
    00427
    00428 tagStore_t tagStoreFree(tagStore_t dbiTags, size_t dbiNTags)
    00429 {
    00430     if (dbiTags != NULL) {
    00431         size_t i;
    00432         for (i = 0; i < dbiNTags; i++) {
    00433             dbiTags[i].str = _free(dbiTags[i].str);
    00434             dbiTags[i].val = freeStringBuf(dbiTags[i].val);
    00435         }
    00436         dbiTags = _free(dbiTags);
    00437     }
    00438     return NULL;
    00439 }
    00440
    00441 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
    00442
    00446 void tagTypeValidate(HE_t he)
    00447 {
    00448 /* XXX hack around known borkage for now. */
    00449 if (!he->signature)
    00450 if (!(he->tag == 261 || he->tag == 269))
    00451 if ((tagType(he->tag) & 0xffff) != he->t)
    00452 fprintf(stderr, "==> warning: tag %u type(0x%x) != implicit type(0x%x)\n", (unsigned) he->tag, he->t, tagType(he->tag));
    00453 }
    00454 #endif