ref: e59ffed426f628794d4669f152eff9a6239b99db
dir: /os/boot/pc/inflate.c/
#include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include <flate.h> typedef struct Biobuf Biobuf; struct Biobuf { uchar *bp; uchar *p; uchar *ep; }; static int header(Biobuf*); static int trailer(Biobuf*, Biobuf*); static int getc(void*); static ulong offset(Biobuf*); static int crcwrite(void *out, void *buf, int n); static ulong get4(Biobuf *b); static ulong Boffset(Biobuf *bp); /* GZIP flags */ enum { Ftext= (1<<0), Fhcrc= (1<<1), Fextra= (1<<2), Fname= (1<<3), Fcomment= (1<<4), GZCRCPOLY = 0xedb88320UL, }; static ulong *crctab; static ulong crc; extern void diff(char*); //XXX int gunzip(uchar *out, int outn, uchar *in, int inn) { Biobuf bin, bout; int err; crc = 0; crctab = mkcrctab(GZCRCPOLY); err = inflateinit(); if(err != FlateOk) print("inflateinit failed: %s\n", flateerr(err)); bin.bp = bin.p = in; bin.ep = in+inn; bout.bp = bout.p = out; bout.ep = out+outn; err = header(&bin); if(err != FlateOk) return err; err = inflate(&bout, crcwrite, &bin, getc); if(err != FlateOk) print("inflate failed: %s\n", flateerr(err)); err = trailer(&bout, &bin); if(err != FlateOk) return err; return Boffset(&bout); } static int header(Biobuf *bin) { int i, flag; if(getc(bin) != 0x1f || getc(bin) != 0x8b){ print("bad magic\n"); return FlateCorrupted; } if(getc(bin) != 8){ print("unknown compression type\n"); return FlateCorrupted; } flag = getc(bin); /* mod time */ get4(bin); /* extra flags */ getc(bin); /* OS type */ getc(bin); if(flag & Fextra) for(i=getc(bin); i>0; i--) getc(bin); /* name */ if(flag&Fname) while(getc(bin) != 0) ; /* comment */ if(flag&Fcomment) while(getc(bin) != 0) ; /* crc16 */ if(flag&Fhcrc) { getc(bin); getc(bin); } return FlateOk; } static int trailer(Biobuf *bout, Biobuf *bin) { /* crc32 */ if(crc != get4(bin)){ print("crc mismatch\n"); return FlateCorrupted; } /* length */ if(get4(bin) != Boffset(bout)){ print("bad output len\n"); return FlateCorrupted; } return FlateOk; } static ulong get4(Biobuf *b) { ulong v; int i, c; v = 0; for(i = 0; i < 4; i++){ c = getc(b); v |= c << (i * 8); } return v; } static int getc(void *in) { Biobuf *bp = in; // if((bp->p - bp->bp) % 10000 == 0) // print("."); if(bp->p >= bp->ep) return -1; return *bp->p++; } static ulong Boffset(Biobuf *bp) { return bp->p - bp->bp; } static int crcwrite(void *out, void *buf, int n) { Biobuf *bp; int nn; crc = blockcrc(crctab, crc, buf, n); bp = out; nn = n; if(nn > bp->ep-bp->p) nn = bp->ep-bp->p; if(nn > 0) memmove(bp->p, buf, nn); bp->p += n; return n; } #undef malloc #undef free void * malloc(ulong n) { return ialloc(n, 8); } void free(void *) { }