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