This source file includes following definitions.
- zcalloc
- zcfree
- get_byte
- getLong
- check_header
- open
- close
- read
- lseek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include "stand.h"
44 #include "../libz/zlib.h"
45
46 #define EOF (-1)
47
48 #define zmemcpy memcpy
49
50 #ifdef SAVE_MEMORY
51 #define Z_BUFSIZE 1024
52 #else
53 #define Z_BUFSIZE 4096
54 #endif
55
56 static int gz_magic[2] = {0x1f, 0x8b};
57
58
59 #define ASCII_FLAG 0x01
60 #define HEAD_CRC 0x02
61 #define EXTRA_FIELD 0x04
62 #define ORIG_NAME 0x08
63 #define COMMENT 0x10
64 #define RESERVED 0xE0
65
66 static struct sd {
67 z_stream stream;
68 int z_err;
69 int z_eof;
70 int fd;
71 unsigned char *inbuf;
72 unsigned long crc;
73 int transparent;
74 } *ss[SOPEN_MAX];
75
76 #ifdef DEBUG
77 int z_verbose = 0;
78 #endif
79
80
81
82
83
84 void *zcalloc(void *, unsigned int, unsigned int);
85 void zcfree(void *, void *);
86
87 void *
88 zcalloc(void *opaque, unsigned int items, unsigned int size)
89 {
90 return(alloc(items * size));
91 }
92
93 void
94 zcfree(void *opaque, void *ptr)
95 {
96 free(ptr, 0);
97 }
98
99 static int
100 get_byte(struct sd *s)
101 {
102 if (s->z_eof)
103 return EOF;
104 if (s->stream.avail_in == 0) {
105 errno = 0;
106 s->stream.avail_in = oread(s->fd, s->inbuf, Z_BUFSIZE);
107 if (s->stream.avail_in <= 0) {
108 s->z_eof = 1;
109 if (errno)
110 s->z_err = Z_ERRNO;
111 return EOF;
112 }
113 s->stream.next_in = s->inbuf;
114 }
115 s->stream.avail_in--;
116 return *(s->stream.next_in)++;
117 }
118
119 static unsigned long
120 getLong(struct sd *s)
121 {
122 unsigned long x = (unsigned long)get_byte(s);
123 int c;
124
125 x += ((unsigned long)get_byte(s))<<8;
126 x += ((unsigned long)get_byte(s))<<16;
127 c = get_byte(s);
128 if (c == EOF)
129 s->z_err = Z_DATA_ERROR;
130 x += ((unsigned long)c)<<24;
131 return x;
132 }
133
134 static void
135 check_header(struct sd *s)
136 {
137 int method;
138 int flags;
139 unsigned int len;
140 int c;
141
142
143 for (len = 0; len < 2; len++) {
144 c = get_byte(s);
145 if (c != gz_magic[len]) {
146 if (len != 0) {
147 s->stream.avail_in++;
148 s->stream.next_in--;
149 }
150 if (c != EOF) {
151 s->stream.avail_in++;
152 s->stream.next_in--;
153 s->transparent = 1;
154 }
155
156 s->z_err = s->stream.avail_in != 0 ? Z_OK :
157 Z_STREAM_END;
158 return;
159 }
160 }
161 method = get_byte(s);
162 flags = get_byte(s);
163 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
164 s->z_err = Z_DATA_ERROR;
165 return;
166 }
167
168
169 for (len = 0; len < 6; len++)
170 (void)get_byte(s);
171
172 if ((flags & EXTRA_FIELD) != 0) {
173 len = (unsigned int)get_byte(s);
174 len += ((unsigned int)get_byte(s))<<8;
175
176 while (len-- != 0 && get_byte(s) != EOF)
177 ;
178 }
179 if ((flags & ORIG_NAME) != 0) {
180 while ((c = get_byte(s)) != 0 && c != EOF)
181 ;
182 }
183 if ((flags & COMMENT) != 0) {
184 while ((c = get_byte(s)) != 0 && c != EOF)
185 ;
186 }
187 if ((flags & HEAD_CRC) != 0) {
188 for (len = 0; len < 2; len++)
189 (void)get_byte(s);
190 }
191 s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
192 }
193
194
195
196
197
198 int
199 open(const char *fname, int mode)
200 {
201 int fd;
202 struct sd *s = 0;
203
204 if (((fd = oopen(fname, mode)) == -1) ||
205 (mode != 0))
206 return(fd);
207
208 ss[fd] = s = alloc(sizeof(struct sd));
209 if (!s)
210 goto errout;
211 bzero(s, sizeof(struct sd));
212
213 #ifdef SAVE_MEMORY
214 if (inflateInit2(&(s->stream), -11) != Z_OK)
215 #else
216 if (inflateInit2(&(s->stream), -15) != Z_OK)
217 #endif
218 goto errout;
219
220 s->stream.next_in = s->inbuf = (unsigned char *)alloc(Z_BUFSIZE);
221 if (!s->inbuf) {
222 inflateEnd(&(s->stream));
223 goto errout;
224 }
225
226 s->fd = fd;
227 check_header(s);
228 return(fd);
229
230 errout:
231 if (s)
232 free(s, sizeof(struct sd));
233 oclose(fd);
234 return(-1);
235 }
236
237 int
238 close(int fd)
239 {
240 struct open_file *f;
241 struct sd *s;
242
243 if ((unsigned)fd >= SOPEN_MAX) {
244 errno = EBADF;
245 return (-1);
246 }
247 f = &files[fd];
248
249 if (!(f->f_flags & F_READ))
250 return(oclose(fd));
251
252 s = ss[fd];
253
254 inflateEnd(&(s->stream));
255
256 free(s->inbuf, Z_BUFSIZE);
257 free(s, sizeof(struct sd));
258
259 return(oclose(fd));
260 }
261
262 ssize_t
263 read(int fd, void *buf, size_t len)
264 {
265 struct sd *s;
266 unsigned char *start = buf;
267
268 s = ss[fd];
269
270 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
271 return -1;
272 if (s->z_err == Z_STREAM_END)
273 return 0;
274
275 s->stream.next_out = buf;
276 s->stream.avail_out = len;
277
278 while (s->stream.avail_out != 0) {
279
280 if (s->transparent) {
281
282 unsigned int n = s->stream.avail_in;
283
284 if (n > s->stream.avail_out)
285 n = s->stream.avail_out;
286 if (n > 0) {
287 zmemcpy(s->stream.next_out, s->stream.next_in, n);
288 s->stream.next_out += n;
289 s->stream.next_in += n;
290 s->stream.avail_out -= n;
291 s->stream.avail_in -= n;
292 }
293 if (s->stream.avail_out > 0) {
294 int n;
295
296 n = oread(fd, s->stream.next_out,
297 s->stream.avail_out);
298 if (n <= 0) {
299 s->z_eof = 1;
300 if (errno) {
301 s->z_err = Z_ERRNO;
302 break;
303 }
304 }
305 s->stream.avail_out -= n;
306 }
307 len -= s->stream.avail_out;
308 s->stream.total_in += (unsigned long)len;
309 s->stream.total_out += (unsigned long)len;
310 if (len == 0)
311 s->z_eof = 1;
312 return (int)len;
313 }
314
315 if (s->stream.avail_in == 0 && !s->z_eof) {
316 errno = 0;
317 s->stream.avail_in = oread(fd, s->inbuf, Z_BUFSIZE);
318 if (s->stream.avail_in <= 0) {
319 s->z_eof = 1;
320 if (errno) {
321 s->z_err = Z_ERRNO;
322 break;
323 }
324 }
325 s->stream.next_in = s->inbuf;
326 }
327 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
328
329 if (s->z_err == Z_STREAM_END) {
330
331 s->crc = crc32(s->crc, start,
332 (unsigned int)(s->stream.next_out - start));
333 start = s->stream.next_out;
334
335 if (getLong(s) != s->crc) {
336 s->z_err = Z_DATA_ERROR;
337 } else {
338 (void)getLong(s);
339
340
341
342
343
344
345 check_header(s);
346 if (s->z_err == Z_OK) {
347 unsigned long total_in = s->stream.total_in;
348 unsigned long total_out = s->stream.total_out;
349
350 inflateReset(&(s->stream));
351 s->stream.total_in = total_in;
352 s->stream.total_out = total_out;
353 s->crc = crc32(0L, Z_NULL, 0);
354 }
355 }
356 }
357 if (s->z_err != Z_OK || s->z_eof)
358 break;
359 }
360 s->crc = crc32(s->crc, start, (unsigned int)(s->stream.next_out - start));
361
362 return (int)(len - s->stream.avail_out);
363 }
364
365 off_t
366 lseek(int fd, off_t offset, int where)
367 {
368 struct open_file *f;
369 struct sd *s;
370
371 if ((unsigned)fd >= SOPEN_MAX) {
372 errno = EBADF;
373 return (-1);
374 }
375 f = &files[fd];
376
377 if (!(f->f_flags & F_READ))
378 return(olseek(fd, offset, where));
379
380 s = ss[fd];
381
382 if (s->transparent) {
383 off_t res = olseek(fd, offset, where);
384 if (res != (off_t)-1) {
385
386 s->stream.avail_in = 0;
387 }
388 return(res);
389 }
390
391 switch(where) {
392 case SEEK_CUR:
393 offset += s->stream.total_out;
394 case SEEK_SET:
395
396
397
398 if (offset < s->stream.total_out) {
399 off_t res;
400 void *sav_inbuf;
401
402 res = olseek(fd, 0, SEEK_SET);
403 if (res == (off_t)-1)
404 return(res);
405
406
407 inflateEnd(&(s->stream));
408
409 sav_inbuf = s->inbuf;
410 bzero(s, sizeof(struct sd));
411
412 inflateInit2(&(s->stream), -15);
413 s->stream.next_in = s->inbuf = sav_inbuf;
414
415 s->fd = fd;
416 check_header(s);
417 }
418
419
420 if (offset > s->stream.total_out) {
421 off_t toskip = offset - s->stream.total_out;
422
423 while(toskip > 0) {
424 #define DUMMYBUFSIZE 256
425 char dummybuf[DUMMYBUFSIZE];
426 off_t len = toskip;
427
428 if (len > DUMMYBUFSIZE)
429 len = DUMMYBUFSIZE;
430 if (read(fd, dummybuf, len) != len) {
431 errno = EOFFSET;
432 return((off_t)-1);
433 }
434 toskip -= len;
435 }
436 }
437 #ifdef DEBUG
438 if (offset != s->stream.total_out)
439 panic("lseek compressed");
440 #endif
441 return(offset);
442 case SEEK_END:
443 errno = EOFFSET;
444 break;
445 default:
446 errno = EINVAL;
447 }
448 return((off_t)-1);
449 }