#include #include #include #include #include #include "byteorder.h" #include "lbx.h" #define LBX_MAGIC 0x0000fead int lbx_errno = 0; struct lbx_state { const char *name; FILE *f; long foff; uint16_t nfiles; uint32_t offsets[]; }; struct lbx_state *lbx_fopen(FILE *f, const char *name) { 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){ .name = name, .nfiles = nfiles, .f = f, .foff = sizeof nfiles + sizeof magic + sizeof version, }; 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; } free(new); return NULL; } struct lbx_state *lbx_open(const char *path) { struct lbx_state *new = NULL; FILE *f; if ((f = fopen(path, "rb"))) { const char *name = strrchr(path, '/'); new = lbx_fopen(f, name ? name+1 : path); } 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"; }