1 /*
2    Based on gzio.c from zlib 1.2.3, but considerably modified!
3 
4    Copyright (C) 1995-2005 Jean-loup Gailly.
5    For conditions of distribution and use, see copyright notice in zlib.h:
6 
7   This software is provided 'as-is', without any express or implied
8   warranty.  In no event will the authors be held liable for any damages
9   arising from the use of this software.
10 
11   Permission is granted to anyone to use this software for any purpose,
12   including commercial applications, and to alter it and redistribute it
13   freely, subject to the following restrictions:
14 
15   1. The origin of this software must not be misrepresented; you must not
16      claim that you wrote the original software. If you use this software
17      in a product, an acknowledgment in the product documentation would be
18      appreciated but is not required.
19   2. Altered source versions must be plainly marked as such, and must not be
20      misrepresented as being the original software.
21   3. This notice may not be removed or altered from any source distribution.
22 
23   Jean-loup Gailly        Mark Adler
24   jloup@gzip.org          madler@alumni.caltech.edu
25 
26 */
27 
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h> /* for Win32, HAVE_OFF_T and HAVE_FSEEKO */
31 #endif
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 
38 #include "zlib.h"
39 
40 #ifdef Win32
41 # define OS_CODE  0x06
42 #else
43 # define OS_CODE  0x03
44 #endif
45 
46 /* R ADDITION */
47 #ifdef Win32
48 # define Rz_off_t off64_t
49 #elif defined(HAVE_OFF_T) && defined(HAVE_FSEEKO)
50 # define Rz_off_t off_t
51 #else
52 # define Rz_off_t long
53 #endif
54 
55 
56 #define Z_BUFSIZE 16384
57 
58 typedef struct gz_stream {
59     z_stream stream;
60     int      z_err;   /* error code for last stream operation */
61     int      z_eof;   /* set if end of input file */
62     FILE     *file;   /* .gz file */
63     Byte     buffer[Z_BUFSIZE];  /* input or output buffer */
64     uLong    crc;     /* crc32 of uncompressed data */
65     int      transparent; /* 1 if input file is not compressed */
66     char     mode;    /* 'w' or 'r' */
67     Rz_off_t  start;  /* start of compressed data in file (header skipped) */
68     Rz_off_t  in;     /* bytes into deflate or inflate */
69     Rz_off_t  out;    /* bytes out of deflate or inflate */
70 } gz_stream;
71 
72 
get_byte(gz_stream * s)73 static int get_byte(gz_stream *s)
74 {
75     if (s->z_eof) return EOF;
76     if (s->stream.avail_in == 0) {
77         errno = 0;
78         s->stream.avail_in = (uInt) fread(s->buffer, 1, Z_BUFSIZE, s->file);
79         if (s->stream.avail_in == 0) {
80             s->z_eof = 1;
81             if (ferror(s->file)) s->z_err = Z_ERRNO;
82             return EOF;
83         }
84         s->stream.next_in = s->buffer;
85     }
86     s->stream.avail_in--;
87     return *(s->stream.next_in)++;
88 }
89 
destroy(gz_stream * s)90 static int destroy (gz_stream *s)
91 {
92     int err = Z_OK;
93 
94     if (!s) return Z_STREAM_ERROR;
95 
96     if (s->stream.state != NULL) {
97         if (s->mode == 'w') err = deflateEnd(&(s->stream));
98         else if (s->mode == 'r') err = inflateEnd(&(s->stream));
99     }
100     if (s->file != NULL && fclose(s->file)) {
101 #ifdef ESPIPE
102         if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
103 #endif
104             err = Z_ERRNO;
105     }
106     if (s->z_err < 0) err = s->z_err;
107 
108     if(s) free(s);
109     return err;
110 }
111 
112 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
113 
114 /* gzip flag byte */
115 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text, unused */
116 #define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
117 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
118 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
119 #define COMMENT      0x10 /* bit 4 set: file comment present */
120 #define RESERVED     0xE0 /* bits 5..7: reserved */
121 
check_header(gz_stream * s)122 static void check_header(gz_stream *s)
123 {
124     int method; /* method byte */
125     int flags;  /* flags byte */
126     uInt len;
127     int c;
128 
129     /* Assure two bytes in the buffer so we can peek ahead -- handle case
130        where first byte of header is at the end of the buffer after the last
131        gzip segment */
132     len = s->stream.avail_in;
133     if (len < 2) {
134         if (len) s->buffer[0] = s->stream.next_in[0];
135         errno = 0;
136         len = (uInt) fread(s->buffer + len, 1, Z_BUFSIZE >> len, s->file);
137         if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
138         s->stream.avail_in += len;
139         s->stream.next_in = s->buffer;
140         if (s->stream.avail_in < 2) {
141             s->transparent = s->stream.avail_in;
142             return;
143         }
144     }
145 
146     /* Peek ahead to check the gzip magic header */
147     if (s->stream.next_in[0] != gz_magic[0] ||
148         s->stream.next_in[1] != gz_magic[1]) {
149         s->transparent = 1;
150         return;
151     }
152     s->stream.avail_in -= 2;
153     s->stream.next_in += 2;
154 
155     /* Check the rest of the gzip header */
156     method = get_byte(s);
157     flags = get_byte(s);
158     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
159         s->z_err = Z_DATA_ERROR;
160         return;
161     }
162 
163     /* Discard time, xflags and OS code: */
164     for (len = 0; len < 6; len++) (void)get_byte(s);
165 
166     if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
167         len  =  (uInt )get_byte(s);
168         len += ((uInt) get_byte(s)) << 8;
169         /* len is garbage if EOF but the loop below will quit anyway */
170         while (len-- != 0 && get_byte(s) != EOF) ;
171     }
172     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
173         while ((c = get_byte(s)) != 0 && c != EOF) ;
174     }
175     if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
176         while ((c = get_byte(s)) != 0 && c != EOF) ;
177     }
178     if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
179         for (len = 0; len < 2; len++) (void) get_byte(s);
180     }
181     s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
182 }
183 
R_gzopen(const char * path,const char * mode)184 gzFile R_gzopen (const char *path, const char *mode)
185 {
186     int err;
187     int level = Z_DEFAULT_COMPRESSION; /* compression level */
188     int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
189     char *p = (char *) mode;
190     gz_stream *s;
191     char fmode[80]; /* copy of mode, without the compression level */
192     char *m = fmode;
193 
194     if (!path || !mode) return Z_NULL;
195 
196     s = (gz_stream *) malloc(sizeof(gz_stream));
197     if (!s) return Z_NULL;
198 
199     s->stream.zalloc = (alloc_func) 0;
200     s->stream.zfree = (free_func) 0;
201     s->stream.opaque = (voidpf) 0;
202     s->stream.next_in = s->buffer;
203     s->stream.next_out = s->buffer;
204     s->stream.avail_in = s->stream.avail_out = 0;
205     s->file = NULL;
206     s->z_err = Z_OK;
207     s->z_eof = 0;
208     s->in = 0;
209     s->out = 0;
210     s->crc = crc32(0L, Z_NULL, 0);
211     s->transparent = 0;
212     s->mode = '\0';
213     do {
214         if (*p == 'r') s->mode = 'r';
215         if (*p == 'w' || *p == 'a') s->mode = 'w';
216         if (*p >= '0' && *p <= '9') level = *p - '0';
217         else if (*p == 'f') strategy = Z_FILTERED;
218         else if (*p == 'h') strategy = Z_HUFFMAN_ONLY;
219         else if (*p == 'R') strategy = Z_RLE;
220         else *m++ = *p; /* copy the mode */
221     } while (*p++ && m != fmode + sizeof(fmode));
222     if (s->mode == '\0') return destroy(s), (gzFile) Z_NULL;
223 
224     if (s->mode == 'w') {
225         err = deflateInit2(&(s->stream), level,
226                            Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, strategy);
227         /* windowBits is passed < 0 to suppress zlib header */
228         if (err != Z_OK) return destroy(s), (gzFile) Z_NULL;
229     } else {
230         err = inflateInit2(&(s->stream), -MAX_WBITS);
231         /* windowBits is passed < 0 to tell that there is no zlib header.
232          * Note that in this case inflate *requires* an extra "dummy" byte
233          * after the compressed stream in order to complete decompression and
234          * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
235          * present after the compressed stream.
236          */
237         if (err != Z_OK) return destroy(s), (gzFile) Z_NULL;
238     }
239     s->stream.avail_out = Z_BUFSIZE;
240 
241     errno = 0;
242     s->file = fopen(path, fmode);
243     if (s->file == NULL) return destroy(s), (gzFile) Z_NULL;
244 
245     if (s->mode == 'w') {
246         /* Write a very simple .gz header */
247         fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
248 		Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/,
249 		OS_CODE);
250         s->start = 10L;
251     } else {
252         check_header(s); /* skip the .gz header */
253         s->start = f_tell(s->file) - s->stream.avail_in;
254     }
255     return (gzFile) s;
256 }
257 
z_putLong(FILE * file,uLong x)258 static void z_putLong (FILE *file, uLong x)
259 {
260     int n;
261     for (n = 0; n < 4; n++) {
262         fputc((int) (x & 0xff), file);
263         x >>= 8;
264     }
265 }
266 
getLong(gz_stream * s)267 static uLong getLong (gz_stream *s)
268 {
269     uLong x = (uLong) get_byte(s);
270     int c;
271 
272     x += ((uLong) get_byte(s)) << 8;
273     x += ((uLong) get_byte(s)) << 16;
274     c = get_byte(s);
275     if (c == EOF) s->z_err = Z_DATA_ERROR;
276     x += ((uLong) c) << 24;
277     return x;
278 }
279 
R_gzread(gzFile file,voidp buf,unsigned len)280 static int R_gzread (gzFile file, voidp buf, unsigned len)
281 {
282     gz_stream *s = (gz_stream*) file;
283     Bytef *start = (Bytef*) buf; /* starting point for crc computation */
284     Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
285 
286     if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
287 
288     if (s->z_err == Z_DATA_ERROR) {
289 	warning("invalid or incomplete compressed data");
290 	return -1;
291     } else if(s->z_err == Z_ERRNO) {
292 	warning("error reading the file");
293 	return -1;
294     }
295     if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
296 
297     next_out = (Byte*) buf;
298     s->stream.next_out = (Bytef*) buf;
299     s->stream.avail_out = len;
300 
301     while (s->stream.avail_out != 0) {
302 
303         if (s->transparent) {
304             /* Copy first the lookahead bytes: */
305             uInt n = s->stream.avail_in;
306             if (n > s->stream.avail_out) n = s->stream.avail_out;
307             if (n > 0) {
308                 memcpy(s->stream.next_out, s->stream.next_in, n);
309                 next_out += n;
310                 s->stream.next_out = next_out;
311                 s->stream.next_in   += n;
312                 s->stream.avail_out -= n;
313                 s->stream.avail_in  -= n;
314             }
315             if (s->stream.avail_out > 0) {
316                 s->stream.avail_out -=
317                     (uInt) fread(next_out, 1, s->stream.avail_out, s->file);
318             }
319             len -= s->stream.avail_out;
320             s->in  += len;
321             s->out += len;
322             if (len == 0) s->z_eof = 1;
323             return (int)len;
324         }
325         if (s->stream.avail_in == 0 && !s->z_eof) {
326             errno = 0;
327             s->stream.avail_in = (uInt) fread(s->buffer, 1, Z_BUFSIZE, s->file);
328             if (s->stream.avail_in == 0) {
329                 s->z_eof = 1;
330                 if (ferror(s->file)) {
331                     s->z_err = Z_ERRNO;
332                     break;
333                 }
334             }
335             s->stream.next_in = s->buffer;
336         }
337         s->in += s->stream.avail_in;
338         s->out += s->stream.avail_out;
339         s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
340         s->in -= s->stream.avail_in;
341         s->out -= s->stream.avail_out;
342 
343         if (s->z_err == Z_STREAM_END) {
344             /* Check CRC and original size */
345             s->crc = crc32(s->crc, start, (uInt) (s->stream.next_out - start));
346             start = s->stream.next_out;
347 
348             if (getLong(s) != s->crc) {
349 		warning("invalid or incomplete compressed data");
350                 s->z_err = Z_DATA_ERROR;
351             } else {
352                 (void)getLong(s);
353                 /* The uncompressed length returned by above getlong() may be
354                  * different from s->out in case of concatenated .gz files.
355                  * Check for such files:
356                  */
357                 check_header(s);
358                 if (s->z_err == Z_OK) {
359                     inflateReset(&(s->stream));
360                     s->crc = crc32(0L, Z_NULL, 0);
361                 }
362             }
363         }
364         if (s->z_err != Z_OK || s->z_eof) break;
365     }
366     s->crc = crc32(s->crc, start, (uInt) (s->stream.next_out - start));
367 
368     if (len == s->stream.avail_out &&
369         (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) {
370 	if(s->z_err == Z_DATA_ERROR)
371 	    warning("invalid or incomplete compressed data");
372 	else if(s->z_err == Z_ERRNO)
373 	    warning("error reading the file");
374 	return -1;
375     }
376     return (int)(len - s->stream.avail_out);
377 }
378 
379 /* for devPS.c */
R_gzgets(gzFile file,char * buf,int len)380 char *R_gzgets(gzFile file, char *buf, int len)
381 {
382     char *b = buf;
383     if (buf == Z_NULL || len <= 0) return Z_NULL;
384 
385     while (--len > 0 && R_gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
386     *buf = '\0';
387     return b == buf && len > 0 ? Z_NULL : b;
388 }
389 
390 
R_gzwrite(gzFile file,voidpc buf,unsigned len)391 static int R_gzwrite (gzFile file, voidpc buf, unsigned len)
392 {
393     gz_stream *s = (gz_stream*) file;
394 
395     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
396 
397     s->stream.next_in = (Bytef*) buf;
398     s->stream.avail_in = len;
399 
400     while (s->stream.avail_in != 0) {
401         if (s->stream.avail_out == 0) {
402             s->stream.next_out = s->buffer;
403             if (fwrite(s->buffer, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
404                 s->z_err = Z_ERRNO;
405                 break;
406             }
407             s->stream.avail_out = Z_BUFSIZE;
408         }
409         s->in += s->stream.avail_in;
410         s->out += s->stream.avail_out;
411         s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
412         s->in -= s->stream.avail_in;
413         s->out -= s->stream.avail_out;
414         if (s->z_err != Z_OK) break;
415     }
416     s->crc = crc32(s->crc, (const Bytef *) buf, len);
417 
418     return (int) (len - s->stream.avail_in);
419 }
420 
421 
gz_flush(gzFile file,int flush)422 static int gz_flush (gzFile file, int flush)
423 {
424     uInt len;
425     int done = 0;
426     gz_stream *s = (gz_stream*) file;
427 
428     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
429 
430     s->stream.avail_in = 0; /* should be zero already anyway */
431 
432     for (;;) {
433         len = Z_BUFSIZE - s->stream.avail_out;
434         if (len != 0) {
435             if ((uInt)fwrite(s->buffer, 1, len, s->file) != len) {
436                 s->z_err = Z_ERRNO;
437                 return Z_ERRNO;
438             }
439             s->stream.next_out = s->buffer;
440             s->stream.avail_out = Z_BUFSIZE;
441         }
442         if (done) break;
443         s->out += s->stream.avail_out;
444         s->z_err = deflate(&(s->stream), flush);
445         s->out -= s->stream.avail_out;
446 
447         /* Ignore the second of two consecutive flushes: */
448         if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
449 
450         /* deflate has finished flushing only when it hasn't used up
451          * all the available space in the output buffer:
452          */
453         done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
454 
455         if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
456     }
457     return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
458 }
459 
460 /* return value 0 for success, 1 for failure */
int_gzrewind(gzFile file)461 static int int_gzrewind (gzFile file)
462 {
463     gz_stream *s = (gz_stream*) file;
464 
465     if (s == NULL || s->mode != 'r') return -1;
466 
467     s->z_err = Z_OK;
468     s->z_eof = 0;
469     s->stream.avail_in = 0;
470     s->stream.next_in = s->buffer;
471     s->crc = crc32(0L, Z_NULL, 0);
472     if (!s->transparent) (void) inflateReset(&s->stream);
473     s->in = 0;
474     s->out = 0;
475     return f_seek(s->file, s->start, SEEK_SET);
476 }
477 
R_gztell(gzFile file)478 static Rz_off_t R_gztell (gzFile file)
479 {
480     gz_stream *s = (gz_stream*) file;
481     if (s->mode == 'w') return s->in; else return s->out;
482 }
483 
484 /* NB: return value is in line with fseeko, not gzseek */
R_gzseek(gzFile file,Rz_off_t offset,int whence)485 static int R_gzseek (gzFile file, Rz_off_t offset, int whence)
486 {
487     gz_stream *s = (gz_stream*) file;
488 
489     if (s == NULL || whence == SEEK_END ||
490         s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) return -1;
491 
492     if (s->mode == 'w') {
493         if (whence == SEEK_SET) offset -= s->in;
494         if (offset < 0) return -1;
495 
496         /* At this point, offset is the number of zero bytes to write. */
497 	memset(s->buffer, 0, Z_BUFSIZE);
498 	while (offset > 0)  {
499             uInt size = Z_BUFSIZE;
500             if (offset < Z_BUFSIZE) size = (uInt) offset;
501             size = R_gzwrite(file, s->buffer, size);
502             if (size == 0) return -1;
503             offset -= size;
504         }
505         return 0;
506     }
507 
508     /* Rest of function is for reading only */
509 
510     /* compute absolute position */
511     if (whence == SEEK_CUR) offset += s->out;
512     if (offset < 0) return -1;
513 
514     if (s->transparent) {
515         s->stream.avail_in = 0;
516         s->stream.next_in = s->buffer;
517         if (f_seek(s->file, offset, SEEK_SET) < 0) return -1;
518         s->in = s->out = offset;
519         return 0;
520     }
521 
522     /* For a negative seek, rewind and use positive seek */
523     if (offset >= s->out) offset -= s->out;
524     else if (int_gzrewind(file) < 0) return -1;
525 
526     /* offset is now the number of bytes to skip. */
527     while (offset > 0)  {
528         int size = Z_BUFSIZE;
529         if (offset < Z_BUFSIZE) size = (int) offset;
530         size = R_gzread(file, s->buffer, (uInt) size);
531         if (size <= 0) return -1;
532         offset -= size;
533     }
534     return 0;
535 }
536 
R_gzclose(gzFile file)537 int R_gzclose (gzFile file)
538 {
539     gz_stream *s = (gz_stream*) file;
540     if (s == NULL) return Z_STREAM_ERROR;
541     if (s->mode == 'w') {
542         if (gz_flush (file, Z_FINISH) != Z_OK)
543 	    return destroy((gz_stream*) file);
544         z_putLong (s->file, s->crc);
545         z_putLong (s->file, (uLong) (s->in & 0xffffffff));
546     }
547     return destroy((gz_stream*) file);
548 }
549 
550 /*
551 static voidpf
552 R_zlib_alloc(voidpf ptr, uInt items, uInt size)
553 {
554     return R_alloc(items, size);
555 }
556 
557 static void
558 R_zlib_free(voidpf ptr, voidpf addr) {}
559 */
560 
561 /* added in 4.0.0, modified from uncompress[2] */
562 static int
R_uncompress(Bytef * dest,uLong * destLen,Bytef * source,uLong sourceLen,int opt)563 R_uncompress(Bytef *dest, uLong *destLen, Bytef *source, uLong sourceLen,
564 	     int opt)
565 {
566     z_stream stream;
567 
568     stream.next_in = source;
569     stream.avail_in = 0;
570     stream.zalloc = (alloc_func)0;
571     stream.zfree = (free_func)0;
572     stream.opaque = (voidpf)0;
573 
574     /*
575        opt is the main difference from uncompress
576        0 means no headers (zlib)
577        16 selects gzip
578        32 allows auto-selection.
579     */
580     int err = inflateInit2( &stream, MAX_WBITS + opt );
581     if(err != Z_OK) return err;
582 
583     const uInt max = (uInt)-1;  // could have used UINT_MAX
584     uLong len = sourceLen, left = *destLen;
585     stream.next_out = dest;
586     stream.avail_out = 0;
587 
588     do { // do >= 2^32 bits in chunks
589         if (stream.avail_out == 0) {
590             stream.avail_out = left > (uLong)max ? max : (uInt)left;
591             left -= stream.avail_out;
592         }
593         if (stream.avail_in == 0) {
594             stream.avail_in = len > (uLong)max ? max : (uInt)len;
595             len -= stream.avail_in;
596         }
597         err = inflate(&stream, Z_NO_FLUSH);
598     } while (err == Z_OK);
599 
600     *destLen = stream.total_out;
601     inflateEnd(&stream);
602     return err;
603 }
604