summaryrefslogtreecommitdiff
path: root/lib/header.c
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2011-11-30 11:24:42 +0200
committerPanu Matilainen <pmatilai@redhat.com>2011-11-30 11:59:35 +0200
commitcd5222b6e323355c26991885d744aa06e0164c59 (patch)
tree3ea3c29ccb294e207d08b6a2a663c255fb8fa8ed /lib/header.c
parenteae671556470136c37951f53ca966cd1bd09aac4 (diff)
downloadlibrpm-tizen-cd5222b6e323355c26991885d744aa06e0164c59.tar.gz
librpm-tizen-cd5222b6e323355c26991885d744aa06e0164c59.tar.bz2
librpm-tizen-cd5222b6e323355c26991885d744aa06e0164c59.zip
Implement "fast" flag to headerImport()
- regionSwab() calling dataLength() on headerImport() is one of the busiest paths in rpm, and dataLength() on string types is a very expensive call as it has to walk through the string looking for \0's. The data size is actually available most of the time by just looking at offsets (idea lifted from rpm5.org), which is an order of magnitude faster than crawling string data. The downside (there always is one) is that with offsets, string data is not validated to contain sufficient number of \0's, which means malformed headers could cause us to crash, burn and overflow when accessing the string data. - The new "fast" mode enables offset-based calculation at callers discretion, ie if the caller can reasonably assume the header is sane (known to be previously validated etc), using the fast-flag will make header loading/importing considerably faster. For now, only headerImport() will use the fast mode but it might make sense to remember the setting in the header and use for other operations as well.
Diffstat (limited to 'lib/header.c')
-rw-r--r--lib/header.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/lib/header.c b/lib/header.c
index a0b392ae6..d0c9b7102 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -380,13 +380,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 +413,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;
@@ -580,7 +586,7 @@ void * headerExport(Header h, unsigned int *bsize)
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;
@@ -596,7 +602,7 @@ void * headerExport(Header h, unsigned int *bsize)
}
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;
}
@@ -773,6 +779,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)
@@ -797,7 +804,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;
@@ -840,7 +848,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;
@@ -852,7 +861,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;
@@ -1076,7 +1085,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);