diff options
Diffstat (limited to 'gzio.c')
-rw-r--r-- | gzio.c | 121 |
1 files changed, 106 insertions, 15 deletions
@@ -7,6 +7,15 @@ | |||
7 | 7 | ||
8 | /* @(#) $Id$ */ | 8 | /* @(#) $Id$ */ |
9 | 9 | ||
10 | #ifdef _LARGEFILE64_SOURCE | ||
11 | # ifndef _LARGEFILE_SOURCE | ||
12 | # define _LARGEFILE_SOURCE | ||
13 | # endif | ||
14 | # ifdef _FILE_OFFSET_BITS | ||
15 | # undef _FILE_OFFSET_BITS | ||
16 | # endif | ||
17 | #endif | ||
18 | |||
10 | #include "zutil.h" | 19 | #include "zutil.h" |
11 | #include <stdio.h> | 20 | #include <stdio.h> |
12 | 21 | ||
@@ -39,6 +48,14 @@ extern voidp malloc OF((uInt size)); | |||
39 | extern void free OF((voidpf ptr)); | 48 | extern void free OF((voidpf ptr)); |
40 | #endif | 49 | #endif |
41 | 50 | ||
51 | #ifdef NO_FSEEKO | ||
52 | # define FSEEK fseek | ||
53 | # define FTELL ftell | ||
54 | #else | ||
55 | # define FSEEK fseeko | ||
56 | # define FTELL ftello | ||
57 | #endif | ||
58 | |||
42 | #define ALLOC(size) malloc(size) | 59 | #define ALLOC(size) malloc(size) |
43 | #define TRYFREE(p) {if (p) free(p);} | 60 | #define TRYFREE(p) {if (p) free(p);} |
44 | 61 | ||
@@ -64,15 +81,27 @@ typedef struct gz_stream { | |||
64 | char *path; /* path name for debugging only */ | 81 | char *path; /* path name for debugging only */ |
65 | int transparent; /* 1 if input file is not a .gz file */ | 82 | int transparent; /* 1 if input file is not a .gz file */ |
66 | char mode; /* 'w' or 'r' */ | 83 | char mode; /* 'w' or 'r' */ |
84 | #ifdef _LARGEFILE64_SOURCE | ||
85 | off64_t start; /* start of compressed data in file (header skipped) */ | ||
86 | off64_t in; /* bytes into deflate or inflate */ | ||
87 | off64_t out; /* bytes out of deflate or inflate */ | ||
88 | #else | ||
67 | z_off_t start; /* start of compressed data in file (header skipped) */ | 89 | z_off_t start; /* start of compressed data in file (header skipped) */ |
68 | z_off_t in; /* bytes into deflate or inflate */ | 90 | z_off_t in; /* bytes into deflate or inflate */ |
69 | z_off_t out; /* bytes out of deflate or inflate */ | 91 | z_off_t out; /* bytes out of deflate or inflate */ |
92 | #endif | ||
70 | int back; /* one character push-back */ | 93 | int back; /* one character push-back */ |
71 | int last; /* true if push-back is last character */ | 94 | int last; /* true if push-back is last character */ |
72 | } gz_stream; | 95 | } gz_stream; |
73 | 96 | ||
74 | 97 | ||
75 | local gzFile gz_open OF((const char *path, const char *mode, int fd)); | 98 | local gzFile gz_open OF((const char *path, const char *mode, int fd, |
99 | int use64)); | ||
100 | #ifdef _LARGEFILE64_SOURCE | ||
101 | local off64_t gz_seek OF((gzFile file, off64_t offset, int whence, int use64)); | ||
102 | #else | ||
103 | local z_off_t gz_seek OF((gzFile file, z_off_t offset, int whence, int use64)); | ||
104 | #endif | ||
76 | local int do_flush OF((gzFile file, int flush)); | 105 | local int do_flush OF((gzFile file, int flush)); |
77 | local int get_byte OF((gz_stream *s)); | 106 | local int get_byte OF((gz_stream *s)); |
78 | local void check_header OF((gz_stream *s)); | 107 | local void check_header OF((gz_stream *s)); |
@@ -89,10 +118,11 @@ local uLong getLong OF((gz_stream *s)); | |||
89 | can be checked to distinguish the two cases (if errno is zero, the | 118 | can be checked to distinguish the two cases (if errno is zero, the |
90 | zlib error is Z_MEM_ERROR). | 119 | zlib error is Z_MEM_ERROR). |
91 | */ | 120 | */ |
92 | local gzFile gz_open (path, mode, fd) | 121 | local gzFile gz_open (path, mode, fd, use64) |
93 | const char *path; | 122 | const char *path; |
94 | const char *mode; | 123 | const char *mode; |
95 | int fd; | 124 | int fd; |
125 | int use64; | ||
96 | { | 126 | { |
97 | int err; | 127 | int err; |
98 | int level = Z_DEFAULT_COMPRESSION; /* compression level */ | 128 | int level = Z_DEFAULT_COMPRESSION; /* compression level */ |
@@ -164,12 +194,7 @@ local gzFile gz_open (path, mode, fd) | |||
164 | s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); | 194 | s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); |
165 | 195 | ||
166 | err = inflateInit2(&(s->stream), -MAX_WBITS); | 196 | err = inflateInit2(&(s->stream), -MAX_WBITS); |
167 | /* windowBits is passed < 0 to tell that there is no zlib header. | 197 | /* windowBits is passed < 0 to tell that there is no zlib header */ |
168 | * Note that in this case inflate *requires* an extra "dummy" byte | ||
169 | * after the compressed stream in order to complete decompression and | ||
170 | * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are | ||
171 | * present after the compressed stream. | ||
172 | */ | ||
173 | if (err != Z_OK || s->inbuf == Z_NULL) { | 198 | if (err != Z_OK || s->inbuf == Z_NULL) { |
174 | return destroy(s), (gzFile)Z_NULL; | 199 | return destroy(s), (gzFile)Z_NULL; |
175 | } | 200 | } |
@@ -177,7 +202,8 @@ local gzFile gz_open (path, mode, fd) | |||
177 | s->stream.avail_out = Z_BUFSIZE; | 202 | s->stream.avail_out = Z_BUFSIZE; |
178 | 203 | ||
179 | errno = 0; | 204 | errno = 0; |
180 | s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); | 205 | s->file = fd < 0 ? (use64 ? F_OPEN64(path, fmode) : F_OPEN(path, fmode)) : |
206 | (FILE*)fdopen(fd, fmode); | ||
181 | 207 | ||
182 | if (s->file == NULL) { | 208 | if (s->file == NULL) { |
183 | return destroy(s), (gzFile)Z_NULL; | 209 | return destroy(s), (gzFile)Z_NULL; |
@@ -198,7 +224,7 @@ local gzFile gz_open (path, mode, fd) | |||
198 | */ | 224 | */ |
199 | } else { | 225 | } else { |
200 | check_header(s); /* skip the .gz header */ | 226 | check_header(s); /* skip the .gz header */ |
201 | s->start = ftell(s->file) - s->stream.avail_in; | 227 | s->start = FTELL(s->file) - s->stream.avail_in; |
202 | } | 228 | } |
203 | 229 | ||
204 | return (gzFile)s; | 230 | return (gzFile)s; |
@@ -211,7 +237,17 @@ gzFile ZEXPORT gzopen (path, mode) | |||
211 | const char *path; | 237 | const char *path; |
212 | const char *mode; | 238 | const char *mode; |
213 | { | 239 | { |
214 | return gz_open (path, mode, -1); | 240 | return gz_open (path, mode, -1, 0); |
241 | } | ||
242 | |||
243 | /* =========================================================================== | ||
244 | Opens a gzip (.gz) file for reading or writing for 64-bit offsets | ||
245 | */ | ||
246 | gzFile ZEXPORT gzopen64 (path, mode) | ||
247 | const char *path; | ||
248 | const char *mode; | ||
249 | { | ||
250 | return gz_open (path, mode, -1, 1); | ||
215 | } | 251 | } |
216 | 252 | ||
217 | /* =========================================================================== | 253 | /* =========================================================================== |
@@ -227,7 +263,7 @@ gzFile ZEXPORT gzdopen (fd, mode) | |||
227 | if (fd < 0) return (gzFile)Z_NULL; | 263 | if (fd < 0) return (gzFile)Z_NULL; |
228 | sprintf(name, "<fd:%d>", fd); /* for debugging */ | 264 | sprintf(name, "<fd:%d>", fd); /* for debugging */ |
229 | 265 | ||
230 | return gz_open (name, mode, fd); | 266 | return gz_open (name, mode, fd, 0); |
231 | } | 267 | } |
232 | 268 | ||
233 | /* =========================================================================== | 269 | /* =========================================================================== |
@@ -767,10 +803,17 @@ int ZEXPORT gzflush (file, flush) | |||
767 | SEEK_END is not implemented, returns error. | 803 | SEEK_END is not implemented, returns error. |
768 | In this version of the library, gzseek can be extremely slow. | 804 | In this version of the library, gzseek can be extremely slow. |
769 | */ | 805 | */ |
770 | z_off_t ZEXPORT gzseek (file, offset, whence) | 806 | #ifdef _LARGEFILE64_SOURCE |
807 | local off64_t gz_seek (file, offset, whence, use64) | ||
808 | gzFile file; | ||
809 | off64_t offset; | ||
810 | #else | ||
811 | local z_off_t gz_seek (file, offset, whence, use64) | ||
771 | gzFile file; | 812 | gzFile file; |
772 | z_off_t offset; | 813 | z_off_t offset; |
814 | #endif | ||
773 | int whence; | 815 | int whence; |
816 | int use64; | ||
774 | { | 817 | { |
775 | gz_stream *s = (gz_stream*)file; | 818 | gz_stream *s = (gz_stream*)file; |
776 | 819 | ||
@@ -819,7 +862,13 @@ z_off_t ZEXPORT gzseek (file, offset, whence) | |||
819 | s->back = EOF; | 862 | s->back = EOF; |
820 | s->stream.avail_in = 0; | 863 | s->stream.avail_in = 0; |
821 | s->stream.next_in = s->inbuf; | 864 | s->stream.next_in = s->inbuf; |
822 | if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; | 865 | #ifdef _LARGEFILE64_SOURCE |
866 | if ((use64 ? fseeko64(s->file, offset, SEEK_SET) : | ||
867 | FSEEK(s->file, offset, SEEK_SET)) < 0) | ||
868 | return -1L; | ||
869 | #else | ||
870 | if (FSEEK(s->file, offset, SEEK_SET) < 0) return -1L; | ||
871 | #endif | ||
823 | 872 | ||
824 | s->in = s->out = offset; | 873 | s->in = s->out = offset; |
825 | return offset; | 874 | return offset; |
@@ -855,6 +904,35 @@ z_off_t ZEXPORT gzseek (file, offset, whence) | |||
855 | } | 904 | } |
856 | 905 | ||
857 | /* =========================================================================== | 906 | /* =========================================================================== |
907 | Define external functions gzseek() and gzseek64() using local gz_seek(). | ||
908 | */ | ||
909 | z_off_t ZEXPORT gzseek (file, offset, whence) | ||
910 | gzFile file; | ||
911 | z_off_t offset; | ||
912 | int whence; | ||
913 | { | ||
914 | return (z_off_t)gz_seek(file, offset, whence, 0); | ||
915 | } | ||
916 | |||
917 | #ifdef _LARGEFILE64_SOURCE | ||
918 | off64_t ZEXPORT gzseek64 (file, offset, whence) | ||
919 | gzFile file; | ||
920 | off64_t offset; | ||
921 | int whence; | ||
922 | { | ||
923 | return gz_seek(file, offset, whence, 1); | ||
924 | } | ||
925 | #else | ||
926 | z_off_t ZEXPORT gzseek64 (file, offset, whence) | ||
927 | gzFile file; | ||
928 | z_off_t offset; | ||
929 | int whence; | ||
930 | { | ||
931 | return gz_seek(file, offset, whence, 0); | ||
932 | } | ||
933 | #endif | ||
934 | |||
935 | /* =========================================================================== | ||
858 | Rewinds input file. | 936 | Rewinds input file. |
859 | */ | 937 | */ |
860 | int ZEXPORT gzrewind (file) | 938 | int ZEXPORT gzrewind (file) |
@@ -873,7 +951,7 @@ int ZEXPORT gzrewind (file) | |||
873 | if (!s->transparent) (void)inflateReset(&s->stream); | 951 | if (!s->transparent) (void)inflateReset(&s->stream); |
874 | s->in = 0; | 952 | s->in = 0; |
875 | s->out = 0; | 953 | s->out = 0; |
876 | return fseek(s->file, s->start, SEEK_SET); | 954 | return FSEEK(s->file, s->start, SEEK_SET); |
877 | } | 955 | } |
878 | 956 | ||
879 | /* =========================================================================== | 957 | /* =========================================================================== |
@@ -888,6 +966,19 @@ z_off_t ZEXPORT gztell (file) | |||
888 | } | 966 | } |
889 | 967 | ||
890 | /* =========================================================================== | 968 | /* =========================================================================== |
969 | 64-bit version | ||
970 | */ | ||
971 | #ifdef _LARGEFILE64_SOURCE | ||
972 | off64_t ZEXPORT gztell64 (file) | ||
973 | #else | ||
974 | z_off_t ZEXPORT gztell64 (file) | ||
975 | #endif | ||
976 | gzFile file; | ||
977 | { | ||
978 | return gzseek64(file, 0L, SEEK_CUR); | ||
979 | } | ||
980 | |||
981 | /* =========================================================================== | ||
891 | Returns 1 when EOF has previously been detected reading the given | 982 | Returns 1 when EOF has previously been detected reading the given |
892 | input stream, otherwise zero. | 983 | input stream, otherwise zero. |
893 | */ | 984 | */ |