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