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