|
rpm
5.4.4
|
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, (int (*) (const char **, const char **))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_DEPCACHE: 00211 strncpy(nameBuf, "Depcache", 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 case RPMDBI_SEQNO: 00232 strncpy(nameBuf, "Seqno", nameBufLen); 00233 break; 00234 case RPMDBI_BTREE: 00235 strncpy(nameBuf, "Btree", nameBufLen); 00236 break; 00237 case RPMDBI_HASH: 00238 strncpy(nameBuf, "Hash", nameBufLen); 00239 break; 00240 case RPMDBI_QUEUE: 00241 strncpy(nameBuf, "Queue", nameBufLen); 00242 break; 00243 case RPMDBI_RECNO: 00244 strncpy(nameBuf, "Recno", nameBufLen); 00245 break; 00246 case RPMDBI_HEAP: 00247 strncpy(nameBuf, "Heap", nameBufLen); 00248 break; 00249 00250 /* XXX make sure rpmdb indices are identically named. */ 00251 case RPMTAG_CONFLICTS: 00252 strncpy(nameBuf, "Conflictname", nameBufLen); 00253 break; 00254 case RPMTAG_HDRID: 00255 strncpy(nameBuf, "Sha1header", nameBufLen); 00256 break; 00257 00258 /* XXX make sure that h.['filenames'] in python "works". */ 00259 case 0x54aafb71: 00260 strncpy(nameBuf, "Filenames", nameBufLen); 00261 break; 00262 00263 default: 00264 if (_rpmTags.byValue == NULL) 00265 break; 00266 l = 0; 00267 u = _rpmTags.byValueSize; 00268 while (l < u) { 00269 i = (l + u) / 2; 00270 t = _rpmTags.byValue[i]; 00271 00272 comparison = ((int)tag - (int)t->val); 00273 00274 if (comparison < 0) 00275 u = i; 00276 else if (comparison > 0) 00277 l = i + 1; 00278 else { 00279 /* Make sure that the bsearch retrieve is stable. */ 00280 while (i > 0 && tag == _rpmTags.byValue[i-1]->val) { 00281 i--; 00282 t = _rpmTags.byValue[i]; 00283 } 00284 s = (*_rpmTags.tagCanonicalize) (t->name); 00285 strncpy(nameBuf, s, nameBufLen); 00286 s = _free(s); 00287 /*@loopbreak@*/ break; 00288 } 00289 } 00290 break; 00291 } 00292 if (nameBuf[0] == '\0') 00293 xx = snprintf(nameBuf, nameBufLen, "Tag_0x%08x", (unsigned) tag); 00294 nameBuf[nameBufLen-1] = '\0'; 00295 /*@-globstate@*/ /* _rpmTags.nameBuf reachable. */ 00296 return nameBuf; 00297 /*@=globstate@*/ 00298 } 00299 /*@=mods@*/ 00300 00301 static unsigned int _tagType(rpmTag tag) 00302 { 00303 headerTagTableEntry t; 00304 size_t i, l, u; 00305 int comparison; 00306 int xx; 00307 00308 if (_rpmTags.aTags == NULL) 00309 xx = tagLoadATags(&_rpmTags.aTags, NULL); 00310 if (_rpmTags.byValue == NULL) 00311 xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue); 00312 00313 switch (tag) { 00314 case RPMDBI_PACKAGES: 00315 case RPMDBI_DEPCACHE: 00316 case RPMDBI_ADDED: 00317 case RPMDBI_REMOVED: 00318 case RPMDBI_AVAILABLE: 00319 case RPMDBI_HDLIST: 00320 case RPMDBI_ARGLIST: 00321 case RPMDBI_FTSWALK: 00322 case RPMDBI_SEQNO: 00323 case RPMDBI_BTREE: 00324 case RPMDBI_HASH: 00325 case RPMDBI_QUEUE: 00326 case RPMDBI_RECNO: 00327 case RPMDBI_HEAP: 00328 break; 00329 default: 00330 if (_rpmTags.byValue == NULL) 00331 break; 00332 l = 0; 00333 u = _rpmTags.byValueSize; 00334 while (l < u) { 00335 i = (l + u) / 2; 00336 t = _rpmTags.byValue[i]; 00337 00338 comparison = ((int)tag - (int)t->val); 00339 00340 if (comparison < 0) 00341 u = i; 00342 else if (comparison > 0) 00343 l = i + 1; 00344 else { 00345 /* Make sure that the bsearch retrieve is stable. */ 00346 while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) { 00347 i--; 00348 t = _rpmTags.byValue[i]; 00349 } 00350 return t->type; 00351 } 00352 } 00353 break; 00354 } 00355 return 0; 00356 } 00357 00358 static rpmTag _tagValue(const char * tagstr) 00359 { 00360 headerTagTableEntry t; 00361 int comparison; 00362 size_t i, l, u; 00363 const char * s; 00364 rpmTag tag; 00365 int xx; 00366 00367 /* XXX headerSprintf looks up by "RPMTAG_FOO", not "FOO". */ 00368 if (!strncasecmp(tagstr, "RPMTAG_", sizeof("RPMTAG_")-1)) 00369 tagstr += sizeof("RPMTAG_") - 1; 00370 00371 if (!xstrcasecmp(tagstr, "Packages")) 00372 return RPMDBI_PACKAGES; 00373 if (!xstrcasecmp(tagstr, "Depcache")) 00374 return RPMDBI_DEPCACHE; 00375 if (!xstrcasecmp(tagstr, "Added")) 00376 return RPMDBI_ADDED; 00377 if (!xstrcasecmp(tagstr, "Removed")) 00378 return RPMDBI_REMOVED; 00379 if (!xstrcasecmp(tagstr, "Available")) 00380 return RPMDBI_AVAILABLE; 00381 if (!xstrcasecmp(tagstr, "Hdlist")) 00382 return RPMDBI_HDLIST; 00383 if (!xstrcasecmp(tagstr, "Arglist")) 00384 return RPMDBI_ARGLIST; 00385 if (!xstrcasecmp(tagstr, "Ftswalk")) 00386 return RPMDBI_FTSWALK; 00387 if (!xstrcasecmp(tagstr, "Seqno")) 00388 return RPMDBI_SEQNO; 00389 if (!xstrcasecmp(tagstr, "Btree")) 00390 return RPMDBI_BTREE; 00391 if (!xstrcasecmp(tagstr, "Hash")) 00392 return RPMDBI_HASH; 00393 if (!xstrcasecmp(tagstr, "Queue")) 00394 return RPMDBI_QUEUE; 00395 if (!xstrcasecmp(tagstr, "Recno")) 00396 return RPMDBI_RECNO; 00397 if (!xstrcasecmp(tagstr, "Heap")) 00398 return RPMDBI_HEAP; 00399 00400 if (_rpmTags.aTags == NULL) 00401 xx = tagLoadATags(&_rpmTags.aTags, NULL); 00402 if (_rpmTags.byName == NULL) 00403 xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName); 00404 if (_rpmTags.byName == NULL) 00405 goto exit; 00406 00407 l = 0; 00408 u = _rpmTags.byNameSize; 00409 while (l < u) { 00410 i = (l + u) / 2; 00411 t = _rpmTags.byName[i]; 00412 00413 comparison = xstrcasecmp(tagstr, t->name + (sizeof("RPMTAG_")-1)); 00414 00415 if (comparison < 0) 00416 u = i; 00417 else if (comparison > 0) 00418 l = i + 1; 00419 else 00420 return t->val; 00421 } 00422 00423 exit: 00424 /* Generate an arbitrary tag string. */ 00425 s = _tagCanonicalize(tagstr); 00426 tag = _tagGenerate(s); 00427 s = _free(s); 00428 return tag; 00429 } 00430 00431 const char * tagName(rpmTag tag) 00432 { 00433 return ((*rpmTags->tagName)(tag)); 00434 } 00435 00436 unsigned int tagType(rpmTag tag) 00437 { 00438 return ((*rpmTags->tagType)(tag)); 00439 } 00440 00441 rpmTag tagValue(const char * tagstr) 00442 { 00443 return ((*rpmTags->tagValue)(tagstr)); 00444 } 00445 00446 char * tagCanonicalize(const char * s) 00447 { 00448 return ((*rpmTags->tagCanonicalize)(s)); 00449 } 00450 00451 rpmTag tagGenerate(const char * s) 00452 { 00453 return ((*rpmTags->tagGenerate)(s)); 00454 } 00455 00456 void tagClean(headerTagIndices _rpmTags) 00457 { 00458 if (_rpmTags == NULL) 00459 _rpmTags = rpmTags; 00460 if (_rpmTags) { 00461 _rpmTags->nameBuf = _free(_rpmTags->nameBuf); 00462 _rpmTags->byName = _free(_rpmTags->byName); 00463 _rpmTags->byValue = _free(_rpmTags->byValue); 00464 _rpmTags->aTags = argvFree(_rpmTags->aTags); 00465 } 00466 } 00467 00468 tagStore_t tagStoreFree(tagStore_t dbiTags, size_t dbiNTags) 00469 { 00470 if (dbiTags != NULL) { 00471 size_t i; 00472 for (i = 0; i < dbiNTags; i++) { 00473 dbiTags[i].str = _free(dbiTags[i].str); 00474 dbiTags[i].iob = rpmiobFree(dbiTags[i].iob); 00475 } 00476 dbiTags = _free(dbiTags); 00477 } 00478 return NULL; 00479 } 00480 00481 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 00482 00486 void tagTypeValidate(HE_t he) 00487 { 00488 /* XXX hack around known borkage for now. */ 00489 if (!he->signature) 00490 if (!(he->tag == 261 || he->tag == 269)) 00491 if ((tagType(he->tag) & 0xffff) != he->t) 00492 fprintf(stderr, "==> warning: tag %u type(0x%x) != implicit type(0x%x)\n", (unsigned) he->tag, he->t, tagType(he->tag)); 00493 } 00494 #endif
1.7.5.1