Geant4  10.01.p03
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 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  case 'T':
161  state->direct = 1;
162  default: /* could consider as an error, but just ignore */
163  ;
164  }
165  mode++;
166  }
167 
168  /* must provide an "r", "w", or "a" */
169  if (state->mode == GZ_NONE) {
170  free(state);
171  return NULL;
172  }
173 
174  /* can't force transparent read */
175  if (state->mode == GZ_READ) {
176  if (state->direct) {
177  free(state);
178  return NULL;
179  }
180  state->direct = 1; /* for empty file */
181  }
182 
183  /* save the path name for error messages */
184 #ifdef _WIN32
185  if (fd == -2) {
186  len = wcstombs(NULL, (const wchar_t *)path, 0);
187  if (len == (size_t)-1)
188  len = 0;
189  }
190  else
191 #endif
192  len = strlen((const char *)path);
193  state->path = (char*)malloc(len + 1);
194  if (state->path == NULL) {
195  free(state);
196  return NULL;
197  }
198 #ifdef _WIN32
199  if (fd == -2)
200  if (len)
201  wcstombs(state->path, (const wchar_t *)path, len + 1);
202  else
203  *(state->path) = 0;
204  else
205 #endif
206  strcpy(state->path, (const char *)path);
207 
208  /* compute the flags for open() */
209  oflag =
210 #ifdef O_LARGEFILE
211  O_LARGEFILE |
212 #endif
213 #ifdef O_BINARY
214  O_BINARY |
215 #endif
216 #ifdef O_CLOEXEC
217  (cloexec ? O_CLOEXEC : 0) |
218 #endif
219  (state->mode == GZ_READ ?
220  O_RDONLY :
221  (O_WRONLY | O_CREAT |
222 #ifdef O_EXCL
223  (exclusive ? O_EXCL : 0) |
224 #endif
225  (state->mode == GZ_WRITE ?
226  O_TRUNC :
227  O_APPEND)));
228 
229  /* open the file with the appropriate flags (or just use fd) */
230  state->fd = fd > -1 ? fd : (
231 #ifdef _WIN32
232  fd == -2 ? _wopen((const wchar_t *)path, oflag, 0666) :
233 #endif
234  open((const char *)path, oflag, 0666));
235  if (state->fd == -1) {
236  free(state->path);
237  free(state);
238  return NULL;
239  }
240  if (state->mode == GZ_APPEND)
241  state->mode = GZ_WRITE; /* simplify later checks */
242 
243  /* save the current position for rewinding (only if reading) */
244  if (state->mode == GZ_READ) {
245  state->start = LSEEK(state->fd, 0, SEEK_CUR);
246  if (state->start == -1) state->start = 0;
247  }
248 
249  /* initialize stream */
250  gz_reset(state);
251 
252  /* return stream */
253  return (gzFile)state;
254 }
255 
256 /* -- see zlib.h -- */
257 gzFile ZEXPORT gzopen(const char *path,const char * mode)
258 {
259  return gz_open(path, -1, mode);
260 }
261 
262 /* -- see zlib.h -- */
263 gzFile ZEXPORT gzopen64(const char *path,const char * mode)
264 {
265  return gz_open(path, -1, mode);
266 }
267 
268 /* -- see zlib.h -- */
269 gzFile ZEXPORT gzdopen(int fd, const char *mode)
270 {
271  char *path; /* identifier for error messages */
272  gzFile gz;
273 
274  if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
275  return NULL;
276  sprintf(path, "<fd:%d>", fd); /* for debugging */
277  gz = gz_open(path, fd, mode);
278  free(path);
279  return gz;
280 }
281 
282 /* -- see zlib.h -- */
283 #ifdef _WIN32
284 gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode)
285 {
286  return gz_open(path, -2, mode);
287 }
288 #endif
289 
290 /* -- see zlib.h -- */
291 int ZEXPORT gzbuffer(gzFile file, unsigned size)
292 {
293  gz_statep state;
294 
295  /* get internal structure and check integrity */
296  if (file == NULL)
297  return -1;
298  state = (gz_statep)file;
299  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
300  return -1;
301 
302  /* make sure we haven't already allocated memory */
303  if (state->size != 0)
304  return -1;
305 
306  /* check and set requested size */
307  if (size < 2)
308  size = 2; /* need two bytes to check magic header */
309  state->want = size;
310  return 0;
311 }
312 
313 /* -- see zlib.h -- */
314 int ZEXPORT gzrewind(gzFile file)
315 {
316  gz_statep state;
317 
318  /* get internal structure */
319  if (file == NULL)
320  return -1;
321  state = (gz_statep)file;
322 
323  /* check that we're reading and that there's no error */
324  if (state->mode != GZ_READ ||
325  (state->err != Z_OK && state->err != Z_BUF_ERROR))
326  return -1;
327 
328  /* back up and start over */
329  if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
330  return -1;
331  gz_reset(state);
332  return 0;
333 }
334 
335 /* -- see zlib.h -- */
336 z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
337 {
338  unsigned n;
339  z_off64_t ret;
340  gz_statep state;
341 
342  /* get internal structure and check integrity */
343  if (file == NULL)
344  return -1;
345  state = (gz_statep)file;
346  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
347  return -1;
348 
349  /* check that there's no error */
350  if (state->err != Z_OK && state->err != Z_BUF_ERROR)
351  return -1;
352 
353  /* can only seek from start or relative to current position */
354  if (whence != SEEK_SET && whence != SEEK_CUR)
355  return -1;
356 
357  /* normalize offset to a SEEK_CUR specification */
358  if (whence == SEEK_SET)
359  offset -= state->x.pos;
360  else if (state->seek)
361  offset += state->skip;
362  state->seek = 0;
363 
364  /* if within raw area while reading, just go there */
365  if (state->mode == GZ_READ && state->how == COPY &&
366  state->x.pos + offset >= 0) {
367  ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
368  if (ret == -1)
369  return -1;
370  state->x.have = 0;
371  state->eof = 0;
372  state->past = 0;
373  state->seek = 0;
374  gz_error(state, Z_OK, NULL);
375  state->strm.avail_in = 0;
376  state->x.pos += offset;
377  return state->x.pos;
378  }
379 
380  /* calculate skip amount, rewinding if needed for back seek when reading */
381  if (offset < 0) {
382  if (state->mode != GZ_READ) /* writing -- can't go backwards */
383  return -1;
384  offset += state->x.pos;
385  if (offset < 0) /* before start of file! */
386  return -1;
387  if (gzrewind(file) == -1) /* rewind, then skip to offset */
388  return -1;
389  }
390 
391  /* if reading, skip what's in output buffer (one less gzgetc() check) */
392  if (state->mode == GZ_READ) {
393  n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
394  (unsigned)offset : state->x.have;
395  state->x.have -= n;
396  state->x.next += n;
397  state->x.pos += n;
398  offset -= n;
399  }
400 
401  /* request skip (if not zero) */
402  if (offset) {
403  state->seek = 1;
404  state->skip = offset;
405  }
406  return state->x.pos + offset;
407 }
408 
409 /* -- see zlib.h -- */
410 z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
411 {
412  z_off64_t ret;
413 
414  ret = gzseek64(file, (z_off64_t)offset, whence);
415  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
416 }
417 
418 /* -- see zlib.h -- */
419 z_off64_t ZEXPORT gztell64(gzFile file)
420 {
421  gz_statep state;
422 
423  /* get internal structure and check integrity */
424  if (file == NULL)
425  return -1;
426  state = (gz_statep)file;
427  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
428  return -1;
429 
430  /* return position */
431  return state->x.pos + (state->seek ? state->skip : 0);
432 }
433 
434 /* -- see zlib.h -- */
435 z_off_t ZEXPORT gztell(gzFile file)
436 {
437  z_off64_t ret;
438 
439  ret = gztell64(file);
440  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
441 }
442 
443 /* -- see zlib.h -- */
444 z_off64_t ZEXPORT gzoffset64(gzFile file)
445 {
446  z_off64_t offset;
447  gz_statep state;
448 
449  /* get internal structure and check integrity */
450  if (file == NULL)
451  return -1;
452  state = (gz_statep)file;
453  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
454  return -1;
455 
456  /* compute and return effective offset in file */
457  offset = LSEEK(state->fd, 0, SEEK_CUR);
458  if (offset == -1)
459  return -1;
460  if (state->mode == GZ_READ) /* reading */
461  offset -= state->strm.avail_in; /* don't count buffered input */
462  return offset;
463 }
464 
465 /* -- see zlib.h -- */
466 z_off_t ZEXPORT gzoffset(gzFile file)
467 {
468  z_off64_t ret;
469 
470  ret = gzoffset64(file);
471  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
472 }
473 
474 /* -- see zlib.h -- */
475 int ZEXPORT gzeof(gzFile file)
476 {
477  gz_statep state;
478 
479  /* get internal structure and check integrity */
480  if (file == NULL)
481  return 0;
482  state = (gz_statep)file;
483  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
484  return 0;
485 
486  /* return end-of-file state */
487  return state->mode == GZ_READ ? state->past : 0;
488 }
489 
490 /* -- see zlib.h -- */
491 const char * ZEXPORT gzerror(gzFile file, int *errnum)
492 {
493  gz_statep state;
494 
495  /* get internal structure and check integrity */
496  if (file == NULL)
497  return NULL;
498  state = (gz_statep)file;
499  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
500  return NULL;
501 
502  /* return error information */
503  if (errnum != NULL)
504  *errnum = state->err;
505  return state->msg == NULL ? "" : state->msg;
506 }
507 
508 /* -- see zlib.h -- */
509 void ZEXPORT gzclearerr(gzFile file)
510 {
511  gz_statep state;
512 
513  /* get internal structure and check integrity */
514  if (file == NULL)
515  return;
516  state = (gz_statep)file;
517  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
518  return;
519 
520  /* clear error and end-of-file */
521  if (state->mode == GZ_READ) {
522  state->eof = 0;
523  state->past = 0;
524  }
525  gz_error(state, Z_OK, NULL);
526 }
527 
528 /* Create an error message in allocated memory and set state->err and
529  state->msg accordingly. Free any previous error message already there. Do
530  not try to free or allocate space if the error is Z_MEM_ERROR (out of
531  memory). Simply save the error message as a static string. If there is an
532  allocation failure constructing the error message, then convert the error to
533  out of memory. */
534 void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
535 {
536  /* free previously allocated message and clear */
537  if (state->msg != NULL) {
538  if (state->err != Z_MEM_ERROR)
539  free(state->msg);
540  state->msg = NULL;
541  }
542 
543  /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
544  if (err != Z_OK && err != Z_BUF_ERROR)
545  state->x.have = 0;
546 
547  /* set error code, and if no message, then done */
548  state->err = err;
549  if (msg == NULL)
550  return;
551 
552  /* for an out of memory error, save as static string */
553  if (err == Z_MEM_ERROR) {
554  state->msg = (char *)msg;
555  return;
556  }
557 
558  /* construct error message with path */
559  if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
560  state->err = Z_MEM_ERROR;
561  state->msg = (char *)"out of memory";
562  return;
563  }
564  strcpy(state->msg, state->path);
565  strcat(state->msg, ": ");
566  strcat(state->msg, msg);
567  return;
568 }
569 
570 #ifndef INT_MAX
571 /* portably return maximum value for an int (when limits.h presumed not
572  available) -- we need to do this to cover cases where 2's complement not
573  used, since C standard permits 1's complement and sign-bit representations,
574  otherwise we could just use ((unsigned)-1) >> 1 */
576 {
577  unsigned p, q;
578 
579  p = 1;
580  do {
581  q = p;
582  p <<= 1;
583  p++;
584  } while (p > q);
585  return q >> 1;
586 }
587 #endif
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
Definition: gzlib.cc:534
z_off_t ZEXPORT gzoffset(gzFile file)
Definition: gzlib.cc:466
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
Definition: gzlib.cc:410
#define ZLIB_INTERNAL
Definition: compress.cc:8
void ZEXPORT gzclearerr(gzFile file)
Definition: gzlib.cc:509
z_off64_t ZEXPORT gzoffset64(gzFile file)
Definition: gzlib.cc:444
const char *ZEXPORT gzerror(gzFile file, int *errnum)
Definition: gzlib.cc:491
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
Definition: gzlib.cc:336
local gzFile gz_open(const void *path, int fd, const char *mode)
Definition: gzlib.cc:89
int ZEXPORT gzeof(gzFile file)
Definition: gzlib.cc:475
gzFile ZEXPORT gzopen64(const char *path, const char *mode)
Definition: gzlib.cc:263
#define local
Definition: adler32.cc:10
z_off_t ZEXPORT gztell(gzFile file)
Definition: gzlib.cc:435
unsigned ZLIB_INTERNAL gz_intmax()
Definition: gzlib.cc:575
local void gz_reset(gz_statep state)
Definition: gzlib.cc:74
z_off64_t ZEXPORT gztell64(gzFile file)
Definition: gzlib.cc:419
gzFile ZEXPORT gzopen(const char *path, const char *mode)
Definition: gzlib.cc:257
const G4int n
int ZEXPORT gzrewind(gzFile file)
Definition: gzlib.cc:314
int ZEXPORT gzbuffer(gzFile file, unsigned size)
Definition: gzlib.cc:291
gzFile ZEXPORT gzdopen(int fd, const char *mode)
Definition: gzlib.cc:269
#define LSEEK
Definition: gzlib.cc:14
static PROLOG_HANDLER error
Definition: xmlrole.cc:108
local void gz_reset OF((gz_statep))