]> git.draconx.ca Git - upkg.git/blobdiff - src/libupkg.c
Implement file reading API on exports.
[upkg.git] / src / libupkg.c
index 66546fd3dd80f3f1858f80d579a5f7ca7cd4b192..e2bcf2983adb0d614669b763b34d001a5d58d23d 100644 (file)
@@ -47,6 +47,8 @@ struct upkg_import {
 struct upkg_private {
        FILE *f;
 
+       struct upkg_file *last_file;
+
        struct upkg_name   *names;
        struct upkg_export *exports;
        struct upkg_import *imports;
@@ -385,3 +387,49 @@ const char *upkg_get_name(struct upkg *pkg, unsigned long idx)
                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;
+}