rpm  5.4.10
header.c
Go to the documentation of this file.
1 
5 /* RPM - Copyright (C) 1995-2002 Red Hat Software */
6 
7 /* Data written to file descriptors is in network byte order. */
8 /* Data read from file descriptors is expected to be in */
9 /* network byte order and is converted on the fly to host order. */
10 
11 #include "system.h"
12 
13 #include <rpmiotypes.h>
14 #include <rpmio.h> /* XXX for rpmioPool et al */
15 #define _RPMTAG_INTERNAL
16 #include <header_internal.h>
17 
18 #include "debug.h"
19 
20 /*@access Header @*/
21 /*@access HeaderIterator @*/
22 /*@access headerSprintfExtension @*/
23 /*@access headerTagTableEntry @*/
24 
25 /*@access entryInfo @*/
26 /*@access indexEntry @*/
27 
28 #ifdef __cplusplus
29 GENfree(rpmuint32_t *)
30 GENfree(indexEntry)
31 GENfree(HeaderIterator)
32 #endif /* __cplusplus */
33 
34 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
35 extern void tagTypeValidate(HE_t he)
36  /*@*/;
37 #endif
38 
39 /*@unchecked@*/
40 int _hdr_debug = 0;
41 
44 /*@-type@*/
45 /*@observer@*/ /*@unchecked@*/
46 static unsigned char header_magic[8] = {
47  0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
48 };
49 /*@=type@*/
50 
54 /*@observer@*/ /*@unchecked@*/
55 static int typeSizes[16] = {
56  0,
57  1,
58  1,
59  2,
60  4,
61  8,
62  -1,
63  1,
64  -1,
65  -1,
66  0,
67  0,
68  0,
69  0,
70  0,
71  0
72 };
73 
77 /*@unchecked@*/
78 static size_t headerMaxbytes = (1024*1024*1024);
79 
83 /*@unchecked@*/
84 int _hdr_stats = 0;
85 
86 /*@-compmempass@*/
87 /*@unchecked@*/
88 static struct rpmop_s hdr_loadops;
89 /*@unchecked@*/ /*@relnull@*/
91 /*@unchecked@*/
92 static struct rpmop_s hdr_getops;
93 /*@unchecked@*/ /*@relnull@*/
95 /*@=compmempass@*/
96 
97 void * headerGetStats(Header h, int opx)
98 {
99  rpmop op = NULL;
100  if (_hdr_stats)
101  switch (opx) {
102  case 18: op = &h->h_loadops; break; /* RPMTS_OP_HDRLOAD */
103  case 19: op = &h->h_getops; break; /* RPMTS_OP_HDRGET */
104  }
105  return op;
106 }
107 
108 /*@-mustmod@*/
109 static void headerScrub(void * _h) /* XXX headerFini already in use */
110  /*@modifies *_h @*/
111 {
112  Header h = (Header) _h;
113 
114  if (h->index != NULL) {
116  indexEntry entry = h->index;
117  size_t i;
118  for (i = 0; i < h->indexUsed; i++, entry++) {
119  if ((h->flags & mask) && ENTRY_IS_REGION(entry)) {
120  if (entry->length > 0) {
121  rpmuint32_t * ei = (rpmuint32_t *) entry->data;
122  if ((ei - 2) == h->blob) {
123  if (h->flags & HEADERFLAG_MAPPED) {
124  if (munmap(h->blob, h->bloblen) != 0)
125  fprintf(stderr,
126  "==> munmap(%p[%u]) error(%d): %s\n",
127  h->blob, (unsigned)h->bloblen,
128  errno, strerror(errno));
129  h->blob = NULL;
130  } else
131  h->blob = _free(h->blob);
132  h->bloblen = 0;
133  }
134  entry->data = NULL;
135  }
136  } else if (!ENTRY_IN_REGION(entry)) {
137  entry->data = _free(entry->data);
138  }
139  entry->data = NULL;
140  entry->length = 0;
141  }
142  h->index = _free(h->index);
143  }
144  h->origin = _free(h->origin);
145  h->baseurl = _free(h->baseurl);
146  h->digest = _free(h->digest);
147  h->parent = _free(h->parent);
148 
149 /*@-nullstate@*/
150  if (_hdr_stats) {
151  if (_hdr_loadops) /* RPMTS_OP_HDRLOAD */
152  (void) rpmswAdd(_hdr_loadops, (rpmop) headerGetStats(h, 18));
153  if (_hdr_getops) /* RPMTS_OP_HDRGET */
154  (void) rpmswAdd(_hdr_getops, (rpmop) headerGetStats(h, 19));
155  }
156 /*@=nullstate@*/
157 }
158 /*@=mustmod@*/
159 
160 /*@unchecked@*/ /*@only@*/ /*@null@*/
162 
163 static Header headerGetPool(/*@null@*/ rpmioPool pool)
164  /*@globals _headerPool, fileSystem @*/
165  /*@modifies pool, _headerPool, fileSystem @*/
166 {
167  Header h;
168 
169  if (_headerPool == NULL) {
170 ANNOTATE_BENIGN_RACE(&_headerPool, "");
171  _headerPool = rpmioNewPool("h", sizeof(*h), -1, _hdr_debug,
172  NULL, NULL, headerScrub);
173  pool = _headerPool;
174  }
175  h = (Header) rpmioGetPool(pool, sizeof(*h));
176  memset(((char *)h)+sizeof(h->_item), 0, sizeof(*h)-sizeof(h->_item));
177  return h;
178 }
179 
181 {
182  Header h = headerGetPool(_headerPool);
183 
184  (void) memcpy(h->magic, header_magic, sizeof(h->magic));
185  h->blob = NULL;
186  h->bloblen = 0;
187  h->origin = NULL;
188  h->baseurl = NULL;
189  h->digest = NULL;
190  h->parent = NULL;
191  h->rpmdb = NULL;
192  memset(&h->sb, 0, sizeof(h->sb));
193  h->instance = 0;
194  h->startoff = 0;
195  h->endoff = 0;
196  memset(&h->h_loadops, 0, sizeof(h->h_loadops));
197  memset(&h->h_getops, 0, sizeof(h->h_getops));
199  h->indexUsed = 0;
201 
202  h->index = (indexEntry) (h->indexAlloced
203  ? xcalloc(h->indexAlloced, sizeof(*h->index))
204  : NULL);
205 
206 /*@-globstate -nullret -observertrans @*/
207  return headerLink(h);
208 /*@=globstate =nullret =observertrans @*/
209 }
210 
213 static int indexCmp(const void * avp, const void * bvp)
214  /*@*/
215 {
216  /*@-castexpose@*/
217  indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp;
218  /*@=castexpose@*/
219  return ((int)ap->info.tag - (int)bp->info.tag);
220 }
221 
226 static
228  /*@modifies h @*/
229 {
230  if (!(h->flags & HEADERFLAG_SORTED)) {
231  qsort(h->index, h->indexUsed, sizeof(*h->index), indexCmp);
232  h->flags |= HEADERFLAG_SORTED;
233  }
234 }
235 
238 static int offsetCmp(const void * avp, const void * bvp) /*@*/
239 {
240  /*@-castexpose@*/
241  indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp;
242  /*@=castexpose@*/
243  int rc = ((int)ap->info.offset - (int)bp->info.offset);
244 
245  if (rc == 0) {
246  /* Within a region, entries sort by address. Added drips sort by tag. */
247  if (ap->info.offset < 0)
248  rc = (((char *)ap->data) - ((char *)bp->data));
249  else
250  rc = ((int)ap->info.tag - (int)bp->info.tag);
251  }
252  return rc;
253 }
254 
259 static
261  /*@modifies h @*/
262 {
263  qsort(h->index, h->indexUsed, sizeof(*h->index), offsetCmp);
264 }
265 
267 {
268  indexEntry entry;
269  size_t size = 0;
270  size_t pad = 0;
271  size_t i;
272 
273  if (h == NULL)
274  return size;
275 
276  headerSort(h);
277 
278  size += sizeof(header_magic); /* XXX HEADER_MAGIC_YES */
279 
280  /*@-sizeoftype@*/
281  size += 2 * sizeof(rpmuint32_t); /* count of index entries */
282  /*@=sizeoftype@*/
283 
284  for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
285  size_t diff;
286  rpmTagType type;
287 
288  /* Regions go in as is ... */
289  if (ENTRY_IS_REGION(entry)) {
290  size += entry->length;
291  /* XXX Legacy regions do not include the region tag and data. */
292  /*@-sizeoftype@*/
293  if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
294  size += sizeof(struct entryInfo_s) + entry->info.count;
295  /*@=sizeoftype@*/
296  continue;
297  }
298 
299  /* ... and region elements are skipped. */
300  if (entry->info.offset < 0)
301  continue;
302 
303  /* Alignment */
304  type = entry->info.type;
305  if (typeSizes[type] > 1) {
306  diff = typeSizes[type] - (size % typeSizes[type]);
307  if ((int)diff != typeSizes[type]) {
308  size += diff;
309  pad += diff;
310  }
311  }
312 
313  /*@-sizeoftype@*/
314  size += sizeof(struct entryInfo_s) + entry->length;
315  /*@=sizeoftype@*/
316  }
317 
318  return size;
319 }
320 
331  int onDisk, /*@null@*/ rpmTagData * pend)
332  /*@*/
333 {
334  const unsigned char * s = (unsigned char *) (*p).ui8p;
335  const unsigned char * se = (unsigned char *) (pend ? (*pend).ui8p : NULL);
336  size_t length = 0;
337 
338  switch (type) {
339 #if !defined(SUPPORT_I18NSTRING_TYPE)
340  case RPM_I18NSTRING_TYPE:
341 assert(0);
342 #endif
343  case RPM_STRING_TYPE:
344  if (count != 1)
345  return 0;
346  while (*s++ != '\0') {
347  if (se && s > se)
348  return 0;
349  length++;
350  }
351  length++; /* count nul terminator too. */
352  break;
353  /* These are like RPM_STRING_TYPE, except they're *always* an array */
354  /* Compute sum of length of all strings, including nul terminators */
355 #if defined(SUPPORT_I18NSTRING_TYPE)
356  case RPM_I18NSTRING_TYPE:
357 #endif
359  if (onDisk) {
360  while (count--) {
361  length++; /* count nul terminator too */
362  while (*s++ != '\0') {
363  if (se && s > se)
364  return 0;
365  length++;
366  }
367  }
368  } else {
369  const char ** av = (*p).argv;
370  while (count--) {
371  /* add one for null termination */
372  length += strlen(*av++) + 1;
373  }
374  }
375  break;
376  default:
377  if (typeSizes[type] == -1)
378  return 0;
379  length = typeSizes[(type & 0xf)] * count;
380  if ((se && (s + length) > se))
381  return 0;
382  break;
383  }
384 
385  return length;
386 }
387 
392 static unsigned char * tagSwab(/*@out@*/ /*@returned@*/ unsigned char * t,
393  const HE_t he, size_t nb)
394  /*@modifies *t @*/
395 {
396  rpmuint32_t i;
397 
398  switch (he->t) {
399  case RPM_UINT64_TYPE:
400  { rpmuint32_t * tt = (rpmuint32_t *)t;
401 assert(nb == (he->c * sizeof(rpmuint64_t)));
402  for (i = 0; i < he->c; i++) {
403  rpmuint32_t j = 2 * i;
404  rpmuint32_t b = (rpmuint32_t) htonl(he->p.ui32p[j]);
405  tt[j ] = (rpmuint32_t) htonl(he->p.ui32p[j+1]);
406  tt[j+1] = b;
407  }
408  } break;
409  case RPM_UINT32_TYPE:
410  { rpmuint32_t * tt = (rpmuint32_t *)t;
411 assert(nb == (he->c * sizeof(*tt)));
412  for (i = 0; i < he->c; i++)
413  tt[i] = (rpmuint32_t) htonl(he->p.ui32p[i]);
414  } break;
415  case RPM_UINT16_TYPE:
416  { rpmuint16_t * tt = (rpmuint16_t *)t;
417 assert(nb == (he->c * sizeof(*tt)));
418  for (i = 0; i < he->c; i++)
419  tt[i] = (rpmuint16_t) htons(he->p.ui16p[i]);
420  } break;
421  default:
422 assert(he->p.ptr != NULL);
423  if ((void *)t != he->p.ptr && nb)
424  memcpy(t, he->p.ptr, nb);
425  t += nb;
426  break;
427  }
428 /*@-compdef@*/
429  return t;
430 /*@=compdef@*/
431 }
432 
438 static int rpmheRealloc(HE_t he)
439  /*@modifies he @*/
440 {
441  size_t nb = 0;
442  int rc = 1; /* assume success */
443 
444  switch (he->t) {
445  default:
446 assert(0); /* XXX stop unimplemented oversights. */
447  break;
448  case RPM_BIN_TYPE:
449  he->freeData = 1; /* XXX RPM_BIN_TYPE is malloc'd */
450  /*@fallthrough@*/
451  case 1:
452  case RPM_UINT8_TYPE:
453  nb = he->c * sizeof(*he->p.ui8p);
454  break;
455  case RPM_UINT16_TYPE:
456  nb = he->c * sizeof(*he->p.ui16p);
457  break;
458  case RPM_UINT32_TYPE:
459  nb = he->c * sizeof(*he->p.ui32p);
460  break;
461  case RPM_UINT64_TYPE:
462  nb = he->c * sizeof(*he->p.ui64p);
463  break;
464 #if !defined(SUPPORT_I18NSTRING_TYPE)
465  case RPM_I18NSTRING_TYPE:
466 assert(0);
467 #endif
468  case RPM_STRING_TYPE:
469  if (he->p.str)
470  nb = strlen(he->p.str) + 1;
471  else
472  rc = 0;
473  break;
474 #if defined(SUPPORT_I18NSTRING_TYPE)
475  case RPM_I18NSTRING_TYPE:
476 #endif
478  break;
479  }
480 
481  /* Allocate all returned storage (if not already). */
482  if (he->p.ptr && nb && !he->freeData) {
483  void * ptr = (void *) DRD_xmalloc(nb);
484  if (tagSwab((unsigned char *)ptr, he, nb) != NULL)
485  he->p.ptr = ptr;
486  else {
487 /*@-dependenttrans@*/
488  ptr = _free(ptr);
489 /*@=dependenttrans@*/
490  rc = 0;
491  }
492  }
493 
494  if (rc)
495  he->freeData = 1;
496 
497  return rc;
498 }
499 
526 /*@-globs@*/ /* XXX rpm_typeAlign usage */
527 static rpmuint32_t regionSwab(/*@null@*/ indexEntry entry, rpmuint32_t il, rpmuint32_t dl,
528  entryInfo pe,
529  unsigned char * dataStart,
530  /*@null@*/ const unsigned char * dataEnd,
531  rpmint32_t regionid)
532  /*@modifies *entry @*/
533 {
534  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
535  rpmTagData p;
536  rpmTagData pend;
537  unsigned char * tprev = NULL;
538  unsigned char * t = NULL;
539  size_t tdel = 0;
540  size_t tl = dl;
541  struct indexEntry_s ieprev;
542 
543 assert(dataEnd != NULL);
544 assert(entry != NULL);
545 
546  memset(&ieprev, 0, sizeof(ieprev));
547  for (; il > 0; il--, pe++) {
548  struct indexEntry_s ie;
549  rpmTagType type;
550 
551  ie.info.tag = (rpmTag) ntohl(pe->tag);
552  ie.info.type = (rpmTagType) ntohl(pe->type);
553  ie.info.count = (rpmuint32_t) ntohl(pe->count);
554  ie.info.offset = (rpmint32_t) ntohl(pe->offset);
555 assert(ie.info.offset >= 0); /* XXX insurance */
556 
557  if (hdrchkType(ie.info.type))
558  return 0;
559  if (hdrchkData(ie.info.count))
560  return 0;
561  if (hdrchkData(ie.info.offset))
562  return 0;
563  if (hdrchkAlign(ie.info.type, ie.info.offset))
564  return 0;
565 
566  ie.data = t = dataStart + ie.info.offset;
567  if (dataEnd && t >= dataEnd)
568  return 0;
569 
570  p.ptr = ie.data;
571  pend.ui8p = (rpmuint8_t *) dataEnd;
572 
573  /* Compute the tag data store length using offsets. */
574  if (il > 1)
575  ie.length = ((rpmuint32_t)ntohl(pe[1].offset) - ie.info.offset);
576  else {
577  /* XXX (dataEnd - t) +/- REGION_TAG_COUNT forces dataLength() */
578  ie.length = dataLength(ie.info.type, &p, ie.info.count, 1, &pend);
579  }
580 
581  if (ie.length == 0 || hdrchkData(ie.length))
582  return 0;
583 
584  ie.rdlen = 0;
585 
586  if (entry) {
587  ie.info.offset = regionid;
588 /*@-kepttrans@*/ /* entry->data is kept */
589  *entry = ie; /* structure assignment */
590 /*@=kepttrans@*/
591  entry++;
592  }
593 
594  /* Alignment */
595  type = ie.info.type;
596  if (typeSizes[type] > 1) {
597  size_t diff = typeSizes[type] - (dl % typeSizes[type]);
598  if ((int)diff != typeSizes[type]) {
599  dl += diff;
600 #ifdef DYING
601  if (ieprev.info.type == RPM_I18NSTRING_TYPE)
602  ieprev.length += diff;
603 #endif
604  }
605  }
606  tdel = (tprev ? (t - tprev) : 0);
607 #ifdef DYING
608  if (ieprev.info.type == RPM_I18NSTRING_TYPE)
609  tdel = ieprev.length;
610 #endif
611 
612  if (ie.info.tag >= HEADER_I18NTABLE) {
613  tprev = t;
614  } else {
615  tprev = dataStart;
616  /* XXX HEADER_IMAGE tags don't include region sub-tag. */
617  /*@-sizeoftype@*/
618  if (ie.info.tag == HEADER_IMAGE)
619  tprev -= REGION_TAG_COUNT;
620  /*@=sizeoftype@*/
621  }
622 
623  t += ie.length;
624 
625  dl += ie.length;
626  if (dataEnd && (dataStart + dl) > dataEnd) return 0;
627  tl += tdel;
628  ieprev = ie; /* structure assignment */
629 
630  }
631  tdel = (tprev ? (t - tprev) : 0);
632  tl += tdel;
633 
634  /* XXX
635  * There are two hacks here:
636  * 1) tl is 16b (i.e. REGION_TAG_COUNT) short while doing headerReload().
637  * 2) the 8/98 rpm bug with inserting i18n tags needs to use tl, not dl.
638  */
639  /*@-sizeoftype@*/
640  if (tl+REGION_TAG_COUNT == dl)
641  tl += REGION_TAG_COUNT;
642  /*@=sizeoftype@*/
643 
644  return dl;
645 }
646 /*@=globs@*/
647 
648 void * headerUnload(Header h, size_t * lenp)
649 {
650  void * sw;
651  rpmuint32_t * ei = NULL;
652  entryInfo pe;
653  unsigned char * dataStart;
654  unsigned char * te;
655  unsigned pad;
656  size_t len = 0;
657  rpmuint32_t il = 0;
658  rpmuint32_t dl = 0;
659  indexEntry entry;
660  rpmTagType type;
661  size_t i;
662  size_t drlen;
663  size_t ndribbles;
664  size_t driplen;
665  size_t ndrips;
666  int legacy = 0;
667 
668  if ((sw = headerGetStats(h, 18)) != NULL) /* RPMTS_OP_HDRLOAD */
669  (void) rpmswEnter((rpmop)sw, 0);
670 
671  /* Sort entries by (offset,tag). */
672  headerUnsort(h);
673 
674  /* Compute (il,dl) for all tags, including those deleted in region. */
675  pad = 0;
676  drlen = ndribbles = driplen = ndrips = 0;
677  for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
678  if (ENTRY_IS_REGION(entry)) {
679  rpmuint32_t rdl;
680  rpmuint32_t ril;
681  rpmint32_t rid;
682 
683 assert(entry->info.offset <= 0); /* XXX insurance */
684  rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */
685  ril = (rpmuint32_t)(rdl/sizeof(*pe));
686  rid = (rpmuint32_t)entry->info.offset;
687 
688  il += ril;
689  dl += entry->rdlen + entry->info.count;
690  /* XXX Legacy regions do not include the region tag and data. */
691  if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
692  il += 1;
693 
694  /* Skip rest of entries in region, but account for dribbles. */
695  for (; i < h->indexUsed && entry->info.offset <= rid+1; i++, entry++) {
696  if (entry->info.offset <= rid)
697  /*@innercontinue@*/ continue;
698 
699  /* Alignment */
700  type = entry->info.type;
701  if (typeSizes[type] > 1) {
702  size_t diff = typeSizes[type] - (dl % typeSizes[type]);
703  if ((int)diff != typeSizes[type]) {
704  drlen += diff;
705  pad += diff;
706  dl += diff;
707  }
708  }
709 
710  ndribbles++;
711  il++;
712  drlen += entry->length;
713  dl += entry->length;
714  }
715  i--;
716  entry--;
717  continue;
718  }
719 
720  /* Ignore deleted drips. */
721  if (entry->data == NULL || entry->length == 0)
722  continue;
723 
724  /* Alignment */
725  type = entry->info.type;
726  if (typeSizes[type] > 1) {
727  size_t diff = typeSizes[type] - (dl % typeSizes[type]);
728  if ((int)diff != typeSizes[type]) {
729  driplen += diff;
730  pad += diff;
731  dl += diff;
732  } else
733  diff = 0;
734  }
735 
736  ndrips++;
737  il++;
738  driplen += entry->length;
739  dl += entry->length;
740  }
741 
742  /* Sanity checks on header intro. */
743  if (hdrchkTags(il) || hdrchkData(dl))
744  goto errxit;
745 
746  len = sizeof(il) + sizeof(dl) + (il * sizeof(*pe)) + dl;
747 
748  ei = (rpmuint32_t *) xmalloc(len);
749  ei[0] = (rpmuint32_t) htonl(il);
750  ei[1] = (rpmuint32_t) htonl(dl);
751 
752  pe = (entryInfo) &ei[2];
753  dataStart = te = (unsigned char *) (pe + il);
754 
755  pad = 0;
756  for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
757  const char * src;
758  unsigned char *t;
759  size_t rdlen;
760 
761  if (entry->data == NULL || entry->length == 0)
762  continue;
763 
764  t = te;
765  pe->tag = (rpmTag) htonl(entry->info.tag);
766  pe->type = (rpmTagType) htonl(entry->info.type);
767  pe->count = (rpmuint32_t) htonl(entry->info.count);
768 
769  if (ENTRY_IS_REGION(entry)) {
770  rpmuint32_t rdl;
771  rpmuint32_t ril;
772  rpmint32_t rid;
773 
774 assert(entry->info.offset <= 0); /* XXX insurance */
775 
776  rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */
777  ril = (rpmuint32_t)(rdl/sizeof(*pe) + ndribbles);
778  rid = (rpmuint32_t)entry->info.offset;
779 
780  src = (char *)entry->data;
781  rdlen = entry->rdlen;
782 
783  /* XXX Legacy regions do not include the region tag and data. */
784  if (i == 0 && (h->flags & HEADERFLAG_LEGACY)) {
785  rpmuint32_t stei[4];
786 
787  legacy = 1;
788  memcpy(pe+1, src, rdl);
789  memcpy(te, src + rdl, rdlen);
790  te += rdlen;
791 
792  pe->offset = (rpmint32_t) htonl(te - dataStart);
793  stei[0] = (rpmuint32_t) pe->tag;
794  stei[1] = (rpmuint32_t) pe->type;
795  stei[2] = (rpmuint32_t) htonl(-rdl-entry->info.count);
796  stei[3] = (rpmuint32_t) pe->count;
797  memcpy(te, stei, entry->info.count);
798  te += entry->info.count;
799  ril++;
800  rdlen += entry->info.count;
801 
802  } else {
803 
804  memcpy(pe+1, src + sizeof(*pe), ((ril-1) * sizeof(*pe)));
805  memcpy(te, src + (ril * sizeof(*pe)), rdlen+entry->info.count+drlen);
806  te += rdlen;
807  { /*@-castexpose@*/
808  entryInfo se = (entryInfo)src;
809  /*@=castexpose@*/
810  rpmint32_t off = (rpmint32_t) ntohl(se->offset);
811  pe->offset = (rpmint32_t)((off)
812  ? htonl(te - dataStart) : htonl(off));
813  }
814  te += entry->info.count + drlen;
815 
816  }
817 
818  /* Skip rest of entries in region. */
819  while (i < h->indexUsed && entry->info.offset <= rid+1) {
820  i++;
821  entry++;
822  }
823  i--;
824  entry--;
825  pe += ril;
826  continue;
827  }
828 
829  /* Ignore deleted drips. */
830  if (entry->data == NULL || entry->length == 0)
831  continue;
832 
833  /* Alignment */
834  type = entry->info.type;
835  if (typeSizes[type] > 1) {
836  size_t diff;
837  diff = typeSizes[type] - ((te - dataStart) % typeSizes[type]);
838  if ((int)diff != typeSizes[type]) {
839  memset(te, 0, diff);
840  te += diff;
841  pad += diff;
842  }
843  }
844 
845  /* Move tag data into header data store. */
846  pe->offset = (rpmint32_t) htonl(te - dataStart);
847  memcpy(te, entry->data, entry->length);
848  te += entry->length;
849  pe++;
850  }
851 
852  /* Insure that there are no memcpy underruns/overruns. */
853  if (((unsigned char *)pe) != dataStart)
854  goto errxit;
855  if ((((unsigned char *)ei)+len) != te)
856  goto errxit;
857 
858  if (lenp)
859  *lenp = len;
860 
861  h->flags &= ~HEADERFLAG_SORTED;
862  headerSort(h);
863 
864  if (sw != NULL) (void) rpmswExit((rpmop)sw, len);
865 
866  return (void *) ei;
867 
868 errxit:
869  if (sw != NULL) (void) rpmswExit((rpmop)sw, len);
870  /*@-usereleased@*/
871  ei = _free(ei);
872  /*@=usereleased@*/
873  return (void *) ei;
874 }
875 
883 static /*@null@*/
884 indexEntry findEntry(/*@null@*/ Header h, rpmTag tag, rpmTagType type)
885  /*@modifies h @*/
886 {
887  indexEntry entry, entry2, last;
888  struct indexEntry_s key;
889 
890  if (h == NULL) return NULL;
891  if (!(h->flags & HEADERFLAG_SORTED)) headerSort(h);
892 
893  key.info.tag = tag;
894 
895  entry2 = entry = (indexEntry)
896  bsearch(&key, h->index, h->indexUsed, sizeof(*h->index), indexCmp);
897  if (entry == NULL)
898  return NULL;
899 
900  if (type == 0)
901  return entry;
902 
903  /* look backwards */
904  while (entry->info.tag == tag && entry->info.type != type &&
905  entry > h->index) entry--;
906 
907  if (entry->info.tag == tag && entry->info.type == type)
908  return entry;
909 
910  last = h->index + h->indexUsed;
911  /*@-usereleased@*/ /* FIX: entry2 = entry. Code looks bogus as well. */
912  while (entry2->info.tag == tag && entry2->info.type != type &&
913  entry2 < last) entry2++;
914  /*@=usereleased@*/
915 
916  if (entry->info.tag == tag && entry->info.type == type)
917  return entry;
918 
919  return NULL;
920 }
921 
931 static
933  /*@modifies h @*/
934 {
935  indexEntry last = h->index + h->indexUsed;
936  indexEntry entry, first;
937  int ne;
938 
939  entry = findEntry(h, tag, (rpmTagType)0);
940  if (!entry) return 1;
941 
942  /* Make sure entry points to the first occurrence of this tag. */
943  while (entry > h->index && (entry - 1)->info.tag == tag)
944  entry--;
945 
946  /* Free data for tags being removed. */
947  for (first = entry; first < last; first++) {
948  void * data;
949  if (first->info.tag != tag)
950  break;
951  data = first->data;
952  first->data = NULL;
953  first->length = 0;
954  if (ENTRY_IN_REGION(first))
955  continue;
956  data = _free(data);
957  }
958 
959  ne = (first - entry);
960  if (ne > 0) {
961  h->indexUsed -= ne;
962  ne = last - first;
963  if (ne > 0)
964  memmove(entry, first, (ne * sizeof(*entry)));
965  }
966 
967  return 0;
968 }
969 
970 Header headerLoad(void * uh)
971 {
972  void * sw = NULL;
973  rpmuint32_t * ei = (rpmuint32_t *) uh;
974  rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]); /* index length */
975  rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]); /* data length */
976  /*@-sizeoftype@*/
977  size_t pvlen = sizeof(il) + sizeof(dl) +
978  (il * sizeof(struct entryInfo_s)) + dl;
979  /*@=sizeoftype@*/
980  void * pv = uh;
981  Header h = NULL;
982  entryInfo pe;
983  unsigned char * dataStart;
984  unsigned char * dataEnd;
985  indexEntry entry;
986  rpmuint32_t rdlen;
987  int i;
988 
989  /* Sanity checks on header intro. */
990  if (hdrchkTags(il) || hdrchkData(dl))
991  goto errxit;
992 
993  ei = (rpmuint32_t *) pv;
994  /*@-castexpose@*/
995  pe = (entryInfo) &ei[2];
996  /*@=castexpose@*/
997  dataStart = (unsigned char *) (pe + il);
998  dataEnd = dataStart + dl;
999 
1001  memset(&h->h_loadops, 0, sizeof(h->h_loadops));
1002  if ((sw = headerGetStats(h, 18)) != NULL) /* RPMTS_OP_HDRLOAD */
1003  (void) rpmswEnter((rpmop)sw, 0);
1004  { unsigned char * hmagic = header_magic;
1005  (void) memcpy(h->magic, hmagic, sizeof(h->magic));
1006  }
1007  /*@-assignexpose -kepttrans@*/
1008  h->blob = uh;
1009  h->bloblen = pvlen;
1010  /*@=assignexpose =kepttrans@*/
1011  h->origin = NULL;
1012  h->baseurl = NULL;
1013  h->digest = NULL;
1014  h->parent = NULL;
1015  h->rpmdb = NULL;
1016  memset(&h->sb, 0, sizeof(h->sb));
1017  h->instance = 0;
1018  h->startoff = 0;
1019  h->endoff = (rpmuint32_t) pvlen;
1020  memset(&h->h_getops, 0, sizeof(h->h_getops));
1021  h->indexAlloced = il + 1;
1022  h->indexUsed = il;
1023  h->index = (indexEntry) DRD_xcalloc(h->indexAlloced, sizeof(*h->index));
1024  h->flags = HEADERFLAG_SORTED;
1025  h = headerLink(h);
1026 assert(h != NULL);
1027 
1028  entry = h->index;
1029  i = 0;
1030  if (!(htonl(pe->tag) < HEADER_I18NTABLE)) {
1031  h->flags |= HEADERFLAG_LEGACY;
1032  entry->info.type = REGION_TAG_TYPE;
1033  entry->info.tag = (rpmTag) HEADER_IMAGE;
1034  /*@-sizeoftype@*/
1036  /*@=sizeoftype@*/
1037  entry->info.offset = ((unsigned char *)pe - dataStart); /* negative offset */
1038 
1039  /*@-assignexpose@*/
1040  entry->data = pe;
1041  /*@=assignexpose@*/
1042  entry->length = pvlen - sizeof(il) - sizeof(dl);
1043  rdlen = regionSwab(entry+1, il, 0, pe, dataStart, dataEnd, entry->info.offset);
1044 #if 0 /* XXX don't check, the 8/98 i18n bug fails here. */
1045  if (rdlen != dl)
1046  goto errxit;
1047 #endif
1048  entry->rdlen = rdlen;
1049  entry++;
1050  h->indexUsed++;
1051  } else {
1052  rpmuint32_t rdl;
1053  rpmuint32_t ril;
1054 
1055  h->flags &= ~HEADERFLAG_LEGACY;
1056 
1057  entry->info.type = (rpmTagType) htonl(pe->type);
1058  entry->info.count = (rpmuint32_t) htonl(pe->count);
1059  entry->info.tag = (rpmTag) htonl(pe->tag);
1060 
1061  if (!ENTRY_IS_REGION(entry))
1062  goto errxit;
1063  if (entry->info.type != REGION_TAG_TYPE)
1064  goto errxit;
1065  if (entry->info.count != REGION_TAG_COUNT)
1066  goto errxit;
1067 
1068  { rpmint32_t off = (rpmint32_t) ntohl(pe->offset);
1069 
1070  if (hdrchkData(off))
1071  goto errxit;
1072  if (off) {
1073 /*@-sizeoftype@*/
1074  size_t nb = REGION_TAG_COUNT;
1075 /*@=sizeoftype@*/
1076  rpmuint32_t * stei = (rpmuint32_t *)
1077  memcpy(alloca(nb), dataStart + off, nb);
1078  rdl = (rpmuint32_t)-ntohl(stei[2]); /* negative offset */
1079 assert((rpmint32_t)rdl >= 0); /* XXX insurance */
1080  ril = (rpmuint32_t)(rdl/sizeof(*pe));
1081  if (hdrchkTags(ril) || hdrchkData(rdl))
1082  goto errxit;
1083  } else {
1084  ril = il;
1085  /*@-sizeoftype@*/
1086  rdl = (rpmuint32_t)(ril * sizeof(struct entryInfo_s));
1087  /*@=sizeoftype@*/
1088  entry->info.tag = (rpmTag) HEADER_IMAGE;
1089  }
1090  }
1091  entry->info.offset = (rpmint32_t) -rdl; /* negative offset */
1092 
1093  /*@-assignexpose@*/
1094  entry->data = pe;
1095  /*@=assignexpose@*/
1096  entry->length = pvlen - sizeof(il) - sizeof(dl);
1097  rdlen = regionSwab(entry+1, (ril-1), 0, pe+1, dataStart, dataEnd, entry->info.offset);
1098  if (rdlen == 0)
1099  goto errxit;
1100  entry->rdlen = rdlen;
1101 
1102  if (ril < (rpmuint32_t)h->indexUsed) {
1103  indexEntry newEntry = entry + ril;
1104  size_t ne = (h->indexUsed - ril);
1105  rpmint32_t rid = entry->info.offset+1;
1106 
1107  /* Load dribble entries from region. */
1108  rdlen = regionSwab(newEntry, (rpmuint32_t)ne, rdlen, pe+ril,
1109  dataStart, dataEnd, rid);
1110  if (rdlen == 0)
1111  goto errxit;
1112 
1113  { indexEntry firstEntry = newEntry;
1114  size_t save = h->indexUsed;
1115  size_t j;
1116 
1117  /* Dribble entries replace duplicate region entries. */
1118  h->indexUsed -= ne;
1119  for (j = 0; j < ne; j++, newEntry++) {
1120  (void) headerRemoveEntry(h, newEntry->info.tag);
1121  if (newEntry->info.tag == HEADER_BASENAMES)
1123  }
1124 
1125  /* If any duplicate entries were replaced, move new entries down. */
1126  if (h->indexUsed < (save - ne)) {
1127  memmove(h->index + h->indexUsed, firstEntry,
1128  (ne * sizeof(*entry)));
1129  }
1130  h->indexUsed += ne;
1131  }
1132  }
1133 
1134  rdlen += REGION_TAG_COUNT;
1135  if (rdlen != dl)
1136  goto errxit;
1137  }
1138 
1139  h->flags &= ~HEADERFLAG_SORTED;
1140  headerSort(h);
1141 
1142  if (sw != NULL) (void) rpmswExit((rpmop)sw, pvlen);
1143 
1144  /*@-globstate -observertrans @*/
1145  return h;
1146  /*@=globstate =observertrans @*/
1147 
1148 errxit:
1149  if (sw != NULL) (void) rpmswExit((rpmop)sw, pvlen);
1150  /*@-usereleased@*/
1151  if (h) {
1152  h->index = _free(h->index);
1153  yarnPossess(h->_item.use); /* XXX rpmioPutItem expects locked. */
1154  h = (Header) rpmioPutPool((rpmioItem)h);
1155  }
1156  /*@=usereleased@*/
1157  /*@-refcounttrans -globstate@*/
1158  return h;
1159  /*@=refcounttrans =globstate@*/
1160 }
1161 
1162 int headerGetMagic(Header h, unsigned char ** magicp, size_t * nmagicp)
1163 {
1164  unsigned char * hmagic = header_magic;
1165  if (magicp)
1166  *magicp = (h ? h->magic : hmagic);
1167  if (nmagicp)
1168  *nmagicp = (h ? sizeof(h->magic) : sizeof(header_magic));
1169  return 0;
1170 }
1171 
1172 int headerSetMagic(Header h, unsigned char * magic, size_t nmagic)
1173 {
1174  if (nmagic > sizeof(h->magic))
1175  nmagic = sizeof(h->magic);
1176  if (h) {
1177  memset(h->magic, 0, sizeof(h->magic));
1178  if (nmagic > 0)
1179  memmove(h->magic, magic, nmagic);
1180  }
1181  return 0;
1182 }
1183 
1184 const char * headerGetOrigin(Header h)
1185 {
1186  return (h != NULL ? h->origin : NULL);
1187 }
1188 
1189 int headerSetOrigin(Header h, const char * origin)
1190 {
1191  if (h != NULL) {
1192  h->origin = _free(h->origin);
1193  h->origin = xstrdup(origin);
1194  }
1195  return 0;
1196 }
1197 
1198 const char * headerGetParent(Header h)
1199 {
1200  return (h != NULL ? h->parent : NULL);
1201 }
1202 
1203 int headerSetParent(Header h, const char * parent)
1204 {
1205  if (h != NULL) {
1206  h->parent = _free(h->parent);
1207  h->parent = xstrdup(parent);
1208  }
1209  return 0;
1210 }
1211 
1212 const char * headerGetBaseURL(Header h)
1213 {
1214 /*@-retexpose@*/
1215  return (h != NULL ? h->baseurl : NULL);
1216 /*@=retexpose@*/
1217 }
1218 
1219 int headerSetBaseURL(Header h, const char * baseurl)
1220 {
1221  if (h != NULL) {
1222  h->baseurl = _free(h->baseurl);
1223  h->baseurl = xstrdup(baseurl);
1224  }
1225  return 0;
1226 }
1227 
1228 struct stat * headerGetStatbuf(Header h)
1229 {
1230 /*@-immediatetrans -retexpose@*/
1231  return (h != NULL ? &h->sb : NULL);
1232 /*@=immediatetrans =retexpose@*/
1233 }
1234 
1235 int headerSetStatbuf(Header h, struct stat * st)
1236 {
1237  if (h != NULL && st != NULL)
1238  memcpy(&h->sb, st, sizeof(h->sb));
1239  return 0;
1240 }
1241 
1242 const char * headerGetDigest(Header h)
1243 {
1244 /*@-compdef -retexpose -usereleased @*/
1245  return (h != NULL ? h->digest : NULL);
1246 /*@=compdef =retexpose =usereleased @*/
1247 }
1248 
1249 int headerSetDigest(Header h, const char * digest)
1250 {
1251  if (h != NULL) {
1252  h->digest = _free(h->digest);
1253  if (digest)
1254  h->digest = xstrdup(digest);
1255  }
1256  return 0;
1257 }
1258 
1260 {
1261 /*@-compdef -retexpose -usereleased @*/
1262  return (h != NULL ? h->rpmdb : NULL);
1263 /*@=compdef =retexpose =usereleased @*/
1264 }
1265 
1266 void * headerSetRpmdb(Header h, void * rpmdb)
1267 {
1268 /*@-assignexpose -temptrans @*/
1269  if (h != NULL)
1270  h->rpmdb = rpmdb;
1271 /*@=assignexpose =temptrans @*/
1272  return NULL;
1273 }
1274 
1276 {
1277  return (h != NULL ? h->instance : 0);
1278 }
1279 
1280 uint32_t headerSetInstance(Header h, uint32_t instance)
1281 {
1282  uint32_t oinstance = 0;
1283  if (h != NULL) {
1284  oinstance = h->instance;
1285  h->instance = instance;
1286  }
1287  return oinstance;
1288 }
1289 
1291 {
1292  return (h != NULL ? h->startoff : 0);
1293 }
1294 
1296 {
1297  if (h != NULL)
1298  h->startoff = startoff;
1299  return 0;
1300 }
1301 
1303 {
1304  return (h != NULL ? h->endoff : 0);
1305 }
1306 
1308 {
1309  if (h != NULL)
1310  h->endoff = endoff;
1311  return 0;
1312 }
1313 
1315 {
1316  Header nh;
1317  void * uh;
1318  const char * origin = (h->origin != NULL ? xstrdup(h->origin) : NULL);
1319  const char * parent = (h->parent != NULL ? xstrdup(h->parent) : NULL);
1320  const char * baseurl = (h->baseurl != NULL ? xstrdup(h->baseurl) : NULL);
1321  const char * digest = (h->digest != NULL ? xstrdup(h->digest) : NULL);
1322  struct stat sb = h->sb; /* structure assignment */
1323  void * rpmdb = h->rpmdb;
1324  rpmuint32_t instance = headerGetInstance(h);
1325  int xx;
1326 
1327 /*@-onlytrans@*/
1328  uh = headerUnload(h, NULL);
1329  (void)headerFree(h);
1330  h = NULL ;
1331 /*@=onlytrans@*/
1332  if (uh == NULL)
1333  return NULL;
1334  nh = headerLoad(uh);
1335  if (nh == NULL) {
1336  uh = _free(uh);
1337  return NULL;
1338  }
1339  nh->flags &= ~(HEADERFLAG_MAPPED|HEADERFLAG_RDONLY); /* XXX unnecessary */
1340  nh->flags |= HEADERFLAG_ALLOCATED;
1341  if (ENTRY_IS_REGION(nh->index)) {
1342  if (tag == HEADER_SIGNATURES || tag == HEADER_IMMUTABLE)
1343  nh->index[0].info.tag = tag;
1344  }
1345  if (origin != NULL) {
1346  xx = headerSetOrigin(nh, origin);
1347  origin = _free(origin);
1348  }
1349  if (parent != NULL) {
1350  xx = headerSetParent(nh, parent);
1351  parent = _free(parent);
1352  }
1353  if (baseurl != NULL) {
1354  xx = headerSetBaseURL(nh, baseurl);
1355  baseurl = _free(baseurl);
1356  }
1357  if (digest != NULL) {
1358  xx = headerSetDigest(nh, digest);
1359  digest = _free(digest);
1360  }
1361 /*@-assignexpose@*/
1362  nh->sb = sb; /* structure assignment */
1363 /*@=assignexpose@*/
1364  (void) headerSetRpmdb(nh, rpmdb);
1365  xx = (int) headerSetInstance(nh, instance);
1366 if (_hdr_debug)
1367 fprintf(stderr, "--> h %p ==== %s: blob %p[%u] flags 0x%x\n", nh, __FUNCTION__, nh->blob, (unsigned)nh->bloblen, nh->flags);
1368  return nh;
1369 }
1370 
1371 static Header headerMap(const void * uh, int map)
1372  /*@*/
1373 {
1374  rpmuint32_t * ei = (rpmuint32_t *) uh;
1375  rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]); /* index length */
1376  rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]); /* data length */
1377  /*@-sizeoftype@*/
1378  size_t pvlen = sizeof(il) + sizeof(dl) +
1379  (il * sizeof(struct entryInfo_s)) + dl;
1380  /*@=sizeoftype@*/
1381  void * nuh = NULL;
1382  Header nh = NULL;
1383 
1384  /* Sanity checks on header intro. */
1385  if (hdrchkTags(il) || hdrchkData(dl) || pvlen >= headerMaxbytes)
1386  return NULL;
1387 
1388  if (map) {
1389  static const int prot = PROT_READ | PROT_WRITE;
1390  static const int flags = MAP_PRIVATE| MAP_ANONYMOUS;
1391  static const int fdno = -1;
1392  static const off_t off = 0;
1393  nuh = mmap(NULL, pvlen, prot, flags, fdno, off);
1394  if (nuh == NULL || nuh == (void *)-1)
1395  fprintf(stderr,
1396  "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
1397  NULL, (unsigned)pvlen, prot, flags, fdno, (unsigned)off,
1398  errno, strerror(errno));
1399  memcpy(nuh, uh, pvlen);
1400  if (mprotect(nuh, pvlen, PROT_READ) != 0)
1401  fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n",
1402  nuh, (unsigned)pvlen, PROT_READ,
1403  errno, strerror(errno));
1404  nh = headerLoad(nuh);
1405  if (nh != NULL) {
1406 assert(nh->bloblen == pvlen);
1407  nh->flags |= HEADERFLAG_MAPPED;
1408  nh->flags |= HEADERFLAG_RDONLY;
1409  } else {
1410  if (munmap(nuh, pvlen) != 0)
1411  fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n",
1412  nuh, (unsigned)pvlen, errno, strerror(errno));
1413  }
1414  } else {
1415  nuh = memcpy(xmalloc(pvlen), uh, pvlen);
1416  if ((nh = headerLoad(nuh)) != NULL)
1417  nh->flags |= HEADERFLAG_ALLOCATED;
1418  else
1419  nuh = _free(nuh);
1420  }
1421 
1422  return nh;
1423 }
1424 
1425 Header headerCopyLoad(const void * uh)
1426 {
1427  static const int map = 1;
1428  return headerMap(uh, map);
1429 }
1430 
1432 {
1433  /*@-mods@*/ /*@ FIX: h modified by sort. */
1434  return (findEntry(h, tag, (rpmTagType)0) != NULL ? 1 : 0);
1435  /*@=mods@*/
1436 }
1437 
1446 static int copyEntry(const indexEntry entry, HE_t he, int minMem)
1447  /*@modifies he @*/
1448 {
1449  rpmTagCount count = entry->info.count;
1450  int rc = 1; /* XXX 1 on success. */
1451 
1452  switch (entry->info.type) {
1453  case RPM_BIN_TYPE:
1454  /*
1455  * XXX This only works for
1456  * XXX "sealed" HEADER_IMMUTABLE/HEADER_SIGNATURES/HEADER_IMAGE.
1457  * XXX This will *not* work for unsealed legacy HEADER_IMAGE (i.e.
1458  * XXX a legacy header freshly read, but not yet unloaded to the rpmdb).
1459  */
1460  if (ENTRY_IS_REGION(entry)) {
1461  rpmuint32_t * ei = ((rpmuint32_t *)entry->data) - 2;
1462  /*@-castexpose@*/
1463  entryInfo pe = (entryInfo) (ei + 2);
1464  /*@=castexpose@*/
1465  unsigned char * dataStart = (unsigned char *) (pe + ntohl(ei[0]));
1466  rpmuint32_t rdl;
1467  rpmuint32_t ril;
1468 
1469 assert(entry->info.offset <= 0); /* XXX insurance */
1470  rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */
1471  ril = (rpmuint32_t)(rdl/sizeof(*pe));
1472  /*@-sizeoftype@*/
1473  rdl = (rpmuint32_t)entry->rdlen;
1474  count = 2 * sizeof(*ei) + (ril * sizeof(*pe)) + rdl;
1475  if (entry->info.tag == HEADER_IMAGE) {
1476  ril -= 1;
1477  pe += 1;
1478  } else {
1479  count += REGION_TAG_COUNT;
1480  rdl += REGION_TAG_COUNT;
1481  }
1482 
1483  he->p.ui32p = ei = (rpmuint32_t *) DRD_xmalloc(count);
1484  ei[0] = (rpmuint32_t)htonl(ril);
1485  ei[1] = (rpmuint32_t)htonl(rdl);
1486 
1487  /*@-castexpose@*/
1488  pe = (entryInfo) memcpy(ei + 2, pe, (ril * sizeof(*pe)));
1489  /*@=castexpose@*/
1490 
1491  (void) memcpy(pe + ril, dataStart, rdl);
1492  } else {
1493  count = (rpmTagCount)entry->length;
1494  he->p.ptr = (!minMem
1495  ? memcpy(DRD_xmalloc(count), entry->data, count)
1496  : entry->data);
1497  }
1498  break;
1499 #if !defined(SUPPORT_I18NSTRING_TYPE)
1500  case RPM_I18NSTRING_TYPE:
1501 assert(0);
1502 #endif
1503  case RPM_STRING_TYPE:
1504  if (count == 1) {
1505  he->p.str = (char *) entry->data;
1506  break;
1507  }
1508  /*@fallthrough@*/
1509 #if defined(SUPPORT_I18NSTRING_TYPE)
1510  case RPM_I18NSTRING_TYPE:
1511 #endif
1512  case RPM_STRING_ARRAY_TYPE:
1513  { const char ** argv;
1514  size_t nb = count * sizeof(*argv);
1515  char * t;
1516  unsigned i;
1517 
1518  /*@-mods@*/
1519  if (minMem) {
1520  he->p.argv = argv = (const char **) DRD_xmalloc(nb);
1521  t = (char *) entry->data;
1522  } else {
1523  he->p.argv = argv = (const char **) DRD_xmalloc(nb + entry->length);
1524  t = (char *) &argv[count];
1525  memcpy(t, entry->data, entry->length);
1526  }
1527  /*@=mods@*/
1528  for (i = 0; i < (unsigned) count; i++) {
1529  argv[i] = t;
1530  t = strchr(t, 0);
1531  t++;
1532  }
1533  } break;
1534 
1535  default:
1536  he->p.ptr = entry->data;
1537  break;
1538  }
1539  he->t = entry->info.type;
1540  he->c = count;
1541  return rc;
1542 }
1543 
1544 #if defined(SUPPORT_I18NSTRING_TYPE)
1545 
1563 static int headerMatchLocale(const char *td, const char *l, const char *le)
1564  /*@*/
1565 {
1566  const char *fe;
1567 
1568 
1569 #if 0
1570  { const char *s, *ll, *CC, *EE, *dd;
1571  char *lbuf, *t.
1572 
1573  /* Copy the buffer and parse out components on the fly. */
1574  lbuf = (char *) alloca(le - l + 1);
1575  for (s = l, ll = t = lbuf; *s; s++, t++) {
1576  switch (*s) {
1577  case '_':
1578  *t = '\0';
1579  CC = t + 1;
1580  break;
1581  case '.':
1582  *t = '\0';
1583  EE = t + 1;
1584  break;
1585  case '@':
1586  *t = '\0';
1587  dd = t + 1;
1588  break;
1589  default:
1590  *t = *s;
1591  break;
1592  }
1593  }
1594 
1595  if (ll) /* ISO language should be lower case */
1596  for (t = ll; *t; t++) *t = tolower(*t);
1597  if (CC) /* ISO country code should be upper case */
1598  for (t = CC; *t; t++) *t = toupper(*t);
1599 
1600  /* There are a total of 16 cases to attempt to match. */
1601  }
1602 #endif
1603 
1604  /* First try a complete match. */
1605  if (strlen(td) == (size_t)(le - l) && !strncmp(td, l, (size_t)(le - l)))
1606  return 1;
1607 
1608  /* Next, try stripping optional dialect and matching. */
1609  for (fe = l; fe < le && *fe != '@'; fe++)
1610  {};
1611  if (fe < le && !strncmp(td, l, (fe - l)))
1612  return 1;
1613 
1614  /* Next, try stripping optional codeset and matching. */
1615  for (fe = l; fe < le && *fe != '.'; fe++)
1616  {};
1617  if (fe < le && !strncmp(td, l, (fe - l)))
1618  return 1;
1619 
1620  /* Finally, try stripping optional country code and matching. */
1621  for (fe = l; fe < le && *fe != '_'; fe++)
1622  {};
1623  if (fe < le && !strncmp(td, l, (fe - l)))
1624  return 2;
1625 
1626  return 0;
1627 }
1628 
1635 /*@dependent@*/ /*@exposed@*/ static char *
1636 headerFindI18NString(Header h, indexEntry entry)
1637  /*@*/
1638 {
1639  const char *lang, *l, *le;
1640  indexEntry table;
1641 
1642  /* XXX Drepper sez' this is the order. */
1643  if ((lang = getenv("LANGUAGE")) == NULL &&
1644  (lang = getenv("LC_ALL")) == NULL &&
1645  (lang = getenv("LC_MESSAGES")) == NULL &&
1646  (lang = getenv("LANG")) == NULL)
1647  return (char *) entry->data;
1648 
1649  /*@-mods@*/
1650  if ((table = findEntry(h, (rpmTag)HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE)) == NULL)
1651  return (char *) entry->data;
1652  /*@=mods@*/
1653 
1654  for (l = lang; *l != '\0'; l = le) {
1655  const char *td;
1656  char *ed, *ed_weak = NULL;
1657  rpmuint32_t langNum;
1658 
1659  while (*l && *l == ':') /* skip leading colons */
1660  l++;
1661  if (*l == '\0')
1662  break;
1663  for (le = l; *le && *le != ':'; le++) /* find end of this locale */
1664  {};
1665 
1666  /* For each entry in the header ... */
1667  for (langNum = 0, td = (const char *)table->data, ed = (char *)entry->data;
1668  langNum < entry->info.count;
1669  langNum++, td += strlen(td) + 1, ed += strlen(ed) + 1)
1670  {
1671  int match = headerMatchLocale(td, l, le);
1672  if (match == 1) return (char *) ed;
1673  else if (match == 2) ed_weak = ed;
1674  }
1675  if (ed_weak) return (char *) ed_weak;
1676  }
1677 
1678  return (char *) entry->data;
1679 }
1680 #endif
1681 
1689 static int intGetEntry(Header h, HE_t he, int flags)
1690  /*@modifies he @*/
1691 {
1692  int minMem = 0;
1693  indexEntry entry;
1694  int rc;
1695 
1696  /* First find the tag */
1697 /*@-mods@*/ /*@ FIX: h modified by sort. */
1698  entry = findEntry(h, he->tag, (rpmTagType)0);
1699 /*@=mods@*/
1700  if (entry == NULL) {
1701  he->t = (rpmTagType)0;
1702  he->p.ptr = NULL;
1703  he->c = 0;
1704  return 0;
1705  }
1706 
1707  switch (entry->info.type) {
1708 #if defined(SUPPORT_I18NSTRING_TYPE)
1709  case RPM_I18NSTRING_TYPE:
1710  if (!(flags & HEADERGET_NOI18NSTRING)) {
1711  rc = 1;
1712  he->t = RPM_STRING_TYPE;
1713  he->c = 1;
1714 /*@-dependenttrans@*/
1715  he->p.str = headerFindI18NString(h, entry);
1716 /*@=dependenttrans@*/
1717  break;
1718  }
1719  /*@fallthrough@*/
1720 #endif
1721  default:
1722  rc = copyEntry(entry, he, minMem);
1723  break;
1724  }
1725 
1726  /* XXX 1 on success */
1727  return (rc == 1 ? 1 : 0);
1728 }
1729 
1737 static int copyData(char * t, const HE_t he, size_t nb)
1738  /*@modifies *t @*/
1739 {
1740  int rc = 0; /* assume success */
1741 
1742  switch (he->t) {
1743 #if defined(SUPPORT_I18NSTRING_TYPE) /* XXX used while reloading? */
1744  case RPM_I18NSTRING_TYPE:
1745 #endif
1746  case RPM_STRING_ARRAY_TYPE:
1747  { const char ** av = he->p.argv;
1748  rpmTagCount cnt = he->c;
1749  const char * s;
1750 
1751  while (cnt-- > 0 && nb > 0) {
1752  if ((s = *av++) != NULL)
1753  do {
1754  *t++ = *s++;
1755  } while (s[-1] && --nb > 0);
1756  }
1757  } break;
1758  default:
1759  if (tagSwab((unsigned char *)t, he, nb) == NULL)
1760  rc = 1;
1761  break;
1762  }
1763  return rc;
1764 }
1765 
1772 /*@null@*/
1773 static void *
1774 grabData(HE_t he, /*@out@*/ size_t * lenp)
1775  /*@modifies *lenp @*/
1776 {
1777  size_t nb = dataLength(he->t, &he->p, he->c, 0, NULL);
1778  char * t = NULL;
1779 
1780  if (nb > 0) {
1781  t = (char *) xmalloc(nb);
1782  if (copyData(t, he, nb)) {
1783  t = _free(t);
1784  nb = 0;
1785  }
1786  }
1787  if (lenp)
1788  *lenp = nb;
1789  return t;
1790 }
1791 
1803 static
1805  /*@modifies h @*/
1806 {
1807  indexEntry entry;
1808  rpmTagData data;
1809  size_t length = 0;
1810  int rc = 0; /* assume failure */
1811 
1812  /* Count must always be >= 1 for headerAddEntry. */
1813  if (he->c == 0)
1814  return rc;
1815 
1816  if (hdrchkType(he->t))
1817  return rc;
1818  if (hdrchkData(he->c))
1819  return rc;
1820 
1821  data.ptr = grabData(he, &length);
1822  if (data.ptr == NULL || length == 0)
1823  return rc;
1824 
1825  /* Allocate more index space if necessary */
1826  if (h->indexUsed == h->indexAlloced) {
1828  h->index = (indexEntry) xrealloc(h->index, h->indexAlloced * sizeof(*h->index));
1829  }
1830 
1831  /* Fill in the index */
1832  entry = h->index + h->indexUsed;
1833  entry->info.tag = he->tag;
1834  entry->info.type = he->t;
1835  entry->info.count = he->c;
1836  entry->info.offset = 0;
1837  entry->data = data.ptr;
1838  entry->length = length;
1839 
1840  if (h->indexUsed > 0 && he->tag < h->index[h->indexUsed-1].info.tag)
1841  h->flags &= ~HEADERFLAG_SORTED;
1842  h->indexUsed++;
1843  rc = 1;
1844 
1845  return rc;
1846 }
1847 
1857 static
1859  /*@modifies h @*/
1860 {
1861  rpmTagData src = { he->p.ptr };
1862  char * t;
1863  indexEntry entry;
1864  size_t length;
1865  int rc = 0; /* assume failure */
1866 
1867 #if !defined(SUPPORT_I18NSTRING_TYPE)
1868 assert(he->t != RPM_I18NSTRING_TYPE);
1869 #endif
1870  if (he->t == RPM_STRING_TYPE
1871 #if defined(SUPPORT_I18NSTRING_TYPE)
1872  || he->t == RPM_I18NSTRING_TYPE
1873 #endif
1874  ) {
1875  /* we can't do this */
1876  return rc;
1877  }
1878 
1879  /* Find the tag entry in the header. */
1880  entry = findEntry(h, he->tag, he->t);
1881  if (!entry)
1882  return rc;
1883 
1884  length = dataLength(he->t, &src, he->c, 0, NULL);
1885  if (length == 0)
1886  return rc;
1887 
1888  if (ENTRY_IN_REGION(entry)) {
1889  char * t = (char *) xmalloc(entry->length + length);
1890  memcpy(t, entry->data, entry->length);
1891  entry->data = t;
1892  entry->info.offset = 0;
1893  } else
1894  entry->data = xrealloc(entry->data, entry->length + length);
1895 
1896  t = ((char *) entry->data) + entry->length;
1897  if (!copyData(t, he, length))
1898  rc = 1;
1899 
1900  entry->length += length;
1901 
1902  entry->info.count += he->c;
1903 
1904  return rc;
1905 }
1906 
1913 static
1915  /*@modifies h @*/
1916 {
1917  return (findEntry(h, he->tag, he->t)
1918  ? headerAppendEntry(h, he)
1919  : headerAddEntry(h, he));
1920 }
1921 
1922 #if defined(SUPPORT_I18NSTRING_TYPE)
1923 int headerAddI18NString(Header h, rpmTag tag, const char * string,
1924  const char * lang)
1925 {
1926  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1927  indexEntry table, entry;
1928  rpmTagData p;
1929  size_t length;
1930  size_t ghosts;
1931  rpmuint32_t i;
1932  rpmuint32_t langNum;
1933  char * buf;
1934  int xx;
1935 
1937  entry = findEntry(h, tag, RPM_I18NSTRING_TYPE);
1938 
1939  if (!table && entry)
1940  return 0; /* this shouldn't ever happen!! */
1941 
1942  if (!table && !entry) {
1943  const char * argv[2];
1944  int count = 0;
1945  p.argv = argv;
1946  if (!lang || (lang[0] == 'C' && lang[1] == '\0')) {
1947  /*@-observertrans -readonlytrans@*/
1948  p.argv[count++] = "C";
1949  /*@=observertrans =readonlytrans@*/
1950  } else {
1951  /*@-observertrans -readonlytrans@*/
1952  p.argv[count++] = "C";
1953  /*@=observertrans =readonlytrans@*/
1954  p.argv[count++] = lang;
1955  }
1956  he->tag = (rpmTag) HEADER_I18NTABLE;
1957  he->t = RPM_STRING_ARRAY_TYPE;
1958  he->p.ptr = p.ptr;
1959  he->c = count;
1960  xx = headerAddEntry(h, he);
1961  if (!xx)
1962  return 0;
1963  table = findEntry(h, he->tag, he->t);
1964  }
1965 
1966  if (!table)
1967  return 0;
1968  if (!lang) lang = "C";
1969 
1970  { const char * l = (const char *) table->data;
1971  for (langNum = 0; langNum < table->info.count; langNum++) {
1972  if (!strcmp(l, lang)) break;
1973  l += strlen(l) + 1;
1974  }
1975  }
1976 
1977  if (langNum >= table->info.count) {
1978  length = strlen(lang) + 1;
1979  if (ENTRY_IN_REGION(table)) {
1980  char * t = (char *) xmalloc(table->length + length);
1981  memcpy(t, table->data, table->length);
1982  table->data = t;
1983  table->info.offset = 0;
1984  } else
1985  table->data = xrealloc(table->data, table->length + length);
1986  memmove(((char *)table->data) + table->length, lang, length);
1987  table->length += length;
1988  table->info.count++;
1989  }
1990 
1991  if (!entry) {
1992  p.argv = (const char **) alloca(sizeof(*p.argv) * (langNum + 1));
1993 /*@-observertrans -readonlytrans@*/
1994  for (i = 0; i < langNum; i++)
1995  p.argv[i] = "";
1996 /*@=observertrans =readonlytrans@*/
1997  p.argv[langNum] = string;
1998  he->tag = tag;
1999  he->t = RPM_I18NSTRING_TYPE;
2000  he->p.ptr = p.ptr;
2001  he->c = langNum + 1;
2002 /*@-compmempass@*/
2003  xx = headerAddEntry(h, he);
2004 /*@=compmempass@*/
2005  return xx;
2006  } else if (langNum >= entry->info.count) {
2007  ghosts = langNum - entry->info.count;
2008 
2009  length = strlen(string) + 1 + ghosts;
2010  if (ENTRY_IN_REGION(entry)) {
2011  char * t = (char *) xmalloc(entry->length + length);
2012  memcpy(t, entry->data, entry->length);
2013  entry->data = t;
2014  entry->info.offset = 0;
2015  } else
2016  entry->data = xrealloc(entry->data, entry->length + length);
2017 
2018  memset(((char *)entry->data) + entry->length, 0, ghosts);
2019  memmove(((char *)entry->data) + entry->length + ghosts, string, strlen(string)+1);
2020 
2021  entry->length += length;
2022  entry->info.count = langNum + 1;
2023  } else {
2024  char *b, *be, *e, *ee, *t;
2025  size_t bn, sn, en;
2026 
2027  /* Set beginning/end pointers to previous data */
2028  b = be = e = ee = (char *) entry->data;
2029  for (i = 0; i < table->info.count; i++) {
2030  if (i == langNum)
2031  be = ee;
2032  ee += strlen(ee) + 1;
2033  if (i == langNum)
2034  e = ee;
2035  }
2036 
2037  /* Get storage for new buffer */
2038  bn = (be-b);
2039  sn = strlen(string) + 1;
2040  en = (ee-e);
2041  length = bn + sn + en;
2042  t = buf = (char *) xmalloc(length);
2043 
2044  /* Copy values into new storage */
2045  memcpy(t, b, bn);
2046  t += bn;
2047 /*@-mayaliasunique@*/
2048  memcpy(t, string, sn);
2049  t += sn;
2050  memcpy(t, e, en);
2051  t += en;
2052 /*@=mayaliasunique@*/
2053 
2054  /* Replace i18N string array */
2055  entry->length -= strlen(be) + 1;
2056  entry->length += sn;
2057 
2058  if (ENTRY_IN_REGION(entry)) {
2059  entry->info.offset = 0;
2060  } else
2061  entry->data = _free(entry->data);
2062  /*@-dependenttrans@*/
2063  entry->data = buf;
2064  /*@=dependenttrans@*/
2065  }
2066 
2067  return 0;
2068 }
2069 #endif
2070 
2078 static
2080  /*@modifies h @*/
2081 {
2082  indexEntry entry;
2083  rpmTagData oldData;
2084  rpmTagData newData;
2085  size_t length = 0;
2086 
2087  /* First find the tag */
2088  entry = findEntry(h, he->tag, he->t);
2089  if (!entry)
2090  return 0;
2091 
2092  newData.ptr = grabData(he, &length);
2093  if (newData.ptr == NULL || length == 0)
2094  return 0;
2095 
2096  /* make sure entry points to the first occurrence of this tag */
2097  while (entry > h->index && (entry - 1)->info.tag == he->tag)
2098  entry--;
2099 
2100  /* free after we've grabbed the new data in case the two are intertwined;
2101  that's a bad idea but at least we won't break */
2102  oldData.ptr = entry->data;
2103 
2104  entry->info.count = he->c;
2105  entry->info.type = he->t;
2106  entry->data = newData.ptr;
2107  entry->length = length;
2108 
2109  if (ENTRY_IN_REGION(entry)) {
2110  entry->info.offset = 0;
2111  } else
2112  oldData.ptr = _free(oldData.ptr);
2113 
2114  return 1;
2115 }
2116 
2122  size_t next_index;
2123 };
2124 
2126 {
2127  if (hi != NULL) {
2128  (void)headerFree(hi->h);
2129  hi->h = NULL;
2130  hi = _free(hi);
2131  }
2132  return hi;
2133 }
2134 
2136 {
2137  HeaderIterator hi = (HeaderIterator) xmalloc(sizeof(*hi));
2138 
2139  headerSort(h);
2140 
2141 /*@-assignexpose -castexpose @*/
2142  hi->h = headerLink(h);
2143 /*@=assignexpose =castexpose @*/
2144 assert(hi->h != NULL);
2145  hi->next_index = 0;
2146  return hi;
2147 }
2148 
2149 int headerNext(HeaderIterator hi, HE_t he, /*@unused@*/ unsigned int flags)
2150 {
2151  void * sw;
2152  Header h = hi->h;
2153  size_t slot = hi->next_index;
2154  indexEntry entry = NULL;
2155  int rc;
2156 
2157  /* Insure that *he is reliably initialized. */
2158  memset(he, 0, sizeof(*he));
2159 
2160  for (slot = hi->next_index; slot < h->indexUsed; slot++) {
2161  entry = h->index + slot;
2162  if (!ENTRY_IS_REGION(entry))
2163  break;
2164  }
2165  hi->next_index = slot;
2166  if (entry == NULL || slot >= h->indexUsed)
2167  return 0;
2168 
2169  hi->next_index++;
2170 
2171  if ((sw = headerGetStats(h, 19)) != NULL) /* RPMTS_OP_HDRGET */
2172  (void) rpmswEnter((rpmop)sw, 0);
2173 
2174  he->tag = entry->info.tag;
2175  rc = copyEntry(entry, he, 0);
2176  if (rc)
2177  rc = rpmheRealloc(he);
2178 
2179  if (sw != NULL) (void) rpmswExit((rpmop)sw, 0);
2180 
2181  /* XXX 1 on success */
2182  return ((rc == 1) ? 1 : 0);
2183 }
2184 
2186 {
2187  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2188  Header nh = headerNew();
2189  HeaderIterator hi;
2190 
2191  for (hi = headerInit(h);
2192  headerNext(hi, he, 0);
2193  he->p.ptr = _free(he->p.ptr))
2194  {
2195  if (he->p.ptr) (void) headerAddEntry(nh, he);
2196  }
2197  hi = headerFini(hi);
2198 
2199  return headerReload(nh, (rpmTag)HEADER_IMAGE);
2200 }
2201 
2202 void headerCopyTags(Header headerFrom, Header headerTo, rpmTag * tagstocopy)
2203 {
2204  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2205  rpmTag * tagno;
2206  int xx;
2207 
2208  if (headerFrom == headerTo)
2209  return;
2210 
2211  for (tagno = tagstocopy; *tagno != 0; tagno++) {
2212  if (headerIsEntry(headerTo, *tagno))
2213  continue;
2214  he->tag = *tagno;
2215  if (!headerGet(headerFrom, he, 0))
2216  continue;
2217  xx = headerPut(headerTo, he, 0);
2218  he->p.ptr = _free(he->p.ptr);
2219  }
2220 }
2221 
2222 int headerGet(Header h, HE_t he, unsigned int flags)
2223 {
2224  void * sw;
2225  const char * name;
2227  headerSprintfExtension ext = NULL;
2228  int extNum;
2229  int rc;
2230 
2231  if (h == NULL || he == NULL) return 0; /* XXX this is nutty. */
2232 
2233  /* Insure that *he is reliably initialized. */
2234  { rpmTag tag = he->tag;
2235  memset(he, 0, sizeof(*he));
2236  he->tag = tag;
2237  }
2238  name = tagName(he->tag);
2239 
2240  if ((sw = headerGetStats(h, 19)) != NULL) /* RPMTS_OP_HDRGET */
2241  (void) rpmswEnter((rpmop)sw, 0);
2242 
2243  /* Search extensions for specific tag override. */
2244  if (!(flags & HEADERGET_NOEXTENSION))
2245  for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
2246  ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
2247  {
2248  if (ext->name == NULL || ext->type != HEADER_EXT_TAG)
2249  continue;
2250  if (!xstrcasecmp(ext->name + (sizeof("RPMTAG_")-1), name))
2251  break;
2252  }
2253 
2254  if (ext && ext->name != NULL && ext->type == HEADER_EXT_TAG) {
2255  rc = ext->u.tagFunction(h, he);
2256  rc = (rc == 0); /* XXX invert extension return. */
2257  } else
2258  rc = intGetEntry(h, he, flags);
2259 
2260  if (rc)
2261  rc = rpmheRealloc(he);
2262 
2263  if (sw != NULL) (void) rpmswExit((rpmop)sw, 0);
2264 
2265 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
2266 /*@-modfilesys@*/
2267  /* XXX verify that explicit and implicit types are identical. */
2268  if (rc)
2269  tagTypeValidate(he);
2270 /*@=modfilesys@*/
2271 #endif
2272 
2273 /*@-modfilesys@*/
2274  if (!((rc == 0 && he->freeData == 0 && he->p.ptr == NULL) ||
2275  (rc == 1 && he->freeData == 1 && he->p.ptr != NULL)))
2276  {
2277 if (_hdr_debug)
2278 fprintf(stderr, "==> %s(%u) %u %p[%u] free %u rc %d\n", name, (unsigned) he->tag, (unsigned) he->t, he->p.ptr, (unsigned) he->c, he->freeData, rc);
2279  }
2280 /*@=modfilesys@*/
2281 
2282  return rc;
2283 }
2284 
2285 int headerPut(Header h, HE_t he, /*@unused@*/ unsigned int flags)
2286 {
2287  int rc;
2288 
2289 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
2290 /*@-modfilesys@*/
2291  /* XXX verify that explicit and implicit types are identical. */
2292  tagTypeValidate(he);
2293 /*@=modfilesys@*/
2294 #endif
2295 
2296  if (he->append)
2297  rc = headerAddOrAppendEntry(h, he);
2298  else
2299  rc = headerAddEntry(h, he);
2300 
2301  return rc;
2302 }
2303 
2304 int headerDel(Header h, HE_t he, /*@unused@*/ unsigned int flags)
2305  /*@modifies h @*/
2306 {
2307  return headerRemoveEntry(h, he->tag);
2308 }
2309 
2310 int headerMod(Header h, HE_t he, /*@unused@*/ unsigned int flags)
2311  /*@modifies h @*/
2312 {
2313 
2314 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
2315 /*@-modfilesys@*/
2316  /* XXX verify that explicit and implicit types are identical. */
2317  tagTypeValidate(he);
2318 /*@=modfilesys@*/
2319 #endif
2320 
2321  return headerModifyEntry(h, he);
2322 }
rpmTagType t
Definition: rpmtag.h:505
void * headerGetStats(Header h, int opx)
Return header stats accumulator structure.
Definition: header.c:97
const char * str
Definition: rpmtag.h:72
rpmTag tag
Definition: rpmtag.h:504
int _hdr_stats
Global header stats enabler.
Definition: header.c:84
const char * origin
const char ** argv
Definition: rpmtag.h:74
#define ANNOTATE_BENIGN_RACE(_a, _b)
Definition: debug.h:159
rpmtime_t rpmswExit(rpmop op, ssize_t rc)
Exit timed operation.
Definition: rpmsw.c:264
struct entryInfo_s info
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1431
const char * headerGetDigest(Header h)
Return digest of origin *.rpm file.
Definition: header.c:1242
const char * digest
#define HEADER_IMMUTABLE
Definition: rpmtag.h:117
char * getenv(const char *name)
rpmuint32_t headerSetStartOff(Header h, rpmuint32_t startoff)
Store header starting byte offset.
Definition: header.c:1295
const char * headerGetParent(Header h)
Return header parent identifier (e.g parent&#39;s NVRA).
Definition: header.c:1198
yarnLock use
Definition: rpmiotypes.h:41
rpmioPool _headerPool
Definition: header.c:161
char * xstrdup(const char *str)
Definition: rpmmalloc.c:322
rpmuint32_t * ui32p
Definition: rpmtag.h:69
static unsigned char header_magic[8]
Definition: header.c:46
#define HEADER_SIGNATURES
Definition: rpmtag.h:116
struct headerToken_s * Header
Definition: rpmtag.h:21
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2222
rpmTagType type
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2285
#define HEADER_IMAGE
Header private tags.
Definition: rpmtag.h:115
The Header data structure.
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2125
rpmuint32_t headerGetEndOff(Header h)
Return header ending byte offset.
Definition: header.c:1302
rpmuint16_t * ui16p
Definition: rpmtag.h:68
rpmuint32_t headerGetStartOff(Header h)
Return header starting byte offset.
Definition: header.c:1290
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
Definition: rpmsw.c:280
#define DRD_xcalloc(_nmemb, _size)
Definition: debug.h:174
int headerSetOrigin(Header h, const char *origin)
Store header origin (e.g path or URL).
Definition: header.c:1189
#define HEADERGET_NOEXTENSION
Definition: rpmtag.h:776
static int indexCmp(const void *avp, const void *bvp)
Definition: header.c:213
struct rpmioItem_s _item
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2135
#define SUPPORT_I18NSTRING_TYPE
Eliminate RPM_I18NSTRING_TYPE.
Definition: system.h:744
int headerSetMagic(Header h, unsigned char *magic, size_t nmagic)
Store header magic.
Definition: header.c:1172
int errno
static Header headerMap(const void *uh, int map)
Definition: header.c:1371
#define DRD_xmalloc(_nb)
Definition: debug.h:173
int headerDel(Header h, HE_t he, unsigned int flags)
Remove tag container from header.
Definition: header.c:2304
unsigned short rpmuint16_t
Definition: rpmiotypes.h:24
Header headerCopyLoad(const void *uh)
Make a copy and convert header to in-memory representation.
Definition: header.c:1425
#define HEADERFLAG_ALLOCATED
static struct rpmop_s hdr_loadops
Definition: header.c:88
Header tag iterator data structure.
Definition: header.c:2120
#define HEADERGET_NOI18NSTRING
Definition: rpmtag.h:777
#define HEADERFLAG_RDONLY
int headerSetParent(Header h, const char *parent)
Store header parent (e.g parent&#39;s NVRA).
Definition: header.c:1203
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2149
#define REGION_TAG_TYPE
void * headerUnload(Header h, size_t *lenp)
headerUnload.
Definition: header.c:648
rpmTagCount count
char * alloca()
int headerMod(Header h, HE_t he, unsigned int flags)
Modify tag container in header.
Definition: header.c:2310
unsigned int rpmuint32_t
Definition: rpmiotypes.h:25
struct _HE_s * HE_t
Definition: rpmtag.h:58
static int typeSizes[16]
Size of header data types.
Definition: header.c:55
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:301
static int rpmheRealloc(HE_t he)
Always realloc HE_t memory.
Definition: header.c:438
void * ptr
Definition: rpmtag.h:66
uint32_t headerSetInstance(Header h, uint32_t instance)
Store header instance (e.g path or URL).
Definition: header.c:1280
static size_t headerMaxbytes
Maximum no.
Definition: header.c:78
static int headerRemoveEntry(Header h, rpmTag tag)
Delete tag in header.
Definition: header.c:932
#define HEADERFLAG_LEGACY
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:221
struct entryInfo_s * entryInfo
Description of tag data.
static int headerModifyEntry(Header h, HE_t he)
Modify tag in header.
Definition: header.c:2079
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:23
rpmop _hdr_getops
Definition: header.c:94
static int intGetEntry(Header h, HE_t he, int flags)
Retrieve tag data from header.
Definition: header.c:1689
rpmTagData p
Definition: rpmtag.h:507
unsigned long long rpmuint64_t
Definition: rpmiotypes.h:26
struct stat * headerGetStatbuf(Header h)
Return header stat(2) buffer (of origin *.rpm file).
Definition: header.c:1228
static int headerAddEntry(Header h, HE_t he)
Add tag to header.
Definition: header.c:1804
struct stat sb
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
rpmuint32_t headerSetEndOff(Header h, rpmuint32_t endoff)
Store header ending byte offset.
Definition: header.c:1307
struct rpmop_s h_loadops
#define hdrchkTags(_ntags)
Sanity check on no.
#define ENTRY_IS_REGION(_e)
int _hdr_debug
Definition: header.c:40
#define HEADER_I18NTABLE
Definition: rpmtag.h:119
Header headerLoad(void *uh)
Convert header to in-memory representation.
Definition: header.c:970
static indexEntry findEntry(Header h, rpmTag tag, rpmTagType type)
Find matching (tag,type) entry in header.
Definition: header.c:884
struct rpmdb_s * rpmdb
Database of headers and tag value indices.
Definition: rpmtypes.h:43
const struct headerSprintfExtension_s * headerSprintfExtension
Definition: rpmtag.h:133
rpmioItem rpmioPutPool(rpmioItem item)
Put unused item into pool (or free).
Definition: rpmmalloc.c:265
rpmTagCount c
Definition: rpmtag.h:508
#define HEADER_OLDFILENAMES
static const char * lang
int xstrcasecmp(const char *s1, const char *s2)
Locale insensitive strcasecmp(3).
Definition: strcasecmp.c:9
Header headerFree(Header h)
Dereference a header instance.
int headerGetMagic(Header h, unsigned char **magicp, size_t *nmagicp)
Return header magic.
Definition: header.c:1162
int rpmswEnter(rpmop op, ssize_t rc)
Enter timed operation.
Definition: rpmsw.c:248
const char * headerGetOrigin(Header h)
Return header origin (e.g path or URL).
Definition: header.c:1184
#define HEADERFLAG_MAPPED
int headerSetDigest(Header h, const char *digest)
Store digest of origin *.rpm file.
Definition: header.c:1249
rpmuint8_t * ui8p
Definition: rpmtag.h:67
static unsigned char * tagSwab(unsigned char *t, const HE_t he, size_t nb)
Swab rpmuint64_t/rpmuint32_t/rpmuint16_t arrays within header region.
Definition: header.c:392
enum rpmTagType_e rpmTagType
Definition: rpmtag.h:46
Cumulative statistics for an operation.
Definition: rpmsw.h:33
#define INDEX_MALLOC_SIZE
Header headerCopy(Header h)
Duplicate a header.
Definition: header.c:2185
#define hdrchkAlign(_type, _off)
Header headerLink(Header h)
Reference a header instance.
static Header headerGetPool(rpmioPool pool)
Definition: header.c:163
rpmuint32_t instance
size_t headerSizeof(Header h)
Return size of on-disk header representation in bytes.
Definition: header.c:266
int rpmint32_t
Definition: rpmiotypes.h:30
Definition: rpmtag.h:503
void headerCopyTags(Header headerFrom, Header headerTo, rpmTag *tagstocopy)
Duplicate tag values from one header into another.
Definition: header.c:2202
unsigned int freeData
Definition: rpmtag.h:510
#define REGION_TAG_COUNT
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:110
unsigned char magic[8]
rpmuint32_t endoff
#define HEADERFLAG_SORTED
static int copyData(char *t, const HE_t he, size_t nb)
Copy (swab&#39;d) data into store.
Definition: header.c:1737
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
static int headerAddOrAppendEntry(Header h, HE_t he)
Add or append element to tag array in header.
Definition: header.c:1914
Header headerReload(Header h, rpmTag tag)
Convert header to on-disk representation, and then reload.
Definition: header.c:1314
static struct rpmop_s hdr_getops
Definition: header.c:92
static void headerUnsort(Header h)
Restore tags in header to original ordering.
Definition: header.c:260
static void headerSort(Header h)
Sort tags in header.
Definition: header.c:227
#define HEADER_BASENAMES
static rpmuint32_t regionSwab(indexEntry entry, rpmuint32_t il, rpmuint32_t dl, entryInfo pe, unsigned char *dataStart, const unsigned char *dataEnd, rpmint32_t regionid)
Swab rpmuint64_t/rpmuint32_t/rpmuint16_t arrays within header region.
Definition: header.c:527
rpmuint32_t startoff
static int copyEntry(const indexEntry entry, HE_t he, int minMem)
Retrieve data from header entry.
Definition: header.c:1446
rpmuint32_t flags
static void headerScrub(void *_h)
Definition: header.c:109
indexEntry index
struct rpmop_s h_getops
rpmop _hdr_loadops
Definition: header.c:90
struct indexEntry_s * indexEntry
A single tag from a Header.
#define hdrchkData(_nbytes)
Sanity check on data size and/or offset and/or count.
static size_t dataLength(rpmTagType type, rpmTagData *p, rpmTagCount count, int onDisk, rpmTagData *pend)
Return length of entry data.
Definition: header.c:330
static int headerAppendEntry(Header h, HE_t he)
Append element to tag array in header.
Definition: header.c:1858
void * headerGetRpmdb(Header h)
Return rpmdb pointer.
Definition: header.c:1259
static const char * name
static int offsetCmp(const void *avp, const void *bvp)
Definition: header.c:238
rpmint32_t offset
#define xmalloc
Definition: system.h:33
void * headerSetRpmdb(Header h, void *rpmdb)
Store rpmdb pointer.
Definition: header.c:1266
const char * parent
const char * baseurl
enum rpmTag_e rpmTag
Definition: rpmtag.h:471
size_t next_index
Definition: header.c:2122
#define ENTRY_IN_REGION(_e)
Header headerNew(void)
Create new (empty) header instance.
Definition: header.c:180
int headerSetBaseURL(Header h, const char *baseurl)
Store header base URL (e.g path or URL).
Definition: header.c:1219
uint32_t headerGetInstance(Header h)
Return header instance (if from rpmdb).
Definition: header.c:1275
const char * headerGetBaseURL(Header h)
Return header base URL (e.g path or URL).
Definition: header.c:1212
#define xrealloc
Definition: system.h:36
rpmuint32_t rpmTagCount
Definition: rpmtag.h:54
int headerSetStatbuf(Header h, struct stat *st)
Copy into header stat(2) buffer (of origin *.rpm file).
Definition: header.c:1235
static void * grabData(HE_t he, size_t *lenp)
Return (malloc&#39;ed) copy of (swab&#39;d) entry data.
Definition: header.c:1774
headerSprintfExtension headerCompoundFormats
Supported default header extension/tag output formats.
Definition: hdrfmt.c:5249
struct headerIterator_s * HeaderIterator
Definition: rpmtag.h:125
#define hdrchkType(_type)
Sanity check on type values.
rpmuint64_t * ui64p
Definition: rpmtag.h:70
unsigned int append
Definition: rpmtag.h:512