abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
gzread.c
Go to the documentation of this file.
1 /* gzread.c -- zlib functions for reading gzip files
2  * Copyright (C) 2004, 2005, 2010 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "misc/util/abc_global.h"
10 
11 #include "gzguts.h"
12 
14 
15 /* Local functions */
16 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
17 local int gz_avail OF((gz_statep));
18 local int gz_next4 OF((gz_statep, unsigned long *));
19 local int gz_head OF((gz_statep));
21 local int gz_make OF((gz_statep));
23 
24 /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
25  state->fd, and update state->eof, state->err, and state->msg as appropriate.
26  This function needs to loop on read(), since read() is not guaranteed to
27  read the number of bytes requested, depending on the type of descriptor. */
28 local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have)
29 {
30  int ret;
31 
32  *have = 0;
33  do {
34  ret = read(state->fd, buf + *have, len - *have);
35  if (ret <= 0)
36  break;
37  *have += ret;
38  } while (*have < len);
39  if (ret < 0) {
40  gz_error(state, Z_ERRNO, zstrerror());
41  return -1;
42  }
43  if (ret == 0)
44  state->eof = 1;
45  return 0;
46 }
47 
48 /* Load up input buffer and set eof flag if last data loaded -- return -1 on
49  error, 0 otherwise. Note that the eof flag is set when the end of the input
50  file is reached, even though there may be unused data in the buffer. Once
51  that data has been used, no more attempts will be made to read the file.
52  gz_avail() assumes that strm->avail_in == 0. */
54 {
55  z_streamp strm = &(state->strm);
56 
57  if (state->err != Z_OK)
58  return -1;
59  if (state->eof == 0) {
60  if (gz_load(state, state->in, state->size,
61  (unsigned *)&(strm->avail_in)) == -1)
62  return -1;
63  strm->next_in = state->in;
64  }
65  return 0;
66 }
67 
68 /* Get next byte from input, or -1 if end or error. */
69 #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
70  (strm->avail_in == 0 ? -1 : \
71  (strm->avail_in--, *(strm->next_in)++)))
72 
73 /* Get a four-byte little-endian integer and return 0 on success and the value
74  in *ret. Otherwise -1 is returned and *ret is not modified. */
75 local int gz_next4(gz_statep state, unsigned long *ret)
76 {
77  int ch;
78  unsigned long val;
79  z_streamp strm = &(state->strm);
80 
81  val = NEXT();
82  val += (unsigned)NEXT() << 8;
83  val += (unsigned long)NEXT() << 16;
84  ch = NEXT();
85  if (ch == -1)
86  return -1;
87  val += (unsigned long)ch << 24;
88  *ret = val;
89  return 0;
90 }
91 
92 /* Look for gzip header, set up for inflate or copy. state->have must be zero.
93  If this is the first time in, allocate required memory. state->how will be
94  left unchanged if there is no more input data available, will be set to COPY
95  if there is no gzip header and direct copying will be performed, or it will
96  be set to GZIP for decompression, and the gzip header will be skipped so
97  that the next available input data is the raw deflate stream. If direct
98  copying, then leftover input data from the input buffer will be copied to
99  the output buffer. In that case, all further file reads will be directly to
100  either the output buffer or a user buffer. If decompressing, the inflate
101  state and the check value will be initialized. gz_head() will return 0 on
102  success or -1 on failure. Failures may include read errors or gzip header
103  errors. */
105 {
106  z_streamp strm = &(state->strm);
107  int flags;
108  unsigned len;
109 
110  /* allocate read buffers and inflate memory */
111  if (state->size == 0) {
112  /* allocate buffers */
113  state->in = (unsigned char *)malloc(state->want);
114  state->out = (unsigned char *)malloc(state->want << 1);
115  if (state->in == NULL || state->out == NULL) {
116  if (state->out != NULL)
117  free(state->out);
118  if (state->in != NULL)
119  free(state->in);
120  gz_error(state, Z_MEM_ERROR, "out of memory");
121  return -1;
122  }
123  state->size = state->want;
124 
125  /* allocate inflate memory */
126  state->strm.zalloc = Z_NULL;
127  state->strm.zfree = Z_NULL;
128  state->strm.opaque = Z_NULL;
129  state->strm.avail_in = 0;
130  state->strm.next_in = Z_NULL;
131  if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
132  free(state->out);
133  free(state->in);
134  state->size = 0;
135  gz_error(state, Z_MEM_ERROR, "out of memory");
136  return -1;
137  }
138  }
139 
140  /* get some data in the input buffer */
141  if (strm->avail_in == 0) {
142  if (gz_avail(state) == -1)
143  return -1;
144  if (strm->avail_in == 0)
145  return 0;
146  }
147 
148  /* look for the gzip magic header bytes 31 and 139 */
149  if (strm->next_in[0] == 31) {
150  strm->avail_in--;
151  strm->next_in++;
152  if (strm->avail_in == 0 && gz_avail(state) == -1)
153  return -1;
154  if (strm->avail_in && strm->next_in[0] == 139) {
155  /* we have a gzip header, woo hoo! */
156  strm->avail_in--;
157  strm->next_in++;
158 
159  /* skip rest of header */
160  if (NEXT() != 8) { /* compression method */
161  gz_error(state, Z_DATA_ERROR, "unknown compression method");
162  return -1;
163  }
164  flags = NEXT();
165  if (flags & 0xe0) { /* reserved flag bits */
166  gz_error(state, Z_DATA_ERROR, "unknown header flags set");
167  return -1;
168  }
169  NEXT(); /* modification time */
170  NEXT();
171  NEXT();
172  NEXT();
173  NEXT(); /* extra flags */
174  NEXT(); /* operating system */
175  if (flags & 4) { /* extra field */
176  len = (unsigned)NEXT();
177  len += (unsigned)NEXT() << 8;
178  while (len--)
179  if (NEXT() < 0)
180  break;
181  }
182  if (flags & 8) /* file name */
183  while (NEXT() > 0)
184  ;
185  if (flags & 16) /* comment */
186  while (NEXT() > 0)
187  ;
188  if (flags & 2) { /* header crc */
189  NEXT();
190  NEXT();
191  }
192  /* an unexpected end of file is not checked for here -- it will be
193  noticed on the first request for uncompressed data */
194 
195  /* set up for decompression */
196  inflateReset(strm);
197  strm->adler = crc32(0L, Z_NULL, 0);
198  state->how = GZIP;
199  state->direct = 0;
200  return 0;
201  }
202  else {
203  /* not a gzip file -- save first byte (31) and fall to raw i/o */
204  state->out[0] = 31;
205  state->have = 1;
206  }
207  }
208 
209  /* doing raw i/o, save start of raw data for seeking, copy any leftover
210  input to output -- this assumes that the output buffer is larger than
211  the input buffer, which also assures space for gzungetc() */
212  state->raw = state->pos;
213  state->next = state->out;
214  if (strm->avail_in) {
215  memcpy(state->next + state->have, strm->next_in, strm->avail_in);
216  state->have += strm->avail_in;
217  strm->avail_in = 0;
218  }
219  state->how = COPY;
220  state->direct = 1;
221  return 0;
222 }
223 
224 /* Decompress from input to the provided next_out and avail_out in the state.
225  If the end of the compressed data is reached, then verify the gzip trailer
226  check value and length (modulo 2^32). state->have and state->next are set
227  to point to the just decompressed data, and the crc is updated. If the
228  trailer is verified, state->how is reset to LOOK to look for the next gzip
229  stream or raw data, once state->have is depleted. Returns 0 on success, -1
230  on failure. Failures may include invalid compressed data or a failed gzip
231  trailer verification. */
233 {
234  int ret;
235  unsigned had;
236  unsigned long crc, len;
237  z_streamp strm = &(state->strm);
238 
239  /* fill output buffer up to end of deflate stream */
240  had = strm->avail_out;
241  do {
242  /* get more input for inflate() */
243  if (strm->avail_in == 0 && gz_avail(state) == -1)
244  return -1;
245  if (strm->avail_in == 0) {
246  gz_error(state, Z_DATA_ERROR, "unexpected end of file");
247  return -1;
248  }
249 
250  /* decompress and handle errors */
251  ret = inflate(strm, Z_NO_FLUSH);
252  if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
253  gz_error(state, Z_STREAM_ERROR,
254  "internal error: inflate stream corrupt");
255  return -1;
256  }
257  if (ret == Z_MEM_ERROR) {
258  gz_error(state, Z_MEM_ERROR, "out of memory");
259  return -1;
260  }
261  if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
262  gz_error(state, Z_DATA_ERROR,
263  strm->msg == NULL ? "compressed data error" : strm->msg);
264  return -1;
265  }
266  } while (strm->avail_out && ret != Z_STREAM_END);
267 
268  /* update available output and crc check value */
269  state->have = had - strm->avail_out;
270  state->next = strm->next_out - state->have;
271  strm->adler = crc32(strm->adler, state->next, state->have);
272 
273  /* check gzip trailer if at end of deflate stream */
274  if (ret == Z_STREAM_END) {
275  if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
276  gz_error(state, Z_DATA_ERROR, "unexpected end of file");
277  return -1;
278  }
279  if (crc != strm->adler) {
280  gz_error(state, Z_DATA_ERROR, "incorrect data check");
281  return -1;
282  }
283  if (len != (strm->total_out & 0xffffffffL)) {
284  gz_error(state, Z_DATA_ERROR, "incorrect length check");
285  return -1;
286  }
287  state->how = LOOK; /* ready for next stream, once have is 0 (leave
288  state->direct unchanged to remember how) */
289  }
290 
291  /* good decompression */
292  return 0;
293 }
294 
295 /* Make data and put in the output buffer. Assumes that state->have == 0.
296  Data is either copied from the input file or decompressed from the input
297  file depending on state->how. If state->how is LOOK, then a gzip header is
298  looked for (and skipped if found) to determine wither to copy or decompress.
299  Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY
300  or GZIP unless the end of the input file has been reached and all data has
301  been processed. */
303 {
304  z_streamp strm = &(state->strm);
305 
306  if (state->how == LOOK) { /* look for gzip header */
307  if (gz_head(state) == -1)
308  return -1;
309  if (state->have) /* got some data from gz_head() */
310  return 0;
311  }
312  if (state->how == COPY) { /* straight copy */
313  if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
314  return -1;
315  state->next = state->out;
316  }
317  else if (state->how == GZIP) { /* decompress */
318  strm->avail_out = state->size << 1;
319  strm->next_out = state->out;
320  if (gz_decomp(state) == -1)
321  return -1;
322  }
323  return 0;
324 }
325 
326 /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
328 {
329  unsigned n;
330 
331  /* skip over len bytes or reach end-of-file, whichever comes first */
332  while (len)
333  /* skip over whatever is in output buffer */
334  if (state->have) {
335  n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
336  (unsigned)len : state->have;
337  state->have -= n;
338  state->next += n;
339  state->pos += n;
340  len -= n;
341  }
342 
343  /* output buffer empty -- return if we're at the end of the input */
344  else if (state->eof && state->strm.avail_in == 0)
345  break;
346 
347  /* need more data to skip -- load up output buffer */
348  else {
349  /* get more output, looking for header if required */
350  if (gz_make(state) == -1)
351  return -1;
352  }
353  return 0;
354 }
355 
356 /* -- see zlib.h -- */
357 int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
358 {
359  unsigned got, n;
360  gz_statep state;
361  z_streamp strm;
362 
363  /* get internal structure */
364  if (file == NULL)
365  return -1;
366  state = (gz_statep)file;
367  strm = &(state->strm);
368 
369  /* check that we're reading and that there's no error */
370  if (state->mode != GZ_READ || state->err != Z_OK)
371  return -1;
372 
373  /* since an int is returned, make sure len fits in one, otherwise return
374  with an error (this avoids the flaw in the interface) */
375  if ((int)len < 0) {
376  gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
377  return -1;
378  }
379 
380  /* if len is zero, avoid unnecessary operations */
381  if (len == 0)
382  return 0;
383 
384  /* process a skip request */
385  if (state->seek) {
386  state->seek = 0;
387  if (gz_skip(state, state->skip) == -1)
388  return -1;
389  }
390 
391  /* get len bytes to buf, or less than len if at the end */
392  got = 0;
393  do {
394  /* first just try copying data from the output buffer */
395  if (state->have) {
396  n = state->have > len ? len : state->have;
397  memcpy(buf, state->next, n);
398  state->next += n;
399  state->have -= n;
400  }
401 
402  /* output buffer empty -- return if we're at the end of the input */
403  else if (state->eof && strm->avail_in == 0)
404  break;
405 
406  /* need output data -- for small len or new stream load up our output
407  buffer */
408  else if (state->how == LOOK || len < (state->size << 1)) {
409  /* get more output, looking for header if required */
410  if (gz_make(state) == -1)
411  return -1;
412  continue; /* no progress yet -- go back to memcpy() above */
413  /* the copy above assures that we will leave with space in the
414  output buffer, allowing at least one gzungetc() to succeed */
415  }
416 
417  /* large len -- read directly into user buffer */
418  else if (state->how == COPY) { /* read directly */
419  if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
420  return -1;
421  }
422 
423  /* large len -- decompress directly into user buffer */
424  else { /* state->how == GZIP */
425  strm->avail_out = len;
426  strm->next_out = (unsigned char *)buf;
427  if (gz_decomp(state) == -1)
428  return -1;
429  n = state->have;
430  state->have = 0;
431  }
432 
433  /* update progress */
434  len -= n;
435  buf = (char *)buf + n;
436  got += n;
437  state->pos += n;
438  } while (len);
439 
440  /* return number of bytes read into user buffer (will fit in int) */
441  return (int)got;
442 }
443 
444 /* -- see zlib.h -- */
446 {
447  int ret;
448  unsigned char buf[1];
449  gz_statep state;
450 
451  /* get internal structure */
452  if (file == NULL)
453  return -1;
454  state = (gz_statep)file;
455 
456  /* check that we're reading and that there's no error */
457  if (state->mode != GZ_READ || state->err != Z_OK)
458  return -1;
459 
460  /* try output buffer (no need to check for skip request) */
461  if (state->have) {
462  state->have--;
463  state->pos++;
464  return *(state->next)++;
465  }
466 
467  /* nothing there -- try gzread() */
468  ret = gzread(file, buf, 1);
469  return ret < 1 ? -1 : buf[0];
470 }
471 
472 /* -- see zlib.h -- */
473 int ZEXPORT gzungetc(int c, gzFile file)
474 {
475  gz_statep state;
476 
477  /* get internal structure */
478  if (file == NULL)
479  return -1;
480  state = (gz_statep)file;
481 
482  /* check that we're reading and that there's no error */
483  if (state->mode != GZ_READ || state->err != Z_OK)
484  return -1;
485 
486  /* process a skip request */
487  if (state->seek) {
488  state->seek = 0;
489  if (gz_skip(state, state->skip) == -1)
490  return -1;
491  }
492 
493  /* can't push EOF */
494  if (c < 0)
495  return -1;
496 
497  /* if output buffer empty, put byte at end (allows more pushing) */
498  if (state->have == 0) {
499  state->have = 1;
500  state->next = state->out + (state->size << 1) - 1;
501  state->next[0] = c;
502  state->pos--;
503  return c;
504  }
505 
506  /* if no room, give up (must have already done a gzungetc()) */
507  if (state->have == (state->size << 1)) {
508  gz_error(state, Z_BUF_ERROR, "out of room to push characters");
509  return -1;
510  }
511 
512  /* slide output data if needed and insert byte before existing data */
513  if (state->next == state->out) {
514  unsigned char *src = state->out + state->have;
515  unsigned char *dest = state->out + (state->size << 1);
516  while (src > state->out)
517  *--dest = *--src;
518  state->next = dest;
519  }
520  state->have++;
521  state->next--;
522  state->next[0] = c;
523  state->pos--;
524  return c;
525 }
526 
527 /* -- see zlib.h -- */
528 char * ZEXPORT gzgets(gzFile file, char *buf, int len)
529 {
530  unsigned left, n;
531  char *str;
532  unsigned char *eol;
533  gz_statep state;
534 
535  /* check parameters and get internal structure */
536  if (file == NULL || buf == NULL || len < 1)
537  return NULL;
538  state = (gz_statep)file;
539 
540  /* check that we're reading and that there's no error */
541  if (state->mode != GZ_READ || state->err != Z_OK)
542  return NULL;
543 
544  /* process a skip request */
545  if (state->seek) {
546  state->seek = 0;
547  if (gz_skip(state, state->skip) == -1)
548  return NULL;
549  }
550 
551  /* copy output bytes up to new line or len - 1, whichever comes first --
552  append a terminating zero to the string (we don't check for a zero in
553  the contents, let the user worry about that) */
554  str = buf;
555  left = (unsigned)len - 1;
556  if (left) do {
557  /* assure that something is in the output buffer */
558  if (state->have == 0) {
559  if (gz_make(state) == -1)
560  return NULL; /* error */
561  if (state->have == 0) { /* end of file */
562  if (buf == str) /* got bupkus */
563  return NULL;
564  break; /* got something -- return it */
565  }
566  }
567 
568  /* look for end-of-line in current output buffer */
569  n = state->have > left ? left : state->have;
570  eol = (unsigned char *)memchr(state->next, '\n', n);
571  if (eol != NULL)
572  n = (unsigned)(eol - state->next) + 1;
573 
574  /* copy through end-of-line, or remainder if not found */
575  memcpy(buf, state->next, n);
576  state->have -= n;
577  state->next += n;
578  state->pos += n;
579  left -= n;
580  buf += n;
581  } while (left && eol == NULL);
582 
583  /* found end-of-line or out of space -- terminate string and return it */
584  buf[0] = 0;
585  return str;
586 }
587 
588 /* -- see zlib.h -- */
590 {
591  gz_statep state;
592 
593  /* get internal structure */
594  if (file == NULL)
595  return 0;
596  state = (gz_statep)file;
597 
598  /* check that we're reading */
599  if (state->mode != GZ_READ)
600  return 0;
601 
602  /* if the state is not known, but we can find out, then do so (this is
603  mainly for right after a gzopen() or gzdopen()) */
604  if (state->how == LOOK && state->have == 0)
605  (void)gz_head(state);
606 
607  /* return 1 if reading direct, 0 if decompressing a gzip stream */
608  return state->direct;
609 }
610 
611 /* -- see zlib.h -- */
613 {
614  int ret;
615  gz_statep state;
616 
617  /* get internal structure */
618  if (file == NULL)
619  return Z_STREAM_ERROR;
620  state = (gz_statep)file;
621 
622  /* check that we're reading */
623  if (state->mode != GZ_READ)
624  return Z_STREAM_ERROR;
625 
626  /* free memory and close file */
627  if (state->size) {
628  inflateEnd(&(state->strm));
629  free(state->out);
630  free(state->in);
631  }
632  gz_error(state, Z_OK, NULL);
633  free(state->path);
634  ret = close(state->fd);
635  free(state);
636  return ret ? Z_ERRNO : Z_OK;
637 }
638 
639 
641 
int ZEXPORT gzdirect(gzFile file)
Definition: gzread.c:589
Definition: inflate.h:38
char * malloc()
VOID_HACK free()
int ZEXPORT inflateReset(z_streamp strm)
Definition: inflate.c:110
#define Z_NO_FLUSH
Definition: zlib.h:172
local int gz_skip(gz_statep state, z_off64_t len)
Definition: gzread.c:327
local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have)
Definition: gzread.c:28
#define GT_OFF(x)
Definition: gzguts.h:144
#define Z_ERRNO
Definition: zlib.h:184
#define GZ_READ
Definition: gzguts.h:89
#define Z_NEED_DICT
Definition: zlib.h:183
#define z_off64_t
Definition: zconf.h:402
local int gz_head(gz_statep state)
Definition: gzread.c:104
char * memcpy()
#define Z_STREAM_ERROR
Definition: zlib.h:185
voidp gzFile
Definition: zlib.h:1173
int ZEXPORT gzungetc(int c, gzFile file)
Definition: gzread.c:473
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1561
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
Definition: gzlib.c:464
#define zstrerror()
Definition: gzguts.h:59
#define Z_DATA_ERROR
Definition: zlib.h:186
int ZEXPORT gzclose_r(gzFile file)
Definition: gzread.c:612
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
#define Z_STREAM_END
Definition: zlib.h:182
#define local
Definition: adler32.c:17
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
Definition: crc32.c:230
local int gz_decomp(gz_statep state)
Definition: gzread.c:232
#define Z_MEM_ERROR
Definition: zlib.h:187
Byte * voidp
Definition: zconf.h:356
char *ZEXPORT gzgets(gzFile file, char *buf, int len)
Definition: gzread.c:528
local int gz_make(gz_statep state)
Definition: gzread.c:302
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
int ZEXPORT gzgetc(gzFile file)
Definition: gzread.c:445
local int gz_avail(gz_statep state)
Definition: gzread.c:53
#define LOOK
Definition: gzguts.h:94
char * memchr()
#define Z_BUF_ERROR
Definition: zlib.h:188
#define Z_OK
Definition: zlib.h:181
gz_state FAR * gz_statep
Definition: gzguts.h:129
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:580
local int gz_next4(gz_statep state, unsigned long *ret)
Definition: gzread.c:75
#define Z_NULL
Definition: zlib.h:216
#define NEXT()
Definition: gzread.c:69
z_stream FAR * z_streamp
Definition: zlib.h:114
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
Definition: gzread.c:357
ABC_NAMESPACE_IMPL_START local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *))
#define ZEXPORT
Definition: zconf.h:322
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1227
#define GZIP
Definition: deflate.h:25