diff options
Diffstat (limited to 'gzio.c')
-rw-r--r-- | gzio.c | 90 |
1 files changed, 70 insertions, 20 deletions
@@ -11,7 +11,9 @@ | |||
11 | 11 | ||
12 | #include "zutil.h" | 12 | #include "zutil.h" |
13 | 13 | ||
14 | #ifndef NO_DUMMY_DECL | ||
14 | struct internal_state {int dummy;}; /* for buggy compilers */ | 15 | struct internal_state {int dummy;}; /* for buggy compilers */ |
16 | #endif | ||
15 | 17 | ||
16 | #ifndef Z_BUFSIZE | 18 | #ifndef Z_BUFSIZE |
17 | # ifdef MAXSEG_64K | 19 | # ifdef MAXSEG_64K |
@@ -55,6 +57,8 @@ typedef struct gz_stream { | |||
55 | int transparent; /* 1 if input file is not a .gz file */ | 57 | int transparent; /* 1 if input file is not a .gz file */ |
56 | char mode; /* 'w' or 'r' */ | 58 | char mode; /* 'w' or 'r' */ |
57 | long startpos; /* start of compressed data in file (header skipped) */ | 59 | long startpos; /* start of compressed data in file (header skipped) */ |
60 | int back; /* one character push-back */ | ||
61 | int last; /* true if push-back is last character */ | ||
58 | } gz_stream; | 62 | } gz_stream; |
59 | 63 | ||
60 | 64 | ||
@@ -102,6 +106,7 @@ local gzFile gz_open (path, mode, fd) | |||
102 | s->file = NULL; | 106 | s->file = NULL; |
103 | s->z_err = Z_OK; | 107 | s->z_err = Z_OK; |
104 | s->z_eof = 0; | 108 | s->z_eof = 0; |
109 | s->back = EOF; | ||
105 | s->crc = crc32(0L, Z_NULL, 0); | 110 | s->crc = crc32(0L, Z_NULL, 0); |
106 | s->msg = NULL; | 111 | s->msg = NULL; |
107 | s->transparent = 0; | 112 | s->transparent = 0; |
@@ -391,6 +396,18 @@ int ZEXPORT gzread (file, buf, len) | |||
391 | s->stream.next_out = (Bytef*)buf; | 396 | s->stream.next_out = (Bytef*)buf; |
392 | s->stream.avail_out = len; | 397 | s->stream.avail_out = len; |
393 | 398 | ||
399 | if (s->stream.avail_out && s->back != EOF) { | ||
400 | *next_out++ = s->back; | ||
401 | s->stream.next_out++; | ||
402 | s->stream.avail_out--; | ||
403 | s->back = EOF; | ||
404 | s->stream.total_out++; | ||
405 | if (s->last) { | ||
406 | s->z_err = Z_STREAM_END; | ||
407 | return 1; | ||
408 | } | ||
409 | } | ||
410 | |||
394 | while (s->stream.avail_out != 0) { | 411 | while (s->stream.avail_out != 0) { |
395 | 412 | ||
396 | if (s->transparent) { | 413 | if (s->transparent) { |
@@ -477,6 +494,24 @@ int ZEXPORT gzgetc(file) | |||
477 | 494 | ||
478 | 495 | ||
479 | /* =========================================================================== | 496 | /* =========================================================================== |
497 | Push one byte back onto the stream. | ||
498 | */ | ||
499 | int ZEXPORT gzungetc(c, file) | ||
500 | int c; | ||
501 | gzFile file; | ||
502 | { | ||
503 | gz_stream *s = (gz_stream*)file; | ||
504 | |||
505 | if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; | ||
506 | s->back = c; | ||
507 | s->stream.total_out--; | ||
508 | s->last = (s->z_err == Z_STREAM_END); | ||
509 | if (s->z_eof) s->z_eof = 0; | ||
510 | return c; | ||
511 | } | ||
512 | |||
513 | |||
514 | /* =========================================================================== | ||
480 | Reads bytes from the compressed file until len-1 characters are | 515 | Reads bytes from the compressed file until len-1 characters are |
481 | read, or a newline character is read and transferred to buf, or an | 516 | read, or a newline character is read and transferred to buf, or an |
482 | end-of-file condition is encountered. The string is then terminated | 517 | end-of-file condition is encountered. The string is then terminated |
@@ -535,6 +570,7 @@ int ZEXPORT gzwrite (file, buf, len) | |||
535 | return (int)(len - s->stream.avail_in); | 570 | return (int)(len - s->stream.avail_in); |
536 | } | 571 | } |
537 | 572 | ||
573 | |||
538 | /* =========================================================================== | 574 | /* =========================================================================== |
539 | Converts, formats, and writes the args to the compressed file under | 575 | Converts, formats, and writes the args to the compressed file under |
540 | control of the format string, as in fprintf. gzprintf returns the number of | 576 | control of the format string, as in fprintf. gzprintf returns the number of |
@@ -549,34 +585,30 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) | |||
549 | va_list va; | 585 | va_list va; |
550 | int len; | 586 | int len; |
551 | 587 | ||
588 | buf[sizeof(buf) - 1] = 0; | ||
552 | va_start(va, format); | 589 | va_start(va, format); |
553 | #ifdef NO_vsnprintf | 590 | #ifdef NO_vsnprintf |
554 | # ifdef HAS_vsprintf_void | 591 | # ifdef HAS_vsprintf_void |
555 | (void)vsprintf(buf, format, va); | 592 | (void)vsprintf(buf, format, va); |
556 | va_end(va); | 593 | va_end(va); |
557 | len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ | 594 | for (len = 0; len < sizeof(buf); len++) |
558 | if (len <= 0) return 0; | 595 | if (buf[len] == 0) break; |
559 | # else | 596 | # else |
560 | len = vsprintf(buf, format, va); | 597 | len = vsprintf(buf, format, va); |
561 | va_end(va); | 598 | va_end(va); |
562 | if (len <= 0 || len >= sizeof(buf)) | ||
563 | return 0; | ||
564 | # endif | 599 | # endif |
565 | #else | 600 | #else |
566 | # ifdef HAS_vsnprintf_void | 601 | # ifdef HAS_vsnprintf_void |
567 | (void)vsnprintf(buf, sizeof(buf), format, va); | 602 | (void)vsnprintf(buf, sizeof(buf), format, va); |
568 | va_end(va); | 603 | va_end(va); |
569 | len = strlen(buf); | 604 | len = strlen(buf); |
570 | if (len <= 0) | ||
571 | return 0; | ||
572 | # else | 605 | # else |
573 | len = vsnprintf(buf, sizeof(buf), format, va); | 606 | len = vsnprintf(buf, sizeof(buf), format, va); |
574 | va_end(va); | 607 | va_end(va); |
575 | if (len <= 0 || len >= sizeof(buf)) | ||
576 | return 0; | ||
577 | # endif | 608 | # endif |
578 | #endif | 609 | #endif |
579 | 610 | if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) | |
611 | return 0; | ||
580 | return gzwrite(file, buf, (unsigned)len); | 612 | return gzwrite(file, buf, (unsigned)len); |
581 | } | 613 | } |
582 | #else /* not ANSI C */ | 614 | #else /* not ANSI C */ |
@@ -591,33 +623,29 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |||
591 | char buf[Z_PRINTF_BUFSIZE]; | 623 | char buf[Z_PRINTF_BUFSIZE]; |
592 | int len; | 624 | int len; |
593 | 625 | ||
626 | buf[sizeof(buf) - 1] = 0; | ||
594 | #ifdef NO_snprintf | 627 | #ifdef NO_snprintf |
595 | # ifdef HAS_sprintf_void | 628 | # ifdef HAS_sprintf_void |
596 | sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, | 629 | sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, |
597 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 630 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
598 | len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ | 631 | for (len = 0; len < sizeof(buf); len++) |
599 | if (len <= 0) return 0; | 632 | if (buf[len] == 0) break; |
600 | # else | 633 | # else |
601 | len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, | 634 | len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, |
602 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 635 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
603 | if (len <= 0 || len >= sizeof(buf)) | ||
604 | return 0; | ||
605 | # endif | 636 | # endif |
606 | #else | 637 | #else |
607 | # ifdef HAS_snprintf_void | 638 | # ifdef HAS_snprintf_void |
608 | snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, | 639 | snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, |
609 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 640 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
610 | len = strlen(buf); | 641 | len = strlen(buf); |
611 | if (len <= 0) | ||
612 | return 0; | ||
613 | # else | 642 | # else |
614 | len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, | 643 | len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, |
615 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 644 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
616 | if (len <= 0 || len >= sizeof(buf)) | ||
617 | return 0; | ||
618 | # endif | 645 | # endif |
619 | #endif | 646 | #endif |
620 | 647 | if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) | |
648 | return 0; | ||
621 | return gzwrite(file, buf, len); | 649 | return gzwrite(file, buf, len); |
622 | } | 650 | } |
623 | #endif | 651 | #endif |
@@ -762,6 +790,7 @@ z_off_t ZEXPORT gzseek (file, offset, whence) | |||
762 | 790 | ||
763 | if (s->transparent) { | 791 | if (s->transparent) { |
764 | /* map to fseek */ | 792 | /* map to fseek */ |
793 | s->back = EOF; | ||
765 | s->stream.avail_in = 0; | 794 | s->stream.avail_in = 0; |
766 | s->stream.next_in = s->inbuf; | 795 | s->stream.next_in = s->inbuf; |
767 | if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; | 796 | if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; |
@@ -782,6 +811,12 @@ z_off_t ZEXPORT gzseek (file, offset, whence) | |||
782 | s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); | 811 | s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); |
783 | if (s->outbuf == Z_NULL) return -1L; | 812 | if (s->outbuf == Z_NULL) return -1L; |
784 | } | 813 | } |
814 | if (offset && s->back != EOF) { | ||
815 | s->back == EOF; | ||
816 | s->stream.total_out++; | ||
817 | offset--; | ||
818 | if (s->last) s->z_err = Z_STREAM_END; | ||
819 | } | ||
785 | while (offset > 0) { | 820 | while (offset > 0) { |
786 | int size = Z_BUFSIZE; | 821 | int size = Z_BUFSIZE; |
787 | if (offset < Z_BUFSIZE) size = (int)offset; | 822 | if (offset < Z_BUFSIZE) size = (int)offset; |
@@ -805,12 +840,13 @@ int ZEXPORT gzrewind (file) | |||
805 | 840 | ||
806 | s->z_err = Z_OK; | 841 | s->z_err = Z_OK; |
807 | s->z_eof = 0; | 842 | s->z_eof = 0; |
843 | s->back = EOF; | ||
808 | s->stream.avail_in = 0; | 844 | s->stream.avail_in = 0; |
809 | s->stream.next_in = s->inbuf; | 845 | s->stream.next_in = s->inbuf; |
810 | s->crc = crc32(0L, Z_NULL, 0); | 846 | s->crc = crc32(0L, Z_NULL, 0); |
811 | 847 | ||
812 | if (s->startpos == 0) { /* not a compressed file */ | 848 | if (s->startpos == 0) { /* not a compressed file */ |
813 | rewind(s->file); | 849 | fseek(s->file, 0L, SEEK_SET); /* rewind() is not always available */ |
814 | return 0; | 850 | return 0; |
815 | } | 851 | } |
816 | 852 | ||
@@ -906,7 +942,7 @@ int ZEXPORT gzclose (file) | |||
906 | errnum is set to Z_ERRNO and the application may consult errno | 942 | errnum is set to Z_ERRNO and the application may consult errno |
907 | to get the exact error code. | 943 | to get the exact error code. |
908 | */ | 944 | */ |
909 | const char* ZEXPORT gzerror (file, errnum) | 945 | const char * ZEXPORT gzerror (file, errnum) |
910 | gzFile file; | 946 | gzFile file; |
911 | int *errnum; | 947 | int *errnum; |
912 | { | 948 | { |
@@ -932,3 +968,17 @@ const char* ZEXPORT gzerror (file, errnum) | |||
932 | strcat(s->msg, m); | 968 | strcat(s->msg, m); |
933 | return (const char*)s->msg; | 969 | return (const char*)s->msg; |
934 | } | 970 | } |
971 | |||
972 | /* =========================================================================== | ||
973 | Clear the error and end-of-file flags, and do the same for the real file. | ||
974 | */ | ||
975 | void ZEXPORT gzclearerr (file) | ||
976 | gzFile file; | ||
977 | { | ||
978 | gz_stream *s = (gz_stream*)file; | ||
979 | |||
980 | if (s == NULL) return; | ||
981 | if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; | ||
982 | s->z_eof = 0; | ||
983 | clearerr(s->file); | ||
984 | } | ||