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