X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/82c24245034226967611c9d2c4f6f04b4f9db6cc..b46bbe4f64a68fdec38675690f9576c2cbdf4cd3:/src/libupkg.c diff --git a/src/libupkg.c b/src/libupkg.c index 8072516..d5203b4 100644 --- a/src/libupkg.c +++ b/src/libupkg.c @@ -156,7 +156,7 @@ 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; @@ -191,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; @@ -220,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; @@ -263,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; } @@ -288,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; @@ -420,6 +422,105 @@ const char *upkg_get_name(struct upkg *pkg, unsigned long idx) return pkg->priv->names[idx].name; } +long upkg_export_find(struct upkg *pkg, const char *name) +{ + /* This is wrong. + * Export names are not necessarily unique within a package. */ + for (unsigned i = 0; i < pkg->export_count; i++) { + struct upkg_export *export = &pkg->priv->exports[i]; + if (strcmp(export->name, name) == 0) { + return i; + } + } + + return -1; +} + +const char *upkg_export_name(struct upkg *pkg, unsigned long idx) +{ + if (idx < pkg->export_count) + return pkg->priv->exports[idx].name; + return NULL; +} + +const char *upkg_export_class(struct upkg *pkg, unsigned long idx, + const char **package, const char **group) +{ + struct upkg_export *export; + struct upkg_import *iclass, *ipackage; + unsigned long pkg_idx; + + if (idx >= pkg->export_count) + return NULL; + + export = &pkg->priv->exports[idx]; + + /* ASSUMPTION: class references are always imports */ + if (export->class > 0) { + fprintf(stderr, "Assumption Violated: class not import\n"); + return NULL; + } + + /* ASSUMPTION: group references are always exports */ + if (export->package < 0) { + fprintf(stderr, "Assumption Violated: group not export\n"); + return NULL; + } + + /* Get the group name. */ + if (export->package > 0) { + pkg_idx = export->package - 1; + + if (pkg_idx >= pkg->export_count) { + return NULL; + } + + /* Lots more to handle. Function arguments are stupid. */ + + if (group) *group = pkg->priv->exports[pkg_idx].name; + } else { + if (group) *group = NULL; + } + + /* Get the class. */ + if (export->class == 0) { + if (package) *package = "Core"; + return "Class"; + } + + pkg_idx = -(export->class + 1); + if (pkg_idx >= pkg->import_count) + return NULL; + iclass = &pkg->priv->imports[pkg_idx]; + + /* ASSUMPTION: Class references are always Core.Class */ + if (strcmp(iclass->class_name, "Class") || strcmp(iclass->class_package, "Core")) { + fprintf(stderr, "Assumption Violated: class not Core.Class\n"); + return NULL; + } + + /* ASSUMPTION: Package references are always imports */ + if (iclass->package >= 0) { + fprintf(stderr, "Assumption Violated: package not import\n"); + return NULL; + } + + /* Get the package. */ + pkg_idx = -(iclass->package + 1); + if (pkg_idx >= pkg->import_count) + return NULL; + ipackage = &pkg->priv->imports[pkg_idx]; + + /* ASSUMPTION: Package references are always Core.Package */ + if (strcmp(ipackage->class_name, "Package") || strcmp(ipackage->class_package, "Core")) { + fprintf(stderr, "Assumption Violated: package not Core.Package\n"); + return NULL; + } + + if (package) *package = ipackage->object_name; + return iclass->object_name; +} + struct upkg_file *upkg_export_open(struct upkg *pkg, unsigned long idx) { struct upkg_file *f; @@ -476,6 +577,7 @@ int upkg_export_seek(struct upkg_file *f, long offset, int whence) 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; @@ -501,7 +603,7 @@ 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)) + if (want < n || (rc < want && feof(f->pkg->priv->f))) f->eof = 1; return rc; }