rpm 5.2.1
|
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, internalState @*/ 00025 /*@modifies *argvp, rpmGlobalMacroContext, internalState @*/ 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 == (size_t)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, internalState @*/ 00161 /*@modifies rpmGlobalMacroContext, internalState @*/; 00162 static unsigned int _tagType(rpmTag tag) 00163 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00164 /*@modifies rpmGlobalMacroContext, internalState @*/; 00165 static rpmTag _tagValue(const char * tagstr) 00166 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00167 /*@modifies rpmGlobalMacroContext, internalState @*/; 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 /* XXX make sure that h.['filenames'] in python "works". */ 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 /* Make sure that the bsearch retrieve is stable. */ 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 /*@loopbreak@*/ 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 /*@-globstate@*/ /* _rpmTags.nameBuf reachable. */ 00278 return nameBuf; 00279 /*@=globstate@*/ 00280 } 00281 /*@=mods@*/ 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 /* Make sure that the bsearch retrieve is stable. */ 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 /* XXX headerSprintf looks up by "RPMTAG_FOO", not "FOO". */ 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 /* Generate an arbitrary tag string. */ 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 /* XXX hack around known borkage for now. */ 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