rpm 5.2.1

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

- File List
- Globals

tagname.c
Go to the documentation of this file.
1
5 #include "system.h"
6
7 #include <rpmio_internal.h> /* XXX DIGEST_CTX, xtolower, xstrcasecmp */
8 #include <rpmmacro.h>
9 #include <argv.h>
10 #define _RPMTAG_INTERNAL
11 #include <rpmtag.h>
12 #include "debug.h"
13
14 /*@access headerTagTableEntry @*/
15 /*@access headerTagIndices @*/
16
22 static int tagLoadATags(/*@null@*/ ARGV_t * argvp,
23 int (*cmp) (const void * avp, const void * bvp))
24 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
25 /*@modifies *argvp, rpmGlobalMacroContext, internalState @*/
26 {
27 ARGV_t aTags = NULL;
28 char * s = rpmExpand("%{?_arbitrary_tags}", NULL);
29
30 if (s && *s)
31 (void) argvSplit(&aTags, s, ":");
32 else
33 aTags = xcalloc(1, sizeof(*aTags));
34 if (aTags && aTags[0] && aTags[1])
35 (void) argvSort(aTags, cmp);
36 s = _free(s);
37
38 if (argvp)
39 *argvp = aTags;
40 else
41 aTags = argvFree(aTags);
42 /*@-nullstate@*/ /* *argvp may be NULL */
43 return 0;
44 /*@=nullstate@*/
45 }
46
53 static int tagCmpName(const void * avp, const void * bvp)
54 /*@*/
55 {
56 headerTagTableEntry a = *(headerTagTableEntry *) avp;
57 headerTagTableEntry b = *(headerTagTableEntry *) bvp;
58 return strcmp(a->name, b->name);
59 }
60
67 static int tagCmpValue(const void * avp, const void * bvp)
68 /*@*/
69 {
70 headerTagTableEntry a = *(headerTagTableEntry *) avp;
71 headerTagTableEntry b = *(headerTagTableEntry *) bvp;
72 int ret = ((int)a->val - (int)b->val);
73 /* Make sure that sort is stable, longest name first. */
74 if (ret == 0)
75 ret = ((int)strlen(b->name) - (int)strlen(a->name));
76 return ret;
77 }
78
86 static int tagLoadIndex(headerTagTableEntry ** ipp, size_t * np,
87 int (*cmp) (const void * avp, const void * bvp))
88 /*@modifies *ipp, *np @*/
89 {
90 headerTagTableEntry tte, *ip;
91 size_t n = 0;
92
93 ip = xcalloc(rpmTagTableSize, sizeof(*ip));
94 n = 0;
95 /*@-dependenttrans@*/ /*@-observertrans@*/ /*@-castexpose@*/ /*@-mods@*/ /*@-modobserver@*/
96 for (tte = rpmTagTable; tte->name != NULL; tte++) {
97 ip[n] = tte;
98 n++;
99 }
100 assert(n == (size_t)rpmTagTableSize);
101 /*@=dependenttrans@*/ /*@=observertrans@*/ /*@=castexpose@*/ /*@=mods@*/ /*@=modobserver@*/
102
103 if (n > 1)
104 qsort(ip, n, sizeof(*ip), cmp);
105 *ipp = ip;
106 *np = n;
107 return 0;
108 }
109
110 static char * _tagCanonicalize(const char * s)
111 /*@*/
112 {
113 const char * se;
114 size_t nb = 0;
115 char * te;
116 char * t;
117 int c;
118
119 if (!strncasecmp(s, "RPMTAG_", sizeof("RPMTAG_")-1))
120 s += sizeof("RPMTAG_") - 1;
121 se = s;
122 while ((c = (int)*se++) && xisalnum(c))
123 nb++;
124
125 te = t = xmalloc(nb+1);
126 if (*s != '\0' && nb > 0) {
127 *te++ = (char) xtoupper((int)*s++);
128 nb--;
129 }
130 while (nb--)
131 *te++ = (char) xtolower((int)*s++);
132 *te = '\0';
133
134 return t;
135 }
136
137 static rpmTag _tagGenerate(const char *s)
138 /*@*/
139 {
140 DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
141 const char * digest = NULL;
142 size_t digestlen = 0;
143 size_t nb = strlen(s);
144 rpmTag tag = 0;
145 int xx;
146
147 xx = rpmDigestUpdate(ctx, s, nb);
148 xx = rpmDigestFinal(ctx, &digest, &digestlen, 0);
149 if (digest && digestlen > 4) {
150 memcpy(&tag, digest + (digestlen - 4), 4);
151 tag &= 0x3fffffff;
152 tag |= 0x40000000;
153 }
154 digest = _free(digest);
155 return tag;
156 }
157
158 /* forward refs */
159 static const char * _tagName(rpmTag tag)
160 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
161 /*@modifies rpmGlobalMacroContext, internalState @*/;
162 static unsigned int _tagType(rpmTag tag)
163 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
164 /*@modifies rpmGlobalMacroContext, internalState @*/;
165 static rpmTag _tagValue(const char * tagstr)
166 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
167 /*@modifies rpmGlobalMacroContext, internalState @*/;
168
169 /*@unchecked@*/
170 static struct headerTagIndices_s _rpmTags = {
171 tagLoadIndex,
172 NULL, 0, tagCmpName, _tagValue,
173 NULL, 0, tagCmpValue, _tagName, _tagType,
174 256, NULL, NULL, _tagCanonicalize, _tagGenerate
175 };
176
177 /*@-compmempass@*/
178 /*@unchecked@*/
179 headerTagIndices rpmTags = &_rpmTags;
180 /*@=compmempass@*/
181
182 /*@-mods@*/
183 static const char * _tagName(rpmTag tag)
184 {
185 char * nameBuf;
186 size_t nameBufLen = 0;
187 headerTagTableEntry t;
188 size_t i, l, u;
189 int comparison;
190 int xx;
191 char *s;
192
193 if (_rpmTags.aTags == NULL)
194 xx = tagLoadATags(&_rpmTags.aTags, NULL);
195 if (_rpmTags.byValue == NULL)
196 xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize,
197 tagCmpValue);
198 if (_rpmTags.nameBufLen == 0)
199 _rpmTags.nameBufLen = 256;
200 if (_rpmTags.nameBuf == NULL)
201 _rpmTags.nameBuf = xcalloc(1, _rpmTags.nameBufLen);
202 nameBuf = _rpmTags.nameBuf;
203 nameBuf[0] = nameBuf[1] = '\0';
204 nameBufLen = _rpmTags.nameBufLen;
205
206 switch (tag) {
207 case RPMDBI_PACKAGES:
208 strncpy(nameBuf, "Packages", nameBufLen);
209 break;
210 case RPMDBI_DEPENDS:
211 strncpy(nameBuf, "Depends", nameBufLen);
212 break;
213 case RPMDBI_ADDED:
214 strncpy(nameBuf, "Added", nameBufLen);
215 break;
216 case RPMDBI_REMOVED:
217 strncpy(nameBuf, "Removed", nameBufLen);
218 break;
219 case RPMDBI_AVAILABLE:
220 strncpy(nameBuf, "Available", nameBufLen);
221 break;
222 case RPMDBI_HDLIST:
223 strncpy(nameBuf, "Hdlist", nameBufLen);
224 break;
225 case RPMDBI_ARGLIST:
226 strncpy(nameBuf, "Arglist", nameBufLen);
227 break;
228 case RPMDBI_FTSWALK:
229 strncpy(nameBuf, "Ftswalk", nameBufLen);
230 break;
231
232 /* XXX make sure rpmdb indices are identically named. */
233 case RPMTAG_CONFLICTS:
234 strncpy(nameBuf, "Conflictname", nameBufLen);
235 break;
236 case RPMTAG_HDRID:
237 strncpy(nameBuf, "Sha1header", nameBufLen);
238 break;
239
240 /* XXX make sure that h.['filenames'] in python "works". */
241 case 0x54aafb71:
242 strncpy(nameBuf, "Filenames", nameBufLen);
243 break;
244
245 default:
246 if (_rpmTags.byValue == NULL)
247 break;
248 l = 0;
249 u = _rpmTags.byValueSize;
250 while (l < u) {
251 i = (l + u) / 2;
252 t = _rpmTags.byValue[i];
253
254 comparison = ((int)tag - (int)t->val);
255
256 if (comparison < 0)
257 u = i;
258 else if (comparison > 0)
259 l = i + 1;
260 else {
261 /* Make sure that the bsearch retrieve is stable. */
262 while (i > 0 && tag == _rpmTags.byValue[i-1]->val) {
263 i--;
264 t = _rpmTags.byValue[i];
265 }
266 s = (*_rpmTags.tagCanonicalize) (t->name);
267 strncpy(nameBuf, s, nameBufLen);
268 s = _free(s);
269 /*@loopbreak@*/ break;
270 }
271 }
272 break;
273 }
274 if (nameBuf[0] == '\0')
275 xx = snprintf(nameBuf, nameBufLen, "Tag_0x%08x", (unsigned) tag);
276 nameBuf[nameBufLen-1] = '\0';
277 /*@-globstate@*/ /* _rpmTags.nameBuf reachable. */
278 return nameBuf;
279 /*@=globstate@*/
280 }
281 /*@=mods@*/
282
283 static unsigned int _tagType(rpmTag tag)
284 {
285 headerTagTableEntry t;
286 size_t i, l, u;
287 int comparison;
288 int xx;
289
290 if (_rpmTags.aTags == NULL)
291 xx = tagLoadATags(&_rpmTags.aTags, NULL);
292 if (_rpmTags.byValue == NULL)
293 xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
294
295 switch (tag) {
296 case RPMDBI_PACKAGES:
297 case RPMDBI_DEPENDS:
298 case RPMDBI_ADDED:
299 case RPMDBI_REMOVED:
300 case RPMDBI_AVAILABLE:
301 case RPMDBI_HDLIST:
302 case RPMDBI_ARGLIST:
303 case RPMDBI_FTSWALK:
304 break;
305 default:
306 if (_rpmTags.byValue == NULL)
307 break;
308 l = 0;
309 u = _rpmTags.byValueSize;
310 while (l < u) {
311 i = (l + u) / 2;
312 t = _rpmTags.byValue[i];
313
314 comparison = ((int)tag - (int)t->val);
315
316 if (comparison < 0)
317 u = i;
318 else if (comparison > 0)
319 l = i + 1;
320 else {
321 /* Make sure that the bsearch retrieve is stable. */
322 while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) {
323 i--;
324 t = _rpmTags.byValue[i];
325 }
326 return t->type;
327 }
328 }
329 break;
330 }
331 return 0;
332 }
333
334 static rpmTag _tagValue(const char * tagstr)
335 {
336 headerTagTableEntry t;
337 int comparison;
338 size_t i, l, u;
339 const char * s;
340 rpmTag tag;
341 int xx;
342
343 /* XXX headerSprintf looks up by "RPMTAG_FOO", not "FOO". */
344 if (!strncasecmp(tagstr, "RPMTAG_", sizeof("RPMTAG_")-1))
345 tagstr += sizeof("RPMTAG_") - 1;
346
347 if (!xstrcasecmp(tagstr, "Packages"))
348 return RPMDBI_PACKAGES;
349 if (!xstrcasecmp(tagstr, "Depends"))
350 return RPMDBI_DEPENDS;
351 if (!xstrcasecmp(tagstr, "Added"))
352 return RPMDBI_ADDED;
353 if (!xstrcasecmp(tagstr, "Removed"))
354 return RPMDBI_REMOVED;
355 if (!xstrcasecmp(tagstr, "Available"))
356 return RPMDBI_AVAILABLE;
357 if (!xstrcasecmp(tagstr, "Hdlist"))
358 return RPMDBI_HDLIST;
359 if (!xstrcasecmp(tagstr, "Arglist"))
360 return RPMDBI_ARGLIST;
361 if (!xstrcasecmp(tagstr, "Ftswalk"))
362 return RPMDBI_FTSWALK;
363
364 if (_rpmTags.aTags == NULL)
365 xx = tagLoadATags(&_rpmTags.aTags, NULL);
366 if (_rpmTags.byName == NULL)
367 xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
368 if (_rpmTags.byName == NULL)
369 goto exit;
370
371 l = 0;
372 u = _rpmTags.byNameSize;
373 while (l < u) {
374 i = (l + u) / 2;
375 t = _rpmTags.byName[i];
376
377 comparison = xstrcasecmp(tagstr, t->name + (sizeof("RPMTAG_")-1));
378
379 if (comparison < 0)
380 u = i;
381 else if (comparison > 0)
382 l = i + 1;
383 else
384 return t->val;
385 }
386
387 exit:
388 /* Generate an arbitrary tag string. */
389 s = _tagCanonicalize(tagstr);
390 tag = _tagGenerate(s);
391 s = _free(s);
392 return tag;
393 }
394
395 const char * tagName(rpmTag tag)
396 {
397 return ((*rpmTags->tagName)(tag));
398 }
399
400 unsigned int tagType(rpmTag tag)
401 {
402 return ((*rpmTags->tagType)(tag));
403 }
404
405 rpmTag tagValue(const char * tagstr)
406 {
407 return ((*rpmTags->tagValue)(tagstr));
408 }
409
410 char * tagCanonicalize(const char * s)
411 {
412 return ((*rpmTags->tagCanonicalize)(s));
413 }
414
415 rpmTag tagGenerate(const char * s)
416 {
417 return ((*rpmTags->tagGenerate)(s));
418 }
419
420 void tagClean(headerTagIndices _rpmTags)
421 {
422 if (_rpmTags == NULL)
423 _rpmTags = rpmTags;
424 if (_rpmTags) {
425 _rpmTags->nameBuf = _free(_rpmTags->nameBuf);
426 _rpmTags->byName = _free(_rpmTags->byName);
427 _rpmTags->byValue = _free(_rpmTags->byValue);
428 _rpmTags->aTags = argvFree(_rpmTags->aTags);
429 }
430 }
431
432 tagStore_t tagStoreFree(tagStore_t dbiTags, size_t dbiNTags)
433 {
434 if (dbiTags != NULL) {
435 size_t i;
436 for (i = 0; i < dbiNTags; i++) {
437 dbiTags[i].str = _free(dbiTags[i].str);
438 dbiTags[i].iob = rpmiobFree(dbiTags[i].iob);
439 }
440 dbiTags = _free(dbiTags);
441 }
442 return NULL;
443 }
444
445 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
446
450 void tagTypeValidate(HE_t he)
451 {
452 /* XXX hack around known borkage for now. */
453 if (!he->signature)
454 if (!(he->tag == 261 || he->tag == 269))
455 if ((tagType(he->tag) & 0xffff) != he->t)
456 fprintf(stderr, "==> warning: tag %u type(0x%x) != implicit type(0x%x)\n", (unsigned) he->tag, he->t, tagType(he->tag));
457 }
458 #endif