]> git.draconx.ca Git - liblbx.git/commitdiff
Add lbx_mopen() to allow "opening" a region of memory as an LBX archive.
authorNick Bowler <draconx@gmail.com>
Sun, 23 Dec 2007 22:47:17 +0000 (17:47 -0500)
committerNick Bowler <draconx@gmail.com>
Sun, 23 Dec 2007 22:47:17 +0000 (17:47 -0500)
src/lbx.c
src/lbx.h

index 597d0433e313a5898bac2e407f989a53d0339bbb..20c32e75ae7deb69b8389a7a041f924840585414 100644 (file)
--- a/src/lbx.c
+++ b/src/lbx.c
@@ -3,6 +3,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "byteorder.h"
 #include "lbx.h"
@@ -15,6 +16,8 @@ int lbx_errno = 0;
 struct lbx_state {
        const char *name;
 
+       unsigned char *mem;
+       size_t memsize;
        FILE *f;
        long foff;
 
@@ -70,6 +73,59 @@ readerr:
        return NULL;
 }
 
+static int _lbx_memcpy(void *dest, struct lbx_state *src, size_t size)
+{
+       if (src->foff + size > src->memsize)
+               return -1;
+       memcpy(dest, src->mem + src->foff, size);
+       src->foff += size;
+       return 0;
+}
+
+struct lbx_state *lbx_mopen(void *_mem, size_t size, const char *name)
+{
+       struct lbx_state *new = NULL;
+       struct lbx_state tmp = { .mem = _mem, .memsize = size };
+       uint16_t nfiles, version;
+       uint32_t magic;
+
+       if (_lbx_memcpy(&nfiles,  &tmp, sizeof nfiles)  == -1) goto eof;
+       if (_lbx_memcpy(&magic,   &tmp, sizeof magic)   == -1) goto eof;
+       if (_lbx_memcpy(&version, &tmp, sizeof version) == -1) goto eof;
+
+       nfiles  = letohs(nfiles);
+       magic   = letohl(magic);
+       version = letohs(version);
+
+       if (magic != LBX_MAGIC) {
+               lbx_errno = LBX_EMAGIC;
+               return NULL;
+       }
+       
+       new = malloc(sizeof *new + (nfiles+1)*(sizeof *new->offsets));
+       if (!new) {
+               lbx_errno = -errno;
+               return NULL;
+       }
+       
+       *new = (struct lbx_state){
+               .name    = name,
+               .nfiles  = nfiles,
+               .mem     = _mem,
+               .memsize = size,
+               .foff    = tmp.foff,
+       };
+       
+       if (_lbx_memcpy(new->offsets, new, (nfiles+1)*(sizeof *new->offsets)))
+               goto eof;
+
+       return new;
+eof:
+       free(new);
+       lbx_errno = LBX_EEOF;
+       return NULL;
+}
+
 struct lbx_state *lbx_open(const char *path)
 {
        struct lbx_state *new = NULL;
@@ -143,37 +199,41 @@ static int _lbx_fseek(struct lbx_state *lbx, size_t base)
        return 0;
 }
 
-size_t lbx_extract(struct lbx_state *lbx, size_t index, FILE *of)
+static size_t
+_lbx_mextract(struct lbx_state *lbx, size_t base, size_t len, FILE *of)
+{
+       size_t rc;
+
+       assert(lbx->mem);
+       assert(base + len <= lbx->memsize);
+
+       rc = fwrite(lbx->mem + base, 1, len, of);
+       if (rc < len)
+               lbx_errno = -errno;
+
+       return rc;
+}
+
+static size_t
+_lbx_fextract(struct lbx_state *lbx, size_t base, size_t len, FILE *of)
 {
        unsigned char buf[1024];
-       size_t rc, written = 0, base, len;
+       size_t rc, written = 0;
 
-       if (index >= lbx->nfiles) {
-               lbx_errno = LBX_ERANGE;
-               return 0;
-       }
-       
-       base = lbx->offsets[index];
-       len  = lbx->offsets[index+1] - lbx->offsets[index];
+       assert(lbx->f);
 
-       if (_lbx_fseek(lbx, base) == -1) {
-               /* lbx_errno set by _lbx_fseek(). */
+       if (_lbx_fseek(lbx, base) == -1)
                return 0;
-       }
-
-       /* Copy file data */
+       
        while (len) {
-               size_t amt = MIN(sizeof buf, len);
+               size_t amt = MIN(len, sizeof buf);
 
                rc = fread(buf, 1, amt, lbx->f);
                lbx->foff += rc;
                len -= rc;
                if (rc < amt) {
-                       if (feof(lbx->f)) {
-                               lbx_errno = LBX_EEOF;
-                       } else {
-                               lbx_errno = -errno;
-                       }
+                       if (feof(lbx->f)) lbx_errno = LBX_EEOF;
+                       else lbx_errno = -errno;
                        break;
                }
 
@@ -188,11 +248,29 @@ size_t lbx_extract(struct lbx_state *lbx, size_t index, FILE *of)
        return written;
 }
 
+size_t lbx_extract(struct lbx_state *lbx, size_t index, FILE *of)
+{
+       size_t base, len;
+
+       if (index >= lbx->nfiles) {
+               lbx_errno = LBX_ERANGE;
+               return 0;
+       }
+       
+       base = lbx->offsets[index];
+       len  = lbx->offsets[index+1] - lbx->offsets[index];
+
+       if (lbx->mem)
+               return _lbx_mextract(lbx, base, len, of);
+       return _lbx_fextract(lbx, base, len, of);
+}
+
 void lbx_close(struct lbx_state *lbx)
 {
        if (!lbx) return;
 
-       fclose(lbx->f);
+       if (lbx->f)
+               fclose(lbx->f);
        free(lbx);
 }
 
index 19848d25ab93e2481509bab5bd5711fc6b48cdaa..92c533b39c3aa47956f58cabab0ed21f820671c5 100644 (file)
--- a/src/lbx.h
+++ b/src/lbx.h
@@ -22,6 +22,7 @@ struct lbx_statbuf {
 
 /* Archive operations */
 LBX   *lbx_fopen(FILE *, const char *);
+LBX   *lbx_mopen(void *, size_t, const char *);
 LBX   *lbx_open(const char *);
 void   lbx_close(LBX *);
 size_t lbx_numfiles(LBX *);