+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;
+}
+