52 # define Rz_off_t off64_t
53 #elif defined(HAVE_OFF_T) && defined(HAVE_FSEEKO)
54 # define Rz_off_t off_t
56 # define Rz_off_t long
60 #define Z_BUFSIZE 16384
62 typedef struct gz_stream {
67 Byte buffer[Z_BUFSIZE];
77 static int get_byte(gz_stream *s)
79 if (s->z_eof)
return EOF;
80 if (s->stream.avail_in == 0) {
82 s->stream.avail_in = (uInt) fread(s->buffer, 1, Z_BUFSIZE, s->file);
83 if (s->stream.avail_in == 0) {
85 if (ferror(s->file)) s->z_err = Z_ERRNO;
88 s->stream.next_in = s->buffer;
91 return *(s->stream.next_in)++;
94 static int destroy (gz_stream *s)
98 if (!s)
return Z_STREAM_ERROR;
100 if (s->stream.state != NULL) {
101 if (s->mode ==
'w') err = deflateEnd(&(s->stream));
102 else if (s->mode ==
'r') err = inflateEnd(&(s->stream));
104 if (s->file != NULL && fclose(s->file)) {
110 if (s->z_err < 0) err = s->z_err;
116 static int const gz_magic[2] = {0x1f, 0x8b};
119 #define ASCII_FLAG 0x01
120 #define HEAD_CRC 0x02
121 #define EXTRA_FIELD 0x04
122 #define ORIG_NAME 0x08
124 #define RESERVED 0xE0
126 static void check_header(gz_stream *s)
136 len = s->stream.avail_in;
138 if (len) s->buffer[0] = s->stream.next_in[0];
140 len = (uInt) fread(s->buffer + len, 1, Z_BUFSIZE >> len, s->file);
141 if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
142 s->stream.avail_in += len;
143 s->stream.next_in = s->buffer;
144 if (s->stream.avail_in < 2) {
145 s->transparent = s->stream.avail_in;
151 if (s->stream.next_in[0] != gz_magic[0] ||
152 s->stream.next_in[1] != gz_magic[1]) {
156 s->stream.avail_in -= 2;
157 s->stream.next_in += 2;
160 method = get_byte(s);
162 if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
163 s->z_err = Z_DATA_ERROR;
168 for (len = 0; len < 6; len++) (
void)get_byte(s);
170 if ((flags & EXTRA_FIELD) != 0) {
171 len = (uInt )get_byte(s);
172 len += ((uInt) get_byte(s)) << 8;
174 while (len-- != 0 && get_byte(s) != EOF) ;
176 if ((flags & ORIG_NAME) != 0) {
177 while ((c = get_byte(s)) != 0 && c != EOF) ;
179 if ((flags & COMMENT) != 0) {
180 while ((c = get_byte(s)) != 0 && c != EOF) ;
182 if ((flags & HEAD_CRC) != 0) {
183 for (len = 0; len < 2; len++) (
void) get_byte(s);
185 s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
188 gzFile R_gzopen (
const char *path,
const char *mode)
191 int level = Z_DEFAULT_COMPRESSION;
192 int strategy = Z_DEFAULT_STRATEGY;
193 char *p = (
char *) mode;
198 if (!path || !mode)
return Z_NULL;
200 s = (gz_stream *) malloc(
sizeof(gz_stream));
201 if (!s)
return Z_NULL;
203 s->stream.zalloc = (alloc_func) 0;
204 s->stream.zfree = (free_func) 0;
205 s->stream.opaque = (voidpf) 0;
206 s->stream.next_in = s->buffer;
207 s->stream.next_out = s->buffer;
208 s->stream.avail_in = s->stream.avail_out = 0;
214 s->crc = crc32(0L, Z_NULL, 0);
218 if (*p ==
'r') s->mode =
'r';
219 if (*p ==
'w' || *p ==
'a') s->mode =
'w';
220 if (*p >=
'0' && *p <=
'9') level = *p -
'0';
221 else if (*p ==
'f') strategy = Z_FILTERED;
222 else if (*p ==
'h') strategy = Z_HUFFMAN_ONLY;
223 else if (*p ==
'R') strategy = Z_RLE;
225 }
while (*p++ && m != fmode +
sizeof(fmode));
226 if (s->mode ==
'\0')
return destroy(s), (gzFile) Z_NULL;
228 if (s->mode ==
'w') {
229 err = deflateInit2(&(s->stream), level,
230 Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, strategy);
232 if (err != Z_OK)
return destroy(s), (gzFile) Z_NULL;
234 err = inflateInit2(&(s->stream), -MAX_WBITS);
241 if (err != Z_OK)
return destroy(s), (gzFile) Z_NULL;
243 s->stream.avail_out = Z_BUFSIZE;
246 s->file = fopen(path, fmode);
247 if (s->file == NULL)
return destroy(s), (gzFile) Z_NULL;
249 if (s->mode ==
'w') {
251 fprintf(s->file,
"%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
252 Z_DEFLATED, 0 , 0,0,0,0 , 0 ,
257 s->start = f_tell(s->file) - s->stream.avail_in;
262 static void z_putLong (FILE *file, uLong x)
265 for (n = 0; n < 4; n++) {
266 fputc((
int) (x & 0xff), file);
271 static uLong getLong (gz_stream *s)
273 uLong x = (uLong) get_byte(s);
276 x += ((uLong) get_byte(s)) << 8;
277 x += ((uLong) get_byte(s)) << 16;
279 if (c == EOF) s->z_err = Z_DATA_ERROR;
280 x += ((uLong) c) << 24;
284 static int R_gzread (gzFile file, voidp buf,
unsigned len)
286 gz_stream *s = (gz_stream*) file;
287 Bytef *start = (Bytef*) buf;
290 if (s == NULL || s->mode !=
'r')
return Z_STREAM_ERROR;
292 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
return -1;
293 if (s->z_err == Z_STREAM_END)
return 0;
295 next_out = (Byte*) buf;
296 s->stream.next_out = (Bytef*) buf;
297 s->stream.avail_out = len;
299 while (s->stream.avail_out != 0) {
301 if (s->transparent) {
303 uInt n = s->stream.avail_in;
304 if (n > s->stream.avail_out) n = s->stream.avail_out;
306 memcpy(s->stream.next_out, s->stream.next_in, n);
308 s->stream.next_out = next_out;
309 s->stream.next_in += n;
310 s->stream.avail_out -= n;
311 s->stream.avail_in -= n;
313 if (s->stream.avail_out > 0) {
314 s->stream.avail_out -=
315 (uInt) fread(next_out, 1, s->stream.avail_out, s->file);
317 len -= s->stream.avail_out;
320 if (len == 0) s->z_eof = 1;
323 if (s->stream.avail_in == 0 && !s->z_eof) {
325 s->stream.avail_in = (uInt) fread(s->buffer, 1, Z_BUFSIZE, s->file);
326 if (s->stream.avail_in == 0) {
328 if (ferror(s->file)) {
333 s->stream.next_in = s->buffer;
335 s->in += s->stream.avail_in;
336 s->out += s->stream.avail_out;
337 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
338 s->in -= s->stream.avail_in;
339 s->out -= s->stream.avail_out;
341 if (s->z_err == Z_STREAM_END) {
343 s->crc = crc32(s->crc, start, (uInt) (s->stream.next_out - start));
344 start = s->stream.next_out;
346 if (getLong(s) != s->crc) {
347 s->z_err = Z_DATA_ERROR;
355 if (s->z_err == Z_OK) {
356 inflateReset(&(s->stream));
357 s->crc = crc32(0L, Z_NULL, 0);
361 if (s->z_err != Z_OK || s->z_eof)
break;
363 s->crc = crc32(s->crc, start, (uInt) (s->stream.next_out - start));
365 if (len == s->stream.avail_out &&
366 (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
368 return (
int)(len - s->stream.avail_out);
372 char *R_gzgets(gzFile file,
char *buf,
int len)
375 if (buf == Z_NULL || len <= 0)
return Z_NULL;
377 while (--len > 0 && R_gzread(file, buf, 1) == 1 && *buf++ !=
'\n') ;
379 return b == buf && len > 0 ? Z_NULL : b;
383 static int R_gzwrite (gzFile file, voidpc buf,
unsigned len)
385 gz_stream *s = (gz_stream*) file;
387 if (s == NULL || s->mode !=
'w')
return Z_STREAM_ERROR;
389 s->stream.next_in = (Bytef*) buf;
390 s->stream.avail_in = len;
392 while (s->stream.avail_in != 0) {
393 if (s->stream.avail_out == 0) {
394 s->stream.next_out = s->buffer;
395 if (fwrite(s->buffer, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
399 s->stream.avail_out = Z_BUFSIZE;
401 s->in += s->stream.avail_in;
402 s->out += s->stream.avail_out;
403 s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
404 s->in -= s->stream.avail_in;
405 s->out -= s->stream.avail_out;
406 if (s->z_err != Z_OK)
break;
408 s->crc = crc32(s->crc, (
const Bytef *) buf, len);
410 return (
int) (len - s->stream.avail_in);
414 static int gz_flush (gzFile file,
int flush)
418 gz_stream *s = (gz_stream*) file;
420 if (s == NULL || s->mode !=
'w')
return Z_STREAM_ERROR;
422 s->stream.avail_in = 0;
425 len = Z_BUFSIZE - s->stream.avail_out;
427 if ((uInt)fwrite(s->buffer, 1, len, s->file) != len) {
431 s->stream.next_out = s->buffer;
432 s->stream.avail_out = Z_BUFSIZE;
435 s->out += s->stream.avail_out;
436 s->z_err = deflate(&(s->stream), flush);
437 s->out -= s->stream.avail_out;
440 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
445 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
447 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END)
break;
449 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
453 static int int_gzrewind (gzFile file)
455 gz_stream *s = (gz_stream*) file;
457 if (s == NULL || s->mode !=
'r')
return -1;
461 s->stream.avail_in = 0;
462 s->stream.next_in = s->buffer;
463 s->crc = crc32(0L, Z_NULL, 0);
464 if (!s->transparent) (void) inflateReset(&s->stream);
467 return f_seek(s->file, s->start, SEEK_SET);
470 static Rz_off_t R_gztell (gzFile file)
472 gz_stream *s = (gz_stream*) file;
473 if (s->mode ==
'w')
return s->in;
else return s->out;
477 static int R_gzseek (gzFile file, Rz_off_t offset,
int whence)
479 gz_stream *s = (gz_stream*) file;
481 if (s == NULL || whence == SEEK_END ||
482 s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR)
return -1;
484 if (s->mode ==
'w') {
485 if (whence == SEEK_SET) offset -= s->in;
486 if (offset < 0)
return -1;
489 memset(s->buffer, 0, Z_BUFSIZE);
491 uInt size = Z_BUFSIZE;
492 if (offset < Z_BUFSIZE) size = (uInt) offset;
493 size = R_gzwrite(file, s->buffer, size);
494 if (size == 0)
return -1;
503 if (whence == SEEK_CUR) offset += s->out;
504 if (offset < 0)
return -1;
506 if (s->transparent) {
507 s->stream.avail_in = 0;
508 s->stream.next_in = s->buffer;
509 if (f_seek(s->file, offset, SEEK_SET) < 0)
return -1;
510 s->in = s->out = offset;
515 if (offset >= s->out) offset -= s->out;
516 else if (int_gzrewind(file) < 0)
return -1;
520 int size = Z_BUFSIZE;
521 if (offset < Z_BUFSIZE) size = (int) offset;
522 size = R_gzread(file, s->buffer, (uInt) size);
523 if (size <= 0)
return -1;
529 int R_gzclose (gzFile file)
531 gz_stream *s = (gz_stream*) file;
532 if (s == NULL)
return Z_STREAM_ERROR;
533 if (s->mode ==
'w') {
534 if (gz_flush (file, Z_FINISH) != Z_OK)
535 return destroy((gz_stream*) file);
536 z_putLong (s->file, s->crc);
537 z_putLong (s->file, (uLong) (s->in & 0xffffffff));
539 return destroy((gz_stream*) file);