]> git.draconx.ca Git - liblbx.git/blob - src/lbx.c
Implement stub list operation.
[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         FILE *f;
16         long offset;
17
18         uint16_t nfiles;
19         uint32_t offsets[];
20 };
21
22 struct lbx_state *lbx_fopen(FILE *f)
23 {
24         struct lbx_state *new = NULL;
25         uint16_t nfiles, version;
26         uint32_t magic;
27
28         if (fread(&nfiles,  sizeof nfiles,  1, f) != 1) goto readerr;
29         if (fread(&magic,   sizeof magic,   1, f) != 1) goto readerr;
30         if (fread(&version, sizeof version, 1, f) != 1) goto readerr;
31
32         nfiles  = letohs(nfiles);
33         magic   = letohl(magic);
34         version = letohs(version);
35
36         if (magic != LBX_MAGIC) {
37                 lbx_errno = LBX_EMAGIC;
38                 return NULL;
39         }
40         
41         new = malloc(sizeof *new + (nfiles+1)*(sizeof *new->offsets));
42         if (!new) {
43                 lbx_errno = -errno;
44                 return NULL;
45         }
46         
47         *new = (struct lbx_state){
48                 .nfiles = nfiles,
49                 .f = f,
50         };
51         
52         if (fread(new->offsets, sizeof *new->offsets, nfiles+1, f) != nfiles+1)
53                 goto readerr;
54
55         return new;
56 readerr:
57         if (feof(f)) {
58                 lbx_errno = LBX_EEOF;
59         } else {
60                 lbx_errno = -errno;
61         }
62
63         free(new);
64         return NULL;
65 }
66
67 struct lbx_state *lbx_open(const char *path)
68 {
69         struct lbx_state *new = NULL;
70         FILE *f;
71         
72         if ((f = fopen(path, "rb"))) {
73                 new = lbx_fopen(f);
74         } else {
75                 lbx_errno = -errno;
76         }
77
78         return new;
79 }
80
81 size_t lbx_numfiles(struct lbx_state *lbx)
82 {
83         return lbx->nfiles;
84 }
85
86 void lbx_close(struct lbx_state *lbx)
87 {
88         if (!lbx) return;
89
90         fclose(lbx->f);
91         free(lbx);
92 }
93
94 const char *lbx_strerror(void)
95 {
96         if (lbx_errno < 0)
97                 return strerror(-lbx_errno);
98
99         switch (lbx_errno) {
100         case LBX_ESUCCESS: return "Success";
101         case LBX_EMAGIC:   return "Bad magic number";
102         case LBX_EEOF:     return "Unexpected end-of-file";
103         }
104
105         return "Unknown error";
106 }