summaryrefslogtreecommitdiff
path: root/os/boot/libflate/inflatezlibblock.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/boot/libflate/inflatezlibblock.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/boot/libflate/inflatezlibblock.c')
-rw-r--r--os/boot/libflate/inflatezlibblock.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/os/boot/libflate/inflatezlibblock.c b/os/boot/libflate/inflatezlibblock.c
new file mode 100644
index 00000000..d149cf87
--- /dev/null
+++ b/os/boot/libflate/inflatezlibblock.c
@@ -0,0 +1,67 @@
+#include "lib9.h"
+#include <flate.h>
+#include "zlib.h"
+
+typedef struct Block Block;
+
+struct Block
+{
+ uchar *pos;
+ uchar *limit;
+};
+
+static int
+blgetc(void *vb)
+{
+ Block *b;
+
+ b = vb;
+ if(b->pos >= b->limit)
+ return -1;
+ return *b->pos++;
+}
+
+static int
+blwrite(void *vb, void *buf, int n)
+{
+ Block *b;
+
+ b = vb;
+
+ if(n > b->limit - b->pos)
+ n = b->limit - b->pos;
+ memmove(b->pos, buf, n);
+ b->pos += n;
+ return n;
+}
+
+int
+inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
+{
+ Block bd, bs;
+ int ok;
+
+ if(ssize < 6)
+ return FlateInputFail;
+
+ if(((src[0] << 8) | src[1]) % 31)
+ return FlateCorrupted;
+ if((src[0] & ZlibMeth) != ZlibDeflate
+ || (src[0] & ZlibCInfo) > ZlibWin32k)
+ return FlateCorrupted;
+
+ bs.pos = src + 2;
+ bs.limit = src + ssize - 6;
+
+ bd.pos = dst;
+ bd.limit = dst + dsize;
+
+ ok = inflate(&bd, blwrite, &bs, blgetc);
+ if(ok != FlateOk)
+ return ok;
+
+ if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
+ return FlateCorrupted;
+
+ return bd.pos - dst;
+}