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