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