ReactOS  0.4.14-dev-297-g23e575c
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-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();
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. */
92  const void *path;
93  int fd;
94  const char *mode;
95 {
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 -- */
271  const char *path;
272  const char *mode;
273 {
274  return gz_open(path, -1, mode);
275 }
276 
277 /* -- see zlib.h -- */
279  const char *path;
280  const char *mode;
281 {
282  return gz_open(path, -1, mode);
283 }
284 
285 /* -- see zlib.h -- */
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 -- */
317  gzFile file;
318  unsigned size;
319 {
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 -- */
344  gzFile file;
345 {
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 -- */
367  gzFile file;
369  int whence;
370 {
371  unsigned n;
372  z_off64_t ret;
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 -- */
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 -- */
456  gzFile file;
457 {
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 -- */
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 -- */
483  gzFile file;
484 {
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 -- */
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 -- */
516  gzFile file;
517 {
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 {
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 -- */
554  gzFile file;
555 {
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. */
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
unsigned long z_size_t
Definition: zconf.h:250
#define SEEK_CUR
Definition: util.h:63
#define Z_HUFFMAN_ONLY
Definition: zlib.h:197
_CRTIMP int __cdecl _wopen(const wchar_t *_Filename, int _OpenFlag,...)
Definition: file.c:2020
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define COPY(len)
Definition: rtl.c:274
#define error(str)
Definition: mkdosfs.c:1605
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define open
Definition: acwin.h:95
#define GZ_NONE
Definition: gzguts.h:159
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLsizei const GLchar ** path
Definition: glext.h:7234
#define free
Definition: debug_ros.c:5
int ZEXPORT gzeof(gzFile file)
Definition: gzlib.c:515
#define z_off_t
Definition: zconf.h:504
GLintptr offset
Definition: glext.h:5920
#define GT_OFF(x)
Definition: gzguts.h:217
z_off64_t ZEXPORT gzoffset64(gzFile file)
Definition: gzlib.c:482
#define GZ_APPEND
Definition: gzguts.h:162
GLdouble n
Definition: glext.h:7729
#define GZ_READ
Definition: gzguts.h:160
#define snprintf
Definition: wintirpc.h:48
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define z_off64_t
Definition: zconf.h:513
static int fd
Definition: io.c:51
z_off_t ZEXPORT gztell(gzFile file)
Definition: gzlib.c:472
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:200
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define Z_BUF_ERROR
Definition: zlib.h:184
int ZEXPORT gzrewind(gzFile file)
Definition: gzlib.c:343
z_off64_t ZEXPORT gztell64(gzFile file)
Definition: gzlib.c:455
#define O_WRONLY
Definition: acwin.h:111
#define Z_OK
Definition: zlib.h:177
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
Definition: gzlib.c:443
gzFile gz_open(void *path, int fd, const char *mode) const
Definition: gzlib.c:91
smooth NULL
Definition: ftsmooth.c:416
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:193
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
#define O_EXCL
Definition: fcntl.h:40
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
Definition: gzlib.c:579
#define SEEK_SET
Definition: jmemansi.c:26
int ZEXPORT gzbuffer(gzFile file, unsigned size)
Definition: gzlib.c:316
#define GZ_WRITE
Definition: gzguts.h:161
GLsizeiptr size
Definition: glext.h:5919
#define LSEEK
Definition: gzlib.c:14
gzFile ZEXPORT gzdopen(int fd, const char *mode)
Definition: gzlib.c:286
#define Z_FILTERED
Definition: zlib.h:196
#define O_LARGEFILE
Definition: port.h:154
const char file[]
Definition: icontest.c:11
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
#define FormatMessage
Definition: winbase.h:3619
int ret
static int state
Definition: maze.c:121
GLenum GLsizei len
Definition: glext.h:6722
#define O_TRUNC
Definition: acwin.h:112
#define err(...)
z_off_t ZEXPORT gzoffset(gzFile file)
Definition: gzlib.c:505
GLenum mode
Definition: glext.h:6217
#define local
Definition: zutil.h:30
const char *ZEXPORT gzerror(gzFile file, int *errnum)
Definition: gzlib.c:532
#define LOOK
Definition: gzguts.h:165
#define GZBUFSIZE
Definition: gzguts.h:156
void ZEXPORT gzclearerr(gzFile file)
Definition: gzlib.c:553
gzFile ZEXPORT gzopen64(char *path, const char *mode) const
Definition: gzlib.c:278
#define ZLIB_INTERNAL
Definition: compress.c:32
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define O_BINARY
Definition: acwin.h:109
Definition: services.c:325
gzFile ZEXPORT gzopen(char *path, const char *mode) const
Definition: gzlib.c:270
#define msg(x)
Definition: auth_time.c:54
gz_state FAR * gz_statep
Definition: gzguts.h:202
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define SEEK_END
Definition: cabinet.c:27
#define Z_FIXED
Definition: zlib.h:199
#define malloc
Definition: debug_ros.c:4
unsigned ZLIB_INTERNAL gz_intmax()
Definition: gzlib.c:625
GLfloat GLfloat p
Definition: glext.h:8902
#define Z_RLE
Definition: zlib.h:198
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
Definition: gzlib.c:366
size_t __cdecl wcstombs(_Out_writes_opt_z_(_MaxCount) char *_Dest, _In_z_ const wchar_t *_Source, _In_ size_t _MaxCount)
#define ZEXPORT
Definition: zconf.h:380
#define O_CREAT
Definition: acwin.h:110
#define Z_MEM_ERROR
Definition: zlib.h:183
void gz_reset OF((gz_statep))
void gz_reset(gz_statep state)
Definition: gzlib.c:75
#define O_APPEND
Definition: fcntl.h:37
#define O_RDONLY
Definition: acwin.h:108
Definition: fci.c:126