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