diff options
author | jbj <devnull@localhost> | 2000-11-07 13:16:43 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2000-11-07 13:16:43 +0000 |
commit | 636e4b37718ea8f87fcf29f934aa0a03e9bfcc69 (patch) | |
tree | dacb8a92f1982cad14d08db959bbe97d92a5a7da /lib | |
parent | 62c5a919309223a72c05bbcd2e26559bce67def1 (diff) | |
download | rpm-636e4b37718ea8f87fcf29f934aa0a03e9bfcc69.tar.gz rpm-636e4b37718ea8f87fcf29f934aa0a03e9bfcc69.tar.bz2 rpm-636e4b37718ea8f87fcf29f934aa0a03e9bfcc69.zip |
- load headers as single contiguous region.
CVS patchset: 4244
CVS date: 2000/11/07 13:16:43
Diffstat (limited to 'lib')
-rw-r--r-- | lib/header.c | 627 | ||||
-rw-r--r-- | lib/header.h | 56 | ||||
-rw-r--r-- | lib/package.c | 9 | ||||
-rw-r--r-- | lib/rpmlib.h | 17 | ||||
-rw-r--r-- | lib/signature.c | 51 |
5 files changed, 491 insertions, 269 deletions
diff --git a/lib/header.c b/lib/header.c index 569c21d16..9cfc2873d 100644 --- a/lib/header.c +++ b/lib/header.c @@ -23,6 +23,10 @@ #include <rpmio.h> #include <header.h> + +/* XXX avoid rpmlib.h for debugging. */ +/*@observer@*/ const char *const tagName(int tag) /*@*/; + #define INDEX_MALLOC_SIZE 8 #define PARSER_BEGIN 0 @@ -62,19 +66,30 @@ struct entryInfo { */ struct indexEntry { struct entryInfo info; /*!< Description of tag data. */ -/*@owned@*/ void * data; /*!< Location of tag data. */ + void * data; /*!< Location of tag data. */ int length; /*!< Computable, but why bother? */ }; /** + * A single contiguous region from a Header. + */ +typedef struct { + int allocated; /*!< Should region be freed? */ + int len; /*!< No. bytes in region. */ +/*@shared@*/ void * data; /*!< Region data. */ +} * headerRegion; + +/** * The Header data structure. */ struct headerToken { +/*@owned@*/ headerRegion regions;/*!< Data regions. */ struct indexEntry *index; /*!< Array of tags. */ + int nregions; /*!< No. of data regions. */ int indexUsed; /*!< Current size of tag array. */ int indexAlloced; /*!< Allocated size of tag array. */ - int sorted; /*!< Header is sorted by tag value? */ -/*@refs@*/ int usageCount; /*!< Reference count. */ + int sorted; /*!< Are header entries sorted? */ +/*@refs@*/ int nrefs; /*!< Reference count. */ }; /** @@ -180,13 +195,9 @@ static void headerProbe(Header h, const char *msg) #endif /* HAVE_MCHECK_H */ static void copyEntry(const struct indexEntry * entry, /*@out@*/ int_32 * type, - /*@out@*/ void ** p, /*@out@*/ int_32 * c, int minimizeMemory) + /*@out@*/ const void ** p, /*@out@*/ int_32 * c, int minimizeMemory) /*@modifies *type, *p, *c @*/ { - int i, tableSize; - char ** ptrEntry; - char * chptr; - if (type) *type = entry->info.type; if (c) @@ -204,14 +215,18 @@ static void copyEntry(const struct indexEntry * entry, /*@out@*/ int_32 * type, /*@fallthrough@*/ case RPM_STRING_ARRAY_TYPE: case RPM_I18NSTRING_TYPE: - i = entry->info.count; - tableSize = i * sizeof(char *); + { const char ** ptrEntry; + char * chptr; + int i = entry->info.count; + int tableSize = i * sizeof(char *); + if (minimizeMemory) { ptrEntry = *p = xmalloc(tableSize); chptr = entry->data; } else { - ptrEntry = *p = xmalloc(tableSize + entry->length); /* XXX memory leak */ - chptr = ((char *) *p) + tableSize; + chptr = xmalloc(tableSize + entry->length); /* XXX memory leak */ + ptrEntry = *p = (void *)chptr; + chptr += tableSize; memcpy(chptr, entry->data, entry->length); } while (i--) { @@ -219,7 +234,7 @@ static void copyEntry(const struct indexEntry * entry, /*@out@*/ int_32 * type, chptr = strchr(chptr, 0); chptr++; } - break; + } break; default: *p = entry->data; @@ -315,7 +330,7 @@ void headerFreeIterator(HeaderIterator iter) } int headerNextIterator(HeaderIterator iter, - int_32 *tag, int_32 *type, void **p, int_32 *c) + int_32 * tag, int_32 * type, const void ** p, int_32 * c) { Header h = iter->h; int slot = iter->next_index; @@ -332,26 +347,41 @@ int headerNextIterator(HeaderIterator iter, return 1; } -static int indexCmp(const void *ap, const void *bp) /*@*/ +static int indexCmp(const void *avp, const void *bvp) /*@*/ { - int_32 a = ((const struct indexEntry *)ap)->info.tag; - int_32 b = ((const struct indexEntry *)bp)->info.tag; - - return (a - b); + const struct indexEntry * ap = avp; + const struct indexEntry * bp = bvp; + return (ap->info.tag - bp->info.tag); } void headerSort(Header h) { if (!h->sorted) { - qsort(h->index, h->indexUsed, sizeof(struct indexEntry), indexCmp); + qsort(h->index, h->indexUsed, sizeof(*h->index), indexCmp); h->sorted = 1; } } +static int offsetCmp(const void *avp, const void *bvp) /*@*/ +{ + const struct indexEntry * ap = avp; + const struct indexEntry * bp = bvp; + int rc = (ap->info.offset - bp->info.offset); + + if (rc == 0) + rc = (ap->info.tag - bp->info.tag); + return rc; +} + +void headerUnsort(Header h) +{ + qsort(h->index, h->indexUsed, sizeof(*h->index), offsetCmp); +} + Header headerCopy(Header h) { int_32 tag, type, count; - void *ptr; + const void *ptr; HeaderIterator headerIter; Header res = headerNew(); @@ -360,7 +390,7 @@ Header headerCopy(Header h) while (headerNextIterator(headerIter, &tag, &type, &ptr, &count)) { headerAddEntry(res, tag, type, ptr, count); if (type == RPM_STRING_ARRAY_TYPE || - type == RPM_I18NSTRING_TYPE) free(ptr); + type == RPM_I18NSTRING_TYPE) free((void *)ptr); } res->sorted = 1; @@ -375,108 +405,193 @@ Header headerCopy(Header h) /* Header loading and unloading */ /* */ /********************************************************************/ +#if 0 +static void fprIndexEntry(const char *msg, struct indexEntry *entry, int i) +{ + const char * val; + fprintf(stderr, "%6d %*s %p: %p[%d]", + i, (3*entry->info.offset), "", + entry, entry->data, entry->length); + + switch (entry->info.type) { + case RPM_STRING_TYPE: + case RPM_STRING_ARRAY_TYPE: + case RPM_I18NSTRING_TYPE: + val = (const char *) entry->data; + break; + case RPM_CHAR_TYPE: + val = "CHAR"; + break; + case RPM_INT8_TYPE: + val = "INT8"; + break; + case RPM_INT16_TYPE: + val = "INT16"; + break; + case RPM_INT32_TYPE: + val = "INT32"; + break; + case RPM_BIN_TYPE: + val = "BIN"; + break; + default: + val = ""; + break; + } + + fprintf(stderr, "\t%-8.8s %s(%d) %s\n", + val, + tagName(entry->info.tag), entry->info.tag, + (msg ? msg : "")); +} +#endif Header headerLoad(void *pv) { - int_32 il; /* index length, data length */ - char *p = pv; + int_32 *ei = (int_32 *) pv; + int_32 il = ntohl(ei[0]); /* index length */ + int_32 dl = ntohl(ei[1]); /* data length */ + int pvlen = sizeof(il) + sizeof(dl) + + (il * sizeof(struct entryInfo)) + dl; + char *p = (char *) &ei[2]; + Header h = xmalloc(sizeof(*h)); + const char * dataStart; struct entryInfo * pe; struct indexEntry * entry; - struct headerToken *h = xmalloc(sizeof(struct headerToken)); - const char * src; - char * dst; + int prevtag = 0; int i; - int count; - - il = ntohl(*((int_32 *) p)); - p += sizeof(int_32); - /* we can skip the data length -- we only store this to allow reading - from disk */ - p += sizeof(int_32); + h->nregions = 1; + h->regions = xcalloc(h->nregions, sizeof(*h->regions)); + h->regions[0].allocated = 0; + h->regions[0].len = pvlen; + h->regions[0].data = pv; - h->indexAlloced = il; + h->indexAlloced = il + 1; h->indexUsed = il; - h->index = xmalloc(sizeof(struct indexEntry) * il); - h->usageCount = 1; - - /* This assumes you only headerLoad() something you headerUnload()-ed */ + h->index = xcalloc(h->indexAlloced, sizeof(struct indexEntry)); h->sorted = 1; + h->nrefs = 1; pe = (struct entryInfo *) p; - dataStart = (char *) (pe + h->indexUsed); + dataStart = (char *) (pe + il); + + entry = h->index; + i = 0; + if (htonl(pe->tag) != HEADER_IMAGE) { + entry->info.type = RPM_BIN_TYPE; + prevtag = entry->info.tag = HEADER_IMAGE; + entry->info.count = 1; + entry->info.offset = h->nregions - 1; + entry->data = h->regions[0].data; + entry->length = h->regions[0].len; + entry++; + i++; + il++; + h->indexUsed++; + } + + for (; i < h->indexUsed; i++, entry++, pe++) { + char * t; + int j; - for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++, pe++) { entry->info.type = htonl(pe->type); + if (entry->info.type < RPM_MIN_TYPE || entry->info.type > RPM_MAX_TYPE) + return NULL; + entry->info.tag = htonl(pe->tag); - entry->info.count = htonl(pe->count); - entry->info.offset = -1; - if (entry->info.type < RPM_MIN_TYPE || - entry->info.type > RPM_MAX_TYPE) return NULL; + /* Check that header entries are sorted. */ + if (entry->info.tag < prevtag) + h->sorted = 0; + prevtag = entry->info.tag; - src = dataStart + htonl(pe->offset); - entry->length = dataLength(entry->info.type, src, - entry->info.count, 1); - entry->data = dst = xmalloc(entry->length); + entry->info.count = htonl(pe->count); + entry->info.offset = htonl(pe->offset); + + if (entry->info.offset < 0) { + h->regions = xrealloc(h->regions, + (h->nregions + 1) * sizeof(*h->regions)); + h->regions[h->nregions].allocated = 0; + h->regions[h->nregions].len = 0; /* XXX WRONG */ + h->regions[h->nregions].data = dataStart + entry->info.offset; + h->nregions++; + + entry->info.offset = h->nregions - 1; + entry->data = h->regions[entry->info.offset].data; + entry->length = h->regions[entry->info.offset].len; + continue; + } - /* copy data w/ endian conversions */ + entry->data = t = dataStart + entry->info.offset; + entry->length = dataLength(entry->info.type, t, entry->info.count, 1); + entry->info.offset = h->nregions; + + /* Perform endian conversions. */ switch (entry->info.type) { case RPM_INT32_TYPE: - count = entry->info.count; - while (count--) { - *((int_32 *)dst) = htonl(*((int_32 *)src)); - src += sizeof(int_32); - dst += sizeof(int_32); - } + for (j = entry->info.count; j > 0; j--, t += sizeof(int_32)) + *((int_32 *)t) = htonl(*((int_32 *)t)); break; - case RPM_INT16_TYPE: - count = entry->info.count; - while (count--) { - *((int_16 *)dst) = htons(*((int_16 *)src)); - src += sizeof(int_16); - dst += sizeof(int_16); - } - break; - - default: - memcpy(dst, src, entry->length); + for (j = entry->info.count; j > 0; j--, t += sizeof(int_16)) + *((int_16 *)t) = htons(*((int_16 *)t)); break; } } + if (!h->sorted) headerSort(h); + return h; } -static void *doHeaderUnload(Header h, /*@out@*/int * lengthPtr) +static /*@only@*/ void * doHeaderUnload(Header h, /*@out@*/ int * lengthPtr) /*@modifies h, *lengthPtr @*/ { - int i; - int type, diff; - void *p; - int_32 *pi; + int_32 * ei; struct entryInfo * pe; - struct indexEntry * entry; - char * chptr, * src, * dataStart; - int count; + const char * dataStart; + char * te; + unsigned pad = 0; + unsigned len; + int_32 il; + int_32 dl; + struct indexEntry * entry; + int i; - headerSort(h); + /* Sort entries by (region,tag) */ + headerUnsort(h); + i = h->sorted; + h->sorted = 1; + len = headerSizeof(h, HEADER_MAGIC_NO); + h->sorted = i; + + il = h->indexUsed; + dl = len - (sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo))); + entry = h->index; + i = 0; - *lengthPtr = headerSizeof(h, 0); - pi = p = xmalloc(*lengthPtr); + if (entry->info.tag == HEADER_IMAGE) { + entry++; + i++; + il--; + dl += sizeof(struct entryInfo); + } - *pi++ = htonl(h->indexUsed); + ei = xmalloc(len); + ei[0] = htonl(il); + ei[1] = htonl(dl); - /* data length */ - *pi++ = htonl(*lengthPtr - sizeof(int_32) - sizeof(int_32) - - (sizeof(struct entryInfo) * h->indexUsed)); + pe = (struct entryInfo *) &ei[2]; + dataStart = te = (char *) (pe + il); - pe = (struct entryInfo *) pi; - dataStart = chptr = (char *) (pe + h->indexUsed); + for (; i < h->indexUsed; i++, entry++, pe++) { + const char * src; + unsigned diff; + int_32 type; + int count; - for (i = 0, entry = h->index; i < h->indexUsed; i++, entry++, pe++) { pe->type = htonl(entry->info.type); pe->tag = htonl(entry->info.tag); pe->count = htonl(entry->info.count); @@ -484,14 +599,15 @@ static void *doHeaderUnload(Header h, /*@out@*/int * lengthPtr) /* Alignment */ type = entry->info.type; if (typeSizes[type] > 1) { - diff = typeSizes[type] - ((chptr - dataStart) % typeSizes[type]); + diff = typeSizes[type] - ((te - dataStart) % typeSizes[type]); if (diff != typeSizes[type]) { - memset(chptr, 0, diff); - chptr += diff; + memset(te, 0, diff); + te += diff; + pad += diff; } } - pe->offset = htonl(chptr - dataStart); + pe->offset = htonl(te - dataStart); /* copy data w/ endian conversions */ switch (entry->info.type) { @@ -499,8 +615,8 @@ static void *doHeaderUnload(Header h, /*@out@*/int * lengthPtr) count = entry->info.count; src = entry->data; while (count--) { - *((int_32 *)chptr) = htonl(*((int_32 *)src)); - chptr += sizeof(int_32); + *((int_32 *)te) = htonl(*((int_32 *)src)); + te += sizeof(int_32); src += sizeof(int_32); } break; @@ -509,31 +625,44 @@ static void *doHeaderUnload(Header h, /*@out@*/int * lengthPtr) count = entry->info.count; src = entry->data; while (count--) { - *((int_16 *)chptr) = htons(*((int_16 *)src)); - chptr += sizeof(int_16); + *((int_16 *)te) = htons(*((int_16 *)src)); + te += sizeof(int_16); src += sizeof(int_16); } break; default: - memcpy(chptr, entry->data, entry->length); - chptr += entry->length; + memcpy(te, entry->data, entry->length); + te += entry->length; break; } } - return p; + if (lengthPtr) + *lengthPtr = len; + + headerSort(h); + + return (void *)ei; } void *headerUnload(Header h) { - void * uh; int length; - - uh = doHeaderUnload(h, &length); + void * uh = doHeaderUnload(h, &length); return uh; } +Header headerReload(Header h) +{ + int length; + void * uh = doHeaderUnload(h, &length); + headerFree(h); + h = headerLoad(uh); + h->regions[0].allocated = 1; + return h; +} + /********************************************************************/ /* */ /* Reading and writing headers */ @@ -542,47 +671,42 @@ void *headerUnload(Header h) int headerWrite(FD_t fd, Header h, enum hMagic magicp) { - void * p; int length; - int_32 l; + void * uh = doHeaderUnload(h, &length); ssize_t nb; - p = doHeaderUnload(h, &length); + switch (magicp) { + case HEADER_MAGIC_YES: + { int_32 l = htonl(0); - if (magicp) { nb = Fwrite(header_magic, sizeof(char), sizeof(header_magic), fd); - if (nb != sizeof(header_magic)) { - free(p); - return 1; - } - l = htonl(0); + if (nb != sizeof(header_magic)) + goto exit; nb = Fwrite(&l, sizeof(char), sizeof(l), fd); - if (nb != sizeof(l)) { - free(p); - return 1; - } - } - - nb = Fwrite(p, sizeof(char), length, fd); - if (nb != length) { - free(p); - return 1; + if (nb != sizeof(l)) + goto exit; + } break; + case HEADER_MAGIC_NO: + break; } - free(p); - return 0; + nb = Fwrite(uh, sizeof(char), length, fd); + +exit: + free(uh); + return (nb == length ? 0 : 1); } Header headerRead(FD_t fd, enum hMagic magicp) { - int_32 block[40]; + int_32 block[4]; int_32 reserved; - int_32 * p; - int_32 il, dl; + int_32 * ei; + int_32 il; + int_32 dl; int_32 magic; Header h; - void * dataBlock; - int totalSize; + int len; int i; memset(block, 0, sizeof(block)); @@ -590,41 +714,42 @@ Header headerRead(FD_t fd, enum hMagic magicp) if (magicp == HEADER_MAGIC_YES) i += 2; - if (timedRead(fd, (char *)block, i * sizeof(*block)) != (i * sizeof(*block))) + if (timedRead(fd, (char *)block, i*sizeof(*block)) != (i * sizeof(*block))) return NULL; + i = 0; if (magicp == HEADER_MAGIC_YES) { magic = block[i++]; if (memcmp(&magic, header_magic, sizeof(magic))) return NULL; - reserved = block[i++]; } il = ntohl(block[i++]); dl = ntohl(block[i++]); - totalSize = sizeof(int_32) + sizeof(int_32) + - (il * sizeof(struct entryInfo)) + dl; + len = sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo)) + dl; /* * XXX Limit total size of header to 32Mb (~16 times largest known size). */ - if (totalSize > (32*1024*1024)) + if (len > (32*1024*1024)) return NULL; - dataBlock = p = xmalloc(totalSize); - *p++ = htonl(il); - *p++ = htonl(dl); + ei = xmalloc(len); + ei[0] = htonl(il); + ei[1] = htonl(dl); + len -= sizeof(il) + sizeof(dl); - totalSize -= sizeof(int_32) + sizeof(int_32); - if (timedRead(fd, (char *)p, totalSize) != totalSize) + if (timedRead(fd, (char *)&ei[2], len) != len) { + free(ei); return NULL; + } - h = headerLoad(dataBlock); + h = headerLoad(ei); - free(dataBlock); + h->regions[0].allocated = 1; return h; } @@ -761,7 +886,6 @@ void headerDump(Header h, FILE *f, int flags, /********************************************************************/ static struct indexEntry *findEntry(Header h, int_32 tag, int_32 type) - /*@modifies h @*/ { struct indexEntry * entry, * entry2, * last; struct indexEntry key; @@ -771,11 +895,12 @@ static struct indexEntry *findEntry(Header h, int_32 tag, int_32 type) key.info.tag = tag; entry2 = entry = - bsearch(&key, h->index, h->indexUsed, sizeof(struct indexEntry), - indexCmp); - if (!entry) return NULL; + bsearch(&key, h->index, h->indexUsed, sizeof(*entry), indexCmp); + if (entry == NULL) + return NULL; - if (type == RPM_NULL_TYPE) return entry; + if (type == RPM_NULL_TYPE) + return entry; /* look backwards */ while (entry->info.tag == tag && entry->info.type != type && @@ -799,7 +924,8 @@ int headerIsEntry(Header h, int_32 tag) return (findEntry(h, tag, RPM_NULL_TYPE) ? 1 : 0); } -int headerGetRawEntry(Header h, int_32 tag, int_32 *type, void **p, int_32 *c) +int headerGetRawEntry(Header h, int_32 tag, int_32 * type, const void ** p, + int_32 *c) { struct indexEntry * entry; @@ -936,8 +1062,8 @@ headerFindI18NString(Header h, struct indexEntry *entry) } static int intGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, - /*@out@*/ void **p, /*@out@*/ int_32 *c, int minMem) - /*@modifies h, *type, *p, *c @*/ + /*@out@*/ const void **p, /*@out@*/ int_32 *c, int minMem) + /*@modifies *type, *p, *c @*/ { struct indexEntry * entry; char * chptr; @@ -968,12 +1094,12 @@ static int intGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, int headerGetEntryMinMemory(Header h, int_32 tag, int_32 *type, void **p, int_32 *c) { - return intGetEntry(h, tag, type, p, c, 1); + return intGetEntry(h, tag, type, (const void **)p, c, 1); } int headerGetEntry(Header h, int_32 tag, int_32 * type, void **p, int_32 * c) { - return intGetEntry(h, tag, type, p, c, 0); + return intGetEntry(h, tag, type, (const void **)p, c, 0); } /********************************************************************/ @@ -984,68 +1110,104 @@ int headerGetEntry(Header h, int_32 tag, int_32 * type, void **p, int_32 * c) Header headerNew() { - Header h = xmalloc(sizeof(struct headerToken)); + Header h = xcalloc(1, sizeof(*h)); + h->nregions = 0; h->indexAlloced = INDEX_MALLOC_SIZE; - h->index = xcalloc(h->indexAlloced, sizeof(struct indexEntry)); h->indexUsed = 0; + h->sorted = 1; + h->nrefs = 1; - h->sorted = 0; - h->usageCount = 1; + h->index = (h->indexAlloced + ? xcalloc(h->indexAlloced, sizeof(*h->index)) + : NULL); + h->regions = (h->nregions + ? xcalloc(h->nregions, sizeof(*h->regions)) + : NULL); - return (Header) h; + return h; } void headerFree(Header h) { - int i; - - if (--h->usageCount) return; - for (i = 0; i < h->indexUsed; i++) - free(h->index[i].data); + if (--h->nrefs) + return; + if (h->index) { + struct indexEntry * entry = h->index; + int i; + for (i = 0; i < h->indexUsed; i++, entry++) { + if (entry->info.tag < HEADER_I18NTABLE) + continue; + if (entry->info.offset > 0) + continue; + free(entry->data); + entry->data = NULL; + } + free(h->index); + h->index = NULL; + } - free(h->index); + if (h->regions) { + /* XXX only region[0] needs to be free'ed if regions are nested. */ + if (h->regions[0].allocated) { + free(h->regions[0].data); + h->regions[0].data = NULL; + } + free(h->regions); + h->regions = NULL; + } /*@-refcounttrans@*/ free(h); /*@=refcounttrans@*/ } Header headerLink(Header h) { HEADERPROBE(h, "headerLink"); - h->usageCount++; + h->nrefs++; /*@-refcounttrans@*/ return h; /*@=refcounttrans@*/ } int headerUsageCount(Header h) { - return h->usageCount; + return h->nrefs; } unsigned int headerSizeof(Header h, enum hMagic magicp) { - unsigned int size; - int i, diff; - int_32 type; + struct indexEntry * entry; + unsigned int size = 0, pad = 0; + int i; headerSort(h); - size = sizeof(int_32); /* count of index entries */ - size += sizeof(int_32); /* length of data */ - size += sizeof(struct entryInfo) * h->indexUsed; - if (magicp) - size += 8; + entry = h->index; + for (i = 0; i < h->indexUsed; i++, entry++) { + unsigned diff; + int_32 type; + + if (entry->info.tag < HEADER_I18NTABLE) { + size -= sizeof(struct entryInfo); + continue; + } - for (i = 0; i < h->indexUsed; i++) { /* Alignment */ - type = h->index[i].info.type; + type = entry->info.type; if (typeSizes[type] > 1) { diff = typeSizes[type] - (size % typeSizes[type]); - if (diff != typeSizes[type]) + if (diff != typeSizes[type]) { size += diff; + pad += diff; + } } - size += h->index[i].length; + size += entry->length; } + size += sizeof(struct entryInfo) * h->indexUsed; + size += sizeof(int_32); /* count of index entries */ + size += sizeof(int_32); /* length of data */ + if (magicp) + size += 2*sizeof(int_32); + return size; } @@ -1082,15 +1244,13 @@ static void * grabData(int_32 type, const void * p, int_32 c, /*@out@*/ int * lengthPtr) /*@modifies *lengthPtr @*/ { - int length; - void * data; - - length = dataLength(type, p, c, 0); - data = xmalloc(length); + int length = dataLength(type, p, c, 0); + void * data = xmalloc(length); copyData(type, data, p, c, length); - *lengthPtr = length; + if (lengthPtr) + *lengthPtr = length; return data; } @@ -1104,8 +1264,6 @@ int headerAddEntry(Header h, int_32 tag, int_32 type, const void *p, int_32 c) { struct indexEntry *entry; - h->sorted = 0; - if (c <= 0) { fprintf(stderr, _("Bad count for headerAddEntry(): %d\n"), (int) c); exit(EXIT_FAILURE); @@ -1120,15 +1278,20 @@ int headerAddEntry(Header h, int_32 tag, int_32 type, const void *p, int_32 c) } /* Fill in the index */ - entry = h->index + h->indexUsed++; + entry = h->index + h->indexUsed; entry->info.tag = tag; entry->info.type = type; entry->info.count = c; - entry->info.offset = -1; - + entry->info.offset = 0; entry->data = grabData(type, p, c, &entry->length); - h->sorted = 0; + if (h->indexUsed > 0 && tag < h->index[h->indexUsed-1].info.tag) + h->sorted = 0; + h->indexUsed++; + +#ifdef DYING + headerSort(h); +#endif return 1; } @@ -1139,15 +1302,14 @@ headerGetLangs(Header h) char **s, *e, **table; int i, type, count; - if (!headerGetRawEntry(h, HEADER_I18NTABLE, &type, (void **)&s, &count)) + if (!headerGetRawEntry(h, HEADER_I18NTABLE, &type, (const void **)&s, &count)) return NULL; if ((table = (char **)xcalloc((count+1), sizeof(char *))) == NULL) return NULL; - for (i = 0, e = *s; i < count > 0; i++, e += strlen(e)+1) { + for (i = 0, e = *s; i < count > 0; i++, e += strlen(e)+1) table[i] = e; - } table[count] = NULL; return table; @@ -1198,7 +1360,13 @@ int headerAddI18NString(Header h, int_32 tag, const char * string, const char * if (langNum >= table->info.count) { length = strlen(lang) + 1; - table->data = xrealloc(table->data, table->length + length); + if (table->info.offset > 0) { + char * t = xmalloc(table->length + length); + memcpy(t, table->data, table->length); + table->data = t; + table->info.offset = 0; + } else + table->data = xrealloc(table->data, table->length + length); memcpy(((char *)table->data) + table->length, lang, length); table->length += length; table->info.count++; @@ -1215,7 +1383,13 @@ int headerAddI18NString(Header h, int_32 tag, const char * string, const char * ghosts = langNum - entry->info.count; length = strlen(string) + 1 + ghosts; - entry->data = xrealloc(entry->data, entry->length + length); + if (entry->info.offset > 0) { + char * t = xmalloc(entry->length + length); + memcpy(t, entry->data, entry->length); + entry->data = t; + entry->info.offset = 0; + } else + entry->data = xrealloc(entry->data, entry->length + length); memset(((char *)entry->data) + entry->length, '\0', ghosts); strcpy(((char *)entry->data) + entry->length + ghosts, string); @@ -1254,7 +1428,10 @@ int headerAddI18NString(Header h, int_32 tag, const char * string, const char * /* Replace I18N string array */ entry->length -= strlen(be) + 1; entry->length += sn; - free(entry->data); + if (entry->info.offset > 0) { + entry->info.offset = 0; + } else + free(entry->data); entry->data = buf; } @@ -1284,19 +1461,20 @@ int headerModifyEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c) entry->info.type = type; entry->data = grabData(type, p, c, &entry->length); - free(oldData); - + if (entry->info.offset > 0) { + entry->info.offset = 0; + } else + free(oldData); + return 1; } int headerAddOrAppendEntry(Header h, int_32 tag, int_32 type, void * p, int_32 c) { - if (findEntry(h, tag, type)) { - return headerAppendEntry(h, tag, type, p, c); - } else { - return headerAddEntry(h, tag, type, p, c); - } + return (findEntry(h, tag, type) + ? headerAppendEntry(h, tag, type, p, c) + : headerAddEntry(h, tag, type, p, c)); } int headerAppendEntry(Header h, int_32 tag, int_32 type, void * p, int_32 c) @@ -1316,7 +1494,13 @@ int headerAppendEntry(Header h, int_32 tag, int_32 type, void * p, int_32 c) length = dataLength(type, p, c, 0); - entry->data = xrealloc(entry->data, entry->length + length); + if (entry->info.offset > 0) { + char * t = xmalloc(entry->length + length); + memcpy(t, entry->data, entry->length); + entry->data = t; + entry->info.offset = 0; + } else + entry->data = xrealloc(entry->data, entry->length + length); copyData(type, ((char *) entry->data) + entry->length, p, c, length); entry->length += length; @@ -1328,15 +1512,36 @@ int headerAppendEntry(Header h, int_32 tag, int_32 type, void * p, int_32 c) int headerRemoveEntry(Header h, int_32 tag) { - struct indexEntry * entry, * last; + struct indexEntry * last = h->index + h->indexUsed; + struct indexEntry * entry, * first; + int ne; entry = findEntry(h, tag, RPM_NULL_TYPE); if (!entry) return 1; - /* make sure entry points to the first occurence of this tag */ + /* Make sure entry points to the first occurence of this tag. */ while (entry > h->index && (entry - 1)->info.tag == tag) entry--; + /* Free data for tags being removed. */ + for (first = entry; first < last; first++) { + if (first->info.tag != tag) + break; + if (first->info.offset > 0) + continue; + free(first->data); + first->data = NULL; + } + + ne = (first - entry); + if (ne > 0) { + h->indexUsed -= ne; + ne = last - first; + if (ne > 0) + memmove(entry, first, (ne * sizeof(*entry))); + } + +#if 0 /* We might be better off just counting the number of items off the end and issuing one big memcpy, but memcpy() doesn't have to work on overlapping regions thanks to ANSI <sigh>. A alloca() and two @@ -1346,14 +1551,21 @@ int headerRemoveEntry(Header h, int_32 tag) remember that this repeating this is basically nlogn thanks to this dumb implementation (but n is the best we'd do anyway) */ - last = h->index + h->indexUsed; + if (entry->info.offset > 0) { + char * t = xmalloc(entry->length); + memcpy(t, entry->data, entry->length); + entry->data = t; + entry->info.offset = 0; + } + while (entry->info.tag == tag && entry < last) { free(entry->data); *(entry++) = *(--last); } h->indexUsed = last - h->index; - h->sorted = 0; + headerSort(h); +#endif return 0; } @@ -1405,15 +1617,15 @@ static void findTag(char * name, const struct headerTagTableEntry * tags, { const struct headerTagTableEntry * entry; const struct headerSprintfExtension * ext; - char * tagname; + const char * tagname; *tagMatch = NULL; *extMatch = NULL; if (strncmp("RPMTAG_", name, sizeof("RPMTAG_")-1)) { - tagname = alloca(strlen(name) + 10); - strcpy(tagname, "RPMTAG_"); - strcat(tagname, name); + char * t = alloca(strlen(name) + sizeof("RPMTAG_")); + (void) stpcpy( stpcpy(t, "RPMTAG_"), name); + tagname = t; } else { tagname = name; } @@ -1873,8 +2085,7 @@ static char * formatValue(struct sprintfTag * tag, Header h, type = RPM_INT32_TYPE; } - strcpy(buf, "%"); - strcat(buf, tag->format); + (void) stpcpy( stpcpy(buf, "%"), tag->format); if (tag->type) { ext = extensions; diff --git a/lib/header.h b/lib/header.h index f11beacc9..bc851d6c0 100644 --- a/lib/header.h +++ b/lib/header.h @@ -191,7 +191,7 @@ Header headerRead(FD_t fd, enum hMagic magicp) * @return 0 on success, 1 on error */ int headerWrite(FD_t fd, Header h, enum hMagic magicp) - /*@modifies fd, h @*/; + /*@modifies fd @*/; /** \ingroup header * Return size of on-disk header representation in bytes. @@ -199,8 +199,7 @@ int headerWrite(FD_t fd, Header h, enum hMagic magicp) * @param magicp include size of 8 bytes for (magic, 0)? * @return size of on-disk header */ -unsigned int headerSizeof(Header h, enum hMagic magicp) - /*@modifies h @*/; +unsigned int headerSizeof(Header h, enum hMagic magicp) /*@*/; /** \ingroup header * Convert header to in-memory representation. @@ -214,8 +213,15 @@ Header headerLoad(void *p) /*@*/; * @param h header (with pointers) * @return on-disk header (with offsets) */ -void *headerUnload(Header h) - /*@modifes h @*/; +void *headerUnload(Header h) /*@*/; + +/** \ingroup header + * Convert header to on-disk representation, and then reload. + * This is used to insure that all header data is in one chunk. + * @param h header (with pointers) + * @return on-disk header (with offsets) + */ +Header headerReload(/*@only@*/ Header h) /*@*/; /** \ingroup header * Create new (empty) header instance. @@ -228,7 +234,8 @@ Header headerNew(void) /*@*/; * @param h header * @return referenced header instance */ -Header headerLink(Header h) /*@modifies h @*/; +Header headerLink(Header h) + /*@modifies h @*/; /** \ingroup header * Dereference a header instance. @@ -270,7 +277,7 @@ typedef const char * errmsg_t; const struct headerTagTableEntry * tags, const struct headerSprintfExtension * extentions, /*@out@*/ errmsg_t * errmsg) - /*@modifies h, *errmsg @*/; + /*@modifies *errmsg @*/; /** \ingroup header * Add tag to header. @@ -308,8 +315,7 @@ int headerModifyEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c) * @param h header * @return array of locales (or NULL on error) */ -char ** headerGetLangs(Header h) - /*@modifies h @*/; +char ** headerGetLangs(Header h) /*@*/; /** \ingroup header * Add locale specific tag to header. @@ -379,7 +385,7 @@ int headerAddOrAppendEntry(Header h, int_32 tag, int_32 type, */ int headerGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, /*@out@*/ void **p, /*@out@*/int_32 *c) - /*@modifies h, *type, *p, *c @*/; + /*@modifies *type, *p, *c @*/; /** \ingroup header * Retrieve tag value using header internal array. @@ -395,7 +401,7 @@ int headerGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, */ int headerGetEntryMinMemory(Header h, int_32 tag, int_32 *type, /*@out@*/ void **p, /*@out@*/ int_32 *c) - /*@modifies h, *type, *p, *c @*/; + /*@modifies *type, *p, *c @*/; /** \ingroup header * Retrieve tag value with type match. @@ -410,8 +416,8 @@ int headerGetEntryMinMemory(Header h, int_32 tag, int_32 *type, * @return 1 on success, 0 on failure */ int headerGetRawEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, - /*@out@*/ void **p, /*@out@*/ int_32 *c) - /*@modifies h, *type, *p, *c @*/; + /*@out@*/ const void **p, /*@out@*/ int_32 *c) + /*@modifies *type, *p, *c @*/; /** \ingroup header * Check if tag is in header. @@ -419,8 +425,7 @@ int headerGetRawEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, * @param tag tag * @return 1 on success, 0 on failure */ -int headerIsEntry(Header h, int_32 tag) - /*@modifies h @*/; +int headerIsEntry(Header h, int_32 tag) /*@*/; /** \ingroup header * Delete tag in header. @@ -440,7 +445,7 @@ int headerRemoveEntry(Header h, int_32 tag) * @return header tag iterator */ HeaderIterator headerInitIterator(Header h) - /*@modifies h @*/; + /*@modifies h*/; /** \ingroup header * Return next tag from header. @@ -452,8 +457,8 @@ HeaderIterator headerInitIterator(Header h) * @return 1 on success, 0 on failure */ int headerNextIterator(HeaderIterator iter, - /*@out@*/ int_32 *tag, /*@out@*/ int_32 *type, /*@out@*/ void **p, - /*@out@*/ int_32 *c) + /*@out@*/ int_32 * tag, /*@out@*/ int_32 * type, + /*@out@*/ const void ** p, /*@out@*/ int_32 * c) /*@modifies iter, *tag, *type, *p, *c @*/; /** \ingroup header @@ -478,6 +483,13 @@ void headerSort(Header h) /*@modifies h @*/; /** \ingroup header + * Restore tags in header to original ordering. + * @param h header + */ +void headerUnsort(Header h) + /*@modifies h @*/; + +/** \ingroup header * Duplicate tag values from one header into another. * @param headerFrom source header * @param headerTo destination header @@ -505,9 +517,11 @@ typedef enum rpmTagType_e { } rpmTagType; -/* Tags -- general use tags should start at 1000 (RPM's tag space starts - there) */ - +/** + * Header private tags. + * @note General use tags should start at 1000 (RPM's tag space starts there). + */ +#define HEADER_IMAGE 90 #define HEADER_I18NTABLE 100 #ifdef __cplusplus diff --git a/lib/package.c b/lib/package.c index c7f03308f..d9400146b 100644 --- a/lib/package.c +++ b/lib/package.c @@ -48,9 +48,8 @@ static int readPackageHeaders(FD_t fd, /*@out@*/ struct rpmlead * leadPtr, /* if fd points to a socket, pipe, etc, sb.st_size is *always* zero */ if (S_ISREG(sb.st_mode) && sb.st_size < sizeof(*lead)) return 1; - if (readLead(fd, lead)) { + if (readLead(fd, lead)) return 2; - } if (lead->magic[0] != RPMLEAD_MAGIC0 || lead->magic[1] != RPMLEAD_MAGIC1 || lead->magic[2] != RPMLEAD_MAGIC2 || lead->magic[3] != RPMLEAD_MAGIC3) { @@ -66,15 +65,13 @@ static int readPackageHeaders(FD_t fd, /*@out@*/ struct rpmlead * leadPtr, case 2: case 3: case 4: - if (rpmReadSignature(fd, sigs, lead->signature_type)) { + if (rpmReadSignature(fd, sigs, lead->signature_type)) return 2; - } *hdr = headerRead(fd, (lead->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO); if (*hdr == NULL) { - if (sigs != NULL) { + if (sigs != NULL) headerFree(*sigs); - } return 2; } diff --git a/lib/rpmlib.h b/lib/rpmlib.h index eaee33a55..8041df51c 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -53,7 +53,7 @@ int rpmReadPackageHeader(FD_t fd, /*@out@*/ Header * hdr, * @return 0 always */ int headerNVR(Header h, /*@out@*/ const char **np, /*@out@*/ const char **vp, - /*@out@*/ const char **rp) /*@modifies h, *np, *vp, *rp @*/; + /*@out@*/ const char **rp) /*@modifies *np, *vp, *rp @*/; /** * Retrieve file names from header. @@ -87,7 +87,7 @@ void rpmBuildFileList(Header h, /*@out@*/ const char *** fileListPtr, */ int rpmHeaderGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, /*@out@*/ void **p, /*@out@*/ int_32 *c) - /*@modifies h, *type, *p, *c @*/; + /*@modifies *type, *p, *c @*/; /** * Retrieve tag info from header. @@ -104,7 +104,7 @@ int rpmHeaderGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type, */ int rpmPackageGetEntry(void *leadp, Header sigs, Header h, int_32 tag, int_32 *type, void **p, int_32 *c) - /*@modifies sigs, h, *type, *p, *c @*/; + /*@modifies *type, *p, *c @*/; /** * Automatically generated table of tag name/value pairs. @@ -132,11 +132,15 @@ extern const struct headerSprintfExtension rpmHeaderFormats[]; /** - * Tags identify data in package headers + * Tags identify data in package headers. * @note tags should not have value 0! */ typedef enum rpmTag_e { + RPMTAG_HEADERIMAGE = HEADER_IMAGE, /*!< Header allocated image. */ + + RPMTAG_HEADERI18NTABLE = HEADER_I18NTABLE, /*!< I18N string locales. */ + /* Retrofit (and uniqify) signature tags for use by tagName() and rpmQuery. */ /* the md5 sum was broken *twice* on big endian machines */ /* XXX 2nd underscore prevents tagTable generation */ @@ -147,7 +151,7 @@ typedef enum rpmTag_e { RPMTAG_SIGLEMD5_2 = RPMTAG_SIG_BASE+4, RPMTAG_SIGMD5 = RPMTAG_SIG_BASE+5, RPMTAG_SIGGPG = RPMTAG_SIG_BASE+6, - RPMTAG_SIGPGP5 = RPMTAG_SIG_BASE+7, /* internal */ + RPMTAG_SIGPGP5 = RPMTAG_SIG_BASE+7, /*!< internal */ RPMTAG_NAME = 1000, RPMTAG_VERSION = 1001, @@ -912,7 +916,8 @@ typedef enum rpmtransFlags_e { * @return no. of entries */ int rpmGetRpmlibProvides(/*@out@*/ const char ***provNames, - /*@out@*/ int **provFlags, /*@out@*/ const char ***provVersions) /*@*/; + /*@out@*/ int **provFlags, /*@out@*/ const char ***provVersions) + /*@ modifies *provNames, *provFlags, *provVersions @*/; /** \ingroup rpmtrans * Compare two versioned dependency ranges, looking for overlap. diff --git a/lib/signature.c b/lib/signature.c index 9cd12382d..ecea5b1ba 100644 --- a/lib/signature.c +++ b/lib/signature.c @@ -128,7 +128,8 @@ int rpmReadSignature(FD_t fd, Header *headerp, short sig_type) int sigSize, pad; int_32 type, count; int_32 *archSize; - Header h; + Header h = NULL; + int rc = 1; /* assume failure */ if (headerp) *headerp = NULL; @@ -136,58 +137,52 @@ int rpmReadSignature(FD_t fd, Header *headerp, short sig_type) switch (sig_type) { case RPMSIG_NONE: rpmMessage(RPMMESS_DEBUG, _("No signature\n")); + rc = 0; break; case RPMSIG_PGP262_1024: rpmMessage(RPMMESS_DEBUG, _("Old PGP signature\n")); /* These are always 256 bytes */ if (timedRead(fd, buf, 256) != 256) - return 1; - if (headerp) { - *headerp = headerNew(); - headerAddEntry(*headerp, RPMSIGTAG_PGP, RPM_BIN_TYPE, buf, 152); - } + break; + h = headerNew(); + headerAddEntry(h, RPMSIGTAG_PGP, RPM_BIN_TYPE, buf, 152); + rc = 0; break; case RPMSIG_MD5: case RPMSIG_MD5_PGP: rpmError(RPMERR_BADSIGTYPE, _("Old (internal-only) signature! How did you get that!?")); - return 1; - /*@notreached@*/ break; + break; case RPMSIG_HEADERSIG: rpmMessage(RPMMESS_DEBUG, _("New Header signature\n")); /* This is a new style signature */ h = headerRead(fd, HEADER_MAGIC_YES); if (h == NULL) - return 1; + break; sigSize = headerSizeof(h, HEADER_MAGIC_YES); pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */ rpmMessage(RPMMESS_DEBUG, _("Signature size: %d\n"), sigSize); rpmMessage(RPMMESS_DEBUG, _("Signature pad : %d\n"), pad); - if (! headerGetEntry(h, RPMSIGTAG_SIZE, &type, (void **)&archSize, &count)) { - headerFree(h); - return 1; - } - if (checkSize(fd, *archSize, sigSize + pad)) { - headerFree(h); - return 1; - } + if (! headerGetEntry(h, RPMSIGTAG_SIZE, &type, (void **)&archSize, &count)) + break; + if (checkSize(fd, *archSize, sigSize + pad)) + break; if (pad) { - if (timedRead(fd, buf, pad) != pad) { - headerFree(h); - return 1; - } - } - if (headerp) { - *headerp = h; - } else { - headerFree(h); + if (timedRead(fd, buf, pad) != pad) + break; } + rc = 0; break; default: - return 1; + break; } - return 0; + if (rc == 0 && headerp) + *headerp = h; + else + headerFree(h); + + return rc; } int rpmWriteSignature(FD_t fd, Header header) |