#include #include #include #include #include #include "byteorder.h" #include "lbx.h" #define LBX_MAGIC 0x0000fead int lbx_errno = 0; struct lbx_state { FILE *f; long offset; uint16_t nfiles; uint32_t offsets[]; }; struct lbx_state *lbx_fopen(FILE *f) { struct lbx_state *new = NULL; uint16_t nfiles, version; uint32_t magic; if (fread(&nfiles, sizeof nfiles, 1, f) != 1) goto readerr; if (fread(&magic, sizeof magic, 1, f) != 1) goto readerr; if (fread(&version, sizeof version, 1, f) != 1) goto readerr; 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){ .nfiles = nfiles, .f = f, }; if (fread(new->offsets, sizeof *new->offsets, nfiles+1, f) != nfiles+1) goto readerr; return new; readerr: if (feof(f)) { lbx_errno = LBX_EEOF; } else { lbx_errno = -errno; } free(new); return NULL; } struct lbx_state *lbx_open(const char *path) { struct lbx_state *new = NULL; FILE *f; if ((f = fopen(path, "rb"))) { new = lbx_fopen(f); } else { lbx_errno = -errno; } return new; } size_t lbx_numfiles(struct lbx_state *lbx) { return lbx->nfiles; } void lbx_close(struct lbx_state *lbx) { if (!lbx) return; fclose(lbx->f); free(lbx); } const char *lbx_strerror(void) { if (lbx_errno < 0) return strerror(-lbx_errno); switch (lbx_errno) { case LBX_ESUCCESS: return "Success"; case LBX_EMAGIC: return "Bad magic number"; case LBX_EEOF: return "Unexpected end-of-file"; } return "Unknown error"; }