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