From: Nick Bowler Date: Mon, 2 Nov 2009 03:36:58 +0000 (-0500) Subject: liblbx: Convert lbx_fopen to use the packing routines from libupkg. X-Git-Url: https://git.draconx.ca/gitweb/liblbx.git/commitdiff_plain/32081e3bb50124d451a660872f6dff57232e5172 liblbx: Convert lbx_fopen to use the packing routines from libupkg. --- diff --git a/src/Makefile.inc b/src/Makefile.inc index c60dbc5..fd3d0a8 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -7,10 +7,10 @@ lbxdir = $(includedir)/lbx lbx_HEADERS = src/lbx.h src/image.h -noinst_HEADERS += src/byteorder.h src/misc.h src/tools.h +noinst_HEADERS += src/byteorder.h src/misc.h src/tools.h src/pack.h lib_LTLIBRARIES += liblbx.la -liblbx_la_SOURCES = src/misc.c src/lbx.c src/image.c +liblbx_la_SOURCES = src/misc.c src/lbx.c src/image.c src/pack.c bin_PROGRAMS += lbxtool lbxtool_SOURCES = src/lbxtool.c diff --git a/src/lbx.c b/src/lbx.c index d3fc011..d75a123 100644 --- a/src/lbx.c +++ b/src/lbx.c @@ -30,11 +30,12 @@ #include #include -#include "byteorder.h" +#include "pack.h" #include "misc.h" #include "lbx.h" -#define LBX_MAGIC 0x0000fead +#define LBX_MAGIC 0x0000fead +#define LBX_HDR_SIZE 8 int lbx_errno = 0; @@ -50,52 +51,65 @@ struct lbx_state { uint32_t offsets[]; }; -struct lbx_state *lbx_fopen(FILE *f, const char *name) +static struct lbx_state *lbx_init(unsigned char hdr[static LBX_HDR_SIZE]) { - 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); + unsigned short nfiles = unpack_16_le(hdr+0); + unsigned long magic = unpack_32_le(hdr+2); + unsigned short version = unpack_16_le(hdr+6); + struct lbx_state *lbx; if (magic != LBX_MAGIC) { - lbx_errno = LBX_EMAGIC; + lbx_errno = -LBX_EMAGIC; return NULL; } - - new = malloc(sizeof *new + (nfiles+1)*(sizeof *new->offsets)); - if (!new) { + + lbx = malloc(sizeof *lbx + sizeof lbx->offsets[0] * (nfiles+1)); + if (!lbx) { lbx_errno = -errno; return NULL; } - - *new = (struct lbx_state){ - .name = name, + + *lbx = (struct lbx_state) { .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 { + return lbx; +} + +struct lbx_state *lbx_fopen(FILE *f, const char *name) +{ + unsigned char hdr_buf[LBX_HDR_SIZE]; + struct lbx_state *lbx; + + if (fread(hdr_buf, 1, sizeof hdr_buf, f) != sizeof hdr_buf) { lbx_errno = -errno; + return NULL; } - free(new); - return NULL; + lbx = lbx_init(hdr_buf); + if (!lbx) + return NULL; + + lbx->name = name; + lbx->f = f; + lbx->foff = sizeof hdr_buf; + + for (unsigned i = 0; i <= lbx->nfiles; i++) { + unsigned char buf[4]; + + if (fread(buf, 1, sizeof buf, f) != sizeof buf) { + lbx_errno = -errno; + if (feof(f)) + lbx_errno = LBX_EEOF; + free(lbx); + return NULL; + } + + lbx->offsets[i] = unpack_32_le(buf); + lbx->foff += sizeof buf; + } + + return lbx; } static int _lbx_memcpy(void *dest, struct lbx_state *src, size_t size) diff --git a/src/pack.c b/src/pack.c new file mode 100644 index 0000000..1128a19 --- /dev/null +++ b/src/pack.c @@ -0,0 +1,123 @@ +/* + * Portable binary serialisation of integral types. + * Copyright (C) 2009 Nick Bowler + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. This file is offered as-is, + * without any warranty. + */ + +#include "pack.h" + +/* Unsigned integer packing. */ +#define DEFPACK_BE(bits, type) void pack_ ## bits ## _be ( \ + unsigned char *out, type v \ +) { \ + unsigned i; \ + for (i = 1; i <= bits/8; i++) { \ + out[bits/8 - i] = v % 256; \ + v /= 256; \ + } \ +} + +#define DEFPACK_LE(bits, type) void pack_ ## bits ## _le ( \ + unsigned char *out, type v \ +) { \ + unsigned i; \ + for (i = 0; i < bits/8; i++) { \ + out[i] = v % 256; \ + v /= 256; \ + } \ +} + +DEFPACK_BE(16, unsigned short) +DEFPACK_BE(32, unsigned long) +#if PACK_HAVE_64BIT +DEFPACK_BE(64, unsigned long long) +#endif + +DEFPACK_LE(16, unsigned short) +DEFPACK_LE(32, unsigned long) +#if PACK_HAVE_64BIT +DEFPACK_LE(64, unsigned long long) +#endif + +#define DEFUNPACK_BE(bits, type) type unpack_ ## bits ## _be ( \ + const unsigned char *in \ +) { \ + type v = 0; \ + unsigned i; \ + for (i = 0; i < bits/8; i++) { \ + v *= 256; \ + v += in[i]; \ + } \ + return v; \ +} + +#define DEFUNPACK_LE(bits, type) type unpack_ ## bits ## _le ( \ + const unsigned char *in \ +) { \ + type v = 0; \ + unsigned i; \ + for (i = 1; i <= bits/8; i++) { \ + v *= 256; \ + v += in[bits/8 - i]; \ + } \ + return v; \ +} + +DEFUNPACK_BE(16, unsigned short) +DEFUNPACK_BE(32, unsigned long) +#if PACK_HAVE_64BIT +DEFUNPACK_BE(64, unsigned long long) +#endif + +DEFUNPACK_LE(16, unsigned short) +DEFUNPACK_LE(32, unsigned long) +#if PACK_HAVE_64BIT +DEFUNPACK_LE(64, unsigned long long) +#endif + +/* + * Two's complement signed integer packing. This is unlikely to work on + * systems that don't themselves use two's complement. + */ + +#define DEFUNPACK_SBE(bits, max, type) type unpack_s ## bits ## _be ( \ + const unsigned char *in \ +) { \ + type v = 0; \ + unsigned i; \ + int sign = (in[0] & 0x80) ? 1 : 0; \ + for (i = 0; i < bits/8; i++) { \ + v *= 256; \ + v += in[i] & (i == 0 ? 0x7f : 0xff); \ + } \ + return sign*(-max-1) + v; \ +} + +#define DEFUNPACK_SLE(bits, max, type) type unpack_s ## bits ## _le ( \ + const unsigned char *in \ +) { \ + type v = 0; \ + unsigned i; \ + int sign = (in[bits/8 - 1] & 0x80) ? 1 : 0; \ + for (i = 1; i <= bits/8; i++) { \ + v *= 256; \ + v += in[bits/8 - i] & (i == 1 ? 0x7f : 0xff); \ + } \ + return sign*(-max-1) + v; \ +} + +DEFUNPACK_SBE(16, 32767, short) +DEFUNPACK_SBE(32, 2147483647l, long) +#if PACK_HAVE_64BIT +DEFUNPACK_SBE(64, 9223372036854775807ll, long long) +#endif + +DEFUNPACK_SLE(16, 32767, short) +DEFUNPACK_SLE(32, 2147483647l, long) +#if PACK_HAVE_64BIT +DEFUNPACK_SLE(64, 9223372036854775807ll, long long) +#endif diff --git a/src/pack.h b/src/pack.h new file mode 100644 index 0000000..d47ddc4 --- /dev/null +++ b/src/pack.h @@ -0,0 +1,55 @@ +/* + * Portable binary serialisation of integral types. + * Copyright (C) 2009 Nick Bowler + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright + * notice and this notice are preserved. This file is offered as-is, + * without any warranty. + */ + +#ifndef PACK_H_ +#define PACK_H_ + +#include +#if !defined(PACK_HAVE_64BIT) && defined(ULLONG_MAX) && defined(LLONG_MAX) +# define PACK_HAVE_64BIT 1 +#endif + +void pack_16_be(unsigned char *, unsigned short); +void pack_32_be(unsigned char *, unsigned long); +#if PACK_HAVE_64BIT +void pack_64_be(unsigned char *, unsigned long long); +#endif + +void pack_16_le(unsigned char *, unsigned short); +void pack_32_le(unsigned char *, unsigned long); +#if PACK_HAVE_64BIT +void pack_64_le(unsigned char *, unsigned long long); +#endif + +unsigned short unpack_16_be(const unsigned char *); +unsigned long unpack_32_be(const unsigned char *); +#if PACK_HAVE_64BIT +unsigned long long unpack_64_be(const unsigned char *); +#endif + +unsigned short unpack_16_le(const unsigned char *); +unsigned long unpack_32_le(const unsigned char *); +#if PACK_HAVE_64BIT +unsigned long long unpack_64_le(const unsigned char *); +#endif + +short unpack_s16_be(const unsigned char *); +long unpack_s32_be(const unsigned char *); +#if PACK_HAVE_64BIT +long long unpack_s64_be(const unsigned char *); +#endif + +short unpack_s16_le(const unsigned char *); +long unpack_s32_le(const unsigned char *); +#if PACK_HAVE_64BIT +long long unpack_s64_le(const unsigned char *); +#endif + +#endif