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