#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <stdint.h>
+#include <errno.h>
#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[];
};
uint16_t nfiles, version;
uint32_t magic;
- if (fread(&nfiles, sizeof nfiles, 1, f) != 1) return NULL;
- if (fread(&magic, sizeof magic, 1, f) != 1) return NULL;
- if (fread(&version, sizeof version, 1, f) != 1) return NULL;
+ 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)
+ if (magic != LBX_MAGIC) {
+ lbx_errno = LBX_EMAGIC;
return NULL;
+ }
new = malloc(sizeof *new + (nfiles+1)*(sizeof *new->offsets));
- if (!new)
+ if (!new) {
+ lbx_errno = -errno;
return NULL;
+ }
*new = (struct lbx_state){
.nfiles = nfiles,
};
if (fread(new->offsets, sizeof *new->offsets, nfiles+1, f) != nfiles+1)
- return free(new), NULL;
+ 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")))
+ 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";
+}
static const char *progname;
#define errmsg(fmt, ...) (\
- fprintf(stderr, "%s: " fmt ": %m.\n", progname, __VA_ARGS__)\
+ fprintf(stderr, "%s: " fmt, progname, __VA_ARGS__)\
)
enum {
MODE_EXTRACT,
};
+int list(FILE *f, int verbose) {
+ LBX *lbx = lbx_fopen(f);
+ if (!lbx) {
+ errmsg("failed to open archive: %s.\n", lbx_strerror());
+ return EXIT_FAILURE;
+ }
+
+ if (verbose) {
+ printf("Files in archive: %zd\n", lbx_numfiles(lbx));
+ }
+
+ lbx_close(lbx);
+}
+
int main(int argc, char **argv)
{
- int mode = MODE_NONE;
+ int mode = MODE_NONE, verbose = 0;
FILE *f = stdin;
int opt;
- struct option longopts[] = {
+ static const char *sopts = "lxf:v";
+ static const struct option lopts[] = {
{ "list", 0, NULL, 'l' },
{ "extract", 0, NULL, 'x' },
{ "file", 1, NULL, 'f' },
+ { "verbose", 0, NULL, 'v' },
+
{ 0 }
};
- progname = argv[0];
- while ((opt = getopt_long(argc, argv, "lxf:", longopts, NULL)) != -1) {
+ progname = "lbxtool"; /* argv[0]; */
+ while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
switch(opt) {
case 'l':
mode = MODE_LIST;
case 'f':
f = fopen(optarg, "rb");
if (!f) {
- errmsg("failed to open file", 0, 4);
+ errmsg("failed to open file %s: %m\n", optarg);
return EXIT_FAILURE;
}
break;
+ case 'v':
+ verbose = 1;
+ break;
default:
return EXIT_FAILURE;
}
}
- if (mode == MODE_NONE) {
- fprintf(stderr, "%s: you must specify a mode.\n", progname);
- return EXIT_FAILURE;
+ switch (mode) {
+ case MODE_LIST:
+ return list(f, verbose);
+ case MODE_EXTRACT:
+ return EXIT_SUCCESS;
}
+
+ fprintf(stderr, "%s: you must specify a mode.\n", progname);
+ return EXIT_FAILURE;
}