diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2011-11-30 11:24:42 +0200 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2011-11-30 11:59:35 +0200 |
commit | cd5222b6e323355c26991885d744aa06e0164c59 (patch) | |
tree | 3ea3c29ccb294e207d08b6a2a663c255fb8fa8ed /lib/header.c | |
parent | eae671556470136c37951f53ca966cd1bd09aac4 (diff) | |
download | librpm-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.c | 25 |
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); |