Modify eu-strip option to perform strip in post script of rpm package & add option...
[platform/upstream/rpm.git] / lib / header.c
index 403084b..90079f3 100644 (file)
 
 #include "system.h"
 #include <netdb.h>
+#include <errno.h>
 #include <rpm/rpmtypes.h>
 #include <rpm/rpmstring.h>
 #include "lib/header_internal.h"
 #include "lib/misc.h"                  /* tag function proto */
 
+#include <errno.h>
 #include "debug.h"
 
 /** \ingroup header
@@ -199,7 +201,7 @@ int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
            return i;
        if (hdrchkAlign(info->type, info->offset))
            return i;
-       if (!negate && hdrchkRange(dl, info->offset))
+       if (hdrchkRange(dl, info->offset))
            return i;
        if (hdrchkData(info->count))
            return i;
@@ -301,16 +303,27 @@ unsigned headerSizeof(Header h, int magicp)
     return size;
 }
 
-/* Bounded header string (array) size calculation, return -1 on error */
+/*
+ * Header string (array) size calculation, bounded if end is non-NULL.
+ * Return length (including \0 termination) on success, -1 on error.
+ */
 static inline int strtaglen(const char *str, rpm_count_t c, const char *end)
 {
     const char *start = str;
     const char *s;
 
-    while ((s = memchr(start, '\0', end-start))) {
-       if (--c == 0 || s > end)
-           break;
-       start = s + 1;
+    if (end) {
+       while ((s = memchr(start, '\0', end-start))) {
+           if (--c == 0 || s > end)
+               break;
+           start = s + 1;
+       }
+    } else {
+       while ((s = strchr(start, '\0'))) {
+           if (--c == 0)
+               break;
+           start = s + 1;
+       }
     }
     return (c > 0) ? -1 : (s - str + 1);
 }
@@ -328,8 +341,7 @@ static int dataLength(rpm_tagtype_t type, rpm_constdata_t p, rpm_count_t count,
                         int onDisk, rpm_constdata_t pend)
 {
     const char * s = p;
-    /* Not all callers supply data end, avoid falling over edge of the world */
-    const char * se = pend ? pend : s + HEADER_DATA_MAX;
+    const char * se = pend;
     int length = 0;
 
     switch (type) {
@@ -380,13 +392,14 @@ static int dataLength(rpm_tagtype_t type, rpm_constdata_t p, rpm_count_t count,
  * @param dataStart    header data start
  * @param dataEnd      header data end
  * @param regionid     region offset
+ * @param fast         use offsets for data sizes if possible
  * @return             no. bytes of data in region, -1 on error
  */
 static int regionSwab(indexEntry entry, int il, int dl,
                entryInfo pe,
                unsigned char * dataStart,
                const unsigned char * dataEnd,
-               int regionid)
+               int regionid, int fast)
 {
     if ((entry != NULL && regionid >= 0) || (entry == NULL && regionid != 0))
        return -1;
@@ -412,7 +425,12 @@ static int regionSwab(indexEntry entry, int il, int dl,
        if (dataEnd && (unsigned char *)ie.data >= dataEnd)
            return -1;
 
-       ie.length = dataLength(ie.info.type, ie.data, ie.info.count, 1, dataEnd);
+       if (fast && il > 1) {
+           ie.length = ntohl(pe[1].offset) - ie.info.offset;
+       } else {
+           ie.length = dataLength(ie.info.type, ie.data, ie.info.count,
+                                  1, dataEnd);
+       }
        if (ie.length < 0 || hdrchkData(ie.length))
            return -1;
 
@@ -461,13 +479,7 @@ static int regionSwab(indexEntry entry, int il, int dl,
     return dl;
 }
 
-/** \ingroup header
- * doHeaderUnload.
- * @param h            header
- * @retval *lengthPtr  no. bytes in unloaded header blob
- * @return             unloaded header blob (NULL on error)
- */
-static void * doHeaderUnload(Header h, size_t * lengthPtr)
+void * headerExport(Header h, unsigned int *bsize)
 {
     int32_t * ei = NULL;
     entryInfo pe;
@@ -586,7 +598,7 @@ static void * doHeaderUnload(Header h, size_t * lengthPtr)
                ril++;
                rdlen += entry->info.count;
 
-               count = regionSwab(NULL, ril, 0, pe, t, NULL, 0);
+               count = regionSwab(NULL, ril, 0, pe, t, NULL, 0, 0);
                if (count != rdlen)
                    goto errxit;
 
@@ -602,7 +614,7 @@ static void * doHeaderUnload(Header h, size_t * lengthPtr)
                }
                te += entry->info.count + drlen;
 
-               count = regionSwab(NULL, ril, 0, pe, t, NULL, 0);
+               count = regionSwab(NULL, ril, 0, pe, t, NULL, 0, 0);
                if (count != (rdlen + entry->info.count + drlen))
                    goto errxit;
            }
@@ -677,8 +689,8 @@ static void * doHeaderUnload(Header h, size_t * lengthPtr)
     if ((((char *)ei)+len) != te)
        goto errxit;
 
-    if (lengthPtr)
-       *lengthPtr = len;
+    if (bsize)
+       *bsize = len;
 
     headerSort(h);
 
@@ -691,7 +703,7 @@ errxit:
 
 void * headerUnload(Header h)
 {
-    return doHeaderUnload(h, NULL);
+    return headerExport(h, NULL);
 }
 
 /**
@@ -779,6 +791,7 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
     unsigned char * dataEnd;
     indexEntry entry; 
     int rdlen;
+    int fast = (flags & HEADERIMPORT_FAST);
 
     /* Sanity checks on header intro. */
     if (bsize && bsize != pvlen)
@@ -803,7 +816,8 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
 
        entry->data = pe;
        entry->length = pvlen - sizeof(il) - sizeof(dl);
-       rdlen = regionSwab(entry+1, il, 0, pe, dataStart, dataEnd, entry->info.offset);
+       rdlen = regionSwab(entry+1, il, 0, pe,
+                          dataStart, dataEnd, entry->info.offset, fast);
        if (rdlen != dl)
            goto errxit;
        entry->rdlen = rdlen;
@@ -816,10 +830,13 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
 
        entry->info.type = htonl(pe->type);
        entry->info.count = htonl(pe->count);
+       entry->info.tag = htonl(pe->tag);
 
-       if (hdrchkType(entry->info.type))
+       if (!ENTRY_IS_REGION(entry))
            goto errxit;
-       if (hdrchkTags(entry->info.count))
+       if (entry->info.type != REGION_TAG_TYPE)
+           goto errxit;
+       if (entry->info.count != REGION_TAG_COUNT)
            goto errxit;
 
        {   int off = ntohl(pe->offset);
@@ -835,7 +852,6 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
                ril = rdl/sizeof(*pe);
                if (hdrchkTags(ril) || hdrchkData(rdl))
                    goto errxit;
-               entry->info.tag = htonl(pe->tag);
            } else {
                ril = il;
                rdl = (ril * sizeof(struct entryInfo_s));
@@ -846,7 +862,8 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
 
        entry->data = pe;
        entry->length = pvlen - sizeof(il) - sizeof(dl);
-       rdlen = regionSwab(entry+1, ril-1, 0, pe+1, dataStart, dataEnd, entry->info.offset);
+       rdlen = regionSwab(entry+1, ril-1, 0, pe+1,
+                          dataStart, dataEnd, entry->info.offset, fast);
        if (rdlen < 0)
            goto errxit;
        entry->rdlen = rdlen;
@@ -858,7 +875,7 @@ Header headerImport(void * blob, unsigned int bsize, headerImportFlags flags)
 
            /* Load dribble entries from region. */
            rdlen = regionSwab(newEntry, ne, rdlen, pe+ril,
-                               dataStart, dataEnd, rid);
+                               dataStart, dataEnd, rid, fast);
            if (rdlen < 0)
                goto errxit;
 
@@ -908,8 +925,8 @@ errxit:
 Header headerReload(Header h, rpmTagVal tag)
 {
     Header nh;
-    size_t uc = 0;
-    void * uh = doHeaderUnload(h, &uc);
+    unsigned int uc = 0;
+    void * uh = headerExport(h, &uc);
 
     h = headerFree(h);
     if (uh == NULL)
@@ -949,7 +966,7 @@ Header headerRead(FD_t fd, int magicp)
     if (magicp == HEADER_MAGIC_YES) {
        int32_t magic;
 
-       if (Fread(block, 1, 4*sizeof(*block), fd) != 4*sizeof(*block))
+       if (Freadall(fd, block, 4*sizeof(*block)) != 4*sizeof(*block))
            goto exit;
 
        magic = block[0];
@@ -960,7 +977,7 @@ Header headerRead(FD_t fd, int magicp)
        il = ntohl(block[2]);
        dl = ntohl(block[3]);
     } else {
-       if (Fread(block, 1, 2*sizeof(*block), fd) != 2*sizeof(*block))
+       if (Freadall(fd, block, 2*sizeof(*block)) != 2*sizeof(*block))
            goto exit;
 
        il = ntohl(block[0]);
@@ -978,7 +995,7 @@ Header headerRead(FD_t fd, int magicp)
     ei[0] = htonl(il);
     ei[1] = htonl(dl);
 
-    if (Fread((char *)&ei[2], 1, blen, fd) != blen)
+    if (Freadall(fd, (char *)&ei[2], blen) != blen)
        goto exit;
     
     h = headerImport(ei, len, 0);
@@ -993,10 +1010,10 @@ exit:
 int headerWrite(FD_t fd, Header h, int magicp)
 {
     ssize_t nb;
-    size_t length;
+    unsigned int length;
     void * uh;
 
-    uh = doHeaderUnload(h, &length);
+    uh = headerExport(h, &length);
     if (uh == NULL)
        return 1;
     switch (magicp) {
@@ -1082,7 +1099,7 @@ static int copyTdEntry(const indexEntry entry, rpmtd td, headerGetFlags flags)
 
            dataStart = (unsigned char *) memcpy(pe + ril, dataStart, rdl);
 
-           rc = regionSwab(NULL, ril, 0, pe, dataStart, dataStart + rdl, 0);
+           rc = regionSwab(NULL, ril, 0, pe, dataStart, dataStart + rdl, 0, 0);
            /* don't return data on failure */
            if (rc < 0) {
                td->data = _free(td->data);
@@ -1307,6 +1324,9 @@ static int intGetTdEntry(Header h, rpmtd td, headerGetFlags flags)
        }
     }
 
+    if (rc == 0)
+       td->flags |= RPMTD_INVALID;
+
     /* XXX 1 on success */
     return ((rc == 1) ? 1 : 0);
 }
@@ -1387,7 +1407,7 @@ static int intAddEntry(Header h, rpmtd td)
 {
     indexEntry entry;
     rpm_data_t data;
-    int length;
+    int length = 0;
 
     /* Count must always be >= 1 for headerAddEntry. */
     if (td->count <= 0)
@@ -1398,9 +1418,8 @@ static int intAddEntry(Header h, rpmtd td)
     if (hdrchkData(td->count))
        return 0;
 
-    length = 0;
     data = grabData(td->type, td->data, td->count, &length);
-    if (data == NULL || length <= 0)
+    if (data == NULL)
        return 0;
 
     /* Allocate more index space if necessary */
@@ -1620,16 +1639,15 @@ int headerMod(Header h, rpmtd td)
     indexEntry entry;
     rpm_data_t oldData;
     rpm_data_t data;
-    int length;
+    int length = 0;
 
     /* First find the tag */
     entry = findEntry(h, td->tag, td->type);
     if (!entry)
        return 0;
 
-    length = 0;
     data = grabData(td->type, td->data, td->count, &length);
-    if (data == NULL || length <= 0)
+    if (data == NULL)
        return 0;
 
     /* make sure entry points to the first occurence of this tag */
@@ -1729,3 +1747,29 @@ void headerSetInstance(Header h, unsigned int instance)
     h->instance = instance;
 }    
 
+#define RETRY_ERROR(_err) \
+    ((_err) == EINTR || (_err) == EAGAIN || (_err) == EWOULDBLOCK)
+
+ssize_t Freadall(FD_t fd, void * buf, ssize_t size)
+{
+    ssize_t total = 0;
+    ssize_t nb = 0;
+    char * bufp = buf;
+
+    while (total < size) {
+       nb = Fread(bufp, 1, size - total, fd);
+
+       if (nb == 0 || (nb < 0 && !RETRY_ERROR(errno))) {
+           total = nb;
+           break;
+       }
+
+       if (nb > 0) {
+           bufp += nb;
+           total += nb;
+       }
+    }
+
+    return total;
+}
+