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