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