* 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).
*/
-static size_t decode_index(long *val, unsigned char *bytes, size_t n)
+size_t upkg_decode_index(long *val, unsigned char *bytes, size_t n)
{
size_t i = 0;
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;
}
len = 0;
- rc = decode_index(&export->class, buf+len, nbuf-len);
+ rc = upkg_decode_index(&export->class, buf+len, nbuf-len);
if (rc == 0) goto err;
len += rc;
- rc = decode_index(&export->super, buf+len, nbuf-len);
+ rc = upkg_decode_index(&export->super, buf+len, nbuf-len);
if (rc == 0) goto err;
len += rc;
export->package = unpack_32_le(buf+len);
len += 4;
- rc = decode_index(&tmp, buf+len, nbuf-len);
+ rc = upkg_decode_index(&tmp, buf+len, nbuf-len);
if (rc == 0 || tmp < 0 || tmp >= pkg->name_count) goto err;
export->name = pkg->priv->names[tmp].name;
len += rc;
export->flags = unpack_32_le(buf+len);
len += 4;
- rc = decode_index(&export->size, buf+len, nbuf-len);
+ rc = upkg_decode_index(&export->size, buf+len, nbuf-len);
if (rc == 0) goto err;
len += rc;
if (export->size) {
- rc = decode_index(&export->offset, buf+len, nbuf-len);
+ rc = upkg_decode_index(&export->offset, buf+len, nbuf-len);
if (rc == 0) goto err;
len += rc;
}
}
len = 0;
- rc = decode_index(&tmp, buf+len, nbuf-len);
+ rc = upkg_decode_index(&tmp, buf+len, nbuf-len);
if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
import->class_package = pkg->priv->names[tmp].name;
len += rc;
- rc = decode_index(&tmp, buf+len, nbuf-len);
+ rc = upkg_decode_index(&tmp, buf+len, nbuf-len);
if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
import->class_name = pkg->priv->names[tmp].name;
len += rc;
import->package = unpack_32_le(buf+len);
len += 4;
- rc = decode_index(&tmp, buf+len, nbuf-len);
+ rc = upkg_decode_index(&tmp, buf+len, nbuf-len);
if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
import->object_name = pkg->priv->names[tmp].name;
len += rc;
}
pkg->priv->f = f;
+ if (pkg_init_guid(pkg) != 0) {
+ goto err2;
+ }
+
if (pkg_init_names(pkg) != 0) {
goto err2;
}
.pkg = pkg,
.base = pkg->priv->exports[idx].offset,
.len = pkg->priv->exports[idx].size,
+ .name = pkg->priv->exports[idx].name,
};
return f;
free(f);
}
+long upkg_export_tell(struct upkg_file *f)
+{
+ return f->offset;
+}
+
+int upkg_export_seek(struct upkg_file *f, long offset, int whence)
+{
+ int rc = EOF;
+
+ switch (whence) {
+ case SEEK_CUR:
+ offset = f->offset + offset;
+ case SEEK_SET:
+ if (offset < 0 || offset > f->len)
+ return EOF;
+ rc = fseek(f->pkg->priv->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 = fseek(f->pkg->priv->f, f->base + offset, SEEK_SET);
+ break;
+ }
+
+ 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;
+}
+
size_t upkg_export_read(struct upkg_file *f, void *buf, size_t n)
{
size_t want = MIN(n, f->len - f->offset);
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;
}