summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 21:23:42 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2007-07-05 21:23:42 +0200
commitbc1e507198ecadf12b4c40f4977487cd4d2df34b (patch)
treecc48d5136a4743e1701ee1228f47891a822d3974 /lib
parent75a10b942c77c0720b2f81c971672673b944d922 (diff)
downloadbarebox-bc1e507198ecadf12b4c40f4977487cd4d2df34b.tar.gz
barebox-bc1e507198ecadf12b4c40f4977487cd4d2df34b.tar.xz
add gunzip
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/gunzip.c85
2 files changed, 86 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 13aa1ce8d9..0aaf53f69a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@ obj-y += xfuncs.o
obj-y += getopt.o
obj-y += readkey.o
obj-$(CONFIG_BZLIB) += bzlib.o bzlib_crctable.o bzlib_decompress.o bzlib_huffman.o bzlib_randtable.o
-obj-$(CONFIG_ZLIB) += zlib.o
+obj-$(CONFIG_ZLIB) += zlib.o gunzip.o
obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_CMDLINE_EDITING) += readline.o
obj-$(CONFIG_SIMPLE_READLINE) += readline_simple.o
diff --git a/lib/gunzip.c b/lib/gunzip.c
new file mode 100644
index 0000000000..c41568afd6
--- /dev/null
+++ b/lib/gunzip.c
@@ -0,0 +1,85 @@
+#include <common.h>
+#include <zlib.h>
+#include <malloc.h>
+
+#define ZALLOC_ALIGNMENT 16
+
+static void *zalloc(void *x, unsigned items, unsigned size)
+{
+ void *p;
+
+ size *= items;
+ size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
+
+ p = malloc (size);
+
+ return (p);
+}
+
+static void zfree(void *x, void *addr, unsigned nb)
+{
+ free (addr);
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+#define DEFLATED 8
+
+int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ puts ("Error: Bad gzipped data\n");
+ return (-1);
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ puts ("Error: gunzip out of data in header\n");
+ return (-1);
+ }
+
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ s.outcb = (cb_func)WATCHDOG_RESET;
+#else
+ s.outcb = Z_NULL;
+#endif /* CONFIG_HW_WATCHDOG */
+
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf ("Error: inflateInit2() returned %d\n", r);
+ return (-1);
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ printf ("Error: inflate() returned %d\n", r);
+ return (-1);
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
+
+ return (0);
+}