00001
00005 #include "system.h"
00006
00007 #include <rpmio_internal.h>
00008 #include <rpmmacro.h>
00009 #include <argv.h>
00010 #define _RPMTAG_INTERNAL
00011 #include <rpmtag.h>
00012 #include "debug.h"
00013
00014
00015
00016
00022 static int tagLoadATags( ARGV_t * argvp,
00023 int (*cmp) (const void * avp, const void * bvp))
00024
00025
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
00043 return 0;
00044
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
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
00089 {
00090 headerTagTableEntry tte, *ip;
00091 size_t n = 0;
00092
00093 ip = xcalloc(rpmTagTableSize, sizeof(*ip));
00094 n = 0;
00095
00096 for (tte = rpmTagTable; tte->name != NULL; tte++) {
00097 ip[n] = tte;
00098 n++;
00099 }
00100 assert(n == (size_t)rpmTagTableSize);
00101
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
00159 static const char * _tagName(rpmTag tag)
00160
00161 ;
00162 static unsigned int _tagType(rpmTag tag)
00163
00164 ;
00165 static rpmTag _tagValue(const char * tagstr)
00166
00167 ;
00168
00169
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
00178
00179 headerTagIndices rpmTags = &_rpmTags;
00180
00181
00182
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
00233 case RPMTAG_CONFLICTS:
00234 strncpy(nameBuf, "Conflictname", nameBufLen);
00235 break;
00236 case RPMTAG_HDRID:
00237 strncpy(nameBuf, "Sha1header", nameBufLen);
00238 break;
00239
00240
00241 case 0x54aafb71:
00242 strncpy(nameBuf, "Filenames", nameBufLen);
00243 break;
00244
00245 default:
00246 if (_rpmTags.byValue == NULL)
00247 break;
00248 l = 0;
00249 u = _rpmTags.byValueSize;
00250 while (l < u) {
00251 i = (l + u) / 2;
00252 t = _rpmTags.byValue[i];
00253
00254 comparison = ((int)tag - (int)t->val);
00255
00256 if (comparison < 0)
00257 u = i;
00258 else if (comparison > 0)
00259 l = i + 1;
00260 else {
00261
00262 while (i > 0 && tag == _rpmTags.byValue[i-1]->val) {
00263 i--;
00264 t = _rpmTags.byValue[i];
00265 }
00266 s = (*_rpmTags.tagCanonicalize) (t->name);
00267 strncpy(nameBuf, s, nameBufLen);
00268 s = _free(s);
00269 break;
00270 }
00271 }
00272 break;
00273 }
00274 if (nameBuf[0] == '\0')
00275 xx = snprintf(nameBuf, nameBufLen, "Tag_0x%08x", (unsigned) tag);
00276 nameBuf[nameBufLen-1] = '\0';
00277
00278 return nameBuf;
00279
00280 }
00281
00282
00283 static unsigned int _tagType(rpmTag tag)
00284 {
00285 headerTagTableEntry t;
00286 size_t i, l, u;
00287 int comparison;
00288 int xx;
00289
00290 if (_rpmTags.aTags == NULL)
00291 xx = tagLoadATags(&_rpmTags.aTags, NULL);
00292 if (_rpmTags.byValue == NULL)
00293 xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
00294
00295 switch (tag) {
00296 case RPMDBI_PACKAGES:
00297 case RPMDBI_DEPENDS:
00298 case RPMDBI_ADDED:
00299 case RPMDBI_REMOVED:
00300 case RPMDBI_AVAILABLE:
00301 case RPMDBI_HDLIST:
00302 case RPMDBI_ARGLIST:
00303 case RPMDBI_FTSWALK:
00304 break;
00305 default:
00306 if (_rpmTags.byValue == NULL)
00307 break;
00308 l = 0;
00309 u = _rpmTags.byValueSize;
00310 while (l < u) {
00311 i = (l + u) / 2;
00312 t = _rpmTags.byValue[i];
00313
00314 comparison = ((int)tag - (int)t->val);
00315
00316 if (comparison < 0)
00317 u = i;
00318 else if (comparison > 0)
00319 l = i + 1;
00320 else {
00321
00322 while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) {
00323 i--;
00324 t = _rpmTags.byValue[i];
00325 }
00326 return t->type;
00327 }
00328 }
00329 break;
00330 }
00331 return 0;
00332 }
00333
00334 static rpmTag _tagValue(const char * tagstr)
00335 {
00336 headerTagTableEntry t;
00337 int comparison;
00338 size_t i, l, u;
00339 const char * s;
00340 rpmTag tag;
00341 int xx;
00342
00343
00344 if (!strncasecmp(tagstr, "RPMTAG_", sizeof("RPMTAG_")-1))
00345 tagstr += sizeof("RPMTAG_") - 1;
00346
00347 if (!xstrcasecmp(tagstr, "Packages"))
00348 return RPMDBI_PACKAGES;
00349 if (!xstrcasecmp(tagstr, "Depends"))
00350 return RPMDBI_DEPENDS;
00351 if (!xstrcasecmp(tagstr, "Added"))
00352 return RPMDBI_ADDED;
00353 if (!xstrcasecmp(tagstr, "Removed"))
00354 return RPMDBI_REMOVED;
00355 if (!xstrcasecmp(tagstr, "Available"))
00356 return RPMDBI_AVAILABLE;
00357 if (!xstrcasecmp(tagstr, "Hdlist"))
00358 return RPMDBI_HDLIST;
00359 if (!xstrcasecmp(tagstr, "Arglist"))
00360 return RPMDBI_ARGLIST;
00361 if (!xstrcasecmp(tagstr, "Ftswalk"))
00362 return RPMDBI_FTSWALK;
00363
00364 if (_rpmTags.aTags == NULL)
00365 xx = tagLoadATags(&_rpmTags.aTags, NULL);
00366 if (_rpmTags.byName == NULL)
00367 xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
00368 if (_rpmTags.byName == NULL)
00369 goto exit;
00370
00371 l = 0;
00372 u = _rpmTags.byNameSize;
00373 while (l < u) {
00374 i = (l + u) / 2;
00375 t = _rpmTags.byName[i];
00376
00377 comparison = xstrcasecmp(tagstr, t->name + (sizeof("RPMTAG_")-1));
00378
00379 if (comparison < 0)
00380 u = i;
00381 else if (comparison > 0)
00382 l = i + 1;
00383 else
00384 return t->val;
00385 }
00386
00387 exit:
00388
00389 s = _tagCanonicalize(tagstr);
00390 tag = _tagGenerate(s);
00391 s = _free(s);
00392 return tag;
00393 }
00394
00395 const char * tagName(rpmTag tag)
00396 {
00397 return ((*rpmTags->tagName)(tag));
00398 }
00399
00400 unsigned int tagType(rpmTag tag)
00401 {
00402 return ((*rpmTags->tagType)(tag));
00403 }
00404
00405 rpmTag tagValue(const char * tagstr)
00406 {
00407 return ((*rpmTags->tagValue)(tagstr));
00408 }
00409
00410 char * tagCanonicalize(const char * s)
00411 {
00412 return ((*rpmTags->tagCanonicalize)(s));
00413 }
00414
00415 rpmTag tagGenerate(const char * s)
00416 {
00417 return ((*rpmTags->tagGenerate)(s));
00418 }
00419
00420 void tagClean(headerTagIndices _rpmTags)
00421 {
00422 if (_rpmTags == NULL)
00423 _rpmTags = rpmTags;
00424 if (_rpmTags) {
00425 _rpmTags->nameBuf = _free(_rpmTags->nameBuf);
00426 _rpmTags->byName = _free(_rpmTags->byName);
00427 _rpmTags->byValue = _free(_rpmTags->byValue);
00428 _rpmTags->aTags = argvFree(_rpmTags->aTags);
00429 }
00430 }
00431
00432 tagStore_t tagStoreFree(tagStore_t dbiTags, size_t dbiNTags)
00433 {
00434 if (dbiTags != NULL) {
00435 size_t i;
00436 for (i = 0; i < dbiNTags; i++) {
00437 dbiTags[i].str = _free(dbiTags[i].str);
00438 dbiTags[i].iob = rpmiobFree(dbiTags[i].iob);
00439 }
00440 dbiTags = _free(dbiTags);
00441 }
00442 return NULL;
00443 }
00444
00445 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00446
00450 void tagTypeValidate(HE_t he)
00451 {
00452
00453 if (!he->signature)
00454 if (!(he->tag == 261 || he->tag == 269))
00455 if ((tagType(he->tag) & 0xffff) != he->t)
00456 fprintf(stderr, "==> warning: tag %u type(0x%x) != implicit type(0x%x)\n", (unsigned) he->tag, he->t, tagType(he->tag));
00457 }
00458 #endif