123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- #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 *)
- {
- }
|