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