- 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.
@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 \
break;
}
}
- headerFreeIterator(hi);
+ hi = headerFreeIterator(hi);
/* Add the build restrictions */
for (hi = headerInitIterator(spec->buildRestrictions);
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,
tagName(tag), NVR);
res = 1;
}
- headerFreeIterator(hi);
+ hi = headerFreeIterator(hi);
return res;
}
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 \
+++ /dev/null
-/** \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);
-}
* \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.
/*@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
Header headerLink(Header h)
/*@modifies h @*/
{
- return (HV(h)->link) (h);
+ return (h2hv(h)->hdrlink) (h);
}
/*@-exportlocal@*/
void headerSort(Header h)
/*@modifies h @*/
{
- return (HV(h)->sort) (h);
+ return (h2hv(h)->hdrsort) (h);
}
/** \ingroup header
void headerUnsort(Header h)
/*@modifies h @*/
{
- return (HV(h)->unsort) (h);
+ return (h2hv(h)->hdrunsort) (h);
}
/*@=exportlocal@*/
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
/*@only@*/ /*@null@*/ void * headerUnload(Header h)
/*@modifies h @*/
{
- return (HV(h)->unload) (h);
+ return (h2hv(h)->hdrunload) (h);
}
/** \ingroup header
/*@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
/*@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
* @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
/*@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
/*@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.
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
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
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
const char * lang)
/*@modifies h @*/
{
- return (HV(h)->addi18n) (h, tag, string, lang);
+ return (h2hv(h)->hdraddi18n) (h, tag, string, lang);
}
/** \ingroup header
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
int headerRemoveEntry(Header h, int_32 tag)
/*@modifies h @*/
{
- return (HV(h)->remove) (h, tag);
+ return (h2hv(h)->hdrremove) (h, tag);
}
/** \ingroup header
/*@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
}
#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
/*@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
/*@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
/*@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
/*@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
};
-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
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)
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. */
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;
}
}
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;
}
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 @*/
{
}
#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;
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. */
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;
if (lengthPtr)
*lengthPtr = len;
- h->sorted = 0;
+ h->flags &= ~HEADERFLAG_SORTED;
headerSort(h);
return (void *) ei;
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;
{
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
struct indexEntry key;
if (h == NULL) return NULL;
- if (!h->sorted) headerSort(h);
+ if (!(h->flags & HEADERFLAG_SORTED)) headerSort(h);
key.info.tag = 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,
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);
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;
{ 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,
headerUnload,
headerReload,
headerCopy,
+ headerLoad,
+ headerCopyLoad,
+ headerRead,
+ headerWrite,
headerIsEntry,
+ headerFreeTag,
headerGetEntry,
headerGetEntryMinMemory,
- headerGetRawEntry,
headerAddEntry,
headerAppendEntry,
headerAddOrAppendEntry,
headerModifyEntry,
headerRemoveEntry,
headerSprintf,
+ headerCopyTags,
+ headerFreeIterator,
+ headerInitIterator,
+ headerNextIterator,
+ NULL, NULL,
+ 1
};
+
+/*@-compmempass -redef@*/
+HV_t hdrVec = &hdrVec1;
+/*@=compmempass =redef@*/
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@*/
} * 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.
* @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
* @param h header
* @return header tag iterator
*/
-HeaderIterator headerInitIterator(Header h)
+typedef
+HeaderIterator (*HDRinititer) (Header h)
/*@modifies h */;
/** \ingroup header
* @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
* 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. */
};
#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
/*@*/;
/** \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
if (!headerIsEntry(h, tag))
(void) hae(h, tag, type, ptr, count);
}
- headerFreeIterator(hi);
+ hi = headerFreeIterator(hi);
}
Header headerRegenSigHeader(const Header h)
if (!headerIsEntry(sig, stag))
(void) headerAddEntry(sig, stag, type, ptr, count);
}
- headerFreeIterator(hi);
+ hi = headerFreeIterator(hi);
return sig;
}
/*@=mods@*/
}
}
}
- headerFreeIterator(hi);
+ hi = headerFreeIterator(hi);
res += res2;
(void) unlink(sigtarget);
sigtarget = _free(sigtarget);
lib/formats.c
lib/fs.c
lib/fsm.c
-lib/hdrinline.c
lib/header.c
lib/header_internal.c
lib/manifest.c