diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-07-14 13:27:21 +0300 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-07-14 13:27:21 +0300 |
commit | 8d1eeb58e450ef4a81497c3233a929350af3e467 (patch) | |
tree | d2dcec64c9449ea431fb259410e1136479e21bc8 /src | |
parent | ab37bd0b0c0da340222f8420ec2ee6ccdd13ce24 (diff) | |
download | apk-tools-8d1eeb58e450ef4a81497c3233a929350af3e467.tar.gz apk-tools-8d1eeb58e450ef4a81497c3233a929350af3e467.tar.bz2 apk-tools-8d1eeb58e450ef4a81497c3233a929350af3e467.tar.xz apk-tools-8d1eeb58e450ef4a81497c3233a929350af3e467.zip |
blob: some helpers to replace snprintf
snprintf is dog slow. make the blob stuff have some helper functions
so we can use them in code paths that are executed often.
Diffstat (limited to 'src')
-rw-r--r-- | src/apk_blob.h | 12 | ||||
-rw-r--r-- | src/archive.c | 2 | ||||
-rw-r--r-- | src/blob.c | 127 | ||||
-rw-r--r-- | src/cache.c | 7 | ||||
-rw-r--r-- | src/database.c | 69 | ||||
-rw-r--r-- | src/package.c | 56 |
6 files changed, 167 insertions, 106 deletions
diff --git a/src/apk_blob.h b/src/apk_blob.h index bea2d08..9ad79c4 100644 --- a/src/apk_blob.h +++ b/src/apk_blob.h @@ -44,13 +44,15 @@ int apk_blob_rsplit(apk_blob_t blob, char split, apk_blob_t *l, apk_blob_t *r); unsigned long apk_blob_hash_seed(apk_blob_t, unsigned long seed); unsigned long apk_blob_hash(apk_blob_t str); int apk_blob_compare(apk_blob_t a, apk_blob_t b); -unsigned int apk_blob_parse_uint(apk_blob_t *b, int radix); -int apk_blob_parse_char(apk_blob_t *b); - int apk_blob_for_each_segment(apk_blob_t blob, const char *split, apk_blob_cb cb, void *ctx); -int apk_hexdump_parse(apk_blob_t to, apk_blob_t from); -int apk_hexdump_format(int tolen, char *to, apk_blob_t from); +void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal); +void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix); +void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary); + +void apk_blob_pull_char(apk_blob_t *b, int expected); +unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix); +void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to); #endif diff --git a/src/archive.c b/src/archive.c index 7e5a926..450c956 100644 --- a/src/archive.c +++ b/src/archive.c @@ -48,7 +48,7 @@ struct tar_header { static int get_octal(char *s, size_t l) { apk_blob_t b = APK_BLOB_PTR_LEN(s, l); - return apk_blob_parse_uint(&b, 8); + return apk_blob_pull_uint(&b, 8); } struct apk_tar_entry_istream { @@ -151,62 +151,117 @@ static inline int dx(int c) return -1; } -unsigned int apk_blob_parse_uint(apk_blob_t *blob, int base) +void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal) { - unsigned int val; - int ch; - - val = 0; - while (blob->len && blob->ptr[0] != 0) { - ch = dx(blob->ptr[0]); - if (ch < 0 || ch >= base) - break; - val *= base; - val += ch; + if (APK_BLOB_IS_NULL(*to)) + return; - blob->ptr++; - blob->len--; + if (to->len < literal.len) { + *to = APK_BLOB_NULL; + return; } - return val; + memcpy(to->ptr, literal.ptr, literal.len); + to->ptr += literal.len; + to->len -= literal.len; } -int apk_blob_parse_char(apk_blob_t *blob) +static const char *xd = "0123456789abcdefghijklmnopqrstuvwxyz"; + +void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix) { - int r; + char buf[64]; + char *ptr = &buf[sizeof(buf)-1]; - if (blob->len == 0 || blob->ptr == NULL) - return -1; - r = blob->ptr[0]; - blob->ptr++; - blob->len--; + if (value == 0) { + apk_blob_push_blob(to, APK_BLOB_STR("0")); + return; + } + + while (value != 0) { + *(ptr--) = xd[value % radix]; + value /= radix; + } - return r; + apk_blob_push_blob(to, APK_BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1])); } -int apk_hexdump_parse(apk_blob_t to, apk_blob_t from) +void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary) { + char *d; int i; - if (to.len * 2 != from.len) - return -1; + if (APK_BLOB_IS_NULL(*to)) + return; - for (i = 0; i < from.len / 2; i++) - to.ptr[i] = (dx(from.ptr[i*2]) << 4) + dx(from.ptr[i*2+1]); + if (to->len < binary.len * 2) { + *to = APK_BLOB_NULL; + return; + } - return 0; + for (i = 0, d = to->ptr; i < binary.len; i++) { + *(d++) = xd[(binary.ptr[i] >> 4) & 0xf]; + *(d++) = xd[binary.ptr[i] & 0xf]; + } + to->ptr = d; + to->len -= binary.len * 2; } -int apk_hexdump_format(int tolen, char *to, apk_blob_t from) +void apk_blob_pull_char(apk_blob_t *b, int expected) { - static const char *xd = "0123456789abcdef"; - int i; + if (APK_BLOB_IS_NULL(*b)) + return; + if (b->len < 1 || b->ptr[0] != expected) { + *b = APK_BLOB_NULL; + return; + } + b->ptr ++; + b->len --; +} + +unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix) +{ + unsigned int val; + int ch; + + val = 0; + while (b->len && b->ptr[0] != 0) { + ch = dx(b->ptr[0]); + if (ch < 0 || ch >= radix) + break; + val *= radix; + val += ch; - for (i = 0; i < from.len && i*2+2 < tolen; i++) { - to[i*2+0] = xd[(from.ptr[i] >> 4) & 0xf]; - to[i*2+1] = xd[from.ptr[i] & 0xf]; + b->ptr++; + b->len--; } - to[i*2] = 0; - return i*2; + return val; +} + +void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to) +{ + char *s, *d; + int i, r1, r2; + + if (APK_BLOB_IS_NULL(*b)) + return; + + if (to.len > b->len * 2) + goto err; + + for (i = 0, s = b->ptr, d = to.ptr; i < to.len; i++) { + r1 = dx(*(s++)); + if (r1 < 0) + goto err; + r2 = dx(*(s++)); + if (r2 < 0) + goto err; + *(d++) = (r1 << 4) + r2; + } + b->ptr = s; + b->len -= to.len * 2; + return; +err: + *b = APK_BLOB_NULL; } diff --git a/src/cache.c b/src/cache.c index 6efbfe1..423af72 100644 --- a/src/cache.c +++ b/src/cache.c @@ -71,6 +71,7 @@ static int cache_clean(struct apk_database *db) struct apk_package *pkg; char path[256]; int delete, i; + apk_blob_t b; csum_t csum; snprintf(path, sizeof(path), "%s/%s", db->root, db->cache_dir); @@ -88,9 +89,9 @@ static int cache_clean(struct apk_database *db) do { if (strlen(de->d_name) <= sizeof(csum_t)*2+2) break; - if (apk_hexdump_parse(APK_BLOB_BUF(csum), - APK_BLOB_PTR_LEN(de->d_name, - sizeof(csum_t) * 2)) != 0) + b = APK_BLOB_PTR_LEN(de->d_name, sizeof(csum_t) * 2); + apk_blob_pull_hexdump(&b, APK_BLOB_BUF(csum)); + if (APK_BLOB_IS_NULL(b)) break; if (de->d_name[sizeof(csum_t)*2] != '.') break; diff --git a/src/database.c b/src/database.c index 9aeab77..5767b97 100644 --- a/src/database.c +++ b/src/database.c @@ -454,13 +454,11 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) apk_error("FDB directory metadata entry before directory entry"); return -1; } - diri->uid = apk_blob_parse_uint(&l, 10); - if (apk_blob_parse_char(&l) != ':') - goto bad_mode; - diri->gid = apk_blob_parse_uint(&l, 10); - if (apk_blob_parse_char(&l) != ':') - goto bad_mode; - diri->mode = apk_blob_parse_uint(&l, 8); + diri->uid = apk_blob_pull_uint(&l, 10); + apk_blob_pull_char(&l, ':'); + diri->gid = apk_blob_pull_uint(&l, 10); + apk_blob_pull_char(&l, ':'); + diri->mode = apk_blob_pull_uint(&l, 8); break; case 'R': if (diri == NULL) { @@ -475,21 +473,20 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) apk_error("FDB checksum entry before file entry"); return -1; } - if (apk_hexdump_parse(APK_BLOB_BUF(file->csum), l)) { - apk_error("Not a valid checksum"); - return -1; - } + + apk_blob_pull_hexdump(&l, APK_BLOB_BUF(file->csum)); break; default: apk_error("FDB entry '%c' unsupported", field); return -1; } + if (APK_BLOB_IS_NULL(l)) { + apk_error("FDB format error in entry '%c'", field); + return -1; + } } return 0; -bad_mode: - apk_error("FDB bad directory mode entry"); - return -1; } static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) @@ -499,7 +496,8 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) struct apk_db_file *file; struct hlist_node *c1, *c2; char buf[1024]; - int n = 0, r; + apk_blob_t bbuf = APK_BLOB_BUF(buf); + int r; list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) { r = apk_pkg_write_index_entry(pkg, os); @@ -507,30 +505,32 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) return r; hlist_for_each_entry(diri, c1, &pkg->owned_dirs, pkg_dirs_list) { - n += snprintf(&buf[n], sizeof(buf)-n, - "F:%s\n" - "M:%d:%d:%o\n", - diri->dir->name, - diri->uid, diri->gid, diri->mode); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:")); + apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nM:")); + apk_blob_push_uint(&bbuf, diri->uid, 10); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(":")); + apk_blob_push_uint(&bbuf, diri->gid, 10); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(":")); + apk_blob_push_uint(&bbuf, diri->mode, 8); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) { - n += snprintf(&buf[n], sizeof(buf)-n, - "R:%s\n", - file->name); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:")); + apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen)); if (csum_valid(file->csum)) { - n += snprintf(&buf[n], sizeof(buf)-n, "Z:"); - n += apk_hexdump_format(sizeof(buf)-n, &buf[n], - APK_BLOB_BUF(file->csum)); - n += snprintf(&buf[n], sizeof(buf)-n, "\n"); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nZ:")); + apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(file->csum)); } + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); - if (os->write(os, buf, n) != n) + if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf) return -1; - n = 0; + bbuf = APK_BLOB_BUF(buf); } - if (n != 0 && os->write(os, buf, n) != n) + if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf) return -1; - n = 0; + bbuf = APK_BLOB_BUF(buf); } os->write(os, "\n", 1); } @@ -943,9 +943,12 @@ static void apk_db_cache_get_name(char *buf, size_t bufsz, const char *file, int temp) { char csumstr[sizeof(csum_t)*2+1]; + apk_blob_t bbuf = APK_BLOB_BUF(csumstr); + + apk_blob_push_hexdump(&bbuf, + APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t))); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("")); - apk_hexdump_format(sizeof(csumstr), csumstr, - APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t))); snprintf(buf, bufsz, "%s/%s/%s.%s%s", db->root, db->cache_dir, csumstr, file, temp ? ".new" : ""); } diff --git a/src/package.c b/src/package.c index 1b72f1c..c6c6737 100644 --- a/src/package.c +++ b/src/package.c @@ -290,17 +290,19 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, apk_deps_parse(db, &pkg->depends, value); break; case 'C': - apk_hexdump_parse(APK_BLOB_BUF(pkg->csum), value); + apk_blob_pull_hexdump(&value, APK_BLOB_BUF(pkg->csum)); break; case 'S': - pkg->size = apk_blob_parse_uint(&value, 10); + pkg->size = apk_blob_pull_uint(&value, 10); break; case 'I': - pkg->installed_size = apk_blob_parse_uint(&value, 10); + pkg->installed_size = apk_blob_pull_uint(&value, 10); break; default: return -1; } + if (APK_BLOB_IS_NULL(value)) + return -1; return 0; } @@ -643,22 +645,29 @@ int apk_pkg_write_index_entry(struct apk_package *info, struct apk_ostream *os) { char buf[512]; - int n, r, t = 0; - - n = snprintf(buf, sizeof(buf), - "P:%s\n" - "V:%s\n" - "S:%zu\n" - "I:%zu\n" - "T:%s\n" - "U:%s\n" - "L:%s\n", - info->name->name, info->version, - info->size, info->installed_size, - info->description, info->url, info->license); - if (os->write(os, buf, n) != n) + apk_blob_t bbuf = APK_BLOB_BUF(buf); + int r; + + apk_blob_push_blob(&bbuf, APK_BLOB_STR("C:")); + apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(info->csum)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nP:")); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->name->name)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nV:")); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->version)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nS:")); + apk_blob_push_uint(&bbuf, info->size, 10); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nI:")); + apk_blob_push_uint(&bbuf, info->installed_size, 10); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nT:")); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->description)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nU:")); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->url)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nL:")); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->license)); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); + + if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf) return -1; - t += n; if (info->depends != NULL) { if (os->write(os, "D:", 2) != 2) @@ -668,18 +677,9 @@ int apk_pkg_write_index_entry(struct apk_package *info, return r; if (os->write(os, "\n", 1) != 1) return -1; - t += r + 3; } - n = snprintf(buf, sizeof(buf), "C:"); - n += apk_hexdump_format(sizeof(buf)-n, &buf[n], APK_BLOB_BUF(info->csum)); - n += snprintf(&buf[n], sizeof(buf)-n, "\n"); - - if (os->write(os, buf, n) != n) - return -1; - t += n; - - return n; + return 0; } int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b) |