Geant4  10.03
gzlib.cc
Go to the documentation of this file.
1 /* gzlib.c -- zlib functions common to reading and writing gzip files
2  * Copyright (C) 2004, 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 #if defined(_WIN32) && !defined(__BORLANDC__)
9 # define LSEEK _lseeki64
10 #else
11 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
12 # define LSEEK lseek64
13 #else
14 # define LSEEK lseek
15 #endif
16 #endif
17 
18 /* Local functions */
19 local void gz_reset OF((gz_statep));
20 local gzFile gz_open OF((const void *, int, const char *));
21 
22 #if defined UNDER_CE
23 
24 /* Map the Windows error number in ERROR to a locale-dependent error message
25  string and return a pointer to it. Typically, the values for ERROR come
26  from GetLastError.
27 
28  The string pointed to shall not be modified by the application, but may be
29  overwritten by a subsequent call to gz_strwinerror
30 
31  The gz_strwinerror function does not change the current setting of
32  GetLastError. */
33 char ZLIB_INTERNAL *gz_strwinerror (DWORD error)
34 {
35  static char buf[1024];
36 
37  wchar_t *msgbuf;
38  DWORD lasterr = GetLastError();
39  DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
40  | FORMAT_MESSAGE_ALLOCATE_BUFFER,
41  NULL,
42  error,
43  0, /* Default language */
44  (LPVOID)&msgbuf,
45  0,
46  NULL);
47  if (chars != 0) {
48  /* If there is an \r\n appended, zap it. */
49  if (chars >= 2
50  && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
51  chars -= 2;
52  msgbuf[chars] = 0;
53  }
54 
55  if (chars > sizeof (buf) - 1) {
56  chars = sizeof (buf) - 1;
57  msgbuf[chars] = 0;
58  }
59 
60  wcstombs(buf, msgbuf, chars + 1);
61  LocalFree(msgbuf);
62  }
63  else {
64  sprintf(buf, "unknown win32 error (%ld)", error);
65  }
66 
67  SetLastError(lasterr);
68  return buf;
69 }
70 
71 #endif /* UNDER_CE */
72 
73 /* Reset gzip file state */
74 local void gz_reset(gz_statep state)
75 {
76  state->x.have = 0; /* no output data available */
77  if (state->mode == GZ_READ) { /* for reading ... */
78  state->eof = 0; /* not at end of file */
79  state->past = 0; /* have not read past end yet */
80  state->how = LOOK; /* look for gzip header */
81  }
82  state->seek = 0; /* no seek request pending */
83  gz_error(state, Z_OK, NULL); /* clear error */
84  state->x.pos = 0; /* no uncompressed data yet */
85  state->strm.avail_in = 0; /* no input data yet */
86 }
87 
88 /* Open a gzip file either by name or file descriptor. */
89 local gzFile gz_open(const void *path,int fd, const char *mode)
90 {
91  gz_statep state;
92  size_t len;
93  int oflag;
94 #ifdef O_CLOEXEC
95  int cloexec = 0;
96 #endif
97 #ifdef O_EXCL
98  int exclusive = 0;
99 #endif
100 
101  /* check input */
102  if (path == NULL)
103  return NULL;
104 
105  /* allocate gzFile structure to return */
106  state = (gz_statep)malloc(sizeof(gz_state));
107  if (state == NULL)
108  return NULL;
109  state->size = 0; /* no buffers allocated yet */
110  state->want = GZBUFSIZE; /* requested buffer size */
111  state->msg = NULL; /* no error message yet */
112 
113  /* interpret mode */
114  state->mode = GZ_NONE;
115  state->level = Z_DEFAULT_COMPRESSION;
116  state->strategy = Z_DEFAULT_STRATEGY;
117  state->direct = 0;
118  while (*mode) {
119  if (*mode >= '0' && *mode <= '9')
120  state->level = *mode - '0';
121  else
122  switch (*mode) {
123  case 'r':
124  state->mode = GZ_READ;
125  break;
126 #ifndef NO_GZCOMPRESS
127  case 'w':
128  state->mode = GZ_WRITE;
129  break;
130  case 'a':
131  state->mode = GZ_APPEND;
132  break;
133 #endif
134  case '+': /* can't read and write at the same time */
135  free(state);
136  return NULL;
137  case 'b': /* ignore -- will request binary anyway */
138  break;
139 #ifdef O_CLOEXEC
140  case 'e':
141  cloexec = 1;
142  break;
143 #endif
144 #ifdef O_EXCL
145  case 'x':
146  exclusive = 1;
147  break;
148 #endif
149  case 'f':
150  state->strategy = Z_FILTERED;
151  break;
152  case 'h':
153  state->strategy = Z_HUFFMAN_ONLY;
154  break;
155  case 'R':
156  state->strategy = Z_RLE;
157  break;
158  case 'F':
159  state->strategy = Z_FIXED;
160  break;
161  case 'T':
162  state->direct = 1;
163  break;
164  default: /* could consider as an error, but just ignore */
165  ;
166  }
167  mode++;
168  }
169 
170  /* must provide an "r", "w", or "a" */
171  if (state->mode == GZ_NONE) {
172  free(state);
173  return NULL;
174  }
175 
176  /* can't force transparent read */
177  if (state->mode == GZ_READ) {
178  if (state->direct) {
179  free(state);
180  return NULL;
181  }
182  state->direct = 1; /* for empty file */
183  }
184 
185  /* save the path name for error messages */
186 #ifdef _WIN32
187  if (fd == -2) {
188  len = wcstombs(NULL, (const wchar_t *)path, 0);
189  if (len == (size_t)-1)
190  len = 0;
191  }
192  else
193 #endif
194  len = strlen((const char *)path);
195  state->path = (char*)malloc(len + 1);
196  if (state->path == NULL) {
197  free(state);
198  return NULL;
199  }
200 #ifdef _WIN32
201  if (fd == -2)
202  if (len)
203  wcstombs(state->path, (const wchar_t *)path, len + 1);
204  else
205  *(state->path) = 0;
206  else
207 #endif
208 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
209  snprintf(state->path, len + 1, "%s", (const char *)path);
210 #else
211  strcpy(state->path, path);
212 #endif
213 
214  /* compute the flags for open() */
215  oflag =
216 #ifdef O_LARGEFILE
217  O_LARGEFILE |
218 #endif
219 #ifdef O_BINARY
220  O_BINARY |
221 #endif
222 #ifdef O_CLOEXEC
223  (cloexec ? O_CLOEXEC : 0) |
224 #endif
225  (state->mode == GZ_READ ?
226  O_RDONLY :
227  (O_WRONLY | O_CREAT |
228 #ifdef O_EXCL
229  (exclusive ? O_EXCL : 0) |
230 #endif
231  (state->mode == GZ_WRITE ?
232  O_TRUNC :
233  O_APPEND)));
234 
235  /* open the file with the appropriate flags (or just use fd) */
236  state->fd = fd > -1 ? fd : (
237 #ifdef _WIN32
238  fd == -2 ? _wopen((const wchar_t *)path, oflag, 0666) :
239 #endif
240  open((const char *)path, oflag, 0666));
241  if (state->fd == -1) {
242  free(state->path);
243  free(state);
244  return NULL;
245  }
246  if (state->mode == GZ_APPEND)
247  state->mode = GZ_WRITE; /* simplify later checks */
248 
249  /* save the current position for rewinding (only if reading) */
250  if (state->mode == GZ_READ) {
251  state->start = LSEEK(state->fd, 0, SEEK_CUR);
252  if (state->start == -1) state->start = 0;
253  }
254 
255  /* initialize stream */
256  gz_reset(state);
257 
258  /* return stream */
259  return (gzFile)state;
260 }
261 
262 /* -- see zlib.h -- */
263 gzFile ZEXPORT gzopen(const char *path,const char * mode)
264 {
265  return gz_open(path, -1, mode);
266 }
267 
268 /* -- see zlib.h -- */
269 gzFile ZEXPORT gzopen64(const char *path,const char * mode)
270 {
271  return gz_open(path, -1, mode);
272 }
273 
274 /* -- see zlib.h -- */
275 gzFile ZEXPORT gzdopen(int fd, const char *mode)
276 {
277  char *path; /* identifier for error messages */
278  gzFile gz;
279 
280  if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
281  return NULL;
282 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
283  snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
284 #else
285  sprintf(path, "<fd:%d>", fd); /* for debugging */
286 #endif
287  gz = gz_open(path, fd, mode);
288  free(path);
289  return gz;
290 }
291 
292 /* -- see zlib.h -- */
293 #ifdef _WIN32
294 gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode)
295 {
296  return gz_open(path, -2, mode);
297 }
298 #endif
299 
300 /* -- see zlib.h -- */
301 int ZEXPORT gzbuffer(gzFile file, unsigned size)
302 {
303  gz_statep state;
304 
305  /* get internal structure and check integrity */
306  if (file == NULL)
307  return -1;
308  state = (gz_statep)file;
309  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
310  return -1;
311 
312  /* make sure we haven't already allocated memory */
313  if (state->size != 0)
314  return -1;
315 
316  /* check and set requested size */
317  if (size < 2)
318  size = 2; /* need two bytes to check magic header */
319  state->want = size;
320  return 0;
321 }
322 
323 /* -- see zlib.h -- */
324 int ZEXPORT gzrewind(gzFile file)
325 {
326  gz_statep state;
327 
328  /* get internal structure */
329  if (file == NULL)
330  return -1;
331  state = (gz_statep)file;
332 
333  /* check that we're reading and that there's no error */
334  if (state->mode != GZ_READ ||
335  (state->err != Z_OK && state->err != Z_BUF_ERROR))
336  return -1;
337 
338  /* back up and start over */
339  if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
340  return -1;
341  gz_reset(state);
342  return 0;
343 }
344 
345 /* -- see zlib.h -- */
346 z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
347 {
348  unsigned n;
349  z_off64_t ret;
350  gz_statep state;
351 
352  /* get internal structure and check integrity */
353  if (file == NULL)
354  return -1;
355  state = (gz_statep)file;
356  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
357  return -1;
358 
359  /* check that there's no error */
360  if (state->err != Z_OK && state->err != Z_BUF_ERROR)
361  return -1;
362 
363  /* can only seek from start or relative to current position */
364  if (whence != SEEK_SET && whence != SEEK_CUR)
365  return -1;
366 
367  /* normalize offset to a SEEK_CUR specification */
368  if (whence == SEEK_SET)
369  offset -= state->x.pos;
370  else if (state->seek)
371  offset += state->skip;
372  state->seek = 0;
373 
374  /* if within raw area while reading, just go there */
375  if (state->mode == GZ_READ && state->how == COPY &&
376  state->x.pos + offset >= 0) {
377  ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
378  if (ret == -1)
379  return -1;
380  state->x.have = 0;
381  state->eof = 0;
382  state->past = 0;
383  state->seek = 0;
384  gz_error(state, Z_OK, NULL);
385  state->strm.avail_in = 0;
386  state->x.pos += offset;
387  return state->x.pos;
388  }
389 
390  /* calculate skip amount, rewinding if needed for back seek when reading */
391  if (offset < 0) {
392  if (state->mode != GZ_READ) /* writing -- can't go backwards */
393  return -1;
394  offset += state->x.pos;
395  if (offset < 0) /* before start of file! */
396  return -1;
397  if (gzrewind(file) == -1) /* rewind, then skip to offset */
398  return -1;
399  }
400 
401  /* if reading, skip what's in output buffer (one less gzgetc() check) */
402  if (state->mode == GZ_READ) {
403  n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
404  (unsigned)offset : state->x.have;
405  state->x.have -= n;
406  state->x.next += n;
407  state->x.pos += n;
408  offset -= n;
409  }
410 
411  /* request skip (if not zero) */
412  if (offset) {
413  state->seek = 1;
414  state->skip = offset;
415  }
416  return state->x.pos + offset;
417 }
418 
419 /* -- see zlib.h -- */
420 z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
421 {
422  z_off64_t ret;
423 
424  ret = gzseek64(file, (z_off64_t)offset, whence);
425  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
426 }
427 
428 /* -- see zlib.h -- */
429 z_off64_t ZEXPORT gztell64(gzFile file)
430 {
431  gz_statep state;
432 
433  /* get internal structure and check integrity */
434  if (file == NULL)
435  return -1;
436  state = (gz_statep)file;
437  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
438  return -1;
439 
440  /* return position */
441  return state->x.pos + (state->seek ? state->skip : 0);
442 }
443 
444 /* -- see zlib.h -- */
445 z_off_t ZEXPORT gztell(gzFile file)
446 {
447  z_off64_t ret;
448 
449  ret = gztell64(file);
450  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
451 }
452 
453 /* -- see zlib.h -- */
454 z_off64_t ZEXPORT gzoffset64(gzFile file)
455 {
456  z_off64_t offset;
457  gz_statep state;
458 
459  /* get internal structure and check integrity */
460  if (file == NULL)
461  return -1;
462  state = (gz_statep)file;
463  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
464  return -1;
465 
466  /* compute and return effective offset in file */
467  offset = LSEEK(state->fd, 0, SEEK_CUR);
468  if (offset == -1)
469  return -1;
470  if (state->mode == GZ_READ) /* reading */
471  offset -= state->strm.avail_in; /* don't count buffered input */
472  return offset;
473 }
474 
475 /* -- see zlib.h -- */
476 z_off_t ZEXPORT gzoffset(gzFile file)
477 {
478  z_off64_t ret;
479 
480  ret = gzoffset64(file);
481  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
482 }
483 
484 /* -- see zlib.h -- */
485 int ZEXPORT gzeof(gzFile file)
486 {
487  gz_statep state;
488 
489  /* get internal structure and check integrity */
490  if (file == NULL)
491  return 0;
492  state = (gz_statep)file;
493  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
494  return 0;
495 
496  /* return end-of-file state */
497  return state->mode == GZ_READ ? state->past : 0;
498 }
499 
500 /* -- see zlib.h -- */
501 const char * ZEXPORT gzerror(gzFile file, int *errnum)
502 {
503  gz_statep state;
504 
505  /* get internal structure and check integrity */
506  if (file == NULL)
507  return NULL;
508  state = (gz_statep)file;
509  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
510  return NULL;
511 
512  /* return error information */
513  if (errnum != NULL)
514  *errnum = state->err;
515  return state->err == Z_MEM_ERROR ? "out of memory" :
516  (state->msg == NULL ? "" : state->msg);
517 }
518 
519 /* -- see zlib.h -- */
520 void ZEXPORT gzclearerr(gzFile file)
521 {
522  gz_statep state;
523 
524  /* get internal structure and check integrity */
525  if (file == NULL)
526  return;
527  state = (gz_statep)file;
528  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
529  return;
530 
531  /* clear error and end-of-file */
532  if (state->mode == GZ_READ) {
533  state->eof = 0;
534  state->past = 0;
535  }
536  gz_error(state, Z_OK, NULL);
537 }
538 
539 /* Create an error message in allocated memory and set state->err and
540  state->msg accordingly. Free any previous error message already there. Do
541  not try to free or allocate space if the error is Z_MEM_ERROR (out of
542  memory). Simply save the error message as a static string. If there is an
543  allocation failure constructing the error message, then convert the error to
544  out of memory. */
545 void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
546 {
547  /* free previously allocated message and clear */
548  if (state->msg != NULL) {
549  if (state->err != Z_MEM_ERROR)
550  free(state->msg);
551  state->msg = NULL;
552  }
553 
554  /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
555  if (err != Z_OK && err != Z_BUF_ERROR)
556  state->x.have = 0;
557 
558  /* set error code, and if no message, then done */
559  state->err = err;
560  if (msg == NULL)
561  return;
562 
563  /* for an out of memory error, return literal string when requested */
564  if (err == Z_MEM_ERROR)
565  return;
566 
567  /* construct error message with path */
568  if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
569  NULL) {
570  state->err = Z_MEM_ERROR;
571  return;
572  }
573 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
574  snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
575  "%s%s%s", state->path, ": ", msg);
576 #else
577  strcpy(state->msg, state->path);
578  strcat(state->msg, ": ");
579  strcat(state->msg, msg);
580 #endif
581  return;
582 }
583 
584 #ifndef INT_MAX
585 /* portably return maximum value for an int (when limits.h presumed not
586  available) -- we need to do this to cover cases where 2's complement not
587  used, since C standard permits 1's complement and sign-bit representations,
588  otherwise we could just use ((unsigned)-1) >> 1 */
590 {
591  unsigned p, q;
592 
593  p = 1;
594  do {
595  q = p;
596  p <<= 1;
597  p++;
598  } while (p > q);
599  return q >> 1;
600 }
601 #endif
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
Definition: gzlib.cc:545
z_off_t ZEXPORT gzoffset(gzFile file)
Definition: gzlib.cc:476
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
Definition: gzlib.cc:420
#define ZLIB_INTERNAL
Definition: compress.cc:8
void ZEXPORT gzclearerr(gzFile file)
Definition: gzlib.cc:520
z_off64_t ZEXPORT gzoffset64(gzFile file)
Definition: gzlib.cc:454
const char *ZEXPORT gzerror(gzFile file, int *errnum)
Definition: gzlib.cc:501
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
Definition: gzlib.cc:346
local gzFile gz_open(const void *path, int fd, const char *mode)
Definition: gzlib.cc:89
int ZEXPORT gzeof(gzFile file)
Definition: gzlib.cc:485
gzFile ZEXPORT gzopen64(const char *path, const char *mode)
Definition: gzlib.cc:269
#define local
Definition: adler32.cc:10
z_off_t ZEXPORT gztell(gzFile file)
Definition: gzlib.cc:445
unsigned ZLIB_INTERNAL gz_intmax()
Definition: gzlib.cc:589
local void gz_reset(gz_statep state)
Definition: gzlib.cc:74
z_off64_t ZEXPORT gztell64(gzFile file)
Definition: gzlib.cc:429
gzFile ZEXPORT gzopen(const char *path, const char *mode)
Definition: gzlib.cc:263
const G4int n
int ZEXPORT gzrewind(gzFile file)
Definition: gzlib.cc:324
int ZEXPORT gzbuffer(gzFile file, unsigned size)
Definition: gzlib.cc:301
gzFile ZEXPORT gzdopen(int fd, const char *mode)
Definition: gzlib.cc:275
#define LSEEK
Definition: gzlib.cc:14
static PROLOG_HANDLER error
Definition: xmlrole.cc:112
local void gz_reset OF((gz_statep))