From 03e948b1af5e17259fb1da0acff9902604ac1b5f Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Fri, 5 Jun 2009 01:29:08 -0400 Subject: [PATCH] Implement lookups in the name table. --- libupkg.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++---- upkg.c | 5 +++ upkg.h | 1 + 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/libupkg.c b/libupkg.c index 617aefa..b932d86 100644 --- a/libupkg.c +++ b/libupkg.c @@ -1,18 +1,47 @@ #include #include +#include #include "upkg.h" #include "pack.h" +struct upkg_name { + unsigned long index, flags; + char *name; +}; struct upkg_private { FILE *f; + struct upkg_name *names; unsigned long name_offset, export_offset, import_offset; unsigned char guid[16]; }; +static int namecmp(const void *_a, const void *_b, void *_pkg) +{ + const struct upkg_name *a = _a, *b = _b; + if (a->index < b->index) + return -1; + if (a->index > b->index) + return -1; + return 0; +} + +static long decode_index(unsigned char *bytes) +{ + long val = 0; + size_t i = 1; + + val += bytes[0] & 0x3f; + if (bytes[0] & 0x40) do { + val += bytes[i] & 0x7f; + } while (bytes[i] & 0x80 && i < 5); + + return bytes[0] & 0x80 ? -val : val; +} + static struct upkg *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE]) { struct upkg *pkg; @@ -42,38 +71,115 @@ static struct upkg *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE]) return pkg; } +static int pkg_init_names(struct upkg *pkg) +{ + size_t rc, nbuf = 0, len; + unsigned long index = 0; + char buf[512]; + + if (fseek(pkg->priv->f, pkg->priv->name_offset, SEEK_SET) != 0) + return -1; + + pkg->priv->names = malloc(pkg->name_count * sizeof *pkg->priv->names); + if (!pkg->priv->names) + return -1; + + while (index < pkg->name_count) { + struct upkg_name *name = &pkg->priv->names[index]; + name->index = index; + + /* Read some data into buffer. */ + if (!feof(pkg->priv->f)) { + rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f); + if (rc == 0) + goto err; + nbuf += rc; + } + + if (pkg->version >= 64) { + len = buf[0]; + if (nbuf <= len + 4 || buf[len]) + goto err; + name->name = malloc(len); + if (!name->name) + goto err; + memcpy(name->name, buf+1, len); + name->flags = unpack_32_le(buf+len+1); + + nbuf -= len + 5; + memmove(buf, buf+len+5, nbuf); + index++; + } else { + abort(); + } + } + + return 0; +err: + free(pkg->priv->names); + return -1; +} + struct upkg *upkg_fopen(const char *path) { unsigned char hdr_buf[UPKG_HDR_SIZE]; struct upkg *pkg; FILE *f; - + if (!(f = fopen(path, "rb"))) { return NULL; } if (fread(hdr_buf, sizeof hdr_buf, 1, f) != 1) { - goto err; + goto err1; } if (unpack_32_le(hdr_buf) != UPKG_HDR_MAGIC) { - goto err; + goto err1; } /* Initialize package structure. */ pkg = init_upkg(hdr_buf); if (!pkg) { - goto err; + goto err1; } pkg->priv->f = f; + if (pkg_init_names(pkg) != 0) { + goto err2; + } + return pkg; -err: +err2: + free(pkg->priv); + free(pkg); +err1: fclose(f); return NULL; } int upkg_close(struct upkg *pkg) { - if (pkg->priv->f) - return fclose(pkg->priv->f); + int rc = 0; + + if (pkg->priv->f) { + rc = fclose(pkg->priv->f); + + for (unsigned i = 0; i < pkg->name_count; i++) { + free(pkg->priv->names[i].name); + } + free(pkg->priv->names); + + return rc; + } + + free(pkg->priv); + free(pkg); + return 0; } + +const char *upkg_get_name(struct upkg *pkg, unsigned long idx) +{ + if (idx >= pkg->name_count) + return 0; + return pkg->priv->names[idx].name; +} diff --git a/upkg.c b/upkg.c index 3cfd727..970de56 100644 --- a/upkg.c +++ b/upkg.c @@ -36,9 +36,14 @@ int main(int argc, char **argv) printf("Version: %u\n", pkg->version); printf("License: %u\n", pkg->license); + printf("Flags: %lx\n", pkg->flags); print_upkg_flags("\t", pkg->flags); + printf("Names: %zu\n", pkg->name_count); + for (unsigned long i = 0; i < pkg->name_count; i++) { + printf("\t%s\n", upkg_get_name(pkg, i)); + } upkg_close(pkg); return 0; diff --git a/upkg.h b/upkg.h index c4d582d..f20f18e 100644 --- a/upkg.h +++ b/upkg.h @@ -22,5 +22,6 @@ struct upkg { struct upkg *upkg_fopen(const char *path); int upkg_close(struct upkg *pkg); +const char *upkg_get_name(struct upkg *pkg, unsigned long idx); #endif -- 2.43.2