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