- finalize per-header methods, accessing headerFoo through vector.
authorjbj <devnull@localhost>
Tue, 19 Jun 2001 16:59:23 +0000 (16:59 +0000)
committerjbj <devnull@localhost>
Tue, 19 Jun 2001 16:59:23 +0000 (16:59 +0000)
CVS patchset: 4880
CVS date: 2001/06/19 16:59:23

14 files changed:
CHANGES
Doxyfile.in
build/files.c
build/parsePreamble.c
lib/Makefile.am
lib/hdrinline.c [deleted file]
lib/hdrinline.h
lib/hdrproto.h
lib/header.c
lib/header.h
lib/header_internal.h
lib/package.c
lib/rpmchecksig.c
po/POTFILES.in

diff --git a/CHANGES b/CHANGES
index 457bf1b..ea2cc50 100644 (file)
--- a/CHANGES
+++ b/CHANGES
        - fix: Ferror returned spurious error for gzdio/bzdio.
        - check for API/ABI creep, diddle up some compatibility.
        - preliminary abstraction to support per-header methods.
+       - finalize per-header methods, accessing headerFoo through vector.
 
 4.0 -> 4.0.[12]
        - add doxygen and lclint annotations most everywhere.
index 1322653..bef1df0 100644 (file)
@@ -359,7 +359,6 @@ INPUT                  = \
        @top_srcdir@/lib/fs.c \
        @top_srcdir@/lib/fsm.c \
        @top_srcdir@/lib/fsm.h \
-       @top_srcdir@/lib/hdrinline.c \
        @top_srcdir@/lib/hdrinline.h \
        @top_srcdir@/lib/hdrproto.h \
        @top_srcdir@/lib/header.c \
index a5cea7f..a8d09d5 100644 (file)
@@ -1826,7 +1826,7 @@ void initSourceHeader(Spec spec)
            break;
        }
     }
-    headerFreeIterator(hi);
+    hi = headerFreeIterator(hi);
 
     /* Add the build restrictions */
     for (hi = headerInitIterator(spec->buildRestrictions);
@@ -1836,7 +1836,7 @@ void initSourceHeader(Spec spec)
        if (ptr)
            (void) headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
     }
-    headerFreeIterator(hi);
+    hi = headerFreeIterator(hi);
 
     if (spec->BANames && spec->BACount > 0) {
        (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDARCHS,
index 161843e..104be59 100644 (file)
@@ -293,7 +293,7 @@ static int checkForDuplicates(Header h, const char * NVR)
                     tagName(tag), NVR);
        res = 1;
     }
-    headerFreeIterator(hi);
+    hi = headerFreeIterator(hi);
 
     return res;
 }
index f1371b2..4376b9f 100644 (file)
@@ -33,7 +33,7 @@ LIBS =
 lib_LTLIBRARIES = librpm.la
 librpm_la_SOURCES = \
        cpio.c depends.c formats.c fs.c fsm.c getdate.c \
-       header.c hdrinline.c header_internal.c \
+       header.c header_internal.c \
        manifest.c md5.c md5sum.c misc.c package.c \
        problems.c poptBT.c poptI.c poptK.c poptQV.c psm.c query.c \
        rpmchecksig.c rpminstall.c rpmlead.c rpmlibprov.c rpmrc.c rpmvercmp.c \
diff --git a/lib/hdrinline.c b/lib/hdrinline.c
deleted file mode 100644 (file)
index ce9392e..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/** \ingroup header
- * \file lib/hdrinline.c
- */
-
-#include "system.h"
-
-#include <header_internal.h>
-
-#include "debug.h"
-
-int _hdrinline_debug = 0;
-
-/*@access Header @*/
-/*@access entryInfo @*/
-/*@access indexEntry @*/
-
-/*@access extensionCache @*/
-/*@access sprintfTag @*/
-/*@access sprintfToken @*/
-
-/**
- * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
- * @param p            memory to free
- * @return             NULL always
- */
-/*@unused@*/ static inline /*@null@*/ void *
-_free(/*@only@*/ /*@null@*/ const void * p) /*@modifies *p @*/
-{
-    if (p != NULL)     free((void *)p);
-    return NULL;
-}
-
-Header headerNew()
-{
-    Header h = xcalloc(1, sizeof(*h));
-
-    /*@-assignexpose@*/
-    h->hv = hv;                /* structure assignment */
-    /*@=assignexpose@*/
-    h->indexAlloced = INDEX_MALLOC_SIZE;
-    h->indexUsed = 0;
-    h->region_allocated = 0;
-    h->sorted = 1;
-    h->legacy = 0;
-    h->nrefs = 1;
-
-    h->index = (h->indexAlloced
-       ? xcalloc(h->indexAlloced, sizeof(*h->index))
-       : NULL);
-
-    /*@-globstate@*/
-    return h;
-    /*@=globstate@*/
-}
-
-Header headerLoad(void * uh)
-{
-    int_32 * ei = (int_32 *) uh;
-    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;
-    void * pv = uh;
-    Header h = xcalloc(1, sizeof(*h));
-    entryInfo pe;
-    char * dataStart;
-    indexEntry entry; 
-    int rdlen;
-    int i;
-
-    ei = (int_32 *) pv;
-    /*@-castexpose@*/
-    pe = (entryInfo) &ei[2];
-    /*@=castexpose@*/
-    dataStart = (char *) (pe + il);
-
-    /*@-assignexpose@*/
-    h->hv = hv;                /* structure assignment */
-    /*@=assignexpose@*/
-    h->indexAlloced = il + 1;
-    h->indexUsed = il;
-    h->index = xcalloc(h->indexAlloced, sizeof(*h->index));
-    h->sorted = 1;
-    h->region_allocated = 0;
-    h->nrefs = 1;
-
-    /*
-     * XXX XFree86-libs, ash, and pdksh from Red Hat 5.2 have bogus
-     * %verifyscript tag that needs to be diddled.
-     */
-    if (ntohl(pe->tag) == 15 &&
-       ntohl(pe->type) == RPM_STRING_TYPE &&
-       ntohl(pe->count) == 1)
-    {
-       pe->tag = htonl(1079);
-    }
-
-    entry = h->index;
-    i = 0;
-    if (!(htonl(pe->tag) < HEADER_I18NTABLE)) {
-       h->legacy = 1;
-       entry->info.type = REGION_TAG_TYPE;
-       entry->info.tag = HEADER_IMAGE;
-       entry->info.count = REGION_TAG_COUNT;
-       entry->info.offset = ((char *)pe - dataStart); /* negative offset */
-
-       /*@-assignexpose@*/
-       entry->data = pe;
-       /*@=assignexpose@*/
-       entry->length = pvlen - sizeof(il) - sizeof(dl);
-       rdlen = regionSwab(entry+1, il, 0, pe, dataStart, entry->info.offset);
-       if (rdlen != dl) goto errxit;
-       entry->rdlen = rdlen;
-       entry++;
-       h->indexUsed++;
-    } else {
-       int nb = ntohl(pe->count);
-       int_32 rdl;
-       int_32 ril;
-
-       h->legacy = 0;
-       entry->info.type = htonl(pe->type);
-       if (entry->info.type < RPM_MIN_TYPE || entry->info.type > RPM_MAX_TYPE)
-           goto errxit;
-       entry->info.count = htonl(pe->count);
-
-       {  int off = ntohl(pe->offset);
-          if (off) {
-               int_32 * stei = memcpy(alloca(nb), dataStart + off, nb);
-               rdl = -ntohl(stei[2]);  /* negative offset */
-               ril = rdl/sizeof(*pe);
-               entry->info.tag = htonl(pe->tag);
-           } else {
-               ril = il;
-               rdl = (ril * sizeof(struct entryInfo));
-               entry->info.tag = HEADER_IMAGE;
-           }
-       }
-       entry->info.offset = -rdl;      /* negative offset */
-
-       /*@-assignexpose@*/
-       entry->data = pe;
-       /*@=assignexpose@*/
-       entry->length = pvlen - sizeof(il) - sizeof(dl);
-       rdlen = regionSwab(entry+1, ril-1, 0, pe+1, dataStart, entry->info.offset);
-       if (rdlen < 0) goto errxit;
-       entry->rdlen = rdlen;
-
-       if (ril < h->indexUsed) {
-           indexEntry newEntry = entry + ril;
-           int ne = (h->indexUsed - ril);
-           int rid = entry->info.offset+1;
-           int rc;
-
-           /* Load dribble entries from region. */
-           rc = regionSwab(newEntry, ne, 0, pe+ril, dataStart, rid);
-           if (rc < 0) goto errxit;
-           rdlen += rc;
-
-         { indexEntry firstEntry = newEntry;
-           int save = h->indexUsed;
-           int j;
-
-           /* Dribble entries replace duplicate region entries. */
-           h->indexUsed -= ne;
-           for (j = 0; j < ne; j++, newEntry++) {
-               (void) headerRemoveEntry(h, newEntry->info.tag);
-               if (newEntry->info.tag == HEADER_BASENAMES)
-                   (void) headerRemoveEntry(h, HEADER_OLDFILENAMES);
-           }
-
-           /* If any duplicate entries were replaced, move new entries down. */
-           if (h->indexUsed < (save - ne)) {
-               memmove(h->index + h->indexUsed, firstEntry,
-                       (ne * sizeof(*entry)));
-           }
-           h->indexUsed += ne;
-         }
-       }
-    }
-
-    h->sorted = 0;
-    headerSort(h);
-
-    /*@-globstate@*/
-    return h;
-    /*@=globstate@*/
-
-errxit:
-    /*@-usereleased@*/
-    if (h) {
-       h->index = _free(h->index);
-       /*@-refcounttrans@*/
-       h = _free(h);
-       /*@=refcounttrans@*/
-    }
-    /*@=usereleased@*/
-    /*@-refcounttrans -globstate@*/
-    return h;
-    /*@=refcounttrans =globstate@*/
-}
-
-int headerWrite(FD_t fd, Header h, enum hMagic magicp)
-{
-    ssize_t nb;
-    int length;
-    const void * uh;
-
-    if (h == NULL)
-       return 1;
-    uh = doHeaderUnload(h, &length);
-    if (uh == NULL)
-       return 1;
-    switch (magicp) {
-    case HEADER_MAGIC_YES:
-       nb = Fwrite(header_magic, sizeof(char), sizeof(header_magic), fd);
-       if (nb != sizeof(header_magic))
-           goto exit;
-       break;
-    case HEADER_MAGIC_NO:
-       break;
-    }
-
-    nb = Fwrite(uh, sizeof(char), length, fd);
-
-exit:
-    uh = _free(uh);
-    return (nb == length ? 0 : 1);
-}
-
-Header headerCopyLoad(void * uh)
-{
-    int_32 * ei = (int_32 *) uh;
-    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;
-    void * nuh = memcpy(xmalloc(pvlen), uh, pvlen);
-    Header h;
-
-    h = headerLoad(nuh);
-    if (h == NULL) {
-       nuh = _free(nuh);
-       return h;
-    }
-    h->region_allocated = 1;
-    return h;
-}
-
-Header headerRead(FD_t fd, enum hMagic magicp)
-{
-    int_32 block[4];
-    int_32 reserved;
-    int_32 * ei = NULL;
-    int_32 il;
-    int_32 dl;
-    int_32 magic;
-    Header h = NULL;
-    int len;
-    int i;
-
-    memset(block, 0, sizeof(block));
-    i = 2;
-    if (magicp == HEADER_MAGIC_YES)
-       i += 2;
-
-    if (timedRead(fd, (char *)block, i*sizeof(*block)) != (i * sizeof(*block)))
-       goto exit;
-
-    i = 0;
-
-    if (magicp == HEADER_MAGIC_YES) {
-       magic = block[i++];
-       if (memcmp(&magic, header_magic, sizeof(magic)))
-           goto exit;
-       reserved = block[i++];
-    }
-    
-    il = ntohl(block[i++]);
-    dl = ntohl(block[i++]);
-
-    len = sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo)) + dl;
-
-    /*
-     * XXX Limit total size of header to 32Mb (~16 times largest known size).
-     */
-    if (len > (32*1024*1024))
-       goto exit;
-
-    ei = xmalloc(len);
-    ei[0] = htonl(il);
-    ei[1] = htonl(dl);
-    len -= sizeof(il) + sizeof(dl);
-
-    if (timedRead(fd, (char *)&ei[2], len) != len)
-       goto exit;
-    
-    h = headerLoad(ei);
-
-exit:
-    if (h) {
-       if (h->region_allocated)
-           ei = _free(ei);
-       h->region_allocated = 1;
-    } else if (ei)
-       ei = _free(ei);
-    return h;
-}
-
-void headerCopyTags(Header headerFrom, Header headerTo, hTAG_t tagstocopy)
-{
-    int * p;
-
-    if (headerFrom == headerTo)
-       return;
-
-    for (p = tagstocopy; *p != 0; p++) {
-       char *s;
-       int_32 type;
-       int_32 count;
-       if (headerIsEntry(headerTo, *p))
-           continue;
-       if (!headerGetEntryMinMemory(headerFrom, *p, &type,
-                               (hPTR_t *) &s, &count))
-           continue;
-       (void) headerAddEntry(headerTo, *p, type, s, count);
-       s = headerFreeData(s, type);
-    }
-}
-
-/**
- * Header tag iterator data structure.
- */
-struct headerIteratorS {
-/*@unused@*/ Header h;         /*!< Header being iterated. */
-/*@unused@*/ int next_index;   /*!< Next tag index. */
-};
-
-void headerFreeIterator(HeaderIterator hi)
-{
-    hi->h = headerFree(hi->h);
-    hi = _free(hi);
-}
-
-HeaderIterator headerInitIterator(Header h)
-{
-    HeaderIterator hi = xmalloc(sizeof(struct headerIteratorS));
-
-    headerSort(h);
-
-    hi->h = headerLink(h);
-    hi->next_index = 0;
-    return hi;
-}
-
-int headerNextIterator(HeaderIterator hi,
-                hTAG_t tag, hTYP_t type, hPTR_t * p, hCNT_t c)
-{
-    Header h = hi->h;
-    int slot = hi->next_index;
-    indexEntry entry = NULL;
-    int rc;
-
-    for (slot = hi->next_index; slot < h->indexUsed; slot++) {
-       entry = h->index + slot;
-       if (!ENTRY_IS_REGION(entry))
-           break;
-    }
-    hi->next_index = slot;
-    if (entry == NULL || slot >= h->indexUsed)
-       return 0;
-    /*@-noeffect@*/    /* LCL: no clue */
-    hi->next_index++;
-    /*@=noeffect@*/
-
-    if (tag)
-       *tag = entry->info.tag;
-
-    rc = copyEntry(entry, type, p, c, 0);
-
-    /* XXX 1 on success */
-    return ((rc == 1) ? 1 : 0);
-}
index dc17010..2f3808d 100644 (file)
@@ -5,16 +5,35 @@
  * \file lib/hdrinline.h
  */
 
-/*@-exportlocal@*/
-extern int _hdrinline_debug;
-/*@=exportlocal@*/
-
 #ifdef __cplusplus
 extern "C" {
 #endif
-/*@+voidabstract -nullpass -abstract -mustmod -compdef -shadow -predboolothers @*/
+/*@+voidabstract -nullpass -mustmod -compdef -shadow -predboolothers @*/
 
-#define        HV(_h)  ((HV_t *)(_h))
+/** \ingroup header
+ * Header methods for rpm headers.
+ */
+extern struct HV_s * hdrVec;
+
+/** \ingroup header
+ */
+/*@unused@*/ static inline HV_t h2hv(Header h)
+{
+    /*@-abstract -castexpose -refcounttrans@*/
+    return ((HV_t)h);
+    /*@=abstract =castexpose =refcounttrans@*/
+}
+
+/** \ingroup header
+ * Create new (empty) header instance.
+ * @return             header
+ */
+/*@unused@*/ static inline
+Header headerNew(void)
+       /*@*/
+{
+    return hdrVec->hdrnew();
+}
 
 /** \ingroup header
  * Dereference a header instance.
@@ -25,8 +44,10 @@ extern "C" {
 /*@null@*/ Header headerFree( /*@null@*/ /*@killref@*/ Header h)
        /*@modifies h @*/
 {
+    /*@-abstract@*/
     if (h == NULL) return NULL;
-    return (HV(h)->free) (h);
+    /*@=abstract@*/
+    return (h2hv(h)->hdrfree) (h);
 }
 
 /** \ingroup header
@@ -38,7 +59,7 @@ extern "C" {
 Header headerLink(Header h)
        /*@modifies h @*/
 {
-    return (HV(h)->link) (h);
+    return (h2hv(h)->hdrlink) (h);
 }
 
 /*@-exportlocal@*/
@@ -50,7 +71,7 @@ Header headerLink(Header h)
 void headerSort(Header h)
        /*@modifies h @*/
 {
-    return (HV(h)->sort) (h);
+    return (h2hv(h)->hdrsort) (h);
 }
 
 /** \ingroup header
@@ -61,7 +82,7 @@ void headerSort(Header h)
 void headerUnsort(Header h)
        /*@modifies h @*/
 {
-    return (HV(h)->unsort) (h);
+    return (h2hv(h)->hdrunsort) (h);
 }
 /*@=exportlocal@*/
 
@@ -75,8 +96,10 @@ void headerUnsort(Header h)
 unsigned int headerSizeof(/*@null@*/ Header h, enum hMagic magicp)
        /*@modifies h @*/
 {
+    /*@-abstract@*/
     if (h == NULL) return 0;
-    return (HV(h)->size) (h, magicp);
+    /*@=abstract@*/
+    return (h2hv(h)->hdrsizeof) (h, magicp);
 }
 
 /** \ingroup header
@@ -88,7 +111,7 @@ unsigned int headerSizeof(/*@null@*/ Header h, enum hMagic magicp)
 /*@only@*/ /*@null@*/ void * headerUnload(Header h)
        /*@modifies h @*/
 {
-    return (HV(h)->unload) (h);
+    return (h2hv(h)->hdrunload) (h);
 }
 
 /** \ingroup header
@@ -102,7 +125,9 @@ unsigned int headerSizeof(/*@null@*/ Header h, enum hMagic magicp)
 /*@null@*/ Header headerReload(/*@only@*/ Header h, int tag)
        /*@modifies h @*/
 {
-    return (HV(h)->reload) (h, tag);
+    /*@-onlytrans@*/
+    return (h2hv(h)->hdrreload) (h, tag);
+    /*@=onlytrans@*/
 }
 
 /** \ingroup header
@@ -114,7 +139,61 @@ unsigned int headerSizeof(/*@null@*/ Header h, enum hMagic magicp)
 /*@null@*/ Header headerCopy(Header h)
        /*@modifies h @*/
 {
-    return (HV(h)->copy) (h);
+    return (h2hv(h)->hdrcopy) (h);
+}
+
+/** \ingroup header
+ * Convert header to in-memory representation.
+ * @param uh           on-disk header blob (i.e. with offsets)
+ * @return             header
+ */
+/*@unused@*/ static inline
+/*@null@*/ Header headerLoad(/*@kept@*/ void * uh)
+       /*@modifies uh @*/
+{
+    return hdrVec->hdrload(uh);
+}
+
+/** \ingroup header
+ * Make a copy and convert header to in-memory representation.
+ * @param uh           on-disk header blob (i.e. with offsets)
+ * @return             header
+ */
+/*@unused@*/ static inline
+/*@null@*/ Header headerCopyLoad(const void * uh)
+       /*@*/
+{
+    return hdrVec->hdrcopyload(uh);
+}
+
+/** \ingroup header
+ * Read (and load) header from file handle.
+ * @param fd           file handle
+ * @param magicp       read (and verify) 8 bytes of (magic, 0)?
+ * @return             header (or NULL on error)
+ */
+/*@unused@*/ static inline
+/*@null@*/ Header headerRead(FD_t fd, enum hMagic magicp)
+       /*@modifies fd, fileSystem @*/
+{
+    return hdrVec->hdrread(fd, magicp);
+}
+
+/** \ingroup header
+ * Write (with unload) header to file handle.
+ * @param fd           file handle
+ * @param h            header
+ * @param magicp       prefix write with 8 bytes of (magic, 0)?
+ * @return             0 on success, 1 on error
+ */
+/*@unused@*/ static inline
+int headerWrite(FD_t fd, /*@null@*/ Header h, enum hMagic magicp)
+       /*@modifies fd, h, fileSystem @*/
+{
+    /*@-abstract@*/
+    if (h == NULL) return 0;
+    /*@=abstract@*/
+    return (h2hv(h)->hdrwrite) (fd, h, magicp);
 }
 
 /** \ingroup header
@@ -124,11 +203,28 @@ unsigned int headerSizeof(/*@null@*/ Header h, enum hMagic magicp)
  * @return             1 on success, 0 on failure
  */
 /*@unused@*/ static inline
-int headerIsEntry(/*@null@*/Header h, int_32 tag)
+int headerIsEntry(/*@null@*/ Header h, int_32 tag)
        /*@modifies h @*/
 {
+    /*@-abstract@*/
     if (h == NULL) return 0;
-    return (HV(h)->isentry) (h, tag);
+    /*@=abstract@*/
+    return (h2hv(h)->hdrisentry) (h, tag);
+}
+
+/** \ingroup header
+ * Free data allocated when retrieved from header.
+ * @param h            header
+ * @param data         address of data (or NULL)
+ * @param type         type of data (or -1 to force free)
+ * @return             NULL always
+ */
+/*@unused@*/ static inline
+/*@null@*/ void * headerFreeTag(Header h,
+               /*@only@*/ /*@null@*/ const void * data, rpmTagType type)
+       /*@modifies data @*/
+{
+    return (h2hv(h)->hdrfreetag) (h, data, type);
 }
 
 /** \ingroup header
@@ -151,7 +247,7 @@ int headerGetEntry(Header h, int_32 tag,
                        /*@null@*/ /*@out@*/ hCNT_t c)
        /*@modifies *type, *p, *c @*/
 {
-    return (HV(h)->get) (h, tag, type, p, c);
+    return (h2hv(h)->hdrget) (h, tag, type, p, c);
 }
 
 /** \ingroup header
@@ -173,32 +269,8 @@ int headerGetEntryMinMemory(Header h, int_32 tag,
                        /*@null@*/ /*@out@*/ hCNT_t c)
        /*@modifies *type, *p, *c @*/
 {
-    return (HV(h)->getmin) (h, tag, type, p, c);
-}
-
-/** \ingroup header
- * Retrieve tag value with type match.
- * If *type is RPM_NULL_TYPE any type will match, otherwise only *type will
- * match.
- *
- * @param h            header
- * @param tag          tag
- * @retval type                address of tag value data type (or NULL)
- * @retval p           address of pointer to tag value(s) (or NULL)
- * @retval c           address of number of values (or NULL)
- * @return             1 on success, 0 on failure
- */
-/*@-exportlocal@*/
-/*@unused@*/ static inline
-int headerGetRawEntry(Header h, int_32 tag,
-                       /*@null@*/ /*@out@*/ hTYP_t type,
-                       /*@null@*/ /*@out@*/ hPTR_t * p, 
-                       /*@null@*/ /*@out@*/ hCNT_t c)
-       /*@modifies *type, *p, *c @*/
-{
-    return (HV(h)->getraw) (h, tag, type, p, c);
+    return (h2hv(h)->hdrgetmin) (h, tag, type, p, c);
 }
-/*@=exportlocal@*/
 
 /** \ingroup header
  * Add tag to header.
@@ -219,7 +291,7 @@ int headerGetRawEntry(Header h, int_32 tag,
 int headerAddEntry(Header h, int_32 tag, int_32 type, const void * p, int_32 c)
        /*@modifies h @*/
 {
-    return (HV(h)->add) (h, tag, type, p, c);
+    return (h2hv(h)->hdradd) (h, tag, type, p, c);
 }
 
 /** \ingroup header
@@ -241,7 +313,7 @@ int headerAppendEntry(Header h, int_32 tag, int_32 type,
                const void * p, int_32 c)
        /*@modifies h @*/
 {
-    return (HV(h)->append) (h, tag, type, p, c);
+    return (h2hv(h)->hdrappend) (h, tag, type, p, c);
 }
 
 /** \ingroup header
@@ -259,7 +331,7 @@ int headerAddOrAppendEntry(Header h, int_32 tag, int_32 type,
                const void * p, int_32 c)
        /*@modifies h @*/
 {
-    return (HV(h)->addorappend) (h, tag, type, p, c);
+    return (h2hv(h)->hdraddorappend) (h, tag, type, p, c);
 }
 
 /** \ingroup header
@@ -287,7 +359,7 @@ int headerAddI18NString(Header h, int_32 tag, const char * string,
                const char * lang)
        /*@modifies h @*/
 {
-    return (HV(h)->addi18n) (h, tag, string, lang);
+    return (h2hv(h)->hdraddi18n) (h, tag, string, lang);
 }
 
 /** \ingroup header
@@ -305,7 +377,7 @@ int headerModifyEntry(Header h, int_32 tag, int_32 type,
                        const void * p, int_32 c)
        /*@modifies h @*/
 {
-    return (HV(h)->modify) (h, tag, type, p, c);
+    return (h2hv(h)->hdrmodify) (h, tag, type, p, c);
 }
 
 /** \ingroup header
@@ -321,7 +393,7 @@ int headerModifyEntry(Header h, int_32 tag, int_32 type,
 int headerRemoveEntry(Header h, int_32 tag)
        /*@modifies h @*/
 {
-    return (HV(h)->remove) (h, tag);
+    return (h2hv(h)->hdrremove) (h, tag);
 }
 
 /** \ingroup header
@@ -342,9 +414,67 @@ int headerRemoveEntry(Header h, int_32 tag)
                     /*@null@*/ /*@out@*/ errmsg_t * errmsg)
        /*@modifies *errmsg @*/
 {
-    return (HV(h)->sprintf) (h, fmt, tags, extensions, errmsg);
+    return (h2hv(h)->hdrsprintf) (h, fmt, tags, extensions, errmsg);
+}
+
+/** \ingroup header
+ * Duplicate tag values from one header into another.
+ * @param headerFrom   source header
+ * @param headerTo     destination header
+ * @param tagstocopy   array of tags that are copied
+ */
+/*@unused@*/ static inline
+void headerCopyTags(Header headerFrom, Header headerTo, hTAG_t tagstocopy)
+       /*@modifies headerFrom, headerTo @*/
+{
+    return hdrVec->hdrcopytags(headerFrom, headerTo, tagstocopy);
+}
+
+/** \ingroup header
+ * Destroy header tag iterator.
+ * @param hi           header tag iterator
+ * @return             NULL always
+ */
+/*@unused@*/ static inline
+HeaderIterator headerFreeIterator(/*@only@*/ HeaderIterator hi)
+       /*@modifies hi @*/
+{
+    return hdrVec->hdrfreeiter(hi);
+}
+
+/** \ingroup header
+ * Create header tag iterator.
+ * @param h            header
+ * @return             header tag iterator
+ */
+/*@unused@*/ static inline
+HeaderIterator headerInitIterator(Header h)
+       /*@modifies h */
+{
+    return hdrVec->hdrinititer(h);
+}
+
+/** \ingroup header
+ * Return next tag from header.
+ * @param hi           header tag iterator
+ * @retval tag         address of tag
+ * @retval type                address of tag value data type
+ * @retval p           address of pointer to tag value(s)
+ * @retval c           address of number of values
+ * @return             1 on success, 0 on failure
+ */
+/*@unused@*/ static inline
+int headerNextIterator(HeaderIterator hi,
+               /*@null@*/ /*@out@*/ hTAG_t tag,
+               /*@null@*/ /*@out@*/ hTYP_t type,
+               /*@null@*/ /*@out@*/ hPTR_t * p,
+               /*@null@*/ /*@out@*/ hCNT_t c)
+       /*@modifies hi, *tag, *type, *p, *c @*/
+{
+    return hdrVec->hdrnextiter(hi, tag, type, p, c);
 }
-/*@=voidabstract =nullpass =abstract =mustmod =compdef =shadow =predboolothers @*/
+
+/*@=voidabstract =nullpass =mustmod =compdef =shadow =predboolothers @*/
 
 #ifdef __cplusplus
 }
index 96735ff..67b61b1 100644 (file)
@@ -10,6 +10,12 @@ extern "C" {
 #endif
 
 /** \ingroup header
+ * Create new (empty) header instance.
+ * @return             header
+ */
+Header headerNew(void) /*@*/;
+
+/** \ingroup header
  * Dereference a header instance.
  * @param h            header
  * @return             NULL always
@@ -77,6 +83,43 @@ unsigned int headerSizeof(/*@null@*/ Header h, enum hMagic magicp)
        /*@modifies h @*/;
 
 /** \ingroup header
+ * Convert header to in-memory representation.
+ * @param uh           on-disk header blob (i.e. with offsets)
+ * @return             header
+ */
+/*@-exportlocal@*/
+/*@null@*/ Header headerLoad(/*@kept@*/ void * uh)
+       /*@modifies uh @*/;
+/*@=exportlocal@*/
+
+/** \ingroup header
+ * Write (with unload) header to file handle.
+ * @param fd           file handle
+ * @param h            header
+ * @param magicp       prefix write with 8 bytes of (magic, 0)?
+ * @return             0 on success, 1 on error
+ */
+int headerWrite(FD_t fd, /*@null@*/ Header h, enum hMagic magicp)
+       /*@modifies fd, h, fileSystem @*/;
+
+/** \ingroup header
+ * Make a copy and convert header to in-memory representation.
+ * @param uh           on-disk header blob (i.e. with offsets)
+ * @return             header
+ */
+/*@null@*/ Header headerCopyLoad(const void * uh)
+       /*@*/;
+
+/** \ingroup header
+ * Read (and load) header from file handle.
+ * @param fd           file handle
+ * @param magicp       read (and verify) 8 bytes of (magic, 0)?
+ * @return             header (or NULL on error)
+ */
+/*@null@*/ Header headerRead(FD_t fd, enum hMagic magicp)
+       /*@modifies fd, fileSystem @*/;
+
+/** \ingroup header
  * Check if tag is in header.
  * @param h            header
  * @param tag          tag
@@ -123,26 +166,6 @@ int headerGetEntryMinMemory(Header h, int_32 tag,
        /*@modifies *type, *p, *c @*/;
 
 /** \ingroup header
- * Retrieve tag value with type match.
- * If *type is RPM_NULL_TYPE any type will match, otherwise only *type will
- * match.
- *
- * @param h            header
- * @param tag          tag
- * @retval type                address of tag value data type (or NULL)
- * @retval p           address of pointer to tag value(s) (or NULL)
- * @retval c           address of number of values (or NULL)
- * @return             1 on success, 0 on failure
- */
-/*@-exportlocal@*/
-int headerGetRawEntry(Header h, int_32 tag,
-                       /*@null@*/ /*@out@*/ hTYP_t type,
-                       /*@null@*/ /*@out@*/ hPTR_t * p, 
-                       /*@null@*/ /*@out@*/ hCNT_t c)
-       /*@modifies *type, *p, *c @*/;
-/*@=exportlocal@*/
-
-/** \ingroup header
  * Add tag to header.
  * Duplicate tags are okay, but only defined for iteration (with the
  * exceptions noted below). While you are allowed to add i18n string
@@ -259,6 +282,47 @@ int headerRemoveEntry(Header h, int_32 tag)
                     /*@null@*/ /*@out@*/ errmsg_t * errmsg)
        /*@modifies *errmsg @*/;
 
+/** \ingroup header
+ * Duplicate tag values from one header into another.
+ * @param headerFrom   source header
+ * @param headerTo     destination header
+ * @param tagstocopy   array of tags that are copied
+ */
+void headerCopyTags(Header headerFrom, Header headerTo, hTAG_t tagstocopy)
+       /*@modifies headerTo @*/;
+
+/** \ingroup header
+ * Destroy header tag iterator.
+ * @param hi           header tag iterator
+ * @return             NULL always
+ */
+/*@null@*/ HeaderIterator headerFreeIterator(/*@only@*/ HeaderIterator hi)
+       /*@modifies hi @*/;
+
+/** \ingroup header
+ * Create header tag iterator.
+ * @param h            header
+ * @return             header tag iterator
+ */
+HeaderIterator headerInitIterator(Header h)
+       /*@modifies h */;
+
+/** \ingroup header
+ * Return next tag from header.
+ * @param hi           header tag iterator
+ * @retval tag         address of tag
+ * @retval type                address of tag value data type
+ * @retval p           address of pointer to tag value(s)
+ * @retval c           address of number of values
+ * @return             1 on success, 0 on failure
+ */
+int headerNextIterator(HeaderIterator hi,
+               /*@null@*/ /*@out@*/ hTAG_t tag,
+               /*@null@*/ /*@out@*/ hTYP_t type,
+               /*@null@*/ /*@out@*/ hPTR_t * p,
+               /*@null@*/ /*@out@*/ hCNT_t c)
+       /*@modifies hi, *tag, *type, *p, *c @*/;
+
 #ifdef __cplusplus
 }
 #endif
index 65df111..3c64b05 100644 (file)
 /*@access extensionCache @*/
 /*@access sprintfTag @*/
 /*@access sprintfToken @*/
+/*@access HV_t @*/
 
 #define PARSER_BEGIN   0
 #define PARSER_IN_ARRAY 1
 #define PARSER_IN_EXPR  2
 
-unsigned char header_magic[8] = {
+/** \ingroup header
+ */
+static unsigned char header_magic[8] = {
        0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
 };
 
@@ -51,6 +54,8 @@ static int typeSizes[] =  {
        -1      /*!< RPM_I18NSTRING_TYPE */
 };
 
+HV_t hdrVec;   /* forward reference */
+
 /**
  * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
  * @param p            memory to free
@@ -63,6 +68,27 @@ _free(/*@only@*/ /*@null@*/ const void * p) /*@modifies *p @*/
     return NULL;
 }
 
+Header headerNew()
+{
+    Header h = xcalloc(1, sizeof(*h));
+
+    /*@-assignexpose@*/
+    h->hv = *hdrVec;           /* structure assignment */
+    /*@=assignexpose@*/
+    h->indexAlloced = INDEX_MALLOC_SIZE;
+    h->indexUsed = 0;
+    h->flags = HEADERFLAG_SORTED;
+    h->nrefs = 1;
+
+    h->index = (h->indexAlloced
+       ? xcalloc(h->indexAlloced, sizeof(*h->index))
+       : NULL);
+
+    /*@-globstate@*/
+    return h;
+    /*@=globstate@*/
+}
+
 Header headerFree(Header h)
 {
     if (h == NULL || --h->nrefs > 0)
@@ -72,7 +98,7 @@ Header headerFree(Header h)
        indexEntry entry = h->index;
        int i;
        for (i = 0; i < h->indexUsed; i++, entry++) {
-           if (h->region_allocated && ENTRY_IS_REGION(entry)) {
+           if ((h->flags & HEADERFLAG_ALLOCATED) && ENTRY_IS_REGION(entry)) {
                if (entry->length > 0) {
                    int_32 * ei = entry->data;
                    ei -= 2; /* XXX HACK: adjust to beginning of header. */
@@ -108,9 +134,9 @@ static int indexCmp(const void * avp, const void * bvp)     /*@*/
 
 void headerSort(Header h)
 {
-    if (!h->sorted) {
+    if (!(h->flags & HEADERFLAG_SORTED)) {
        qsort(h->index, h->indexUsed, sizeof(*h->index), indexCmp);
-       h->sorted = 1;
+       h->flags |= HEADERFLAG_SORTED;
     }
 }
 
@@ -163,7 +189,7 @@ unsigned int headerSizeof(Header h, enum hMagic magicp)
         if (ENTRY_IS_REGION(entry)) {
            size += entry->length;
            /* XXX Legacy regions do not include the region tag and data. */
-           if (i == 0 && h->legacy)
+           if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
                size += sizeof(struct entryInfo) + entry->info.count;
            continue;
         }
@@ -252,7 +278,32 @@ static int dataLength(int_32 type, hPTR_t p, int_32 count, int onDisk)
     return length;
 }
 
-int regionSwab(/*@null@*/ indexEntry entry, int il, int dl,
+/** \ingroup header
+ * Swap int_32 and int_16 arrays within header region.
+ *
+ * This code is way more twisty than I would like.
+ *
+ * A bug with RPM_I18NSTRING_TYPE in rpm-2.5.x (fixed in August 1998)
+ * causes the offset and length of elements in a header region to disagree
+ * regarding the total length of the region data.
+ *
+ * The "fix" is to compute the size using both offset and length and
+ * return the larger of the two numbers as the size of the region.
+ * Kinda like computing left and right Riemann sums of the data elements
+ * to determine the size of a data structure, go figger :-).
+ *
+ * There's one other twist if a header region tag is in the set to be swabbed,
+ * as the data for a header region is located after all other tag data.
+ *
+ * @param entry                header entry
+ * @param il           no. of entries
+ * @param dl           start no. bytes of data
+ * @param pe           header physical entry pointer (swapped)
+ * @param dataStart    header data
+ * @param regionid     region offset
+ * @return             no. bytes of data in region, -1 on error
+ */
+static int regionSwab(/*@null@*/ indexEntry entry, int il, int dl,
                entryInfo pe, char * dataStart, int regionid)
        /*@modifies *entry, *dataStart @*/
 {
@@ -348,7 +399,10 @@ int headerDrips(const Header h)
 }
 #endif
 
-/*@only@*/ /*@null@*/ void * doHeaderUnload(Header h, /*@out@*/ int * lengthPtr)
+/** \ingroup header
+ */
+static /*@only@*/ /*@null@*/ void * doHeaderUnload(Header h,
+               /*@out@*/ int * lengthPtr)
        /*@modifies h, *lengthPtr @*/
 {
     int_32 * ei = NULL;
@@ -381,7 +435,7 @@ int headerDrips(const Header h)
            il += ril;
            dl += entry->rdlen + entry->info.count;
            /* XXX Legacy regions do not include the region tag and data. */
-           if (i == 0 && h->legacy)
+           if (i == 0 && (h->flags & HEADERFLAG_LEGACY))
                il += 1;
 
            /* Skip rest of entries in region, but account for dribbles. */
@@ -466,7 +520,7 @@ t = te;
            rdlen = entry->rdlen;
 
            /* XXX Legacy regions do not include the region tag and data. */
-           if (i == 0 && h->legacy) {
+           if (i == 0 && (h->flags & HEADERFLAG_LEGACY)) {
                int_32 stei[4];
 
                legacy = 1;
@@ -570,7 +624,7 @@ t = te;
     if (lengthPtr)
        *lengthPtr = len;
 
-    h->sorted = 0;
+    h->flags &= ~HEADERFLAG_SORTED;
     headerSort(h);
 
     return (void *) ei;
@@ -605,9 +659,9 @@ Header headerReload(Header h, int tag)
        uh = _free(uh);
        return NULL;
     }
-    if (nh->region_allocated)
+    if (nh->flags & HEADERFLAG_ALLOCATED)
        uh = _free(uh);
-    nh->region_allocated = 1;
+    nh->flags |= HEADERFLAG_ALLOCATED;
     if (ENTRY_IS_REGION(nh->index)) {
        if (tag == HEADER_SIGNATURES || tag == HEADER_IMMUTABLE)
            nh->index[0].info.tag = tag;
@@ -628,11 +682,267 @@ Header headerCopy(Header h)
     {
        if (ptr) (void) headerAddEntry(nh, tag, type, ptr, count);
     }
-    headerFreeIterator(hi);
+    hi = headerFreeIterator(hi);
 
     return headerReload(nh, HEADER_IMAGE);
 }
 
+Header headerLoad(void * uh)
+{
+    int_32 * ei = (int_32 *) uh;
+    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;
+    void * pv = uh;
+    Header h = xcalloc(1, sizeof(*h));
+    entryInfo pe;
+    char * dataStart;
+    indexEntry entry; 
+    int rdlen;
+    int i;
+
+    ei = (int_32 *) pv;
+    /*@-castexpose@*/
+    pe = (entryInfo) &ei[2];
+    /*@=castexpose@*/
+    dataStart = (char *) (pe + il);
+
+    /*@-assignexpose@*/
+    h->hv = *hdrVec;           /* structure assignment */
+    /*@=assignexpose@*/
+    h->indexAlloced = il + 1;
+    h->indexUsed = il;
+    h->index = xcalloc(h->indexAlloced, sizeof(*h->index));
+    h->flags = HEADERFLAG_SORTED;
+    h->nrefs = 1;
+
+    /*
+     * XXX XFree86-libs, ash, and pdksh from Red Hat 5.2 have bogus
+     * %verifyscript tag that needs to be diddled.
+     */
+    if (ntohl(pe->tag) == 15 &&
+       ntohl(pe->type) == RPM_STRING_TYPE &&
+       ntohl(pe->count) == 1)
+    {
+       pe->tag = htonl(1079);
+    }
+
+    entry = h->index;
+    i = 0;
+    if (!(htonl(pe->tag) < HEADER_I18NTABLE)) {
+       h->flags |= HEADERFLAG_LEGACY;
+       entry->info.type = REGION_TAG_TYPE;
+       entry->info.tag = HEADER_IMAGE;
+       entry->info.count = REGION_TAG_COUNT;
+       entry->info.offset = ((char *)pe - dataStart); /* negative offset */
+
+       /*@-assignexpose@*/
+       entry->data = pe;
+       /*@=assignexpose@*/
+       entry->length = pvlen - sizeof(il) - sizeof(dl);
+       rdlen = regionSwab(entry+1, il, 0, pe, dataStart, entry->info.offset);
+       if (rdlen != dl) goto errxit;
+       entry->rdlen = rdlen;
+       entry++;
+       h->indexUsed++;
+    } else {
+       int nb = ntohl(pe->count);
+       int_32 rdl;
+       int_32 ril;
+
+       h->flags &= ~HEADERFLAG_LEGACY;
+
+       entry->info.type = htonl(pe->type);
+       if (entry->info.type < RPM_MIN_TYPE || entry->info.type > RPM_MAX_TYPE)
+           goto errxit;
+       entry->info.count = htonl(pe->count);
+
+       {  int off = ntohl(pe->offset);
+          if (off) {
+               int_32 * stei = memcpy(alloca(nb), dataStart + off, nb);
+               rdl = -ntohl(stei[2]);  /* negative offset */
+               ril = rdl/sizeof(*pe);
+               entry->info.tag = htonl(pe->tag);
+           } else {
+               ril = il;
+               rdl = (ril * sizeof(struct entryInfo));
+               entry->info.tag = HEADER_IMAGE;
+           }
+       }
+       entry->info.offset = -rdl;      /* negative offset */
+
+       /*@-assignexpose@*/
+       entry->data = pe;
+       /*@=assignexpose@*/
+       entry->length = pvlen - sizeof(il) - sizeof(dl);
+       rdlen = regionSwab(entry+1, ril-1, 0, pe+1, dataStart, entry->info.offset);
+       if (rdlen < 0) goto errxit;
+       entry->rdlen = rdlen;
+
+       if (ril < h->indexUsed) {
+           indexEntry newEntry = entry + ril;
+           int ne = (h->indexUsed - ril);
+           int rid = entry->info.offset+1;
+           int rc;
+
+           /* Load dribble entries from region. */
+           rc = regionSwab(newEntry, ne, 0, pe+ril, dataStart, rid);
+           if (rc < 0) goto errxit;
+           rdlen += rc;
+
+         { indexEntry firstEntry = newEntry;
+           int save = h->indexUsed;
+           int j;
+
+           /* Dribble entries replace duplicate region entries. */
+           h->indexUsed -= ne;
+           for (j = 0; j < ne; j++, newEntry++) {
+               (void) headerRemoveEntry(h, newEntry->info.tag);
+               if (newEntry->info.tag == HEADER_BASENAMES)
+                   (void) headerRemoveEntry(h, HEADER_OLDFILENAMES);
+           }
+
+           /* If any duplicate entries were replaced, move new entries down. */
+           if (h->indexUsed < (save - ne)) {
+               memmove(h->index + h->indexUsed, firstEntry,
+                       (ne * sizeof(*entry)));
+           }
+           h->indexUsed += ne;
+         }
+       }
+    }
+
+    h->flags &= ~HEADERFLAG_SORTED;
+    headerSort(h);
+
+    /*@-globstate@*/
+    return h;
+    /*@=globstate@*/
+
+errxit:
+    /*@-usereleased@*/
+    if (h) {
+       h->index = _free(h->index);
+       /*@-refcounttrans@*/
+       h = _free(h);
+       /*@=refcounttrans@*/
+    }
+    /*@=usereleased@*/
+    /*@-refcounttrans -globstate@*/
+    return h;
+    /*@=refcounttrans =globstate@*/
+}
+
+Header headerCopyLoad(const void * uh)
+{
+    int_32 * ei = (int_32 *) uh;
+    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;
+    void * nuh = memcpy(xmalloc(pvlen), uh, pvlen);
+    Header h;
+
+    h = headerLoad(nuh);
+    if (h == NULL) {
+       nuh = _free(nuh);
+       return h;
+    }
+    h->flags |= HEADERFLAG_ALLOCATED;
+    return h;
+}
+
+Header headerRead(FD_t fd, enum hMagic magicp)
+{
+    int_32 block[4];
+    int_32 reserved;
+    int_32 * ei = NULL;
+    int_32 il;
+    int_32 dl;
+    int_32 magic;
+    Header h = NULL;
+    int len;
+    int i;
+
+    memset(block, 0, sizeof(block));
+    i = 2;
+    if (magicp == HEADER_MAGIC_YES)
+       i += 2;
+
+    if (timedRead(fd, (char *)block, i*sizeof(*block)) != (i * sizeof(*block)))
+       goto exit;
+
+    i = 0;
+
+    if (magicp == HEADER_MAGIC_YES) {
+       magic = block[i++];
+       if (memcmp(&magic, header_magic, sizeof(magic)))
+           goto exit;
+       reserved = block[i++];
+    }
+    
+    il = ntohl(block[i++]);
+    dl = ntohl(block[i++]);
+
+    len = sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo)) + dl;
+
+    /*
+     * XXX Limit total size of header to 32Mb (~16 times largest known size).
+     */
+    if (len > (32*1024*1024))
+       goto exit;
+
+    ei = xmalloc(len);
+    ei[0] = htonl(il);
+    ei[1] = htonl(dl);
+    len -= sizeof(il) + sizeof(dl);
+
+    if (timedRead(fd, (char *)&ei[2], len) != len)
+       goto exit;
+    
+    h = headerLoad(ei);
+
+exit:
+    if (h) {
+       if (h->flags & HEADERFLAG_ALLOCATED)
+           ei = _free(ei);
+       h->flags |= HEADERFLAG_ALLOCATED;
+    } else if (ei)
+       ei = _free(ei);
+    /*@-mustmod@*/     /* FIX: timedRead macro obscures annotation */
+    return h;
+    /*@-mustmod@*/
+}
+
+int headerWrite(FD_t fd, Header h, enum hMagic magicp)
+{
+    ssize_t nb;
+    int length;
+    const void * uh;
+
+    if (h == NULL)
+       return 1;
+    uh = doHeaderUnload(h, &length);
+    if (uh == NULL)
+       return 1;
+    switch (magicp) {
+    case HEADER_MAGIC_YES:
+       nb = Fwrite(header_magic, sizeof(char), sizeof(header_magic), fd);
+       if (nb != sizeof(header_magic))
+           goto exit;
+       break;
+    case HEADER_MAGIC_NO:
+       break;
+    }
+
+    nb = Fwrite(uh, sizeof(char), length, fd);
+
+exit:
+    uh = _free(uh);
+    return (nb == length ? 0 : 1);
+}
+
 /**
  * Find matching (tag,type) entry in header.
  * @param h            header
@@ -648,7 +958,7 @@ indexEntry findEntry(/*@null@*/ Header h, int_32 tag, int_32 type)
     struct indexEntry key;
 
     if (h == NULL) return NULL;
-    if (!h->sorted) headerSort(h);
+    if (!(h->flags & HEADERFLAG_SORTED)) headerSort(h);
 
     key.info.tag = tag;
 
@@ -684,7 +994,17 @@ int headerIsEntry(Header h, int_32 tag)
     /*@=mods@*/        
 }
 
-int copyEntry(const indexEntry entry,
+/** \ingroup header
+ * Retrieve data from header entry.
+ * @todo Permit retrieval of regions other than HEADER_IMUTABLE.
+ * @param entry                header entry
+ * @retval type                address of type (or NULL)
+ * @retval p           address of data (or NULL)
+ * @retval c           address of count (or NULL)
+ * @param minMem       string pointers refer to header memory?
+ * @return             1 on success, otherwise error.
+ */
+static int copyEntry(const indexEntry entry,
                /*@null@*/ /*@out@*/ hTYP_t type,
                /*@null@*/ /*@out@*/ hPTR_t * p,
                /*@null@*/ /*@out@*/ hCNT_t c,
@@ -958,6 +1278,29 @@ static int intGetEntry(Header h, int_32 tag,
     return ((rc == 1) ? 1 : 0);
 }
 
+/** \ingroup header
+ * Free data allocated when retrieved from header.
+ * @param h            header
+ * @param data         address of data (or NULL)
+ * @param type         type of data (or -1 to force free)
+ * @return             NULL always
+ */
+static /*@null@*/ void * headerFreeTag(/*@unused@*/ Header h,
+               /*@only@*/ /*@null@*/ const void * data, rpmTagType type)
+       /*@modifies data @*/
+{
+    if (data) {
+       /*@-branchstate@*/
+       if (type == -1 ||
+           type == RPM_STRING_ARRAY_TYPE ||
+           type == RPM_I18NSTRING_TYPE ||
+           type == RPM_BIN_TYPE)
+               data = _free(data);
+       /*@=branchstate@*/
+    }
+    return NULL;
+}
+
 int headerGetEntry(Header h, int_32 tag, hTYP_t type, void **p, hCNT_t c)
 {
     return intGetEntry(h, tag, type, (hPTR_t *)p, c, 0);
@@ -1071,7 +1414,7 @@ int headerAddEntry(Header h, int_32 tag, int_32 type, hPTR_t p, int_32 c)
     entry->data = grabData(type, p, c, &entry->length);
 
     if (h->indexUsed > 0 && tag < h->index[h->indexUsed-1].info.tag)
-       h->sorted = 0;
+       h->flags &= ~HEADERFLAG_SORTED;
     h->indexUsed++;
 
     return 1;
@@ -2317,7 +2660,83 @@ const struct headerSprintfExtension headerDefaultFormats[] = {
     { HEADER_EXT_LAST, NULL, { NULL } }
 };
 
-HV_t hv = {
+void headerCopyTags(Header headerFrom, Header headerTo, hTAG_t tagstocopy)
+{
+    int * p;
+
+    if (headerFrom == headerTo)
+       return;
+
+    for (p = tagstocopy; *p != 0; p++) {
+       char *s;
+       int_32 type;
+       int_32 count;
+       if (headerIsEntry(headerTo, *p))
+           continue;
+       if (!headerGetEntryMinMemory(headerFrom, *p, &type,
+                               (hPTR_t *) &s, &count))
+           continue;
+       (void) headerAddEntry(headerTo, *p, type, s, count);
+       s = headerFreeData(s, type);
+    }
+}
+
+/**
+ * Header tag iterator data structure.
+ */
+struct headerIteratorS {
+/*@unused@*/ Header h;         /*!< Header being iterated. */
+/*@unused@*/ int next_index;   /*!< Next tag index. */
+};
+
+HeaderIterator headerFreeIterator(HeaderIterator hi)
+{
+    hi->h = headerFree(hi->h);
+    hi = _free(hi);
+    return hi;
+}
+
+HeaderIterator headerInitIterator(Header h)
+{
+    HeaderIterator hi = xmalloc(sizeof(struct headerIteratorS));
+
+    headerSort(h);
+
+    hi->h = headerLink(h);
+    hi->next_index = 0;
+    return hi;
+}
+
+int headerNextIterator(HeaderIterator hi,
+                hTAG_t tag, hTYP_t type, hPTR_t * p, hCNT_t c)
+{
+    Header h = hi->h;
+    int slot = hi->next_index;
+    indexEntry entry = NULL;
+    int rc;
+
+    for (slot = hi->next_index; slot < h->indexUsed; slot++) {
+       entry = h->index + slot;
+       if (!ENTRY_IS_REGION(entry))
+           break;
+    }
+    hi->next_index = slot;
+    if (entry == NULL || slot >= h->indexUsed)
+       return 0;
+    /*@-noeffect@*/    /* LCL: no clue */
+    hi->next_index++;
+    /*@=noeffect@*/
+
+    if (tag)
+       *tag = entry->info.tag;
+
+    rc = copyEntry(entry, type, p, c, 0);
+
+    /* XXX 1 on success */
+    return ((rc == 1) ? 1 : 0);
+}
+static struct HV_s hdrVec1 = {
+    headerNew,
     headerFree,
     headerLink,
     headerSort,
@@ -2326,10 +2745,14 @@ HV_t hv = {
     headerUnload,
     headerReload,
     headerCopy,
+    headerLoad,
+    headerCopyLoad,
+    headerRead,
+    headerWrite,
     headerIsEntry,
+    headerFreeTag,
     headerGetEntry,
     headerGetEntryMinMemory,
-    headerGetRawEntry,
     headerAddEntry,
     headerAppendEntry,
     headerAddOrAppendEntry,
@@ -2337,4 +2760,14 @@ HV_t hv = {
     headerModifyEntry,
     headerRemoveEntry,
     headerSprintf,
+    headerCopyTags,
+    headerFreeIterator,
+    headerInitIterator,
+    headerNextIterator,
+    NULL, NULL,
+    1
 };
+
+/*@-compmempass -redef@*/
+HV_t hdrVec = &hdrVec1;
+/*@=compmempass =redef@*/
index 2dedb0e..8a44807 100644 (file)
@@ -203,6 +203,56 @@ enum hMagic {
        HEADER_MAGIC_YES        = 1
 };
 
+/** \ingroup header
+ * The basic types of data in tags from headers.
+ */
+typedef enum rpmTagType_e {
+#define        RPM_MIN_TYPE            0
+    RPM_NULL_TYPE              =  0,
+    RPM_CHAR_TYPE              =  1,
+    RPM_INT8_TYPE              =  2,
+    RPM_INT16_TYPE             =  3,
+    RPM_INT32_TYPE             =  4,
+/*    RPM_INT64_TYPE   = 5,   ---- These aren't supported (yet) */
+    RPM_STRING_TYPE            =  6,
+    RPM_BIN_TYPE               =  7,
+    RPM_STRING_ARRAY_TYPE      =  8,
+    RPM_I18NSTRING_TYPE                =  9
+#define        RPM_MAX_TYPE            9
+} rpmTagType;
+
+/** \ingroup header
+ * New rpm data types under consideration/development.
+ * These data types may (or may not) be added to rpm at some point. In order
+ * to avoid incompatibility with legacy versions of rpm, these data (sub-)types
+ * are introduced into the header by overloading RPM_BIN_TYPE, with the binary
+ * value of the tag a 16 byte image of what should/will be in the header index,
+ * followed by per-tag private data.
+ */
+/*@-enummemuse -typeuse @*/
+typedef enum rpmSubTagType_e {
+       RPM_REGION_TYPE         = -10,
+       RPM_BIN_ARRAY_TYPE      = -11,
+  /*!<@todo Implement, kinda like RPM_STRING_ARRAY_TYPE for known (but variable)
+       length binary data. */
+       RPM_XREF_TYPE           = -12
+  /*!<@todo Implement, intent is to to carry a (???,tagNum,valNum) cross
+       reference to retrieve data from other tags. */
+} rpmSubTagType;
+/*@=enummemuse =typeuse @*/
+
+/**
+ * Header private tags.
+ * @note General use tags should start at 1000 (RPM's tag space starts there).
+ */
+#define        HEADER_IMAGE            61
+#define        HEADER_SIGNATURES       62
+#define        HEADER_IMMUTABLE        63
+#define        HEADER_REGIONS          64
+#define HEADER_I18NTABLE       100
+#define        HEADER_SIGBASE          256
+#define        HEADER_TAGBASE          1000
+
 /**
  */
 /*@-typeuse -fielduse@*/
@@ -232,231 +282,308 @@ typedef struct HE_s {
 } * HE_t;
 /*@=typeuse =fielduse@*/
 
+/** \ingroup header
+ * Create new (empty) header instance.
+ * @return             header
+ */
 typedef
-/*@null@*/ Header (*HVfree) (/*@null@*/ /*@killref@*/ Header h)
-        /*@modifies h @*/;
+Header (*HDRnew) (void)
+       /*@*/;
 
+/** \ingroup header
+ * Dereference a header instance.
+ * @param h            header
+ * @return             NULL always
+ */
 typedef
-Header (*HVlink) (Header h)
+/*@null@*/ Header (*HDRfree) (/*@null@*/ /*@killref@*/ Header h)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Reference a header instance.
+ * @param h            header
+ * @return             referenced header instance
+ */
 typedef
-void (*HVsort) (Header h)
+Header (*HDRlink) (Header h)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Sort tags in header.
+ * @todo Eliminate from API.
+ * @param h            header
+ */
 typedef
-void (*HVunsort) (Header h)
+void (*HDRsort) (Header h)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Restore tags in header to original ordering.
+ * @todo Eliminate from API.
+ * @param h            header
+ */
 typedef
-unsigned int (*HVsize) (/*@null@*/ Header h, enum hMagic magicp)
+void (*HDRunsort) (Header h)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Return size of on-disk header representation in bytes.
+ * @param h            header
+ * @param magicp       include size of 8 bytes for (magic, 0)?
+ * @return             size of on-disk header
+ */
 typedef
-/*@only@*/ /*@null@*/ void * (*HVunload) (Header h)
+unsigned int (*HDRsizeof) (/*@null@*/ Header h, enum hMagic magicp)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Convert header to on-disk representation.
+ * @param h            header (with pointers)
+ * @return             on-disk header blob (i.e. with offsets)
+ */
 typedef
-/*@null@*/ Header (*HVreload) (/*@only@*/ Header h, int tag)
+/*@only@*/ /*@null@*/ void * (*HDRunload) (Header h)
         /*@modifies 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)
+ * @param tag          region tag
+ * @return             on-disk header (with offsets)
+ */
 typedef
-Header (*HVcopy) (Header h)
+/*@null@*/ Header (*HDRreload) (/*@only@*/ Header h, int tag)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Duplicate a header.
+ * @param h            header
+ * @return             new header instance
+ */
 typedef
-int (*HVisentry) (/*@null@*/Header h, int_32 tag)
-        /*@*/;  
-
-typedef
-int (*HVget) (Header h, int_32 tag,
-                       /*@null@*/ /*@out@*/ hTYP_t type,
-                       /*@null@*/ /*@out@*/ void ** p,
-                       /*@null@*/ /*@out@*/ hCNT_t c)
-       /*@modifies *type, *p, *c @*/;
-
-typedef
-int (*HVgetmin) (Header h, int_32 tag,
-                       /*@null@*/ /*@out@*/ hTYP_t type,
-                       /*@null@*/ /*@out@*/ hPTR_t * p,
-                       /*@null@*/ /*@out@*/ hCNT_t c)
-       /*@modifies *type, *p, *c @*/;
-
-typedef
-int (*HVgetraw) (Header h, int_32 tag,
-                       /*@null@*/ /*@out@*/ hTYP_t type,
-                       /*@null@*/ /*@out@*/ hPTR_t * p,
-                       /*@null@*/ /*@out@*/ hCNT_t c)
-       /*@modifies *type, *p, *c @*/;
-
-typedef
-int (*HVadd) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
+Header (*HDRcopy) (Header h)
         /*@modifies h @*/;
 
+/** \ingroup header
+ * Convert header to in-memory representation.
+ * @param uh           on-disk header blob (i.e. with offsets)
+ * @return             header
+ */
 typedef
-int (*HVappend) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
-        /*@modifies h @*/;
+/*@null@*/ Header (*HDRload) (/*@kept@*/ void * uh)
+       /*@modifies uh @*/;
 
+/** \ingroup header
+ * Make a copy and convert header to in-memory representation.
+ * @param uh           on-disk header blob (i.e. with offsets)
+ * @return             header
+ */
 typedef
-int (*HVaddorappend) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
-        /*@modifies h @*/;
+/*@null@*/ Header (*HDRcopyload) (const void * uh)
+       /*@*/;
 
+/** \ingroup header
+ * Read (and load) header from file handle.
+ * @param fd           file handle
+ * @param magicp       read (and verify) 8 bytes of (magic, 0)?
+ * @return             header (or NULL on error)
+ */
 typedef
-int (*HVaddi18n) (Header h, int_32 tag, const char * string,
-                const char * lang)
-        /*@modifies h @*/;
+/*@null@*/ Header (*HDRhdrread) (FD_t fd, enum hMagic magicp)
+       /*@modifies fd, fileSystem @*/;
 
+/** \ingroup header
+ * Write (with unload) header to file handle.
+ * @param fd           file handle
+ * @param h            header
+ * @param magicp       prefix write with 8 bytes of (magic, 0)?
+ * @return             0 on success, 1 on error
+ */
 typedef
-int (*HVmodify) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
-        /*@modifies h @*/;
+int (*HDRhdrwrite) (FD_t fd, /*@null@*/ Header h, enum hMagic magicp)
+       /*@modifies fd, h, fileSystem @*/;
 
+/** \ingroup header
+ * Check if tag is in header.
+ * @param h            header
+ * @param tag          tag
+ * @return             1 on success, 0 on failure
+ */
 typedef
-int (*HVremove) (Header h, int_32 tag)
-        /*@modifies h @*/;
+int (*HDRisentry) (/*@null@*/Header h, int_32 tag)
+        /*@*/;  
 
+/** \ingroup header
+ * Free data allocated when retrieved from header.
+ * @param h            header
+ * @param data         address of data (or NULL)
+ * @param type         type of data (or -1 to force free)
+ * @return             NULL always
+ */
 typedef
-/*@only@*/ char * (*HVsprintf) (Header h, const char * fmt,
-                    const struct headerTagTableEntry * tags,
-                    const struct headerSprintfExtension * extensions,
-                    /*@null@*/ /*@out@*/ errmsg_t * errmsg)
-       /*@modifies *errmsg @*/;
-
-typedef struct HV_s {
-    HVfree     free;
-    HVlink     link;
-    HVsort     sort;
-    HVunsort   unsort;
-    HVsize     size;
-    HVunload   unload;
-    HVreload   reload;
-    HVcopy     copy;
-    HVisentry  isentry;
-    HVget      get;
-    HVgetmin   getmin;
-    HVgetraw   getraw;
-    HVadd      add;
-    HVappend   append;
-    HVaddorappend addorappend;
-    HVaddi18n  addi18n;
-    HVmodify   modify;
-    HVremove   remove;
-    HVsprintf  sprintf;
-} HV_t;
+/*@null@*/ void * (*HDRfreetag) (Header h,
+               /*@only@*/ /*@null@*/ const void * data, rpmTagType type)
+       /*@modifies data @*/;
 
 /** \ingroup header
- * The basic types of data in tags from headers.
+ * Retrieve tag value.
+ * Will never return RPM_I18NSTRING_TYPE! RPM_STRING_TYPE elements with
+ * RPM_I18NSTRING_TYPE equivalent entries are translated (if HEADER_I18NTABLE
+ * entry is present).
+ *
+ * @param h            header
+ * @param tag          tag
+ * @retval type                address of tag value data type (or NULL)
+ * @retval p           address of pointer to tag value(s) (or NULL)
+ * @retval c           address of number of values (or NULL)
+ * @return             1 on success, 0 on failure
  */
-typedef enum rpmTagType_e {
-#define        RPM_MIN_TYPE            0
-    RPM_NULL_TYPE              =  0,
-    RPM_CHAR_TYPE              =  1,
-    RPM_INT8_TYPE              =  2,
-    RPM_INT16_TYPE             =  3,
-    RPM_INT32_TYPE             =  4,
-/*    RPM_INT64_TYPE   = 5,   ---- These aren't supported (yet) */
-    RPM_STRING_TYPE            =  6,
-    RPM_BIN_TYPE               =  7,
-    RPM_STRING_ARRAY_TYPE      =  8,
-    RPM_I18NSTRING_TYPE                =  9
-#define        RPM_MAX_TYPE            9
-} rpmTagType;
+typedef
+int (*HDRget) (Header h, int_32 tag,
+                       /*@null@*/ /*@out@*/ hTYP_t type,
+                       /*@null@*/ /*@out@*/ void ** p,
+                       /*@null@*/ /*@out@*/ hCNT_t c)
+       /*@modifies *type, *p, *c @*/;
 
 /** \ingroup header
- * New rpm data types under consideration/development.
- * These data types may (or may not) be added to rpm at some point. In order
- * to avoid incompatibility with legacy versions of rpm, these data (sub-)types
- * are introduced into the header by overloading RPM_BIN_TYPE, with the binary
- * value of the tag a 16 byte image of what should/will be in the header index,
- * followed by per-tag private data.
+ * Retrieve tag value using header internal array.
+ * Get an entry using as little extra RAM as possible to return the tag value.
+ * This is only an issue for RPM_STRING_ARRAY_TYPE.
+ *
+ * @param h            header
+ * @param tag          tag
+ * @retval type                address of tag value data type (or NULL)
+ * @retval p           address of pointer to tag value(s) (or NULL)
+ * @retval c           address of number of values (or NULL)
+ * @return             1 on success, 0 on failure
  */
-/*@-enummemuse -typeuse @*/
-typedef enum rpmSubTagType_e {
-       RPM_REGION_TYPE         = -10,
-       RPM_BIN_ARRAY_TYPE      = -11,
-  /*!<@todo Implement, kinda like RPM_STRING_ARRAY_TYPE for known (but variable)
-       length binary data. */
-       RPM_XREF_TYPE           = -12
-  /*!<@todo Implement, intent is to to carry a (???,tagNum,valNum) cross
-       reference to retrieve data from other tags. */
-} rpmSubTagType;
-/*@=enummemuse =typeuse @*/
+typedef
+int (*HDRgetmin) (Header h, int_32 tag,
+                       /*@null@*/ /*@out@*/ hTYP_t type,
+                       /*@null@*/ /*@out@*/ hPTR_t * p,
+                       /*@null@*/ /*@out@*/ hCNT_t c)
+       /*@modifies *type, *p, *c @*/;
 
-/**
- * Header private tags.
- * @note General use tags should start at 1000 (RPM's tag space starts there).
+/** \ingroup header
+ * Add tag to header.
+ * Duplicate tags are okay, but only defined for iteration (with the
+ * exceptions noted below). While you are allowed to add i18n string
+ * arrays through this function, you probably don't mean to. See
+ * headerAddI18NString() instead.
+ *
+ * @param h            header
+ * @param tag          tag
+ * @param type         tag value data type
+ * @param p            pointer to tag value(s)
+ * @param c            number of values
+ * @return             1 on success, 0 on failure
  */
-#define        HEADER_IMAGE            61
-#define        HEADER_SIGNATURES       62
-#define        HEADER_IMMUTABLE        63
-#define        HEADER_REGIONS          64
-#define HEADER_I18NTABLE       100
-#define        HEADER_SIGBASE          256
-#define        HEADER_TAGBASE          1000
+typedef
+int (*HDRadd) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
+        /*@modifies h @*/;
 
 /** \ingroup header
- * Free data allocated when retrieved from header.
- * @param data         address of data (or NULL)
- * @param type         type of data (or -1 to force free)
- * @return             NULL always
+ * Append element to tag array in header.
+ * Appends item p to entry w/ tag and type as passed. Won't work on
+ * RPM_STRING_TYPE. Any pointers into header memory returned from
+ * headerGetEntryMinMemory() for this entry are invalid after this
+ * call has been made!
+ *
+ * @param h            header
+ * @param tag          tag
+ * @param type         tag value data type
+ * @param p            pointer to tag value(s)
+ * @param c            number of values
+ * @return             1 on success, 0 on failure
  */
-/*@unused@*/ static inline /*@null@*/
-void * headerFreeData( /*@only@*/ /*@null@*/ const void * data, rpmTagType type)
-       /*@modifies data @*/
-{
-    if (data) {
-       /*@-branchstate@*/
-       if (type == -1 ||
-           type == RPM_STRING_ARRAY_TYPE ||
-           type == RPM_I18NSTRING_TYPE ||
-           type == RPM_BIN_TYPE)
-               free((void *)data);
-       /*@=branchstate@*/
-    }
-    return NULL;
-}
+typedef
+int (*HDRappend) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
+        /*@modifies h @*/;
 
 /** \ingroup header
- * Create new (empty) header instance.
- * @return             header
+ * Add or append element to tag array in header.
+ * @todo Arg "p" should have const.
+ * @param h            header
+ * @param tag          tag
+ * @param type         tag value data type
+ * @param p            pointer to tag value(s)
+ * @param c            number of values
+ * @return             1 on success, 0 on failure
  */
-Header headerNew(void) /*@*/;
+typedef
+int (*HDRaddorappend) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
+        /*@modifies h @*/;
 
 /** \ingroup header
- * Convert header to in-memory representation.
- * @param uh           on-disk header blob (i.e. with offsets)
- * @return             header
+ * Add locale specific tag to header.
+ * A NULL lang is interpreted as the C locale. Here are the rules:
+ * \verbatim
+ *     - If the tag isn't in the header, it's added with the passed string
+ *        as new value.
+ *     - If the tag occurs multiple times in entry, which tag is affected
+ *        by the operation is undefined.
+ *     - If the tag is in the header w/ this language, the entry is
+ *        *replaced* (like headerModifyEntry()).
+ * \endverbatim
+ * This function is intended to just "do the right thing". If you need
+ * more fine grained control use headerAddEntry() and headerModifyEntry().
+ *
+ * @param h            header
+ * @param tag          tag
+ * @param string       tag value
+ * @param lang         locale
+ * @return             1 on success, 0 on failure
  */
-/*@-exportlocal@*/
-/*@null@*/ Header headerLoad(/*@kept@*/ void * uh)
-       /*@modifies uh @*/;
-/*@=exportlocal@*/
+typedef
+int (*HDRaddi18n) (Header h, int_32 tag, const char * string,
+                const char * lang)
+        /*@modifies h @*/;
 
 /** \ingroup header
- * Write (with unload) header to file handle.
- * @param fd           file handle
+ * Modify tag in header.
+ * If there are multiple entries with this tag, the first one gets replaced.
  * @param h            header
- * @param magicp       prefix write with 8 bytes of (magic, 0)?
- * @return             0 on success, 1 on error
+ * @param tag          tag
+ * @param type         tag value data type
+ * @param p            pointer to tag value(s)
+ * @param c            number of values
+ * @return             1 on success, 0 on failure
  */
-int headerWrite(FD_t fd, /*@null@*/ Header h, enum hMagic magicp)
-       /*@modifies fd, h, fileSystem @*/;
+typedef
+int (*HDRmodify) (Header h, int_32 tag, int_32 type, const void * p, int_32 c)
+        /*@modifies h @*/;
 
 /** \ingroup header
- * Make a copy and convert header to in-memory representation.
- * @param uh           on-disk header blob (i.e. with offsets)
- * @return             header
+ * Delete tag in header.
+ * Removes all entries of type tag from the header, returns 1 if none were
+ * found.
+ *
+ * @param h            header
+ * @param tag          tag
+ * @return             0 on success, 1 on failure (INCONSISTENT)
  */
-/*@null@*/ Header headerCopyLoad(void * uh)
-       /*@modifies uh @*/;
+typedef
+int (*HDRremove) (Header h, int_32 tag)
+        /*@modifies h @*/;
 
 /** \ingroup header
- * Read (and load) header from file handle.
- * @param fd           file handle
- * @param magicp       read (and verify) 8 bytes of (magic, 0)?
- * @return             header (or NULL on error)
+ * Return formatted output string from header tags.
+ * The returned string must be free()d.
+ *
+ * @param h            header
+ * @param fmt          format to use
+ * @param tags         array of tag name/value pairs
+ * @param extensions   chained table of formatting extensions.
+ * @retval errmsg      error message (if any)
+ * @return             formatted output string (malloc'ed)
  */
-/*@null@*/ Header headerRead(FD_t fd, enum hMagic magicp)
-       /*@modifies fd, fileSystem @*/;
+typedef
+/*@only@*/ char * (*HDRhdrsprintf) (Header h, const char * fmt,
+                    const struct headerTagTableEntry * tags,
+                    const struct headerSprintfExtension * extensions,
+                    /*@null@*/ /*@out@*/ errmsg_t * errmsg)
+       /*@modifies *errmsg @*/;
 
 /** \ingroup header
  * Duplicate tag values from one header into another.
@@ -464,14 +591,17 @@ int headerWrite(FD_t fd, /*@null@*/ Header h, enum hMagic magicp)
  * @param headerTo     destination header
  * @param tagstocopy   array of tags that are copied
  */
-void headerCopyTags(Header headerFrom, Header headerTo, hTAG_t tagstocopy)
+typedef
+void (*HDRcopytags) (Header headerFrom, Header headerTo, hTAG_t tagstocopy)
        /*@modifies headerFrom, headerTo @*/;
 
 /** \ingroup header
  * Destroy header tag iterator.
  * @param hi           header tag iterator
+ * @return             NULL always
  */
-void headerFreeIterator(/*@only@*/ HeaderIterator hi)
+typedef
+HeaderIterator (*HDRfreeiter) (/*@only@*/ HeaderIterator hi)
        /*@modifies hi @*/;
 
 /** \ingroup header
@@ -479,7 +609,8 @@ void headerFreeIterator(/*@only@*/ HeaderIterator hi)
  * @param h            header
  * @return             header tag iterator
  */
-HeaderIterator headerInitIterator(Header h)
+typedef
+HeaderIterator (*HDRinititer) (Header h)
        /*@modifies h */;
 
 /** \ingroup header
@@ -491,13 +622,77 @@ HeaderIterator headerInitIterator(Header h)
  * @retval c           address of number of values
  * @return             1 on success, 0 on failure
  */
-int headerNextIterator(HeaderIterator hi,
+typedef
+int (*HDRnextiter) (HeaderIterator hi,
                /*@null@*/ /*@out@*/ hTAG_t tag,
                /*@null@*/ /*@out@*/ hTYP_t type,
                /*@null@*/ /*@out@*/ hPTR_t * p,
                /*@null@*/ /*@out@*/ hCNT_t c)
        /*@modifies hi, *tag, *type, *p, *c @*/;
 
+/** \ingroup header
+ * Header method vectors.
+ */
+typedef /*@abstract@*/ struct HV_s * HV_t;
+struct HV_s {
+    HDRnew     hdrnew;
+    HDRfree    hdrfree;
+    HDRlink    hdrlink;
+    HDRsort    hdrsort;
+    HDRunsort  hdrunsort;
+    HDRsizeof  hdrsizeof;
+    HDRunload  hdrunload;
+    HDRreload  hdrreload;
+    HDRcopy    hdrcopy;
+    HDRload    hdrload;
+    HDRcopyload        hdrcopyload;
+    HDRhdrread hdrread;
+    HDRhdrwrite        hdrwrite;
+    HDRisentry hdrisentry;
+    HDRfreetag hdrfreetag;
+    HDRget     hdrget;
+    HDRgetmin  hdrgetmin;
+    HDRadd     hdradd;
+    HDRappend  hdrappend;
+    HDRaddorappend hdraddorappend;
+    HDRaddi18n hdraddi18n;
+    HDRmodify  hdrmodify;
+    HDRremove  hdrremove;
+    HDRhdrsprintf hdrsprintf;
+    HDRcopytags        hdrcopytags;
+    HDRfreeiter        hdrfreeiter;
+    HDRinititer        hdrinititer;
+    HDRnextiter        hdrnextiter;
+    void *     hdrvecs;
+    void *     hdrdata;
+    int                hdrversion;
+};
+
+/** \ingroup header
+ * Free data allocated when retrieved from header.
+ * @deprecated Use headerFreeTag() instead.
+ * @todo Remove from API.
+ *
+ * @param data         address of data (or NULL)
+ * @param type         type of data (or -1 to force free)
+ * @return             NULL always
+ */
+/*@unused@*/ static inline /*@null@*/
+void * headerFreeData( /*@only@*/ /*@null@*/ const void * data, rpmTagType type)
+       /*@modifies data @*/
+{
+    if (data) {
+       /*@-branchstate@*/
+       if (type == -1 ||
+           type == RPM_STRING_ARRAY_TYPE ||
+           type == RPM_I18NSTRING_TYPE ||
+           type == RPM_BIN_TYPE)
+               free((void *)data);
+       /*@=branchstate@*/
+    }
+    return NULL;
+}
+
 #if defined(__HEADER_PROTOTYPES__)
 #include <hdrproto.h>
 #else
index 1087214..02266b4 100644 (file)
@@ -51,13 +51,14 @@ struct indexEntry {
  * The Header data structure.
  */
 struct headerToken {
-/*@unused@*/ HV_t hv;          /*!< Header public methods. */
+/*@unused@*/ struct HV_s hv;   /*!< Header public methods. */
 /*@owned@*/ indexEntry index;  /*!< Array of tags. */
     int indexUsed;             /*!< Current size of tag array. */
     int indexAlloced;          /*!< Allocated size of tag array. */
-    int region_allocated;      /*!< Is 1st header region allocated? */
-    int sorted;                /*!< Are header entries sorted? */
-    int legacy;                        /*!< Header came from legacy source? */
+    int flags;
+#define        HEADERFLAG_SORTED       (1 << 0) /*!< Are header entries sorted? */
+#define        HEADERFLAG_ALLOCATED    (1 << 1) /*!< Is 1st header region allocated? */
+#define        HEADERFLAG_LEGACY       (1 << 2) /*!< Header came from legacy source? */
 /*@refs@*/ int nrefs;  /*!< Reference count. */
 };
 
@@ -124,65 +125,6 @@ extern "C" {
 #endif
 
 /** \ingroup header
- */
-extern unsigned char header_magic[8];
-
-/** \ingroup header
- */
-extern HV_t hv;
-
-/** \ingroup header
- * Swap int_32 and int_16 arrays within header region.
- *
- * This code is way more twisty than I would like.
- *
- * A bug with RPM_I18NSTRING_TYPE in rpm-2.5.x (fixed in August 1998)
- * causes the offset and length of elements in a header region to disagree
- * regarding the total length of the region data.
- *
- * The "fix" is to compute the size using both offset and length and
- * return the larger of the two numbers as the size of the region.
- * Kinda like computing left and right Riemann sums of the data elements
- * to determine the size of a data structure, go figger :-).
- *
- * There's one other twist if a header region tag is in the set to be swabbed,
- * as the data for a header region is located after all other tag data.
- *
- * @param entry                header entry
- * @param il           no. of entries
- * @param dl           start no. bytes of data
- * @param pe           header physical entry pointer (swapped)
- * @param dataStart    header data
- * @param regionid     region offset
- * @return             no. bytes of data in region, -1 on error
- */
-int regionSwab(/*@null@*/ indexEntry entry, int il, int dl,
-               entryInfo pe, char * dataStart, int regionid)
-       /*@modifies entry, *dataStart @*/;
-
-/** \ingroup header
- */
-/*@only@*/ /*@null@*/ void * doHeaderUnload(Header h, /*@out@*/ int * lengthPtr)
-       /*@modifies h, *lengthPtr @*/;
-
-/** \ingroup header
- * Retrieve data from header entry.
- * @todo Permit retrieval of regions other than HEADER_IMUTABLE.
- * @param entry                header entry
- * @retval type                address of type (or NULL)
- * @retval p           address of data (or NULL)
- * @retval c           address of count (or NULL)
- * @param minMem       string pointers refer to header memory?
- * @return             1 on success, otherwise error.
- */
-int copyEntry(const indexEntry entry,
-               /*@null@*/ /*@out@*/ hTYP_t type,
-               /*@null@*/ /*@out@*/ hPTR_t * p,
-               /*@null@*/ /*@out@*/ hCNT_t c,
-               int minMem)
-       /*@modifies *type, *p, *c @*/;
-
-/** \ingroup header
  * Return array of locales found in header.
  * The array is terminated with a NULL sentinel.
  * @param h            header
@@ -193,6 +135,26 @@ int copyEntry(const indexEntry entry,
        /*@*/;
 
 /** \ingroup header
+ * Retrieve tag value with type match.
+ * If *type is RPM_NULL_TYPE any type will match, otherwise only *type will
+ * match.
+ *
+ * @param h            header
+ * @param tag          tag
+ * @retval type                address of tag value data type (or NULL)
+ * @retval p           address of pointer to tag value(s) (or NULL)
+ * @retval c           address of number of values (or NULL)
+ * @return             1 on success, 0 on failure
+ */
+/*@-exportlocal@*/
+int headerGetRawEntry(Header h, int_32 tag,
+                       /*@null@*/ /*@out@*/ hTYP_t type,
+                       /*@null@*/ /*@out@*/ hPTR_t * p, 
+                       /*@null@*/ /*@out@*/ hCNT_t c)
+       /*@modifies *type, *p, *c @*/;
+/*@=exportlocal@*/
+
+/** \ingroup header
  * Return header reference count.
  * @param h            header
  * @return             no. of references
index 1958321..cc2f6a7 100644 (file)
@@ -49,7 +49,7 @@ void headerMergeLegacySigs(Header h, const Header sig)
        if (!headerIsEntry(h, tag))
            (void) hae(h, tag, type, ptr, count);
     }
-    headerFreeIterator(hi);
+    hi = headerFreeIterator(hi);
 }
 
 Header headerRegenSigHeader(const Header h)
@@ -82,7 +82,7 @@ Header headerRegenSigHeader(const Header h)
        if (!headerIsEntry(sig, stag))
            (void) headerAddEntry(sig, stag, type, ptr, count);
     }
-    headerFreeIterator(hi);
+    hi = headerFreeIterator(hi);
     return sig;
 }
 /*@=mods@*/
index 76426d5..ff2bcba 100644 (file)
@@ -426,7 +426,7 @@ int rpmCheckSig(rpmCheckSigFlags flags, const char **argv)
                }
            }
        }
-       headerFreeIterator(hi);
+       hi = headerFreeIterator(hi);
        res += res2;
        (void) unlink(sigtarget);
        sigtarget = _free(sigtarget);
index 8af440d..e0d9ce8 100644 (file)
@@ -29,7 +29,6 @@ lib/depends.c
 lib/formats.c
 lib/fs.c
 lib/fsm.c
-lib/hdrinline.c
 lib/header.c
 lib/header_internal.c
 lib/manifest.c