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 { diff --git a/src/blob.c b/src/blob.c index 9f253cb..cbcb312 100644 --- a/src/blob.c +++ b/src/blob.c @@ -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) +{ + if (APK_BLOB_IS_NULL(*to)) + return; + + if (to->len < literal.len) { + *to = APK_BLOB_NULL; + return; + } + + memcpy(to->ptr, literal.ptr, literal.len); + to->ptr += literal.len; + to->len -= literal.len; +} + +static const char *xd = "0123456789abcdefghijklmnopqrstuvwxyz"; + +void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix) +{ + char buf[64]; + char *ptr = &buf[sizeof(buf)-1]; + + if (value == 0) { + apk_blob_push_blob(to, APK_BLOB_STR("0")); + return; + } + + while (value != 0) { + *(ptr--) = xd[value % radix]; + value /= radix; + } + + apk_blob_push_blob(to, APK_BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1])); +} + +void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary) +{ + char *d; + int i; + + if (APK_BLOB_IS_NULL(*to)) + return; + + if (to->len < binary.len * 2) { + *to = APK_BLOB_NULL; + return; + } + + 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; +} + +void apk_blob_pull_char(apk_blob_t *b, int expected) +{ + 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 (blob->len && blob->ptr[0] != 0) { - ch = dx(blob->ptr[0]); - if (ch < 0 || ch >= base) + while (b->len && b->ptr[0] != 0) { + ch = dx(b->ptr[0]); + if (ch < 0 || ch >= radix) break; - val *= base; + val *= radix; val += ch; - blob->ptr++; - blob->len--; + b->ptr++; + b->len--; } return val; } -int apk_blob_parse_char(apk_blob_t *blob) +void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to) { - int r; + char *s, *d; + int i, r1, r2; - if (blob->len == 0 || blob->ptr == NULL) - return -1; - r = blob->ptr[0]; - blob->ptr++; - blob->len--; + if (APK_BLOB_IS_NULL(*b)) + return; - return r; -} + if (to.len > b->len * 2) + goto err; -int apk_hexdump_parse(apk_blob_t to, apk_blob_t from) -{ - int i; - - if (to.len * 2 != from.len) - return -1; - - for (i = 0; i < from.len / 2; i++) - to.ptr[i] = (dx(from.ptr[i*2]) << 4) + dx(from.ptr[i*2+1]); - - return 0; -} - -int apk_hexdump_format(int tolen, char *to, apk_blob_t from) -{ - static const char *xd = "0123456789abcdef"; - int i; - - 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]; + 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; } - to[i*2] = 0; - - return i*2; + 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; + apk_blob_t bbuf = APK_BLOB_BUF(buf); + int r; - 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_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)