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