rpm  5.4.15
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 
17 #ifdef __cplusplus
18 GENfree(tagStore_t)
19 GENfree(headerTagTableEntry *)
20 #endif /* __cplusplus */
21 
27 static int tagLoadATags(/*@null@*/ ARGV_t * argvp,
28  int (*cmp) (const void * avp, const void * bvp))
29  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
30  /*@modifies *argvp, rpmGlobalMacroContext, internalState @*/
31 {
32  ARGV_t aTags = NULL;
33  char * s = rpmExpand("%{?_arbitrary_tags}", NULL);
34 
35  if (s && *s)
36  (void) argvSplit(&aTags, s, ":");
37  else
38  aTags = (ARGV_t) xcalloc(1, sizeof(*aTags));
39  if (aTags && aTags[0] && aTags[1])
40  (void) argvSort(aTags, (int (*) (const char **, const char **))cmp);
41  s = _free(s);
42 
43  if (argvp)
44  *argvp = aTags;
45  else
46  aTags = argvFree(aTags);
47 /*@-nullstate@*/ /* *argvp may be NULL */
48  return 0;
49 /*@=nullstate@*/
50 }
51 
58 static int tagCmpName(const void * avp, const void * bvp)
59  /*@*/
60 {
63  return strcmp(a->name, b->name);
64 }
65 
72 static int tagCmpValue(const void * avp, const void * bvp)
73  /*@*/
74 {
77  int ret = ((int)a->val - (int)b->val);
78  /* Make sure that sort is stable, longest name first. */
79  if (ret == 0)
80  ret = ((int)strlen(b->name) - (int)strlen(a->name));
81  return ret;
82 }
83 
91 static int tagLoadIndex(headerTagTableEntry ** ipp, size_t * np,
92  int (*cmp) (const void * avp, const void * bvp))
93  /*@modifies *ipp, *np @*/
94 {
95  headerTagTableEntry tte, *ip;
96  size_t n = 0;
97 
98  ip = (headerTagTableEntry *) xcalloc(rpmTagTableSize, sizeof(*ip));
99  n = 0;
100 /*@-dependenttrans@*/ /*@-observertrans@*/ /*@-castexpose@*/ /*@-mods@*/ /*@-modobserver@*/
101  for (tte = rpmTagTable; tte->name != NULL; tte++) {
102  ip[n] = tte;
103  n++;
104  }
105 assert(n == (size_t)rpmTagTableSize);
106 /*@=dependenttrans@*/ /*@=observertrans@*/ /*@=castexpose@*/ /*@=mods@*/ /*@=modobserver@*/
107 
108  if (n > 1)
109  qsort(ip, n, sizeof(*ip), cmp);
110  *ipp = ip;
111  *np = n;
112  return 0;
113 }
114 
115 static char * _tagCanonicalize(const char * s)
116  /*@*/
117 {
118  const char * se;
119  size_t nb = 0;
120  char * te;
121  char * t;
122  int c;
123 
124  if (!strncasecmp(s, "RPMTAG_", sizeof("RPMTAG_")-1))
125  s += sizeof("RPMTAG_") - 1;
126  se = s;
127  while ((c = (int)*se++) && xisalnum(c))
128  nb++;
129 
130  te = t = (char *) xmalloc(nb+1);
131  if (*s != '\0' && nb > 0) {
132  *te++ = (char) xtoupper((int)*s++);
133  nb--;
134  }
135  while (nb--)
136  *te++ = (char) xtolower((int)*s++);
137  *te = '\0';
138 
139  return t;
140 }
141 
142 static rpmTag _tagGenerate(const char *s)
143  /*@*/
144 {
146  const char * digest = NULL;
147  size_t digestlen = 0;
148  size_t nb = strlen(s);
149  rpmTag tag = (rpmTag)0;
150  int xx;
151 
152  xx = rpmDigestUpdate(ctx, s, nb);
153  xx = rpmDigestFinal(ctx, &digest, &digestlen, 0);
154  if (digest && digestlen > 4) {
155  memcpy(&tag, digest + (digestlen - 4), 4);
156  tag = (rpmTag) (tag & 0x3fffffff);
157  tag = (rpmTag) (tag | 0x40000000);
158  }
159  digest = _free(digest);
160  return tag;
161 }
162 
163 /* forward refs */
164 static const char * _tagName(rpmTag tag)
165  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
166  /*@modifies rpmGlobalMacroContext, internalState @*/;
167 static unsigned int _tagType(rpmTag tag)
168  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
169  /*@modifies rpmGlobalMacroContext, internalState @*/;
170 static rpmTag _tagValue(const char * tagstr)
171  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
172  /*@modifies rpmGlobalMacroContext, internalState @*/;
173 
174 /*@unchecked@*/
175 static struct headerTagIndices_s _rpmTags = {
176  tagLoadIndex,
177  NULL, 0, tagCmpName, _tagValue,
178  NULL, 0, tagCmpValue, _tagName, (rpmTag (*)(rpmTag)) _tagType,
179  256, NULL, NULL, _tagCanonicalize, _tagGenerate
180 };
181 
182 /*@-compmempass@*/
183 /*@unchecked@*/
185 /*@=compmempass@*/
186 
187 /*@-mods@*/
188 static const char * _tagName(rpmTag tag)
189 {
190  char * nameBuf;
191  size_t nameBufLen = 0;
193  size_t i, l, u;
194  int comparison;
195  int xx;
196  char *s;
197 
198  if (_rpmTags.aTags == NULL)
199  xx = tagLoadATags(&_rpmTags.aTags, NULL);
200  if (_rpmTags.byValue == NULL)
201  xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize,
202  tagCmpValue);
203  if (_rpmTags.nameBufLen == 0)
204  _rpmTags.nameBufLen = 256;
205  if (_rpmTags.nameBuf == NULL)
206  _rpmTags.nameBuf = (char *) xcalloc(1, _rpmTags.nameBufLen);
207  nameBuf = _rpmTags.nameBuf;
208  nameBuf[0] = nameBuf[1] = '\0';
209  nameBufLen = _rpmTags.nameBufLen;
210 
211  switch (tag) {
212  case RPMDBI_PACKAGES:
213  strncpy(nameBuf, "Packages", nameBufLen);
214  break;
215  case RPMDBI_DEPCACHE:
216  strncpy(nameBuf, "Depcache", nameBufLen);
217  break;
218  case RPMDBI_ADDED:
219  strncpy(nameBuf, "Added", nameBufLen);
220  break;
221  case RPMDBI_REMOVED:
222  strncpy(nameBuf, "Removed", nameBufLen);
223  break;
224  case RPMDBI_AVAILABLE:
225  strncpy(nameBuf, "Available", nameBufLen);
226  break;
227  case RPMDBI_HDLIST:
228  strncpy(nameBuf, "Hdlist", nameBufLen);
229  break;
230  case RPMDBI_ARGLIST:
231  strncpy(nameBuf, "Arglist", nameBufLen);
232  break;
233  case RPMDBI_FTSWALK:
234  strncpy(nameBuf, "Ftswalk", nameBufLen);
235  break;
236  case RPMDBI_SEQNO:
237  strncpy(nameBuf, "Seqno", nameBufLen);
238  break;
239  case RPMDBI_BTREE:
240  strncpy(nameBuf, "Btree", nameBufLen);
241  break;
242  case RPMDBI_HASH:
243  strncpy(nameBuf, "Hash", nameBufLen);
244  break;
245  case RPMDBI_QUEUE:
246  strncpy(nameBuf, "Queue", nameBufLen);
247  break;
248  case RPMDBI_RECNO:
249  strncpy(nameBuf, "Recno", nameBufLen);
250  break;
251  case RPMDBI_HEAP:
252  strncpy(nameBuf, "Heap", nameBufLen);
253  break;
254 
255  /* XXX make sure rpmdb indices are identically named. */
256  case RPMTAG_CONFLICTS:
257  strncpy(nameBuf, "Conflictname", nameBufLen);
258  break;
259  case RPMTAG_HDRID:
260  strncpy(nameBuf, "Sha1header", nameBufLen);
261  break;
262 
263  /* XXX make sure that h.['filenames'] in python "works". */
264  case 0x54aafb71:
265  strncpy(nameBuf, "Filenames", nameBufLen);
266  break;
267 
268  default:
269  if (_rpmTags.byValue == NULL)
270  break;
271  l = 0;
272  u = _rpmTags.byValueSize;
273  while (l < u) {
274  i = (l + u) / 2;
275  t = _rpmTags.byValue[i];
276 
277  comparison = ((int)tag - (int)t->val);
278 
279  if (comparison < 0)
280  u = i;
281  else if (comparison > 0)
282  l = i + 1;
283  else {
284  /* Make sure that the bsearch retrieve is stable. */
285  while (i > 0 && tag == _rpmTags.byValue[i-1]->val) {
286  i--;
287  t = _rpmTags.byValue[i];
288  }
289  s = (*_rpmTags.tagCanonicalize) (t->name);
290  strncpy(nameBuf, s, nameBufLen);
291  s = _free(s);
292  /*@loopbreak@*/ break;
293  }
294  }
295  break;
296  }
297  if (nameBuf[0] == '\0')
298  xx = snprintf(nameBuf, nameBufLen, "Tag_0x%08x", (unsigned) tag);
299  nameBuf[nameBufLen-1] = '\0';
300 /*@-globstate@*/ /* _rpmTags.nameBuf reachable. */
301  return nameBuf;
302 /*@=globstate@*/
303 }
304 /*@=mods@*/
305 
306 static unsigned int _tagType(rpmTag tag)
307 {
309  size_t i, l, u;
310  int comparison;
311  int xx;
312 
313  if (_rpmTags.aTags == NULL)
314  xx = tagLoadATags(&_rpmTags.aTags, NULL);
315  if (_rpmTags.byValue == NULL)
316  xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
317 
318  switch (tag) {
319  case RPMDBI_PACKAGES:
320  case RPMDBI_DEPCACHE:
321  case RPMDBI_ADDED:
322  case RPMDBI_REMOVED:
323  case RPMDBI_AVAILABLE:
324  case RPMDBI_HDLIST:
325  case RPMDBI_ARGLIST:
326  case RPMDBI_FTSWALK:
327  case RPMDBI_SEQNO:
328  case RPMDBI_BTREE:
329  case RPMDBI_HASH:
330  case RPMDBI_QUEUE:
331  case RPMDBI_RECNO:
332  case RPMDBI_HEAP:
333  break;
334  default:
335  if (_rpmTags.byValue == NULL)
336  break;
337  l = 0;
338  u = _rpmTags.byValueSize;
339  while (l < u) {
340  i = (l + u) / 2;
341  t = _rpmTags.byValue[i];
342 
343  comparison = ((int)tag - (int)t->val);
344 
345  if (comparison < 0)
346  u = i;
347  else if (comparison > 0)
348  l = i + 1;
349  else {
350  /* Make sure that the bsearch retrieve is stable. */
351  while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) {
352  i--;
353  t = _rpmTags.byValue[i];
354  }
355  return t->type;
356  }
357  }
358  break;
359  }
360  return 0;
361 }
362 
363 static rpmTag _tagValue(const char * tagstr)
364 {
366  int comparison;
367  size_t i, l, u;
368  const char * s;
369  rpmTag tag;
370  int xx;
371 
372  /* XXX headerSprintf looks up by "RPMTAG_FOO", not "FOO". */
373  if (!strncasecmp(tagstr, "RPMTAG_", sizeof("RPMTAG_")-1))
374  tagstr += sizeof("RPMTAG_") - 1;
375 
376  if (!xstrcasecmp(tagstr, "Packages"))
377  return RPMDBI_PACKAGES;
378  if (!xstrcasecmp(tagstr, "Depcache"))
379  return RPMDBI_DEPCACHE;
380  if (!xstrcasecmp(tagstr, "Added"))
381  return RPMDBI_ADDED;
382  if (!xstrcasecmp(tagstr, "Removed"))
383  return RPMDBI_REMOVED;
384  if (!xstrcasecmp(tagstr, "Available"))
385  return RPMDBI_AVAILABLE;
386  if (!xstrcasecmp(tagstr, "Hdlist"))
387  return RPMDBI_HDLIST;
388  if (!xstrcasecmp(tagstr, "Arglist"))
389  return RPMDBI_ARGLIST;
390  if (!xstrcasecmp(tagstr, "Ftswalk"))
391  return RPMDBI_FTSWALK;
392  if (!xstrcasecmp(tagstr, "Seqno"))
393  return RPMDBI_SEQNO;
394  if (!xstrcasecmp(tagstr, "Btree"))
395  return RPMDBI_BTREE;
396  if (!xstrcasecmp(tagstr, "Hash"))
397  return RPMDBI_HASH;
398  if (!xstrcasecmp(tagstr, "Queue"))
399  return RPMDBI_QUEUE;
400  if (!xstrcasecmp(tagstr, "Recno"))
401  return RPMDBI_RECNO;
402  if (!xstrcasecmp(tagstr, "Heap"))
403  return RPMDBI_HEAP;
404 
405  if (_rpmTags.aTags == NULL)
406  xx = tagLoadATags(&_rpmTags.aTags, NULL);
407  if (_rpmTags.byName == NULL)
408  xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
409  if (_rpmTags.byName == NULL)
410  goto exit;
411 
412  l = 0;
413  u = _rpmTags.byNameSize;
414  while (l < u) {
415  i = (l + u) / 2;
416  t = _rpmTags.byName[i];
417 
418  comparison = xstrcasecmp(tagstr, t->name + (sizeof("RPMTAG_")-1));
419 
420  if (comparison < 0)
421  u = i;
422  else if (comparison > 0)
423  l = i + 1;
424  else
425  return t->val;
426  }
427 
428 exit:
429  /* Generate an arbitrary tag string. */
430  s = _tagCanonicalize(tagstr);
431  tag = _tagGenerate(s);
432  s = _free(s);
433  return tag;
434 }
435 
436 const char * tagName(rpmTag tag)
437 {
438  return ((*rpmTags->tagName)(tag));
439 }
440 
441 unsigned int tagType(rpmTag tag)
442 {
443  return ((*rpmTags->tagType)(tag));
444 }
445 
446 rpmTag tagValue(const char * tagstr)
447 {
448  return ((*rpmTags->tagValue)(tagstr));
449 }
450 
451 char * tagCanonicalize(const char * s)
452 {
453  return ((*rpmTags->tagCanonicalize)(s));
454 }
455 
456 rpmTag tagGenerate(const char * s)
457 {
458  return ((*rpmTags->tagGenerate)(s));
459 }
460 
462 {
463  if (_rpmTags == NULL)
464  _rpmTags = rpmTags;
465  if (_rpmTags) {
466  _rpmTags->nameBuf = _free(_rpmTags->nameBuf);
467  _rpmTags->byName = _free(_rpmTags->byName);
468  _rpmTags->byValue = _free(_rpmTags->byValue);
469  _rpmTags->aTags = argvFree(_rpmTags->aTags);
470  }
471 }
472 
473 tagStore_t tagStoreFree(tagStore_t dbiTags, size_t dbiNTags)
474 {
475  if (dbiTags != NULL) {
476  size_t i;
477  for (i = 0; i < dbiNTags; i++) {
478  dbiTags[i].str = _free(dbiTags[i].str);
479  dbiTags[i].iob = rpmiobFree(dbiTags[i].iob);
480  }
481  dbiTags = _free(dbiTags);
482  }
483  return NULL;
484 }
485 
486 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
487 
491 void tagTypeValidate(HE_t he);
492 void tagTypeValidate(HE_t he)
493 {
494  HE_s he_s = *he;
495 
496  /* XXX Re-map RPM_I18NSTRING_TYPE -> RPM_STRING_TYPE */
497  if (he_s.t == RPM_I18NSTRING_TYPE)
498  he_s.t = RPM_STRING_TYPE;
499 
500  /* XXX Arbitrary tags are always strings. */
501  if ((he_s.tag & 0x40000000)
502  && (he_s.t == RPM_STRING_TYPE || he_s.t == RPM_STRING_ARRAY_TYPE))
503  return;
504 
505  /* XXX Make 0x3fffffff disappear for now. Signature? */
506  if (he_s.tag == 0x3fffffff && he_s.t == RPM_BIN_TYPE)
507  return;
508 
509 /* XXX hack around known borkage for now. */
510 if (!(he_s.tag == 62))
511 if (!(he_s.tag == 261 || he_s.tag == 269))
512 if (!(he_s.tag == 1000 || he_s.tag == 1004 || he_s.tag == 1007))
513 if (!(he_s.tag == 1029))
514 if (!(he_s.tag == 1086 || he_s.tag == 1087))
515 if (he_s.t != (tagType(he_s.tag) & 0xffff))
516 fprintf(stderr, "==> warning: tag %u type(0x%x) != implicit type(0x%x)\n", (unsigned) he_s.tag, he_s.t, tagType(he_s.tag));
517 }
518 #endif
const bson * b
Definition: bson.h:280
rpmTagType t
Definition: rpmtag.h:504
rpmTag tag
Definition: rpmtag.h:503
headerTagTableEntry rpmTagTable
Automatically generated table of tag name/value pairs.
Definition: tagtbl.c:239
char * tagCanonicalize(const char *s)
Canonicalize a rpmTag string.
Definition: tagname.c:451
rpmTag tagValue(const char *tagstr)
Return tag value from name.
Definition: tagname.c:446
rpmTag tagGenerate(const char *s)
Generate a tag from arbitrary string.
Definition: tagname.c:456
static char * _tagCanonicalize(const char *s)
Definition: tagname.c:115
unsigned int tagType(rpmTag tag)
Return tag data type from value.
Definition: tagname.c:441
static int xtoupper(int c)
Definition: rpmiotypes.h:577
static int tagCmpName(const void *avp, const void *bvp)
Compare tag table entries by name.
Definition: tagname.c:58
static int xisalnum(int c)
Definition: rpmiotypes.h:549
void tagClean(headerTagIndices _rpmTags)
Free memory in header tag indices.
Definition: tagname.c:461
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest context.
Definition: digest.c:247
#define RPMDBI_QUEUE
Definition: rpmtag.h:491
#define RPMDBI_REMOVED
Definition: rpmtag.h:483
static int tagLoadATags(ARGV_t *argvp, int(*cmp)(const void *avp, const void *bvp))
Load/sort arbitrary tags.
Definition: tagname.c:27
#define RPMDBI_RECNO
Definition: rpmtag.h:492
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
static int xtolower(int c)
Definition: rpmiotypes.h:574
const char * str
Definition: bson.h:593
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
#define RPMDBI_SEQNO
Definition: rpmtag.h:488
static int tagLoadIndex(headerTagTableEntry **ipp, size_t *np, int(*cmp)(const void *avp, const void *bvp))
Load/sort a tag index.
Definition: tagname.c:91
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:986
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
#define RPMDBI_HEAP
Definition: rpmtag.h:493
#define RPMDBI_FTSWALK
Definition: rpmtag.h:487
Digest private data.
Definition: digest.c:130
struct tagStore_s * tagStore_t
Definition: rpmtag.h:521
static struct headerTagIndices_s _rpmTags
Definition: tagname.c:175
static rpmTag _tagGenerate(const char *s)
Definition: tagname.c:142
headerTagIndices rpmTags
Definition: tagname.c:184
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
int xstrcasecmp(const char *s1, const char *s2)
Locale insensitive strcasecmp(3).
Definition: strcasecmp.c:9
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3252
#define RPMDBI_DEPCACHE
Definition: rpmtag.h:480
#define RPMDBI_HDLIST
Definition: rpmtag.h:485
static int tagCmpValue(const void *avp, const void *bvp)
Compare tag table entries by value.
Definition: tagname.c:72
#define RPMTAG_CONFLICTS
Definition: rpmtag.h:242
#define RPMDBI_ARGLIST
Definition: rpmtag.h:486
Definition: rpmtag.h:502
const char const int i
Definition: bson.h:778
#define RPMDBI_BTREE
Definition: rpmtag.h:489
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
static int cmp(const void *arg1, const void *arg2)
Definition: set.c:1363
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
int rpmTagTableSize
Number of entries in rpmTagTable.
Definition: tagtbl.c:242
const struct headerTagTableEntry_s * headerTagTableEntry
Definition: rpmtag.h:525
#define RPMTAG_HDRID
Definition: rpmtag.h:170
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
Definition: argv.c:233
tagStore_t tagStoreFree(tagStore_t dbiTags, size_t dbiNTags)
Destroy tagStore array.
Definition: tagname.c:473
#define RPMDBI_AVAILABLE
Definition: rpmtag.h:484
int argvSort(ARGV_t argv, int(*compar)(ARGstr_t *, ARGstr_t *))
Sort an argv array.
Definition: argv.c:137
int rpmDigestFinal(DIGEST_CTX ctx, void *datap, size_t *lenp, int asAscii)
Return digest and destroy context.
Definition: digest.c:1000
struct headerTagIndices_s * headerTagIndices
Definition: rpmtag.h:130
static const char * _tagName(rpmTag tag)
Definition: tagname.c:188
#define xmalloc
Definition: system.h:32
ARGstr_t * ARGV_t
Definition: argv.h:12
enum rpmTag_e rpmTag
Definition: rpmtag.h:470
static unsigned int _tagType(rpmTag tag)
Definition: tagname.c:306
static rpmTag _tagValue(const char *tagstr)
Definition: tagname.c:363
#define RPMDBI_HASH
Definition: rpmtag.h:490
#define RPMDBI_PACKAGES
Pseudo-tags used by the rpmdb and rpmgi iterator API's.
Definition: rpmtag.h:479
#define RPMDBI_ADDED
Definition: rpmtag.h:482