-
- if (fread(new->offsets, sizeof *new->offsets, nfiles+1, f) != nfiles+1)
- goto readerr;
- new->foff += sizeof *new->offsets * (nfiles+1);
-
- return new;
-readerr:
- if (feof(f)) {
- lbx_errno = LBX_EEOF;
- } else {
- lbx_errno = -errno;
+
+ return lbx;
+}
+
+static char *str_dup(const char *s)
+{
+ char *buf;
+
+ buf = malloc(strlen(s)+1);
+ if (buf)
+ strcpy(buf, s);
+ return buf;
+}
+
+struct lbx_state *lbx_open(void *f, const struct lbx_file_ops *fops,
+ int (*destructor)(void *), const char *name)
+{
+ unsigned char hdr_buf[LBX_HDR_SIZE];
+ struct lbx_state *lbx = NULL;
+ char *dupname = NULL;
+
+ dupname = str_dup(name);
+ if (!dupname) {
+ lbx_error_raise(LBX_ENOMEM);
+ goto err;
+ }
+
+ if (fops->read(hdr_buf, sizeof hdr_buf, f) != sizeof hdr_buf) {
+ if (fops->eof(f))
+ lbx_error_raise(LBX_EEOF);
+ goto err;
+ }
+
+ lbx = lbx_init(hdr_buf);
+ if (!lbx)
+ goto err;
+
+ lbx->name = dupname;
+ lbx->dtor = destructor;
+ lbx->fops = fops;
+ lbx->f = f;
+
+ for (unsigned i = 0; i <= lbx->nfiles; i++) {
+ unsigned char buf[4];
+
+ if (fops->read(buf, sizeof buf, f) != sizeof buf) {
+ if (fops->eof(f))
+ lbx_error_raise(LBX_EEOF);
+ goto err;
+ }
+
+ lbx->offsets[i] = unpack_32_le(buf);