00001
00005
00006
00007
00008
00009
00010
00011 #include "system.h"
00012
00013 #include <rpmio.h>
00014 #define _RPMTAG_INTERNAL
00015 #include <header_internal.h>
00016
00017 #include "debug.h"
00018
00019
00020 int _hdr_debug = 0;
00021
00022
00023
00024
00025
00026
00027
00028
00029
00032
00033
00034 static unsigned char header_magic[8] = {
00035 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
00036 };
00037
00038
00042
00043 static int typeSizes[16] = {
00044 0,
00045 1,
00046 1,
00047 2,
00048 4,
00049 8,
00050 -1,
00051 1,
00052 -1,
00053 -1,
00054 0,
00055 0,
00056 0,
00057 0,
00058 0,
00059 0
00060 };
00061
00065
00066 static size_t headerMaxbytes = (1024*1024*1024);
00067
00071
00072 int _hdr_stats = 0;
00073
00074
00075
00076 static struct rpmop_s hdr_loadops;
00077
00078 rpmop _hdr_loadops = &hdr_loadops;
00079
00080 static struct rpmop_s hdr_getops;
00081
00082 rpmop _hdr_getops = &hdr_getops;
00083
00084
00085 void * headerGetStats(Header h, int opx)
00086 {
00087 rpmop op = NULL;
00088 if (_hdr_stats)
00089 switch (opx) {
00090 case 18: op = &h->h_loadops; break;
00091 case 19: op = &h->h_getops; break;
00092 }
00093 return op;
00094 }
00095
00096 Header headerLink(Header h)
00097 {
00098
00099 if (h == NULL) return NULL;
00100
00101
00102 h->nrefs++;
00103
00104 if (_hdr_debug)
00105 fprintf(stderr, "--> h %p ++ %d at %s:%u\n", h, h->nrefs, __FILE__, __LINE__);
00106
00107
00108
00109 return h;
00110
00111 }
00112
00113 Header headerUnlink(Header h)
00114 {
00115 if (h == NULL) return NULL;
00116
00117 if (_hdr_debug)
00118 fprintf(stderr, "--> h %p -- %d at %s:%u\n", h, h->nrefs, __FILE__, __LINE__);
00119
00120 h->nrefs--;
00121 return NULL;
00122 }
00123
00124 Header headerFree(Header h)
00125 {
00126 (void) headerUnlink(h);
00127
00128
00129 if (h == NULL || h->nrefs > 0)
00130 return NULL;
00131
00132 if (h->index) {
00133 indexEntry entry = h->index;
00134 size_t i;
00135 for (i = 0; i < h->indexUsed; i++, entry++) {
00136 if ((h->flags & HEADERFLAG_ALLOCATED) && ENTRY_IS_REGION(entry)) {
00137 if (entry->length > 0) {
00138 uint32_t * ei = entry->data;
00139 if ((ei - 2) == h->blob)
00140 h->blob = _free(h->blob);
00141 entry->data = NULL;
00142 }
00143 } else if (!ENTRY_IN_REGION(entry)) {
00144 entry->data = _free(entry->data);
00145 }
00146 entry->data = NULL;
00147 }
00148 h->index = _free(h->index);
00149 }
00150 h->origin = _free(h->origin);
00151
00152
00153 if (_hdr_stats) {
00154 if (_hdr_loadops)
00155 (void) rpmswAdd(_hdr_loadops, headerGetStats(h, 18));
00156 if (_hdr_getops)
00157 (void) rpmswAdd(_hdr_getops, headerGetStats(h, 19));
00158 }
00159
00160
00161 h = _free(h);
00162 return h;
00163
00164 }
00165
00166 Header headerNew(void)
00167 {
00168 Header h = xcalloc(1, sizeof(*h));
00169
00170 (void) memcpy(h->magic, header_magic, sizeof(h->magic));
00171 h->blob = NULL;
00172 h->origin = NULL;
00173 h->instance = 0;
00174 h->indexAlloced = INDEX_MALLOC_SIZE;
00175 h->indexUsed = 0;
00176 h->flags |= HEADERFLAG_SORTED;
00177
00178 h->index = (h->indexAlloced
00179 ? xcalloc(h->indexAlloced, sizeof(*h->index))
00180 : NULL);
00181
00182 h->nrefs = 0;
00183
00184 return headerLink(h);
00185
00186 }
00187
00190 static int indexCmp(const void * avp, const void * bvp)
00191
00192 {
00193
00194 indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp;
00195
00196 return ((int)ap->info.tag - (int)bp->info.tag);
00197 }
00198
00203 static
00204 void headerSort(Header h)
00205
00206 {
00207 if (!(h->flags & HEADERFLAG_SORTED)) {
00208 qsort(h->index, h->indexUsed, sizeof(*h->index), indexCmp);
00209 h->flags |= HEADERFLAG_SORTED;
00210 }
00211 }
00212
00215 static int offsetCmp(const void * avp, const void * bvp)
00216 {
00217
00218 indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp;
00219
00220 int rc = ((int)ap->info.offset - (int)bp->info.offset);
00221
00222 if (rc == 0) {
00223
00224 if (ap->info.offset < 0)
00225 rc = (((char *)ap->data) - ((char *)bp->data));
00226 else
00227 rc = ((int)ap->info.tag - (int)bp->info.tag);
00228 }
00229 return rc;
00230 }
00231
00236 static
00237 void headerUnsort(Header h)
00238
00239 {
00240 qsort(h->index, h->indexUsed, sizeof(*h->index), offsetCmp);
00241 }
00242
00243 size_t headerSizeof(Header h)
00244 {
00245 indexEntry entry;
00246 size_t size = 0;
00247 size_t pad = 0;
00248 size_t i;
00249
00250 if (h == NULL)
00251 return size;
00252
00253 headerSort(h);
00254
00255 size += sizeof(header_magic);
00256
00257
00258 size += 2 * sizeof(uint32_t);
00259
00260
00261 for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
00262 size_t diff;
00263 rpmTagType type;
00264
00265
00266 if (ENTRY_IS_REGION(entry)) {
00267 size += entry->length;
00268
00269
00270 if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
00271 size += sizeof(struct entryInfo_s) + entry->info.count;
00272
00273 continue;
00274 }
00275
00276
00277 if (entry->info.offset < 0)
00278 continue;
00279
00280
00281 type = entry->info.type;
00282 if (typeSizes[type] > 1) {
00283 diff = typeSizes[type] - (size % typeSizes[type]);
00284 if (diff != typeSizes[type]) {
00285 size += diff;
00286 pad += diff;
00287 }
00288 }
00289
00290
00291 size += sizeof(struct entryInfo_s) + entry->length;
00292
00293 }
00294
00295 return size;
00296 }
00297
00307 static size_t dataLength(rpmTagType type, rpmTagData * p, rpmTagCount count,
00308 int onDisk, rpmTagData * pend)
00309
00310 {
00311 const unsigned char * s = (unsigned char *) (*p).ui8p;
00312 const unsigned char * se = (unsigned char *) (pend ? (*pend).ui8p : NULL);
00313 size_t length = 0;
00314
00315 switch (type) {
00316 case RPM_STRING_TYPE:
00317 if (count != 1)
00318 return 0;
00319 while (*s++ != '\0') {
00320 if (se && s > se)
00321 return 0;
00322 length++;
00323 }
00324 length++;
00325 break;
00326
00327
00328 case RPM_I18NSTRING_TYPE:
00329 case RPM_STRING_ARRAY_TYPE:
00330 if (onDisk) {
00331 while (count--) {
00332 length++;
00333 while (*s++ != '\0') {
00334 if (se && s > se)
00335 return 0;
00336 length++;
00337 }
00338 }
00339 } else {
00340 const char ** av = (*p).argv;
00341 while (count--) {
00342
00343 length += strlen(*av++) + 1;
00344 }
00345 }
00346 break;
00347 default:
00348 if (typeSizes[type] == -1)
00349 return 0;
00350 length = typeSizes[(type & 0xf)] * count;
00351 if ((se && (s + length) > se))
00352 return 0;
00353 break;
00354 }
00355
00356 return length;
00357 }
00358
00385
00386 static uint32_t regionSwab( indexEntry entry, uint32_t il, uint32_t dl,
00387 entryInfo pe,
00388 unsigned char * dataStart,
00389 const unsigned char * dataEnd,
00390 int32_t regionid)
00391
00392 {
00393 rpmTagData p;
00394 rpmTagData pend;
00395 unsigned char * tprev = NULL;
00396 unsigned char * t = NULL;
00397 size_t tdel = 0;
00398 size_t tl = dl;
00399 struct indexEntry_s ieprev;
00400
00401 memset(&ieprev, 0, sizeof(ieprev));
00402 for (; il > 0; il--, pe++) {
00403 struct indexEntry_s ie;
00404 rpmTagType type;
00405
00406 ie.info.tag = (uint32_t) ntohl(pe->tag);
00407 ie.info.type = (uint32_t) ntohl(pe->type);
00408 ie.info.count = (uint32_t) ntohl(pe->count);
00409 ie.info.offset = (int32_t) ntohl(pe->offset);
00410 assert(ie.info.offset >= 0);
00411
00412 if (hdrchkType(ie.info.type))
00413 return 0;
00414 if (hdrchkData(ie.info.count))
00415 return 0;
00416 if (hdrchkData(ie.info.offset))
00417 return 0;
00418 if (hdrchkAlign(ie.info.type, ie.info.offset))
00419 return 0;
00420
00421 ie.data = t = dataStart + ie.info.offset;
00422 if (dataEnd && t >= dataEnd)
00423 return 0;
00424
00425 p.ptr = ie.data;
00426 pend.ui8p = (uint8_t *) dataEnd;
00427
00428 ie.length = dataLength(ie.info.type, &p, ie.info.count, 1, &pend);
00429
00430 if (ie.length == 0 || hdrchkData(ie.length))
00431 return 0;
00432
00433 ie.rdlen = 0;
00434
00435 if (entry) {
00436 ie.info.offset = regionid;
00437
00438 *entry = ie;
00439
00440 entry++;
00441 }
00442
00443
00444 type = ie.info.type;
00445 if (typeSizes[type] > 1) {
00446 size_t diff = typeSizes[type] - (dl % typeSizes[type]);
00447 if (diff != typeSizes[type]) {
00448 dl += diff;
00449 if (ieprev.info.type == RPM_I18NSTRING_TYPE)
00450 ieprev.length += diff;
00451 }
00452 }
00453 tdel = (tprev ? (t - tprev) : 0);
00454 if (ieprev.info.type == RPM_I18NSTRING_TYPE)
00455 tdel = ieprev.length;
00456
00457 if (ie.info.tag >= HEADER_I18NTABLE) {
00458 tprev = t;
00459 } else {
00460 tprev = dataStart;
00461
00462
00463 if (ie.info.tag == HEADER_IMAGE)
00464 tprev -= REGION_TAG_COUNT;
00465
00466 }
00467
00468
00469 switch (ntohl(pe->type)) {
00470 case RPM_UINT64_TYPE:
00471 { uint64_t * it = (uint64_t *)t;
00472 uint32_t b[2];
00473 for (; ie.info.count > 0; ie.info.count--, it += 1) {
00474 if (dataEnd && ((unsigned char *)it) >= dataEnd)
00475 return 0;
00476 b[1] = (uint32_t) htonl(((uint32_t *)it)[0]);
00477 b[0] = (uint32_t) htonl(((uint32_t *)it)[1]);
00478 if (b[1] != ((uint32_t *)it)[0])
00479 memcpy(it, b, sizeof(b));
00480 }
00481 t = (unsigned char *) it;
00482 } break;
00483 case RPM_UINT32_TYPE:
00484 { uint32_t * it = (uint32_t *)t;
00485 for (; ie.info.count > 0; ie.info.count--, it += 1) {
00486 if (dataEnd && ((unsigned char *)it) >= dataEnd)
00487 return 0;
00488 *it = (uint32_t) htonl(*it);
00489 }
00490 t = (unsigned char *) it;
00491 } break;
00492 case RPM_UINT16_TYPE:
00493 { uint16_t * it = (uint16_t *) t;
00494 for (; ie.info.count > 0; ie.info.count--, it += 1) {
00495 if (dataEnd && ((unsigned char *)it) >= dataEnd)
00496 return 0;
00497 *it = (uint16_t) htons(*it);
00498 }
00499 t = (unsigned char *) it;
00500 } break;
00501 default:
00502 t += ie.length;
00503 break;
00504 }
00505
00506 dl += ie.length;
00507 if (dataEnd && (dataStart + dl) > dataEnd) return 0;
00508 tl += tdel;
00509 ieprev = ie;
00510
00511 }
00512 tdel = (tprev ? (t - tprev) : 0);
00513 tl += tdel;
00514
00515
00516
00517
00518
00519
00520
00521 if (tl+REGION_TAG_COUNT == dl)
00522 tl += REGION_TAG_COUNT;
00523
00524
00525 return dl;
00526 }
00527
00528
00529 void * headerUnload(Header h, size_t * lenp)
00530 {
00531 void * sw;
00532 uint32_t * ei = NULL;
00533 entryInfo pe;
00534 unsigned char * dataStart;
00535 unsigned char * te;
00536 unsigned pad;
00537 size_t len = 0;
00538 uint32_t il = 0;
00539 uint32_t dl = 0;
00540 indexEntry entry;
00541 rpmTagType type;
00542 size_t i;
00543 size_t drlen;
00544 size_t ndribbles;
00545 size_t driplen;
00546 size_t ndrips;
00547 int legacy = 0;
00548
00549 if ((sw = headerGetStats(h, 18)) != NULL)
00550 (void) rpmswEnter(sw, 0);
00551
00552
00553 headerUnsort(h);
00554
00555
00556 pad = 0;
00557 drlen = ndribbles = driplen = ndrips = 0;
00558 for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
00559 if (ENTRY_IS_REGION(entry)) {
00560 uint32_t rdl;
00561 uint32_t ril;
00562 int32_t rid;
00563
00564 assert(entry->info.offset <= 0);
00565 rdl = -entry->info.offset;
00566 ril = rdl/sizeof(*pe);
00567 rid = entry->info.offset;
00568
00569 il += ril;
00570 dl += entry->rdlen + entry->info.count;
00571
00572 if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
00573 il += 1;
00574
00575
00576 for (; i < h->indexUsed && entry->info.offset <= rid+1; i++, entry++) {
00577 if (entry->info.offset <= rid)
00578 continue;
00579
00580
00581 type = entry->info.type;
00582 if (typeSizes[type] > 1) {
00583 size_t diff = typeSizes[type] - (dl % typeSizes[type]);
00584 if (diff != typeSizes[type]) {
00585 drlen += diff;
00586 pad += diff;
00587 dl += diff;
00588 }
00589 }
00590
00591 ndribbles++;
00592 il++;
00593 drlen += entry->length;
00594 dl += entry->length;
00595 }
00596 i--;
00597 entry--;
00598 continue;
00599 }
00600
00601
00602 if (entry->data == NULL || entry->length == 0)
00603 continue;
00604
00605
00606 type = entry->info.type;
00607 if (typeSizes[type] > 1) {
00608 size_t diff = typeSizes[type] - (dl % typeSizes[type]);
00609 if (diff != typeSizes[type]) {
00610 driplen += diff;
00611 pad += diff;
00612 dl += diff;
00613 } else
00614 diff = 0;
00615 }
00616
00617 ndrips++;
00618 il++;
00619 driplen += entry->length;
00620 dl += entry->length;
00621 }
00622
00623
00624 if (hdrchkTags(il) || hdrchkData(dl))
00625 goto errxit;
00626
00627 len = sizeof(il) + sizeof(dl) + (il * sizeof(*pe)) + dl;
00628
00629 ei = xmalloc(len);
00630 ei[0] = (uint32_t) htonl(il);
00631 ei[1] = (uint32_t) htonl(dl);
00632
00633 pe = (entryInfo) &ei[2];
00634 dataStart = te = (unsigned char *) (pe + il);
00635
00636 pad = 0;
00637 for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) {
00638 const char * src;
00639 unsigned char *t;
00640 uint32_t count;
00641 uint32_t rdlen;
00642
00643 if (entry->data == NULL || entry->length == 0)
00644 continue;
00645
00646 t = te;
00647 pe->tag = (uint32_t) htonl(entry->info.tag);
00648 pe->type = (uint32_t) htonl(entry->info.type);
00649 pe->count = (uint32_t) htonl(entry->info.count);
00650
00651 if (ENTRY_IS_REGION(entry)) {
00652 uint32_t rdl;
00653 uint32_t ril;
00654 int32_t rid;
00655
00656 assert(entry->info.offset <= 0);
00657
00658 rdl = -entry->info.offset;
00659 ril = rdl/sizeof(*pe) + ndribbles;
00660 rid = entry->info.offset;
00661
00662 src = (char *)entry->data;
00663 rdlen = entry->rdlen;
00664
00665
00666 if (i == 0 && (h->flags & HEADERFLAG_LEGACY)) {
00667 uint32_t stei[4];
00668
00669 legacy = 1;
00670 memcpy(pe+1, src, rdl);
00671 memcpy(te, src + rdl, rdlen);
00672 te += rdlen;
00673
00674 pe->offset = (int32_t) htonl(te - dataStart);
00675 stei[0] = (uint32_t) pe->tag;
00676 stei[1] = (uint32_t) pe->type;
00677 stei[2] = (uint32_t) htonl(-rdl-entry->info.count);
00678 stei[3] = (uint32_t) pe->count;
00679 memcpy(te, stei, entry->info.count);
00680 te += entry->info.count;
00681 ril++;
00682 rdlen += entry->info.count;
00683
00684 count = regionSwab(NULL, ril, 0, pe, t, NULL, 0);
00685 if (count != rdlen)
00686 goto errxit;
00687
00688 } else {
00689
00690 memcpy(pe+1, src + sizeof(*pe), ((ril-1) * sizeof(*pe)));
00691 memcpy(te, src + (ril * sizeof(*pe)), rdlen+entry->info.count+drlen);
00692 te += rdlen;
00693 {
00694 entryInfo se = (entryInfo)src;
00695
00696 int32_t off = (int32_t) ntohl(se->offset);
00697 pe->offset = (int32_t)((off)
00698 ? htonl(te - dataStart) : htonl(off));
00699 }
00700 te += entry->info.count + drlen;
00701
00702 count = regionSwab(NULL, ril, 0, pe, t, NULL, 0);
00703 if (count != (rdlen + entry->info.count + drlen))
00704 goto errxit;
00705 }
00706
00707
00708 while (i < h->indexUsed && entry->info.offset <= rid+1) {
00709 i++;
00710 entry++;
00711 }
00712 i--;
00713 entry--;
00714 pe += ril;
00715 continue;
00716 }
00717
00718
00719 if (entry->data == NULL || entry->length == 0)
00720 continue;
00721
00722
00723 type = entry->info.type;
00724 if (typeSizes[type] > 1) {
00725 unsigned diff;
00726 diff = typeSizes[type] - ((te - dataStart) % typeSizes[type]);
00727 if (diff != typeSizes[type]) {
00728 memset(te, 0, diff);
00729 te += diff;
00730 pad += diff;
00731 }
00732 }
00733
00734 pe->offset = (int32_t) htonl(te - dataStart);
00735
00736
00737 switch (entry->info.type) {
00738 case RPM_UINT64_TYPE:
00739 { uint32_t b[2];
00740 count = entry->info.count;
00741 src = entry->data;
00742 while (count--) {
00743 b[1] = (uint32_t) htonl(((uint32_t *)src)[0]);
00744 b[0] = (uint32_t) htonl(((uint32_t *)src)[1]);
00745 if (b[1] == ((uint32_t *)src)[0])
00746 memcpy(te, src, sizeof(b));
00747 else
00748 memcpy(te, b, sizeof(b));
00749 te += sizeof(b);
00750 src += sizeof(b);
00751 }
00752 } break;
00753
00754 case RPM_UINT32_TYPE:
00755 count = entry->info.count;
00756 src = entry->data;
00757 while (count--) {
00758 *((uint32_t *)te) = (uint32_t) htonl(*((uint32_t *)src));
00759
00760 te += sizeof(uint32_t);
00761 src += sizeof(uint32_t);
00762
00763 }
00764 break;
00765
00766 case RPM_UINT16_TYPE:
00767 count = entry->info.count;
00768 src = entry->data;
00769 while (count--) {
00770 *((uint16_t *)te) = (uint16_t) htons(*((uint16_t *)src));
00771
00772 te += sizeof(uint16_t);
00773 src += sizeof(uint16_t);
00774
00775 }
00776 break;
00777
00778 default:
00779 memcpy(te, entry->data, entry->length);
00780 te += entry->length;
00781 break;
00782 }
00783 pe++;
00784 }
00785
00786
00787 if (((unsigned char *)pe) != dataStart)
00788 goto errxit;
00789 if ((((unsigned char *)ei)+len) != te)
00790 goto errxit;
00791
00792 if (lenp)
00793 *lenp = len;
00794
00795 h->flags &= ~HEADERFLAG_SORTED;
00796 headerSort(h);
00797
00798 if (sw != NULL) (void) rpmswExit(sw, len);
00799
00800 return (void *) ei;
00801
00802 errxit:
00803 if (sw != NULL) (void) rpmswExit(sw, len);
00804
00805 ei = _free(ei);
00806
00807 return (void *) ei;
00808 }
00809
00817 static
00818 indexEntry findEntry( Header h, rpmTag tag, rpmTagType type)
00819
00820 {
00821 indexEntry entry, entry2, last;
00822 struct indexEntry_s key;
00823
00824 if (h == NULL) return NULL;
00825 if (!(h->flags & HEADERFLAG_SORTED)) headerSort(h);
00826
00827 key.info.tag = tag;
00828
00829 entry2 = entry =
00830 bsearch(&key, h->index, h->indexUsed, sizeof(*h->index), indexCmp);
00831 if (entry == NULL)
00832 return NULL;
00833
00834 if (type == 0)
00835 return entry;
00836
00837
00838 while (entry->info.tag == tag && entry->info.type != type &&
00839 entry > h->index) entry--;
00840
00841 if (entry->info.tag == tag && entry->info.type == type)
00842 return entry;
00843
00844 last = h->index + h->indexUsed;
00845
00846 while (entry2->info.tag == tag && entry2->info.type != type &&
00847 entry2 < last) entry2++;
00848
00849
00850 if (entry->info.tag == tag && entry->info.type == type)
00851 return entry;
00852
00853 return NULL;
00854 }
00855
00865 static
00866 int headerRemoveEntry(Header h, rpmTag tag)
00867
00868 {
00869 indexEntry last = h->index + h->indexUsed;
00870 indexEntry entry, first;
00871 int ne;
00872
00873 entry = findEntry(h, tag, 0);
00874 if (!entry) return 1;
00875
00876
00877 while (entry > h->index && (entry - 1)->info.tag == tag)
00878 entry--;
00879
00880
00881 for (first = entry; first < last; first++) {
00882 void * data;
00883 if (first->info.tag != tag)
00884 break;
00885 data = first->data;
00886 first->data = NULL;
00887 first->length = 0;
00888 if (ENTRY_IN_REGION(first))
00889 continue;
00890 data = _free(data);
00891 }
00892
00893 ne = (first - entry);
00894 if (ne > 0) {
00895 h->indexUsed -= ne;
00896 ne = last - first;
00897 if (ne > 0)
00898 memmove(entry, first, (ne * sizeof(*entry)));
00899 }
00900
00901 return 0;
00902 }
00903
00904 Header headerLoad(void * uh)
00905 {
00906 void * sw = NULL;
00907 uint32_t * ei = (uint32_t *) uh;
00908 uint32_t il = (uint32_t) ntohl(ei[0]);
00909 uint32_t dl = (uint32_t) ntohl(ei[1]);
00910
00911 size_t pvlen = sizeof(il) + sizeof(dl) +
00912 (il * sizeof(struct entryInfo_s)) + dl;
00913
00914 void * pv = uh;
00915 Header h = NULL;
00916 entryInfo pe;
00917 unsigned char * dataStart;
00918 unsigned char * dataEnd;
00919 indexEntry entry;
00920 uint32_t rdlen;
00921 int i;
00922
00923
00924 if (hdrchkTags(il) || hdrchkData(dl))
00925 goto errxit;
00926
00927 ei = (uint32_t *) pv;
00928
00929 pe = (entryInfo) &ei[2];
00930
00931 dataStart = (unsigned char *) (pe + il);
00932 dataEnd = dataStart + dl;
00933
00934 h = xcalloc(1, sizeof(*h));
00935 if ((sw = headerGetStats(h, 18)) != NULL)
00936 (void) rpmswEnter(sw, 0);
00937 { unsigned char * hmagic = header_magic;
00938 (void) memcpy(h->magic, hmagic, sizeof(h->magic));
00939 }
00940
00941 h->blob = uh;
00942
00943 h->indexAlloced = il + 1;
00944 h->indexUsed = il;
00945 h->index = xcalloc(h->indexAlloced, sizeof(*h->index));
00946 h->flags |= HEADERFLAG_SORTED;
00947 h->nrefs = 0;
00948 h = headerLink(h);
00949
00950 entry = h->index;
00951 i = 0;
00952 if (!(htonl(pe->tag) < HEADER_I18NTABLE)) {
00953 h->flags |= HEADERFLAG_LEGACY;
00954 entry->info.type = REGION_TAG_TYPE;
00955 entry->info.tag = HEADER_IMAGE;
00956
00957 entry->info.count = REGION_TAG_COUNT;
00958
00959 entry->info.offset = ((unsigned char *)pe - dataStart);
00960
00961
00962 entry->data = pe;
00963
00964 entry->length = pvlen - sizeof(il) - sizeof(dl);
00965 rdlen = regionSwab(entry+1, il, 0, pe, dataStart, dataEnd, entry->info.offset);
00966 #if 0
00967 if (rdlen != dl)
00968 goto errxit;
00969 #endif
00970 entry->rdlen = rdlen;
00971 entry++;
00972 h->indexUsed++;
00973 } else {
00974 uint32_t rdl;
00975 uint32_t ril;
00976
00977 h->flags &= ~HEADERFLAG_LEGACY;
00978
00979 entry->info.type = (uint32_t) htonl(pe->type);
00980 entry->info.count = (uint32_t) htonl(pe->count);
00981
00982 if (hdrchkType(entry->info.type))
00983 goto errxit;
00984 if (hdrchkTags(entry->info.count))
00985 goto errxit;
00986
00987 { int32_t off = (int32_t) ntohl(pe->offset);
00988
00989 if (hdrchkData(off))
00990 goto errxit;
00991 if (off) {
00992
00993 size_t nb = REGION_TAG_COUNT;
00994
00995 uint32_t * stei = memcpy(alloca(nb), dataStart + off, nb);
00996 rdl = -ntohl(stei[2]);
00997 assert((int32_t)rdl >= 0);
00998 ril = rdl/sizeof(*pe);
00999 if (hdrchkTags(ril) || hdrchkData(rdl))
01000 goto errxit;
01001 entry->info.tag = (uint32_t) htonl(pe->tag);
01002 } else {
01003 ril = il;
01004
01005 rdl = (ril * sizeof(struct entryInfo_s));
01006
01007 entry->info.tag = HEADER_IMAGE;
01008 }
01009 }
01010 entry->info.offset = (int32_t) -rdl;
01011
01012
01013 entry->data = pe;
01014
01015 entry->length = pvlen - sizeof(il) - sizeof(dl);
01016 rdlen = regionSwab(entry+1, (ril-1), 0, pe+1, dataStart, dataEnd, entry->info.offset);
01017 if (rdlen == 0)
01018 goto errxit;
01019 entry->rdlen = rdlen;
01020
01021 if (ril < h->indexUsed) {
01022 indexEntry newEntry = entry + ril;
01023 size_t ne = (h->indexUsed - ril);
01024 int32_t rid = entry->info.offset+1;
01025 uint32_t rc;
01026
01027
01028 rc = regionSwab(newEntry, ne, 0, pe+ril, dataStart, dataEnd, rid);
01029 if (rc == 0)
01030 goto errxit;
01031 rdlen += rc;
01032
01033 { indexEntry firstEntry = newEntry;
01034 size_t save = h->indexUsed;
01035 size_t j;
01036
01037
01038 h->indexUsed -= ne;
01039 for (j = 0; j < ne; j++, newEntry++) {
01040 (void) headerRemoveEntry(h, newEntry->info.tag);
01041 if (newEntry->info.tag == HEADER_BASENAMES)
01042 (void) headerRemoveEntry(h, HEADER_OLDFILENAMES);
01043 }
01044
01045
01046 if (h->indexUsed < (save - ne)) {
01047 memmove(h->index + h->indexUsed, firstEntry,
01048 (ne * sizeof(*entry)));
01049 }
01050 h->indexUsed += ne;
01051 }
01052 }
01053 }
01054
01055 h->flags &= ~HEADERFLAG_SORTED;
01056 headerSort(h);
01057
01058 if (sw != NULL) (void) rpmswExit(sw, pvlen);
01059
01060
01061 return h;
01062
01063
01064 errxit:
01065 if (sw != NULL) (void) rpmswExit(sw, pvlen);
01066
01067 if (h) {
01068 h->index = _free(h->index);
01069
01070 h = _free(h);
01071
01072 }
01073
01074
01075 return h;
01076
01077 }
01078
01079 int headerGetMagic(Header h, unsigned char ** magicp, size_t * nmagicp)
01080 {
01081 unsigned char * hmagic = header_magic;
01082 if (magicp)
01083 *magicp = (h ? h->magic : hmagic);
01084 if (nmagicp)
01085 *nmagicp = (h ? sizeof(h->magic) : sizeof(header_magic));
01086 return 0;
01087 }
01088
01089 int headerSetMagic(Header h, unsigned char * magic, size_t nmagic)
01090 {
01091 if (nmagic > sizeof(h->magic))
01092 nmagic = sizeof(h->magic);
01093 if (h) {
01094 memset(h->magic, 0, sizeof(h->magic));
01095 if (nmagic > 0)
01096 memmove(h->magic, magic, nmagic);
01097 }
01098 return 0;
01099 }
01100
01101 const char * headerGetOrigin(Header h)
01102 {
01103 return (h != NULL ? h->origin : NULL);
01104 }
01105
01106 int headerSetOrigin(Header h, const char * origin)
01107 {
01108 if (h != NULL) {
01109 h->origin = _free(h->origin);
01110 h->origin = xstrdup(origin);
01111 }
01112 return 0;
01113 }
01114
01115 uint32_t headerGetInstance(Header h)
01116 {
01117 return (h != NULL ? h->instance : 0);
01118 }
01119
01120 uint32_t headerSetInstance(Header h, uint32_t instance)
01121 {
01122 if (h != NULL)
01123 h->instance = instance;
01124 return 0;
01125 }
01126
01127 Header headerReload(Header h, int tag)
01128 {
01129 Header nh;
01130 void * uh;
01131 const char * origin = (h->origin != NULL ? xstrdup(h->origin) : NULL);
01132 uint32_t instance = h->instance;
01133 int xx;
01134
01135
01136 uh = headerUnload(h, NULL);
01137 h = headerFree(h);
01138
01139 if (uh == NULL)
01140 return NULL;
01141 nh = headerLoad(uh);
01142 if (nh == NULL) {
01143 uh = _free(uh);
01144 return NULL;
01145 }
01146 if (nh->flags & HEADERFLAG_ALLOCATED)
01147 uh = _free(uh);
01148 nh->flags |= HEADERFLAG_ALLOCATED;
01149 if (ENTRY_IS_REGION(nh->index)) {
01150 if (tag == HEADER_SIGNATURES || tag == HEADER_IMMUTABLE)
01151 nh->index[0].info.tag = tag;
01152 }
01153 if (origin != NULL) {
01154 xx = headerSetOrigin(nh, origin);
01155 origin = _free(origin);
01156 }
01157 xx = (int) headerSetInstance(nh, instance);
01158 return nh;
01159 }
01160
01161 Header headerCopyLoad(const void * uh)
01162 {
01163 uint32_t * ei = (uint32_t *) uh;
01164 uint32_t il = (uint32_t) ntohl(ei[0]);
01165 uint32_t dl = (uint32_t) ntohl(ei[1]);
01166
01167 size_t pvlen = sizeof(il) + sizeof(dl) +
01168 (il * sizeof(struct entryInfo_s)) + dl;
01169
01170 void * nuh = NULL;
01171 Header h = NULL;
01172
01173
01174 if (!(hdrchkTags(il) || hdrchkData(dl)) && pvlen < headerMaxbytes) {
01175 nuh = memcpy(xmalloc(pvlen), uh, pvlen);
01176 if ((h = headerLoad(nuh)) != NULL)
01177 h->flags |= HEADERFLAG_ALLOCATED;
01178 }
01179 if (h == NULL)
01180 nuh = _free(nuh);
01181 return h;
01182 }
01183
01184 int headerIsEntry(Header h, rpmTag tag)
01185 {
01186
01187 return (findEntry(h, tag, 0) ? 1 : 0);
01188
01189 }
01190
01199 static int copyEntry(const indexEntry entry, HE_t he, int minMem)
01200
01201 {
01202 rpmTagCount count = entry->info.count;
01203 uint32_t rdlen;
01204 int rc = 1;
01205
01206 switch (entry->info.type) {
01207 case RPM_BIN_TYPE:
01208
01209
01210
01211
01212
01213
01214 if (ENTRY_IS_REGION(entry)) {
01215 uint32_t * ei = ((uint32_t *)entry->data) - 2;
01216
01217 entryInfo pe = (entryInfo) (ei + 2);
01218
01219 unsigned char * dataStart = (unsigned char *) (pe + ntohl(ei[0]));
01220 uint32_t rdl;
01221 uint32_t ril;
01222
01223 assert(entry->info.offset <= 0);
01224 rdl = -entry->info.offset;
01225 ril = rdl/sizeof(*pe);
01226
01227 rdl = entry->rdlen;
01228 count = 2 * sizeof(*ei) + (ril * sizeof(*pe)) + rdl;
01229 if (entry->info.tag == HEADER_IMAGE) {
01230 ril -= 1;
01231 pe += 1;
01232 } else {
01233 count += REGION_TAG_COUNT;
01234 rdl += REGION_TAG_COUNT;
01235 }
01236
01237 he->p.ui32p = ei = xmalloc(count);
01238 ei[0] = htonl(ril);
01239 ei[1] = htonl(rdl);
01240
01241
01242 pe = (entryInfo) memcpy(ei + 2, pe, (ril * sizeof(*pe)));
01243
01244
01245 dataStart = (unsigned char *) memcpy(pe + ril, dataStart, rdl);
01246
01247
01248 rdlen = regionSwab(NULL, ril, 0, pe, dataStart, NULL, 0);
01249
01250 rc = (rdlen == 0) ? 0 : 1;
01251 } else {
01252 count = entry->length;
01253 he->p.ptr = (!minMem
01254 ? memcpy(xmalloc(count), entry->data, count)
01255 : entry->data);
01256 }
01257 break;
01258 case RPM_STRING_TYPE:
01259 if (count == 1) {
01260 he->p.str = entry->data;
01261 break;
01262 }
01263
01264 case RPM_I18NSTRING_TYPE:
01265 case RPM_STRING_ARRAY_TYPE:
01266 { const char ** argv;
01267 size_t nb = count * sizeof(*argv);
01268 char * t;
01269 unsigned i;
01270
01271
01272 if (minMem) {
01273 he->p.argv = argv = xmalloc(nb);
01274 t = entry->data;
01275 } else {
01276 he->p.argv = argv = xmalloc(nb + entry->length);
01277 t = (char *) &argv[count];
01278 memcpy(t, entry->data, entry->length);
01279 }
01280
01281 for (i = 0; i < (unsigned) count; i++) {
01282 argv[i] = t;
01283 t = strchr(t, 0);
01284 t++;
01285 }
01286 } break;
01287
01288 default:
01289 he->p.ptr = entry->data;
01290 break;
01291 }
01292 he->t = entry->info.type;
01293 he->c = count;
01294 return rc;
01295 }
01296
01315 static int headerMatchLocale(const char *td, const char *l, const char *le)
01316
01317 {
01318 const char *fe;
01319
01320
01321 #if 0
01322 { const char *s, *ll, *CC, *EE, *dd;
01323 char *lbuf, *t.
01324
01325
01326 lbuf = alloca(le - l + 1);
01327 for (s = l, ll = t = lbuf; *s; s++, t++) {
01328 switch (*s) {
01329 case '_':
01330 *t = '\0';
01331 CC = t + 1;
01332 break;
01333 case '.':
01334 *t = '\0';
01335 EE = t + 1;
01336 break;
01337 case '@':
01338 *t = '\0';
01339 dd = t + 1;
01340 break;
01341 default:
01342 *t = *s;
01343 break;
01344 }
01345 }
01346
01347 if (ll)
01348 for (t = ll; *t; t++) *t = tolower(*t);
01349 if (CC)
01350 for (t = CC; *t; t++) *t = toupper(*t);
01351
01352
01353 }
01354 #endif
01355
01356
01357 if (strlen(td) == (le-l) && !strncmp(td, l, (le - l)))
01358 return 1;
01359
01360
01361 for (fe = l; fe < le && *fe != '@'; fe++)
01362 {};
01363 if (fe < le && !strncmp(td, l, (fe - l)))
01364 return 1;
01365
01366
01367 for (fe = l; fe < le && *fe != '.'; fe++)
01368 {};
01369 if (fe < le && !strncmp(td, l, (fe - l)))
01370 return 1;
01371
01372
01373 for (fe = l; fe < le && *fe != '_'; fe++)
01374 {};
01375 if (fe < le && !strncmp(td, l, (fe - l)))
01376 return 1;
01377
01378 return 0;
01379 }
01380
01387 static char *
01388 headerFindI18NString(Header h, indexEntry entry)
01389
01390 {
01391 const char *lang, *l, *le;
01392 indexEntry table;
01393
01394
01395 if ((lang = getenv("LANGUAGE")) == NULL &&
01396 (lang = getenv("LC_ALL")) == NULL &&
01397 (lang = getenv("LC_MESSAGES")) == NULL &&
01398 (lang = getenv("LANG")) == NULL)
01399 return entry->data;
01400
01401
01402 if ((table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE)) == NULL)
01403 return entry->data;
01404
01405
01406 for (l = lang; *l != '\0'; l = le) {
01407 const char *td;
01408 char *ed;
01409 uint32_t langNum;
01410
01411 while (*l && *l == ':')
01412 l++;
01413 if (*l == '\0')
01414 break;
01415 for (le = l; *le && *le != ':'; le++)
01416 {};
01417
01418
01419 for (langNum = 0, td = table->data, ed = entry->data;
01420 langNum < entry->info.count;
01421 langNum++, td += strlen(td) + 1, ed += strlen(ed) + 1) {
01422
01423 if (headerMatchLocale(td, l, le))
01424 return ed;
01425
01426 }
01427 }
01428
01429 return entry->data;
01430 }
01431
01439 static int intGetEntry(Header h, HE_t he, int flags)
01440
01441 {
01442 int minMem = 0;
01443 indexEntry entry;
01444 int rc;
01445
01446
01447
01448 entry = findEntry(h, he->tag, 0);
01449
01450 if (entry == NULL) {
01451 he->t = 0;
01452 he->p.ptr = NULL;
01453 he->c = 0;
01454 return 0;
01455 }
01456
01457 switch (entry->info.type) {
01458 case RPM_I18NSTRING_TYPE:
01459 if (!(flags & HEADERGET_NOI18NSTRING)) {
01460 rc = 1;
01461 he->t = RPM_STRING_TYPE;
01462 he->c = 1;
01463
01464 he->p.str = headerFindI18NString(h, entry);
01465
01466 break;
01467 }
01468
01469 default:
01470 rc = copyEntry(entry, he, minMem);
01471 break;
01472 }
01473
01474
01475 return ((rc == 1) ? 1 : 0);
01476 }
01477
01480 static void copyData(rpmTagType type, rpmTagData * dest, rpmTagData * src,
01481 rpmTagCount cnt, size_t len)
01482
01483 {
01484 switch (type) {
01485 case RPM_I18NSTRING_TYPE:
01486 case RPM_STRING_ARRAY_TYPE:
01487 { const char ** av = (*src).argv;
01488 char * t = (char *) (*dest).str;
01489
01490 while (cnt-- > 0 && len > 0) {
01491 const char * s;
01492 if ((s = *av++) == NULL)
01493 continue;
01494 do {
01495 *t++ = *s++;
01496 } while (s[-1] && --len > 0);
01497 }
01498 } break;
01499 default:
01500 memmove((*dest).ptr, (*src).ptr, len);
01501 break;
01502 }
01503 }
01504
01513
01514 static void *
01515 grabData(rpmTagType type, rpmTagData * p, rpmTagCount c, size_t * lenp)
01516
01517
01518 {
01519 rpmTagData data = { .ptr = NULL };
01520 size_t length;
01521
01522 length = dataLength(type, p, c, 0, NULL);
01523 if (length > 0) {
01524 data.ptr = xmalloc(length);
01525 copyData(type, &data, p, c, length);
01526 }
01527
01528 if (lenp)
01529 *lenp = length;
01530 return data.ptr;
01531 }
01532
01544 static
01545 int headerAddEntry(Header h, HE_t he)
01546
01547 {
01548 indexEntry entry;
01549 rpmTagData q = { .ptr = he->p.ptr };
01550 rpmTagData data;
01551 size_t length;
01552
01553
01554 if (he->c == 0)
01555 return 0;
01556
01557 if (hdrchkType(he->t))
01558 return 0;
01559 if (hdrchkData(he->c))
01560 return 0;
01561
01562 length = 0;
01563 data.ptr = grabData(he->t, &q, he->c, &length);
01564 if (data.ptr == NULL || length == 0)
01565 return 0;
01566
01567
01568 if (h->indexUsed == h->indexAlloced) {
01569 h->indexAlloced += INDEX_MALLOC_SIZE;
01570 h->index = xrealloc(h->index, h->indexAlloced * sizeof(*h->index));
01571 }
01572
01573
01574 entry = h->index + h->indexUsed;
01575 entry->info.tag = he->tag;
01576 entry->info.type = he->t;
01577 entry->info.count = he->c;
01578 entry->info.offset = 0;
01579 entry->data = data.ptr;
01580 entry->length = length;
01581
01582 if (h->indexUsed > 0 && he->tag < h->index[h->indexUsed-1].info.tag)
01583 h->flags &= ~HEADERFLAG_SORTED;
01584 h->indexUsed++;
01585
01586 return 1;
01587 }
01588
01598 static
01599 int headerAppendEntry(Header h, HE_t he)
01600
01601 {
01602 rpmTagData src = { .ptr = he->p.ptr };
01603 rpmTagData dest = { .ptr = NULL };
01604 indexEntry entry;
01605 size_t length;
01606
01607 if (he->t == RPM_STRING_TYPE || he->t == RPM_I18NSTRING_TYPE) {
01608
01609 return 0;
01610 }
01611
01612
01613 entry = findEntry(h, he->tag, he->t);
01614 if (!entry)
01615 return 0;
01616
01617 length = dataLength(he->t, &src, he->c, 0, NULL);
01618 if (length == 0)
01619 return 0;
01620
01621 if (ENTRY_IN_REGION(entry)) {
01622 char * t = xmalloc(entry->length + length);
01623 memcpy(t, entry->data, entry->length);
01624 entry->data = t;
01625 entry->info.offset = 0;
01626 } else
01627 entry->data = xrealloc(entry->data, entry->length + length);
01628
01629 dest.ptr = ((char *) entry->data) + entry->length;
01630 copyData(he->t, &dest, &src, he->c, length);
01631
01632 entry->length += length;
01633
01634 entry->info.count += he->c;
01635
01636 return 1;
01637 }
01638
01645 static
01646 int headerAddOrAppendEntry(Header h, HE_t he)
01647
01648 {
01649 return (findEntry(h, he->tag, he->t)
01650 ? headerAppendEntry(h, he)
01651 : headerAddEntry(h, he));
01652 }
01653
01654 int headerAddI18NString(Header h, rpmTag tag, const char * string,
01655 const char * lang)
01656 {
01657 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01658 indexEntry table, entry;
01659 rpmTagData p;
01660 size_t length;
01661 size_t ghosts;
01662 uint32_t i;
01663 uint32_t langNum;
01664 char * buf;
01665 int xx;
01666
01667 table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE);
01668 entry = findEntry(h, tag, RPM_I18NSTRING_TYPE);
01669
01670 if (!table && entry)
01671 return 0;
01672
01673 if (!table && !entry) {
01674 const char * argv[2];
01675 int count = 0;
01676 p.argv = argv;
01677 if (!lang || (lang[0] == 'C' && lang[1] == '\0')) {
01678
01679 p.argv[count++] = "C";
01680
01681 } else {
01682
01683 p.argv[count++] = "C";
01684
01685 p.argv[count++] = lang;
01686 }
01687 he->tag = HEADER_I18NTABLE;
01688 he->t = RPM_STRING_ARRAY_TYPE;
01689 he->p.ptr = p.ptr;
01690 he->c = count;
01691 xx = headerAddEntry(h, he);
01692 if (!xx)
01693 return 0;
01694 table = findEntry(h, he->tag, he->t);
01695 }
01696
01697 if (!table)
01698 return 0;
01699 if (!lang) lang = "C";
01700
01701 { const char * l = table->data;
01702 for (langNum = 0; langNum < table->info.count; langNum++) {
01703 if (!strcmp(l, lang)) break;
01704 l += strlen(l) + 1;
01705 }
01706 }
01707
01708 if (langNum >= table->info.count) {
01709 length = strlen(lang) + 1;
01710 if (ENTRY_IN_REGION(table)) {
01711 char * t = xmalloc(table->length + length);
01712 memcpy(t, table->data, table->length);
01713 table->data = t;
01714 table->info.offset = 0;
01715 } else
01716 table->data = xrealloc(table->data, table->length + length);
01717 memmove(((char *)table->data) + table->length, lang, length);
01718 table->length += length;
01719 table->info.count++;
01720 }
01721
01722 if (!entry) {
01723 p.argv = alloca(sizeof(*p.argv) * (langNum + 1));
01724
01725 for (i = 0; i < langNum; i++)
01726 p.argv[i] = "";
01727
01728 p.argv[langNum] = string;
01729 he->tag = tag;
01730 he->t = RPM_I18NSTRING_TYPE;
01731 he->p.ptr = p.ptr;
01732 he->c = langNum + 1;
01733
01734 xx = headerAddEntry(h, he);
01735
01736 return xx;
01737 } else if (langNum >= entry->info.count) {
01738 ghosts = langNum - entry->info.count;
01739
01740 length = strlen(string) + 1 + ghosts;
01741 if (ENTRY_IN_REGION(entry)) {
01742 char * t = xmalloc(entry->length + length);
01743 memcpy(t, entry->data, entry->length);
01744 entry->data = t;
01745 entry->info.offset = 0;
01746 } else
01747 entry->data = xrealloc(entry->data, entry->length + length);
01748
01749 memset(((char *)entry->data) + entry->length, 0, ghosts);
01750 memmove(((char *)entry->data) + entry->length + ghosts, string, strlen(string)+1);
01751
01752 entry->length += length;
01753 entry->info.count = langNum + 1;
01754 } else {
01755 char *b, *be, *e, *ee, *t;
01756 size_t bn, sn, en;
01757
01758
01759 b = be = e = ee = entry->data;
01760 for (i = 0; i < table->info.count; i++) {
01761 if (i == langNum)
01762 be = ee;
01763 ee += strlen(ee) + 1;
01764 if (i == langNum)
01765 e = ee;
01766 }
01767
01768
01769 bn = (be-b);
01770 sn = strlen(string) + 1;
01771 en = (ee-e);
01772 length = bn + sn + en;
01773 t = buf = xmalloc(length);
01774
01775
01776 memcpy(t, b, bn);
01777 t += bn;
01778
01779 memcpy(t, string, sn);
01780 t += sn;
01781 memcpy(t, e, en);
01782 t += en;
01783
01784
01785
01786 entry->length -= strlen(be) + 1;
01787 entry->length += sn;
01788
01789 if (ENTRY_IN_REGION(entry)) {
01790 entry->info.offset = 0;
01791 } else
01792 entry->data = _free(entry->data);
01793
01794 entry->data = buf;
01795
01796 }
01797
01798 return 0;
01799 }
01800
01808 static
01809 int headerModifyEntry(Header h, HE_t he)
01810
01811 {
01812 indexEntry entry;
01813 rpmTagData q = { .ptr = he->p.ptr };
01814 rpmTagData oldData;
01815 rpmTagData newData;
01816 size_t length;
01817
01818
01819 entry = findEntry(h, he->tag, he->t);
01820 if (!entry)
01821 return 0;
01822
01823 length = 0;
01824 newData.ptr = grabData(he->t, &q, he->c, &length);
01825 if (newData.ptr == NULL || length == 0)
01826 return 0;
01827
01828
01829 while (entry > h->index && (entry - 1)->info.tag == he->tag)
01830 entry--;
01831
01832
01833
01834 oldData.ptr = entry->data;
01835
01836 entry->info.count = he->c;
01837 entry->info.type = he->t;
01838 entry->data = newData.ptr;
01839 entry->length = length;
01840
01841 if (ENTRY_IN_REGION(entry)) {
01842 entry->info.offset = 0;
01843 } else
01844 oldData.ptr = _free(oldData.ptr);
01845
01846 return 1;
01847 }
01848
01854 static int rpmheRealloc(HE_t he)
01855
01856 {
01857 size_t nb = 0;
01858 int rc = 1;
01859
01860 switch (he->t) {
01861 default:
01862 assert(0);
01863 break;
01864 case RPM_BIN_TYPE:
01865 he->freeData = 1;
01866
01867 case RPM_UINT8_TYPE:
01868 nb = he->c * sizeof(*he->p.ui8p);
01869 break;
01870 case RPM_UINT16_TYPE:
01871 nb = he->c * sizeof(*he->p.ui16p);
01872 break;
01873 case RPM_UINT32_TYPE:
01874 nb = he->c * sizeof(*he->p.ui32p);
01875 break;
01876 case RPM_UINT64_TYPE:
01877 nb = he->c * sizeof(*he->p.ui64p);
01878 break;
01879 case RPM_STRING_TYPE:
01880 if (he->p.str)
01881 nb = strlen(he->p.str) + 1;
01882 else
01883 rc = 0;
01884 break;
01885 case RPM_I18NSTRING_TYPE:
01886 case RPM_STRING_ARRAY_TYPE:
01887 break;
01888 }
01889
01890
01891 if (he->p.ptr && nb && !he->freeData) {
01892 void * ptr = memcpy(xmalloc(nb), he->p.ptr, nb);
01893 he->p.ptr = ptr;
01894 }
01895
01896 if (rc)
01897 he->freeData = 1;
01898
01899 return rc;
01900 }
01901
01905 struct headerIterator_s {
01906 Header h;
01907 size_t next_index;
01908 };
01909
01910 HeaderIterator headerFini( HeaderIterator hi)
01911 {
01912 if (hi != NULL) {
01913 hi->h = headerFree(hi->h);
01914 hi = _free(hi);
01915 }
01916 return hi;
01917 }
01918
01919 HeaderIterator headerInit(Header h)
01920 {
01921 HeaderIterator hi = xmalloc(sizeof(*hi));
01922
01923 headerSort(h);
01924
01925 hi->h = headerLink(h);
01926 hi->next_index = 0;
01927 return hi;
01928 }
01929
01930 int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
01931 {
01932 void * sw;
01933 Header h = hi->h;
01934 size_t slot = hi->next_index;
01935 indexEntry entry = NULL;
01936 int rc;
01937
01938
01939 memset(he, 0, sizeof(*he));
01940
01941 for (slot = hi->next_index; slot < h->indexUsed; slot++) {
01942 entry = h->index + slot;
01943 if (!ENTRY_IS_REGION(entry))
01944 break;
01945 }
01946 hi->next_index = slot;
01947 if (entry == NULL || slot >= h->indexUsed)
01948 return 0;
01949
01950 hi->next_index++;
01951
01952 if ((sw = headerGetStats(h, 19)) != NULL)
01953 (void) rpmswEnter(sw, 0);
01954
01955 he->tag = entry->info.tag;
01956 rc = copyEntry(entry, he, 0);
01957 if (rc)
01958 rc = rpmheRealloc(he);
01959
01960 if (sw != NULL) (void) rpmswExit(sw, 0);
01961
01962
01963 return ((rc == 1) ? 1 : 0);
01964 }
01965
01966 Header headerCopy(Header h)
01967 {
01968 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01969 Header nh = headerNew();
01970 HeaderIterator hi;
01971
01972 for (hi = headerInit(h);
01973 headerNext(hi, he, 0);
01974 he->p.ptr = _free(he->p.ptr))
01975 {
01976 if (he->p.ptr) (void) headerAddEntry(nh, he);
01977 }
01978 hi = headerFini(hi);
01979
01980 return headerReload(nh, HEADER_IMAGE);
01981 }
01982
01983 void headerCopyTags(Header headerFrom, Header headerTo, rpmTag * tagstocopy)
01984 {
01985 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01986 rpmTag * tagno;
01987 int xx;
01988
01989 if (headerFrom == headerTo)
01990 return;
01991
01992 for (tagno = tagstocopy; *tagno != 0; tagno++) {
01993 if (headerIsEntry(headerTo, *tagno))
01994 continue;
01995 he->tag = *tagno;
01996 if (!headerGet(headerFrom, he, 0))
01997 continue;
01998 xx = headerPut(headerTo, he, 0);
01999 he->p.ptr = _free(he->p.ptr);
02000 }
02001 }
02002
02003 int headerGet(Header h, HE_t he, unsigned int flags)
02004 {
02005 void * sw;
02006 const char * name;
02007 headerSprintfExtension exts = headerCompoundFormats;
02008 headerSprintfExtension ext = NULL;
02009 int extNum;
02010 int rc;
02011
02012 if (h == NULL || he == NULL) return 0;
02013
02014
02015 { rpmTag tag = he->tag;
02016 memset(he, 0, sizeof(*he));
02017 he->tag = tag;
02018 }
02019 name = tagName(he->tag);
02020
02021 if ((sw = headerGetStats(h, 19)) != NULL)
02022 (void) rpmswEnter(sw, 0);
02023
02024
02025 if (!(flags & HEADERGET_NOEXTENSION))
02026 for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST;
02027 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++)
02028 {
02029 if (ext->name == NULL || ext->type != HEADER_EXT_TAG)
02030 continue;
02031 if (!xstrcasecmp(ext->name + (sizeof("RPMTAG_")-1), name))
02032 break;
02033 }
02034
02035 if (ext && ext->name != NULL && ext->type == HEADER_EXT_TAG) {
02036 rc = ext->u.tagFunction(h, he);
02037 rc = (rc == 0);
02038 } else
02039 rc = intGetEntry(h, he, flags);
02040
02041 if (rc)
02042 rc = rpmheRealloc(he);
02043
02044 if (sw != NULL) (void) rpmswExit(sw, 0);
02045
02046 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
02047
02048
02049 if (rc)
02050 tagTypeValidate(he);
02051
02052 #endif
02053
02054
02055 if (!((rc == 0 && he->freeData == 0 && he->p.ptr == NULL) ||
02056 (rc == 1 && he->freeData == 1 && he->p.ptr != NULL)))
02057 {
02058 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);
02059 }
02060
02061
02062 return rc;
02063 }
02064
02065 int headerPut(Header h, HE_t he, unsigned int flags)
02066 {
02067 int rc;
02068
02069 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
02070
02071
02072 tagTypeValidate(he);
02073
02074 #endif
02075
02076 if (he->append)
02077 rc = headerAddOrAppendEntry(h, he);
02078 else
02079 rc = headerAddEntry(h, he);
02080
02081 return rc;
02082 }
02083
02084 int headerDel(Header h, HE_t he, unsigned int flags)
02085
02086 {
02087 return headerRemoveEntry(h, he->tag);
02088 }
02089
02090 int headerMod(Header h, HE_t he, unsigned int flags)
02091
02092 {
02093
02094 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
02095
02096
02097 tagTypeValidate(he);
02098
02099 #endif
02100
02101 return headerModifyEntry(h, he);
02102 }