rpm  5.2.1
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 {
58  return strcmp(a->name, b->name);
59 }
60 
67 static int tagCmpValue(const void * avp, const void * bvp)
68  /*@*/
69 {
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 {
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@*/
180 /*@=compmempass@*/
181 
182 /*@-mods@*/
183 static const char * _tagName(rpmTag tag)
184 {
185  char * nameBuf;
186  size_t nameBufLen = 0;
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 {
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 {
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 
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