rpm 5.3.12
|
00001 00005 /* RPM - Copyright (C) 1995-2002 Red Hat Software */ 00006 00007 /* Data written to file descriptors is in network byte order. */ 00008 /* Data read from file descriptors is expected to be in */ 00009 /* network byte order and is converted on the fly to host order. */ 00010 00011 #include "system.h" 00012 00013 #include <rpmiotypes.h> 00014 #include <rpmio.h> /* XXX for rpmioPool et al */ 00015 #define _RPMTAG_INTERNAL 00016 #include <header_internal.h> 00017 00018 #include "debug.h" 00019 00020 /*@unchecked@*/ 00021 int _hdr_debug = 0; 00022 00023 /*@access Header @*/ 00024 /*@access HeaderIterator @*/ 00025 /*@access headerSprintfExtension @*/ 00026 /*@access headerTagTableEntry @*/ 00027 00028 /*@access entryInfo @*/ 00029 /*@access indexEntry @*/ 00030 00033 /*@-type@*/ 00034 /*@observer@*/ /*@unchecked@*/ 00035 static unsigned char header_magic[8] = { 00036 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00 00037 }; 00038 /*@=type@*/ 00039 00043 /*@observer@*/ /*@unchecked@*/ 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 /*@unchecked@*/ 00067 static size_t headerMaxbytes = (1024*1024*1024); 00068 00072 /*@unchecked@*/ 00073 int _hdr_stats = 0; 00074 00075 /*@-compmempass@*/ 00076 /*@unchecked@*/ 00077 static struct rpmop_s hdr_loadops; 00078 /*@unchecked@*/ /*@relnull@*/ 00079 rpmop _hdr_loadops = &hdr_loadops; 00080 /*@unchecked@*/ 00081 static struct rpmop_s hdr_getops; 00082 /*@unchecked@*/ /*@relnull@*/ 00083 rpmop _hdr_getops = &hdr_getops; 00084 /*@=compmempass@*/ 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; /* RPMTS_OP_HDRLOAD */ 00092 case 19: op = &h->h_getops; break; /* RPMTS_OP_HDRGET */ 00093 } 00094 return op; 00095 } 00096 00097 /*@-mustmod@*/ 00098 static void headerScrub(void * _h) /* XXX headerFini already in use */ 00099 /*@modifies *_h @*/ 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, (unsigned)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 h->parent = _free(h->parent); 00137 00138 /*@-nullstate@*/ 00139 if (_hdr_stats) { 00140 if (_hdr_loadops) /* RPMTS_OP_HDRLOAD */ 00141 (void) rpmswAdd(_hdr_loadops, headerGetStats(h, 18)); 00142 if (_hdr_getops) /* RPMTS_OP_HDRGET */ 00143 (void) rpmswAdd(_hdr_getops, headerGetStats(h, 19)); 00144 } 00145 /*@=nullstate@*/ 00146 } 00147 /*@=mustmod@*/ 00148 00149 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00150 rpmioPool _headerPool; 00151 00152 static Header headerGetPool(/*@null@*/ rpmioPool pool) 00153 /*@globals _headerPool, fileSystem @*/ 00154 /*@modifies pool, _headerPool, fileSystem @*/ 00155 { 00156 Header h; 00157 00158 if (_headerPool == NULL) { 00159 _headerPool = rpmioNewPool("h", sizeof(*h), -1, _hdr_debug, 00160 NULL, NULL, headerScrub); 00161 pool = _headerPool; 00162 } 00163 return (Header) rpmioGetPool(pool, sizeof(*h)); 00164 } 00165 00166 Header headerNew(void) 00167 { 00168 Header h = headerGetPool(_headerPool); 00169 00170 (void) memcpy(h->magic, header_magic, sizeof(h->magic)); 00171 h->blob = NULL; 00172 h->bloblen = 0; 00173 h->origin = NULL; 00174 h->baseurl = NULL; 00175 h->digest = NULL; 00176 h->parent = NULL; 00177 h->rpmdb = NULL; 00178 memset(&h->sb, 0, sizeof(h->sb)); 00179 h->instance = 0; 00180 h->startoff = 0; 00181 h->endoff = 0; 00182 memset(&h->h_loadops, 0, sizeof(h->h_loadops)); 00183 memset(&h->h_getops, 0, sizeof(h->h_getops)); 00184 h->indexAlloced = INDEX_MALLOC_SIZE; 00185 h->indexUsed = 0; 00186 h->flags = HEADERFLAG_SORTED; 00187 00188 h->index = (h->indexAlloced 00189 ? xcalloc(h->indexAlloced, sizeof(*h->index)) 00190 : NULL); 00191 00192 /*@-globstate -nullret -observertrans @*/ 00193 return headerLink(h); 00194 /*@=globstate =nullret =observertrans @*/ 00195 } 00196 00199 static int indexCmp(const void * avp, const void * bvp) 00200 /*@*/ 00201 { 00202 /*@-castexpose@*/ 00203 indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp; 00204 /*@=castexpose@*/ 00205 return ((int)ap->info.tag - (int)bp->info.tag); 00206 } 00207 00212 static 00213 void headerSort(Header h) 00214 /*@modifies h @*/ 00215 { 00216 if (!(h->flags & HEADERFLAG_SORTED)) { 00217 qsort(h->index, h->indexUsed, sizeof(*h->index), indexCmp); 00218 h->flags |= HEADERFLAG_SORTED; 00219 } 00220 } 00221 00224 static int offsetCmp(const void * avp, const void * bvp) /*@*/ 00225 { 00226 /*@-castexpose@*/ 00227 indexEntry ap = (indexEntry) avp, bp = (indexEntry) bvp; 00228 /*@=castexpose@*/ 00229 int rc = ((int)ap->info.offset - (int)bp->info.offset); 00230 00231 if (rc == 0) { 00232 /* Within a region, entries sort by address. Added drips sort by tag. */ 00233 if (ap->info.offset < 0) 00234 rc = (((char *)ap->data) - ((char *)bp->data)); 00235 else 00236 rc = ((int)ap->info.tag - (int)bp->info.tag); 00237 } 00238 return rc; 00239 } 00240 00245 static 00246 void headerUnsort(Header h) 00247 /*@modifies h @*/ 00248 { 00249 qsort(h->index, h->indexUsed, sizeof(*h->index), offsetCmp); 00250 } 00251 00252 size_t headerSizeof(Header h) 00253 { 00254 indexEntry entry; 00255 size_t size = 0; 00256 size_t pad = 0; 00257 size_t i; 00258 00259 if (h == NULL) 00260 return size; 00261 00262 headerSort(h); 00263 00264 size += sizeof(header_magic); /* XXX HEADER_MAGIC_YES */ 00265 00266 /*@-sizeoftype@*/ 00267 size += 2 * sizeof(rpmuint32_t); /* count of index entries */ 00268 /*@=sizeoftype@*/ 00269 00270 for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) { 00271 size_t diff; 00272 rpmTagType type; 00273 00274 /* Regions go in as is ... */ 00275 if (ENTRY_IS_REGION(entry)) { 00276 size += entry->length; 00277 /* XXX Legacy regions do not include the region tag and data. */ 00278 /*@-sizeoftype@*/ 00279 if (i == 0 && (h->flags & HEADERFLAG_LEGACY)) 00280 size += sizeof(struct entryInfo_s) + entry->info.count; 00281 /*@=sizeoftype@*/ 00282 continue; 00283 } 00284 00285 /* ... and region elements are skipped. */ 00286 if (entry->info.offset < 0) 00287 continue; 00288 00289 /* Alignment */ 00290 type = entry->info.type; 00291 if (typeSizes[type] > 1) { 00292 diff = typeSizes[type] - (size % typeSizes[type]); 00293 if ((int)diff != typeSizes[type]) { 00294 size += diff; 00295 pad += diff; 00296 } 00297 } 00298 00299 /*@-sizeoftype@*/ 00300 size += sizeof(struct entryInfo_s) + entry->length; 00301 /*@=sizeoftype@*/ 00302 } 00303 00304 return size; 00305 } 00306 00316 static size_t dataLength(rpmTagType type, rpmTagData * p, rpmTagCount count, 00317 int onDisk, /*@null@*/ rpmTagData * pend) 00318 /*@*/ 00319 { 00320 const unsigned char * s = (unsigned char *) (*p).ui8p; 00321 const unsigned char * se = (unsigned char *) (pend ? (*pend).ui8p : NULL); 00322 size_t length = 0; 00323 00324 switch (type) { 00325 case RPM_STRING_TYPE: 00326 if (count != 1) 00327 return 0; 00328 while (*s++ != '\0') { 00329 if (se && s > se) 00330 return 0; 00331 length++; 00332 } 00333 length++; /* count nul terminator too. */ 00334 break; 00335 /* These are like RPM_STRING_TYPE, except they're *always* an array */ 00336 /* Compute sum of length of all strings, including nul terminators */ 00337 case RPM_I18NSTRING_TYPE: 00338 case RPM_STRING_ARRAY_TYPE: 00339 if (onDisk) { 00340 while (count--) { 00341 length++; /* count nul terminator too */ 00342 while (*s++ != '\0') { 00343 if (se && s > se) 00344 return 0; 00345 length++; 00346 } 00347 } 00348 } else { 00349 const char ** av = (*p).argv; 00350 while (count--) { 00351 /* add one for null termination */ 00352 length += strlen(*av++) + 1; 00353 } 00354 } 00355 break; 00356 default: 00357 if (typeSizes[type] == -1) 00358 return 0; 00359 length = typeSizes[(type & 0xf)] * count; 00360 if ((se && (s + length) > se)) 00361 return 0; 00362 break; 00363 } 00364 00365 return length; 00366 } 00367 00372 static unsigned char * tagSwab(/*@out@*/ /*@returned@*/ unsigned char * t, 00373 const HE_t he, size_t nb) 00374 /*@modifies *t @*/ 00375 { 00376 rpmuint32_t i; 00377 00378 switch (he->t) { 00379 case RPM_UINT64_TYPE: 00380 { rpmuint32_t * tt = (rpmuint32_t *)t; 00381 assert(nb == (he->c * sizeof(*tt))); 00382 for (i = 0; i < he->c; i++) { 00383 rpmuint32_t j = 2 * i; 00384 rpmuint32_t b = (rpmuint32_t) htonl(he->p.ui32p[j]); 00385 tt[j ] = (rpmuint32_t) htonl(he->p.ui32p[j+1]); 00386 tt[j+1] = b; 00387 } 00388 } break; 00389 case RPM_UINT32_TYPE: 00390 { rpmuint32_t * tt = (rpmuint32_t *)t; 00391 assert(nb == (he->c * sizeof(*tt))); 00392 for (i = 0; i < he->c; i++) 00393 tt[i] = (rpmuint32_t) htonl(he->p.ui32p[i]); 00394 } break; 00395 case RPM_UINT16_TYPE: 00396 { rpmuint16_t * tt = (rpmuint16_t *)t; 00397 assert(nb == (he->c * sizeof(*tt))); 00398 for (i = 0; i < he->c; i++) 00399 tt[i] = (rpmuint16_t) htons(he->p.ui16p[i]); 00400 } break; 00401 default: 00402 assert(he->p.ptr != NULL); 00403 if ((void *)t != he->p.ptr && nb) 00404 memcpy(t, he->p.ptr, nb); 00405 t += nb; 00406 break; 00407 } 00408 /*@-compdef@*/ 00409 return t; 00410 /*@=compdef@*/ 00411 } 00412 00418 static int rpmheRealloc(HE_t he) 00419 /*@modifies he @*/ 00420 { 00421 size_t nb = 0; 00422 int rc = 1; /* assume success */ 00423 00424 switch (he->t) { 00425 default: 00426 assert(0); /* XXX stop unimplemented oversights. */ 00427 break; 00428 case RPM_BIN_TYPE: 00429 he->freeData = 1; /* XXX RPM_BIN_TYPE is malloc'd */ 00430 /*@fallthrough@*/ 00431 case 1: 00432 case RPM_UINT8_TYPE: 00433 nb = he->c * sizeof(*he->p.ui8p); 00434 break; 00435 case RPM_UINT16_TYPE: 00436 nb = he->c * sizeof(*he->p.ui16p); 00437 break; 00438 case RPM_UINT32_TYPE: 00439 nb = he->c * sizeof(*he->p.ui32p); 00440 break; 00441 case RPM_UINT64_TYPE: 00442 nb = he->c * sizeof(*he->p.ui64p); 00443 break; 00444 case RPM_STRING_TYPE: 00445 if (he->p.str) 00446 nb = strlen(he->p.str) + 1; 00447 else 00448 rc = 0; 00449 break; 00450 case RPM_I18NSTRING_TYPE: 00451 case RPM_STRING_ARRAY_TYPE: 00452 break; 00453 } 00454 00455 /* Allocate all returned storage (if not already). */ 00456 if (he->p.ptr && nb && !he->freeData) { 00457 void * ptr = xmalloc(nb); 00458 if (tagSwab(ptr, he, nb) != NULL) 00459 he->p.ptr = ptr; 00460 else { 00461 /*@-dependenttrans@*/ 00462 ptr = _free(ptr); 00463 /*@=dependenttrans@*/ 00464 rc = 0; 00465 } 00466 } 00467 00468 if (rc) 00469 he->freeData = 1; 00470 00471 return rc; 00472 } 00473 00500 /*@-globs@*/ /* XXX rpm_typeAlign usage */ 00501 static rpmuint32_t regionSwab(/*@null@*/ indexEntry entry, rpmuint32_t il, rpmuint32_t dl, 00502 entryInfo pe, 00503 unsigned char * dataStart, 00504 /*@null@*/ const unsigned char * dataEnd, 00505 rpmint32_t regionid) 00506 /*@modifies *entry @*/ 00507 { 00508 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00509 rpmTagData p; 00510 rpmTagData pend; 00511 unsigned char * tprev = NULL; 00512 unsigned char * t = NULL; 00513 size_t tdel = 0; 00514 size_t tl = dl; 00515 struct indexEntry_s ieprev; 00516 00517 assert(dataEnd != NULL); 00518 assert(entry != NULL); 00519 assert(dl == 0); /* XXX eliminate dl argument (its always 0) */ 00520 00521 memset(&ieprev, 0, sizeof(ieprev)); 00522 for (; il > 0; il--, pe++) { 00523 struct indexEntry_s ie; 00524 rpmTagType type; 00525 00526 ie.info.tag = (rpmuint32_t) ntohl(pe->tag); 00527 ie.info.type = (rpmuint32_t) ntohl(pe->type); 00528 ie.info.count = (rpmuint32_t) ntohl(pe->count); 00529 ie.info.offset = (rpmint32_t) ntohl(pe->offset); 00530 assert(ie.info.offset >= 0); /* XXX insurance */ 00531 00532 if (hdrchkType(ie.info.type)) 00533 return 0; 00534 if (hdrchkData(ie.info.count)) 00535 return 0; 00536 if (hdrchkData(ie.info.offset)) 00537 return 0; 00538 if (hdrchkAlign(ie.info.type, ie.info.offset)) 00539 return 0; 00540 00541 ie.data = t = dataStart + ie.info.offset; 00542 if (dataEnd && t >= dataEnd) 00543 return 0; 00544 00545 p.ptr = ie.data; 00546 pend.ui8p = (rpmuint8_t *) dataEnd; 00547 00548 /* Compute the tag data store length using offsets. */ 00549 if (il > 1) 00550 ie.length = ((rpmuint32_t)ntohl(pe[1].offset) - ie.info.offset); 00551 else { 00552 /* XXX (dataEnd - t) +/- REGION_TAG_COUNT forces dataLength() */ 00553 ie.length = dataLength(ie.info.type, &p, ie.info.count, 1, &pend); 00554 } 00555 00556 if (ie.length == 0 || hdrchkData(ie.length)) 00557 return 0; 00558 00559 ie.rdlen = 0; 00560 00561 if (entry) { 00562 ie.info.offset = regionid; 00563 /*@-kepttrans@*/ /* entry->data is kept */ 00564 *entry = ie; /* structure assignment */ 00565 /*@=kepttrans@*/ 00566 entry++; 00567 } 00568 00569 /* Alignment */ 00570 type = ie.info.type; 00571 if (typeSizes[type] > 1) { 00572 size_t diff = typeSizes[type] - (dl % typeSizes[type]); 00573 if ((int)diff != typeSizes[type]) { 00574 dl += diff; 00575 #ifdef DYING 00576 if (ieprev.info.type == RPM_I18NSTRING_TYPE) 00577 ieprev.length += diff; 00578 #endif 00579 } 00580 } 00581 tdel = (tprev ? (t - tprev) : 0); 00582 #ifdef DYING 00583 if (ieprev.info.type == RPM_I18NSTRING_TYPE) 00584 tdel = ieprev.length; 00585 #endif 00586 00587 if (ie.info.tag >= HEADER_I18NTABLE) { 00588 tprev = t; 00589 } else { 00590 tprev = dataStart; 00591 /* XXX HEADER_IMAGE tags don't include region sub-tag. */ 00592 /*@-sizeoftype@*/ 00593 if (ie.info.tag == HEADER_IMAGE) 00594 tprev -= REGION_TAG_COUNT; 00595 /*@=sizeoftype@*/ 00596 } 00597 00598 t += ie.length; 00599 00600 dl += ie.length; 00601 if (dataEnd && (dataStart + dl) > dataEnd) return 0; 00602 tl += tdel; 00603 ieprev = ie; /* structure assignment */ 00604 00605 } 00606 tdel = (tprev ? (t - tprev) : 0); 00607 tl += tdel; 00608 00609 /* XXX 00610 * There are two hacks here: 00611 * 1) tl is 16b (i.e. REGION_TAG_COUNT) short while doing headerReload(). 00612 * 2) the 8/98 rpm bug with inserting i18n tags needs to use tl, not dl. 00613 */ 00614 /*@-sizeoftype@*/ 00615 if (tl+REGION_TAG_COUNT == dl) 00616 tl += REGION_TAG_COUNT; 00617 /*@=sizeoftype@*/ 00618 00619 return dl; 00620 } 00621 /*@=globs@*/ 00622 00623 void * headerUnload(Header h, size_t * lenp) 00624 { 00625 void * sw; 00626 rpmuint32_t * ei = NULL; 00627 entryInfo pe; 00628 unsigned char * dataStart; 00629 unsigned char * te; 00630 unsigned pad; 00631 size_t len = 0; 00632 rpmuint32_t il = 0; 00633 rpmuint32_t dl = 0; 00634 indexEntry entry; 00635 rpmTagType type; 00636 size_t i; 00637 size_t drlen; 00638 size_t ndribbles; 00639 size_t driplen; 00640 size_t ndrips; 00641 int legacy = 0; 00642 00643 if ((sw = headerGetStats(h, 18)) != NULL) /* RPMTS_OP_HDRLOAD */ 00644 (void) rpmswEnter(sw, 0); 00645 00646 /* Sort entries by (offset,tag). */ 00647 headerUnsort(h); 00648 00649 /* Compute (il,dl) for all tags, including those deleted in region. */ 00650 pad = 0; 00651 drlen = ndribbles = driplen = ndrips = 0; 00652 for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) { 00653 if (ENTRY_IS_REGION(entry)) { 00654 rpmuint32_t rdl; 00655 rpmuint32_t ril; 00656 rpmint32_t rid; 00657 00658 assert(entry->info.offset <= 0); /* XXX insurance */ 00659 rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */ 00660 ril = (rpmuint32_t)(rdl/sizeof(*pe)); 00661 rid = (rpmuint32_t)entry->info.offset; 00662 00663 il += ril; 00664 dl += entry->rdlen + entry->info.count; 00665 /* XXX Legacy regions do not include the region tag and data. */ 00666 if (i == 0 && (h->flags & HEADERFLAG_LEGACY)) 00667 il += 1; 00668 00669 /* Skip rest of entries in region, but account for dribbles. */ 00670 for (; i < h->indexUsed && entry->info.offset <= rid+1; i++, entry++) { 00671 if (entry->info.offset <= rid) 00672 /*@innercontinue@*/ continue; 00673 00674 /* Alignment */ 00675 type = entry->info.type; 00676 if (typeSizes[type] > 1) { 00677 size_t diff = typeSizes[type] - (dl % typeSizes[type]); 00678 if ((int)diff != typeSizes[type]) { 00679 drlen += diff; 00680 pad += diff; 00681 dl += diff; 00682 } 00683 } 00684 00685 ndribbles++; 00686 il++; 00687 drlen += entry->length; 00688 dl += entry->length; 00689 } 00690 i--; 00691 entry--; 00692 continue; 00693 } 00694 00695 /* Ignore deleted drips. */ 00696 if (entry->data == NULL || entry->length == 0) 00697 continue; 00698 00699 /* Alignment */ 00700 type = entry->info.type; 00701 if (typeSizes[type] > 1) { 00702 size_t diff = typeSizes[type] - (dl % typeSizes[type]); 00703 if ((int)diff != typeSizes[type]) { 00704 driplen += diff; 00705 pad += diff; 00706 dl += diff; 00707 } else 00708 diff = 0; 00709 } 00710 00711 ndrips++; 00712 il++; 00713 driplen += entry->length; 00714 dl += entry->length; 00715 } 00716 00717 /* Sanity checks on header intro. */ 00718 if (hdrchkTags(il) || hdrchkData(dl)) 00719 goto errxit; 00720 00721 len = sizeof(il) + sizeof(dl) + (il * sizeof(*pe)) + dl; 00722 00723 ei = xmalloc(len); 00724 ei[0] = (rpmuint32_t) htonl(il); 00725 ei[1] = (rpmuint32_t) htonl(dl); 00726 00727 pe = (entryInfo) &ei[2]; 00728 dataStart = te = (unsigned char *) (pe + il); 00729 00730 pad = 0; 00731 for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++) { 00732 const char * src; 00733 unsigned char *t; 00734 size_t rdlen; 00735 00736 if (entry->data == NULL || entry->length == 0) 00737 continue; 00738 00739 t = te; 00740 pe->tag = (rpmuint32_t) htonl(entry->info.tag); 00741 pe->type = (rpmuint32_t) htonl(entry->info.type); 00742 pe->count = (rpmuint32_t) htonl(entry->info.count); 00743 00744 if (ENTRY_IS_REGION(entry)) { 00745 rpmuint32_t rdl; 00746 rpmuint32_t ril; 00747 rpmint32_t rid; 00748 00749 assert(entry->info.offset <= 0); /* XXX insurance */ 00750 00751 rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */ 00752 ril = (rpmuint32_t)(rdl/sizeof(*pe) + ndribbles); 00753 rid = (rpmuint32_t)entry->info.offset; 00754 00755 src = (char *)entry->data; 00756 rdlen = entry->rdlen; 00757 00758 /* XXX Legacy regions do not include the region tag and data. */ 00759 if (i == 0 && (h->flags & HEADERFLAG_LEGACY)) { 00760 rpmuint32_t stei[4]; 00761 00762 legacy = 1; 00763 memcpy(pe+1, src, rdl); 00764 memcpy(te, src + rdl, rdlen); 00765 te += rdlen; 00766 00767 pe->offset = (rpmint32_t) htonl(te - dataStart); 00768 stei[0] = (rpmuint32_t) pe->tag; 00769 stei[1] = (rpmuint32_t) pe->type; 00770 stei[2] = (rpmuint32_t) htonl(-rdl-entry->info.count); 00771 stei[3] = (rpmuint32_t) pe->count; 00772 memcpy(te, stei, entry->info.count); 00773 te += entry->info.count; 00774 ril++; 00775 rdlen += entry->info.count; 00776 00777 } else { 00778 00779 memcpy(pe+1, src + sizeof(*pe), ((ril-1) * sizeof(*pe))); 00780 memcpy(te, src + (ril * sizeof(*pe)), rdlen+entry->info.count+drlen); 00781 te += rdlen; 00782 { /*@-castexpose@*/ 00783 entryInfo se = (entryInfo)src; 00784 /*@=castexpose@*/ 00785 rpmint32_t off = (rpmint32_t) ntohl(se->offset); 00786 pe->offset = (rpmint32_t)((off) 00787 ? htonl(te - dataStart) : htonl(off)); 00788 } 00789 te += entry->info.count + drlen; 00790 00791 } 00792 00793 /* Skip rest of entries in region. */ 00794 while (i < h->indexUsed && entry->info.offset <= rid+1) { 00795 i++; 00796 entry++; 00797 } 00798 i--; 00799 entry--; 00800 pe += ril; 00801 continue; 00802 } 00803 00804 /* Ignore deleted drips. */ 00805 if (entry->data == NULL || entry->length == 0) 00806 continue; 00807 00808 /* Alignment */ 00809 type = entry->info.type; 00810 if (typeSizes[type] > 1) { 00811 size_t diff; 00812 diff = typeSizes[type] - ((te - dataStart) % typeSizes[type]); 00813 if ((int)diff != typeSizes[type]) { 00814 memset(te, 0, diff); 00815 te += diff; 00816 pad += diff; 00817 } 00818 } 00819 00820 /* Move tag data into header data store. */ 00821 pe->offset = (rpmint32_t) htonl(te - dataStart); 00822 memcpy(te, entry->data, entry->length); 00823 te += entry->length; 00824 pe++; 00825 } 00826 00827 /* Insure that there are no memcpy underruns/overruns. */ 00828 if (((unsigned char *)pe) != dataStart) 00829 goto errxit; 00830 if ((((unsigned char *)ei)+len) != te) 00831 goto errxit; 00832 00833 if (lenp) 00834 *lenp = len; 00835 00836 h->flags &= ~HEADERFLAG_SORTED; 00837 headerSort(h); 00838 00839 if (sw != NULL) (void) rpmswExit(sw, len); 00840 00841 return (void *) ei; 00842 00843 errxit: 00844 if (sw != NULL) (void) rpmswExit(sw, len); 00845 /*@-usereleased@*/ 00846 ei = _free(ei); 00847 /*@=usereleased@*/ 00848 return (void *) ei; 00849 } 00850 00858 static /*@null@*/ 00859 indexEntry findEntry(/*@null@*/ Header h, rpmTag tag, rpmTagType type) 00860 /*@modifies h @*/ 00861 { 00862 indexEntry entry, entry2, last; 00863 struct indexEntry_s key; 00864 00865 if (h == NULL) return NULL; 00866 if (!(h->flags & HEADERFLAG_SORTED)) headerSort(h); 00867 00868 key.info.tag = tag; 00869 00870 entry2 = entry = 00871 bsearch(&key, h->index, h->indexUsed, sizeof(*h->index), indexCmp); 00872 if (entry == NULL) 00873 return NULL; 00874 00875 if (type == 0) 00876 return entry; 00877 00878 /* look backwards */ 00879 while (entry->info.tag == tag && entry->info.type != type && 00880 entry > h->index) entry--; 00881 00882 if (entry->info.tag == tag && entry->info.type == type) 00883 return entry; 00884 00885 last = h->index + h->indexUsed; 00886 /*@-usereleased@*/ /* FIX: entry2 = entry. Code looks bogus as well. */ 00887 while (entry2->info.tag == tag && entry2->info.type != type && 00888 entry2 < last) entry2++; 00889 /*@=usereleased@*/ 00890 00891 if (entry->info.tag == tag && entry->info.type == type) 00892 return entry; 00893 00894 return NULL; 00895 } 00896 00906 static 00907 int headerRemoveEntry(Header h, rpmTag tag) 00908 /*@modifies h @*/ 00909 { 00910 indexEntry last = h->index + h->indexUsed; 00911 indexEntry entry, first; 00912 int ne; 00913 00914 entry = findEntry(h, tag, 0); 00915 if (!entry) return 1; 00916 00917 /* Make sure entry points to the first occurence of this tag. */ 00918 while (entry > h->index && (entry - 1)->info.tag == tag) 00919 entry--; 00920 00921 /* Free data for tags being removed. */ 00922 for (first = entry; first < last; first++) { 00923 void * data; 00924 if (first->info.tag != tag) 00925 break; 00926 data = first->data; 00927 first->data = NULL; 00928 first->length = 0; 00929 if (ENTRY_IN_REGION(first)) 00930 continue; 00931 data = _free(data); 00932 } 00933 00934 ne = (first - entry); 00935 if (ne > 0) { 00936 h->indexUsed -= ne; 00937 ne = last - first; 00938 if (ne > 0) 00939 memmove(entry, first, (ne * sizeof(*entry))); 00940 } 00941 00942 return 0; 00943 } 00944 00945 Header headerLoad(void * uh) 00946 { 00947 void * sw = NULL; 00948 rpmuint32_t * ei = (rpmuint32_t *) uh; 00949 rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]); /* index length */ 00950 rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]); /* data length */ 00951 /*@-sizeoftype@*/ 00952 size_t pvlen = sizeof(il) + sizeof(dl) + 00953 (il * sizeof(struct entryInfo_s)) + dl; 00954 /*@=sizeoftype@*/ 00955 void * pv = uh; 00956 Header h = NULL; 00957 entryInfo pe; 00958 unsigned char * dataStart; 00959 unsigned char * dataEnd; 00960 indexEntry entry; 00961 rpmuint32_t rdlen; 00962 int i; 00963 00964 /* Sanity checks on header intro. */ 00965 if (hdrchkTags(il) || hdrchkData(dl)) 00966 goto errxit; 00967 00968 ei = (rpmuint32_t *) pv; 00969 /*@-castexpose@*/ 00970 pe = (entryInfo) &ei[2]; 00971 /*@=castexpose@*/ 00972 dataStart = (unsigned char *) (pe + il); 00973 dataEnd = dataStart + dl; 00974 00975 h = headerGetPool(_headerPool); 00976 memset(&h->h_loadops, 0, sizeof(h->h_loadops)); 00977 if ((sw = headerGetStats(h, 18)) != NULL) /* RPMTS_OP_HDRLOAD */ 00978 (void) rpmswEnter(sw, 0); 00979 { unsigned char * hmagic = header_magic; 00980 (void) memcpy(h->magic, hmagic, sizeof(h->magic)); 00981 } 00982 /*@-assignexpose -kepttrans@*/ 00983 h->blob = uh; 00984 h->bloblen = pvlen; 00985 /*@=assignexpose =kepttrans@*/ 00986 h->origin = NULL; 00987 h->baseurl = NULL; 00988 h->digest = NULL; 00989 h->parent = NULL; 00990 h->rpmdb = NULL; 00991 memset(&h->sb, 0, sizeof(h->sb)); 00992 h->instance = 0; 00993 h->startoff = 0; 00994 h->endoff = (rpmuint32_t) pvlen; 00995 memset(&h->h_getops, 0, sizeof(h->h_getops)); 00996 h->indexAlloced = il + 1; 00997 h->indexUsed = il; 00998 h->index = xcalloc(h->indexAlloced, sizeof(*h->index)); 00999 h->flags = HEADERFLAG_SORTED; 01000 h = headerLink(h); 01001 assert(h != NULL); 01002 01003 entry = h->index; 01004 i = 0; 01005 if (!(htonl(pe->tag) < HEADER_I18NTABLE)) { 01006 h->flags |= HEADERFLAG_LEGACY; 01007 entry->info.type = REGION_TAG_TYPE; 01008 entry->info.tag = HEADER_IMAGE; 01009 /*@-sizeoftype@*/ 01010 entry->info.count = (rpmTagCount)REGION_TAG_COUNT; 01011 /*@=sizeoftype@*/ 01012 entry->info.offset = ((unsigned char *)pe - dataStart); /* negative offset */ 01013 01014 /*@-assignexpose@*/ 01015 entry->data = pe; 01016 /*@=assignexpose@*/ 01017 entry->length = pvlen - sizeof(il) - sizeof(dl); 01018 rdlen = regionSwab(entry+1, il, 0, pe, dataStart, dataEnd, entry->info.offset); 01019 #if 0 /* XXX don't check, the 8/98 i18n bug fails here. */ 01020 if (rdlen != dl) 01021 goto errxit; 01022 #endif 01023 entry->rdlen = rdlen; 01024 entry++; 01025 h->indexUsed++; 01026 } else { 01027 rpmuint32_t rdl; 01028 rpmuint32_t ril; 01029 01030 h->flags &= ~HEADERFLAG_LEGACY; 01031 01032 entry->info.type = (rpmuint32_t) htonl(pe->type); 01033 entry->info.count = (rpmuint32_t) htonl(pe->count); 01034 01035 if (hdrchkType(entry->info.type)) 01036 goto errxit; 01037 if (hdrchkTags(entry->info.count)) 01038 goto errxit; 01039 01040 { rpmint32_t off = (rpmint32_t) ntohl(pe->offset); 01041 01042 if (hdrchkData(off)) 01043 goto errxit; 01044 if (off) { 01045 /*@-sizeoftype@*/ 01046 size_t nb = REGION_TAG_COUNT; 01047 /*@=sizeoftype@*/ 01048 rpmuint32_t * stei = memcpy(alloca(nb), dataStart + off, nb); 01049 rdl = (rpmuint32_t)-ntohl(stei[2]); /* negative offset */ 01050 assert((rpmint32_t)rdl >= 0); /* XXX insurance */ 01051 ril = (rpmuint32_t)(rdl/sizeof(*pe)); 01052 if (hdrchkTags(ril) || hdrchkData(rdl)) 01053 goto errxit; 01054 entry->info.tag = (rpmuint32_t) htonl(pe->tag); 01055 } else { 01056 ril = il; 01057 /*@-sizeoftype@*/ 01058 rdl = (rpmuint32_t)(ril * sizeof(struct entryInfo_s)); 01059 /*@=sizeoftype@*/ 01060 entry->info.tag = HEADER_IMAGE; 01061 } 01062 } 01063 entry->info.offset = (rpmint32_t) -rdl; /* negative offset */ 01064 01065 /*@-assignexpose@*/ 01066 entry->data = pe; 01067 /*@=assignexpose@*/ 01068 entry->length = pvlen - sizeof(il) - sizeof(dl); 01069 rdlen = regionSwab(entry+1, (ril-1), 0, pe+1, dataStart, dataEnd, entry->info.offset); 01070 if (rdlen == 0) 01071 goto errxit; 01072 entry->rdlen = rdlen; 01073 01074 if (ril < (rpmuint32_t)h->indexUsed) { 01075 indexEntry newEntry = entry + ril; 01076 size_t ne = (h->indexUsed - ril); 01077 rpmint32_t rid = entry->info.offset+1; 01078 rpmuint32_t rc; 01079 01080 /* Load dribble entries from region. */ 01081 rc = regionSwab(newEntry, (rpmuint32_t)ne, 0, pe+ril, dataStart, dataEnd, rid); 01082 if (rc == 0) 01083 goto errxit; 01084 rdlen += rc; 01085 01086 { indexEntry firstEntry = newEntry; 01087 size_t save = h->indexUsed; 01088 size_t j; 01089 01090 /* Dribble entries replace duplicate region entries. */ 01091 h->indexUsed -= ne; 01092 for (j = 0; j < ne; j++, newEntry++) { 01093 (void) headerRemoveEntry(h, newEntry->info.tag); 01094 if (newEntry->info.tag == HEADER_BASENAMES) 01095 (void) headerRemoveEntry(h, HEADER_OLDFILENAMES); 01096 } 01097 01098 /* If any duplicate entries were replaced, move new entries down. */ 01099 if (h->indexUsed < (save - ne)) { 01100 memmove(h->index + h->indexUsed, firstEntry, 01101 (ne * sizeof(*entry))); 01102 } 01103 h->indexUsed += ne; 01104 } 01105 } 01106 } 01107 01108 h->flags &= ~HEADERFLAG_SORTED; 01109 headerSort(h); 01110 01111 if (sw != NULL) (void) rpmswExit(sw, pvlen); 01112 01113 /*@-globstate -observertrans @*/ 01114 return h; 01115 /*@=globstate =observertrans @*/ 01116 01117 errxit: 01118 if (sw != NULL) (void) rpmswExit(sw, pvlen); 01119 /*@-usereleased@*/ 01120 if (h) { 01121 h->index = _free(h->index); 01122 yarnPossess(h->_item.use); /* XXX rpmioPutItem expects locked. */ 01123 h = (Header) rpmioPutPool((rpmioItem)h); 01124 } 01125 /*@=usereleased@*/ 01126 /*@-refcounttrans -globstate@*/ 01127 return h; 01128 /*@=refcounttrans =globstate@*/ 01129 } 01130 01131 int headerGetMagic(Header h, unsigned char ** magicp, size_t * nmagicp) 01132 { 01133 unsigned char * hmagic = header_magic; 01134 if (magicp) 01135 *magicp = (h ? h->magic : hmagic); 01136 if (nmagicp) 01137 *nmagicp = (h ? sizeof(h->magic) : sizeof(header_magic)); 01138 return 0; 01139 } 01140 01141 int headerSetMagic(Header h, unsigned char * magic, size_t nmagic) 01142 { 01143 if (nmagic > sizeof(h->magic)) 01144 nmagic = sizeof(h->magic); 01145 if (h) { 01146 memset(h->magic, 0, sizeof(h->magic)); 01147 if (nmagic > 0) 01148 memmove(h->magic, magic, nmagic); 01149 } 01150 return 0; 01151 } 01152 01153 const char * headerGetOrigin(Header h) 01154 { 01155 return (h != NULL ? h->origin : NULL); 01156 } 01157 01158 int headerSetOrigin(Header h, const char * origin) 01159 { 01160 if (h != NULL) { 01161 h->origin = _free(h->origin); 01162 h->origin = xstrdup(origin); 01163 } 01164 return 0; 01165 } 01166 01167 const char * headerGetParent(Header h) 01168 { 01169 return (h != NULL ? h->parent : NULL); 01170 } 01171 01172 int headerSetParent(Header h, const char * parent) 01173 { 01174 if (h != NULL) { 01175 h->parent = _free(h->parent); 01176 h->parent = xstrdup(parent); 01177 } 01178 return 0; 01179 } 01180 01181 const char * headerGetBaseURL(Header h) 01182 { 01183 /*@-retexpose@*/ 01184 return (h != NULL ? h->baseurl : NULL); 01185 /*@=retexpose@*/ 01186 } 01187 01188 int headerSetBaseURL(Header h, const char * baseurl) 01189 { 01190 if (h != NULL) { 01191 h->baseurl = _free(h->baseurl); 01192 h->baseurl = xstrdup(baseurl); 01193 } 01194 return 0; 01195 } 01196 01197 struct stat * headerGetStatbuf(Header h) 01198 { 01199 /*@-immediatetrans -retexpose@*/ 01200 return (h != NULL ? &h->sb : NULL); 01201 /*@=immediatetrans =retexpose@*/ 01202 } 01203 01204 int headerSetStatbuf(Header h, struct stat * st) 01205 { 01206 if (h != NULL && st != NULL) 01207 memcpy(&h->sb, st, sizeof(h->sb)); 01208 return 0; 01209 } 01210 01211 const char * headerGetDigest(Header h) 01212 { 01213 /*@-compdef -retexpose -usereleased @*/ 01214 return (h != NULL ? h->digest : NULL); 01215 /*@=compdef =retexpose =usereleased @*/ 01216 } 01217 01218 int headerSetDigest(Header h, const char * digest) 01219 { 01220 if (h != NULL) { 01221 h->digest = _free(h->digest); 01222 if (digest) 01223 h->digest = xstrdup(digest); 01224 } 01225 return 0; 01226 } 01227 01228 void * headerGetRpmdb(Header h) 01229 { 01230 /*@-compdef -retexpose -usereleased @*/ 01231 return (h != NULL ? h->rpmdb : NULL); 01232 /*@=compdef =retexpose =usereleased @*/ 01233 } 01234 01235 void * headerSetRpmdb(Header h, void * rpmdb) 01236 { 01237 /*@-assignexpose -temptrans @*/ 01238 if (h != NULL) 01239 h->rpmdb = rpmdb; 01240 /*@=assignexpose =temptrans @*/ 01241 return NULL; 01242 } 01243 01244 uint32_t headerGetInstance(Header h) 01245 { 01246 return (h != NULL ? h->instance : 0); 01247 } 01248 01249 uint32_t headerSetInstance(Header h, uint32_t instance) 01250 { 01251 uint32_t oinstance = 0; 01252 if (h != NULL) { 01253 oinstance = h->instance; 01254 h->instance = instance; 01255 } 01256 return oinstance; 01257 } 01258 01259 rpmuint32_t headerGetStartOff(Header h) 01260 { 01261 return (h != NULL ? h->startoff : 0); 01262 } 01263 01264 rpmuint32_t headerSetStartOff(Header h, rpmuint32_t startoff) 01265 { 01266 if (h != NULL) 01267 h->startoff = startoff; 01268 return 0; 01269 } 01270 01271 rpmuint32_t headerGetEndOff(Header h) 01272 { 01273 return (h != NULL ? h->endoff : 0); 01274 } 01275 01276 rpmuint32_t headerSetEndOff(Header h, rpmuint32_t endoff) 01277 { 01278 if (h != NULL) 01279 h->endoff = endoff; 01280 return 0; 01281 } 01282 01283 Header headerReload(Header h, int tag) 01284 { 01285 Header nh; 01286 void * uh; 01287 const char * origin = (h->origin != NULL ? xstrdup(h->origin) : NULL); 01288 const char * parent = (h->parent != NULL ? xstrdup(h->parent) : NULL); 01289 const char * baseurl = (h->baseurl != NULL ? xstrdup(h->baseurl) : NULL); 01290 const char * digest = (h->digest != NULL ? xstrdup(h->digest) : NULL); 01291 struct stat sb = h->sb; /* structure assignment */ 01292 void * rpmdb = h->rpmdb; 01293 rpmuint32_t instance = headerGetInstance(h); 01294 int xx; 01295 01296 /*@-onlytrans@*/ 01297 uh = headerUnload(h, NULL); 01298 (void)headerFree(h); 01299 h = NULL ; 01300 /*@=onlytrans@*/ 01301 if (uh == NULL) 01302 return NULL; 01303 nh = headerLoad(uh); 01304 if (nh == NULL) { 01305 uh = _free(uh); 01306 return NULL; 01307 } 01308 nh->flags &= ~(HEADERFLAG_MAPPED|HEADERFLAG_RDONLY); /* XXX unnecessary */ 01309 nh->flags |= HEADERFLAG_ALLOCATED; 01310 if (ENTRY_IS_REGION(nh->index)) { 01311 if (tag == HEADER_SIGNATURES || tag == HEADER_IMMUTABLE) 01312 nh->index[0].info.tag = tag; 01313 } 01314 if (origin != NULL) { 01315 xx = headerSetOrigin(nh, origin); 01316 origin = _free(origin); 01317 } 01318 if (parent != NULL) { 01319 xx = headerSetParent(nh, parent); 01320 parent = _free(parent); 01321 } 01322 if (baseurl != NULL) { 01323 xx = headerSetBaseURL(nh, baseurl); 01324 baseurl = _free(baseurl); 01325 } 01326 if (digest != NULL) { 01327 xx = headerSetDigest(nh, digest); 01328 digest = _free(digest); 01329 } 01330 /*@-assignexpose@*/ 01331 nh->sb = sb; /* structure assignment */ 01332 /*@=assignexpose@*/ 01333 (void) headerSetRpmdb(nh, rpmdb); 01334 xx = (int) headerSetInstance(nh, instance); 01335 if (_hdr_debug) 01336 fprintf(stderr, "--> h %p ==== %s: blob %p[%u] flags 0x%x\n", nh, __FUNCTION__, nh->blob, (unsigned)nh->bloblen, nh->flags); 01337 return nh; 01338 } 01339 01340 static Header headerMap(const void * uh, int map) 01341 /*@*/ 01342 { 01343 rpmuint32_t * ei = (rpmuint32_t *) uh; 01344 rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]); /* index length */ 01345 rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]); /* data length */ 01346 /*@-sizeoftype@*/ 01347 size_t pvlen = sizeof(il) + sizeof(dl) + 01348 (il * sizeof(struct entryInfo_s)) + dl; 01349 /*@=sizeoftype@*/ 01350 void * nuh = NULL; 01351 Header nh = NULL; 01352 01353 /* Sanity checks on header intro. */ 01354 if (hdrchkTags(il) || hdrchkData(dl) || pvlen >= headerMaxbytes) 01355 return NULL; 01356 01357 if (map) { 01358 static const int prot = PROT_READ | PROT_WRITE; 01359 static const int flags = MAP_PRIVATE| MAP_ANONYMOUS; 01360 static const int fdno = -1; 01361 static const off_t off = 0; 01362 nuh = mmap(NULL, pvlen, prot, flags, fdno, off); 01363 if (nuh == NULL || nuh == (void *)-1) 01364 fprintf(stderr, 01365 "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n", 01366 NULL, (unsigned)pvlen, prot, flags, fdno, (unsigned)off, 01367 errno, strerror(errno)); 01368 memcpy(nuh, uh, pvlen); 01369 if (mprotect(nuh, pvlen, PROT_READ) != 0) 01370 fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n", 01371 nuh, (unsigned)pvlen, PROT_READ, 01372 errno, strerror(errno)); 01373 nh = headerLoad(nuh); 01374 if (nh != NULL) { 01375 assert(nh->bloblen == pvlen); 01376 nh->flags |= HEADERFLAG_MAPPED; 01377 nh->flags |= HEADERFLAG_RDONLY; 01378 } else { 01379 if (munmap(nuh, pvlen) != 0) 01380 fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n", 01381 nuh, (unsigned)pvlen, errno, strerror(errno)); 01382 } 01383 } else { 01384 nuh = memcpy(xmalloc(pvlen), uh, pvlen); 01385 if ((nh = headerLoad(nuh)) != NULL) 01386 nh->flags |= HEADERFLAG_ALLOCATED; 01387 else 01388 nuh = _free(nuh); 01389 } 01390 01391 return nh; 01392 } 01393 01394 Header headerCopyLoad(const void * uh) 01395 { 01396 static const int map = 1; 01397 return headerMap(uh, map); 01398 } 01399 01400 int headerIsEntry(Header h, rpmTag tag) 01401 { 01402 /*@-mods@*/ /*@ FIX: h modified by sort. */ 01403 return (findEntry(h, tag, 0) ? 1 : 0); 01404 /*@=mods@*/ 01405 } 01406 01415 static int copyEntry(const indexEntry entry, HE_t he, int minMem) 01416 /*@modifies he @*/ 01417 { 01418 rpmTagCount count = entry->info.count; 01419 int rc = 1; /* XXX 1 on success. */ 01420 01421 switch (entry->info.type) { 01422 case RPM_BIN_TYPE: 01423 /* 01424 * XXX This only works for 01425 * XXX "sealed" HEADER_IMMUTABLE/HEADER_SIGNATURES/HEADER_IMAGE. 01426 * XXX This will *not* work for unsealed legacy HEADER_IMAGE (i.e. 01427 * XXX a legacy header freshly read, but not yet unloaded to the rpmdb). 01428 */ 01429 if (ENTRY_IS_REGION(entry)) { 01430 rpmuint32_t * ei = ((rpmuint32_t *)entry->data) - 2; 01431 /*@-castexpose@*/ 01432 entryInfo pe = (entryInfo) (ei + 2); 01433 /*@=castexpose@*/ 01434 unsigned char * dataStart = (unsigned char *) (pe + ntohl(ei[0])); 01435 rpmuint32_t rdl; 01436 rpmuint32_t ril; 01437 01438 assert(entry->info.offset <= 0); /* XXX insurance */ 01439 rdl = (rpmuint32_t)-entry->info.offset; /* negative offset */ 01440 ril = (rpmuint32_t)(rdl/sizeof(*pe)); 01441 /*@-sizeoftype@*/ 01442 rdl = (rpmuint32_t)entry->rdlen; 01443 count = 2 * sizeof(*ei) + (ril * sizeof(*pe)) + rdl; 01444 if (entry->info.tag == HEADER_IMAGE) { 01445 ril -= 1; 01446 pe += 1; 01447 } else { 01448 count += REGION_TAG_COUNT; 01449 rdl += REGION_TAG_COUNT; 01450 } 01451 01452 he->p.ui32p = ei = xmalloc(count); 01453 ei[0] = (rpmuint32_t)htonl(ril); 01454 ei[1] = (rpmuint32_t)htonl(rdl); 01455 01456 /*@-castexpose@*/ 01457 pe = (entryInfo) memcpy(ei + 2, pe, (ril * sizeof(*pe))); 01458 /*@=castexpose@*/ 01459 01460 (void) memcpy(pe + ril, dataStart, rdl); 01461 } else { 01462 count = (rpmTagCount)entry->length; 01463 he->p.ptr = (!minMem 01464 ? memcpy(xmalloc(count), entry->data, count) 01465 : entry->data); 01466 } 01467 break; 01468 case RPM_STRING_TYPE: 01469 if (count == 1) { 01470 he->p.str = entry->data; 01471 break; 01472 } 01473 /*@fallthrough@*/ 01474 case RPM_I18NSTRING_TYPE: 01475 case RPM_STRING_ARRAY_TYPE: 01476 { const char ** argv; 01477 size_t nb = count * sizeof(*argv); 01478 char * t; 01479 unsigned i; 01480 01481 /*@-mods@*/ 01482 if (minMem) { 01483 he->p.argv = argv = xmalloc(nb); 01484 t = entry->data; 01485 } else { 01486 he->p.argv = argv = xmalloc(nb + entry->length); 01487 t = (char *) &argv[count]; 01488 memcpy(t, entry->data, entry->length); 01489 } 01490 /*@=mods@*/ 01491 for (i = 0; i < (unsigned) count; i++) { 01492 argv[i] = t; 01493 t = strchr(t, 0); 01494 t++; 01495 } 01496 } break; 01497 01498 default: 01499 he->p.ptr = entry->data; 01500 break; 01501 } 01502 he->t = entry->info.type; 01503 he->c = count; 01504 return rc; 01505 } 01506 01525 static int headerMatchLocale(const char *td, const char *l, const char *le) 01526 /*@*/ 01527 { 01528 const char *fe; 01529 01530 01531 #if 0 01532 { const char *s, *ll, *CC, *EE, *dd; 01533 char *lbuf, *t. 01534 01535 /* Copy the buffer and parse out components on the fly. */ 01536 lbuf = alloca(le - l + 1); 01537 for (s = l, ll = t = lbuf; *s; s++, t++) { 01538 switch (*s) { 01539 case '_': 01540 *t = '\0'; 01541 CC = t + 1; 01542 break; 01543 case '.': 01544 *t = '\0'; 01545 EE = t + 1; 01546 break; 01547 case '@': 01548 *t = '\0'; 01549 dd = t + 1; 01550 break; 01551 default: 01552 *t = *s; 01553 break; 01554 } 01555 } 01556 01557 if (ll) /* ISO language should be lower case */ 01558 for (t = ll; *t; t++) *t = tolower(*t); 01559 if (CC) /* ISO country code should be upper case */ 01560 for (t = CC; *t; t++) *t = toupper(*t); 01561 01562 /* There are a total of 16 cases to attempt to match. */ 01563 } 01564 #endif 01565 01566 /* First try a complete match. */ 01567 if (strlen(td) == (size_t)(le - l) && !strncmp(td, l, (size_t)(le - l))) 01568 return 1; 01569 01570 /* Next, try stripping optional dialect and matching. */ 01571 for (fe = l; fe < le && *fe != '@'; fe++) 01572 {}; 01573 if (fe < le && !strncmp(td, l, (fe - l))) 01574 return 1; 01575 01576 /* Next, try stripping optional codeset and matching. */ 01577 for (fe = l; fe < le && *fe != '.'; fe++) 01578 {}; 01579 if (fe < le && !strncmp(td, l, (fe - l))) 01580 return 1; 01581 01582 /* Finally, try stripping optional country code and matching. */ 01583 for (fe = l; fe < le && *fe != '_'; fe++) 01584 {}; 01585 if (fe < le && !strncmp(td, l, (fe - l))) 01586 return 2; 01587 01588 return 0; 01589 } 01590 01597 /*@dependent@*/ /*@exposed@*/ static char * 01598 headerFindI18NString(Header h, indexEntry entry) 01599 /*@*/ 01600 { 01601 const char *lang, *l, *le; 01602 indexEntry table; 01603 01604 /* XXX Drepper sez' this is the order. */ 01605 if ((lang = getenv("LANGUAGE")) == NULL && 01606 (lang = getenv("LC_ALL")) == NULL && 01607 (lang = getenv("LC_MESSAGES")) == NULL && 01608 (lang = getenv("LANG")) == NULL) 01609 return entry->data; 01610 01611 /*@-mods@*/ 01612 if ((table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE)) == NULL) 01613 return entry->data; 01614 /*@=mods@*/ 01615 01616 for (l = lang; *l != '\0'; l = le) { 01617 const char *td; 01618 char *ed, *ed_weak = NULL; 01619 rpmuint32_t langNum; 01620 01621 while (*l && *l == ':') /* skip leading colons */ 01622 l++; 01623 if (*l == '\0') 01624 break; 01625 for (le = l; *le && *le != ':'; le++) /* find end of this locale */ 01626 {}; 01627 01628 /* For each entry in the header ... */ 01629 for (langNum = 0, td = table->data, ed = entry->data; 01630 langNum < entry->info.count; 01631 langNum++, td += strlen(td) + 1, ed += strlen(ed) + 1) 01632 { 01633 int match = headerMatchLocale(td, l, le); 01634 if (match == 1) return ed; 01635 else if (match == 2) ed_weak = ed; 01636 } 01637 if (ed_weak) return ed_weak; 01638 } 01639 01640 return entry->data; 01641 } 01642 01650 static int intGetEntry(Header h, HE_t he, int flags) 01651 /*@modifies he @*/ 01652 { 01653 int minMem = 0; 01654 indexEntry entry; 01655 int rc; 01656 01657 /* First find the tag */ 01658 /*@-mods@*/ /*@ FIX: h modified by sort. */ 01659 entry = findEntry(h, he->tag, 0); 01660 /*@=mods@*/ 01661 if (entry == NULL) { 01662 he->t = 0; 01663 he->p.ptr = NULL; 01664 he->c = 0; 01665 return 0; 01666 } 01667 01668 switch (entry->info.type) { 01669 case RPM_I18NSTRING_TYPE: 01670 if (!(flags & HEADERGET_NOI18NSTRING)) { 01671 rc = 1; 01672 he->t = RPM_STRING_TYPE; 01673 he->c = 1; 01674 /*@-dependenttrans@*/ 01675 he->p.str = headerFindI18NString(h, entry); 01676 /*@=dependenttrans@*/ 01677 break; 01678 } 01679 /*@fallthrough@*/ 01680 default: 01681 rc = copyEntry(entry, he, minMem); 01682 break; 01683 } 01684 01685 /* XXX 1 on success */ 01686 return (rc == 1 ? 1 : 0); 01687 } 01688 01696 static int copyData(char * t, const HE_t he, size_t nb) 01697 /*@modifies *t @*/ 01698 { 01699 int rc = 0; /* assume success */ 01700 01701 switch (he->t) { 01702 case RPM_I18NSTRING_TYPE: 01703 case RPM_STRING_ARRAY_TYPE: 01704 { const char ** av = he->p.argv; 01705 rpmTagCount cnt = he->c; 01706 const char * s; 01707 01708 while (cnt-- > 0 && nb > 0) { 01709 if ((s = *av++) != NULL) 01710 do { 01711 *t++ = *s++; 01712 } while (s[-1] && --nb > 0); 01713 } 01714 } break; 01715 default: 01716 if (tagSwab((unsigned char *)t, he, nb) == NULL) 01717 rc = 1; 01718 break; 01719 } 01720 return rc; 01721 } 01722 01729 /*@null@*/ 01730 static void * 01731 grabData(HE_t he, /*@out@*/ size_t * lenp) 01732 /*@modifies *lenp @*/ 01733 { 01734 size_t nb = dataLength(he->t, &he->p, he->c, 0, NULL); 01735 char * t = NULL; 01736 01737 if (nb > 0) { 01738 t = xmalloc(nb); 01739 if (copyData(t, he, nb)) { 01740 t = _free(t); 01741 nb = 0; 01742 } 01743 } 01744 if (lenp) 01745 *lenp = nb; 01746 return t; 01747 } 01748 01760 static 01761 int headerAddEntry(Header h, HE_t he) 01762 /*@modifies h @*/ 01763 { 01764 indexEntry entry; 01765 rpmTagData data; 01766 size_t length = 0; 01767 int rc = 0; /* assume failure */ 01768 01769 /* Count must always be >= 1 for headerAddEntry. */ 01770 if (he->c == 0) 01771 return rc; 01772 01773 if (hdrchkType(he->t)) 01774 return rc; 01775 if (hdrchkData(he->c)) 01776 return rc; 01777 01778 data.ptr = grabData(he, &length); 01779 if (data.ptr == NULL || length == 0) 01780 return rc; 01781 01782 /* Allocate more index space if necessary */ 01783 if (h->indexUsed == h->indexAlloced) { 01784 h->indexAlloced += INDEX_MALLOC_SIZE; 01785 h->index = xrealloc(h->index, h->indexAlloced * sizeof(*h->index)); 01786 } 01787 01788 /* Fill in the index */ 01789 entry = h->index + h->indexUsed; 01790 entry->info.tag = he->tag; 01791 entry->info.type = he->t; 01792 entry->info.count = he->c; 01793 entry->info.offset = 0; 01794 entry->data = data.ptr; 01795 entry->length = length; 01796 01797 if (h->indexUsed > 0 && he->tag < h->index[h->indexUsed-1].info.tag) 01798 h->flags &= ~HEADERFLAG_SORTED; 01799 h->indexUsed++; 01800 rc = 1; 01801 01802 return rc; 01803 } 01804 01814 static 01815 int headerAppendEntry(Header h, HE_t he) 01816 /*@modifies h @*/ 01817 { 01818 rpmTagData src = { .ptr = he->p.ptr }; 01819 char * t; 01820 indexEntry entry; 01821 size_t length; 01822 int rc = 0; /* assume failure */ 01823 01824 if (he->t == RPM_STRING_TYPE || he->t == RPM_I18NSTRING_TYPE) { 01825 /* we can't do this */ 01826 return rc; 01827 } 01828 01829 /* Find the tag entry in the header. */ 01830 entry = findEntry(h, he->tag, he->t); 01831 if (!entry) 01832 return rc; 01833 01834 length = dataLength(he->t, &src, he->c, 0, NULL); 01835 if (length == 0) 01836 return rc; 01837 01838 if (ENTRY_IN_REGION(entry)) { 01839 char * t = xmalloc(entry->length + length); 01840 memcpy(t, entry->data, entry->length); 01841 entry->data = t; 01842 entry->info.offset = 0; 01843 } else 01844 entry->data = xrealloc(entry->data, entry->length + length); 01845 01846 t = ((char *) entry->data) + entry->length; 01847 if (!copyData(t, he, length)) 01848 rc = 1; 01849 01850 entry->length += length; 01851 01852 entry->info.count += he->c; 01853 01854 return rc; 01855 } 01856 01863 static 01864 int headerAddOrAppendEntry(Header h, HE_t he) 01865 /*@modifies h @*/ 01866 { 01867 return (findEntry(h, he->tag, he->t) 01868 ? headerAppendEntry(h, he) 01869 : headerAddEntry(h, he)); 01870 } 01871 01872 int headerAddI18NString(Header h, rpmTag tag, const char * string, 01873 const char * lang) 01874 { 01875 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 01876 indexEntry table, entry; 01877 rpmTagData p; 01878 size_t length; 01879 size_t ghosts; 01880 rpmuint32_t i; 01881 rpmuint32_t langNum; 01882 char * buf; 01883 int xx; 01884 01885 table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE); 01886 entry = findEntry(h, tag, RPM_I18NSTRING_TYPE); 01887 01888 if (!table && entry) 01889 return 0; /* this shouldn't ever happen!! */ 01890 01891 if (!table && !entry) { 01892 const char * argv[2]; 01893 int count = 0; 01894 p.argv = argv; 01895 if (!lang || (lang[0] == 'C' && lang[1] == '\0')) { 01896 /*@-observertrans -readonlytrans@*/ 01897 p.argv[count++] = "C"; 01898 /*@=observertrans =readonlytrans@*/ 01899 } else { 01900 /*@-observertrans -readonlytrans@*/ 01901 p.argv[count++] = "C"; 01902 /*@=observertrans =readonlytrans@*/ 01903 p.argv[count++] = lang; 01904 } 01905 he->tag = HEADER_I18NTABLE; 01906 he->t = RPM_STRING_ARRAY_TYPE; 01907 he->p.ptr = p.ptr; 01908 he->c = count; 01909 xx = headerAddEntry(h, he); 01910 if (!xx) 01911 return 0; 01912 table = findEntry(h, he->tag, he->t); 01913 } 01914 01915 if (!table) 01916 return 0; 01917 if (!lang) lang = "C"; 01918 01919 { const char * l = table->data; 01920 for (langNum = 0; langNum < table->info.count; langNum++) { 01921 if (!strcmp(l, lang)) break; 01922 l += strlen(l) + 1; 01923 } 01924 } 01925 01926 if (langNum >= table->info.count) { 01927 length = strlen(lang) + 1; 01928 if (ENTRY_IN_REGION(table)) { 01929 char * t = xmalloc(table->length + length); 01930 memcpy(t, table->data, table->length); 01931 table->data = t; 01932 table->info.offset = 0; 01933 } else 01934 table->data = xrealloc(table->data, table->length + length); 01935 memmove(((char *)table->data) + table->length, lang, length); 01936 table->length += length; 01937 table->info.count++; 01938 } 01939 01940 if (!entry) { 01941 p.argv = alloca(sizeof(*p.argv) * (langNum + 1)); 01942 /*@-observertrans -readonlytrans@*/ 01943 for (i = 0; i < langNum; i++) 01944 p.argv[i] = ""; 01945 /*@=observertrans =readonlytrans@*/ 01946 p.argv[langNum] = string; 01947 he->tag = tag; 01948 he->t = RPM_I18NSTRING_TYPE; 01949 he->p.ptr = p.ptr; 01950 he->c = langNum + 1; 01951 /*@-compmempass@*/ 01952 xx = headerAddEntry(h, he); 01953 /*@=compmempass@*/ 01954 return xx; 01955 } else if (langNum >= entry->info.count) { 01956 ghosts = langNum - entry->info.count; 01957 01958 length = strlen(string) + 1 + ghosts; 01959 if (ENTRY_IN_REGION(entry)) { 01960 char * t = xmalloc(entry->length + length); 01961 memcpy(t, entry->data, entry->length); 01962 entry->data = t; 01963 entry->info.offset = 0; 01964 } else 01965 entry->data = xrealloc(entry->data, entry->length + length); 01966 01967 memset(((char *)entry->data) + entry->length, 0, ghosts); 01968 memmove(((char *)entry->data) + entry->length + ghosts, string, strlen(string)+1); 01969 01970 entry->length += length; 01971 entry->info.count = langNum + 1; 01972 } else { 01973 char *b, *be, *e, *ee, *t; 01974 size_t bn, sn, en; 01975 01976 /* Set beginning/end pointers to previous data */ 01977 b = be = e = ee = entry->data; 01978 for (i = 0; i < table->info.count; i++) { 01979 if (i == langNum) 01980 be = ee; 01981 ee += strlen(ee) + 1; 01982 if (i == langNum) 01983 e = ee; 01984 } 01985 01986 /* Get storage for new buffer */ 01987 bn = (be-b); 01988 sn = strlen(string) + 1; 01989 en = (ee-e); 01990 length = bn + sn + en; 01991 t = buf = xmalloc(length); 01992 01993 /* Copy values into new storage */ 01994 memcpy(t, b, bn); 01995 t += bn; 01996 /*@-mayaliasunique@*/ 01997 memcpy(t, string, sn); 01998 t += sn; 01999 memcpy(t, e, en); 02000 t += en; 02001 /*@=mayaliasunique@*/ 02002 02003 /* Replace i18N string array */ 02004 entry->length -= strlen(be) + 1; 02005 entry->length += sn; 02006 02007 if (ENTRY_IN_REGION(entry)) { 02008 entry->info.offset = 0; 02009 } else 02010 entry->data = _free(entry->data); 02011 /*@-dependenttrans@*/ 02012 entry->data = buf; 02013 /*@=dependenttrans@*/ 02014 } 02015 02016 return 0; 02017 } 02018 02026 static 02027 int headerModifyEntry(Header h, HE_t he) 02028 /*@modifies h @*/ 02029 { 02030 indexEntry entry; 02031 rpmTagData oldData; 02032 rpmTagData newData; 02033 size_t length = 0; 02034 02035 /* First find the tag */ 02036 entry = findEntry(h, he->tag, he->t); 02037 if (!entry) 02038 return 0; 02039 02040 newData.ptr = grabData(he, &length); 02041 if (newData.ptr == NULL || length == 0) 02042 return 0; 02043 02044 /* make sure entry points to the first occurence of this tag */ 02045 while (entry > h->index && (entry - 1)->info.tag == he->tag) 02046 entry--; 02047 02048 /* free after we've grabbed the new data in case the two are intertwined; 02049 that's a bad idea but at least we won't break */ 02050 oldData.ptr = entry->data; 02051 02052 entry->info.count = he->c; 02053 entry->info.type = he->t; 02054 entry->data = newData.ptr; 02055 entry->length = length; 02056 02057 if (ENTRY_IN_REGION(entry)) { 02058 entry->info.offset = 0; 02059 } else 02060 oldData.ptr = _free(oldData.ptr); 02061 02062 return 1; 02063 } 02064 02068 struct headerIterator_s { 02069 Header h; 02070 size_t next_index; 02071 }; 02072 02073 HeaderIterator headerFini(/*@only@*/ HeaderIterator hi) 02074 { 02075 if (hi != NULL) { 02076 (void)headerFree(hi->h); 02077 hi->h = NULL; 02078 hi = _free(hi); 02079 } 02080 return hi; 02081 } 02082 02083 HeaderIterator headerInit(Header h) 02084 { 02085 HeaderIterator hi = xmalloc(sizeof(*hi)); 02086 02087 headerSort(h); 02088 02089 /*@-assignexpose -castexpose @*/ 02090 hi->h = headerLink(h); 02091 /*@=assignexpose =castexpose @*/ 02092 assert(hi->h != NULL); 02093 hi->next_index = 0; 02094 return hi; 02095 } 02096 02097 int headerNext(HeaderIterator hi, HE_t he, /*@unused@*/ unsigned int flags) 02098 { 02099 void * sw; 02100 Header h = hi->h; 02101 size_t slot = hi->next_index; 02102 indexEntry entry = NULL; 02103 int rc; 02104 02105 /* Insure that *he is reliably initialized. */ 02106 memset(he, 0, sizeof(*he)); 02107 02108 for (slot = hi->next_index; slot < h->indexUsed; slot++) { 02109 entry = h->index + slot; 02110 if (!ENTRY_IS_REGION(entry)) 02111 break; 02112 } 02113 hi->next_index = slot; 02114 if (entry == NULL || slot >= h->indexUsed) 02115 return 0; 02116 02117 hi->next_index++; 02118 02119 if ((sw = headerGetStats(h, 19)) != NULL) /* RPMTS_OP_HDRGET */ 02120 (void) rpmswEnter(sw, 0); 02121 02122 he->tag = entry->info.tag; 02123 rc = copyEntry(entry, he, 0); 02124 if (rc) 02125 rc = rpmheRealloc(he); 02126 02127 if (sw != NULL) (void) rpmswExit(sw, 0); 02128 02129 /* XXX 1 on success */ 02130 return ((rc == 1) ? 1 : 0); 02131 } 02132 02133 Header headerCopy(Header h) 02134 { 02135 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 02136 Header nh = headerNew(); 02137 HeaderIterator hi; 02138 02139 for (hi = headerInit(h); 02140 headerNext(hi, he, 0); 02141 he->p.ptr = _free(he->p.ptr)) 02142 { 02143 if (he->p.ptr) (void) headerAddEntry(nh, he); 02144 } 02145 hi = headerFini(hi); 02146 02147 return headerReload(nh, HEADER_IMAGE); 02148 } 02149 02150 void headerCopyTags(Header headerFrom, Header headerTo, rpmTag * tagstocopy) 02151 { 02152 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 02153 rpmTag * tagno; 02154 int xx; 02155 02156 if (headerFrom == headerTo) 02157 return; 02158 02159 for (tagno = tagstocopy; *tagno != 0; tagno++) { 02160 if (headerIsEntry(headerTo, *tagno)) 02161 continue; 02162 he->tag = *tagno; 02163 if (!headerGet(headerFrom, he, 0)) 02164 continue; 02165 xx = headerPut(headerTo, he, 0); 02166 he->p.ptr = _free(he->p.ptr); 02167 } 02168 } 02169 02170 int headerGet(Header h, HE_t he, unsigned int flags) 02171 { 02172 void * sw; 02173 const char * name; 02174 headerSprintfExtension exts = headerCompoundFormats; 02175 headerSprintfExtension ext = NULL; 02176 int extNum; 02177 int rc; 02178 02179 if (h == NULL || he == NULL) return 0; /* XXX this is nutty. */ 02180 02181 /* Insure that *he is reliably initialized. */ 02182 { rpmTag tag = he->tag; 02183 memset(he, 0, sizeof(*he)); 02184 he->tag = tag; 02185 } 02186 name = tagName(he->tag); 02187 02188 if ((sw = headerGetStats(h, 19)) != NULL) /* RPMTS_OP_HDRGET */ 02189 (void) rpmswEnter(sw, 0); 02190 02191 /* Search extensions for specific tag override. */ 02192 if (!(flags & HEADERGET_NOEXTENSION)) 02193 for (ext = exts, extNum = 0; ext != NULL && ext->type != HEADER_EXT_LAST; 02194 ext = (ext->type == HEADER_EXT_MORE ? *ext->u.more : ext+1), extNum++) 02195 { 02196 if (ext->name == NULL || ext->type != HEADER_EXT_TAG) 02197 continue; 02198 if (!xstrcasecmp(ext->name + (sizeof("RPMTAG_")-1), name)) 02199 break; 02200 } 02201 02202 if (ext && ext->name != NULL && ext->type == HEADER_EXT_TAG) { 02203 rc = ext->u.tagFunction(h, he); 02204 rc = (rc == 0); /* XXX invert extension return. */ 02205 } else 02206 rc = intGetEntry(h, he, flags); 02207 02208 if (rc) 02209 rc = rpmheRealloc(he); 02210 02211 if (sw != NULL) (void) rpmswExit(sw, 0); 02212 02213 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 02214 /*@-modfilesys@*/ 02215 /* XXX verify that explicit and implicit types are identical. */ 02216 if (rc) 02217 tagTypeValidate(he); 02218 /*@=modfilesys@*/ 02219 #endif 02220 02221 /*@-modfilesys@*/ 02222 if (!((rc == 0 && he->freeData == 0 && he->p.ptr == NULL) || 02223 (rc == 1 && he->freeData == 1 && he->p.ptr != NULL))) 02224 { 02225 if (_hdr_debug) 02226 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); 02227 } 02228 /*@=modfilesys@*/ 02229 02230 return rc; 02231 } 02232 02233 int headerPut(Header h, HE_t he, /*@unused@*/ unsigned int flags) 02234 { 02235 int rc; 02236 02237 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 02238 /*@-modfilesys@*/ 02239 /* XXX verify that explicit and implicit types are identical. */ 02240 tagTypeValidate(he); 02241 /*@=modfilesys@*/ 02242 #endif 02243 02244 if (he->append) 02245 rc = headerAddOrAppendEntry(h, he); 02246 else 02247 rc = headerAddEntry(h, he); 02248 02249 return rc; 02250 } 02251 02252 int headerDel(Header h, HE_t he, /*@unused@*/ unsigned int flags) 02253 /*@modifies h @*/ 02254 { 02255 return headerRemoveEntry(h, he->tag); 02256 } 02257 02258 int headerMod(Header h, HE_t he, /*@unused@*/ unsigned int flags) 02259 /*@modifies h @*/ 02260 { 02261 02262 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 02263 /*@-modfilesys@*/ 02264 /* XXX verify that explicit and implicit types are identical. */ 02265 tagTypeValidate(he); 02266 /*@=modfilesys@*/ 02267 #endif 02268 02269 return headerModifyEntry(h, he); 02270 }