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