rpm  5.4.15
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;
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 == (2 * he->c * sizeof(*tt)));
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;
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;
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@*/
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 
1000  h = headerGetPool(_headerPool);
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  goto errxit;
1334  nh = headerLoad(uh);
1335  if (nh == NULL) {
1336  uh = _free(uh);
1337  goto errxit;
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 errxit:
1371  digest = _free(digest);
1372  baseurl = _free(baseurl);
1373  parent = _free(parent);
1374  origin = _free(origin);
1375  return NULL;
1376 }
1377 
1378 static Header headerMap(const void * uh, int map)
1379  /*@*/
1380 {
1381  rpmuint32_t * ei = (rpmuint32_t *) uh;
1382  rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]); /* index length */
1383  rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]); /* data length */
1384  /*@-sizeoftype@*/
1385  size_t pvlen = sizeof(il) + sizeof(dl) +
1386  (il * sizeof(struct entryInfo_s)) + dl;
1387  /*@=sizeoftype@*/
1388  void * nuh = NULL;
1389  Header nh = NULL;
1390 
1391  /* Sanity checks on header intro. */
1392  if (hdrchkTags(il) || hdrchkData(dl) || pvlen >= headerMaxbytes)
1393  return NULL;
1394 
1395  if (map) {
1396  static const int prot = PROT_READ | PROT_WRITE;
1397  static const int flags = MAP_PRIVATE| MAP_ANONYMOUS;
1398  static const int fdno = -1;
1399  static const off_t off = 0;
1400  nuh = mmap(NULL, pvlen, prot, flags, fdno, off);
1401 assert(nuh != NULL && nuh != (void *)-1); /* coverity #1214080 */
1402  if (nuh == NULL || nuh == (void *)-1)
1403  fprintf(stderr,
1404  "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
1405  NULL, (unsigned)pvlen, prot, flags, fdno, (unsigned)off,
1406  errno, strerror(errno));
1407  memcpy(nuh, uh, pvlen);
1408  if (mprotect(nuh, pvlen, PROT_READ) != 0)
1409  fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n",
1410  nuh, (unsigned)pvlen, PROT_READ,
1411  errno, strerror(errno));
1412  nh = headerLoad(nuh);
1413  if (nh != NULL) {
1414 assert(nh->bloblen == pvlen);
1415  nh->flags |= HEADERFLAG_MAPPED;
1416  nh->flags |= HEADERFLAG_RDONLY;
1417  } else {
1418  if (munmap(nuh, pvlen) != 0)
1419  fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n",
1420  nuh, (unsigned)pvlen, errno, strerror(errno));
1421  }
1422  } else {
1423  nuh = memcpy(xmalloc(pvlen), uh, pvlen);
1424  if ((nh = headerLoad(nuh)) != NULL)
1425  nh->flags |= HEADERFLAG_ALLOCATED;
1426  else
1427  nuh = _free(nuh);
1428  }
1429 
1430  return nh;
1431 }
1432 
1433 Header headerCopyLoad(const void * uh)
1434 {
1435  static const int map = 1;
1436  return headerMap(uh, map);
1437 }
1438 
1440 {
1441  /*@-mods@*/ /*@ FIX: h modified by sort. */
1442  return (findEntry(h, tag, (rpmTagType)0) != NULL ? 1 : 0);
1443  /*@=mods@*/
1444 }
1445 
1454 static int copyEntry(const indexEntry entry, HE_t he, int minMem)
1455  /*@modifies he @*/
1456 {
1457  rpmTagCount count = entry->info.count;
1458  int rc = 1; /* XXX 1 on success. */
1459 
1460  switch (entry->info.type) {
1461  case RPM_BIN_TYPE:
1462  /*
1463  * XXX This only works for
1464  * XXX "sealed" HEADER_IMMUTABLE/HEADER_SIGNATURES/HEADER_IMAGE.
1465  * XXX This will *not* work for unsealed legacy HEADER_IMAGE (i.e.
1466  * XXX a legacy header freshly read, but not yet unloaded to the rpmdb).
1467  */
1468  if (ENTRY_IS_REGION(entry)) {
1469  rpmuint32_t * ei = ((rpmuint32_t *)entry->data) - 2;
1470  /*@-castexpose@*/
1471  entryInfo pe = (entryInfo) (ei + 2);
1472  /*@=castexpose@*/
1473  unsigned char * dataStart = (unsigned char *) (pe + ntohl(ei[0]));
1474  rpmuint32_t rdl;
1475  rpmuint32_t ril;
1476 
1477 assert(entry->info.offset <= 0); /* XXX insurance */
1478  rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */
1479  ril = (rpmuint32_t)(rdl/sizeof(*pe));
1480  /*@-sizeoftype@*/
1481  rdl = (rpmuint32_t)entry->rdlen;
1482  count = 2 * sizeof(*ei) + (ril * sizeof(*pe)) + rdl;
1483  if (entry->info.tag == HEADER_IMAGE) {
1484  ril -= 1;
1485  pe += 1;
1486  } else {
1487  count += REGION_TAG_COUNT;
1488  rdl += REGION_TAG_COUNT;
1489  }
1490 
1491  he->p.ui32p = ei = (rpmuint32_t *) DRD_xmalloc(count);
1492  ei[0] = (rpmuint32_t)htonl(ril);
1493  ei[1] = (rpmuint32_t)htonl(rdl);
1494 
1495  /*@-castexpose@*/
1496  pe = (entryInfo) memcpy(ei + 2, pe, (ril * sizeof(*pe)));
1497  /*@=castexpose@*/
1498 
1499  (void) memcpy(pe + ril, dataStart, rdl);
1500  } else {
1501  count = (rpmTagCount)entry->info.count;
1502  he->p.ptr = (!minMem
1503  ? memcpy(DRD_xmalloc(count), entry->data, count)
1504  : entry->data);
1505  }
1506  break;
1507 #if !defined(SUPPORT_I18NSTRING_TYPE)
1508  case RPM_I18NSTRING_TYPE:
1509 assert(0);
1510 #endif
1511  case RPM_STRING_TYPE:
1512  if (count == 1) {
1513  he->p.str = (char *) entry->data;
1514  break;
1515  }
1516  /*@fallthrough@*/
1517 #if defined(SUPPORT_I18NSTRING_TYPE)
1518  case RPM_I18NSTRING_TYPE:
1519 #endif
1520  case RPM_STRING_ARRAY_TYPE:
1521  { const char ** argv;
1522  size_t nb = count * sizeof(*argv);
1523  char * t;
1524  unsigned i;
1525 
1526  /*@-mods@*/
1527  if (minMem) {
1528  he->p.argv = argv = (const char **) DRD_xmalloc(nb);
1529  t = (char *) entry->data;
1530  } else {
1531  he->p.argv = argv = (const char **) DRD_xmalloc(nb + entry->length);
1532  t = (char *) &argv[count];
1533  memcpy(t, entry->data, entry->length);
1534  }
1535  /*@=mods@*/
1536  for (i = 0; i < (unsigned) count; i++) {
1537  argv[i] = t;
1538  t = strchr(t, 0);
1539  t++;
1540  }
1541  } break;
1542 
1543  default:
1544  he->p.ptr = entry->data;
1545  break;
1546  }
1547  he->t = entry->info.type;
1548  he->c = count;
1549  return rc;
1550 }
1551 
1552 #if defined(SUPPORT_I18NSTRING_TYPE)
1553 
1571 static int headerMatchLocale(const char *td, const char *l, const char *le)
1572  /*@*/
1573 {
1574  const char *fe;
1575 
1576 
1577 #if 0
1578  { const char *s, *ll, *CC, *EE, *dd;
1579  char *lbuf, *t.
1580 
1581  /* Copy the buffer and parse out components on the fly. */
1582  lbuf = (char *) alloca(le - l + 1);
1583  for (s = l, ll = t = lbuf; *s; s++, t++) {
1584  switch (*s) {
1585  case '_':
1586  *t = '\0';
1587  CC = t + 1;
1588  break;
1589  case '.':
1590  *t = '\0';
1591  EE = t + 1;
1592  break;
1593  case '@':
1594  *t = '\0';
1595  dd = t + 1;
1596  break;
1597  default:
1598  *t = *s;
1599  break;
1600  }
1601  }
1602 
1603  if (ll) /* ISO language should be lower case */
1604  for (t = ll; *t; t++) *t = tolower(*t);
1605  if (CC) /* ISO country code should be upper case */
1606  for (t = CC; *t; t++) *t = toupper(*t);
1607 
1608  /* There are a total of 16 cases to attempt to match. */
1609  }
1610 #endif
1611 
1612  /* First try a complete match. */
1613  if (strlen(td) == (size_t)(le - l) && !strncmp(td, l, (size_t)(le - l)))
1614  return 1;
1615 
1616  /* Next, try stripping optional dialect and matching. */
1617  for (fe = l; fe < le && *fe != '@'; fe++)
1618  {};
1619  if (fe < le && !strncmp(td, l, (fe - l)))
1620  return 1;
1621 
1622  /* Next, try stripping optional codeset and matching. */
1623  for (fe = l; fe < le && *fe != '.'; fe++)
1624  {};
1625  if (fe < le && !strncmp(td, l, (fe - l)))
1626  return 1;
1627 
1628  /* Finally, try stripping optional country code and matching. */
1629  for (fe = l; fe < le && *fe != '_'; fe++)
1630  {};
1631  if (fe < le && !strncmp(td, l, (fe - l)))
1632  return 2;
1633 
1634  return 0;
1635 }
1636 
1643 /*@dependent@*/ /*@exposed@*/ static char *
1644 headerFindI18NString(Header h, indexEntry entry)
1645  /*@*/
1646 {
1647  const char *lang, *l, *le;
1648  indexEntry table;
1649 
1650  /* XXX Drepper sez' this is the order. */
1651  if ((lang = getenv("LANGUAGE")) == NULL &&
1652  (lang = getenv("LC_ALL")) == NULL &&
1653  (lang = getenv("LC_MESSAGES")) == NULL &&
1654  (lang = getenv("LANG")) == NULL)
1655  return (char *) entry->data;
1656 
1657  /*@-mods@*/
1658  if ((table = findEntry(h, (rpmTag)HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE)) == NULL)
1659  return (char *) entry->data;
1660  /*@=mods@*/
1661 
1662  for (l = lang; *l != '\0'; l = le) {
1663  const char *td;
1664  char *ed, *ed_weak = NULL;
1665  rpmuint32_t langNum;
1666 
1667  while (*l && *l == ':') /* skip leading colons */
1668  l++;
1669  if (*l == '\0')
1670  break;
1671  for (le = l; *le && *le != ':'; le++) /* find end of this locale */
1672  {};
1673 
1674  /* For each entry in the header ... */
1675  for (langNum = 0, td = (const char *)table->data, ed = (char *)entry->data;
1676  langNum < entry->info.count;
1677  langNum++, td += strlen(td) + 1, ed += strlen(ed) + 1)
1678  {
1679  int match = headerMatchLocale(td, l, le);
1680  if (match == 1) return (char *) ed;
1681  else if (match == 2) ed_weak = ed;
1682  }
1683  if (ed_weak) return (char *) ed_weak;
1684  }
1685 
1686 /* when everything fail, try gettext */
1687  return ((entry->data != NULL) && *(char*)(entry->data)) ? _(entry->data) : (char *) entry->data;
1688 }
1689 #endif
1690 
1698 static int intGetEntry(Header h, HE_t he, int flags)
1699  /*@modifies he @*/
1700 {
1701  int minMem = 0;
1702  indexEntry entry;
1703  int rc;
1704 
1705  /* First find the tag */
1706 /*@-mods@*/ /*@ FIX: h modified by sort. */
1707  entry = findEntry(h, he->tag, (rpmTagType)0);
1708 /*@=mods@*/
1709  if (entry == NULL) {
1710  he->t = (rpmTagType)0;
1711  he->p.ptr = NULL;
1712  he->c = 0;
1713  return 0;
1714  }
1715 
1716  switch (entry->info.type) {
1717 #if defined(SUPPORT_I18NSTRING_TYPE)
1718  case RPM_I18NSTRING_TYPE:
1719  if (!(flags & HEADERGET_NOI18NSTRING)) {
1720  rc = 1;
1721  he->t = RPM_STRING_TYPE;
1722  he->c = 1;
1723 /*@-dependenttrans@*/
1724  he->p.str = headerFindI18NString(h, entry);
1725 /*@=dependenttrans@*/
1726  break;
1727  }
1728  /*@fallthrough@*/
1729 #endif
1730  default:
1731  rc = copyEntry(entry, he, minMem);
1732  break;
1733  }
1734 
1735  /* XXX 1 on success */
1736  return (rc == 1 ? 1 : 0);
1737 }
1738 
1746 static int copyData(char * t, const HE_t he, size_t nb)
1747  /*@modifies *t @*/
1748 {
1749  int rc = 0; /* assume success */
1750 
1751  switch (he->t) {
1752 #if defined(SUPPORT_I18NSTRING_TYPE) /* XXX used while reloading? */
1753  case RPM_I18NSTRING_TYPE:
1754 #endif
1755  case RPM_STRING_ARRAY_TYPE:
1756  { const char ** av = he->p.argv;
1757  rpmTagCount cnt = he->c;
1758  const char * s;
1759 
1760  while (cnt-- > 0 && nb > 0) {
1761  if ((s = *av++) != NULL)
1762  do {
1763  *t++ = *s++;
1764  } while (s[-1] && --nb > 0);
1765  }
1766  } break;
1767  default:
1768  if (tagSwab((unsigned char *)t, he, nb) == NULL)
1769  rc = 1;
1770  break;
1771  }
1772  return rc;
1773 }
1774 
1781 /*@null@*/
1782 static void *
1783 grabData(HE_t he, /*@out@*/ size_t * lenp)
1784  /*@modifies *lenp @*/
1785 {
1786  size_t nb = dataLength(he->t, &he->p, he->c, 0, NULL);
1787  char * t = NULL;
1788 
1789  if (nb > 0) {
1790  t = (char *) xmalloc(nb);
1791  if (copyData(t, he, nb)) {
1792  t = _free(t);
1793  nb = 0;
1794  }
1795  }
1796  if (lenp)
1797  *lenp = nb;
1798  return t;
1799 }
1800 
1812 static
1814  /*@modifies h @*/
1815 {
1816  indexEntry entry;
1817  rpmTagData data;
1818  size_t length = 0;
1819  int rc = 0; /* assume failure */
1820 
1821  /* Count must always be >= 1 for headerAddEntry. */
1822  if (he->c == 0)
1823  return rc;
1824 
1825  if (hdrchkType(he->t))
1826  return rc;
1827  if (hdrchkData(he->c))
1828  return rc;
1829 
1830  data.ptr = grabData(he, &length);
1831  if (data.ptr == NULL || length == 0)
1832  return rc;
1833 
1834  /* Allocate more index space if necessary */
1835  if (h->indexUsed == h->indexAlloced) {
1837  h->index = (indexEntry) xrealloc(h->index, h->indexAlloced * sizeof(*h->index));
1838  }
1839 
1840  /* Fill in the index */
1841  entry = h->index + h->indexUsed;
1842  entry->info.tag = he->tag;
1843  entry->info.type = he->t;
1844  entry->info.count = he->c;
1845  entry->info.offset = 0;
1846  entry->data = data.ptr;
1847  entry->length = length;
1848 
1849  if (h->indexUsed > 0 && he->tag < h->index[h->indexUsed-1].info.tag)
1850  h->flags &= ~HEADERFLAG_SORTED;
1851  h->indexUsed++;
1852  rc = 1;
1853 
1854  return rc;
1855 }
1856 
1866 static
1868  /*@modifies h @*/
1869 {
1870  rpmTagData src = { he->p.ptr };
1871  char * t;
1872  indexEntry entry;
1873  size_t length;
1874  int rc = 0; /* assume failure */
1875 
1876 #if !defined(SUPPORT_I18NSTRING_TYPE)
1877 assert(he->t != RPM_I18NSTRING_TYPE);
1878 #endif
1879  if (he->t == RPM_STRING_TYPE
1880 #if defined(SUPPORT_I18NSTRING_TYPE)
1881  || he->t == RPM_I18NSTRING_TYPE
1882 #endif
1883  ) {
1884  /* we can't do this */
1885  return rc;
1886  }
1887 
1888  /* Find the tag entry in the header. */
1889  entry = findEntry(h, he->tag, he->t);
1890  if (!entry)
1891  return rc;
1892 
1893  length = dataLength(he->t, &src, he->c, 0, NULL);
1894  if (length == 0)
1895  return rc;
1896 
1897  if (ENTRY_IN_REGION(entry)) {
1898  char * t = (char *) xmalloc(entry->length + length);
1899  memcpy(t, entry->data, entry->length);
1900  entry->data = t;
1901  entry->info.offset = 0;
1902  } else
1903  entry->data = xrealloc(entry->data, entry->length + length);
1904 
1905  t = ((char *) entry->data) + entry->length;
1906  if (!copyData(t, he, length))
1907  rc = 1;
1908 
1909  entry->length += length;
1910 
1911  entry->info.count += he->c;
1912 
1913  return rc;
1914 }
1915 
1922 static
1924  /*@modifies h @*/
1925 {
1926  return (findEntry(h, he->tag, he->t)
1927  ? headerAppendEntry(h, he)
1928  : headerAddEntry(h, he));
1929 }
1930 
1931 #if defined(SUPPORT_I18NSTRING_TYPE)
1932 int headerAddI18NString(Header h, rpmTag tag, const char * string,
1933  const char * lang)
1934 {
1935  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1936  indexEntry table, entry;
1937  rpmTagData p;
1938  size_t length;
1939  size_t ghosts;
1940  rpmuint32_t i;
1941  rpmuint32_t langNum;
1942  char * buf;
1943  int xx;
1944 
1945  table = findEntry(h, (rpmTag)HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE);
1946  entry = findEntry(h, tag, RPM_I18NSTRING_TYPE);
1947 
1948  if (!table && entry)
1949  return 0; /* this shouldn't ever happen!! */
1950 
1951  if (!table && !entry) {
1952  const char * argv[2];
1953  int count = 0;
1954  p.argv = argv;
1955  if (!lang || (lang[0] == 'C' && lang[1] == '\0')) {
1956  /*@-observertrans -readonlytrans@*/
1957  p.argv[count++] = "C";
1958  /*@=observertrans =readonlytrans@*/
1959  } else {
1960  /*@-observertrans -readonlytrans@*/
1961  p.argv[count++] = "C";
1962  /*@=observertrans =readonlytrans@*/
1963  p.argv[count++] = lang;
1964  }
1965  he->tag = (rpmTag) HEADER_I18NTABLE;
1966  he->t = RPM_STRING_ARRAY_TYPE;
1967  he->p.ptr = p.ptr;
1968  he->c = count;
1969  xx = headerAddEntry(h, he);
1970  if (!xx)
1971  return 0;
1972  table = findEntry(h, he->tag, he->t);
1973  }
1974 
1975  if (!table)
1976  return 0;
1977  if (!lang) lang = "C";
1978 
1979  { const char * l = (const char *) table->data;
1980  for (langNum = 0; langNum < table->info.count; langNum++) {
1981  if (!strcmp(l, lang)) break;
1982  l += strlen(l) + 1;
1983  }
1984  }
1985 
1986  if (langNum >= table->info.count) {
1987  length = strlen(lang) + 1;
1988  if (ENTRY_IN_REGION(table)) {
1989  char * t = (char *) xmalloc(table->length + length);
1990  memcpy(t, table->data, table->length);
1991  table->data = t;
1992  table->info.offset = 0;
1993  } else
1994  table->data = xrealloc(table->data, table->length + length);
1995  memmove(((char *)table->data) + table->length, lang, length);
1996  table->length += length;
1997  table->info.count++;
1998  }
1999 
2000  if (!entry) {
2001  p.argv = (const char **) alloca(sizeof(*p.argv) * (langNum + 1));
2002 /*@-observertrans -readonlytrans@*/
2003  for (i = 0; i < langNum; i++)
2004  p.argv[i] = "";
2005 /*@=observertrans =readonlytrans@*/
2006  p.argv[langNum] = string;
2007  he->tag = tag;
2008  he->t = RPM_I18NSTRING_TYPE;
2009  he->p.ptr = p.ptr;
2010  he->c = langNum + 1;
2011 /*@-compmempass@*/
2012  xx = headerAddEntry(h, he);
2013 /*@=compmempass@*/
2014  return xx;
2015  } else if (langNum >= entry->info.count) {
2016  ghosts = langNum - entry->info.count;
2017 
2018  length = strlen(string) + 1 + ghosts;
2019  if (ENTRY_IN_REGION(entry)) {
2020  char * t = (char *) xmalloc(entry->length + length);
2021  memcpy(t, entry->data, entry->length);
2022  entry->data = t;
2023  entry->info.offset = 0;
2024  } else
2025  entry->data = xrealloc(entry->data, entry->length + length);
2026 
2027  memset(((char *)entry->data) + entry->length, 0, ghosts);
2028  memmove(((char *)entry->data) + entry->length + ghosts, string, strlen(string)+1);
2029 
2030  entry->length += length;
2031  entry->info.count = langNum + 1;
2032  } else {
2033  char *b, *be, *e, *ee, *t;
2034  size_t bn, sn, en;
2035 
2036  /* Set beginning/end pointers to previous data */
2037  b = be = e = ee = (char *) entry->data;
2038  for (i = 0; i < table->info.count; i++) {
2039  if (i == langNum)
2040  be = ee;
2041  ee += strlen(ee) + 1;
2042  if (i == langNum)
2043  e = ee;
2044  }
2045 
2046  /* Get storage for new buffer */
2047  bn = (be-b);
2048  sn = strlen(string) + 1;
2049  en = (ee-e);
2050  length = bn + sn + en;
2051  t = buf = (char *) xmalloc(length);
2052 
2053  /* Copy values into new storage */
2054  memcpy(t, b, bn);
2055  t += bn;
2056 /*@-mayaliasunique@*/
2057  memcpy(t, string, sn);
2058  t += sn;
2059  memcpy(t, e, en);
2060  t += en;
2061 /*@=mayaliasunique@*/
2062 
2063  /* Replace i18N string array */
2064  entry->length -= strlen(be) + 1;
2065  entry->length += sn;
2066 
2067  if (ENTRY_IN_REGION(entry)) {
2068  entry->info.offset = 0;
2069  } else
2070  entry->data = _free(entry->data);
2071  /*@-dependenttrans@*/
2072  entry->data = buf;
2073  /*@=dependenttrans@*/
2074  }
2075 
2076  return 0;
2077 }
2078 #endif
2079 
2087 static
2089  /*@modifies h @*/
2090 {
2091  indexEntry entry;
2092  rpmTagData oldData;
2093  rpmTagData newData;
2094  size_t length = 0;
2095 
2096  /* First find the tag */
2097  entry = findEntry(h, he->tag, he->t);
2098  if (!entry)
2099  return 0;
2100 
2101  newData.ptr = grabData(he, &length);
2102  if (newData.ptr == NULL || length == 0)
2103  return 0;
2104 
2105  /* make sure entry points to the first occurrence of this tag */
2106  while (entry > h->index && (entry - 1)->info.tag == he->tag)
2107  entry--;
2108 
2109  /* free after we've grabbed the new data in case the two are intertwined;
2110  that's a bad idea but at least we won't break */
2111  oldData.ptr = entry->data;
2112 
2113  entry->info.count = he->c;
2114  entry->info.type = he->t;
2115  entry->data = newData.ptr;
2116  entry->length = length;
2117 
2118  if (ENTRY_IN_REGION(entry)) {
2119  entry->info.offset = 0;
2120  } else
2121  oldData.ptr = _free(oldData.ptr);
2122 
2123  return 1;
2124 }
2125 
2131  size_t next_index;
2132 };
2133 
2135 {
2136  if (hi != NULL) {
2137  (void)headerFree(hi->h);
2138  hi->h = NULL;
2139  hi = _free(hi);
2140  }
2141  return hi;
2142 }
2143 
2145 {
2146  HeaderIterator hi = (HeaderIterator) xmalloc(sizeof(*hi));
2147 
2148  headerSort(h);
2149 
2150 /*@-assignexpose -castexpose @*/
2151  hi->h = headerLink(h);
2152 /*@=assignexpose =castexpose @*/
2153 assert(hi->h != NULL);
2154  hi->next_index = 0;
2155  return hi;
2156 }
2157 
2158 int headerNext(HeaderIterator hi, HE_t he, /*@unused@*/ unsigned int flags)
2159 {
2160  void * sw;
2161  Header h = hi->h;
2162  size_t slot = hi->next_index;
2163  indexEntry entry = NULL;
2164  int rc;
2165 
2166  /* Ensure that *he is reliably initialized. */
2167  memset(he, 0, sizeof(*he));
2168 
2169  for (slot = hi->next_index; slot < h->indexUsed; slot++) {
2170  entry = h->index + slot;
2171  if (!ENTRY_IS_REGION(entry))
2172  break;
2173  }
2174  hi->next_index = slot;
2175  if (entry == NULL || slot >= h->indexUsed)
2176  return 0;
2177 
2178  hi->next_index++;
2179 
2180  if ((sw = headerGetStats(h, 19)) != NULL) /* RPMTS_OP_HDRGET */
2181  (void) rpmswEnter((rpmop)sw, 0);
2182 
2183  he->tag = entry->info.tag;
2184  rc = copyEntry(entry, he, 0);
2185  if (rc)
2186  rc = rpmheRealloc(he);
2187 
2188  if (sw != NULL) (void) rpmswExit((rpmop)sw, 0);
2189 
2190  /* XXX 1 on success */
2191  return ((rc == 1) ? 1 : 0);
2192 }
2193 
2195 {
2196  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2197  Header nh = headerNew();
2198  HeaderIterator hi;
2199 
2200  for (hi = headerInit(h);
2201  headerNext(hi, he, 0);
2202  he->p.ptr = _free(he->p.ptr))
2203  {
2204  if (he->p.ptr) (void) headerAddEntry(nh, he);
2205  }
2206  hi = headerFini(hi);
2207 
2208  return headerReload(nh, (rpmTag)HEADER_IMAGE);
2209 }
2210 
2211 void headerCopyTags(Header headerFrom, Header headerTo, rpmTag * tagstocopy)
2212 {
2213  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2214  rpmTag * tagno;
2215  int xx;
2216 
2217  if (headerFrom == headerTo)
2218  return;
2219 
2220  for (tagno = tagstocopy; *tagno != 0; tagno++) {
2221  if (headerIsEntry(headerTo, *tagno))
2222  continue;
2223  he->tag = *tagno;
2224  if (!headerGet(headerFrom, he, HEADERGET_NOEXTENSION))
2225  continue;
2226  xx = headerPut(headerTo, he, 0);
2227  he->p.ptr = _free(he->p.ptr);
2228  }
2229 }
2230 
2231 int headerGet(Header h, HE_t he, unsigned int flags)
2232 {
2233  void * sw;
2234  const char * name;
2236  headerSprintfExtension ext = NULL;
2237  int extNum;
2238  int rc;
2239 
2240  if (h == NULL || he == NULL) return 0; /* XXX this is nutty. */
2241 
2242  /* Ensure that *he is reliably initialized. */
2243  { rpmTag tag = he->tag;
2244  memset(he, 0, sizeof(*he));
2245  he->tag = tag;
2246  }
2247  name = tagName(he->tag);
2248 
2249  if ((sw = headerGetStats(h, 19)) != NULL) /* RPMTS_OP_HDRGET */
2250  (void) rpmswEnter((rpmop)sw, 0);
2251 
2252  /* Search extensions for specific tag override. */
2253  if (!(flags & HEADERGET_NOEXTENSION))
2254  for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
2255  ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
2256  {
2257  if (ext->name == NULL || ext->type != HEADER_EXT_TAG)
2258  continue;
2259  if (!xstrcasecmp(ext->name + (sizeof("RPMTAG_")-1), name))
2260  break;
2261  }
2262 
2263  if (ext && ext->name != NULL && ext->type == HEADER_EXT_TAG) {
2264  rc = ext->u.tagFunction(h, he);
2265  rc = (rc == 0); /* XXX invert extension return. */
2266  } else
2267  rc = intGetEntry(h, he, flags);
2268 
2269  if (rc)
2270  rc = rpmheRealloc(he);
2271 
2272  if (sw != NULL) (void) rpmswExit((rpmop)sw, 0);
2273 
2274 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
2275 /*@-modfilesys@*/
2276  /* XXX verify that explicit and implicit types are identical. */
2277  if (rc)
2278  tagTypeValidate(he);
2279 /*@=modfilesys@*/
2280 #endif
2281 
2282 /*@-modfilesys@*/
2283  if (!((rc == 0 && he->freeData == 0 && he->p.ptr == NULL) ||
2284  (rc == 1 && he->freeData == 1 && he->p.ptr != NULL)))
2285  {
2286 if (_hdr_debug)
2287 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);
2288  }
2289 /*@=modfilesys@*/
2290 
2291  return rc;
2292 }
2293 
2294 int headerPut(Header h, HE_t he, /*@unused@*/ unsigned int flags)
2295 {
2296  int rc;
2297 
2298 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
2299 /*@-modfilesys@*/
2300  /* XXX verify that explicit and implicit types are identical. */
2301  tagTypeValidate(he);
2302 /*@=modfilesys@*/
2303 #endif
2304 
2305  if (he->append)
2306  rc = headerAddOrAppendEntry(h, he);
2307  else
2308  rc = headerAddEntry(h, he);
2309 
2310  return rc;
2311 }
2312 
2313 int headerDel(Header h, HE_t he, /*@unused@*/ unsigned int flags)
2314  /*@modifies h @*/
2315 {
2316  return headerRemoveEntry(h, he->tag);
2317 }
2318 
2319 int headerMod(Header h, HE_t he, /*@unused@*/ unsigned int flags)
2320  /*@modifies h @*/
2321 {
2322 
2323 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
2324 /*@-modfilesys@*/
2325  /* XXX verify that explicit and implicit types are identical. */
2326  tagTypeValidate(he);
2327 /*@=modfilesys@*/
2328 #endif
2329 
2330  return headerModifyEntry(h, he);
2331 }
const bson * b
Definition: bson.h:280
rpmTagType t
Definition: rpmtag.h:504
void * headerGetStats(Header h, int opx)
Return header stats accumulator structure.
Definition: header.c:97
const char * str
Definition: rpmtag.h:73
rpmTag tag
Definition: rpmtag.h:503
int _hdr_stats
Global header stats enabler.
Definition: header.c:84
const char * origin
const char ** argv
Definition: rpmtag.h:75
#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:1439
const char * headerGetDigest(Header h)
Return digest of origin *.rpm file.
Definition: header.c:1242
const char * digest
const char const char size_t len
Definition: bson.h:823
#define HEADER_IMMUTABLE
Definition: rpmtag.h:118
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's NVRA).
Definition: header.c:1198
void yarnPossess(yarnLock bolt)
Definition: yarn.c:262
yarnLock use
Definition: rpmiotypes.h:44
rpmioPool _headerPool
Definition: header.c:161
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
rpmuint32_t * ui32p
Definition: rpmtag.h:70
static unsigned char header_magic[8]
Definition: header.c:46
#define HEADER_SIGNATURES
Definition: rpmtag.h:117
struct headerToken_s * Header
Definition: rpmtag.h:22
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2231
rpmTagType type
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2294
#define HEADER_IMAGE
Header private tags.
Definition: rpmtag.h:116
The Header data structure.
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2134
rpmuint32_t headerGetEndOff(Header h)
Return header ending byte offset.
Definition: header.c:1302
rpmuint16_t * ui16p
Definition: rpmtag.h:69
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:775
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:2144
#define SUPPORT_I18NSTRING_TYPE
Eliminate RPM_I18NSTRING_TYPE.
Definition: system.h:775
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:1378
#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:2313
unsigned short rpmuint16_t
Definition: rpmiotypes.h:27
Header headerCopyLoad(const void *uh)
Make a copy and convert header to in-memory representation.
Definition: header.c:1433
#define HEADERFLAG_ALLOCATED
static struct rpmop_s hdr_loadops
Definition: header.c:88
Header tag iterator data structure.
Definition: header.c:2129
#define HEADERGET_NOI18NSTRING
Definition: rpmtag.h:776
#define HEADERFLAG_RDONLY
int headerSetParent(Header h, const char *parent)
Store header parent (e.g parent's NVRA).
Definition: header.c:1203
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2158
#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:2319
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
struct _HE_s * HE_t
Definition: rpmtag.h:59
static int typeSizes[16]
Size of header data types.
Definition: header.c:55
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
static int rpmheRealloc(HE_t he)
Always realloc HE_t memory.
Definition: header.c:438
void * ptr
Definition: rpmtag.h:67
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:220
struct entryInfo_s * entryInfo
Description of tag data.
static int headerModifyEntry(Header h, HE_t he)
Modify tag in header.
Definition: header.c:2088
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
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:1698
const char const bson * data
Definition: mongo.h:463
rpmTagData p
Definition: rpmtag.h:506
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:1813
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:120
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:134
rpmioItem rpmioPutPool(rpmioItem item)
Put unused item into pool (or free).
Definition: rpmmalloc.c:264
rpmTagCount c
Definition: rpmtag.h:507
#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 const bson const bson * op
Definition: mongo.h:505
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:68
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:47
Cumulative statistics for an operation.
Definition: rpmsw.h:39
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
#define INDEX_MALLOC_SIZE
Header headerCopy(Header h)
Duplicate a header.
Definition: header.c:2194
#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:33
Definition: rpmtag.h:502
const char const int i
Definition: bson.h:778
void headerCopyTags(Header headerFrom, Header headerTo, rpmTag *tagstocopy)
Duplicate tag values from one header into another.
Definition: header.c:2211
unsigned int freeData
Definition: rpmtag.h:509
#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:109
unsigned char magic[8]
const char const char size_t size
Definition: bson.h:895
rpmuint32_t endoff
#define HEADERFLAG_SORTED
static int copyData(char *t, const HE_t he, size_t nb)
Copy (swab'd) data into store.
Definition: header.c:1746
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
static int headerAddOrAppendEntry(Header h, HE_t he)
Add or append element to tag array in header.
Definition: header.c:1923
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:1454
rpmuint32_t flags
static void headerScrub(void *_h)
Definition: header.c:109
indexEntry index
const char char type
Definition: bson.h:908
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:1867
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
#define _(Text)
Definition: system.h:29
rpmint32_t offset
#define xmalloc
Definition: system.h:32
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:470
size_t next_index
Definition: header.c:2131
#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:35
rpmuint32_t rpmTagCount
Definition: rpmtag.h:55
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'ed) copy of (swab'd) entry data.
Definition: header.c:1783
headerSprintfExtension headerCompoundFormats
Supported default header extension/tag output formats.
Definition: hdrfmt.c:5278
struct headerIterator_s * HeaderIterator
Definition: rpmtag.h:126
#define hdrchkType(_type)
Sanity check on type values.
int j
Definition: mongo.h:438
rpmuint64_t * ui64p
Definition: rpmtag.h:71
unsigned int append
Definition: rpmtag.h:511