struct upkg_private {
FILE *f;
+ struct upkg_file *last_file;
+
struct upkg_name *names;
struct upkg_export *exports;
struct upkg_import *imports;
return 0;
return pkg->priv->names[idx].name;
}
+
+struct upkg_file *upkg_export_open(struct upkg *pkg, unsigned long idx)
+{
+ struct upkg_file *f;
+
+ if (idx >= pkg->export_count)
+ return NULL;
+
+ f = malloc(sizeof *f);
+ if (f == NULL)
+ return NULL;
+
+ *f = (struct upkg_file) {
+ .pkg = pkg,
+ .base = pkg->priv->exports[idx].offset,
+ .len = pkg->priv->exports[idx].size,
+ };
+
+ return f;
+}
+
+void upkg_export_close(struct upkg_file *f)
+{
+ if (f->pkg->priv->last_file == f)
+ f->pkg->priv->last_file = NULL;
+ free(f);
+}
+
+size_t upkg_export_read(struct upkg_file *f, void *buf, size_t n)
+{
+ size_t want = MIN(n, f->len - f->offset);
+ size_t rc;
+
+ if (want == 0) {
+ return 0;
+ }
+
+ if (f != f->pkg->priv->last_file) {
+ if (fseek(f->pkg->priv->f, f->base + f->offset, SEEK_SET))
+ return 0;
+ }
+
+ rc = fread(buf, 1, want, f->pkg->priv->f);
+ f->offset += rc;
+ return rc;
+}
#ifndef UPKG_H_
#define UPKG_H_
+#include <stddef.h>
+
#define UPKG_FLAG_ALLOW_DOWNLOAD 0x0001
#define UPKG_FLAG_CLIENT_OPTIONAL 0x0002
#define UPKG_FLAG_SERVER_ONLY 0x0004
struct upkg_private *priv;
};
+struct upkg_file {
+ struct upkg *pkg;
+ unsigned long base, offset, len;
+};
+
struct upkg *upkg_fopen(const char *path);
int upkg_close(struct upkg *pkg);
+
const char *upkg_get_name(struct upkg *pkg, unsigned long idx);
+struct upkg_file *upkg_export_open(struct upkg *pkg, unsigned long idx);
+size_t upkg_export_read(struct upkg_file *f, void *buf, size_t n);
+void upkg_export_close(struct upkg_file *f);
+
#endif