]> git.draconx.ca Git - liblbx.git/blob - src/lbx.c
Add a name field to support LBX1 fallback.
[liblbx.git] / src / lbx.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <errno.h>
6
7 #include "byteorder.h"
8 #include "lbx.h"
9
10 #define LBX_MAGIC 0x0000fead
11
12 int lbx_errno = 0;
13
14 struct lbx_state {
15         const char *name;
16
17         FILE *f;
18         long foff;
19
20         uint16_t nfiles;
21         uint32_t offsets[];
22 };
23
24 struct lbx_state *lbx_fopen(FILE *f, const char *name)
25 {
26         struct lbx_state *new = NULL;
27         uint16_t nfiles, version;
28         uint32_t magic;
29
30         if (fread(&nfiles,  sizeof nfiles,  1, f) != 1) goto readerr;
31         if (fread(&magic,   sizeof magic,   1, f) != 1) goto readerr;
32         if (fread(&version, sizeof version, 1, f) != 1) goto readerr;
33
34         nfiles  = letohs(nfiles);
35         magic   = letohl(magic);
36         version = letohs(version);
37
38         if (magic != LBX_MAGIC) {
39                 lbx_errno = LBX_EMAGIC;
40                 return NULL;
41         }
42         
43         new = malloc(sizeof *new + (nfiles+1)*(sizeof *new->offsets));
44         if (!new) {
45                 lbx_errno = -errno;
46                 return NULL;
47         }
48         
49         *new = (struct lbx_state){
50                 .name   = name,
51                 .nfiles = nfiles,
52                 .f      = f,
53                 .foff   = sizeof nfiles + sizeof magic + sizeof version,
54         };
55         
56         if (fread(new->offsets, sizeof *new->offsets, nfiles+1, f) != nfiles+1)
57                 goto readerr;
58         new->foff += sizeof *new->offsets * (nfiles+1);
59
60         return new;
61 readerr:
62         if (feof(f)) {
63                 lbx_errno = LBX_EEOF;
64         } else {
65                 lbx_errno = -errno;
66         }
67
68         free(new);
69         return NULL;
70 }
71
72 struct lbx_state *lbx_open(const char *path)
73 {
74         struct lbx_state *new = NULL;
75         FILE *f;
76         
77         if ((f = fopen(path, "rb"))) {
78                 const char *name = strrchr(path, '/');
79                 new = lbx_fopen(f, name ? name+1 : path);
80         } else {
81                 lbx_errno = -errno;
82         }
83
84         return new;
85 }
86
87 size_t lbx_numfiles(struct lbx_state *lbx)
88 {
89         return lbx->nfiles;
90 }
91
92 void lbx_close(struct lbx_state *lbx)
93 {
94         if (!lbx) return;
95
96         fclose(lbx->f);
97         free(lbx);
98 }
99
100 const char *lbx_strerror(void)
101 {
102         if (lbx_errno < 0)
103                 return strerror(-lbx_errno);
104
105         switch (lbx_errno) {
106         case LBX_ESUCCESS: return "Success";
107         case LBX_EMAGIC:   return "Bad magic number";
108         case LBX_EEOF:     return "Unexpected end-of-file";
109         }
110
111         return "Unknown error";
112 }