X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/bb9c28745ae254b832805e5d41f2a5e6c3cb8f40..b5a18d3dd9ca4315f9d7f75e90363410db405935:/src/libupkg.c diff --git a/src/libupkg.c b/src/libupkg.c index 178e235..c87f668 100644 --- a/src/libupkg.c +++ b/src/libupkg.c @@ -46,15 +46,10 @@ struct upkg_name { struct upkg_export_priv { struct upkg_export pub; - long class, super; + long super; unsigned long size, offset; }; -struct upkg_import { - const char *class_package, *class_name, *object_name; - long package; -}; - struct upkg_priv { struct upkg pub; @@ -110,12 +105,11 @@ const struct upkg_file_ops upkg_default_fops = { * Stores the result in *val and returns the number of input bytes read (or 0 * if the input is invalid, in which case *val is undefined). */ -size_t upkg_decode_index(long *val, unsigned char *bytes, size_t n) +size_t upkg_decode_index(long *val, const unsigned char *bytes, size_t n) { - size_t i = 0; - *val = 0; - while (i < MIN(n, 5)) { + + for (size_t i = 0; i < MIN(n, 5); i++) { /* * Least significant bytes are first, so we need to do this * nonsense. @@ -127,18 +121,14 @@ size_t upkg_decode_index(long *val, unsigned char *bytes, size_t n) *val += tmp; if (!(bytes[i] & (i == 0 ? 0x40 : 0x80))) { - i++; - break; + if (bytes[0] & 0x80) + *val = -*val; + return i+1; } - - i++; } - if (i > MIN(n, 5) || n == 0) - return 0; - if (bytes[0] & 0x80) - *val = -*val; - return i; + /* Error */ + return 0; } static struct upkg_priv *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE]) @@ -292,7 +282,7 @@ static int pkg_init_exports(struct upkg_priv *pkg) } len = 0; - rc = upkg_decode_index(&export->class, buf+len, nbuf-len); + rc = upkg_decode_index(&export->pub.class, buf+len, nbuf-len); if (rc == 0) goto err; len += rc; @@ -301,9 +291,19 @@ static int pkg_init_exports(struct upkg_priv *pkg) len += rc; if (nbuf-len < 4) goto err; - export->pub.package = unpack_s32_le(buf+len); + tmp = unpack_s32_le(buf+len); + if (tmp < 0) + goto err; len += 4; + export->pub.parent = NULL; + if (tmp > 0) { + tmp--; + if (tmp >= pkg->pub.export_count) + goto err; + export->pub.parent = &pkg->exports[tmp].pub; + } + rc = upkg_decode_index(&tmp, buf+len, nbuf-len); if (rc == 0 || tmp < 0 || tmp >= pkg->pub.name_count) goto err; export->pub.name = pkg->names[tmp].name; @@ -376,12 +376,22 @@ static int pkg_init_imports(struct upkg_priv *pkg) len += rc; if (nbuf-len < 4) goto err; - import->package = unpack_s32_le(buf+len); + tmp = unpack_s32_le(buf+len); + if (tmp > 0) + goto err; len += 4; + import->parent = NULL; + if (tmp < 0) { + tmp = -(tmp + 1); + if (tmp >= pkg->pub.import_count) + goto err; + import->parent = &pkg->imports[tmp]; + } + rc = upkg_decode_index(&tmp, buf+len, nbuf-len); if (rc == 0 || len >= pkg->pub.name_count) goto err; - import->object_name = pkg->names[tmp].name; + import->name = pkg->names[tmp].name; len += rc; nbuf -= len; @@ -493,22 +503,22 @@ const char *upkg_get_name(struct upkg *pub, unsigned long idx) return pkg->names[idx].name; } -long upkg_export_find(struct upkg *pub, long parent, const char *name) +long upkg_export_find(struct upkg *pub, long parent_index, const char *name) { struct upkg_priv *pkg = (struct upkg_priv *)pub; + struct upkg_export *parent = NULL; - /* This only makes sense if the assertion below is not violated. */ - long package = parent < 0 ? 0 : parent + 1; + if (parent_index >= 0) { + if (parent_index >= pkg->pub.export_count) + return -1; + parent = &pkg->exports[parent_index].pub; + } for (unsigned long i = 0; i < pkg->pub.export_count; i++) { struct upkg_export_priv *e = &pkg->exports[i]; - /* Assertion: an object's package is an export. */ - format_assert(e->pub.package >= 0, continue); - if (e->pub.package == package - && strcmp(e->pub.name, name) == 0) { + if (e->pub.parent == parent && !strcmp(e->pub.name, name)) return i; - } } return -1; @@ -523,52 +533,13 @@ const struct upkg_export *upkg_get_export(struct upkg *pub, unsigned long idx) return NULL; } -const char *upkg_export_class(struct upkg *pub, unsigned long idx, - const char **package) +const struct upkg_import *upkg_get_import(struct upkg *pub, unsigned long idx) { struct upkg_priv *pkg = (struct upkg_priv *)pub; - struct upkg_export_priv *export; - struct upkg_import *iclass, *ipackage; - unsigned long pkg_idx; - - if (idx >= pkg->pub.export_count) - return NULL; - - export = &pkg->exports[idx]; - - /* Assumption: class references are always imports. */ - format_assert(export->class <= 0, return NULL); - - /* Get the class. */ - if (export->class == 0) { - if (package) *package = "Core"; - return "Class"; - } - - pkg_idx = -(export->class + 1); - if (pkg_idx >= pkg->pub.import_count) - return NULL; - iclass = &pkg->imports[pkg_idx]; - - /* Assumption: class references are always Core.Class. */ - format_assert(!strcmp(iclass->class_package, "Core"), return NULL); - format_assert(!strcmp(iclass->class_name, "Class"), return NULL); - /* Assumption: package references are always imports. */ - format_assert(iclass->package <= 0, return NULL); - - /* Get the package. */ - pkg_idx = -(iclass->package + 1); - if (pkg_idx >= pkg->pub.import_count) - return NULL; - ipackage = &pkg->imports[pkg_idx]; - - /* Assumption: package references are always Core.Package. */ - format_assert(!strcmp(ipackage->class_package, "Core"), return NULL); - format_assert(!strcmp(ipackage->class_name, "Package"), return NULL); - - if (package) *package = ipackage->object_name; - return iclass->object_name; + if (idx < pkg->pub.import_count) + return &pkg->imports[idx]; + return NULL; } struct upkg_file *upkg_export_open(struct upkg *pub, unsigned long idx) @@ -584,7 +555,7 @@ struct upkg_file *upkg_export_open(struct upkg *pub, unsigned long idx) return NULL; *f = (struct upkg_file) { - .pkg = pkg, + .pkg = pub, .base = pkg->exports[idx].offset, .len = pkg->exports[idx].size, .name = pkg->exports[idx].pub.name, @@ -595,8 +566,10 @@ struct upkg_file *upkg_export_open(struct upkg *pub, unsigned long idx) void upkg_export_close(struct upkg_file *f) { - if (f->pkg->last_file == f) - f->pkg->last_file = NULL; + struct upkg_priv *pkg = (struct upkg_priv *)f->pkg; + + if (pkg->last_file == f) + pkg->last_file = NULL; free(f); } @@ -607,7 +580,8 @@ long upkg_export_tell(struct upkg_file *f) int upkg_export_seek(struct upkg_file *f, long offset, int whence) { - const struct upkg_file_ops *fops = f->pkg->fops; + struct upkg_priv *pkg = (struct upkg_priv *)f->pkg; + const struct upkg_file_ops *fops = pkg->fops; int rc = EOF; switch (whence) { @@ -616,23 +590,23 @@ int upkg_export_seek(struct upkg_file *f, long offset, int whence) case SEEK_SET: if (offset < 0 || offset > f->len) return EOF; - rc = fops->seek(f->pkg->f, f->base + offset, SEEK_SET); + rc = fops->seek(pkg->f, f->base + offset, SEEK_SET); break; case SEEK_END: offset = -offset; if (offset < 0 || offset > f->len) return EOF; offset = f->len - offset; - rc = fops->seek(f->pkg->f, f->base + offset, SEEK_SET); + rc = fops->seek(pkg->f, f->base + offset, SEEK_SET); break; } if (rc == 0) { - f->pkg->last_file = f; + pkg->last_file = f; f->offset = offset; f->eof = 0; - } else if (f->pkg->last_file == f) { - f->pkg->last_file = NULL; + } else if (pkg->last_file == f) { + pkg->last_file = NULL; } return rc; @@ -640,7 +614,8 @@ int upkg_export_seek(struct upkg_file *f, long offset, int whence) size_t upkg_export_read(struct upkg_file *f, void *buf, size_t n) { - const struct upkg_file_ops *fops = f->pkg->fops; + struct upkg_priv *pkg = (struct upkg_priv *)f->pkg; + const struct upkg_file_ops *fops = pkg->fops; size_t want = MIN(n, f->len - f->offset); size_t rc; @@ -648,15 +623,15 @@ size_t upkg_export_read(struct upkg_file *f, void *buf, size_t n) return 0; } - if (f != f->pkg->last_file) { - if (fops->seek(f->pkg->f, f->base + f->offset, SEEK_SET)) + if (f != pkg->last_file) { + if (fops->seek(pkg->f, f->base + f->offset, SEEK_SET)) return 0; } - rc = fops->read(buf, want, f->pkg->f); + rc = fops->read(buf, want, pkg->f); f->offset += rc; - if (want < n || (rc < want && fops->eof(f->pkg->f))) + if (want < n || (rc < want && fops->eof(pkg->f))) f->eof = 1; return rc; }