X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/3dd8f219561d68c12b04ef2d226a23e495b7c540..d4361f57c265eb4793ceffb045687727ee619678:/src/libupkg.c diff --git a/src/libupkg.c b/src/libupkg.c index f7c55ba..8e5de38 100644 --- a/src/libupkg.c +++ b/src/libupkg.c @@ -124,11 +124,39 @@ static struct upkg *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE]) return &alloc->pkg; } +static int pkg_init_guid(struct upkg *pkg) +{ + size_t rc; + + if (pkg->version < 68) { + unsigned long heritage_count, heritage_offset; + unsigned char buf[8]; + + rc = fread(buf, 1, sizeof buf, pkg->priv->f); + if (rc < 8) + return -1; + + heritage_count = unpack_32_le(buf+0); + heritage_offset = unpack_32_le(buf+4); + + if (heritage_count == 0) + return -1; + if (fseek(pkg->priv->f, heritage_offset, SEEK_SET) != 0) + return -1; + } + + rc = fread(pkg->guid, 1, 16, pkg->priv->f); + if (rc < 16) + return -1; + + return 0; +} + static int pkg_init_names(struct upkg *pkg) { size_t rc, len, nbuf = 0; unsigned long index = 0; - char buf[512]; + unsigned char buf[512]; if (fseek(pkg->priv->f, pkg->priv->name_offset, SEEK_SET) != 0) return -1; @@ -163,7 +191,7 @@ static int pkg_init_names(struct upkg *pkg) memmove(buf, buf+len+1, nbuf); index++; } else { - char *c = memchr(buf, 0, nbuf); + unsigned char *c = memchr(buf, 0, nbuf); if (!c || nbuf <= c - buf + 5) goto err; len = c - buf + 1; @@ -192,7 +220,7 @@ static int pkg_init_exports(struct upkg *pkg) { size_t rc, len, nbuf = 0; unsigned long index = 0; - char buf[512]; + unsigned char buf[512]; if (fseek(pkg->priv->f, pkg->priv->export_offset, SEEK_SET) != 0) return -1; @@ -235,13 +263,15 @@ static int pkg_init_exports(struct upkg *pkg) export->flags = unpack_32_le(buf+len); len += 4; - rc = upkg_decode_index(&export->size, buf+len, nbuf-len); - if (rc == 0) goto err; + rc = upkg_decode_index(&tmp, buf+len, nbuf-len); + if (rc == 0 || tmp < 0) goto err; + export->size = tmp; len += rc; if (export->size) { - rc = upkg_decode_index(&export->offset, buf+len, nbuf-len); - if (rc == 0) goto err; + rc = upkg_decode_index(&tmp, buf+len, nbuf-len); + if (rc == 0 || tmp < 0) goto err; + export->offset = tmp; len += rc; } @@ -260,7 +290,7 @@ static int pkg_init_imports(struct upkg *pkg) { size_t rc, len, nbuf = 0; unsigned long index = 0; - char buf[512]; + unsigned char buf[512]; if (fseek(pkg->priv->f, pkg->priv->import_offset, SEEK_SET) != 0) return -1; @@ -335,6 +365,10 @@ struct upkg *upkg_fopen(const char *path) } pkg->priv->f = f; + if (pkg_init_guid(pkg) != 0) { + goto err2; + } + if (pkg_init_names(pkg) != 0) { goto err2; } @@ -442,8 +476,14 @@ int upkg_export_seek(struct upkg_file *f, long offset, int whence) break; } - if (rc == 0) + if (rc == 0) { f->pkg->priv->last_file = f; + f->offset = offset; + f->eof = 0; + } else if (f->pkg->priv->last_file == f) { + f->pkg->priv->last_file = NULL; + } + return rc; } @@ -463,5 +503,8 @@ size_t upkg_export_read(struct upkg_file *f, void *buf, size_t n) rc = fread(buf, 1, want, f->pkg->priv->f); f->offset += rc; + + if (want < n || (rc < want && feof(f->pkg->priv->f))) + f->eof = 1; return rc; }