Biomedical Image Analysis Library
The Biomedical Image Analysis Library is a poweful tool for developers, physicians, researchers, engineers, and so on.
gzlib.c
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 (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 */
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 {
97  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 _WIN32
192  if (fd == -2) {
193  len = wcstombs(NULL, path, 0);
194  if (len == (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 _WIN32
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  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 _WIN32
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  state->mode = GZ_WRITE; /* simplify later checks */
253 
254  /* save the current position for rewinding (only if reading) */
255  if (state->mode == GZ_READ) {
256  state->start = LSEEK(state->fd, 0, SEEK_CUR);
257  if (state->start == -1) state->start = 0;
258  }
259 
260  /* initialize stream */
261  gz_reset(state);
262 
263  /* return stream */
264  return (gzFile)state;
265 }
266 
267 /* -- see zlib.h -- */
268 gzFile ZEXPORT gzopen(path, mode)
269  const char *path;
270  const char *mode;
271 {
272  return gz_open(path, -1, mode);
273 }
274 
275 /* -- see zlib.h -- */
276 gzFile ZEXPORT gzopen64(path, mode)
277  const char *path;
278  const char *mode;
279 {
280  return gz_open(path, -1, mode);
281 }
282 
283 /* -- see zlib.h -- */
284 gzFile ZEXPORT gzdopen(fd, mode)
285  int fd;
286  const char *mode;
287 {
288  char *path; /* identifier for error messages */
289  gzFile gz;
290 
291  if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
292  return NULL;
293 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
294  snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
295 #else
296  sprintf(path, "<fd:%d>", fd); /* for debugging */
297 #endif
298  gz = gz_open(path, fd, mode);
299  free(path);
300  return gz;
301 }
302 
303 /* -- see zlib.h -- */
304 #ifdef _WIN32
305 gzFile ZEXPORT gzopen_w(path, mode)
306  const wchar_t *path;
307  const char *mode;
308 {
309  return gz_open(path, -2, mode);
310 }
311 #endif
312 
313 /* -- see zlib.h -- */
315  gzFile file;
316  unsigned size;
317 {
319 
320  /* get internal structure and check integrity */
321  if (file == NULL)
322  return -1;
323  state = (gz_statep)file;
324  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
325  return -1;
326 
327  /* make sure we haven't already allocated memory */
328  if (state->size != 0)
329  return -1;
330 
331  /* check and set requested size */
332  if (size < 2)
333  size = 2; /* need two bytes to check magic header */
334  state->want = size;
335  return 0;
336 }
337 
338 /* -- see zlib.h -- */
340  gzFile file;
341 {
343 
344  /* get internal structure */
345  if (file == NULL)
346  return -1;
347  state = (gz_statep)file;
348 
349  /* check that we're reading and that there's no error */
350  if (state->mode != GZ_READ ||
351  (state->err != Z_OK && state->err != Z_BUF_ERROR))
352  return -1;
353 
354  /* back up and start over */
355  if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
356  return -1;
357  gz_reset(state);
358  return 0;
359 }
360 
361 /* -- see zlib.h -- */
362 z_off64_t ZEXPORT gzseek64(file, offset, whence)
363  gzFile file;
364  z_off64_t offset;
365  int whence;
366 {
367  unsigned n;
368  z_off64_t ret;
370 
371  /* get internal structure and check integrity */
372  if (file == NULL)
373  return -1;
374  state = (gz_statep)file;
375  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
376  return -1;
377 
378  /* check that there's no error */
379  if (state->err != Z_OK && state->err != Z_BUF_ERROR)
380  return -1;
381 
382  /* can only seek from start or relative to current position */
383  if (whence != SEEK_SET && whence != SEEK_CUR)
384  return -1;
385 
386  /* normalize offset to a SEEK_CUR specification */
387  if (whence == SEEK_SET)
388  offset -= state->x.pos;
389  else if (state->seek)
390  offset += state->skip;
391  state->seek = 0;
392 
393  /* if within raw area while reading, just go there */
394  if (state->mode == GZ_READ && state->how == COPY &&
395  state->x.pos + offset >= 0) {
396  ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
397  if (ret == -1)
398  return -1;
399  state->x.have = 0;
400  state->eof = 0;
401  state->past = 0;
402  state->seek = 0;
403  gz_error(state, Z_OK, NULL);
404  state->strm.avail_in = 0;
405  state->x.pos += offset;
406  return state->x.pos;
407  }
408 
409  /* calculate skip amount, rewinding if needed for back seek when reading */
410  if (offset < 0) {
411  if (state->mode != GZ_READ) /* writing -- can't go backwards */
412  return -1;
413  offset += state->x.pos;
414  if (offset < 0) /* before start of file! */
415  return -1;
416  if (gzrewind(file) == -1) /* rewind, then skip to offset */
417  return -1;
418  }
419 
420  /* if reading, skip what's in output buffer (one less gzgetc() check) */
421  if (state->mode == GZ_READ) {
422  n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
423  (unsigned)offset : state->x.have;
424  state->x.have -= n;
425  state->x.next += n;
426  state->x.pos += n;
427  offset -= n;
428  }
429 
430  /* request skip (if not zero) */
431  if (offset) {
432  state->seek = 1;
433  state->skip = offset;
434  }
435  return state->x.pos + offset;
436 }
437 
438 /* -- see zlib.h -- */
439 z_off_t ZEXPORT gzseek(file, offset, whence)
440  gzFile file;
441  z_off_t offset;
442  int whence;
443 {
444  z_off64_t ret;
445 
446  ret = gzseek64(file, (z_off64_t)offset, whence);
447  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
448 }
449 
450 /* -- see zlib.h -- */
452  gzFile file;
453 {
455 
456  /* get internal structure and check integrity */
457  if (file == NULL)
458  return -1;
459  state = (gz_statep)file;
460  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
461  return -1;
462 
463  /* return position */
464  return state->x.pos + (state->seek ? state->skip : 0);
465 }
466 
467 /* -- see zlib.h -- */
469  gzFile file;
470 {
471  z_off64_t ret;
472 
473  ret = gztell64(file);
474  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
475 }
476 
477 /* -- see zlib.h -- */
479  gzFile file;
480 {
481  z_off64_t offset;
483 
484  /* get internal structure and check integrity */
485  if (file == NULL)
486  return -1;
487  state = (gz_statep)file;
488  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
489  return -1;
490 
491  /* compute and return effective offset in file */
492  offset = LSEEK(state->fd, 0, SEEK_CUR);
493  if (offset == -1)
494  return -1;
495  if (state->mode == GZ_READ) /* reading */
496  offset -= state->strm.avail_in; /* don't count buffered input */
497  return offset;
498 }
499 
500 /* -- see zlib.h -- */
502  gzFile file;
503 {
504  z_off64_t ret;
505 
506  ret = gzoffset64(file);
507  return ret == (z_off_t)ret ? (z_off_t)ret : -1;
508 }
509 
510 /* -- see zlib.h -- */
512  gzFile file;
513 {
515 
516  /* get internal structure and check integrity */
517  if (file == NULL)
518  return 0;
519  state = (gz_statep)file;
520  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
521  return 0;
522 
523  /* return end-of-file state */
524  return state->mode == GZ_READ ? state->past : 0;
525 }
526 
527 /* -- see zlib.h -- */
528 const char * ZEXPORT gzerror(file, errnum)
529  gzFile file;
530  int *errnum;
531 {
533 
534  /* get internal structure and check integrity */
535  if (file == NULL)
536  return NULL;
537  state = (gz_statep)file;
538  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
539  return NULL;
540 
541  /* return error information */
542  if (errnum != NULL)
543  *errnum = state->err;
544  return state->err == Z_MEM_ERROR ? "out of memory" :
545  (state->msg == NULL ? "" : state->msg);
546 }
547 
548 /* -- see zlib.h -- */
550  gzFile file;
551 {
553 
554  /* get internal structure and check integrity */
555  if (file == NULL)
556  return;
557  state = (gz_statep)file;
558  if (state->mode != GZ_READ && state->mode != GZ_WRITE)
559  return;
560 
561  /* clear error and end-of-file */
562  if (state->mode == GZ_READ) {
563  state->eof = 0;
564  state->past = 0;
565  }
566  gz_error(state, Z_OK, NULL);
567 }
568 
569 /* Create an error message in allocated memory and set state->err and
570  state->msg accordingly. Free any previous error message already there. Do
571  not try to free or allocate space if the error is Z_MEM_ERROR (out of
572  memory). Simply save the error message as a static string. If there is an
573  allocation failure constructing the error message, then convert the error to
574  out of memory. */
575 void ZLIB_INTERNAL gz_error(state, err, msg)
577  int err;
578  const char *msg;
579 {
580  /* free previously allocated message and clear */
581  if (state->msg != NULL) {
582  if (state->err != Z_MEM_ERROR)
583  free(state->msg);
584  state->msg = NULL;
585  }
586 
587  /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
588  if (err != Z_OK && err != Z_BUF_ERROR)
589  state->x.have = 0;
590 
591  /* set error code, and if no message, then done */
592  state->err = err;
593  if (msg == NULL)
594  return;
595 
596  /* for an out of memory error, return literal string when requested */
597  if (err == Z_MEM_ERROR)
598  return;
599 
600  /* construct error message with path */
601  if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
602  NULL) {
603  state->err = Z_MEM_ERROR;
604  return;
605  }
606 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
607  snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
608  "%s%s%s", state->path, ": ", msg);
609 #else
610  strcpy(state->msg, state->path);
611  strcat(state->msg, ": ");
612  strcat(state->msg, msg);
613 #endif
614  return;
615 }
616 
617 #ifndef INT_MAX
618 /* portably return maximum value for an int (when limits.h presumed not
619  available) -- we need to do this to cover cases where 2's complement not
620  used, since C standard permits 1's complement and sign-bit representations,
621  otherwise we could just use ((unsigned)-1) >> 1 */
623 {
624  unsigned p, q;
625 
626  p = 1;
627  do {
628  q = p;
629  p <<= 1;
630  p++;
631  } while (p > q);
632  return q >> 1;
633 }
634 #endif
#define OF(args)
Definition: zconf.h:269
Definition: inflate.h:36
int err
Definition: gzguts.h:189
unsigned want
Definition: gzguts.h:173
static gzFile gz_open()
#define GZ_NONE
Definition: gzguts.h:151
long gzseek(gzFile file, long offset, int whence)
Definition: gzlib.c:439
Definition: blast.c:37
long gzoffset(gzFile file)
Definition: gzlib.c:501
#define z_off_t
Definition: zconf.h:481
int gzbuffer(gzFile file, unsigned size)
Definition: gzlib.c:314
#define GT_OFF(x)
Definition: gzguts.h:209
#define GZ_APPEND
Definition: gzguts.h:154
#define GZ_READ
Definition: gzguts.h:152
int past
Definition: gzguts.h:181
gzFile gzopen(char *path, char *mode)
Definition: gzlib.c:268
#define z_off64_t
Definition: zconf.h:490
int mode
Definition: gzguts.h:169
long gzseek64(gzFile file, long offset, int whence)
Definition: gzlib.c:362
void gzclearerr(gzFile file)
Definition: gzlib.c:549
#define ZLIB_INTERNAL
Definition: compress.c:8
#define Z_FILTERED
Definition: zlib.h:192
int how
Definition: gzguts.h:178
void free()
unsigned have
Definition: zlib.h:1671
int fd
Definition: gzguts.h:170
static size_t size
Definition: enough.c:173
#define Z_FIXED
Definition: zlib.h:195
char * msg
Definition: gzguts.h:190
gzFile gzopen64(char *path, char *mode)
Definition: gzlib.c:276
long skip
Definition: gzguts.h:186
z_stream strm
Definition: gzguts.h:192
int level
Definition: gzguts.h:183
char * path
Definition: gzguts.h:171
long gztell64(gzFile file)
Definition: gzlib.c:451
void error(const char *msg)
Definition: untgz.c:593
#define GZ_WRITE
Definition: gzguts.h:153
#define LSEEK
Definition: gzlib.c:14
void gz_error(gz_statep state, int err, char *msg)
Definition: gzlib.c:575
static void gz_reset()
#define SEEK_CUR
Definition: zip.c:80
#define local
Definition: adler32.c:10
int gzeof(gzFile file)
Definition: gzlib.c:511
gzFile gzdopen(int fd, char *mode)
Definition: gzlib.c:284
#define Z_MEM_ERROR
Definition: zlib.h:179
struct gzFile_s x
Definition: gzguts.h:164
int gzrewind(gzFile file)
Definition: gzlib.c:339
#define SEEK_SET
Definition: zip.c:88
#define Z_HUFFMAN_ONLY
Definition: zlib.h:193
long start
Definition: gzguts.h:179
#define LOOK
Definition: gzguts.h:157
#define GZBUFSIZE
Definition: gzguts.h:148
gz_state * gz_statep
Definition: gzguts.h:194
#define Z_BUF_ERROR
Definition: zlib.h:180
#define Z_OK
Definition: zlib.h:173
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:196
#define const
Definition: zconf.h:217
uInt avail_in
Definition: zlib.h:87
int seek
Definition: gzguts.h:187
long gztell(gzFile file)
Definition: gzlib.c:468
int direct
Definition: gzguts.h:176
unsigned size
Definition: gzguts.h:172
Definition: gzappend.c:170
char * gzerror(gzFile file, int *errnum)
Definition: gzlib.c:528
#define ZEXPORT
Definition: zconf.h:357
long pos
Definition: zlib.h:1673
int eof
Definition: gzguts.h:180
unsigned char * next
Definition: zlib.h:1672
voidp malloc()
unsigned gz_intmax()
Definition: gzlib.c:622
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:189
long gzoffset64(gzFile file)
Definition: gzlib.c:478
int strategy
Definition: gzguts.h:184
#define Z_RLE
Definition: zlib.h:194