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