Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* included by expand and 9boot with different header files */
2
 
3
typedef struct Biobuf	Biobuf;
4
 
5
struct Biobuf
6
{
7
	uchar *bp;
8
	uchar *p;
9
	uchar *ep;
10
};
11
 
12
static ulong	Boffset(Biobuf *bp);
13
static int	crcwrite(void *out, void *buf, int n);
14
static ulong	get4(Biobuf *b);
15
static int	getc(void*);
16
static int	header(Biobuf*);
17
static ulong	offset(Biobuf*);
18
static int	trailer(Biobuf*, Biobuf*);
19
 
20
/* GZIP flags */
21
enum {
22
	Ftext=		(1<<0),
23
	Fhcrc=		(1<<1),
24
	Fextra=		(1<<2),
25
	Fname=		(1<<3),
26
	Fcomment=	(1<<4),
27
 
28
	GZCRCPOLY	= 0xedb88320UL,
29
};
30
 
31
static ulong	*crctab;
32
static ulong	crc;
33
 
34
int
35
gunzip(uchar *out, int outn, uchar *in, int inn)
36
{
37
	Biobuf bin, bout;
38
	int err;
39
 
40
	crc = 0;
41
	crctab = mkcrctab(GZCRCPOLY);
42
	err = inflateinit();
43
	if(err != FlateOk)
44
		print("inflateinit failed: %s\n", flateerr(err));
45
 
46
	bin.bp = bin.p = in;
47
	bin.ep = in+inn;
48
	bout.bp = bout.p = out;
49
	bout.ep = out+outn;
50
 
51
	err = header(&bin);
52
	if(err != FlateOk)
53
		return err;
54
 
55
	err = inflate(&bout, crcwrite, &bin, getc);
56
	if(err != FlateOk)
57
		print("inflate failed: %s\n", flateerr(err));
58
 
59
	err = trailer(&bout, &bin);
60
	if(err != FlateOk)
61
		return err;
62
 
63
	return Boffset(&bout);
64
}
65
 
66
static int
67
header(Biobuf *bin)
68
{
69
	int i, flag;
70
 
71
	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
72
		print("bad magic\n");
73
		return FlateCorrupted;
74
	}
75
	if(getc(bin) != 8){
76
		print("unknown compression type\n");
77
		return FlateCorrupted;
78
	}
79
 
80
	flag = getc(bin);
81
 
82
	/* mod time */
83
	get4(bin);
84
 
85
	/* extra flags */
86
	getc(bin);
87
 
88
	/* OS type */
89
	getc(bin);
90
 
91
	if(flag & Fextra)
92
		for(i=getc(bin); i>0; i--)
93
			getc(bin);
94
 
95
	/* name */
96
	if(flag&Fname)
97
		while(getc(bin) != 0)
98
			;
99
 
100
	/* comment */
101
	if(flag&Fcomment)
102
		while(getc(bin) != 0)
103
			;
104
 
105
	/* crc16 */
106
	if(flag&Fhcrc) {
107
		getc(bin);
108
		getc(bin);
109
	}
110
 
111
	return FlateOk;
112
}
113
 
114
static int
115
trailer(Biobuf *bout, Biobuf *bin)
116
{
117
	/* crc32 */
118
	if(crc != get4(bin)){
119
		print("crc mismatch\n");
120
		return FlateCorrupted;
121
	}
122
 
123
	/* length */
124
	if(get4(bin) != Boffset(bout)){
125
		print("bad output len\n");
126
		return FlateCorrupted;
127
	}
128
	return FlateOk;
129
}
130
 
131
static ulong
132
get4(Biobuf *b)
133
{
134
	ulong v;
135
	int i, c;
136
 
137
	v = 0;
138
	for(i = 0; i < 4; i++){
139
		c = getc(b);
140
		v |= c << (i * 8);
141
	}
142
	return v;
143
}
144
 
145
static int
146
getc(void *in)
147
{
148
	Biobuf *bp = in;
149
 
150
//	if((bp->p - bp->bp) % 10000 == 0)
151
//		print(".");
152
	if(bp->p >= bp->ep){
153
		print("EOF");
154
		return -1;
155
	}
156
	return *bp->p++;
157
}
158
 
159
static ulong
160
Boffset(Biobuf *bp)
161
{
162
	return bp->p - bp->bp;
163
}
164
 
165
static int
166
crcwrite(void *out, void *buf, int n)
167
{
168
	Biobuf *bp;
169
	int nn;
170
 
171
	crc = blockcrc(crctab, crc, buf, n);
172
	bp = out;
173
	nn = n;
174
	if(nn > bp->ep-bp->p)
175
		nn = bp->ep-bp->p;
176
	if(nn > 0)
177
		memmove(bp->p, buf, nn);
178
	bp->p += n;
179
	return n;
180
}